mirror of
https://github.com/aws-actions/configure-aws-credentials.git
synced 2026-09-02 05:55:10 +09:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 58b282f00f | |||
| 472e549195 | |||
| 187737abc2 | |||
| 8d8bc098cc | |||
| fa078d278f |
@@ -2,6 +2,13 @@
|
|||||||
|
|
||||||
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.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
+57
-5
File diff suppressed because one or more lines are too long
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+89
-2
@@ -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 () => {
|
||||||
|
|||||||
Generated
+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.0",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -1203,9 +1203,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"aws-sdk": {
|
"aws-sdk": {
|
||||||
"version": "2.684.0",
|
"version": "2.686.0",
|
||||||
"resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.684.0.tgz",
|
"resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.686.0.tgz",
|
||||||
"integrity": "sha512-OkSMKIbRTBd3YV5iAklJxZFyLg0jRO2XW6+WhMuDBHMEs8aRbZw4iAD85wFC8tG7X9o0kcjnWfZUDq7MK1dcDg==",
|
"integrity": "sha512-QhYhJ5y8tUG5SlmY3CSf9RBaa3EFbta28oarOyiwceHKmY80cMCafRI1YypT6CVDx/q91dbnSNQfWhs0cZPbBQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"buffer": "4.9.1",
|
"buffer": "4.9.1",
|
||||||
"events": "1.1.1",
|
"events": "1.1.1",
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "aws-actions-configure-aws-credentials",
|
"name": "aws-actions-configure-aws-credentials",
|
||||||
"version": "1.3.5",
|
"version": "1.4.0",
|
||||||
"description": "Configure AWS Credentials",
|
"description": "Configure AWS Credentials",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
"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.686.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@zeit/ncc": "^0.22.3",
|
"@zeit/ncc": "^0.22.3",
|
||||||
|
|||||||
Reference in New Issue
Block a user