Compare commits

..

22 Commits

Author SHA1 Message Date
JM Faircloth 0b1f582bde simplify more 2023-07-05 16:01:13 -05:00
JM Faircloth 32afcc7f20 remove unused var assignment 2023-07-05 14:33:14 -05:00
JM Faircloth d12e95ba40 remove comment 2023-07-05 13:21:29 -05:00
JM Faircloth 4ef647191c final cleanup 2023-07-05 12:58:41 -05:00
JM Faircloth 1a47f33407 fix test string format 2023-07-05 12:55:58 -05:00
JM Faircloth b239ef37f5 update test check 2023-07-05 12:52:39 -05:00
JM Faircloth ccc7cef6eb fix test string format 2023-07-05 12:49:58 -05:00
JM Faircloth 8e836c6e8e fix ordering of build steps 2023-07-05 12:45:57 -05:00
JM Faircloth a2cae737a3 add debug 2023-07-05 12:43:02 -05:00
JM Faircloth b536ec9ec6 add test cases 2023-07-05 12:39:34 -05:00
JM Faircloth e5605de996 fix lint and pass token to build 2023-07-05 12:30:19 -05:00
JM Faircloth 788264dddd add more tests 2023-07-05 12:25:38 -05:00
JM Faircloth a24b038252 fix secrets stored in JSON format 2023-07-03 15:57:28 -05:00
John-Michael Faircloth e926631bb2 Update to v2.7.1 (#472)
* Update to v2.7.1

* update changelog
2023-07-03 11:09:52 -05:00
John-Michael Faircloth 5213b69445 Revert "fix secrets stored in json format (#466)" (#471)
* Revert "fix secrets stored in json format (#466)"

This reverts commit b9f4d16071.

* fix build: use new Verified Publisher image hashicorp/vault
2023-07-03 10:31:51 -05:00
Robert 357cb9c034 Update to v2.7.0 (#468) 2023-06-21 14:23:47 -05:00
John-Michael Faircloth b9f4d16071 fix secrets stored in json format (#466)
* fix secrets in json format

* fix actionlint

* add more comments and docs

* revert build.yml test

* add test for json

* fix selector

* fix e2e test

* fix e2e test 2

* remove test

* remove isNaN check

* update changelog
2023-06-21 11:55:50 -05:00
Thy Ton 62aa8bb4c4 Fix e2e CI failure from "Test that overwrite env var works in nested action (#453)" (#467)
Fix e2e CI failure VAULT-17057
Co-authored-by: Leonardo Villela <leonardo.villela37@gmail.com>
2023-06-13 11:22:43 -07:00
John-Michael Faircloth ec2980c187 chore: update jira teams and add actionlint (#465)
* chore: update jira teams and add actionlint

* update local test to workflow_dispatch

* define outputs

* try actionlint's skip_outputs setting

* move skip_outputs to action definition in tests

* move skip_outpus to action.yml

* remove skip_outputs

* move outputs

* call actionlint directly to pass args

* try to fix quoting

* truncate ignore

* try escaping

* add comment
2023-06-12 14:58:04 -05:00
John-Michael Faircloth 166100bd2a fix warning about outputToken being an unexpected input (#461) 2023-06-08 10:31:49 -05:00
John-Michael Faircloth dc4f72debb Revert "Test that overwrite env var works in nested action (#453)" (#464)
This reverts commit d27529ebde.
2023-06-08 10:25:58 -05:00
John-Michael Faircloth a87a71c289 ensure we run the build for all branches (#463)
* ensure we run the build for all branches

* remove pull_request_target since push is sufficient

* remove github.ref for checkouts
2023-06-08 09:43:08 -05:00
15 changed files with 314 additions and 79 deletions
+22
View File
@@ -0,0 +1,22 @@
name: Lint GitHub Actions Workflows
on:
push:
paths:
- '.github/workflows/**'
jobs:
actionlint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
- name: "Lint workflow files"
uses: docker://docker.mirror.hashicorp.services/rhysd/actionlint:latest
with:
# Ignore actionlint errors from strict typing for outputs that we use
# in our e2e tests.
# This error occurs because vault-action's outputs are dynamic but
# actionlint expects action.yml to define them.
args: >
-ignore "property \"othersecret\" is not defined in object type"
-ignore "property \"jsonstring\" is not defined in object type"
-ignore "property \"jsonstringmultiline\" is not defined in object type"
+21 -47
View File
@@ -1,9 +1,5 @@
on: on:
push: push:
branches:
- main
pull_request_target:
types: [opened, reopened, synchronize]
workflow_dispatch: workflow_dispatch:
jobs: jobs:
@@ -11,8 +7,6 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
with:
ref: ${{ github.ref }}
- uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 - uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0
with: with:
@@ -40,8 +34,6 @@ jobs:
steps: steps:
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
with:
ref: ${{ github.ref }}
- name: Run docker-compose - name: Run docker-compose
run: docker-compose up -d vault run: docker-compose up -d vault
@@ -76,8 +68,6 @@ jobs:
steps: steps:
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
with:
ref: ${{ github.ref }}
- name: Run docker-compose - name: Run docker-compose
run: docker-compose up -d vault-enterprise run: docker-compose up -d vault-enterprise
@@ -114,8 +104,6 @@ jobs:
steps: steps:
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
with:
ref: ${{ github.ref }}
- name: Run docker-compose - name: Run docker-compose
run: docker-compose up -d vault run: docker-compose up -d vault
@@ -174,11 +162,8 @@ jobs:
/cubbyhole/test foo ; /cubbyhole/test foo ;
/cubbyhole/test zip | NAMED_CUBBYSECRET ; /cubbyhole/test zip | NAMED_CUBBYSECRET ;
- name: Verify Vault Action Outputs # The ordering of these two Test Vault Action Overwrites Env Vars In Subsequent Action steps matters
run: npm run test:integration:e2e # They should come before the Verify Vault Action Outputs step
env:
OTHER_SECRET_OUTPUT: ${{ steps.kv-secrets.outputs.otherSecret }}
- name: Test Vault Action Overwrites Env Vars In Subsequent Action (part 1/2) - name: Test Vault Action Overwrites Env Vars In Subsequent Action (part 1/2)
uses: ./ uses: ./
with: with:
@@ -186,6 +171,7 @@ jobs:
token: testtoken token: testtoken
secrets: | secrets: |
secret/data/test secret | SUBSEQUENT_TEST_SECRET; secret/data/test secret | SUBSEQUENT_TEST_SECRET;
- name: Test Vault Action Overwrites Env Vars In Subsequent Action (part 2/2) - name: Test Vault Action Overwrites Env Vars In Subsequent Action (part 2/2)
uses: ./ uses: ./
with: with:
@@ -194,13 +180,27 @@ jobs:
secrets: | secrets: |
secret/data/subsequent-test secret | SUBSEQUENT_TEST_SECRET; secret/data/subsequent-test secret | SUBSEQUENT_TEST_SECRET;
- name: Test JSON Secrets
uses: ./
with:
url: http://localhost:8200
token: testtoken
secrets: |
secret/data/test-json-data jsonData;
secret/data/test-json-string jsonString;
secret/data/test-json-string-multiline jsonStringMultiline;
- name: Verify Vault Action Outputs
run: npm run test:integration:e2e
env:
OTHER_SECRET_OUTPUT: ${{ steps.kv-secrets.outputs.otherSecret }}
e2e-tls: e2e-tls:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
with:
ref: ${{ github.ref }}
- name: Run docker-compose - name: Run docker-compose
run: docker-compose up -d vault-tls run: docker-compose up -d vault-tls
@@ -234,7 +234,7 @@ jobs:
- name: Test Vault Action (default KV V2) - name: Test Vault Action (default KV V2)
uses: ./ uses: ./
id: kv-secrets id: kv-secrets-tls
with: with:
url: https://localhost:8200 url: https://localhost:8200
token: ${{ env.VAULT_TOKEN }} token: ${{ env.VAULT_TOKEN }}
@@ -285,30 +285,4 @@ jobs:
- name: Verify Vault Action Outputs - name: Verify Vault Action Outputs
run: npm run test:integration:e2e-tls run: npm run test:integration:e2e-tls
env: env:
OTHER_SECRET_OUTPUT: ${{ steps.kv-secrets.outputs.otherSecret }} OTHER_SECRET_OUTPUT: ${{ steps.kv-secrets-tls.outputs.otherSecret }}
# Removing publish step for now.
# publish:
# if: github.event_name == 'push' && contains(github.ref, 'main')
# runs-on: ubuntu-latest
# needs: [build, integration, e2e]
# steps:
# - uses: actions/checkout@v1
# - uses: actions/setup-node@v3
# with:
# node-version: '16.14.0'
# - name: setup npm cache
# uses: actions/cache@v1
# with:
# path: ~/.npm
# key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
# restore-keys: |
# ${{ runner.os }}-node-
# - name: npm install
# run: npm ci
# - name: release
# if: success() && endsWith(github.ref, 'main')
# run: npx semantic-release
# env:
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
+1 -1
View File
@@ -14,4 +14,4 @@ jobs:
JIRA_SYNC_USER_EMAIL: ${{ secrets.JIRA_SYNC_USER_EMAIL }} JIRA_SYNC_USER_EMAIL: ${{ secrets.JIRA_SYNC_USER_EMAIL }}
JIRA_SYNC_API_TOKEN: ${{ secrets.JIRA_SYNC_API_TOKEN }} JIRA_SYNC_API_TOKEN: ${{ secrets.JIRA_SYNC_API_TOKEN }}
with: with:
teams-array: '["applications-eco"]' teams-array: '["ecosystem", "applications-eco"]'
+50 -13
View File
@@ -1,24 +1,61 @@
# This is a sample workflow to help test contributions # This is a sample workflow to help test contributions
# Change the branch name, url and token to fit with your own environment # Change the branch name, url and token to fit with your own environment
# Use 'on: push' instead of 'on: local-test' if you wish to run the test on github # To run this locally with act use:
# If running locally with act, run the workflow with 'act local-test' # act workflow_dispatch -j local-test
#
# If you have permissions, you can run this workflow via the GitHub UI.
# Otherwise, use 'on: push' instead of 'on: workflow_dispatch'.
# Don't forget to revert the file changes and invalidate any tokens that were committed before opening a pull-request # Don't forget to revert the file changes and invalidate any tokens that were
on: local-test # committed before opening a pull request.
on: workflow_dispatch
name: local-test name: local-test
jobs: jobs:
build: local-test:
name: local-test name: local-test
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Import Secrets - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
uses: hashicorp/vault-action@YOUR_BRANCH_NAME
with: - uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0
url: http://localhost:8200 with:
method: token node-version: '16.14.0'
token: testtoken
secrets: | - name: NPM Install
secret/data/test secret | SAMPLE_SECRET; run: npm ci
- name: NPM Build
run: npm run build
- name: Setup Vault
run: node ./integrationTests/e2e/setup.js
env:
VAULT_HOST: localhost
VAULT_PORT: 8200
- name: Import Secrets
id: import-secrets
# use the local changes
uses: ./
# run against a specific version of vault-action
# uses: hashicorp/vault-action@v2.1.2
with:
url: http://localhost:8200
method: token
token: testtoken
secrets: |
secret/data/test-json-string jsonString;
- name: Check Secrets
run: |
touch secrets.json
echo "${{ steps.import-secrets.outputs.jsonString }}" >> secrets.json
- name: Check json file format
run: |
echo
cat secrets.json
jq -c . < secrets.json
+3
View File
@@ -59,3 +59,6 @@ typings/
# next.js build output # next.js build output
.next .next
# GoLand IDE project files
.idea
+18
View File
@@ -1,5 +1,23 @@
## Unreleased ## Unreleased
* Add changes here
## 2.7.1 (July 3, 2023)
Bugs:
* Revert [GH-466](https://github.com/hashicorp/vault-action/pull/466) which caused a regression in secrets stored as JSON strings [GH-471](https://github.com/hashicorp/vault-action/pull/471)
## 2.7.0 (June 21, 2023)
Bugs:
* Fix a regression that broke support for secrets in JSON format [GH-466](https://github.com/hashicorp/vault-action/pull/466)
Improvements:
* Fix a warning about outputToken being an unexpected input [GH-461](https://github.com/hashicorp/vault-action/pull/461)
## 2.6.0 (June 7, 2023) ## 2.6.0 (June 7, 2023)
Features: Features:
+3
View File
@@ -0,0 +1,3 @@
.PHONY: local-test
local-test:
docker compose down; docker-compose up -d vault && act workflow_dispatch -j local-test
+15 -10
View File
@@ -546,18 +546,23 @@ $ npm run test:integration:basic # Choose one of: basic, enterprise, e2e, e2e-tl
### Running the action locally ### Running the action locally
You can use the [act](https://github.com/nektos/act) command to test your changes locally if desired. Unfortunately it is not currently possible to use uncommitted local changes for a shared workfow. You will still need to push You can use the [act](https://github.com/nektos/act) command to test your
the changes you would like to validate beforehand. Even if a commit is necessary, this is still a more detailed and faster feedback loop than waiting for the action to be executed by Github in a different repository. changes locally.
Edit the ./.github/workflows/local-test.yaml file and add any steps necessary
to test your changes. You may have to additionally edit the Vault url, token
and secret path if you are not using one of the provided containerized
instances. The `local-test` job will call the ./integrationTests/e2e/setup.js
script to bootstrap your local Vault instance with secrets.
Run your feature branch locally:
Push your changes into a feature branch.
```sh ```sh
$ git checkout -b my-feature-branch act workflow_dispatch -j local-test
$ git commit -m "testing new changes"
$ git push
``` ```
Edit the ./.github/workflows/local-test.yaml file to use your new feature branch. You may have to additionally edit the vault url, token and secret path if you are not using one of the provided containerized instance. Or use the provided make target which will also spin up a Vault container:
Run your feature branch locally.
```sh ```sh
$ act local-test make local-test
``` ```
+4
View File
@@ -56,6 +56,10 @@ inputs:
description: 'Whether or not export Vault token as environment variables.' description: 'Whether or not export Vault token as environment variables.'
default: 'false' default: 'false'
required: false required: false
outputToken:
description: 'Whether or not to set the `vault_token` output to contain the Vault token after authentication.'
default: 'false'
required: false
caCertificate: caCertificate:
description: 'Base64 encoded CA certificate to verify the Vault server certificate.' description: 'Base64 encoded CA certificate to verify the Vault server certificate.'
required: false required: false
+2 -2
View File
@@ -2,7 +2,7 @@
version: "3.0" version: "3.0"
services: services:
vault: vault:
image: vault:latest image: hashicorp/vault:latest
environment: environment:
VAULT_DEV_ROOT_TOKEN_ID: testtoken VAULT_DEV_ROOT_TOKEN_ID: testtoken
ports: ports:
@@ -17,7 +17,7 @@ services:
- 8200:8200 - 8200:8200
privileged: true privileged: true
vault-tls: vault-tls:
image: vault:latest image: hashicorp/vault:latest
hostname: vault-tls hostname: vault-tls
environment: environment:
VAULT_CAPATH: /etc/vault/ca.crt VAULT_CAPATH: /etc/vault/ca.crt
+6
View File
@@ -10,5 +10,11 @@ describe('e2e', () => {
expect(process.env.FOO).toBe("bar"); expect(process.env.FOO).toBe("bar");
expect(process.env.NAMED_CUBBYSECRET).toBe("zap"); expect(process.env.NAMED_CUBBYSECRET).toBe("zap");
expect(process.env.SUBSEQUENT_TEST_SECRET).toBe("SUBSEQUENT_TEST_SECRET"); expect(process.env.SUBSEQUENT_TEST_SECRET).toBe("SUBSEQUENT_TEST_SECRET");
expect(process.env.JSONSTRING).toBe('{"x":1,"y":"qux"}');
expect(process.env.JSONSTRINGMULTILINE).toBe('{"x": 1, "y": "q\\nux"}');
let result = JSON.stringify('{"x":1,"y":"qux"}');
result = result.substring(1, result.length - 1);
expect(process.env.JSONDATA).toBe(result);
}); });
}); });
+40
View File
@@ -3,6 +3,8 @@ const got = require('got');
const vaultUrl = `${process.env.VAULT_HOST}:${process.env.VAULT_PORT}`; const vaultUrl = `${process.env.VAULT_HOST}:${process.env.VAULT_PORT}`;
const vaultToken = `${process.env.VAULT_TOKEN}` === undefined ? `${process.env.VAULT_TOKEN}` : "testtoken"; const vaultToken = `${process.env.VAULT_TOKEN}` === undefined ? `${process.env.VAULT_TOKEN}` : "testtoken";
const jsonStringMultiline = '{"x": 1, "y": "q\\nux"}';
(async () => { (async () => {
try { try {
// Verify Connection // Verify Connection
@@ -36,6 +38,44 @@ const vaultToken = `${process.env.VAULT_TOKEN}` === undefined ? `${process.env.V
} }
}); });
await got(`http://${vaultUrl}/v1/secret/data/test-json-string`, {
method: 'POST',
headers: {
'X-Vault-Token': vaultToken,
},
json: {
data: {
// this is stored in Vault as a string
jsonString: '{"x":1,"y":"qux"}',
},
},
});
await got(`http://${vaultUrl}/v1/secret/data/test-json-data`, {
method: 'POST',
headers: {
'X-Vault-Token': vaultToken,
},
json: {
data: {
// this is stored in Vault as a map
jsonData: {"x":1,"y":"qux"},
},
},
});
await got(`http://${vaultUrl}/v1/secret/data/test-json-string-multiline`, {
method: 'POST',
headers: {
'X-Vault-Token': vaultToken,
},
json: {
data: {
jsonStringMultiline,
},
},
});
await got(`http://${vaultUrl}/v1/sys/mounts/my-secret`, { await got(`http://${vaultUrl}/v1/sys/mounts/my-secret`, {
method: 'POST', method: 'POST',
headers: { headers: {
+76 -1
View File
@@ -220,6 +220,58 @@ describe('exportSecrets', () => {
expect(core.setOutput).toBeCalledWith('key', '1'); expect(core.setOutput).toBeCalledWith('key', '1');
}); });
it('JSON data secret retrieval', async () => {
const jsonData = {"x":1,"y":2};
// for secrets stored in Vault as pure JSON, we call stringify twice
// and remove the added surrounding quotes
let result = JSON.stringify(JSON.stringify(jsonData));
result = result.substring(1, result.length - 1);
mockInput('test key');
mockVaultData({
key: jsonData,
});
await exportSecrets();
expect(core.exportVariable).toBeCalledWith('KEY', result);
expect(core.setOutput).toBeCalledWith('key', result);
});
it('JSON string secret retrieval', async () => {
const jsonString = '{"x":1,"y":2}';
mockInput('test key');
mockVaultData({
key: jsonString,
});
await exportSecrets();
expect(core.exportVariable).toBeCalledWith('KEY', jsonString);
expect(core.setOutput).toBeCalledWith('key', jsonString);
});
it('multi-line JSON string secret retrieval', async () => {
const jsonString = `
{
"x":1,
"y":"bar"
}
`;
mockInput('test key');
mockVaultData({
key: jsonString,
});
await exportSecrets();
expect(core.exportVariable).toBeCalledWith('KEY', jsonString);
expect(core.setOutput).toBeCalledWith('key', jsonString);
});
it('intl secret retrieval', async () => { it('intl secret retrieval', async () => {
mockInput('测试 测试'); mockInput('测试 测试');
mockVaultData({ mockVaultData({
@@ -334,7 +386,30 @@ describe('exportSecrets', () => {
expect(core.setOutput).toBeCalledWith('key', 'secret'); expect(core.setOutput).toBeCalledWith('key', 'secret');
}) })
it('multi-line secret gets masked for each line', async () => { it('multi-line secret', async () => {
const multiLineString = `ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom/BWDSU
GPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlELEVf4h9lFX5QVkbPppSwg0cda3
Pbv7kOdJ/MTyBlWXFCR+HAo3FXRitBqxiX1nKhXpHAZsMciLq8V6RjsNAQwdsdMFvSlVK/7XA
NrRFi9wrf+M7Q==`;
mockInput('test key');
mockVaultData({
key: multiLineString
});
mockExportToken("false")
await exportSecrets();
expect(core.setSecret).toBeCalledTimes(5); // 1 for each non-empty line + VAULT_TOKEN
expect(core.setSecret).toBeCalledWith("ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom/BWDSU");
expect(core.setSecret).toBeCalledWith("GPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlELEVf4h9lFX5QVkbPppSwg0cda3");
expect(core.setSecret).toBeCalledWith("Pbv7kOdJ/MTyBlWXFCR+HAo3FXRitBqxiX1nKhXpHAZsMciLq8V6RjsNAQwdsdMFvSlVK/7XA");
expect(core.setSecret).toBeCalledWith("NrRFi9wrf+M7Q==");
expect(core.setOutput).toBeCalledWith('key', multiLineString);
})
it('multi-line secret gets masked for each non-empty line', async () => {
const multiLineString = `a multi-line string const multiLineString = `a multi-line string
with blank lines with blank lines
+1 -1
View File
@@ -66,4 +66,4 @@ describe('exportSecrets retries', () => {
done(); done();
}); });
}); });
}); });
+52 -4
View File
@@ -67,12 +67,19 @@ async function getSecrets(secretRequests, client) {
/** /**
* Uses a Jsonata selector retrieve a bit of data from the result * Uses a Jsonata selector retrieve a bit of data from the result
* @param {object} data * @param {object} data
* @param {string} selector * @param {string} selector
*/ */
async function selectData(data, selector) { async function selectData(data, selector) {
const ata = jsonata(selector); const ata = jsonata(selector);
let result = JSON.stringify(await ata.evaluate(data)); let d = await ata.evaluate(data);
console.log(selector);
// If we have a Javascript Object, then this data was stored in Vault as
// pure JSON (not a JSON string). We will capture that before we stringify it.
const storedAsJSONData = isObject(d);
result = JSON.stringify(d);
// Compat for custom engines // Compat for custom engines
if (!result && ((ata.ast().type === "path" && ata.ast()['steps'].length === 1) || ata.ast().type === "string") && selector !== 'data' && 'data' in data) { if (!result && ((ata.ast().type === "path" && ata.ast()['steps'].length === 1) || ata.ast().type === "string") && selector !== 'data' && 'data' in data) {
result = JSON.stringify(await jsonata(`data.${selector}`).evaluate(data)); result = JSON.stringify(await jsonata(`data.${selector}`).evaluate(data));
@@ -81,12 +88,53 @@ async function selectData(data, selector) {
} }
if (result.startsWith(`"`)) { if (result.startsWith(`"`)) {
// we need to strip the beginning and ending quotes otherwise it will
// always successfully parse as a JSON string
// result = result.substring(1, result.length - 1);
// if (!isJSONString(result)) {
// // add the quotes back so we can parse it into a Javascript object
// // to allow support for multi-line secrets. See https://github.com/hashicorp/vault-action/issues/160
// result = `"${result}"`
console.log(" =>>> PARSING")
result = JSON.parse(result); result = JSON.parse(result);
// }
} else {
console.log('does not start with quote')
// Support secrets stored in Vault as pure JSON.
// See https://github.com/hashicorp/vault-action/issues/194 and https://github.com/hashicorp/vault-action/pull/173
result = JSON.stringify(result);
result = result.substring(1, result.length - 1);
} }
return result; return result;
} }
/**
* isOjbect returns true if target is a Javascript object
* @param {Type} target
*/
function isObject(target) {
return typeof target === 'object' && target !== null;
}
/**
* isJSONString returns true if target parses as a valid JSON string
* @param {Type} target
*/
function isJSONString(target) {
if (typeof target !== "string"){
return false;
}
try {
JSON.parse(target);
} catch (e) {
return false;
}
return true;
}
module.exports = { module.exports = {
getSecrets, getSecrets,
selectData selectData
} }