diff --git a/README.md b/README.md index 8dce6af1..f500e925 100644 --- a/README.md +++ b/README.md @@ -232,7 +232,7 @@ with: You can configure trust between your own OIDC Provider and Vault with the JWT auth method. Provide a `role` & `jwtPrivateKey` parameters, -additionally you can pass `jwtKeyPassword` & `jwtTtl` parameters +additionally you can pass `jwtKeyPassword`, `jwtTtl`, & `jwtIat` parameters. ```yaml with: @@ -243,6 +243,7 @@ with: jwtPrivateKey: ${{ secrets.JWT_PRIVATE_KEY }} jwtKeyPassword: ${{ secrets.JWT_KEY_PASS }} jwtTtl: 3600 # 1 hour, default value + jwtIat: 60 # 1 min, default value. Negative int postdates ``` ### Kubernetes diff --git a/action.yml b/action.yml index e3d28550..8156bf20 100644 --- a/action.yml +++ b/action.yml @@ -86,6 +86,10 @@ inputs: description: 'Time in seconds, after which token expires' required: false default: 3600 + jwtIat: + description: 'Number of seconds (int) to predate the token issued at (iat).' + required: false + default: 60 secretEncodingType: 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 diff --git a/integrationTests/basic/jwt_auth.test.js b/integrationTests/basic/jwt_auth.test.js index df2703b5..3c24e5aa 100644 --- a/integrationTests/basic/jwt_auth.test.js +++ b/integrationTests/basic/jwt_auth.test.js @@ -44,7 +44,7 @@ function mockGithubOIDCResponse(aud= "https://github.com/hashicorp/vault-action" ref_type: "branch", job_workflow_ref: "hashicorp/vault-action/.github/workflows/workflow.yml@refs/heads/main", iss: 'vault-action', - iat: now, + iat: now - 60, nbf: now, exp: now + 3600, }; diff --git a/src/auth.js b/src/auth.js index 331083ab..6120c7ff 100644 --- a/src/auth.js +++ b/src/auth.js @@ -32,12 +32,13 @@ async function retrieveToken(method, client) { 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 tokenIat = core.getInput('jwtIat', { required: false }) || '60'; const githubAudience = core.getInput('jwtGithubAudience', { required: false }); if (!privateKey) { jwt = await core.getIDToken(githubAudience) } else { - jwt = generateJwt(privateKey, keyPassword, Number(tokenTtl)); + jwt = generateJwt(privateKey, keyPassword, Number(tokenTtl), Number(tokenIat)); } return await getClientToken(client, method, path, { jwt: jwt, role: role }); @@ -79,14 +80,15 @@ async function retrieveToken(method, client) { * @param {string} privateKey * @param {string} keyPassword * @param {number} ttl + * @param {number} iat */ -function generateJwt(privateKey, keyPassword, ttl) { +function generateJwt(privateKey, keyPassword, ttl, iat) { const alg = 'RS256'; const header = { alg: alg, typ: 'JWT' }; const now = rsasign.KJUR.jws.IntDate.getNow(); const payload = { iss: 'vault-action', - iat: now, + iat: now - iat, nbf: now, exp: now + ttl, event: process.env.GITHUB_EVENT_NAME,