mirror of
https://github.com/aws-actions/configure-aws-credentials.git
synced 2026-09-03 06:05:04 +09:00
Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9a78866a56 | |||
| 58784d3648 | |||
| e22426a453 | |||
| fe3da2c1fd | |||
| 67b6c7c1a9 | |||
| 7ab2a28ca9 | |||
| 77a21a780c | |||
| ae509cd90a | |||
| f04843b510 | |||
| 5b6b815585 | |||
| 1a820d1dd7 | |||
| cdd78886ae | |||
| 053a0e8b78 | |||
| 863af956d9 | |||
| f4f3929463 | |||
| 96febc6582 | |||
| da082bd937 | |||
| 554e695b56 | |||
| 06ce89fcf6 | |||
| 684c75b685 | |||
| 442c1ba794 | |||
| c787feb964 | |||
| 58b282f00f | |||
| 472e549195 | |||
| 187737abc2 | |||
| 8d8bc098cc | |||
| fa078d278f |
@@ -1,9 +0,0 @@
|
|||||||
version: 1
|
|
||||||
update_configs:
|
|
||||||
- package_manager: "javascript"
|
|
||||||
directory: "/"
|
|
||||||
update_schedule: "monthly"
|
|
||||||
automerged_updates:
|
|
||||||
- match:
|
|
||||||
dependency_type: "all"
|
|
||||||
update_type: "semver:minor"
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: npm
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: monthly
|
||||||
|
open-pull-requests-limit: 10
|
||||||
+8
-3
@@ -12,17 +12,18 @@ pull_request_rules:
|
|||||||
- -merged
|
- -merged
|
||||||
- -closed
|
- -closed
|
||||||
- author!=dependabot[bot]
|
- author!=dependabot[bot]
|
||||||
- author!=dependabot-preview[bot]
|
|
||||||
actions:
|
actions:
|
||||||
merge:
|
merge:
|
||||||
method: squash
|
method: squash
|
||||||
strict: smart
|
strict: smart
|
||||||
strict_method: merge
|
strict_method: merge
|
||||||
|
|
||||||
- name: Automatically approve Dependabot PRs
|
- name: Automatically approve and merge Dependabot PRs
|
||||||
conditions:
|
conditions:
|
||||||
- base=master
|
- base=master
|
||||||
- author~=^dependabot(|-preview)\[bot\]$
|
- author=dependabot[bot]
|
||||||
|
- status-success=Run Unit Tests
|
||||||
|
- status-success=Semantic Pull Request
|
||||||
- -title~=(WIP|wip)
|
- -title~=(WIP|wip)
|
||||||
- -label~=(blocked|do-not-merge)
|
- -label~=(blocked|do-not-merge)
|
||||||
- -merged
|
- -merged
|
||||||
@@ -30,3 +31,7 @@ pull_request_rules:
|
|||||||
actions:
|
actions:
|
||||||
review:
|
review:
|
||||||
type: APPROVE
|
type: APPROVE
|
||||||
|
merge:
|
||||||
|
method: squash
|
||||||
|
strict: smart+fasttrack
|
||||||
|
strict_method: merge
|
||||||
|
|||||||
@@ -2,6 +2,22 @@
|
|||||||
|
|
||||||
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.
|
||||||
|
|
||||||
|
### [1.4.2](https://github.com/aws-actions/configure-aws-credentials/compare/v1.4.1...v1.4.2) (2020-06-30)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* add comma to set of special characters ([#78](https://github.com/aws-actions/configure-aws-credentials/issues/78)) ([f04843b](https://github.com/aws-actions/configure-aws-credentials/commit/f04843b510a6c8adf77eed907a616cf00a99970d))
|
||||||
|
|
||||||
|
### [1.4.1](https://github.com/aws-actions/configure-aws-credentials/compare/v1.4.0...v1.4.1) (2020-06-09)
|
||||||
|
|
||||||
|
## [1.4.0](https://github.com/aws-actions/configure-aws-credentials/compare/v1.3.5...v1.4.0) (2020-06-03)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* Refresh and validate credentials after setting env var creds ([#71](https://github.com/aws-actions/configure-aws-credentials/issues/71)) ([472e549](https://github.com/aws-actions/configure-aws-credentials/commit/472e549195ba1f153e9fb72e39dc2a094e5de13e))
|
||||||
|
|
||||||
### [1.3.5](https://github.com/aws-actions/configure-aws-credentials/compare/v1.3.4...v1.3.5) (2020-05-27)
|
### [1.3.5](https://github.com/aws-actions/configure-aws-credentials/compare/v1.3.4...v1.3.5) (2020-05-27)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Vendored
+229
-81
File diff suppressed because one or more lines are too long
@@ -82,7 +82,7 @@ function sanitizeGithubWorkflowName(name) {
|
|||||||
// Workflow names can be almost any valid UTF-8 string, but tags are more restrictive.
|
// Workflow names can be almost any valid UTF-8 string, but tags are more restrictive.
|
||||||
// This replaces anything not conforming to the tag restrictions by inverting the regular expression.
|
// This replaces anything not conforming to the tag restrictions by inverting the regular expression.
|
||||||
// See the AWS documentation for constraint specifics https://docs.aws.amazon.com/STS/latest/APIReference/API_Tag.html.
|
// See the AWS documentation for constraint specifics https://docs.aws.amazon.com/STS/latest/APIReference/API_Tag.html.
|
||||||
const nameWithoutSpecialCharacters = name.replace(/[^\p{L}\p{Z}\p{N}_.:/=+-@]/gu, SANITIZATION_CHARACTER);
|
const nameWithoutSpecialCharacters = name.replace(/[^\p{L}\p{Z}\p{N}_:/=+.-@-]/gu, SANITIZATION_CHARACTER);
|
||||||
const nameTruncated = nameWithoutSpecialCharacters.slice(0, MAX_TAG_VALUE_LENGTH)
|
const nameTruncated = nameWithoutSpecialCharacters.slice(0, MAX_TAG_VALUE_LENGTH)
|
||||||
return nameTruncated
|
return nameTruncated
|
||||||
}
|
}
|
||||||
@@ -132,6 +132,50 @@ async function exportAccountId(maskAccountId, region) {
|
|||||||
return accountId;
|
return accountId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function loadCredentials() {
|
||||||
|
// Force the SDK to re-resolve credentials with the default provider chain.
|
||||||
|
//
|
||||||
|
// This action typically sets credentials in the environment via environment variables.
|
||||||
|
// The SDK never refreshes those env-var-based credentials after initial load.
|
||||||
|
// In case there were already env-var creds set in the actions environment when this action
|
||||||
|
// loaded, this action needs to refresh the SDK creds after overwriting those environment variables.
|
||||||
|
//
|
||||||
|
// The credentials object needs to be entirely recreated (instead of simply refreshed),
|
||||||
|
// because the credential object type could change when this action writes env var creds.
|
||||||
|
// For example, the first load could return EC2 instance metadata credentials
|
||||||
|
// in a self-hosted runner, and the second load could return environment credentials
|
||||||
|
// from an assume-role call in this action.
|
||||||
|
aws.config.credentials = null;
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
aws.config.getCredentials((err) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
resolve(aws.config.credentials);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function validateCredentials(expectedAccessKeyId) {
|
||||||
|
let credentials;
|
||||||
|
try {
|
||||||
|
credentials = await loadCredentials();
|
||||||
|
|
||||||
|
if (!credentials.accessKeyId) {
|
||||||
|
throw new Error('Access key ID empty after loading credentials');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(`Credentials could not be loaded, please check your action inputs: ${error.message}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const actualAccessKeyId = credentials.accessKeyId;
|
||||||
|
|
||||||
|
if (expectedAccessKeyId && expectedAccessKeyId != actualAccessKeyId) {
|
||||||
|
throw new Error('Unexpected failure: Credentials loaded by the SDK do not match the access key ID configured by the action');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function getStsClient(region) {
|
function getStsClient(region) {
|
||||||
return new aws.STS({
|
return new aws.STS({
|
||||||
region,
|
region,
|
||||||
@@ -172,6 +216,13 @@ async function run() {
|
|||||||
exportCredentials({accessKeyId, secretAccessKey, sessionToken});
|
exportCredentials({accessKeyId, secretAccessKey, sessionToken});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Regardless of whether any source credentials were provided as inputs,
|
||||||
|
// validate that the SDK can actually pick up credentials. This validates
|
||||||
|
// cases where this action is on a self-hosted runner that doesn't have credentials
|
||||||
|
// configured correctly, and cases where the user intended to provide input
|
||||||
|
// credentials but the secrets inputs resolved to empty strings.
|
||||||
|
await validateCredentials(accessKeyId);
|
||||||
|
|
||||||
const sourceAccountId = await exportAccountId(maskAccountId, region);
|
const sourceAccountId = await exportAccountId(maskAccountId, region);
|
||||||
|
|
||||||
// Get role credentials if configured to do so
|
// Get role credentials if configured to do so
|
||||||
@@ -185,6 +236,7 @@ async function run() {
|
|||||||
roleSessionName
|
roleSessionName
|
||||||
});
|
});
|
||||||
exportCredentials(roleCredentials);
|
exportCredentials(roleCredentials);
|
||||||
|
await validateCredentials(roleCredentials.accessKeyId);
|
||||||
await exportAccountId(maskAccountId, region);
|
await exportAccountId(maskAccountId, region);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+90
-3
@@ -1,6 +1,6 @@
|
|||||||
const core = require('@actions/core');
|
const core = require('@actions/core');
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
|
const aws = require('aws-sdk');
|
||||||
const run = require('.');
|
const run = require('.');
|
||||||
|
|
||||||
jest.mock('@actions/core');
|
jest.mock('@actions/core');
|
||||||
@@ -49,6 +49,9 @@ const mockStsAssumeRole = jest.fn();
|
|||||||
|
|
||||||
jest.mock('aws-sdk', () => {
|
jest.mock('aws-sdk', () => {
|
||||||
return {
|
return {
|
||||||
|
config: {
|
||||||
|
getCredentials: jest.fn()
|
||||||
|
},
|
||||||
STS: jest.fn(() => ({
|
STS: jest.fn(() => ({
|
||||||
getCallerIdentity: mockStsCallerIdentity,
|
getCallerIdentity: mockStsCallerIdentity,
|
||||||
assumeRole: mockStsAssumeRole,
|
assumeRole: mockStsAssumeRole,
|
||||||
@@ -82,6 +85,27 @@ describe('Configure AWS Credentials', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
aws.config.getCredentials.mockReset();
|
||||||
|
aws.config.getCredentials
|
||||||
|
.mockImplementationOnce(callback => {
|
||||||
|
if (!aws.config.credentials) {
|
||||||
|
aws.config.credentials = {
|
||||||
|
accessKeyId: FAKE_ACCESS_KEY_ID,
|
||||||
|
secretAccessKey: FAKE_SECRET_ACCESS_KEY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
callback(null);
|
||||||
|
})
|
||||||
|
.mockImplementationOnce(callback => {
|
||||||
|
if (!aws.config.credentials) {
|
||||||
|
aws.config.credentials = {
|
||||||
|
accessKeyId: FAKE_STS_ACCESS_KEY_ID,
|
||||||
|
secretAccessKey: FAKE_STS_SECRET_ACCESS_KEY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
callback(null);
|
||||||
|
});
|
||||||
|
|
||||||
mockStsAssumeRole.mockImplementation(() => {
|
mockStsAssumeRole.mockImplementation(() => {
|
||||||
return {
|
return {
|
||||||
promise() {
|
promise() {
|
||||||
@@ -134,6 +158,59 @@ describe('Configure AWS Credentials', () => {
|
|||||||
expect(core.setSecret).toHaveBeenCalledWith(FAKE_ACCOUNT_ID);
|
expect(core.setSecret).toHaveBeenCalledWith(FAKE_ACCOUNT_ID);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('action with no accessible credentials fails', async () => {
|
||||||
|
process.env.SHOW_STACK_TRACE = 'false';
|
||||||
|
const mockInputs = {'aws-region': FAKE_REGION};
|
||||||
|
core.getInput = jest
|
||||||
|
.fn()
|
||||||
|
.mockImplementation(mockGetInput(mockInputs));
|
||||||
|
aws.config.getCredentials.mockReset();
|
||||||
|
aws.config.getCredentials.mockImplementation(callback => {
|
||||||
|
callback(new Error('No credentials to load'));
|
||||||
|
});
|
||||||
|
|
||||||
|
await run();
|
||||||
|
|
||||||
|
expect(core.setFailed).toHaveBeenCalledWith("Credentials could not be loaded, please check your action inputs: No credentials to load");
|
||||||
|
});
|
||||||
|
|
||||||
|
test('action with empty credentials fails', async () => {
|
||||||
|
process.env.SHOW_STACK_TRACE = 'false';
|
||||||
|
const mockInputs = {'aws-region': FAKE_REGION};
|
||||||
|
core.getInput = jest
|
||||||
|
.fn()
|
||||||
|
.mockImplementation(mockGetInput(mockInputs));
|
||||||
|
aws.config.getCredentials.mockReset();
|
||||||
|
aws.config.getCredentials.mockImplementation(callback => {
|
||||||
|
aws.config.credentials = {
|
||||||
|
accessKeyId: ''
|
||||||
|
}
|
||||||
|
callback(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
await run();
|
||||||
|
|
||||||
|
expect(core.setFailed).toHaveBeenCalledWith("Credentials could not be loaded, please check your action inputs: Access key ID empty after loading credentials");
|
||||||
|
});
|
||||||
|
|
||||||
|
test('action fails when credentials are not set in the SDK correctly', async () => {
|
||||||
|
process.env.SHOW_STACK_TRACE = 'false';
|
||||||
|
core.getInput = jest
|
||||||
|
.fn()
|
||||||
|
.mockImplementation(mockGetInput(ASSUME_ROLE_INPUTS));
|
||||||
|
aws.config.getCredentials.mockReset();
|
||||||
|
aws.config.getCredentials.mockImplementation(callback => {
|
||||||
|
aws.config.credentials = {
|
||||||
|
accessKeyId: FAKE_ACCESS_KEY_ID
|
||||||
|
}
|
||||||
|
callback(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
await run();
|
||||||
|
|
||||||
|
expect(core.setFailed).toHaveBeenCalledWith("Unexpected failure: Credentials loaded by the SDK do not match the access key ID configured by the action");
|
||||||
|
});
|
||||||
|
|
||||||
test('session token is optional', async () => {
|
test('session token is optional', async () => {
|
||||||
const mockInputs = {...CREDS_INPUTS, 'aws-region': 'eu-west-1'};
|
const mockInputs = {...CREDS_INPUTS, 'aws-region': 'eu-west-1'};
|
||||||
core.getInput = jest
|
core.getInput = jest
|
||||||
@@ -154,12 +231,19 @@ describe('Configure AWS Credentials', () => {
|
|||||||
expect(core.setSecret).toHaveBeenCalledWith(FAKE_ACCOUNT_ID);
|
expect(core.setSecret).toHaveBeenCalledWith(FAKE_ACCOUNT_ID);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('session token is cleared if necessary', async () => {
|
test('existing env var creds are cleared', async () => {
|
||||||
const mockInputs = {...CREDS_INPUTS, 'aws-region': 'eu-west-1'};
|
const mockInputs = {...CREDS_INPUTS, 'aws-region': 'eu-west-1'};
|
||||||
core.getInput = jest
|
core.getInput = jest
|
||||||
.fn()
|
.fn()
|
||||||
.mockImplementation(mockGetInput(mockInputs));
|
.mockImplementation(mockGetInput(mockInputs));
|
||||||
|
process.env.AWS_ACCESS_KEY_ID = 'foo';
|
||||||
|
process.env.AWS_SECRET_ACCESS_KEY = 'bar';
|
||||||
process.env.AWS_SESSION_TOKEN = 'helloworld';
|
process.env.AWS_SESSION_TOKEN = 'helloworld';
|
||||||
|
aws.config.credentials = {
|
||||||
|
accessKeyId: 'foo',
|
||||||
|
secretAccessKey: 'bar',
|
||||||
|
sessionToken: 'helloworld'
|
||||||
|
};
|
||||||
|
|
||||||
await run();
|
await run();
|
||||||
expect(mockStsAssumeRole).toHaveBeenCalledTimes(0);
|
expect(mockStsAssumeRole).toHaveBeenCalledTimes(0);
|
||||||
@@ -174,6 +258,9 @@ describe('Configure AWS Credentials', () => {
|
|||||||
expect(core.exportVariable).toHaveBeenCalledWith('AWS_REGION', 'eu-west-1');
|
expect(core.exportVariable).toHaveBeenCalledWith('AWS_REGION', 'eu-west-1');
|
||||||
expect(core.setOutput).toHaveBeenCalledWith('aws-account-id', FAKE_ACCOUNT_ID);
|
expect(core.setOutput).toHaveBeenCalledWith('aws-account-id', FAKE_ACCOUNT_ID);
|
||||||
expect(core.setSecret).toHaveBeenCalledWith(FAKE_ACCOUNT_ID);
|
expect(core.setSecret).toHaveBeenCalledWith(FAKE_ACCOUNT_ID);
|
||||||
|
expect(aws.config.credentials.accessKeyId).toBe(FAKE_ACCESS_KEY_ID);
|
||||||
|
expect(aws.config.credentials.secretAccessKey).toBe(FAKE_SECRET_ACCESS_KEY);
|
||||||
|
expect(aws.config.credentials.sessionToken).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('validates region name', async () => {
|
test('validates region name', async () => {
|
||||||
@@ -417,7 +504,7 @@ describe('Configure AWS Credentials', () => {
|
|||||||
|
|
||||||
process.env = {...process.env, GITHUB_WORKFLOW: 'Workflow!"#$%&\'()*+, -./:;<=>?@[]^_`{|}~🙂💥🍌1yFvMOeD3ZHYsHrGjCceOboMYzBPo0CRNFdcsVRG6UgR3A912a8KfcBtEVvkAS7kRBq80umGff8mux5IN1y55HQWPNBNyaruuVr4islFXte4FDQZexGJRUSMyHQpxJ8OmZnET84oDmbvmIjgxI6IBrdihX9PHMapT4gQvRYnLqNiKb18rEMWDNoZRy51UPX5sWK2GKPipgKSO9kqLckZai9D2AN2RlWCxtMqChNtxuxjqeqhoQZo0oaq39sjcRZgAAAAAAA'};
|
process.env = {...process.env, GITHUB_WORKFLOW: 'Workflow!"#$%&\'()*+, -./:;<=>?@[]^_`{|}~🙂💥🍌1yFvMOeD3ZHYsHrGjCceOboMYzBPo0CRNFdcsVRG6UgR3A912a8KfcBtEVvkAS7kRBq80umGff8mux5IN1y55HQWPNBNyaruuVr4islFXte4FDQZexGJRUSMyHQpxJ8OmZnET84oDmbvmIjgxI6IBrdihX9PHMapT4gQvRYnLqNiKb18rEMWDNoZRy51UPX5sWK2GKPipgKSO9kqLckZai9D2AN2RlWCxtMqChNtxuxjqeqhoQZo0oaq39sjcRZgAAAAAAA'};
|
||||||
|
|
||||||
const sanitizedWorkflowName = 'Workflow__________+, -./:;<=>?@____________1yFvMOeD3ZHYsHrGjCceOboMYzBPo0CRNFdcsVRG6UgR3A912a8KfcBtEVvkAS7kRBq80umGff8mux5IN1y55HQWPNBNyaruuVr4islFXte4FDQZexGJRUSMyHQpxJ8OmZnET84oDmbvmIjgxI6IBrdihX9PHMapT4gQvRYnLqNiKb18rEMWDNoZRy51UPX5sWK2GKPipgKSO9kqLckZa'
|
const sanitizedWorkflowName = 'Workflow__________+_ -./:;<=>?@____________1yFvMOeD3ZHYsHrGjCceOboMYzBPo0CRNFdcsVRG6UgR3A912a8KfcBtEVvkAS7kRBq80umGff8mux5IN1y55HQWPNBNyaruuVr4islFXte4FDQZexGJRUSMyHQpxJ8OmZnET84oDmbvmIjgxI6IBrdihX9PHMapT4gQvRYnLqNiKb18rEMWDNoZRy51UPX5sWK2GKPipgKSO9kqLckZa'
|
||||||
|
|
||||||
await run();
|
await run();
|
||||||
expect(mockStsAssumeRole).toHaveBeenCalledWith({
|
expect(mockStsAssumeRole).toHaveBeenCalledWith({
|
||||||
|
|||||||
Generated
+619
-841
File diff suppressed because it is too large
Load Diff
+4
-4
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "aws-actions-configure-aws-credentials",
|
"name": "aws-actions-configure-aws-credentials",
|
||||||
"version": "1.3.5",
|
"version": "1.4.2",
|
||||||
"description": "Configure AWS Credentials",
|
"description": "Configure AWS Credentials",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -26,11 +26,11 @@
|
|||||||
"homepage": "https://github.com/aws-actions/configure-aws-credentials#readme",
|
"homepage": "https://github.com/aws-actions/configure-aws-credentials#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.2.4",
|
"@actions/core": "^1.2.4",
|
||||||
"aws-sdk": "^2.684.0"
|
"aws-sdk": "^2.707.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@zeit/ncc": "^0.22.3",
|
"@zeit/ncc": "^0.22.3",
|
||||||
"eslint": "^7.1.0",
|
"eslint": "^7.3.1",
|
||||||
"jest": "^26.0.1"
|
"jest": "^26.1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user