* feat!: v3 release

Squashed commit of the following:

commit 9df144b3ae
Merge: 19d3f3a 131c7b6
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Wed Aug 23 14:41:33 2023 -0700

    Merge remote-tracking branch 'origin' into vNext

commit 131c7b6fd1
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Aug 22 03:12:24 2023 +0000

    chore: Bump jest from 29.6.2 to 29.6.3 (#786)

    Bumps [jest](https://github.com/jestjs/jest/tree/HEAD/packages/jest) from 29.6.2 to 29.6.3.
    - [Release notes](https://github.com/jestjs/jest/releases)
    - [Changelog](https://github.com/jestjs/jest/blob/main/CHANGELOG.md)
    - [Commits](https://github.com/jestjs/jest/commits/v29.6.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>
    Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>

commit 6334b403eb
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Aug 22 03:11:45 2023 +0000

    chore: Bump aws-sdk from 2.1436.0 to 2.1441.0 (#787)

    Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1436.0 to 2.1441.0.
    - [Release notes](https://github.com/aws/aws-sdk-js/releases)
    - [Commits](https://github.com/aws/aws-sdk-js/compare/v2.1436.0...v2.1441.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>

commit 19d3f3a169
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Fri Aug 18 20:13:39 2023 -0700

    chore: update readme and changelog

commit 4403e8d882
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Fri Aug 18 17:12:47 2023 -0700

    chore: update workflows

commit 0f1923f1a1
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Fri Aug 18 17:01:59 2023 -0700

    chore: update .github with current

commit 60a9bf1676
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Fri Aug 18 17:00:14 2023 -0700

    chore: update .github with current

commit d3464b25f8
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Fri Aug 18 16:58:01 2023 -0700

    chore: add examples to vNext branch

commit 7cd050ca4d
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Fri Aug 18 16:54:12 2023 -0700

    chore: update readme

commit 0e32a13775
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Fri Aug 18 16:19:17 2023 -0700

    chore: update readme

commit 2625b45d56
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Fri Aug 18 15:12:36 2023 -0700

    chore: update readme

commit 19eb4df27e
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Thu Aug 17 17:22:20 2023 -0700

    chore: update readme

commit 71ff793a0f
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Thu Aug 17 17:18:42 2023 -0700

    chore: update readme

commit a272f95336
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Wed Aug 16 17:05:42 2023 -0700

    chore: update readme

commit 360ea313a7
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Aug 15 03:33:37 2023 +0000

    chore: Bump aws-sdk from 2.1431.0 to 2.1436.0 (#783)

    Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1431.0 to 2.1436.0.
    - [Release notes](https://github.com/aws/aws-sdk-js/releases)
    - [Commits](https://github.com/aws/aws-sdk-js/compare/v2.1431.0...v2.1436.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>

commit de93b00c9f
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Aug 15 03:32:58 2023 +0000

    chore: Bump eslint from 8.46.0 to 8.47.0 (#784)

    Bumps [eslint](https://github.com/eslint/eslint) from 8.46.0 to 8.47.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.46.0...v8.47.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>

commit 4dd1aeed85
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Fri Aug 11 16:41:44 2023 -0700

    chore: remove unused dependency, fixing vulnerability

commit 7f4507af3c
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Fri Aug 11 16:24:09 2023 -0700

    fix: maxRetry hit infinite loop with negative input

commit 746d33e7c1
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Aug 8 03:23:17 2023 +0000

    chore: Bump aws-sdk from 2.1426.0 to 2.1431.0 (#782)

    Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1426.0 to 2.1431.0.
    - [Release notes](https://github.com/aws/aws-sdk-js/releases)
    - [Commits](https://github.com/aws/aws-sdk-js/compare/v2.1426.0...v2.1431.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>

commit 706fc9ae3d
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Aug 1 03:41:00 2023 +0000

    chore: Bump eslint from 8.45.0 to 8.46.0 (#780)

    Bumps [eslint](https://github.com/eslint/eslint) from 8.45.0 to 8.46.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.45.0...v8.46.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>

commit 9918371ad5
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Aug 1 03:39:16 2023 +0000

    chore: Bump aws-sdk from 2.1421.0 to 2.1426.0 (#781)

    Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1421.0 to 2.1426.0.
    - [Release notes](https://github.com/aws/aws-sdk-js/releases)
    - [Commits](https://github.com/aws/aws-sdk-js/compare/v2.1421.0...v2.1426.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>

commit 345462ab9e
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Aug 1 03:38:28 2023 +0000

    chore: Bump jest from 29.6.1 to 29.6.2 (#779)

    Bumps [jest](https://github.com/facebook/jest/tree/HEAD/packages/jest) from 29.6.1 to 29.6.2.
    - [Release notes](https://github.com/facebook/jest/releases)
    - [Changelog](https://github.com/jestjs/jest/blob/main/CHANGELOG.md)
    - [Commits](https://github.com/facebook/jest/commits/v29.6.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>

commit 80a7a6c2a2
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Jul 25 03:22:02 2023 +0000

    chore: Bump aws-sdk from 2.1416.0 to 2.1421.0 (#778)

    Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1416.0 to 2.1421.0.
    - [Release notes](https://github.com/aws/aws-sdk-js/releases)
    - [Commits](https://github.com/aws/aws-sdk-js/compare/v2.1416.0...v2.1421.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>

commit 385d7e1d64
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Jul 18 03:25:33 2023 +0000

    chore: Bump aws-sdk from 2.1413.0 to 2.1416.0 (#774)

    Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1413.0 to 2.1416.0.
    - [Release notes](https://github.com/aws/aws-sdk-js/releases)
    - [Commits](https://github.com/aws/aws-sdk-js/compare/v2.1413.0...v2.1416.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>

commit 48560b5d49
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Jul 18 03:24:46 2023 +0000

    chore: Bump eslint from 8.44.0 to 8.45.0 (#773)

    Bumps [eslint](https://github.com/eslint/eslint) from 8.44.0 to 8.45.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.44.0...v8.45.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>

commit 35d8f9588b
Author: Shailja Khurana <117320115+khushail@users.noreply.github.com>
Date:   Fri Jul 14 15:14:02 2023 -0700

    added workflow for handling answerable discussions (#772)

commit 86df881b31
Author: Tom Keller <1083460+kellertk@users.noreply.github.com>
Date:   Wed Jul 12 14:51:43 2023 -0700

    chore: add link to CF template in README (#771)

commit a621db3279
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Jul 11 03:16:22 2023 +0000

    chore: Bump jest from 29.5.0 to 29.6.1 (#768)

    Bumps [jest](https://github.com/facebook/jest/tree/HEAD/packages/jest) from 29.5.0 to 29.6.1.
    - [Release notes](https://github.com/facebook/jest/releases)
    - [Changelog](https://github.com/jestjs/jest/blob/main/CHANGELOG.md)
    - [Commits](https://github.com/facebook/jest/commits/v29.6.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>

commit 90858a2e70
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Jul 11 03:15:36 2023 +0000

    chore: Bump aws-sdk from 2.1410.0 to 2.1413.0 (#767)

    Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1410.0 to 2.1413.0.
    - [Release notes](https://github.com/aws/aws-sdk-js/releases)
    - [Commits](https://github.com/aws/aws-sdk-js/compare/v2.1410.0...v2.1413.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>

commit 228a9916ee
Author: Tom Keller <1083460+kellertk@users.noreply.github.com>
Date:   Fri Jul 7 16:49:10 2023 -0700

    Update README.md for OIDC changes (#764)

commit 65c2143642
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Thu Jul 6 15:19:05 2023 -0700

    chore: add final tests, add outputs to action.yml

commit 7b893ba14b
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Wed Jul 5 18:55:04 2023 -0700

    feat: getIDToken retry, feat: special character in key retry

commit 3c981da079
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Jul 4 03:30:19 2023 +0000

    chore: Bump eslint from 8.43.0 to 8.44.0 (#761)

    Bumps [eslint](https://github.com/eslint/eslint) from 8.43.0 to 8.44.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.43.0...v8.44.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>

commit 222080786b
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Jul 4 03:29:03 2023 +0000

    chore: Bump aws-sdk from 2.1405.0 to 2.1410.0 (#760)

    Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1405.0 to 2.1410.0.
    - [Release notes](https://github.com/aws/aws-sdk-js/releases)
    - [Commits](https://github.com/aws/aws-sdk-js/compare/v2.1405.0...v2.1410.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>

commit aa2675f083
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Mon Jul 3 16:13:19 2023 -0700

    implement last changes for vNext

commit 256d740e71
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Fri Jun 30 16:20:47 2023 -0700

    chore: remove unnecessary step in unit test job

commit cd5cd29d7f
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Fri Jun 30 16:17:47 2023 -0700

    chore: declare eol in gitattributes

commit 7b90497500
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Fri Jun 30 16:11:12 2023 -0700

    chore: disable auto crlf in unit tests

commit fb67439785
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Fri Jun 30 15:48:15 2023 -0700

    fix boolean input

commit 2b32a8f2c6
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Fri Jun 30 15:40:41 2023 -0700

    fix webIdentityTokenFile option, rearrange validation logic

commit 7526948ef9
Author: Peter Woodworth <44349620+peterwoodworth@users.noreply.github.com>
Date:   Thu Jun 29 17:29:11 2023 -0700

    chore: vnext unit tests (#758)

    * fix: unit tests

    * get unit tests running

commit 0270d0bcec
Author: Peter Woodworth <44349620+peterwoodworth@users.noreply.github.com>
Date:   Tue Jun 27 14:22:02 2023 -0700

    chore: update readme with new thumbprint (#755)

commit 4b8efb08db
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Jun 27 03:58:21 2023 +0000

    chore: Bump aws-sdk from 2.1400.0 to 2.1405.0 (#754)

    Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1400.0 to 2.1405.0.
    - [Release notes](https://github.com/aws/aws-sdk-js/releases)
    - [Commits](https://github.com/aws/aws-sdk-js/compare/v2.1400.0...v2.1405.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>

commit d26f2d03f8
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Wed Jun 21 16:45:34 2023 -0700

    feat: role-chaining

commit 20f59875fe
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Wed Jun 21 15:13:42 2023 -0700

    feat: optional policy inputs when assuming role

commit 10024331f6
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Wed Jun 21 15:08:37 2023 -0700

    feat: optional policy inputs when assuming role

commit 2cee35f9a9
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Wed Jun 21 14:51:50 2023 -0700

    feat: optional policy inputs when assuming role

commit 8aa25a5cb6
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Wed Jun 21 14:50:04 2023 -0700

    feat: optional policy inputs when assuming role

commit e849bae717
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Tue Jun 20 18:02:34 2023 -0700

    chore: remove windows self-hosted runner

commit 8a5ae330dd
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Tue Jun 20 16:10:30 2023 -0700

    chore: expand integ tests

commit 819a6d1c74
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Jun 20 03:58:58 2023 +0000

    chore: Bump eslint from 8.42.0 to 8.43.0 (#750)

    Bumps [eslint](https://github.com/eslint/eslint) from 8.42.0 to 8.43.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.42.0...v8.43.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>

commit e57babb541
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Jun 20 03:58:19 2023 +0000

    chore: Bump aws-sdk from 2.1396.0 to 2.1400.0 (#749)

    Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1396.0 to 2.1400.0.
    - [Release notes](https://github.com/aws/aws-sdk-js/releases)
    - [Commits](https://github.com/aws/aws-sdk-js/compare/v2.1396.0...v2.1400.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>

commit c613996f9a
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Mon Jun 19 18:38:44 2023 -0700

    chore: attempting to get to minimal integ test success

commit c13a9c8ef3
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Mon Jun 19 18:36:40 2023 -0700

    chore: attempting to get to minimal integ test success

commit b98e10c776
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Mon Jun 19 18:25:03 2023 -0700

    chore: set failing configuration on integ workflow matrix

commit 6d193465ae
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Mon Jun 19 16:32:19 2023 -0700

    chore: remove push workflow trigger

commit a8f18666db
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Mon Jun 19 16:29:33 2023 -0700

    chore: fix workflow file indentation

commit 7dec5a88ce
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Mon Jun 19 16:28:05 2023 -0700

    chore: update workflow to be able to trigger

commit 0a8178a52a
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Mon Jun 19 16:21:45 2023 -0700

    chore: update workflow to be able to trigger

commit 506b27277d
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Mon Jun 19 16:17:53 2023 -0700

    chore: update workflow to be able to trigger

commit 5fd3084fc3
Author: Peter Woodworth <44349620+peterwoodworth@users.noreply.github.com>
Date:   Wed Jun 14 15:02:32 2023 -0700

    chore: update changelog for release (#745)

commit d00f6c6f41
Author: Dimitar <dimitarshr@gmail.com>
Date:   Wed Jun 14 22:43:04 2023 +0100

    Allow inline session policies for assuming role (#739)

    * Allow to pass inline session policy as a parameter

    Update the action file

    Regenerate the dist/ content

    Add test

    * Fix typos

    * Fix stylistic error

    * Move the inline policy logic to allow assumeRole to use it as well; Update and add tests

    * Add an option for managed policies

    * Regenerate the dist/ files

    * Use multiline input for managed policies

    * Update readme

    * Update readme

    ---------

    Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>

commit ae734070a0
Author: GitHub Actions <github-aws-sdk-osds-automation@amazon.com>
Date:   Tue Jun 13 04:55:26 2023 +0000

    chore: Update dist

commit 3d528c5f7d
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Jun 13 04:54:37 2023 +0000

    chore: Bump aws-sdk from 2.1391.0 to 2.1396.0 (#744)

    Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1391.0 to 2.1396.0.
    - [Release notes](https://github.com/aws/aws-sdk-js/releases)
    - [Commits](https://github.com/aws/aws-sdk-js/compare/v2.1391.0...v2.1396.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>

commit e7aae61719
Author: GitHub Actions <github-aws-sdk-osds-automation@amazon.com>
Date:   Tue Jun 6 03:59:43 2023 +0000

    chore: Update dist

commit 979ee1f6f4
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Jun 6 03:59:04 2023 +0000

    chore: Bump aws-sdk from 2.1386.0 to 2.1391.0 (#742)

    Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1386.0 to 2.1391.0.
    - [Release notes](https://github.com/aws/aws-sdk-js/releases)
    - [Commits](https://github.com/aws/aws-sdk-js/compare/v2.1386.0...v2.1391.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>

commit 184acc09ea
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Jun 6 03:58:21 2023 +0000

    chore: Bump eslint from 8.41.0 to 8.42.0 (#741)

    Bumps [eslint](https://github.com/eslint/eslint) from 8.41.0 to 8.42.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.41.0...v8.42.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>

commit 375a690dc0
Author: Peter Woodworth <44349620+peterwoodworth@users.noreply.github.com>
Date:   Wed May 31 14:43:39 2023 -0700

    chore: update changelog for v2.1.0 (#738)

    * chore: update changelog for v2.1.0

    * chore: update changelog for v2.1.0

    ---------

    Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>

commit 8337ca3433
Author: Peter Woodworth <44349620+peterwoodworth@users.noreply.github.com>
Date:   Wed May 31 14:38:06 2023 -0700

    update time to ancient (#729)

    Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>

commit 5727f247b6
Author: GitHub Actions <github-aws-sdk-osds-automation@amazon.com>
Date:   Tue May 30 03:59:04 2023 +0000

    chore: Update dist

commit de3676366f
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue May 30 03:58:14 2023 +0000

    chore: Bump aws-sdk from 2.1382.0 to 2.1386.0 (#736)

    Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1382.0 to 2.1386.0.
    - [Release notes](https://github.com/aws/aws-sdk-js/releases)
    - [Commits](https://github.com/aws/aws-sdk-js/compare/v2.1382.0...v2.1386.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>

commit 81fba9ea6a
Author: escudero89 <532828+escudero89@users.noreply.github.com>
Date:   Fri May 26 00:10:40 2023 +0200

    Update README.md with v2 instead of v1 (#733)

commit 8815b6557c
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue May 23 03:59:25 2023 +0000

    chore: Bump eslint from 8.40.0 to 8.41.0 (#732)

    Bumps [eslint](https://github.com/eslint/eslint) from 8.40.0 to 8.41.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.40.0...v8.41.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>

commit 3d77523f10
Author: GitHub Actions <github-aws-sdk-osds-automation@amazon.com>
Date:   Tue May 23 03:58:44 2023 +0000

    chore: Update dist

commit 4eb7afece4
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue May 23 03:58:06 2023 +0000

    chore: Bump aws-sdk from 2.1378.0 to 2.1382.0 (#731)

    Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1378.0 to 2.1382.0.
    - [Release notes](https://github.com/aws/aws-sdk-js/releases)
    - [Commits](https://github.com/aws/aws-sdk-js/compare/v2.1378.0...v2.1382.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>

commit d713a182c5
Author: GitHub Actions <github-aws-sdk-osds-automation@amazon.com>
Date:   Tue May 16 03:58:29 2023 +0000

    chore: Update dist

commit 1910078421
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue May 16 03:57:45 2023 +0000

    chore: Bump aws-sdk from 2.1374.0 to 2.1378.0 (#726)

    Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1374.0 to 2.1378.0.
    - [Release notes](https://github.com/aws/aws-sdk-js/releases)
    - [Commits](https://github.com/aws/aws-sdk-js/compare/v2.1374.0...v2.1378.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>

commit 580afbba80
Author: GitHub Actions <github-aws-sdk-osds-automation@amazon.com>
Date:   Tue May 9 03:59:53 2023 +0000

    chore: Update dist

commit 1daf2a1967
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue May 9 03:59:14 2023 +0000

    chore: Bump aws-sdk from 2.1369.0 to 2.1374.0 (#723)

    Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1369.0 to 2.1374.0.
    - [Release notes](https://github.com/aws/aws-sdk-js/releases)
    - [Commits](https://github.com/aws/aws-sdk-js/compare/v2.1369.0...v2.1374.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>

commit 76ad093bd5
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue May 9 03:57:57 2023 +0000

    chore: Bump eslint from 8.39.0 to 8.40.0 (#722)

    Bumps [eslint](https://github.com/eslint/eslint) from 8.39.0 to 8.40.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.39.0...v8.40.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>

commit 6fbd316fd1
Author: Milo Hyson <siggimoo@users.noreply.github.com>
Date:   Fri May 5 18:27:52 2023 -0700

    Add role-chaining support (#688)

    * Add role-chaining support

    * fix version in readme

    * minor readme adjustment

    ---------

    Co-authored-by: Milo Hyson <mhyson@tunein.com>
    Co-authored-by: peterwoodworth <woodwoop@amazon.com>
    Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>

commit 19f3a6d67f
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue May 2 03:59:57 2023 +0000

    chore: Bump axios from 1.3.6 to 1.4.0 (#720)

    Bumps [axios](https://github.com/axios/axios) from 1.3.6 to 1.4.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.3.6...v1.4.0)

    ---
    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>

commit 96aac45bfc
Author: GitHub Actions <github-aws-sdk-osds-automation@amazon.com>
Date:   Tue May 2 03:58:25 2023 +0000

    chore: Update dist

commit 5e6a264592
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue May 2 03:57:46 2023 +0000

    chore: Bump aws-sdk from 2.1364.0 to 2.1369.0 (#719)

    Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1364.0 to 2.1369.0.
    - [Release notes](https://github.com/aws/aws-sdk-js/releases)
    - [Commits](https://github.com/aws/aws-sdk-js/compare/v2.1364.0...v2.1369.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>

commit 82ea2d2853
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Apr 25 04:01:50 2023 +0000

    chore: Bump axios from 1.3.5 to 1.3.6 (#716)

    Bumps [axios](https://github.com/axios/axios) from 1.3.5 to 1.3.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.3.5...v1.3.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>
    Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>

commit e0213bba7a
Author: GitHub Actions <github-aws-sdk-osds-automation@amazon.com>
Date:   Tue Apr 25 03:59:31 2023 +0000

    chore: Update dist

commit 2beda2fb7c
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Apr 25 03:58:42 2023 +0000

    chore: Bump aws-sdk from 2.1360.0 to 2.1364.0 (#715)

    Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1360.0 to 2.1364.0.
    - [Release notes](https://github.com/aws/aws-sdk-js/releases)
    - [Commits](https://github.com/aws/aws-sdk-js/compare/v2.1360.0...v2.1364.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>

commit 0afc5d47c7
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Apr 25 03:57:35 2023 +0000

    chore: Bump eslint from 8.38.0 to 8.39.0 (#714)

    Bumps [eslint](https://github.com/eslint/eslint) from 8.38.0 to 8.39.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.38.0...v8.39.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>

commit 31bd3ae2db
Author: GitHub Actions <github-aws-sdk-osds-automation@amazon.com>
Date:   Tue Apr 18 03:59:23 2023 +0000

    chore: Update dist

commit 46648cb772
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Apr 18 03:58:27 2023 +0000

    chore: Bump aws-sdk from 2.1354.0 to 2.1360.0 (#713)

    Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1354.0 to 2.1360.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.1354.0...v2.1360.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>

commit 60a5c129d0
Author: Jonathan Lang <jonathan.lang@tngtech.com>
Date:   Wed Apr 12 00:46:13 2023 +0200

    Fix Typo in README.md (#707)

commit f576cc9d9b
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Apr 11 04:00:40 2023 +0000

    chore: Bump axios from 1.3.4 to 1.3.5 (#712)

    Bumps [axios](https://github.com/axios/axios) from 1.3.4 to 1.3.5.
    - [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.4...v1.3.5)

    ---
    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>

commit 9c17403327
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Apr 11 03:59:38 2023 +0000

    chore: Bump eslint from 8.35.0 to 8.38.0 (#711)

    Bumps [eslint](https://github.com/eslint/eslint) from 8.35.0 to 8.38.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.35.0...v8.38.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>

commit 9c1a10e79c
Author: GitHub Actions <github-aws-sdk-osds-automation@amazon.com>
Date:   Tue Apr 11 03:58:34 2023 +0000

    chore: Update dist

commit 9192d9ecb4
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Apr 11 03:57:48 2023 +0000

    chore: Bump aws-sdk from 2.1329.0 to 2.1354.0 (#710)

    Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1329.0 to 2.1354.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.1329.0...v2.1354.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>

commit 26227bfa7d
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Wed Mar 22 16:52:04 2023 -0700

    chore: adjust cleanup build target

commit 0d90ddd1f2
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Wed Mar 22 16:51:12 2023 -0700

    chore: adjust cleanup build again

commit fc80f28dba
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Wed Mar 22 16:37:58 2023 -0700

    chore: adjust cleanup build and some imports

commit 3088522ce8
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Wed Mar 22 16:32:37 2023 -0700

    chore: build and set cleanup file

commit 0181111f1d
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Wed Mar 22 15:12:07 2023 -0700

    chore: build action

commit b723544115
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Wed Mar 22 15:08:39 2023 -0700

    fix: branch name is not sanitized, slight refactor

commit 0e613a0980
Author: Adrian Środoń <adriansrodon@tuta.io>
Date:   Mon Mar 20 23:24:34 2023 +0100

    docs: add note about case sensivity to CloudFormation template (#696)

    * docs: add note about case sensivity to CloudFormation template

    * Move case-sensivity notes to CloudFormation template

commit 12d07d4800
Author: Tom Keller <kellertk@amazon.com>
Date:   Fri Mar 17 17:46:57 2023 -0700

    feat: update tests

commit f6fdf0cdbd
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Wed Mar 15 14:12:01 2023 -0700

    feat: aws region is optional, use global sts endpoint when not set

commit cb1361ade3
Author: Peter Woodworth <44349620+peterwoodworth@users.noreply.github.com>
Date:   Mon Mar 13 14:50:02 2023 -0700

    docs: clarify safety of version migration in readme (#692)

commit f9f25e69f5
Author: peterwoodworth <woodwoop@amazon.com>
Date:   Fri Mar 10 14:35:59 2023 -0800

    refactor, add new major version features and proxy

commit 83f0e97b2f
Merge: 7fc5f08 f86a0c3
Author: Peter Woodworth <44349620+peterwoodworth@users.noreply.github.com>
Date:   Tue Mar 7 17:36:19 2023 -0800

    Merge pull request #687 from fabienfoerster/patch-2

    Update README examples to use v2

commit f86a0c30a5
Author: Fabien Foerster <f.foerster@bevolta.com>
Date:   Tue Mar 7 21:29:17 2023 +0100

    Update README examples to use v2

commit 7fc5f080e5
Author: GitHub Actions <github-aws-sdk-osds-automation@amazon.com>
Date:   Tue Mar 7 01:02:37 2023 +0000

    chore: Update dist

commit ffc08eae73
Author: Tom Keller <kellertk@amazon.com>
Date:   Mon Mar 6 17:01:09 2023 -0800

    Rename master to main

commit e1e17a757e
Author: Tom Keller <1083460+kellertk@users.noreply.github.com>
Date:   Mon Mar 6 16:35:37 2023 -0800

    Version 2 release (#685)

    * Update README for v2

    * Remove codeql analysis

    * Version bump checkout action

    * Tweak closed issue message

    * Changes for v2 release

    * Adjust action name

    * Update CHANGELOG

    * Update action to use node 16

    * Update versions

    * Typo

commit bab55d3830
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Feb 28 04:09:09 2023 +0000

    chore: Bump axios from 1.3.3 to 1.3.4 (#679)

    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>

commit 07b737a14f
Author: GitHub Actions <github-aws-sdk-osds-automation@amazon.com>
Date:   Tue Feb 28 04:00:33 2023 +0000

    chore: Update dist

commit 26e4efa71f
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Feb 28 03:59:47 2023 +0000

    chore: Bump aws-sdk from 2.1320.0 to 2.1324.0 (#677)

    Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1320.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.1320.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>
    Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>

commit 7e0ecf0346
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Feb 28 03:58:55 2023 +0000

    chore: Bump eslint from 8.34.0 to 8.35.0 (#675)

    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>

commit 567d4149d6
Merge: 32eb1b4 85ec61b
Author: Peter Woodworth <44349620+peterwoodworth@users.noreply.github.com>
Date:   Tue Feb 21 18:49:30 2023 -0800

    Merge pull request #563 from russau/docs/readme-role-update

    Minor: include a role condition test for AUD in sample CFN template

commit 32eb1b4a66
Author: Jackson Welsh <me@jacksonwel.sh>
Date:   Tue Feb 21 20:36:17 2023 -0600

    feat: document mask-aws-account-id input (#606)

    Closes aws-actions#304

    Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>

commit 6ca2577643
Author: GitHub Actions <github-aws-sdk-osds-automation@amazon.com>
Date:   Wed Feb 22 02:34:29 2023 +0000

    chore: Update dist

commit f1de076135
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Wed Feb 22 02:33:40 2023 +0000

    chore: Bump aws-sdk from 2.1273.0 to 2.1320.0 (#666)

    Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1273.0 to 2.1320.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.1320.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>

commit 077fd1fc8f
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Feb 21 04:00:04 2023 +0000

    chore: Bump jest from 29.4.2 to 29.4.3 (#663)

    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>

commit 1416c559c0
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Feb 14 04:08:31 2023 +0000

    chore: Bump eslint from 8.33.0 to 8.34.0 (#653)

    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>

commit c3f9f9cde3
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Feb 14 04:02:34 2023 +0000

    chore: Bump jest from 29.4.1 to 29.4.2 (#655)

    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>

commit 1a61b71d4c
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Feb 14 04:00:54 2023 +0000

    chore: Bump axios from 1.3.2 to 1.3.3 (#651)

    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>

commit 07d5781915
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Feb 7 03:03:40 2023 +0000

    chore: Bump axios from 1.2.6 to 1.3.2 (#648)

    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>

commit 5ed46d9d6a
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Jan 31 03:10:42 2023 +0000

    chore: Bump eslint from 8.32.0 to 8.33.0 (#645)

    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>

commit 0d34112acb
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Jan 31 03:06:27 2023 +0000

    chore: Bump jest from 29.3.1 to 29.4.1 (#643)

    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>

commit fa45146389
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Jan 31 03:05:11 2023 +0000

    chore: Bump @vercel/ncc from 0.36.0 to 0.36.1 (#640)

    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>

commit a075dc0410
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Jan 31 03:03:44 2023 +0000

    chore: Bump axios from 1.2.3 to 1.2.6 (#639)

    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>

commit 3e21ee4ae7
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Jan 24 03:04:28 2023 +0000

    chore: Bump axios from 1.2.2 to 1.2.3 (#630)

    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>

commit 491cd39cf6
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Jan 17 03:05:35 2023 +0000

    chore: Bump eslint from 8.31.0 to 8.32.0 (#625)

    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>

commit 3654529dc6
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Jan 3 03:06:41 2023 +0000

    chore: Bump json5 from 2.2.1 to 2.2.3 (#620)

    Bumps [json5](https://github.com/json5/json5) from 2.2.1 to 2.2.3.
    - [Release notes](https://github.com/json5/json5/releases)
    - [Changelog](https://github.com/json5/json5/blob/main/CHANGELOG.md)
    - [Commits](https://github.com/json5/json5/compare/v2.2.1...v2.2.3)

    ---
    updated-dependencies:
    - dependency-name: json5
      dependency-type: indirect
    ...

    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>

commit aa5a031041
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Jan 3 03:04:46 2023 +0000

    chore: Bump eslint from 8.30.0 to 8.31.0 (#619)

    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>

commit 55443b3d5b
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Jan 3 03:03:28 2023 +0000

    chore: Bump axios from 1.2.1 to 1.2.2 (#616)

    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>

commit 48f0cb7848
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Dec 20 03:04:13 2022 +0000

    chore: Bump eslint from 8.29.0 to 8.30.0 (#610)

    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>

commit 90d1b38cb5
Author: GitHub Actions <github-aws-sdk-osds-automation@amazon.com>
Date:   Tue Dec 13 03:05:43 2022 +0000

    chore: Update dist

commit 422c797285
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Dec 13 03:04:51 2022 +0000

    chore: Bump aws-sdk from 2.1268.0 to 2.1273.0 (#603)

    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>

commit 4b942d82b0
Author: GitHub Actions <github-aws-sdk-osds-automation@amazon.com>
Date:   Tue Dec 6 03:10:45 2022 +0000

    chore: Update dist

commit 7437ed192e
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Dec 6 03:09:51 2022 +0000

    chore: Bump aws-sdk from 2.1262.0 to 2.1268.0 (#596)

    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>

commit ed4ba44f95
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Dec 6 03:08:24 2022 +0000

    chore: Bump @vercel/ncc from 0.34.0 to 0.36.0 (#594)

    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>

commit 10dc6d923a
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Dec 6 03:05:08 2022 +0000

    chore: Bump axios from 1.2.0 to 1.2.1 (#590)

    Bumps [axios](https://github.…

* chore: tweak readme for v3
This commit is contained in:
Tom Keller
2023-08-23 16:35:15 -07:00
committed by GitHub
parent 131c7b6fd1
commit ef93a73b13
47 changed files with 66665 additions and 48076 deletions

19
.editorconfig Normal file
View File

@@ -0,0 +1,19 @@
# 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

2
.eslintignore Normal file
View File

@@ -0,0 +1,2 @@
build
dist

View File

@@ -1,18 +0,0 @@
{
"env": {
"commonjs": true,
"es6": true,
"node": true,
"jest": true
},
"extends": "eslint:recommended",
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parserOptions": {
"ecmaVersion": 2018
},
"rules": {
}
}

168
.eslintrc.yml Normal file
View File

@@ -0,0 +1,168 @@
env:
jest: true
node: true
root: true
plugins:
- import
- prettier
parserOptions:
ecmaVersion: 2021
sourceType: module
extends:
- plugin:prettier/recommended
- prettier
rules:
prettier/prettier: [error]
import/no-extraneous-dependencies:
- error
- devDependencies:
- "**/test/**"
- "**/build-tools/**"
optionalDependencies: false
peerDependencies: true
import/no-unresolved: [error]
import/order:
- warn
- groups:
- builtin
- external
alphabetize:
order: asc
caseInsensitive: true
array-callback-return: [warn]
no-await-in-loop: [warn]
no-constant-binary-expression: [error]
no-constructor-return: [error]
no-duplicate-imports: [error]
no-self-compare: [warn]
no-template-curly-in-string: [error]
no-unmodified-loop-condition: [error]
no-unreachable-loop: [error]
no-unused-private-class-members: [error]
no-use-before-define: [error]
require-atomic-updates: [error]
block-scoped-var: [warn]
camelcase: [warn]
class-methods-use-this: [error]
consistent-return: [warn]
consistent-this: [warn]
default-case-last: [warn]
default-param-last: [warn]
dot-notation: [error]
eqeqeq: [error]
guard-for-in: [warn]
logical-assignment-operators:
- error
- always
- enforceForIfStatements: false
no-array-constructor: [error]
no-bitwise: [error]
no-console: [warn]
no-empty-function: [warn]
no-eval: [error]
no-extra-bind: [error]
no-labels: [error]
no-implicit-globals: [error]
no-invalid-this: [error]
key-spacing: [error]
no-multiple-empty-lines: [error]
no-return-await: [warn]
no-trailing-spaces: [error]
no-lonely-if: [error]
no-nested-ternary: [warn]
no-mixed-operators: [warn]
no-proto: [error]
no-sequences: [error]
no-throw-literal: [error]
no-useless-call: [error]
no-useless-concat: [warn]
no-var: [error]
one-var-declaration-per-line: [error]
prefer-const: [warn]
prefer-arrow-callback: [warn]
prefer-regex-literals: [warn]
prefer-promise-reject-errors: [warn]
prefer-spread: [warn]
prefer-template: [warn]
require-await: [error]
overrides:
- files:
- '**/*.ts'
parser: '@typescript-eslint/parser'
parserOptions:
ecmaVersion: 2021
sourceType: module
project: ./tsconfig.json
extends:
- plugin:@typescript-eslint/recommended
- plugin:@typescript-eslint/recommended-requiring-type-checking
- plugin:import/typescript
rules:
'@typescript-eslint/array-type':
- warn
- default: array-simple
'@typescript-eslint/ban-tslint-comment': [error]
'@typescript-eslint/consistent-indexed-object-style': [warn]
'@typescript-eslint/consistent-type-assertions': [warn]
'@typescript-eslint/prefer-includes': [warn]
dot-notation: [off]
'@typescript-eslint/dot-notation': [error]
'@typescript-eslint/no-explicit-any': [off]
'@typescript-eslint/consistent-type-exports': [warn]
'@typescript-eslint/consistent-type-imports': [warn]
'@typescript-eslint/no-base-to-string': [error]
'@typescript-eslint/no-confusing-non-null-assertion': [warn]
'@typescript-eslint/no-invalid-void-type': [error]
'@typescript-eslint/no-meaningless-void-operator': [warn]
'@typescript-eslint/no-redundant-type-constituents': [warn]
'@typescript-eslint/no-unnecessary-boolean-literal-compare': [warn]
'@typescript-eslint/no-unnecessary-condition': [warn]
'@typescript-eslint/no-unnecessary-qualifier': [warn]
'@typescript-eslint/no-unnecessary-type-arguments': [warn]
'@typescript-eslint/non-nullable-type-assertion-style': [warn]
'@typescript-eslint/prefer-for-of': [error]
'@typescript-eslint/prefer-literal-enum-member': [warn]
'@typescript-eslint/prefer-optional-chain': [warn]
'@typescript-eslint/prefer-readonly': [warn]
'@typescript-eslint/prefer-regexp-exec': [warn]
'@typescript-eslint/prefer-string-starts-ends-with': [warn]
'@typescript-eslint/prefer-ts-expect-error': [error]
'@typescript-eslint/promise-function-async': [warn]
'@typescript-eslint/require-array-sort-compare': [error]
default-param-last: [off]
'@typescript-eslint/default-param-last': [warn]
no-array-constructor: [off]
'@typescript-eslint/no-array-constructor': [error]
no-dupe-class-members: [off]
'@typescript-eslint/no-dupe-class-members': [warn]
no-invalid-this: [off]
'@typescript-eslint/no-invalid-this': [warn]
no-unused-vars: [off]
'@typescript-eslint/no-unused-vars':
- error
- varsIgnorePattern: '^_'
argsIgnorePattern: '^_'
caughtErrorsIgnorePattern: '^_'
'@typescript-eslint/no-non-null-assertion': [off]
'@typescript-eslint/no-require-imports':
- error
no-return-await: [off]
'@typescript-eslint/return-await': [error]
no-shadow: [off]
'@typescript-eslint/no-shadow': [error]
'@typescript-eslint/no-floating-promises': [error]
"@typescript-eslint/member-ordering":
- error
- default:
- public-static-field
- public-static-method
- protected-static-field
- protected-static-method
- private-static-field
- private-static-method
- field
- constructor
- method
no-use-before-define: [off]
'@typescript-eslint/no-use-before-define': [error]
no-duplicate-imports: [off]

7
.gitattributes vendored Normal file
View File

@@ -0,0 +1,7 @@
/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

View File

@@ -1,16 +0,0 @@
on:
[pull_request]
name: Check
jobs:
check:
name: Run Unit Tests
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Run tests
run: |
npm ci
npm test

View File

@@ -1,51 +0,0 @@
name: "Close Stale Issues"
# Controls when the action will run.
on:
workflow_dispatch:
schedule:
- cron: "0 */4 * * *"
jobs:
cleanup:
permissions:
issues: write
contents: read
pull-requests: write
runs-on: ubuntu-latest
name: Stale issue job
steps:
- 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
stale-pr-label: closing-soon
exempt-pr-labels: no-autoclose
response-requested-label: response-requested
# Don't set closed-for-staleness label to skip closing very old issues
# regardless of label
closed-for-staleness-label: closed-for-staleness
# Issue timing
days-before-stale: 5
days-before-close: 2
days-before-ancient: 36500
# 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
# the total number of +1, heart, hooray, and rocket reactions
# on an issue.
minimum-upvotes-to-exempt: 5
repo-token: ${{ secrets.GITHUB_TOKEN }}
loglevel: DEBUG
# Set dry-run to true to not perform label or close actions.
dry-run: false

View File

@@ -13,6 +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.
** Note **
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.
If you wish to keep having a conversation with other community members under this issue feel free to do so.

View File

@@ -15,4 +15,4 @@ jobs:
- name: Stale discussions action
uses: aws-github-ops/handle-stale-discussions@v1
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}

View File

@@ -1,4 +1,4 @@
name: Update dist files on
name: Update dist files on main branch
on:
push:
@@ -27,7 +27,7 @@ jobs:
npm test
npm run package
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v2
uses: aws-actions/configure-aws-credentials@v3
with:
aws-region: us-west-2
role-to-assume: ${{ secrets.SECRETS_AWS_ROLE_TO_ASSUME }}

27
.github/workflows/pull-request-lint.yml vendored Normal file
View File

@@ -0,0 +1,27 @@
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@v4.5.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
types: |-
feat
fix
chore
requireScope: false

68
.github/workflows/tests-integ.yml vendored Normal file
View File

@@ -0,0 +1,68 @@
name: Run 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]
node: [14, 16, 18]
name: Run OIDC integ tests
runs-on: ${{ matrix.os }}
timeout-minutes: 30
steps:
- name: "Checkout repository"
uses: actions/checkout@v3
- 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]
node: [14, 16, 18]
name: Run access key integ tests
runs-on: ${{ matrix.os }}
timeout-minutes: 30
steps:
- name: "Checkout repository"
uses: actions/checkout@v3
- 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-iam-user:
strategy:
fail-fast: false
matrix:
os: [[self-hosted, linux-fargate], windows-latest, ubuntu-latest, macos-latest]
node: [14, 16, 18]
name: Run IAM User integ tests
runs-on: ${{ matrix.os }}
timeout-minutes: 30
steps:
- name: "Checkout repository"
uses: actions/checkout@v3
- 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 }}

41
.github/workflows/tests-unit.yml vendored Normal file
View File

@@ -0,0 +1,41 @@
on:
[pull_request]
name: Run unit tests
jobs:
unit-test:
strategy:
fail-fast: false
matrix:
os: [windows-latest, ubuntu-latest, macos-latest]
node: [14, 16, 18]
name: Run unit tests
runs-on: ${{ matrix.os }}
timeout-minutes: 5
steps:
- name: "Checkout repository"
uses: actions/checkout@v3
- name: "Setup node"
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node }}
- 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@v3
- name: "Setup node"
uses: actions/setup-node@v3
with:
node-version: 16
- name: "Install dependencies"
uses: bahmutov/npm-install@v1
- name: "Lint code"
run: npm run lint --if-present

70
.gitignore vendored
View File

@@ -1,66 +1,6 @@
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
node_modules
coverage
# 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
.DS_Store
Thumbs.db
build
test-reports

8
.prettierrc.json Normal file
View File

@@ -0,0 +1,8 @@
{
"printWidth": 120,
"semi": true,
"singleQuote": true,
"trailingComma": "es5",
"bracketSpacing": true,
"overrides": []
}

View File

@@ -2,6 +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.
## [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

View File

@@ -1,6 +1,4 @@
MIT License
Copyright 2019 Amazon.com, Inc. or its affiliates.
Copyright (c) 2019-2022 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

460
README.md
View File

@@ -5,43 +5,76 @@ and exports 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.
### Recent updates
---
**GitHub OIDC Changes**
### News
In #[357](https://github.com/aws-actions/configure-aws-credentials/issues/357), we
observed that GitHub recently started offering one of several intermediate OIDC
endpoint thumbprints. Because IAM requires statically configured endpoint
thumbprints, AWS customers that had only one thumbprint configured could see
intermittent authentication failures. **As of July 6, 2023, AWS has made a change to
IAM that will no longer require any particular certificate thumbprint for
tokens.actions.githubusercontent.com**, which is the GitHub OIDC endpoint. Instead,
AWS secures communication with GitHub OIDC using our library of trusted CAs rather
than using a certificate thumbprint to verify the server certificate. The IAM APIs
still require that a thumbprint is configured, but those thumbprints will be ignored
when authenticating tokens.actions.githubusercontent.com.
We have recently released `v3` of Configure AWS Credentials! With this new
release we have migrated the code to TypeScript, and have also migrated away
from using `v2` of the JavaScript AWS SDK. This should eliminate the warning you
have seen in your workflow logs about `v2` deprecation.
GitHub Enterprise Server customers use a different endpoint so they are not affected by
this change.
In addition to the refactored codebase, we have also introduced some changes to
existing functionality, added some new features, and fixed some bugs. These
changes should be backwards compatible with your existing workflows.
*Original message:*
There are now [two possible intermediary certificates](https://github.blog/changelog/2023-06-27-github-actions-update-on-oidc-integration-with-aws/) for the Actions SSL certificate. Previously, the certificate with the thumbprint `6938fd4d98bab03faadb97b34396831e3780aea1` was guaranteed to return. Now, the certificate with the thumbprint `1c58a3a8518e8759bf075b76b750d4f2df264fcd` can also be returned, so you will need to [update your identity provider](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc.html) with this additional new thumbprint.
**Notable changes to existing functionality**
- By default, the assumed role credentials will only be valid for one hour in
_all_ use cases. This is changed from 6 hours in `v2`. You can adjust this value
with the `role-duration-seconds` input.
- By default, your account ID will not be masked in workflow logs. This was
changed from being masked by default in the previous version. AWS does consider
account IDs as sensitive information, so this change reflects that stance. You
can rever to the old default and mask your account ID in workflow logs by
setting the `mask-aws-account-id` input to `true`.
**New features**
- You can now configure retry settings in case your STS call fails. By default,
we retry with exponential backoff twelve times. You can disable this behavior
altogether by setting the `disable-retry` input to `true`, or you can configure
the number of times the action will retry with the `retry-max-attempts` input.
- You can now set the returned credentials as action step outputs. To do this,
you can set the `output-credentials` prop to `true`.
- There's now an option to clear the AWS-related environment variables at the
start of the action. Clearing these variables is often a workaround for
problems, so enabling this can be helpful if existing credentials or environment
variables are interfering with the action. You can enable this by setting the
`unset-current-credentials` input to `true`.
**Bug fixes**
You can find a list of bugs that have been fixed in v3 in the
[changelog](./changelog.md).
---
### Table of Contents
<!-- toc -->
- [Usage](#usage)
- [Credentials](#credentials)
- [Assuming a Role](#assuming-a-role)
+ [Session tagging](#session-tagging)
- [Overview](#overview)
- [Security recommendations](#security-recommendations)
- [Using this action](#using-this-action)
+ [Credential Lifetime](#credential-lifetime)
+ [External ID](#external-id)
+ [Session tagging](#session-tagging-and-name)
+ [Sample IAM Role Permissions](#sample-iam-role-cloudformation-template)
+ [Misc](#misc)
- [OIDC](#OIDC)
+ [Audience](#audience)
+ [Sample IAM OIDC CloudFormation Template](#sample-iam-oidc-cloudformation-template)
+ [Claims and scoping permissions](#claims-and-scoping-permissions)
+ [Further info](#further-info)
- [Self-Hosted Runners](#self-hosted-runners)
+ [Proxy Configuration](#proxy-configuration)
+ [Use with the AWS CLI](#use-with-the-aws-cli)
- [Examples](#examples)
- [License Summary](#license-summary)
- [Security Disclosures](#security-disclosures)
<!-- tocstop -->
## Usage
We support four methods for fetching credentials from AWS, but we recommend that
## Overview
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.
@@ -49,14 +82,14 @@ To do that, you would add the following step to your workflow:
```yaml
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v2
uses: aws-actions/configure-aws-credentials@v3
with:
role-to-assume: arn:aws:iam::123456789100:role/my-github-actions-role
aws-region: us-east-2
```
This will cause the action to perform an `AssumeRoleWithWebIdentity` call and
return temporary security credentials for use by other actions. In order for
this to work, you'll need to preconfigure the IAM IdP in your AWS account
This will cause the action to perform an [`AssumeRoleWithWebIdentity`](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRoleWithWebIdentity.html) call and
return temporary security credentials for use by other steps in your workflow. In order for
this to work, you'll need to preconfigure the IAM Identity Provider in your AWS account
(see [Assuming a Role](#assuming-a-role) for details).
You can use this action with the AWS CLI available in
@@ -78,7 +111,7 @@ jobs:
- name: Checkout
uses: actions/checkout@v3
- name: Configure AWS credentials from Test account
uses: aws-actions/configure-aws-credentials@v2
uses: aws-actions/configure-aws-credentials@v3
with:
role-to-assume: arn:aws:iam::111111111111:role/my-github-actions-role-test
aws-region: us-east-1
@@ -86,7 +119,7 @@ jobs:
run: |
aws s3 sync . s3://my-s3-test-website-bucket
- name: Configure AWS credentials from Production account
uses: aws-actions/configure-aws-credentials@v2
uses: aws-actions/configure-aws-credentials@v3
with:
role-to-assume: arn:aws:iam::222222222222:role/my-github-actions-role-prod
aws-region: us-west-2
@@ -98,7 +131,13 @@ jobs:
See [action.yml](action.yml) for the full documentation for this action's inputs
and outputs.
## Credentials
### Note about GHES
Some of this documentation may be inaccurate if you are using GHES (GitHub Enterprise Servers), please take note to review the GitHub documentation when relevant.
For example, the URL that the OIDC JWT is issued from is different than the usual `tokens.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.
## Security recommendations
We recommend following
[Amazon IAM best practices](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html)
@@ -109,15 +148,18 @@ for the AWS credentials used in GitHub Actions workflows, including:
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
There are four different supported ways to retrieve credentials. 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`, or setting `role-chaining`, will signal to the action that you wish to use the
OIDC provider. If `role-chaining` is `true`, existing credentials in the environment will be used to assume `role-to-assume`.
## Using this action
There are five different supported ways to retrieve credentials:
The following table describes which identity is used based on which values are supplied to the Action:
- 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`)
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. 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 is used based on which values are supplied to the Action:
| **Identity Used** | `aws-access-key-id` | `role-to-assume` | `web-identity-token-file` | `role-chaining` |
| --------------------------------------------------------------- | ------------------- | ---------------- | ------------------------- | - |
@@ -128,97 +170,135 @@ The following table describes which identity is used based on which values are s
| Assume Role using existing credentials | | ✔ | | ✔ |
### Credential Lifetime
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`) .
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.
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`.
### Examples
### External ID
If your role requires an external ID to assume, you can provide the external ID with the `role-external-id` input
#### AssumeRoleWithWebIdentity (recommended)
### Session tagging and name
The default session name is "GitHubActions", and you can modify it by specifying the desired name in `role-session-name`.
The session will 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, unless you 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 [issue 419](https://github.com/aws-actions/configure-aws-credentials/issues/419) for more info
You can skip this session tagging by providing
`role-skip-session-tagging` as true in the action's inputs:
```yaml
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v2
uses: aws-actions/configure-aws-credentials@v3
with:
aws-region: us-east-2
role-to-assume: arn:aws:iam::123456789100:role/my-github-actions-role
role-session-name: MySessionName
role-skip-session-tagging: true
```
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 static IAM credentials in repository secrets
### Session policies
#### 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
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v2
uses: aws-actions/configure-aws-credentials@v3
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@v2
with:
aws-region: us-east-2
role-to-assume: arn:aws:iam::987654321000:role/my-second-role
role-session-name: MySessionName
role-chaining: true
inline-session-policy: '{"Version":"2012-10-17","Statement":[{"Sid":"Stmt1","Effect":"Allow","Action":"s3:List*","Resource":"*"}]}'
```
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`.
Or we can have a nicely formatted JSON as well:
```yaml
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v2
uses: aws-actions/configure-aws-credentials@v3
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
inline-session-policy: >-
{
"Version": "2012-10-17",
"Statement": [
{
"Sid":"Stmt1",
"Effect":"Allow",
"Action":"s3:List*",
"Resource":"*"
}
]
}
```
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`.
#### AssumeRoleWithWebIdentity using a custom audience
#### 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
- name: Configure AWS Credentials for Beta Customers
uses: aws-actions/configure-aws-credentials@v2
uses: aws-actions/configure-aws-credentials@v3
with:
audience: beta-customers
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@v3
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, and the recommended solution is to include another step in your workflow which unsets the environment variables set by this action. Now if you set the `unset-current-credentials` input to `true`, the workaround is made eaiser
## 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, this action will create a JWT unique to the workflow run, and it will use this JWT to assume the role. For this action to create the JWT, it is required for your workflow to have the `id-token: write` permission:
```yaml
permissions:
id-token: write
contents: read
```
### Audience
When the JWT is created, an audience needs to be specified. By default, the audience is `sts.amazon.com` and this will work for most cases. Changing the default audience may be necessary when using non-default AWS partitions. You can specify the audience through the `audience` input:
```yaml
- name: Configure AWS Credentials for China region audience
uses: aws-actions/configure-aws-credentials@v3
with:
audience: sts.amazonaws.com.cn
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.
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).
#### AssumeRoleWithWebIdentity and disable secure Action outputs
```yaml
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v2
with:
aws-region: us-east-2
role-to-assume: arn:aws:iam::123456789100:role/my-github-actions-role
role-session-name: MySessionName
mask-aws-account-id: false
```
In this example, account ID masking has been disabled. By default, the AWS
account ID will be obscured in the action's output. This may be helpful when
debugging action failures.
## Sample IAM OIDC CloudFormation Template
If you choose to use GitHub's OIDC provider, you must first set up federation
### Sample IAM OIDC CloudFormation Template
To use GitHub's OIDC provider, you must first set up federation
with the provider in 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).
Note that the thumbprint has been set to all F's because the thumbprint is not
used when authenticating tokens.actions.githubusercontent.com. Instead, IAM
used when authenticating `tokens.actions.githubusercontent.com`. Instead, IAM
uses its library of trusted CAs to authenticate. However, this value is still
required by the API.
@@ -282,16 +362,14 @@ Outputs:
Value: !GetAtt Role.Arn
```
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 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.
### 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.
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 info
For further information on OIDC and GitHub Actions, please see:
@@ -301,82 +379,6 @@ 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@v2
with:
role-skip-session-tagging: true
```
### Inline session policy
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@v2
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@v2
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@v2
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@v2
with:
managed-session-policies: |
arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
arn:aws:iam::aws:policy/AmazonS3OutpostsReadOnlyAccess
```
## Self-Hosted Runners
If you run your GitHub Actions in a
@@ -388,13 +390,13 @@ authenticate on your runner, this Action will as well.
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).
[default methods for the AWS SDK for Javascript](https://docs.aws.amazon.com/sdk-for-javascript/v3/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:
```yaml
uses: aws-actions/configure-aws-credentials@v2
uses: aws-actions/configure-aws-credentials@v3
with:
aws-region: us-east-2
```
@@ -404,7 +406,7 @@ 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:
```yaml
uses: aws-actions/configure-aws-credentials@v2
uses: aws-actions/configure-aws-credentials@v3
with:
aws-region: us-east-2
role-to-assume: my-github-actions-role
@@ -427,7 +429,7 @@ environment.
Manually configured proxy:
```yaml
uses: aws-actions/configure-aws-credentials@v2
uses: aws-actions/configure-aws-credentials@v3
with:
aws-region: us-east-2
role-to-assume: my-github-actions-role
@@ -451,6 +453,78 @@ to executing `aws` commands need to have the AWS CLI
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@v3
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@v3
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@v3
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@v3
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@v3
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@v3
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.
## License Summary
This code is made available under the MIT license.

11666
THIRD-PARTY

File diff suppressed because it is too large Load Diff

View File

@@ -1,76 +1,81 @@
name: 'Configure AWS Credentials For GitHub Actions'
description: 'Configure AWS credential and region environment variables for use with the AWS CLI and AWS SDKs'
name: '"Configure AWS Credentials" Action for GitHub Actions'
description: Configures AWS credentials for use in subsequent steps in a GitHub Action workflow
runs:
using: node16
main: dist/index.js
post: dist/cleanup/index.js
branding:
icon: 'cloud'
color: 'orange'
color: orange
icon: cloud
inputs:
audience:
default: 'sts.amazonaws.com'
description: 'The audience to use for the OIDC provider'
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.
required: false
aws-access-key-id:
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.
description: AWS Access Key ID. Provide this key if you want to assume a role using access keys rather than a web identity token.
required: false
aws-secret-access-key:
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.
description: AWS Secret Access Key. Required if aws-access-key-id is provided.
required: false
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
description: AWS Session Token.
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-duration-seconds:
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)'
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'
required: false
http-proxy:
description: 'Proxy to use for the AWS SDK agent'
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'
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
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.
required: false
role-session-name:
description: "Role session name (default: GitHubActions)"
required: false
role-skip-session-tagging:
description: Skip session tagging during role assumption
required: false
inline-session-policy:
description: 'Inline session policy'
description: Define an inline session policy to use when assuming a role
required: false
managed-session-policies:
description: 'List of 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
outputs:
aws-account-id:
description: 'The AWS account ID for the provided credentials'
runs:
using: 'node16'
main: 'dist/index.js'
post: 'dist/cleanup/index.js'
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

View File

@@ -1,51 +0,0 @@
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();
});
});

18401
dist/cleanup/index.js generated vendored

File diff suppressed because it is too large Load Diff

14
dist/cleanup/src/CredentialsClient.d.ts generated vendored Normal file
View File

@@ -0,0 +1,14 @@
import { STSClient } from '@aws-sdk/client-sts';
export interface CredentialsClientProps {
region?: string;
proxyServer?: string;
}
export declare class CredentialsClient {
region?: string;
private _stsClient?;
private readonly requestHandler?;
constructor(props: CredentialsClientProps);
get stsClient(): STSClient;
validateCredentials(expectedAccessKeyId?: string, roleChaining?: boolean): Promise<void>;
private loadCredentials;
}

15
dist/cleanup/src/assumeRole.d.ts generated vendored Normal file
View File

@@ -0,0 +1,15 @@
import type { CredentialsClient } from './CredentialsClient';
export interface assumeRoleParams {
credentialsClient: CredentialsClient;
roleToAssume: string;
roleDuration: number;
roleSessionName: string;
roleSkipSessionTagging?: boolean;
sourceAccountId?: string;
roleExternalId?: string;
webIdentityTokenFile?: string;
webIdentityToken?: string;
inlineSessionPolicy?: string;
managedSessionPolicies?: any[];
}
export declare function assumeRole(params: assumeRoleParams): Promise<import("@aws-sdk/client-sts").AssumeRoleCommandOutput>;

11
dist/cleanup/src/cleanup/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,11 @@
/**
* When the GitHub Actions job is done, clean up any environment variables that
* may have been set by the configure-aws-credentials steps in the job.
*
* Environment variables are not intended to be shared across different jobs in
* the same GitHub Actions workflow: GitHub Actions documentation states that
* each job runs in a fresh instance. However, doing our own cleanup will
* give us additional assurance that these environment variables are not shared
* with any other jobs.
*/
export declare function cleanup(): void;

16
dist/cleanup/src/helpers.d.ts generated vendored Normal file
View File

@@ -0,0 +1,16 @@
import type { Credentials } from '@aws-sdk/client-sts';
import type { CredentialsClient } from './CredentialsClient';
export declare function exportCredentials(creds?: Partial<Credentials>, outputCredentials?: boolean): void;
export declare function unsetCredentials(): void;
export declare function exportRegion(region: string): void;
export declare function exportAccountId(credentialsClient: CredentialsClient, maskAccountId?: boolean): Promise<string>;
export declare function sanitizeGitHubVariables(name: string): string;
export declare function defaultSleep(ms: number): Promise<unknown>;
declare let sleep: typeof defaultSleep;
export declare function withsleep(s: typeof sleep): void;
export declare function reset(): void;
export declare function verifyKeys(creds: Partial<Credentials> | undefined): void;
export declare function retryAndBackoff<T>(fn: () => Promise<T>, isRetryable: boolean, maxRetries?: number, retries?: number, base?: number): Promise<T>;
export declare function errorMessage(error: unknown): string;
export declare function isDefined<T>(i: T | undefined | null): i is T;
export {};

1
dist/cleanup/src/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1 @@
export declare function run(): Promise<void>;

1
dist/cleanup/test/cleanup.test.d.ts generated vendored Normal file
View File

@@ -0,0 +1 @@
export {};

1
dist/cleanup/test/helpers.test.d.ts generated vendored Normal file
View File

@@ -0,0 +1 @@
export {};

1
dist/cleanup/test/index.test.d.ts generated vendored Normal file
View File

@@ -0,0 +1 @@
export {};

64949
dist/index.js generated vendored

File diff suppressed because one or more lines are too long

View File

@@ -20,7 +20,7 @@ jobs:
- name: Checkout
uses: actions/checkout@v3
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v1-node16
uses: aws-actions/configure-aws-credentials@v3
with:
aws-region: us-east-1
## the following creates an ARN based on the values entered into github secrets

429
index.js
View File

@@ -1,429 +0,0 @@
const core = require('@actions/core');
const aws = require('aws-sdk');
const assert = require('assert');
const fs = require('fs');
const path = require('path');
const proxy = require('https-proxy-agent');
// 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,
inlineSessionPolicy,
managedSessionPolicies
} = 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;
}
if (isDefined(inlineSessionPolicy)) {
assumeRoleRequest.Policy = inlineSessionPolicy;
}
if (managedSessionPolicies && managedSessionPolicies.length) {
const policyArns = []
for (const managedSessionPolicy of managedSessionPolicies) {
policyArns.push({arn: managedSessionPolicy})
}
assumeRoleRequest.PolicyArns = policyArns;
}
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, roleChaining) {
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}`);
}
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');
}
}
}
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);
}
}
function configureProxy(proxyServer) {
const proxyFromEnv = process.env.HTTP_PROXY || process.env.http_proxy;
if (proxyFromEnv || proxyServer) {
let proxyToSet = null;
if (proxyServer){
console.log(`Setting proxy from actions input: ${proxyServer}`);
proxyToSet = proxyServer;
} else {
console.log(`Setting proxy from environment: ${proxyFromEnv}`);
proxyToSet = proxyFromEnv;
}
aws.config.update({
httpOptions: { agent: proxy(proxyToSet) }
});
}
}
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 });
const roleChainingInput = core.getInput('role-chaining', { required: false }) || 'false';
const roleChaining = roleChainingInput.toLowerCase() === 'true';
let roleDurationSeconds = core.getInput('role-duration-seconds', {required: false})
|| (sessionToken && SESSION_ROLE_DURATION)
|| (roleChaining && 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 });
const proxyServer = core.getInput('http-proxy', { required: false });
const inlineSessionPolicy = core.getInput('inline-session-policy', { required: false });
const managedSessionPolicies = core.getMultilineInput('managed-session-policies', { 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 different 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 identity 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 && !roleChaining
}
// 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});
}
// Configures proxy
configureProxy(proxyServer);
// 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, roleChaining);
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,
inlineSessionPolicy,
managedSessionPolicies
}) }, 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();
}

File diff suppressed because it is too large Load Diff

31
jest.config.cjs Normal file
View File

@@ -0,0 +1,31 @@
/** @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;

15391
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,38 +1,64 @@
{
"name": "aws-actions-configure-aws-credentials",
"version": "2.0.0",
"description": "Configure AWS Credentials",
"main": "index.js",
"name": "configure-aws-credentials",
"description": "A GitHub Action to configure AWS credentials",
"scripts": {
"lint": "eslint **.js",
"package": "ncc build index.js -o dist && ncc build cleanup.js -o dist/cleanup",
"test": "npm run lint && jest --coverage --verbose"
"build": "tsc --project tsconfig.build.json",
"lint": "eslint .",
"package": "npm run build && ncc build --license THIRD-PARTY -o dist && ncc build src/cleanup/index.ts -o dist/cleanup && copyup -E dist/THIRD-PARTY . && del-cli dist/THIRD-PARTY",
"test": "npm run lint && jest --verbose"
},
"repository": {
"type": "git",
"url": "git+https://github.com/aws-actions/configure-aws-credentials.git"
"author": {
"name": "Amazon.com, Inc. or its affiliates",
"url": "https://aws.amazon.com",
"organization": true
},
"devDependencies": {
"@aws-sdk/credential-provider-env": "^3.186.0",
"@aws-sdk/property-provider": "^3.188.0",
"@jest/globals": "^29.1.2",
"@types/jest": "^29.1.2",
"@types/node": "^14",
"@typescript-eslint/eslint-plugin": "^5",
"@typescript-eslint/parser": "^5",
"@vercel/ncc": "^0.34.0",
"aws-sdk-client-mock": "^2.0.0",
"copyfiles": "^2.4.1",
"del-cli": "^5.0.0",
"eslint": "^8",
"eslint-config-prettier": "^8.5.0",
"eslint-import-resolver-node": "^0.3.6",
"eslint-import-resolver-typescript": "^3.5.1",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-prettier": "^4.2.1",
"jest": "^29.1.2",
"jest-junit": "^13",
"json-schema": "^0.4.0",
"prettier": "^2.7.1",
"standard-version": "^9",
"ts-jest": "^29.0.3",
"typescript": "^4.8.4"
},
"dependencies": {
"@actions/core": "^1.10.0",
"@aws-sdk/client-sts": "^3",
"@aws-sdk/node-http-handler": "^3",
"https-proxy-agent": "^5.0.0"
},
"keywords": [
"AWS",
"GitHub",
"Actions",
"JavaScript"
"aws",
"github",
"github-action"
],
"author": "AWS",
"engines": {
"node": ">= 14.0.0"
},
"main": "build/index.js",
"license": "MIT",
"homepage": "https://github.com/aws-actions/configure-aws-credentials",
"version": "0.0.0",
"bugs": {
"url": "https://github.com/aws-actions/configure-aws-credentials/issues"
},
"homepage": "https://github.com/aws-actions/configure-aws-credentials#readme",
"dependencies": {
"@actions/core": "^1.10.0",
"aws-sdk": "^2.1441.0",
"axios": "^1.4.0",
"https-proxy-agent": "^5.0.1"
},
"devDependencies": {
"@vercel/ncc": "^0.36.1",
"eslint": "^8.47.0",
"jest": "^29.6.3"
}
"types": "build/index.d.ts",
"private": true
}

70
src/CredentialsClient.ts Normal file
View File

@@ -0,0 +1,70 @@
import { info } from '@actions/core';
import { STSClient } from '@aws-sdk/client-sts';
import { NodeHttpHandler } from '@aws-sdk/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;
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();
}
}

169
src/assumeRole.ts Normal file
View File

@@ -0,0 +1,169 @@
import assert from 'assert';
import fs from 'fs';
import path from '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, verifyKeys } 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,
})
);
verifyKeys(creds.Credentials);
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,
})
);
verifyKeys(creds.Credentials);
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 }));
verifyKeys(creds.Credentials);
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?: any[];
}
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>;
keys.forEach((k) => commonAssumeRoleParams[k] === undefined && delete commonAssumeRoleParams[k]);
// Instantiate STS client
const stsClient = credentialsClient.stsClient;
// Assume role using one of three methods
switch (true) {
case !!webIdentityToken: {
return assumeRoleWithOIDC(commonAssumeRoleParams, stsClient, webIdentityToken!);
}
case !!webIdentityTokenFile: {
return assumeRoleWithWebIdentityTokenFile(
commonAssumeRoleParams,
stsClient,
webIdentityTokenFile!,
GITHUB_WORKSPACE
);
}
default: {
return assumeRoleWithCredentials(commonAssumeRoleParams, stsClient);
}
}
}

View File

@@ -1,4 +1,5 @@
const core = require('@actions/core');
import * as core from '@actions/core';
import { errorMessage } from '../helpers';
/**
* When the GitHub Actions job is done, clean up any environment variables that
@@ -11,7 +12,7 @@ const core = require('@actions/core');
* with any other jobs.
*/
async function cleanup() {
export 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
@@ -22,15 +23,15 @@ async function cleanup() {
core.exportVariable('AWS_SESSION_TOKEN', '');
core.exportVariable('AWS_DEFAULT_REGION', '');
core.exportVariable('AWS_REGION', '');
}
catch (error) {
core.setFailed(error.message);
} catch (error) {
core.setFailed(errorMessage(error));
}
}
module.exports = cleanup;
/* istanbul ignore next */
/* c8 ignore start */
if (require.main === module) {
cleanup();
try {
cleanup();
} catch (error) {
core.setFailed(errorMessage(error));
}
}

142
src/helpers.ts Normal file
View File

@@ -0,0 +1,142 @@
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 = /[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]+/;
// 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);
}
}
}
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;
}
if (creds.AccessKeyId) {
if (SPECIAL_CHARS_REGEX.test(creds.AccessKeyId)) {
throw new Error('AccessKeyId contains special characters.');
}
}
if (creds.SecretAccessKey) {
if (SPECIAL_CHARS_REGEX.test(creds.SecretAccessKey)) {
throw new Error('SecretAccessKey contains special characters.');
}
}
}
// 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() * (Math.pow(2, retries) * base));
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 */

182
src/index.ts Normal file
View File

@@ -0,0 +1,182 @@
import * as core from '@actions/core';
import { assumeRole } from './assumeRole';
import { CredentialsClient } from './CredentialsClient';
import {
errorMessage,
retryAndBackoff,
exportRegion,
exportCredentials,
exportAccountId,
unsetCredentials,
} 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 {
// 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 = 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: any[] = [];
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';
const disableRetry = disableRetryInput.toLowerCase() === 'true';
let maxRetries = parseInt(core.getInput('retry-max-attempts', { required: false })) || 12;
if (maxRetries < 1) {
maxRetries = 1;
}
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?'
);
}
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 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) {
throw new Error('Could not determine how to assume credentials. Please check your inputs and try again.');
}
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) {
const roleCredentials = await retryAndBackoff(
async () => {
return assumeRole({
credentialsClient,
sourceAccountId,
roleToAssume,
roleExternalId,
roleDuration,
roleSessionName,
roleSkipSessionTagging,
webIdentityTokenFile,
webIdentityToken,
inlineSessionPolicy,
managedSessionPolicies,
});
},
!disableRetry,
maxRetries
);
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 */
if (require.main === module) {
(async () => {
await run();
})().catch((error) => {
core.setFailed(errorMessage(error));
});
}

52
test/cleanup.test.ts Normal file
View File

@@ -0,0 +1,52 @@
import * as core from '@actions/core';
import { cleanup } from '../src/cleanup';
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();
jest.spyOn(core, 'exportVariable').mockImplementation();
jest.spyOn(core, 'setSecret').mockImplementation();
jest.spyOn(core, 'setOutput').mockImplementation();
jest.spyOn(core, 'setFailed').mockImplementation();
process.env = { ...OLD_ENV, ...ACTION_ENVIRONMENT_VARIABLES };
});
afterEach(() => {
process.env = OLD_ENV;
});
test('replaces AWS credential and region env vars 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', '');
});
test('error is caught and fails the action', () => {
jest.spyOn(core, 'exportVariable').mockImplementation(() => {
throw new Error();
});
cleanup();
expect(core.setFailed).toHaveBeenCalled();
});
});

26
test/helpers.test.ts Normal file
View File

@@ -0,0 +1,26 @@
import * as helpers from '../src/helpers';
describe('helpers', () => {
beforeEach(() => {
jest.resetModules();
jest.clearAllMocks();
});
test('removes brackets from GitHub Actor', () => {
expect(helpers.sanitizeGitHubVariables('foo[bot]')).toEqual('foo_bot_');
});
test('removes special characters from worflow names', () => {
expect(helpers.sanitizeGitHubVariables('sdf234@#$%$^&*()_+{}|:"<>?')).toEqual('sdf234@__________+___:____');
});
test('can sleep', () => {
const sleep = helpers.defaultSleep(10);
expect(Promise.race([sleep, new Promise((_res, rej) => setTimeout(rej, 20))])).resolves;
});
test("backoff function doesn't retry non-retryable errors", async () => {
const fn = jest.fn().mockRejectedValue('i am not retryable');
await expect(helpers.retryAndBackoff(fn, false)).rejects.toMatch('i am not retryable');
expect(fn).toHaveBeenCalledTimes(1);
});
});

847
test/index.test.ts Normal file
View File

@@ -0,0 +1,847 @@
import * as core from '@actions/core';
import {
AssumeRoleCommand,
AssumeRoleWithWebIdentityCommand,
GetCallerIdentityCommand,
STSClient,
} from '@aws-sdk/client-sts';
import { fromEnv } from '@aws-sdk/credential-provider-env';
import { CredentialsProviderError } from '@aws-sdk/property-provider';
import { mockClient } from 'aws-sdk-client-mock';
import { withsleep, reset } from '../src/helpers';
import { run } from '../src/index';
// #region
const FAKE_ACCESS_KEY_ID = 'MYAWSACCESSKEYID';
const FAKE_SECRET_ACCESS_KEY = 'MYAWSSECRETACCESSKEY';
const FAKE_SESSION_TOKEN = 'MYAWSSESSIONTOKEN';
const FAKE_STS_ACCESS_KEY_ID = 'STSAWSACCESSKEYID';
const FAKE_STS_SECRET_ACCESS_KEY = 'STSAWSSECRETACCESSKEY';
const FAKE_STS_SESSION_TOKEN = 'STSAWSSESSIONTOKEN';
const FAKE_ASSUMED_ROLE_ID = 'AROAFAKEASSUMEDROLEID';
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 MANAGED_SESSION_POLICY_INPUT = [
'arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess',
'arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess',
];
const ENVIRONMENT_VARIABLE_OVERRIDES = {
SHOW_STACK_TRACE: 'false',
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_';
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,
};
const ASSUME_ROLE_INPUTS = { ...CREDS_INPUTS, 'role-to-assume': ROLE_ARN, 'aws-region': FAKE_REGION };
// #endregion
const mockedSTS = mockClient(STSClient);
function mockGetInput(requestResponse: Record<string, string>) {
return function (name: string, _options: unknown): string {
return requestResponse[name]!;
};
}
function mockGetMultilineInput(requestResponse: Record<string, string[]>) {
return function (name: string, _options: unknown): string[] {
return requestResponse[name]!;
};
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
jest.mock('fs', () => ({
...jest.requireActual('fs'),
existsSync: jest.fn(() => true),
readFileSync: jest.fn(() => 'testpayload'),
}));
jest.mock('@aws-sdk/credential-provider-env', () => ({
// This is the actual implementation in the SDK ^_^
fromEnv: jest.fn().mockImplementation(() => () => {
const accessKeyId = process.env['AWS_ACCESS_KEY_ID'];
const secretAccessKey = process.env['AWS_SECRET_ACCESS_KEY'];
const sessionToken = process.env['AWS_SESSION_TOKEN'];
const expiration = process.env['AWS_CREDENTIAL_EXPIRATION'];
return {
accessKeyId,
secretAccessKey,
sessionToken,
expiration,
};
}),
}));
describe('Configure AWS Credentials', () => {
const OLD_ENV = process.env;
beforeEach(() => {
jest.resetModules();
process.env = { ...OLD_ENV, ...ENVIRONMENT_VARIABLE_OVERRIDES };
jest.clearAllMocks();
mockedSTS.reset();
(fromEnv as jest.Mock).mockReset();
jest.spyOn(core, 'getMultilineInput').mockImplementation(() => []);
jest.spyOn(core, 'getIDToken').mockImplementation(async () => Promise.resolve('testtoken'));
jest.spyOn(core, 'exportVariable').mockImplementation();
jest.spyOn(core, 'setSecret').mockImplementation();
jest.spyOn(core, 'setOutput').mockImplementation();
jest.spyOn(core, 'setFailed').mockImplementation();
jest.spyOn(core, 'debug').mockImplementation();
jest.spyOn(core, 'info').mockImplementation((string) => {
return string;
});
(fromEnv as jest.Mock)
.mockImplementationOnce(() => () => ({
accessKeyId: FAKE_ACCESS_KEY_ID,
secretAccessKey: FAKE_SECRET_ACCESS_KEY,
}))
.mockImplementationOnce(() => () => ({
accessKeyId: FAKE_STS_ACCESS_KEY_ID,
secretAccessKey: FAKE_STS_SECRET_ACCESS_KEY,
}));
mockedSTS
.on(GetCallerIdentityCommand)
.resolvesOnce({ Account: FAKE_ACCOUNT_ID })
.resolvesOnce({ Account: FAKE_ROLE_ACCOUNT_ID });
mockedSTS.on(AssumeRoleCommand).resolves({
Credentials: {
AccessKeyId: FAKE_STS_ACCESS_KEY_ID,
SecretAccessKey: FAKE_STS_SECRET_ACCESS_KEY,
SessionToken: FAKE_STS_SESSION_TOKEN,
Expiration: new Date(8640000000000000),
},
AssumedRoleUser: {
AssumedRoleId: FAKE_ASSUMED_ROLE_ID,
Arn: ROLE_ARN,
},
});
mockedSTS.on(AssumeRoleWithWebIdentityCommand).resolves({
Credentials: {
AccessKeyId: FAKE_STS_ACCESS_KEY_ID,
SecretAccessKey: FAKE_STS_SECRET_ACCESS_KEY,
SessionToken: FAKE_STS_SESSION_TOKEN,
Expiration: new Date(8640000000000000),
},
AssumedRoleUser: {
AssumedRoleId: FAKE_ASSUMED_ROLE_ID,
Arn: ROLE_ARN,
},
});
withsleep(async () => {
return Promise.resolve();
});
});
afterEach(() => {
process.env = OLD_ENV;
reset();
});
test('exports env vars', async () => {
jest.spyOn(core, 'getInput').mockImplementation(mockGetInput(DEFAULT_INPUTS));
await run();
expect(mockedSTS.commandCalls(AssumeRoleCommand)).toHaveLength(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', 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);
});
test('action fails when github env vars are not set', async () => {
jest.spyOn(core, 'getInput').mockImplementation(mockGetInput(ASSUME_ROLE_INPUTS));
delete process.env['GITHUB_SHA'];
await run();
expect(core.setFailed).toHaveBeenCalledWith(
'Missing required environment variables. Are you running in GitHub Actions?'
);
});
test('action does not require GITHUB_REF env var', async () => {
jest.spyOn(core, 'getInput').mockImplementation(mockGetInput(DEFAULT_INPUTS));
delete process.env['GITHUB_REF'];
await run();
expect(core.setFailed).toHaveBeenCalledTimes(0);
});
test('action with no accessible credentials fails', async () => {
const mockInputs = { 'aws-region': FAKE_REGION };
jest.spyOn(core, 'getInput').mockImplementation(mockGetInput(mockInputs));
(fromEnv as jest.Mock).mockReset();
(fromEnv as jest.Mock).mockImplementation(() => () => {
throw new CredentialsProviderError('test');
});
await run();
expect(core.setFailed).toHaveBeenCalledWith(
'Could not determine how to assume credentials. Please check your inputs and try again.'
);
});
test('action with empty credentials fails', async () => {
const mockInputs = { 'aws-region': FAKE_REGION };
jest.spyOn(core, 'getInput').mockImplementation(mockGetInput(mockInputs));
(fromEnv as jest.Mock).mockReset();
(fromEnv as jest.Mock).mockImplementation(
() => async () => Promise.resolve({ accessKeyId: '', secretAccessKey: '' })
);
await run();
expect(core.setFailed).toHaveBeenCalledWith(
'Could not determine how to assume credentials. Please check your inputs and try again.'
);
});
test('action fails when credentials are not set in the SDK correctly', async () => {
jest.spyOn(core, 'getInput').mockImplementation(mockGetInput(DEFAULT_INPUTS));
(fromEnv as jest.Mock).mockReset();
(fromEnv as jest.Mock).mockImplementationOnce(() => async () => Promise.resolve({ accessKeyId: '123' }));
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' };
jest.spyOn(core, 'getInput').mockImplementation(mockGetInput(mockInputs));
await run();
expect(mockedSTS.commandCalls(AssumeRoleCommand)).toHaveLength(0);
expect(core.exportVariable).toHaveBeenCalledTimes(4);
expect(core.setSecret).toHaveBeenCalledTimes(2);
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);
});
test('existing env var creds are cleared', async () => {
const mockInputs = { ...CREDS_INPUTS, 'aws-region': 'eu-west-1' };
jest.spyOn(core, 'getInput').mockImplementation(mockGetInput(mockInputs));
process.env['AWS_ACCESS_KEY_ID'] = 'foo';
process.env['AWS_SECRET_ACCESS_KEY'] = 'bar';
process.env['AWS_SESSION_TOKEN'] = 'helloworld';
await run();
expect(mockedSTS.commandCalls(AssumeRoleCommand)).toHaveLength(0);
expect(core.exportVariable).toHaveBeenCalledTimes(5);
expect(core.setSecret).toHaveBeenCalledTimes(2);
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);
});
test('validates region name', async () => {
const mockInputs = { ...CREDS_INPUTS, 'aws-region': '$AWS_REGION' };
jest.spyOn(core, 'getInput').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 () => {
const inputsWIthoutSecretKey = { ...DEFAULT_INPUTS };
//@ts-expect-error deleting a required property to test failure condition
delete inputsWIthoutSecretKey['aws-secret-access-key'];
jest.spyOn(core, 'getInput').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 into masking account ID', async () => {
const mockInputs = { ...CREDS_INPUTS, 'aws-region': 'us-east-1', 'mask-aws-account-id': 'true' };
jest.spyOn(core, 'getInput').mockImplementation(mockGetInput(mockInputs));
await run();
expect(mockedSTS.commandCalls(AssumeRoleCommand)).toHaveLength(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).toHaveBeenCalledWith(FAKE_ACCOUNT_ID);
expect(core.setSecret).toHaveBeenCalledTimes(3);
});
test('error is caught by core.setFailed and caught', async () => {
jest.spyOn(core, 'getInput').mockImplementation(mockGetInput(DEFAULT_INPUTS));
mockedSTS.reset();
mockedSTS.on(GetCallerIdentityCommand).rejects();
await run();
expect(core.setFailed).toHaveBeenCalled();
});
test('role assumption tags', async () => {
jest.spyOn(core, 'getInput').mockImplementation(mockGetInput(ASSUME_ROLE_INPUTS));
await run();
expect(mockedSTS.commandCalls(AssumeRoleCommand)[0]?.args[0].input).toEqual({
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('role assumption duration provided', async () => {
jest
.spyOn(core, 'getInput')
.mockImplementation(mockGetInput({ ...ASSUME_ROLE_INPUTS, 'role-duration-seconds': '5' }));
await run();
expect(mockedSTS.commandCalls(AssumeRoleCommand)[0]?.args[0].input).toEqual({
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 () => {
jest
.spyOn(core, 'getInput')
.mockImplementation(mockGetInput({ ...ASSUME_ROLE_INPUTS, 'role-session-name': 'MySessionName' }));
await run();
expect(mockedSTS.commandCalls(AssumeRoleCommand)[0]?.args[0].input).toEqual({
RoleArn: ROLE_ARN,
RoleSessionName: 'MySessionName',
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('role name provided instead of ARN', async () => {
jest
.spyOn(core, 'getInput')
.mockImplementation(mockGetInput({ ...CREDS_INPUTS, 'role-to-assume': ROLE_NAME, 'aws-region': FAKE_REGION }));
await run();
expect(mockedSTS.commandCalls(AssumeRoleCommand)[0]?.args[0].input).toEqual({
RoleArn: 'arn:aws:iam::123456789012:role/MY-ROLE',
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('web identity token file provided with absolute path', async () => {
jest.spyOn(core, 'getInput').mockImplementation(
mockGetInput({
'role-to-assume': ROLE_ARN,
'aws-region': FAKE_REGION,
'web-identity-token-file': '/fake/token/file',
})
);
await run();
expect(mockedSTS.commandCalls(AssumeRoleWithWebIdentityCommand)[0]?.args[0].input).toEqual({
RoleArn: 'arn:aws:iam::111111111111:role/MY-ROLE',
RoleSessionName: 'GitHubActions',
DurationSeconds: 3600,
WebIdentityToken: 'testpayload',
});
});
test('web identity token file provided with relative path', async () => {
jest.spyOn(core, 'getInput').mockImplementation(
mockGetInput({
'role-to-assume': ROLE_ARN,
'aws-region': FAKE_REGION,
'web-identity-token-file': 'fake/token/file',
})
);
await run();
expect(mockedSTS.commandCalls(AssumeRoleWithWebIdentityCommand)[0]?.args[0].input).toEqual({
RoleArn: 'arn:aws:iam::111111111111:role/MY-ROLE',
RoleSessionName: 'GitHubActions',
DurationSeconds: 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';
jest
.spyOn(core, 'getInput')
.mockImplementation(mockGetInput({ 'role-to-assume': ROLE_ARN, 'aws-region': FAKE_REGION }));
await run();
expect(mockedSTS.commandCalls(AssumeRoleWithWebIdentityCommand)[0]?.args[0].input).toEqual({
RoleArn: 'arn:aws:iam::111111111111:role/MY-ROLE',
RoleSessionName: 'GitHubActions',
DurationSeconds: 3600,
WebIdentityToken: 'testtoken',
});
expect(core.getIDToken).toHaveBeenCalledTimes(1);
});
test('getIDToken call retries when failing', async () => {
process.env['GITHUB_ACTIONS'] = 'true';
process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN'] = 'test-token';
jest.spyOn(core, 'getIDToken').mockImplementation(() => {
throw new Error('test error');
});
jest
.spyOn(core, 'getInput')
.mockImplementation(mockGetInput({ 'role-to-assume': ROLE_ARN, 'aws-region': FAKE_REGION }));
await run();
expect(core.getIDToken).toHaveBeenCalledTimes(12);
expect(core.setFailed).toHaveBeenCalledWith('getIDToken call failed: test error');
});
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';
jest.spyOn(core, 'getInput').mockImplementation(
mockGetInput({
'role-to-assume': ROLE_ARN,
'aws-region': FAKE_REGION,
'role-duration-seconds': CUSTOM_ROLE_DURATION,
})
);
await run();
expect(mockedSTS.commandCalls(AssumeRoleWithWebIdentityCommand)[0]?.args[0].input).toEqual({
RoleArn: 'arn:aws:iam::111111111111:role/MY-ROLE',
RoleSessionName: 'GitHubActions',
DurationSeconds: parseInt(CUSTOM_ROLE_DURATION),
WebIdentityToken: 'testtoken',
});
});
test('GH OIDC check fails if token is not set', async () => {
process.env['GITHUB_ACTIONS'] = 'true';
jest.spyOn(core, 'getInput').mockImplementation(
mockGetInput({
'role-to-assume': ROLE_ARN,
'aws-region': FAKE_REGION,
})
);
await run();
expect(core.info).toHaveBeenCalledWith(
'It looks like you might be trying to authenticate with OIDC. Did you mean to set the `id-token` permission?'
);
expect(core.setFailed).toHaveBeenCalledWith(
'Could not determine how to assume credentials. Please check your inputs and try again.'
);
});
test('role assumption fails after maximum trials using OIDC provider', async () => {
process.env['GITHUB_ACTIONS'] = 'true';
process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN'] = 'test-token';
jest
.spyOn(core, 'getInput')
.mockImplementation(mockGetInput({ 'role-to-assume': ROLE_ARN, 'aws-region': FAKE_REGION }));
mockedSTS.reset();
mockedSTS.on(AssumeRoleWithWebIdentityCommand).rejects();
await run();
expect(mockedSTS.commandCalls(AssumeRoleWithWebIdentityCommand).length).toEqual(12);
});
test('role assumption fails after one trial when disabling retry', async () => {
process.env['GITHUB_ACTIONS'] = 'true';
process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN'] = 'test-token';
jest
.spyOn(core, 'getInput')
.mockImplementation(
mockGetInput({ 'role-to-assume': ROLE_ARN, 'aws-region': FAKE_REGION, 'disable-retry': 'true' })
);
mockedSTS.reset();
mockedSTS.on(AssumeRoleWithWebIdentityCommand).rejects();
await run();
expect(mockedSTS.commandCalls(AssumeRoleWithWebIdentityCommand).length).toEqual(1);
});
test('role assumption fails if access key id contains special characters', async () => {
jest.spyOn(core, 'getInput').mockImplementation(mockGetInput({ ...ASSUME_ROLE_INPUTS }));
mockedSTS.on(AssumeRoleCommand).resolves({
Credentials: {
AccessKeyId: 'asdf+',
SecretAccessKey: FAKE_STS_SECRET_ACCESS_KEY,
SessionToken: FAKE_STS_SESSION_TOKEN,
Expiration: new Date(8640000000000000),
},
});
await run();
expect(mockedSTS.commandCalls(AssumeRoleCommand).length).toEqual(12);
expect(core.setFailed).toHaveBeenCalledWith(
'Could not assume role with user credentials: AccessKeyId contains special characters.'
);
});
test('role assumption fails if secret access key contains special characters', async () => {
jest.spyOn(core, 'getInput').mockImplementation(mockGetInput({ ...ASSUME_ROLE_INPUTS }));
mockedSTS.on(AssumeRoleCommand).resolves({
Credentials: {
AccessKeyId: FAKE_STS_ACCESS_KEY_ID,
SecretAccessKey: 'asdf+',
SessionToken: FAKE_STS_SESSION_TOKEN,
Expiration: new Date(8640000000000000),
},
});
await run();
expect(mockedSTS.commandCalls(AssumeRoleCommand).length).toEqual(12);
expect(core.setFailed).toHaveBeenCalledWith(
'Could not assume role with user credentials: SecretAccessKey contains special characters.'
);
});
test('role assumption succeeds if keys have no special characters', async () => {
jest.spyOn(core, 'getInput').mockImplementation(mockGetInput({ ...ASSUME_ROLE_INPUTS }));
mockedSTS.on(AssumeRoleCommand).resolves({
Credentials: {
AccessKeyId: FAKE_STS_ACCESS_KEY_ID,
SecretAccessKey: FAKE_STS_SECRET_ACCESS_KEY,
SessionToken: FAKE_STS_SESSION_TOKEN,
Expiration: new Date(8640000000000000),
},
});
await run();
expect(mockedSTS.commandCalls(AssumeRoleCommand).length).toEqual(1);
});
test('max retries is configurable', async () => {
process.env['GITHUB_ACTIONS'] = 'true';
process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN'] = 'test-token';
jest.spyOn(core, 'getInput').mockImplementation(
mockGetInput({
'role-to-assume': ROLE_ARN,
'aws-region': FAKE_REGION,
'retry-max-attempts': '15',
})
);
mockedSTS.reset();
mockedSTS.on(AssumeRoleWithWebIdentityCommand).rejects();
await run();
expect(mockedSTS.commandCalls(AssumeRoleWithWebIdentityCommand).length).toEqual(15);
expect(core.setFailed).toHaveBeenCalledWith('Could not assume role with OIDC: ');
});
test('max retries negative input does not retry', async () => {
process.env['GITHUB_ACTIONS'] = 'true';
process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN'] = 'test-token';
jest.spyOn(core, 'getInput').mockImplementation(
mockGetInput({
'role-to-assume': ROLE_ARN,
'aws-region': FAKE_REGION,
'retry-max-attempts': '-1',
})
);
mockedSTS.reset();
mockedSTS.on(AssumeRoleWithWebIdentityCommand).rejects();
await run();
expect(mockedSTS.commandCalls(AssumeRoleWithWebIdentityCommand).length).toEqual(1);
expect(core.setFailed).toHaveBeenCalledWith('Could not assume role with OIDC: ');
});
test('role external ID provided', async () => {
jest
.spyOn(core, 'getInput')
.mockImplementation(mockGetInput({ ...ASSUME_ROLE_INPUTS, 'role-external-id': 'abcdef' }));
await run();
expect(mockedSTS.commandCalls(AssumeRoleCommand)[0]?.args[0].input).toEqual({
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 },
],
ExternalId: 'abcdef',
});
});
test('workflow name sanitized in role assumption tags', async () => {
jest.spyOn(core, 'getInput').mockImplementation(mockGetInput(ASSUME_ROLE_INPUTS));
process.env = {
...process.env,
GITHUB_WORKFLOW:
'Workflow!"#$%&\'()*+, -./:;<=>?@[]^_`{|}~🙂💥🍌1yFvMOeD3ZHYsHrGjCceOboMYzBPo0CRNFdcsVRG6UgR3A912a8KfcBtEVvkAS7kRBq80umGff8mux5IN1y55HQWPNBNyaruuVr4islFXte4FDQZexGJRUSMyHQpxJ8OmZnET84oDmbvmIjgxI6IBrdihX9PHMapT4gQvRYnLqNiKb18rEMWDNoZRy51UPX5sWK2GKPipgKSO9kqLckZai9D2AN2RlWCxtMqChNtxuxjqeqhoQZo0oaq39sjcRZgAAAAAAA',
};
const sanitizedWorkflowName =
'Workflow__________+_ -./:__=__@____________1yFvMOeD3ZHYsHrGjCceOboMYzBPo0CRNFdcsVRG6UgR3A912a8KfcBtEVvkAS7kRBq80umGff8mux5IN1y55HQWPNBNyaruuVr4islFXte4FDQZexGJRUSMyHQpxJ8OmZnET84oDmbvmIjgxI6IBrdihX9PHMapT4gQvRYnLqNiKb18rEMWDNoZRy51UPX5sWK2GKPipgKSO9kqLckZa';
await run();
expect(mockedSTS.commandCalls(AssumeRoleCommand)[0]?.args[0].input).toEqual({
RoleArn: ROLE_ARN,
RoleSessionName: 'GitHubActions',
DurationSeconds: 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 () => {
jest
.spyOn(core, 'getInput')
.mockImplementation(mockGetInput({ ...ASSUME_ROLE_INPUTS, 'role-skip-session-tagging': 'true' }));
await run();
expect(mockedSTS.commandCalls(AssumeRoleCommand)[0]?.args[0].input).toEqual({
RoleArn: ROLE_ARN,
RoleSessionName: 'GitHubActions',
DurationSeconds: 3600,
Tags: undefined,
});
});
test('skip tagging provided as false', async () => {
jest
.spyOn(core, 'getInput')
.mockImplementation(mockGetInput({ ...ASSUME_ROLE_INPUTS, 'role-skip-session-tagging': 'false' }));
await run();
expect(mockedSTS.commandCalls(AssumeRoleCommand)[0]?.args[0].input).toEqual({
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('skip tagging not provided', async () => {
jest.spyOn(core, 'getInput').mockImplementation(mockGetInput({ ...ASSUME_ROLE_INPUTS }));
await run();
expect(mockedSTS.commandCalls(AssumeRoleCommand)[0]?.args[0].input).toEqual({
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('masks variables before exporting', async () => {
jest.spyOn(core, 'getInput').mockImplementation(mockGetInput(ASSUME_ROLE_INPUTS));
const maskedValues: string[] = [];
const publicFields = ['AWS_REGION', 'AWS_DEFAULT_REGION'];
jest.spyOn(core, 'setSecret').mockImplementation((secret) => {
maskedValues.push(secret);
});
jest.spyOn(core, 'exportVariable').mockImplementation((name, value) => {
const val = String(value);
if (!maskedValues.includes(val) && !publicFields.includes(name)) {
throw new Error(`{value} for variable ${name} is not masked yet!`);
}
process.env[name] = val;
});
await run();
expect(core.exportVariable).toReturn();
});
test('inline policy and managed session policies are provided in assume role calls', async () => {
jest
.spyOn(core, 'getInput')
.mockImplementation(mockGetInput({ ...ASSUME_ROLE_INPUTS, 'inline-session-policy': 'inline' }));
jest
.spyOn(core, 'getMultilineInput')
.mockImplementation(mockGetMultilineInput({ 'managed-session-policies': MANAGED_SESSION_POLICY_INPUT }));
await run();
expect(mockedSTS.commandCalls(AssumeRoleCommand)[0]?.args[0].input).toEqual({
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 },
],
Policy: 'inline',
PolicyArns: [
{ arn: 'arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess' },
{ arn: 'arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess' },
],
});
});
test('prints assumed role id', async () => {
jest.spyOn(core, 'getInput').mockImplementation(mockGetInput(ASSUME_ROLE_INPUTS));
await run();
expect(core.info).toHaveBeenCalledWith(`Authenticated as assumedRoleId ${FAKE_ASSUMED_ROLE_ID}`);
});
test('unsets credentials if enabled', async () => {
jest
.spyOn(core, 'getInput')
.mockImplementation(mockGetInput({ ...ASSUME_ROLE_INPUTS, 'unset-current-credentials': 'true' }));
await run();
expect(core.exportVariable).toHaveBeenCalledTimes(12);
});
test('sets credentials as output if enabled', async () => {
jest
.spyOn(core, 'getInput')
.mockImplementation(mockGetInput({ ...ASSUME_ROLE_INPUTS, 'output-credentials': 'true' }));
await run();
expect(core.setOutput).toHaveBeenCalledTimes(4);
});
});

9
tsconfig.build.json Normal file
View File

@@ -0,0 +1,9 @@
{
"extends": "./tsconfig.json",
"exclude": [
"test/**/*.ts"
],
"compilerOptions": {
"rootDir": "src"
},
}

34
tsconfig.json Normal file
View File

@@ -0,0 +1,34 @@
{
"compilerOptions": {
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"strict": true,
"exactOptionalPropertyTypes": false,
"noFallthroughCasesInSwitch": true,
"noImplicitOverride": true,
"noImplicitReturns": true,
"noPropertyAccessFromIndexSignature": true,
"noUncheckedIndexedAccess": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"module": "CommonJS",
"resolveJsonModule": true,
"outDir": "build",
"declaration": true,
"newLine": "lf",
"noEmitOnError": true,
"sourceMap": true,
"disableSizeLimit": true,
"forceConsistentCasingInFileNames": true,
"lib": [ "ES2020" ],
"target": "ES2020",
"noErrorTruncation": true,
"esModuleInterop": true
},
"include": [
"src/**/*.ts",
"test/**/*.ts"
],
"exclude": [],
}