From 47dbc643a8c668dcca731c2ee3e84331ffd3986c Mon Sep 17 00:00:00 2001 From: John-Michael Faircloth Date: Mon, 15 Apr 2024 16:42:20 -0500 Subject: [PATCH] fix wildcard handling when field contains dot (#542) * fix wildcard handling when field contains dot * changelog --- CHANGELOG.md | 4 +++ dist/index.js | 34 +++++++++++++--------- integrationTests/basic/integration.test.js | 18 ++++++++++++ src/secrets.js | 34 +++++++++++++--------- 4 files changed, 62 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f9befec..ec8575f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## Unreleased +Improvements: + +* fix wildcard handling when field contains dot [GH-542](https://github.com/hashicorp/vault-action/pull/542) + Features: * `secretId` is no longer required for approle to support advanced use cases like machine login when `bind_secret_id` is false. [GH-522](https://github.com/hashicorp/vault-action/pull/522) diff --git a/dist/index.js b/dist/index.js index 987f4366..ef4ffaa9 100644 --- a/dist/index.js +++ b/dist/index.js @@ -18999,7 +18999,7 @@ async function getSecrets(secretRequests, client, ignoreNotFound) { body = JSON.parse(body); - if (selector == WILDCARD) { + if (selector == WILDCARD) { let keys = body.data; if (body.data["data"] != undefined) { keys = keys.data; @@ -19007,20 +19007,26 @@ async function getSecrets(secretRequests, client, ignoreNotFound) { for (let key in keys) { let newRequest = Object.assign({},secretRequest); - newRequest.selector = key; - + newRequest.selector = key; + if (secretRequest.selector === secretRequest.outputVarName) { newRequest.outputVarName = key; - newRequest.envVarName = key; - } - else { + newRequest.envVarName = key; + } else { newRequest.outputVarName = secretRequest.outputVarName+key; - newRequest.envVarName = secretRequest.envVarName+key; + newRequest.envVarName = secretRequest.envVarName+key; } newRequest.outputVarName = normalizeOutputKey(newRequest.outputVarName); - newRequest.envVarName = normalizeOutputKey(newRequest.envVarName,true); - + newRequest.envVarName = normalizeOutputKey(newRequest.envVarName,true); + + // JSONata field references containing reserved tokens should + // be enclosed in backticks + // https://docs.jsonata.org/simple#examples + if (key.includes(".")) { + const backtick = '`'; + key = backtick.concat(key, backtick); + } selector = key; results = await selectAndAppendResults( @@ -19034,13 +19040,13 @@ async function getSecrets(secretRequests, client, ignoreNotFound) { } else { results = await selectAndAppendResults( - selector, - body, - cachedResponse, - secretRequest, + selector, + body, + cachedResponse, + secretRequest, results ); - } + } } return results; diff --git a/integrationTests/basic/integration.test.js b/integrationTests/basic/integration.test.js index 39a874e9..93efb14b 100644 --- a/integrationTests/basic/integration.test.js +++ b/integrationTests/basic/integration.test.js @@ -31,6 +31,14 @@ describe('integration', () => { }, }); + await got(`${vaultUrl}/v1/secret/data/test-with-dot-char`, { + method: 'POST', + headers: { + 'X-Vault-Token': vaultToken, + }, + body: `{"data":{"secret.foo":"SUPERSECRET"}}` + }); + await got(`${vaultUrl}/v1/secret/data/nested/test`, { method: 'POST', headers: { @@ -193,6 +201,16 @@ describe('integration', () => { expect(core.exportVariable).toBeCalledWith('OTHERSECRETDASH', 'OTHERSUPERSECRET'); }); + it('get wildcard secrets with dot char', async () => { + mockInput(`secret/data/test-with-dot-char * ;`); + + await exportSecrets(); + + expect(core.exportVariable).toBeCalledTimes(1); + + expect(core.exportVariable).toBeCalledWith('SECRET__FOO', 'SUPERSECRET'); + }); + it('get wildcard secrets', async () => { mockInput(`secret/data/test * ;`); diff --git a/src/secrets.js b/src/secrets.js index 10677da9..82375c7a 100644 --- a/src/secrets.js +++ b/src/secrets.js @@ -59,7 +59,7 @@ async function getSecrets(secretRequests, client, ignoreNotFound) { body = JSON.parse(body); - if (selector == WILDCARD) { + if (selector == WILDCARD) { let keys = body.data; if (body.data["data"] != undefined) { keys = keys.data; @@ -67,20 +67,26 @@ async function getSecrets(secretRequests, client, ignoreNotFound) { for (let key in keys) { let newRequest = Object.assign({},secretRequest); - newRequest.selector = key; - + newRequest.selector = key; + if (secretRequest.selector === secretRequest.outputVarName) { newRequest.outputVarName = key; - newRequest.envVarName = key; - } - else { + newRequest.envVarName = key; + } else { newRequest.outputVarName = secretRequest.outputVarName+key; - newRequest.envVarName = secretRequest.envVarName+key; + newRequest.envVarName = secretRequest.envVarName+key; } newRequest.outputVarName = normalizeOutputKey(newRequest.outputVarName); - newRequest.envVarName = normalizeOutputKey(newRequest.envVarName,true); - + newRequest.envVarName = normalizeOutputKey(newRequest.envVarName,true); + + // JSONata field references containing reserved tokens should + // be enclosed in backticks + // https://docs.jsonata.org/simple#examples + if (key.includes(".")) { + const backtick = '`'; + key = backtick.concat(key, backtick); + } selector = key; results = await selectAndAppendResults( @@ -94,13 +100,13 @@ async function getSecrets(secretRequests, client, ignoreNotFound) { } else { results = await selectAndAppendResults( - selector, - body, - cachedResponse, - secretRequest, + selector, + body, + cachedResponse, + secretRequest, results ); - } + } } return results;