mirror of
https://github.com/hashicorp/vault-action.git
synced 2025-11-09 16:16:55 +00:00
Merge c1b8c73d07 into 1d767e3957
This commit is contained in:
commit
a2519fbb6f
4 changed files with 125 additions and 29 deletions
58
README.md
58
README.md
|
|
@ -67,7 +67,7 @@ Retrieved secrets are available as environment variables or outputs for subseque
|
||||||
# ...
|
# ...
|
||||||
```
|
```
|
||||||
|
|
||||||
If your project needs a format other than env vars and step outputs, you can use additional steps to transform them into the desired format.
|
If your project needs a format other than env vars and step outputs, you can use additional steps to transform them into the desired format.
|
||||||
For example, a common pattern is to save all the secrets in a JSON file:
|
For example, a common pattern is to save all the secrets in a JSON file:
|
||||||
```yaml
|
```yaml
|
||||||
#...
|
#...
|
||||||
|
|
@ -420,31 +420,33 @@ steps:
|
||||||
|
|
||||||
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 | | |
|
||||||
| `method` | The method to use to authenticate with Vault. | `token` | |
|
| `method` | The method to use to authenticate with Vault. | `token` | |
|
||||||
| `role` | Vault role for specified auth method | | |
|
| `role` | Vault role for specified auth method | | |
|
||||||
| `path` | Custom vault path, if the auth method was enabled at a different path | | |
|
| `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 | | |
|
||||||
| `jwtPrivateKey` | Base64 encoded Private key to sign JWT | | |
|
| `jwtPrivateKey` | Base64 encoded Private key to sign JWT | | |
|
||||||
| `jwtKeyPassword` | Password for key stored in jwtPrivateKey (if needed) | | |
|
| `jwtKeyPassword` | Password for key stored in jwtPrivateKey (if needed) | | |
|
||||||
| `jwtGithubAudience` | Identifies the recipient ("aud" claim) that the JWT is intended for |`sigstore`| |
|
| `jwtGithubAudience` | Identifies the recipient ("aud" claim) that the JWT is intended for | `sigstore` | |
|
||||||
| `jwtTtl` | Time in seconds, after which token expires | | 3600 |
|
| `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` | |
|
| `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. | | |
|
| `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. | | |
|
| `extraHeaders` | A string of newline separated extra headers to include on every request. | | |
|
||||||
| `exportEnv` | Whether or not export secrets as environment variables. | `true` | |
|
| `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` | |
|
| `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. | | |
|
| `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. | | |
|
| `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. | | |
|
| `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` | |
|
| `tlsSkipVerify` | When set to true, disables verification of server certificates when testing the action. | `false` | |
|
||||||
|
| `retryVaultTokenRetrieval` | When set to true, attempts to authenticate with Vault will be retried when an HTTP error occurs | `false` | |
|
||||||
|
|
||||||
|
|
||||||
## Masking - Hiding Secrets from Logs
|
## Masking - Hiding Secrets from Logs
|
||||||
|
|
||||||
|
|
@ -473,7 +475,7 @@ $ npm install && npm run build
|
||||||
|
|
||||||
### Vault test instance
|
### Vault test instance
|
||||||
|
|
||||||
The Github Action needs access to a working Vault instance to function.
|
The Github Action needs access to a working Vault instance to function.
|
||||||
Multiple docker configurations are available via the docker-compose.yml file to run containers compatible with the various acceptance test suites.
|
Multiple docker configurations are available via the docker-compose.yml file to run containers compatible with the various acceptance test suites.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
|
@ -520,4 +522,4 @@ Edit the ./.github/workflows/local-test.yaml file to use your new feature branch
|
||||||
Run your feature branch locally.
|
Run your feature branch locally.
|
||||||
```sh
|
```sh
|
||||||
$ act local-test
|
$ act local-test
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,9 @@ inputs:
|
||||||
secretEncodingType:
|
secretEncodingType:
|
||||||
description: 'The encoding type of the secret to decode. If not specified, the secret will not be decoded. Supported values: base64, hex, utf8'
|
description: 'The encoding type of the secret to decode. If not specified, the secret will not be decoded. Supported values: base64, hex, utf8'
|
||||||
required: false
|
required: false
|
||||||
|
retryVaultTokenRetrieval:
|
||||||
|
description: 'Enable retrying retrieval of Vault server tokens. If not specified the token request to the Vault server will only be tried once.'
|
||||||
|
required: false
|
||||||
runs:
|
runs:
|
||||||
using: 'node16'
|
using: 'node16'
|
||||||
main: 'dist/index.js'
|
main: 'dist/index.js'
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ async function exportSecrets() {
|
||||||
headers: {},
|
headers: {},
|
||||||
https: {},
|
https: {},
|
||||||
retry: {
|
retry: {
|
||||||
|
methods: [...got.defaults.options.retry.methods],
|
||||||
statusCodes: [
|
statusCodes: [
|
||||||
...got.defaults.options.retry.statusCodes,
|
...got.defaults.options.retry.statusCodes,
|
||||||
// Vault returns 412 when the token in use hasn't yet been replicated
|
// Vault returns 412 when the token in use hasn't yet been replicated
|
||||||
|
|
@ -68,6 +69,11 @@ async function exportSecrets() {
|
||||||
defaultOptions.headers["X-Vault-Namespace"] = vaultNamespace;
|
defaultOptions.headers["X-Vault-Namespace"] = vaultNamespace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const retryVaultTokenRetrieval = (core.getInput('retryVaultTokenRetrieval', { required: false }) || 'false').toLowerCase() != 'false';
|
||||||
|
if (retryVaultTokenRetrieval === true) {
|
||||||
|
defaultOptions.retry.methods.push('POST');
|
||||||
|
}
|
||||||
|
|
||||||
const vaultToken = await retrieveToken(vaultMethod, got.extend(defaultOptions));
|
const vaultToken = await retrieveToken(vaultMethod, got.extend(defaultOptions));
|
||||||
defaultOptions.headers['X-Vault-Token'] = vaultToken;
|
defaultOptions.headers['X-Vault-Token'] = vaultToken;
|
||||||
const client = got.extend(defaultOptions);
|
const client = got.extend(defaultOptions);
|
||||||
|
|
|
||||||
|
|
@ -66,4 +66,89 @@ describe('exportSecrets retries', () => {
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('exportSecrets retrieve token retries', () => {
|
||||||
|
var server = new ServerMock({ host: "127.0.0.1", port: 0 });
|
||||||
|
var calls = 0;
|
||||||
|
|
||||||
|
beforeEach((done) => {
|
||||||
|
calls = 0;
|
||||||
|
jest.resetAllMocks();
|
||||||
|
|
||||||
|
when(core.getInput)
|
||||||
|
.calledWith('token', expect.anything())
|
||||||
|
.mockReturnValueOnce('EXAMPLE');
|
||||||
|
|
||||||
|
when(core.getInput)
|
||||||
|
.calledWith('secrets', expect.anything())
|
||||||
|
.mockReturnValueOnce("kv/mysecret key");
|
||||||
|
|
||||||
|
when(core.getInput)
|
||||||
|
.calledWith('method', expect.anything())
|
||||||
|
.mockReturnValueOnce('approle')
|
||||||
|
|
||||||
|
when(core.getInput)
|
||||||
|
.calledWith('roleId', expect.anything())
|
||||||
|
.mockReturnValueOnce('roleId')
|
||||||
|
|
||||||
|
when(core.getInput)
|
||||||
|
.calledWith('secretId', expect.anything())
|
||||||
|
.mockReturnValueOnce('secretId')
|
||||||
|
|
||||||
|
when(core.getInput)
|
||||||
|
.calledWith('retryVaultTokenRetrieval', expect.anything())
|
||||||
|
.mockReturnValueOnce('true')
|
||||||
|
|
||||||
|
server.start(() => {
|
||||||
|
expect(server.getHttpPort()).not.toBeNull();
|
||||||
|
when(core.getInput)
|
||||||
|
.calledWith('url', expect.anything())
|
||||||
|
.mockReturnValueOnce('http://127.0.0.1:' + server.getHttpPort());
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach((done) => {
|
||||||
|
server.stop(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
function mockKvRetrieval() {
|
||||||
|
server.on({
|
||||||
|
path: '/v1/kv/mysecret',
|
||||||
|
reply: {
|
||||||
|
status: 200,
|
||||||
|
headers: { "content-type": "application/json" },
|
||||||
|
body: function() {
|
||||||
|
return JSON.stringify({ data: {"key": "value"} })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function mockStatusCodes(statusCodes) {
|
||||||
|
server.on({
|
||||||
|
method: 'POST',
|
||||||
|
path: '/v1/auth/approle/login',
|
||||||
|
reply: {
|
||||||
|
status: function() {
|
||||||
|
let status = statusCodes[calls];
|
||||||
|
calls += 1;
|
||||||
|
return status;
|
||||||
|
},
|
||||||
|
body: function() {
|
||||||
|
return JSON.stringify({ auth: {"client_token": "token"} });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
it('retries on 500 status code', (done) => {
|
||||||
|
mockKvRetrieval()
|
||||||
|
mockStatusCodes([500, 201])
|
||||||
|
exportSecrets().then(() => {
|
||||||
|
expect(calls).toEqual(2);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue