From 76997ececd8d4785d64ed4d607e79638a36bebf6 Mon Sep 17 00:00:00 2001 From: Peter Woodworth <44349620+peterwoodworth@users.noreply.github.com> Date: Thu, 24 Aug 2023 14:38:12 -0700 Subject: [PATCH] fix: action fails when intending to use existing credentials (#796) * fix: action fails when intending to use existing credentials * fix: action fails when intending to use existing credentials * fix: action fails when intending to use existing credentials * fix: action fails when intending to use existing credentials * fix: action fails when intending to use existing credentials * fix: action fails when intending to use existing credentials --------- Co-authored-by: Tom Keller <1083460+kellertk@users.noreply.github.com> --- .github/workflows/tests-integ.yml | 22 ++++++++++++++++++++++ README.md | 16 +++++++++------- dist/index.js | 9 ++++++--- src/index.ts | 11 ++++++++--- test/index.test.ts | 22 +++++++++++++++++++++- 5 files changed, 66 insertions(+), 14 deletions(-) diff --git a/.github/workflows/tests-integ.yml b/.github/workflows/tests-integ.yml index 0ed6c2e3e..84dd38466 100644 --- a/.github/workflows/tests-integ.yml +++ b/.github/workflows/tests-integ.yml @@ -48,6 +48,28 @@ jobs: role-to-assume: ${{ secrets.SECRETS_AWS_ROLE_TO_ASSUME }} role-session-name: IntegAccessKeysAssumeRole role-external-id: ${{ secrets.SECRETS_AWS_ROLE_EXTERNAL_ID }} + integ-access-keys-env: + strategy: + fail-fast: false + matrix: + os: [[self-hosted, linux-fargate], windows-latest, ubuntu-latest, macos-latest] + node: [14, 16, 18] + name: Run access key from env integ tests + runs-on: ${{ matrix.os }} + timeout-minutes: 30 + steps: + - name: "Checkout repository" + uses: actions/checkout@v3 + - name: Integ test for access keys + uses: ./ + env: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + with: + aws-region: us-west-2 + role-to-assume: ${{ secrets.SECRETS_AWS_ROLE_TO_ASSUME }} + role-session-name: IntegAccessKeysAssumeRole + role-external-id: ${{ secrets.SECRETS_AWS_ROLE_EXTERNAL_ID }} integ-iam-user: strategy: fail-fast: false diff --git a/README.md b/README.md index 8423a1c82..7c51facd1 100644 --- a/README.md +++ b/README.md @@ -161,13 +161,15 @@ We recommend using [GitHub's OIDC provider](https://docs.github.com/en/actions/d 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` | -| --------------------------------------------------------------- | ------------------- | ---------------- | ------------------------- | - | -| [✅ Recommended] Assume Role directly using GitHub OIDC provider | | ✔ | | | -| IAM User | ✔ | | | | -| Assume Role using IAM User credentials | ✔ | ✔ | | | -| Assume Role using WebIdentity Token File credentials | | ✔ | ✔ | | -| Assume Role using existing credentials | | ✔ | | ✔ | +| **Identity Used** | `aws-access-key-id` | `role-to-assume` | `web-identity-token-file` | `role-chaining` | `id-token` permission +| --------------------------------------------------------------- | ------------------- | ---------------- | ------------------------- | - | - | +| [✅ Recommended] Assume Role directly using GitHub OIDC provider | | ✔ | | | ✔ | +| IAM User | ✔ | | | | | +| Assume Role using IAM User credentials | ✔ | ✔ | | | | +| Assume Role using WebIdentity Token File credentials | | ✔ | ✔ | | | +| Assume Role using existing credentials | | ✔ | | ✔ | | + +*Note: `role-chaining` is not necessary to use existing credentials in every use case. If you're getting a "Credentials loaded by the SDK do not match" error, try enabling this prop. ### Credential Lifetime The default session duration is **1 hour**. diff --git a/dist/index.js b/dist/index.js index a384a2c78..660921077 100644 --- a/dist/index.js +++ b/dist/index.js @@ -478,7 +478,8 @@ async function run() { !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?'); + core.info('It looks like you might be trying to authenticate with OIDC. Did you mean to set the `id-token` permission? ' + + 'If you are not trying to authenticate with OIDC and the action is working successfully, you can ignore this message.'); } return (!!roleToAssume && !!process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN'] && @@ -519,10 +520,12 @@ async function run() { // in any error messages. (0, helpers_1.exportCredentials)({ AccessKeyId, SecretAccessKey, SessionToken }); } - else if (!webIdentityTokenFile && !roleChaining) { + else if (!webIdentityTokenFile && + !roleChaining && + !(process.env['AWS_ACCESS_KEY_ID'] && process.env['AWS_SECRET_ACCESS_KEY'])) { throw new Error('Could not determine how to assume credentials. Please check your inputs and try again.'); } - if (AccessKeyId || roleChaining) { + if (AccessKeyId || roleChaining || (process.env['AWS_ACCESS_KEY_ID'] && process.env['AWS_SECRET_ACCESS_KEY'])) { // 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. diff --git a/src/index.ts b/src/index.ts index 2db4e03a9..cc24be861 100644 --- a/src/index.ts +++ b/src/index.ts @@ -78,7 +78,8 @@ export async function run() { !roleChaining ) { core.info( - 'It looks like you might be trying to authenticate with OIDC. Did you mean to set the `id-token` permission?' + 'It looks like you might be trying to authenticate with OIDC. Did you mean to set the `id-token` permission? ' + + 'If you are not trying to authenticate with OIDC and the action is working successfully, you can ignore this message.' ); } return ( @@ -127,11 +128,15 @@ export async function run() { // the source credentials to already be masked as secrets // in any error messages. exportCredentials({ AccessKeyId, SecretAccessKey, SessionToken }); - } else if (!webIdentityTokenFile && !roleChaining) { + } else if ( + !webIdentityTokenFile && + !roleChaining && + !(process.env['AWS_ACCESS_KEY_ID'] && process.env['AWS_SECRET_ACCESS_KEY']) + ) { throw new Error('Could not determine how to assume credentials. Please check your inputs and try again.'); } - if (AccessKeyId || roleChaining) { + if (AccessKeyId || roleChaining || (process.env['AWS_ACCESS_KEY_ID'] && process.env['AWS_SECRET_ACCESS_KEY'])) { // 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. diff --git a/test/index.test.ts b/test/index.test.ts index 50a88dd69..a2951d7d5 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -519,13 +519,33 @@ describe('Configure AWS Credentials', () => { 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?' + 'It looks like you might be trying to authenticate with OIDC. Did you mean to set the `id-token` permission?' + + ' If you are not trying to authenticate with OIDC and the action is working successfully, you can ignore this message.' ); expect(core.setFailed).toHaveBeenCalledWith( 'Could not determine how to assume credentials. Please check your inputs and try again.' ); }); + test('Assume role with existing credentials if nothing else set', async () => { + process.env['AWS_ACCESS_KEY_ID'] = FAKE_ACCESS_KEY_ID; + process.env['AWS_SECRET_ACCESS_KEY'] = FAKE_SECRET_ACCESS_KEY; + 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?' + + ' If you are not trying to authenticate with OIDC and the action is working successfully, you can ignore this message.' + ); + expect(mockedSTS.commandCalls(AssumeRoleCommand).length).toEqual(1); + }); + 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';