mirror of
https://github.com/aws-actions/configure-aws-credentials.git
synced 2026-09-01 05:45:06 +09:00
Compare commits
118 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 | |||
| f24d7193d9 | |||
| f6095d9dc4 | |||
| df1fa04984 | |||
| 1c397386a2 | |||
| 21e0c4b1ca | |||
| b0f2baf098 | |||
| 4320d1b180 | |||
| 5d1959cbc9 | |||
| 3ecfae8a2c | |||
| 2f26d75abd | |||
| 658557f884 | |||
| f157a6574f | |||
| 9e38641911 | |||
| 2c168adcae | |||
| 4d5f2395c0 | |||
| a4f326760c | |||
| 93edf43b3a | |||
| fe54dce1bb | |||
| 423f4e15fb | |||
| 11e58be8bc | |||
| 7f5e3139fe | |||
| 5a0cf0167f | |||
| adb43a2cd3 | |||
| e62ae06aa8 | |||
| 66d7591932 | |||
| 76dfa67953 | |||
| ab246ce5fb | |||
| ca537c9527 | |||
| 72a198126f | |||
| 203a39c651 | |||
| c401b8a98c | |||
| 27e906a655 | |||
| 483d6b517a | |||
| c7765366a4 |
@@ -24,7 +24,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
parse-json-secrets: true
|
parse-json-secrets: true
|
||||||
secret-ids: |
|
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
|
- name: Enable PR automerge
|
||||||
run: gh pr merge --auto --squash "$PR_URL"
|
run: gh pr merge --auto --squash "$PR_URL"
|
||||||
env:
|
env:
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
name: Dependabot auto-approve
|
name: Dependabot auto-approve
|
||||||
on: pull_request
|
on:
|
||||||
|
pull_request_target:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
id-token: write
|
id-token: write
|
||||||
|
contents: read
|
||||||
jobs:
|
jobs:
|
||||||
dependabot:
|
dependabot:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -17,14 +21,14 @@ jobs:
|
|||||||
uses: aws-actions/configure-aws-credentials@v4
|
uses: aws-actions/configure-aws-credentials@v4
|
||||||
with:
|
with:
|
||||||
aws-region: us-west-2
|
aws-region: us-west-2
|
||||||
role-to-assume: ${{ secrets.SECRETS_AWS_PACKAGING_ROLE_TO_ASSUME }}
|
role-to-assume: ${{ secrets.CONFIGUREAWSCREDENTIALSPACKAGEROLEARN }}
|
||||||
role-duration-seconds: 900
|
role-duration-seconds: 900
|
||||||
- name: Get bot user token
|
- name: Get bot user token
|
||||||
uses: aws-actions/aws-secretsmanager-get-secrets@v2
|
uses: aws-actions/aws-secretsmanager-get-secrets@v2
|
||||||
with:
|
with:
|
||||||
parse-json-secrets: true
|
parse-json-secrets: true
|
||||||
secret-ids: |
|
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
|
- name: Approve PR if not already approved
|
||||||
run: |
|
run: |
|
||||||
gh pr checkout "$PR_URL"
|
gh pr checkout "$PR_URL"
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
parse-json-secrets: true
|
parse-json-secrets: true
|
||||||
secret-ids: |
|
secret-ids: |
|
||||||
OSDS,arn:aws:secretsmanager:us-west-2:206735643321:secret:github-aws-sdk-osds-automation-gebs9n
|
${{ secrets.OSDS_PACKAGING_ROLE }}
|
||||||
- name: Commit
|
- name: Commit
|
||||||
run: |
|
run: |
|
||||||
echo "::add-mask::${{ env.OSDS_ACCESS_TOKEN }}"
|
echo "::add-mask::${{ env.OSDS_ACCESS_TOKEN }}"
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
with:
|
with:
|
||||||
parse-json-secrets: true
|
parse-json-secrets: true
|
||||||
secret-ids: |
|
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
|
- name: Run release-please
|
||||||
uses: googleapis/release-please-action@v4
|
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",
|
".release-please-manifest.json": "4.0.2",
|
||||||
"package.json": "4.0.2",
|
"package.json": "4.0.2",
|
||||||
".": "4.1.0"
|
".": "4.3.0"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,55 @@
|
|||||||
|
|
||||||
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.
|
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)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add Expiration field to Outputs ([a4f3267](https://github.com/aws-actions/configure-aws-credentials/commit/a4f326760c1c1bf49ab86051c658d6501816b930))
|
||||||
|
* Document role-duration-seconds range ([5a0cf01](https://github.com/aws-actions/configure-aws-credentials/commit/5a0cf0167f837dfa7af7d951ba6a78a38dc2b79e))
|
||||||
|
* support action inputs as environment variables ([#1338](https://github.com/aws-actions/configure-aws-credentials/issues/1338)) ([2c168ad](https://github.com/aws-actions/configure-aws-credentials/commit/2c168adcae62d67531ba83842723c8f30695116a))
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* make sure action builds, also fix dependabot autoapprove ([c401b8a](https://github.com/aws-actions/configure-aws-credentials/commit/c401b8a98c5067672f52e0387cdd87d54acfe1fd))
|
||||||
|
* role chaning on mulitple runs ([#1340](https://github.com/aws-actions/configure-aws-credentials/issues/1340)) ([9e38641](https://github.com/aws-actions/configure-aws-credentials/commit/9e386419117a9edd458297e4f1822a5df7506a03))
|
||||||
|
|
||||||
## [4.1.0](https://github.com/aws-actions/configure-aws-credentials/compare/v4.0.3...v4.1.0) (2025-02-08)
|
## [4.1.0](https://github.com/aws-actions/configure-aws-credentials/compare/v4.0.3...v4.1.0) (2025-02-08)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,98 +1,130 @@
|
|||||||
## Configure AWS Credentials for GitHub Actions
|
Configure AWS Credentials
|
||||||
Configure your AWS credentials and region environment variables for use in other
|
=========================
|
||||||
GitHub Actions.
|
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
|
Quick Start (OIDC, recommended)
|
||||||
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
|
1. Create an IAM Identity Provider in your AWS account for GitHub OIDC. (See
|
||||||
for AWS API calls.
|
[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
|
```json
|
||||||
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
|
"Version": "2012-10-17",
|
||||||
and AWS region. One way to do that in GitHub Actions is to use a repository
|
"Statement": [
|
||||||
secret with IAM credentials, but this doesn't follow [AWS security
|
{
|
||||||
guidelines](https://docs.aws.amazon.com/IAM/latest/UserGuide/security-creds.html)
|
"Effect": "Allow",
|
||||||
on using long term credentials. Instead, we recommend that you use a long term
|
"Principal": {
|
||||||
credential or JWT to fetch a temporary credential, and use that with your tools
|
"Federated": "arn:aws:iam::<AWS_ACCOUNT_ID>:oidc-provider/token.actions.githubusercontent.com"
|
||||||
instead. This GitHub Action facilitates just that.
|
},
|
||||||
|
"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
|
```yaml
|
||||||
variables. In essence, this Action runs through the standard [credential
|
# Need ID token write permission to use OIDC
|
||||||
resolution flow](https://docs.aws.amazon.com/sdkref/latest/guide/standardized-credentials.html),
|
permissions:
|
||||||
and at the end, exports environment variables for you to use later.
|
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
|
Security Recommendations
|
||||||
you use GitHub's OIDC provider in conjunction with a configured AWS IAM
|
------------------------
|
||||||
Identity Provider endpoint.
|
* 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
|
1. Use a `core.getIDToken()` call to authenticate via OIDC.
|
||||||
|
2. Re-export existing long-lived IAM credentials (access key ID and secret
|
||||||
Some of this documentation may be inaccurate if you are using GHES (GitHub
|
access key) as environment variables.
|
||||||
Enterprise Server), please take note to review the GitHub documentation when
|
3. Use static credentials stored in GitHub Secrets to fetch temporary
|
||||||
relevant.
|
credentials via STS AssumeRole.
|
||||||
|
4. Use a Web Identity Token to fetch temporary credentials via STS
|
||||||
For example, the URL that the OIDC JWT is issued from is different than the
|
AssumeRoleWithWebIdentity.
|
||||||
usual `token.actions.githubusercontent.com`, and will be unique to your
|
5. Use credentials stored in the Action environment to fetch temporary
|
||||||
enterprise server. As a result, you will need to configure this differently when
|
credentials via STS AssumeRole.
|
||||||
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`)
|
|
||||||
|
|
||||||
Because we use the AWS JavaScript SDK, we always will use the [credential
|
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).
|
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.
|
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).
|
<details>
|
||||||
This method uses OIDC to get short-lived credentials needed for your actions.
|
<summary>Inputs and their effects on the credential resolution flow</summary>
|
||||||
See [OIDC](#OIDC) for more information on how to setup your AWS account to
|
|
||||||
assume a role with OIDC.
|
|
||||||
|
|
||||||
The following table describes which method we'll use to get your credentials
|
| **Identity Used** | `aws-access-key-id` | `role-to-assume` | `web-identity-token-file` | `role-chaining` |
|
||||||
based on which values are supplied to the Action:
|
| ---------------------------------------- | ------------------- | ---------------- | ------------------------- | --------------- |
|
||||||
|
| [✅ Recommended] GitHub OIDC | | ✔ | | |
|
||||||
| **Identity Used** | `aws-access-key-id` | `role-to-assume` | `web-identity-token-file` | `role-chaining` | `id-token` permission
|
| IAM User (no AssumeRole) | ✔ | | | |
|
||||||
| --------------------------------------------------------------- | ------------------- | ---------------- | ------------------------- | - | - |
|
| AssumeRole using static IAM credentials | ✔ | ✔ | | |
|
||||||
| [✅ Recommended] Assume Role directly using GitHub OIDC provider | | ✔ | | | ✔ |
|
| AssumeWithWebIdentity use a token file | | ✔ | ✔ | |
|
||||||
| IAM User | ✔ | | | | |
|
| AssumeRole using existing credentials | | ✔ | | ✔ |
|
||||||
| Assume Role using IAM User credentials | ✔ | ✔ | | | |
|
|
||||||
| Assume Role using WebIdentity Token File credentials | | ✔ | ✔ | | |
|
|
||||||
| Assume Role using existing credentials | | ✔ | | ✔ | |
|
|
||||||
|
|
||||||
*Note: `role-chaining` is not always necessary to use existing credentials.
|
*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,
|
If you're getting a "Credentials loaded by the SDK do not match" error,
|
||||||
try enabling this option.*
|
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
|
### Options
|
||||||
See [action.yml](./action.yml) for more detail.
|
See [action.yml](./action.yml) for more detail.
|
||||||
|
<details>
|
||||||
|
<summary>Options list and descriptions</summary>
|
||||||
|
|
||||||
| Option | Description | Required |
|
| Option | Description | Required |
|
||||||
|---------------------------|---------------------------------------------------------------------------------------------------|----------|
|
|---------------------------|---------------------------------------------------------------------------------------------------|----------|
|
||||||
@@ -105,33 +137,82 @@ See [action.yml](./action.yml) for more detail.
|
|||||||
| audience | The JWT audience when using OIDC. Used in non-default AWS partitions, like China regions. | No |
|
| audience | The JWT audience when using OIDC. Used in non-default AWS partitions, like China regions. | No |
|
||||||
| http-proxy | An HTTP proxy to use for API calls. | No |
|
| http-proxy | An HTTP proxy to use for API calls. | No |
|
||||||
| mask-aws-account-id | AWS account IDs are not considered secret. Setting this will hide account IDs from output anyway. | No |
|
| mask-aws-account-id | AWS account IDs are not considered secret. Setting this will hide account IDs from output anyway. | No |
|
||||||
| role-duration-seconds | The assumed role duration in seconds, if assuming a role. Defaults to 1 hour. | No |
|
| role-duration-seconds | The assumed role duration in seconds, if assuming a role. Defaults to 1 hour (3600 seconds). Acceptable values range from 15 minutes (900 seconds) to 12 hours (43200 seconds). | No |
|
||||||
| role-external-id | The external ID of the role to assume. Only needed if your role requires it. | No |
|
| role-external-id | The external ID of the role to assume. Only needed if your role requires it. | No |
|
||||||
| role-session-name | Defaults to "GitHubActions", but may be changed if required. | No |
|
| role-session-name | Defaults to "GitHubActions", but may be changed if required. | No |
|
||||||
| role-skip-session-tagging | Skips session tagging if set. | No |
|
| role-skip-session-tagging | Skips session tagging if set. | No |
|
||||||
| inline-session-policy | You may further restrict the assumed role policy by defining an inline policy here. | No |
|
| 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 |
|
| 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. 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 |
|
| 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 |
|
| 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 |
|
| 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 |
|
| 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 |
|
| 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
|
#### Adjust the retry mechanism
|
||||||
The default session duration is **1 hour**.
|
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
|
#### Mask account ID
|
||||||
`role-duration-seconds`, but the duration cannot exceed the maximum that was
|
Your account ID is not masked by default in workflow logs. You can set the
|
||||||
defined when the IAM Role was created.
|
`mask-aws-account-id` input to `true` to mask your account ID in workflow logs
|
||||||
|
if desired.
|
||||||
|
|
||||||
#### External ID
|
#### Unset current credentials
|
||||||
If your role requires an external ID to assume, you can provide the external ID
|
Sometimes, existing credentials in your runner can get in the way of the
|
||||||
with the `role-external-id` input
|
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 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
|
the desired name in `role-session-name`.
|
||||||
|
|
||||||
|
*Note: you might find it helpful to set the `role-session-name` to `${{ github.run_id }}`
|
||||||
|
so as to clarify in audit logs which AWS actions were performed by which workflow
|
||||||
|
run.*
|
||||||
|
|
||||||
|
The session will be tagged with the
|
||||||
following tags: (Refer to [GitHub's documentation for `GITHUB_` environment
|
following tags: (Refer to [GitHub's documentation for `GITHUB_` environment
|
||||||
variable definitions](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/using-environment-variables#default-environment-variables))
|
variable definitions](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/using-environment-variables#default-environment-variables))
|
||||||
|
|
||||||
@@ -151,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
|
`GITHUB_ACTOR` or `GITHUB_WORKFLOW` contain invalid characters, the characters
|
||||||
will be replaced with an '*'._
|
will be replaced with an '*'._
|
||||||
|
|
||||||
The action will use session tagging by default during role assumption, unless
|
The action will use session tagging by default unless you are using OIDC.
|
||||||
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
|
|
||||||
```
|
|
||||||
|
|
||||||
### Session policies
|
### Session policies
|
||||||
Session policies are not required, but they allow you to limit the scope of the
|
Session policies are not required, but they allow you to limit the scope of the
|
||||||
@@ -176,15 +243,19 @@ session policy by its ARN.
|
|||||||
#### Inline session policies
|
#### Inline session policies
|
||||||
An IAM policy in stringified JSON format that you want to use as an inline
|
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
|
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
|
```yaml
|
||||||
uses: aws-actions/configure-aws-credentials@v4
|
uses: aws-actions/configure-aws-credentials@v4.2.1
|
||||||
with:
|
with:
|
||||||
inline-session-policy: '{"Version":"2012-10-17","Statement":[{"Sid":"Stmt1","Effect":"Allow","Action":"s3:List*","Resource":"*"}]}'
|
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:
|
Or we can have a nicely formatted JSON as well:
|
||||||
```yaml
|
```yaml
|
||||||
uses: aws-actions/configure-aws-credentials@v4
|
uses: aws-actions/configure-aws-credentials@v4.2.1
|
||||||
with:
|
with:
|
||||||
inline-session-policy: >-
|
inline-session-policy: >-
|
||||||
{
|
{
|
||||||
@@ -199,56 +270,33 @@ Or we can have a nicely formatted JSON as well:
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
</details>
|
||||||
|
|
||||||
#### Managed session policies
|
#### Managed session policies
|
||||||
The Amazon Resource Names (ARNs) of the IAM managed policies that you want to
|
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
|
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
|
```yaml
|
||||||
uses: aws-actions/configure-aws-credentials@v4
|
uses: aws-actions/configure-aws-credentials@v4.2.1
|
||||||
with:
|
with:
|
||||||
managed-session-policies: arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
|
managed-session-policies: arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
|
||||||
```
|
```
|
||||||
And we can pass multiple managed policies likes this:
|
And we can pass multiple managed policies likes this:
|
||||||
```yaml
|
```yaml
|
||||||
uses: aws-actions/configure-aws-credentials@v4
|
uses: aws-actions/configure-aws-credentials@v4.2.1
|
||||||
with:
|
with:
|
||||||
managed-session-policies: |
|
managed-session-policies: |
|
||||||
arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
|
arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
|
||||||
arn:aws:iam::aws:policy/AmazonS3OutpostsReadOnlyAccess
|
arn:aws:iam::aws:policy/AmazonS3OutpostsReadOnlyAccess
|
||||||
```
|
```
|
||||||
|
</details>
|
||||||
|
|
||||||
### Misc
|
OIDC Configuration
|
||||||
|
-------------------
|
||||||
#### Adjust the retry mechanism
|
|
||||||
You can now configure retry settings for when the STS call fails. By default, we
|
|
||||||
retry with exponential backoff `12` times. You can disable this behavior
|
|
||||||
altogether by setting the `disable-retry` input to `true`, or you can configure
|
|
||||||
the number of times it retries with the `retry-max-attempts` input.
|
|
||||||
|
|
||||||
#### Mask account ID
|
|
||||||
Your account ID is not masked by default in workflow logs since it's not
|
|
||||||
considered sensitive information. However, you can set the `mask-aws-account-id`
|
|
||||||
input to `true` to mask your account ID in workflow logs if desired.
|
|
||||||
|
|
||||||
#### Unset current credentials
|
|
||||||
Sometimes, existing credentials in your runner can get in the way of the
|
|
||||||
intended outcome. You can set the `unset-current-credentials` input to `true` to
|
|
||||||
work around this issue.
|
|
||||||
|
|
||||||
#### Special characters in AWS_SECRET_ACCESS_KEY
|
|
||||||
Some edge cases are unable to properly parse an `AWS_SECRET_ACCESS_KEY` if it
|
|
||||||
contains special characters. For more information, please see the
|
|
||||||
[AWS CLI documentation](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-troubleshooting.html#tshoot-signature-does-not-match).
|
|
||||||
If you set the `special-characters-workaround` option, this action will
|
|
||||||
continually retry fetching credentials until we get one that does not have
|
|
||||||
special characters. This option overrides the `disable-retry` and
|
|
||||||
`retry-max-attempts` options. We recommend that you do not enable this option
|
|
||||||
unless required, because retrying APIs infinitely until they succeed is not best
|
|
||||||
practice.
|
|
||||||
|
|
||||||
## OIDC
|
|
||||||
|
|
||||||
We recommend using [GitHub's OIDC
|
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)
|
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
|
to get short-lived AWS credentials needed for your actions. When using OIDC, you
|
||||||
@@ -267,15 +315,6 @@ To get this to work
|
|||||||
|
|
||||||
5. Specify that role's ARN when setting up this action.
|
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
|
### OIDC Audience
|
||||||
|
|
||||||
When the JWT is created, an audience needs to be specified. Normally, you would
|
When the JWT is created, an audience needs to be specified. Normally, you would
|
||||||
@@ -286,83 +325,33 @@ You can specify the audience through the `audience` input:
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- name: Configure AWS Credentials for China region audience
|
- name: Configure AWS Credentials for China region audience
|
||||||
uses: aws-actions/configure-aws-credentials@v4
|
uses: aws-actions/configure-aws-credentials@v4.2.1
|
||||||
with:
|
with:
|
||||||
audience: sts.amazonaws.com.cn
|
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
|
role-to-assume: arn:aws-cn:iam::123456789100:role/my-github-actions-role
|
||||||
```
|
```
|
||||||
|
|
||||||
### Configuring IAM to trust GitHub
|
### Configuring IAM to trust GitHub
|
||||||
To use GitHub's OIDC provider, you must first set up federation
|
To use GitHub's OIDC provider, you must first set up federation in your AWS
|
||||||
with the provider as an IAM IdP. The GitHub OIDC provider only needs to be
|
account. This involves creating an IAM Identity Provider that trusts GitHub's
|
||||||
created once per account (i.e. multiple IAM Roles that can be assumed by the
|
OIDC endpoint. You can create an IAM Identity Provider in the AWS Management
|
||||||
GitHub's OIDC can share a single OIDC Provider). Here is a sample CloudFormation
|
Console by specifying the following details:
|
||||||
template that will configure this trust for you.
|
- **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
|
Prior versions of this documentation gave instructions for specifying the
|
||||||
not used when authenticating `token.actions.githubusercontent.com`. This is a
|
certificate fingerprint, but this is no longer necessary. The thumbprint, if
|
||||||
special case used *only when GitHub's OIDC is authenticating to IAM*. IAM uses
|
specified, will be ignored.
|
||||||
its library of trusted CAs to authenticate. The value is still the API, so it
|
|
||||||
must be specified.
|
|
||||||
|
|
||||||
You can copy the template below, or load it from here:
|
You can also create the IAM Identity Provider using the AWS CLI:
|
||||||
https://d38mtn6aq9zhn6.cloudfront.net/configure-aws-credentials-latest.yml
|
|
||||||
|
|
||||||
```yaml
|
```bash
|
||||||
Parameters:
|
aws iam create-open-id-connect-provider \
|
||||||
GitHubOrg:
|
--url https://token.actions.githubusercontent.com \
|
||||||
Description: Name of GitHub organization/user (case sensitive)
|
--client-id-list sts.amazonaws.com
|
||||||
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
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Claims and scoping permissions
|
### Claims and scoping permissions
|
||||||
@@ -404,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 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/)
|
* [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
|
### AssumeRoleWithWebIdentity
|
||||||
[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
|
|
||||||
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
|
|
||||||
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
|
|
||||||
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)
|
|
||||||
```yaml
|
```yaml
|
||||||
- name: Configure AWS Credentials
|
- name: Configure AWS Credentials
|
||||||
uses: aws-actions/configure-aws-credentials@v4
|
uses: aws-actions/configure-aws-credentials@v4.2.1
|
||||||
with:
|
with:
|
||||||
aws-region: us-east-2
|
aws-region: us-east-2
|
||||||
role-to-assume: arn:aws:iam::123456789100:role/my-github-actions-role
|
role-to-assume: arn:aws:iam::123456789100:role/my-github-actions-role
|
||||||
@@ -494,13 +413,13 @@ environment variable and use it to assume the role
|
|||||||
### AssumeRole with role previously assumed by action in same workflow
|
### AssumeRole with role previously assumed by action in same workflow
|
||||||
```yaml
|
```yaml
|
||||||
- name: Configure AWS Credentials
|
- name: Configure AWS Credentials
|
||||||
uses: aws-actions/configure-aws-credentials@v4
|
uses: aws-actions/configure-aws-credentials@v4.2.1
|
||||||
with:
|
with:
|
||||||
aws-region: us-east-2
|
aws-region: us-east-2
|
||||||
role-to-assume: arn:aws:iam::123456789100:role/my-github-actions-role
|
role-to-assume: arn:aws:iam::123456789100:role/my-github-actions-role
|
||||||
role-session-name: MySessionName
|
role-session-name: MySessionName
|
||||||
- name: Configure other AWS Credentials
|
- name: Configure other AWS Credentials
|
||||||
uses: aws-actions/configure-aws-credentials@v4
|
uses: aws-actions/configure-aws-credentials@v4.2.1
|
||||||
with:
|
with:
|
||||||
aws-region: us-east-2
|
aws-region: us-east-2
|
||||||
role-to-assume: arn:aws:iam::987654321000:role/my-second-role
|
role-to-assume: arn:aws:iam::987654321000:role/my-second-role
|
||||||
@@ -515,7 +434,7 @@ role, `arn:aws:iam::987654321000:role/my-second-role`.
|
|||||||
### AssumeRole with static IAM credentials in repository secrets
|
### AssumeRole with static IAM credentials in repository secrets
|
||||||
```yaml
|
```yaml
|
||||||
- name: Configure AWS Credentials
|
- name: Configure AWS Credentials
|
||||||
uses: aws-actions/configure-aws-credentials@v4
|
uses: aws-actions/configure-aws-credentials@v4.2.1
|
||||||
with:
|
with:
|
||||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||||
@@ -534,7 +453,7 @@ name, like `role-to-assume: my-github-actions-role`.
|
|||||||
```yaml
|
```yaml
|
||||||
- name: Configure AWS Credentials 1
|
- name: Configure AWS Credentials 1
|
||||||
id: creds
|
id: creds
|
||||||
uses: aws-actions/configure-aws-credentials@v4
|
uses: aws-actions/configure-aws-credentials@v4.2.1
|
||||||
with:
|
with:
|
||||||
aws-region: us-east-2
|
aws-region: us-east-2
|
||||||
role-to-assume: arn:aws:iam::123456789100:role/my-github-actions-role
|
role-to-assume: arn:aws:iam::123456789100:role/my-github-actions-role
|
||||||
@@ -543,7 +462,7 @@ name, like `role-to-assume: my-github-actions-role`.
|
|||||||
run: |
|
run: |
|
||||||
aws sts get-caller-identity
|
aws sts get-caller-identity
|
||||||
- name: Configure AWS Credentials 2
|
- name: Configure AWS Credentials 2
|
||||||
uses: aws-actions/configure-aws-credentials@v4
|
uses: aws-actions/configure-aws-credentials@v4.2.1
|
||||||
with:
|
with:
|
||||||
aws-region: us-east-2
|
aws-region: us-east-2
|
||||||
aws-access-key-id: ${{ steps.creds.outputs.aws-access-key-id }}
|
aws-access-key-id: ${{ steps.creds.outputs.aws-access-key-id }}
|
||||||
@@ -558,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
|
`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
|
the `aws-session-token` input in a situation where session tokens are fetched
|
||||||
and passed to this action.
|
and passed to this action.
|
||||||
|
|
||||||
## License Summary
|
License
|
||||||
|
-------
|
||||||
This code is made available under the MIT 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
|
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
|
do not create a GitHub issue. Instead, please follow the instructions
|
||||||
[here](https://aws.amazon.com/security/vulnerability-reporting/) or [email AWS
|
[here](https://aws.amazon.com/security/vulnerability-reporting/) or
|
||||||
security directly](mailto:aws-security@amazon.com).
|
[email AWS security](mailto:aws-security@amazon.com) directly.
|
||||||
|
|||||||
+2
-2
@@ -1,2 +1,2 @@
|
|||||||
const { fs } = require('memfs')
|
const { fs } = require('memfs');
|
||||||
module.exports = fs
|
module.exports = fs;
|
||||||
|
|||||||
@@ -61,6 +61,10 @@ inputs:
|
|||||||
output-credentials:
|
output-credentials:
|
||||||
description: Whether to set credentials as step output
|
description: Whether to set credentials as step output
|
||||||
required: false
|
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:
|
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
|
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
|
required: false
|
||||||
@@ -84,3 +88,5 @@ outputs:
|
|||||||
description: The AWS secret access key for the provided credentials
|
description: The AWS secret access key for the provided credentials
|
||||||
aws-session-token:
|
aws-session-token:
|
||||||
description: The AWS session token for the provided credentials
|
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,
|
"lineWidth": 120,
|
||||||
"indentWidth": 2,
|
"indentWidth": 2,
|
||||||
"lineEnding": "lf",
|
"lineEnding": "lf",
|
||||||
"enabled": true,
|
"enabled": true
|
||||||
},
|
},
|
||||||
"linter": {
|
"linter": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"rules": {
|
"rules": {
|
||||||
"performance": {
|
"performance": {
|
||||||
"noDelete": "off",
|
"noDelete": "off"
|
||||||
},
|
},
|
||||||
"complexity": {
|
"complexity": {
|
||||||
"noExtraBooleanCast": "off",
|
"noExtraBooleanCast": "off"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
"javascript": {
|
"javascript": {
|
||||||
"formatter": {
|
"formatter": {
|
||||||
@@ -23,12 +23,12 @@
|
|||||||
"jsxQuoteStyle": "double",
|
"jsxQuoteStyle": "double",
|
||||||
"quoteStyle": "single",
|
"quoteStyle": "single",
|
||||||
"bracketSpacing": true,
|
"bracketSpacing": true,
|
||||||
"arrowParentheses": "always",
|
"arrowParentheses": "always"
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
"json": {
|
"json": {
|
||||||
"formatter": {
|
"formatter": {
|
||||||
"trailingCommas": "all",
|
"trailingCommas": "none"
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
-14
@@ -1,14 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
||||||
-17
@@ -1,17 +0,0 @@
|
|||||||
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?: {
|
|
||||||
arn: string;
|
|
||||||
}[];
|
|
||||||
}
|
|
||||||
export declare function assumeRole(params: assumeRoleParams): Promise<import("@aws-sdk/client-sts").AssumeRoleCommandOutput>;
|
|
||||||
-11
@@ -1,11 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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;
|
|
||||||
-17
@@ -1,17 +0,0 @@
|
|||||||
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): boolean;
|
|
||||||
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 declare function areCredentialsValid(credentialsClient: CredentialsClient): Promise<boolean>;
|
|
||||||
export {};
|
|
||||||
-1
@@ -1 +0,0 @@
|
|||||||
export declare function run(): Promise<void>;
|
|
||||||
+5124
-3322
File diff suppressed because one or more lines are too long
-14
@@ -1,14 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
||||||
-17
@@ -1,17 +0,0 @@
|
|||||||
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?: {
|
|
||||||
arn: string;
|
|
||||||
}[];
|
|
||||||
}
|
|
||||||
export declare function assumeRole(params: assumeRoleParams): Promise<import("@aws-sdk/client-sts").AssumeRoleCommandOutput>;
|
|
||||||
-11
@@ -1,11 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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
@@ -1,16 +0,0 @@
|
|||||||
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): boolean;
|
|
||||||
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
@@ -1 +0,0 @@
|
|||||||
export declare function run(): Promise<void>;
|
|
||||||
-1
@@ -1 +0,0 @@
|
|||||||
export {};
|
|
||||||
-1
@@ -1 +0,0 @@
|
|||||||
export {};
|
|
||||||
-1
@@ -1 +0,0 @@
|
|||||||
export {};
|
|
||||||
-74
@@ -1,74 +0,0 @@
|
|||||||
import type * as core from '@actions/core';
|
|
||||||
declare const _default: {
|
|
||||||
readonly outputs: {
|
|
||||||
STS_CREDENTIALS: {
|
|
||||||
Credentials: {
|
|
||||||
AccessKeyId: string;
|
|
||||||
SecretAccessKey: string;
|
|
||||||
SessionToken: string;
|
|
||||||
Expiration: Date;
|
|
||||||
};
|
|
||||||
AssumedRoleUser: {
|
|
||||||
Arn: string;
|
|
||||||
AssumedRoleId: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
GET_CALLER_IDENTITY: {
|
|
||||||
Account: string;
|
|
||||||
Arn: string;
|
|
||||||
};
|
|
||||||
FAKE_STS_ACCESS_KEY_ID: string;
|
|
||||||
FAKE_STS_SECRET_ACCESS_KEY: string;
|
|
||||||
FAKE_STS_SESSION_TOKEN: string;
|
|
||||||
ODD_CHARACTER_CREDENTIALS: {
|
|
||||||
Credentials: {
|
|
||||||
AccessKeyId: string;
|
|
||||||
SecretAccessKey: string;
|
|
||||||
SessionToken: string;
|
|
||||||
Expiration: Date;
|
|
||||||
};
|
|
||||||
AssumedRoleUser: {
|
|
||||||
Arn: string;
|
|
||||||
AssumedRoleId: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
readonly envs: {
|
|
||||||
GITHUB_REPOSITORY: string;
|
|
||||||
GITHUB_WORKFLOW: string;
|
|
||||||
GITHUB_ACTION: string;
|
|
||||||
GITHUB_ACTOR: string;
|
|
||||||
GITHUB_SHA: string;
|
|
||||||
GITHUB_WORKSPACE: string;
|
|
||||||
GITHUB_ACTIONS: string;
|
|
||||||
};
|
|
||||||
readonly GH_OIDC_INPUTS: {
|
|
||||||
'role-to-assume': string;
|
|
||||||
'aws-region': string;
|
|
||||||
'special-characters-workaround': string;
|
|
||||||
};
|
|
||||||
readonly IAM_USER_INPUTS: {
|
|
||||||
'aws-access-key-id': string;
|
|
||||||
'aws-secret-access-key': string;
|
|
||||||
'aws-region': string;
|
|
||||||
};
|
|
||||||
readonly IAM_ASSUMEROLE_INPUTS: {
|
|
||||||
'aws-access-key-id': string;
|
|
||||||
'aws-secret-access-key': string;
|
|
||||||
'role-to-assume': string;
|
|
||||||
'aws-region': string;
|
|
||||||
};
|
|
||||||
readonly WEBIDENTITY_TOKEN_FILE_INPUTS: {
|
|
||||||
'web-identity-token-file': string;
|
|
||||||
'role-to-assume': string;
|
|
||||||
'aws-region': string;
|
|
||||||
};
|
|
||||||
readonly EXISTING_ROLE_INPUTS: {
|
|
||||||
'role-to-assume': string;
|
|
||||||
'role-chaining': string;
|
|
||||||
'aws-region': string;
|
|
||||||
};
|
|
||||||
readonly getInput: (fakeEnv: Record<string, string>) => (name: string, options?: core.InputOptions) => string;
|
|
||||||
readonly getMultilineInput: (fakeEnv: Record<string, string[]>) => (name: string, options?: core.InputOptions) => string[];
|
|
||||||
};
|
|
||||||
export default _default;
|
|
||||||
+5603
-3741
File diff suppressed because one or more lines are too long
Generated
+1278
-976
File diff suppressed because it is too large
Load Diff
+15
-13
@@ -1,12 +1,14 @@
|
|||||||
{
|
{
|
||||||
"name": "configure-aws-credentials",
|
"name": "configure-aws-credentials",
|
||||||
"description": "A GitHub Action to configure AWS credentials",
|
"description": "A GitHub Action to configure AWS credentials",
|
||||||
"version": "4.1.0",
|
"version": "4.3.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
"lint": "biome check --error-on-warnings ./src",
|
"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",
|
"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"
|
"test": "npm run lint && vitest run && npm run build",
|
||||||
|
"clean": "del-cli coverage test-reports node_modules"
|
||||||
},
|
},
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Amazon.com, Inc. or its affiliates",
|
"name": "Amazon.com, Inc. or its affiliates",
|
||||||
@@ -14,26 +16,26 @@
|
|||||||
"organization": true
|
"organization": true
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@aws-sdk/credential-provider-env": "^3.515.0",
|
"@aws-sdk/credential-provider-env": "^3.858.0",
|
||||||
"@biomejs/biome": "1.9.4",
|
"@biomejs/biome": "2.1.3",
|
||||||
"@smithy/property-provider": "^4.0.1",
|
"@smithy/property-provider": "^4.0.3",
|
||||||
"@types/node": "^22.13.1",
|
"@types/node": "^24.1.0",
|
||||||
"@vercel/ncc": "^0.38.3",
|
"@vercel/ncc": "^0.38.3",
|
||||||
"@vitest/coverage-v8": "^2.1.9",
|
"@vitest/coverage-v8": "^3.2.4",
|
||||||
"aws-sdk-client-mock": "^4.1.0",
|
"aws-sdk-client-mock": "^4.1.0",
|
||||||
"cpy-cli": "^5.0.0",
|
"cpy-cli": "^5.0.0",
|
||||||
"del-cli": "^6.0.0",
|
"del-cli": "^6.0.0",
|
||||||
"json-schema": "^0.4.0",
|
"json-schema": "^0.4.0",
|
||||||
"memfs": "^4.17.0",
|
"memfs": "^4.25.1",
|
||||||
"standard-version": "^9.5.0",
|
"standard-version": "^9.5.0",
|
||||||
"typescript": "^5.7.3",
|
"typescript": "^5.8.3",
|
||||||
"vitest": "^2.1.9"
|
"vitest": "^3.2.4"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.11.1",
|
"@actions/core": "^1.11.1",
|
||||||
"@aws-sdk/client-sts": "^3.741.0",
|
"@aws-sdk/client-sts": "^3.858.0",
|
||||||
"@smithy/node-http-handler": "^4.0.1",
|
"@smithy/node-http-handler": "^4.1.0",
|
||||||
"https-proxy-agent": "^5.0.1"
|
"https-proxy-agent": "^7.0.6"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"aws",
|
"aws",
|
||||||
|
|||||||
@@ -142,7 +142,6 @@ export async function assumeRole(params: assumeRoleParams) {
|
|||||||
PolicyArns: managedSessionPolicies?.length ? managedSessionPolicies : undefined,
|
PolicyArns: managedSessionPolicies?.length ? managedSessionPolicies : undefined,
|
||||||
};
|
};
|
||||||
const keys = Object.keys(commonAssumeRoleParams) as Array<keyof typeof commonAssumeRoleParams>;
|
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]);
|
keys.forEach((k) => commonAssumeRoleParams[k] === undefined && delete commonAssumeRoleParams[k]);
|
||||||
|
|
||||||
// Instantiate STS client
|
// Instantiate STS client
|
||||||
|
|||||||
+15
-12
@@ -13,18 +13,21 @@ import { errorMessage } from '../helpers';
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export function cleanup() {
|
export function cleanup() {
|
||||||
try {
|
const outputEnvCredentialsInput = core.getInput('output-env-credentials', { required: false }) || 'true';
|
||||||
// The GitHub Actions toolkit does not have an option to completely unset
|
if (outputEnvCredentialsInput === 'true') {
|
||||||
// environment variables, so we overwrite the current value with an empty
|
try {
|
||||||
// string. The AWS CLI and AWS SDKs will behave correctly: they treat an
|
// The GitHub Actions toolkit does not have an option to completely unset
|
||||||
// empty string value as if the environment variable does not exist.
|
// environment variables, so we overwrite the current value with an empty
|
||||||
core.exportVariable('AWS_ACCESS_KEY_ID', '');
|
// string. The AWS CLI and AWS SDKs will behave correctly: they treat an
|
||||||
core.exportVariable('AWS_SECRET_ACCESS_KEY', '');
|
// empty string value as if the environment variable does not exist.
|
||||||
core.exportVariable('AWS_SESSION_TOKEN', '');
|
core.exportVariable('AWS_ACCESS_KEY_ID', '');
|
||||||
core.exportVariable('AWS_DEFAULT_REGION', '');
|
core.exportVariable('AWS_SECRET_ACCESS_KEY', '');
|
||||||
core.exportVariable('AWS_REGION', '');
|
core.exportVariable('AWS_SESSION_TOKEN', '');
|
||||||
} catch (error) {
|
core.exportVariable('AWS_DEFAULT_REGION', '');
|
||||||
core.setFailed(errorMessage(error));
|
core.exportVariable('AWS_REGION', '');
|
||||||
|
} catch (error) {
|
||||||
|
core.setFailed(errorMessage(error));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* c8 ignore start */
|
/* c8 ignore start */
|
||||||
|
|||||||
+76
-19
@@ -7,25 +7,73 @@ const MAX_TAG_VALUE_LENGTH = 256;
|
|||||||
const SANITIZATION_CHARACTER = '_';
|
const SANITIZATION_CHARACTER = '_';
|
||||||
const SPECIAL_CHARS_REGEX = /[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]+/;
|
const SPECIAL_CHARS_REGEX = /[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]+/;
|
||||||
|
|
||||||
|
export function translateEnvVariables() {
|
||||||
|
const envVars = [
|
||||||
|
'AWS_REGION',
|
||||||
|
'ROLE_TO_ASSUME',
|
||||||
|
'WEB_IDENTITY_TOKEN_FILE',
|
||||||
|
'ROLE_CHAINING',
|
||||||
|
'AUDIENCE',
|
||||||
|
'HTTP_PROXY',
|
||||||
|
'MASK_AWS_ACCOUNT_ID',
|
||||||
|
'ROLE_DURATION_SECONDS',
|
||||||
|
'ROLE_EXTERNAL_ID',
|
||||||
|
'ROLE_SESSION_NAME',
|
||||||
|
'ROLE_SKIP_SESSION_TAGGING',
|
||||||
|
'INLINE_SESSION_POLICY',
|
||||||
|
'MANAGED_SESSION_POLICIES',
|
||||||
|
'OUTPUT_CREDENTIALS',
|
||||||
|
'UNSET_CURRENT_CREDENTIALS',
|
||||||
|
'DISABLE_RETRY',
|
||||||
|
'RETRY_MAX_ATTEMPTS',
|
||||||
|
'SPECIAL_CHARACTERS_WORKAROUND',
|
||||||
|
'USE_EXISTING_CREDENTIALS',
|
||||||
|
];
|
||||||
|
// 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]) {
|
||||||
|
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.
|
// 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
|
// 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) {
|
if (creds?.AccessKeyId) {
|
||||||
core.setSecret(creds.AccessKeyId);
|
core.setSecret(creds.AccessKeyId);
|
||||||
core.exportVariable('AWS_ACCESS_KEY_ID', creds.AccessKeyId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (creds?.SecretAccessKey) {
|
if (creds?.SecretAccessKey) {
|
||||||
core.setSecret(creds.SecretAccessKey);
|
core.setSecret(creds.SecretAccessKey);
|
||||||
core.exportVariable('AWS_SECRET_ACCESS_KEY', creds.SecretAccessKey);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (creds?.SessionToken) {
|
if (creds?.SessionToken) {
|
||||||
core.setSecret(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
|
if (outputEnvCredentials) {
|
||||||
core.exportVariable('AWS_SESSION_TOKEN', '');
|
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) {
|
if (outputCredentials) {
|
||||||
@@ -38,20 +86,27 @@ export function exportCredentials(creds?: Partial<Credentials>, outputCredential
|
|||||||
if (creds?.SessionToken) {
|
if (creds?.SessionToken) {
|
||||||
core.setOutput('aws-session-token', creds.SessionToken);
|
core.setOutput('aws-session-token', creds.SessionToken);
|
||||||
}
|
}
|
||||||
|
if (creds?.Expiration) {
|
||||||
|
core.setOutput('aws-expiration', creds.Expiration);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function unsetCredentials() {
|
export function unsetCredentials(outputEnvCredentials?: boolean) {
|
||||||
core.exportVariable('AWS_ACCESS_KEY_ID', '');
|
if (outputEnvCredentials) {
|
||||||
core.exportVariable('AWS_SECRET_ACCESS_KEY', '');
|
core.exportVariable('AWS_ACCESS_KEY_ID', '');
|
||||||
core.exportVariable('AWS_SESSION_TOKEN', '');
|
core.exportVariable('AWS_SECRET_ACCESS_KEY', '');
|
||||||
core.exportVariable('AWS_REGION', '');
|
core.exportVariable('AWS_SESSION_TOKEN', '');
|
||||||
core.exportVariable('AWS_DEFAULT_REGION', '');
|
core.exportVariable('AWS_REGION', '');
|
||||||
|
core.exportVariable('AWS_DEFAULT_REGION', '');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function exportRegion(region: string) {
|
export function exportRegion(region: string, outputEnvCredentials?: boolean) {
|
||||||
core.exportVariable('AWS_DEFAULT_REGION', region);
|
if (outputEnvCredentials) {
|
||||||
core.exportVariable('AWS_REGION', region);
|
core.exportVariable('AWS_DEFAULT_REGION', region);
|
||||||
|
core.exportVariable('AWS_REGION', region);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obtains account ID from STS Client and sets it as output
|
// Obtains account ID from STS Client and sets it as output
|
||||||
@@ -59,13 +114,16 @@ export async function exportAccountId(credentialsClient: CredentialsClient, mask
|
|||||||
const client = credentialsClient.stsClient;
|
const client = credentialsClient.stsClient;
|
||||||
const identity = await client.send(new GetCallerIdentityCommand({}));
|
const identity = await client.send(new GetCallerIdentityCommand({}));
|
||||||
const accountId = identity.Account;
|
const accountId = identity.Account;
|
||||||
if (!accountId) {
|
const arn = identity.Arn;
|
||||||
throw new Error('Could not get Account ID from STS. Did you set credentials?');
|
if (!accountId || !arn) {
|
||||||
|
throw new Error('Could not get Account ID or ARN from STS. Did you set credentials?');
|
||||||
}
|
}
|
||||||
if (maskAccountId) {
|
if (maskAccountId) {
|
||||||
core.setSecret(accountId);
|
core.setSecret(accountId);
|
||||||
|
core.setSecret(arn);
|
||||||
}
|
}
|
||||||
core.setOutput('aws-account-id', accountId);
|
core.setOutput('aws-account-id', accountId);
|
||||||
|
core.setOutput('authenticated-arn', arn);
|
||||||
return accountId;
|
return accountId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,7 +184,6 @@ export async function retryAndBackoff<T>(
|
|||||||
}
|
}
|
||||||
// It's retryable, so sleep and retry.
|
// It's retryable, so sleep and retry.
|
||||||
await sleep(Math.random() * (2 ** retries * base));
|
await sleep(Math.random() * (2 ** retries * base));
|
||||||
// biome-ignore lint/style/noParameterAssign: This is a loop variable
|
|
||||||
retries += 1;
|
retries += 1;
|
||||||
if (retries >= maxRetries) {
|
if (retries >= maxRetries) {
|
||||||
throw err;
|
throw err;
|
||||||
|
|||||||
+13
-7
@@ -1,7 +1,7 @@
|
|||||||
import * as core from '@actions/core';
|
import * as core from '@actions/core';
|
||||||
import type { AssumeRoleCommandOutput } from '@aws-sdk/client-sts';
|
import type { AssumeRoleCommandOutput } from '@aws-sdk/client-sts';
|
||||||
import { CredentialsClient } from './CredentialsClient';
|
|
||||||
import { assumeRole } from './assumeRole';
|
import { assumeRole } from './assumeRole';
|
||||||
|
import { CredentialsClient } from './CredentialsClient';
|
||||||
import {
|
import {
|
||||||
areCredentialsValid,
|
areCredentialsValid,
|
||||||
errorMessage,
|
errorMessage,
|
||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
exportCredentials,
|
exportCredentials,
|
||||||
exportRegion,
|
exportRegion,
|
||||||
retryAndBackoff,
|
retryAndBackoff,
|
||||||
|
translateEnvVariables,
|
||||||
unsetCredentials,
|
unsetCredentials,
|
||||||
verifyKeys,
|
verifyKeys,
|
||||||
} from './helpers';
|
} from './helpers';
|
||||||
@@ -19,6 +20,7 @@ const REGION_REGEX = /^[a-z0-9-]+$/g;
|
|||||||
|
|
||||||
export async function run() {
|
export async function run() {
|
||||||
try {
|
try {
|
||||||
|
translateEnvVariables();
|
||||||
// Get inputs
|
// Get inputs
|
||||||
const AccessKeyId = core.getInput('aws-access-key-id', { required: false });
|
const AccessKeyId = core.getInput('aws-access-key-id', { required: false });
|
||||||
const SecretAccessKey = core.getInput('aws-secret-access-key', {
|
const SecretAccessKey = core.getInput('aws-secret-access-key', {
|
||||||
@@ -44,7 +46,7 @@ export async function run() {
|
|||||||
const roleSessionName = core.getInput('role-session-name', { required: false }) || ROLE_SESSION_NAME;
|
const roleSessionName = core.getInput('role-session-name', { required: false }) || ROLE_SESSION_NAME;
|
||||||
const roleSkipSessionTaggingInput = core.getInput('role-skip-session-tagging', { required: false }) || 'false';
|
const roleSkipSessionTaggingInput = core.getInput('role-skip-session-tagging', { required: false }) || 'false';
|
||||||
const roleSkipSessionTagging = roleSkipSessionTaggingInput.toLowerCase() === 'true';
|
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', {
|
const inlineSessionPolicy = core.getInput('inline-session-policy', {
|
||||||
required: false,
|
required: false,
|
||||||
});
|
});
|
||||||
@@ -54,6 +56,8 @@ export async function run() {
|
|||||||
const roleChaining = roleChainingInput.toLowerCase() === 'true';
|
const roleChaining = roleChainingInput.toLowerCase() === 'true';
|
||||||
const outputCredentialsInput = core.getInput('output-credentials', { required: false }) || 'false';
|
const outputCredentialsInput = core.getInput('output-credentials', { required: false }) || 'false';
|
||||||
const outputCredentials = outputCredentialsInput.toLowerCase() === 'true';
|
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 unsetCurrentCredentialsInput = core.getInput('unset-current-credentials', { required: false }) || 'false';
|
||||||
const unsetCurrentCredentials = unsetCurrentCredentialsInput.toLowerCase() === 'true';
|
const unsetCurrentCredentials = unsetCurrentCredentialsInput.toLowerCase() === 'true';
|
||||||
const disableRetryInput = core.getInput('disable-retry', { required: false }) || 'false';
|
const disableRetryInput = core.getInput('disable-retry', { required: false }) || 'false';
|
||||||
@@ -106,13 +110,13 @@ export async function run() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (unsetCurrentCredentials) {
|
if (unsetCurrentCredentials) {
|
||||||
unsetCredentials();
|
unsetCredentials(outputEnvCredentials);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!region.match(REGION_REGEX)) {
|
if (!region.match(REGION_REGEX)) {
|
||||||
throw new Error(`Region is not valid: ${region}`);
|
throw new Error(`Region is not valid: ${region}`);
|
||||||
}
|
}
|
||||||
exportRegion(region);
|
exportRegion(region, outputEnvCredentials);
|
||||||
|
|
||||||
// Instantiate credentials client
|
// Instantiate credentials client
|
||||||
const credentialsClient = new CredentialsClient({ region, proxyServer });
|
const credentialsClient = new CredentialsClient({ region, proxyServer });
|
||||||
@@ -151,7 +155,7 @@ export async function run() {
|
|||||||
// Plus, in the assume role case, if the AssumeRole call fails, we want
|
// Plus, in the assume role case, if the AssumeRole call fails, we want
|
||||||
// the source credentials to already be masked as secrets
|
// the source credentials to already be masked as secrets
|
||||||
// in any error messages.
|
// in any error messages.
|
||||||
exportCredentials({ AccessKeyId, SecretAccessKey, SessionToken });
|
exportCredentials({ AccessKeyId, SecretAccessKey, SessionToken }, outputCredentials, outputEnvCredentials);
|
||||||
} else if (!webIdentityTokenFile && !roleChaining) {
|
} else if (!webIdentityTokenFile && !roleChaining) {
|
||||||
// Proceed only if credentials can be picked up
|
// Proceed only if credentials can be picked up
|
||||||
await credentialsClient.validateCredentials();
|
await credentialsClient.validateCredentials();
|
||||||
@@ -191,7 +195,7 @@ export async function run() {
|
|||||||
);
|
);
|
||||||
} while (specialCharacterWorkaround && !verifyKeys(roleCredentials.Credentials));
|
} while (specialCharacterWorkaround && !verifyKeys(roleCredentials.Credentials));
|
||||||
core.info(`Authenticated as assumedRoleId ${roleCredentials.AssumedRoleUser?.AssumedRoleId}`);
|
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
|
// We need to validate the credentials in 2 of our use-cases
|
||||||
// First: self-hosted runners. If the GITHUB_ACTIONS environment variable
|
// First: self-hosted runners. If the GITHUB_ACTIONS environment variable
|
||||||
// is set to `true` then we are NOT in a self-hosted runner.
|
// is set to `true` then we are NOT in a self-hosted runner.
|
||||||
@@ -199,7 +203,9 @@ export async function run() {
|
|||||||
if (!process.env.GITHUB_ACTIONS || AccessKeyId) {
|
if (!process.env.GITHUB_ACTIONS || AccessKeyId) {
|
||||||
await credentialsClient.validateCredentials(roleCredentials.Credentials?.AccessKeyId);
|
await credentialsClient.validateCredentials(roleCredentials.Credentials?.AccessKeyId);
|
||||||
}
|
}
|
||||||
await exportAccountId(credentialsClient, maskAccountId);
|
if (outputEnvCredentials) {
|
||||||
|
await exportAccountId(credentialsClient, maskAccountId);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
core.info('Proceeding with IAM user credentials');
|
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 * as core from '@actions/core';
|
||||||
import { mockClient } from 'aws-sdk-client-mock';
|
|
||||||
import { STSClient } from '@aws-sdk/client-sts';
|
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';
|
import mocks from './mockinputs.test';
|
||||||
|
|
||||||
const mockedSTSClient = mockClient(STSClient);
|
const mockedSTSClient = mockClient(STSClient);
|
||||||
@@ -45,4 +45,9 @@ describe('Configure AWS Credentials cleanup', {}, () => {
|
|||||||
cleanup();
|
cleanup();
|
||||||
expect(core.setFailed).toHaveBeenCalled();
|
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);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
+26
-7
@@ -1,7 +1,7 @@
|
|||||||
import { describe, it, expect, vi } from 'vitest';
|
import { beforeEach } from 'node:test';
|
||||||
import * as helpers from '../src/helpers';
|
|
||||||
import * as core from '@actions/core';
|
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', {}, () => {
|
describe('Configure AWS Credentials helpers', {}, () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@@ -11,9 +11,9 @@ describe('Configure AWS Credentials helpers', {}, () => {
|
|||||||
const actor = 'actor[bot]';
|
const actor = 'actor[bot]';
|
||||||
expect(helpers.sanitizeGitHubVariables(actor)).toBe('actor_bot_');
|
expect(helpers.sanitizeGitHubVariables(actor)).toBe('actor_bot_');
|
||||||
});
|
});
|
||||||
it('can sleep', {}, () => {
|
it('can sleep', {}, async () => {
|
||||||
const sleep = helpers.defaultSleep(10);
|
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', {}, () => {
|
it('removes special characters from workflow names', {}, () => {
|
||||||
expect(helpers.sanitizeGitHubVariables('sdf234@#$%$^&*()_+{}|:"<>?')).toEqual('sdf234@__________+___:____');
|
expect(helpers.sanitizeGitHubVariables('sdf234@#$%$^&*()_+{}|:"<>?')).toEqual('sdf234@__________+___:____');
|
||||||
@@ -27,8 +27,12 @@ describe('Configure AWS Credentials helpers', {}, () => {
|
|||||||
vi.spyOn(core, 'setOutput').mockImplementation(() => {});
|
vi.spyOn(core, 'setOutput').mockImplementation(() => {});
|
||||||
vi.spyOn(core, 'setSecret').mockImplementation(() => {});
|
vi.spyOn(core, 'setSecret').mockImplementation(() => {});
|
||||||
vi.spyOn(core, 'exportVariable').mockImplementation(() => {});
|
vi.spyOn(core, 'exportVariable').mockImplementation(() => {});
|
||||||
helpers.exportCredentials({ AccessKeyId: 'test', SecretAccessKey: 'test', SessionToken: 'test' }, true);
|
helpers.exportCredentials(
|
||||||
expect(core.setOutput).toHaveBeenCalledTimes(3);
|
{ AccessKeyId: 'test', SecretAccessKey: 'test', SessionToken: 'test', Expiration: new Date(8640000000000000) },
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
expect(core.setOutput).toHaveBeenCalledTimes(4);
|
||||||
expect(core.setSecret).toHaveBeenCalledTimes(3);
|
expect(core.setSecret).toHaveBeenCalledTimes(3);
|
||||||
expect(core.exportVariable).toHaveBeenCalledTimes(3);
|
expect(core.exportVariable).toHaveBeenCalledTimes(3);
|
||||||
});
|
});
|
||||||
@@ -42,4 +46,19 @@ describe('Configure AWS Credentials helpers', {}, () => {
|
|||||||
expect(process.env.AWS_DEFAULT_REGION).toBeUndefined;
|
expect(process.env.AWS_DEFAULT_REGION).toBeUndefined;
|
||||||
process.env = env;
|
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 {
|
import {
|
||||||
AssumeRoleCommand,
|
AssumeRoleCommand,
|
||||||
AssumeRoleWithWebIdentityCommand,
|
AssumeRoleWithWebIdentityCommand,
|
||||||
GetCallerIdentityCommand,
|
GetCallerIdentityCommand,
|
||||||
STSClient,
|
STSClient,
|
||||||
} from '@aws-sdk/client-sts';
|
} 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 { 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 { CredentialsClient } from '../src/CredentialsClient';
|
||||||
import { before } from 'node:test';
|
import { run } from '../src/index';
|
||||||
|
import mocks from './mockinputs.test';
|
||||||
|
|
||||||
const mockedSTSClient = mockClient(STSClient);
|
const mockedSTSClient = mockClient(STSClient);
|
||||||
|
|
||||||
@@ -48,7 +47,7 @@ describe('Configure AWS Credentials', {}, () => {
|
|||||||
expect(core.info).toHaveBeenCalledWith('Authenticated as assumedRoleId AROAFAKEASSUMEDROLEID');
|
expect(core.info).toHaveBeenCalledWith('Authenticated as assumedRoleId AROAFAKEASSUMEDROLEID');
|
||||||
expect(core.info).toHaveBeenCalledTimes(2);
|
expect(core.info).toHaveBeenCalledTimes(2);
|
||||||
expect(core.setOutput).toHaveBeenCalledWith('aws-account-id', '111111111111');
|
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('STSAWSACCESSKEYID');
|
||||||
expect(core.setSecret).toHaveBeenCalledWith('STSAWSSECRETACCESSKEY');
|
expect(core.setSecret).toHaveBeenCalledWith('STSAWSSECRETACCESSKEY');
|
||||||
expect(core.setSecret).toHaveBeenCalledWith('STSAWSSESSIONTOKEN');
|
expect(core.setSecret).toHaveBeenCalledWith('STSAWSSESSIONTOKEN');
|
||||||
@@ -72,7 +71,7 @@ describe('Configure AWS Credentials', {}, () => {
|
|||||||
expect(core.info).toHaveBeenCalledWith('Authenticated as assumedRoleId AROAFAKEASSUMEDROLEID');
|
expect(core.info).toHaveBeenCalledWith('Authenticated as assumedRoleId AROAFAKEASSUMEDROLEID');
|
||||||
expect(core.info).toHaveBeenCalledTimes(3);
|
expect(core.info).toHaveBeenCalledTimes(3);
|
||||||
expect(core.setOutput).toHaveBeenCalledWith('aws-account-id', '111111111111');
|
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('STSAWSACCESSKEYID');
|
||||||
expect(core.setSecret).toHaveBeenCalledWith('STSAWSSECRETACCESSKEY');
|
expect(core.setSecret).toHaveBeenCalledWith('STSAWSSECRETACCESSKEY');
|
||||||
expect(core.setSecret).toHaveBeenCalledWith('STSAWSSESSIONTOKEN');
|
expect(core.setSecret).toHaveBeenCalledWith('STSAWSSESSIONTOKEN');
|
||||||
@@ -107,7 +106,7 @@ describe('Configure AWS Credentials', {}, () => {
|
|||||||
expect(core.setSecret).toHaveBeenCalledWith('MYAWSSECRETACCESSKEY');
|
expect(core.setSecret).toHaveBeenCalledWith('MYAWSSECRETACCESSKEY');
|
||||||
expect(core.setSecret).toHaveBeenCalledTimes(2);
|
expect(core.setSecret).toHaveBeenCalledTimes(2);
|
||||||
expect(core.setOutput).toHaveBeenCalledWith('aws-account-id', '111111111111');
|
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).toHaveBeenCalledWith('Proceeding with IAM user credentials');
|
||||||
expect(core.info).toHaveBeenCalledOnce();
|
expect(core.info).toHaveBeenCalledOnce();
|
||||||
expect(core.setFailed).not.toHaveBeenCalled();
|
expect(core.setFailed).not.toHaveBeenCalled();
|
||||||
@@ -141,7 +140,7 @@ describe('Configure AWS Credentials', {}, () => {
|
|||||||
expect(core.setSecret).toHaveBeenCalledWith('MYAWSSECRETACCESSKEY');
|
expect(core.setSecret).toHaveBeenCalledWith('MYAWSSECRETACCESSKEY');
|
||||||
expect(core.setSecret).toHaveBeenCalledTimes(5);
|
expect(core.setSecret).toHaveBeenCalledTimes(5);
|
||||||
expect(core.setOutput).toHaveBeenCalledWith('aws-account-id', '111111111111');
|
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('Assuming role with user credentials');
|
||||||
expect(core.info).toHaveBeenCalledWith('Authenticated as assumedRoleId AROAFAKEASSUMEDROLEID');
|
expect(core.info).toHaveBeenCalledWith('Authenticated as assumedRoleId AROAFAKEASSUMEDROLEID');
|
||||||
expect(core.info).toHaveBeenCalledTimes(2);
|
expect(core.info).toHaveBeenCalledTimes(2);
|
||||||
@@ -174,7 +173,7 @@ describe('Configure AWS Credentials', {}, () => {
|
|||||||
expect(core.setSecret).toHaveBeenCalledWith('STSAWSSESSIONTOKEN');
|
expect(core.setSecret).toHaveBeenCalledWith('STSAWSSESSIONTOKEN');
|
||||||
expect(core.setSecret).toHaveBeenCalledTimes(3);
|
expect(core.setSecret).toHaveBeenCalledTimes(3);
|
||||||
expect(core.setOutput).toHaveBeenCalledWith('aws-account-id', '111111111111');
|
expect(core.setOutput).toHaveBeenCalledWith('aws-account-id', '111111111111');
|
||||||
expect(core.setOutput).toHaveBeenCalledTimes(1);
|
expect(core.setOutput).toHaveBeenCalledTimes(2);
|
||||||
expect(core.setFailed).not.toHaveBeenCalled();
|
expect(core.setFailed).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -205,7 +204,7 @@ describe('Configure AWS Credentials', {}, () => {
|
|||||||
expect(core.setSecret).toHaveBeenCalledWith('STSAWSSESSIONTOKEN');
|
expect(core.setSecret).toHaveBeenCalledWith('STSAWSSESSIONTOKEN');
|
||||||
expect(core.setSecret).toHaveBeenCalledTimes(3);
|
expect(core.setSecret).toHaveBeenCalledTimes(3);
|
||||||
expect(core.setOutput).toHaveBeenCalledWith('aws-account-id', '111111111111');
|
expect(core.setOutput).toHaveBeenCalledWith('aws-account-id', '111111111111');
|
||||||
expect(core.setOutput).toHaveBeenCalledTimes(2);
|
expect(core.setOutput).toHaveBeenCalledTimes(4);
|
||||||
expect(core.setFailed).not.toHaveBeenCalled();
|
expect(core.setFailed).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
it('exports environment variables from inputs', {}, async () => {
|
it('exports environment variables from inputs', {}, async () => {
|
||||||
@@ -238,7 +237,7 @@ describe('Configure AWS Credentials', {}, () => {
|
|||||||
expect(core.setSecret).toHaveBeenCalledWith('STSAWSSESSIONTOKEN');
|
expect(core.setSecret).toHaveBeenCalledWith('STSAWSSESSIONTOKEN');
|
||||||
expect(core.setSecret).toHaveBeenCalledTimes(6);
|
expect(core.setSecret).toHaveBeenCalledTimes(6);
|
||||||
expect(core.setOutput).toHaveBeenCalledWith('aws-account-id', '111111111111');
|
expect(core.setOutput).toHaveBeenCalledWith('aws-account-id', '111111111111');
|
||||||
expect(core.setOutput).toHaveBeenCalledTimes(2);
|
expect(core.setOutput).toHaveBeenCalledTimes(4);
|
||||||
expect(core.setFailed).not.toHaveBeenCalled();
|
expect(core.setFailed).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -300,17 +299,115 @@ describe('Configure AWS Credentials', {}, () => {
|
|||||||
await run();
|
await run();
|
||||||
expect(core.setFailed).toHaveBeenCalled();
|
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));
|
vi.spyOn(core, 'getInput').mockImplementation(mocks.getInput(mocks.USE_EXISTING_CREDENTIALS_INPUTS));
|
||||||
mockedSTSClient.on(GetCallerIdentityCommand).rejects();
|
mockedSTSClient.on(GetCallerIdentityCommand).rejects();
|
||||||
await run();
|
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));
|
vi.spyOn(core, 'getInput').mockImplementation(mocks.getInput(mocks.USE_EXISTING_CREDENTIALS_INPUTS));
|
||||||
mockedSTSClient.on(GetCallerIdentityCommand).resolves(mocks.outputs.GET_CALLER_IDENTITY);
|
mockedSTSClient.on(GetCallerIdentityCommand).resolves(mocks.outputs.GET_CALLER_IDENTITY);
|
||||||
await run();
|
await run();
|
||||||
expect(core.setFailed).not.toHaveBeenCalled();
|
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',
|
'aws-region': 'fake-region-1',
|
||||||
'use-existing-credentials': 'true',
|
'use-existing-credentials': 'true',
|
||||||
'role-to-assume': 'arn:aws:iam::111111111111:role/MY-ROLE',
|
'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 = {
|
const envs = {
|
||||||
|
|||||||
+5
-10
@@ -13,23 +13,18 @@
|
|||||||
"module": "CommonJS",
|
"module": "CommonJS",
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"outDir": "build",
|
"outDir": "build",
|
||||||
"declaration": true,
|
"declaration": false,
|
||||||
"newLine": "lf",
|
"newLine": "lf",
|
||||||
"noEmitOnError": true,
|
"noEmitOnError": true,
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"disableSizeLimit": true,
|
"disableSizeLimit": true,
|
||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"lib": [ "ES2020" ],
|
"lib": ["ES2020"],
|
||||||
"target": "ES2020",
|
"target": "ES2020",
|
||||||
"noErrorTruncation": true,
|
"noErrorTruncation": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"rootDir": "src",
|
"rootDir": "src"
|
||||||
},
|
},
|
||||||
"include": [
|
"include": ["src/**/*.ts"],
|
||||||
"src/**/*.ts"
|
"exclude": ["test/**/*.ts"]
|
||||||
],
|
|
||||||
"exclude": [
|
|
||||||
"test/**/*.ts"
|
|
||||||
],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-5
@@ -1,11 +1,8 @@
|
|||||||
{
|
{
|
||||||
"extends": "./tsconfig.json",
|
"extends": "./tsconfig.json",
|
||||||
"include": [
|
"include": ["test/**/*.ts", "src/**/*.ts"],
|
||||||
"test/**/*.ts",
|
|
||||||
"src/**/*.ts"
|
|
||||||
],
|
|
||||||
"exclude": [],
|
"exclude": [],
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"rootDir": "./"
|
"rootDir": "./"
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user