Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,37 @@ describe('External secrets utils', () => {
const result = extractProviderKeysFromExpression(expression);
expect(result.sort()).toEqual(['aws', 'vault']);
});

it('extracts provider from mixed dot and double-quoted bracket notation', () => {
expect(
extractProviderKeysFromExpression('={{ $secrets.azureKeyVault["postgres-n8n-data"] }}'),
).toEqual(['azureKeyVault']);
});

it('extracts provider from mixed dot and single-quoted bracket notation', () => {
expect(
extractProviderKeysFromExpression("={{ $secrets.azureKeyVault['postgres-n8n-data'] }}"),
).toEqual(['azureKeyVault']);
});

it('extracts hyphenated provider from mixed dot and bracket notation', () => {
expect(
extractProviderKeysFromExpression('={{ $secrets.my-vault["postgres-n8n-data"] }}'),
).toEqual(['my-vault']);
});

it('extracts provider when bracket access is followed by further dot access', () => {
expect(extractProviderKeysFromExpression('={{ $secrets.vault["key"].subfield }}')).toEqual([
'vault',
]);
});

it('extracts multiple providers from expression mixing dot and bracket notation', () => {
const result = extractProviderKeysFromExpression(
'={{ $secrets.vault["a"] + ":" + $secrets.aws.b }}',
);
expect(result.sort()).toEqual(['aws', 'vault']);
});
});

describe('getExternalSecretExpressionPaths', () => {
Expand Down
7 changes: 5 additions & 2 deletions packages/cli/src/credentials/external-secrets.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,12 @@ export function extractProviderKeysFromExpression(expression: string): string[]
for (const expression of expressionBlocks) {
const expressionContent = expression[1]; // Content inside {{ }}

// Match all dot notation occurrences: $secrets.providerKey
// Match dot-accessed provider keys: $secrets.providerKey. The lookahead
// accepts either a further dot ($secrets.vault.key) or an opening
// bracket ($secrets.vault["key"]) so mixed expressions still resolve
// the provider key when the secret name can't use dot notation.
const dotMatches = expressionContent.matchAll(
new RegExp(`\\$secrets\\.(${PROVIDER_KEY_PATTERN})(?=\\.)`, 'g'),
new RegExp(`\\$secrets\\.(${PROVIDER_KEY_PATTERN})(?=[.\\[])`, 'g'),
);
for (const match of dotMatches) {
providerKeys.add(match[1]);
Expand Down