Compare commits

..

80 Commits

Author SHA1 Message Date
GitHub Actions 023daa7fe5 chore: Update dist 2023-02-28 04:08:41 +00:00
dependabot[bot] f586cc8d6c chore: Bump aws-sdk from 2.1319.0 to 2.1324.0 (#678)
Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1319.0 to 2.1324.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.1319.0...v2.1324.0)

---
updated-dependencies:
- dependency-name: aws-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-28 04:07:50 +00:00
dependabot[bot] 5726671b7e chore: Bump axios from 1.3.3 to 1.3.4 (#676)
Bumps [axios](https://github.com/axios/axios) from 1.3.3 to 1.3.4.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.3.3...v1.3.4)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2023-02-28 03:59:33 +00:00
dependabot[bot] 682539baa7 chore: Bump eslint from 8.34.0 to 8.35.0 (#674)
Bumps [eslint](https://github.com/eslint/eslint) from 8.34.0 to 8.35.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.34.0...v8.35.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-28 03:58:18 +00:00
Tom Keller 186395a864 fix!: proxy changes to v1-node16 (runtime failures 2023-02-24 16:00:06 -08:00
Tom Keller a19d847176 Merge branch 'master' into v1-node16 2023-02-24 14:36:52 -08:00
Tom Keller afbf093795 Revert "Merge branch 'master' into v1-node16"
This reverts commit df03f9f89e, reversing
changes made to 5f641521a3.
2023-02-24 14:28:16 -08:00
Tom Keller df03f9f89e Merge branch 'master' into v1-node16 2023-02-24 14:04:51 -08:00
GitHub Actions 5f641521a3 chore: Update dist 2023-02-21 04:01:43 +00:00
dependabot[bot] cf1ab7af03 chore: Bump aws-sdk from 2.1314.0 to 2.1319.0 (#664)
Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1314.0 to 2.1319.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.1314.0...v2.1319.0)

---
updated-dependencies:
- dependency-name: aws-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2023-02-21 04:00:52 +00:00
dependabot[bot] feaa7fa4a6 chore: Bump jest from 29.4.2 to 29.4.3 (#662)
Bumps [jest](https://github.com/facebook/jest/tree/HEAD/packages/jest) from 29.4.2 to 29.4.3.
- [Release notes](https://github.com/facebook/jest/releases)
- [Changelog](https://github.com/facebook/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/jest/commits/v29.4.3/packages/jest)

---
updated-dependencies:
- dependency-name: jest
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-21 03:59:32 +00:00
dependabot[bot] 4f2f92e5ab chore: Bump jest from 29.4.1 to 29.4.2 (#657)
Bumps [jest](https://github.com/facebook/jest/tree/HEAD/packages/jest) from 29.4.1 to 29.4.2.
- [Release notes](https://github.com/facebook/jest/releases)
- [Changelog](https://github.com/facebook/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/jest/commits/v29.4.2/packages/jest)

---
updated-dependencies:
- dependency-name: jest
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2023-02-14 04:05:29 +00:00
GitHub Actions 63c92be916 chore: Update dist 2023-02-14 04:04:16 +00:00
dependabot[bot] d57f6a99b2 chore: Bump aws-sdk from 2.1310.0 to 2.1314.0 (#656)
Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1310.0 to 2.1314.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.1310.0...v2.1314.0)

---
updated-dependencies:
- dependency-name: aws-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-14 04:03:21 +00:00
dependabot[bot] b10102e8c0 chore: Bump axios from 1.3.2 to 1.3.3 (#652)
Bumps [axios](https://github.com/axios/axios) from 1.3.2 to 1.3.3.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.3.2...v1.3.3)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2023-02-14 04:00:13 +00:00
dependabot[bot] 329c87d69e chore: Bump eslint from 8.33.0 to 8.34.0 (#654)
Bumps [eslint](https://github.com/eslint/eslint) from 8.33.0 to 8.34.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.33.0...v8.34.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-14 03:59:24 +00:00
GitHub Actions 7c78a8afc0 chore: Update dist 2023-02-07 03:05:41 +00:00
dependabot[bot] bfc885690a chore: Bump aws-sdk from 2.1305.0 to 2.1310.0 (#649)
Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1305.0 to 2.1310.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.1305.0...v2.1310.0)

---
updated-dependencies:
- dependency-name: aws-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-07 03:04:53 +00:00
dependabot[bot] b8843be31a chore: Bump axios from 1.2.6 to 1.3.2 (#647)
Bumps [axios](https://github.com/axios/axios) from 1.2.6 to 1.3.2.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.2.6...v1.3.2)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-07 03:02:30 +00:00
dependabot[bot] 07c2f971ba chore: Bump eslint from 8.32.0 to 8.33.0 (#644)
Bumps [eslint](https://github.com/eslint/eslint) from 8.32.0 to 8.33.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.32.0...v8.33.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2023-01-31 03:09:14 +00:00
GitHub Actions afaecf5658 chore: Update dist 2023-01-31 03:07:50 +00:00
dependabot[bot] 9395f54576 chore: Bump aws-sdk from 2.1300.0 to 2.1305.0 (#646)
Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1300.0 to 2.1305.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.1300.0...v2.1305.0)

---
updated-dependencies:
- dependency-name: aws-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-31 03:07:04 +00:00
dependabot[bot] 15bf15ef24 chore: Bump jest from 29.3.1 to 29.4.1 (#642)
Bumps [jest](https://github.com/facebook/jest/tree/HEAD/packages/jest) from 29.3.1 to 29.4.1.
- [Release notes](https://github.com/facebook/jest/releases)
- [Changelog](https://github.com/facebook/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/jest/commits/v29.4.1/packages/jest)

---
updated-dependencies:
- dependency-name: jest
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2023-01-31 03:04:46 +00:00
dependabot[bot] 0bb734a034 chore: Bump @vercel/ncc from 0.36.0 to 0.36.1 (#641)
Bumps [@vercel/ncc](https://github.com/vercel/ncc) from 0.36.0 to 0.36.1.
- [Release notes](https://github.com/vercel/ncc/releases)
- [Commits](https://github.com/vercel/ncc/compare/0.36.0...0.36.1)

---
updated-dependencies:
- dependency-name: "@vercel/ncc"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2023-01-31 03:03:53 +00:00
dependabot[bot] 104814938c chore: Bump axios from 1.2.3 to 1.2.6 (#638)
Bumps [axios](https://github.com/axios/axios) from 1.2.3 to 1.2.6.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.2.3...v1.2.6)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-31 03:02:35 +00:00
dependabot[bot] 8203047ce9 chore: Bump axios from 1.2.2 to 1.2.3 (#631)
Bumps [axios](https://github.com/axios/axios) from 1.2.2 to 1.2.3.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/1.2.2...v1.2.3)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-24 03:07:20 +00:00
GitHub Actions a3d672ff77 chore: Update dist 2023-01-24 03:04:23 +00:00
dependabot[bot] 3c5e8d9305 chore: Bump aws-sdk from 2.1295.0 to 2.1300.0 (#629)
Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1295.0 to 2.1300.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.1295.0...v2.1300.0)

---
updated-dependencies:
- dependency-name: aws-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-24 03:03:37 +00:00
GitHub Actions 26c46c2ae7 chore: Update dist 2023-01-17 03:06:51 +00:00
dependabot[bot] 011701cc1b chore: Bump aws-sdk from 2.1291.0 to 2.1295.0 (#626)
Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1291.0 to 2.1295.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.1291.0...v2.1295.0)

---
updated-dependencies:
- dependency-name: aws-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2023-01-17 03:06:06 +00:00
dependabot[bot] b9e6c47506 chore: Bump eslint from 8.31.0 to 8.32.0 (#624)
Bumps [eslint](https://github.com/eslint/eslint) from 8.31.0 to 8.32.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.31.0...v8.32.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-17 03:04:52 +00:00
GitHub Actions 9727186006 chore: Update dist 2023-01-10 03:03:21 +00:00
dependabot[bot] 8c40159721 chore: Bump aws-sdk from 2.1286.0 to 2.1291.0 (#623)
Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1286.0 to 2.1291.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.1286.0...v2.1291.0)

---
updated-dependencies:
- dependency-name: aws-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-10 03:02:30 +00:00
dependabot[bot] ada05fa00e chore: Bump axios from 1.2.1 to 1.2.2 (#617)
Bumps [axios](https://github.com/axios/axios) from 1.2.1 to 1.2.2.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.2.1...1.2.2)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2023-01-03 03:06:18 +00:00
dependabot[bot] 90be1075bb chore: Bump eslint from 8.30.0 to 8.31.0 (#618)
Bumps [eslint](https://github.com/eslint/eslint) from 8.30.0 to 8.31.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.30.0...v8.31.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2023-01-03 03:04:37 +00:00
GitHub Actions b1e291fd46 chore: Update dist 2023-01-03 03:03:12 +00:00
dependabot[bot] 5bf8e889ef chore: Bump aws-sdk from 2.1282.0 to 2.1286.0 (#615)
Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1282.0 to 2.1286.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.1282.0...v2.1286.0)

---
updated-dependencies:
- dependency-name: aws-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-03 03:02:24 +00:00
GitHub Actions 8fd75be9bb chore: Update dist 2022-12-27 03:03:20 +00:00
dependabot[bot] 65cd794383 chore: Bump aws-sdk from 2.1278.0 to 2.1282.0 (#614)
Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1278.0 to 2.1282.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.1278.0...v2.1282.0)

---
updated-dependencies:
- dependency-name: aws-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-27 03:02:29 +00:00
GitHub Actions 56320524c9 chore: Update dist 2022-12-20 03:04:22 +00:00
dependabot[bot] 4a10c382ea chore: Bump aws-sdk from 2.1273.0 to 2.1278.0 (#609)
Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1273.0 to 2.1278.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.1273.0...v2.1278.0)

---
updated-dependencies:
- dependency-name: aws-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-20 03:03:44 +00:00
dependabot[bot] d4fb44140f chore: Bump eslint from 8.29.0 to 8.30.0 (#607)
Bumps [eslint](https://github.com/eslint/eslint) from 8.29.0 to 8.30.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.29.0...v8.30.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-20 03:03:30 +00:00
GitHub Actions 95bc17402b chore: Update dist 2022-12-13 03:06:02 +00:00
dependabot[bot] b016bfd40a chore: Bump aws-sdk from 2.1268.0 to 2.1273.0 (#602)
Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1268.0 to 2.1273.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.1268.0...v2.1273.0)

---
updated-dependencies:
- dependency-name: aws-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-13 03:05:06 +00:00
dependabot[bot] abcf4fe216 chore: Bump axios from 1.2.0 to 1.2.1 (#595)
Bumps [axios](https://github.com/axios/axios) from 1.2.0 to 1.2.1.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.2.0...v1.2.1)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2022-12-06 03:08:30 +00:00
dependabot[bot] 6a502811f6 chore: Bump @vercel/ncc from 0.34.0 to 0.36.0 (#593)
Bumps [@vercel/ncc](https://github.com/vercel/ncc) from 0.34.0 to 0.36.0.
- [Release notes](https://github.com/vercel/ncc/releases)
- [Commits](https://github.com/vercel/ncc/compare/0.34.0...0.36.0)

---
updated-dependencies:
- dependency-name: "@vercel/ncc"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2022-12-06 03:07:00 +00:00
GitHub Actions fc10f5e66c chore: Update dist 2022-12-06 03:05:42 +00:00
dependabot[bot] 2fbb264794 chore: Bump aws-sdk from 2.1262.0 to 2.1268.0 (#597)
Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1262.0 to 2.1268.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.1262.0...v2.1268.0)

---
updated-dependencies:
- dependency-name: aws-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2022-12-06 03:04:54 +00:00
dependabot[bot] 7704dba423 chore: Bump eslint from 8.28.0 to 8.29.0 (#591)
Bumps [eslint](https://github.com/eslint/eslint) from 8.28.0 to 8.29.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.28.0...v8.29.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-06 03:02:38 +00:00
dependabot[bot] 495fc37803 chore: Bump axios from 1.1.3 to 1.2.0 (#589)
Bumps [axios](https://github.com/axios/axios) from 1.1.3 to 1.2.0.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.1.3...v1.2.0)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-29 03:08:57 +00:00
GitHub Actions c44e4cd308 chore: Update dist 2022-11-29 03:05:00 +00:00
dependabot[bot] 5db0c4b245 chore: Bump aws-sdk from 2.1259.0 to 2.1262.0 (#588)
Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1259.0 to 2.1262.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.1259.0...v2.1262.0)

---
updated-dependencies:
- dependency-name: aws-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-29 03:04:09 +00:00
dependabot[bot] 8962602b76 chore: Bump eslint from 8.27.0 to 8.28.0 (#583)
Bumps [eslint](https://github.com/eslint/eslint) from 8.27.0 to 8.28.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.27.0...v8.28.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2022-11-22 03:34:04 +00:00
GitHub Actions 996af9a61b chore: Update dist 2022-11-22 03:31:45 +00:00
dependabot[bot] 70f70f3d01 chore: Bump aws-sdk from 2.1254.0 to 2.1259.0 (#582)
Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1254.0 to 2.1259.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.1254.0...v2.1259.0)

---
updated-dependencies:
- dependency-name: aws-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-22 03:30:55 +00:00
GitHub Actions 40d50e0dc7 chore: Update dist 2022-11-15 03:05:40 +00:00
dependabot[bot] d70ae8a9b8 chore: Bump aws-sdk from 2.1249.0 to 2.1254.0 (#577)
Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1249.0 to 2.1254.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.1249.0...v2.1254.0)

---
updated-dependencies:
- dependency-name: aws-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2022-11-15 03:04:55 +00:00
dependabot[bot] 29858782df chore: Bump jest from 29.3.0 to 29.3.1 (#575)
Bumps [jest](https://github.com/facebook/jest/tree/HEAD/packages/jest) from 29.3.0 to 29.3.1.
- [Release notes](https://github.com/facebook/jest/releases)
- [Changelog](https://github.com/facebook/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/jest/commits/v29.3.1/packages/jest)

---
updated-dependencies:
- dependency-name: jest
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-15 03:03:35 +00:00
dependabot[bot] daed12437b chore: Bump eslint from 8.26.0 to 8.27.0 (#573)
Bumps [eslint](https://github.com/eslint/eslint) from 8.26.0 to 8.27.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.26.0...v8.27.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-08 03:20:41 +00:00
dependabot[bot] 3d0ec8cfd7 chore: Bump jest from 29.2.2 to 29.3.0 (#571)
Bumps [jest](https://github.com/facebook/jest/tree/HEAD/packages/jest) from 29.2.2 to 29.3.0.
- [Release notes](https://github.com/facebook/jest/releases)
- [Changelog](https://github.com/facebook/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/jest/commits/v29.3.0/packages/jest)

---
updated-dependencies:
- dependency-name: jest
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2022-11-08 03:08:29 +00:00
GitHub Actions 89d6bf8b63 chore: Update dist 2022-11-08 03:07:25 +00:00
dependabot[bot] 89d9dc8901 chore: Bump aws-sdk from 2.1244.0 to 2.1249.0 (#569)
Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1244.0 to 2.1249.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.1244.0...v2.1249.0)

---
updated-dependencies:
- dependency-name: aws-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-08 03:06:39 +00:00
Tom Keller 59775fae63 Merge branch 'master' into v1-node16 2022-11-04 17:45:19 -07:00
dependabot[bot] 8461db48ce chore: Bump aws-sdk from 2.1239.0 to 2.1244.0 (#559)
Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1239.0 to 2.1244.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.1239.0...v2.1244.0)

---
updated-dependencies:
- dependency-name: aws-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-01 03:41:45 +00:00
Tom Keller 1c6d3132e1 Merge branch 'master' into v1-node16 2022-10-26 13:16:25 -07:00
Peter Woodworth 77b504aefa update package lock with node 14 (#556) 2022-10-26 13:15:51 -07:00
Peter Woodworth 993b6a062d update package lock (#555) 2022-10-26 13:15:50 -07:00
Tom Keller 1fee7bbf94 Merge branch 'master' into v1-node16 2022-10-25 17:33:46 -07:00
Tom Keller 096a34b527 Merge branch 'master' into v1-node16 2022-10-25 16:56:51 -07:00
Tom Keller 036f9c6a9f Merge branch 'master' into v1-node16 2022-10-25 09:48:37 -07:00
dependabot[bot] 1908557210 chore: Bump eslint from 8.25.0 to 8.26.0 (#544)
Bumps [eslint](https://github.com/eslint/eslint) from 8.25.0 to 8.26.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.25.0...v8.26.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-25 03:38:47 +00:00
dependabot[bot] 7be15a02d9 chore: Bump aws-sdk from 2.1234.0 to 2.1239.0 (#545)
Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1234.0 to 2.1239.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.1234.0...v2.1239.0)

---
updated-dependencies:
- dependency-name: aws-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2022-10-25 03:37:17 +00:00
dependabot[bot] 7289c29462 chore: Bump jest from 29.2.0 to 29.2.2 (#547)
Bumps [jest](https://github.com/facebook/jest/tree/HEAD/packages/jest) from 29.2.0 to 29.2.2.
- [Release notes](https://github.com/facebook/jest/releases)
- [Changelog](https://github.com/facebook/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/jest/commits/v29.2.2/packages/jest)

---
updated-dependencies:
- dependency-name: jest
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-25 03:36:23 +00:00
Tom Keller a485a1e9a4 Merge branch 'master' into v1-node16 2022-10-18 21:11:25 -07:00
dependabot[bot] c3748b7f3f chore: Bump axios from 1.1.2 to 1.1.3 (#533)
Bumps [axios](https://github.com/axios/axios) from 1.1.2 to 1.1.3.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.1.2...v1.1.3)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-18 03:25:50 +00:00
dependabot[bot] 2db6cd9a80 chore: Bump aws-sdk from 2.1232.0 to 2.1234.0 (#538)
Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1232.0 to 2.1234.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.1232.0...v2.1234.0)

---
updated-dependencies:
- dependency-name: aws-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2022-10-18 03:24:23 +00:00
dependabot[bot] d90b587a73 chore: Bump jest from 29.1.2 to 29.2.0 (#536)
Bumps [jest](https://github.com/facebook/jest/tree/HEAD/packages/jest) from 29.1.2 to 29.2.0.
- [Release notes](https://github.com/facebook/jest/releases)
- [Changelog](https://github.com/facebook/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/jest/commits/v29.2.0/packages/jest)

---
updated-dependencies:
- dependency-name: jest
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-18 03:22:49 +00:00
dependabot[bot] 2aed65ee75 chore: Bump aws-sdk from 2.1231.0 to 2.1232.0 (#527)
Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1231.0 to 2.1232.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.1231.0...v2.1232.0)

---
updated-dependencies:
- dependency-name: aws-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-13 20:52:46 +00:00
Peter Woodworth cdfc29bebf Merge pull request #524 from kellertk/v1-node16
fix: temporarily bump node version to 16
2022-10-13 13:17:15 -07:00
Tom Keller a30b23eed5 fix: temporarily bump node version to 16 2022-10-13 13:09:41 -07:00
56 changed files with 47737 additions and 115053 deletions
-19
View File
@@ -1,19 +0,0 @@
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
[Makefile]
indent_style = tab
indent_size = 4
+18
View File
@@ -0,0 +1,18 @@
{
"env": {
"commonjs": true,
"es6": true,
"node": true,
"jest": true
},
"extends": "eslint:recommended",
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parserOptions": {
"ecmaVersion": 2018
},
"rules": {
}
}
-7
View File
@@ -1,7 +0,0 @@
/dist/** linguist-generated
/package-lock.json linguist-generated
*.json text eol=lf
*.js text eol=lf
*.jsx text eol=lf
*.ts text eol=lf
*.tsx text eol=lf
-8
View File
@@ -12,14 +12,6 @@ body:
description: What is the problem? A clear and concise description of the bug.
validations:
required: true
- type: checkboxes
id: regression
attributes:
label: Regression Issue
description: What is a regression? If it worked in a previous version but doesn't in the latest version, it's considered a regression. In this case, please provide specific version number in the report.
options:
- label: Select this option if this issue appears to be a regression.
required: false
- type: textarea
id: expected
attributes:
+1 -1
View File
@@ -4,6 +4,6 @@
---
* [ ] Have you followed the guidelines in our [Contributing guide?](https://github.com/aws-actions/configure-aws-credentials/blob/main/CONTRIBUTING.md)
* [ ] Have you followed the guidelines in our [Contributing guide?](https://github.com/aws-actions/configure-aws-credentials/blob/master/CONTRIBUTING.md)
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.
+8 -1
View File
@@ -6,4 +6,11 @@ updates:
interval: weekly
day: tuesday
open-pull-requests-limit: 10
target-branch: 'main'
target-branch: 'master'
- package-ecosystem: npm
directory: "/"
schedule:
interval: weekly
day: tuesday
open-pull-requests-limit: 10
target-branch: 'v1-node16'
@@ -1,32 +0,0 @@
on:
pull_request_review:
types: submitted
jobs:
approved_pr:
name: Automerge approved PRs
permissions:
contents: write
pull-requests: write
id-token: write
if: ${{ github.event.review.state == 'approved' && github.repository == 'aws-actions/configure-aws-credentials' && (github.event.review.author_association == 'OWNER' || github.event.review.author_association == 'MEMBER' || github.event.review.user.login == 'aws-sdk-osds') }}
runs-on: ubuntu-latest
steps:
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: us-west-2
role-to-assume: ${{ secrets.SECRETS_AWS_PACKAGING_ROLE_TO_ASSUME }}
role-duration-seconds: 900
role-session-name: SecretsManagerFetch
- name: Get bot user token
uses: aws-actions/aws-secretsmanager-get-secrets@v2
with:
parse-json-secrets: true
secret-ids: |
OSDS,arn:aws:secretsmanager:us-west-2:206735643321:secret:github-aws-sdk-osds-automation-gebs9n
- name: Enable PR automerge
run: gh pr merge --auto --squash "$PR_URL"
env:
PR_URL: ${{ github.event.pull_request.html_url }}
GITHUB_TOKEN: ${{ env.OSDS_ACCESS_TOKEN }}
-20
View File
@@ -1,20 +0,0 @@
name: Test Configure AWS Credential
on:
workflow_dispatch:
jobs:
cawsc:
runs-on: ubuntu-latest
permissions:
id-token: write
steps:
- name: CAWSC
uses: aws-actions/configure-aws-credentials@main
with:
aws-region: us-west-2
role-to-assume: ${{ secrets.SECRETS_AWS_PACKAGING_ROLE_TO_ASSUME }}
role-duration-seconds: 900
role-session-name: TestCAWSC
- name: Whoami
run: |
aws sts get-caller-identity
+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
+4 -4
View File
@@ -15,14 +15,14 @@ jobs:
runs-on: ubuntu-latest
name: Stale issue job
steps:
- uses: aws-actions/stale-issue-cleanup@v6
- uses: aws-actions/stale-issue-cleanup@v5
with:
# Setting messages to an empty string will cause the automation to skip
# that category
ancient-issue-message: This issue has not received any attention in 1 year. If you want to keep this issue open, please leave a comment below and auto-close will be canceled.
stale-issue-message: This issue has not received a response in a while. If you want to keep this issue open, please leave a comment below and auto-close will be canceled.
stale-pr-message: This PR has not received a response in a while. If you want to keep this issue open, please leave a comment below and auto-close will be canceled.
# These labels are required
stale-issue-label: closing-soon
exempt-issue-labels: no-autoclose
@@ -37,7 +37,7 @@ jobs:
# Issue timing
days-before-stale: 5
days-before-close: 2
days-before-ancient: 36500
days-before-ancient: 365
# If you don't want to mark a issue as being ancient based on a
# threshold of "upvotes", you can set this here. An "upvote" is
@@ -48,4 +48,4 @@ jobs:
repo-token: ${{ secrets.GITHUB_TOKEN }}
loglevel: DEBUG
# Set dry-run to true to not perform label or close actions.
dry-run: false
dry-run: false
+3 -1
View File
@@ -13,5 +13,7 @@ jobs:
# These inputs are both required
repo-token: "${{ secrets.GITHUB_TOKEN }}"
message: |
Comments on closed issues are hard for our team to see.
### ⚠️Comment Visibility Warning⚠️
Comments on closed issues are hard for our team to see.
If you need more assistance, please either tag a team member or open a new issue that references this one.
If you wish to keep having a conversation with other community members under this issue feel free to do so.
+71
View File
@@ -0,0 +1,71 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
name: "CodeQL"
on:
push:
branches: [master]
pull_request:
# The branches below must be a subset of the branches above
branches: [master]
schedule:
- cron: '0 0 * * 2'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
# Override automatic language detection by changing the below list
# Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python']
language: ['javascript']
# Learn more...
# https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection
steps:
- name: Checkout repository
uses: actions/checkout@v2
with:
# We must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head.
fetch-depth: 2
# If this run was triggered by a pull request event, then checkout
# the head of the pull request instead of the merge commit.
- run: git checkout HEAD^2
if: ${{ github.event_name == 'pull_request' }}
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
@@ -1,41 +0,0 @@
name: Dependabot auto-approve
on:
pull_request:
workflow_dispatch:
permissions:
pull-requests: write
id-token: write
contents: read
jobs:
dependabot:
runs-on: ubuntu-latest
if: ${{ github.event.pull_request.user.login == 'dependabot[bot]' && github.repository == 'aws-actions/configure-aws-credentials' }}
steps:
- name: Get Metadata
id: dependabot-metadata
uses: dependabot/fetch-metadata@v2
- uses: actions/checkout@v4
name: Clone repo
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: us-west-2
role-to-assume: arn:aws:iam::206735643321:role/ConfigureAwsCredentialsPackageRole
role-duration-seconds: 900
- name: Get bot user token
uses: aws-actions/aws-secretsmanager-get-secrets@v2
with:
parse-json-secrets: true
secret-ids: |
OSDS,arn:aws:secretsmanager:us-west-2:206735643321:secret:github-aws-sdk-osds-automation-gebs9n
- name: Approve PR if not already approved
run: |
gh pr checkout "$PR_URL"
if [ "$(gh pr status --json reviewDecision - q .currentBranch.reviewDecision)" != "APPROVED" ]; then
gh pr review "$PR_URL" --approve
else echo "PR already approved"
fi
env:
PR_URL: ${{ github.event.pull_request.html_url }}
GITHUB_TOKEN: ${{ env.OSDS_ACCESS_TOKEN }}
@@ -1,18 +0,0 @@
name: HandleStaleDiscussions
on:
schedule:
- cron: '0 */4 * * *'
discussion_comment:
types: [created]
jobs:
handle-stale-discussions:
name: Handle stale discussions
runs-on: ubuntu-latest
permissions:
discussions: write
steps:
- name: Stale discussions action
uses: aws-github-ops/handle-stale-discussions@v1
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
@@ -1,32 +0,0 @@
# Apply potential regression label on issues
name: issue-regression-label
on:
issues:
types: [opened, edited]
jobs:
add-regression-label:
runs-on: ubuntu-latest
permissions:
issues: write
steps:
- name: Fetch template body
id: check_regression
uses: actions/github-script@v7
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TEMPLATE_BODY: ${{ github.event.issue.body }}
with:
script: |
const regressionPattern = /\[x\] Select this option if this issue appears to be a regression\./i;
const template = `${process.env.TEMPLATE_BODY}`
const match = regressionPattern.test(template);
core.setOutput('is_regression', match);
- name: Manage regression label
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
if [ "${{ steps.check_regression.outputs.is_regression }}" == "true" ]; then
gh issue edit ${{ github.event.issue.number }} --add-label "potential-regression" -R ${{ github.repository }}
else
gh issue edit ${{ github.event.issue.number }} --remove-label "potential-regression" -R ${{ github.repository }}
fi
@@ -1,12 +1,12 @@
name: Update dist files on main branch
name: Update dist files on
on:
push:
branches:
- main
- master
- v1-node16
paths-ignore:
- 'dist/**'
workflow_dispatch:
jobs:
package:
@@ -17,7 +17,7 @@ jobs:
contents: read
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
with:
fetch-depth: 0
ref: ${{ github.ref_name }}
@@ -28,24 +28,24 @@ jobs:
npm test
npm run package
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
uses: aws-actions/configure-aws-credentials@v1-node16
with:
aws-region: us-west-2
role-to-assume: ${{ secrets.SECRETS_AWS_PACKAGING_ROLE_TO_ASSUME }}
role-to-assume: ${{ secrets.SECRETS_AWS_ROLE_TO_ASSUME }}
role-duration-seconds: 900
role-session-name: SecretsManagerFetch
- name: Get bot user token
uses: aws-actions/aws-secretsmanager-get-secrets@v2
uses: aws-actions/aws-secretsmanager-get-secrets@v1
with:
parse-json-secrets: true
secret-ids: |
OSDS,arn:aws:secretsmanager:us-west-2:206735643321:secret:github-aws-sdk-osds-automation-gebs9n
OSDS,arn:aws:secretsmanager:us-west-2:294535624312:secret:github-aws-sdk-osds-automation-ZHNalp
- name: Commit
run: |
echo "::add-mask::${{ env.OSDS_ACCESS_TOKEN }}"
echo "::add-mask::${{ env.OSDS_ACCESS_TOKEN }}}"
git config user.name "GitHub Actions"
git config user.email "github-aws-sdk-osds-automation@amazon.com"
git remote set-url origin https://${{ env.OSDS_ACCESS_TOKEN }}@github.com/aws-actions/configure-aws-credentials.git
git remote set-url origin https://x-access-token:${{ env.OSDS_ACCESS_TOKEN }}@github.com/aws-actions/configure-aws-credentials.git
git add dist
git commit -m "chore: Update dist" || echo "No changes to commit"
git push --force origin
git push origin
-27
View File
@@ -1,27 +0,0 @@
name: pull-request-lint
on:
pull_request_target:
types:
- labeled
- opened
- synchronize
- reopened
- ready_for_review
- edited
jobs:
validate:
name: Validate PR title
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- uses: amannn/action-semantic-pull-request@v5.5.3
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
types: |-
feat
fix
chore
requireScope: false
-43
View File
@@ -1,43 +0,0 @@
---
name: Release Please
on:
push:
branches:
- main
permissions:
id-token: write
contents: write
pull-requests: write
jobs:
release-please:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: us-west-2
role-to-assume: ${{ secrets.SECRETS_AWS_PACKAGING_ROLE_TO_ASSUME }}
role-duration-seconds: 900
role-session-name: ${{ github.run_id }}
- name: Get git credentials
uses: aws-actions/aws-secretsmanager-get-secrets@v2
with:
parse-json-secrets: true
secret-ids: |
OSDS,arn:aws:secretsmanager:us-west-2:206735643321:secret:github-aws-sdk-osds-automation-gebs9n
- name: Run release-please
uses: googleapis/release-please-action@v4
with:
release-type: node
token: ${{ env.OSDS_ACCESS_TOKEN }}
config-file: release-please-config.json
manifest-file: .release-please-manifest.json
-112
View File
@@ -1,112 +0,0 @@
name: Run Integ tests
on:
workflow_dispatch:
jobs:
integ-oidc:
permissions:
contents: read
id-token: write
strategy:
fail-fast: false
matrix:
os: [[self-hosted, linux-fargate], windows-latest, ubuntu-latest, macos-latest]
name: Run OIDC integ tests
runs-on: ${{ matrix.os }}
timeout-minutes: 30
steps:
- name: "Checkout repository"
uses: actions/checkout@v4
- name: Integ test for OIDC
uses: ./
with:
aws-region: us-west-2
role-to-assume: ${{ secrets.SECRETS_OIDC_AWS_ROLE_TO_ASSUME }}
role-duration-seconds: 900
role-session-name: IntegOidcAssumeRole
role-external-id: ${{ secrets.SECRETS_OIDC_AWS_ROLE_EXTERNAL_ID }}
integ-oidc-env:
permissions:
contents: read
id-token: write
strategy:
fail-fast: false
matrix:
os: [[self-hosted, linux-fargate], windows-latest, ubuntu-latest, macos-latest]
name: Run OIDC integ tests with existing invalid env vars
runs-on: ${{ matrix.os }}
env:
AWS_ACCESS_KEY_ID: dummyaccesskeyid
AWS_SECRET_ACCESS_KEY: dummysecretkey
AWS_SESSION_TOKEN: dummytoken
timeout-minutes: 30
steps:
- name: "Checkout repository"
uses: actions/checkout@v4
- name: Integ test for OIDC
uses: ./
with:
aws-region: us-west-2
role-to-assume: ${{ secrets.SECRETS_OIDC_AWS_ROLE_TO_ASSUME }}
role-duration-seconds: 900
role-session-name: IntegOidcAssumeRole
role-external-id: ${{ secrets.SECRETS_OIDC_AWS_ROLE_EXTERNAL_ID }}
integ-access-keys:
strategy:
fail-fast: false
matrix:
os: [[self-hosted, linux-fargate], windows-latest, ubuntu-latest, macos-latest]
name: Run access key integ tests
runs-on: ${{ matrix.os }}
timeout-minutes: 30
steps:
- name: "Checkout repository"
uses: actions/checkout@v4
- name: Integ test for access keys
uses: ./
with:
aws-region: us-west-2
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
role-to-assume: ${{ secrets.SECRETS_AWS_ROLE_TO_ASSUME }}
role-session-name: IntegAccessKeysAssumeRole
role-external-id: ${{ secrets.SECRETS_AWS_ROLE_EXTERNAL_ID }}
integ-access-keys-env:
strategy:
fail-fast: false
matrix:
os: [[self-hosted, linux-fargate], windows-latest, ubuntu-latest, macos-latest]
name: Run access key from env integ tests
runs-on: ${{ matrix.os }}
timeout-minutes: 30
steps:
- name: "Checkout repository"
uses: actions/checkout@v4
- name: Integ test for access keys
uses: ./
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
with:
aws-region: us-west-2
role-to-assume: ${{ secrets.SECRETS_AWS_ROLE_TO_ASSUME }}
role-session-name: IntegAccessKeysAssumeRole
role-external-id: ${{ secrets.SECRETS_AWS_ROLE_EXTERNAL_ID }}
integ-iam-user:
strategy:
fail-fast: false
matrix:
os: [[self-hosted, linux-fargate], windows-latest, ubuntu-latest, macos-latest]
name: Run IAM User integ tests
runs-on: ${{ matrix.os }}
timeout-minutes: 30
steps:
- name: "Checkout repository"
uses: actions/checkout@v4
- name: Integ test for IAM user
uses: ./
with:
aws-region: us-west-2
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
-40
View File
@@ -1,40 +0,0 @@
on:
[pull_request]
name: Run unit tests
jobs:
unit-test:
strategy:
fail-fast: false
matrix:
os: [windows-latest, ubuntu-latest, macos-latest]
name: Run unit tests
runs-on: ${{ matrix.os }}
timeout-minutes: 5
steps:
- name: "Checkout repository"
uses: actions/checkout@v4
- name: "Setup node"
uses: actions/setup-node@v4
with:
node-version: 20
- name: "Install dependencies"
uses: bahmutov/npm-install@v1
- name: "Run tests"
run: npm run test --if-present
lint:
name: Ensure code standards
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: "Checkout repostiory"
uses: actions/checkout@v4
- name: "Setup node"
uses: actions/setup-node@v4
with:
node-version: 20
- name: "Install dependencies"
uses: bahmutov/npm-install@v1
- name: "Lint code"
run: npm run lint --if-present
+65 -5
View File
@@ -1,6 +1,66 @@
node_modules
node_modules/
# Editors
.vscode
.idea
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
.DS_Store
Thumbs.db
build
test-reports
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Other Dependency directories
jspm_packages/
# TypeScript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
# next.js build output
.next
+39
View File
@@ -0,0 +1,39 @@
queue_rules:
- name: default
conditions:
# Conditions to get out of the queue (= merged)
- status-success=Run Unit Tests
pull_request_rules:
- name: Automatically merge on CI success and review approval
conditions:
- base~=master|v1-node16|integ-tests
- "#approved-reviews-by>=1"
- -approved-reviews-by~=author
- status-success=Run Unit Tests
- label!=work-in-progress
- -title~=(WIP|wip)
- -merged
- -closed
- author!=dependabot[bot]
actions:
queue:
method: squash
name: default
- name: Automatically approve and merge Dependabot PRs
conditions:
- base~=master|v1-node16
- author=dependabot[bot]
- status-success=Run Unit Tests
- -title~=(WIP|wip)
- -label~=(blocked|do-not-merge)
- -merged
- -closed
actions:
review:
type: APPROVE
queue:
method: squash
name: default
-5
View File
@@ -1,5 +0,0 @@
{
".release-please-manifest.json": "4.0.2",
"package.json": "4.0.2",
".": "4.2.0"
}
-116
View File
@@ -2,122 +2,6 @@
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.
## [4.2.0](https://github.com/aws-actions/configure-aws-credentials/compare/v4.1.0...v4.2.0) (2025-05-06)
### Features
* add Expiration field to Outputs ([a4f3267](https://github.com/aws-actions/configure-aws-credentials/commit/a4f326760c1c1bf49ab86051c658d6501816b930))
* Document role-duration-seconds range ([5a0cf01](https://github.com/aws-actions/configure-aws-credentials/commit/5a0cf0167f837dfa7af7d951ba6a78a38dc2b79e))
* support action inputs as environment variables ([#1338](https://github.com/aws-actions/configure-aws-credentials/issues/1338)) ([2c168ad](https://github.com/aws-actions/configure-aws-credentials/commit/2c168adcae62d67531ba83842723c8f30695116a))
### Bug Fixes
* make sure action builds, also fix dependabot autoapprove ([c401b8a](https://github.com/aws-actions/configure-aws-credentials/commit/c401b8a98c5067672f52e0387cdd87d54acfe1fd))
* role chaning on mulitple runs ([#1340](https://github.com/aws-actions/configure-aws-credentials/issues/1340)) ([9e38641](https://github.com/aws-actions/configure-aws-credentials/commit/9e386419117a9edd458297e4f1822a5df7506a03))
## [4.1.0](https://github.com/aws-actions/configure-aws-credentials/compare/v4.0.3...v4.1.0) (2025-02-08)
### Features
* idempotent fetch ([#1289](https://github.com/aws-actions/configure-aws-credentials/issues/1289)) ([eb70354](https://github.com/aws-actions/configure-aws-credentials/commit/eb70354fb423a380b6e4ab4b9f15d2ee9ffae911))
### Bug Fixes
* build failure due to tests ([#1283](https://github.com/aws-actions/configure-aws-credentials/issues/1283)) ([134d71e](https://github.com/aws-actions/configure-aws-credentials/commit/134d71efe0ecbe9ad6965f2f766c0cae63a7685f))
* Dependabot autoapprove ([#1284](https://github.com/aws-actions/configure-aws-credentials/issues/1284)) ([b9ee51d](https://github.com/aws-actions/configure-aws-credentials/commit/b9ee51dc600fe38c892e24f60ca26476e0e0b6de))
* Dependabot autoapprove id-token write permission ([#1285](https://github.com/aws-actions/configure-aws-credentials/issues/1285)) ([f0af89b](https://github.com/aws-actions/configure-aws-credentials/commit/f0af89b102390dcf10ce402195d74a98f24861f3))
* typo ([#1281](https://github.com/aws-actions/configure-aws-credentials/issues/1281)) ([39fd91c](https://github.com/aws-actions/configure-aws-credentials/commit/39fd91c08ed8bf770034de4e62662503e8007d76))
## [4.0.3](https://github.com/aws-actions/configure-aws-credentials/compare/v4.0.2...v4.0.3) (2025-01-27)
### Features
* added release-please action config ([0f88004](https://github.com/aws-actions/configure-aws-credentials/commit/0f88004d9c27e0bdbbc254b3f7c8053cb38f04d7))
### Bug Fixes
* add id-token permission to automerge ([97834a4](https://github.com/aws-actions/configure-aws-credentials/commit/97834a484a5ab3c40fa9e2eb40fcf8041105a573))
* cpy syntax on npm package ([#1195](https://github.com/aws-actions/configure-aws-credentials/issues/1195)) ([83b5a56](https://github.com/aws-actions/configure-aws-credentials/commit/83b5a565471214aec459e234bef606339fe07111))
* force push packaged files to main ([bfd2185](https://github.com/aws-actions/configure-aws-credentials/commit/bfd218503eb87938c29603a551e19c6b594f5fe5))
### Miscellaneous Chores
* release 4.0.3 ([ca00fd4](https://github.com/aws-actions/configure-aws-credentials/commit/ca00fd4d3842ad58c3c21ebfe69defa1f0e7bdc4))
## [4.0.2](https://github.com/aws-actions/configure-aws-credentials/compare/v4.0.1...v4.0.2) (2024-02-09)
* Revert 4.0.1 to remove warning
## [4.0.1](https://github.com/aws-actions/configure-aws-credentials/compare/v4.0.0...v4.0.1) (2023-10-03)
### Documentation
* Throw a warning when customers use long-term credentials.
## [4.0.0](https://github.com/aws-actions/configure-aws-credentials/compare/v3.0.2...v4.0.0) (2023-09-11)
* Upgraded runtime to `node20` from `node16`
## [3.0.2](https://github.com/aws-actions/configure-aws-credentials/compare/v3.0.1...v3.0.2) (2023-09-07)
### Bug Fixes
* fixes #817 #819: validation logic throwing unwanted errors [d78f55b](https://github.com/aws-actions/configure-aws-credentials/commit/d78f55b1db65186cb251a8504ae9527af06fc5fd)
## [3.0.1](https://github.com/aws-actions/configure-aws-credentials/compare/v3.0.0...v3.0.1) (2023-08-24)
### Features
* Can configure `special-characters-workaround` to keep retrying credentials if the returned
credentials have special characters (Fixes #599)
### Bug Fixes
* Fixes #792: Action fails when intending to use existing credentials
* Minor typo fix from @ubaid-ansari21
### Changes to existing functionality
* Special characters are now allowed in returned credential variables unless you configure the
`special-characters-workaround` option
## [3.0.0](https://github.com/aws-actions/configure-aws-credentials/compare/v2.2.0...v3.0.0) (2023-08-21)
### Features
* Can configure `max-retries` and `disable-retry` to modify retry functionality when the assume role call fails
* Set returned credentials as step outputs with `output-credentials`
* Clear AWS related environment variables at the start of the action with `unset-current-credentials`
* Unique role identifier is now printed in the workflow logs
### Bug Fixes
* Can't use credentials if they contain a special character
* Retry functionality added when generating the JWT fails
* Can now use `webIdentityTokenFile` option
* Branch name validation too strict
* JS SDK v2 deprecation warning in workflow logs
### Changes to existing functionality
* Default session duration is now 1 hour in all cases (from 6 hours in some cases)
* Account ID will not be masked by default in logs
## [2.2.0](https://github.com/aws-actions/configure-aws-credentials/compare/v2.1.0...v2.2.0) (2023-05-31)
### Features
* `inline-session-policy` prop enables assuming a role with inline session policies ([d00f6c6](https://github.com/aws-actions/configure-aws-credentials/commit/d00f6c6f41fde02a9fd0d469040be6ed0df69e73))
* `managed-session-policies` prop enables assuming a role with managed policy arns ([d00f6c6](https://github.com/aws-actions/configure-aws-credentials/commit/d00f6c6f41fde02a9fd0d469040be6ed0df69e73))
## [2.1.0](https://github.com/aws-actions/configure-aws-credentials/compare/v2.0.0...v2.1.0) (2023-05-31)
### Features
* `role-chaining` prop enables role chaining use case ([6fbd316](https://github.com/aws-actions/configure-aws-credentials/commit/6fbd316fd15f52c3d9f68e7aa06eae4f5699a518))
## [2.0.0](https://github.com/aws-actions/configure-aws-credentials/compare/v1.7.0...v2.0.0) (2023-03-06)
### Features
* Version bump to use Node 16 by default.
## [1.7.0](https://github.com/aws-actions/configure-aws-credentials/compare/v1.6.1...v1.7.0) (2022-08-03)
+2 -2
View File
@@ -23,7 +23,7 @@ reported the issue. Please try to include as much information as you can. Detail
## Contributing via Pull Requests
Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that:
1. You are working against the latest source on the *main* branch.
1. You are working against the latest source on the *master* branch.
2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already.
3. You open an issue to discuss any significant work - we would hate for your time to be wasted.
@@ -56,6 +56,6 @@ If you discover a potential security issue in this project we ask that you notif
## Licensing
See the [LICENSE](https://github.com/aws-actions/configure-aws-credentials/blob/main/LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution.
See the [LICENSE](https://github.com/aws-actions/configure-aws-credentials/blob/master/LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution.
We may ask you to sign a [Contributor License Agreement (CLA)](http://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes.
+3 -1
View File
@@ -1,4 +1,6 @@
Copyright (c) 2019-2022 Amazon.com, Inc. or its affiliates
MIT License
Copyright 2019 Amazon.com, Inc. or its affiliates.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+160 -460
View File
@@ -1,336 +1,154 @@
## Configure AWS Credentials for GitHub Actions
Configure your AWS credentials and region environment variables for use in other
GitHub Actions.
## "Configure AWS Credentials" Action For GitHub Actions
This action implements the AWS JavaScript SDK credential resolution chain
and exports session environment variables for your other Actions to use.
Environment variable exports are detected by both the AWS SDKs and the AWS CLI
for AWS API calls.
Configure AWS credential and region environment variables for use in other GitHub Actions. The environment variables will be detected by both the AWS SDKs and the AWS CLI to determine the credentials and region to use for AWS API calls.
## Overview
API calls to AWS need to be signed with credential information, so when you use
one of the AWS SDKs or an AWS tool, you must provide it with AWS credentials and
and AWS region. One way to do that in GitHub Actions is to use a repository
secret with IAM credentials, but this doesn't follow [AWS security
guidelines](https://docs.aws.amazon.com/IAM/latest/UserGuide/security-creds.html)
on using long term credentials. Instead, we recommend that you use a long term
credential or JWT to fetch a temporary credential, and use that with your tools
instead. This GitHub Action facilitates just that.
## NOTICE: node12 deprecation warning
GitHub actions has recently started throwing warning messages regarding the deprecation of Node 12. If you would like to stop seeing this warning, configure your action to use `aws-actions/configure-aws-credentials@v1-node16`. Both the `v1` branch and the `v1-node16` branch will receive the same updates moving forward. See [this issue](https://github.com/aws-actions/configure-aws-credentials/issues/489) for more information on this topic.
AWS SDKs and Tools look for your credentials in standardized environment
variables. In essence, this Action runs through the standard [credential
resolution flow](https://docs.aws.amazon.com/sdkref/latest/guide/standardized-credentials.html),
and at the end, exports environment variables for you to use later.
**Table of Contents**
We support five methods for fetching credentials from AWS, but we recommend that
you use GitHub's OIDC provider in conjunction with a configured AWS IAM
Identity Provider endpoint.
<!-- toc -->
For more information on how to do that, read on.
- [Usage](#usage)
- [Credentials](#credentials)
- [Assuming a Role](#assuming-a-role)
+ [Session tagging](#session-tagging)
+ [Sample IAM Role Permissions](#sample-iam-role-cloudformation-template)
- [Self-Hosted Runners](#self-hosted-runners)
- [License Summary](#license-summary)
- [Security Disclosures](#security-disclosures)
### Note about GHES
<!-- tocstop -->
Some of this documentation may be inaccurate if you are using GHES (GitHub
Enterprise Server), please take note to review the GitHub documentation when
relevant.
## Usage
For example, the URL that the OIDC JWT is issued from is different than the
usual `token.actions.githubusercontent.com`, and will be unique to your
enterprise server. As a result, you will need to configure this differently when
you create the Identity Provider.
Add the following step to your workflow:
We do not presently have a GHES testing environment to validate this action. If
you are running in GHES and encounter problems, please
[let us know](https://github.com/aws-actions/configure-aws-credentials/issues/new/choose).
## Security recommendations
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.
* [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.
Do not assume overly permissive roles, even for testing.
* [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.
* Use temporary credentials when possible.
* Periodically rotate any long-term credentials you use.
## Using this action
There are five different supported ways to retrieve credentials:
- Using GitHub's OIDC provider (`AssumeRoleWithWebIdentity`)
- Proceeding as an IAM user (No STS call is made)
- Using access keys as action input (`AssumeRole`)
- Using a WebIdentity Token File (`AssumeRoleWithWebIdentity`)
- Using existing credentials in your runner (`AssumeRole`)
Because we use the AWS JavaScript SDK, we always will use the [credential
resolution flow for Node.js](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/setting-credentials-node.html).
Depending on your inputs, the action might override parts of this flow.
We recommend using the first option above: [GitHub's OIDC provider](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services).
This method uses OIDC to get short-lived credentials needed for your actions.
See [OIDC](#OIDC) for more information on how to setup your AWS account to
assume a role with OIDC.
The following table describes which method we'll use to get your credentials
based on which values are supplied to the Action:
| **Identity Used** | `aws-access-key-id` | `role-to-assume` | `web-identity-token-file` | `role-chaining` | `id-token` permission
| --------------------------------------------------------------- | ------------------- | ---------------- | ------------------------- | - | - |
| [✅ Recommended] Assume Role directly using GitHub OIDC provider | | ✔ | | | ✔ |
| IAM User | ✔ | | | | |
| Assume Role using IAM User credentials | ✔ | ✔ | | | |
| Assume Role using WebIdentity Token File credentials | | ✔ | ✔ | | |
| Assume Role using existing credentials | | ✔ | | ✔ | |
*Note: `role-chaining` is not always necessary to use existing credentials.
If you're getting a "Credentials loaded by the SDK do not match" error,
try enabling this option.*
### Options
See [action.yml](./action.yml) for more detail.
| Option | Description | Required |
|---------------------------|---------------------------------------------------------------------------------------------------|----------|
| aws-region | Which AWS region to use | Yes |
| role-to-assume | Role for which to fetch credentials. Only required for some authentication types. | No |
| aws-access-key-id | AWS access key to use. Only required for some authentication types. | No |
| aws-secret-access-key | AWS secret key to use. Only required for some authentication types. | No |
| aws-session-token | AWS session token to use. Used in uncommon authentication scenarios. | No |
| role-chaining | Use existing credentials from the environment to assume a new role. | No |
| audience | The JWT audience when using OIDC. Used in non-default AWS partitions, like China regions. | No |
| http-proxy | An HTTP proxy to use for API calls. | No |
| mask-aws-account-id | AWS account IDs are not considered secret. Setting this will hide account IDs from output anyway. | No |
| role-duration-seconds | The assumed role duration in seconds, if assuming a role. Defaults to 1 hour (3600 seconds). Acceptable values range from 15 minutes (900 seconds) to 12 hours (43200 seconds). | No |
| role-external-id | The external ID of the role to assume. Only needed if your role requires it. | No |
| role-session-name | Defaults to "GitHubActions", but may be changed if required. | No |
| role-skip-session-tagging | Skips session tagging if set. | No |
| inline-session-policy | You may further restrict the assumed role policy by defining an inline policy here. | No |
| managed-session-policies | You may further restrict the assumed role policy by specifying a managed policy here. | No |
| output-credentials | When set, outputs fetched credentials as action step output. (Outputs access-key-id, secret-access-key, session-token, and expiration). Defaults to false. | No |
| unset-current-credentials | When set, attempts to unset any existing credentials in your action runner. | No |
| disable-retry | Disabled retry/backoff logic for assume role calls. By default, retries are enabled. | No |
| retry-max-attempts | Limits the number of retry attempts before giving up. Defaults to 12. | No |
| special-characters-workaround | Uncommonly, some environments cannot tolerate special characters in a secret key. This option will retry fetching credentials until the secret access key does not contain special characters. This option overrides disable-retry and retry-max-attempts. | No |
| use-existing-credentials | When set, the action will check if existing credentials are valid and exit if they are. Defaults to false. | No |
#### Credential Lifetime
The default session duration is **1 hour**.
If you would like to adjust this you can pass a duration to
`role-duration-seconds`, but the duration cannot exceed the maximum that was
defined when the IAM Role was created.
#### External ID
If your role requires an external ID to assume, you can provide the external ID
with the `role-external-id` input
#### Session tagging and name
The default session name is "GitHubActions", and you can modify it by specifying
the desired name in `role-session-name`.
_Note: you might find it helpful to set the `role-session-name` to `${{ github.run_id }}`
so as to clarify in audit logs which AWS actions were performed by which workflow
run._
The session will be tagged with the
following tags: (Refer to [GitHub's documentation for `GITHUB_` environment
variable definitions](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 tag 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 '*'._
The action will use session tagging by default during role assumption, unless
you follow our recommendation and are assuming a role with a WebIdentity. For
WebIdentity role assumption, the session tags have to be included in the encoded
WebIdentity token. This means that tags can only be supplied by the OIDC
provider, and they cannot set during the AssumeRoleWithWebIdentity API call
within the Action. See [#419](https://github.com/aws-actions/configure-aws-credentials/issues/419)
for more information.
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@v4
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v1
with:
role-skip-session-tagging: true
role-to-assume: arn:aws:iam::123456789100:role/my-github-actions-role
aws-region: us-east-2
```
### Session policies
Session policies are not required, but they allow you to limit the scope of the
fetched credentials without making changes to IAM roles. You can specify inline
session policies right in your workflow file, or refer to an existing managed
session policy by its ARN.
#### Inline session policies
An IAM policy in stringified JSON format that you want to use as an inline
session policy. Depending on preferences, the JSON could be written on a single
line like this:
```yaml
uses: aws-actions/configure-aws-credentials@v4
with:
inline-session-policy: '{"Version":"2012-10-17","Statement":[{"Sid":"Stmt1","Effect":"Allow","Action":"s3:List*","Resource":"*"}]}'
```
Or we can have a nicely formatted JSON as well:
```yaml
uses: aws-actions/configure-aws-credentials@v4.1.0
with:
inline-session-policy: >-
{
"Version": "2012-10-17",
"Statement": [
{
"Sid":"Stmt1",
"Effect":"Allow",
"Action":"s3:List*",
"Resource":"*"
}
]
}
```
#### Managed session policies
The Amazon Resource Names (ARNs) of the IAM managed policies that you want to
use as managed session policies. The policies must exist in the same account as
the role. You can pass a single managed policy like this:
```yaml
uses: aws-actions/configure-aws-credentials@v4.1.0
with:
managed-session-policies: arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
```
And we can pass multiple managed policies likes this:
```yaml
uses: aws-actions/configure-aws-credentials@v4.1.0
with:
managed-session-policies: |
arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
arn:aws:iam::aws:policy/AmazonS3OutpostsReadOnlyAccess
```
### Misc
#### Adjust the retry mechanism
You can now configure retry settings for when the STS call fails. By default, we
retry with exponential backoff `12` times. You can disable this behavior
altogether by setting the `disable-retry` input to `true`, or you can configure
the number of times it retries with the `retry-max-attempts` input.
#### Mask account ID
Your account ID is not masked by default in workflow logs since it's not
considered sensitive information. However, you can set the `mask-aws-account-id`
input to `true` to mask your account ID in workflow logs if desired.
#### Unset current credentials
Sometimes, existing credentials in your runner can get in the way of the
intended outcome. You can set the `unset-current-credentials` input to `true` to
work around this issue.
#### Special characters in AWS_SECRET_ACCESS_KEY
Some edge cases are unable to properly parse an `AWS_SECRET_ACCESS_KEY` if it
contains special characters. For more information, please see the
[AWS CLI documentation](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-troubleshooting.html#tshoot-signature-does-not-match).
If you set the `special-characters-workaround` option, this action will
continually retry fetching credentials until we get one that does not have
special characters. This option overrides the `disable-retry` and
`retry-max-attempts` options. We recommend that you do not enable this option
unless required, because retrying APIs infinitely until they succeed is not best
practice.
## OIDC
We recommend using [GitHub's OIDC
provider](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services)
to get short-lived AWS credentials needed for your actions. When using OIDC, you
configure IAM to accept JWTs from GitHub's OIDC endpoint. This action will
then create a JWT unique to the workflow run using the OIDC endpoint, and it
will use the JWT to assume the specified role with short-term credentials.
To get this to work
1. Configure your workflow to use the `id-token: write` permission.
2. Configure your audience, if required.
3. In your AWS account, configure IAM to trust GitHub's OIDC identity provider.
4. Configure an IAM role with appropriate claim limits and permission scope.
*Note*: Naming your role "GitHubActions" has been reported to not work. See
[#953](https://github.com/aws-actions/configure-aws-credentials/issues/953).
5. Specify that role's ARN when setting up this action.
First, in order for this action to create the JWT, your workflow file must have
the `id-token: write` permission:
For example, you can use this action with the AWS CLI available in [GitHub's hosted virtual environments](https://help.github.com/en/actions/reference/software-installed-on-github-hosted-runners).
You can also run this action multiple times to use different AWS accounts, regions, or IAM roles in the same GitHub Actions workflow job.
```yaml
jobs:
deploy:
name: Upload to Amazon S3
runs-on: ubuntu-latest
# These permissions are needed to interact with GitHub's OIDC Token endpoint.
permissions:
id-token: write
contents: read
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Configure AWS credentials from Test account
uses: aws-actions/configure-aws-credentials@v1
with:
role-to-assume: arn:aws:iam::111111111111:role/my-github-actions-role-test
aws-region: us-east-1
- name: Copy files to the test website with the AWS CLI
run: |
aws s3 sync . s3://my-s3-test-website-bucket
- name: Configure AWS credentials from Production account
uses: aws-actions/configure-aws-credentials@v1
with:
role-to-assume: arn:aws:iam::222222222222:role/my-github-actions-role-prod
aws-region: us-west-2
- name: Copy files to the production website with the AWS CLI
run: |
aws s3 sync . s3://my-s3-prod-website-bucket
```
### OIDC Audience
See [action.yml](action.yml) for the full documentation for this action's inputs and outputs.
When the JWT is created, an audience needs to be specified. Normally, you would
use `sts.amazonaws.com`, and this action uses this by default if you don't
specify one. This will work for most cases. Changing the default audience may
be necessary when using non-default AWS partitions, such as China regions.
You can specify the audience through the `audience` input:
## 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.
* [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.
* [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
We recommend using [GitHub's OIDC provider](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services) to get short-lived credentials needed for your actions.
Specifying `role-to-assume` **without** providing an `aws-access-key-id` or a `web-identity-token-file` will signal to the action that you wish to use the OIDC provider.
The default session duration is **1 hour** when using the OIDC provider to directly assume an IAM Role or when an `aws-session-token` is directly provided.
The default session duration is **6 hours** when using an IAM User to assume an IAM Role (by providing an `aws-access-key-id`, `aws-secret-access-key`, and a `role-to-assume`) .
If you would like to adjust this you can pass a duration to `role-duration-seconds`, but the duration cannot exceed the maximum that was defined when the IAM Role was created.
The default session name is GitHubActions, and you can modify it by specifying the desired name in `role-session-name`.
The default audience is `sts.amazonaws.com` which you can replace by specifying the desired audience name in `audience`.
The following table describes which identity is used based on which values are supplied to the Action:
| **Identity Used** | `aws-access-key-id` | `role-to-assume` | `web-identity-token-file` |
|------------------------------------------------------------------|---------------------|------------------|---------------------------|
| [✅ Recommended] Assume Role directly using GitHub OIDC provider | | ✔ | |
| IAM User | ✔ | | |
| Assume Role using IAM User credentials | ✔ | ✔ | |
| Assume Role using WebIdentity Token File credentials | | ✔ | ✔ |
### Examples
```yaml
- name: Configure AWS Credentials for China region audience
uses: aws-actions/configure-aws-credentials@v4.1.0
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v1
with:
audience: sts.amazonaws.com.cn
aws-region: us-east-3
role-to-assume: arn:aws-cn:iam::123456789100:role/my-github-actions-role
aws-region: us-east-2
role-to-assume: arn:aws:iam::123456789100:role/my-github-actions-role
role-session-name: MySessionName
```
In this example, the Action will load the OIDC token from the GitHub-provided environment variable and use it to assume the role `arn:aws:iam::123456789100:role/my-github-actions-role` with the session name `MySessionName`.
### Configuring IAM to trust GitHub
To use GitHub's OIDC provider, you must first set up federation
with the provider as an IAM IdP. The GitHub OIDC provider only needs to be
created once per account (i.e. multiple IAM Roles that can be assumed by the
GitHub's OIDC can share a single OIDC Provider). Here is a sample CloudFormation
template that will configure this trust for you.
```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: ${{ secrets.AWS_ROLE_TO_ASSUME }}
role-external-id: ${{ secrets.AWS_ROLE_EXTERNAL_ID }}
role-duration-seconds: 1200
role-session-name: MySessionName
```
In this example, the secret `AWS_ROLE_TO_ASSUME` contains a string like `arn:aws:iam::123456789100:role/my-github-actions-role`. To assume a role in the same account as the static credentials, you can simply specify the role name, like `role-to-assume: my-github-actions-role`.
Note that the thumbprint below has been set to all F's because the thumbprint is
not used when authenticating `token.actions.githubusercontent.com`. This is a
special case used *only when GitHub's OIDC is authenticating to IAM*. IAM uses
its library of trusted CAs to authenticate. The value is still the API, so it
must be specified.
```yaml
- name: Configure AWS Credentials for Beta Customers
uses: aws-actions/configure-aws-credentials@v1
with:
audience: beta-customers
aws-region: us-east-3
role-to-assume: arn:aws:iam::123456789100:role/my-github-actions-role
role-session-name: MySessionName
```
In this example, the audience has been changed from the default to use a different audience name `beta-customers`. This can help ensure that the role can only affect those AWS accounts whose GitHub OIDC providers have explicitly opted in to the `beta-customers` label.
You can copy the template below, or load it from here:
https://d38mtn6aq9zhn6.cloudfront.net/configure-aws-credentials-latest.yml
Changing the default audience may be necessary when using non-default [AWS partitions](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html).
### Sample IAM Role CloudFormation Template
```yaml
Parameters:
GitHubOrg:
Description: Name of GitHub organization/user (case sensitive)
Type: String
RepositoryName:
Description: Name of GitHub repository (case sensitive)
Type: String
OIDCProviderArn:
Description: Arn for the GitHub OIDC Provider.
Default: ""
Type: String
OIDCAudience:
Description: Audience supplied to configure-aws-credentials.
Default: "sts.amazonaws.com"
Type: String
Conditions:
CreateOIDCProvider: !Equals
@@ -351,8 +169,6 @@ Resources:
- !Ref GithubOidc
- !Ref OIDCProviderArn
Condition:
StringEquals:
token.actions.githubusercontent.com:aud: !Ref OIDCAudience
StringLike:
token.actions.githubusercontent.com:sub: !Sub repo:${GitHubOrg}/${RepositoryName}:*
@@ -364,43 +180,16 @@ Resources:
ClientIdList:
- sts.amazonaws.com
ThumbprintList:
- ffffffffffffffffffffffffffffffffffffffff
- 6938fd4d98bab03faadb97b34396831e3780aea1
Outputs:
Role:
Value: !GetAtt Role.Arn
```
### Claims and scoping permissions
To align with the Amazon IAM best practice of [granting least
privilege](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege),
the assume role policy document should contain a
[`Condition`](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_condition.html)
that specifies a subject (`sub`) allowed to assume the role. [GitHub also
recommends](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect#defining-trust-conditions-on-cloud-roles-using-oidc-claims)
filtering for the correct audience (`aud`). See [AWS IAM
documentation](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_iam-condition-keys.html#condition-keys-wif)
on which claims you can filter for in your trust policies.
The GitHub OIDC Provider only needs to be created once per account (i.e. multiple IAM Roles that can be assumed by the GitHub's OIDC can share a single OIDC Provider).
Without a subject (`sub`) condition, any GitHub user or repository could
potentially assume the role. The subject can be scoped to a GitHub organization
and repository as shown in the CloudFormation template. However, scoping it down
to your org and repo may cause the role assumption to fail in some cases. See
[Example subject claims](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect#example-subject-claims)
for specific details on what the subject value will be depending on your
workflow. You can also [customize your subject claim](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect#customizing-the-token-claims)
if you want full control over the information you can filter for in your trust
policy. If you aren't sure what your subject (`sub`) key is, you can add the
[`actions-oidc-debugger`](https://github.com/github/actions-oidc-debugger)
action to your workflow to see the value of the subject (`sub`) key, as well as
other claims.
Additional claim conditions can be added for higher specificity as explained in
the [GitHub documentation](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect).
Due to implementation details, not every OIDC claim is presently supported by
IAM.
### Further information about OIDC
To align with the Amazon IAM best practice of [granting least privilege](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege), the assume role policy document should contain a [`Condition`](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_condition.html) that specifies a subject allowed to assume the role. Without a subject condition, any GitHub user or repository could potentially assume the role. The subject can be scoped to a GitHub organization and repository as shown in the CloudFormation template. Additional claim conditions can be added for higher specificity as explained in the [GitHub docs](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect).
For further information on OIDC and GitHub Actions, please see:
@@ -410,166 +199,77 @@ For further information on OIDC and GitHub Actions, please see:
* [GitHub docs: Configuring OpenID Connect in Amazon Web Services](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services)
* [GitHub changelog: GitHub Actions: Secure cloud deployments with OpenID Connect](https://github.blog/changelog/2021-10-27-github-actions-secure-cloud-deployments-with-openid-connect/)
### 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 characters, the characters will be replaced with an '*'._
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.
This means that Tags can only be supplied by the OIDC provider and not set during the AssumeRoleWithWebIdentity API call within the Action.
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. We will use the standard AWS JavaScript SDK credential
resolution methods to find your credentials, so if the AWS JS SDK can
authenticate on your runner, this Action will as well.
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.
If no access key credentials are given in the action inputs, this action will
use credentials from the runner environment using the
[default methods for the AWS SDK for Javascript](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/setting-credentials-node.html).
If no access key credentials are given in the action inputs, this action will use credentials from the runner environment using the [default methods for the AWS SDK for Javascript](https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/setting-credentials-node.html).
You can use this action to simply configure the region and account ID in the
environment, and then use the runner's credentials for all AWS API calls made by
your Actions workflow:
You can use this action to simply configure the region and account ID in the environment, and then use the runner's credentials for all AWS API calls made by your Actions workflow:
```yaml
uses: aws-actions/configure-aws-credentials@v4.1.0
uses: aws-actions/configure-aws-credentials@v1
with:
aws-region: us-east-2
```
In this case, your runner's credentials must have permissions to call any AWS
APIs called by your Actions workflow.
In this case, your runner's credentials must have permissions to call any AWS APIs called by your Actions workflow.
Or, you can use this action to assume a role, and then use the role credentials
for all AWS API calls made by your Actions workflow:
Or, you can use this action to assume a role, and then use the role credentials for all AWS API calls made by your Actions workflow:
```yaml
uses: aws-actions/configure-aws-credentials@v4.1.0
uses: aws-actions/configure-aws-credentials@v1
with:
aws-region: us-east-2
role-to-assume: my-github-actions-role
```
In this case, your runner's credentials must have permissions to assume the
role.
In this case, your runner's credentials must have permissions to assume the role.
You can also assume a role using a web identity token file, such as if using
[Amazon EKS IRSA](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts-technical-overview.html). Pods running in EKS
worker nodes that do not run as root can use this file to assume a role with a
web identity.
You can also assume a role using a web identity token file, such as if using [Amazon EKS IRSA](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts-technical-overview.html).
Pods running in EKS worker nodes that do not run as root can use this file to assume a role with a web identity.
### Proxy Configuration
If need use a HTTP proxy you can set it in the action manually.
Additionally this action will always consider the `HTTP_PROXY` environment
variable.
Manually configured proxy:
You can configure your workflow as follows in order to use this file:
```yaml
uses: aws-actions/configure-aws-credentials@v4.1.0
uses: aws-actions/configure-aws-credentials@v1
with:
aws-region: us-east-2
role-to-assume: my-github-actions-role
http-proxy: "http://companydomain.com:3128"
```
Proxy configured in the environment variable:
```bash
# Your environment configuration
HTTP_PROXY="http://companydomain.com:3128"
web-identity-token-file: /var/run/secrets/eks.amazonaws.com/serviceaccount/token
```
### Use with the AWS CLI
This workflow does _not_ install the [AWS CLI](https://aws.amazon.com/cli/)
into your environment. Self-hosted runners that intend to run this action prior
to executing `aws` commands need to have the AWS CLI
[installed](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html)
if it's not already present.
Most [GitHub hosted runner environments](https://github.com/actions/virtual-environments)
should include the AWS CLI by default.
## Examples
### AssumeRoleWithWebIdentity (recommended)
```yaml
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4.1.0
with:
aws-region: us-east-2
role-to-assume: arn:aws:iam::123456789100:role/my-github-actions-role
role-session-name: MySessionName
```
In this example, the Action will load the OIDC token from the GitHub-provided
environment variable and use it to assume the role
`arn:aws:iam::123456789100:role/my-github-actions-role` with the session name
`MySessionName`.
### AssumeRole with role previously assumed by action in same workflow
```yaml
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4.1.0
with:
aws-region: us-east-2
role-to-assume: arn:aws:iam::123456789100:role/my-github-actions-role
role-session-name: MySessionName
- name: Configure other AWS Credentials
uses: aws-actions/configure-aws-credentials@v4.1.0
with:
aws-region: us-east-2
role-to-assume: arn:aws:iam::987654321000:role/my-second-role
role-session-name: MySessionName
role-chaining: true
```
In this two-step example, the first step will use OIDC to assume the role
`arn:aws:iam::123456789100:role/my-github-actions-role` just as in the prior
example. Following that, a second step will use this role to assume a different
role, `arn:aws:iam::987654321000:role/my-second-role`.
### AssumeRole with static IAM credentials in repository secrets
```yaml
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4.1.0
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: ${{ secrets.AWS_ROLE_TO_ASSUME }}
role-external-id: ${{ secrets.AWS_ROLE_EXTERNAL_ID }}
role-duration-seconds: 1200
role-session-name: MySessionName
```
In this example, the secret `AWS_ROLE_TO_ASSUME` contains a string like
`arn:aws:iam::123456789100:role/my-github-actions-role`. To assume a role in
the same account as the static credentials, you can simply specify the role
name, like `role-to-assume: my-github-actions-role`.
### Retrieving credentials from step output, AssumeRole with temporary credentials
```yaml
- name: Configure AWS Credentials 1
id: creds
uses: aws-actions/configure-aws-credentials@v4.1.0
with:
aws-region: us-east-2
role-to-assume: arn:aws:iam::123456789100:role/my-github-actions-role
output-credentials: true
- name: get caller identity 1
run: |
aws sts get-caller-identity
- name: Configure AWS Credentials 2
uses: aws-actions/configure-aws-credentials@v4.1.0
with:
aws-region: us-east-2
aws-access-key-id: ${{ steps.creds.outputs.aws-access-key-id }}
aws-secret-access-key: ${{ steps.creds.outputs.aws-secret-access-key }}
aws-session-token: ${{ steps.creds.outputs.aws-session-token }}
role-to-assume: arn:aws:iam::123456789100:role/my-other-github-actions-role
- name: get caller identity2
run: |
aws sts get-caller-identity
```
This example shows that you can reference the fetched credentials as outputs if
`output-credentials` is set to true. This example also shows that you can use
the `aws-session-token` input in a situation where session tokens are fetched
and passed to this action.
This workflow does _not_ install the [AWS CLI](https://aws.amazon.com/cli/) into your environment. Self-hosted runners that intend to run this action prior to executing `aws` commands need to have the AWS CLI [installed](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html) if it's not already present.
Most [GitHub hosted runner environments](https://github.com/actions/virtual-environments) should include the AWS CLI by default.
## License Summary
This code is made available under the MIT license.
## Security Disclosures
If you would like to report a potential security issue in this project, please
do not create a GitHub issue. Instead, please follow the instructions
[here](https://aws.amazon.com/security/vulnerability-reporting/) or [email AWS
security directly](mailto:aws-security@amazon.com).
If you would like to report a potential security issue in this project, please do not create a GitHub issue. Instead, please follow the instructions [here](https://aws.amazon.com/security/vulnerability-reporting/) or [email AWS security directly](mailto:aws-security@amazon.com).
+215 -11446
View File
File diff suppressed because it is too large Load Diff
-2
View File
@@ -1,2 +0,0 @@
const { fs } = require('memfs')
module.exports = fs
+45 -67
View File
@@ -1,86 +1,64 @@
name: '"Configure AWS Credentials" Action for GitHub Actions'
description: Configures AWS credentials for use in subsequent steps in a GitHub Action workflow
runs:
using: node20
main: dist/index.js
post: dist/cleanup/index.js
name: '"Configure AWS Credentials" Action For GitHub Actions'
description: 'Configure AWS credential and region environment variables for use with the AWS CLI and AWS SDKs'
branding:
color: orange
icon: cloud
icon: 'cloud'
color: 'orange'
inputs:
aws-region:
description: AWS Region, e.g. us-east-2
required: true
role-to-assume:
description: The Amazon Resource Name (ARN) of the role to assume. Use the provided credentials to assume an IAM role and configure the Actions environment with the assumed role credentials rather than with the provided credentials.
audience:
default: 'sts.amazonaws.com'
description: 'The audience to use for the OIDC provider'
required: false
aws-access-key-id:
description: AWS Access Key ID. Provide this key if you want to assume a role using access keys rather than a web identity token.
description: >-
AWS Access Key ID. This input is required if running in the GitHub hosted environment.
It is optional if running in a self-hosted environment that already has AWS credentials,
for example on an EC2 instance.
required: false
aws-secret-access-key:
description: AWS Secret Access Key. Required if aws-access-key-id is provided.
description: >-
AWS Secret Access Key. This input is required if running in the GitHub hosted environment.
It is optional if running in a self-hosted environment that already has AWS credentials,
for example on an EC2 instance.
required: false
aws-session-token:
description: AWS Session Token.
description: 'AWS Session Token'
required: false
aws-region:
description: 'AWS Region, e.g. us-east-2'
required: true
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 an IAM role and configure the Actions
environment with the assumed role credentials rather than with the provided
credentials
required: false
web-identity-token-file:
description: Use the web identity token file from the provided file system path in order to assume an IAM role using a web identity, e.g. from within an Amazon EKS worker node.
required: false
role-chaining:
description: Use existing credentials from the environment to assume a new role, rather than providing credentials as input.
required: false
audience:
description: The audience to use for the OIDC provider
required: false
default: sts.amazonaws.com
http-proxy:
description: Proxy to use for the AWS SDK agent
required: false
mask-aws-account-id:
description: Whether to mask the AWS account ID for these credentials as a secret value. By default the account ID will not be masked
description: >-
Use the web identity token file from the provided file system path in order to
assume an IAM role using a web identity. E.g., from within an Amazon EKS worker node
required: false
role-duration-seconds:
description: Role duration in seconds. Default is one hour.
required: false
role-external-id:
description: The external ID of the role to assume.
description: "Role duration in seconds (default: 6 hours, 1 hour for OIDC/specified aws-session-token)"
required: false
role-session-name:
description: "Role session name (default: GitHubActions)"
description: 'Role session name (default: GitHubActions)'
required: false
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
description: 'Skip session tagging during role assumption'
required: false
inline-session-policy:
description: Define an inline session policy to use when assuming a role
required: false
managed-session-policies:
description: Define a list of managed session policies to use when assuming a role
required: false
output-credentials:
description: Whether to set credentials as step output
required: false
unset-current-credentials:
description: Whether to unset the existing credentials in your runner. May be useful if you run this action multiple times in the same job
required: false
disable-retry:
description: Whether to disable the retry and backoff mechanism when the assume role call fails. By default the retry mechanism is enabled
required: false
retry-max-attempts:
description: The maximum number of attempts it will attempt to retry the assume role call. By default it will retry 12 times
required: false
special-characters-workaround:
description: Some environments do not support special characters in AWS_SECRET_ACCESS_KEY. This option will retry fetching credentials until the secret access key does not contain special characters. This option overrides disable-retry and retry-max-attempts. This option is disabled by default
required: false
use-existing-credentials:
description: When enabled, this option will check if there are already valid credentials in the environment. If there are, new credentials will not be fetched. If there are not, the action will run as normal.
outputs:
aws-account-id:
description: The AWS account ID for the provided credentials
aws-access-key-id:
description: The AWS access key ID for the provided credentials
aws-secret-access-key:
description: The AWS secret access key for the provided credentials
aws-session-token:
description: The AWS session token for the provided credentials
description: 'The AWS account ID for the provided credentials'
runs:
using: 'node16'
main: 'dist/index.js'
post: 'dist/cleanup/index.js'
-34
View File
@@ -1,34 +0,0 @@
{
"formatter": {
"indentStyle": "space",
"lineWidth": 120,
"indentWidth": 2,
"lineEnding": "lf",
"enabled": true,
},
"linter": {
"enabled": true,
"rules": {
"performance": {
"noDelete": "off",
},
"complexity": {
"noExtraBooleanCast": "off",
}
},
},
"javascript": {
"formatter": {
"trailingCommas": "all",
"jsxQuoteStyle": "double",
"quoteStyle": "single",
"bracketSpacing": true,
"arrowParentheses": "always",
},
},
"json": {
"formatter": {
"trailingCommas": "all",
},
},
}
+10 -11
View File
@@ -1,5 +1,4 @@
import * as core from '@actions/core';
import { errorMessage } from '../helpers';
const core = require('@actions/core');
/**
* When the GitHub Actions job is done, clean up any environment variables that
@@ -12,7 +11,7 @@ import { errorMessage } from '../helpers';
* with any other jobs.
*/
export function cleanup() {
async function cleanup() {
try {
// The GitHub Actions toolkit does not have an option to completely unset
// environment variables, so we overwrite the current value with an empty
@@ -23,15 +22,15 @@ export function cleanup() {
core.exportVariable('AWS_SESSION_TOKEN', '');
core.exportVariable('AWS_DEFAULT_REGION', '');
core.exportVariable('AWS_REGION', '');
} catch (error) {
core.setFailed(errorMessage(error));
}
catch (error) {
core.setFailed(error.message);
}
}
/* c8 ignore start */
module.exports = cleanup;
/* istanbul ignore next */
if (require.main === module) {
try {
cleanup();
} catch (error) {
core.setFailed(errorMessage(error));
}
cleanup();
}
+51
View File
@@ -0,0 +1,51 @@
const core = require('@actions/core');
const cleanup = require('./cleanup.js');
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_REGION = 'fake-region-1';
const ACTION_ENVIRONMENT_VARIABLES = {
AWS_ACCESS_KEY_ID: FAKE_ACCESS_KEY_ID,
AWS_SECRET_ACCESS_KEY: FAKE_SECRET_ACCESS_KEY,
AWS_SESSION_TOKEN: FAKE_SESSION_TOKEN,
AWS_DEFAULT_REGION: FAKE_REGION,
AWS_REGION: FAKE_REGION,
};
describe('Configure AWS Credentials', () => {
const OLD_ENV = process.env;
beforeEach(() => {
jest.resetModules();
process.env = {...OLD_ENV, ...ACTION_ENVIRONMENT_VARIABLES};
});
afterEach(() => {
process.env = OLD_ENV;
});
test('replaces AWS credential and region env vars with empty strings', async () => {
await cleanup();
expect(core.setFailed).toHaveBeenCalledTimes(0);
expect(core.exportVariable).toHaveBeenCalledTimes(5);
expect(core.exportVariable).toHaveBeenCalledWith('AWS_ACCESS_KEY_ID', '');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_SECRET_ACCESS_KEY', '');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_SESSION_TOKEN', '');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_DEFAULT_REGION', '');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_REGION', '');
});
test('error is caught and fails the action', async () => {
core.exportVariable.mockReset();
core.exportVariable.mockImplementation(() => {
throw new Error();
});
await cleanup();
expect(core.setFailed).toBeCalled();
});
});
+221 -46163
View File
File diff suppressed because one or more lines are too long
+42691 -47740
View File
File diff suppressed because one or more lines are too long
@@ -6,7 +6,7 @@ jobs:
sast-guard:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v3
- uses: grolston/guard-action@main
with:
data_directory: './cloudformation/' ## change to your template directory
+3 -3
View File
@@ -18,16 +18,16 @@ jobs:
contents: read
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
uses: aws-actions/configure-aws-credentials@v1-node16
with:
aws-region: us-east-1
## the following creates an ARN based on the values entered into github secrets
role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/${{ secrets.AWS_DEPLOY_ROLE }}
role-session-name: myGitHubActions
- name: Deploy EC2 Bastion
uses: aws-actions/aws-cloudformation-github-deploy@v1.3.0
uses: aws-actions/aws-cloudformation-github-deploy@v1.0.3
with:
name: myEC2bastion
## change to path to template in your github repo
+1 -1
View File
@@ -1,6 +1,6 @@
# federated-setup
## [github-action-oidc-federation](./github-actions-oidc-federation.yml)
## [github-action-oidc-federation](./github-actions-odic-federation.yml)
Setup of the OIDC federation between your GitHub Organization/repository and your AWS account.
+380
View File
@@ -0,0 +1,380 @@
const core = require('@actions/core');
const aws = require('aws-sdk');
const assert = require('assert');
const fs = require('fs');
const path = require('path');
// Use 1hr as role duration when using session token or OIDC
// Otherwise, use the max duration of GitHub action (6hr)
const MAX_ACTION_RUNTIME = 6 * 3600;
const SESSION_ROLE_DURATION = 3600;
const DEFAULT_ROLE_DURATION_FOR_OIDC_ROLES = 3600;
const USER_AGENT = 'configure-aws-credentials-for-github-actions';
const MAX_TAG_VALUE_LENGTH = 256;
const SANITIZATION_CHARACTER = '_';
const ROLE_SESSION_NAME = 'GitHubActions';
const REGION_REGEX = /^[a-z0-9-]+$/g;
async function assumeRole(params) {
// Assume a role to get short-lived credentials using longer-lived credentials.
const isDefined = i => !!i;
const {
sourceAccountId,
roleToAssume,
roleExternalId,
roleDurationSeconds,
roleSessionName,
region,
roleSkipSessionTagging,
webIdentityTokenFile,
webIdentityToken
} = params;
assert(
[roleToAssume, roleDurationSeconds, roleSessionName, region].every(isDefined),
"Missing required input when assuming a Role."
);
const {GITHUB_REPOSITORY, GITHUB_WORKFLOW, GITHUB_ACTION, GITHUB_ACTOR, GITHUB_SHA} = process.env;
assert(
[GITHUB_REPOSITORY, GITHUB_WORKFLOW, GITHUB_ACTION, GITHUB_ACTOR, GITHUB_SHA].every(isDefined),
'Missing required environment value. Are you running in GitHub Actions?'
);
const sts = getStsClient(region);
let roleArn = roleToAssume;
if (!roleArn.startsWith('arn:aws')) {
// Supports only 'aws' partition. Customers in other partitions ('aws-cn') will need to provide full ARN
assert(
isDefined(sourceAccountId),
"Source Account ID is needed if the Role Name is provided and not the Role 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: 'Commit', Value: GITHUB_SHA},
];
if (isDefined(process.env.GITHUB_REF)) {
tagArray.push({Key: 'Branch', Value: process.env.GITHUB_REF});
}
const roleSessionTags = roleSkipSessionTagging ? undefined : tagArray;
if(roleSessionTags == undefined){
core.debug("Role session tagging has been skipped.")
} else {
core.debug(roleSessionTags.length + " role session tags are being used.")
}
const assumeRoleRequest = {
RoleArn: roleArn,
RoleSessionName: roleSessionName,
DurationSeconds: roleDurationSeconds,
Tags: roleSessionTags
};
if (roleExternalId) {
assumeRoleRequest.ExternalId = roleExternalId;
}
let assumeFunction = sts.assumeRole.bind(sts);
// These are customizations needed for the GH OIDC Provider
if(isDefined(webIdentityToken)) {
delete assumeRoleRequest.Tags;
assumeRoleRequest.WebIdentityToken = webIdentityToken;
assumeFunction = sts.assumeRoleWithWebIdentity.bind(sts);
} else if(isDefined(webIdentityTokenFile)) {
core.debug("webIdentityTokenFile provided. Will call sts:AssumeRoleWithWebIdentity and take session tags from token contents.");
delete assumeRoleRequest.Tags;
const webIdentityTokenFilePath = path.isAbsolute(webIdentityTokenFile) ?
webIdentityTokenFile :
path.join(process.env.GITHUB_WORKSPACE, webIdentityTokenFile);
if (!fs.existsSync(webIdentityTokenFilePath)) {
throw new Error(`Web identity token file does not exist: ${webIdentityTokenFilePath}`);
}
try {
assumeRoleRequest.WebIdentityToken = await fs.promises.readFile(webIdentityTokenFilePath, 'utf8');
assumeFunction = sts.assumeRoleWithWebIdentity.bind(sts);
} catch(error) {
throw new Error(`Web identity token file could not be read: ${error.message}`);
}
}
return assumeFunction(assumeRoleRequest)
.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.setSecret(accessKeyId);
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.setSecret(secretAccessKey);
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.setSecret(sessionToken);
core.exportVariable('AWS_SESSION_TOKEN', sessionToken);
} else if (process.env.AWS_SESSION_TOKEN) {
// clear session token from previous credentials action
core.exportVariable('AWS_SESSION_TOKEN', '');
}
}
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, region) {
// Get the AWS account ID
const sts = getStsClient(region);
const identity = await sts.getCallerIdentity().promise();
const accountId = identity.Account;
if (!maskAccountId || maskAccountId.toLowerCase() == 'true') {
core.setSecret(accountId);
}
core.setOutput('aws-account-id', accountId);
return accountId;
}
function loadCredentials() {
// Force the SDK to re-resolve credentials with the default provider chain.
//
// This action typically sets credentials in the environment via environment variables.
// The SDK never refreshes those env-var-based credentials after initial load.
// In case there were already env-var creds set in the actions environment when this action
// loaded, this action needs to refresh the SDK creds after overwriting those environment variables.
//
// The credentials object needs to be entirely recreated (instead of simply refreshed),
// because the credential object type could change when this action writes env var creds.
// For example, the first load could return EC2 instance metadata credentials
// in a self-hosted runner, and the second load could return environment credentials
// from an assume-role call in this action.
aws.config.credentials = null;
return new Promise((resolve, reject) => {
aws.config.getCredentials((err) => {
if (err) {
reject(err);
}
resolve(aws.config.credentials);
})
});
}
async function validateCredentials(expectedAccessKeyId) {
let credentials;
try {
credentials = await loadCredentials();
if (!credentials.accessKeyId) {
throw new Error('Access key ID empty after loading credentials');
}
} catch (error) {
throw new Error(`Credentials could not be loaded, please check your action inputs: ${error.message}`);
}
const actualAccessKeyId = credentials.accessKeyId;
if (expectedAccessKeyId && expectedAccessKeyId != actualAccessKeyId) {
throw new Error('Unexpected failure: Credentials loaded by the SDK do not match the access key ID configured by the action');
}
}
function getStsClient(region) {
return new aws.STS({
region,
stsRegionalEndpoints: 'regional',
customUserAgent: USER_AGENT
});
}
let defaultSleep = function (ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
};
let sleep = defaultSleep;
// retryAndBackoff retries with exponential backoff the promise if the error isRetryable upto maxRetries time.
const retryAndBackoff = async (fn, isRetryable, retries = 0, maxRetries = 12, base = 50) => {
try {
return await fn();
} catch (err) {
if (!isRetryable) {
throw err;
}
// It's retryable, so sleep and retry.
await sleep(Math.random() * (Math.pow(2, retries) * base) );
retries += 1;
if (retries === maxRetries) {
throw err;
}
return await retryAndBackoff(fn, isRetryable, retries, maxRetries, base);
}
}
async function run() {
try {
// Get inputs
const accessKeyId = core.getInput('aws-access-key-id', { required: false });
const audience = core.getInput('audience', { required: false });
const secretAccessKey = core.getInput('aws-secret-access-key', { required: false });
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 roleExternalId = core.getInput('role-external-id', { required: false });
let roleDurationSeconds = core.getInput('role-duration-seconds', {required: false})
|| (sessionToken && SESSION_ROLE_DURATION)
|| MAX_ACTION_RUNTIME;
const roleSessionName = core.getInput('role-session-name', { required: false }) || ROLE_SESSION_NAME;
const roleSkipSessionTaggingInput = core.getInput('role-skip-session-tagging', { required: false })|| 'false';
const roleSkipSessionTagging = roleSkipSessionTaggingInput.toLowerCase() === 'true';
const webIdentityTokenFile = core.getInput('web-identity-token-file', { required: false });
if (!region.match(REGION_REGEX)) {
throw new Error(`Region is not valid: ${region}`);
}
exportRegion(region);
// This wraps the logic for deciding if we should rely on the GH OIDC provider since we may need to reference
// the decision in a few differennt places. Consolidating it here makes the logic clearer elsewhere.
const useGitHubOIDCProvider = () => {
// The assumption here is that self-hosted runners won't be populating the `ACTIONS_ID_TOKEN_REQUEST_TOKEN`
// environment variable and they won't be providing a web idenity token file or access key either.
// V2 of the action might relax this a bit and create an explicit precedence for these so that customers
// can provide as much info as they want and we will follow the established credential loading precedence.
return roleToAssume && process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN && !accessKeyId && !webIdentityTokenFile
}
// Always export the source credentials and account ID.
// The STS client for calling AssumeRole pulls creds from the environment.
// Plus, in the assume role case, if the AssumeRole call fails, we want
// the source credentials and account ID to already be masked as secrets
// in any error messages.
if (accessKeyId) {
if (!secretAccessKey) {
throw new Error("'aws-secret-access-key' must be provided if 'aws-access-key-id' is provided");
}
exportCredentials({accessKeyId, secretAccessKey, sessionToken});
}
// Attempt to load credentials from the GitHub OIDC provider.
// If a user provides an IAM Role Arn and DOESN'T provide an Access Key Id
// The only way to assume the role is via GitHub's OIDC provider.
let sourceAccountId;
let webIdentityToken;
if(useGitHubOIDCProvider()) {
webIdentityToken = await core.getIDToken(audience);
roleDurationSeconds = core.getInput('role-duration-seconds', {required: false}) || DEFAULT_ROLE_DURATION_FOR_OIDC_ROLES;
// We don't validate the credentials here because we don't have them yet when using OIDC.
} else {
// Regardless of whether any source credentials were provided as inputs,
// validate that the SDK can actually pick up credentials. This validates
// cases where this action is on a self-hosted runner that doesn't have credentials
// configured correctly, and cases where the user intended to provide input
// credentials but the secrets inputs resolved to empty strings.
await validateCredentials(accessKeyId);
sourceAccountId = await exportAccountId(maskAccountId, region);
}
// Get role credentials if configured to do so
if (roleToAssume) {
const roleCredentials = await retryAndBackoff(
async () => { return await assumeRole({
sourceAccountId,
region,
roleToAssume,
roleExternalId,
roleDurationSeconds,
roleSessionName,
roleSkipSessionTagging,
webIdentityTokenFile,
webIdentityToken
}) }, true);
exportCredentials(roleCredentials);
// We need to validate the credentials in 2 of our use-cases
// First: self-hosted runners. If the GITHUB_ACTIONS environment variable
// is set to `true` then we are NOT in a self-hosted runner.
// Second: Customer provided credentials manually (IAM User keys stored in GH Secrets)
if (!process.env.GITHUB_ACTIONS || accessKeyId) {
await validateCredentials(roleCredentials.accessKeyId);
}
await exportAccountId(maskAccountId, region);
}
}
catch (error) {
core.setFailed(error.message);
const showStackTrace = process.env.SHOW_STACK_TRACE;
if (showStackTrace === 'true') {
throw(error)
}
}
}
exports.withSleep = function (s) {
sleep = s;
};
exports.reset = function () {
sleep = defaultSleep;
};
exports.run = run
/* istanbul ignore next */
if (require.main === module) {
run();
}
+807
View File
@@ -0,0 +1,807 @@
const core = require('@actions/core');
const assert = require('assert');
const aws = require('aws-sdk');
const { run, withSleep, reset } = require('./index.js');
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 FAKE_ROLE_ACCOUNT_ID = '111111111111';
const ROLE_NAME = 'MY-ROLE';
const ROLE_ARN = 'arn:aws:iam::111111111111:role/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_SHA: 'MY-COMMIT-ID',
GITHUB_REF: 'MY-BRANCH',
GITHUB_WORKSPACE: '/home/github'
};
const GITHUB_ACTOR_SANITIZED = 'MY-USERNAME_bot_'
function mockGetInput(requestResponse) {
return function (name, options) { // eslint-disable-line no-unused-vars
return requestResponse[name]
}
}
const CREDS_INPUTS = {
'aws-access-key-id': FAKE_ACCESS_KEY_ID,
'aws-secret-access-key': FAKE_SECRET_ACCESS_KEY
};
const DEFAULT_INPUTS = {
...CREDS_INPUTS,
'aws-session-token': FAKE_SESSION_TOKEN,
'aws-region': FAKE_REGION,
'mask-aws-account-id': 'TRUE'
};
const ASSUME_ROLE_INPUTS = {...CREDS_INPUTS, 'role-to-assume': ROLE_ARN, 'aws-region': FAKE_REGION};
const mockStsCallerIdentity = jest.fn();
const mockStsAssumeRole = jest.fn();
const mockStsAssumeRoleWithWebIdentity = jest.fn();
jest.mock('aws-sdk', () => {
return {
config: {
getCredentials: jest.fn()
},
STS: jest.fn(() => ({
getCallerIdentity: mockStsCallerIdentity,
assumeRole: mockStsAssumeRole,
assumeRoleWithWebIdentity: mockStsAssumeRoleWithWebIdentity
}))
};
});
jest.mock('fs', () => {
return {
promises: {
readFile: jest.fn(() => Promise.resolve('testpayload')),
},
existsSync: jest.fn(() => true)
};
});
jest.mock('axios', () => ({
get: jest.fn(() => Promise.resolve({ data: { value: "testtoken" }})),
}));
describe('Configure AWS Credentials', () => {
beforeEach(() => {
jest.resetModules();
process.env = { ...ENVIRONMENT_VARIABLE_OVERRIDES };
jest.clearAllMocks();
core.getInput = jest
.fn()
.mockImplementation(mockGetInput(DEFAULT_INPUTS));
core.getIDToken = jest
.fn()
.mockImplementation(() => {
return "testtoken"
});
mockStsCallerIdentity.mockReset();
mockStsCallerIdentity
.mockReturnValueOnce({
promise() {
return Promise.resolve({ Account: FAKE_ACCOUNT_ID });
}
})
.mockReturnValueOnce({
promise() {
return Promise.resolve({ Account: FAKE_ROLE_ACCOUNT_ID });
}
});
aws.config.getCredentials.mockReset();
aws.config.getCredentials
.mockImplementationOnce(callback => {
if (!aws.config.credentials) {
aws.config.credentials = {
accessKeyId: FAKE_ACCESS_KEY_ID,
secretAccessKey: FAKE_SECRET_ACCESS_KEY
}
}
callback(null);
})
.mockImplementationOnce(callback => {
if (!aws.config.credentials) {
aws.config.credentials = {
accessKeyId: FAKE_STS_ACCESS_KEY_ID,
secretAccessKey: FAKE_STS_SECRET_ACCESS_KEY
}
}
callback(null);
});
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
}
});
}
}
});
mockStsAssumeRoleWithWebIdentity.mockImplementation(() => {
return {
promise() {
return Promise.resolve({
Credentials: {
AccessKeyId: FAKE_STS_ACCESS_KEY_ID,
SecretAccessKey: FAKE_STS_SECRET_ACCESS_KEY,
SessionToken: FAKE_STS_SESSION_TOKEN
}
});
}
}
});
withSleep(() => {
return Promise.resolve();
});
});
afterEach(() => {
reset();
});
test('exports env vars', async () => {
await run();
expect(mockStsAssumeRole).toHaveBeenCalledTimes(0);
expect(core.exportVariable).toHaveBeenCalledTimes(5);
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('action fails when github env vars are not set', async () => {
process.env.SHOW_STACK_TRACE = 'false';
core.getInput = jest
.fn()
.mockImplementation(mockGetInput(ASSUME_ROLE_INPUTS));
delete process.env.GITHUB_SHA;
await run();
expect(core.setFailed).toHaveBeenCalledWith('Missing required environment value. Are you running in GitHub Actions?');
});
test('action does not require GITHUB_REF env var', async () => {
core.getInput = jest
.fn()
.mockImplementation(mockGetInput(ASSUME_ROLE_INPUTS));
delete process.env.GITHUB_REF;
await run();
});
test('hosted runners can pull creds from a self-hosted environment', async () => {
const mockInputs = {'aws-region': FAKE_REGION};
core.getInput = jest
.fn()
.mockImplementation(mockGetInput(mockInputs));
await run();
expect(mockStsAssumeRole).toHaveBeenCalledTimes(0);
expect(core.exportVariable).toHaveBeenCalledTimes(2);
expect(core.setSecret).toHaveBeenCalledTimes(1);
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('action with no accessible credentials fails', async () => {
process.env.SHOW_STACK_TRACE = 'false';
const mockInputs = {'aws-region': FAKE_REGION};
core.getInput = jest
.fn()
.mockImplementation(mockGetInput(mockInputs));
aws.config.getCredentials.mockReset();
aws.config.getCredentials.mockImplementation(callback => {
callback(new Error('No credentials to load'));
});
await run();
expect(core.setFailed).toHaveBeenCalledWith("Credentials could not be loaded, please check your action inputs: No credentials to load");
});
test('action with empty credentials fails', async () => {
process.env.SHOW_STACK_TRACE = 'false';
const mockInputs = {'aws-region': FAKE_REGION};
core.getInput = jest
.fn()
.mockImplementation(mockGetInput(mockInputs));
aws.config.getCredentials.mockReset();
aws.config.getCredentials.mockImplementation(callback => {
aws.config.credentials = {
accessKeyId: ''
}
callback(null);
});
await run();
expect(core.setFailed).toHaveBeenCalledWith("Credentials could not be loaded, please check your action inputs: Access key ID empty after loading credentials");
});
test('action fails when credentials are not set in the SDK correctly', async () => {
process.env.SHOW_STACK_TRACE = 'false';
core.getInput = jest
.fn()
.mockImplementation(mockGetInput(ASSUME_ROLE_INPUTS));
aws.config.getCredentials.mockReset();
aws.config.getCredentials.mockImplementation(callback => {
aws.config.credentials = {
accessKeyId: FAKE_ACCESS_KEY_ID
}
callback(null);
});
await run();
expect(core.setFailed).toHaveBeenCalledWith("Unexpected failure: Credentials loaded by the SDK do not match the access key ID configured by the action");
});
test('session token is optional', async () => {
const mockInputs = {...CREDS_INPUTS, 'aws-region': 'eu-west-1'};
core.getInput = jest
.fn()
.mockImplementation(mockGetInput(mockInputs));
await run();
expect(mockStsAssumeRole).toHaveBeenCalledTimes(0);
expect(core.exportVariable).toHaveBeenCalledTimes(4);
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', FAKE_ACCOUNT_ID);
expect(core.setSecret).toHaveBeenCalledWith(FAKE_ACCOUNT_ID);
});
test('existing env var creds are cleared', async () => {
const mockInputs = {...CREDS_INPUTS, 'aws-region': 'eu-west-1'};
core.getInput = jest
.fn()
.mockImplementation(mockGetInput(mockInputs));
process.env.AWS_ACCESS_KEY_ID = 'foo';
process.env.AWS_SECRET_ACCESS_KEY = 'bar';
process.env.AWS_SESSION_TOKEN = 'helloworld';
aws.config.credentials = {
accessKeyId: 'foo',
secretAccessKey: 'bar',
sessionToken: 'helloworld'
};
await run();
expect(mockStsAssumeRole).toHaveBeenCalledTimes(0);
expect(core.exportVariable).toHaveBeenCalledTimes(5);
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_SESSION_TOKEN', '');
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', FAKE_ACCOUNT_ID);
expect(core.setSecret).toHaveBeenCalledWith(FAKE_ACCOUNT_ID);
expect(aws.config.credentials.accessKeyId).toBe(FAKE_ACCESS_KEY_ID);
expect(aws.config.credentials.secretAccessKey).toBe(FAKE_SECRET_ACCESS_KEY);
expect(aws.config.credentials.sessionToken).toBeUndefined();
});
test('validates region name', async () => {
process.env.SHOW_STACK_TRACE = 'false';
const mockInputs = {...CREDS_INPUTS, 'aws-region': '$AWS_REGION'};
core.getInput = jest
.fn()
.mockImplementation(mockGetInput(mockInputs));
await run();
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
.fn()
.mockImplementation(mockGetInput(mockInputs));
await run();
expect(mockStsAssumeRole).toHaveBeenCalledTimes(0);
expect(core.exportVariable).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_DEFAULT_REGION', 'us-east-1');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_REGION', 'us-east-1');
expect(core.setOutput).toHaveBeenCalledWith('aws-account-id', FAKE_ACCOUNT_ID);
expect(core.setSecret).toHaveBeenCalledTimes(2);
});
test('error is caught by core.setFailed and caught', async () => {
process.env.SHOW_STACK_TRACE = 'false';
mockStsCallerIdentity.mockReset();
mockStsCallerIdentity.mockImplementation(() => {
throw new Error();
});
await run();
expect(core.setFailed).toBeCalled();
});
test('error is caught by core.setFailed and passed', async () => {
mockStsCallerIdentity.mockReset();
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(7);
expect(core.setSecret).toHaveBeenCalledTimes(7);
expect(core.setOutput).toHaveBeenCalledTimes(2);
// first the source credentials are exported and masked
expect(core.setSecret).toHaveBeenNthCalledWith(1, FAKE_ACCESS_KEY_ID);
expect(core.setSecret).toHaveBeenNthCalledWith(2, FAKE_SECRET_ACCESS_KEY);
expect(core.setSecret).toHaveBeenNthCalledWith(3, FAKE_ACCOUNT_ID);
expect(core.exportVariable).toHaveBeenNthCalledWith(1, 'AWS_DEFAULT_REGION', FAKE_REGION);
expect(core.exportVariable).toHaveBeenNthCalledWith(2, 'AWS_REGION', FAKE_REGION);
expect(core.exportVariable).toHaveBeenNthCalledWith(3, 'AWS_ACCESS_KEY_ID', FAKE_ACCESS_KEY_ID);
expect(core.exportVariable).toHaveBeenNthCalledWith(4, 'AWS_SECRET_ACCESS_KEY', FAKE_SECRET_ACCESS_KEY);
expect(core.setOutput).toHaveBeenNthCalledWith(1, 'aws-account-id', FAKE_ACCOUNT_ID);
// then the role credentials are exported and masked
expect(core.setSecret).toHaveBeenNthCalledWith(4, FAKE_STS_ACCESS_KEY_ID);
expect(core.setSecret).toHaveBeenNthCalledWith(5, FAKE_STS_SECRET_ACCESS_KEY);
expect(core.setSecret).toHaveBeenNthCalledWith(6, FAKE_STS_SESSION_TOKEN);
expect(core.setSecret).toHaveBeenNthCalledWith(7, FAKE_ROLE_ACCOUNT_ID);
expect(core.exportVariable).toHaveBeenNthCalledWith(5, 'AWS_ACCESS_KEY_ID', FAKE_STS_ACCESS_KEY_ID);
expect(core.exportVariable).toHaveBeenNthCalledWith(6, 'AWS_SECRET_ACCESS_KEY', FAKE_STS_SECRET_ACCESS_KEY);
expect(core.exportVariable).toHaveBeenNthCalledWith(7, 'AWS_SESSION_TOKEN', FAKE_STS_SESSION_TOKEN);
expect(core.setOutput).toHaveBeenNthCalledWith(2, 'aws-account-id', FAKE_ROLE_ACCOUNT_ID);
});
test('assume role can pull source credentials from self-hosted environment', async () => {
core.getInput = jest
.fn()
.mockImplementation(mockGetInput({'role-to-assume': ROLE_ARN, 'aws-region': FAKE_REGION}));
await run();
expect(mockStsAssumeRole).toHaveBeenCalledTimes(1);
expect(core.exportVariable).toHaveBeenCalledTimes(5);
expect(core.setSecret).toHaveBeenCalledTimes(5);
expect(core.setOutput).toHaveBeenCalledTimes(2);
// first the source account is exported and masked
expect(core.setSecret).toHaveBeenNthCalledWith(1, FAKE_ACCOUNT_ID);
expect(core.exportVariable).toHaveBeenNthCalledWith(1, 'AWS_DEFAULT_REGION', FAKE_REGION);
expect(core.exportVariable).toHaveBeenNthCalledWith(2, 'AWS_REGION', FAKE_REGION);
expect(core.setOutput).toHaveBeenNthCalledWith(1, 'aws-account-id', FAKE_ACCOUNT_ID);
// then the role credentials are exported and masked
expect(core.setSecret).toHaveBeenNthCalledWith(2, FAKE_STS_ACCESS_KEY_ID);
expect(core.setSecret).toHaveBeenNthCalledWith(3, FAKE_STS_SECRET_ACCESS_KEY);
expect(core.setSecret).toHaveBeenNthCalledWith(4, FAKE_STS_SESSION_TOKEN);
expect(core.setSecret).toHaveBeenNthCalledWith(5, FAKE_ROLE_ACCOUNT_ID);
expect(core.exportVariable).toHaveBeenNthCalledWith(3, 'AWS_ACCESS_KEY_ID', FAKE_STS_ACCESS_KEY_ID);
expect(core.exportVariable).toHaveBeenNthCalledWith(4, 'AWS_SECRET_ACCESS_KEY', FAKE_STS_SECRET_ACCESS_KEY);
expect(core.exportVariable).toHaveBeenNthCalledWith(5, 'AWS_SESSION_TOKEN', FAKE_STS_SESSION_TOKEN);
expect(core.setOutput).toHaveBeenNthCalledWith(2, 'aws-account-id', FAKE_ROLE_ACCOUNT_ID);
});
test('role assumption tags', async () => {
core.getInput = jest
.fn()
.mockImplementation(mockGetInput(ASSUME_ROLE_INPUTS));
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: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_REF},
]
})
});
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_ARN,
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: 'Commit', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_SHA},
{Key: 'Branch', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_REF},
]
})
});
test('role assumption session name provided', async () => {
core.getInput = jest
.fn()
.mockImplementation(mockGetInput({...ASSUME_ROLE_INPUTS, 'role-session-name': 'MySessionName'}));
await run();
expect(mockStsAssumeRole).toHaveBeenCalledWith({
RoleArn: ROLE_ARN,
RoleSessionName: 'MySessionName',
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: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_REF},
]
})
});
test('sets durationSeconds to one hour when session token provided and no duration is provided', async () => {
core.getInput = jest
.fn()
.mockImplementation(mockGetInput({...ASSUME_ROLE_INPUTS, 'aws-session-token': FAKE_SESSION_TOKEN}));
await run();
expect(mockStsAssumeRole).toHaveBeenCalledWith({
RoleArn: ROLE_ARN,
RoleSessionName: 'GitHubActions',
DurationSeconds: 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: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_REF},
]
})
});
test('sets durationSeconds to one 6 hours no session token or duration is provided', async () => {
core.getInput = jest
.fn()
.mockImplementation(mockGetInput({...ASSUME_ROLE_INPUTS}));
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: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_REF},
]
})
});
test('role name provided instead of ARN', async () => {
core.getInput = jest
.fn()
.mockImplementation(mockGetInput({...CREDS_INPUTS, 'role-to-assume': ROLE_NAME, 'aws-region': FAKE_REGION}));
await run();
expect(mockStsAssumeRole).toHaveBeenCalledWith({
RoleArn: 'arn:aws:iam::123456789012:role/MY-ROLE',
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: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_REF},
]
})
});
test('web identity token file provided with absolute path', async () => {
core.getInput = jest
.fn()
.mockImplementation(mockGetInput({'role-to-assume': ROLE_ARN, 'aws-region': FAKE_REGION, 'web-identity-token-file': '/fake/token/file'}));
await run();
expect(mockStsAssumeRoleWithWebIdentity).toHaveBeenCalledWith({
RoleArn: 'arn:aws:iam::111111111111:role/MY-ROLE',
RoleSessionName: 'GitHubActions',
DurationSeconds: 6 * 3600,
WebIdentityToken: 'testpayload'
})
});
test('web identity token file provided with relative path', async () => {
core.getInput = jest
.fn()
.mockImplementation(mockGetInput({'role-to-assume': ROLE_ARN, 'aws-region': FAKE_REGION, 'web-identity-token-file': 'fake/token/file'}));
await run();
expect(mockStsAssumeRoleWithWebIdentity).toHaveBeenCalledWith({
RoleArn: 'arn:aws:iam::111111111111:role/MY-ROLE',
RoleSessionName: 'GitHubActions',
DurationSeconds: 6 * 3600,
WebIdentityToken: 'testpayload'
})
});
test('only role arn and region provided to use GH OIDC Token', async () => {
process.env.GITHUB_ACTIONS = 'true';
process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN = 'test-token';
core.getInput = jest
.fn()
.mockImplementation(mockGetInput({'role-to-assume': ROLE_ARN, 'aws-region': FAKE_REGION}));
await run();
expect(mockStsAssumeRoleWithWebIdentity).toHaveBeenCalledWith({
RoleArn: 'arn:aws:iam::111111111111:role/MY-ROLE',
RoleSessionName: 'GitHubActions',
DurationSeconds: 3600,
WebIdentityToken: 'testtoken'
});
expect(core.setSecret).toHaveBeenNthCalledWith(1, FAKE_STS_ACCESS_KEY_ID);
expect(core.setSecret).toHaveBeenNthCalledWith(2, FAKE_STS_SECRET_ACCESS_KEY);
expect(core.setSecret).toHaveBeenNthCalledWith(3, FAKE_STS_SESSION_TOKEN);
});
test('GH OIDC With custom role duration', async () => {
const CUSTOM_ROLE_DURATION = 1234;
process.env.GITHUB_ACTIONS = 'true';
process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN = 'test-token';
core.getInput = jest
.fn()
.mockImplementation(mockGetInput({'role-to-assume': ROLE_ARN, 'aws-region': FAKE_REGION, 'role-duration-seconds': CUSTOM_ROLE_DURATION}));
await run();
expect(mockStsAssumeRoleWithWebIdentity).toHaveBeenCalledWith({
RoleArn: 'arn:aws:iam::111111111111:role/MY-ROLE',
RoleSessionName: 'GitHubActions',
DurationSeconds: CUSTOM_ROLE_DURATION,
WebIdentityToken: 'testtoken'
});
expect(core.setSecret).toHaveBeenNthCalledWith(1, FAKE_STS_ACCESS_KEY_ID);
expect(core.setSecret).toHaveBeenNthCalledWith(2, FAKE_STS_SECRET_ACCESS_KEY);
expect(core.setSecret).toHaveBeenNthCalledWith(3, FAKE_STS_SESSION_TOKEN);
});
test('role assumption fails after maximun trials using OIDC Provider', async () => {
process.env.GITHUB_ACTIONS = 'true';
process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN = 'test-token';
core.getInput = jest
.fn()
.mockImplementation(mockGetInput({'role-to-assume': ROLE_ARN, 'aws-region': FAKE_REGION}));
mockStsAssumeRoleWithWebIdentity.mockReset();
mockStsAssumeRoleWithWebIdentity.mockImplementation(() => {
throw new Error();
});
await assert.rejects(() => run());
expect(mockStsAssumeRoleWithWebIdentity).toHaveBeenCalledTimes(12)
});
test('role external ID provided', async () => {
core.getInput = jest
.fn()
.mockImplementation(mockGetInput({...ASSUME_ROLE_INPUTS, 'role-external-id': 'abcdef'}));
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: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_REF},
],
ExternalId: 'abcdef'
})
});
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_ARN,
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: 'Commit', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_SHA},
{Key: 'Branch', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_REF},
]
})
});
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: 'Commit', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_SHA},
{Key: 'Branch', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_REF},
]
})
});
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: 'Commit', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_SHA},
{Key: 'Branch', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_REF},
]
})
});
test('masks variables before exporting', async () => {
let maskedValues = [];
const publicFields = ['AWS_REGION', 'AWS_DEFAULT_REGION'];
core.setSecret.mockReset();
core.setSecret.mockImplementation((secret) => {
maskedValues.push(secret);
});
core.exportVariable.mockReset();
core.exportVariable.mockImplementation((name, value) => {
if (!maskedValues.includes(value) && !publicFields.includes(name)) {
throw new Error(value + " for variable " + name + " is not masked yet!");
}
});
core.getInput = jest
.fn()
.mockImplementation(mockGetInput(ASSUME_ROLE_INPUTS));
await run();
});
});
-31
View File
@@ -1,31 +0,0 @@
/** @type {import('jest').Config} */
const config = {
verbose: true,
transform: {
'^.+\\.m?[tj]sx?$': ['ts-jest'],
},
testMatch: [
'<rootDir>/src/**/__tests__/**/*.ts?(x)',
'<rootDir>/(test|src)/**/*(*.)@(spec|test).ts?(x)',
'<rootDir>/test/**/*.(test|spec).(js|jsx|ts|tsx)',
],
clearMocks: true,
collectCoverage: true,
coverageReporters: ['json', 'lcov', 'clover', 'cobertura', 'text'],
coverageDirectory: 'coverage',
coveragePathIgnorePatterns: ['/node_modules/'],
testPathIgnorePatterns: ['/node_modules/'],
watchPathIgnorePatterns: ['/node_modules/'],
reporters: [
'default',
[
'jest-junit',
{
outputDirectory: 'test-reports',
},
],
],
preset: 'ts-jest/presets/default-legacy',
};
module.exports = config;
+2885 -7271
View File
File diff suppressed because it is too large Load Diff
+26 -43
View File
@@ -1,54 +1,37 @@
{
"name": "configure-aws-credentials",
"description": "A GitHub Action to configure AWS credentials",
"version": "4.2.0",
"name": "aws-actions-configure-aws-credentials",
"version": "1.7.0",
"description": "Configure AWS Credentials",
"main": "index.js",
"scripts": {
"build": "tsc",
"lint": "biome check --error-on-warnings ./src",
"package": "npm run build && ncc build --license THIRD-PARTY -o dist && ncc build src/cleanup/index.ts -o dist/cleanup && cpy dist/THIRD-PARTY . && del-cli dist/THIRD-PARTY",
"test": "npm run lint && vitest run && npm run build"
"lint": "eslint **.js",
"package": "ncc build index.js -o dist && ncc build cleanup.js -o dist/cleanup",
"test": "npm run lint && jest --coverage --verbose"
},
"author": {
"name": "Amazon.com, Inc. or its affiliates",
"url": "https://aws.amazon.com",
"organization": true
},
"devDependencies": {
"@aws-sdk/credential-provider-env": "^3.515.0",
"@biomejs/biome": "1.9.4",
"@smithy/property-provider": "^4.0.1",
"@types/node": "^22.15.11",
"@vercel/ncc": "^0.38.3",
"@vitest/coverage-v8": "^3.1.2",
"aws-sdk-client-mock": "^4.1.0",
"cpy-cli": "^5.0.0",
"del-cli": "^6.0.0",
"json-schema": "^0.4.0",
"memfs": "^4.17.1",
"standard-version": "^9.5.0",
"typescript": "^5.8.3",
"vitest": "^3.1.2"
},
"dependencies": {
"@actions/core": "^1.11.1",
"@aws-sdk/client-sts": "^3.803.0",
"@smithy/node-http-handler": "^4.0.1",
"https-proxy-agent": "^5.0.1"
"repository": {
"type": "git",
"url": "git+https://github.com/aws-actions/configure-aws-credentials.git"
},
"keywords": [
"aws",
"github",
"github-action"
"AWS",
"GitHub",
"Actions",
"JavaScript"
],
"engines": {
"node": ">= 14.0.0"
},
"main": "build/index.js",
"author": "AWS",
"license": "MIT",
"homepage": "https://github.com/aws-actions/configure-aws-credentials",
"bugs": {
"url": "https://github.com/aws-actions/configure-aws-credentials/issues"
},
"types": "build/index.d.ts",
"private": true
"homepage": "https://github.com/aws-actions/configure-aws-credentials#readme",
"dependencies": {
"@actions/core": "^1.10.0",
"aws-sdk": "^2.1324.0",
"axios": "^1.3.4"
},
"devDependencies": {
"@vercel/ncc": "^0.36.1",
"eslint": "^8.35.0",
"jest": "^29.4.3"
}
}
-13
View File
@@ -1,13 +0,0 @@
{
"packages": {
".": {
"changelog-path": "CHANGELOG.md",
"release-type": "node",
"bump-minor-pre-major": false,
"bump-patch-for-minor-pre-major": false,
"draft": false,
"prerelease": false
}
},
"$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json"
}
-71
View File
@@ -1,71 +0,0 @@
import { info } from '@actions/core';
import { STSClient } from '@aws-sdk/client-sts';
import type { AwsCredentialIdentity } from '@aws-sdk/types';
import { NodeHttpHandler } from '@smithy/node-http-handler';
import { HttpsProxyAgent } from 'https-proxy-agent';
import { errorMessage } from './helpers';
const USER_AGENT = 'configure-aws-credentials-for-github-actions';
export interface CredentialsClientProps {
region?: string;
proxyServer?: string;
}
export class CredentialsClient {
public region?: string;
private _stsClient?: STSClient;
private readonly requestHandler?: NodeHttpHandler;
constructor(props: CredentialsClientProps) {
this.region = props.region;
if (props.proxyServer) {
info('Configuring proxy handler for STS client');
const handler = new HttpsProxyAgent(props.proxyServer);
this.requestHandler = new NodeHttpHandler({
httpAgent: handler,
httpsAgent: handler,
});
}
}
public get stsClient(): STSClient {
if (!this._stsClient) {
this._stsClient = new STSClient({
region: this.region,
customUserAgent: USER_AGENT,
requestHandler: this.requestHandler ? this.requestHandler : undefined,
});
}
return this._stsClient;
}
public async validateCredentials(expectedAccessKeyId?: string, roleChaining?: boolean) {
let credentials: AwsCredentialIdentity;
try {
credentials = await this.loadCredentials();
if (!credentials.accessKeyId) {
throw new Error('Access key ID empty after loading credentials');
}
} catch (error) {
throw new Error(`Credentials could not be loaded, please check your action inputs: ${errorMessage(error)}`);
}
if (!roleChaining) {
const actualAccessKeyId = credentials.accessKeyId;
if (expectedAccessKeyId && expectedAccessKeyId !== actualAccessKeyId) {
throw new Error(
'Unexpected failure: Credentials loaded by the SDK do not match the access key ID configured by the action',
);
}
}
}
private async loadCredentials() {
const client = new STSClient({
requestHandler: this.requestHandler ? this.requestHandler : undefined,
});
return client.config.credentials();
}
}
-164
View File
@@ -1,164 +0,0 @@
import assert from 'node:assert';
import fs from 'node:fs';
import path from 'node:path';
import * as core from '@actions/core';
import type { AssumeRoleCommandInput, STSClient, Tag } from '@aws-sdk/client-sts';
import { AssumeRoleCommand, AssumeRoleWithWebIdentityCommand } from '@aws-sdk/client-sts';
import type { CredentialsClient } from './CredentialsClient';
import { errorMessage, isDefined, sanitizeGitHubVariables } from './helpers';
async function assumeRoleWithOIDC(params: AssumeRoleCommandInput, client: STSClient, webIdentityToken: string) {
delete params.Tags;
core.info('Assuming role with OIDC');
try {
const creds = await client.send(
new AssumeRoleWithWebIdentityCommand({
...params,
WebIdentityToken: webIdentityToken,
}),
);
return creds;
} catch (error) {
throw new Error(`Could not assume role with OIDC: ${errorMessage(error)}`);
}
}
async function assumeRoleWithWebIdentityTokenFile(
params: AssumeRoleCommandInput,
client: STSClient,
webIdentityTokenFile: string,
workspace: string,
) {
core.debug(
'webIdentityTokenFile provided. Will call sts:AssumeRoleWithWebIdentity and take session tags from token contents.',
);
const webIdentityTokenFilePath = path.isAbsolute(webIdentityTokenFile)
? webIdentityTokenFile
: path.join(workspace, webIdentityTokenFile);
if (!fs.existsSync(webIdentityTokenFilePath)) {
throw new Error(`Web identity token file does not exist: ${webIdentityTokenFilePath}`);
}
core.info('Assuming role with web identity token file');
try {
const webIdentityToken = fs.readFileSync(webIdentityTokenFilePath, 'utf8');
delete params.Tags;
const creds = await client.send(
new AssumeRoleWithWebIdentityCommand({
...params,
WebIdentityToken: webIdentityToken,
}),
);
return creds;
} catch (error) {
throw new Error(`Could not assume role with web identity token file: ${errorMessage(error)}`);
}
}
async function assumeRoleWithCredentials(params: AssumeRoleCommandInput, client: STSClient) {
core.info('Assuming role with user credentials');
try {
const creds = await client.send(new AssumeRoleCommand({ ...params }));
return creds;
} catch (error) {
throw new Error(`Could not assume role with user credentials: ${errorMessage(error)}`);
}
}
export interface assumeRoleParams {
credentialsClient: CredentialsClient;
roleToAssume: string;
roleDuration: number;
roleSessionName: string;
roleSkipSessionTagging?: boolean;
sourceAccountId?: string;
roleExternalId?: string;
webIdentityTokenFile?: string;
webIdentityToken?: string;
inlineSessionPolicy?: string;
managedSessionPolicies?: { arn: string }[];
}
export async function assumeRole(params: assumeRoleParams) {
const {
credentialsClient,
sourceAccountId,
roleToAssume,
roleExternalId,
roleDuration,
roleSessionName,
roleSkipSessionTagging,
webIdentityTokenFile,
webIdentityToken,
inlineSessionPolicy,
managedSessionPolicies,
} = { ...params };
// Load GitHub environment variables
const { GITHUB_REPOSITORY, GITHUB_WORKFLOW, GITHUB_ACTION, GITHUB_ACTOR, GITHUB_SHA, GITHUB_WORKSPACE } = process.env;
if (!GITHUB_REPOSITORY || !GITHUB_WORKFLOW || !GITHUB_ACTION || !GITHUB_ACTOR || !GITHUB_SHA || !GITHUB_WORKSPACE) {
throw new Error('Missing required environment variables. Are you running in GitHub Actions?');
}
// Load role session tags
const tagArray: Tag[] = [
{ Key: 'GitHub', Value: 'Actions' },
{ Key: 'Repository', Value: GITHUB_REPOSITORY },
{ Key: 'Workflow', Value: sanitizeGitHubVariables(GITHUB_WORKFLOW) },
{ Key: 'Action', Value: GITHUB_ACTION },
{ Key: 'Actor', Value: sanitizeGitHubVariables(GITHUB_ACTOR) },
{ Key: 'Commit', Value: GITHUB_SHA },
];
if (process.env.GITHUB_REF) {
tagArray.push({
Key: 'Branch',
Value: sanitizeGitHubVariables(process.env.GITHUB_REF),
});
}
const tags = roleSkipSessionTagging ? undefined : tagArray;
if (!tags) {
core.debug('Role session tagging has been skipped.');
} else {
core.debug(`${tags.length} role session tags are being used.`);
}
// Calculate role ARN from name and account ID (currently only supports `aws` partition)
let roleArn = roleToAssume;
if (!roleArn.startsWith('arn:aws')) {
assert(
isDefined(sourceAccountId),
'Source Account ID is needed if the Role Name is provided and not the Role Arn.',
);
roleArn = `arn:aws:iam::${sourceAccountId}:role/${roleArn}`;
}
// Ready common parameters to assume role
const commonAssumeRoleParams: AssumeRoleCommandInput = {
RoleArn: roleArn,
RoleSessionName: roleSessionName,
DurationSeconds: roleDuration,
Tags: tags ? tags : undefined,
ExternalId: roleExternalId ? roleExternalId : undefined,
Policy: inlineSessionPolicy ? inlineSessionPolicy : undefined,
PolicyArns: managedSessionPolicies?.length ? managedSessionPolicies : undefined,
};
const keys = Object.keys(commonAssumeRoleParams) as Array<keyof typeof commonAssumeRoleParams>;
// biome-ignore lint/complexity/noForEach: Legacy code
keys.forEach((k) => commonAssumeRoleParams[k] === undefined && delete commonAssumeRoleParams[k]);
// Instantiate STS client
const stsClient = credentialsClient.stsClient;
// Assume role using one of three methods
if (!!webIdentityToken) {
return assumeRoleWithOIDC(commonAssumeRoleParams, stsClient, webIdentityToken);
}
if (!!webIdentityTokenFile) {
return assumeRoleWithWebIdentityTokenFile(
commonAssumeRoleParams,
stsClient,
webIdentityTokenFile,
GITHUB_WORKSPACE,
);
}
return assumeRoleWithCredentials(commonAssumeRoleParams, stsClient);
}
-191
View File
@@ -1,191 +0,0 @@
import * as core from '@actions/core';
import type { Credentials } from '@aws-sdk/client-sts';
import { GetCallerIdentityCommand } from '@aws-sdk/client-sts';
import type { CredentialsClient } from './CredentialsClient';
const MAX_TAG_VALUE_LENGTH = 256;
const SANITIZATION_CHARACTER = '_';
const SPECIAL_CHARS_REGEX = /[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]+/;
export function translateEnvVariables() {
const envVars = [
'AWS_REGION',
'ROLE_TO_ASSUME',
'WEB_IDENTITY_TOKEN_FILE',
'ROLE_CHAINING',
'AUDIENCE',
'HTTP_PROXY',
'MASK_AWS_ACCOUNT_ID',
'ROLE_DURATION_SECONDS',
'ROLE_EXTERNAL_ID',
'ROLE_SESSION_NAME',
'ROLE_SKIP_SESSION_TAGGING',
'INLINE_SESSION_POLICY',
'MANAGED_SESSION_POLICIES',
'OUTPUT_CREDENTIALS',
'UNSET_CURRENT_CREDENTIALS',
'DISABLE_RETRY',
'RETRY_MAX_ATTEMPTS',
'SPECIAL_CHARACTERS_WORKAROUND',
'USE_EXISTING_CREDENTIALS',
];
for (const envVar of envVars) {
if (process.env[envVar]) {
process.env[`INPUT_${envVar.replace(/_/g, '-')}`] = process.env[envVar];
}
}
}
// 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
export function exportCredentials(creds?: Partial<Credentials>, outputCredentials?: boolean) {
if (creds?.AccessKeyId) {
core.setSecret(creds.AccessKeyId);
core.exportVariable('AWS_ACCESS_KEY_ID', creds.AccessKeyId);
}
if (creds?.SecretAccessKey) {
core.setSecret(creds.SecretAccessKey);
core.exportVariable('AWS_SECRET_ACCESS_KEY', creds.SecretAccessKey);
}
if (creds?.SessionToken) {
core.setSecret(creds.SessionToken);
core.exportVariable('AWS_SESSION_TOKEN', creds.SessionToken);
} else if (process.env.AWS_SESSION_TOKEN) {
// clear session token from previous credentials action
core.exportVariable('AWS_SESSION_TOKEN', '');
}
if (outputCredentials) {
if (creds?.AccessKeyId) {
core.setOutput('aws-access-key-id', creds.AccessKeyId);
}
if (creds?.SecretAccessKey) {
core.setOutput('aws-secret-access-key', creds.SecretAccessKey);
}
if (creds?.SessionToken) {
core.setOutput('aws-session-token', creds.SessionToken);
}
if (creds?.Expiration) {
core.setOutput('aws-expiration', creds.Expiration);
}
}
}
export function unsetCredentials() {
core.exportVariable('AWS_ACCESS_KEY_ID', '');
core.exportVariable('AWS_SECRET_ACCESS_KEY', '');
core.exportVariable('AWS_SESSION_TOKEN', '');
core.exportVariable('AWS_REGION', '');
core.exportVariable('AWS_DEFAULT_REGION', '');
}
export function exportRegion(region: string) {
core.exportVariable('AWS_DEFAULT_REGION', region);
core.exportVariable('AWS_REGION', region);
}
// Obtains account ID from STS Client and sets it as output
export async function exportAccountId(credentialsClient: CredentialsClient, maskAccountId?: boolean) {
const client = credentialsClient.stsClient;
const identity = await client.send(new GetCallerIdentityCommand({}));
const accountId = identity.Account;
if (!accountId) {
throw new Error('Could not get Account ID from STS. Did you set credentials?');
}
if (maskAccountId) {
core.setSecret(accountId);
}
core.setOutput('aws-account-id', accountId);
return accountId;
}
// Tags have a more restrictive set of acceptable characters than GitHub environment variables can.
// 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.
export function sanitizeGitHubVariables(name: string) {
const nameWithoutSpecialCharacters = name.replace(/[^\p{L}\p{Z}\p{N}_.:/=+\-@]/gu, SANITIZATION_CHARACTER);
const nameTruncated = nameWithoutSpecialCharacters.slice(0, MAX_TAG_VALUE_LENGTH);
return nameTruncated;
}
export async function defaultSleep(ms: number) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
let sleep = defaultSleep;
export function withsleep(s: typeof sleep) {
sleep = s;
}
export function reset() {
sleep = defaultSleep;
}
export function verifyKeys(creds: Partial<Credentials> | undefined) {
if (!creds) {
return false;
}
if (creds.AccessKeyId) {
if (SPECIAL_CHARS_REGEX.test(creds.AccessKeyId)) {
core.debug('AccessKeyId contains special characters.');
return false;
}
}
if (creds.SecretAccessKey) {
if (SPECIAL_CHARS_REGEX.test(creds.SecretAccessKey)) {
core.debug('SecretAccessKey contains special characters.');
return false;
}
}
return true;
}
// Retries the promise with exponential backoff if the error isRetryable up to maxRetries time.
export async function retryAndBackoff<T>(
fn: () => Promise<T>,
isRetryable: boolean,
maxRetries = 12,
retries = 0,
base = 50,
): Promise<T> {
try {
return await fn();
} catch (err) {
if (!isRetryable) {
throw err;
}
// It's retryable, so sleep and retry.
await sleep(Math.random() * (2 ** retries * base));
// biome-ignore lint/style/noParameterAssign: This is a loop variable
retries += 1;
if (retries >= maxRetries) {
throw err;
}
return await retryAndBackoff(fn, isRetryable, maxRetries, retries, base);
}
}
/* c8 ignore start */
export function errorMessage(error: unknown) {
return error instanceof Error ? error.message : String(error);
}
export function isDefined<T>(i: T | undefined | null): i is T {
return i !== undefined && i !== null;
}
/* c8 ignore stop */
export async function areCredentialsValid(credentialsClient: CredentialsClient) {
const client = credentialsClient.stsClient;
try {
const identity = await client.send(new GetCallerIdentityCommand({}));
if (identity.Account) {
return true;
}
return false;
} catch (_) {
return false;
}
}
-227
View File
@@ -1,227 +0,0 @@
import * as core from '@actions/core';
import type { AssumeRoleCommandOutput } from '@aws-sdk/client-sts';
import { CredentialsClient } from './CredentialsClient';
import { assumeRole } from './assumeRole';
import {
areCredentialsValid,
errorMessage,
exportAccountId,
exportCredentials,
exportRegion,
retryAndBackoff,
translateEnvVariables,
unsetCredentials,
verifyKeys,
} from './helpers';
const DEFAULT_ROLE_DURATION = 3600; // One hour (seconds)
const ROLE_SESSION_NAME = 'GitHubActions';
const REGION_REGEX = /^[a-z0-9-]+$/g;
export async function run() {
try {
translateEnvVariables();
// Get inputs
const AccessKeyId = core.getInput('aws-access-key-id', { required: false });
const SecretAccessKey = core.getInput('aws-secret-access-key', {
required: false,
});
const sessionTokenInput = core.getInput('aws-session-token', {
required: false,
});
const SessionToken = sessionTokenInput === '' ? undefined : sessionTokenInput;
const region = core.getInput('aws-region', { required: true });
const roleToAssume = core.getInput('role-to-assume', { required: false });
const audience = core.getInput('audience', { required: false });
const maskAccountIdInput = core.getInput('mask-aws-account-id', { required: false }) || 'false';
const maskAccountId = maskAccountIdInput.toLowerCase() === 'true';
const roleExternalId = core.getInput('role-external-id', {
required: false,
});
const webIdentityTokenFile = core.getInput('web-identity-token-file', {
required: false,
});
const roleDuration =
Number.parseInt(core.getInput('role-duration-seconds', { required: false })) || DEFAULT_ROLE_DURATION;
const roleSessionName = core.getInput('role-session-name', { required: false }) || ROLE_SESSION_NAME;
const roleSkipSessionTaggingInput = core.getInput('role-skip-session-tagging', { required: false }) || 'false';
const roleSkipSessionTagging = roleSkipSessionTaggingInput.toLowerCase() === 'true';
const proxyServer = core.getInput('http-proxy', { required: false });
const inlineSessionPolicy = core.getInput('inline-session-policy', {
required: false,
});
const managedSessionPoliciesInput = core.getMultilineInput('managed-session-policies', { required: false });
const managedSessionPolicies: { arn: string }[] = [];
const roleChainingInput = core.getInput('role-chaining', { required: false }) || 'false';
const roleChaining = roleChainingInput.toLowerCase() === 'true';
const outputCredentialsInput = core.getInput('output-credentials', { required: false }) || 'false';
const outputCredentials = outputCredentialsInput.toLowerCase() === 'true';
const unsetCurrentCredentialsInput = core.getInput('unset-current-credentials', { required: false }) || 'false';
const unsetCurrentCredentials = unsetCurrentCredentialsInput.toLowerCase() === 'true';
const disableRetryInput = core.getInput('disable-retry', { required: false }) || 'false';
let disableRetry = disableRetryInput.toLowerCase() === 'true';
const specialCharacterWorkaroundInput =
core.getInput('special-characters-workaround', { required: false }) || 'false';
const specialCharacterWorkaround = specialCharacterWorkaroundInput.toLowerCase() === 'true';
const useExistingCredentialsInput = core.getInput('use-existing-credentials', { required: false }) || 'false';
const useExistingCredentials = useExistingCredentialsInput.toLowerCase() === 'true';
let maxRetries = Number.parseInt(core.getInput('retry-max-attempts', { required: false })) || 12;
switch (true) {
case specialCharacterWorkaround:
// 😳
disableRetry = false;
maxRetries = 12;
break;
case maxRetries < 1:
maxRetries = 1;
break;
}
for (const managedSessionPolicy of managedSessionPoliciesInput) {
managedSessionPolicies.push({ arn: managedSessionPolicy });
}
// Logic to decide whether to attempt to use OIDC or not
const useGitHubOIDCProvider = () => {
// The `ACTIONS_ID_TOKEN_REQUEST_TOKEN` environment variable is set when the `id-token` permission is granted.
// This is necessary to authenticate with OIDC, but not strictly set just for OIDC. If it is not set and all other
// checks pass, it is likely but not guaranteed that the user needs but lacks this permission in their workflow.
// So, we will log a warning when it is the only piece absent
if (
!!roleToAssume &&
!webIdentityTokenFile &&
!AccessKeyId &&
!process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN &&
!roleChaining
) {
core.info(
'It looks like you might be trying to authenticate with OIDC. Did you mean to set the `id-token` permission? ' +
'If you are not trying to authenticate with OIDC and the action is working successfully, you can ignore this message.',
);
}
return (
!!roleToAssume &&
!!process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN &&
!AccessKeyId &&
!webIdentityTokenFile &&
!roleChaining
);
};
if (unsetCurrentCredentials) {
unsetCredentials();
}
if (!region.match(REGION_REGEX)) {
throw new Error(`Region is not valid: ${region}`);
}
exportRegion(region);
// Instantiate credentials client
const credentialsClient = new CredentialsClient({ region, proxyServer });
let sourceAccountId: string;
let webIdentityToken: string;
//if the user wants to attempt to use existing credentials, check if we have some already
if (useExistingCredentials) {
const validCredentials = await areCredentialsValid(credentialsClient);
if (validCredentials) {
core.notice('Pre-existing credentials are valid. No need to generate new ones.');
return;
}
core.notice('No valid credentials exist. Running as normal.');
}
// If OIDC is being used, generate token
// Else, export credentials provided as input
if (useGitHubOIDCProvider()) {
try {
webIdentityToken = await retryAndBackoff(
async () => {
return core.getIDToken(audience);
},
!disableRetry,
maxRetries,
);
} catch (error) {
throw new Error(`getIDToken call failed: ${errorMessage(error)}`);
}
} else if (AccessKeyId) {
if (!SecretAccessKey) {
throw new Error("'aws-secret-access-key' must be provided if 'aws-access-key-id' is provided");
}
// The STS client for calling AssumeRole pulls creds from the environment.
// Plus, in the assume role case, if the AssumeRole call fails, we want
// the source credentials to already be masked as secrets
// in any error messages.
exportCredentials({ AccessKeyId, SecretAccessKey, SessionToken });
} else if (!webIdentityTokenFile && !roleChaining) {
// Proceed only if credentials can be picked up
await credentialsClient.validateCredentials();
sourceAccountId = await exportAccountId(credentialsClient, maskAccountId);
}
if (AccessKeyId || roleChaining) {
// Validate that the SDK can actually pick up credentials.
// This validates cases where this action is using existing environment credentials,
// and cases where the user intended to provide input credentials but the secrets inputs resolved to empty strings.
await credentialsClient.validateCredentials(AccessKeyId, roleChaining);
sourceAccountId = await exportAccountId(credentialsClient, maskAccountId);
}
// Get role credentials if configured to do so
if (roleToAssume) {
let roleCredentials: AssumeRoleCommandOutput;
do {
roleCredentials = await retryAndBackoff(
async () => {
return assumeRole({
credentialsClient,
sourceAccountId,
roleToAssume,
roleExternalId,
roleDuration,
roleSessionName,
roleSkipSessionTagging,
webIdentityTokenFile,
webIdentityToken,
inlineSessionPolicy,
managedSessionPolicies,
});
},
!disableRetry,
maxRetries,
);
} while (specialCharacterWorkaround && !verifyKeys(roleCredentials.Credentials));
core.info(`Authenticated as assumedRoleId ${roleCredentials.AssumedRoleUser?.AssumedRoleId}`);
exportCredentials(roleCredentials.Credentials, outputCredentials);
// We need to validate the credentials in 2 of our use-cases
// First: self-hosted runners. If the GITHUB_ACTIONS environment variable
// is set to `true` then we are NOT in a self-hosted runner.
// Second: Customer provided credentials manually (IAM User keys stored in GH Secrets)
if (!process.env.GITHUB_ACTIONS || AccessKeyId) {
await credentialsClient.validateCredentials(roleCredentials.Credentials?.AccessKeyId);
}
await exportAccountId(credentialsClient, maskAccountId);
} else {
core.info('Proceeding with IAM user credentials');
}
} catch (error) {
core.setFailed(errorMessage(error));
const showStackTrace = process.env.SHOW_STACK_TRACE;
if (showStackTrace === 'true') {
throw error;
}
}
}
/* c8 ignore start */
/* istanbul ignore next */
if (require.main === module) {
(async () => {
await run();
})().catch((error) => {
core.setFailed(errorMessage(error));
});
}
-48
View File
@@ -1,48 +0,0 @@
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { cleanup } from '../src/cleanup';
import * as core from '@actions/core';
import { mockClient } from 'aws-sdk-client-mock';
import { STSClient } from '@aws-sdk/client-sts';
import mocks from './mockinputs.test';
const mockedSTSClient = mockClient(STSClient);
describe('Configure AWS Credentials cleanup', {}, () => {
beforeEach(() => {
// Reset mock state
vi.restoreAllMocks();
mockedSTSClient.reset();
// Mock GitHub Actions core functions
vi.spyOn(core, 'exportVariable').mockImplementation((_n, _v) => {});
vi.spyOn(core, 'setSecret').mockImplementation((_s) => {});
vi.spyOn(core, 'setFailed').mockImplementation((_m) => {});
vi.spyOn(core, 'setOutput').mockImplementation((_n, _v) => {});
vi.spyOn(core, 'debug').mockImplementation((_m) => {});
vi.spyOn(core, 'info').mockImplementation((_m) => {});
process.env = {
...mocks.envs,
AWS_ACCESS_KEY_ID: 'CLEANUPTEST',
AWS_SECRET_ACCESS_KEY: 'CLEANUPTEST',
AWS_SESSION_TOKEN: 'CLEANUPTEST',
AWS_REGION: 'CLEANUPTEST',
AWS_DEFAULT_REGION: 'CLEANUPTEST',
};
});
it('replaces AWS credential and region environment variables with empty strings', {}, () => {
cleanup();
expect(core.setFailed).toHaveBeenCalledTimes(0);
expect(core.exportVariable).toHaveBeenCalledTimes(5);
expect(core.exportVariable).toHaveBeenCalledWith('AWS_ACCESS_KEY_ID', '');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_SECRET_ACCESS_KEY', '');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_SESSION_TOKEN', '');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_DEFAULT_REGION', '');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_REGION', '');
});
it('handles errors', {}, () => {
vi.spyOn(core, 'exportVariable').mockImplementationOnce(() => {
throw new Error('Test error');
});
cleanup();
expect(core.setFailed).toHaveBeenCalled();
});
});
-45
View File
@@ -1,45 +0,0 @@
import { describe, it, expect, vi } from 'vitest';
import * as helpers from '../src/helpers';
import * as core from '@actions/core';
import { before, beforeEach } from 'node:test';
describe('Configure AWS Credentials helpers', {}, () => {
beforeEach(() => {
vi.restoreAllMocks();
});
it('removes brackets from GitHub Actor', {}, () => {
const actor = 'actor[bot]';
expect(helpers.sanitizeGitHubVariables(actor)).toBe('actor_bot_');
});
it('can sleep', {}, () => {
const sleep = helpers.defaultSleep(10);
expect(Promise.race([sleep, new Promise((_, reject) => setTimeout(reject, 20))])).resolves.toBe(undefined);
});
it('removes special characters from workflow names', {}, () => {
expect(helpers.sanitizeGitHubVariables('sdf234@#$%$^&*()_+{}|:"<>?')).toEqual('sdf234@__________+___:____');
});
it("doesn't retry non-retryable errors", {}, async () => {
const fn = vi.fn().mockRejectedValue('i am not retryable');
await expect(helpers.retryAndBackoff(fn, false)).rejects.toMatch('i am not retryable');
expect(fn).toHaveBeenCalledTimes(1);
});
it('can output creds when told to', {}, () => {
vi.spyOn(core, 'setOutput').mockImplementation(() => {});
vi.spyOn(core, 'setSecret').mockImplementation(() => {});
vi.spyOn(core, 'exportVariable').mockImplementation(() => {});
helpers.exportCredentials({ AccessKeyId: 'test', SecretAccessKey: 'test', SessionToken: 'test', Expiration: new Date(8640000000000000) }, true);
expect(core.setOutput).toHaveBeenCalledTimes(4);
expect(core.setSecret).toHaveBeenCalledTimes(3);
expect(core.exportVariable).toHaveBeenCalledTimes(3);
});
it('can unset credentials', {}, () => {
const env = process.env;
helpers.unsetCredentials();
expect(process.env.AWS_ACCESS_KEY_ID).toBeUndefined;
expect(process.env.AWS_SECRET_ACCESS_KEY).toBeUndefined;
expect(process.env.AWS_SESSION_TOKEN).toBeUndefined;
expect(process.env.AWS_REGION).toBeUndefined;
expect(process.env.AWS_DEFAULT_REGION).toBeUndefined;
process.env = env;
});
});
-316
View File
@@ -1,316 +0,0 @@
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import {
AssumeRoleCommand,
AssumeRoleWithWebIdentityCommand,
GetCallerIdentityCommand,
STSClient,
} from '@aws-sdk/client-sts';
import { fs, vol } from 'memfs';
import * as core from '@actions/core';
import mocks from './mockinputs.test';
import { mockClient } from 'aws-sdk-client-mock';
import { run } from '../src/index';
import { CredentialsClient } from '../src/CredentialsClient';
import { before } from 'node:test';
const mockedSTSClient = mockClient(STSClient);
describe('Configure AWS Credentials', {}, () => {
beforeEach(() => {
// Reset mock state
vi.restoreAllMocks();
mockedSTSClient.reset();
// Mock GitHub Actions core functions
vi.spyOn(core, 'exportVariable').mockImplementation((_n, _v) => {});
vi.spyOn(core, 'setSecret').mockImplementation((_s) => {});
vi.spyOn(core, 'setFailed').mockImplementation((_m) => {});
vi.spyOn(core, 'setOutput').mockImplementation((_n, _v) => {});
vi.spyOn(core, 'debug').mockImplementation((_m) => {});
vi.spyOn(core, 'info').mockImplementation((_m) => {});
vi.spyOn(core, 'notice').mockImplementation((_m) => {});
// Remove any existing environment variables before each test to prevent the
// SDK from picking them up
process.env = { ...mocks.envs };
});
describe('GitHub OIDC Authentication', {}, () => {
beforeEach(() => {
vi.clearAllMocks();
vi.spyOn(core, 'getInput').mockImplementation(mocks.getInput(mocks.GH_OIDC_INPUTS));
vi.spyOn(core, 'getIDToken').mockResolvedValue('testoidctoken');
mockedSTSClient.on(GetCallerIdentityCommand).resolvesOnce({ ...mocks.outputs.GET_CALLER_IDENTITY });
process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN = 'fake-token';
});
it('exports environment variables', async () => {
mockedSTSClient.on(AssumeRoleWithWebIdentityCommand).resolvesOnce(mocks.outputs.STS_CREDENTIALS);
await run();
expect(core.info).toHaveBeenCalledWith('Assuming role with OIDC');
expect(core.info).toHaveBeenCalledWith('Authenticated as assumedRoleId AROAFAKEASSUMEDROLEID');
expect(core.info).toHaveBeenCalledTimes(2);
expect(core.setOutput).toHaveBeenCalledWith('aws-account-id', '111111111111');
expect(core.setOutput).toHaveBeenCalledOnce();
expect(core.setSecret).toHaveBeenCalledWith('STSAWSACCESSKEYID');
expect(core.setSecret).toHaveBeenCalledWith('STSAWSSECRETACCESSKEY');
expect(core.setSecret).toHaveBeenCalledWith('STSAWSSESSIONTOKEN');
expect(core.setSecret).toHaveBeenCalledTimes(3);
expect(core.exportVariable).toHaveBeenCalledWith('AWS_ACCESS_KEY_ID', 'STSAWSACCESSKEYID');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_SECRET_ACCESS_KEY', 'STSAWSSECRETACCESSKEY');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_SESSION_TOKEN', 'STSAWSSESSIONTOKEN');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_REGION', 'fake-region-1');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_DEFAULT_REGION', 'fake-region-1');
expect(core.exportVariable).toHaveBeenCalledTimes(5);
expect(core.setFailed).not.toHaveBeenCalled();
});
it('handles the special character workaround', async () => {
mockedSTSClient
.on(AssumeRoleWithWebIdentityCommand)
.resolvesOnce(mocks.outputs.ODD_CHARACTER_CREDENTIALS)
.resolvesOnce(mocks.outputs.STS_CREDENTIALS);
await run();
expect(core.info).toHaveBeenCalledWith('Assuming role with OIDC');
expect(core.info).toHaveBeenCalledWith('Assuming role with OIDC');
expect(core.info).toHaveBeenCalledWith('Authenticated as assumedRoleId AROAFAKEASSUMEDROLEID');
expect(core.info).toHaveBeenCalledTimes(3);
expect(core.setOutput).toHaveBeenCalledWith('aws-account-id', '111111111111');
expect(core.setOutput).toHaveBeenCalledOnce();
expect(core.setSecret).toHaveBeenCalledWith('STSAWSACCESSKEYID');
expect(core.setSecret).toHaveBeenCalledWith('STSAWSSECRETACCESSKEY');
expect(core.setSecret).toHaveBeenCalledWith('STSAWSSESSIONTOKEN');
expect(core.setSecret).toHaveBeenCalledTimes(3);
expect(core.exportVariable).toHaveBeenCalledWith('AWS_ACCESS_KEY_ID', 'STSAWSACCESSKEYID');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_SECRET_ACCESS_KEY', 'STSAWSSECRETACCESSKEY');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_SESSION_TOKEN', 'STSAWSSESSIONTOKEN');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_REGION', 'fake-region-1');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_DEFAULT_REGION', 'fake-region-1');
expect(core.exportVariable).toHaveBeenCalledTimes(5);
expect(core.setFailed).not.toHaveBeenCalled();
});
});
describe('IAM User Authentication', {}, () => {
beforeEach(() => {
vi.spyOn(core, 'getInput').mockImplementation(mocks.getInput(mocks.IAM_USER_INPUTS));
mockedSTSClient.on(GetCallerIdentityCommand).resolvesOnce({ ...mocks.outputs.GET_CALLER_IDENTITY });
// biome-ignore lint/suspicious/noExplicitAny: any required to mock private method
vi.spyOn(CredentialsClient.prototype as any, 'loadCredentials').mockResolvedValueOnce({
accessKeyId: 'MYAWSACCESSKEYID',
});
});
it('exports environment variables', async () => {
await run();
expect(core.exportVariable).toHaveBeenCalledWith('AWS_ACCESS_KEY_ID', 'MYAWSACCESSKEYID');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_SECRET_ACCESS_KEY', 'MYAWSSECRETACCESSKEY');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_REGION', 'fake-region-1');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_DEFAULT_REGION', 'fake-region-1');
expect(core.exportVariable).toHaveBeenCalledTimes(4);
expect(core.setSecret).toHaveBeenCalledWith('MYAWSACCESSKEYID');
expect(core.setSecret).toHaveBeenCalledWith('MYAWSSECRETACCESSKEY');
expect(core.setSecret).toHaveBeenCalledTimes(2);
expect(core.setOutput).toHaveBeenCalledWith('aws-account-id', '111111111111');
expect(core.setOutput).toHaveBeenCalledOnce();
expect(core.info).toHaveBeenCalledWith('Proceeding with IAM user credentials');
expect(core.info).toHaveBeenCalledOnce();
expect(core.setFailed).not.toHaveBeenCalled();
});
});
describe('AssumeRole with IAM LTC', {}, () => {
beforeEach(() => {
vi.spyOn(core, 'getInput').mockImplementation(mocks.getInput(mocks.IAM_ASSUMEROLE_INPUTS));
mockedSTSClient.on(AssumeRoleCommand).resolvesOnce(mocks.outputs.STS_CREDENTIALS);
mockedSTSClient.on(GetCallerIdentityCommand).resolves({ ...mocks.outputs.GET_CALLER_IDENTITY }); // 3 times
// biome-ignore lint/suspicious/noExplicitAny: any required to mock private method
vi.spyOn(CredentialsClient.prototype as any, 'loadCredentials')
.mockResolvedValueOnce({ accessKeyId: 'MYAWSACCESSKEYID' })
.mockResolvedValueOnce({ accessKeyId: 'STSAWSACCESSKEYID' });
});
it('exports environment variables', async () => {
await run();
expect(core.exportVariable).toHaveBeenCalledWith('AWS_DEFAULT_REGION', 'fake-region-1');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_REGION', 'fake-region-1');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_ACCESS_KEY_ID', 'MYAWSACCESSKEYID');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_SECRET_ACCESS_KEY', 'MYAWSSECRETACCESSKEY');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_ACCESS_KEY_ID', 'STSAWSACCESSKEYID');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_SECRET_ACCESS_KEY', 'STSAWSSECRETACCESSKEY');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_SESSION_TOKEN', 'STSAWSSESSIONTOKEN');
expect(core.exportVariable).toHaveBeenCalledTimes(7);
expect(core.setSecret).toHaveBeenCalledWith('STSAWSACCESSKEYID');
expect(core.setSecret).toHaveBeenCalledWith('STSAWSSECRETACCESSKEY');
expect(core.setSecret).toHaveBeenCalledWith('STSAWSSESSIONTOKEN');
expect(core.setSecret).toHaveBeenCalledWith('MYAWSACCESSKEYID');
expect(core.setSecret).toHaveBeenCalledWith('MYAWSSECRETACCESSKEY');
expect(core.setSecret).toHaveBeenCalledTimes(5);
expect(core.setOutput).toHaveBeenCalledWith('aws-account-id', '111111111111');
expect(core.setOutput).toHaveBeenCalledTimes(2);
expect(core.info).toHaveBeenCalledWith('Assuming role with user credentials');
expect(core.info).toHaveBeenCalledWith('Authenticated as assumedRoleId AROAFAKEASSUMEDROLEID');
expect(core.info).toHaveBeenCalledTimes(2);
});
});
describe('AssumeRole with WebIdentityTokeFile', {}, () => {
beforeEach(() => {
vi.spyOn(core, 'getInput').mockImplementation(mocks.getInput(mocks.WEBIDENTITY_TOKEN_FILE_INPUTS));
mockedSTSClient.on(AssumeRoleWithWebIdentityCommand).resolvesOnce(mocks.outputs.STS_CREDENTIALS);
mockedSTSClient.on(GetCallerIdentityCommand).resolvesOnce({ ...mocks.outputs.GET_CALLER_IDENTITY });
vi.mock('node:fs');
vol.reset();
fs.mkdirSync('/home/github', { recursive: true });
fs.writeFileSync('/home/github/file.txt', 'test-token');
});
it('exports environment variables', async () => {
await run();
expect(core.info).toHaveBeenCalledWith('Assuming role with web identity token file');
expect(core.info).toHaveBeenCalledWith('Authenticated as assumedRoleId AROAFAKEASSUMEDROLEID');
expect(core.info).toHaveBeenCalledTimes(2);
expect(core.exportVariable).toHaveBeenCalledWith('AWS_DEFAULT_REGION', 'fake-region-1');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_REGION', 'fake-region-1');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_ACCESS_KEY_ID', 'STSAWSACCESSKEYID');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_SECRET_ACCESS_KEY', 'STSAWSSECRETACCESSKEY');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_SESSION_TOKEN', 'STSAWSSESSIONTOKEN');
expect(core.exportVariable).toHaveBeenCalledTimes(5);
expect(core.setSecret).toHaveBeenCalledWith('STSAWSACCESSKEYID');
expect(core.setSecret).toHaveBeenCalledWith('STSAWSSECRETACCESSKEY');
expect(core.setSecret).toHaveBeenCalledWith('STSAWSSESSIONTOKEN');
expect(core.setSecret).toHaveBeenCalledTimes(3);
expect(core.setOutput).toHaveBeenCalledWith('aws-account-id', '111111111111');
expect(core.setOutput).toHaveBeenCalledTimes(1);
expect(core.setFailed).not.toHaveBeenCalled();
});
});
describe('Assume existing role', {}, () => {
beforeEach(() => {
mockedSTSClient.on(AssumeRoleCommand).resolves(mocks.outputs.STS_CREDENTIALS);
mockedSTSClient.on(GetCallerIdentityCommand).resolves({ ...mocks.outputs.GET_CALLER_IDENTITY });
process.env = { ...mocks.envs };
});
it('exports environment variables from env variables', async () => {
vi.spyOn(core, 'getInput').mockImplementation(mocks.getInput(mocks.EXISTING_ROLE_INPUTS));
process.env.AWS_ACCESS_KEY_ID = 'MYAWSACCESSKEYID';
process.env.AWS_SECRET_ACCESS_KEY = 'MYAWSSECRETACCESSKEY';
process.env.AWS_SESSION_TOKEN = 'MYAWSSESSIONTOKEN';
await run();
expect(core.info).toHaveBeenCalledWith('Assuming role with user credentials');
expect(core.info).toHaveBeenCalledWith('Authenticated as assumedRoleId AROAFAKEASSUMEDROLEID');
expect(core.info).toHaveBeenCalledTimes(2);
expect(core.exportVariable).toHaveBeenCalledWith('AWS_DEFAULT_REGION', 'fake-region-1');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_REGION', 'fake-region-1');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_ACCESS_KEY_ID', 'STSAWSACCESSKEYID');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_SECRET_ACCESS_KEY', 'STSAWSSECRETACCESSKEY');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_SESSION_TOKEN', 'STSAWSSESSIONTOKEN');
expect(core.exportVariable).toHaveBeenCalledTimes(5);
expect(core.setSecret).toHaveBeenCalledWith('STSAWSACCESSKEYID');
expect(core.setSecret).toHaveBeenCalledWith('STSAWSSECRETACCESSKEY');
expect(core.setSecret).toHaveBeenCalledWith('STSAWSSESSIONTOKEN');
expect(core.setSecret).toHaveBeenCalledTimes(3);
expect(core.setOutput).toHaveBeenCalledWith('aws-account-id', '111111111111');
expect(core.setOutput).toHaveBeenCalledTimes(2);
expect(core.setFailed).not.toHaveBeenCalled();
});
it('exports environment variables from inputs', {}, async () => {
vi.spyOn(core, 'getInput').mockImplementation(
mocks.getInput({
...mocks.EXISTING_ROLE_INPUTS,
'aws-access-key-id': 'MYAWSACCESSKEYID',
'aws-secret-access-key': 'MYAWSSECRETACCESSKEY',
'aws-session-token': 'MYAWSSESSIONTOKEN',
}),
);
// biome-ignore lint/suspicious/noExplicitAny: any required to mock private method
vi.spyOn(CredentialsClient.prototype as any, 'loadCredentials')
.mockResolvedValueOnce({
accessKeyId: 'MYAWSACCESSKEYID',
})
.mockResolvedValueOnce({ accessKeyId: 'STSAWSACCESSKEYID' });
await run();
expect(core.info).toHaveBeenCalledWith('Assuming role with user credentials');
expect(core.info).toHaveBeenCalledWith('Authenticated as assumedRoleId AROAFAKEASSUMEDROLEID');
expect(core.info).toHaveBeenCalledTimes(2);
expect(core.exportVariable).toHaveBeenCalledWith('AWS_DEFAULT_REGION', 'fake-region-1');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_REGION', 'fake-region-1');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_ACCESS_KEY_ID', 'STSAWSACCESSKEYID');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_SECRET_ACCESS_KEY', 'STSAWSSECRETACCESSKEY');
expect(core.exportVariable).toHaveBeenCalledWith('AWS_SESSION_TOKEN', 'STSAWSSESSIONTOKEN');
expect(core.exportVariable).toHaveBeenCalledTimes(8);
expect(core.setSecret).toHaveBeenCalledWith('STSAWSACCESSKEYID');
expect(core.setSecret).toHaveBeenCalledWith('STSAWSSECRETACCESSKEY');
expect(core.setSecret).toHaveBeenCalledWith('STSAWSSESSIONTOKEN');
expect(core.setSecret).toHaveBeenCalledTimes(6);
expect(core.setOutput).toHaveBeenCalledWith('aws-account-id', '111111111111');
expect(core.setOutput).toHaveBeenCalledTimes(2);
expect(core.setFailed).not.toHaveBeenCalled();
});
});
describe('Odd inputs', {}, () => {
it('fails when github env vars are missing', {}, async () => {
vi.spyOn(core, 'getInput').mockImplementation(mocks.getInput(mocks.IAM_USER_INPUTS));
delete process.env.GITHUB_REPOSITORY;
delete process.env.GITHUB_SHA;
await run();
expect(core.setFailed).toHaveBeenCalled();
});
it('does not fail if GITHUB_REF is missing', {}, async () => {
vi.spyOn(core, 'getInput').mockImplementation(mocks.getInput(mocks.IAM_USER_INPUTS));
mockedSTSClient.on(GetCallerIdentityCommand).resolvesOnce({ ...mocks.outputs.GET_CALLER_IDENTITY });
// biome-ignore lint/suspicious/noExplicitAny: any required to mock private method
vi.spyOn(CredentialsClient.prototype as any, 'loadCredentials').mockResolvedValueOnce({
accessKeyId: 'MYAWSACCESSKEYID',
});
delete process.env.GITHUB_REF;
await run();
expect(core.setFailed).not.toHaveBeenCalled();
});
it('fails with an invalid region', {}, async () => {
vi.spyOn(core, 'getInput').mockImplementation(mocks.getInput({ 'aws-region': '$|<1B1D1 701L37' }));
await run();
expect(core.setFailed).toHaveBeenCalled();
});
it('fails if access key id is provided without secret access key', {}, async () => {
vi.spyOn(core, 'getInput').mockImplementation(
mocks.getInput({ ...mocks.IAM_USER_INPUTS, 'aws-secret-access-key': '' }),
);
await run();
expect(core.setFailed).toHaveBeenCalled();
});
it('handles improper retry-max-attempts input', {}, async () => {
// This should mean we retry one time
vi.spyOn(core, 'getInput').mockImplementation(
mocks.getInput({
...mocks.GH_OIDC_INPUTS,
'retry-max-attempts': '-1',
'special-characters-workaround': 'false',
}),
);
vi.spyOn(core, 'getIDToken').mockResolvedValue('testoidctoken');
mockedSTSClient.on(GetCallerIdentityCommand).resolvesOnce({ ...mocks.outputs.GET_CALLER_IDENTITY });
process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN = 'fake-token';
mockedSTSClient
.on(AssumeRoleWithWebIdentityCommand)
.rejectsOnce(new Error('test error'))
.rejectsOnce(new Error('test error'))
.resolvesOnce(mocks.outputs.STS_CREDENTIALS);
await run();
expect(core.setFailed).toHaveBeenCalled();
});
it('fails if doing OIDC without the ACTIONS_ID_TOKEN_REQUEST_TOKEN', {}, async () => {
vi.spyOn(core, 'getInput').mockImplementation(mocks.getInput(mocks.GH_OIDC_INPUTS));
delete process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN;
await run();
expect(core.setFailed).toHaveBeenCalled();
});
it('gets new creds if told to reuse existing but they\'re invalid', {}, async () => {
vi.spyOn(core, 'getInput').mockImplementation(mocks.getInput(mocks.USE_EXISTING_CREDENTIALS_INPUTS));
mockedSTSClient.on(GetCallerIdentityCommand).rejects();
await run();
expect(core.notice).toHaveBeenCalledWith('No valid credentials exist. Running as normal.')
});
it('doesn\'t get new creds if there are already valid ones and we said use them', {}, async () => {
vi.spyOn(core, 'getInput').mockImplementation(mocks.getInput(mocks.USE_EXISTING_CREDENTIALS_INPUTS));
mockedSTSClient.on(GetCallerIdentityCommand).resolves(mocks.outputs.GET_CALLER_IDENTITY);
await run();
expect(core.setFailed).not.toHaveBeenCalled();
})
});
});
-103
View File
@@ -1,103 +0,0 @@
import type * as core from '@actions/core';
const inputs = {
GH_OIDC_INPUTS: {
'role-to-assume': 'arn:aws:iam::111111111111:role/MY-ROLE',
'aws-region': 'fake-region-1',
'special-characters-workaround': 'true',
},
IAM_USER_INPUTS: {
'aws-access-key-id': 'MYAWSACCESSKEYID',
'aws-secret-access-key': 'MYAWSSECRETACCESSKEY',
'aws-region': 'fake-region-1',
},
IAM_ASSUMEROLE_INPUTS: {
'aws-access-key-id': 'MYAWSACCESSKEYID',
'aws-secret-access-key': 'MYAWSSECRETACCESSKEY',
'role-to-assume': 'arn:aws:iam::111111111111:role/MY-ROLE',
'aws-region': 'fake-region-1',
},
WEBIDENTITY_TOKEN_FILE_INPUTS: {
'web-identity-token-file': 'file.txt',
'role-to-assume': 'arn:aws:iam::111111111111:role/MY-ROLE',
'aws-region': 'fake-region-1',
},
EXISTING_ROLE_INPUTS: {
'role-to-assume': 'arn:aws:iam::111111111111:role/MY-ROLE',
'role-chaining': 'true',
'aws-region': 'fake-region-1',
},
USE_EXISTING_CREDENTIALS_INPUTS: {
'aws-region': 'fake-region-1',
'use-existing-credentials': 'true',
'role-to-assume': 'arn:aws:iam::111111111111:role/MY-ROLE',
}
};
const envs = {
GITHUB_REPOSITORY: 'MY-REPOSITORY-NAME',
GITHUB_WORKFLOW: 'MY-WORKFLOW-ID',
GITHUB_ACTION: 'MY-ACTION-NAME',
GITHUB_ACTOR: 'MY-USERNAME[bot]',
GITHUB_SHA: 'MY-COMMIT-ID',
GITHUB_WORKSPACE: '/home/github',
GITHUB_ACTIONS: 'true',
};
const outputs = {
STS_CREDENTIALS: {
Credentials: {
AccessKeyId: 'STSAWSACCESSKEYID',
SecretAccessKey: 'STSAWSSECRETACCESSKEY',
SessionToken: 'STSAWSSESSIONTOKEN',
Expiration: new Date(8640000000000000),
},
AssumedRoleUser: {
Arn: 'arn:aws:sts::111111111111:assumed-role/MY-ROLE/',
AssumedRoleId: 'AROAFAKEASSUMEDROLEID',
},
},
GET_CALLER_IDENTITY: {
Account: '111111111111',
Arn: 'arn:aws:iam::111111111111:role/MY-ROLE',
},
FAKE_STS_ACCESS_KEY_ID: 'STSAWSACCESSKEYID',
FAKE_STS_SECRET_ACCESS_KEY: 'STSAWSSECRETACCESSKEY',
FAKE_STS_SESSION_TOKEN: 'STSAWSSESSIONTOKEN',
ODD_CHARACTER_CREDENTIALS: {
Credentials: {
AccessKeyId: 'STSA#$%^&',
SecretAccessKey: 'STSA#$%^&Key',
SessionToken: 'STSA#$%^',
Expiration: new Date(8640000000000000),
},
AssumedRoleUser: {
Arn: 'arn:aws:sts::111111111111:assumed-role/MY-ROLE/',
AssumedRoleId: 'AROAFAKEASSUMEDROLEID',
},
},
};
export default {
getInput: (fakeEnv: Record<string, string>) => {
return (name: string, options?: core.InputOptions): string => {
if (!fakeEnv[name]) {
if (options?.required) throw new Error(`Input ${name} not found`);
return '';
}
return fakeEnv[name];
};
},
getMultilineInput: (fakeEnv: Record<string, string[]>) => {
return (name: string, options?: core.InputOptions): string[] => {
if (!fakeEnv[name]) {
if (options?.required) throw new Error(`Input ${name} not found`);
return [];
}
return fakeEnv[name];
};
},
...inputs,
outputs,
envs,
} as const;
-35
View File
@@ -1,35 +0,0 @@
{
"compilerOptions": {
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"strict": true,
"exactOptionalPropertyTypes": false,
"noFallthroughCasesInSwitch": true,
"noImplicitOverride": true,
"noImplicitReturns": true,
"noPropertyAccessFromIndexSignature": false,
"noUncheckedIndexedAccess": true,
"noUnusedParameters": true,
"module": "CommonJS",
"resolveJsonModule": true,
"outDir": "build",
"declaration": false,
"newLine": "lf",
"noEmitOnError": true,
"sourceMap": true,
"disableSizeLimit": true,
"forceConsistentCasingInFileNames": true,
"lib": [ "ES2020" ],
"target": "ES2020",
"noErrorTruncation": true,
"esModuleInterop": true,
"rootDir": "src",
},
"include": [
"src/**/*.ts"
],
"exclude": [
"test/**/*.ts"
],
}
-11
View File
@@ -1,11 +0,0 @@
{
"extends": "./tsconfig.json",
"include": [
"test/**/*.ts",
"src/**/*.ts"
],
"exclude": [],
"compilerOptions": {
"rootDir": "./"
},
}
-10
View File
@@ -1,10 +0,0 @@
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
passWithNoTests: true,
include: ['test/**/*.test.ts'],
coverage: { enabled: true },
typecheck: { tsconfig: './tsconfig.test.json' },
},
});