mirror of
https://github.com/aws-actions/configure-aws-credentials.git
synced 2026-09-02 05:55:10 +09:00
@@ -51,9 +51,9 @@ We recommend following [Amazon IAM best practices](https://docs.aws.amazon.com/I
|
|||||||
* [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.
|
* [Monitor the activity](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#keep-a-log) of the credentials used in GitHub Actions workflows.
|
||||||
|
|
||||||
## Assuming a role
|
## Assuming a role
|
||||||
If you would like to use the credentials you provide to this action to assume a role, you can do so by specifying the role ARN in `role-to-assume`.
|
If you would like to use the static credentials you provide to this action to assume a role, you can do so by specifying the role ARN in `role-to-assume`.
|
||||||
The role credentials will then be output instead of the ones you have provided.
|
The role credentials will then be configured in the Actions environment instead of the static credentials you have provided.
|
||||||
The default session duration is 6 hours, but if you would like to adjust this you can pass a duration to `role-duration-seconds`.
|
The default session duration is 6 hours, but if you would like to adjust this you can pass a duration to `role-duration-seconds`.
|
||||||
The default session name is GitHubActions, and you can modify it by specifying the desired name in `role-session-name`.
|
The default session name is GitHubActions, and you can modify it by specifying the desired name in `role-session-name`.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
@@ -64,10 +64,12 @@ Example:
|
|||||||
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 }}
|
||||||
aws-region: us-east-2
|
aws-region: us-east-2
|
||||||
role-to-assume: arn:aws:iam::123456789100:role/role-to-assume
|
role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
|
||||||
|
role-external-id: ${{ secrets.AWS_ROLE_EXTERNAL_ID }}
|
||||||
role-duration-seconds: 1200
|
role-duration-seconds: 1200
|
||||||
role-session-name: MySessionName
|
role-session-name: MySessionName
|
||||||
```
|
```
|
||||||
|
In this example, the secret `AWS_ROLE_TO_ASSUME` contains a string like `arn:aws:iam::123456789100:role/role-to-assume`.
|
||||||
|
|
||||||
### Session tagging
|
### Session tagging
|
||||||
The session will have the name "GitHubActions" and be tagged with the following tags:
|
The session will have the name "GitHubActions" and be tagged with the following tags:
|
||||||
|
|||||||
+11
-2
@@ -17,10 +17,16 @@ inputs:
|
|||||||
description: 'AWS Region, e.g. us-east-2'
|
description: 'AWS Region, e.g. us-east-2'
|
||||||
required: true
|
required: true
|
||||||
mask-aws-account-id:
|
mask-aws-account-id:
|
||||||
description: "Whether to set the AWS account ID for these credentials as a secret value, so that it is masked in logs. Valid values are 'true' and 'false'. Defaults to true"
|
description: >-
|
||||||
|
Whether to set the AWS account ID for these credentials as a secret value,
|
||||||
|
so that it is masked in logs. Valid values are 'true' and 'false'.
|
||||||
|
Defaults to true
|
||||||
required: false
|
required: false
|
||||||
role-to-assume:
|
role-to-assume:
|
||||||
description: "Use the provided credentials to assume a Role and output the assumed credentials for that Role rather than the provided credentials"
|
description: >-
|
||||||
|
Use the provided credentials to assume an IAM role and configure the Actions
|
||||||
|
environment with the assumed role credentials rather than with the provided
|
||||||
|
credentials
|
||||||
required: false
|
required: false
|
||||||
role-duration-seconds:
|
role-duration-seconds:
|
||||||
description: "Role duration in seconds (default: 6 hours)"
|
description: "Role duration in seconds (default: 6 hours)"
|
||||||
@@ -28,6 +34,9 @@ inputs:
|
|||||||
role-session-name:
|
role-session-name:
|
||||||
description: 'Role session name (default: GitHubActions)'
|
description: 'Role session name (default: GitHubActions)'
|
||||||
required: false
|
required: false
|
||||||
|
role-external-id:
|
||||||
|
description: 'The external ID of the role to assume'
|
||||||
|
required: false
|
||||||
outputs:
|
outputs:
|
||||||
aws-account-id:
|
aws-account-id:
|
||||||
description: 'The AWS account ID for the provided credentials'
|
description: 'The AWS account ID for the provided credentials'
|
||||||
|
|||||||
@@ -15,7 +15,16 @@ async function assumeRole(params) {
|
|||||||
// Assume a role to get short-lived credentials using longer-lived credentials.
|
// Assume a role to get short-lived credentials using longer-lived credentials.
|
||||||
const isDefined = i => !!i;
|
const isDefined = i => !!i;
|
||||||
|
|
||||||
const {roleToAssume, roleDurationSeconds, roleSessionName, accessKeyId, secretAccessKey, sessionToken, region} = params;
|
const {
|
||||||
|
roleToAssume,
|
||||||
|
roleExternalId,
|
||||||
|
roleDurationSeconds,
|
||||||
|
roleSessionName,
|
||||||
|
accessKeyId,
|
||||||
|
secretAccessKey,
|
||||||
|
sessionToken,
|
||||||
|
region,
|
||||||
|
} = params;
|
||||||
assert(
|
assert(
|
||||||
[roleToAssume, roleDurationSeconds, roleSessionName, accessKeyId, secretAccessKey, region].every(isDefined),
|
[roleToAssume, roleDurationSeconds, roleSessionName, accessKeyId, secretAccessKey, region].every(isDefined),
|
||||||
"Missing required input when assuming a Role."
|
"Missing required input when assuming a Role."
|
||||||
@@ -32,7 +41,8 @@ async function assumeRole(params) {
|
|||||||
const sts = new aws.STS({
|
const sts = new aws.STS({
|
||||||
accessKeyId, secretAccessKey, sessionToken, region, endpoint, customUserAgent: USER_AGENT
|
accessKeyId, secretAccessKey, sessionToken, region, endpoint, customUserAgent: USER_AGENT
|
||||||
});
|
});
|
||||||
return sts.assumeRole({
|
|
||||||
|
const assumeRoleRequest = {
|
||||||
RoleArn: roleToAssume,
|
RoleArn: roleToAssume,
|
||||||
RoleSessionName: roleSessionName,
|
RoleSessionName: roleSessionName,
|
||||||
DurationSeconds: roleDurationSeconds,
|
DurationSeconds: roleDurationSeconds,
|
||||||
@@ -45,7 +55,13 @@ async function assumeRole(params) {
|
|||||||
{Key: 'Branch', Value: GITHUB_REF},
|
{Key: 'Branch', Value: GITHUB_REF},
|
||||||
{Key: 'Commit', Value: GITHUB_SHA},
|
{Key: 'Commit', Value: GITHUB_SHA},
|
||||||
]
|
]
|
||||||
})
|
};
|
||||||
|
|
||||||
|
if (roleExternalId) {
|
||||||
|
assumeRoleRequest.ExternalId = roleExternalId;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sts.assumeRole(assumeRoleRequest)
|
||||||
.promise()
|
.promise()
|
||||||
.then(function (data) {
|
.then(function (data) {
|
||||||
return {
|
return {
|
||||||
@@ -121,13 +137,14 @@ async function run() {
|
|||||||
const sessionToken = core.getInput('aws-session-token', { required: false });
|
const sessionToken = core.getInput('aws-session-token', { required: false });
|
||||||
const maskAccountId = core.getInput('mask-aws-account-id', { required: false });
|
const maskAccountId = core.getInput('mask-aws-account-id', { required: false });
|
||||||
const roleToAssume = core.getInput('role-to-assume', {required: false});
|
const roleToAssume = core.getInput('role-to-assume', {required: false});
|
||||||
|
const roleExternalId = core.getInput('role-external-id', { required: false });
|
||||||
const roleDurationSeconds = core.getInput('role-duration-seconds', {required: false}) || MAX_ACTION_RUNTIME;
|
const roleDurationSeconds = core.getInput('role-duration-seconds', {required: false}) || MAX_ACTION_RUNTIME;
|
||||||
const roleSessionName = core.getInput('role-session-name', { required: false }) || ROLE_SESSION_NAME;
|
const roleSessionName = core.getInput('role-session-name', { required: false }) || ROLE_SESSION_NAME;
|
||||||
|
|
||||||
// Get role credentials if configured to do so
|
// Get role credentials if configured to do so
|
||||||
if (roleToAssume) {
|
if (roleToAssume) {
|
||||||
const roleCredentials = await assumeRole(
|
const roleCredentials = await assumeRole(
|
||||||
{accessKeyId, secretAccessKey, sessionToken, region, roleToAssume, roleDurationSeconds, roleSessionName}
|
{accessKeyId, secretAccessKey, sessionToken, region, roleToAssume, roleExternalId, roleDurationSeconds, roleSessionName}
|
||||||
);
|
);
|
||||||
exportCredentials(roleCredentials);
|
exportCredentials(roleCredentials);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+24
-1
@@ -260,11 +260,34 @@ describe('Configure AWS Credentials', () => {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('role external ID provided', async () => {
|
||||||
|
core.getInput = jest
|
||||||
|
.fn()
|
||||||
|
.mockImplementation(mockGetInput({...ASSUME_ROLE_INPUTS, 'role-external-id': 'abcdef'}));
|
||||||
|
|
||||||
|
await run();
|
||||||
|
expect(mockStsAssumeRole).toHaveBeenCalledWith({
|
||||||
|
RoleArn: ROLE_NAME,
|
||||||
|
RoleSessionName: 'GitHubActions',
|
||||||
|
DurationSeconds: 6 * 3600,
|
||||||
|
Tags: [
|
||||||
|
{Key: 'GitHub', Value: 'Actions'},
|
||||||
|
{Key: 'Repository', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_REPOSITORY},
|
||||||
|
{Key: 'Workflow', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_WORKFLOW},
|
||||||
|
{Key: 'Action', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_ACTION},
|
||||||
|
{Key: 'Actor', Value: GITHUB_ACTOR_SANITIZED},
|
||||||
|
{Key: 'Branch', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_REF},
|
||||||
|
{Key: 'Commit', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_SHA},
|
||||||
|
],
|
||||||
|
ExternalId: 'abcdef'
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
test('workflow name sanitized in role assumption tags', async () => {
|
test('workflow name sanitized in role assumption tags', async () => {
|
||||||
core.getInput = jest
|
core.getInput = jest
|
||||||
.fn()
|
.fn()
|
||||||
.mockImplementation(mockGetInput(ASSUME_ROLE_INPUTS));
|
.mockImplementation(mockGetInput(ASSUME_ROLE_INPUTS));
|
||||||
|
|
||||||
process.env = {...process.env, GITHUB_WORKFLOW: 'Workflow!"#$%&\'()*+, -./:;<=>?@[]^_`{|}~🙂💥🍌1yFvMOeD3ZHYsHrGjCceOboMYzBPo0CRNFdcsVRG6UgR3A912a8KfcBtEVvkAS7kRBq80umGff8mux5IN1y55HQWPNBNyaruuVr4islFXte4FDQZexGJRUSMyHQpxJ8OmZnET84oDmbvmIjgxI6IBrdihX9PHMapT4gQvRYnLqNiKb18rEMWDNoZRy51UPX5sWK2GKPipgKSO9kqLckZai9D2AN2RlWCxtMqChNtxuxjqeqhoQZo0oaq39sjcRZgAAAAAAA'};
|
process.env = {...process.env, GITHUB_WORKFLOW: 'Workflow!"#$%&\'()*+, -./:;<=>?@[]^_`{|}~🙂💥🍌1yFvMOeD3ZHYsHrGjCceOboMYzBPo0CRNFdcsVRG6UgR3A912a8KfcBtEVvkAS7kRBq80umGff8mux5IN1y55HQWPNBNyaruuVr4islFXte4FDQZexGJRUSMyHQpxJ8OmZnET84oDmbvmIjgxI6IBrdihX9PHMapT4gQvRYnLqNiKb18rEMWDNoZRy51UPX5sWK2GKPipgKSO9kqLckZai9D2AN2RlWCxtMqChNtxuxjqeqhoQZo0oaq39sjcRZgAAAAAAA'};
|
||||||
|
|
||||||
const sanitizedWorkflowName = 'Workflow__________+, -./:;<=>?@____________1yFvMOeD3ZHYsHrGjCceOboMYzBPo0CRNFdcsVRG6UgR3A912a8KfcBtEVvkAS7kRBq80umGff8mux5IN1y55HQWPNBNyaruuVr4islFXte4FDQZexGJRUSMyHQpxJ8OmZnET84oDmbvmIjgxI6IBrdihX9PHMapT4gQvRYnLqNiKb18rEMWDNoZRy51UPX5sWK2GKPipgKSO9kqLckZa'
|
const sanitizedWorkflowName = 'Workflow__________+, -./:;<=>?@____________1yFvMOeD3ZHYsHrGjCceOboMYzBPo0CRNFdcsVRG6UgR3A912a8KfcBtEVvkAS7kRBq80umGff8mux5IN1y55HQWPNBNyaruuVr4islFXte4FDQZexGJRUSMyHQpxJ8OmZnET84oDmbvmIjgxI6IBrdihX9PHMapT4gQvRYnLqNiKb18rEMWDNoZRy51UPX5sWK2GKPipgKSO9kqLckZa'
|
||||||
|
|||||||
Reference in New Issue
Block a user