Skip to content
Merged
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
3 changes: 3 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ inputs:
description: 'Time in seconds, after which token expires'
required: false
default: 3600
secretEncodingType:
description: 'The encoding type of the secret to decode. If not specified, the secret will not be decoded. Supported values: base64, hex, utf8'
required: false
runs:
using: 'node16'
main: 'dist/index.js'
Expand Down
19 changes: 17 additions & 2 deletions src/action.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const jsonata = require('jsonata');
const { auth: { retrieveToken }, secrets: { getSecrets } } = require('./index');

const AUTH_METHODS = ['approle', 'token', 'github', 'jwt', 'kubernetes'];
const ENCODING_TYPES = ['base64', 'hex', 'utf8'];

async function exportSecrets() {
const vaultUrl = core.getInput('url', { required: true });
Expand All @@ -17,6 +18,8 @@ async function exportSecrets() {
const secretsInput = core.getInput('secrets', { required: false });

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be worth dropping a test case in here to cover the behavior. Not sure how challenging that is (still learning about vault-action myself 🙂).

const secretRequests = parseSecretsInput(secretsInput);

const secretEncodingType = core.getInput('secretEncodingType', { required: false });

const vaultMethod = (core.getInput('method', { required: false }) || 'token').toLowerCase();
const authPayload = core.getInput('authPayload', { required: false });
if (!AUTH_METHODS.includes(vaultMethod) && !authPayload) {
Expand Down Expand Up @@ -81,11 +84,23 @@ async function exportSecrets() {

const results = await getSecrets(requests, client);


for (const result of results) {
const { value, request, cachedResponse } = result;
// Output the result

var value = result.value;
const request = result.request;
const cachedResponse = result.cachedResponse;

if (cachedResponse) {
core.debug('ℹ using cached response');
}

// if a secret is encoded, decode it
if (ENCODING_TYPES.includes(secretEncodingType)) {
value = Buffer.from(value, secretEncodingType).toString();
}

for (const line of value.replace(/\r/g, '').split('\n')) {
if (line.length > 0) {
command.issue('add-mask', line);
Expand All @@ -99,7 +114,7 @@ async function exportSecrets() {
}
};

/** @typedef {Object} SecretRequest
/** @typedef {Object} SecretRequest
* @property {string} path
* @property {string} envVarName
* @property {string} outputVarName
Expand Down
19 changes: 19 additions & 0 deletions src/action.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,12 @@ describe('exportSecrets', () => {
.mockReturnValueOnce(doExport);
}

function mockEncodeType(doEncode) {
when(core.getInput)
.calledWith('secretEncodingType', expect.anything())
.mockReturnValueOnce(doEncode);
}

it('simple secret retrieval', async () => {
mockInput('test key');
mockVaultData({
Expand All @@ -196,6 +202,19 @@ describe('exportSecrets', () => {
expect(core.setOutput).toBeCalledWith('key', '1');
});

it('encoded secret retrieval', async () => {
mockInput('test key');
mockVaultData({
key: 'MQ=='
});
mockEncodeType('base64');

await exportSecrets();

expect(core.exportVariable).toBeCalledWith('KEY', '1');
expect(core.setOutput).toBeCalledWith('key', '1');
});

it('intl secret retrieval', async () => {
mockInput('测试 测试');
mockVaultData({
Expand Down