Compare commits

..

23 commits
v2.8.1 ... main

Author SHA1 Message Date
compliance-pr-automation-bot[bot]
2c5827061f
[Compliance] - PR Template Changes Required (#586)
Co-authored-by: compliance-pr-automation[bot] <1425255+compliance-pr-automation-bot[bot]@users.noreply.github.com>
2025-07-28 16:10:23 -07:00
John-Michael Faircloth
4c06c5ccf5
Prepare for v3.4.0 release (#584)
* Prepare for v3.4.0 release

* update dist
2025-06-13 11:30:03 -05:00
dependabot[bot]
d07b4dc505
chore(deps): bump jsrsasign from 11.0.0 to 11.1.0 (#521)
Bumps [jsrsasign](https://github.com/kjur/jsrsasign) from 11.0.0 to 11.1.0.
- [Release notes](https://github.com/kjur/jsrsasign/releases)
- [Changelog](https://github.com/kjur/jsrsasign/blob/master/ChangeLog.txt)
- [Commits](https://github.com/kjur/jsrsasign/compare/11.0.0...11.1.0)

---
updated-dependencies:
- dependency-name: jsrsasign
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-13 10:30:05 -05:00
John-Michael Faircloth
8ab17d80fa
Prevent possible DoS via polynomial regex (#583) 2025-06-13 09:17:23 -05:00
John-Michael Faircloth
b022ecdb0c
fix: replace all dot chars during normalization (#580)
* fix: replace all dot chars during normalization

* changelog
2025-05-14 09:32:58 -05:00
Tom Chwojko-Frank
4d5899dd0e
Adding codeowners file (#578) 2025-04-14 16:20:35 -07:00
Rory
7709c60978
feat: added double asterisk wildcard selector to prevent uppercasing of keys before exporting envs (#545)
* feat: added double asterisk wildcard selector to prevent uppercasing of keys before exporting envs

* chore: update changelog

---------

Co-authored-by: John-Michael Faircloth <fairclothjm@users.noreply.github.com>
2025-03-03 15:31:00 -06:00
John-Michael Faircloth
4b1f32b395
Prepare for v3.2.0 release (#575)
* Prepare for v3.2.0 release

* changelog update
2025-03-03 14:18:41 -06:00
Andre Fuentes
5d06ce836f
Retry core.getIDToken for JWT Auth Method (#574)
* adding generic async retry function and retry core.getIDToken

* adding test and build
2025-03-03 12:02:57 -06:00
kpcraig
a1b77a0929
Prepare for v3.1.0 release (#571) 2025-01-09 13:09:19 -05:00
Dave Sewell
3b999aeea2
chore: Update dist/index for latest code (#568) 2024-12-20 17:41:11 -08:00
Dave Sewell
c46b8b8822
chore: Update docker compose command (#567) 2024-12-06 12:47:10 -05:00
Dave Sewell
33b70ff01a
feat: Add PKI capability (#564) 2024-12-05 12:22:45 -05:00
John-Michael Faircloth
8b7eaceb79
docs: add namespace example to readme (#562)
* docs: add namespace example to readme

* fix integration test jwt audience
2024-08-01 08:50:57 -05:00
John-Michael Faircloth
148ee648cc
chore: add details on kvv2 path (#554) 2024-05-22 15:22:30 -05:00
John-Michael Faircloth
0f302fb182
chore: bump and pin github actions (#552) 2024-05-14 16:12:19 -05:00
John-Michael Faircloth
47dbc643a8
fix wildcard handling when field contains dot (#542)
* fix wildcard handling when field contains dot

* changelog
2024-04-15 16:42:20 -05:00
John-Michael Faircloth
66531b2752
Revert convert to esm (#544)
* Revert "update got dependency and convert to esm module (#533)"

This reverts commit 77efb36ae3.

* keep new local test file changes

* keep changes to PR template

* update changelog
2024-04-15 16:39:55 -05:00
dependabot[bot]
ee41aa2fcf
chore(deps): bump jsonata from 2.0.3 to 2.0.4 (#531)
* chore(deps): bump jsonata from 2.0.3 to 2.0.4

Bumps [jsonata](https://github.com/jsonata-js/jsonata) from 2.0.3 to 2.0.4.
- [Release notes](https://github.com/jsonata-js/jsonata/releases)
- [Changelog](https://github.com/jsonata-js/jsonata/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jsonata-js/jsonata/compare/v2.0.3...v2.0.4)

---
updated-dependencies:
- dependency-name: jsonata
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* changelog

* changelog++

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: JM Faircloth <jmfaircloth@hashicorp.com>
2024-03-22 09:18:20 -05:00
John-Michael Faircloth
77efb36ae3
update got dependency and convert to esm module (#533)
* update require got to import got

* convert remaining to esm

* wip: replace jest with vitest

* fix test imports and vitest config

* remove dist package.json

* fix import in ent test

* add dist

* move actions/core to prod dependency

* remove unused import that was breaking esm compilation

* simplify imports

* use module.createRequire to import jsonata

* add doc link comment

* add comments on import insanity

* add more comments

* update PR tempalte

* bump got and remove jest deps

* revert debug npm run command

* fix fs import

* simplify vitest config for each test suite
2024-03-19 10:42:34 -05:00
John-Michael Faircloth
a727ce205a
approle: do not require secret_id (#522)
* approle: support bind_secret_id

* add changelog
2024-02-28 11:15:56 -06:00
John-Michael Faircloth
d1720f055e
fix changelog link (#530) 2024-02-15 11:55:33 -06:00
John-Michael Faircloth
92626383ce
Prepare for v3.0.0 release (#529) 2024-02-15 11:53:53 -06:00
23 changed files with 1522 additions and 561 deletions

View file

@ -8,7 +8,6 @@ Relates OR Closes #0000
### Checklist ### Checklist
- [ ] Added [CHANGELOG](https://github.com/hashicorp/vault-action/blob/master/CHANGELOG.md) entry (only for user-facing changes) - [ ] Added [CHANGELOG](https://github.com/hashicorp/vault-action/blob/master/CHANGELOG.md) entry (only for user-facing changes)
- [ ] Did not commit changes to `dist/index.js` (This is only done for releases by vault-action maintainers)
### Community Note ### Community Note
@ -19,3 +18,15 @@ Relates OR Closes #0000
prioritize this request prioritize this request
* Please do not leave "+1" comments, they generate extra noise for pull request * Please do not leave "+1" comments, they generate extra noise for pull request
followers and do not help prioritize the request followers and do not help prioritize the request
## PCI review checklist
<!-- heimdall_github_prtemplate:grc-pci_dss-2024-01-05 -->
- [ ] I have documented a clear reason for, and description of, the change I am making.
- [ ] If applicable, I've documented a plan to revert these changes if they require more than reverting the pull request.
- [ ] If applicable, I've documented the impact of any changes to security controls.
Examples of changes to security controls include using new access control methods, adding or removing logging pipelines, etc.

View file

@ -1,11 +1,14 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options: # Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates # https://docs.github.com/en/code-security/dependabot/dependabot-security-updates/configuring-dependabot-security-updates
version: 2 version: 2
updates: updates:
- package-ecosystem: "npm" # See documentation for possible values - package-ecosystem: "npm"
directory: "/" # Location of package manifests directory: "/" # Location of package manifests
open-pull-requests-limit: 0 # only require security updates and exclude version updates
schedule: schedule:
interval: "daily" interval: "weekly"
# For got, ignore all updates since it is now native ESM
# see https://github.com/hashicorp/vault-action/pull/457#issuecomment-1601445634
ignore:
- dependency-name: "got"

View file

@ -8,7 +8,7 @@ jobs:
actionlint: actionlint:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: "Lint workflow files" - name: "Lint workflow files"
uses: docker://docker.mirror.hashicorp.services/rhysd/actionlint:latest uses: docker://docker.mirror.hashicorp.services/rhysd/actionlint:latest
with: with:

View file

@ -6,283 +6,282 @@ jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
with: with:
node-version: '16.14.0' node-version: "20.9.0"
- name: Setup NPM Cache - name: Setup NPM Cache
uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1
with: with:
path: ~/.npm path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: | restore-keys: |
${{ runner.os }}-node- ${{ runner.os }}-node-
- name: NPM Install - name: NPM Install
run: npm ci run: npm ci
- name: NPM Build - name: NPM Build
run: npm run build run: npm run build
- name: NPM Run Test - name: NPM Run Test
run: npm run test run: npm run test
integrationOSS: integrationOSS:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Run docker-compose - name: Run docker compose
run: docker-compose up -d vault run: docker compose up -d vault
- uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
with: with:
node-version: '16.14.0' node-version: "20.9.0"
- name: Setup NPM Cache - name: Setup NPM Cache
uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1
with: with:
path: ~/.npm path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: | restore-keys: |
${{ runner.os }}-node- ${{ runner.os }}-node-
- name: NPM Install - name: NPM Install
run: npm ci run: npm ci
- name: NPM Build - name: NPM Build
run: npm run build run: npm run build
- name: NPM Run test;integration:basic - name: NPM Run test;integration:basic
run: npm run test:integration:basic run: npm run test:integration:basic
env: env:
VAULT_HOST: localhost VAULT_HOST: localhost
VAULT_PORT: 8200 VAULT_PORT: 8200
CI: true CI: true
integrationEnterprise: integrationEnterprise:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Run docker-compose - name: Run docker compose
run: docker-compose up -d vault-enterprise run: docker compose up -d vault-enterprise
env: env:
VAULT_LICENSE_CI: ${{ secrets.VAULT_LICENSE_CI }} VAULT_LICENSE_CI: ${{ secrets.VAULT_LICENSE_CI }}
- uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
with: with:
node-version: '16.14.0' node-version: "20.9.0"
- name: Setup NPM Cache - name: Setup NPM Cache
uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1
with: with:
path: ~/.npm path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: | restore-keys: |
${{ runner.os }}-node- ${{ runner.os }}-node-
- name: NPM Install - name: NPM Install
run: npm ci run: npm ci
- name: NPM Build - name: NPM Build
run: npm run build run: npm run build
- name: NPM Run test:integration:enterprise - name: NPM Run test:integration:enterprise
run: npm run test:integration:enterprise run: npm run test:integration:enterprise
env: env:
VAULT_HOST: localhost VAULT_HOST: localhost
VAULT_PORT: 8200 VAULT_PORT: 8200
CI: true CI: true
e2e: e2e:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Run docker-compose - name: Run docker compose
run: docker-compose up -d vault run: docker compose up -d vault
- uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
with: with:
node-version: '16.14.0' node-version: "20.9.0"
- name: Setup NPM Cache - name: Setup NPM Cache
uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1
with: with:
path: ~/.npm path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: | restore-keys: |
${{ runner.os }}-node- ${{ runner.os }}-node-
- name: NPM Install - name: NPM Install
run: npm ci run: npm ci
- name: NPM Build - name: NPM Build
run: npm run build run: npm run build
- name: Setup Vault - name: Setup Vault
run: node ./integrationTests/e2e/setup.js run: node ./integrationTests/e2e/setup.js
env: env:
VAULT_HOST: localhost VAULT_HOST: localhost
VAULT_PORT: 8200 VAULT_PORT: 8200
- name: Test Vault Action (default KV V2) - name: Test Vault Action (default KV V2)
uses: ./ uses: ./
id: kv-secrets id: kv-secrets
with: with:
url: http://localhost:8200 url: http://localhost:8200
token: testtoken token: testtoken
secrets: | secrets: |
secret/data/test secret ; secret/data/test secret ;
secret/data/test secret | NAMED_SECRET ; secret/data/test secret | NAMED_SECRET ;
secret/data/nested/test otherSecret ; secret/data/nested/test otherSecret ;
- name: Test Vault Action (default KV V1) - name: Test Vault Action (default KV V1)
uses: ./ uses: ./
with: with:
url: http://localhost:8200 url: http://localhost:8200
token: testtoken token: testtoken
secrets: | secrets: |
my-secret/test altSecret ; my-secret/test altSecret ;
my-secret/test altSecret | NAMED_ALTSECRET ; my-secret/test altSecret | NAMED_ALTSECRET ;
my-secret/nested/test otherAltSecret ; my-secret/nested/test otherAltSecret ;
- name: Test Vault Action (cubbyhole) - name: Test Vault Action (cubbyhole)
uses: ./ uses: ./
with: with:
url: http://localhost:8200 url: http://localhost:8200
token: testtoken token: testtoken
secrets: | secrets: |
/cubbyhole/test foo ; /cubbyhole/test foo ;
/cubbyhole/test zip | NAMED_CUBBYSECRET ; /cubbyhole/test zip | NAMED_CUBBYSECRET ;
# The ordering of these two Test Vault Action Overwrites Env Vars In Subsequent Action steps matters # The ordering of these two Test Vault Action Overwrites Env Vars In Subsequent Action steps matters
# They should come before the Verify Vault Action Outputs step # They should come before the Verify Vault Action Outputs step
- 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:
url: http://localhost:8200/ url: http://localhost:8200/
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:
url: http://localhost:8200/ url: http://localhost:8200/
token: testtoken token: testtoken
secrets: | secrets: |
secret/data/subsequent-test secret | SUBSEQUENT_TEST_SECRET; secret/data/subsequent-test secret | SUBSEQUENT_TEST_SECRET;
- name: Test JSON Secrets - name: Test JSON Secrets
uses: ./ uses: ./
with: with:
url: http://localhost:8200 url: http://localhost:8200
token: testtoken token: testtoken
secrets: | secrets: |
secret/data/test-json-data jsonData; secret/data/test-json-data jsonData;
secret/data/test-json-string jsonString; secret/data/test-json-string jsonString;
secret/data/test-json-string-multiline jsonStringMultiline; 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 }}
- 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@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Run docker-compose - name: Run docker compose
run: docker-compose up -d vault-tls run: docker compose up -d vault-tls
- uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
with: with:
node-version: '16.14.0' node-version: "20.9.0"
- name: Setup NPM Cache - name: Setup NPM Cache
uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1
with: with:
path: ~/.npm path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: | restore-keys: |
${{ runner.os }}-node- ${{ runner.os }}-node-
- name: NPM Install - name: NPM Install
run: npm ci run: npm ci
- name: NPM Build - name: NPM Build
run: npm run build run: npm run build
- name: Setup Vault - name: Setup Vault
run: node ./integrationTests/e2e-tls/setup.js run: node ./integrationTests/e2e-tls/setup.js
env: env:
VAULT_HOST: localhost VAULT_HOST: localhost
VAULT_PORT: 8200 VAULT_PORT: 8200
VAULTCA: ${{ secrets.VAULTCA }} VAULTCA: ${{ secrets.VAULTCA }}
VAULT_CLIENT_CERT: ${{ secrets.VAULT_CLIENT_CERT }} VAULT_CLIENT_CERT: ${{ secrets.VAULT_CLIENT_CERT }}
VAULT_CLIENT_KEY: ${{ secrets.VAULT_CLIENT_KEY }} VAULT_CLIENT_KEY: ${{ secrets.VAULT_CLIENT_KEY }}
- name: Test Vault Action (default KV V2) - name: Test Vault Action (default KV V2)
uses: ./ uses: ./
id: kv-secrets-tls id: kv-secrets-tls
with: with:
url: https://localhost:8200 url: https://localhost:8200
token: ${{ env.VAULT_TOKEN }} token: ${{ env.VAULT_TOKEN }}
caCertificate: ${{ secrets.VAULTCA }} caCertificate: ${{ secrets.VAULTCA }}
clientCertificate: ${{ secrets.VAULT_CLIENT_CERT }} clientCertificate: ${{ secrets.VAULT_CLIENT_CERT }}
clientKey: ${{ secrets.VAULT_CLIENT_KEY }} clientKey: ${{ secrets.VAULT_CLIENT_KEY }}
secrets: | secrets: |
secret/data/test secret ; secret/data/test secret ;
secret/data/test secret | NAMED_SECRET ; secret/data/test secret | NAMED_SECRET ;
secret/data/nested/test otherSecret ; secret/data/nested/test otherSecret ;
- name: Test Vault Action (tlsSkipVerify) - name: Test Vault Action (tlsSkipVerify)
uses: ./ uses: ./
with: with:
url: https://localhost:8200 url: https://localhost:8200
token: ${{ env.VAULT_TOKEN }} token: ${{ env.VAULT_TOKEN }}
tlsSkipVerify: true tlsSkipVerify: true
clientCertificate: ${{ secrets.VAULT_CLIENT_CERT }} clientCertificate: ${{ secrets.VAULT_CLIENT_CERT }}
clientKey: ${{ secrets.VAULT_CLIENT_KEY }} clientKey: ${{ secrets.VAULT_CLIENT_KEY }}
secrets: | secrets: |
secret/data/tlsSkipVerify skip ; secret/data/tlsSkipVerify skip ;
- name: Test Vault Action (default KV V1) - name: Test Vault Action (default KV V1)
uses: ./ uses: ./
with: with:
url: https://localhost:8200 url: https://localhost:8200
token: ${{ env.VAULT_TOKEN }} token: ${{ env.VAULT_TOKEN }}
caCertificate: ${{ secrets.VAULTCA }} caCertificate: ${{ secrets.VAULTCA }}
clientCertificate: ${{ secrets.VAULT_CLIENT_CERT }} clientCertificate: ${{ secrets.VAULT_CLIENT_CERT }}
clientKey: ${{ secrets.VAULT_CLIENT_KEY }} clientKey: ${{ secrets.VAULT_CLIENT_KEY }}
secrets: | secrets: |
my-secret/test altSecret ; my-secret/test altSecret ;
my-secret/test altSecret | NAMED_ALTSECRET ; my-secret/test altSecret | NAMED_ALTSECRET ;
my-secret/nested/test otherAltSecret ; my-secret/nested/test otherAltSecret ;
- name: Test Vault Action (cubbyhole) - name: Test Vault Action (cubbyhole)
uses: ./ uses: ./
with: with:
url: https://localhost:8200 url: https://localhost:8200
token: ${{ env.VAULT_TOKEN }} token: ${{ env.VAULT_TOKEN }}
secrets: | secrets: |
/cubbyhole/test foo ; /cubbyhole/test foo ;
/cubbyhole/test zip | NAMED_CUBBYSECRET ; /cubbyhole/test zip | NAMED_CUBBYSECRET ;
caCertificate: ${{ secrets.VAULTCA }} caCertificate: ${{ secrets.VAULTCA }}
clientCertificate: ${{ secrets.VAULT_CLIENT_CERT }} clientCertificate: ${{ secrets.VAULT_CLIENT_CERT }}
clientKey: ${{ secrets.VAULT_CLIENT_KEY }} clientKey: ${{ secrets.VAULT_CLIENT_KEY }}
- 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-tls.outputs.otherSecret }} OTHER_SECRET_OUTPUT: ${{ steps.kv-secrets-tls.outputs.otherSecret }}

View file

@ -18,11 +18,11 @@ jobs:
name: local-test name: local-test
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
with: with:
node-version: '16.14.0' node-version: '20.9.0'
- name: NPM Install - name: NPM Install
run: npm ci run: npm ci
@ -48,14 +48,26 @@ jobs:
token: testtoken token: testtoken
secrets: | secrets: |
secret/data/test-json-string jsonString; secret/data/test-json-string jsonString;
secret/data/test-json-data jsonData;
- name: Check Secrets - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
run: | with:
touch secrets.json github-token: "foobar"
echo "${{ steps.import-secrets.outputs.jsonString }}" >> secrets.json script: |
const { JSONSTRING, JSONDATA } = process.env
- name: Check json file format console.log(`string ${JSONSTRING}`)
run: | console.log(`data ${JSONDATA}`)
echo const str = JSONDATA
cat secrets.json
jq -c . < secrets.json let valid = true
try {
JSON.parse(str)
} catch (e) {
valid = false
}
if (valid) {
console.log("valid json")
} else {
console.log("not valid json")
}

View file

@ -1,5 +1,47 @@
## Unreleased ## Unreleased
## 3.4.0 (June 13, 2025)
Bugs:
* replace all dot chars during normalization (https://github.com/hashicorp/vault-action/pull/580)
Improvements:
* Prevent possible DoS via polynomial regex (https://github.com/hashicorp/vault-action/pull/583)
## 3.3.0 (March 3, 2025)
Features:
* Wildcard secret imports can use `**` to retain case of exported env keys [GH-545](https://github.com/hashicorp/vault-action/pull/545)
## 3.2.0 (March 3, 2025)
Improvements:
* Add retry for jwt auth login to fix intermittent login failures [GH-574](https://github.com/hashicorp/vault-action/pull/574)
## 3.1.0 (January 9, 2025)
Improvements:
* fix wildcard handling when field contains dot [GH-542](https://github.com/hashicorp/vault-action/pull/542)
* bump body-parser from 1.20.0 to 1.20.3
* bump braces from 3.0.2 to 3.0.3
* bump cross-spawn from 7.0.3 to 7.0.6
* bump micromatch from 4.0.5 to 4.0.8
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)
* Use `pki` configuration to generate certificates from Vault [GH-564](https://github.com/hashicorp/vault-action/pull/564)
## 3.0.0 (February 15, 2024)
Improvements:
* Bump node runtime from node16 to node20 [GH-529](https://github.com/hashicorp/vault-action/pull/529)
## 2.8.1 (February 15, 2024) ## 2.8.1 (February 15, 2024)
Bugs: Bugs:

1
CODEOWNERS Normal file
View file

@ -0,0 +1 @@
* @hashicorp/vault-ecosystem

View file

@ -1,3 +1,3 @@
.PHONY: local-test .PHONY: local-test
local-test: local-test:
docker compose down; docker-compose up -d vault && act workflow_dispatch -j local-test docker compose down; docker compose up -d vault && act workflow_dispatch -j local-test -W .github/workflows/local-test.yaml

237
README.md
View file

@ -30,6 +30,7 @@ is not meant to modify Vaults state.
- [Simple Key](#simple-key) - [Simple Key](#simple-key)
- [Set Output Variable Name](#set-output-variable-name) - [Set Output Variable Name](#set-output-variable-name)
- [Multiple Secrets](#multiple-secrets) - [Multiple Secrets](#multiple-secrets)
- [KV secrets engine version 2](#kv-secrets-engine-version-2)
- [Other Secret Engines](#other-secret-engines) - [Other Secret Engines](#other-secret-engines)
- [Adding Extra Headers](#adding-extra-headers) - [Adding Extra Headers](#adding-extra-headers)
- [HashiCorp Cloud Platform or Vault Enterprise](#hashicorp-cloud-platform-or-vault-enterprise) - [HashiCorp Cloud Platform or Vault Enterprise](#hashicorp-cloud-platform-or-vault-enterprise)
@ -45,46 +46,51 @@ is not meant to modify Vaults state.
```yaml ```yaml
jobs: jobs:
build: build:
# ... # ...
steps: steps:
# ... # ...
- name: Import Secrets - name: Import Secrets
id: import-secrets id: import-secrets
uses: hashicorp/vault-action@v2 uses: hashicorp/vault-action@v2
with: with:
url: https://vault.mycompany.com:8200 url: https://vault.mycompany.com:8200
token: ${{ secrets.VAULT_TOKEN }} token: ${{ secrets.VAULT_TOKEN }}
caCertificate: ${{ secrets.VAULT_CA_CERT }} caCertificate: ${{ secrets.VAULT_CA_CERT }}
secrets: | secrets: |
secret/data/ci/aws accessKey | AWS_ACCESS_KEY_ID ; secret/data/ci/aws accessKey | AWS_ACCESS_KEY_ID ;
secret/data/ci/aws secretKey | AWS_SECRET_ACCESS_KEY ; secret/data/ci/aws secretKey | AWS_SECRET_ACCESS_KEY ;
secret/data/ci npm_token secret/data/ci npm_token
# ... # ...
``` ```
Retrieved secrets are available as environment variables or outputs for subsequent steps: Retrieved secrets are available as environment variables or outputs for subsequent steps:
```yaml ```yaml
#... #...
- name: Step following 'Import Secrets' - name: Step following 'Import Secrets'
run: | run: |
ACCESS_KEY_ID = "${{ env.AWS_ACCESS_KEY_ID }}" ACCESS_KEY_ID = "${{ env.AWS_ACCESS_KEY_ID }}"
SECRET_ACCESS_KEY = "${{ steps.import-secrets.outputs.AWS_SECRET_ACCESS_KEY }}" SECRET_ACCESS_KEY = "${{ steps.import-secrets.outputs.AWS_SECRET_ACCESS_KEY }}"
# ...
# ...
``` ```
If your project needs a format other than env vars and step outputs, you can use additional steps to transform them into the desired format. If your project needs a format other than env vars and step outputs, you can use additional steps to transform them into the desired format.
For example, a common pattern is to save all the secrets in a JSON file: For example, a common pattern is to save all the secrets in a JSON file:
```yaml ```yaml
#... #...
- name: Step following 'Import Secrets' - name: Step following 'Import Secrets'
run: | run: |
touch secrets.json touch secrets.json
echo '${{ toJson(steps.import-secrets.outputs) }}' >> secrets.json echo '${{ toJson(steps.import-secrets.outputs) }}' >> secrets.json
# ...
# ...
``` ```
Which with our example would yield a file containing: Which with our example would yield a file containing:
```json ```json
{ {
"ACCESS_KEY_ID": "MY_KEY_ID", "ACCESS_KEY_ID": "MY_KEY_ID",
@ -95,7 +101,6 @@ Which with our example would yield a file containing:
Note that all secrets are masked so programs need to read the file themselves otherwise all values will be replaced with a `***` placeholder. Note that all secrets are masked so programs need to read the file themselves otherwise all values will be replaced with a `***` placeholder.
## Authentication Methods ## Authentication Methods
Consider using a [Vault authentication method](https://www.vaultproject.io/docs/auth) such as the JWT auth method with Consider using a [Vault authentication method](https://www.vaultproject.io/docs/auth) such as the JWT auth method with
@ -109,7 +114,7 @@ and Vault using the
Each GitHub Actions workflow receives an auto-generated OIDC token with claims Each GitHub Actions workflow receives an auto-generated OIDC token with claims
to establish the identity of the workflow. to establish the identity of the workflow.
__Vault Configuration__ **Vault Configuration**
<details> <details>
<summary>Click to toggle instructions for configuring Vault.</summary> <summary>Click to toggle instructions for configuring Vault.</summary>
@ -120,7 +125,6 @@ Pass the following parameters to your auth method configuration:
- `oidc_discovery_url`: `https://token.actions.githubusercontent.com` - `oidc_discovery_url`: `https://token.actions.githubusercontent.com`
- `bound_issuer`: `https://token.actions.githubusercontent.com` - `bound_issuer`: `https://token.actions.githubusercontent.com`
Configure a [Vault role](https://www.vaultproject.io/api/auth/jwt#create-role) for the auth method. Configure a [Vault role](https://www.vaultproject.io/api/auth/jwt#create-role) for the auth method.
- `role_type`: `jwt` - `role_type`: `jwt`
@ -136,12 +140,12 @@ Configure a [Vault role](https://www.vaultproject.io/api/auth/jwt#create-role) f
- For wildcard (non-exact) matches, use `bound_claims`. - For wildcard (non-exact) matches, use `bound_claims`.
- `bound_claims_type`: `glob` - `bound_claims_type`: `glob`
- `bound_claims`: JSON object. Maps one or more claim names to corresponding wildcard values. - `bound_claims`: JSON object. Maps one or more claim names to corresponding wildcard values.
```json ```json
{"sub": "repo:<orgName>/*"} { "sub": "repo:<orgName>/*" }
``` ```
- For exact matches, use `bound_subject`. - For exact matches, use `bound_subject`.
@ -154,17 +158,17 @@ Configure a [Vault role](https://www.vaultproject.io/api/auth/jwt#create-role) f
</details> </details>
__GitHub Actions Workflow__ **GitHub Actions Workflow**
In the GitHub Actions workflow, the workflow needs permissions to read contents In the GitHub Actions workflow, the workflow needs permissions to read contents
and write the ID token. and write the ID token.
```yaml ```yaml
jobs: jobs:
retrieve-secret: retrieve-secret:
permissions: permissions:
contents: read contents: read
id-token: write id-token: write
``` ```
In the action, provide the name of the Vault role you created to the `role` parameter. In the action, provide the name of the Vault role you created to the `role` parameter.
@ -319,7 +323,7 @@ with:
The `secrets` parameter is a set of multiple secret requests separated by the `;` character. The `secrets` parameter is a set of multiple secret requests separated by the `;` character.
Each secret request consists of the `path` and the `key` of the desired secret, and optionally the desired Env Var output name. Each secret request consists of the `path` and the `key` of the desired secret, and optionally the desired Env Var output name.
Note that the selector is using [JSONata](https://docs.jsonata.org/overview.html) and certain characters in keys may need to be escaped. Note that the selector is using [JSONata](https://docs.jsonata.org/overview.html) and certain characters in keys may need to be escaped.
```raw ```raw
@ -332,7 +336,7 @@ To retrieve a key `npmToken` from path `secret/data/ci` that has value `somelong
```yaml ```yaml
with: with:
secrets: secret/data/ci npmToken secrets: secret/data/ci npmToken
``` ```
`vault-action` will automatically normalize the given secret selector key, and set the follow as environment variables for the following steps in the current job: `vault-action` will automatically normalize the given secret selector key, and set the follow as environment variables for the following steps in the current job:
@ -345,12 +349,12 @@ You can also access the secret via outputs:
```yaml ```yaml
steps: steps:
# ... # ...
- name: Import Secrets - name: Import Secrets
id: secrets id: secrets
# Import config... # Import config...
- name: Sensitive Operation - name: Sensitive Operation
run: "my-cli --token '${{ steps.secrets.outputs.npmToken }}'" run: "my-cli --token '${{ steps.secrets.outputs.npmToken }}'"
``` ```
_**Note:** If you'd like to only use outputs and disable automatic environment variables, you can set the `exportEnv` option to `false`._ _**Note:** If you'd like to only use outputs and disable automatic environment variables, you can set the `exportEnv` option to `false`._
@ -361,7 +365,7 @@ However, if you want to set it to a specific name, say `NPM_TOKEN`, you could do
```yaml ```yaml
with: with:
secrets: secret/data/ci npmToken | NPM_TOKEN secrets: secret/data/ci npmToken | NPM_TOKEN
``` ```
With that, `vault-action` will now use your requested name and output: With that, `vault-action` will now use your requested name and output:
@ -378,7 +382,6 @@ steps:
# Import config... # Import config...
- name: Sensitive Operation - name: Sensitive Operation
run: "my-cli --token '${{ steps.secrets.outputs.NPM_TOKEN }}'" run: "my-cli --token '${{ steps.secrets.outputs.NPM_TOKEN }}'"
``` ```
### Multiple Secrets ### Multiple Secrets
@ -387,32 +390,81 @@ This action can take multi-line input, so say you had your AWS keys stored in a
```yaml ```yaml
with: with:
secrets: | secrets: |
secret/data/ci/aws accessKey | AWS_ACCESS_KEY_ID ; secret/data/ci/aws accessKey | AWS_ACCESS_KEY_ID ;
secret/data/ci/aws secretKey | AWS_SECRET_ACCESS_KEY secret/data/ci/aws secretKey | AWS_SECRET_ACCESS_KEY
``` ```
You can specify a wildcard * for the key name to get all keys in the path. If you provide an output name with the wildcard, the name will be prepended to the key name:
You can specify a wildcard \* for the key name to get all keys in the path. If you provide an output name with the wildcard, the name will be prepended to the key name:
```yaml
with:
secrets: |
secret/data/ci/aws * | MYAPP_ ;
```
When using the `exportEnv` option all exported keys will be normalized to uppercase. For example, the key `SecretKey` would be exported as `MYAPP_SECRETKEY`.
You can disable uppercase normalization by specifying double asterisks `**` in the selector path:
```yaml ```yaml
with: with:
secrets: | secrets: |
secret/data/ci/aws * | MYAPP_ ; secret/data/ci/aws ** | MYAPP_ ;
``` ```
### KV secrets engine version 2
When accessing secrets from the KV secrets engine version 2, Vault Action
requires the full path to the secret. This is the same path that would be used
in a Vault policy for the secret. You can find the full path to your secret by
performing a `kv get` command like the following:
```bash
$ vault kv get secret/test
== Secret Path ==
secret/data/test
...
```
Note that the full path is not `secret/test`, but `secret/data/test`.
## PKI Certificate Requests
You can use the `pki` option to generate a certificate and private key for a given role.
````yaml
with:
pki: |
pki/issue/rolename {"common_name": "role.mydomain.com", "ttl": "1h"} ;
pki/issue/otherrole {"common_name": "otherrole.mydomain.com", "ttl": "1h"} ;
```
Resulting in:
```bash
ROLENAME_CA=-----BEGIN CERTIFICATE-----...
ROLENAME_CERT=-----BEGIN CERTIFICATE-----...
ROLENAME_KEY=-----BEGIN RSA PRIVATE KEY-----...
ROLENAME_CA_CHAIN=-----BEGIN CERTIFICATE-----...
OTHERROLE_CA=-----BEGIN CERTIFICATE-----...
OTHERROLE_CERT=-----BEGIN CERTIFICATE-----...
OTHERROLE_KEY=-----BEGIN RSA PRIVATE KEY-----...
OTHERROLE_CA_CHAIN=-----BEGIN CERTIFICATE-----...
````
## Other Secret Engines ## Other Secret Engines
Vault Action currently supports retrieving secrets from any engine where secrets Vault Action currently supports retrieving secrets from any engine where secrets
are retrieved via `GET` requests. This means secret engines such as PKI are currently are retrieved via `GET` requests, except for the PKI engine as noted above.
not supported due to their requirement of sending parameters along with the request
(such as `common_name`).
For example, to request a secret from the `cubbyhole` secret engine: For example, to request a secret from the `cubbyhole` secret engine:
```yaml ```yaml
with: with:
secrets: | secrets: |
/cubbyhole/foo foo ; /cubbyhole/foo foo ;
/cubbyhole/foo zip | MY_KEY ; /cubbyhole/foo zip | MY_KEY ;
``` ```
Resulting in: Resulting in:
@ -440,12 +492,12 @@ If you ever need to add extra headers to the vault request, say if you need to a
```yaml ```yaml
with: with:
secrets: | secrets: |
secret/ci/aws accessKey | AWS_ACCESS_KEY_ID ; secret/data/ci/aws accessKey | AWS_ACCESS_KEY_ID ;
secret/ci/aws secretKey | AWS_SECRET_ACCESS_KEY secret/data/ci/aws secretKey | AWS_SECRET_ACCESS_KEY
extraHeaders: | extraHeaders: |
X-Secure-Id: ${{ secrets.SECURE_ID }} X-Secure-Id: ${{ secrets.SECURE_ID }}
X-Secure-Secret: ${{ secrets.SECURE_SECRET }} X-Secure-Secret: ${{ secrets.SECURE_SECRET }}
``` ```
This will automatically add the `x-secure-id` and `x-secure-secret` headers to every request to Vault. This will automatically add the `x-secure-id` and `x-secure-secret` headers to every request to Vault.
@ -463,19 +515,37 @@ parameter specifying the namespace. In HCP Vault, the namespace defaults to `adm
```yaml ```yaml
steps: steps:
# ... # ...
- name: Import Secrets - name: Import Secrets
uses: hashicorp/vault-action uses: hashicorp/vault-action
with: with:
url: https://vault-enterprise.mycompany.com:8200 url: https://vault-enterprise.mycompany.com:8200
caCertificate: ${{ secrets.VAULT_CA_CERT }} method: token
method: token token: ${{ secrets.VAULT_TOKEN }}
token: ${{ secrets.VAULT_TOKEN }} namespace: admin
namespace: admin secrets: |
secrets: | secret/data/ci/aws accessKey | AWS_ACCESS_KEY_ID ;
secret/ci/aws accessKey | AWS_ACCESS_KEY_ID ; secret/data/ci/aws secretKey | AWS_SECRET_ACCESS_KEY ;
secret/ci/aws secretKey | AWS_SECRET_ACCESS_KEY ; secret/data/ci npm_token
secret/ci npm_token ```
Alternatively, you may need to authenticate to the root namespace and retrieve
a secret from a different namespace. To do this, do not set the `namespace`
parameter. Instead set the namespace in the secret path. For example, `<NAMESPACE>/secret/data/app`:
```yaml
steps:
# ...
- name: Import Secrets
uses: hashicorp/vault-action
with:
url: https://vault-enterprise.mycompany.com:8200
method: token
token: ${{ secrets.VAULT_TOKEN }}
secrets: |
namespace-1/secret/data/ci/aws accessKey | AWS_ACCESS_KEY_ID ;
namespace-1/secret/data/ci/aws secretKey | AWS_SECRET_ACCESS_KEY ;
namespace-1/secret/data/ci npm_token
``` ```
## Reference ## Reference
@ -668,9 +738,10 @@ To make it simpler to consume certain secrets as env vars, if no Env/Output Var
## Contributing ## Contributing
If you wish to contribute to this project, the following dependencies are recommended for local development: If you wish to contribute to this project, the following dependencies are recommended for local development:
- [npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) to install dependencies, build project and run tests - [npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) to install dependencies, build project and run tests
- [docker](https://docs.docker.com/get-docker/) to run the pre-configured vault containers for acceptance tests - [docker](https://docs.docker.com/get-docker/) to run the pre-configured vault containers for acceptance tests
- [docker-compose](https://docs.docker.com/compose/) to spin up the pre-configured vault containers for acceptance tests - [docker compose](https://docs.docker.com/compose/) to spin up the pre-configured vault containers for acceptance tests
- [act](https://github.com/nektos/act) to run the vault-action locally - [act](https://github.com/nektos/act) to run the vault-action locally
### Build ### Build
@ -683,11 +754,11 @@ $ npm install && npm run build
### Vault test instance ### Vault test instance
The Github Action needs access to a working Vault instance to function. The Github Action needs access to a working Vault instance to function.
Multiple docker configurations are available via the docker-compose.yml file to run containers compatible with the various acceptance test suites. Multiple docker configurations are available via the docker-compose.yml file to run containers compatible with the various acceptance test suites.
```sh ```sh
$ docker-compose up -d vault # Choose one of: vault, vault-enterprise, vault-tls depending on which tests you would like to run $ docker compose up -d vault # Choose one of: vault, vault-enterprise, vault-tls depending on which tests you would like to run
``` ```
Instead of using one of the dockerized instance, you can also use your own local or remote Vault instance by exporting these environment variables: Instead of using one of the dockerized instance, you can also use your own local or remote Vault instance by exporting these environment variables:

View file

@ -7,6 +7,9 @@ inputs:
secrets: secrets:
description: 'A semicolon-separated list of secrets to retrieve. These will automatically be converted to environmental variable keys. See README for more details' description: 'A semicolon-separated list of secrets to retrieve. These will automatically be converted to environmental variable keys. See README for more details'
required: false required: false
pki:
description: 'A semicolon-separated list of certificates to generate. These will automatically be converted to environment variable keys. Cannot be used with "secrets". See README for more details'
required: false
namespace: namespace:
description: 'The Vault namespace from which to query secrets. Vault Enterprise only, unset by default' description: 'The Vault namespace from which to query secrets. Vault Enterprise only, unset by default'
required: false required: false
@ -94,7 +97,7 @@ inputs:
required: false required: false
default: 'false' default: 'false'
runs: runs:
using: 'node16' using: 'node20'
main: 'dist/index.js' main: 'dist/index.js'
branding: branding:
icon: 'unlock' icon: 'unlock'

260
dist/index.js vendored

File diff suppressed because one or more lines are too long

View file

@ -31,6 +31,22 @@ 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/test-with-multi-dot-chars`, {
method: 'POST',
headers: {
'X-Vault-Token': vaultToken,
},
body: `{"data":{"secret.foo.bar":"SUPERSECRET"}}`
});
await got(`${vaultUrl}/v1/secret/data/nested/test`, { await got(`${vaultUrl}/v1/secret/data/nested/test`, {
method: 'POST', method: 'POST',
headers: { headers: {
@ -104,6 +120,69 @@ describe('integration', () => {
"other-Secret-dash": 'OTHERCUSTOMSECRET', "other-Secret-dash": 'OTHERCUSTOMSECRET',
}, },
}); });
// Enable pki engine
try {
await got(`${vaultUrl}/v1/sys/mounts/pki`, {
method: 'POST',
headers: {
'X-Vault-Token': vaultToken,
},
json: {
type: 'pki'
}
});
} catch (error) {
const {response} = error;
if (response.statusCode === 400 && response.body.includes("path is already in use")) {
// Engine might already be enabled from previous test runs
} else {
throw error;
}
}
// Configure Root CA
try {
await got(`${vaultUrl}/v1/pki/root/generate/internal`, {
method: 'POST',
headers: {
'X-Vault-Token': vaultToken,
},
json: {
common_name: 'test',
ttl: '24h',
},
});
} catch (error) {
const {response} = error;
if (response.statusCode === 400 && response.body.includes("already exists")) {
// Root CA might already be configured from previous test runs
} else {
throw error;
}
}
// Configure PKI Role
try {
await got(`${vaultUrl}/v1/pki/roles/Test`, {
method: 'POST',
headers: {
'X-Vault-Token': vaultToken,
},
json: {
allowed_domains: ['test'],
allow_bare_domains: true,
max_ttl: '1h',
},
});
} catch (error) {
const {response} = error;
if (response.statusCode === 400 && response.body.includes("already exists")) {
// Role might already be configured from previous test runs
} else {
throw error;
}
}
}); });
beforeEach(() => { beforeEach(() => {
@ -124,6 +203,12 @@ describe('integration', () => {
.mockReturnValueOnce(secrets); .mockReturnValueOnce(secrets);
} }
function mockPkiInput(pki) {
when(core.getInput)
.calledWith('pki', expect.anything())
.mockReturnValueOnce(pki);
}
function mockIgnoreNotFound(shouldIgnore) { function mockIgnoreNotFound(shouldIgnore) {
when(core.getInput) when(core.getInput)
.calledWith('ignoreNotFound', expect.anything()) .calledWith('ignoreNotFound', expect.anything())
@ -154,6 +239,19 @@ describe('integration', () => {
expect(core.exportVariable).toBeCalledWith('NAMED_SECRET', 'SUPERSECRET'); expect(core.exportVariable).toBeCalledWith('NAMED_SECRET', 'SUPERSECRET');
}) })
it('gets a pki certificate', async () => {
mockPkiInput('pki/issue/Test {"common_name":"test","ttl":"1h"}');
await exportSecrets();
expect(core.exportVariable).toBeCalledTimes(4);
expect(core.exportVariable).toBeCalledWith('TEST_KEY', expect.anything());
expect(core.exportVariable).toBeCalledWith('TEST_CERT', expect.anything());
expect(core.exportVariable).toBeCalledWith('TEST_CA', expect.anything());
expect(core.exportVariable).toBeCalledWith('TEST_CA_CHAIN', expect.anything());
});
it('get simple secret', async () => { it('get simple secret', async () => {
mockInput('secret/data/test secret'); mockInput('secret/data/test secret');
@ -193,6 +291,26 @@ describe('integration', () => {
expect(core.exportVariable).toBeCalledWith('OTHERSECRETDASH', 'OTHERSUPERSECRET'); 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 secrets with multiple dot chars', async () => {
mockInput(`secret/data/test-with-multi-dot-chars * ;`);
await exportSecrets();
expect(core.exportVariable).toBeCalledTimes(1);
expect(core.exportVariable).toBeCalledWith('SECRET__FOO__BAR', 'SUPERSECRET');
});
it('get wildcard secrets', async () => { it('get wildcard secrets', async () => {
mockInput(`secret/data/test * ;`); mockInput(`secret/data/test * ;`);
@ -295,7 +413,7 @@ describe('integration', () => {
expect(core.exportVariable).toBeCalledWith('FOO', 'bar'); expect(core.exportVariable).toBeCalledWith('FOO', 'bar');
}); });
it('wildcard supports cubbyhole', async () => { it('wildcard supports cubbyhole with uppercase transform', async () => {
mockInput('/cubbyhole/test *'); mockInput('/cubbyhole/test *');
await exportSecrets(); await exportSecrets();
@ -305,6 +423,32 @@ describe('integration', () => {
expect(core.exportVariable).toBeCalledWith('FOO', 'bar'); expect(core.exportVariable).toBeCalledWith('FOO', 'bar');
expect(core.exportVariable).toBeCalledWith('ZIP', 'zap'); expect(core.exportVariable).toBeCalledWith('ZIP', 'zap');
}); });
it('wildcard supports cubbyhole with no change in case', async () => {
mockInput('/cubbyhole/test **');
await exportSecrets();
expect(core.exportVariable).toBeCalledTimes(2);
expect(core.exportVariable).toBeCalledWith('foo', 'bar');
expect(core.exportVariable).toBeCalledWith('zip', 'zap');
});
it('wildcard supports cubbyhole with mixed case change', async () => {
mockInput(`
/cubbyhole/test * ;
/cubbyhole/test **`);
await exportSecrets();
expect(core.exportVariable).toBeCalledTimes(4);
expect(core.exportVariable).toBeCalledWith('FOO', 'bar');
expect(core.exportVariable).toBeCalledWith('ZIP', 'zap');
expect(core.exportVariable).toBeCalledWith('foo', 'bar');
expect(core.exportVariable).toBeCalledWith('zip', 'zap');
});
it('caches responses', async () => { it('caches responses', async () => {
mockInput(` mockInput(`

View file

@ -97,6 +97,8 @@ describe('jwt auth', () => {
} }
}); });
// write the jwt config, the jwt role will be written on a per-test
// basis since the audience may vary
await got(`${vaultUrl}/v1/auth/jwt/config`, { await got(`${vaultUrl}/v1/auth/jwt/config`, {
method: 'POST', method: 'POST',
headers: { headers: {
@ -108,22 +110,6 @@ describe('jwt auth', () => {
} }
}); });
await got(`${vaultUrl}/v1/auth/jwt/role/default`, {
method: 'POST',
headers: {
'X-Vault-Token': vaultToken,
},
json: {
role_type: 'jwt',
bound_audiences: null,
bound_claims: {
iss: 'vault-action'
},
user_claim: 'iss',
policies: ['reader']
}
});
await got(`${vaultUrl}/v1/secret/data/test`, { await got(`${vaultUrl}/v1/secret/data/test`, {
method: 'POST', method: 'POST',
headers: { headers: {
@ -138,6 +124,24 @@ describe('jwt auth', () => {
}); });
describe('authenticate with private key', () => { describe('authenticate with private key', () => {
beforeAll(async () => {
await got(`${vaultUrl}/v1/auth/jwt/role/default`, {
method: 'POST',
headers: {
'X-Vault-Token': vaultToken,
},
json: {
role_type: 'jwt',
bound_audiences: null,
bound_claims: {
iss: 'vault-action'
},
user_claim: 'iss',
policies: ['reader']
}
});
});
beforeEach(() => { beforeEach(() => {
jest.resetAllMocks(); jest.resetAllMocks();
@ -170,6 +174,22 @@ describe('jwt auth', () => {
describe('authenticate with Github OIDC', () => { describe('authenticate with Github OIDC', () => {
beforeAll(async () => { beforeAll(async () => {
await got(`${vaultUrl}/v1/auth/jwt/role/default`, {
method: 'POST',
headers: {
'X-Vault-Token': vaultToken,
},
json: {
role_type: 'jwt',
bound_audiences: 'https://github.com/hashicorp/vault-action',
bound_claims: {
iss: 'vault-action'
},
user_claim: 'iss',
policies: ['reader']
}
});
await got(`${vaultUrl}/v1/auth/jwt/role/default-sigstore`, { await got(`${vaultUrl}/v1/auth/jwt/role/default-sigstore`, {
method: 'POST', method: 'POST',
headers: { headers: {
@ -177,7 +197,7 @@ describe('jwt auth', () => {
}, },
json: { json: {
role_type: 'jwt', role_type: 'jwt',
bound_audiences: null, bound_audiences: 'sigstore',
bound_claims: { bound_claims: {
iss: 'vault-action', iss: 'vault-action',
aud: 'sigstore', aud: 'sigstore',

584
package-lock.json generated
View file

@ -11,7 +11,7 @@
"dependencies": { "dependencies": {
"got": "^11.8.6", "got": "^11.8.6",
"jsonata": "^2.0.3", "jsonata": "^2.0.3",
"jsrsasign": "^11.0.0" "jsrsasign": "^11.1.0"
}, },
"devDependencies": { "devDependencies": {
"@actions/core": "^1.10.1", "@actions/core": "^1.10.1",
@ -1396,21 +1396,22 @@
"dev": true "dev": true
}, },
"node_modules/body-parser": { "node_modules/body-parser": {
"version": "1.20.0", "version": "1.20.3",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
"integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"bytes": "3.1.2", "bytes": "3.1.2",
"content-type": "~1.0.4", "content-type": "~1.0.5",
"debug": "2.6.9", "debug": "2.6.9",
"depd": "2.0.0", "depd": "2.0.0",
"destroy": "1.2.0", "destroy": "1.2.0",
"http-errors": "2.0.0", "http-errors": "2.0.0",
"iconv-lite": "0.4.24", "iconv-lite": "0.4.24",
"on-finished": "2.4.1", "on-finished": "2.4.1",
"qs": "6.10.3", "qs": "6.13.0",
"raw-body": "2.5.1", "raw-body": "2.5.2",
"type-is": "~1.6.18", "type-is": "~1.6.18",
"unpipe": "1.0.0" "unpipe": "1.0.0"
}, },
@ -1445,12 +1446,13 @@
} }
}, },
"node_modules/braces": { "node_modules/braces": {
"version": "3.0.2", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"fill-range": "^7.0.1" "fill-range": "^7.1.1"
}, },
"engines": { "engines": {
"node": ">=8" "node": ">=8"
@ -1508,6 +1510,7 @@
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
"integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
"dev": true, "dev": true,
"license": "MIT",
"engines": { "engines": {
"node": ">= 0.8" "node": ">= 0.8"
} }
@ -1551,14 +1554,32 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/call-bind": { "node_modules/call-bind-apply-helpers": {
"version": "1.0.2", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz",
"integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"function-bind": "^1.1.1", "es-errors": "^1.3.0",
"get-intrinsic": "^1.0.2" "function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/call-bound": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz",
"integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==",
"dev": true,
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.1",
"get-intrinsic": "^1.2.6"
},
"engines": {
"node": ">= 0.4"
}, },
"funding": { "funding": {
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
@ -1753,10 +1774,11 @@
"dev": true "dev": true
}, },
"node_modules/content-type": { "node_modules/content-type": {
"version": "1.0.4", "version": "1.0.5",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
"integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
"dev": true, "dev": true,
"license": "MIT",
"engines": { "engines": {
"node": ">= 0.6" "node": ">= 0.6"
} }
@ -1789,10 +1811,11 @@
} }
}, },
"node_modules/cross-spawn": { "node_modules/cross-spawn": {
"version": "7.0.3", "version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"path-key": "^3.1.0", "path-key": "^3.1.0",
"shebang-command": "^2.0.0", "shebang-command": "^2.0.0",
@ -1880,6 +1903,7 @@
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
"dev": true, "dev": true,
"license": "MIT",
"engines": { "engines": {
"node": ">= 0.8" "node": ">= 0.8"
} }
@ -1912,6 +1936,21 @@
"node": "^14.15.0 || ^16.10.0 || >=18.0.0" "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
} }
}, },
"node_modules/dunder-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
"dev": true,
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.1",
"es-errors": "^1.3.0",
"gopd": "^1.2.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/ee-first": { "node_modules/ee-first": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
@ -1968,6 +2007,39 @@
"is-arrayish": "^0.2.1" "is-arrayish": "^0.2.1"
} }
}, },
"node_modules/es-define-property": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-errors": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-object-atoms": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz",
"integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==",
"dev": true,
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/escalade": { "node_modules/escalade": {
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
@ -2069,10 +2141,11 @@
} }
}, },
"node_modules/fill-range": { "node_modules/fill-range": {
"version": "7.0.1", "version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"to-regex-range": "^5.0.1" "to-regex-range": "^5.0.1"
}, },
@ -2186,14 +2259,25 @@
} }
}, },
"node_modules/get-intrinsic": { "node_modules/get-intrinsic": {
"version": "1.1.2", "version": "1.2.7",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz",
"integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"function-bind": "^1.1.1", "call-bind-apply-helpers": "^1.0.1",
"has": "^1.0.3", "es-define-property": "^1.0.1",
"has-symbols": "^1.0.3" "es-errors": "^1.3.0",
"es-object-atoms": "^1.0.0",
"function-bind": "^1.1.2",
"get-proto": "^1.0.0",
"gopd": "^1.2.0",
"has-symbols": "^1.1.0",
"hasown": "^2.0.2",
"math-intrinsics": "^1.1.0"
},
"engines": {
"node": ">= 0.4"
}, },
"funding": { "funding": {
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
@ -2208,6 +2292,20 @@
"node": ">=8.0.0" "node": ">=8.0.0"
} }
}, },
"node_modules/get-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
"dev": true,
"license": "MIT",
"dependencies": {
"dunder-proto": "^1.0.1",
"es-object-atoms": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/get-stream": { "node_modules/get-stream": {
"version": "6.0.1", "version": "6.0.1",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
@ -2249,6 +2347,19 @@
"node": ">=4" "node": ">=4"
} }
}, },
"node_modules/gopd": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/got": { "node_modules/got": {
"version": "11.8.6", "version": "11.8.6",
"resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz",
@ -2279,18 +2390,6 @@
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
"dev": true "dev": true
}, },
"node_modules/has": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
"dev": true,
"dependencies": {
"function-bind": "^1.1.1"
},
"engines": {
"node": ">= 0.4.0"
}
},
"node_modules/has-flag": { "node_modules/has-flag": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -2301,10 +2400,11 @@
} }
}, },
"node_modules/has-symbols": { "node_modules/has-symbols": {
"version": "1.0.3", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
"dev": true, "dev": true,
"license": "MIT",
"engines": { "engines": {
"node": ">= 0.4" "node": ">= 0.4"
}, },
@ -2313,10 +2413,11 @@
} }
}, },
"node_modules/hasown": { "node_modules/hasown": {
"version": "2.0.0", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
"integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"function-bind": "^1.1.2" "function-bind": "^1.1.2"
}, },
@ -2340,6 +2441,7 @@
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
"integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"depd": "2.0.0", "depd": "2.0.0",
"inherits": "2.0.4", "inherits": "2.0.4",
@ -2356,6 +2458,7 @@
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
"dev": true, "dev": true,
"license": "MIT",
"engines": { "engines": {
"node": ">= 0.8" "node": ">= 0.8"
} }
@ -2397,6 +2500,7 @@
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"safer-buffer": ">= 2.1.2 < 3" "safer-buffer": ">= 2.1.2 < 3"
}, },
@ -2489,6 +2593,7 @@
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true, "dev": true,
"license": "MIT",
"engines": { "engines": {
"node": ">=0.12.0" "node": ">=0.12.0"
} }
@ -3262,17 +3367,18 @@
} }
}, },
"node_modules/jsonata": { "node_modules/jsonata": {
"version": "2.0.3", "version": "2.0.4",
"resolved": "https://registry.npmjs.org/jsonata/-/jsonata-2.0.3.tgz", "resolved": "https://registry.npmjs.org/jsonata/-/jsonata-2.0.4.tgz",
"integrity": "sha512-Up2H81MUtjqI/dWwWX7p4+bUMfMrQJVMN/jW6clFMTiYP528fBOBNtRu944QhKTs3+IsVWbgMeUTny5fw2VMUA==", "integrity": "sha512-vfavX4/G/yrYxE+UrmT/oUJ3ph7KqUrb0R7b0LVRcntQwxw+Z5kA1pNUIQzX5hF04Oe1eKxyoIPsmXtc2LgJTQ==",
"engines": { "engines": {
"node": ">= 8" "node": ">= 8"
} }
}, },
"node_modules/jsrsasign": { "node_modules/jsrsasign": {
"version": "11.0.0", "version": "11.1.0",
"resolved": "https://registry.npmjs.org/jsrsasign/-/jsrsasign-11.0.0.tgz", "resolved": "https://registry.npmjs.org/jsrsasign/-/jsrsasign-11.1.0.tgz",
"integrity": "sha512-BtRwVKS+5dsgPpAtzJcpo5OoWjSs1/zllSBG0+8o8/aV0Ki76m6iZwHnwnsqoTdhfFZDN1XIdcaZr5ZkP+H2gg==", "integrity": "sha512-Ov74K9GihaK9/9WncTe1mPmvrO7Py665TUfUKvraXBpu+xcTWitrtuOwcjf4KMU9maPaYn0OuaWy0HOzy/GBXg==",
"license": "MIT",
"funding": { "funding": {
"url": "https://github.com/kjur/jsrsasign#donations" "url": "https://github.com/kjur/jsrsasign#donations"
} }
@ -3396,6 +3502,16 @@
"tmpl": "1.0.5" "tmpl": "1.0.5"
} }
}, },
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/media-typer": { "node_modules/media-typer": {
"version": "0.3.0", "version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
@ -3412,12 +3528,13 @@
"dev": true "dev": true
}, },
"node_modules/micromatch": { "node_modules/micromatch": {
"version": "4.0.5", "version": "4.0.8",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
"integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"braces": "^3.0.2", "braces": "^3.0.3",
"picomatch": "^2.3.1" "picomatch": "^2.3.1"
}, },
"engines": { "engines": {
@ -3602,10 +3719,14 @@
} }
}, },
"node_modules/object-inspect": { "node_modules/object-inspect": {
"version": "1.12.2", "version": "1.13.3",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz",
"integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==",
"dev": true, "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": { "funding": {
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
@ -3868,12 +3989,13 @@
] ]
}, },
"node_modules/qs": { "node_modules/qs": {
"version": "6.10.3", "version": "6.13.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
"integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
"dev": true, "dev": true,
"license": "BSD-3-Clause",
"dependencies": { "dependencies": {
"side-channel": "^1.0.4" "side-channel": "^1.0.6"
}, },
"engines": { "engines": {
"node": ">=0.6" "node": ">=0.6"
@ -3892,10 +4014,11 @@
} }
}, },
"node_modules/raw-body": { "node_modules/raw-body": {
"version": "2.5.1", "version": "2.5.2",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
"integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"bytes": "3.1.2", "bytes": "3.1.2",
"http-errors": "2.0.0", "http-errors": "2.0.0",
@ -3985,7 +4108,8 @@
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"dev": true "dev": true,
"license": "MIT"
}, },
"node_modules/semver": { "node_modules/semver": {
"version": "6.3.1", "version": "6.3.1",
@ -4024,14 +4148,76 @@
} }
}, },
"node_modules/side-channel": { "node_modules/side-channel": {
"version": "1.0.4", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
"integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"call-bind": "^1.0.0", "es-errors": "^1.3.0",
"get-intrinsic": "^1.0.2", "object-inspect": "^1.13.3",
"object-inspect": "^1.9.0" "side-channel-list": "^1.0.0",
"side-channel-map": "^1.0.1",
"side-channel-weakmap": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/side-channel-list": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
"integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
"dev": true,
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"object-inspect": "^1.13.3"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/side-channel-map": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
"integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
"dev": true,
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
"es-errors": "^1.3.0",
"get-intrinsic": "^1.2.5",
"object-inspect": "^1.13.3"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/side-channel-weakmap": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
"integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
"dev": true,
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
"es-errors": "^1.3.0",
"get-intrinsic": "^1.2.5",
"object-inspect": "^1.13.3",
"side-channel-map": "^1.0.1"
},
"engines": {
"node": ">= 0.4"
}, },
"funding": { "funding": {
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
@ -4231,6 +4417,7 @@
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"is-number": "^7.0.0" "is-number": "^7.0.0"
}, },
@ -5585,21 +5772,21 @@
"dev": true "dev": true
}, },
"body-parser": { "body-parser": {
"version": "1.20.0", "version": "1.20.3",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
"integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==",
"dev": true, "dev": true,
"requires": { "requires": {
"bytes": "3.1.2", "bytes": "3.1.2",
"content-type": "~1.0.4", "content-type": "~1.0.5",
"debug": "2.6.9", "debug": "2.6.9",
"depd": "2.0.0", "depd": "2.0.0",
"destroy": "1.2.0", "destroy": "1.2.0",
"http-errors": "2.0.0", "http-errors": "2.0.0",
"iconv-lite": "0.4.24", "iconv-lite": "0.4.24",
"on-finished": "2.4.1", "on-finished": "2.4.1",
"qs": "6.10.3", "qs": "6.13.0",
"raw-body": "2.5.1", "raw-body": "2.5.2",
"type-is": "~1.6.18", "type-is": "~1.6.18",
"unpipe": "1.0.0" "unpipe": "1.0.0"
}, },
@ -5632,12 +5819,12 @@
} }
}, },
"braces": { "braces": {
"version": "3.0.2", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"dev": true, "dev": true,
"requires": { "requires": {
"fill-range": "^7.0.1" "fill-range": "^7.1.1"
} }
}, },
"browserslist": { "browserslist": {
@ -5702,14 +5889,24 @@
} }
} }
}, },
"call-bind": { "call-bind-apply-helpers": {
"version": "1.0.2", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz",
"integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==",
"dev": true, "dev": true,
"requires": { "requires": {
"function-bind": "^1.1.1", "es-errors": "^1.3.0",
"get-intrinsic": "^1.0.2" "function-bind": "^1.1.2"
}
},
"call-bound": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz",
"integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==",
"dev": true,
"requires": {
"call-bind-apply-helpers": "^1.0.1",
"get-intrinsic": "^1.2.6"
} }
}, },
"callsites": { "callsites": {
@ -5849,9 +6046,9 @@
} }
}, },
"content-type": { "content-type": {
"version": "1.0.4", "version": "1.0.5",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
"integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
"dev": true "dev": true
}, },
"convert-source-map": { "convert-source-map": {
@ -5876,9 +6073,9 @@
} }
}, },
"cross-spawn": { "cross-spawn": {
"version": "7.0.3", "version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"dev": true, "dev": true,
"requires": { "requires": {
"path-key": "^3.1.0", "path-key": "^3.1.0",
@ -5952,6 +6149,17 @@
"integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==",
"dev": true "dev": true
}, },
"dunder-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
"dev": true,
"requires": {
"call-bind-apply-helpers": "^1.0.1",
"es-errors": "^1.3.0",
"gopd": "^1.2.0"
}
},
"ee-first": { "ee-first": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
@ -5999,6 +6207,27 @@
"is-arrayish": "^0.2.1" "is-arrayish": "^0.2.1"
} }
}, },
"es-define-property": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
"dev": true
},
"es-errors": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
"dev": true
},
"es-object-atoms": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz",
"integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==",
"dev": true,
"requires": {
"es-errors": "^1.3.0"
}
},
"escalade": { "escalade": {
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
@ -6075,9 +6304,9 @@
} }
}, },
"fill-range": { "fill-range": {
"version": "7.0.1", "version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
"dev": true, "dev": true,
"requires": { "requires": {
"to-regex-range": "^5.0.1" "to-regex-range": "^5.0.1"
@ -6166,14 +6395,21 @@
"dev": true "dev": true
}, },
"get-intrinsic": { "get-intrinsic": {
"version": "1.1.2", "version": "1.2.7",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz",
"integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==",
"dev": true, "dev": true,
"requires": { "requires": {
"function-bind": "^1.1.1", "call-bind-apply-helpers": "^1.0.1",
"has": "^1.0.3", "es-define-property": "^1.0.1",
"has-symbols": "^1.0.3" "es-errors": "^1.3.0",
"es-object-atoms": "^1.0.0",
"function-bind": "^1.1.2",
"get-proto": "^1.0.0",
"gopd": "^1.2.0",
"has-symbols": "^1.1.0",
"hasown": "^2.0.2",
"math-intrinsics": "^1.1.0"
} }
}, },
"get-package-type": { "get-package-type": {
@ -6182,6 +6418,16 @@
"integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==",
"dev": true "dev": true
}, },
"get-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
"dev": true,
"requires": {
"dunder-proto": "^1.0.1",
"es-object-atoms": "^1.0.0"
}
},
"get-stream": { "get-stream": {
"version": "6.0.1", "version": "6.0.1",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
@ -6208,6 +6454,12 @@
"integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
"dev": true "dev": true
}, },
"gopd": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
"dev": true
},
"got": { "got": {
"version": "11.8.6", "version": "11.8.6",
"resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz",
@ -6232,15 +6484,6 @@
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
"dev": true "dev": true
}, },
"has": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
"dev": true,
"requires": {
"function-bind": "^1.1.1"
}
},
"has-flag": { "has-flag": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -6248,15 +6491,15 @@
"dev": true "dev": true
}, },
"has-symbols": { "has-symbols": {
"version": "1.0.3", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
"dev": true "dev": true
}, },
"hasown": { "hasown": {
"version": "2.0.0", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
"integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"function-bind": "^1.1.2" "function-bind": "^1.1.2"
@ -6978,14 +7221,14 @@
"dev": true "dev": true
}, },
"jsonata": { "jsonata": {
"version": "2.0.3", "version": "2.0.4",
"resolved": "https://registry.npmjs.org/jsonata/-/jsonata-2.0.3.tgz", "resolved": "https://registry.npmjs.org/jsonata/-/jsonata-2.0.4.tgz",
"integrity": "sha512-Up2H81MUtjqI/dWwWX7p4+bUMfMrQJVMN/jW6clFMTiYP528fBOBNtRu944QhKTs3+IsVWbgMeUTny5fw2VMUA==" "integrity": "sha512-vfavX4/G/yrYxE+UrmT/oUJ3ph7KqUrb0R7b0LVRcntQwxw+Z5kA1pNUIQzX5hF04Oe1eKxyoIPsmXtc2LgJTQ=="
}, },
"jsrsasign": { "jsrsasign": {
"version": "11.0.0", "version": "11.1.0",
"resolved": "https://registry.npmjs.org/jsrsasign/-/jsrsasign-11.0.0.tgz", "resolved": "https://registry.npmjs.org/jsrsasign/-/jsrsasign-11.1.0.tgz",
"integrity": "sha512-BtRwVKS+5dsgPpAtzJcpo5OoWjSs1/zllSBG0+8o8/aV0Ki76m6iZwHnwnsqoTdhfFZDN1XIdcaZr5ZkP+H2gg==" "integrity": "sha512-Ov74K9GihaK9/9WncTe1mPmvrO7Py665TUfUKvraXBpu+xcTWitrtuOwcjf4KMU9maPaYn0OuaWy0HOzy/GBXg=="
}, },
"keyv": { "keyv": {
"version": "4.3.2", "version": "4.3.2",
@ -7081,6 +7324,12 @@
"tmpl": "1.0.5" "tmpl": "1.0.5"
} }
}, },
"math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
"dev": true
},
"media-typer": { "media-typer": {
"version": "0.3.0", "version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
@ -7094,12 +7343,12 @@
"dev": true "dev": true
}, },
"micromatch": { "micromatch": {
"version": "4.0.5", "version": "4.0.8",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
"integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
"dev": true, "dev": true,
"requires": { "requires": {
"braces": "^3.0.2", "braces": "^3.0.3",
"picomatch": "^2.3.1" "picomatch": "^2.3.1"
} }
}, },
@ -7233,9 +7482,9 @@
} }
}, },
"object-inspect": { "object-inspect": {
"version": "1.12.2", "version": "1.13.3",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz",
"integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==",
"dev": true "dev": true
}, },
"on-finished": { "on-finished": {
@ -7418,12 +7667,12 @@
"dev": true "dev": true
}, },
"qs": { "qs": {
"version": "6.10.3", "version": "6.13.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
"integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
"dev": true, "dev": true,
"requires": { "requires": {
"side-channel": "^1.0.4" "side-channel": "^1.0.6"
} }
}, },
"random-bytes": { "random-bytes": {
@ -7433,9 +7682,9 @@
"dev": true "dev": true
}, },
"raw-body": { "raw-body": {
"version": "2.5.1", "version": "2.5.2",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
"integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
"dev": true, "dev": true,
"requires": { "requires": {
"bytes": "3.1.2", "bytes": "3.1.2",
@ -7535,14 +7784,51 @@
"dev": true "dev": true
}, },
"side-channel": { "side-channel": {
"version": "1.0.4", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
"integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
"dev": true, "dev": true,
"requires": { "requires": {
"call-bind": "^1.0.0", "es-errors": "^1.3.0",
"get-intrinsic": "^1.0.2", "object-inspect": "^1.13.3",
"object-inspect": "^1.9.0" "side-channel-list": "^1.0.0",
"side-channel-map": "^1.0.1",
"side-channel-weakmap": "^1.0.2"
}
},
"side-channel-list": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
"integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
"dev": true,
"requires": {
"es-errors": "^1.3.0",
"object-inspect": "^1.13.3"
}
},
"side-channel-map": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
"integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
"dev": true,
"requires": {
"call-bound": "^1.0.2",
"es-errors": "^1.3.0",
"get-intrinsic": "^1.2.5",
"object-inspect": "^1.13.3"
}
},
"side-channel-weakmap": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
"integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
"dev": true,
"requires": {
"call-bound": "^1.0.2",
"es-errors": "^1.3.0",
"get-intrinsic": "^1.2.5",
"object-inspect": "^1.13.3",
"side-channel-map": "^1.0.1"
} }
}, },
"signal-exit": { "signal-exit": {

View file

@ -36,7 +36,7 @@
"dependencies": { "dependencies": {
"got": "^11.8.6", "got": "^11.8.6",
"jsonata": "^2.0.3", "jsonata": "^2.0.3",
"jsrsasign": "^11.0.0" "jsrsasign": "^11.1.0"
}, },
"peerDependencies": { "peerDependencies": {
"@actions/core": ">=1 <2" "@actions/core": ">=1 <2"

View file

@ -4,9 +4,9 @@ const command = require('@actions/core/lib/command');
const got = require('got').default; const got = require('got').default;
const jsonata = require('jsonata'); const jsonata = require('jsonata');
const { normalizeOutputKey } = require('./utils'); const { normalizeOutputKey } = require('./utils');
const { WILDCARD } = require('./constants'); const { WILDCARD, WILDCARD_UPPERCASE } = require('./constants');
const { auth: { retrieveToken }, secrets: { getSecrets } } = require('./index'); const { auth: { retrieveToken }, secrets: { getSecrets }, pki: { getCertificates } } = require('./index');
const AUTH_METHODS = ['approle', 'token', 'github', 'jwt', 'kubernetes', 'ldap', 'userpass']; const AUTH_METHODS = ['approle', 'token', 'github', 'jwt', 'kubernetes', 'ldap', 'userpass'];
const ENCODING_TYPES = ['base64', 'hex', 'utf8']; const ENCODING_TYPES = ['base64', 'hex', 'utf8'];
@ -22,6 +22,16 @@ async function exportSecrets() {
const secretsInput = core.getInput('secrets', { required: false }); const secretsInput = core.getInput('secrets', { required: false });
const secretRequests = parseSecretsInput(secretsInput); const secretRequests = parseSecretsInput(secretsInput);
const pkiInput = core.getInput('pki', { required: false });
let pkiRequests = [];
if (pkiInput) {
if (secretsInput) {
throw Error('You cannot provide both "secrets" and "pki" inputs.');
}
pkiRequests = parsePkiInput(pkiInput);
}
const secretEncodingType = core.getInput('secretEncodingType', { required: false }); const secretEncodingType = core.getInput('secretEncodingType', { required: false });
const vaultMethod = (core.getInput('method', { required: false }) || 'token').toLowerCase(); const vaultMethod = (core.getInput('method', { required: false }) || 'token').toLowerCase();
@ -84,12 +94,12 @@ async function exportSecrets() {
core.exportVariable('VAULT_TOKEN', `${vaultToken}`); core.exportVariable('VAULT_TOKEN', `${vaultToken}`);
} }
const requests = secretRequests.map(request => { let results = [];
const { path, selector } = request; if (pkiRequests.length > 0) {
return request; results = await getCertificates(pkiRequests, client);
}); } else {
results = await getSecrets(secretRequests, client);
const results = await getSecrets(requests, client); }
for (const result of results) { for (const result of results) {
@ -128,6 +138,43 @@ async function exportSecrets() {
* @property {string} selector * @property {string} selector
*/ */
/**
* Parses a pki input string into key paths and the request parameters.
* @param {string} pkiInput
*/
function parsePkiInput(pkiInput) {
if (!pkiInput) {
return []
}
const secrets = pkiInput
.split(';')
.filter(key => !!key)
.map(key => key.trim())
.filter(key => key.length !== 0);
return secrets.map(secret => {
const path = secret.substring(0, secret.indexOf(' '));
const parameters = secret.substring(secret.indexOf(' ') + 1);
core.debug(` Parsing PKI: ${path} with parameters: ${parameters}`);
if (!path || !parameters) {
throw Error(`You must provide a valid path and parameters. Input: "${secret}"`);
}
let outputVarName = path.split('/').pop();
let envVarName = normalizeOutputKey(outputVarName);
return {
path,
envVarName,
outputVarName,
parameters: JSON.parse(parameters),
};
});
}
/** /**
* Parses a secrets input string into key paths and their resulting environment variable name. * Parses a secrets input string into key paths and their resulting environment variable name.
* @param {string} secretsInput * @param {string} secretsInput
@ -174,7 +221,7 @@ function parseSecretsInput(secretsInput) {
const selectorAst = jsonata(selectorQuoted).ast(); const selectorAst = jsonata(selectorQuoted).ast();
const selector = selectorQuoted.replace(new RegExp('"', 'g'), ''); const selector = selectorQuoted.replace(new RegExp('"', 'g'), '');
if (selector !== WILDCARD && (selectorAst.type !== "path" || selectorAst.steps[0].stages) && selectorAst.type !== "string" && !outputVarName) { if (selector !== WILDCARD && selector !== WILDCARD_UPPERCASE && (selectorAst.type !== "path" || selectorAst.steps[0].stages) && selectorAst.type !== "string" && !outputVarName) {
throw Error(`You must provide a name for the output key when using json selectors. Input: "${secret}"`); throw Error(`You must provide a name for the output key when using json selectors. Input: "${secret}"`);
} }

View file

@ -5,6 +5,8 @@ const fs = require('fs');
const { default: got } = require('got'); const { default: got } = require('got');
const defaultKubernetesTokenPath = '/var/run/secrets/kubernetes.io/serviceaccount/token' const defaultKubernetesTokenPath = '/var/run/secrets/kubernetes.io/serviceaccount/token'
const retries = 5
const retries_delay = 3000
/*** /***
* Authenticate with Vault and retrieve a Vault token that can be used for requests. * Authenticate with Vault and retrieve a Vault token that can be used for requests.
* @param {string} method * @param {string} method
@ -17,7 +19,7 @@ async function retrieveToken(method, client) {
switch (method) { switch (method) {
case 'approle': { case 'approle': {
const vaultRoleId = core.getInput('roleId', { required: true }); const vaultRoleId = core.getInput('roleId', { required: true });
const vaultSecretId = core.getInput('secretId', { required: true }); const vaultSecretId = core.getInput('secretId', { required: false });
return await getClientToken(client, method, path, { role_id: vaultRoleId, secret_id: vaultSecretId }); return await getClientToken(client, method, path, { role_id: vaultRoleId, secret_id: vaultSecretId });
} }
case 'github': { case 'github': {
@ -35,7 +37,10 @@ async function retrieveToken(method, client) {
const githubAudience = core.getInput('jwtGithubAudience', { required: false }); const githubAudience = core.getInput('jwtGithubAudience', { required: false });
if (!privateKey) { if (!privateKey) {
jwt = await core.getIDToken(githubAudience) jwt = await retryAsyncFunction(retries, retries_delay, core.getIDToken, githubAudience)
.then((result) => {
return result;
});
} else { } else {
jwt = generateJwt(privateKey, keyPassword, Number(tokenTtl)); jwt = generateJwt(privateKey, keyPassword, Number(tokenTtl));
} }
@ -142,6 +147,30 @@ async function getClientToken(client, method, path, payload) {
} }
} }
/***
* Generic function for retrying an async function
* @param {number} retries
* @param {number} delay
* @param {Function} func
* @param {any[]} args
*/
async function retryAsyncFunction(retries, delay, func, ...args) {
let attempt = 0;
while (attempt < retries) {
try {
const result = await func(...args);
return result;
} catch (error) {
attempt++;
if (attempt < retries) {
await new Promise(resolve => setTimeout(resolve, delay));
} else {
throw error;
}
}
}
}
/*** /***
* @typedef {Object} VaultLoginResponse * @typedef {Object} VaultLoginResponse
* @property {{ * @property {{

View file

@ -85,4 +85,23 @@ describe("test retrival for token", () => {
const url = got.post.mock.calls[0][0] const url = got.post.mock.calls[0][0]
expect(url).toContain('differentK8sPath') expect(url).toContain('differentK8sPath')
}) })
it("test retrieval with jwt", async () => {
const method = "jwt"
const jwtToken = "someTestToken"
const testRole = "testRole"
const privateKeyRaw = ""
mockApiResponse()
mockInput("role", testRole)
mockInput("jwtPrivateKey", privateKeyRaw)
core.getIDToken = jest.fn()
core.getIDToken.mockReturnValueOnce(jwtToken)
const token = await retrieveToken(method, got)
expect(token).toEqual(testToken)
const payload = got.post.mock.calls[0][1].json
expect(payload).toEqual({ jwt: jwtToken, role: testRole })
const url = got.post.mock.calls[0][0]
expect(url).toContain('jwt')
})
}) })

View file

@ -1,5 +1,7 @@
const WILDCARD = '*'; const WILDCARD_UPPERCASE = '*';
const WILDCARD = '**';
module.exports = { module.exports = {
WILDCARD WILDCARD,
}; WILDCARD_UPPERCASE,
};

View file

@ -1,7 +1,9 @@
const auth = require('./auth'); const auth = require('./auth');
const secrets = require('./secrets'); const secrets = require('./secrets');
const pki = require('./pki');
module.exports = { module.exports = {
auth, auth,
secrets secrets,
pki
}; };

76
src/pki.js Normal file
View file

@ -0,0 +1,76 @@
const { normalizeOutputKey } = require('./utils');
const core = require('@actions/core');
/** A map of postfix values mapped to the key in the certificate response and a transformer function */
const outputMap = {
cert: { key: 'certificate', tx: (v) => v },
key: { key: 'private_key', tx: (v) => v },
ca: { key: 'issuing_ca', tx: (v) => v },
ca_chain: { key: 'ca_chain', tx: (v) => v.join('\n') },
};
/**
* @typedef PkiRequest
* @type {object}
* @property {string} path - The path to the PKI endpoint
* @property {Record<string, any>} parameters - The parameters to send to the PKI endpoint
* @property {string} envVarName - The name of the environment variable to set
* @property {string} outputVarName - The name of the output variable to set
*/
/**
* @typedef {Object} PkiResponse
* @property {PkiRequest} request
* @property {string} value
* @property {boolean} cachedResponse
*/
/**
* Generate and return the certificates from the PKI engine
* @param {Array<PkiRequest>} pkiRequests
* @param {import('got').Got} client
* @return {Promise<Array<PkiResponse>>}
*/
async function getCertificates(pkiRequests, client) {
/** @type Array<PkiResponse> */
let results = [];
for (const pkiRequest of pkiRequests) {
const { path, parameters } = pkiRequest;
const requestPath = `v1/${path}`;
let body;
try {
const result = await client.post(requestPath, {
body: JSON.stringify(parameters),
});
body = result.body;
} catch (error) {
core.error(`${error.response?.body ?? error.message}`);
throw error;
}
body = JSON.parse(body);
core.info(`✔ Successfully generated certificate (serial number ${body.data.serial_number})`);
Object.entries(outputMap).forEach(([key, value]) => {
const val = value.tx(body.data[value.key]);
results.push({
request: {
...pkiRequest,
envVarName: normalizeOutputKey(`${pkiRequest.envVarName}_${key}`, true),
outputVarName: normalizeOutputKey(`${pkiRequest.outputVarName}_${key}`),
},
value: val,
cachedResponse: false,
});
});
}
return results;
}
module.exports = {
getCertificates,
};

View file

@ -1,5 +1,5 @@
const jsonata = require("jsonata"); const jsonata = require("jsonata");
const { WILDCARD } = require("./constants"); const { WILDCARD, WILDCARD_UPPERCASE} = require("./constants");
const { normalizeOutputKey } = require("./utils"); const { normalizeOutputKey } = require("./utils");
const core = require('@actions/core'); const core = require('@actions/core');
@ -26,6 +26,7 @@ const core = require('@actions/core');
async function getSecrets(secretRequests, client, ignoreNotFound) { async function getSecrets(secretRequests, client, ignoreNotFound) {
const responseCache = new Map(); const responseCache = new Map();
let results = []; let results = [];
let upperCaseEnv = false;
for (const secretRequest of secretRequests) { for (const secretRequest of secretRequests) {
let { path, selector } = secretRequest; let { path, selector } = secretRequest;
@ -59,7 +60,8 @@ async function getSecrets(secretRequests, client, ignoreNotFound) {
body = JSON.parse(body); body = JSON.parse(body);
if (selector == WILDCARD) { if (selector === WILDCARD || selector === WILDCARD_UPPERCASE) {
upperCaseEnv = selector === WILDCARD_UPPERCASE;
let keys = body.data; let keys = body.data;
if (body.data["data"] != undefined) { if (body.data["data"] != undefined) {
keys = keys.data; keys = keys.data;
@ -67,20 +69,26 @@ async function getSecrets(secretRequests, client, ignoreNotFound) {
for (let key in keys) { for (let key in keys) {
let newRequest = Object.assign({},secretRequest); let newRequest = Object.assign({},secretRequest);
newRequest.selector = key; newRequest.selector = key;
if (secretRequest.selector === secretRequest.outputVarName) { if (secretRequest.selector === secretRequest.outputVarName) {
newRequest.outputVarName = key; newRequest.outputVarName = key;
newRequest.envVarName = key; newRequest.envVarName = key;
} } else {
else {
newRequest.outputVarName = secretRequest.outputVarName+key; newRequest.outputVarName = secretRequest.outputVarName+key;
newRequest.envVarName = secretRequest.envVarName+key; newRequest.envVarName = secretRequest.envVarName+key;
} }
newRequest.outputVarName = normalizeOutputKey(newRequest.outputVarName); newRequest.outputVarName = normalizeOutputKey(newRequest.outputVarName);
newRequest.envVarName = normalizeOutputKey(newRequest.envVarName,true); newRequest.envVarName = normalizeOutputKey(newRequest.envVarName, upperCaseEnv);
// 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; selector = key;
results = await selectAndAppendResults( results = await selectAndAppendResults(
@ -94,13 +102,13 @@ async function getSecrets(secretRequests, client, ignoreNotFound) {
} }
else { else {
results = await selectAndAppendResults( results = await selectAndAppendResults(
selector, selector,
body, body,
cachedResponse, cachedResponse,
secretRequest, secretRequest,
results results
); );
} }
} }
return results; return results;
@ -145,7 +153,7 @@ const selectAndAppendResults = async (
secretRequest, secretRequest,
results results
) => { ) => {
if (!selector.match(/.*[\.].*/)) { if (!selector.includes(".")) {
selector = '"' + selector + '"'; selector = '"' + selector + '"';
} }
selector = "data." + selector; selector = "data." + selector;

View file

@ -3,12 +3,12 @@
* @param {string} dataKey * @param {string} dataKey
* @param {boolean=} isEnvVar * @param {boolean=} isEnvVar
*/ */
function normalizeOutputKey(dataKey, isEnvVar = false) { function normalizeOutputKey(dataKey, upperCase = false) {
let outputKey = dataKey let outputKey = dataKey
.replace(".", "__") .replaceAll(".", "__")
.replace(new RegExp("-", "g"), "") .replace(new RegExp("-", "g"), "")
.replace(/[^\p{L}\p{N}_-]/gu, ""); .replace(/[^\p{L}\p{N}_-]/gu, "");
if (isEnvVar) { if (upperCase) {
outputKey = outputKey.toUpperCase(); outputKey = outputKey.toUpperCase();
} }
return outputKey; return outputKey;