mirror of
https://github.com/aws-actions/configure-aws-credentials.git
synced 2026-09-03 06:05:04 +09:00
fix: enforce allowed-account-ids on the use-existing-credentials path
The early return for valid pre-existing credentials skipped the allowed-account-ids check, now included.
This commit is contained in:
@@ -5,7 +5,6 @@ import type { Credentials, STSClient } from '@aws-sdk/client-sts';
|
|||||||
import { GetCallerIdentityCommand } from '@aws-sdk/client-sts';
|
import { GetCallerIdentityCommand } from '@aws-sdk/client-sts';
|
||||||
import type { AwsCredentialIdentity } from '@aws-sdk/types';
|
import type { AwsCredentialIdentity } from '@aws-sdk/types';
|
||||||
import type { UserAgent } from '@smithy/types';
|
import type { UserAgent } from '@smithy/types';
|
||||||
import type { CredentialsClient } from './CredentialsClient';
|
|
||||||
|
|
||||||
const MAX_TAG_VALUE_LENGTH = 256;
|
const MAX_TAG_VALUE_LENGTH = 256;
|
||||||
const SANITIZATION_CHARACTER = '_';
|
const SANITIZATION_CHARACTER = '_';
|
||||||
@@ -282,19 +281,6 @@ export function isDefined<T>(i: T | undefined | null): i is T {
|
|||||||
}
|
}
|
||||||
/* c8 ignore stop */
|
/* c8 ignore stop */
|
||||||
|
|
||||||
export async function areCredentialsValid(credentialsClient: CredentialsClient) {
|
|
||||||
const client = credentialsClient.stsClient;
|
|
||||||
try {
|
|
||||||
const identity = await client.send(new GetCallerIdentityCommand({}));
|
|
||||||
if (identity.Account) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
} catch (_) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Like core.getBooleanInput, but respects the required option.
|
* Like core.getBooleanInput, but respects the required option.
|
||||||
*
|
*
|
||||||
|
|||||||
+13
-5
@@ -3,12 +3,12 @@ import type { AssumeRoleCommandOutput } from '@aws-sdk/client-sts';
|
|||||||
import { assumeRole } from './assumeRole';
|
import { assumeRole } from './assumeRole';
|
||||||
import { CredentialsClient } from './CredentialsClient';
|
import { CredentialsClient } from './CredentialsClient';
|
||||||
import {
|
import {
|
||||||
areCredentialsValid,
|
|
||||||
errorMessage,
|
errorMessage,
|
||||||
exportAccountId,
|
exportAccountId,
|
||||||
exportCredentials,
|
exportCredentials,
|
||||||
exportRegion,
|
exportRegion,
|
||||||
getBooleanInput,
|
getBooleanInput,
|
||||||
|
getCallerIdentity,
|
||||||
retryAndBackoff,
|
retryAndBackoff,
|
||||||
toCredentialIdentity,
|
toCredentialIdentity,
|
||||||
translateEnvVariables,
|
translateEnvVariables,
|
||||||
@@ -53,8 +53,8 @@ export async function run() {
|
|||||||
});
|
});
|
||||||
const roleChaining = getBooleanInput('role-chaining', { required: false });
|
const roleChaining = getBooleanInput('role-chaining', { required: false });
|
||||||
const outputCredentials = getBooleanInput('output-credentials', { required: false });
|
const outputCredentials = getBooleanInput('output-credentials', { required: false });
|
||||||
// Default to always outputting environment credentials unless profile is specified. If profile is specified, default
|
// Default to always outputting environment credentials unless profile is specified. If profile is specified,
|
||||||
// to no environment credentials (but still output them if the user specifically requests it).
|
// default to no environment credentials (but still output them if the user specifically requests it).
|
||||||
const outputEnvCredentials = getBooleanInput('output-env-credentials', { required: false, default: !awsProfile });
|
const outputEnvCredentials = getBooleanInput('output-env-credentials', { required: false, default: !awsProfile });
|
||||||
const unsetCurrentCredentials = getBooleanInput('unset-current-credentials', { required: false });
|
const unsetCurrentCredentials = getBooleanInput('unset-current-credentials', { required: false });
|
||||||
let disableRetry = getBooleanInput('disable-retry', { required: false });
|
let disableRetry = getBooleanInput('disable-retry', { required: false });
|
||||||
@@ -165,8 +165,16 @@ export async function run() {
|
|||||||
|
|
||||||
//if the user wants to attempt to use existing credentials, check if we have some already
|
//if the user wants to attempt to use existing credentials, check if we have some already
|
||||||
if (useExistingCredentials) {
|
if (useExistingCredentials) {
|
||||||
const validCredentials = await areCredentialsValid(credentialsClient);
|
const identity = await (async () => {
|
||||||
if (validCredentials) {
|
try {
|
||||||
|
return await getCallerIdentity(credentialsClient.stsClient);
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
if (identity) {
|
||||||
|
// The allowed-account-ids guardrail applies to reused credentials too.
|
||||||
|
validateAccountId(expectedAccountIds, identity.Account);
|
||||||
core.notice('Pre-existing credentials are valid. No need to generate new ones.');
|
core.notice('Pre-existing credentials are valid. No need to generate new ones.');
|
||||||
if (timeoutId) clearTimeout(timeoutId);
|
if (timeoutId) clearTimeout(timeoutId);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1015,6 +1015,33 @@ describe('Configure AWS Credentials', {}, () => {
|
|||||||
await run();
|
await run();
|
||||||
expect(core.setFailed).not.toHaveBeenCalled();
|
expect(core.setFailed).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('fails on the use-existing-credentials path when the account is not allowed', async () => {
|
||||||
|
vi.mocked(core.getInput).mockImplementation(
|
||||||
|
mocks.getInput({
|
||||||
|
...mocks.USE_EXISTING_CREDENTIALS_INPUTS,
|
||||||
|
'allowed-account-ids': '999999999999',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
mockedSTSClient.on(GetCallerIdentityCommand).resolves({ ...mocks.outputs.GET_CALLER_IDENTITY });
|
||||||
|
|
||||||
|
await run();
|
||||||
|
expect(core.setFailed).toHaveBeenCalledWith(expect.stringContaining('does not match'));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('reuses existing credentials when their account is allowed', async () => {
|
||||||
|
vi.mocked(core.getInput).mockImplementation(
|
||||||
|
mocks.getInput({
|
||||||
|
...mocks.USE_EXISTING_CREDENTIALS_INPUTS,
|
||||||
|
'allowed-account-ids': '111111111111',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
mockedSTSClient.on(GetCallerIdentityCommand).resolves({ ...mocks.outputs.GET_CALLER_IDENTITY });
|
||||||
|
|
||||||
|
await run();
|
||||||
|
expect(core.notice).toHaveBeenCalledWith('Pre-existing credentials are valid. No need to generate new ones.');
|
||||||
|
expect(core.setFailed).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Global Timeout Configuration', {}, () => {
|
describe('Global Timeout Configuration', {}, () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user