mirror of
https://github.com/aws-actions/configure-aws-credentials.git
synced 2026-08-24 04:25:05 +09:00
Compare commits
84 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d0834ad3a6 | |||
| 3f7c218721 | |||
| c7b374462f | |||
| cbea70821e | |||
| 9581336d17 | |||
| 51f5560378 | |||
| d343995f27 | |||
| 59b441846a | |||
| 9fa0b155aa | |||
| 59489ba544 | |||
| a021b96993 | |||
| e7ec4b66d5 | |||
| 5b3c895046 | |||
| 63b1cdc38a | |||
| fc2b804e37 | |||
| 243d714529 | |||
| 9227d6ee4a | |||
| 84ac3de26c | |||
| cfc1102463 | |||
| 0ed0e57cf8 | |||
| 5fd1747fbc | |||
| 6b8bbaed05 | |||
| 8128bbdaac | |||
| 77e8c97f17 | |||
| b09a246f74 | |||
| 10850c9616 | |||
| a31e903eec | |||
| b88116ba3b | |||
| 68858db075 | |||
| 93f10a2e06 | |||
| fd13a40502 | |||
| a159d7bb53 | |||
| a9a3826013 | |||
| f503a18704 | |||
| 66d12fc03b | |||
| 37fe9a740b | |||
| 0d129e7d87 | |||
| 3d8cba388a | |||
| a19327083a | |||
| bca7d38ca4 | |||
| 3bb878b6ab | |||
| 3c7407c187 | |||
| 20ef22c966 | |||
| a95656fcd9 | |||
| 15a2ebe5a0 | |||
| 875428c99e | |||
| f03bfa9b96 | |||
| a93de34720 | |||
| ab0ba40832 | |||
| c3b3ce61b0 | |||
| 33adce1577 | |||
| 3d90187bb1 | |||
| 6f3d50aafb | |||
| aeb75711d0 | |||
| 7a01614d60 | |||
| b7878cdf5c | |||
| 0adfac7013 | |||
| 243e417dfd | |||
| 308756d6c3 | |||
| 151e7fee89 | |||
| a275d07fc4 | |||
| 2d7f362573 | |||
| b92d0d98bf | |||
| ff4bb8c1f9 | |||
| 2092c6a253 | |||
| ca88fa5aed | |||
| 91b1921080 | |||
| 34b52a3920 | |||
| 439a529737 | |||
| 244b4ca7be | |||
| 21cf8e5f31 | |||
| 6ccac84ceb | |||
| e20bc6c550 | |||
| 97c66b881d | |||
| ffa925d298 | |||
| b475783126 | |||
| e56e6c4038 | |||
| c0573b22e0 | |||
| df9c8fed6b | |||
| e7aeb52aa2 | |||
| 51886263f2 | |||
| a7d7b7872a | |||
| e10de4c3ea | |||
| 85f7c4ce7f |
@@ -24,7 +24,7 @@ jobs:
|
||||
with:
|
||||
parse-json-secrets: true
|
||||
secret-ids: |
|
||||
OSDS,arn:aws:secretsmanager:us-west-2:206735643321:secret:github-aws-sdk-osds-automation-gebs9n
|
||||
${{ secrets.OSDS_PACKAGING_ROLE }}
|
||||
- name: Enable PR automerge
|
||||
run: gh pr merge --auto --squash "$PR_URL"
|
||||
env:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: Dependabot auto-approve
|
||||
on:
|
||||
pull_request:
|
||||
on:
|
||||
pull_request_target:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
@@ -21,14 +21,14 @@ jobs:
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
aws-region: us-west-2
|
||||
role-to-assume: arn:aws:iam::206735643321:role/ConfigureAwsCredentialsPackageRole
|
||||
role-to-assume: ${{ secrets.CONFIGUREAWSCREDENTIALSPACKAGEROLEARN }}
|
||||
role-duration-seconds: 900
|
||||
- name: Get bot user token
|
||||
uses: aws-actions/aws-secretsmanager-get-secrets@v2
|
||||
with:
|
||||
parse-json-secrets: true
|
||||
secret-ids: |
|
||||
OSDS,arn:aws:secretsmanager:us-west-2:206735643321:secret:github-aws-sdk-osds-automation-gebs9n
|
||||
${{ secrets.OSDS_PACKAGING_ROLE }}
|
||||
- name: Approve PR if not already approved
|
||||
run: |
|
||||
gh pr checkout "$PR_URL"
|
||||
|
||||
@@ -39,7 +39,7 @@ jobs:
|
||||
with:
|
||||
parse-json-secrets: true
|
||||
secret-ids: |
|
||||
OSDS,arn:aws:secretsmanager:us-west-2:206735643321:secret:github-aws-sdk-osds-automation-gebs9n
|
||||
${{ secrets.OSDS_PACKAGING_ROLE }}
|
||||
- name: Commit
|
||||
run: |
|
||||
echo "::add-mask::${{ env.OSDS_ACCESS_TOKEN }}"
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
with:
|
||||
parse-json-secrets: true
|
||||
secret-ids: |
|
||||
OSDS,arn:aws:secretsmanager:us-west-2:206735643321:secret:github-aws-sdk-osds-automation-gebs9n
|
||||
${{ secrets.OSDS_PACKAGING_ROLE }}
|
||||
|
||||
- name: Run release-please
|
||||
uses: googleapis/release-please-action@v4
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
name: Run Integ tests
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
integ-oidc:
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [[self-hosted, linux-fargate], windows-latest, ubuntu-latest, macos-latest]
|
||||
name: Run OIDC integ tests
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: "Checkout repository"
|
||||
uses: actions/checkout@v4
|
||||
- name: Integ test for OIDC
|
||||
uses: ./
|
||||
with:
|
||||
aws-region: us-west-2
|
||||
role-to-assume: ${{ secrets.SECRETS_OIDC_AWS_ROLE_TO_ASSUME }}
|
||||
role-duration-seconds: 900
|
||||
role-session-name: IntegOidcAssumeRole
|
||||
role-external-id: ${{ secrets.SECRETS_OIDC_AWS_ROLE_EXTERNAL_ID }}
|
||||
integ-oidc-env:
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [[self-hosted, linux-fargate], windows-latest, ubuntu-latest, macos-latest]
|
||||
name: Run OIDC integ tests with existing invalid env vars
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: dummyaccesskeyid
|
||||
AWS_SECRET_ACCESS_KEY: dummysecretkey
|
||||
AWS_SESSION_TOKEN: dummytoken
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: "Checkout repository"
|
||||
uses: actions/checkout@v4
|
||||
- name: Integ test for OIDC
|
||||
uses: ./
|
||||
with:
|
||||
aws-region: us-west-2
|
||||
role-to-assume: ${{ secrets.SECRETS_OIDC_AWS_ROLE_TO_ASSUME }}
|
||||
role-duration-seconds: 900
|
||||
role-session-name: IntegOidcAssumeRole
|
||||
role-external-id: ${{ secrets.SECRETS_OIDC_AWS_ROLE_EXTERNAL_ID }}
|
||||
integ-access-keys:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [[self-hosted, linux-fargate], windows-latest, ubuntu-latest, macos-latest]
|
||||
name: Run access key integ tests
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: "Checkout repository"
|
||||
uses: actions/checkout@v4
|
||||
- name: Integ test for access keys
|
||||
uses: ./
|
||||
with:
|
||||
aws-region: us-west-2
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
role-to-assume: ${{ secrets.SECRETS_AWS_ROLE_TO_ASSUME }}
|
||||
role-session-name: IntegAccessKeysAssumeRole
|
||||
role-external-id: ${{ secrets.SECRETS_AWS_ROLE_EXTERNAL_ID }}
|
||||
integ-access-keys-env:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [[self-hosted, linux-fargate], windows-latest, ubuntu-latest, macos-latest]
|
||||
name: Run access key from env integ tests
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: "Checkout repository"
|
||||
uses: actions/checkout@v4
|
||||
- name: Integ test for access keys
|
||||
uses: ./
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
with:
|
||||
aws-region: us-west-2
|
||||
role-to-assume: ${{ secrets.SECRETS_AWS_ROLE_TO_ASSUME }}
|
||||
role-session-name: IntegAccessKeysAssumeRole
|
||||
role-external-id: ${{ secrets.SECRETS_AWS_ROLE_EXTERNAL_ID }}
|
||||
integ-iam-user:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [[self-hosted, linux-fargate], windows-latest, ubuntu-latest, macos-latest]
|
||||
name: Run IAM User integ tests
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: "Checkout repository"
|
||||
uses: actions/checkout@v4
|
||||
- name: Integ test for IAM user
|
||||
uses: ./
|
||||
with:
|
||||
aws-region: us-west-2
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
".release-please-manifest.json": "4.0.2",
|
||||
"package.json": "4.0.2",
|
||||
".": "4.2.0"
|
||||
".": "4.3.0"
|
||||
}
|
||||
|
||||
@@ -2,6 +2,40 @@
|
||||
|
||||
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
||||
|
||||
## [4.3.0](https://github.com/aws-actions/configure-aws-credentials/compare/v4.3.0...v4.3.0) (2025-08-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* properly set proxy environment variable ([cbea708](https://github.com/aws-actions/configure-aws-credentials/commit/cbea70821e4ab985ad3be0e5a93390523e257cde))
|
||||
|
||||
|
||||
### Miscellaneous Chores
|
||||
|
||||
* release 4.3.0 ([3f7c218](https://github.com/aws-actions/configure-aws-credentials/commit/3f7c2187213bafaa1ea60a850b27082cbf55dda0))
|
||||
|
||||
## [4.3.0](https://github.com/aws-actions/configure-aws-credentials/compare/v4.2.1...v4.3.0) (2025-08-04)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* depenency update and feature cleanup ([#1414](https://github.com/aws-actions/configure-aws-credentials/issues/1414)) ([59489ba](https://github.com/aws-actions/configure-aws-credentials/commit/59489ba544930000b7b67412c167f5fe816568cf)), closes [#1062](https://github.com/aws-actions/configure-aws-credentials/issues/1062) [#1191](https://github.com/aws-actions/configure-aws-credentials/issues/1191)
|
||||
* Optional environment variable output ([c3b3ce6](https://github.com/aws-actions/configure-aws-credentials/commit/c3b3ce61b02510937ff02916a4eb153874bc5085))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **docs:** readme samples versioning ([5b3c895](https://github.com/aws-actions/configure-aws-credentials/commit/5b3c89504689ea1ea2b6000b23a6a2aac463662a))
|
||||
* the wrong example region for China partition in README ([37fe9a7](https://github.com/aws-actions/configure-aws-credentials/commit/37fe9a740bcb30ee8cccd96feb90666c937311f2))
|
||||
|
||||
## [4.2.1](https://github.com/aws-actions/configure-aws-credentials/compare/v4.2.0...v4.2.1) (2025-05-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* ensure explicit inputs take precedence over environment variables ([e56e6c4](https://github.com/aws-actions/configure-aws-credentials/commit/e56e6c4038915cd5a7238a671fe97f44c98a40b0))
|
||||
* prioritize explicit inputs over environment variables ([df9c8fe](https://github.com/aws-actions/configure-aws-credentials/commit/df9c8fed6b364f0d1fb0e6e03a0ec26f1ea4e3fc))
|
||||
|
||||
## [4.2.0](https://github.com/aws-actions/configure-aws-credentials/compare/v4.1.0...v4.2.0) (2025-05-06)
|
||||
|
||||
|
||||
|
||||
@@ -1,98 +1,130 @@
|
||||
## Configure AWS Credentials for GitHub Actions
|
||||
Configure your AWS credentials and region environment variables for use in other
|
||||
GitHub Actions.
|
||||
Configure AWS Credentials
|
||||
=========================
|
||||
Authenticate to AWS in GitHub Actions! Works especially well with [AWS Secrets
|
||||
Manager](https://github.com/aws-actions/aws-secretsmanager-get-secrets).
|
||||
|
||||
This action implements the AWS JavaScript SDK credential resolution chain
|
||||
and exports session environment variables for your other Actions to use.
|
||||
Environment variable exports are detected by both the AWS SDKs and the AWS CLI
|
||||
for AWS API calls.
|
||||
Quick Start (OIDC, recommended)
|
||||
-------------------------------
|
||||
1. Create an IAM Identity Provider in your AWS account for GitHub OIDC. (See
|
||||
[OIDC configuration](#oidc-configuration) below for details.)
|
||||
2. Create an IAM Role in your AWS account with a trust policy that allows GitHub
|
||||
Actions to assume it:
|
||||
<details>
|
||||
<summary>GitHub OIDC Trust Policy</summary>
|
||||
|
||||
## Overview
|
||||
API calls to AWS need to be signed with credential information, so when you use
|
||||
one of the AWS SDKs or an AWS tool, you must provide it with AWS credentials and
|
||||
and AWS region. One way to do that in GitHub Actions is to use a repository
|
||||
secret with IAM credentials, but this doesn't follow [AWS security
|
||||
guidelines](https://docs.aws.amazon.com/IAM/latest/UserGuide/security-creds.html)
|
||||
on using long term credentials. Instead, we recommend that you use a long term
|
||||
credential or JWT to fetch a temporary credential, and use that with your tools
|
||||
instead. This GitHub Action facilitates just that.
|
||||
```json
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"Federated": "arn:aws:iam::<AWS_ACCOUNT_ID>:oidc-provider/token.actions.githubusercontent.com"
|
||||
},
|
||||
"Action": "sts:AssumeRoleWithWebIdentity",
|
||||
"Condition": {
|
||||
"StringEquals": {
|
||||
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
|
||||
"token.actions.githubusercontent.com:sub": "repo:<GITHUB_ORG>/<GITHUB_REPOSITORY>:ref:refs/heads/<GITHUB_BRANCH>"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
</details>
|
||||
3. Attach permissions to the IAM Role that allow it to access the AWS resources
|
||||
you need.
|
||||
4. Add the following to your GitHub Actions workflow:
|
||||
<details>
|
||||
<summary>Example Workflow</summary>
|
||||
|
||||
AWS SDKs and Tools look for your credentials in standardized environment
|
||||
variables. In essence, this Action runs through the standard [credential
|
||||
resolution flow](https://docs.aws.amazon.com/sdkref/latest/guide/standardized-credentials.html),
|
||||
and at the end, exports environment variables for you to use later.
|
||||
```yaml
|
||||
# Need ID token write permission to use OIDC
|
||||
permissions:
|
||||
id-token: write
|
||||
jobs:
|
||||
run_job_with_aws:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@main # Or a specific version
|
||||
with:
|
||||
role-to-assume: <Role ARN you created in step 2>
|
||||
aws-region: <AWS Region you want to use>
|
||||
- name: Additional steps
|
||||
run: |
|
||||
# Your commands that require AWS credentials
|
||||
aws sts get-caller-identity
|
||||
```
|
||||
</details>
|
||||
That's it! Your GitHub Actions workflow can now access AWS resources using the
|
||||
IAM Role you created. Other authentication scenarios are also supported (see
|
||||
below).
|
||||
|
||||
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.
|
||||
Security Recommendations
|
||||
------------------------
|
||||
* Use temporary credentials when possible. OIDC is recommended because it
|
||||
provides temporary credentials and it's easy to set up.
|
||||
* Do not store credentials in your repository's code. Consider using
|
||||
[git-secrets](https://github.com/awslabs/git-secrets) to prevent committing
|
||||
secrets to your repository.
|
||||
* [Grant least privilege](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege)
|
||||
to your workflows. Grant only those permissions that are necessary for the
|
||||
workflow to run.
|
||||
* [Monitor the activity](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#keep-a-log)
|
||||
of the credentials used in workflows.
|
||||
* Periodically rotate any long-lived credentials that you use.
|
||||
* Store sensitive information in a secure way, such as using
|
||||
[AWS Secrets Manager](https://aws.amazon.com/secrets-manager/) or
|
||||
[GitHub Secrets](https://docs.github.com/en/actions/security-guides/encrypted-secrets).
|
||||
|
||||
For more information on how to do that, read on.
|
||||
Other Authentication Scenarios
|
||||
------------------------------
|
||||
This action supports five different authentication methods that are configured
|
||||
by specifying different inputs.
|
||||
|
||||
### Note about GHES
|
||||
|
||||
Some of this documentation may be inaccurate if you are using GHES (GitHub
|
||||
Enterprise Server), please take note to review the GitHub documentation when
|
||||
relevant.
|
||||
|
||||
For example, the URL that the OIDC JWT is issued from is different than the
|
||||
usual `token.actions.githubusercontent.com`, and will be unique to your
|
||||
enterprise server. As a result, you will need to configure this differently when
|
||||
you create the Identity Provider.
|
||||
|
||||
We do not presently have a GHES testing environment to validate this action. If
|
||||
you are running in GHES and encounter problems, please
|
||||
[let us know](https://github.com/aws-actions/configure-aws-credentials/issues/new/choose).
|
||||
|
||||
## Security recommendations
|
||||
|
||||
We recommend following
|
||||
[Amazon IAM best practices](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html)
|
||||
for the AWS credentials used in GitHub Actions workflows, including:
|
||||
* Do not store credentials in your repository's code.
|
||||
* [Grant least privilege](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege)
|
||||
to the credentials used in GitHub Actions workflows. Grant only the
|
||||
permissions required to perform the actions in your GitHub Actions workflows.
|
||||
Do not assume overly permissive roles, even for testing.
|
||||
* [Monitor the activity](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#keep-a-log)
|
||||
of the credentials used in GitHub Actions workflows.
|
||||
* Use temporary credentials when possible.
|
||||
* Periodically rotate any long-term credentials you use.
|
||||
|
||||
## Using this action
|
||||
There are five different supported ways to retrieve credentials:
|
||||
|
||||
- Using GitHub's OIDC provider (`AssumeRoleWithWebIdentity`)
|
||||
- Proceeding as an IAM user (No STS call is made)
|
||||
- Using access keys as action input (`AssumeRole`)
|
||||
- Using a WebIdentity Token File (`AssumeRoleWithWebIdentity`)
|
||||
- Using existing credentials in your runner (`AssumeRole`)
|
||||
1. Use a `core.getIDToken()` call to authenticate via OIDC.
|
||||
2. Re-export existing long-lived IAM credentials (access key ID and secret
|
||||
access key) as environment variables.
|
||||
3. Use static credentials stored in GitHub Secrets to fetch temporary
|
||||
credentials via STS AssumeRole.
|
||||
4. Use a Web Identity Token to fetch temporary credentials via STS
|
||||
AssumeRoleWithWebIdentity.
|
||||
5. Use credentials stored in the Action environment to fetch temporary
|
||||
credentials via STS AssumeRole.
|
||||
|
||||
Because we use the AWS JavaScript SDK, we always will use the [credential
|
||||
resolution flow for Node.js](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/setting-credentials-node.html).
|
||||
Depending on your inputs, the action might override parts of this flow.
|
||||
|
||||
We recommend using the first option above: [GitHub's OIDC provider](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services).
|
||||
This method uses OIDC to get short-lived credentials needed for your actions.
|
||||
See [OIDC](#OIDC) for more information on how to setup your AWS account to
|
||||
assume a role with OIDC.
|
||||
<details>
|
||||
<summary>Inputs and their effects on the credential resolution flow</summary>
|
||||
|
||||
The following table describes which method we'll use to get your credentials
|
||||
based on which values are supplied to the Action:
|
||||
|
||||
| **Identity Used** | `aws-access-key-id` | `role-to-assume` | `web-identity-token-file` | `role-chaining` | `id-token` permission
|
||||
| --------------------------------------------------------------- | ------------------- | ---------------- | ------------------------- | - | - |
|
||||
| [✅ Recommended] Assume Role directly using GitHub OIDC provider | | ✔ | | | ✔ |
|
||||
| IAM User | ✔ | | | | |
|
||||
| Assume Role using IAM User credentials | ✔ | ✔ | | | |
|
||||
| Assume Role using WebIdentity Token File credentials | | ✔ | ✔ | | |
|
||||
| Assume Role using existing credentials | | ✔ | | ✔ | |
|
||||
| **Identity Used** | `aws-access-key-id` | `role-to-assume` | `web-identity-token-file` | `role-chaining` |
|
||||
| ---------------------------------------- | ------------------- | ---------------- | ------------------------- | --------------- |
|
||||
| [✅ Recommended] GitHub OIDC | | ✔ | | |
|
||||
| IAM User (no AssumeRole) | ✔ | | | |
|
||||
| AssumeRole using static IAM credentials | ✔ | ✔ | | |
|
||||
| AssumeWithWebIdentity use a token file | | ✔ | ✔ | |
|
||||
| AssumeRole using existing credentials | | ✔ | | ✔ |
|
||||
|
||||
*Note: `role-chaining` is not always necessary to use existing credentials.
|
||||
If you're getting a "Credentials loaded by the SDK do not match" error,
|
||||
try enabling this option.*
|
||||
</details>
|
||||
|
||||
Additionally, **`aws-region`** is always required.
|
||||
|
||||
*Note: If you use GitHub Enterprise Server, you must use the you may need to
|
||||
adjust examples here to match your environment.*
|
||||
|
||||
Additional Options
|
||||
------------------
|
||||
### Options
|
||||
See [action.yml](./action.yml) for more detail.
|
||||
<details>
|
||||
<summary>Options list and descriptions</summary>
|
||||
|
||||
| Option | Description | Required |
|
||||
|---------------------------|---------------------------------------------------------------------------------------------------|----------|
|
||||
@@ -111,31 +143,74 @@ See [action.yml](./action.yml) for more detail.
|
||||
| role-skip-session-tagging | Skips session tagging if set. | No |
|
||||
| inline-session-policy | You may further restrict the assumed role policy by defining an inline policy here. | No |
|
||||
| managed-session-policies | You may further restrict the assumed role policy by specifying a managed policy here. | No |
|
||||
| output-credentials | When set, outputs fetched credentials as action step output. (Outputs access-key-id, secret-access-key, session-token, and expiration). Defaults to false. | No |
|
||||
| output-credentials | When set, outputs fetched credentials as action step output. (Outputs aws-access-key-id, aws-secret-access-key, aws-session-token, aws-account-id, and aws-expiration). Defaults to false. | No |
|
||||
| output-env-credentials | When set, outputs fetched credentials as environment variables (AWS_REGION, AWS_DEFAULT_REGION, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN). Defaults to true. Set to false if you need to avoid setting/changing env variables. You'd probably want to use output-credentials if you disable this. (NOTE: Setting to false will prevent the aws-account-id from being exported as a step output). | No |
|
||||
| unset-current-credentials | When set, attempts to unset any existing credentials in your action runner. | No |
|
||||
| disable-retry | Disabled retry/backoff logic for assume role calls. By default, retries are enabled. | No |
|
||||
| retry-max-attempts | Limits the number of retry attempts before giving up. Defaults to 12. | No |
|
||||
| special-characters-workaround | Uncommonly, some environments cannot tolerate special characters in a secret key. This option will retry fetching credentials until the secret access key does not contain special characters. This option overrides disable-retry and retry-max-attempts. | No |
|
||||
| use-existing-credentials | When set, the action will check if existing credentials are valid and exit if they are. Defaults to false. | No |
|
||||
</details>
|
||||
|
||||
#### Credential Lifetime
|
||||
The default session duration is **1 hour**.
|
||||
#### Adjust the retry mechanism
|
||||
You can configure retry settings for if 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.
|
||||
|
||||
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.
|
||||
#### Mask account ID
|
||||
Your account ID is not masked by default in workflow logs. You can set the
|
||||
`mask-aws-account-id` input to `true` to mask your account ID in workflow logs
|
||||
if desired.
|
||||
|
||||
#### External ID
|
||||
If your role requires an external ID to assume, you can provide the external ID
|
||||
with the `role-external-id` input
|
||||
#### Unset current credentials
|
||||
Sometimes, existing credentials in your runner can get in the way of the
|
||||
intended outcome. You can set the `unset-current-credentials` input to `true` to
|
||||
work around this issue.
|
||||
|
||||
#### Session tagging and name
|
||||
#### Use an HTTP proxy
|
||||
|
||||
If need use an HTTP proxy you can set it in the action manually. Additionally
|
||||
this action will always consider the `HTTP_PROXY` environment variable.
|
||||
|
||||
<details>
|
||||
<summary>Proxy configuration</summary>
|
||||
|
||||
Manually configured proxy:
|
||||
```yaml
|
||||
uses: aws-actions/configure-aws-credentials@v4.2.1
|
||||
with:
|
||||
aws-region: us-east-2
|
||||
role-to-assume: my-github-actions-role
|
||||
http-proxy: "http://companydomain.com:3128"
|
||||
```
|
||||
|
||||
Proxy configured in the environment variable:
|
||||
```bash
|
||||
# Your environment configuration
|
||||
HTTP_PROXY="http://companydomain.com:3128"
|
||||
```
|
||||
</details>
|
||||
|
||||
#### Special characters in AWS_SECRET_ACCESS_KEY
|
||||
Some edge cases are unable to properly parse an `AWS_SECRET_ACCESS_KEY` if it
|
||||
contains special characters. For more information, please see the
|
||||
[AWS CLI documentation](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-troubleshooting.html#tshoot-signature-does-not-match).
|
||||
If you set the `special-characters-workaround` option, this action will
|
||||
continually retry fetching credentials until we get one that does not have
|
||||
special characters. This option overrides the `disable-retry` and
|
||||
`retry-max-attempts` options. We recommend that you do not enable this option
|
||||
unless required, because retrying APIs infinitely until they succeed is not best
|
||||
practice.
|
||||
|
||||
Session Naming and Policies
|
||||
---------------------------
|
||||
The default session name is "GitHubActions", and you can modify it by specifying
|
||||
the desired name in `role-session-name`.
|
||||
|
||||
_Note: you might find it helpful to set the `role-session-name` to `${{ github.run_id }}`
|
||||
*Note: you might find it helpful to set the `role-session-name` to `${{ github.run_id }}`
|
||||
so as to clarify in audit logs which AWS actions were performed by which workflow
|
||||
run._
|
||||
run.*
|
||||
|
||||
The session will be tagged with the
|
||||
following tags: (Refer to [GitHub's documentation for `GITHUB_` environment
|
||||
@@ -157,21 +232,7 @@ Particularly, `GITHUB_WORKFLOW` will be truncated if it's too long. If
|
||||
`GITHUB_ACTOR` or `GITHUB_WORKFLOW` contain invalid characters, the characters
|
||||
will be replaced with an '*'._
|
||||
|
||||
The action will use session tagging by default during role assumption, unless
|
||||
you follow our recommendation and are assuming a role with a WebIdentity. For
|
||||
WebIdentity role assumption, the session tags have to be included in the encoded
|
||||
WebIdentity token. This means that tags can only be supplied by the OIDC
|
||||
provider, and they cannot set during the AssumeRoleWithWebIdentity API call
|
||||
within the Action. See [#419](https://github.com/aws-actions/configure-aws-credentials/issues/419)
|
||||
for more information.
|
||||
|
||||
You can skip this session tagging by providing
|
||||
`role-skip-session-tagging` as true in the action's inputs:
|
||||
```yaml
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
role-skip-session-tagging: true
|
||||
```
|
||||
The action will use session tagging by default unless you are using OIDC.
|
||||
|
||||
### Session policies
|
||||
Session policies are not required, but they allow you to limit the scope of the
|
||||
@@ -182,15 +243,19 @@ session policy by its ARN.
|
||||
#### Inline session policies
|
||||
An IAM policy in stringified JSON format that you want to use as an inline
|
||||
session policy. Depending on preferences, the JSON could be written on a single
|
||||
line like this:
|
||||
line.
|
||||
|
||||
<details>
|
||||
<summary>Inline session policy examples</summary>
|
||||
|
||||
```yaml
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
uses: aws-actions/configure-aws-credentials@v4.2.1
|
||||
with:
|
||||
inline-session-policy: '{"Version":"2012-10-17","Statement":[{"Sid":"Stmt1","Effect":"Allow","Action":"s3:List*","Resource":"*"}]}'
|
||||
```
|
||||
Or we can have a nicely formatted JSON as well:
|
||||
```yaml
|
||||
uses: aws-actions/configure-aws-credentials@v4.1.0
|
||||
uses: aws-actions/configure-aws-credentials@v4.2.1
|
||||
with:
|
||||
inline-session-policy: >-
|
||||
{
|
||||
@@ -205,56 +270,33 @@ Or we can have a nicely formatted JSON as well:
|
||||
]
|
||||
}
|
||||
```
|
||||
</details>
|
||||
|
||||
#### 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:
|
||||
the role.
|
||||
|
||||
<details>
|
||||
<summary>Managed session policy examples</summary>
|
||||
|
||||
```yaml
|
||||
uses: aws-actions/configure-aws-credentials@v4.1.0
|
||||
uses: aws-actions/configure-aws-credentials@v4.2.1
|
||||
with:
|
||||
managed-session-policies: arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
|
||||
```
|
||||
And we can pass multiple managed policies likes this:
|
||||
```yaml
|
||||
uses: aws-actions/configure-aws-credentials@v4.1.0
|
||||
uses: aws-actions/configure-aws-credentials@v4.2.1
|
||||
with:
|
||||
managed-session-policies: |
|
||||
arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
|
||||
arn:aws:iam::aws:policy/AmazonS3OutpostsReadOnlyAccess
|
||||
```
|
||||
</details>
|
||||
|
||||
### Misc
|
||||
|
||||
#### Adjust the retry mechanism
|
||||
You can now configure retry settings for when the STS call fails. By default, we
|
||||
retry with exponential backoff `12` times. You can disable this behavior
|
||||
altogether by setting the `disable-retry` input to `true`, or you can configure
|
||||
the number of times it retries with the `retry-max-attempts` input.
|
||||
|
||||
#### Mask account ID
|
||||
Your account ID is not masked by default in workflow logs since it's not
|
||||
considered sensitive information. However, you can set the `mask-aws-account-id`
|
||||
input to `true` to mask your account ID in workflow logs if desired.
|
||||
|
||||
#### Unset current credentials
|
||||
Sometimes, existing credentials in your runner can get in the way of the
|
||||
intended outcome. You can set the `unset-current-credentials` input to `true` to
|
||||
work around this issue.
|
||||
|
||||
#### Special characters in AWS_SECRET_ACCESS_KEY
|
||||
Some edge cases are unable to properly parse an `AWS_SECRET_ACCESS_KEY` if it
|
||||
contains special characters. For more information, please see the
|
||||
[AWS CLI documentation](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-troubleshooting.html#tshoot-signature-does-not-match).
|
||||
If you set the `special-characters-workaround` option, this action will
|
||||
continually retry fetching credentials until we get one that does not have
|
||||
special characters. This option overrides the `disable-retry` and
|
||||
`retry-max-attempts` options. We recommend that you do not enable this option
|
||||
unless required, because retrying APIs infinitely until they succeed is not best
|
||||
practice.
|
||||
|
||||
## OIDC
|
||||
|
||||
OIDC Configuration
|
||||
-------------------
|
||||
We recommend using [GitHub's OIDC
|
||||
provider](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services)
|
||||
to get short-lived AWS credentials needed for your actions. When using OIDC, you
|
||||
@@ -273,15 +315,6 @@ To get this to work
|
||||
|
||||
5. Specify that role's ARN when setting up this action.
|
||||
|
||||
First, in order for this action to create the JWT, your workflow file must have
|
||||
the `id-token: write` permission:
|
||||
|
||||
```yaml
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
```
|
||||
|
||||
### OIDC Audience
|
||||
|
||||
When the JWT is created, an audience needs to be specified. Normally, you would
|
||||
@@ -292,83 +325,33 @@ You can specify the audience through the `audience` input:
|
||||
|
||||
```yaml
|
||||
- name: Configure AWS Credentials for China region audience
|
||||
uses: aws-actions/configure-aws-credentials@v4.1.0
|
||||
uses: aws-actions/configure-aws-credentials@v4.2.1
|
||||
with:
|
||||
audience: sts.amazonaws.com.cn
|
||||
aws-region: us-east-3
|
||||
aws-region: cn-northwest-1
|
||||
role-to-assume: arn:aws-cn:iam::123456789100:role/my-github-actions-role
|
||||
```
|
||||
|
||||
### Configuring IAM to trust GitHub
|
||||
To use GitHub's OIDC provider, you must first set up federation
|
||||
with the provider as an IAM IdP. The GitHub OIDC provider only needs to be
|
||||
created once per account (i.e. multiple IAM Roles that can be assumed by the
|
||||
GitHub's OIDC can share a single OIDC Provider). Here is a sample CloudFormation
|
||||
template that will configure this trust for you.
|
||||
To use GitHub's OIDC provider, you must first set up federation in your AWS
|
||||
account. This involves creating an IAM Identity Provider that trusts GitHub's
|
||||
OIDC endpoint. You can create an IAM Identity Provider in the AWS Management
|
||||
Console by specifying the following details:
|
||||
- **Provider Type**: OIDC
|
||||
- **Provider URL**: `https://token.actions.githubusercontent.com`
|
||||
- **Audience**: `sts.amazonaws.com` (or your custom audience if you specified
|
||||
one in the `audience` input)
|
||||
|
||||
Note that the thumbprint below has been set to all F's because the thumbprint is
|
||||
not used when authenticating `token.actions.githubusercontent.com`. This is a
|
||||
special case used *only when GitHub's OIDC is authenticating to IAM*. IAM uses
|
||||
its library of trusted CAs to authenticate. The value is still the API, so it
|
||||
must be specified.
|
||||
Prior versions of this documentation gave instructions for specifying the
|
||||
certificate fingerprint, but this is no longer necessary. The thumbprint, if
|
||||
specified, will be ignored.
|
||||
|
||||
You can copy the template below, or load it from here:
|
||||
https://d38mtn6aq9zhn6.cloudfront.net/configure-aws-credentials-latest.yml
|
||||
You can also create the IAM Identity Provider using the AWS CLI:
|
||||
|
||||
```yaml
|
||||
Parameters:
|
||||
GitHubOrg:
|
||||
Description: Name of GitHub organization/user (case sensitive)
|
||||
Type: String
|
||||
RepositoryName:
|
||||
Description: Name of GitHub repository (case sensitive)
|
||||
Type: String
|
||||
OIDCProviderArn:
|
||||
Description: Arn for the GitHub OIDC Provider.
|
||||
Default: ""
|
||||
Type: String
|
||||
OIDCAudience:
|
||||
Description: Audience supplied to configure-aws-credentials.
|
||||
Default: "sts.amazonaws.com"
|
||||
Type: String
|
||||
|
||||
Conditions:
|
||||
CreateOIDCProvider: !Equals
|
||||
- !Ref OIDCProviderArn
|
||||
- ""
|
||||
|
||||
Resources:
|
||||
Role:
|
||||
Type: AWS::IAM::Role
|
||||
Properties:
|
||||
AssumeRolePolicyDocument:
|
||||
Statement:
|
||||
- Effect: Allow
|
||||
Action: sts:AssumeRoleWithWebIdentity
|
||||
Principal:
|
||||
Federated: !If
|
||||
- CreateOIDCProvider
|
||||
- !Ref GithubOidc
|
||||
- !Ref OIDCProviderArn
|
||||
Condition:
|
||||
StringEquals:
|
||||
token.actions.githubusercontent.com:aud: !Ref OIDCAudience
|
||||
StringLike:
|
||||
token.actions.githubusercontent.com:sub: !Sub repo:${GitHubOrg}/${RepositoryName}:*
|
||||
|
||||
GithubOidc:
|
||||
Type: AWS::IAM::OIDCProvider
|
||||
Condition: CreateOIDCProvider
|
||||
Properties:
|
||||
Url: https://token.actions.githubusercontent.com
|
||||
ClientIdList:
|
||||
- sts.amazonaws.com
|
||||
ThumbprintList:
|
||||
- ffffffffffffffffffffffffffffffffffffffff
|
||||
|
||||
Outputs:
|
||||
Role:
|
||||
Value: !GetAtt Role.Arn
|
||||
```bash
|
||||
aws iam create-open-id-connect-provider \
|
||||
--url https://token.actions.githubusercontent.com \
|
||||
--client-id-list sts.amazonaws.com
|
||||
```
|
||||
|
||||
### Claims and scoping permissions
|
||||
@@ -410,83 +393,13 @@ 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/)
|
||||
|
||||
## Self-Hosted Runners
|
||||
Examples
|
||||
--------
|
||||
|
||||
If you run your GitHub Actions in a
|
||||
[self-hosted runner](https://help.github.com/en/actions/hosting-your-own-runners/about-self-hosted-runners) that already has access to AWS credentials, such as
|
||||
an EC2 instance, then you do not need to provide IAM user access key credentials
|
||||
to this action. We will use the standard AWS JavaScript SDK credential
|
||||
resolution methods to find your credentials, so if the AWS JS SDK can
|
||||
authenticate on your runner, this Action will as well.
|
||||
|
||||
If no access key credentials are given in the action inputs, this action will
|
||||
use credentials from the runner environment using the
|
||||
[default methods for the AWS SDK for Javascript](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/setting-credentials-node.html).
|
||||
|
||||
You can use this action to simply configure the region and account ID in the
|
||||
environment, and then use the runner's credentials for all AWS API calls made by
|
||||
your Actions workflow:
|
||||
```yaml
|
||||
uses: aws-actions/configure-aws-credentials@v4.1.0
|
||||
with:
|
||||
aws-region: us-east-2
|
||||
```
|
||||
In this case, your runner's credentials must have permissions to call any AWS
|
||||
APIs called by your Actions workflow.
|
||||
|
||||
Or, you can use this action to assume a role, and then use the role credentials
|
||||
for all AWS API calls made by your Actions workflow:
|
||||
```yaml
|
||||
uses: aws-actions/configure-aws-credentials@v4.1.0
|
||||
with:
|
||||
aws-region: us-east-2
|
||||
role-to-assume: my-github-actions-role
|
||||
```
|
||||
In this case, your runner's credentials must have permissions to assume the
|
||||
role.
|
||||
|
||||
You can also assume a role using a web identity token file, such as if using
|
||||
[Amazon EKS IRSA](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts-technical-overview.html). Pods running in EKS
|
||||
worker nodes that do not run as root can use this file to assume a role with a
|
||||
web identity.
|
||||
|
||||
### Proxy Configuration
|
||||
|
||||
If need use a HTTP proxy you can set it in the action manually.
|
||||
|
||||
Additionally this action will always consider the `HTTP_PROXY` environment
|
||||
variable.
|
||||
|
||||
Manually configured proxy:
|
||||
```yaml
|
||||
uses: aws-actions/configure-aws-credentials@v4.1.0
|
||||
with:
|
||||
aws-region: us-east-2
|
||||
role-to-assume: my-github-actions-role
|
||||
http-proxy: "http://companydomain.com:3128"
|
||||
```
|
||||
|
||||
Proxy configured in the environment variable:
|
||||
```bash
|
||||
# Your environment configuration
|
||||
HTTP_PROXY="http://companydomain.com:3128"
|
||||
```
|
||||
|
||||
### Use with the AWS CLI
|
||||
This workflow does _not_ install the [AWS CLI](https://aws.amazon.com/cli/)
|
||||
into your environment. Self-hosted runners that intend to run this action prior
|
||||
to executing `aws` commands need to have the AWS CLI
|
||||
[installed](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html)
|
||||
if it's not already present.
|
||||
Most [GitHub hosted runner environments](https://github.com/actions/virtual-environments)
|
||||
should include the AWS CLI by default.
|
||||
|
||||
## Examples
|
||||
|
||||
### AssumeRoleWithWebIdentity (recommended)
|
||||
### AssumeRoleWithWebIdentity
|
||||
```yaml
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@v4.1.0
|
||||
uses: aws-actions/configure-aws-credentials@v4.2.1
|
||||
with:
|
||||
aws-region: us-east-2
|
||||
role-to-assume: arn:aws:iam::123456789100:role/my-github-actions-role
|
||||
@@ -500,13 +413,13 @@ environment variable and use it to assume the role
|
||||
### AssumeRole with role previously assumed by action in same workflow
|
||||
```yaml
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@v4.1.0
|
||||
uses: aws-actions/configure-aws-credentials@v4.2.1
|
||||
with:
|
||||
aws-region: us-east-2
|
||||
role-to-assume: arn:aws:iam::123456789100:role/my-github-actions-role
|
||||
role-session-name: MySessionName
|
||||
- name: Configure other AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@v4.1.0
|
||||
uses: aws-actions/configure-aws-credentials@v4.2.1
|
||||
with:
|
||||
aws-region: us-east-2
|
||||
role-to-assume: arn:aws:iam::987654321000:role/my-second-role
|
||||
@@ -521,7 +434,7 @@ role, `arn:aws:iam::987654321000:role/my-second-role`.
|
||||
### AssumeRole with static IAM credentials in repository secrets
|
||||
```yaml
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@v4.1.0
|
||||
uses: aws-actions/configure-aws-credentials@v4.2.1
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
@@ -540,7 +453,7 @@ name, like `role-to-assume: my-github-actions-role`.
|
||||
```yaml
|
||||
- name: Configure AWS Credentials 1
|
||||
id: creds
|
||||
uses: aws-actions/configure-aws-credentials@v4.1.0
|
||||
uses: aws-actions/configure-aws-credentials@v4.2.1
|
||||
with:
|
||||
aws-region: us-east-2
|
||||
role-to-assume: arn:aws:iam::123456789100:role/my-github-actions-role
|
||||
@@ -549,7 +462,7 @@ name, like `role-to-assume: my-github-actions-role`.
|
||||
run: |
|
||||
aws sts get-caller-identity
|
||||
- name: Configure AWS Credentials 2
|
||||
uses: aws-actions/configure-aws-credentials@v4.1.0
|
||||
uses: aws-actions/configure-aws-credentials@v4.2.1
|
||||
with:
|
||||
aws-region: us-east-2
|
||||
aws-access-key-id: ${{ steps.creds.outputs.aws-access-key-id }}
|
||||
@@ -564,12 +477,14 @@ 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
|
||||
|
||||
License
|
||||
-------
|
||||
This code is made available under the MIT license.
|
||||
|
||||
## Security Disclosures
|
||||
Security Disclosures
|
||||
--------------------
|
||||
If you would like to report a potential security issue in this project, please
|
||||
do not create a GitHub issue. Instead, please follow the instructions
|
||||
[here](https://aws.amazon.com/security/vulnerability-reporting/) or [email AWS
|
||||
security directly](mailto:aws-security@amazon.com).
|
||||
do not create a GitHub issue. Instead, please follow the instructions
|
||||
[here](https://aws.amazon.com/security/vulnerability-reporting/) or
|
||||
[email AWS security](mailto:aws-security@amazon.com) directly.
|
||||
|
||||
+2
-2
@@ -1,2 +1,2 @@
|
||||
const { fs } = require('memfs')
|
||||
module.exports = fs
|
||||
const { fs } = require('memfs');
|
||||
module.exports = fs;
|
||||
|
||||
@@ -61,6 +61,10 @@ inputs:
|
||||
output-credentials:
|
||||
description: Whether to set credentials as step output
|
||||
required: false
|
||||
output-env-credentials:
|
||||
description: Whether to export credentials as environment variables. If you set this to false, you probably want to use output-credentials.
|
||||
required: false
|
||||
default: true
|
||||
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
|
||||
@@ -84,3 +88,5 @@ outputs:
|
||||
description: The AWS secret access key for the provided credentials
|
||||
aws-session-token:
|
||||
description: The AWS session token for the provided credentials
|
||||
aws-expiration:
|
||||
description: The expiration time for the provided credentials
|
||||
|
||||
+9
-9
@@ -4,18 +4,18 @@
|
||||
"lineWidth": 120,
|
||||
"indentWidth": 2,
|
||||
"lineEnding": "lf",
|
||||
"enabled": true,
|
||||
"enabled": true
|
||||
},
|
||||
"linter": {
|
||||
"enabled": true,
|
||||
"rules": {
|
||||
"performance": {
|
||||
"noDelete": "off",
|
||||
"noDelete": "off"
|
||||
},
|
||||
"complexity": {
|
||||
"noExtraBooleanCast": "off",
|
||||
"noExtraBooleanCast": "off"
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
"javascript": {
|
||||
"formatter": {
|
||||
@@ -23,12 +23,12 @@
|
||||
"jsxQuoteStyle": "double",
|
||||
"quoteStyle": "single",
|
||||
"bracketSpacing": true,
|
||||
"arrowParentheses": "always",
|
||||
},
|
||||
"arrowParentheses": "always"
|
||||
}
|
||||
},
|
||||
"json": {
|
||||
"formatter": {
|
||||
"trailingCommas": "all",
|
||||
},
|
||||
},
|
||||
"trailingCommas": "none"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4266
-2891
File diff suppressed because one or more lines are too long
+4686
-3271
File diff suppressed because one or more lines are too long
Generated
+1086
-932
File diff suppressed because it is too large
Load Diff
+14
-12
@@ -1,12 +1,14 @@
|
||||
{
|
||||
"name": "configure-aws-credentials",
|
||||
"description": "A GitHub Action to configure AWS credentials",
|
||||
"version": "4.2.0",
|
||||
"version": "4.3.0",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"lint": "biome check --error-on-warnings ./src",
|
||||
"lint:fix": "biome check --write ./src",
|
||||
"package": "npm run build && ncc build --license THIRD-PARTY -o dist && ncc build src/cleanup/index.ts -o dist/cleanup && cpy dist/THIRD-PARTY . && del-cli dist/THIRD-PARTY",
|
||||
"test": "npm run lint && vitest run && npm run build"
|
||||
"test": "npm run lint && vitest run && npm run build",
|
||||
"clean": "del-cli coverage test-reports node_modules"
|
||||
},
|
||||
"author": {
|
||||
"name": "Amazon.com, Inc. or its affiliates",
|
||||
@@ -14,26 +16,26 @@
|
||||
"organization": true
|
||||
},
|
||||
"devDependencies": {
|
||||
"@aws-sdk/credential-provider-env": "^3.515.0",
|
||||
"@biomejs/biome": "1.9.4",
|
||||
"@smithy/property-provider": "^4.0.1",
|
||||
"@types/node": "^22.15.11",
|
||||
"@aws-sdk/credential-provider-env": "^3.858.0",
|
||||
"@biomejs/biome": "2.1.3",
|
||||
"@smithy/property-provider": "^4.0.3",
|
||||
"@types/node": "^24.1.0",
|
||||
"@vercel/ncc": "^0.38.3",
|
||||
"@vitest/coverage-v8": "^3.1.2",
|
||||
"@vitest/coverage-v8": "^3.2.4",
|
||||
"aws-sdk-client-mock": "^4.1.0",
|
||||
"cpy-cli": "^5.0.0",
|
||||
"del-cli": "^6.0.0",
|
||||
"json-schema": "^0.4.0",
|
||||
"memfs": "^4.17.1",
|
||||
"memfs": "^4.25.1",
|
||||
"standard-version": "^9.5.0",
|
||||
"typescript": "^5.8.3",
|
||||
"vitest": "^3.1.2"
|
||||
"vitest": "^3.2.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.11.1",
|
||||
"@aws-sdk/client-sts": "^3.803.0",
|
||||
"@smithy/node-http-handler": "^4.0.1",
|
||||
"https-proxy-agent": "^5.0.1"
|
||||
"@aws-sdk/client-sts": "^3.858.0",
|
||||
"@smithy/node-http-handler": "^4.1.0",
|
||||
"https-proxy-agent": "^7.0.6"
|
||||
},
|
||||
"keywords": [
|
||||
"aws",
|
||||
|
||||
@@ -142,7 +142,6 @@ export async function assumeRole(params: assumeRoleParams) {
|
||||
PolicyArns: managedSessionPolicies?.length ? managedSessionPolicies : undefined,
|
||||
};
|
||||
const keys = Object.keys(commonAssumeRoleParams) as Array<keyof typeof commonAssumeRoleParams>;
|
||||
// biome-ignore lint/complexity/noForEach: Legacy code
|
||||
keys.forEach((k) => commonAssumeRoleParams[k] === undefined && delete commonAssumeRoleParams[k]);
|
||||
|
||||
// Instantiate STS client
|
||||
|
||||
+15
-12
@@ -13,18 +13,21 @@ import { errorMessage } from '../helpers';
|
||||
*/
|
||||
|
||||
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
|
||||
// string. The AWS CLI and AWS SDKs will behave correctly: they treat an
|
||||
// empty string value as if the environment variable does not exist.
|
||||
core.exportVariable('AWS_ACCESS_KEY_ID', '');
|
||||
core.exportVariable('AWS_SECRET_ACCESS_KEY', '');
|
||||
core.exportVariable('AWS_SESSION_TOKEN', '');
|
||||
core.exportVariable('AWS_DEFAULT_REGION', '');
|
||||
core.exportVariable('AWS_REGION', '');
|
||||
} catch (error) {
|
||||
core.setFailed(errorMessage(error));
|
||||
const outputEnvCredentialsInput = core.getInput('output-env-credentials', { required: false }) || 'true';
|
||||
if (outputEnvCredentialsInput === 'true') {
|
||||
try {
|
||||
// The GitHub Actions toolkit does not have an option to completely unset
|
||||
// environment variables, so we overwrite the current value with an empty
|
||||
// string. The AWS CLI and AWS SDKs will behave correctly: they treat an
|
||||
// empty string value as if the environment variable does not exist.
|
||||
core.exportVariable('AWS_ACCESS_KEY_ID', '');
|
||||
core.exportVariable('AWS_SECRET_ACCESS_KEY', '');
|
||||
core.exportVariable('AWS_SESSION_TOKEN', '');
|
||||
core.exportVariable('AWS_DEFAULT_REGION', '');
|
||||
core.exportVariable('AWS_REGION', '');
|
||||
} catch (error) {
|
||||
core.setFailed(errorMessage(error));
|
||||
}
|
||||
}
|
||||
}
|
||||
/* c8 ignore start */
|
||||
|
||||
+45
-20
@@ -29,32 +29,51 @@ export function translateEnvVariables() {
|
||||
'SPECIAL_CHARACTERS_WORKAROUND',
|
||||
'USE_EXISTING_CREDENTIALS',
|
||||
];
|
||||
// Treat HTTPS_PROXY as HTTP_PROXY. Precedence is HTTPS_PROXY > HTTP_PROXY
|
||||
if (process.env.HTTPS_PROXY) process.env.HTTP_PROXY = process.env.HTTPS_PROXY;
|
||||
|
||||
for (const envVar of envVars) {
|
||||
if (process.env[envVar]) {
|
||||
process.env[`INPUT_${envVar.replace(/_/g, '-')}`] = process.env[envVar];
|
||||
const inputKey = `INPUT_${envVar.replace(/_/g, '-')}`;
|
||||
process.env[inputKey] = process.env[inputKey] || process.env[envVar];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Configure the AWS CLI and AWS SDKs using environment variables and set them as secrets.
|
||||
// Setting the credentials as secrets masks them in Github Actions logs
|
||||
export function exportCredentials(creds?: Partial<Credentials>, outputCredentials?: boolean) {
|
||||
export function exportCredentials(
|
||||
creds?: Partial<Credentials>,
|
||||
outputCredentials?: boolean,
|
||||
outputEnvCredentials?: 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 (outputEnvCredentials) {
|
||||
if (creds?.AccessKeyId) {
|
||||
core.exportVariable('AWS_ACCESS_KEY_ID', creds.AccessKeyId);
|
||||
}
|
||||
|
||||
if (creds?.SecretAccessKey) {
|
||||
core.exportVariable('AWS_SECRET_ACCESS_KEY', creds.SecretAccessKey);
|
||||
}
|
||||
|
||||
if (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) {
|
||||
@@ -73,17 +92,21 @@ export function exportCredentials(creds?: Partial<Credentials>, outputCredential
|
||||
}
|
||||
}
|
||||
|
||||
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 unsetCredentials(outputEnvCredentials?: boolean) {
|
||||
if (outputEnvCredentials) {
|
||||
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);
|
||||
export function exportRegion(region: string, outputEnvCredentials?: boolean) {
|
||||
if (outputEnvCredentials) {
|
||||
core.exportVariable('AWS_DEFAULT_REGION', region);
|
||||
core.exportVariable('AWS_REGION', region);
|
||||
}
|
||||
}
|
||||
|
||||
// Obtains account ID from STS Client and sets it as output
|
||||
@@ -91,13 +114,16 @@ export async function exportAccountId(credentialsClient: CredentialsClient, mask
|
||||
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?');
|
||||
const arn = identity.Arn;
|
||||
if (!accountId || !arn) {
|
||||
throw new Error('Could not get Account ID or ARN from STS. Did you set credentials?');
|
||||
}
|
||||
if (maskAccountId) {
|
||||
core.setSecret(accountId);
|
||||
core.setSecret(arn);
|
||||
}
|
||||
core.setOutput('aws-account-id', accountId);
|
||||
core.setOutput('authenticated-arn', arn);
|
||||
return accountId;
|
||||
}
|
||||
|
||||
@@ -158,7 +184,6 @@ export async function retryAndBackoff<T>(
|
||||
}
|
||||
// It's retryable, so sleep and retry.
|
||||
await sleep(Math.random() * (2 ** retries * base));
|
||||
// biome-ignore lint/style/noParameterAssign: This is a loop variable
|
||||
retries += 1;
|
||||
if (retries >= maxRetries) {
|
||||
throw err;
|
||||
|
||||
+11
-7
@@ -1,7 +1,7 @@
|
||||
import * as core from '@actions/core';
|
||||
import type { AssumeRoleCommandOutput } from '@aws-sdk/client-sts';
|
||||
import { CredentialsClient } from './CredentialsClient';
|
||||
import { assumeRole } from './assumeRole';
|
||||
import { CredentialsClient } from './CredentialsClient';
|
||||
import {
|
||||
areCredentialsValid,
|
||||
errorMessage,
|
||||
@@ -46,7 +46,7 @@ export async function run() {
|
||||
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 proxyServer = core.getInput('http-proxy', { required: false }) || process.env.HTTP_PROXY;
|
||||
const inlineSessionPolicy = core.getInput('inline-session-policy', {
|
||||
required: false,
|
||||
});
|
||||
@@ -56,6 +56,8 @@ export async function run() {
|
||||
const roleChaining = roleChainingInput.toLowerCase() === 'true';
|
||||
const outputCredentialsInput = core.getInput('output-credentials', { required: false }) || 'false';
|
||||
const outputCredentials = outputCredentialsInput.toLowerCase() === 'true';
|
||||
const outputEnvCredentialsInput = core.getInput('output-env-credentials', { required: false }) || 'true';
|
||||
const outputEnvCredentials = outputEnvCredentialsInput.toLowerCase() === 'true';
|
||||
const unsetCurrentCredentialsInput = core.getInput('unset-current-credentials', { required: false }) || 'false';
|
||||
const unsetCurrentCredentials = unsetCurrentCredentialsInput.toLowerCase() === 'true';
|
||||
const disableRetryInput = core.getInput('disable-retry', { required: false }) || 'false';
|
||||
@@ -108,13 +110,13 @@ export async function run() {
|
||||
};
|
||||
|
||||
if (unsetCurrentCredentials) {
|
||||
unsetCredentials();
|
||||
unsetCredentials(outputEnvCredentials);
|
||||
}
|
||||
|
||||
if (!region.match(REGION_REGEX)) {
|
||||
throw new Error(`Region is not valid: ${region}`);
|
||||
}
|
||||
exportRegion(region);
|
||||
exportRegion(region, outputEnvCredentials);
|
||||
|
||||
// Instantiate credentials client
|
||||
const credentialsClient = new CredentialsClient({ region, proxyServer });
|
||||
@@ -153,7 +155,7 @@ export async function run() {
|
||||
// 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 });
|
||||
exportCredentials({ AccessKeyId, SecretAccessKey, SessionToken }, outputCredentials, outputEnvCredentials);
|
||||
} else if (!webIdentityTokenFile && !roleChaining) {
|
||||
// Proceed only if credentials can be picked up
|
||||
await credentialsClient.validateCredentials();
|
||||
@@ -193,7 +195,7 @@ export async function run() {
|
||||
);
|
||||
} while (specialCharacterWorkaround && !verifyKeys(roleCredentials.Credentials));
|
||||
core.info(`Authenticated as assumedRoleId ${roleCredentials.AssumedRoleUser?.AssumedRoleId}`);
|
||||
exportCredentials(roleCredentials.Credentials, outputCredentials);
|
||||
exportCredentials(roleCredentials.Credentials, outputCredentials, outputEnvCredentials);
|
||||
// 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.
|
||||
@@ -201,7 +203,9 @@ export async function run() {
|
||||
if (!process.env.GITHUB_ACTIONS || AccessKeyId) {
|
||||
await credentialsClient.validateCredentials(roleCredentials.Credentials?.AccessKeyId);
|
||||
}
|
||||
await exportAccountId(credentialsClient, maskAccountId);
|
||||
if (outputEnvCredentials) {
|
||||
await exportAccountId(credentialsClient, maskAccountId);
|
||||
}
|
||||
} else {
|
||||
core.info('Proceeding with IAM user credentials');
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { cleanup } from '../src/cleanup';
|
||||
import * as core from '@actions/core';
|
||||
import { mockClient } from 'aws-sdk-client-mock';
|
||||
import { STSClient } from '@aws-sdk/client-sts';
|
||||
import { mockClient } from 'aws-sdk-client-mock';
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { cleanup } from '../src/cleanup';
|
||||
import mocks from './mockinputs.test';
|
||||
|
||||
const mockedSTSClient = mockClient(STSClient);
|
||||
@@ -45,4 +45,9 @@ describe('Configure AWS Credentials cleanup', {}, () => {
|
||||
cleanup();
|
||||
expect(core.setFailed).toHaveBeenCalled();
|
||||
});
|
||||
it(`doesn't export credentials as empty env variables if asked not to`, {}, () => {
|
||||
vi.spyOn(core, 'getInput').mockImplementation(mocks.getInput(mocks.NO_ENV_CREDS_INPUTS));
|
||||
cleanup();
|
||||
expect(core.exportVariable).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
});
|
||||
|
||||
+25
-6
@@ -1,7 +1,7 @@
|
||||
import { describe, it, expect, vi } from 'vitest';
|
||||
import * as helpers from '../src/helpers';
|
||||
import { beforeEach } from 'node:test';
|
||||
import * as core from '@actions/core';
|
||||
import { before, beforeEach } from 'node:test';
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
import * as helpers from '../src/helpers';
|
||||
|
||||
describe('Configure AWS Credentials helpers', {}, () => {
|
||||
beforeEach(() => {
|
||||
@@ -11,9 +11,9 @@ describe('Configure AWS Credentials helpers', {}, () => {
|
||||
const actor = 'actor[bot]';
|
||||
expect(helpers.sanitizeGitHubVariables(actor)).toBe('actor_bot_');
|
||||
});
|
||||
it('can sleep', {}, () => {
|
||||
it('can sleep', {}, async () => {
|
||||
const sleep = helpers.defaultSleep(10);
|
||||
expect(Promise.race([sleep, new Promise((_, reject) => setTimeout(reject, 20))])).resolves.toBe(undefined);
|
||||
await expect(Promise.race([sleep, new Promise((_, reject) => setTimeout(reject, 20))])).resolves.toBe(undefined);
|
||||
});
|
||||
it('removes special characters from workflow names', {}, () => {
|
||||
expect(helpers.sanitizeGitHubVariables('sdf234@#$%$^&*()_+{}|:"<>?')).toEqual('sdf234@__________+___:____');
|
||||
@@ -27,7 +27,11 @@ describe('Configure AWS Credentials helpers', {}, () => {
|
||||
vi.spyOn(core, 'setOutput').mockImplementation(() => {});
|
||||
vi.spyOn(core, 'setSecret').mockImplementation(() => {});
|
||||
vi.spyOn(core, 'exportVariable').mockImplementation(() => {});
|
||||
helpers.exportCredentials({ AccessKeyId: 'test', SecretAccessKey: 'test', SessionToken: 'test', Expiration: new Date(8640000000000000) }, true);
|
||||
helpers.exportCredentials(
|
||||
{ AccessKeyId: 'test', SecretAccessKey: 'test', SessionToken: 'test', Expiration: new Date(8640000000000000) },
|
||||
true,
|
||||
true,
|
||||
);
|
||||
expect(core.setOutput).toHaveBeenCalledTimes(4);
|
||||
expect(core.setSecret).toHaveBeenCalledTimes(3);
|
||||
expect(core.exportVariable).toHaveBeenCalledTimes(3);
|
||||
@@ -42,4 +46,19 @@ describe('Configure AWS Credentials helpers', {}, () => {
|
||||
expect(process.env.AWS_DEFAULT_REGION).toBeUndefined;
|
||||
process.env = env;
|
||||
});
|
||||
it(`won't output credentials to env if told not to`, {}, () => {
|
||||
vi.spyOn(core, 'setOutput').mockImplementation(() => {});
|
||||
vi.spyOn(core, 'setSecret').mockImplementation(() => {});
|
||||
vi.spyOn(core, 'exportVariable').mockImplementation(() => {});
|
||||
helpers.exportCredentials(
|
||||
{ AccessKeyId: 'test', SecretAccessKey: 'test', SessionToken: 'test', Expiration: new Date(8640000000000000) },
|
||||
true,
|
||||
false,
|
||||
);
|
||||
helpers.unsetCredentials(false);
|
||||
helpers.exportRegion('fake-test-region', false);
|
||||
expect(core.setOutput).toHaveBeenCalledTimes(4);
|
||||
expect(core.setSecret).toHaveBeenCalledTimes(3);
|
||||
expect(core.exportVariable).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
});
|
||||
|
||||
+114
-17
@@ -1,17 +1,16 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import * as core from '@actions/core';
|
||||
import {
|
||||
AssumeRoleCommand,
|
||||
AssumeRoleWithWebIdentityCommand,
|
||||
GetCallerIdentityCommand,
|
||||
STSClient,
|
||||
} from '@aws-sdk/client-sts';
|
||||
import { fs, vol } from 'memfs';
|
||||
import * as core from '@actions/core';
|
||||
import mocks from './mockinputs.test';
|
||||
import { mockClient } from 'aws-sdk-client-mock';
|
||||
import { run } from '../src/index';
|
||||
import { fs, vol } from 'memfs';
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { CredentialsClient } from '../src/CredentialsClient';
|
||||
import { before } from 'node:test';
|
||||
import { run } from '../src/index';
|
||||
import mocks from './mockinputs.test';
|
||||
|
||||
const mockedSTSClient = mockClient(STSClient);
|
||||
|
||||
@@ -48,7 +47,7 @@ describe('Configure AWS Credentials', {}, () => {
|
||||
expect(core.info).toHaveBeenCalledWith('Authenticated as assumedRoleId AROAFAKEASSUMEDROLEID');
|
||||
expect(core.info).toHaveBeenCalledTimes(2);
|
||||
expect(core.setOutput).toHaveBeenCalledWith('aws-account-id', '111111111111');
|
||||
expect(core.setOutput).toHaveBeenCalledOnce();
|
||||
expect(core.setOutput).toHaveBeenCalledTimes(2);
|
||||
expect(core.setSecret).toHaveBeenCalledWith('STSAWSACCESSKEYID');
|
||||
expect(core.setSecret).toHaveBeenCalledWith('STSAWSSECRETACCESSKEY');
|
||||
expect(core.setSecret).toHaveBeenCalledWith('STSAWSSESSIONTOKEN');
|
||||
@@ -72,7 +71,7 @@ describe('Configure AWS Credentials', {}, () => {
|
||||
expect(core.info).toHaveBeenCalledWith('Authenticated as assumedRoleId AROAFAKEASSUMEDROLEID');
|
||||
expect(core.info).toHaveBeenCalledTimes(3);
|
||||
expect(core.setOutput).toHaveBeenCalledWith('aws-account-id', '111111111111');
|
||||
expect(core.setOutput).toHaveBeenCalledOnce();
|
||||
expect(core.setOutput).toHaveBeenCalledTimes(2);
|
||||
expect(core.setSecret).toHaveBeenCalledWith('STSAWSACCESSKEYID');
|
||||
expect(core.setSecret).toHaveBeenCalledWith('STSAWSSECRETACCESSKEY');
|
||||
expect(core.setSecret).toHaveBeenCalledWith('STSAWSSESSIONTOKEN');
|
||||
@@ -107,7 +106,7 @@ describe('Configure AWS Credentials', {}, () => {
|
||||
expect(core.setSecret).toHaveBeenCalledWith('MYAWSSECRETACCESSKEY');
|
||||
expect(core.setSecret).toHaveBeenCalledTimes(2);
|
||||
expect(core.setOutput).toHaveBeenCalledWith('aws-account-id', '111111111111');
|
||||
expect(core.setOutput).toHaveBeenCalledOnce();
|
||||
expect(core.setOutput).toHaveBeenCalledTimes(2);
|
||||
expect(core.info).toHaveBeenCalledWith('Proceeding with IAM user credentials');
|
||||
expect(core.info).toHaveBeenCalledOnce();
|
||||
expect(core.setFailed).not.toHaveBeenCalled();
|
||||
@@ -141,7 +140,7 @@ describe('Configure AWS Credentials', {}, () => {
|
||||
expect(core.setSecret).toHaveBeenCalledWith('MYAWSSECRETACCESSKEY');
|
||||
expect(core.setSecret).toHaveBeenCalledTimes(5);
|
||||
expect(core.setOutput).toHaveBeenCalledWith('aws-account-id', '111111111111');
|
||||
expect(core.setOutput).toHaveBeenCalledTimes(2);
|
||||
expect(core.setOutput).toHaveBeenCalledTimes(4);
|
||||
expect(core.info).toHaveBeenCalledWith('Assuming role with user credentials');
|
||||
expect(core.info).toHaveBeenCalledWith('Authenticated as assumedRoleId AROAFAKEASSUMEDROLEID');
|
||||
expect(core.info).toHaveBeenCalledTimes(2);
|
||||
@@ -174,7 +173,7 @@ describe('Configure AWS Credentials', {}, () => {
|
||||
expect(core.setSecret).toHaveBeenCalledWith('STSAWSSESSIONTOKEN');
|
||||
expect(core.setSecret).toHaveBeenCalledTimes(3);
|
||||
expect(core.setOutput).toHaveBeenCalledWith('aws-account-id', '111111111111');
|
||||
expect(core.setOutput).toHaveBeenCalledTimes(1);
|
||||
expect(core.setOutput).toHaveBeenCalledTimes(2);
|
||||
expect(core.setFailed).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -205,7 +204,7 @@ describe('Configure AWS Credentials', {}, () => {
|
||||
expect(core.setSecret).toHaveBeenCalledWith('STSAWSSESSIONTOKEN');
|
||||
expect(core.setSecret).toHaveBeenCalledTimes(3);
|
||||
expect(core.setOutput).toHaveBeenCalledWith('aws-account-id', '111111111111');
|
||||
expect(core.setOutput).toHaveBeenCalledTimes(2);
|
||||
expect(core.setOutput).toHaveBeenCalledTimes(4);
|
||||
expect(core.setFailed).not.toHaveBeenCalled();
|
||||
});
|
||||
it('exports environment variables from inputs', {}, async () => {
|
||||
@@ -238,7 +237,7 @@ describe('Configure AWS Credentials', {}, () => {
|
||||
expect(core.setSecret).toHaveBeenCalledWith('STSAWSSESSIONTOKEN');
|
||||
expect(core.setSecret).toHaveBeenCalledTimes(6);
|
||||
expect(core.setOutput).toHaveBeenCalledWith('aws-account-id', '111111111111');
|
||||
expect(core.setOutput).toHaveBeenCalledTimes(2);
|
||||
expect(core.setOutput).toHaveBeenCalledTimes(4);
|
||||
expect(core.setFailed).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -300,17 +299,115 @@ describe('Configure AWS Credentials', {}, () => {
|
||||
await run();
|
||||
expect(core.setFailed).toHaveBeenCalled();
|
||||
});
|
||||
it('gets new creds if told to reuse existing but they\'re invalid', {}, async () => {
|
||||
it("gets new creds if told to reuse existing but they're invalid", {}, async () => {
|
||||
vi.spyOn(core, 'getInput').mockImplementation(mocks.getInput(mocks.USE_EXISTING_CREDENTIALS_INPUTS));
|
||||
mockedSTSClient.on(GetCallerIdentityCommand).rejects();
|
||||
await run();
|
||||
expect(core.notice).toHaveBeenCalledWith('No valid credentials exist. Running as normal.')
|
||||
expect(core.notice).toHaveBeenCalledWith('No valid credentials exist. Running as normal.');
|
||||
});
|
||||
it('doesn\'t get new creds if there are already valid ones and we said use them', {}, async () => {
|
||||
it("doesn't get new creds if there are already valid ones and we said use them", {}, async () => {
|
||||
vi.spyOn(core, 'getInput').mockImplementation(mocks.getInput(mocks.USE_EXISTING_CREDENTIALS_INPUTS));
|
||||
mockedSTSClient.on(GetCallerIdentityCommand).resolves(mocks.outputs.GET_CALLER_IDENTITY);
|
||||
await run();
|
||||
expect(core.setFailed).not.toHaveBeenCalled();
|
||||
})
|
||||
});
|
||||
it("doesn't export credentials as environment variables if told not to", {}, async () => {
|
||||
mockedSTSClient.on(AssumeRoleWithWebIdentityCommand).resolvesOnce(mocks.outputs.STS_CREDENTIALS);
|
||||
vi.spyOn(core, 'getInput').mockImplementation(mocks.getInput(mocks.NO_ENV_CREDS_INPUTS));
|
||||
vi.spyOn(core, 'getIDToken').mockResolvedValue('testoidctoken');
|
||||
process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN = 'fake-token';
|
||||
await run();
|
||||
expect(core.setSecret).toHaveBeenCalledTimes(3);
|
||||
expect(core.exportVariable).toHaveBeenCalledTimes(0);
|
||||
expect(core.setFailed).not.toHaveBeenCalled();
|
||||
});
|
||||
it('can export creds as step outputs without exporting as env variables', {}, async () => {
|
||||
mockedSTSClient.on(AssumeRoleWithWebIdentityCommand).resolvesOnce(mocks.outputs.STS_CREDENTIALS);
|
||||
vi.spyOn(core, 'getInput').mockImplementation(mocks.getInput(mocks.STEP_BUT_NO_ENV_INPUTS));
|
||||
vi.spyOn(core, 'getIDToken').mockResolvedValue('testoidctoken');
|
||||
process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN = 'fake-token';
|
||||
await run();
|
||||
expect(core.setSecret).toHaveBeenCalledTimes(3);
|
||||
expect(core.exportVariable).toHaveBeenCalledTimes(0);
|
||||
expect(core.setOutput).toHaveBeenCalledTimes(4);
|
||||
expect(core.setFailed).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('HTTP Proxy Configuration', {}, () => {
|
||||
beforeEach(() => {
|
||||
vi.spyOn(core, 'getInput').mockImplementation(mocks.getInput(mocks.GH_OIDC_INPUTS));
|
||||
vi.spyOn(core, 'getIDToken').mockResolvedValue('testoidctoken');
|
||||
mockedSTSClient.on(GetCallerIdentityCommand).resolvesOnce({ ...mocks.outputs.GET_CALLER_IDENTITY });
|
||||
mockedSTSClient.on(AssumeRoleWithWebIdentityCommand).resolvesOnce(mocks.outputs.STS_CREDENTIALS);
|
||||
process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN = 'fake-token';
|
||||
});
|
||||
|
||||
it('configures proxy from http-proxy input', async () => {
|
||||
const infoSpy = vi.spyOn(core, 'info');
|
||||
vi.spyOn(core, 'getInput').mockImplementation(
|
||||
mocks.getInput({
|
||||
...mocks.GH_OIDC_INPUTS,
|
||||
'http-proxy': 'http://proxy.example.com:8080'
|
||||
})
|
||||
);
|
||||
|
||||
await run();
|
||||
|
||||
expect(infoSpy).toHaveBeenCalledWith('Configuring proxy handler for STS client');
|
||||
expect(core.setFailed).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('configures proxy from HTTP_PROXY environment variable', async () => {
|
||||
const infoSpy = vi.spyOn(core, 'info');
|
||||
process.env.HTTP_PROXY = 'http://proxy.example.com:8080';
|
||||
|
||||
await run();
|
||||
|
||||
expect(infoSpy).toHaveBeenCalledWith('Configuring proxy handler for STS client');
|
||||
expect(core.setFailed).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('configures proxy from HTTPS_PROXY environment variable', async () => {
|
||||
const infoSpy = vi.spyOn(core, 'info');
|
||||
process.env.HTTPS_PROXY = 'https://proxy.example.com:8080';
|
||||
|
||||
await run();
|
||||
|
||||
expect(infoSpy).toHaveBeenCalledWith('Configuring proxy handler for STS client');
|
||||
expect(core.setFailed).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('prioritizes http-proxy input over environment variables', async () => {
|
||||
const infoSpy = vi.spyOn(core, 'info');
|
||||
process.env.HTTP_PROXY = 'http://env-proxy.example.com:8080';
|
||||
vi.spyOn(core, 'getInput').mockImplementation(
|
||||
mocks.getInput({
|
||||
...mocks.GH_OIDC_INPUTS,
|
||||
'http-proxy': 'http://input-proxy.example.com:8080'
|
||||
})
|
||||
);
|
||||
|
||||
await run();
|
||||
|
||||
expect(infoSpy).toHaveBeenCalledWith('Configuring proxy handler for STS client');
|
||||
expect(core.setFailed).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('properly configures proxy agent in STS client', async () => {
|
||||
const infoSpy = vi.spyOn(core, 'info');
|
||||
|
||||
vi.spyOn(core, 'getInput').mockImplementation(
|
||||
mocks.getInput({
|
||||
...mocks.GH_OIDC_INPUTS,
|
||||
'http-proxy': 'http://proxy.example.com:8080'
|
||||
})
|
||||
);
|
||||
|
||||
await run();
|
||||
|
||||
expect(infoSpy).toHaveBeenCalledWith('Configuring proxy handler for STS client');
|
||||
expect(core.setFailed).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+12
-1
@@ -31,7 +31,18 @@ const inputs = {
|
||||
'aws-region': 'fake-region-1',
|
||||
'use-existing-credentials': 'true',
|
||||
'role-to-assume': 'arn:aws:iam::111111111111:role/MY-ROLE',
|
||||
}
|
||||
},
|
||||
NO_ENV_CREDS_INPUTS: {
|
||||
'role-to-assume': 'arn:aws:iam::111111111111:role/MY-ROLE',
|
||||
'aws-region': 'fake-region-1',
|
||||
'output-env-credentials': 'false',
|
||||
},
|
||||
STEP_BUT_NO_ENV_INPUTS: {
|
||||
'role-to-assume': 'arn:aws:iam::111111111111:role/MY-ROLE',
|
||||
'aws-region': 'fake-region-1',
|
||||
'output-env-credentials': 'false',
|
||||
'output-credentials': 'true',
|
||||
},
|
||||
};
|
||||
|
||||
const envs = {
|
||||
|
||||
+4
-9
@@ -19,17 +19,12 @@
|
||||
"sourceMap": true,
|
||||
"disableSizeLimit": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"lib": [ "ES2020" ],
|
||||
"lib": ["ES2020"],
|
||||
"target": "ES2020",
|
||||
"noErrorTruncation": true,
|
||||
"esModuleInterop": true,
|
||||
"rootDir": "src",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"test/**/*.ts"
|
||||
],
|
||||
"include": ["src/**/*.ts"],
|
||||
"exclude": ["test/**/*.ts"]
|
||||
}
|
||||
|
||||
|
||||
+2
-5
@@ -1,11 +1,8 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"include": [
|
||||
"test/**/*.ts",
|
||||
"src/**/*.ts"
|
||||
],
|
||||
"include": ["test/**/*.ts", "src/**/*.ts"],
|
||||
"exclude": [],
|
||||
"compilerOptions": {
|
||||
"rootDir": "./"
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user