Compare commits

..

47 Commits

Author SHA1 Message Date
AWS SDKs and Tools bot a03048d875 chore(main): release 5.0.0 (#1451) 2025-09-03 12:07:05 -07:00
Tom Keller 337f510212 chore: Fix markdown link formatting in README.md (#1466) 2025-09-03 18:41:20 +00:00
Tom Keller f001d79eaa chore: update README with versioning (#1465)
* chore: update README with versioning and license info

* chore: fix typo
2025-09-03 11:35:44 -07:00
GitHub Actions cf5f2acba3 chore: Update dist 2025-09-03 18:25:19 +00:00
dependabot[bot] b394bdd9f0 chore(deps-dev): bump @aws-sdk/credential-provider-env (#1463)
Bumps [@aws-sdk/credential-provider-env](https://github.com/aws/aws-sdk-js-v3/tree/HEAD/packages/credential-provider-env) from 3.876.0 to 3.879.0.
- [Release notes](https://github.com/aws/aws-sdk-js-v3/releases)
- [Changelog](https://github.com/aws/aws-sdk-js-v3/blob/main/packages/credential-provider-env/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-js-v3/commits/v3.879.0/packages/credential-provider-env)

---
updated-dependencies:
- dependency-name: "@aws-sdk/credential-provider-env"
  dependency-version: 3.879.0
  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>
2025-09-03 18:24:41 +00:00
dependabot[bot] b632c0b5e4 chore(deps-dev): bump memfs from 4.38.1 to 4.38.2 (#1462)
Bumps [memfs](https://github.com/streamich/memfs) from 4.38.1 to 4.38.2.
- [Release notes](https://github.com/streamich/memfs/releases)
- [Changelog](https://github.com/streamich/memfs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/streamich/memfs/compare/v4.38.1...v4.38.2)

---
updated-dependencies:
- dependency-name: memfs
  dependency-version: 4.38.2
  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>
2025-09-03 11:21:36 -07:00
GitHub Actions 978e44aa36 chore: Update dist 2025-09-02 17:38:48 +00:00
Tom Keller c4be498953 feat: support account id allowlist (#1456)
* feat: support account id allowlist

* chore: update readme

---------

Co-authored-by: Michael Lehmann <lehmanmj@amazon.com>
2025-09-02 10:38:09 -07:00
GitHub Actions c5a43c32e1 chore: Update dist 2025-08-30 00:25:47 +00:00
Tom Keller 8c45f6b081 feat: add skip OIDC option (#1458) 2025-08-29 17:25:09 -07:00
Tom Keller a5c87b6a6b chore: update OS matrix in inline-policy for tests-integ-release.yml (#1461)
Removed Windows from the OS matrix in the workflow.
2025-08-29 17:18:16 -07:00
Michael Lehmann 45a41642bb chore: make script inline (#1460)
* add pre-release integ tests

* chore: remove unnecessary sudo and reorganize test files

* chore: inline write token file
2025-08-30 00:11:06 +00:00
Michael Lehmann cb3b499674 chore: redact s3 contents 2025-08-29 16:48:11 -07:00
Michael Lehmann ec8e002276 chore: add pre-release integ tests (#1457)
* add pre-release integ tests

* chore: remove unnecessary sudo and reorganize test files
2025-08-29 16:34:59 -07:00
GitHub Actions 1b2b73eb6a chore: Update dist 2025-08-27 18:21:12 +00:00
dependabot[bot] e30ac4daac chore(deps-dev): bump @aws-sdk/credential-provider-env (#1453)
Bumps [@aws-sdk/credential-provider-env](https://github.com/aws/aws-sdk-js-v3/tree/HEAD/packages/credential-provider-env) from 3.864.0 to 3.873.0.
- [Release notes](https://github.com/aws/aws-sdk-js-v3/releases)
- [Changelog](https://github.com/aws/aws-sdk-js-v3/blob/main/packages/credential-provider-env/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-js-v3/commits/v3.873.0/packages/credential-provider-env)

---
updated-dependencies:
- dependency-name: "@aws-sdk/credential-provider-env"
  dependency-version: 3.873.0
  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>
2025-08-27 18:20:31 +00:00
GitHub Actions 195dc25ad5 chore: Update dist 2025-08-26 23:30:06 +00:00
dependabot[bot] c284255d3b chore(deps): bump @aws-sdk/client-sts from 3.864.0 to 3.873.0 (#1455)
Bumps [@aws-sdk/client-sts](https://github.com/aws/aws-sdk-js-v3/tree/HEAD/clients/client-sts) from 3.864.0 to 3.873.0.
- [Release notes](https://github.com/aws/aws-sdk-js-v3/releases)
- [Changelog](https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-sts/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-js-v3/commits/v3.873.0/clients/client-sts)

---
updated-dependencies:
- dependency-name: "@aws-sdk/client-sts"
  dependency-version: 3.873.0
  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>
2025-08-26 23:29:29 +00:00
dependabot[bot] bee3104844 chore(deps-dev): bump @biomejs/biome from 2.2.0 to 2.2.2 (#1454)
Bumps [@biomejs/biome](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome) from 2.2.0 to 2.2.2.
- [Release notes](https://github.com/biomejs/biome/releases)
- [Changelog](https://github.com/biomejs/biome/blob/main/packages/@biomejs/biome/CHANGELOG.md)
- [Commits](https://github.com/biomejs/biome/commits/@biomejs/biome@2.2.2/packages/@biomejs/biome)

---
updated-dependencies:
- dependency-name: "@biomejs/biome"
  dependency-version: 2.2.2
  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: Tom Keller <1083460+kellertk@users.noreply.github.com>
2025-08-26 23:27:07 +00:00
dependabot[bot] 241c954d31 chore(deps-dev): bump memfs from 4.36.3 to 4.38.1 (#1452)
Bumps [memfs](https://github.com/streamich/memfs) from 4.36.3 to 4.38.1.
- [Release notes](https://github.com/streamich/memfs/releases)
- [Changelog](https://github.com/streamich/memfs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/streamich/memfs/compare/v4.36.3...v4.38.1)

---
updated-dependencies:
- dependency-name: memfs
  dependency-version: 4.38.1
  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>
2025-08-26 20:33:49 +00:00
Tom Keller 0eb446ecb2 chore: update last release sha (#1450) 2025-08-20 13:02:28 -07:00
Tom Keller bd1e9e7da1 chore: exclude dist and github from release-processing (#1447) 2025-08-20 11:48:11 -07:00
GitHub Actions 0be2363ca1 chore: Update dist 2025-08-20 18:37:20 +00:00
Tom Keller 74b3e27aa8 chore: cleanup input handling (#1445)
Co-authored-by: Michael Lehmann <lehmanmj@amazon.com>
2025-08-20 11:36:42 -07:00
kellertk df886f22da chore: tests-unit update 2025-08-20 09:48:34 -07:00
GitHub Actions a688da0051 chore: Update dist 2025-08-20 02:51:17 +00:00
dependabot[bot] 4a45167436 chore(deps-dev): bump @biomejs/biome from 2.1.4 to 2.2.0 (#1440)
* chore(deps-dev): bump @biomejs/biome from 2.1.4 to 2.2.0

Bumps [@biomejs/biome](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome) from 2.1.4 to 2.2.0.
- [Release notes](https://github.com/biomejs/biome/releases)
- [Changelog](https://github.com/biomejs/biome/blob/main/packages/@biomejs/biome/CHANGELOG.md)
- [Commits](https://github.com/biomejs/biome/commits/@biomejs/biome@2.2.0/packages/@biomejs/biome)

---
updated-dependencies:
- dependency-name: "@biomejs/biome"
  dependency-version: 2.2.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

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

* chore: apply updated linting rules

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: kellertk <kellertk@amazon.com>
2025-08-20 02:50:43 +00:00
dependabot[bot] 0928ae2f74 chore(deps-dev): bump memfs from 4.36.0 to 4.36.3 (#1442)
Bumps [memfs](https://github.com/streamich/memfs) from 4.36.0 to 4.36.3.
- [Release notes](https://github.com/streamich/memfs/releases)
- [Changelog](https://github.com/streamich/memfs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/streamich/memfs/compare/v4.36.0...v4.36.3)

---
updated-dependencies:
- dependency-name: memfs
  dependency-version: 4.36.3
  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>
2025-08-19 22:56:48 +00:00
dependabot[bot] 28c84c0297 chore(deps-dev): bump @types/node from 24.2.1 to 24.3.0 (#1443)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 24.2.1 to 24.3.0.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 24.3.0
  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: Tom Keller <1083460+kellertk@users.noreply.github.com>
2025-08-19 22:54:30 +00:00
dependabot[bot] 09a74e37ce chore(deps-dev): bump cpy-cli from 5.0.0 to 6.0.0 (#1441)
Bumps [cpy-cli](https://github.com/sindresorhus/cpy-cli) from 5.0.0 to 6.0.0.
- [Release notes](https://github.com/sindresorhus/cpy-cli/releases)
- [Commits](https://github.com/sindresorhus/cpy-cli/compare/v5.0.0...v6.0.0)

---
updated-dependencies:
- dependency-name: cpy-cli
  dependency-version: 6.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-19 13:19:33 +00:00
Tom Keller 3821430d17 chore: update post-release integ test 2025-08-15 15:42:07 -07:00
Tom Keller 3df3b9e987 use correct ref 2025-08-15 15:29:45 -07:00
Tom Keller a91a6303b8 chore: create tests-integ.yml 2025-08-15 15:29:45 -07:00
dependabot[bot] 209f2a4450 chore(deps-dev): bump @types/node from 24.2.0 to 24.2.1 (#1430)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 24.2.0 to 24.2.1.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 24.2.1
  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>
2025-08-12 18:10:40 +00:00
dependabot[bot] 92fa2639a8 chore(deps-dev): bump @biomejs/biome from 2.1.3 to 2.1.4 (#1433)
Bumps [@biomejs/biome](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome) from 2.1.3 to 2.1.4.
- [Release notes](https://github.com/biomejs/biome/releases)
- [Changelog](https://github.com/biomejs/biome/blob/main/packages/@biomejs/biome/CHANGELOG.md)
- [Commits](https://github.com/biomejs/biome/commits/@biomejs/biome@2.1.4/packages/@biomejs/biome)

---
updated-dependencies:
- dependency-name: "@biomejs/biome"
  dependency-version: 2.1.4
  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>
2025-08-12 18:06:49 +00:00
GitHub Actions 5505db6539 chore: Update dist 2025-08-12 17:57:14 +00:00
dependabot[bot] 51e8c081a1 chore(deps): bump @aws-sdk/client-sts from 3.859.0 to 3.864.0 (#1431)
Bumps [@aws-sdk/client-sts](https://github.com/aws/aws-sdk-js-v3/tree/HEAD/clients/client-sts) from 3.859.0 to 3.864.0.
- [Release notes](https://github.com/aws/aws-sdk-js-v3/releases)
- [Changelog](https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-sts/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-js-v3/commits/v3.864.0/clients/client-sts)

---
updated-dependencies:
- dependency-name: "@aws-sdk/client-sts"
  dependency-version: 3.864.0
  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>
2025-08-12 17:56:35 +00:00
GitHub Actions 00dc4f2d3d chore: Update dist 2025-08-12 17:53:48 +00:00
dependabot[bot] 24a1539a9c chore(deps-dev): bump @aws-sdk/credential-provider-env (#1435)
Bumps [@aws-sdk/credential-provider-env](https://github.com/aws/aws-sdk-js-v3/tree/HEAD/packages/credential-provider-env) from 3.858.0 to 3.864.0.
- [Release notes](https://github.com/aws/aws-sdk-js-v3/releases)
- [Changelog](https://github.com/aws/aws-sdk-js-v3/blob/main/packages/credential-provider-env/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-js-v3/commits/v3.864.0/packages/credential-provider-env)

---
updated-dependencies:
- dependency-name: "@aws-sdk/credential-provider-env"
  dependency-version: 3.864.0
  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: Tom Keller <1083460+kellertk@users.noreply.github.com>
2025-08-12 17:53:08 +00:00
dependabot[bot] 4cc620671e chore(deps): bump @smithy/node-http-handler from 4.1.0 to 4.1.1 (#1429)
Bumps [@smithy/node-http-handler](https://github.com/smithy-lang/smithy-typescript/tree/HEAD/packages/node-http-handler) from 4.1.0 to 4.1.1.
- [Release notes](https://github.com/smithy-lang/smithy-typescript/releases)
- [Changelog](https://github.com/smithy-lang/smithy-typescript/blob/main/packages/node-http-handler/CHANGELOG.md)
- [Commits](https://github.com/smithy-lang/smithy-typescript/commits/@smithy/node-http-handler@4.1.1/packages/node-http-handler)

---
updated-dependencies:
- dependency-name: "@smithy/node-http-handler"
  dependency-version: 4.1.1
  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>
2025-08-12 11:02:38 +00:00
dependabot[bot] aa1f74b81b chore(deps-dev): bump @types/node from 24.1.0 to 24.2.0 (#1427)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 24.1.0 to 24.2.0.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 24.2.0
  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: Tom Keller <1083460+kellertk@users.noreply.github.com>
2025-08-05 15:23:01 +00:00
dependabot[bot] 2de20cdfbc chore(deps-dev): bump memfs from 4.35.0 to 4.36.0 (#1426)
Bumps [memfs](https://github.com/streamich/memfs) from 4.35.0 to 4.36.0.
- [Release notes](https://github.com/streamich/memfs/releases)
- [Changelog](https://github.com/streamich/memfs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/streamich/memfs/compare/v4.35.0...v4.36.0)

---
updated-dependencies:
- dependency-name: memfs
  dependency-version: 4.36.0
  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>
2025-08-05 09:52:29 +00:00
AWS SDKs and Tools bot 7474bc4690 chore(main): release 4.3.1 2025-08-04 16:23:36 -07:00
Tom Keller be2e7ad815 fix: update readme to 4.3.1 (#1424)
This is a fix instead of a chore to force a 4.3.1 tag

Release-as: 4.3.1
2025-08-04 23:17:49 +00:00
Michael Lehmann 4a9906ba73 Merge pull request #1422 from aws-actions/lehmanmj-patch-2
chore: Update README.md
2025-08-04 13:54:52 -07:00
Michael Lehmann 83a7f06197 Update README.md
update readme with latest version
2025-08-04 13:52:04 -07:00
Tom Keller b8b4fdbcd4 Update CHANGELOG.md 2025-08-04 13:47:32 -07:00
20 changed files with 3276 additions and 1669 deletions
+6
View File
@@ -0,0 +1,6 @@
Port 9999
Listen 127.0.0.1
Timeout 600
Allow 127.0.0.1
LogFile "/home/runner/work/configure-aws-credentials/configure-aws-credentials/integ_proxy_log.txt"
LogLevel Connect
+32
View File
@@ -0,0 +1,32 @@
name: Run post-release integration test
on:
push:
branches:
- main
paths:
- 'dist/**'
workflow_dispatch:
jobs:
package_and_test:
name: Package dist files
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- name: Checkout
uses: actions/checkout@v5
with:
fetch-depth: 0
persist-credentials: false
- name: Integation tests
uses: ./
with:
aws-region: us-west-2
role-to-assume: ${{ secrets.CAWSC_integ_role }}
role-session-name: IntegTestCAWSC
- name: Get caller identity
run: |
aws sts get-caller-identity
+202
View File
@@ -0,0 +1,202 @@
name: Run pre-release integ tests
on:
pull_request_target:
permissions:
contents: read
jobs:
oidc:
if: ${{ github.event.pull_request.user.login == 'aws-sdk-osds' && github.repository == 'aws-actions/configure-aws-credentials' }}
permissions:
id-token: write
strategy:
fail-fast: false
matrix:
os: [windows-latest, ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }}
name: OIDC login test
steps:
- name: checkout
uses: actions/checkout@v5
with:
fetch-depth: 0
persist-credentials: false
- name: Configure AWS credentials
uses: ./
with:
aws-region: us-west-2
role-to-assume: ${{ secrets.OIDC_integ_role }}
- name: Get Caller Identity
run: |
aws sts get-caller-identity
#can cut this test out if it's not necessary
static_assumeRole:
if: ${{ github.event.pull_request.user.login == 'aws-sdk-osds' && github.repository == 'aws-actions/configure-aws-credentials' }}
strategy:
fail-fast: false
matrix:
os: [windows-latest, ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }}
name: Static IAM creds test
steps:
- name: checkout
uses: actions/checkout@v5
with:
fetch-depth: 0
persist-credentials: false
- name: Configure AWS credentials
uses: ./
with:
aws-region: us-west-2
aws-access-key-id: ${{ secrets.STATIC_ak_id }}
aws-secret-access-key: ${{ secrets.STATIC_secret_ak }}
role-to-assume: ${{ secrets.STATIC_role }}
- name: Get Caller Identity
run: |
aws sts get-caller-identity
role_chaining:
if: ${{ github.event.pull_request.user.login == 'aws-sdk-osds' && github.repository == 'aws-actions/configure-aws-credentials' }}
permissions:
id-token: write
strategy:
fail-fast: false
matrix:
os: [windows-latest, ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }}
name: Existing Creds + Role Chaining test
steps:
- name: checkout
uses: actions/checkout@v5
with:
fetch-depth: 0
persist-credentials: false
- name: Configure AWS credentials
uses: ./
with:
aws-region: us-west-2
role-to-assume: ${{ secrets.ROLE_chaining_1 }}
- name: Get Caller Identity
run: |
aws sts get-caller-identity
- name: assume second role
uses: ./
with:
aws-region: us-west-2
role-to-assume: ${{ secrets.ROLE_chaining_2 }}
role-chaining: true
- name: get caller identity
run: |
aws sts get-caller-identity
inline_policy:
if: ${{ github.event.pull_request.user.login == 'aws-sdk-osds' && github.repository == 'aws-actions/configure-aws-credentials' }}
permissions:
id-token: write
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }}
name: Inline Policy Test
steps:
- name: checkout
uses: actions/checkout@v5
with:
fetch-depth: 0
persist-credentials: false
- name: get creds w scoped down policy
uses: ./
with:
aws-region: us-west-2
role-to-assume: ${{ secrets.INLINE_policy_role }}
inline-session-policy: '{"Version":"2012-10-17","Statement":[{"Sid":"Stmt1","Effect":"Allow","Action":"s3:ListAllMyBuckets","Resource":"*"}]}'
#NOTE: This step should succeed. The role should have permission only to list all buckets.
- name: list buckets
run: aws s3 ls > /dev/null
#NOTE: This step should fail. we don't want the role to have permission to see the bucket contents.
- name: try to list bucket contents
id: bucketContentsStep
continue-on-error: true
run: aws s3 ls s3://cawsc-integ-tests-bucket > /dev/null
#But the test fails if we could list the bucket contents.
- name: fail if we can list bucket contents
if: steps.bucketContentsStep.outcome == 'success'
run: exit 1
http-proxy:
if: ${{ github.event.pull_request.user.login == 'aws-sdk-osds' && github.repository == 'aws-actions/configure-aws-credentials' }}
permissions:
id-token: write
runs-on: ubuntu-latest
name: HTTP Proxy Test
steps:
- name: checkout
uses: actions/checkout@v5
with:
fetch-depth: 0
persist-credentials: false
- name: install tinyproxy
run: |
sudo apt-get update
sudo apt-get -y install tinyproxy
- name: start tinyproxy
run: tinyproxy -c .github/integ_tests/tinyproxy.conf
- name: Configure AWS credentials
continue-on-error: true
uses: ./
with:
aws-region: us-west-2
role-to-assume: ${{ secrets.OIDC_integ_role }}
http-proxy: http://127.0.0.1:9999
retry-max-attempts: 4
- name: checkout logs
run: cat integ_proxy_log.txt
- name: check logs to see if successful call
run: grep -q "Request" integ_proxy_log.txt && echo "PROXY_CALL_LOGGED=1" >> $GITHUB_ENV || echo "PROXY_CALL_LOGGED=0" >> $GITHUB_ENV
- name: fail job if bad call
if: ${{ env.PROXY_CALL_LOGGED != 1 }}
run: exit 1
token-file:
if: ${{ github.event.pull_request.user.login == 'aws-sdk-osds' && github.repository == 'aws-actions/configure-aws-credentials' }}
permissions:
id-token: write
strategy:
fail-fast: false
matrix:
os: [windows-latest, ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }}
name: Token File Test
steps:
- name: checkout
uses: actions/checkout@v5
with:
fetch-depth: 0
persist-credentials: false
- name: fetch token and write to file
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
async function getIDTokenAction() {
const id_token = await core.getIDToken("sts.amazonaws.com");
return id_token;
}
const idToken = await getIDTokenAction();
fs.writeFileSync(".github/integ_tests/integ_token.txt", idToken, (err) => {
if (err) throw err;
});
- name: get creds with that file
uses: ./
with:
aws-region: us-west-2
role-to-assume: ${{ secrets.OIDC_integ_role }}
web-identity-token-file: .github/integ_tests/integ_token.txt
retry-max-attempts: 4
- name: check creds
run: aws sts get-caller-identity
+5 -3
View File
@@ -2,6 +2,8 @@ on:
[pull_request]
name: Run unit tests
permissions:
contents: read
jobs:
unit-test:
@@ -14,13 +16,13 @@ jobs:
timeout-minutes: 5
steps:
- name: "Checkout repository"
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: "Setup node"
uses: actions/setup-node@v4
uses: actions/setup-node@v4.4.0
with:
node-version: 20
- name: "Install dependencies"
uses: bahmutov/npm-install@v1
run: npm ci
- name: "Run tests"
run: npm run test --if-present
lint:
+1 -1
View File
@@ -1,5 +1,5 @@
{
".release-please-manifest.json": "4.0.2",
"package.json": "4.0.2",
".": "4.3.0"
".": "5.0.0"
}
+21 -7
View File
@@ -2,17 +2,25 @@
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.3.0](https://github.com/aws-actions/configure-aws-credentials/compare/v4.3.0...v4.3.0) (2025-08-04)
## [5.0.0](https://github.com/aws-actions/configure-aws-credentials/compare/v4.3.1...v5.0.0) (2025-09-03)
### ⚠ BREAKING CHANGES
* Cleanup input handling. Changes invalid boolean input behavior (see #1445)
### Features
* add skip OIDC option ([#1458](https://github.com/aws-actions/configure-aws-credentials/issues/1458)) ([8c45f6b](https://github.com/aws-actions/configure-aws-credentials/commit/8c45f6b08196feb86cfdbe431541d5571d9ab2c2))
* Cleanup input handling. Changes invalid boolean input behavior (see [#1445](https://github.com/aws-actions/configure-aws-credentials/issues/1445)) ([74b3e27](https://github.com/aws-actions/configure-aws-credentials/commit/74b3e27aa80db064b5bb8c04b22fc607e817acf7))
* support account id allowlist ([#1456](https://github.com/aws-actions/configure-aws-credentials/issues/1456)) ([c4be498](https://github.com/aws-actions/configure-aws-credentials/commit/c4be498953fc1da2707a50ce4b761a53af3d02af))
## [4.3.1](https://github.com/aws-actions/configure-aws-credentials/compare/v4.3.0...v4.3.1) (2025-08-04)
### Bug Fixes
* properly set proxy environment variable ([cbea708](https://github.com/aws-actions/configure-aws-credentials/commit/cbea70821e4ab985ad3be0e5a93390523e257cde))
### Miscellaneous Chores
* release 4.3.0 ([3f7c218](https://github.com/aws-actions/configure-aws-credentials/commit/3f7c2187213bafaa1ea60a850b27082cbf55dda0))
* update readme to 4.3.1 ([#1424](https://github.com/aws-actions/configure-aws-credentials/issues/1424)) ([be2e7ad](https://github.com/aws-actions/configure-aws-credentials/commit/be2e7ad815e27b890489a89ce2717b0f9e26b56e))
## [4.3.0](https://github.com/aws-actions/configure-aws-credentials/compare/v4.2.1...v4.3.0) (2025-08-04)
@@ -27,6 +35,12 @@ All notable changes to this project will be documented in this file. See [standa
* **docs:** readme samples versioning ([5b3c895](https://github.com/aws-actions/configure-aws-credentials/commit/5b3c89504689ea1ea2b6000b23a6a2aac463662a))
* the wrong example region for China partition in README ([37fe9a7](https://github.com/aws-actions/configure-aws-credentials/commit/37fe9a740bcb30ee8cccd96feb90666c937311f2))
* properly set proxy environment variable ([cbea708](https://github.com/aws-actions/configure-aws-credentials/commit/cbea70821e4ab985ad3be0e5a93390523e257cde))
### Miscellaneous Chores
* release 4.3.0 ([3f7c218](https://github.com/aws-actions/configure-aws-credentials/commit/3f7c2187213bafaa1ea60a850b27082cbf55dda0))
## [4.2.1](https://github.com/aws-actions/configure-aws-credentials/compare/v4.2.0...v4.2.1) (2025-05-14)
+22 -13
View File
@@ -143,13 +143,15 @@ See [action.yml](./action.yml) for more detail.
| 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 aws-access-key-id, aws-secret-access-key, aws-session-token, aws-account-id, and aws-expiration). Defaults to false. | No |
| output-credentials | When set, outputs fetched credentials as action step output. (Outputs aws-access-key-id, aws-secret-access-key, aws-session-token, aws-account-id, authenticated-arn, and aws-expiration). Defaults to false. | No |
| output-env-credentials | When set, outputs fetched credentials as environment variables (AWS_REGION, AWS_DEFAULT_REGION, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN). Defaults to true. Set to false if you need to avoid setting/changing env variables. You'd probably want to use output-credentials if you disable this. (NOTE: Setting to false will prevent the aws-account-id from being exported as a step output). | 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 |
| allowed-account-ids | A comma-delimited list of expected AWS account IDs. The action will fail if we receive credentials for the wrong account. | No |
| force-skip-oidc | When set, the action will skip using GitHub OIDC provider even if the id-token permission is set. | No |
</details>
#### Adjust the retry mechanism
@@ -178,7 +180,7 @@ this action will always consider the `HTTP_PROXY` environment variable.
Manually configured proxy:
```yaml
uses: aws-actions/configure-aws-credentials@v4.2.1
uses: aws-actions/configure-aws-credentials@v4.3.1
with:
aws-region: us-east-2
role-to-assume: my-github-actions-role
@@ -249,13 +251,13 @@ line.
<summary>Inline session policy examples</summary>
```yaml
uses: aws-actions/configure-aws-credentials@v4.2.1
uses: aws-actions/configure-aws-credentials@v4.3.1
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.2.1
uses: aws-actions/configure-aws-credentials@v4.3.1
with:
inline-session-policy: >-
{
@@ -281,13 +283,13 @@ the role.
<summary>Managed session policy examples</summary>
```yaml
uses: aws-actions/configure-aws-credentials@v4.2.1
uses: aws-actions/configure-aws-credentials@v4.3.1
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.2.1
uses: aws-actions/configure-aws-credentials@v4.3.1
with:
managed-session-policies: |
arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
@@ -325,7 +327,7 @@ You can specify the audience through the `audience` input:
```yaml
- name: Configure AWS Credentials for China region audience
uses: aws-actions/configure-aws-credentials@v4.2.1
uses: aws-actions/configure-aws-credentials@v4.3.1
with:
audience: sts.amazonaws.com.cn
aws-region: cn-northwest-1
@@ -399,7 +401,7 @@ Examples
### AssumeRoleWithWebIdentity
```yaml
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4.2.1
uses: aws-actions/configure-aws-credentials@v4.3.1
with:
aws-region: us-east-2
role-to-assume: arn:aws:iam::123456789100:role/my-github-actions-role
@@ -413,13 +415,13 @@ environment variable and use it to assume the role
### AssumeRole with role previously assumed by action in same workflow
```yaml
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4.2.1
uses: aws-actions/configure-aws-credentials@v4.3.1
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.2.1
uses: aws-actions/configure-aws-credentials@v4.3.1
with:
aws-region: us-east-2
role-to-assume: arn:aws:iam::987654321000:role/my-second-role
@@ -434,7 +436,7 @@ 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.2.1
uses: aws-actions/configure-aws-credentials@v4.3.1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
@@ -453,7 +455,7 @@ name, like `role-to-assume: my-github-actions-role`.
```yaml
- name: Configure AWS Credentials 1
id: creds
uses: aws-actions/configure-aws-credentials@v4.2.1
uses: aws-actions/configure-aws-credentials@v4.3.1
with:
aws-region: us-east-2
role-to-assume: arn:aws:iam::123456789100:role/my-github-actions-role
@@ -462,7 +464,7 @@ name, like `role-to-assume: my-github-actions-role`.
run: |
aws sts get-caller-identity
- name: Configure AWS Credentials 2
uses: aws-actions/configure-aws-credentials@v4.2.1
uses: aws-actions/configure-aws-credentials@v4.3.1
with:
aws-region: us-east-2
aws-access-key-id: ${{ steps.creds.outputs.aws-access-key-id }}
@@ -478,6 +480,13 @@ This example shows that you can reference the fetched credentials as outputs if
the `aws-session-token` input in a situation where session tokens are fetched
and passed to this action.
Versioning
----------
Starting with version 5.0.0, this action uses semantic-style release tags and
[immutable releases](https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/immutable-releases).
A floating version tag (vN) is also provided for convenience: this tag will
move to the latest major version (vN -> vN.2.1, vM -> vM.0.0, etc.).
License
-------
This code is made available under the MIT license.
+8
View File
@@ -78,7 +78,15 @@ inputs:
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:
required: false
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.
allowed-account-ids:
required: false
description: An option comma-delimited list of expected AWS account IDs. The action will fail if we receive credentials for the wrong account.
force-skip-oidc:
required: false
description: When enabled, this option will skip using GitHub OIDC provider even if the id-token permission is set. This is sometimes useful when using IAM instance credentials.
outputs:
aws-account-id:
description: The AWS account ID for the provided credentials
+4
View File
@@ -12,6 +12,10 @@
"performance": {
"noDelete": "off"
},
"correctness": {
// Specifying a radix disables interpretation of 0x as a number (needed for backwards compat)
"useParseIntRadix": "off"
},
"complexity": {
"noExtraBooleanCast": "off"
}
Generated Vendored
+923 -379
View File
File diff suppressed because it is too large Load Diff
Generated Vendored
+976 -428
View File
File diff suppressed because it is too large Load Diff
+669 -765
View File
File diff suppressed because it is too large Load Diff
+8 -8
View File
@@ -1,7 +1,7 @@
{
"name": "configure-aws-credentials",
"description": "A GitHub Action to configure AWS credentials",
"version": "4.3.0",
"version": "5.0.0",
"scripts": {
"build": "tsc",
"lint": "biome check --error-on-warnings ./src",
@@ -16,25 +16,25 @@
"organization": true
},
"devDependencies": {
"@aws-sdk/credential-provider-env": "^3.858.0",
"@biomejs/biome": "2.1.3",
"@aws-sdk/credential-provider-env": "^3.879.0",
"@biomejs/biome": "2.2.2",
"@smithy/property-provider": "^4.0.3",
"@types/node": "^24.1.0",
"@types/node": "^24.3.0",
"@vercel/ncc": "^0.38.3",
"@vitest/coverage-v8": "^3.2.4",
"aws-sdk-client-mock": "^4.1.0",
"cpy-cli": "^5.0.0",
"cpy-cli": "^6.0.0",
"del-cli": "^6.0.0",
"json-schema": "^0.4.0",
"memfs": "^4.25.1",
"memfs": "^4.38.2",
"standard-version": "^9.5.0",
"typescript": "^5.8.3",
"vitest": "^3.2.4"
},
"dependencies": {
"@actions/core": "^1.11.1",
"@aws-sdk/client-sts": "^3.858.0",
"@smithy/node-http-handler": "^4.1.0",
"@aws-sdk/client-sts": "^3.873.0",
"@smithy/node-http-handler": "^4.1.1",
"https-proxy-agent": "^7.0.6"
},
"keywords": [
+3 -1
View File
@@ -6,8 +6,10 @@
"bump-minor-pre-major": false,
"bump-patch-for-minor-pre-major": false,
"draft": false,
"prerelease": false
"prerelease": false,
"exclude-paths": [".github", "dist"]
}
},
"last-release-sha": "7474bc4690e29a8392af63c5b98e7449536d5c3a",
"$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json"
}
+22 -4
View File
@@ -3,7 +3,7 @@ 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';
import { errorMessage, getCallerIdentity } from './helpers';
const USER_AGENT = 'configure-aws-credentials-for-github-actions';
@@ -40,7 +40,11 @@ export class CredentialsClient {
return this._stsClient;
}
public async validateCredentials(expectedAccessKeyId?: string, roleChaining?: boolean) {
public async validateCredentials(
expectedAccessKeyId?: string,
roleChaining?: boolean,
expectedAccountIds?: string[],
) {
let credentials: AwsCredentialIdentity;
try {
credentials = await this.loadCredentials();
@@ -50,13 +54,27 @@ export class CredentialsClient {
} catch (error) {
throw new Error(`Credentials could not be loaded, please check your action inputs: ${errorMessage(error)}`);
}
if (expectedAccountIds && expectedAccountIds.length > 0 && expectedAccountIds[0] !== '') {
let callerIdentity: Awaited<ReturnType<typeof getCallerIdentity>>;
try {
callerIdentity = await getCallerIdentity(this.stsClient);
} catch (error) {
throw new Error(`Could not validate account ID of credentials: ${errorMessage(error)}`);
}
if (!callerIdentity.Account || !expectedAccountIds.includes(callerIdentity.Account)) {
throw new Error(
`The account ID of the provided credentials (${
callerIdentity.Account ?? 'unknown'
}) does not match any of the expected account IDs: ${expectedAccountIds.join(', ')}`,
);
}
}
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',
'Credentials loaded by the SDK do not match the expected access key ID configured by the action',
);
}
}
+5 -1
View File
@@ -142,7 +142,11 @@ export async function assumeRole(params: assumeRoleParams) {
PolicyArns: managedSessionPolicies?.length ? managedSessionPolicies : undefined,
};
const keys = Object.keys(commonAssumeRoleParams) as Array<keyof typeof commonAssumeRoleParams>;
keys.forEach((k) => commonAssumeRoleParams[k] === undefined && delete commonAssumeRoleParams[k]);
keys.forEach((k) => {
if (commonAssumeRoleParams[k] === undefined) {
delete commonAssumeRoleParams[k];
}
});
// Instantiate STS client
const stsClient = credentialsClient.stsClient;
+4 -3
View File
@@ -1,5 +1,5 @@
import * as core from '@actions/core';
import { errorMessage } from '../helpers';
import { errorMessage, getBooleanInput } from '../helpers';
/**
* When the GitHub Actions job is done, clean up any environment variables that
@@ -13,8 +13,8 @@ import { errorMessage } from '../helpers';
*/
export function cleanup() {
const outputEnvCredentialsInput = core.getInput('output-env-credentials', { required: false }) || 'true';
if (outputEnvCredentialsInput === 'true') {
// Only attempt to change environment variables if we changed them in the first place
if (getBooleanInput('output-env-credentials', { required: false, default: true })) {
try {
// The GitHub Actions toolkit does not have an option to completely unset
// environment variables, so we overwrite the current value with an empty
@@ -30,6 +30,7 @@ export function cleanup() {
}
}
}
/* c8 ignore start */
if (require.main === module) {
try {
+40 -7
View File
@@ -1,5 +1,5 @@
import * as core from '@actions/core';
import type { Credentials } from '@aws-sdk/client-sts';
import type { Credentials, STSClient } from '@aws-sdk/client-sts';
import { GetCallerIdentityCommand } from '@aws-sdk/client-sts';
import type { CredentialsClient } from './CredentialsClient';
@@ -109,15 +109,19 @@ export function exportRegion(region: string, outputEnvCredentials?: boolean) {
}
}
// Obtains account ID from STS Client and sets it as output
export async function exportAccountId(credentialsClient: CredentialsClient, maskAccountId?: boolean) {
const client = credentialsClient.stsClient;
export async function getCallerIdentity(client: STSClient): Promise<{ Account: string; Arn: string; UserId?: string }> {
const identity = await client.send(new GetCallerIdentityCommand({}));
const accountId = identity.Account;
const arn = identity.Arn;
if (!accountId || !arn) {
if (!identity.Account || !identity.Arn) {
throw new Error('Could not get Account ID or ARN from STS. Did you set credentials?');
}
return { Account: identity.Account, Arn: identity.Arn, UserId: identity.UserId };
}
// Obtains account ID from STS Client and sets it as output
export async function exportAccountId(credentialsClient: CredentialsClient, maskAccountId?: boolean) {
const identity = await getCallerIdentity(credentialsClient.stsClient);
const accountId = identity.Account;
const arn = identity.Arn;
if (maskAccountId) {
core.setSecret(accountId);
core.setSecret(arn);
@@ -214,3 +218,32 @@ export async function areCredentialsValid(credentialsClient: CredentialsClient)
return false;
}
}
/**
* Like core.getBooleanInput, but respects the required option.
*
* From https://github.com/actions/toolkit/blob/6876e2a664ec02908178087905b9155e9892a437/packages/core/src/core.ts
*
* Gets the input value of the boolean type in the YAML 1.2 "core schema" specification.
* Support boolean input list: `true | True | TRUE | false | False | FALSE` .
* The return value is also in boolean type.
* ref: https://yaml.org/spec/1.2/spec.html#id2804923
*
* @param name name of the input to get
* @param options optional. See core.InputOptions. Also supports optional 'default' if the input is not set
* @returns boolean
*/
export function getBooleanInput(name: string, options?: core.InputOptions & { default?: boolean }): boolean {
const trueValue = ['true', 'True', 'TRUE'];
const falseValue = ['false', 'False', 'FALSE'];
const optionsWithoutDefault = { ...options };
delete optionsWithoutDefault.default;
const val = core.getInput(name, optionsWithoutDefault);
if (trueValue.includes(val)) return true;
if (falseValue.includes(val)) return false;
if (val === '') return options?.default ?? false;
throw new TypeError(
`Input does not meet YAML 1.2 "Core Schema" specification: ${name}\n` +
`Support boolean input list: \`true | True | TRUE | false | False | FALSE\``,
);
}
+43 -49
View File
@@ -8,6 +8,7 @@ import {
exportAccountId,
exportCredentials,
exportRegion,
getBooleanInput,
retryAndBackoff,
translateEnvVariables,
unsetCredentials,
@@ -22,68 +23,57 @@ export async function run() {
try {
translateEnvVariables();
// Get inputs
// Undefined inputs are empty strings ( or empty arrays)
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 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 maskAccountId = getBooleanInput('mask-aws-account-id', { required: false });
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 roleSkipSessionTagging = getBooleanInput('role-skip-session-tagging', { required: false });
const proxyServer = core.getInput('http-proxy', { required: false }) || process.env.HTTP_PROXY;
const inlineSessionPolicy = core.getInput('inline-session-policy', {
required: false,
const inlineSessionPolicy = core.getInput('inline-session-policy', { required: false });
const managedSessionPolicies = core.getMultilineInput('managed-session-policies', { required: false }).map((p) => {
return { arn: p };
});
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 outputEnvCredentialsInput = core.getInput('output-env-credentials', { required: false }) || 'true';
const outputEnvCredentials = outputEnvCredentialsInput.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';
const roleChaining = getBooleanInput('role-chaining', { required: false });
const outputCredentials = getBooleanInput('output-credentials', { required: false });
const outputEnvCredentials = getBooleanInput('output-env-credentials', { required: false, default: true });
const unsetCurrentCredentials = getBooleanInput('unset-current-credentials', { required: false });
let disableRetry = getBooleanInput('disable-retry', { required: false });
const specialCharacterWorkaround = getBooleanInput('special-characters-workaround', { required: false });
const useExistingCredentials = core.getInput('use-existing-credentials', { required: false });
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;
const expectedAccountIds = core
.getInput('allowed-account-ids', { required: false })
.split(',')
.map((s) => s.trim());
const forceSkipOidc = getBooleanInput('force-skip-oidc', { required: false });
if (forceSkipOidc && roleToAssume && !AccessKeyId && !webIdentityTokenFile) {
throw new Error(
"If 'force-skip-oidc' is true and 'role-to-assume' is set, 'aws-access-key-id' or 'web-identity-token-file' must be set",
);
}
for (const managedSessionPolicy of managedSessionPoliciesInput) {
managedSessionPolicies.push({ arn: managedSessionPolicy });
if (specialCharacterWorkaround) {
// 😳
disableRetry = false;
maxRetries = 12;
} else if (maxRetries < 1) {
maxRetries = 1;
}
// Logic to decide whether to attempt to use OIDC or not
const useGitHubOIDCProvider = () => {
if (forceSkipOidc) return false;
// 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.
@@ -158,7 +148,7 @@ export async function run() {
exportCredentials({ AccessKeyId, SecretAccessKey, SessionToken }, outputCredentials, outputEnvCredentials);
} else if (!webIdentityTokenFile && !roleChaining) {
// Proceed only if credentials can be picked up
await credentialsClient.validateCredentials();
await credentialsClient.validateCredentials(undefined, roleChaining, expectedAccountIds);
sourceAccountId = await exportAccountId(credentialsClient, maskAccountId);
}
@@ -166,7 +156,7 @@ export async function run() {
// 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);
await credentialsClient.validateCredentials(AccessKeyId, roleChaining, expectedAccountIds);
sourceAccountId = await exportAccountId(credentialsClient, maskAccountId);
}
@@ -201,7 +191,11 @@ export async function run() {
// 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 credentialsClient.validateCredentials(
roleCredentials.Credentials?.AccessKeyId,
roleChaining,
expectedAccountIds,
);
}
if (outputEnvCredentials) {
await exportAccountId(credentialsClient, maskAccountId);
+282
View File
@@ -334,6 +334,288 @@ describe('Configure AWS Credentials', {}, () => {
});
});
describe('Force Skip OIDC', {}, () => {
beforeEach(() => {
vi.clearAllMocks();
mockedSTSClient.reset();
});
it('skips OIDC when force-skip-oidc is true with IAM credentials', async () => {
vi.spyOn(core, 'getInput').mockImplementation(mocks.getInput({
...mocks.IAM_ASSUMEROLE_INPUTS,
'force-skip-oidc': 'true'
}));
vi.spyOn(core, 'getIDToken').mockResolvedValue('testoidctoken');
mockedSTSClient.on(AssumeRoleCommand).resolves(mocks.outputs.STS_CREDENTIALS);
mockedSTSClient.on(GetCallerIdentityCommand).resolves({ ...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' })
.mockResolvedValueOnce({ accessKeyId: 'STSAWSACCESSKEYID' });
process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN = 'fake-token';
await run();
expect(core.getIDToken).not.toHaveBeenCalled();
expect(core.setFailed).not.toHaveBeenCalled();
});
it('skips OIDC when force-skip-oidc is true with web identity token file', async () => {
vi.spyOn(core, 'getInput').mockImplementation(mocks.getInput({
...mocks.WEBIDENTITY_TOKEN_FILE_INPUTS,
'force-skip-oidc': 'true'
}));
vi.spyOn(core, 'getIDToken').mockResolvedValue('testoidctoken');
mockedSTSClient.on(AssumeRoleWithWebIdentityCommand).resolves(mocks.outputs.STS_CREDENTIALS);
mockedSTSClient.on(GetCallerIdentityCommand).resolves({ ...mocks.outputs.GET_CALLER_IDENTITY });
process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN = 'fake-token';
vi.mock('node:fs');
vol.reset();
fs.mkdirSync('/home/github', { recursive: true });
fs.writeFileSync('/home/github/file.txt', 'test-token');
await run();
expect(core.getIDToken).not.toHaveBeenCalled();
expect(core.info).toHaveBeenCalledWith('Assuming role with web identity token file');
expect(core.setFailed).not.toHaveBeenCalled();
});
it('fails when force-skip-oidc is true but no alternative credentials provided', async () => {
vi.spyOn(core, 'getInput').mockImplementation(mocks.getInput({
'role-to-assume': 'arn:aws:iam::111111111111:role/MY-ROLE',
'aws-region': 'fake-region-1',
'force-skip-oidc': 'true'
}));
process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN = 'fake-token';
await run();
expect(core.setFailed).toHaveBeenCalledWith(
"If 'force-skip-oidc' is true and 'role-to-assume' is set, 'aws-access-key-id' or 'web-identity-token-file' must be set"
);
});
it('allows force-skip-oidc without role-to-assume', async () => {
vi.spyOn(core, 'getInput').mockImplementation(mocks.getInput({
...mocks.IAM_USER_INPUTS,
'force-skip-oidc': 'true'
}));
vi.spyOn(core, 'getIDToken').mockResolvedValue('testoidctoken');
mockedSTSClient.on(GetCallerIdentityCommand).resolves({ ...mocks.outputs.GET_CALLER_IDENTITY });
// biome-ignore lint/suspicious/noExplicitAny: any required to mock private method
vi.spyOn(CredentialsClient.prototype as any, 'loadCredentials').mockResolvedValue({
accessKeyId: 'MYAWSACCESSKEYID',
});
process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN = 'fake-token';
await run();
expect(core.getIDToken).not.toHaveBeenCalled();
expect(core.info).toHaveBeenCalledWith('Proceeding with IAM user credentials');
expect(core.setFailed).not.toHaveBeenCalled();
});
it('uses OIDC when force-skip-oidc is false (default behavior)', async () => {
vi.spyOn(core, 'getInput').mockImplementation(mocks.getInput({
...mocks.GH_OIDC_INPUTS,
'force-skip-oidc': 'false'
}));
vi.spyOn(core, 'getIDToken').mockResolvedValue('testoidctoken');
mockedSTSClient.on(AssumeRoleWithWebIdentityCommand).resolves(mocks.outputs.STS_CREDENTIALS);
mockedSTSClient.on(GetCallerIdentityCommand).resolves({ ...mocks.outputs.GET_CALLER_IDENTITY });
process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN = 'fake-token';
await run();
expect(core.getIDToken).toHaveBeenCalledWith('');
expect(core.info).toHaveBeenCalledWith('Assuming role with OIDC');
expect(core.setFailed).not.toHaveBeenCalled();
});
it('uses OIDC when force-skip-oidc is not set (default behavior)', async () => {
vi.spyOn(core, 'getInput').mockImplementation(mocks.getInput(mocks.GH_OIDC_INPUTS));
vi.spyOn(core, 'getIDToken').mockResolvedValue('testoidctoken');
mockedSTSClient.on(AssumeRoleWithWebIdentityCommand).resolves(mocks.outputs.STS_CREDENTIALS);
mockedSTSClient.on(GetCallerIdentityCommand).resolves({ ...mocks.outputs.GET_CALLER_IDENTITY });
process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN = 'fake-token';
await run();
expect(core.getIDToken).toHaveBeenCalledWith('');
expect(core.info).toHaveBeenCalledWith('Assuming role with OIDC');
expect(core.setFailed).not.toHaveBeenCalled();
});
it('works with role chaining when force-skip-oidc is true', async () => {
vi.spyOn(core, 'getInput').mockImplementation(mocks.getInput({
...mocks.EXISTING_ROLE_INPUTS,
'force-skip-oidc': 'true',
'aws-access-key-id': 'MYAWSACCESSKEYID',
'aws-secret-access-key': 'MYAWSSECRETACCESSKEY'
}));
vi.spyOn(core, 'getIDToken').mockResolvedValue('testoidctoken');
mockedSTSClient.on(AssumeRoleCommand).resolves(mocks.outputs.STS_CREDENTIALS);
mockedSTSClient.on(GetCallerIdentityCommand).resolves({ ...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' })
.mockResolvedValueOnce({ accessKeyId: 'STSAWSACCESSKEYID' });
process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN = 'fake-token';
await run();
expect(core.getIDToken).not.toHaveBeenCalled();
expect(core.setFailed).not.toHaveBeenCalled();
});
});
describe('Account ID Validation', {}, () => {
beforeEach(() => {
vi.clearAllMocks();
mockedSTSClient.reset();
});
it('succeeds when account ID matches allowed list', async () => {
vi.spyOn(core, 'getInput').mockImplementation(mocks.getInput({
...mocks.IAM_USER_INPUTS,
'allowed-account-ids': '111111111111'
}));
mockedSTSClient.on(GetCallerIdentityCommand).resolves({ ...mocks.outputs.GET_CALLER_IDENTITY });
// biome-ignore lint/suspicious/noExplicitAny: any required to mock private method
vi.spyOn(CredentialsClient.prototype as any, 'loadCredentials').mockResolvedValue({
accessKeyId: 'MYAWSACCESSKEYID',
});
await run();
expect(core.setFailed).not.toHaveBeenCalled();
expect(core.info).toHaveBeenCalledWith('Proceeding with IAM user credentials');
});
it('succeeds with multiple allowed account IDs when account matches', async () => {
vi.spyOn(core, 'getInput').mockImplementation(mocks.getInput({
...mocks.IAM_USER_INPUTS,
'allowed-account-ids': '999999999999,111111111111,222222222222'
}));
mockedSTSClient.on(GetCallerIdentityCommand).resolves({ ...mocks.outputs.GET_CALLER_IDENTITY });
// biome-ignore lint/suspicious/noExplicitAny: any required to mock private method
vi.spyOn(CredentialsClient.prototype as any, 'loadCredentials').mockResolvedValue({
accessKeyId: 'MYAWSACCESSKEYID',
});
await run();
expect(core.setFailed).not.toHaveBeenCalled();
});
it('fails when account ID does not match allowed list', async () => {
vi.spyOn(core, 'getInput').mockImplementation(mocks.getInput({
...mocks.IAM_USER_INPUTS,
'allowed-account-ids': '999999999999'
}));
mockedSTSClient.on(GetCallerIdentityCommand).resolves({ ...mocks.outputs.GET_CALLER_IDENTITY });
// biome-ignore lint/suspicious/noExplicitAny: any required to mock private method
vi.spyOn(CredentialsClient.prototype as any, 'loadCredentials').mockResolvedValue({
accessKeyId: 'MYAWSACCESSKEYID',
});
await run();
expect(core.setFailed).toHaveBeenCalledWith(
'The account ID of the provided credentials (111111111111) does not match any of the expected account IDs: 999999999999'
);
});
it('fails when account ID does not match any in multiple allowed accounts', async () => {
vi.spyOn(core, 'getInput').mockImplementation(mocks.getInput({
...mocks.IAM_USER_INPUTS,
'allowed-account-ids': '999999999999,888888888888'
}));
mockedSTSClient.on(GetCallerIdentityCommand).resolves({ ...mocks.outputs.GET_CALLER_IDENTITY });
// biome-ignore lint/suspicious/noExplicitAny: any required to mock private method
vi.spyOn(CredentialsClient.prototype as any, 'loadCredentials').mockResolvedValue({
accessKeyId: 'MYAWSACCESSKEYID',
});
await run();
expect(core.setFailed).toHaveBeenCalledWith(
'The account ID of the provided credentials (111111111111) does not match any of the expected account IDs: 999999999999, 888888888888'
);
});
it('works with assume role when account ID matches', async () => {
vi.spyOn(core, 'getInput').mockImplementation(mocks.getInput({
...mocks.IAM_ASSUMEROLE_INPUTS,
'allowed-account-ids': '111111111111'
}));
mockedSTSClient.on(AssumeRoleCommand).resolves(mocks.outputs.STS_CREDENTIALS);
mockedSTSClient.on(GetCallerIdentityCommand).resolves({ ...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' })
.mockResolvedValueOnce({ accessKeyId: 'STSAWSACCESSKEYID' });
await run();
expect(core.setFailed).not.toHaveBeenCalled();
expect(core.info).toHaveBeenCalledWith('Authenticated as assumedRoleId AROAFAKEASSUMEDROLEID');
});
it('works with OIDC when account ID matches', async () => {
vi.spyOn(core, 'getInput').mockImplementation(mocks.getInput({
...mocks.GH_OIDC_INPUTS,
'allowed-account-ids': '111111111111'
}));
vi.spyOn(core, 'getIDToken').mockResolvedValue('testoidctoken');
mockedSTSClient.on(AssumeRoleWithWebIdentityCommand).resolves(mocks.outputs.STS_CREDENTIALS);
mockedSTSClient.on(GetCallerIdentityCommand).resolves({ ...mocks.outputs.GET_CALLER_IDENTITY });
process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN = 'fake-token';
await run();
expect(core.setFailed).not.toHaveBeenCalled();
expect(core.info).toHaveBeenCalledWith('Authenticated as assumedRoleId AROAFAKEASSUMEDROLEID');
});
it('handles GetCallerIdentity API failure gracefully', async () => {
vi.spyOn(core, 'getInput').mockImplementation(mocks.getInput({
...mocks.IAM_USER_INPUTS,
'allowed-account-ids': '111111111111'
}));
mockedSTSClient.on(GetCallerIdentityCommand).rejects(new Error('API Error'));
// biome-ignore lint/suspicious/noExplicitAny: any required to mock private method
vi.spyOn(CredentialsClient.prototype as any, 'loadCredentials').mockResolvedValue({
accessKeyId: 'MYAWSACCESSKEYID',
});
await run();
expect(core.setFailed).toHaveBeenCalledWith('Could not validate account ID of credentials: API Error');
});
it('ignores validation when allowed-account-ids is empty', async () => {
vi.spyOn(core, 'getInput').mockImplementation(mocks.getInput({
...mocks.IAM_USER_INPUTS,
'allowed-account-ids': ''
}));
mockedSTSClient.on(GetCallerIdentityCommand).resolves({ ...mocks.outputs.GET_CALLER_IDENTITY });
// biome-ignore lint/suspicious/noExplicitAny: any required to mock private method
vi.spyOn(CredentialsClient.prototype as any, 'loadCredentials').mockResolvedValue({
accessKeyId: 'MYAWSACCESSKEYID',
});
await run();
expect(core.setFailed).not.toHaveBeenCalled();
expect(core.info).toHaveBeenCalledWith('Proceeding with IAM user credentials');
});
it('handles whitespace in allowed-account-ids input', async () => {
vi.spyOn(core, 'getInput').mockImplementation(mocks.getInput({
...mocks.IAM_USER_INPUTS,
'allowed-account-ids': ' 111111111111 , 222222222222 '
}));
mockedSTSClient.on(GetCallerIdentityCommand).resolves({ ...mocks.outputs.GET_CALLER_IDENTITY });
// biome-ignore lint/suspicious/noExplicitAny: any required to mock private method
vi.spyOn(CredentialsClient.prototype as any, 'loadCredentials').mockResolvedValue({
accessKeyId: 'MYAWSACCESSKEYID',
});
await run();
expect(core.setFailed).not.toHaveBeenCalled();
});
});
describe('HTTP Proxy Configuration', {}, () => {
beforeEach(() => {
vi.spyOn(core, 'getInput').mockImplementation(mocks.getInput(mocks.GH_OIDC_INPUTS));