diff --git a/README.md b/README.md index 90251e5d8..88e296257 100644 --- a/README.md +++ b/README.md @@ -183,7 +183,7 @@ The session will have the name "GitHubActions" and be tagged with the following | Branch | GITHUB_REF | | Commit | GITHUB_SHA | -_Note: all tag values must conform to [the requirements](https://docs.aws.amazon.com/STS/latest/APIReference/API_Tag.html). Particularly, `GITHUB_WORKFLOW` will be truncated if it's too long. If `GITHUB_ACTOR` or `GITHUB_WORKFLOW` contain invalid characters, the characters will be replaced with an '*'._ +_Note: all tag values must conform to [the requirements](https://docs.aws.amazon.com/STS/latest/APIReference/API_Tag.html). Particularly, `GITHUB_WORKFLOW` & `GITHUB_BRANCH` will be truncated if they are too long. If `GITHUB_ACTOR`, `GITHUB_BRANCH`, or `GITHUB_WORKFLOW` contain invalid characters, those characters will be replaced with '_'._ The action will use session tagging by default during role assumption. Note that for WebIdentity role assumption, the session tags have to be included in the encoded WebIdentity token. diff --git a/index.js b/index.js index 229993bb4..603078e2e 100644 --- a/index.js +++ b/index.js @@ -52,17 +52,18 @@ async function assumeRole(params) { roleArn = `arn:aws:iam::${sourceAccountId}:role/${roleArn}`; } + // Workflow names can be almost any valid UTF-8 string, but tags are more restrictive. const tagArray = [ {Key: 'GitHub', Value: 'Actions'}, {Key: 'Repository', Value: GITHUB_REPOSITORY}, - {Key: 'Workflow', Value: sanitizeGithubWorkflowName(GITHUB_WORKFLOW)}, + {Key: 'Workflow', Value: sanitizeForTagValue(GITHUB_WORKFLOW)}, {Key: 'Action', Value: GITHUB_ACTION}, {Key: 'Actor', Value: sanitizeGithubActor(GITHUB_ACTOR)}, {Key: 'Commit', Value: GITHUB_SHA}, ]; if (isDefined(process.env.GITHUB_REF)) { - tagArray.push({Key: 'Branch', Value: process.env.GITHUB_REF}); + tagArray.push({Key: 'Branch', Value: sanitizeForTagValue(process.env.GITHUB_REF)}); } const roleSessionTags = roleSkipSessionTagging ? undefined : tagArray; @@ -130,8 +131,7 @@ function sanitizeGithubActor(actor) { return actor.replace(/\[|\]/g, SANITIZATION_CHARACTER) } -function sanitizeGithubWorkflowName(name) { - // Workflow names can be almost any valid UTF-8 string, but tags are more restrictive. +function sanitizeForTagValue(name) { // This replaces anything not conforming to the tag restrictions by inverting the regular expression. // See the AWS documentation for constraint specifics https://docs.aws.amazon.com/STS/latest/APIReference/API_Tag.html. const nameWithoutSpecialCharacters = name.replace(/[^\p{L}\p{Z}\p{N}_:/=+.-@-]/gu, SANITIZATION_CHARACTER); diff --git a/index.test.js b/index.test.js index 860346d27..b2ce4ed08 100644 --- a/index.test.js +++ b/index.test.js @@ -661,6 +661,33 @@ describe('Configure AWS Credentials', () => { }) }); + test('ref name sanitized in role assumption tags', async () => { + core.getInput = jest + .fn() + .mockImplementation(mockGetInput(ASSUME_ROLE_INPUTS)); + + process.env = {...process.env, GITHUB_REF: 'refs/heads/!"#$%&\'()*+, -./:;<=>?@[]^_`{|}~🙂💥🍌1yFvMOeD3ZHYsHrGjCceOboMYzBPo0CRNFdcsVRG6UgR3A912a8KfcBtEVvkAS7kRBq80umGff8mux5IN1y55HQWPNBNyaruuVr4islFXte4FDQZexGJRUSMyHQpxJ8OmZnET84oDmbvmIjgxI6IBrdihX9PHMapT4gQvRYnLqNiKb18rEMWDNoZRy51UPX5sWK2GKPipgKSO9kqLckZai9D2AN2RlWCxtMqChNtxuxjqeqhoQZo0oaq39sjcRZgAAAAAAA'}; + + const sanitizedRefName = 'refs/heads/__________+_ -./:;<=>?@____________1yFvMOeD3ZHYsHrGjCceOboMYzBPo0CRNFdcsVRG6UgR3A912a8KfcBtEVvkAS7kRBq80umGff8mux5IN1y55HQWPNBNyaruuVr4islFXte4FDQZexGJRUSMyHQpxJ8OmZnET84oDmbvmIjgxI6IBrdihX9PHMapT4gQvRYnLqNiKb18rEMWDNoZRy51UPX5sWK2GKPipgKSO9kqLc'; + + await run(); + expect(mockStsAssumeRole).toHaveBeenCalledWith({ + RoleArn: ROLE_ARN, + RoleSessionName: 'GitHubActions', + DurationSeconds: 6 * 3600, + Tags: [ + {Key: 'GitHub', Value: 'Actions'}, + {Key: 'Repository', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_REPOSITORY}, + {Key: 'Workflow', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_WORKFLOW}, + {Key: 'Action', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_ACTION}, + {Key: 'Actor', Value: GITHUB_ACTOR_SANITIZED}, + {Key: 'Commit', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_SHA}, + {Key: 'Branch', Value: sanitizedRefName}, + ] + }) + }); + + test('skip tagging provided as true', async () => { core.getInput = jest .fn()