Compare commits

...

46 Commits

Author SHA1 Message Date
Release Automation e8a907912d chore(release): 1.1.1 2020-02-07 17:33:45 +00:00
GitHub Actions 3a0d6924fb chore: Update dist 2020-02-06 21:05:04 +00:00
dependabot-preview[bot] d317dedbb3 chore: Bump aws-sdk from 2.610.0 to 2.613.0
Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.610.0 to 2.613.0.
- [Release notes](https://github.com/aws/aws-sdk-js/releases)
- [Changelog](https://github.com/aws/aws-sdk-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-js/compare/v2.610.0...v2.613.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-06 13:04:18 -08:00
Release Automation d15e9e3279 chore(release): 1.1.0 2020-02-06 01:44:18 +00:00
Clare Liguori 260c6cc0ed fix: remove buildspecs 2020-02-04 15:39:05 -08:00
Clare Liguori 1436a160af fix: remove release script 2020-02-04 12:17:38 -08:00
GitHub Actions a4a9d2530c chore: Update dist 2020-02-04 02:15:07 +00:00
dependabot-preview[bot] 1e5e67d2bc chore: Bump @actions/core from 1.2.0 to 1.2.2
Bumps [@actions/core](https://github.com/actions/toolkit/tree/HEAD/packages/core) from 1.2.0 to 1.2.2.
- [Release notes](https://github.com/actions/toolkit/releases)
- [Changelog](https://github.com/actions/toolkit/blob/master/packages/core/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/core)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-03 18:14:31 -08:00
GitHub Actions 5eb8c27349 chore: Update dist 2020-02-04 02:12:53 +00:00
dependabot-preview[bot] 3ea5fc971d chore: Bump aws-sdk from 2.598.0 to 2.610.0
Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.598.0 to 2.610.0.
- [Release notes](https://github.com/aws/aws-sdk-js/releases)
- [Changelog](https://github.com/aws/aws-sdk-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-js/compare/v2.598.0...v2.610.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-03 18:12:03 -08:00
dependabot-preview[bot] 52de4c7182 chore: Bump jest from 24.9.0 to 25.1.0
Bumps [jest](https://github.com/facebook/jest) from 24.9.0 to 25.1.0.
- [Release notes](https://github.com/facebook/jest/releases)
- [Changelog](https://github.com/facebook/jest/blob/master/CHANGELOG.md)
- [Commits](https://github.com/facebook/jest/compare/v24.9.0...v25.1.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-03 18:10:10 -08:00
Clare Liguori adc64e45b8 chore: Match package version to latest tagged version 2020-02-03 18:00:28 -08:00
GitHub Actions a8ef869f65 chore: Update dist 2020-02-03 18:20:52 +00:00
Laurence Armstrong ca04437296 Fix calling setSecret 2020-02-03 13:20:13 -05:00
Clare Liguori 77f2df7a41 fix: resolve commit ID in integ test script 2020-02-02 12:20:20 -05:00
Clare Liguori 3de962edc9 fix: create workflows dir in integ-tests 2020-01-31 16:51:26 -05:00
GitHub Actions 344f5cbe7e chore: Update dist 2020-01-31 02:34:18 +00:00
Laurence Armstrong 4faf8cd19a fix: sanitize AWS session tags (#20)
* Sanitize github actor tag

* Add some tests

* Sanitize Github actions workflow name

* Change sanitization character to an asterisk

* Update readme about assuming a role

* Tidy up assume role readme entry more

* Align sanitize spelling to use -ize

* typo: environement -> environment
2020-01-30 21:33:36 -05:00
Clare Liguori c69f29a23c Remove sudo from codebuild steps 2020-01-30 16:30:31 -05:00
Clare Liguori 52bc82a29b feat: Build and integ test scripts for pipeline 2020-01-30 16:16:17 -05:00
GitHub Actions 8cff48fde9 chore: Update dist 2020-01-28 14:50:47 +00:00
Laurence Armstrong e2fd53ab66 fix: set role credentials as secrets to mask them in logs (#19)
* Set role credentials as secrets to mask them in logs

* Always set aws credentuals as secrets

* Fix typo in comment
2020-01-28 09:50:15 -05:00
GitHub Actions 7b221d2e08 chore: Update dist 2020-01-22 19:04:40 +00:00
Matt Bullock 25960ab095 feat: add support for assuming a role (#17)
* first draft attempt at adding role assumption option

* refinements

* const not var

* clean up asserts

* set explicit sts endpoint and clarify required inputs error message

* streamline mocks

* add new inputs to Action definition

* ignore .idea directory

* add initial assume role test

* make tests fail usefully when not in GitHub Actions

* add logic to handle suppression of stack trace

* pull credentials exports out into function

* convert environment variable patching to use object for source and add needed members

* add test for STS call

* compartmentalization and use custom user agent in role assumption STS client

* change DO_NOT_SUPRESS_STACK_TRACE to SHOW_STACK_TRACE

* update role-to-assume input description
2020-01-22 11:04:03 -08:00
GitHub Actions e3c83cfe60 chore: Update dist 2020-01-06 20:38:44 +00:00
dependabot-preview[bot] cf2cbf51d2 chore: Bump aws-sdk from 2.597.0 to 2.598.0
Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.597.0 to 2.598.0.
- [Release notes](https://github.com/aws/aws-sdk-js/releases)
- [Changelog](https://github.com/aws/aws-sdk-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-js/compare/v2.597.0...v2.598.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-06 12:37:55 -08:00
GitHub Actions 6f58251f8d chore: Update dist 2020-01-06 20:28:06 +00:00
dependabot-preview[bot] d3c4189f16 chore: Bump aws-sdk from 2.596.0 to 2.597.0
Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.596.0 to 2.597.0.
- [Release notes](https://github.com/aws/aws-sdk-js/releases)
- [Changelog](https://github.com/aws/aws-sdk-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-js/compare/v2.596.0...v2.597.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-06 12:27:37 -08:00
dependabot-preview[bot] 4f6148fd2d chore: Bump @zeit/ncc from 0.20.5 to 0.21.0
Bumps [@zeit/ncc](https://github.com/zeit/ncc) from 0.20.5 to 0.21.0.
- [Release notes](https://github.com/zeit/ncc/releases)
- [Commits](https://github.com/zeit/ncc/compare/0.20.5...0.21.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-06 12:27:23 -08:00
GitHub Actions 5f791d0fc5 chore: Update dist 2020-01-01 23:27:33 +00:00
dependabot-preview[bot] 3e55b391c1 chore: Bump aws-sdk from 2.586.0 to 2.596.0
Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.586.0 to 2.596.0.
- [Release notes](https://github.com/aws/aws-sdk-js/releases)
- [Changelog](https://github.com/aws/aws-sdk-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-js/compare/v2.586.0...v2.596.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-01 15:26:52 -08:00
dependabot-preview[bot] 23d406d277 chore: Bump eslint from 6.7.2 to 6.8.0
Bumps [eslint](https://github.com/eslint/eslint) from 6.7.2 to 6.8.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/master/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v6.7.2...v6.8.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-01 15:26:27 -08:00
Clare Liguori 8588cbdcd3 chore: Automated packaging commit uses a conventional commit message 2020-01-01 15:17:20 -08:00
Clare Liguori be8d1ecb70 chore: upgrade to actions/checkout v2 2020-01-01 15:08:04 -08:00
Michael Hausenblas c2cc6055b3 fixes link to GitHub Actions secrets 2019-12-27 16:53:09 -08:00
GitHub Actions 9aba253d91 Update dist 2019-12-09 23:34:03 +00:00
dependabot-preview[bot] 83b93836ae chore: Bump aws-sdk from 2.578.0 to 2.586.0
Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.578.0 to 2.586.0.
- [Release notes](https://github.com/aws/aws-sdk-js/releases)
- [Changelog](https://github.com/aws/aws-sdk-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-js/compare/v2.578.0...v2.586.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-09 15:33:28 -08:00
dependabot-preview[bot] 1169129f3d chore: Bump eslint from 6.7.1 to 6.7.2 (#4)
Bumps [eslint](https://github.com/eslint/eslint) from 6.7.1 to 6.7.2.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/master/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v6.7.1...v6.7.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-09 15:03:08 -08:00
Clare Liguori 11ae4e96f3 Add link action.yml for full input/output documentation 2019-11-29 09:44:16 -08:00
GitHub Actions 18a79864eb Update dist 2019-11-25 14:48:30 +00:00
dependabot-preview[bot] 6f45a2f25a Bump aws-sdk from 2.573.0 to 2.578.0
Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.573.0 to 2.578.0.
- [Release notes](https://github.com/aws/aws-sdk-js/releases)
- [Changelog](https://github.com/aws/aws-sdk-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-js/compare/v2.573.0...v2.578.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-11-25 06:47:51 -08:00
dependabot-preview[bot] d352c53832 Bump eslint from 6.6.0 to 6.7.1
Bumps [eslint](https://github.com/eslint/eslint) from 6.6.0 to 6.7.1.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/master/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v6.6.0...v6.7.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-11-25 06:42:20 -08:00
GitHub Actions d18f724ec8 Update dist 2019-11-18 17:48:26 +00:00
Clare Liguori b6dbec51a5 Packaging workflow, so that dist/ doesn't get out of date 2019-11-18 09:43:17 -08:00
dependabot-preview[bot] e673e43e70 Bump aws-sdk from 2.567.0 to 2.573.0
Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.567.0 to 2.573.0.
- [Release notes](https://github.com/aws/aws-sdk-js/releases)
- [Changelog](https://github.com/aws/aws-sdk-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-js/compare/v2.567.0...v2.573.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-11-17 19:19:07 -08:00
Clare Liguori 5cd5be4c98 Add pull request check 2019-11-17 19:08:41 -08:00
11 changed files with 6255 additions and 8495 deletions
+16
View File
@@ -0,0 +1,16 @@
on:
[pull_request]
name: Check
jobs:
check:
name: Run Unit Tests
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Run tests
run: |
npm ci
npm test
+27
View File
@@ -0,0 +1,27 @@
on:
push:
branches:
- master
name: Package
jobs:
check:
name: Package distribution file
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
with:
ref: master
- name: Package
run: |
npm ci
npm test
npm run package
- name: Commit
run: |
git config --global user.name "GitHub Actions"
git add dist/
git commit -m "chore: Update dist" || echo "No changes to commit"
git push origin HEAD:master
+1
View File
@@ -2,6 +2,7 @@ node_modules/
# Editors
.vscode
.idea
# Logs
logs
+23
View File
@@ -0,0 +1,23 @@
# Changelog
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
### [1.1.1](https://github.com/aws-actions/configure-aws-credentials/compare/v1.1.0...v1.1.1) (2020-02-07)
## [1.1.0](https://github.com/aws-actions/configure-aws-credentials/compare/v1.0.1...v1.1.0) (2020-02-06)
### Features
* add support for assuming a role ([#17](https://github.com/aws-actions/configure-aws-credentials/issues/17)) ([25960ab](https://github.com/aws-actions/configure-aws-credentials/commit/25960ab0950f92074b17fa0cb8ff33eeaa1615f0))
* Build and integ test scripts for pipeline ([52bc82a](https://github.com/aws-actions/configure-aws-credentials/commit/52bc82a29bb08f2f8f87a92f380149945eb8d6f1))
### Bug Fixes
* create workflows dir in integ-tests ([3de962e](https://github.com/aws-actions/configure-aws-credentials/commit/3de962edc9fe1169ff6032bef94b934be53211d1))
* remove buildspecs ([260c6cc](https://github.com/aws-actions/configure-aws-credentials/commit/260c6cc0ed07cbd8ff2a7a74066ad9f67ecc82f7))
* remove release script ([1436a16](https://github.com/aws-actions/configure-aws-credentials/commit/1436a160af84c3a086a812f98daf457a042274cb))
* resolve commit ID in integ test script ([77f2df7](https://github.com/aws-actions/configure-aws-credentials/commit/77f2df7a41882637145683bb1acf60bb04fddc24))
* sanitize AWS session tags ([#20](https://github.com/aws-actions/configure-aws-credentials/issues/20)) ([4faf8cd](https://github.com/aws-actions/configure-aws-credentials/commit/4faf8cd19a5b6cc50c9c66c89dd32d7e6e51bd8a))
* set role credentials as secrets to mask them in logs ([#19](https://github.com/aws-actions/configure-aws-credentials/issues/19)) ([e2fd53a](https://github.com/aws-actions/configure-aws-credentials/commit/e2fd53ab66a094843f790497dcc950894c245786))
+36 -1
View File
@@ -15,15 +15,50 @@ Add the following step to your workflow:
aws-region: us-east-2
```
See [action.yml](action.yml) for the full documentation for this action's inputs and outputs.
## Credentials
We recommend following [Amazon IAM best practices](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html) for the AWS credentials used in GitHub Actions workflows, including:
* Do not store credentials in your repository's code. You may use [GitHub Actions secrets](https://help.github.com/en/github/automating-your-workflow-with-github-actions/virtual-environments-for-github-actions#creating-and-using-secrets-encrypted-variables) to store credentials and redact credentials from GitHub Actions workflow logs.
* Do not store credentials in your repository's code. You may use [GitHub Actions secrets](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets) to store credentials and redact credentials from GitHub Actions workflow logs.
* [Create an individual IAM user](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#create-iam-users) with an access key for use in GitHub Actions workflows, preferably one per repository. Do not use the AWS account root user access key.
* [Grant least privilege](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege) to the credentials used in GitHub Actions workflows. Grant only the permissions required to perform the actions in your GitHub Actions workflows.
* [Rotate the credentials](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#rotate-credentials) used in GitHub Actions workflows regularly.
* [Monitor the activity](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#keep-a-log) of the credentials used in GitHub Actions workflows.
## Assuming a role
If you would like to use the credentials you provide to this action to assume a role, you can do so by specifying the role ARN in `role-to-assume`.
The role credentials will then be output instead of the ones you have provided.
The default session duration is 6 hours, but if you would like to adjust this you can pass a duration to `role-duration-seconds`.
Example:
```yaml
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-2
role-to-assume: arn:aws:iam::123456789100:role/role-to-assume
role-duration-seconds: 1200
```
### Session tagging
The session will have the name "GitHubActions" and be tagged with the following tags:
(`GITHUB_` environment variable definitions can be [found here](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/using-environment-variables#default-environment-variables))
| Key | Value|
| --- | --- |
| GitHub | "Actions" |
| Repository | GITHUB_REPOSITORY |
| Workflow | GITHUB_WORKFLOW |
| Action | GITHUB_ACTION |
| Actor | GITHUB_ACTOR |
| 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 charcters, the characters will be replaced with an '*'._
## License Summary
This code is made available under the MIT license.
+6
View File
@@ -19,6 +19,12 @@ inputs:
mask-aws-account-id:
description: "Whether to set the AWS account ID for these credentials as a secret value, so that it is masked in logs. Valid values are 'true' and 'false'. Defaults to true"
required: false
role-to-assume:
description: "Use the provided credentials to assume a Role and output the assumed credentials for that Role rather than the provided credentials"
required: false
role-duration-seconds:
description: "Role duration in seconds (default: 6 hours)"
required: false
outputs:
aws-account-id:
description: 'The AWS account ID for the provided credentials'
+3016 -6611
View File
File diff suppressed because one or more lines are too long
+129 -28
View File
@@ -1,5 +1,115 @@
const core = require('@actions/core');
const aws = require('aws-sdk');
const assert = require('assert');
const util = require('util');
// The max time that a GitHub action is allowed to run is 6 hours.
// That seems like a reasonable default to use if no role duration is defined.
const MAX_ACTION_RUNTIME = 6 * 3600;
const USER_AGENT = 'configure-aws-credentials-for-github-actions';
const MAX_TAG_VALUE_LENGTH = 256;
const SANITIZATION_CHARACTER = '*'
async function assumeRole(params) {
// Assume a role to get short-lived credentials using longer-lived credentials.
const isDefined = i => !!i;
const {roleToAssume, roleDurationSeconds, accessKeyId, secretAccessKey, sessionToken, region} = params;
assert(
[roleToAssume, roleDurationSeconds, accessKeyId, secretAccessKey, region].every(isDefined),
"Missing required input when assuming a Role."
);
const {GITHUB_REPOSITORY, GITHUB_WORKFLOW, GITHUB_ACTION, GITHUB_ACTOR, GITHUB_REF, GITHUB_SHA} = process.env;
assert(
[GITHUB_REPOSITORY, GITHUB_WORKFLOW, GITHUB_ACTION, GITHUB_ACTOR, GITHUB_REF, GITHUB_SHA].every(isDefined),
'Missing required environment value. Are you running in GitHub Actions?'
);
const endpoint = util.format('https://sts.%s.amazonaws.com', region);
const sts = new aws.STS({
accessKeyId, secretAccessKey, sessionToken, region, endpoint, customUserAgent: USER_AGENT
});
return sts.assumeRole({
RoleArn: roleToAssume,
RoleSessionName: 'GitHubActions',
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},
]
})
.promise()
.then(function (data) {
return {
accessKeyId: data.Credentials.AccessKeyId,
secretAccessKey: data.Credentials.SecretAccessKey,
sessionToken: data.Credentials.SessionToken,
};
});
}
function sanitizeGithubActor(actor) {
// In some circumstances the actor may contain square brackets. For example, if they're a bot ('[bot]')
// Square brackets are not allowed in AWS session tags
return actor.replace(/\[|\]/g, SANITIZATION_CHARACTER)
}
function sanitizeGithubWorkflowName(name) {
// Workflow names can be almost any valid UTF-8 string, but tags are more restrictive.
// 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);
const nameTruncated = nameWithoutSpecialCharacters.slice(0, MAX_TAG_VALUE_LENGTH)
return nameTruncated
}
function exportCredentials(params){
// Configure the AWS CLI and AWS SDKs using environment variables and set them as secrets.
// Setting the credentials as secrets masks them in Github Actions logs
const {accessKeyId, secretAccessKey, sessionToken} = params;
// AWS_ACCESS_KEY_ID:
// Specifies an AWS access key associated with an IAM user or role
core.exportVariable('AWS_ACCESS_KEY_ID', accessKeyId);
core.setSecret(accessKeyId);
// AWS_SECRET_ACCESS_KEY:
// Specifies the secret key associated with the access key. This is essentially the "password" for the access key.
core.exportVariable('AWS_SECRET_ACCESS_KEY', secretAccessKey);
core.setSecret(secretAccessKey);
// AWS_SESSION_TOKEN:
// Specifies the session token value that is required if you are using temporary security credentials.
if (sessionToken) {
core.exportVariable('AWS_SESSION_TOKEN', sessionToken);
core.setSecret(sessionToken);
}
}
function exportRegion(region) {
// AWS_DEFAULT_REGION and AWS_REGION:
// Specifies the AWS Region to send requests to
core.exportVariable('AWS_DEFAULT_REGION', region);
core.exportVariable('AWS_REGION', region);
}
async function exportAccountId(maskAccountId) {
// Get the AWS account ID
const sts = new aws.STS({customUserAgent: USER_AGENT});
const identity = await sts.getCallerIdentity().promise();
const accountId = identity.Account;
core.setOutput('aws-account-id', accountId);
if (!maskAccountId || maskAccountId.toLowerCase() == 'true') {
core.setSecret(accountId);
}
}
async function run() {
try {
@@ -9,41 +119,32 @@ async function run() {
const region = core.getInput('aws-region', { required: true });
const sessionToken = core.getInput('aws-session-token', { required: false });
const maskAccountId = core.getInput('mask-aws-account-id', { required: false });
const roleToAssume = core.getInput('role-to-assume', {required: false});
const roleDurationSeconds = core.getInput('role-duration-seconds', {required: false}) || MAX_ACTION_RUNTIME;
// Configure the AWS CLI and AWS SDKs using environment variables
// AWS_ACCESS_KEY_ID:
// Specifies an AWS access key associated with an IAM user or role
core.exportVariable('AWS_ACCESS_KEY_ID', accessKeyId);
// AWS_SECRET_ACCESS_KEY:
// Specifies the secret key associated with the access key. This is essentially the "password" for the access key.
core.exportVariable('AWS_SECRET_ACCESS_KEY', secretAccessKey);
// AWS_SESSION_TOKEN:
// Specifies the session token value that is required if you are using temporary security credentials.
if (sessionToken) {
core.exportVariable('AWS_SESSION_TOKEN', sessionToken);
// Get role credentials if configured to do so
if (roleToAssume) {
const roleCredentials = await assumeRole(
{accessKeyId, secretAccessKey, sessionToken, region, roleToAssume, roleDurationSeconds}
);
exportCredentials(roleCredentials);
} else {
exportCredentials({accessKeyId, secretAccessKey, sessionToken});
}
// AWS_DEFAULT_REGION and AWS_REGION:
// Specifies the AWS Region to send requests to
core.exportVariable('AWS_DEFAULT_REGION', region);
core.exportVariable('AWS_REGION', region);
exportRegion(region);
// Get the AWS account ID
const sts = new aws.STS({
customUserAgent: 'configure-aws-credentials-for-github-actions'
});
const identity = await sts.getCallerIdentity().promise();
const accountId = identity.Account;
core.setOutput('aws-account-id', accountId);
if (!maskAccountId || maskAccountId.toLowerCase() == 'true') {
core.setSecret(accountId);
}
await exportAccountId(maskAccountId);
}
catch (error) {
core.setFailed(error.message);
const showStackTrace = process.env.SHOW_STACK_TRACE;
if (showStackTrace === 'true') {
throw(error)
}
}
}
+203 -31
View File
@@ -1,89 +1,158 @@
const core = require('@actions/core');
const assert = require('assert');
const run = require('.');
jest.mock('@actions/core');
const FAKE_ACCESS_KEY_ID = 'MY-AWS-ACCESS-KEY-ID';
const FAKE_SECRET_ACCESS_KEY = 'MY-AWS-SECRET-ACCESS-KEY';
const FAKE_SESSION_TOKEN = 'MY-AWS-SESSION-TOKEN';
const FAKE_STS_ACCESS_KEY_ID = 'STS-AWS-ACCESS-KEY-ID';
const FAKE_STS_SECRET_ACCESS_KEY = 'STS-AWS-SECRET-ACCESS-KEY';
const FAKE_STS_SESSION_TOKEN = 'STS-AWS-SESSION-TOKEN';
const FAKE_REGION = 'fake-region-1';
const FAKE_ACCOUNT_ID = '123456789012';
const ROLE_NAME = 'MY-ROLE';
const ENVIRONMENT_VARIABLE_OVERRIDES = {
SHOW_STACK_TRACE: 'true',
GITHUB_REPOSITORY: 'MY-REPOSITORY-NAME',
GITHUB_WORKFLOW: 'MY-WORKFLOW-ID',
GITHUB_ACTION: 'MY-ACTION-NAME',
GITHUB_ACTOR: 'MY-USERNAME[bot]',
GITHUB_REF: 'MY-BRANCH',
GITHUB_SHA: 'MY-COMMIT-ID',
};
const GITHUB_ACTOR_SANITIZED = 'MY-USERNAME*bot*'
function mockGetInput(requestResponse) {
return function (name, options) { // eslint-disable-line no-unused-vars
return requestResponse[name]
}
}
const REQUIRED_INPUTS = {
'aws-access-key-id': FAKE_ACCESS_KEY_ID,
'aws-secret-access-key': FAKE_SECRET_ACCESS_KEY
};
const DEFAULT_INPUTS = {
...REQUIRED_INPUTS,
'aws-session-token': FAKE_SESSION_TOKEN,
'aws-region': FAKE_REGION,
'mask-aws-account-id': 'TRUE'
};
const ASSUME_ROLE_INPUTS = {...REQUIRED_INPUTS, 'role-to-assume': ROLE_NAME, 'aws-region': FAKE_REGION};
const mockStsCallerIdentity = jest.fn();
const mockStsAssumeRole = jest.fn();
jest.mock('aws-sdk', () => {
return {
STS: jest.fn(() => ({
getCallerIdentity: mockStsCallerIdentity
getCallerIdentity: mockStsCallerIdentity,
assumeRole: mockStsAssumeRole,
}))
};
});
describe('Configure AWS Credentials', () => {
const OLD_ENV = process.env;
beforeEach(() => {
jest.resetModules();
process.env = {...OLD_ENV, ...ENVIRONMENT_VARIABLE_OVERRIDES};
jest.clearAllMocks();
core.getInput = jest
.fn()
.mockReturnValueOnce('MY-AWS-ACCESS-KEY-ID') // aws-access-key-id
.mockReturnValueOnce('MY-AWS-SECRET-ACCESS-KEY') // aws-secret-access-key
.mockReturnValueOnce('us-east-2') // aws-default-region
.mockReturnValueOnce('MY-AWS-SESSION-TOKEN') // aws-session-token
.mockReturnValueOnce('TRUE'); // mask-aws-account-id
.mockImplementation(mockGetInput(DEFAULT_INPUTS));
mockStsCallerIdentity.mockImplementation(() => {
return {
promise() {
return Promise.resolve({ Account: '123456789012' });
return Promise.resolve({ Account: FAKE_ACCOUNT_ID });
}
};
});
mockStsAssumeRole.mockImplementation(() => {
return {
promise() {
return Promise.resolve({
Credentials: {
AccessKeyId: FAKE_STS_ACCESS_KEY_ID,
SecretAccessKey: FAKE_STS_SECRET_ACCESS_KEY,
SessionToken: FAKE_STS_SESSION_TOKEN
}
});
}
}
});
});
afterEach(() => {
process.env = OLD_ENV;
});
test('exports env vars', async () => {
await run();
expect(mockStsAssumeRole).toHaveBeenCalledTimes(0);
expect(core.exportVariable).toHaveBeenCalledTimes(5);
expect(core.exportVariable).toHaveBeenCalledWith('AWS_ACCESS_KEY_ID', 'MY-AWS-ACCESS-KEY-ID');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_SECRET_ACCESS_KEY', 'MY-AWS-SECRET-ACCESS-KEY');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_SESSION_TOKEN', 'MY-AWS-SESSION-TOKEN');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_DEFAULT_REGION', 'us-east-2');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_REGION', 'us-east-2');
expect(core.setOutput).toHaveBeenCalledWith('aws-account-id', '123456789012');
expect(core.setSecret).toHaveBeenCalledWith('123456789012');
expect(core.setSecret).toHaveBeenCalledTimes(4);
expect(core.exportVariable).toHaveBeenCalledWith('AWS_ACCESS_KEY_ID', FAKE_ACCESS_KEY_ID);
expect(core.setSecret).toHaveBeenCalledWith(FAKE_ACCESS_KEY_ID);
expect(core.exportVariable).toHaveBeenCalledWith('AWS_SECRET_ACCESS_KEY', FAKE_SECRET_ACCESS_KEY);
expect(core.setSecret).toHaveBeenCalledWith(FAKE_SECRET_ACCESS_KEY);
expect(core.exportVariable).toHaveBeenCalledWith('AWS_SESSION_TOKEN', FAKE_SESSION_TOKEN);
expect(core.setSecret).toHaveBeenCalledWith(FAKE_SESSION_TOKEN);
expect(core.exportVariable).toHaveBeenCalledWith('AWS_DEFAULT_REGION', FAKE_REGION);
expect(core.exportVariable).toHaveBeenCalledWith('AWS_REGION', FAKE_REGION);
expect(core.setOutput).toHaveBeenCalledWith('aws-account-id', FAKE_ACCOUNT_ID);
expect(core.setSecret).toHaveBeenCalledWith(FAKE_ACCOUNT_ID);
});
test('session token is optional', async () => {
const mockInputs = {...REQUIRED_INPUTS, 'aws-region': 'eu-west-1'};
core.getInput = jest
.fn()
.mockReturnValueOnce('MY-AWS-ACCESS-KEY-ID') // aws-access-key-id
.mockReturnValueOnce('MY-AWS-SECRET-ACCESS-KEY') // aws-secret-access-key
.mockReturnValueOnce('eu-west-1'); // aws-default-region
.mockImplementation(mockGetInput(mockInputs));
await run();
expect(mockStsAssumeRole).toHaveBeenCalledTimes(0);
expect(core.exportVariable).toHaveBeenCalledTimes(4);
expect(core.exportVariable).toHaveBeenCalledWith('AWS_ACCESS_KEY_ID', 'MY-AWS-ACCESS-KEY-ID');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_SECRET_ACCESS_KEY', 'MY-AWS-SECRET-ACCESS-KEY');
expect(core.setSecret).toHaveBeenCalledTimes(3);
expect(core.exportVariable).toHaveBeenCalledWith('AWS_ACCESS_KEY_ID', FAKE_ACCESS_KEY_ID);
expect(core.setSecret).toHaveBeenCalledWith(FAKE_ACCESS_KEY_ID);
expect(core.exportVariable).toHaveBeenCalledWith('AWS_SECRET_ACCESS_KEY', FAKE_SECRET_ACCESS_KEY);
expect(core.setSecret).toHaveBeenCalledWith(FAKE_SECRET_ACCESS_KEY);
expect(core.exportVariable).toHaveBeenCalledWith('AWS_DEFAULT_REGION', 'eu-west-1');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_REGION', 'eu-west-1');
expect(core.setOutput).toHaveBeenCalledWith('aws-account-id', '123456789012');
expect(core.setSecret).toHaveBeenCalledWith('123456789012');
expect(core.setOutput).toHaveBeenCalledWith('aws-account-id', FAKE_ACCOUNT_ID);
expect(core.setSecret).toHaveBeenCalledWith(FAKE_ACCOUNT_ID);
});
test('can opt out of masking account ID', async () => {
const mockInputs = {...REQUIRED_INPUTS, 'aws-region': 'us-east-1', 'mask-aws-account-id': 'false'};
core.getInput = jest
.fn()
.mockReturnValueOnce('MY-AWS-ACCESS-KEY-ID') // aws-access-key-id
.mockReturnValueOnce('MY-AWS-SECRET-ACCESS-KEY') // aws-secret-access-key
.mockReturnValueOnce('us-east-1') // aws-default-region
.mockReturnValueOnce('') // aws-session-token
.mockReturnValueOnce('false'); // mask-aws-account-id
.mockImplementation(mockGetInput(mockInputs));
await run();
expect(mockStsAssumeRole).toHaveBeenCalledTimes(0);
expect(core.exportVariable).toHaveBeenCalledTimes(4);
expect(core.exportVariable).toHaveBeenCalledWith('AWS_ACCESS_KEY_ID', 'MY-AWS-ACCESS-KEY-ID');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_SECRET_ACCESS_KEY', 'MY-AWS-SECRET-ACCESS-KEY');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_ACCESS_KEY_ID', FAKE_ACCESS_KEY_ID);
expect(core.setSecret).toHaveBeenCalledWith(FAKE_ACCESS_KEY_ID);
expect(core.exportVariable).toHaveBeenCalledWith('AWS_SECRET_ACCESS_KEY', FAKE_SECRET_ACCESS_KEY);
expect(core.setSecret).toHaveBeenCalledWith(FAKE_SECRET_ACCESS_KEY);
expect(core.exportVariable).toHaveBeenCalledWith('AWS_DEFAULT_REGION', 'us-east-1');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_REGION', 'us-east-1');
expect(core.setOutput).toHaveBeenCalledWith('aws-account-id', '123456789012');
expect(core.setSecret).toHaveBeenCalledTimes(0);
expect(core.setOutput).toHaveBeenCalledWith('aws-account-id', FAKE_ACCOUNT_ID);
expect(core.setSecret).toHaveBeenCalledTimes(2);
});
test('error is caught by core.setFailed', async () => {
test('error is caught by core.setFailed and caught', async () => {
process.env.SHOW_STACK_TRACE = 'false';
mockStsCallerIdentity.mockImplementation(() => {
throw new Error();
});
@@ -92,4 +161,107 @@ describe('Configure AWS Credentials', () => {
expect(core.setFailed).toBeCalled();
});
test('error is caught by core.setFailed and passed', async () => {
mockStsCallerIdentity.mockImplementation(() => {
throw new Error();
});
await assert.rejects(() => run());
expect(core.setFailed).toBeCalled();
});
test('basic role assumption exports', async () => {
core.getInput = jest
.fn()
.mockImplementation(mockGetInput(ASSUME_ROLE_INPUTS));
await run();
expect(mockStsAssumeRole).toHaveBeenCalledTimes(1);
expect(core.exportVariable).toHaveBeenCalledTimes(5);
expect(core.setSecret).toHaveBeenCalledTimes(4);
expect(core.exportVariable).toHaveBeenCalledWith('AWS_ACCESS_KEY_ID', FAKE_STS_ACCESS_KEY_ID);
expect(core.setSecret).toHaveBeenCalledWith(FAKE_STS_ACCESS_KEY_ID);
expect(core.exportVariable).toHaveBeenCalledWith('AWS_SECRET_ACCESS_KEY', FAKE_STS_SECRET_ACCESS_KEY);
expect(core.setSecret).toHaveBeenCalledWith(FAKE_STS_SECRET_ACCESS_KEY);
expect(core.exportVariable).toHaveBeenCalledWith('AWS_SESSION_TOKEN', FAKE_STS_SESSION_TOKEN);
expect(core.setSecret).toHaveBeenCalledWith(FAKE_STS_SESSION_TOKEN);
expect(core.exportVariable).toHaveBeenCalledWith('AWS_DEFAULT_REGION', FAKE_REGION);
expect(core.exportVariable).toHaveBeenCalledWith('AWS_REGION', FAKE_REGION);
expect(core.setOutput).toHaveBeenCalledWith('aws-account-id', FAKE_ACCOUNT_ID);
expect(core.setSecret).toHaveBeenCalledWith(FAKE_ACCOUNT_ID);
});
test('role assumption tags', async () => {
core.getInput = jest
.fn()
.mockImplementation(mockGetInput(ASSUME_ROLE_INPUTS));
await run();
expect(mockStsAssumeRole).toHaveBeenCalledWith({
RoleArn: ROLE_NAME,
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: 'Branch', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_REF},
{Key: 'Commit', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_SHA},
]
})
});
test('role assumption duration provided', async () => {
core.getInput = jest
.fn()
.mockImplementation(mockGetInput({...ASSUME_ROLE_INPUTS, 'role-duration-seconds': 5}));
await run();
expect(mockStsAssumeRole).toHaveBeenCalledWith({
RoleArn: ROLE_NAME,
RoleSessionName: 'GitHubActions',
DurationSeconds: 5,
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('workflow name sanitized in role assumption tags', async () => {
core.getInput = jest
.fn()
.mockImplementation(mockGetInput(ASSUME_ROLE_INPUTS));
process.env = {...process.env, GITHUB_WORKFLOW: 'Workflow!"#$%&\'()*+, -./:;<=>?@[]^_`{|}~🙂💥🍌1yFvMOeD3ZHYsHrGjCceOboMYzBPo0CRNFdcsVRG6UgR3A912a8KfcBtEVvkAS7kRBq80umGff8mux5IN1y55HQWPNBNyaruuVr4islFXte4FDQZexGJRUSMyHQpxJ8OmZnET84oDmbvmIjgxI6IBrdihX9PHMapT4gQvRYnLqNiKb18rEMWDNoZRy51UPX5sWK2GKPipgKSO9kqLckZai9D2AN2RlWCxtMqChNtxuxjqeqhoQZo0oaq39sjcRZgAAAAAAA'};
const sanitizedWorkflowName = 'Workflow**********+, -./:;<=>?@***_********1yFvMOeD3ZHYsHrGjCceOboMYzBPo0CRNFdcsVRG6UgR3A912a8KfcBtEVvkAS7kRBq80umGff8mux5IN1y55HQWPNBNyaruuVr4islFXte4FDQZexGJRUSMyHQpxJ8OmZnET84oDmbvmIjgxI6IBrdihX9PHMapT4gQvRYnLqNiKb18rEMWDNoZRy51UPX5sWK2GKPipgKSO9kqLckZa'
await run();
expect(mockStsAssumeRole).toHaveBeenCalledWith({
RoleArn: ROLE_NAME,
RoleSessionName: 'GitHubActions',
DurationSeconds: 6 * 3600,
Tags: [
{Key: 'GitHub', Value: 'Actions'},
{Key: 'Repository', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_REPOSITORY},
{Key: 'Workflow', Value: sanitizedWorkflowName},
{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},
]
})
});
});
+2792 -1818
View File
File diff suppressed because it is too large Load Diff
+6 -6
View File
@@ -1,6 +1,6 @@
{
"name": "aws-actions-configure-aws-credentials",
"version": "0.0.0",
"version": "1.1.1",
"description": "Configure AWS Credentials",
"main": "index.js",
"scripts": {
@@ -25,12 +25,12 @@
},
"homepage": "https://github.com/aws-actions/configure-aws-credentials#readme",
"dependencies": {
"@actions/core": "^1.2.0",
"aws-sdk": "^2.567.0"
"@actions/core": "^1.2.2",
"aws-sdk": "^2.613.0"
},
"devDependencies": {
"@zeit/ncc": "^0.20.5",
"eslint": "^6.6.0",
"jest": "^24.9.0"
"@zeit/ncc": "^0.21.0",
"eslint": "^6.8.0",
"jest": "^25.1.0"
}
}