mirror of
https://github.com/aws-actions/configure-aws-credentials.git
synced 2026-08-26 04:45:10 +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
|
||||
- -closed
|
||||
- author!=dependabot[bot]
|
||||
- author!=dependabot-preview[bot]
|
||||
actions:
|
||||
merge:
|
||||
method: squash
|
||||
strict: smart
|
||||
strict_method: merge
|
||||
|
||||
- name: Automatically approve Dependabot PRs
|
||||
- name: Automatically approve and merge Dependabot PRs
|
||||
conditions:
|
||||
- base=master
|
||||
- author~=^dependabot(|-preview)\[bot\]$
|
||||
- author=dependabot[bot]
|
||||
- status-success=Run Unit Tests
|
||||
- status-success=Semantic Pull Request
|
||||
- -title~=(WIP|wip)
|
||||
- -label~=(blocked|do-not-merge)
|
||||
- -merged
|
||||
@@ -30,3 +31,7 @@ pull_request_rules:
|
||||
actions:
|
||||
review:
|
||||
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.
|
||||
|
||||
### [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)
|
||||
|
||||
|
||||
|
||||
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.
|
||||
// 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.
|
||||
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)
|
||||
return nameTruncated
|
||||
}
|
||||
@@ -132,6 +132,50 @@ async function exportAccountId(maskAccountId, region) {
|
||||
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) {
|
||||
return new aws.STS({
|
||||
region,
|
||||
@@ -172,6 +216,13 @@ async function run() {
|
||||
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);
|
||||
|
||||
// Get role credentials if configured to do so
|
||||
@@ -185,6 +236,7 @@ async function run() {
|
||||
roleSessionName
|
||||
});
|
||||
exportCredentials(roleCredentials);
|
||||
await validateCredentials(roleCredentials.accessKeyId);
|
||||
await exportAccountId(maskAccountId, region);
|
||||
}
|
||||
}
|
||||
|
||||
+90
-3
@@ -1,6 +1,6 @@
|
||||
const core = require('@actions/core');
|
||||
const assert = require('assert');
|
||||
|
||||
const aws = require('aws-sdk');
|
||||
const run = require('.');
|
||||
|
||||
jest.mock('@actions/core');
|
||||
@@ -49,6 +49,9 @@ const mockStsAssumeRole = jest.fn();
|
||||
|
||||
jest.mock('aws-sdk', () => {
|
||||
return {
|
||||
config: {
|
||||
getCredentials: jest.fn()
|
||||
},
|
||||
STS: jest.fn(() => ({
|
||||
getCallerIdentity: mockStsCallerIdentity,
|
||||
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(() => {
|
||||
return {
|
||||
promise() {
|
||||
@@ -134,6 +158,59 @@ describe('Configure AWS Credentials', () => {
|
||||
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 () => {
|
||||
const mockInputs = {...CREDS_INPUTS, 'aws-region': 'eu-west-1'};
|
||||
core.getInput = jest
|
||||
@@ -154,12 +231,19 @@ describe('Configure AWS Credentials', () => {
|
||||
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'};
|
||||
core.getInput = jest
|
||||
.fn()
|
||||
.mockImplementation(mockGetInput(mockInputs));
|
||||
process.env.AWS_ACCESS_KEY_ID = 'foo';
|
||||
process.env.AWS_SECRET_ACCESS_KEY = 'bar';
|
||||
process.env.AWS_SESSION_TOKEN = 'helloworld';
|
||||
aws.config.credentials = {
|
||||
accessKeyId: 'foo',
|
||||
secretAccessKey: 'bar',
|
||||
sessionToken: 'helloworld'
|
||||
};
|
||||
|
||||
await run();
|
||||
expect(mockStsAssumeRole).toHaveBeenCalledTimes(0);
|
||||
@@ -174,6 +258,9 @@ describe('Configure AWS Credentials', () => {
|
||||
expect(core.exportVariable).toHaveBeenCalledWith('AWS_REGION', 'eu-west-1');
|
||||
expect(core.setOutput).toHaveBeenCalledWith('aws-account-id', 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 () => {
|
||||
@@ -417,7 +504,7 @@ describe('Configure AWS Credentials', () => {
|
||||
|
||||
process.env = {...process.env, GITHUB_WORKFLOW: 'Workflow!"#$%&\'()*+, -./:;<=>?@[]^_`{|}~🙂💥🍌1yFvMOeD3ZHYsHrGjCceOboMYzBPo0CRNFdcsVRG6UgR3A912a8KfcBtEVvkAS7kRBq80umGff8mux5IN1y55HQWPNBNyaruuVr4islFXte4FDQZexGJRUSMyHQpxJ8OmZnET84oDmbvmIjgxI6IBrdihX9PHMapT4gQvRYnLqNiKb18rEMWDNoZRy51UPX5sWK2GKPipgKSO9kqLckZai9D2AN2RlWCxtMqChNtxuxjqeqhoQZo0oaq39sjcRZgAAAAAAA'};
|
||||
|
||||
const sanitizedWorkflowName = 'Workflow__________+, -./:;<=>?@____________1yFvMOeD3ZHYsHrGjCceOboMYzBPo0CRNFdcsVRG6UgR3A912a8KfcBtEVvkAS7kRBq80umGff8mux5IN1y55HQWPNBNyaruuVr4islFXte4FDQZexGJRUSMyHQpxJ8OmZnET84oDmbvmIjgxI6IBrdihX9PHMapT4gQvRYnLqNiKb18rEMWDNoZRy51UPX5sWK2GKPipgKSO9kqLckZa'
|
||||
const sanitizedWorkflowName = 'Workflow__________+_ -./:;<=>?@____________1yFvMOeD3ZHYsHrGjCceOboMYzBPo0CRNFdcsVRG6UgR3A912a8KfcBtEVvkAS7kRBq80umGff8mux5IN1y55HQWPNBNyaruuVr4islFXte4FDQZexGJRUSMyHQpxJ8OmZnET84oDmbvmIjgxI6IBrdihX9PHMapT4gQvRYnLqNiKb18rEMWDNoZRy51UPX5sWK2GKPipgKSO9kqLckZa'
|
||||
|
||||
await run();
|
||||
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",
|
||||
"version": "1.3.5",
|
||||
"version": "1.4.2",
|
||||
"description": "Configure AWS Credentials",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
@@ -26,11 +26,11 @@
|
||||
"homepage": "https://github.com/aws-actions/configure-aws-credentials#readme",
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.2.4",
|
||||
"aws-sdk": "^2.684.0"
|
||||
"aws-sdk": "^2.707.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@zeit/ncc": "^0.22.3",
|
||||
"eslint": "^7.1.0",
|
||||
"jest": "^26.0.1"
|
||||
"eslint": "^7.3.1",
|
||||
"jest": "^26.1.0"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user