mirror of
https://github.com/hashicorp/vault-action.git
synced 2025-11-07 07:06:56 +00:00
Development flow enhancements (#430)
+ added a contribution section to the readme + added a local workflow to test changes + made the vault token configurable for tests * bumped action/checkout
This commit is contained in:
parent
74bc2a617b
commit
3bbbc68bd0
7 changed files with 146 additions and 40 deletions
20
.github/workflows/build.yml
vendored
20
.github/workflows/build.yml
vendored
|
|
@ -10,7 +10,9 @@ jobs:
|
|||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
|
|
@ -37,7 +39,9 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- name: Run docker-compose
|
||||
run: docker-compose up -d vault
|
||||
|
|
@ -71,7 +75,9 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- name: Run docker-compose
|
||||
run: docker-compose up -d vault-enterprise
|
||||
|
|
@ -107,7 +113,9 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- name: Run docker-compose
|
||||
run: docker-compose up -d vault
|
||||
|
|
@ -175,7 +183,9 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- name: Run docker-compose
|
||||
run: docker-compose up -d vault-tls
|
||||
|
|
|
|||
24
.github/workflows/local-test.yaml
vendored
Normal file
24
.github/workflows/local-test.yaml
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
# This is a sample workflow to help test contributions
|
||||
# Change the branch name, url and token to fit with your own environment
|
||||
|
||||
# Use 'on: push' instead of 'on: local-test' if you wish to run the test on github
|
||||
# If running locally with act, run the workflow with 'act local-test'
|
||||
|
||||
# Don't forget to revert the file changes and invalidate any tokens that were committed before opening a pull-request
|
||||
on: local-test
|
||||
|
||||
name: local-test
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: local-test
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Import Secrets
|
||||
uses: hashicorp/vault-action@YOUR_BRANCH_NAME
|
||||
with:
|
||||
url: http://localhost:8200
|
||||
method: token
|
||||
token: testtoken
|
||||
secrets: |
|
||||
secret/data/test secret | SAMPLE_SECRET;
|
||||
68
README.md
68
README.md
|
|
@ -31,6 +31,7 @@ A helper action for easily pulling secrets from HashiCorp Vault™.
|
|||
- [Reference](#reference)
|
||||
- [Masking - Hiding Secrets from Logs](#masking---hiding-secrets-from-logs)
|
||||
- [Normalization](#normalization)
|
||||
- [Contributing](#contributing)
|
||||
|
||||
<!-- /TOC -->
|
||||
|
||||
|
|
@ -419,3 +420,70 @@ This action uses GitHub Action's built-in masking, so all variables will automat
|
|||
## 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 provide an explicit Output Var Key.
|
||||
|
||||
## Contributing
|
||||
|
||||
If you wish to contribute to this project, the following dependencies are recommended for local development:
|
||||
- [npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) to install dependencies, build project and run tests
|
||||
- [docker](https://docs.docker.com/get-docker/) to run the pre-configured vault containers for acceptance tests
|
||||
- [docker-compose](https://docs.docker.com/compose/) to spin up the pre-configured vault containers for acceptance tests
|
||||
- [act](https://github.com/nektos/act) to run the vault-action locally
|
||||
|
||||
### Build
|
||||
|
||||
Use npm to install dependencies and build the project:
|
||||
|
||||
```sh
|
||||
$ npm install && npm run build
|
||||
```
|
||||
|
||||
### Vault test instance
|
||||
|
||||
The Github Action needs access to a working Vault instance to function.
|
||||
Multiple docker configurations are available via the docker-compose.yml file to run containers compatible with the various acceptance test suites.
|
||||
|
||||
```sh
|
||||
$ docker-compose up -d vault # Choose one of: vault, vault-enterprise, vault-tls depending on which tests you would like to run
|
||||
```
|
||||
|
||||
Instead of using one of the dockerized instance, you can also use your own local or remote Vault instance by exporting these environment variables:
|
||||
|
||||
```sh
|
||||
$ export VAULT_HOST=<YOUR VAULT CLUSTER LOCATION> # localhost if undefined
|
||||
$ export VAULT_PORT=<YOUR VAULT PORT> # 8200 if undefined
|
||||
$ export VAULT_TOKEN=<YOUR VAULT TOKEN> # testtoken if undefined
|
||||
```
|
||||
|
||||
### Running unit tests
|
||||
|
||||
Unit tests can be executed at any time with no dependencies or prior setup.
|
||||
|
||||
```sh
|
||||
$ npm test
|
||||
```
|
||||
|
||||
### Running acceptance tests
|
||||
|
||||
With a succesful build to take your local changes into account and a working Vault instance configured, you can now run acceptance tests to validate if any regressions were introduced.
|
||||
|
||||
```sh
|
||||
$ npm run test:integration:basic # Choose one of: basic, enterprise, e2e, e2e-tls
|
||||
```
|
||||
|
||||
### Running the action locally
|
||||
|
||||
You can use the [act](https://github.com/nektos/act) command to test your changes locally if desired. Unfortunately it is not currently possible to use uncommitted local changes for a shared workfow. You will still need to push
|
||||
the changes you would like to validate beforehand. Even if a commit is necessary, this is still a more detailed and faster feedback loop than waiting for the action to be executed by Github in a different repository.
|
||||
|
||||
Push your changes into a feature branch.
|
||||
```sh
|
||||
$ git checkout -b my-feature-branch
|
||||
$ git commit -m "testing new changes"
|
||||
$ git push
|
||||
```
|
||||
|
||||
Edit the ./.github/workflows/local-test.yaml file to use your new feature branch. You may have to additionally edit the vault url, token and secret path if you are not using one of the provided containerized instance.
|
||||
Run your feature branch locally.
|
||||
```sh
|
||||
$ act local-test
|
||||
```
|
||||
|
|
@ -8,20 +8,21 @@ const { when } = require('jest-when');
|
|||
const { exportSecrets } = require('../../src/action');
|
||||
|
||||
const vaultUrl = `http://${process.env.VAULT_HOST || 'localhost'}:${process.env.VAULT_PORT || '8200'}`;
|
||||
const vaultToken = `${process.env.VAULT_TOKEN || 'testtoken'}`
|
||||
|
||||
describe('integration', () => {
|
||||
beforeAll(async () => {
|
||||
// Verify Connection
|
||||
await got(`${vaultUrl}/v1/secret/config`, {
|
||||
headers: {
|
||||
'X-Vault-Token': 'testtoken',
|
||||
'X-Vault-Token': vaultToken,
|
||||
},
|
||||
});
|
||||
|
||||
await got(`${vaultUrl}/v1/secret/data/test`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-Vault-Token': 'testtoken',
|
||||
'X-Vault-Token': vaultToken,
|
||||
},
|
||||
json: {
|
||||
data: {
|
||||
|
|
@ -33,7 +34,7 @@ describe('integration', () => {
|
|||
await got(`${vaultUrl}/v1/secret/data/nested/test`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-Vault-Token': 'testtoken',
|
||||
'X-Vault-Token': vaultToken,
|
||||
},
|
||||
json: {
|
||||
data: {
|
||||
|
|
@ -45,7 +46,7 @@ describe('integration', () => {
|
|||
await got(`${vaultUrl}/v1/secret/data/foobar`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-Vault-Token': 'testtoken',
|
||||
'X-Vault-Token': vaultToken,
|
||||
},
|
||||
json: {
|
||||
data: {
|
||||
|
|
@ -59,7 +60,7 @@ describe('integration', () => {
|
|||
await got(`${vaultUrl}/v1/sys/mounts/secret-kv1`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-Vault-Token': 'testtoken',
|
||||
'X-Vault-Token': vaultToken,
|
||||
},
|
||||
json: {
|
||||
type: 'kv'
|
||||
|
|
@ -77,7 +78,7 @@ describe('integration', () => {
|
|||
await got(`${vaultUrl}/v1/secret-kv1/test`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-Vault-Token': 'testtoken',
|
||||
'X-Vault-Token': vaultToken,
|
||||
},
|
||||
json: {
|
||||
secret: 'CUSTOMSECRET',
|
||||
|
|
@ -87,7 +88,7 @@ describe('integration', () => {
|
|||
await got(`${vaultUrl}/v1/secret-kv1/foobar`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-Vault-Token': 'testtoken',
|
||||
'X-Vault-Token': vaultToken,
|
||||
},
|
||||
json: {
|
||||
fookv1: 'bar',
|
||||
|
|
@ -97,7 +98,7 @@ describe('integration', () => {
|
|||
await got(`${vaultUrl}/v1/secret-kv1/nested/test`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-Vault-Token': 'testtoken',
|
||||
'X-Vault-Token': vaultToken,
|
||||
},
|
||||
json: {
|
||||
"other-Secret-dash": 'OTHERCUSTOMSECRET',
|
||||
|
|
@ -114,7 +115,7 @@ describe('integration', () => {
|
|||
|
||||
when(core.getInput)
|
||||
.calledWith('token', expect.anything())
|
||||
.mockReturnValueOnce('testtoken');
|
||||
.mockReturnValueOnce(vaultToken);
|
||||
});
|
||||
|
||||
function mockInput(secrets) {
|
||||
|
|
@ -207,7 +208,7 @@ describe('integration', () => {
|
|||
await got(`${vaultUrl}/v1/cubbyhole/test`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-Vault-Token': 'testtoken',
|
||||
'X-Vault-Token': vaultToken,
|
||||
},
|
||||
json: {
|
||||
foo: "bar",
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ const { when } = require('jest-when');
|
|||
const { exportSecrets } = require('../../src/action');
|
||||
|
||||
const vaultUrl = `http://${process.env.VAULT_HOST || 'localhost'}:${process.env.VAULT_PORT || '8200'}`;
|
||||
const vaultToken = `${process.env.VAULT_TOKEN || 'testtoken'}`
|
||||
|
||||
/**
|
||||
* Returns Github OIDC response mock
|
||||
|
|
@ -59,7 +60,7 @@ describe('jwt auth', () => {
|
|||
// Verify Connection
|
||||
await got(`${vaultUrl}/v1/secret/config`, {
|
||||
headers: {
|
||||
'X-Vault-Token': 'testtoken',
|
||||
'X-Vault-Token': vaultToken,
|
||||
},
|
||||
});
|
||||
|
||||
|
|
@ -67,7 +68,7 @@ describe('jwt auth', () => {
|
|||
await got(`${vaultUrl}/v1/sys/auth/jwt`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-Vault-Token': 'testtoken',
|
||||
'X-Vault-Token': vaultToken,
|
||||
},
|
||||
json: {
|
||||
type: 'jwt'
|
||||
|
|
@ -85,7 +86,7 @@ describe('jwt auth', () => {
|
|||
await got(`${vaultUrl}/v1/sys/policy/reader`, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'X-Vault-Token': 'testtoken',
|
||||
'X-Vault-Token': vaultToken,
|
||||
},
|
||||
json: {
|
||||
policy: `
|
||||
|
|
@ -99,7 +100,7 @@ describe('jwt auth', () => {
|
|||
await got(`${vaultUrl}/v1/auth/jwt/config`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-Vault-Token': 'testtoken',
|
||||
'X-Vault-Token': vaultToken,
|
||||
},
|
||||
json: {
|
||||
jwt_validation_pubkeys: publicRsaKey,
|
||||
|
|
@ -110,7 +111,7 @@ describe('jwt auth', () => {
|
|||
await got(`${vaultUrl}/v1/auth/jwt/role/default`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-Vault-Token': 'testtoken',
|
||||
'X-Vault-Token': vaultToken,
|
||||
},
|
||||
json: {
|
||||
role_type: 'jwt',
|
||||
|
|
@ -126,7 +127,7 @@ describe('jwt auth', () => {
|
|||
await got(`${vaultUrl}/v1/secret/data/test`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-Vault-Token': 'testtoken',
|
||||
'X-Vault-Token': vaultToken,
|
||||
},
|
||||
json: {
|
||||
data: {
|
||||
|
|
@ -172,7 +173,7 @@ describe('jwt auth', () => {
|
|||
await got(`${vaultUrl}/v1/auth/jwt/role/default-sigstore`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-Vault-Token': 'testtoken',
|
||||
'X-Vault-Token': vaultToken,
|
||||
},
|
||||
json: {
|
||||
role_type: 'jwt',
|
||||
|
|
|
|||
|
|
@ -1,20 +1,21 @@
|
|||
const got = require('got');
|
||||
|
||||
const vaultUrl = `${process.env.VAULT_HOST}:${process.env.VAULT_PORT}`;
|
||||
const vaultToken = `${process.env.VAULT_TOKEN || 'testtoken'}`
|
||||
|
||||
(async () => {
|
||||
try {
|
||||
// Verify Connection
|
||||
await got(`http://${vaultUrl}/v1/secret/config`, {
|
||||
headers: {
|
||||
'X-Vault-Token': 'testtoken',
|
||||
'X-Vault-Token': vaultToken,
|
||||
},
|
||||
});
|
||||
|
||||
await got(`http://${vaultUrl}/v1/secret/data/test`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-Vault-Token': 'testtoken',
|
||||
'X-Vault-Token': vaultToken,
|
||||
},
|
||||
json: {
|
||||
data: {
|
||||
|
|
@ -26,7 +27,7 @@ const vaultUrl = `${process.env.VAULT_HOST}:${process.env.VAULT_PORT}`;
|
|||
await got(`http://${vaultUrl}/v1/secret/data/nested/test`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-Vault-Token': 'testtoken',
|
||||
'X-Vault-Token': vaultToken,
|
||||
},
|
||||
json: {
|
||||
data: {
|
||||
|
|
@ -38,7 +39,7 @@ const vaultUrl = `${process.env.VAULT_HOST}:${process.env.VAULT_PORT}`;
|
|||
await got(`http://${vaultUrl}/v1/sys/mounts/my-secret`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-Vault-Token': 'testtoken',
|
||||
'X-Vault-Token': vaultToken,
|
||||
},
|
||||
json: {
|
||||
type: 'kv'
|
||||
|
|
@ -48,7 +49,7 @@ const vaultUrl = `${process.env.VAULT_HOST}:${process.env.VAULT_PORT}`;
|
|||
await got(`http://${vaultUrl}/v1/my-secret/test`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-Vault-Token': 'testtoken',
|
||||
'X-Vault-Token': vaultToken,
|
||||
},
|
||||
json: {
|
||||
altSecret: 'CUSTOMSECRET',
|
||||
|
|
@ -58,7 +59,7 @@ const vaultUrl = `${process.env.VAULT_HOST}:${process.env.VAULT_PORT}`;
|
|||
await got(`http://${vaultUrl}/v1/my-secret/nested/test`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-Vault-Token': 'testtoken',
|
||||
'X-Vault-Token': vaultToken,
|
||||
},
|
||||
json: {
|
||||
otherAltSecret: 'OTHERCUSTOMSECRET',
|
||||
|
|
@ -68,7 +69,7 @@ const vaultUrl = `${process.env.VAULT_HOST}:${process.env.VAULT_PORT}`;
|
|||
await got(`http://${vaultUrl}/v1/cubbyhole/test`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-Vault-Token': 'testtoken',
|
||||
'X-Vault-Token': vaultToken,
|
||||
},
|
||||
json: {
|
||||
foo: 'bar',
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ const { when } = require('jest-when');
|
|||
const { exportSecrets } = require('../../src/action');
|
||||
|
||||
const vaultUrl = `http://${process.env.VAULT_HOST || 'localhost'}:${process.env.VAULT_PORT || '8201'}`;
|
||||
const vaultToken = `${process.env.VAULT_TOKEN || 'testtoken'}`
|
||||
|
||||
describe('integration', () => {
|
||||
beforeAll(async () => {
|
||||
|
|
@ -15,7 +16,7 @@ describe('integration', () => {
|
|||
// Verify Connection
|
||||
await got(`${vaultUrl}/v1/secret/config`, {
|
||||
headers: {
|
||||
'X-Vault-Token': 'testtoken',
|
||||
'X-Vault-Token': vaultToken,
|
||||
},
|
||||
});
|
||||
|
||||
|
|
@ -48,7 +49,7 @@ describe('integration', () => {
|
|||
|
||||
when(core.getInput)
|
||||
.calledWith('token', expect.anything())
|
||||
.mockReturnValueOnce('testtoken');
|
||||
.mockReturnValueOnce(vaultToken);
|
||||
|
||||
when(core.getInput)
|
||||
.calledWith('namespace', expect.anything())
|
||||
|
|
@ -119,7 +120,7 @@ describe('authenticate with approle', () => {
|
|||
// Verify Connection
|
||||
await got(`${vaultUrl}/v1/secret/config`, {
|
||||
headers: {
|
||||
'X-Vault-Token': 'testtoken',
|
||||
'X-Vault-Token': vaultToken,
|
||||
},
|
||||
});
|
||||
|
||||
|
|
@ -137,7 +138,7 @@ describe('authenticate with approle', () => {
|
|||
await got(`${vaultUrl}/v1/sys/auth/approle`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-Vault-Token': 'testtoken',
|
||||
'X-Vault-Token': vaultToken,
|
||||
'X-Vault-Namespace': 'ns2',
|
||||
},
|
||||
json: {
|
||||
|
|
@ -157,7 +158,7 @@ describe('authenticate with approle', () => {
|
|||
await got(`${vaultUrl}/v1/sys/policies/acl/test`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-Vault-Token': 'testtoken',
|
||||
'X-Vault-Token': vaultToken,
|
||||
'X-Vault-Namespace': 'ns2',
|
||||
},
|
||||
json: {
|
||||
|
|
@ -170,7 +171,7 @@ describe('authenticate with approle', () => {
|
|||
await got(`${vaultUrl}/v1/auth/approle/role/my-role`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-Vault-Token': 'testtoken',
|
||||
'X-Vault-Token': vaultToken,
|
||||
'X-Vault-Namespace': 'ns2',
|
||||
},
|
||||
json: {
|
||||
|
|
@ -181,7 +182,7 @@ describe('authenticate with approle', () => {
|
|||
// Get role-id
|
||||
const roldIdResponse = await got(`${vaultUrl}/v1/auth/approle/role/my-role/role-id`, {
|
||||
headers: {
|
||||
'X-Vault-Token': 'testtoken',
|
||||
'X-Vault-Token': vaultToken,
|
||||
'X-Vault-Namespace': 'ns2',
|
||||
},
|
||||
responseType: 'json',
|
||||
|
|
@ -192,7 +193,7 @@ describe('authenticate with approle', () => {
|
|||
const secretIdResponse = await got(`${vaultUrl}/v1/auth/approle/role/my-role/secret-id`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-Vault-Token': 'testtoken',
|
||||
'X-Vault-Token': vaultToken,
|
||||
'X-Vault-Namespace': 'ns2',
|
||||
},
|
||||
responseType: 'json',
|
||||
|
|
@ -238,7 +239,7 @@ async function enableNamespace(name) {
|
|||
await got(`${vaultUrl}/v1/sys/namespaces/${name}`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-Vault-Token': 'testtoken',
|
||||
'X-Vault-Token': vaultToken,
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
|
|
@ -256,7 +257,7 @@ async function enableEngine(path, namespace, version) {
|
|||
await got(`${vaultUrl}/v1/sys/mounts/${path}`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-Vault-Token': 'testtoken',
|
||||
'X-Vault-Token': vaultToken,
|
||||
'X-Vault-Namespace': namespace,
|
||||
},
|
||||
json: { type: 'kv', config: {}, options: { version }, generate_signing_key: true },
|
||||
|
|
@ -277,7 +278,7 @@ async function writeSecret(engine, path, namespace, version, data) {
|
|||
await got(`${vaultUrl}/v1/${secretPath}`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-Vault-Token': 'testtoken',
|
||||
'X-Vault-Token': vaultToken,
|
||||
'X-Vault-Namespace': namespace,
|
||||
},
|
||||
json: secretPayload
|
||||
|
|
|
|||
Loading…
Reference in a new issue