Compare commits

..

86 Commits

Author SHA1 Message Date
Theron Voran d5a69ceca1 Update to v2.3.1 (#242) 2021-08-23 08:36:01 -07:00
dependabot[bot] f3e4110f8d chore(deps): bump path-parse from 1.0.6 to 1.0.7 (#239) 2021-08-12 19:00:07 +00:00
Theron Voran 8c00f7e4fd set vault license for enterprise tests (#240)
Since hashicorp/vault-enterprise:latest now requires a license to do
anything, we need to set $VAULT_LICENSE when provisioning the
enterprise docker container.
2021-08-12 11:55:16 -07:00
dependabot[bot] ab957d2aec chore(deps): bump normalize-url from 4.5.0 to 4.5.1 (#227) 2021-08-12 17:15:05 +00:00
Theron Voran 0451f06f9f Update to v2.3.0 (#231) 2021-06-23 14:03:57 -07:00
dependabot[bot] b6210c5a51 chore(deps): bump hosted-git-info from 2.8.8 to 2.8.9 (#216)
Bumps [hosted-git-info](https://github.com/npm/hosted-git-info) from 2.8.8 to 2.8.9.
- [Release notes](https://github.com/npm/hosted-git-info/releases)
- [Changelog](https://github.com/npm/hosted-git-info/blob/v2.8.9/CHANGELOG.md)
- [Commits](https://github.com/npm/hosted-git-info/compare/v2.8.8...v2.8.9)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-06-03 11:10:25 -04:00
Jason O'Donnell 09740f679f changelog++ 2021-06-03 11:01:06 -04:00
Falcon Taylor-Carter 72c7a899ca Implement kubernetes auth / Add customizable auth path (#218)
* Implement kubernetes auth / Add customizable auth path

* Fix typo

* Apply suggestions from code review

Co-authored-by: Jason O'Donnell <2160810+jasonodonnell@users.noreply.github.com>

Co-authored-by: Jason O'Donnell <2160810+jasonodonnell@users.noreply.github.com>
2021-06-03 10:59:51 -04:00
Jason O'Donnell 0cf3bd6a39 Update version in example doc (#215) 2021-05-06 14:27:48 -04:00
Jason O'Donnell 0723fd7348 Update to v2.2.0 (#214) 2021-05-06 13:51:05 -04:00
dependabot[bot] 0405c26bc9 chore(deps): bump jsonata from 1.8.3 to 1.8.4 (#171)
Bumps [jsonata](https://github.com/jsonata-js/jsonata) from 1.8.3 to 1.8.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/v1.8.3...v1.8.4)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-05-06 13:42:25 -04:00
dependabot[bot] 2eea93c25e chore(deps-dev): bump @actions/core from 1.2.6 to 1.2.7 (#206)
Bumps [@actions/core](https://github.com/actions/toolkit/tree/HEAD/packages/core) from 1.2.6 to 1.2.7.
- [Release notes](https://github.com/actions/toolkit/releases)
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/core/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/core)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-05-06 13:42:11 -04:00
dependabot[bot] 4d9cf786d6 chore(deps-dev): bump @types/jest from 26.0.22 to 26.0.23 (#207)
Bumps [@types/jest](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jest) from 26.0.22 to 26.0.23.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jest)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-05-06 13:41:52 -04:00
dependabot[bot] 575042000a chore(deps): bump handlebars from 4.7.6 to 4.7.7 (#213)
Bumps [handlebars](https://github.com/wycats/handlebars.js) from 4.7.6 to 4.7.7.
- [Release notes](https://github.com/wycats/handlebars.js/releases)
- [Changelog](https://github.com/handlebars-lang/handlebars.js/blob/master/release-notes.md)
- [Commits](https://github.com/wycats/handlebars.js/compare/v4.7.6...v4.7.7)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-05-06 13:41:29 -04:00
dependabot[bot] cc8ad16bec chore(deps): bump lodash from 4.17.20 to 4.17.21 (#212)
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.20 to 4.17.21.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.20...4.17.21)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-05-06 13:41:20 -04:00
dependabot[bot] cd1614aee3 chore(deps): bump jsrsasign from 10.1.10 to 10.2.0 (#211)
Bumps [jsrsasign](https://github.com/kjur/jsrsasign) from 10.1.10 to 10.2.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/10.1.10...10.2.0)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-05-06 13:38:52 -04:00
Jason O'Donnell f3a53220d9 changelog++ 2021-05-06 13:24:09 -04:00
Tom Proctor 3526e1be65 Mask each line of multi-line secrets (#208)
* Mask each line of multi-line secrets

* Don't include carriage return characters in masking

* Update CHANGELOG.md
2021-05-05 11:54:07 +01:00
Jason O'Donnell f60544fbda changelog++ 2021-05-04 09:02:26 -04:00
Raman Harnak 9e8f22534f Implement JWT auth (#188) 2021-05-04 08:49:35 -04:00
Maryam Ghanizadeh 8417c61f8a chore(deps): bump marked from 1.2.6 to 2.0.1 security reason (#202) 2021-04-22 16:32:18 -04:00
dependabot[bot] 0cca23248c chore(deps-dev): bump @types/jest from 26.0.19 to 26.0.22 (#201)
Bumps [@types/jest](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jest) from 26.0.19 to 26.0.22.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jest)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-04-22 15:46:23 -04:00
dependabot[bot] 8dad53ed10 chore(deps): bump got from 11.8.1 to 11.8.2 (#190)
Bumps [got](https://github.com/sindresorhus/got) from 11.8.1 to 11.8.2.
- [Release notes](https://github.com/sindresorhus/got/releases)
- [Commits](https://github.com/sindresorhus/got/compare/v11.8.1...v11.8.2)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-04-22 15:46:05 -04:00
Jason O'Donnell 937d792a86 Add GitHub authentication notice (#200)
* Add GitHub authentication notice

* Typo in perm name
2021-03-26 14:03:15 -04:00
Jason O'Donnell 5e5c06a3c8 Update to v2.1.2 (#180)
* Update to v2.1.2

* Update index.js
2021-01-21 14:45:22 -05:00
Jason O'Donnell ff547e1516 changelog++ 2021-01-11 11:50:03 -05:00
bilucodota 1d4917ec58 - Support complex keys, such as yaml/json files (#173) 2021-01-11 11:47:51 -05:00
Jason O'Donnell 2fb78ab91e Update to v2.1.1 (#168) 2020-12-15 11:55:39 -05:00
dependabot[bot] c261a0ad69 chore(deps): bump ini from 1.3.5 to 1.3.8 (#167)
Bumps [ini](https://github.com/isaacs/ini) from 1.3.5 to 1.3.8.
- [Release notes](https://github.com/isaacs/ini/releases)
- [Commits](https://github.com/isaacs/ini/compare/v1.3.5...v1.3.8)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-12-15 11:17:21 -05:00
Jon L 6ac603b23e bump readme to action v2.1.0 (#157) 2020-12-15 11:12:08 -05:00
dependabot[bot] 638924aeb4 chore(deps-dev): bump @types/jest from 26.0.14 to 26.0.19 (#164)
Bumps [@types/jest](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jest) from 26.0.14 to 26.0.19.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jest)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-12-15 11:09:42 -05:00
dependabot[bot] 668d59f96b chore(deps): bump got from 11.7.0 to 11.8.1 (#163)
Bumps [got](https://github.com/sindresorhus/got) from 11.7.0 to 11.8.1.
- [Release notes](https://github.com/sindresorhus/got/releases)
- [Commits](https://github.com/sindresorhus/got/compare/v11.7.0...v11.8.1)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-12-15 11:09:17 -05:00
dependabot[bot] 208b49ff6c chore(deps-dev): bump semantic-release from 17.1.2 to 17.3.0 (#158)
Bumps [semantic-release](https://github.com/semantic-release/semantic-release) from 17.1.2 to 17.3.0.
- [Release notes](https://github.com/semantic-release/semantic-release/releases)
- [Commits](https://github.com/semantic-release/semantic-release/compare/v17.1.2...v17.3.0)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-12-15 11:08:50 -05:00
dependabot[bot] 53c0f5bcca chore(deps-dev): bump jest from 26.5.0 to 26.6.3 (#150)
Bumps [jest](https://github.com/facebook/jest) from 26.5.0 to 26.6.3.
- [Release notes](https://github.com/facebook/jest/releases)
- [Changelog](https://github.com/facebook/jest/blob/master/CHANGELOG.md)
- [Commits](https://github.com/facebook/jest/compare/v26.5.0...v26.6.3)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-12-15 11:04:07 -05:00
Jason O'Donnell b4cef0fa36 Revert "chore(deps-dev): bump jest-when from 2.7.2 to 3.0.1 (#147)" (#166)
This reverts commit 7bc0a10ff8.
2020-12-15 11:00:26 -05:00
dependabot[bot] 7bc0a10ff8 chore(deps-dev): bump jest-when from 2.7.2 to 3.0.1 (#147)
Bumps [jest-when](https://github.com/timkindberg/jest-when) from 2.7.2 to 3.0.1.
- [Release notes](https://github.com/timkindberg/jest-when/releases)
- [Commits](https://github.com/timkindberg/jest-when/compare/v2.7.2...v3.0.1)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-12-15 10:15:59 -05:00
Tom Proctor e5febde8e7 Update jira sync github action (#151) 2020-11-18 10:49:47 +00:00
Jason O'Donnell 2ca76a4465 changelog++ 2020-10-06 13:18:57 -04:00
Jason O'Donnell 5b42d37bab Update to v2.0.2 (#133) 2020-10-06 13:15:24 -04:00
dependabot[bot] 124e6eecdb chore(deps-dev): bump jest from 26.4.2 to 26.5.0 (#132)
Bumps [jest](https://github.com/facebook/jest) from 26.4.2 to 26.5.0.
- [Release notes](https://github.com/facebook/jest/releases)
- [Changelog](https://github.com/facebook/jest/blob/master/CHANGELOG.md)
- [Commits](https://github.com/facebook/jest/compare/v26.4.2...v26.5.0)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-10-06 11:06:25 -04:00
dependabot[bot] 43c4212f70 chore(deps-dev): bump @types/jest from 26.0.13 to 26.0.14 (#123)
Bumps [@types/jest](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jest) from 26.0.13 to 26.0.14.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jest)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-10-01 10:33:41 -04:00
dependabot[bot] d4487e4dd0 chore(deps-dev): bump semantic-release from 17.1.1 to 17.1.2 (#124)
Bumps [semantic-release](https://github.com/semantic-release/semantic-release) from 17.1.1 to 17.1.2.
- [Release notes](https://github.com/semantic-release/semantic-release/releases)
- [Commits](https://github.com/semantic-release/semantic-release/compare/v17.1.1...v17.1.2)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-10-01 10:32:59 -04:00
dependabot[bot] c7f47bbfcf chore(deps): bump got from 11.6.2 to 11.7.0 (#126)
Bumps [got](https://github.com/sindresorhus/got) from 11.6.2 to 11.7.0.
- [Release notes](https://github.com/sindresorhus/got/releases)
- [Commits](https://github.com/sindresorhus/got/compare/v11.6.2...v11.7.0)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-10-01 10:32:32 -04:00
dependabot[bot] 11e2f12f99 chore(deps-dev): bump @actions/core from 1.2.5 to 1.2.6 (#130)
Bumps [@actions/core](https://github.com/actions/toolkit/tree/HEAD/packages/core) from 1.2.5 to 1.2.6.
- [Release notes](https://github.com/actions/toolkit/releases)
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/core/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/core)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-10-01 10:30:25 -04:00
Jason O'Donnell 6c64e41adc changelog++ 2020-10-01 10:23:30 -04:00
ZANCO Bertrand 2f76ad395b Add ability to export Vault Token (#127)
* Add export Vault Token

* Set correct condition for default value

* Add test for exportToken
Fix key with dash

* Restore index.js
2020-10-01 10:22:10 -04:00
Jason O'Donnell 307c9ae581 Add pull_request_target to build action (#129)
* Add pull_request_target to build action

* Remove pull_request from action

* Remove branch specification

* Update as per review
2020-09-23 09:48:24 -04:00
Benjamin Rumble b35ef16370 specify version (#122)
* specify version 

Without specifying `@v2.0.0` GitHub says the string is not the correct format

``` 
The workflow is not valid. .github/workflows/integration_tests.yml (Line: 10, Col: 15): Expected format {org}/{repo}[/path]@ref. Actual 'hashicorp/vault-action',Input string was not in a correct format.```

* v2.0.1

Co-authored-by: Jason O'Donnell <2160810+jasonodonnell@users.noreply.github.com>

Co-authored-by: Jason O'Donnell <2160810+jasonodonnell@users.noreply.github.com>
2020-09-22 13:44:55 -04:00
Jason O'Donnell 952d5d48e4 Update to v2.0.1 (#121)
* Update to v2.0.1

* Update changelog
2020-09-15 14:58:16 -04:00
Calvin Leung Huang 649323229c dep: update kind-of to version 6.0.3 (#120) 2020-09-14 14:56:40 -07:00
Calvin Leung Huang 35be1a3b49 dep: update dev dependencies (#119) 2020-09-14 14:45:38 -07:00
Calvin Leung Huang d81a7a778d dep: update jsonata to version 1.8.3 (#118) 2020-09-14 13:01:47 -07:00
dependabot[bot] 3a8d733522 chore(deps-dev): bump @actions/core from 1.2.3 to 1.2.5 (#115) 2020-09-14 19:09:17 +00:00
dependabot[bot] 1db79efc8e chore(deps-dev): bump @types/jest from 25.1.5 to 26.0.13 (#114) 2020-09-14 19:04:49 +00:00
dependabot[bot] 488fc1ce12 chore(deps): bump got from 11.5.1 to 11.6.2 (#117) 2020-09-14 18:58:09 +00:00
dependabot[bot] 722353f009 chore(deps-dev): bump jest from 25.2.7 to 26.4.2 (#116) 2020-09-14 18:54:02 +00:00
Calvin Leung Huang 20a8e522c2 Create dependabot.yml (#113) 2020-09-14 11:45:15 -07:00
dependabot[bot] 35e0a09f2c chore(deps): bump npm from 6.14.4 to 6.14.8 (#112) 2020-09-14 18:17:04 +00:00
dependabot[bot] 5cb0f68cdc chore(deps): bump lodash from 4.17.15 to 4.17.20 (#111)
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.15 to 4.17.20.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.15...4.17.20)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-09-14 11:11:03 -07:00
dependabot[bot] 2977272bf8 chore(deps): bump node-fetch from 2.6.0 to 2.6.1 (#110) 2020-09-14 17:43:06 +00:00
Tom Proctor 2c1083c570 Update Jira sync action versions (#109)
These versions bring a few fixes:
* The action now supports converting the most common bits of markdown syntax into Jira formatting directives
* Replaces Atlassian's comment action, which tries to interpolate bits of text from comments wrapped in {{ github.event_name }} as templates, usually causing an error (in the case I've put there, it will replace the template with `pull_request_target`)
* Remove trailing comma after link that broke the link target Jira selects
2020-09-14 13:06:53 -04:00
Tom Proctor 401e08df03 Add Jira sync workflow (#107) 2020-08-28 10:46:33 +01:00
Jason O'Donnell e27b45646f Update action.yml 2020-08-24 19:22:08 -04:00
Jason O'Donnell 76ca623af3 changelog++ 2020-08-24 19:19:56 -04:00
Jason O'Donnell c8b383ee4e Update doc for TLS (#103) 2020-08-12 11:53:00 -04:00
Jason O'Donnell a214c8c65a changelog++ 2020-08-11 11:14:10 -04:00
Jason O'Donnell f7f0d5a289 Simplify secret request UX (#102)
* Simplify secret UX

* Update doc

* Fix tests
2020-08-11 10:06:28 -04:00
Jason O'Donnell 633de935e7 changelog++ 2020-08-10 11:11:00 -04:00
Jason O'Donnell 5de67274a5 Merge pull request #101 from hashicorp/tlsSkipVerify
Fix bug with tlsSkipVerify and add test coverage
2020-08-07 16:15:00 -04:00
Jason O'Donnell e031fa076e Add missing comment 2020-08-07 15:50:35 -04:00
Jason O'Donnell e5ef6c9c11 Fix bug with tlsSkipVerify and add test coverage 2020-08-07 14:57:44 -04:00
Jason O'Donnell 6cf013b5c0 Merge pull request #100 from hashicorp/build
Update build
2020-08-07 14:41:08 -04:00
Jason O'Donnell 098ee568ed Update build 2020-08-07 14:11:20 -04:00
Jason O'Donnell e055dfd1a4 Update build 2020-08-07 14:02:44 -04:00
Jason O'Donnell b3a02289e7 Merge pull request #97 from hashicorp/tls
Add TLS and mTLS
2020-08-06 14:30:53 -04:00
Jason O'Donnell 683c9b2557 Add toLower and type equality check 2020-08-06 11:10:44 -04:00
Jason O'Donnell e59c94afbe Add TLS and mTLS support 2020-08-05 16:36:27 -04:00
Jason O'Donnell cd01494ae2 Merge pull request #96 from jweissig/patch-1
Updated README.md
2020-08-05 13:12:54 -04:00
Justin Weissig a2d854da53 Updated README.md
Minor spelling and grammar tweaks.
2020-07-31 14:33:00 -07:00
Jim Kalafut d1321fc438 Update README.md 2020-07-31 14:17:53 -07:00
Jim Kalafut 5fb792e09f Merge pull request #95 from hashicorp/readme
Update repository
2020-07-31 14:13:29 -07:00
Jason O'Donnell c63c61cd7e Comment out publish workflow 2020-07-31 16:52:29 -04:00
Jason O'Donnell 944a2bea12 Add CHANGELOG 2020-07-31 16:45:59 -04:00
Jason O'Donnell 2f554c06ec Update README 2020-07-31 16:45:04 -04:00
dependabot-preview[bot] 25ecb3dd46 chore(deps-dev): bump semantic-release from 17.0.4 to 17.0.6 (#46)
Bumps [semantic-release](https://github.com/semantic-release/semantic-release) from 17.0.4 to 17.0.6.
- [Release notes](https://github.com/semantic-release/semantic-release/releases)
- [Commits](https://github.com/semantic-release/semantic-release/compare/v17.0.4...v17.0.6)

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

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-04-17 10:40:23 -05:00
Richard Simpson 734d76c388 Update issue templates 2020-04-12 00:20:00 -05:00
33 changed files with 12367 additions and 7390 deletions
-1
View File
@@ -1 +0,0 @@
ko_fi: richicoder
+23
View File
@@ -0,0 +1,23 @@
---
name: Bug report
about: Create a report to help us improve
title: "[BUG] "
labels: bug
assignees: RichiCoder1
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
The yaml of the `vault-action` step, with any sensitive information masked or removed.
**Expected behavior**
A clear and concise description of what you expected to happen.
**Log Output**
For the most verbose logs, [add a secret called `ACTIONS_STEP_DEBUG` with the value `true`](https://github.com/actions/toolkit/blob/master/docs/action-debugging.md). Then, re-run the workflow if possible and post the *raw logs* for the step here with any sensitive information masked or removed.
**Additional context**
Add any other context about the problem here.
+20
View File
@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: "[FEAT] "
labels: enhancement
assignees: RichiCoder1
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
+11
View File
@@ -0,0 +1,11 @@
# 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:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "npm" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "daily"
+210 -89
View File
@@ -2,167 +2,288 @@ on:
push: push:
branches: branches:
- master - master
pull_request: pull_request_target:
types: [opened, reopened, synchronize]
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
- uses: actions/setup-node@v1 - uses: actions/setup-node@v1
with: with:
node-version: '' node-version: ''
- name: setup npm cache
- name: Setup NPM Cache
uses: actions/cache@v1 uses: actions/cache@v1
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
integration: integrationOSS:
runs-on: ubuntu-latest runs-on: ubuntu-latest
services: steps:
vaultBasic: - uses: actions/checkout@v1
image: vault:1.2.3
ports: - name: Run docker-compose
- 8200/tcp run: docker-compose up -d vault
env:
VAULT_DEV_ROOT_TOKEN_ID: testtoken - uses: actions/setup-node@v1
options: --cap-add=IPC_LOCK with:
vaultEnterprise: node-version: ''
image: hashicorp/vault-enterprise:1.3.0_ent
ports: - name: Setup NPM Cache
- 8200/tcp uses: actions/cache@v1
env: with:
VAULT_DEV_ROOT_TOKEN_ID: testtoken path: ~/.npm
options: --cap-add=IPC_LOCK key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: NPM Install
run: npm ci
- name: NPM Build
run: npm run build
- name: NPM Run test;integration:basic
run: npm run test:integration:basic
env:
VAULT_HOST: localhost
VAULT_PORT: 8200
CI: true
integrationEnterprise:
runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
- uses: actions/setup-node@v1
with: - name: Run docker-compose
node-version: '' run: docker-compose up -d vault-enterprise
- name: setup npm cache env:
uses: actions/cache@v1 VAULT_LICENSE_CI: ${{ secrets.VAULT_LICENSE_CI }}
with:
path: ~/.npm - uses: actions/setup-node@v1
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} with:
restore-keys: | node-version: ''
${{ runner.os }}-node-
- name: npm install - name: Setup NPM Cache
run: npm ci uses: actions/cache@v1
- name: npm build with:
run: npm run build path: ~/.npm
- name: npm run test:integration:basic key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
run: npm run test:integration:basic restore-keys: |
env: ${{ runner.os }}-node-
VAULT_HOST: localhost
VAULT_PORT: ${{ job.services.vaultBasic.ports[8200] }} - name: NPM Install
CI: true run: npm ci
- name: npm run test:integration:enterprise
run: npm run test:integration:enterprise - name: NPM Build
env: run: npm run build
VAULT_HOST: localhost
VAULT_PORT: ${{ job.services.vaultEnterprise.ports[8200] }} - name: NPM Run test:integration:enterprise
CI: true run: npm run test:integration:enterprise
env:
VAULT_HOST: localhost
VAULT_PORT: 8200
CI: true
e2e: e2e:
runs-on: ubuntu-latest runs-on: ubuntu-latest
services:
vault:
image: vault:1.3.0
ports:
- 8200/tcp
env:
VAULT_DEV_ROOT_TOKEN_ID: testtoken
options: --cap-add=IPC_LOCK
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
- name: Run docker-compose
run: docker-compose up -d vault
- uses: actions/setup-node@v1 - uses: actions/setup-node@v1
with: with:
node-version: '' node-version: ''
- name: setup npm cache
- name: Setup NPM Cache
uses: actions/cache@v1 uses: actions/cache@v1
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: ${{ job.services.vault.ports[8200] }} VAULT_PORT: 8200
- name: use vault action (default K/V version 2)
- name: Test Vault Action (default KV V2)
uses: ./ uses: ./
id: kv-secrets id: kv-secrets
with: with:
url: http://localhost:${{ job.services.vault.ports[8200] }} url: http://localhost:8200
token: testtoken token: testtoken
secrets: | secrets: |
test secret ; secret/data/test secret ;
test secret | NAMED_SECRET ; secret/data/test secret | NAMED_SECRET ;
nested/test otherSecret ; secret/data/nested/test otherSecret ;
- name: use vault action (custom K/V version 1)
- name: Test Vault Action (default KV V1)
uses: ./ uses: ./
with: with:
url: http://localhost:${{ job.services.vault.ports[8200] }} url: http://localhost:8200
token: testtoken token: testtoken
path: my-secret
kv-version: 1
secrets: | secrets: |
test altSecret ; my-secret/test altSecret ;
test altSecret | NAMED_ALTSECRET ; my-secret/test altSecret | NAMED_ALTSECRET ;
nested/test otherAltSecret ; my-secret/nested/test otherAltSecret ;
- name: use vault action (using cubbyhole engine)
- name: Test Vault Action (cubbyhole)
uses: ./ uses: ./
with: with:
url: http://localhost:${{ job.services.vault.ports[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 ;
- name: verify
- name: Verify Vault Action Outputs
run: npm run test:e2e run: npm run test:e2e
env: env:
OTHER_SECRET_OUTPUT: ${{ steps.kv-secrets.outputs.otherSecret }} OTHER_SECRET_OUTPUT: ${{ steps.kv-secrets.outputs.otherSecret }}
publish: e2e-tls:
if: github.event_name == 'push' && contains(github.ref, 'master')
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [build, integration, e2e]
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
- name: Run docker-compose
run: docker-compose up -d vault-tls
- uses: actions/setup-node@v1 - uses: actions/setup-node@v1
with: with:
node-version: '' node-version: ''
- name: setup npm cache
- name: Setup NPM Cache
uses: actions/cache@v1 uses: actions/cache@v1
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
run: npm ci - name: NPM Install
- name: release run: npm ci
if: success() && endsWith(github.ref, 'master')
run: npx semantic-release - name: NPM Build
env: run: npm run build
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - name: Setup Vault
run: node ./integrationTests/e2e-tls/setup.js
env:
VAULT_HOST: localhost
VAULT_PORT: 8200
VAULTCA: ${{ secrets.VAULTCA }}
VAULT_CLIENT_CERT: ${{ secrets.VAULT_CLIENT_CERT }}
VAULT_CLIENT_KEY: ${{ secrets.VAULT_CLIENT_KEY }}
- name: Test Vault Action (default KV V2)
uses: ./
id: kv-secrets
with:
url: https://localhost:8200
token: ${{ env.VAULT_TOKEN }}
caCertificate: ${{ secrets.VAULTCA }}
clientCertificate: ${{ secrets.VAULT_CLIENT_CERT }}
clientKey: ${{ secrets.VAULT_CLIENT_KEY }}
secrets: |
secret/data/test secret ;
secret/data/test secret | NAMED_SECRET ;
secret/data/nested/test otherSecret ;
- name: Test Vault Action (tlsSkipVerify)
uses: ./
with:
url: https://localhost:8200
token: ${{ env.VAULT_TOKEN }}
tlsSkipVerify: true
clientCertificate: ${{ secrets.VAULT_CLIENT_CERT }}
clientKey: ${{ secrets.VAULT_CLIENT_KEY }}
secrets: |
secret/data/tlsSkipVerify skip ;
- name: Test Vault Action (default KV V1)
uses: ./
with:
url: https://localhost:8200
token: ${{ env.VAULT_TOKEN }}
caCertificate: ${{ secrets.VAULTCA }}
clientCertificate: ${{ secrets.VAULT_CLIENT_CERT }}
clientKey: ${{ secrets.VAULT_CLIENT_KEY }}
secrets: |
my-secret/test altSecret ;
my-secret/test altSecret | NAMED_ALTSECRET ;
my-secret/nested/test otherAltSecret ;
- name: Test Vault Action (cubbyhole)
uses: ./
with:
url: https://localhost:8200
token: ${{ env.VAULT_TOKEN }}
secrets: |
/cubbyhole/test foo ;
/cubbyhole/test zip | NAMED_CUBBYSECRET ;
caCertificate: ${{ secrets.VAULTCA }}
clientCertificate: ${{ secrets.VAULT_CLIENT_CERT }}
clientKey: ${{ secrets.VAULT_CLIENT_KEY }}
- name: Verify Vault Action Outputs
run: npm run test:e2e-tls
env:
OTHER_SECRET_OUTPUT: ${{ steps.kv-secrets.outputs.otherSecret }}
# Removing publish step for now.
# publish:
# if: github.event_name == 'push' && contains(github.ref, 'master')
# runs-on: ubuntu-latest
# needs: [build, integration, e2e]
# steps:
# - uses: actions/checkout@v1
# - uses: actions/setup-node@v1
# with:
# node-version: ''
# - name: setup npm cache
# uses: actions/cache@v1
# with:
# path: ~/.npm
# key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
# restore-keys: |
# ${{ runner.os }}-node-
# - name: npm install
# run: npm ci
# - name: release
# if: success() && endsWith(github.ref, 'master')
# run: npx semantic-release
# env:
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
+87
View File
@@ -0,0 +1,87 @@
on:
issues:
types: [opened, closed, deleted, reopened]
pull_request_target:
types: [opened, closed, reopened]
issue_comment: # Also triggers when commenting on a PR from the conversation view
types: [created]
name: Jira Sync
jobs:
sync:
runs-on: ubuntu-latest
name: Jira sync
steps:
- name: Check if community user
if: github.event.action == 'opened'
id: vault-team-role
run: |
TEAM=vault
ROLE="$(hub api orgs/hashicorp/teams/${TEAM}/memberships/${{ github.actor }} | jq -r '.role | select(.!=null)')"
if [[ -n ${ROLE} ]]; then
echo "Actor ${{ github.actor }} is a ${TEAM} team member, skipping ticket creation"
else
echo "Actor ${{ github.actor }} is not a ${TEAM} team member"
fi
echo "::set-output name=role::${ROLE}"
env:
GITHUB_TOKEN: ${{ secrets.JIRA_SYNC_GITHUB_TOKEN }}
- name: Login
uses: atlassian/gajira-login@v2.0.0
env:
JIRA_BASE_URL: ${{ secrets.JIRA_SYNC_BASE_URL }}
JIRA_USER_EMAIL: ${{ secrets.JIRA_SYNC_USER_EMAIL }}
JIRA_API_TOKEN: ${{ secrets.JIRA_SYNC_API_TOKEN }}
- name: Preprocess
if: github.event.action == 'opened' || github.event.action == 'created'
id: preprocess
run: |
if [[ "${{ github.event_name }}" == "pull_request_target" ]]; then
echo "::set-output name=type::PR"
else
echo "::set-output name=type::ISS"
fi
- name: Create ticket
if: github.event.action == 'opened' && !steps.vault-team-role.outputs.role
uses: tomhjp/gh-action-jira-create@v0.2.0
with:
project: VAULT
issuetype: "GH Issue"
summary: "${{ github.event.repository.name }} [${{ steps.preprocess.outputs.type }} #${{ github.event.issue.number || github.event.pull_request.number }}]: ${{ github.event.issue.title || github.event.pull_request.title }}"
description: "${{ github.event.issue.body || github.event.pull_request.body }}\n\n_Created from GitHub Action for ${{ github.event.issue.html_url || github.event.pull_request.html_url }} from ${{ github.actor }}_"
# customfield_10089 is Issue Link custom field
# customfield_10091 is team custom field
extraFields: '{"fixVersions": [{"name": "TBD"}], "customfield_10091": ["ecosystem", "runtime"], "customfield_10089": "${{ github.event.issue.html_url || github.event.pull_request.html_url }}"}'
- name: Search
if: github.event.action != 'opened'
id: search
uses: tomhjp/gh-action-jira-search@v0.2.1
with:
# cf[10089] is Issue Link custom field
jql: 'project = "VAULT" and issuetype = "GH Issue" and cf[10089]="${{ github.event.issue.html_url || github.event.pull_request.html_url }}"'
- name: Sync comment
if: github.event.action == 'created' && steps.search.outputs.issue
uses: tomhjp/gh-action-jira-comment@v0.2.0
with:
issue: ${{ steps.search.outputs.issue }}
comment: "${{ github.actor }} ${{ github.event.review.state || 'commented' }}:\n\n${{ github.event.comment.body || github.event.review.body }}\n\n${{ github.event.comment.html_url || github.event.review.html_url }}"
- name: Close ticket
if: (github.event.action == 'closed' || github.event.action == 'deleted') && steps.search.outputs.issue
uses: atlassian/gajira-transition@v2.0.1
with:
issue: ${{ steps.search.outputs.issue }}
transition: Done
- name: Reopen ticket
if: github.event.action == 'reopened' && steps.search.outputs.issue
uses: atlassian/gajira-transition@v2.0.1
with:
issue: ${{ steps.search.outputs.issue }}
transition: "To Do"
+70
View File
@@ -0,0 +1,70 @@
## Unreleased
## 2.3.1 (August 18th, 2021)
Improvements:
* bump normalize-url from 4.5.0 to 4.5.1 [GH-227](https://github.com/hashicorp/vault-action/pull/227)
* bump path-parse from 1.0.6 to 1.0.7 [GH-239](https://github.com/hashicorp/vault-action/pull/239)
## 2.3.0 (June 23rd, 2021)
Features:
* K8s auth method is now supported [GH-218](https://github.com/hashicorp/vault-action/pull/218)
* Custom auth method mount points is configurable [GH-218](https://github.com/hashicorp/vault-action/pull/218)
## 2.2.0 (May 6th, 2021)
Security:
* multi-line secrets are now properly masked in logs [GH-208](https://github.com/hashicorp/vault-action/pull/208)
[CVE-2021-32074](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-32074)
Features:
* JWT auth method is now supported [GH-188](https://github.com/hashicorp/vault-action/pull/188)
## 2.1.2 (January 21st, 2021)
Bugs:
* fixed bug where newlines were being rendered for multi-line secrets [GH-173](https://github.com/hashicorp/vault-action/pull/173)
## 2.1.1 (December 15th, 2020)
Improvements:
* bump jest from 26.5.0 to 26.6.3 [GH-150](https://github.com/hashicorp/vault-action/pull/150)
* bump semantic-release from 17.1.2 to 17.3.0 [GH-158](https://github.com/hashicorp/vault-action/pull/158)
* bump got from 11.7.0 to 11.8.1 [GH-163](https://github.com/hashicorp/vault-action/pull/163)
* bump @types/jest from 26.0.14 to 26.0.19 [GH-164](https://github.com/hashicorp/vault-action/pull/164)
* bump ini from 1.3.5 to 1.3.8 [GH-167](https://github.com/hashicorp/vault-action/pull/167)
## 2.1.0 (October 6th, 2020)
Features:
* Added `exportToken` to share the Vault token as an environment variable [GH-127](https://github.com/hashicorp/vault-action/pull/127)
Security:
* `action/core` updated to 1.2.6 to address minor CVE [GH-130](https://github.com/hashicorp/vault-action/pull/130)
## 2.0.1 (September 15th, 2020)
Improvements:
* bump node-fetch from 2.6.0 to 2.6.1 [GH-110](https://github.com/hashicorp/vault-action/pull/110)
* bump lodash from 4.17.15 to 4.17.20 [GH-111](https://github.com/hashicorp/vault-action/pull/111)
* bump npm from 6.14.4 to 6.14.8 [GH-112](https://github.com/hashicorp/vault-action/pull/112)
* bump @types/jest from 25.1.5 to 26.0.13 [GH-114](https://github.com/hashicorp/vault-action/pull/114)
* bump @actions/core from 1.2.3 to 1.2.5 [GH-115](https://github.com/hashicorp/vault-action/pull/115)
* bump jest from 25.2.7 to 26.4.2 [GH-116](https://github.com/hashicorp/vault-action/pull/116)
* bump got from 11.5.1 to 11.6.2 [GH-117](https://github.com/hashicorp/vault-action/pull/117)
* update jsonata to version 1.8.3 [GH-118](https://github.com/hashicorp/vault-action/pull/118)
* update dev dependencies [GH-119](https://github.com/hashicorp/vault-action/pull/119)
* update kind-of to version 6.0.3 [GH-120](https://github.com/hashicorp/vault-action/pull/120)
## 2.0.0 (August 24th, 2020)
Features:
* Added TLS and mTLS support [GH-97](https://github.com/hashicorp/vault-action/pull/97)
Improvements:
* Breaking change: removed KV specific parameters and generalized secret UX [GH-102](https://github.com/hashicorp/vault-action/pull/102)
Bugs:
+96 -115
View File
@@ -1,27 +1,29 @@
# vault-action # Vault GitHub Action
---
**Please note**: We take Vault's security and our users' trust very seriously. If you believe you have found a security issue in Vault or this Vault Action, _please responsibly disclose_ by contacting us at [security@hashicorp.com](mailto:security@hashicorp.com).
---
A helper action for easily pulling secrets from HashiCorp Vault™. A helper action for easily pulling secrets from HashiCorp Vault™.
By default, this action pulls from [Version 2](https://www.vaultproject.io/docs/secrets/kv/kv-v2/) of the K/V Engine. See examples below for how to [use v1](#using-kv-version-1) as well as [other non-K/V engines](#other-secret-engines).
<!-- TOC --> <!-- TOC -->
- [Example Usage](#example-usage) - [Vault GitHub Action](#vault-github-action)
- [Authentication method](#authentication-method) - [Example Usage](#example-usage)
- [Key Syntax](#key-syntax) - [Authentication method](#authentication-method)
- [Key Syntax](#key-syntax)
- [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)
- [Nested Secrets](#nested-secrets) - [Other Secret Engines](#other-secret-engines)
- [Using K/V version 1](#using-kv-version-1) - [Adding Extra Headers](#adding-extra-headers)
- [Custom K/V Engine Path](#custom-kv-engine-path) - [Vault Enterprise Features](#vault-enterprise-features)
- [Other Secret Engines](#other-secret-engines)
- [Adding Extra Headers](#adding-extra-headers)
- [Vault Enterprise Features](#vault-enterprise-features)
- [Namespace](#namespace) - [Namespace](#namespace)
- [Reference](#reference) - [Reference](#reference)
- [Masking - Hiding Secrets from Logs](#masking---hiding-secrets-from-logs) - [Masking - Hiding Secrets from Logs](#masking---hiding-secrets-from-logs)
- [Normalization](#normalization) - [Normalization](#normalization)
<!-- /TOC --> <!-- /TOC -->
@@ -34,14 +36,15 @@ jobs:
steps: steps:
# ... # ...
- name: Import Secrets - name: Import Secrets
uses: RichiCoder1/vault-action uses: hashicorp/vault-action@v2.3.1
with: with:
url: https://vault.mycompany.com:8200 url: https://vault.mycompany.com:8200
token: ${{ secrets.VaultToken }} token: ${{ secrets.VaultToken }}
caCertificate: ${{ secrets.VAULTCA }}
secrets: | secrets: |
ci/aws accessKey | AWS_ACCESS_KEY_ID ; secret/data/ci/aws accessKey | AWS_ACCESS_KEY_ID ;
ci/aws secretKey | AWS_SECRET_ACCESS_KEY ; secret/data/ci/aws secretKey | AWS_SECRET_ACCESS_KEY ;
ci npm_token secret/data/ci npm_token
# ... # ...
``` ```
@@ -55,6 +58,7 @@ While most workflows will likely use a vault token, you can also use an `approle
with: with:
url: https://vault.mycompany.com:8200 url: https://vault.mycompany.com:8200
token: ${{ secrets.VaultToken }} token: ${{ secrets.VaultToken }}
caCertificate: ${{ secrets.VAULTCA }}
``` ```
- **approle**: you must provide a `roleId` & `secretId` parameter - **approle**: you must provide a `roleId` & `secretId` parameter
```yaml ```yaml
@@ -64,14 +68,43 @@ with:
method: approle method: approle
roleId: ${{ secrets.roleId }} roleId: ${{ secrets.roleId }}
secretId: ${{ secrets.secretId }} secretId: ${{ secrets.secretId }}
caCertificate: ${{ secrets.VAULTCA }}
``` ```
- **github**: you must provide the github token as `githubToken` - **github**: you must provide the github token as `githubToken`
**Notice: [Vault GitHub authentication](https://www.vaultproject.io/docs/auth/github)
requires `read:org` permissions for authentication. The auto-generated `GITHUB_TOKEN`
created for projects does not have these permissions and GitHub does not allow this
token's permissions to be modified. A new GitHub Token secret must be created with
`read:org` permissions to use this authentication method.**
```yaml ```yaml
... ...
with: with:
url: https://vault.mycompany.com:8200 url: https://vault.mycompany.com:8200
method: github method: github
githubToken: ${{ secrets.GITHUB_TOKEN }} githubToken: ${{ secrets.MY_GITHUB_TOKEN }}
caCertificate: ${{ secrets.VAULTCA }}
```
- **jwt**: you must provide a `role` & `jwtPrivateKey` parameters, additionally you can pass `jwtKeyPassword` & `jwtTtl` parameters
```yaml
...
with:
url: https://vault.mycompany.com:8200
method: jwt
role: github-action
jwtPrivateKey: ${{ secrets.JWT_PRIVATE_KEY }}
jwtKeyPassword: ${{ secrets.JWT_KEY_PASS }}
jwtTtl: 3600 # 1 hour, default value
```
- **kubernetes**: you must provide the `role` paramaters. You can optionally override the `kubernetesTokenPath` paramater for custom mounted serviceAccounts. Consider [kubernetes auth](https://www.vaultproject.io/docs/auth/kubernetes) when using self-hosted runners on Kubernetes:
```yaml
...
with:
url: https://vault.mycompany.com:8200
method: kubernetes
role: ${{ secrets.KUBE_ROLE }}
``` ```
If any other method is specified and you provide an `authPayload`, the action will attempt to `POST` to `auth/${method}/login` with the provided payload and parse out the client token. If any other method is specified and you provide an `authPayload`, the action will attempt to `POST` to `auth/${method}/login` with the provided payload and parse out the client token.
@@ -80,7 +113,7 @@ If any other method is specified and you provide an `authPayload`, the action wi
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 is comprised 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.
```raw ```raw
{{ Secret Path }} {{ Secret Key or Selector }} | {{ Env/Output Variable Name }} {{ Secret Path }} {{ Secret Key or Selector }} | {{ Env/Output Variable Name }}
@@ -88,11 +121,11 @@ Each secret request is comprised of the `path` and the `key` of the desired secr
### Simple Key ### Simple Key
To retrieve a key `npmToken` from path `ci` that has value `somelongtoken` from vault you could do: To retrieve a key `npmToken` from path `secret/data/ci` that has value `somelongtoken` from vault you could do:
```yaml ```yaml
with: with:
secrets: 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:
@@ -122,7 +155,7 @@ However, if you want to set it to a specific name, say `NPM_TOKEN`, you could do
```yaml ```yaml
with: with:
secrets: 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:
@@ -149,65 +182,18 @@ This action can take multi-line input, so say you had your AWS keys stored in a
```yaml ```yaml
with: with:
secrets: | secrets: |
ci/aws accessKey | AWS_ACCESS_KEY_ID ; secret/data/ci/aws accessKey | AWS_ACCESS_KEY_ID ;
ci/aws secretKey | AWS_SECRET_ACCESS_KEY secret/data/ci/aws secretKey | AWS_SECRET_ACCESS_KEY
``` ```
### Nested Secrets
By default, `vault-action` will read the key from `data.data` in the response for the K/V v2 engine (default), or `data` for K/V v1 and other Secret Engines (see below for more info).
If you need to retrieve a sub-key from a JSON document, or are interested in some other component of the Vault response, you can specify a different key as the path to the desired out.
_**Important**_: You must specify an [Output Variable Name](#set-output-variable-name) when using this method.
```yaml
with:
secrets: |
my/path pair.key | NESTED_SECRET ;
```
Under the covers, we're using [JSONata](https://jsonata.org/) to provide the querying functionality. Any valid JSONata syntax is valid here, and will be outputed as a `JSON.stringify`-ied result.
### Using K/V version 1
By default, `vault-action` expects a K/V engine using [version 2](https://www.vaultproject.io/docs/secrets/kv/kv-v2.html).
In order to work with a [v1 engine](https://www.vaultproject.io/docs/secrets/kv/kv-v1/), the `kv-version` parameter may be passed:
```yaml
with:
kv-version: 1
```
## Custom K/V Engine Path
When you enable the K/V Engine, by default it's placed at the path `secret`, so a secret named `ci` will be accessed from `secret/ci`. However, [if you enabled the secrets engine using a custom `path`](https://www.vaultproject.io/docs/commands/secrets/enable/#inlinecode--path-4), you
can pass it as follows:
```yaml
with:
path: my-secrets
secrets: ci npmToken
```
This way, the `ci` secret in the example above will be retrieved from `my-secrets/ci`.
## Other Secret Engines ## Other Secret Engines
While this action primarily supports the K/V engine, it is possible to request secrets from other engines in Vault. 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
not supported due to their requirement of sending parameters along with the request
(such as `common_name`).
To do so when specifying the `Secret Path`, just append a leading forward slash (`/`) and specify the path as described in the Vault API documentation. For example, to request a secret from the `cubbyhole` secret engine:
For example, to retrieve a stored secret from the [`cubbyhole` engine](https://www.vaultproject.io/api-docs/secret/cubbyhole/), assuming you have a stored secret at the path `foo` with the contents:
```json
{
"foo": "bar",
"zip": "zap"
}
```
You could request the contents like so:
```yaml ```yaml
with: with:
@@ -235,21 +221,6 @@ steps:
run: "my-cli --token '${{ steps.secrets.outputs.MY_KEY }}'" run: "my-cli --token '${{ steps.secrets.outputs.MY_KEY }}'"
``` ```
Secrets pulled from the same `Secret Path` are cached by default. So if you, for example, are using the `aws` engine and retrieve a key, only a single key for a given path is returned.
e.g.:
```yaml
with:
secrets: |
/aws/creds/ci access_key | AWS_ACCESS_KEY_ID ;
/aws/creds/ci secret_key | AWS_SECRET_ACCESS_KEY
```
would work fine.
*NOTE: Per [Nested Secrets](#nested-secrets), the `Key` is pulled from the `data` property of the response.*
## Adding Extra Headers ## Adding Extra Headers
If you ever need to add extra headers to the vault request, say if you need to authenticate with a firewall, all you need to do is set `extraHeaders`: If you ever need to add extra headers to the vault request, say if you need to authenticate with a firewall, all you need to do is set `extraHeaders`:
@@ -257,8 +228,8 @@ If you ever need to add extra headers to the vault request, say if you need to a
```yaml ```yaml
with: with:
secrets: | secrets: |
ci/aws accessKey | AWS_ACCESS_KEY_ID ; secret/ci/aws accessKey | AWS_ACCESS_KEY_ID ;
ci/aws secretKey | AWS_SECRET_ACCESS_KEY secret/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 }}
@@ -276,37 +247,47 @@ If you need to retrieve secrets from a specific Vault namespace, all that's requ
steps: steps:
# ... # ...
- name: Import Secrets - name: Import Secrets
uses: RichiCoder1/vault-action uses: hashicorp/vault-action
with: with:
url: https://vault-enterprise.mycompany.com:8200 url: https://vault-enterprise.mycompany.com:8200
method: token method: token
caCertificate: ${{ secrets.VAULTCA }}
token: ${{ secrets.VaultToken }} token: ${{ secrets.VaultToken }}
namespace: ns1 namespace: ns1
secrets: | secrets: |
ci/aws accessKey | AWS_ACCESS_KEY_ID ; secret/ci/aws accessKey | AWS_ACCESS_KEY_ID ;
ci/aws secretKey | AWS_SECRET_ACCESS_KEY ; secret/ci/aws secretKey | AWS_SECRET_ACCESS_KEY ;
ci npm_token secret/ci npm_token
``` ```
## Reference ## Reference
Here are all the inputs available through `with`: Here are all the inputs available through `with`:
| Input | Description | Default | Required | | Input | Description | Default | Required |
| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | -------- | | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | -------- |
| `url` | The URL for the vault endpoint | | ✔ | | `url` | The URL for the vault endpoint | | ✔ |
| `secrets` | A semicolon-separated list of secrets to retrieve. These will automatically be converted to environmental variable keys. See README for more details | | ✔ | | `secrets` | A semicolon-separated list of secrets to retrieve. These will automatically be converted to environmental variable keys. See README for more details | | ✔ |
| `namespace` | The Vault namespace from which to query secrets. Vault Enterprise only, unset by default | | | | `namespace` | The Vault namespace from which to query secrets. Vault Enterprise only, unset by default | | |
| `path` | The path of a non-default K/V engine | | | | `method` | The method to use to authenticate with Vault. | `token` | |
| `kv-version` | The version of the K/V engine to use. | `2` | | | `role` | Vault role for specified auth method | | |
| `method` | The method to use to authenticate with Vault. | `token` | | | `path` | Custom vault path, if the auth method was enabled at a different path | | |
| `token` | The Vault Token to be used to authenticate with Vault | | | | `token` | The Vault Token to be used to authenticate with Vault | | |
| `roleId` | The Role Id for App Role authentication | | | | `roleId` | The Role Id for App Role authentication | | |
| `secretId` | The Secret Id for App Role authentication | | | | `secretId` | The Secret Id for App Role authentication | | |
| `githubToken` | The Github Token to be used to authenticate with Vault | | | | `githubToken` | The Github Token to be used to authenticate with Vault | | |
| `authPayload` | The JSON payload to be sent to Vault when using a custom authentication method. | | | | `jwtPrivateKey` | Base64 encoded Private key to sign JWT | | |
| `extraHeaders` | A string of newline separated extra headers to include on every request. | | | | `jwtKeyPassword` | Password for key stored in jwtPrivateKey (if needed) | | |
| `exportEnv` | Whether or not export secrets as environment variables. | `true` | | | `jwtTtl` | Time in seconds, after which token expires | | 3600 |
| `kubernetesTokenPath` | The path to the service-account secret with the jwt token for kubernetes based authentication |`/var/run/secrets/kubernetes.io/serviceaccount/token` | |
| `authPayload` | The JSON payload to be sent to Vault when using a custom authentication method. | | |
| `extraHeaders` | A string of newline separated extra headers to include on every request. | | |
| `exportEnv` | Whether or not export secrets as environment variables. | `true` | |
| `exportToken` | Whether or not export Vault token as environment variables (i.e VAULT_TOKEN). | `false` | |
| `caCertificate` | Base64 encoded CA certificate the server certificate was signed with. | | |
| `clientCertificate` | Base64 encoded client certificate the action uses to authenticate with Vault when mTLS is enabled. | | |
| `clientKey` | Base64 encoded client key the action uses to authenticate with Vault when mTLS is enabled. | | |
| `tlsSkipVerify` | When set to true, disables verification of server certificates when testing the action. | `false` | |
## Masking - Hiding Secrets from Logs ## Masking - Hiding Secrets from Logs
@@ -315,4 +296,4 @@ This action uses GitHub Action's built-in masking, so all variables will automat
## Normalization ## Normalization
To make it simpler to consume certain secrets as env vars, if no Env/Output Var Name is specified `vault-action` will replace and `.` chars with `__`, remove any other non-letter or number characters. If you're concerned about the result, it's recommended to provider an explicit Output Var Key. To make it simpler to consume certain secrets as env vars, if no Env/Output Var Name is specified `vault-action` will replace and `.` chars with `__`, remove any other non-letter or number characters. If you're concerned about the result, it's recommended to provide an explicit Output Var Key.
+38 -8
View File
@@ -1,5 +1,5 @@
name: 'Vault Secrets' name: 'Vault Secrets'
description: 'A Github Action that allows you to consume the v2 K/V backend of HashiCorp Vault™ as secure environment variables' description: 'A Github Action that allows you to consume HashiCorp Vault™ secrets as secure environment variables'
inputs: inputs:
url: url:
description: 'The URL for the vault endpoint' description: 'The URL for the vault endpoint'
@@ -10,17 +10,16 @@ inputs:
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
path:
description: 'The path of a non-default K/V engine'
required: false
kv-version:
description: 'The version of the K/V engine to use.'
default: '2'
required: false
method: method:
description: 'The method to use to authenticate with Vault.' description: 'The method to use to authenticate with Vault.'
default: 'token' default: 'token'
required: false required: false
role:
description: 'Vault role for specified auth method'
required: false
path:
description: 'Custom Vault path, if the auth method was mounted at a different path'
required: false
token: token:
description: 'The Vault Token to be used to authenticate with Vault' description: 'The Vault Token to be used to authenticate with Vault'
required: false required: false
@@ -33,6 +32,10 @@ inputs:
githubToken: githubToken:
description: 'The Github Token to be used to authenticate with Vault' description: 'The Github Token to be used to authenticate with Vault'
required: false required: false
kubernetesTokenPath:
description: 'The path to the Kubernetes service account secret'
required: false
default: '/var/run/secrets/kubernetes.io/serviceaccount/token'
authPayload: authPayload:
description: 'The JSON payload to be sent to Vault when using a custom authentication method.' description: 'The JSON payload to be sent to Vault when using a custom authentication method.'
required: false required: false
@@ -43,6 +46,33 @@ inputs:
description: 'Whether or not export secrets as environment variables.' description: 'Whether or not export secrets as environment variables.'
default: 'true' default: 'true'
required: false required: false
exportToken:
description: 'Whether or not export Vault token as environment variables.'
default: 'false'
required: false
caCertificate:
description: 'Base64 encoded CA certificate to verify the Vault server certificate.'
required: false
clientCertificate:
description: 'Base64 encoded client certificate for mTLS communication with the Vault server.'
required: false
clientKey:
description: 'Base64 encoded client key for mTLS communication with the Vault server.'
required: false
tlsSkipVerify:
description: 'When set to true, disables verification of the Vault server certificate. Setting this to true in production is not recommended.'
required: false
default: 'false'
jwtPrivateKey:
description: 'Base64 encoded Private key to sign JWT'
required: false
jwtKeyPassword:
description: 'Password for key stored in jwtPrivateKey (if needed)'
required: false
jwtTtl:
description: 'Time in seconds, after which token expires'
required: false
default: 3600
runs: runs:
using: 'node12' using: 'node12'
main: 'dist/index.js' main: 'dist/index.js'
+6958 -4177
View File
File diff suppressed because one or more lines are too long
+20 -4
View File
@@ -2,16 +2,32 @@
version: "3.0" version: "3.0"
services: services:
vault: vault:
image: vault:1.3.0 image: vault:latest
environment: environment:
VAULT_DEV_ROOT_TOKEN_ID: testtoken VAULT_DEV_ROOT_TOKEN_ID: testtoken
ports: ports:
- 8200:8200 - 8200:8200
privileged: true privileged: true
vault-enterprise: vault-enterprise:
image: hashicorp/vault-enterprise:1.3.0_ent image: hashicorp/vault-enterprise:latest
environment: environment:
VAULT_DEV_ROOT_TOKEN_ID: testtoken VAULT_DEV_ROOT_TOKEN_ID: testtoken
VAULT_LICENSE: ${VAULT_LICENSE_CI}
ports: ports:
- 8201:8200 - 8200:8200
privileged: true privileged: true
vault-tls:
image: vault:latest
hostname: vault-tls
environment:
VAULT_CAPATH: /etc/vault/ca.crt
ports:
- 8200:8200
privileged: true
volumes:
- ${PWD}/integrationTests/e2e-tls/configs:/etc/vault
- vault-data:/var/lib/vault:rw
entrypoint: vault server -config=/etc/vault/config.hcl
volumes:
vault-data:
+54 -32
View File
@@ -37,14 +37,26 @@ describe('integration', () => {
}, },
json: { json: {
data: { data: {
otherSecret: 'OTHERSUPERSECRET', "other-Secret-dash": 'OTHERSUPERSECRET',
},
}
});
await got(`${vaultUrl}/v1/secret/data/foobar`, {
method: 'POST',
headers: {
'X-Vault-Token': 'testtoken',
},
json: {
data: {
fookv2: 'bar',
}, },
} }
}); });
// Enable custom secret engine // Enable custom secret engine
try { try {
await got(`${vaultUrl}/v1/sys/mounts/my-secret`, { await got(`${vaultUrl}/v1/sys/mounts/secret-kv1`, {
method: 'POST', method: 'POST',
headers: { headers: {
'X-Vault-Token': 'testtoken', 'X-Vault-Token': 'testtoken',
@@ -62,7 +74,7 @@ describe('integration', () => {
} }
} }
await got(`${vaultUrl}/v1/my-secret/test`, { await got(`${vaultUrl}/v1/secret-kv1/test`, {
method: 'POST', method: 'POST',
headers: { headers: {
'X-Vault-Token': 'testtoken', 'X-Vault-Token': 'testtoken',
@@ -72,13 +84,23 @@ describe('integration', () => {
} }
}); });
await got(`${vaultUrl}/v1/my-secret/nested/test`, { await got(`${vaultUrl}/v1/secret-kv1/foobar`, {
method: 'POST', method: 'POST',
headers: { headers: {
'X-Vault-Token': 'testtoken', 'X-Vault-Token': 'testtoken',
}, },
json: { json: {
otherSecret: 'OTHERCUSTOMSECRET', fookv1: 'bar',
}
});
await got(`${vaultUrl}/v1/secret-kv1/nested/test`, {
method: 'POST',
headers: {
'X-Vault-Token': 'testtoken',
},
json: {
"other-Secret-dash": 'OTHERCUSTOMSECRET',
}, },
}); });
}); });
@@ -101,20 +123,8 @@ describe('integration', () => {
.mockReturnValueOnce(secrets); .mockReturnValueOnce(secrets);
} }
function mockEngineName(name) {
when(core.getInput)
.calledWith('path')
.mockReturnValueOnce(name);
}
function mockVersion(version) {
when(core.getInput)
.calledWith('kv-version')
.mockReturnValueOnce(version);
}
it('get simple secret', async () => { it('get simple secret', async () => {
mockInput('test secret'); mockInput('secret/data/test secret');
await exportSecrets(); await exportSecrets();
@@ -122,7 +132,7 @@ describe('integration', () => {
}); });
it('re-map secret', async () => { it('re-map secret', async () => {
mockInput('test secret | TEST_KEY'); mockInput('secret/data/test secret | TEST_KEY');
await exportSecrets(); await exportSecrets();
@@ -130,18 +140,18 @@ describe('integration', () => {
}); });
it('get nested secret', async () => { it('get nested secret', async () => {
mockInput('nested/test otherSecret'); mockInput(`secret/data/nested/test "other-Secret-dash"`);
await exportSecrets(); await exportSecrets();
expect(core.exportVariable).toBeCalledWith('OTHERSECRET', 'OTHERSUPERSECRET'); expect(core.exportVariable).toBeCalledWith('OTHERSECRETDASH', 'OTHERSUPERSECRET');
}); });
it('get multiple secrets', async () => { it('get multiple secrets', async () => {
mockInput(` mockInput(`
test secret ; secret/data/test secret ;
test secret | NAMED_SECRET ; secret/data/test secret | NAMED_SECRET ;
nested/test otherSecret ;`); secret/data/nested/test "other-Secret-dash" ;`);
await exportSecrets(); await exportSecrets();
@@ -149,13 +159,19 @@ describe('integration', () => {
expect(core.exportVariable).toBeCalledWith('SECRET', 'SUPERSECRET'); expect(core.exportVariable).toBeCalledWith('SECRET', 'SUPERSECRET');
expect(core.exportVariable).toBeCalledWith('NAMED_SECRET', 'SUPERSECRET'); expect(core.exportVariable).toBeCalledWith('NAMED_SECRET', 'SUPERSECRET');
expect(core.exportVariable).toBeCalledWith('OTHERSECRET', 'OTHERSUPERSECRET'); expect(core.exportVariable).toBeCalledWith('OTHERSECRETDASH', 'OTHERSUPERSECRET');
});
it('leading slash kvv2', async () => {
mockInput('/secret/data/foobar fookv2');
await exportSecrets();
expect(core.exportVariable).toBeCalledWith('FOOKV2', 'bar');
}); });
it('get secret from K/V v1', async () => { it('get secret from K/V v1', async () => {
mockInput('test secret'); mockInput('secret-kv1/test secret');
mockEngineName('my-secret');
mockVersion('1');
await exportSecrets(); await exportSecrets();
@@ -163,13 +179,19 @@ describe('integration', () => {
}); });
it('get nested secret from K/V v1', async () => { it('get nested secret from K/V v1', async () => {
mockInput('nested/test otherSecret'); mockInput('secret-kv1/nested/test "other-Secret-dash"');
mockEngineName('my-secret');
mockVersion('1');
await exportSecrets(); await exportSecrets();
expect(core.exportVariable).toBeCalledWith('OTHERSECRET', 'OTHERCUSTOMSECRET'); expect(core.exportVariable).toBeCalledWith('OTHERSECRETDASH', 'OTHERCUSTOMSECRET');
});
it('leading slash kvv1', async () => {
mockInput('/secret-kv1/foobar fookv1');
await exportSecrets();
expect(core.exportVariable).toBeCalledWith('FOOKV1', 'bar');
}); });
describe('generic engines', () => { describe('generic engines', () => {
+126
View File
@@ -0,0 +1,126 @@
jest.mock('@actions/core');
jest.mock('@actions/core/lib/command');
const core = require('@actions/core');
const {
privateRsaKeyBase64,
publicRsaKey
} = require('./rsa_keys');
const got = require('got');
const { when } = require('jest-when');
const { exportSecrets } = require('../../src/action');
const vaultUrl = `http://${process.env.VAULT_HOST || 'localhost'}:${process.env.VAULT_PORT || '8200'}`;
describe('jwt auth', () => {
beforeAll(async () => {
// Verify Connection
await got(`${vaultUrl}/v1/secret/config`, {
headers: {
'X-Vault-Token': 'testtoken',
},
});
try {
await got(`${vaultUrl}/v1/sys/auth/jwt`, {
method: 'POST',
headers: {
'X-Vault-Token': 'testtoken',
},
json: {
type: 'jwt'
}
});
} catch (error) {
const {response} = error;
if (response.statusCode === 400 && response.body.includes("path is already in use")) {
// Auth method might already be enabled from previous test runs
} else {
throw error;
}
}
await got(`${vaultUrl}/v1/sys/policy/reader`, {
method: 'PUT',
headers: {
'X-Vault-Token': 'testtoken',
},
json: {
policy: `
path "*" {
capabilities = ["read"]
}
`
}
});
await got(`${vaultUrl}/v1/auth/jwt/config`, {
method: 'POST',
headers: {
'X-Vault-Token': 'testtoken',
},
json: {
jwt_validation_pubkeys: publicRsaKey
}
});
await got(`${vaultUrl}/v1/auth/jwt/role/default`, {
method: 'POST',
headers: {
'X-Vault-Token': 'testtoken',
},
json: {
role_type: 'jwt',
bound_audiences: null,
bound_claims: {
iss: 'vault-action'
},
user_claim: 'iss',
policies: ['reader']
}
});
await got(`${vaultUrl}/v1/secret/data/test`, {
method: 'POST',
headers: {
'X-Vault-Token': 'testtoken',
},
json: {
data: {
secret: 'SUPERSECRET',
},
},
});
});
beforeEach(() => {
jest.resetAllMocks();
when(core.getInput)
.calledWith('url')
.mockReturnValueOnce(`${vaultUrl}`);
when(core.getInput)
.calledWith('method')
.mockReturnValueOnce('jwt');
when(core.getInput)
.calledWith('jwtPrivateKey')
.mockReturnValueOnce(privateRsaKeyBase64);
when(core.getInput)
.calledWith('role')
.mockReturnValueOnce('default');
when(core.getInput)
.calledWith('secrets')
.mockReturnValueOnce('secret/data/test secret');
});
it('successfully authenticates', async () => {
await exportSecrets();
expect(core.exportVariable).toBeCalledWith('SECRET', 'SUPERSECRET');
});
});
+77
View File
@@ -0,0 +1,77 @@
const privateRsaKey = `
-----BEGIN RSA PRIVATE KEY-----
MIIJKAIBAAKCAgEAwavSHLLo7bUSuKX2EKu3YStrNTGdmhku7sAFaeDyi9His1oo
t+wzajWp1rqHaGVk4b5o5z6D7Xhm0zYPhpTTvEd3NyONc9sjVd7sf9rQaBY3QusP
YAdF6j0ydTJGnTeG9N2zhHjdMLR+3F39F9Ry6vddS9w3ibjVERucQtpqGhy5TIWh
ttk3gN3A7dk972+WCQeKUCC6wU6PvAEUPflThQc1hSHldpjVUHQlZkQXl/XHWBzZ
ESwMgiQcAmVL3lkvxmgIYscqWzf8cTHogNrPml9Il89N+2XYcEfXgWLOyzGhQggi
gN9DRHDDE1UWT1foHnmeXAIZPCveKZc/Jp5SASIxaZ+r73mWjVt19GSvEsqtejDR
mMC3jrYCdISrCVsHkbRQq7/yLCi5sJG9p2gD91jCgaBy2tw22nWN/KoHm9p/mhzW
mlWwVJrFTNiP0qccyoa5h1a6WBPt0oCKQk3IAMV5HhVw4DhPx8gvh7qwOZk9vXXA
FyA8bWhOVIFIJ8i8Gq25y7/bukyzqsEPkQ2mKgbQnh3VOUCSugJFodPC/Jf7VQK1
yRpUZH2v7r9cBjHVnUnePGac3Zns7/iRYBvK5cIFUg+X48VXIMKIvs4EA8ee8Vac
Vh8tyR6EuP42BU5fGQlvLC+ZKT165maQv/Vlf52E9W2iFNt3sxB0KFtOkbkCAwEA
AQKCAgBwAwAyuQce9GsvgE0gtzAIcyQ+T8PnLEmIrGZ1JjUhyPJk6PBD78iM1Ry1
pIxMRNhj98yUcgO7hLdz0QCJxenwKyU4LsfRCh0VvSjriZKfoLm1al4qHArDv0E/
pyRQKZ1UYiVBqOXFFZ+JtJJ9BdKxMwAyr9svPEd+7Yki4VAcaiCBsYgmSNthHOBI
sCyyHseX0VSdo1BgHR/kjHs4nMtBVToPFduxDBPTxFkdHKTIrs3smEKzO9bALkJE
4HFQ2CRZjDHNb4N/3pGSplriq6sGjbVel/dyPyU/S03I92zC+KFbn3jVMEunedBZ
jgypNx55Ab4lWNFfi7+iLmfH3ilumsajGSRGVTo0evuBhK5obUudHeXxmvEBa81n
yo38swQFcSF9VOYwLDud6WgryTGLejRspWxbbV1pLp4uBvcDJktzh/fGyboZc2oG
kmrozTenuLEsf85T8o6W9kOe4vNBFngMPjDf9rOw6zMFxO0Iy3d7ag9z0ccGV3zh
66QijkWPXQfaLOaueGCQakS9BI4AJCIIjqv51jo8D86fHOdUwK2RlhVBHW6k+XJo
VGVbeOLNbcOHA0/BU10ZX16F8ZKKBWs0NfNg5O7Vvr6qyAp4zQyUSfXgJHS0De2E
5sLAr8+lemdd/pP/Oi8GHFmo+rwDheH1EYyziA2zm8Zmc7q+QQKCAQEA/LRs4LOJ
XlwDfQE9w5L6geJ/jAKClrGOtP5tzBDjWSZ3xPZeBChXc5U+n2IEyqFU9j2HQlMr
XQl74aEclG/y0371zWm83OEQCEBp2z/VsP7JZuEGNxla1EO6hSZXAZDQrTeOodhZ
6OL6wdIGCQvnFZuiJwCfGItmBBaUjxpRsmyrf9naOM1BwM4PpZUvv18iqoK7YhGz
t9Bs6W/LP2WK3Ze5WShZXXsFxGoWvYJvs8pQYua2TF+SGsnmc8FfmHSFZdu8qhXa
J5XIxjynFweWZqxxCnfS77ejhx1h5s8iwKT1la8VHUJ7Tgcdn98VTcJPRsyYg6TU
xvztwvEfUA7eewKCAQEAxDJUmi3ksP/nMy1Ox7BEnnWKFiVS46g58m9qhF5y8Oib
ypCPt3EvdrXvzjlYJojbXMr0yjvGqiBblDMjewdvxb4CTTAIy3iwOCfHBnzdyNYA
XZjtuD991klQP/BB62CMbCiwC1XBJzN57qxHEgPBwtkQYgSI/M/hQWZehi8JgjW7
PNjDPqYdIck78G8zUQM96u6Y0F+BoQuo/YgKXyeeMhtMiTITN9NpCwa5KdlDunZ0
qlZe1GKnOHmCW0NgeMxNZTRTJXvU7wUigs4isR19GuLuXnHRIwBoydu0UgczCvgh
cGv19uCU/DcoxFF0fGD1Uual1R8KH+0FpN3mnJW0WwKCAQEAxy1Sj70Srcvqd/Gt
g+PqDMvAalNkKHBkoaXUVr6M4yydxCHHMpG1dAWTKT6xtiB4/ei7Hny9NgSOnuVE
yH6AL1DnXnNUB+hgoZBbnxLuVCZOCgecxXr3i0yiy+XPOA2zXIPoqQoEu7mDmZb3
aNP33KEhqooj282rp9dAWpaNBAwBFLFZ/eFSTSxdSs6OptDOWwTVutNnCp996HRU
B3D6hfPbhDl4TmTzw782k0Im1tfEil98GjBN0U2HlX854Mkeh40tZAX7P64gZJdT
v6QcWGrcYjrViFn+yzVOgASNSLf8VXF9O+W1mGelYugLO5HGuG/0WfZmOz0KDdfN
LWW61wKCAQB8qaZMGSEYvmF/iShnhb70GKdXDvwuH3RCcTzzQrgyDvr+qQBIhSit
e0kWdiVmxsrrmSIVZgoDi2/lKOFAiSciNGtt9DmCX/tIky3JF4os1J2C22shCWbB
w++z0Mtx7fULvIavjRuf9vthBiJadfyl/BqGzW7lhIkSbyNci4K1M8L3FJxqsE4O
a7kkOuQWc8LiBh0fObA6ThhgkBJXB+ti1ym4exLvA+vYz7rTtnNshVv35811kgHC
xqJnrtYbq2T6C1dRl+9iuJaHGse8VoppjQv9AsDqRpZOvMVE4cIzFBrbPh4ZcfX4
lGvY4hDr/weiV1/DnWdnhclySnT/xbfFAoIBADjm+PaaMVps8tfgNcLUjOoAQzXo
/ReGOa/Zs7pu3nQp49b+9QBHRXXRrfeJ6NAVAJvgc8PIUsVKQ67yjf1sLHZUSGjc
3wyaAChmMLgl+00kQ7VL4Ls1bEb4Qxho6zoCjvaorN6gcNO8D32Oecux9F9nWinK
zJi1GLoJpVenFT+M4zTWOl3otcVzTDxknFYx9Vul84n2z28GYmw8I0RKcmBKCvHo
q/JyRYl9XunMp/7QDA9IYKTJXqIkiD+ksKtDfWRsy+iLvuVv0z9gA+MlaRTGANpt
ucZsYfhw34I5dpcqrYP4DErpKdYA3nsjx9rNQg0I4Zo7yVCRoiqRHa97GVQ=
-----END RSA PRIVATE KEY-----
`;
const privateRsaKeyBase64 = Buffer.from(privateRsaKey).toString('base64');
const publicRsaKey = `
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAwavSHLLo7bUSuKX2EKu3
YStrNTGdmhku7sAFaeDyi9His1oot+wzajWp1rqHaGVk4b5o5z6D7Xhm0zYPhpTT
vEd3NyONc9sjVd7sf9rQaBY3QusPYAdF6j0ydTJGnTeG9N2zhHjdMLR+3F39F9Ry
6vddS9w3ibjVERucQtpqGhy5TIWhttk3gN3A7dk972+WCQeKUCC6wU6PvAEUPflT
hQc1hSHldpjVUHQlZkQXl/XHWBzZESwMgiQcAmVL3lkvxmgIYscqWzf8cTHogNrP
ml9Il89N+2XYcEfXgWLOyzGhQggigN9DRHDDE1UWT1foHnmeXAIZPCveKZc/Jp5S
ASIxaZ+r73mWjVt19GSvEsqtejDRmMC3jrYCdISrCVsHkbRQq7/yLCi5sJG9p2gD
91jCgaBy2tw22nWN/KoHm9p/mhzWmlWwVJrFTNiP0qccyoa5h1a6WBPt0oCKQk3I
AMV5HhVw4DhPx8gvh7qwOZk9vXXAFyA8bWhOVIFIJ8i8Gq25y7/bukyzqsEPkQ2m
KgbQnh3VOUCSugJFodPC/Jf7VQK1yRpUZH2v7r9cBjHVnUnePGac3Zns7/iRYBvK
5cIFUg+X48VXIMKIvs4EA8ee8VacVh8tyR6EuP42BU5fGQlvLC+ZKT165maQv/Vl
f52E9W2iFNt3sxB0KFtOkbkCAwEAAQ==
-----END PUBLIC KEY-----
`;
module.exports = {
privateRsaKeyBase64,
publicRsaKey
};
+4
View File
@@ -0,0 +1,4 @@
# e2e tests
This test suite runs `vault-action` as a GitHub Action in the context of a live build, and then verifies that the appropriate environmental variables are set.
These tests are intended to mostly be very simple smoke tests to verify that the action is being compiled and run correctly in context.
+24
View File
@@ -0,0 +1,24 @@
-----BEGIN CERTIFICATE-----
MIIEFjCCAv6gAwIBAgIUe0i7/HGZKvbDb30L9mC99KXFwj8wDQYJKoZIhvcNAQEL
BQAwgaIxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQH
Ew1TYW4gRnJhbmNpc2NvMRIwEAYDVQQKEwlIYXNoaUNvcnAxIzAhBgNVBAsTGlRl
c3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MS0wKwYDVQQDEyRQcm90b3R5cGUgVGVz
dCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMjAwODA1MTg1MjAwWhcNMjUwODA0
MTg1MjAwWjCBojELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAU
BgNVBAcTDVNhbiBGcmFuY2lzY28xEjAQBgNVBAoTCUhhc2hpQ29ycDEjMCEGA1UE
CxMaVGVzdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxLTArBgNVBAMTJFByb3RvdHlw
ZSBUZXN0IENlcnRpZmljYXRlIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBAMrRXuu2+zhBs0pLYEdXIaPc4KoWO3xm2RJdbzy3hfjFybQ8
H/Y6Hi7txjGGSb45xSfXT/RF2srNfs235I+sfB8rrEizNpzkXqOgGa8LKvh2tgBT
BK/jDWsEdDhxmkpFhE69wEW+D5ub7QGnx9jrqLKfwCmUA0utlzcFBk2nRNhRtsrp
CI5YL1VN4coLpgXdvbodzbynPzGHe9R/o9K0Uiz2hgHooyKwhkVYwo0BIAQamLFz
TS7lyeLf0thDOxV31NX8SpSucqRf50WHNk8T/YtKZ9EhlBDT4ybZwwvcC/ocxxcg
1LvB0YweZNjSeO78S4CMh1TFGXnF/xOtGABlIbcCAwEAAaNCMEAwDgYDVR0PAQH/
BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFABD/NxvYLpo5zVNeD01
r8IIFYlBMA0GCSqGSIb3DQEBCwUAA4IBAQB7TfpIx53gf/oI3mgR6Ciz287WBzFR
OzhJXwHk5J3mx8VC1W8tDRXih2lCLd/f9qDy6LyL/hZcoonev6w9oReuOMBiH6l4
Pf3yq2aDXX0AoGgm75c1m34kY669JLMsHq5+xuUDeeFUMd60w9zVtZfBSumy/sgN
PdjtvThh8sSByocYULs3tuxZDGyQ6GyQcn/xlMrGtmcD5IuX5IXqcKRVlZttykNx
S2ltcR00fekw8WZyPSzMJaP+/Kcq3T2viN02MS6qEycQZoYfEAMdj+A0kjbsZG9D
6J92z78b2DuLAUvZVpynNk/UbpDeqIDy40V3JDmtvrfGUMkMhMqgK/+J
-----END CERTIFICATE-----
@@ -0,0 +1,25 @@
-----BEGIN CERTIFICATE-----
MIIENTCCAx2gAwIBAgIUMu5h1ysA5DlM6lzZFliT2C2n4lEwDQYJKoZIhvcNAQEL
BQAwgaIxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQH
Ew1TYW4gRnJhbmNpc2NvMRIwEAYDVQQKEwlIYXNoaUNvcnAxIzAhBgNVBAsTGlRl
c3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MS0wKwYDVQQDEyRQcm90b3R5cGUgVGVz
dCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwIBcNMjAwODA1MTg1MjAwWhgPMjEyMDA3
MTIxODUyMDBaMIGMMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEW
MBQGA1UEBxMNU2FuIEZyYW5jaXNjbzESMBAGA1UEChMJSGFzaGlDb3JwMSMwIQYD
VQQLExpUZXN0IENlcnRpZmljYXRlIEF1dGhvcml0eTEXMBUGA1UEAxMOaGFzaGlj
b3JwLnRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC/zYDKdDGo
+Qy7eJUNjOe6jpeGvK1lMu5T1Xka+h2ay6WH5gLyrPw5pi582iYpJdHVbplKMywx
LxZv7mAbKNxqdp8UZKy0A3bCuHQqRF8ssXXHufQ8EGxNkLMLJP0e2q39OnrxXekS
8Ct3aJm3V8qkcV3CpVdPNgJh4TSuneCXIxVWjFYSiyHi0/5TRd2D+aQPz12szg5F
mBW4dLzYKHEMlWcjWG8mxtbLyt+jSR1+tSehQx7KndufdfniOWEDBdbeR3yDnZdn
p8DnRWK4oaEI3Sl8tKlDd1Yp+R96aqOEn1tPW6Jy6Vdvk3fCefclbWZ6B9kiJ/1r
gxq7AN7iKmHNAgMBAAGjdTBzMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggr
BgEFBQcDAjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBRn2mwyk+MPChnLg0iWy1r9
b3JvwTAfBgNVHSMEGDAWgBQAQ/zcb2C6aOc1TXg9Na/CCBWJQTANBgkqhkiG9w0B
AQsFAAOCAQEAOpCy0vHp1Kxgv0VBRrbrwSQLBGP8a1ubVWoeoZQ+EvX9ozqDrHxm
gM4XPYUJlUOOEu0ZRgCW60YK33E1zNKnA1F0/3/rmqMkKnm0BBs/5WzMWtsIBPcU
e0CeJmaRIXnERQMH/svD+RrFo1dcF8rUDIlWez7+xGqoIGBg7v4jEmkZ3HdckcE+
/xvC61YSG8NsJwR/CEcQ8YCyVfgvuS0ukWs4dN15aVDL3Oe61h3bRcGAywOJBrdq
9xaq7ezZp/+lUSkYnatWJBuC/aviH9g9s+gMT0I3fWHh8BB0Ne2txwJ15K/qz5he
TjxFsumrh50aFqjSiEHndtY5UWuGAFLiSw==
-----END CERTIFICATE-----
@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAv82AynQxqPkMu3iVDYznuo6XhrytZTLuU9V5Gvodmsulh+YC
8qz8OaYufNomKSXR1W6ZSjMsMS8Wb+5gGyjcanafFGSstAN2wrh0KkRfLLF1x7n0
PBBsTZCzCyT9Htqt/Tp68V3pEvArd2iZt1fKpHFdwqVXTzYCYeE0rp3glyMVVoxW
Eosh4tP+U0Xdg/mkD89drM4ORZgVuHS82ChxDJVnI1hvJsbWy8rfo0kdfrUnoUMe
yp3bn3X54jlhAwXW3kd8g52XZ6fA50ViuKGhCN0pfLSpQ3dWKfkfemqjhJ9bT1ui
culXb5N3wnn3JW1megfZIif9a4MauwDe4iphzQIDAQABAoIBAQCYHJuidAoaTwGZ
ACV9rJzuqD1lvubpFj5KwEcebPPjmtQ5deIqoaQa+D9wBvYyteq3ENKDNRg8HXL2
7B7OC1bbHB5HZxxMW17pSK3gA39Ti52z+zbGF+Q8k6BbG0efG6DW7nUoTOkWeuCN
/6fA7uAoEDxirQwUJuo2xAsq3MyMLwcs95rke9Bly8ABFNaV1oMZq8YT/w8oSc2b
/7WtxXmChHlVYXTcMqzVPqNFqPRixZRWQ+BSHoXmEDviuGd51L4s9D7iXp32TvUx
DMHeS1DFA2en7ZF1uc9VXZeplkkDtVhUe4d6qOqCcUwDFEvMonnyVSa6/FkR5jYZ
2yujTdfhAoGBAM0hGOnmnDnCjADUt4mZlr+Mf0XmdKzEV+hid4CQUvBoTXgjYMvv
c397eNePce7SwSUE1/APERInGUPhRLVFW5q6/34WRtGBbQkT8ByeJANXes4UFZe3
wdNLczWUlSl0G3jTf+Kh3+K5/PtmyxSrAS/9GIk+ibs1mlJOPyVnWqUJAoGBAO9e
WlP9/ruXluvkQyM5ZlnAnZYMsFGzzPx4tkazUjurtqxQoyZ0z+pPItGQ7lOl+pDA
EWiTun66g+Da9uBiBCJUeXiC1ge2p6bT6N194BrYyrWML9hcIL4mqVojUEUmhnSh
6b9h1pC7vFmw5ZFMIIkS60cfBMgQMZxMJN8NuaulAoGBAJM5hwURg90c2ZkbEyPK
PVz7fLlxnxoEzcc3LOf0LeLoKXnpgma8VJwRxXiJNs+fKgrkwAtG9QyfTU3f1412
2zlhr1ASsv9ZMiXKzpHrmpNfbP+NgLXkqFN7mpPBMZGQCMuemPHTFrpGnODfNTB/
T5newIZ4gSgBX+Jk0IOK+47pAoGAeKo6pK6ck9pV5TIbOg18b/AuQG7DD1yxD/CW
CkvpP1VPb8vygrdN/FLKPZRu39IC3qdD31DhKXNCeb5Hx1MBvICS/1INLLRCDVIz
yDvlFgOFJEG3+LxwcQqyQlMc6s8B5pecarKaZDmPODN5dmZG3HKiEicr1OJ878pe
p+aWW1UCgYBmGFbCc1qqlqp+srYGsv3rIgNs5HSfrAjbgY8xh9foMgrYCRAm57gv
01yVxMXWmKA6ReVEu8OTVy9fkuOL/vw2o+C6W4IPZYdvSQoPwd5Lf+AqxEQvFF1m
tT3SZAM3EhQ7tIXdIQHY27SJ1KlUJMrvUq1CiRWiG/MOKf/87JXPog==
-----END RSA PRIVATE KEY-----
@@ -0,0 +1,15 @@
ui = false
disable_mlock = true
listener "tcp" {
address = "[::]:8200"
cluster_address = "[::]:8201"
tls_cert_file = "/etc/vault/server.crt"
tls_key_file = "/etc/vault/server.key"
tls_client_ca_file = "/etc/vault/ca.crt"
tls_require_and_verify_client_cert = "true"
}
storage "file" {
path = "/var/lib/vault"
}
@@ -0,0 +1,26 @@
-----BEGIN CERTIFICATE-----
MIIEXjCCA0agAwIBAgIUAswquazrfsyDRvXZwn5718DUhU4wDQYJKoZIhvcNAQEL
BQAwgaIxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQH
Ew1TYW4gRnJhbmNpc2NvMRIwEAYDVQQKEwlIYXNoaUNvcnAxIzAhBgNVBAsTGlRl
c3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MS0wKwYDVQQDEyRQcm90b3R5cGUgVGVz
dCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwIBcNMjAwODA1MTg1MjAwWhgPMjEyMDA3
MTIxODUyMDBaMIGMMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEW
MBQGA1UEBxMNU2FuIEZyYW5jaXNjbzESMBAGA1UEChMJSGFzaGlDb3JwMSMwIQYD
VQQLExpUZXN0IENlcnRpZmljYXRlIEF1dGhvcml0eTEXMBUGA1UEAxMOaGFzaGlj
b3JwLnRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC0azdZsrPC
5Rv8nRxVJnLi+oZgCJYgzhCDiEbYqt1QK1gqNXp0ml5ck6ycj0drwzHzrrX+xcPV
5FcNKH3RFyon9XkzjwaXkMv6IkgvH6/jQ1dDW9kWBf3Io3Y59wnD/YaIzNK0CYJS
fRNdsZb4InH8gh+RL33+FeysgJwXG1TVA4tTUj7DQxDE0cDd9UD+C9Yx7OWiUjC1
IjqdFPusX1nziKYjeI5/UiCmOUGqJJRoMPonuzuGIj9GdmBKmga64OfeZFqn4f6a
ay61VnGCwZ24VniUwYElsFbcF2Nv9WqnrOeQlHOsYN68VMqHzaYPqE6SPa6mO5mI
/tmpXrDG3Y+RAgMBAAGjgZ0wgZowDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoG
CCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFE03/UTs2ZmJpWHSmstt
hDngW6F3MB8GA1UdIwQYMBaAFABD/NxvYLpo5zVNeD01r8IIFYlBMCUGA1UdEQQe
MByCCWxvY2FsaG9zdIIJdmF1bHQtdGxzhwR/AAABMA0GCSqGSIb3DQEBCwUAA4IB
AQCzarBGJium5oZDSSP5GqxpS13QP2onEen6I1k2eRdcOqtbfNdQ20RJrb4dfNkE
Dc09KWVlZAn+hYge2KKTXJ+4ltIC9V1LvquyWipNczOT1ve0H9gt3Wm88LdESqI5
HOx43pIaa3cWXBlbzrFmT1SASYm1V5Oo1mXzpUukGokHLLmAz36VVuJGbD0BxYke
5MefG4tNT1SsMsIqVvGxI9NiVs7YTdJu81MctSYK5snsEKnYdi9N7CHOk3bdDpeC
v2Vo7XBk3s4sBMGmnJO+1JOcRFJioooEFkqNyQmg3atfInysVbreKS5KtWNTaCPm
yI55plW8ga5ucja2VX3WbwAO
-----END CERTIFICATE-----
@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAtGs3WbKzwuUb/J0cVSZy4vqGYAiWIM4Qg4hG2KrdUCtYKjV6
dJpeXJOsnI9Ha8Mx8661/sXD1eRXDSh90RcqJ/V5M48Gl5DL+iJILx+v40NXQ1vZ
FgX9yKN2OfcJw/2GiMzStAmCUn0TXbGW+CJx/IIfkS99/hXsrICcFxtU1QOLU1I+
w0MQxNHA3fVA/gvWMezlolIwtSI6nRT7rF9Z84imI3iOf1IgpjlBqiSUaDD6J7s7
hiI/RnZgSpoGuuDn3mRap+H+mmsutVZxgsGduFZ4lMGBJbBW3Bdjb/Vqp6znkJRz
rGDevFTKh82mD6hOkj2upjuZiP7ZqV6wxt2PkQIDAQABAoIBAQCvK0HsVvLtkSCh
HbF6gwAcnHyHFQ8d/rRN4KxYhVynD85j/NRODer8G20F/J6tZDFFlSWinUTMkQxr
/BpcPg9yCIWKp50Q30cMLujCyBMvphw9jBmzplGG0h5hnRbgMXDDtYoFvw3HJST+
XQRlGpxtO7GGdwPvBD5sJdpnHOQ6g7qIYKmlHM99kHU8vr0VghqZAYxEh8RpnYez
NLra+7ep+Zp1pFIniU6B8ohyL3OArbQ65qYrZYriAEI5HeEk0RhjewcPsV56LwbS
CncTVS/dNYgk1zRIvytmbDVD3v/4lLvnpIWeKVdk7p1aGJeCdpLeWNvDLX0Ws67r
QeZQizwhAoGBAMwAIA6+HPsx+8dhNbN3ydX8YU6uUfSeshhshIFZPIYL2vrKyAHU
/GAYVzYJH/cU0IvlLJlLdQuiZkOXEX87tgdfmM/o4Qdl12RR0BvU0Cae0txtzNrP
yTdfZqDhTz/V8jOAXUNA5oQA45Y3rI7JES8hBd1F9WFOH2WINp344GzlAoGBAOJo
SgmRE24VcnfUMqrBpwZBdBrTxDQyTagvd+MuGomIQfcE2Y4rr1eIuJJ0HF5/eYxc
DZRO/LVP9tQ8ozXi2tdmgUdKC79O2edmdOCWW5of464R/TLcM5B4SmS36RtdE3qJ
ig4fcUmsJ15MAGpkXLMh5YSD/N3TmcnURtx06Fk9AoGATi+mGcBnnybzFuF9EYHR
y7/lE6DgLF8+ZvoAdwralY2pqgFaUslsyO/LTRyGMc66d0OoqkAvZfwiMbmOrTMX
ew/6o4Tf6lPwD7UDjAcul/67VlyG7T5CIoTf8r0oAJFhOLf0BrizINiuYX6JFlid
y3BerQYJG/gzNFjWhglDCrkCgYA+3wUISRAjNrN10ShMwL/3/b8XIA1RDVMBTEU3
gfr+jCb9SIx9bWYgoafXi4TBPRbswjdHIvQMCWuankgYU6m/vQhTWp2Of4AFQS9d
moNPdmGMWhR8xidPjAfklimWXq9lDMKYj2SvN64rAmHvKXWQjO4mcVyL4RHIuTkA
STqoZQKBgQDKHd8F6tjZHEFolmjS5l682g7zVTpBhozezJ/RqYvhJh5ew1pXoD/O
Zu9iMfHoDjR4ZUXq6aeLUj/oIt1AsjwaGChOLLAvFbvePgS9XkYkwIlaxS4efAya
+CQE/JmY/a1/c2MDLNMCEXvUqX68pv6iDF8pfn+i4tn0omYqgfUlCA==
-----END RSA PRIVATE KEY-----
+14
View File
@@ -0,0 +1,14 @@
describe('e2e-tls', () => {
it('verify', () => {
expect(process.env.SECRET).toBe("SUPERSECRET");
expect(process.env.NAMED_SECRET).toBe("SUPERSECRET");
expect(process.env.OTHERSECRET).toBe("OTHERSUPERSECRET");
expect(process.env.OTHER_SECRET_OUTPUT).toBe("OTHERSUPERSECRET");
expect(process.env.ALTSECRET).toBe("CUSTOMSECRET");
expect(process.env.NAMED_ALTSECRET).toBe("CUSTOMSECRET");
expect(process.env.OTHERALTSECRET).toBe("OTHERCUSTOMSECRET");
expect(process.env.FOO).toBe("bar");
expect(process.env.NAMED_CUBBYSECRET).toBe("zap");
expect(process.env.SKIP).toBe("true");
});
});
+3
View File
@@ -0,0 +1,3 @@
module.exports = {
verbose: true
};
+197
View File
@@ -0,0 +1,197 @@
const got = require('got');
const core = require('@actions/core');
const vaultUrl = `${process.env.VAULT_HOST}:${process.env.VAULT_PORT}`;
const caCertificateRaw = `${process.env.VAULTCA}`;
const clientCertificateRaw = `${process.env.VAULT_CLIENT_CERT}`;
const clientKeyRaw = `${process.env.VAULT_CLIENT_KEY}`;
(async () => {
try {
var caCertificate = Buffer.from(caCertificateRaw, 'base64').toString();
if (caCertificate == null) {
throw Error("VAULTCA env not set.")
}
var clientCertificate = Buffer.from(clientCertificateRaw, 'base64').toString();
if (clientCertificate == null) {
throw Error("VAULT_CLIENT_CERT env not set.")
}
var clientKey = Buffer.from(clientKeyRaw, 'base64').toString();
if (clientKey == null) {
throw Error("VAULT_CLIENT_KEY env not set.")
}
// Init
const {body} = await got(`https://${vaultUrl}/v1/sys/init`, {
method: 'POST',
json: {
secret_shares: 1,
secret_threshold: 1,
},
responseType: 'json',
https: {
certificateAuthority: caCertificate,
certificate: clientCertificate,
key: clientKey,
}
});
if (body.keys_base64.length != 1) {
throw Error("No unseal key found after init.")
}
var unseal = body.keys_base64[0];
if (body.root_token == "") {
throw Error("No root token found after init.")
}
var rootToken = body.root_token;
core.exportVariable('VAULT_TOKEN', rootToken);
core.setSecret(rootToken)
// Unseal
await got(`https://${vaultUrl}/v1/sys/unseal`, {
method: 'POST',
json: {
key: unseal,
},
https: {
certificateAuthority: caCertificate,
certificate: clientCertificate,
key: clientKey,
}
});
await got(`https://${vaultUrl}/v1/sys/mounts/secret`, {
method: 'POST',
headers: {
'X-Vault-Token': rootToken,
},
https: {
certificateAuthority: caCertificate,
certificate: clientCertificate,
key: clientKey,
},
json: {
type: 'kv-v2'
}
});
await got(`https://${vaultUrl}/v1/secret/data/test`, {
method: 'POST',
headers: {
'X-Vault-Token': rootToken,
},
https: {
certificateAuthority: caCertificate,
certificate: clientCertificate,
key: clientKey,
},
json: {
data: {
secret: 'SUPERSECRET',
},
},
});
await got(`https://${vaultUrl}/v1/secret/data/nested/test`, {
method: 'POST',
headers: {
'X-Vault-Token': rootToken,
},
https: {
certificateAuthority: caCertificate,
certificate: clientCertificate,
key: clientKey,
},
json: {
data: {
otherSecret: 'OTHERSUPERSECRET',
},
}
});
await got(`https://${vaultUrl}/v1/secret/data/tlsSkipVerify`, {
method: 'POST',
headers: {
'X-Vault-Token': rootToken,
},
https: {
certificateAuthority: caCertificate,
certificate: clientCertificate,
key: clientKey,
},
json: {
data: {
skip: 'true',
},
}
});
await got(`https://${vaultUrl}/v1/sys/mounts/my-secret`, {
method: 'POST',
headers: {
'X-Vault-Token': rootToken,
},
https: {
certificateAuthority: caCertificate,
certificate: clientCertificate,
key: clientKey,
},
json: {
type: 'kv'
}
});
await got(`https://${vaultUrl}/v1/my-secret/test`, {
method: 'POST',
headers: {
'X-Vault-Token': rootToken,
},
https: {
certificateAuthority: caCertificate,
certificate: clientCertificate,
key: clientKey,
},
json: {
altSecret: 'CUSTOMSECRET',
}
});
await got(`https://${vaultUrl}/v1/my-secret/nested/test`, {
method: 'POST',
headers: {
'X-Vault-Token': rootToken,
},
https: {
certificateAuthority: caCertificate,
certificate: clientCertificate,
key: clientKey,
},
json: {
otherAltSecret: 'OTHERCUSTOMSECRET',
},
});
await got(`https://${vaultUrl}/v1/cubbyhole/test`, {
method: 'POST',
headers: {
'X-Vault-Token': rootToken,
},
https: {
certificateAuthority: caCertificate,
certificate: clientCertificate,
key: clientKey,
},
json: {
foo: 'bar',
zip: 'zap',
},
});
} catch (error) {
console.log(error);
process.exit(1);
}
})();
+9 -13
View File
@@ -56,7 +56,7 @@ describe('integration', () => {
}); });
it('get simple secret', async () => { it('get simple secret', async () => {
mockInput('test secret'); mockInput('secret/data/test secret');
await exportSecrets(); await exportSecrets();
@@ -64,7 +64,7 @@ describe('integration', () => {
}); });
it('re-map secret', async () => { it('re-map secret', async () => {
mockInput('test secret | TEST_KEY'); mockInput('secret/data/test secret | TEST_KEY');
await exportSecrets(); await exportSecrets();
@@ -72,7 +72,7 @@ describe('integration', () => {
}); });
it('get nested secret', async () => { it('get nested secret', async () => {
mockInput('nested/test otherSecret'); mockInput('secret/data/nested/test otherSecret');
await exportSecrets(); await exportSecrets();
@@ -81,9 +81,9 @@ describe('integration', () => {
it('get multiple secrets', async () => { it('get multiple secrets', async () => {
mockInput(` mockInput(`
test secret ; secret/data/test secret ;
test secret | NAMED_SECRET ; secret/data/test secret | NAMED_SECRET ;
nested/test otherSecret ;`); secret/data/nested/test otherSecret ;`);
await exportSecrets(); await exportSecrets();
@@ -95,9 +95,7 @@ describe('integration', () => {
}); });
it('get secret from K/V v1', async () => { it('get secret from K/V v1', async () => {
mockInput('test secret'); mockInput('my-secret/test secret');
mockEngineName('my-secret');
mockVersion('1');
await exportSecrets(); await exportSecrets();
@@ -105,9 +103,7 @@ describe('integration', () => {
}); });
it('get nested secret from K/V v1', async () => { it('get nested secret from K/V v1', async () => {
mockInput('nested/test otherSecret'); mockInput('my-secret/nested/test otherSecret');
mockEngineName('my-secret');
mockVersion('1');
await exportSecrets(); await exportSecrets();
@@ -229,7 +225,7 @@ describe('authenticate with approle', () => {
}); });
it('authenticate with approle', async() => { it('authenticate with approle', async() => {
mockInput('test secret'); mockInput('secret/data/test secret');
await exportSecrets(); await exportSecrets();
+3923 -2890
View File
File diff suppressed because it is too large Load Diff
+15 -13
View File
@@ -8,7 +8,8 @@
"test": "jest", "test": "jest",
"test:integration:basic": "jest -c integrationTests/basic/jest.config.js", "test:integration:basic": "jest -c integrationTests/basic/jest.config.js",
"test:integration:enterprise": "jest -c integrationTests/enterprise/jest.config.js", "test:integration:enterprise": "jest -c integrationTests/enterprise/jest.config.js",
"test:e2e": "jest -c integrationTests/e2e/jest.config.js" "test:e2e": "jest -c integrationTests/e2e/jest.config.js",
"test:e2e-tls": "jest -c integrationTests/e2e-tls/jest.config.js"
}, },
"files": [ "files": [
"src/**/*", "src/**/*",
@@ -26,7 +27,7 @@
}, },
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/RichiCoder1/vault-action.git" "url": "git+https://github.com/hashicorp/vault-action.git"
}, },
"keywords": [ "keywords": [
"hashicorp", "hashicorp",
@@ -36,26 +37,27 @@
"github-actions", "github-actions",
"javascript" "javascript"
], ],
"author": "Richard Simpson <richardsimpson@outlook.com>", "author": "HashiCorp",
"license": "MIT", "license": "MIT",
"bugs": { "bugs": {
"url": "https://github.com/RichiCoder1/vault-action/issues" "url": "https://github.com/hashicorp/vault-action/issues"
}, },
"homepage": "https://github.com/RichiCoder1/vault-action#readme", "homepage": "https://github.com/hashicorp/vault-action#readme",
"dependencies": { "dependencies": {
"got": "^10.2.2", "got": "^11.5.1",
"jsonata": "^1.8.2" "jsonata": "^1.8.2",
"jsrsasign": "^10.1.10"
}, },
"peerDependencies": { "peerDependencies": {
"@actions/core": ">=1 <2" "@actions/core": ">=1 <2"
}, },
"devDependencies": { "devDependencies": {
"@actions/core": "^1.2.3", "@actions/core": "^1.2.3",
"@types/got": "^9.6.9", "@types/got": "^9.6.11",
"@types/jest": "^25.1.3", "@types/jest": "^26.0.13",
"@zeit/ncc": "^0.22.0", "@zeit/ncc": "^0.22.3",
"jest": "^25.1.0", "jest": "^26.4.2",
"jest-when": "^2.7.0", "jest-when": "^2.7.2",
"semantic-release": "^17.0.4" "semantic-release": "^17.1.1"
} }
} }
+40 -36
View File
@@ -5,18 +5,14 @@ const got = require('got').default;
const jsonata = require('jsonata'); const jsonata = require('jsonata');
const { auth: { retrieveToken }, secrets: { getSecrets } } = require('./index'); const { auth: { retrieveToken }, secrets: { getSecrets } } = require('./index');
const AUTH_METHODS = ['approle', 'token', 'github']; const AUTH_METHODS = ['approle', 'token', 'github', 'jwt', 'kubernetes'];
const VALID_KV_VERSION = [-1, 1, 2];
async function exportSecrets() { async function exportSecrets() {
const vaultUrl = core.getInput('url', { required: true }); const vaultUrl = core.getInput('url', { required: true });
const vaultNamespace = core.getInput('namespace', { required: false }); const vaultNamespace = core.getInput('namespace', { required: false });
const extraHeaders = parseHeadersInput('extraHeaders', { required: false }); const extraHeaders = parseHeadersInput('extraHeaders', { required: false });
const exportEnv = core.getInput('exportEnv', { required: false }) != 'false'; const exportEnv = core.getInput('exportEnv', { required: false }) != 'false';
const exportToken = (core.getInput('exportToken', { required: false }) || 'false').toLowerCase() != 'false';
let enginePath = core.getInput('path', { required: false });
/** @type {number | string} */
let kvVersion = core.getInput('kv-version', { required: false });
const secretsInput = core.getInput('secrets', { required: true }); const secretsInput = core.getInput('secrets', { required: true });
const secretRequests = parseSecretsInput(secretsInput); const secretRequests = parseSecretsInput(secretsInput);
@@ -29,7 +25,28 @@ async function exportSecrets() {
const defaultOptions = { const defaultOptions = {
prefixUrl: vaultUrl, prefixUrl: vaultUrl,
headers: {} headers: {},
https: {}
}
const tlsSkipVerify = (core.getInput('tlsSkipVerify', { required: false }) || 'false').toLowerCase() != 'false';
if (tlsSkipVerify === true) {
defaultOptions.https.rejectUnauthorized = false;
}
const caCertificateRaw = core.getInput('caCertificate', { required: false });
if (caCertificateRaw != null) {
defaultOptions.https.certificateAuthority = Buffer.from(caCertificateRaw, 'base64').toString();
}
const clientCertificateRaw = core.getInput('clientCertificate', { required: false });
if (clientCertificateRaw != null) {
defaultOptions.https.certificate = Buffer.from(clientCertificateRaw, 'base64').toString();
}
const clientKeyRaw = core.getInput('clientKey', { required: false });
if (clientKeyRaw != null) {
defaultOptions.https.key = Buffer.from(clientKeyRaw, 'base64').toString();
} }
for (const [headerName, headerValue] of extraHeaders) { for (const [headerName, headerValue] of extraHeaders) {
@@ -44,32 +61,14 @@ async function exportSecrets() {
defaultOptions.headers['X-Vault-Token'] = vaultToken; defaultOptions.headers['X-Vault-Token'] = vaultToken;
const client = got.extend(defaultOptions); const client = got.extend(defaultOptions);
if (!enginePath) { if (exportToken === true) {
enginePath = 'secret'; command.issue('add-mask', vaultToken);
} core.exportVariable('VAULT_TOKEN', `${vaultToken}`);
if (!kvVersion) {
kvVersion = 2;
}
kvVersion = +kvVersion;
if (Number.isNaN(kvVersion) || !VALID_KV_VERSION.includes(kvVersion)) {
throw Error(`You must provide a valid K/V version (${VALID_KV_VERSION.slice(1).join(', ')}). Input: "${kvVersion}"`);
} }
const requests = secretRequests.map(request => { const requests = secretRequests.map(request => {
const { path, selector } = request; const { path, selector } = request;
return request;
if (path.startsWith('/')) {
return request;
}
const kvPath = (kvVersion === 2)
? `/${enginePath}/data/${path}`
: `/${enginePath}/${path}`;
const kvSelector = (kvVersion === 2)
? `data.data.${selector}`
: `data.${selector}`;
return { ...request, path: kvPath, selector: kvSelector };
}); });
const results = await getSecrets(requests, client); const results = await getSecrets(requests, client);
@@ -78,8 +77,12 @@ async function exportSecrets() {
const { value, request, cachedResponse } = result; const { value, request, cachedResponse } = result;
if (cachedResponse) { if (cachedResponse) {
core.debug(' using cached response'); core.debug(' using cached response');
} }
command.issue('add-mask', value); for (const line of value.replace(/\r/g, '').split('\n')) {
if (line.length > 0) {
command.issue('add-mask', line);
}
}
if (exportEnv) { if (exportEnv) {
core.exportVariable(request.envVarName, `${value}`); core.exportVariable(request.envVarName, `${value}`);
} }
@@ -131,12 +134,13 @@ function parseSecretsInput(secretsInput) {
throw Error(`You must provide a valid path and key. Input: "${secret}"`); throw Error(`You must provide a valid path and key. Input: "${secret}"`);
} }
const [path, selector] = pathParts; const [path, selectorQuoted] = pathParts;
/** @type {any} */ /** @type {any} */
const selectorAst = jsonata(selector).ast(); const selectorAst = jsonata(selectorQuoted).ast();
const selector = selectorQuoted.replace(new RegExp('"', 'g'), '');
if ((selectorAst.type !== "path" || selectorAst.steps[0].stages) && !outputVarName) { if ((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}"`);
} }
@@ -163,7 +167,7 @@ function parseSecretsInput(secretsInput) {
*/ */
function normalizeOutputKey(dataKey, isEnvVar = false) { function normalizeOutputKey(dataKey, isEnvVar = false) {
let outputKey = dataKey let outputKey = dataKey
.replace('.', '__').replace(/[^\p{L}\p{N}_-]/gu, ''); .replace('.', '__').replace(new RegExp('-', 'g'), '').replace(/[^\p{L}\p{N}_-]/gu, '');
if (isEnvVar) { if (isEnvVar) {
outputKey = outputKey.toUpperCase(); outputKey = outputKey.toUpperCase();
} }
@@ -200,4 +204,4 @@ module.exports = {
parseSecretsInput, parseSecretsInput,
normalizeOutputKey, normalizeOutputKey,
parseHeadersInput parseHeadersInput
}; };
+74
View File
@@ -2,6 +2,7 @@ jest.mock('got');
jest.mock('@actions/core'); jest.mock('@actions/core');
jest.mock('@actions/core/lib/command'); jest.mock('@actions/core/lib/command');
const command = require('@actions/core/lib/command');
const core = require('@actions/core'); const core = require('@actions/core');
const got = require('got'); const got = require('got');
const { const {
@@ -178,6 +179,12 @@ describe('exportSecrets', () => {
} }
} }
function mockExportToken(doExport) {
when(core.getInput)
.calledWith('exportToken')
.mockReturnValueOnce(doExport);
}
it('simple secret retrieval', async () => { it('simple secret retrieval', async () => {
mockInput('test key'); mockInput('test key');
mockVaultData({ mockVaultData({
@@ -257,4 +264,71 @@ describe('exportSecrets', () => {
expect(core.exportVariable).toBeCalledWith('KEY__VALUE', '1'); expect(core.exportVariable).toBeCalledWith('KEY__VALUE', '1');
expect(core.setOutput).toBeCalledWith('key__value', '1'); expect(core.setOutput).toBeCalledWith('key__value', '1');
}); });
it('export Vault token', async () => {
mockInput('test key');
mockVaultData({
key: 1
});
mockExportToken("true")
await exportSecrets();
expect(core.exportVariable).toBeCalledTimes(2);
expect(core.exportVariable).toBeCalledWith('VAULT_TOKEN', 'EXAMPLE');
expect(core.exportVariable).toBeCalledWith('KEY', '1');
expect(core.setOutput).toBeCalledWith('key', '1');
});
it('not export Vault token', async () => {
mockInput('test key');
mockVaultData({
key: 1
});
mockExportToken("false")
await exportSecrets();
expect(core.exportVariable).toBeCalledTimes(1);
expect(core.exportVariable).toBeCalledWith('KEY', '1');
expect(core.setOutput).toBeCalledWith('key', '1');
});
it('single-line secret gets masked', async () => {
mockInput('test key');
mockVaultData({
key: 'secret'
});
mockExportToken("false")
await exportSecrets();
expect(command.issue).toBeCalledTimes(1);
expect(command.issue).toBeCalledWith('add-mask', 'secret');
expect(core.setOutput).toBeCalledWith('key', 'secret');
})
it('multi-line secret gets masked for each line', async () => {
const multiLineString = `a multi-line string
with blank lines
`
mockInput('test key');
mockVaultData({
key: multiLineString
});
mockExportToken("false")
await exportSecrets();
expect(command.issue).toBeCalledTimes(2); // 1 for each non-empty line.
expect(command.issue).toBeCalledWith('add-mask', 'a multi-line string');
expect(command.issue).toBeCalledWith('add-mask', 'with blank lines');
expect(core.setOutput).toBeCalledWith('key', multiLineString);
})
}); });
+57 -6
View File
@@ -1,22 +1,46 @@
// @ts-check // @ts-check
const core = require('@actions/core'); const core = require('@actions/core');
const rsasign = require('jsrsasign');
const fs = require('fs');
const defaultKubernetesTokenPath = '/var/run/secrets/kubernetes.io/serviceaccount/token'
/*** /***
* 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
* @param {import('got').Got} client * @param {import('got').Got} client
*/ */
async function retrieveToken(method, client) { async function retrieveToken(method, client) {
const path = core.getInput('path', { required: false }) || method;
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: true });
return await getClientToken(client, method, { role_id: vaultRoleId, secret_id: vaultSecretId }); return await getClientToken(client, method, path, { role_id: vaultRoleId, secret_id: vaultSecretId });
} }
case 'github': { case 'github': {
const githubToken = core.getInput('githubToken', { required: true }); const githubToken = core.getInput('githubToken', { required: true });
return await getClientToken(client, method, { token: githubToken }); return await getClientToken(client, method, path, { token: githubToken });
} }
case 'jwt': {
const role = core.getInput('role', { required: true });
const privateKeyRaw = core.getInput('jwtPrivateKey', { required: true });
const privateKey = Buffer.from(privateKeyRaw, 'base64').toString();
const keyPassword = core.getInput('jwtKeyPassword', { required: false });
const tokenTtl = core.getInput('jwtTtl', { required: false }) || '3600'; // 1 hour
const jwt = generateJwt(privateKey, keyPassword, Number(tokenTtl));
return await getClientToken(client, method, path, { jwt: jwt, role: role });
}
case 'kubernetes': {
const role = core.getInput('role', { required: true })
const tokenPath = core.getInput('kubernetesTokenPath', { required: false }) || defaultKubernetesTokenPath
const data = fs.readFileSync(tokenPath, 'utf8')
if (!(role && data) && data != "") {
throw new Error("Role Name must be set and a kubernetes token must set")
}
return await getClientToken(client, method, path, { jwt: data, role: role })
}
default: { default: {
if (!method || method === 'token') { if (!method || method === 'token') {
return core.getInput('token', { required: true }); return core.getInput('token', { required: true });
@@ -26,19 +50,46 @@ async function retrieveToken(method, client) {
if (!payload) { if (!payload) {
throw Error('When using a custom authentication method, you must provide the payload'); throw Error('When using a custom authentication method, you must provide the payload');
} }
return await getClientToken(client, method, JSON.parse(payload.trim())); return await getClientToken(client, method, path, JSON.parse(payload.trim()));
} }
} }
} }
} }
/***
* Generates signed Json Web Token with specified private key and ttl
* @param {string} privateKey
* @param {string} keyPassword
* @param {number} ttl
*/
function generateJwt(privateKey, keyPassword, ttl) {
const alg = 'RS256';
const header = { alg: alg, typ: 'JWT' };
const now = rsasign.KJUR.jws.IntDate.getNow();
const payload = {
iss: 'vault-action',
iat: now,
nbf: now,
exp: now + ttl,
event: process.env.GITHUB_EVENT_NAME,
workflow: process.env.GITHUB_WORKFLOW,
sha: process.env.GITHUB_SHA,
actor: process.env.GITHUB_ACTOR,
repository: process.env.GITHUB_REPOSITORY,
ref: process.env.GITHUB_REF
};
const decryptedKey = rsasign.KEYUTIL.getKey(privateKey, keyPassword);
return rsasign.KJUR.jws.JWS.sign(alg, JSON.stringify(header), JSON.stringify(payload), decryptedKey);
}
/*** /***
* Call the appropriate login endpoint and parse out the token in the response. * Call the appropriate login endpoint and parse out the token in the response.
* @param {import('got').Got} client * @param {import('got').Got} client
* @param {string} method * @param {string} method
* @param {string} path
* @param {any} payload * @param {any} payload
*/ */
async function getClientToken(client, method, payload) { async function getClientToken(client, method, path, payload) {
/** @type {'json'} */ /** @type {'json'} */
const responseType = 'json'; const responseType = 'json';
var options = { var options = {
@@ -46,10 +97,10 @@ async function getClientToken(client, method, payload) {
responseType, responseType,
}; };
core.debug(`Retrieving Vault Token from v1/auth/${method}/login endpoint`); core.debug(`Retrieving Vault Token from v1/auth/${path}/login endpoint`);
/** @type {import('got').Response<VaultLoginResponse>} */ /** @type {import('got').Response<VaultLoginResponse>} */
const response = await client.post(`v1/auth/${method}/login`, options); const response = await client.post(`v1/auth/${path}/login`, options);
if (response && response.body && response.body.auth && response.body.auth.client_token) { if (response && response.body && response.body.auth && response.body.auth.client_token) {
core.debug('✔ Vault Token successfully retrieved'); core.debug('✔ Vault Token successfully retrieved');
+83
View File
@@ -0,0 +1,83 @@
jest.mock('got');
jest.mock('@actions/core');
jest.mock('@actions/core/lib/command');
jest.mock("fs")
const core = require('@actions/core');
const got = require('got');
const fs = require("fs")
const { when } = require('jest-when');
const {
retrieveToken
} = require('./auth');
function mockInput(name, key) {
when(core.getInput)
.calledWith(name)
.mockReturnValueOnce(key);
}
function mockApiResponse() {
const response = { body: { auth: { client_token: testToken, renewable: true, policies: [], accessor: "accessor" } } }
got.post = jest.fn()
got.post.mockReturnValue(response)
}
const testToken = "testoken";
describe("test retrival for token", () => {
beforeEach(() => {
jest.resetAllMocks();
});
it("test retrival with approle", async () => {
const method = 'approle'
mockApiResponse()
const testRoleId = "testRoleId"
const testSecretId = "testSecretId"
mockInput("roleId", testRoleId)
mockInput("secretId", testSecretId)
const token = await retrieveToken(method, got)
expect(token).toEqual(testToken)
const payload = got.post.mock.calls[0][1].json
expect(payload).toEqual({ role_id: testRoleId, secret_id: testSecretId })
const url = got.post.mock.calls[0][0]
expect(url).toContain('approle')
})
it("test retrival with github token", async () => {
const method = 'github'
mockApiResponse()
const githubToken = "githubtoken"
mockInput("githubToken", githubToken)
const token = await retrieveToken(method, got)
expect(token).toEqual(testToken)
const payload = got.post.mock.calls[0][1].json
expect(payload).toEqual({ token: githubToken })
const url = got.post.mock.calls[0][0]
expect(url).toContain('github')
})
it("test retrival with kubernetes", async () => {
const method = 'kubernetes'
const jwtToken = "someJwtToken"
const testRole = "testRole"
const testTokenPath = "testTokenPath"
const testPath = 'differentK8sPath'
mockApiResponse()
mockInput("kubernetesTokenPath", testTokenPath)
mockInput("role", testRole)
mockInput("path", testPath)
fs.readFileSync = jest.fn()
fs.readFileSync.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('differentK8sPath')
})
})
+1 -1
View File
@@ -7,4 +7,4 @@ const { exportSecrets } = require('./action');
} catch (error) { } catch (error) {
core.setFailed(error.message); core.setFailed(error.message);
} }
})(); })();
+13 -5
View File
@@ -25,9 +25,9 @@ async function getSecrets(secretRequests, client) {
const responseCache = new Map(); const responseCache = new Map();
const results = []; const results = [];
for (const secretRequest of secretRequests) { for (const secretRequest of secretRequests) {
const { path, selector } = secretRequest; let { path, selector } = secretRequest;
const requestPath = `v1${path}`; const requestPath = `v1/${path}`;
let body; let body;
let cachedResponse = false; let cachedResponse = false;
if (responseCache.has(requestPath)) { if (responseCache.has(requestPath)) {
@@ -38,8 +38,16 @@ async function getSecrets(secretRequests, client) {
body = result.body; body = result.body;
responseCache.set(requestPath, body); responseCache.set(requestPath, body);
} }
if (!selector.match(/.*[\.].*/)) {
selector = '"' + selector + '"'
}
selector = "data." + selector
body = JSON.parse(body)
if (body.data["data"] != undefined) {
selector = "data." + selector
}
const value = selectData(JSON.parse(body), selector); const value = selectData(body, selector);
results.push({ results.push({
request: secretRequest, request: secretRequest,
value, value,
@@ -58,14 +66,14 @@ function selectData(data, selector) {
const ata = jsonata(selector); const ata = jsonata(selector);
let result = JSON.stringify(ata.evaluate(data)); let result = JSON.stringify(ata.evaluate(data));
// Compat for custom engines // Compat for custom engines
if (!result && ata.ast().type === "path" && ata.ast()['steps'].length === 1 && selector !== 'data' && 'data' in data) { if (!result && ((ata.ast().type === "path" && ata.ast()['steps'].length === 1) || ata.ast().type === "string") && selector !== 'data' && 'data' in data) {
result = JSON.stringify(jsonata(`data.${selector}`).evaluate(data)); result = JSON.stringify(jsonata(`data.${selector}`).evaluate(data));
} else if (!result) { } else if (!result) {
throw Error(`Unable to retrieve result for ${selector}. No match data was found. Double check your Key or Selector.`); throw Error(`Unable to retrieve result for ${selector}. No match data was found. Double check your Key or Selector.`);
} }
if (result.startsWith(`"`)) { if (result.startsWith(`"`)) {
result = result.substring(1, result.length - 1); result = JSON.parse(result);
} }
return result; return result;
} }