From 2c6158aeefc0a85fbd263eeb978e03cbe42fc266 Mon Sep 17 00:00:00 2001 From: Keith Murry <37637117+spdracers@users.noreply.github.com> Date: Mon, 12 Feb 2024 13:10:18 -0600 Subject: [PATCH 1/2] Introduce jwt Issued At If time drift occurs between the identity provider and the Hashi Vault, authentication will fail. This is resolved by introducing a param to specify the number of seconds in the past for the jwt issued date --- README.md | 3 ++- action.yml | 4 ++++ src/auth.js | 8 +++++--- 3 files changed, 11 insertions(+), 4 deletions(-) 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/src/auth.js b/src/auth.js index 331083ab..47dbfcc5 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,15 +80,16 @@ 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, - nbf: now, + nbf: now - iat, exp: now + ttl, event: process.env.GITHUB_EVENT_NAME, workflow: process.env.GITHUB_WORKFLOW, From da8ea015b733cf65b1f28c2355b7441dca7976e9 Mon Sep 17 00:00:00 2001 From: Keith Murry <37637117+spdracers@users.noreply.github.com> Date: Mon, 19 Feb 2024 14:32:49 -0600 Subject: [PATCH 2/2] Corrected IAT and added explicit value for the mock test --- integrationTests/basic/jwt_auth.test.js | 2 +- src/auth.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) 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 47dbfcc5..6120c7ff 100644 --- a/src/auth.js +++ b/src/auth.js @@ -88,8 +88,8 @@ function generateJwt(privateKey, keyPassword, ttl, iat) { const now = rsasign.KJUR.jws.IntDate.getNow(); const payload = { iss: 'vault-action', - iat: now, - nbf: now - iat, + iat: now - iat, + nbf: now, exp: now + ttl, event: process.env.GITHUB_EVENT_NAME, workflow: process.env.GITHUB_WORKFLOW,