mirror of
https://github.com/hashicorp/vault-action.git
synced 2025-11-14 18:13:45 +00:00
Merge pull request #1 from blz-ea/feature/core-github-oidc
fix: get token via `@actions/core`
This commit is contained in:
commit
eaa7d6890c
6 changed files with 35811 additions and 15150 deletions
35
README.md
35
README.md
|
|
@ -86,8 +86,28 @@ with:
|
|||
githubToken: ${{ secrets.MY_GITHUB_TOKEN }}
|
||||
caCertificate: ${{ secrets.VAULTCA }}
|
||||
```
|
||||
- **jwt**: you must provide a `role` parameter, additionally you can pass `jwtPrivateKey`, `jwtKeyPassword` & `jwtTtl` parameters.
|
||||
Github provided JWT will be used if `jwtPrivateKey` was not specified
|
||||
- **jwt**: (Github OIDC) you must provide a `role` parameter, additionally you can pass `jwtGithubAudience` parameter.
|
||||
|
||||
```yaml
|
||||
...
|
||||
with:
|
||||
url: https://vault.mycompany.com:8200
|
||||
method: jwt
|
||||
role: github-action
|
||||
```
|
||||
|
||||
**Notice:** For Github provided OIDC token to work workflow should have `id-token: write` & `contents: read` specified in the `permissions` section of a workflow
|
||||
|
||||
```yaml
|
||||
...
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
...
|
||||
```
|
||||
|
||||
- **jwt**: you must provide a `role` parameter, additionally you can pass `jwtPrivateKey`, `jwtKeyPassword`, & `jwtTtl` parameters.
|
||||
|
||||
```yaml
|
||||
...
|
||||
with:
|
||||
|
|
@ -99,16 +119,6 @@ with:
|
|||
jwtTtl: 3600 # 1 hour, default value
|
||||
```
|
||||
|
||||
**Notice:** In order for Github provided JWT to work workflow should have `id-token: write` & `contents: read` specified in the `permissions` section of a workflow
|
||||
|
||||
```yaml
|
||||
...
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
...
|
||||
```
|
||||
|
||||
- **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
|
||||
...
|
||||
|
|
@ -289,6 +299,7 @@ Here are all the inputs available through `with`:
|
|||
| `githubToken` | The Github Token to be used to authenticate with Vault | | |
|
||||
| `jwtPrivateKey` | Base64 encoded Private key to sign JWT | | |
|
||||
| `jwtKeyPassword` | Password for key stored in jwtPrivateKey (if needed) | | |
|
||||
| `jwtGithubAudience` | Audience (`aud`) for Github OIDC token | sigstore| |
|
||||
| `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. | | |
|
||||
|
|
|
|||
|
|
@ -69,6 +69,9 @@ inputs:
|
|||
jwtKeyPassword:
|
||||
description: 'Password for key stored in jwtPrivateKey (if needed)'
|
||||
required: false
|
||||
jwtGithubAudience:
|
||||
description: ''
|
||||
required: false
|
||||
jwtTtl:
|
||||
description: 'Time in seconds, after which token expires'
|
||||
required: false
|
||||
|
|
|
|||
1410
dist/index.js
vendored
1410
dist/index.js
vendored
File diff suppressed because it is too large
Load diff
49466
package-lock.json
generated
49466
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -52,7 +52,7 @@
|
|||
"@actions/core": ">=1 <2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@actions/core": "^1.2.3",
|
||||
"@actions/core": "^1.6.0",
|
||||
"@types/got": "^9.6.11",
|
||||
"@types/jest": "^26.0.13",
|
||||
"@zeit/ncc": "^0.22.3",
|
||||
|
|
|
|||
45
src/auth.js
45
src/auth.js
|
|
@ -2,7 +2,6 @@
|
|||
const core = require('@actions/core');
|
||||
const rsasign = require('jsrsasign');
|
||||
const fs = require('fs');
|
||||
const got = require('got').default;
|
||||
|
||||
const defaultKubernetesTokenPath = '/var/run/secrets/kubernetes.io/serviceaccount/token'
|
||||
/***
|
||||
|
|
@ -26,17 +25,15 @@ async function retrieveToken(method, client) {
|
|||
case 'jwt': {
|
||||
/** @type {string} */
|
||||
let jwt;
|
||||
const actionsIDTokenRequestToken = process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN'];
|
||||
const actionsIDTokenRequestURL = process.env['ACTIONS_ID_TOKEN_REQUEST_URL'];
|
||||
|
||||
const role = core.getInput('role', { required: true });
|
||||
const privateKeyRaw = core.getInput('jwtPrivateKey', { required: (!(actionsIDTokenRequestToken && actionsIDTokenRequestURL)) });
|
||||
const privateKeyRaw = core.getInput('jwtPrivateKey', { required: false });
|
||||
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 githubAudience = core.getInput('jwtGithubAudience', { required: false });
|
||||
|
||||
if (!privateKeyRaw && actionsIDTokenRequestToken && actionsIDTokenRequestURL) {
|
||||
jwt = await getJwt(actionsIDTokenRequestToken, `${actionsIDTokenRequestURL}&audience=sigstore`);
|
||||
if (!privateKey) {
|
||||
jwt = await core.getIDToken(githubAudience || 'sigstore')
|
||||
} else {
|
||||
jwt = generateJwt(privateKey, keyPassword, Number(tokenTtl));
|
||||
}
|
||||
|
|
@ -94,34 +91,6 @@ function generateJwt(privateKey, keyPassword, ttl) {
|
|||
return rsasign.KJUR.jws.JWS.sign(alg, JSON.stringify(header), JSON.stringify(payload), decryptedKey);
|
||||
}
|
||||
|
||||
/***
|
||||
* Call the appropriate endpoint and retrieves job's JWT
|
||||
* @param {string} actionsIDTokenRequestToken
|
||||
* @param {string} actionsIDTokenRequestURL
|
||||
*/
|
||||
async function getJwt(actionsIDTokenRequestToken, actionsIDTokenRequestURL) {
|
||||
/** @type {'json'} */
|
||||
const responseType = 'json';
|
||||
const options = {
|
||||
headers: {
|
||||
Authorization: `Bearer ${actionsIDTokenRequestToken}`,
|
||||
},
|
||||
responseType,
|
||||
};
|
||||
const client = got.extend(options)
|
||||
|
||||
core.debug(`Retrieving Vault JWT from ${actionsIDTokenRequestURL} endpoint`);
|
||||
/** @type {import('got').Response<GithubActionsIdTokenResponse>} */
|
||||
const response = await client.get(actionsIDTokenRequestURL, options);
|
||||
|
||||
if (response && response.body && response.body.value) {
|
||||
core.debug('✔ Github Actions ID Token successfully retrieved');
|
||||
return response.body.value;
|
||||
} else {
|
||||
throw Error(`Unable to retrieve token from ${actionsIDTokenRequestURL}'s endpoint.`);
|
||||
}
|
||||
}
|
||||
|
||||
/***
|
||||
* Call the appropriate login endpoint and parse out the token in the response.
|
||||
* @param {import('got').Got} client
|
||||
|
|
@ -167,12 +136,6 @@ async function getClientToken(client, method, path, payload) {
|
|||
* }} auth
|
||||
*/
|
||||
|
||||
/***
|
||||
* @typedef {Object} GithubActionsIdTokenResponse
|
||||
* @property {string} value
|
||||
* @property {string} count
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
retrieveToken,
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue