diff --git a/README.md b/README.md index 9cac264cf..8fdd93154 100644 --- a/README.md +++ b/README.md @@ -157,6 +157,14 @@ The session will have the name "GitHubActions" and be tagged with the following _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 charcters, the characters will be replaced with an '*'._ +The action will use session tagging by default during role assumption. You can skip this session tagging by providing `role-skip-session-tagging` as true in the action's inputs: + +```yaml + uses: aws-actions/configure-aws-credentials@v1 + with: + role-skip-session-tagging: true +``` + ## Self-Hosted Runners If you run your GitHub Actions in a [self-hosted runner](https://help.github.com/en/actions/hosting-your-own-runners/about-self-hosted-runners) that already has access to AWS credentials, such as an EC2 instance, then you do not need to provide IAM user access key credentials to this action. diff --git a/action.yml b/action.yml index 2e3b8f277..5c3ce8328 100644 --- a/action.yml +++ b/action.yml @@ -43,6 +43,9 @@ inputs: role-external-id: description: 'The external ID of the role to assume' required: false + role-skip-session-tagging: + description: 'Skip session tagging during role assumption' + required: false outputs: aws-account-id: description: 'The AWS account ID for the provided credentials' diff --git a/index.js b/index.js index 068db307b..10b60cfcb 100644 --- a/index.js +++ b/index.js @@ -22,6 +22,7 @@ async function assumeRole(params) { roleDurationSeconds, roleSessionName, region, + roleSkipSessionTagging } = params; assert( [sourceAccountId, roleToAssume, roleDurationSeconds, roleSessionName, region].every(isDefined), @@ -41,20 +42,23 @@ async function assumeRole(params) { // Supports only 'aws' partition. Customers in other partitions ('aws-cn') will need to provide full ARN roleArn = `arn:aws:iam::${sourceAccountId}:role/${roleArn}`; } + const tagArray = [ + {Key: 'GitHub', Value: 'Actions'}, + {Key: 'Repository', Value: GITHUB_REPOSITORY}, + {Key: 'Workflow', Value: sanitizeGithubWorkflowName(GITHUB_WORKFLOW)}, + {Key: 'Action', Value: GITHUB_ACTION}, + {Key: 'Actor', Value: sanitizeGithubActor(GITHUB_ACTOR)}, + {Key: 'Branch', Value: GITHUB_REF}, + {Key: 'Commit', Value: GITHUB_SHA}, + ]; + + const roleSessionTags = roleSkipSessionTagging ? undefined : tagArray; const assumeRoleRequest = { RoleArn: roleArn, RoleSessionName: roleSessionName, DurationSeconds: roleDurationSeconds, - Tags: [ - {Key: 'GitHub', Value: 'Actions'}, - {Key: 'Repository', Value: GITHUB_REPOSITORY}, - {Key: 'Workflow', Value: sanitizeGithubWorkflowName(GITHUB_WORKFLOW)}, - {Key: 'Action', Value: GITHUB_ACTION}, - {Key: 'Actor', Value: sanitizeGithubActor(GITHUB_ACTOR)}, - {Key: 'Branch', Value: GITHUB_REF}, - {Key: 'Commit', Value: GITHUB_SHA}, - ] + Tags: roleSessionTags }; if (roleExternalId) { @@ -196,7 +200,8 @@ async function run() { const roleExternalId = core.getInput('role-external-id', { required: false }); const roleDurationSeconds = core.getInput('role-duration-seconds', {required: false}) || MAX_ACTION_RUNTIME; const roleSessionName = core.getInput('role-session-name', { required: false }) || ROLE_SESSION_NAME; - + const roleSkipSessionTagging = core.getInput('role-skip-session-tagging', { required: false }); + if (!region.match(REGION_REGEX)) { throw new Error(`Region is not valid: ${region}`); } @@ -233,7 +238,8 @@ async function run() { roleToAssume, roleExternalId, roleDurationSeconds, - roleSessionName + roleSessionName, + roleSkipSessionTagging }); exportCredentials(roleCredentials); await validateCredentials(roleCredentials.accessKeyId); diff --git a/index.test.js b/index.test.js index 22a254f8c..19fbc6020 100644 --- a/index.test.js +++ b/index.test.js @@ -276,6 +276,19 @@ describe('Configure AWS Credentials', () => { expect(core.setFailed).toHaveBeenCalledWith('Region is not valid: $AWS_REGION'); }); + test('throws error if access key id exists but missing secret access key', async () => { + process.env.SHOW_STACK_TRACE = 'false'; + const inputsWIthoutSecretKey = {...ASSUME_ROLE_INPUTS} + inputsWIthoutSecretKey["aws-secret-access-key"] = undefined + core.getInput = jest + .fn() + .mockImplementation(mockGetInput(inputsWIthoutSecretKey)); + + await run(); + expect(core.setFailed).toHaveBeenCalledWith("'aws-secret-access-key' must be provided if 'aws-access-key-id' is provided"); + + }); + test('can opt out of masking account ID', async () => { const mockInputs = {...CREDS_INPUTS, 'aws-region': 'us-east-1', 'mask-aws-account-id': 'false'}; core.getInput = jest @@ -523,4 +536,62 @@ describe('Configure AWS Credentials', () => { }) }); + test('skip tagging provided as true', async () => { + core.getInput = jest + .fn() + .mockImplementation(mockGetInput({...ASSUME_ROLE_INPUTS, 'role-skip-session-tagging': true})); + + await run(); + expect(mockStsAssumeRole).toHaveBeenCalledWith({ + RoleArn: ROLE_ARN, + RoleSessionName: 'GitHubActions', + DurationSeconds: 21600, + Tags: undefined + }) + }); + + test('skip tagging provided as false', async () => { + core.getInput = jest + .fn() + .mockImplementation(mockGetInput({...ASSUME_ROLE_INPUTS, 'role-skip-session-tagging': false})); + + await run(); + expect(mockStsAssumeRole).toHaveBeenCalledWith({ + RoleArn: ROLE_ARN, + RoleSessionName: 'GitHubActions', + DurationSeconds: 21600, + 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: 'Branch', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_REF}, + {Key: 'Commit', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_SHA}, + ] + }) + }); + + test('skip tagging not provided', async () => { + core.getInput = jest + .fn() + .mockImplementation(mockGetInput({...ASSUME_ROLE_INPUTS})); + + await run(); + expect(mockStsAssumeRole).toHaveBeenCalledWith({ + RoleArn: ROLE_ARN, + RoleSessionName: 'GitHubActions', + DurationSeconds: 21600, + 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: 'Branch', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_REF}, + {Key: 'Commit', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_SHA}, + ] + }) + }); + });