implement last changes for vNext
This commit is contained in:
parent
256d740e71
commit
aa2675f083
8 changed files with 858 additions and 677 deletions
|
|
@ -107,6 +107,7 @@ overrides:
|
|||
'@typescript-eslint/prefer-includes': [warn]
|
||||
dot-notation: [off]
|
||||
'@typescript-eslint/dot-notation': [error]
|
||||
'@typescript-eslint/no-explicit-any': [off]
|
||||
'@typescript-eslint/consistent-type-exports': [warn]
|
||||
'@typescript-eslint/consistent-type-imports': [warn]
|
||||
'@typescript-eslint/no-base-to-string': [error]
|
||||
|
|
|
|||
15
action.yml
15
action.yml
|
|
@ -34,9 +34,6 @@ inputs:
|
|||
description: The audience to use for the OIDC provider
|
||||
required: false
|
||||
default: sts.amazonaws.com
|
||||
disable-oidc:
|
||||
description: Strictly disable action from attempting to fetch credentials with OIDC
|
||||
required: false
|
||||
http-proxy:
|
||||
description: 'Proxy to use for the AWS SDK agent'
|
||||
required: false
|
||||
|
|
@ -61,6 +58,18 @@ inputs:
|
|||
managed-session-policies:
|
||||
description: 'List of managed session policies'
|
||||
required: false
|
||||
output-credentials:
|
||||
description: Whether to set credentials as step output
|
||||
required: false
|
||||
unset-current-credentials:
|
||||
description: Whether to unset the existing credentials in your runner
|
||||
required: false
|
||||
disable-retry:
|
||||
description: Whether to disable the retry and backoff mechanism when the assume role call fails
|
||||
required: false
|
||||
retry-max-attempts:
|
||||
description: The maximum number of attempts it will attempt to retry the assume role call
|
||||
required: false
|
||||
outputs:
|
||||
aws-account-id:
|
||||
description: The AWS account ID for the provided credentials
|
||||
|
|
|
|||
27
dist/cleanup/index.js
generated
vendored
27
dist/cleanup/index.js
generated
vendored
|
|
@ -17583,14 +17583,14 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.isDefined = exports.errorMessage = exports.retryAndBackoff = exports.reset = exports.withsleep = exports.defaultSleep = exports.sanitizeGitHubVariables = exports.exportAccountId = exports.exportRegion = exports.exportCredentials = void 0;
|
||||
exports.isDefined = exports.errorMessage = exports.retryAndBackoff = exports.reset = exports.withsleep = exports.defaultSleep = exports.sanitizeGitHubVariables = exports.exportAccountId = exports.exportRegion = exports.unsetCredentials = exports.exportCredentials = void 0;
|
||||
const core = __importStar(__nccwpck_require__(2186));
|
||||
const client_sts_1 = __nccwpck_require__(2209);
|
||||
const MAX_TAG_VALUE_LENGTH = 256;
|
||||
const SANITIZATION_CHARACTER = '_';
|
||||
// Configure the AWS CLI and AWS SDKs using environment variables and set them as secrets.
|
||||
// Setting the credentials as secrets masks them in Github Actions logs
|
||||
function exportCredentials(creds) {
|
||||
function exportCredentials(creds, outputCredentials) {
|
||||
if (creds?.AccessKeyId) {
|
||||
core.setSecret(creds.AccessKeyId);
|
||||
core.exportVariable('AWS_ACCESS_KEY_ID', creds.AccessKeyId);
|
||||
|
|
@ -17607,8 +17607,27 @@ function exportCredentials(creds) {
|
|||
// clear session token from previous credentials action
|
||||
core.exportVariable('AWS_SESSION_TOKEN', '');
|
||||
}
|
||||
if (outputCredentials) {
|
||||
if (creds?.AccessKeyId) {
|
||||
core.setOutput('aws-access-key-id', creds.AccessKeyId);
|
||||
}
|
||||
if (creds?.SecretAccessKey) {
|
||||
core.setOutput('aws-secret-access-key', creds.SecretAccessKey);
|
||||
}
|
||||
if (creds?.SessionToken) {
|
||||
core.setOutput('aws-session-token', creds.SessionToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.exportCredentials = exportCredentials;
|
||||
function unsetCredentials() {
|
||||
core.exportVariable('AWS_ACCESS_KEY_ID', '');
|
||||
core.exportVariable('AWS_SECRET_ACCESS_KEY', '');
|
||||
core.exportVariable('AWS_SESSION_TOKEN', '');
|
||||
core.exportVariable('AWS_REGION', '');
|
||||
core.exportVariable('AWS_DEFAULT_REGION', '');
|
||||
}
|
||||
exports.unsetCredentials = unsetCredentials;
|
||||
function exportRegion(region) {
|
||||
core.exportVariable('AWS_DEFAULT_REGION', region);
|
||||
core.exportVariable('AWS_REGION', region);
|
||||
|
|
@ -17652,7 +17671,7 @@ function reset() {
|
|||
}
|
||||
exports.reset = reset;
|
||||
// Retries the promise with exponential backoff if the error isRetryable up to maxRetries time.
|
||||
async function retryAndBackoff(fn, isRetryable, retries = 0, maxRetries = 12, base = 50) {
|
||||
async function retryAndBackoff(fn, isRetryable, maxRetries = 12, retries = 0, base = 50) {
|
||||
try {
|
||||
return await fn();
|
||||
}
|
||||
|
|
@ -17666,7 +17685,7 @@ async function retryAndBackoff(fn, isRetryable, retries = 0, maxRetries = 12, ba
|
|||
if (retries === maxRetries) {
|
||||
throw err;
|
||||
}
|
||||
return await retryAndBackoff(fn, isRetryable, retries, maxRetries, base);
|
||||
return await retryAndBackoff(fn, isRetryable, maxRetries, retries, base);
|
||||
}
|
||||
}
|
||||
exports.retryAndBackoff = retryAndBackoff;
|
||||
|
|
|
|||
5
dist/cleanup/src/helpers.d.ts
generated
vendored
5
dist/cleanup/src/helpers.d.ts
generated
vendored
|
|
@ -1,6 +1,7 @@
|
|||
import type { Credentials } from '@aws-sdk/client-sts';
|
||||
import type { CredentialsClient } from './CredentialsClient';
|
||||
export declare function exportCredentials(creds?: Partial<Credentials>): void;
|
||||
export declare function exportCredentials(creds?: Partial<Credentials>, outputCredentials?: boolean): void;
|
||||
export declare function unsetCredentials(): void;
|
||||
export declare function exportRegion(region: string): void;
|
||||
export declare function exportAccountId(credentialsClient: CredentialsClient, maskAccountId?: boolean): Promise<string>;
|
||||
export declare function sanitizeGitHubVariables(name: string): string;
|
||||
|
|
@ -8,7 +9,7 @@ export declare function defaultSleep(ms: number): Promise<unknown>;
|
|||
declare let sleep: typeof defaultSleep;
|
||||
export declare function withsleep(s: typeof sleep): void;
|
||||
export declare function reset(): void;
|
||||
export declare function retryAndBackoff<T>(fn: () => Promise<T>, isRetryable: boolean, retries?: number, maxRetries?: number, base?: number): Promise<T>;
|
||||
export declare function retryAndBackoff<T>(fn: () => Promise<T>, isRetryable: boolean, maxRetries?: number, retries?: number, base?: number): Promise<T>;
|
||||
export declare function errorMessage(error: unknown): string;
|
||||
export declare function isDefined<T>(i: T | undefined | null): i is T;
|
||||
export {};
|
||||
|
|
|
|||
46
dist/index.js
generated
vendored
46
dist/index.js
generated
vendored
|
|
@ -241,14 +241,14 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.isDefined = exports.errorMessage = exports.retryAndBackoff = exports.reset = exports.withsleep = exports.defaultSleep = exports.sanitizeGitHubVariables = exports.exportAccountId = exports.exportRegion = exports.exportCredentials = void 0;
|
||||
exports.isDefined = exports.errorMessage = exports.retryAndBackoff = exports.reset = exports.withsleep = exports.defaultSleep = exports.sanitizeGitHubVariables = exports.exportAccountId = exports.exportRegion = exports.unsetCredentials = exports.exportCredentials = void 0;
|
||||
const core = __importStar(__nccwpck_require__(2186));
|
||||
const client_sts_1 = __nccwpck_require__(2209);
|
||||
const MAX_TAG_VALUE_LENGTH = 256;
|
||||
const SANITIZATION_CHARACTER = '_';
|
||||
// Configure the AWS CLI and AWS SDKs using environment variables and set them as secrets.
|
||||
// Setting the credentials as secrets masks them in Github Actions logs
|
||||
function exportCredentials(creds) {
|
||||
function exportCredentials(creds, outputCredentials) {
|
||||
if (creds?.AccessKeyId) {
|
||||
core.setSecret(creds.AccessKeyId);
|
||||
core.exportVariable('AWS_ACCESS_KEY_ID', creds.AccessKeyId);
|
||||
|
|
@ -265,8 +265,27 @@ function exportCredentials(creds) {
|
|||
// clear session token from previous credentials action
|
||||
core.exportVariable('AWS_SESSION_TOKEN', '');
|
||||
}
|
||||
if (outputCredentials) {
|
||||
if (creds?.AccessKeyId) {
|
||||
core.setOutput('aws-access-key-id', creds.AccessKeyId);
|
||||
}
|
||||
if (creds?.SecretAccessKey) {
|
||||
core.setOutput('aws-secret-access-key', creds.SecretAccessKey);
|
||||
}
|
||||
if (creds?.SessionToken) {
|
||||
core.setOutput('aws-session-token', creds.SessionToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.exportCredentials = exportCredentials;
|
||||
function unsetCredentials() {
|
||||
core.exportVariable('AWS_ACCESS_KEY_ID', '');
|
||||
core.exportVariable('AWS_SECRET_ACCESS_KEY', '');
|
||||
core.exportVariable('AWS_SESSION_TOKEN', '');
|
||||
core.exportVariable('AWS_REGION', '');
|
||||
core.exportVariable('AWS_DEFAULT_REGION', '');
|
||||
}
|
||||
exports.unsetCredentials = unsetCredentials;
|
||||
function exportRegion(region) {
|
||||
core.exportVariable('AWS_DEFAULT_REGION', region);
|
||||
core.exportVariable('AWS_REGION', region);
|
||||
|
|
@ -310,7 +329,7 @@ function reset() {
|
|||
}
|
||||
exports.reset = reset;
|
||||
// Retries the promise with exponential backoff if the error isRetryable up to maxRetries time.
|
||||
async function retryAndBackoff(fn, isRetryable, retries = 0, maxRetries = 12, base = 50) {
|
||||
async function retryAndBackoff(fn, isRetryable, maxRetries = 12, retries = 0, base = 50) {
|
||||
try {
|
||||
return await fn();
|
||||
}
|
||||
|
|
@ -324,7 +343,7 @@ async function retryAndBackoff(fn, isRetryable, retries = 0, maxRetries = 12, ba
|
|||
if (retries === maxRetries) {
|
||||
throw err;
|
||||
}
|
||||
return await retryAndBackoff(fn, isRetryable, retries, maxRetries, base);
|
||||
return await retryAndBackoff(fn, isRetryable, maxRetries, retries, base);
|
||||
}
|
||||
}
|
||||
exports.retryAndBackoff = retryAndBackoff;
|
||||
|
|
@ -398,12 +417,18 @@ async function run() {
|
|||
const roleSkipSessionTaggingInput = core.getInput('role-skip-session-tagging', { required: false }) || 'false';
|
||||
const roleSkipSessionTagging = roleSkipSessionTaggingInput.toLowerCase() === 'true';
|
||||
const proxyServer = core.getInput('http-proxy', { required: false });
|
||||
const disableOIDC = core.getInput('disable-oidc', { required: false });
|
||||
const inlineSessionPolicy = core.getInput('inline-session-policy', { required: false });
|
||||
const managedSessionPoliciesInput = core.getMultilineInput('managed-session-policies', { required: false });
|
||||
const managedSessionPolicies = [];
|
||||
const roleChainingInput = core.getInput('role-chaining', { required: false }) || 'false';
|
||||
const roleChaining = roleChainingInput.toLowerCase() === 'true';
|
||||
const outputCredentialsInput = core.getInput('output-credentials', { required: false }) || 'false';
|
||||
const outputCredentials = outputCredentialsInput.toLowerCase() === 'true';
|
||||
const unsetCurrentCredentialsInput = core.getInput('unset-current-credentials', { required: false }) || 'false';
|
||||
const unsetCurrentCredentials = unsetCurrentCredentialsInput.toLowerCase() === 'true';
|
||||
const disableRetryInput = core.getInput('disable-retry', { required: false }) || 'false';
|
||||
const disableRetry = disableRetryInput.toLowerCase() === 'true';
|
||||
const maxRetries = parseInt(core.getInput('retry-max-attempts', { required: false })) || 12;
|
||||
for (const managedSessionPolicy of managedSessionPoliciesInput) {
|
||||
managedSessionPolicies.push({ arn: managedSessionPolicy });
|
||||
}
|
||||
|
|
@ -412,11 +437,10 @@ async function run() {
|
|||
// The `ACTIONS_ID_TOKEN_REQUEST_TOKEN` environment variable is set when the `id-token` permission is granted.
|
||||
// This is necessary to authenticate with OIDC, but not strictly set just for OIDC. If it is not set and all other
|
||||
// checks pass, it is likely but not guaranteed that the user needs but lacks this permission in their workflow.
|
||||
// So, we will log a warning when it is the only piece absent, as well as add an opportunity to manually disable the entire check.
|
||||
// So, we will log a warning when it is the only piece absent
|
||||
if (!!roleToAssume &&
|
||||
!webIdentityTokenFile &&
|
||||
!AccessKeyId &&
|
||||
!disableOIDC &&
|
||||
!process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN'] &&
|
||||
!roleChaining) {
|
||||
core.info('It looks like you might be trying to authenticate with OIDC. Did you mean to set the `id-token` permission?');
|
||||
|
|
@ -425,9 +449,11 @@ async function run() {
|
|||
!!process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN'] &&
|
||||
!AccessKeyId &&
|
||||
!webIdentityTokenFile &&
|
||||
!disableOIDC &&
|
||||
!roleChaining);
|
||||
};
|
||||
if (unsetCurrentCredentials) {
|
||||
(0, helpers_1.unsetCredentials)();
|
||||
}
|
||||
if (!region.match(REGION_REGEX)) {
|
||||
throw new Error(`Region is not valid: ${region}`);
|
||||
}
|
||||
|
|
@ -477,9 +503,9 @@ async function run() {
|
|||
inlineSessionPolicy,
|
||||
managedSessionPolicies,
|
||||
});
|
||||
}, true);
|
||||
}, !disableRetry, maxRetries);
|
||||
core.info(`Authenticated as assumedRoleId ${roleCredentials.AssumedRoleUser.AssumedRoleId}`);
|
||||
(0, helpers_1.exportCredentials)(roleCredentials.Credentials);
|
||||
(0, helpers_1.exportCredentials)(roleCredentials.Credentials, outputCredentials);
|
||||
// We need to validate the credentials in 2 of our use-cases
|
||||
// First: self-hosted runners. If the GITHUB_ACTIONS environment variable
|
||||
// is set to `true` then we are NOT in a self-hosted runner.
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ const SANITIZATION_CHARACTER = '_';
|
|||
|
||||
// Configure the AWS CLI and AWS SDKs using environment variables and set them as secrets.
|
||||
// Setting the credentials as secrets masks them in Github Actions logs
|
||||
export function exportCredentials(creds?: Partial<Credentials>) {
|
||||
export function exportCredentials(creds?: Partial<Credentials>, outputCredentials?: boolean) {
|
||||
if (creds?.AccessKeyId) {
|
||||
core.setSecret(creds.AccessKeyId);
|
||||
core.exportVariable('AWS_ACCESS_KEY_ID', creds.AccessKeyId);
|
||||
|
|
@ -26,6 +26,26 @@ export function exportCredentials(creds?: Partial<Credentials>) {
|
|||
// clear session token from previous credentials action
|
||||
core.exportVariable('AWS_SESSION_TOKEN', '');
|
||||
}
|
||||
|
||||
if (outputCredentials) {
|
||||
if (creds?.AccessKeyId) {
|
||||
core.setOutput('aws-access-key-id', creds.AccessKeyId);
|
||||
}
|
||||
if (creds?.SecretAccessKey) {
|
||||
core.setOutput('aws-secret-access-key', creds.SecretAccessKey);
|
||||
}
|
||||
if (creds?.SessionToken) {
|
||||
core.setOutput('aws-session-token', creds.SessionToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function unsetCredentials() {
|
||||
core.exportVariable('AWS_ACCESS_KEY_ID', '');
|
||||
core.exportVariable('AWS_SECRET_ACCESS_KEY', '');
|
||||
core.exportVariable('AWS_SESSION_TOKEN', '');
|
||||
core.exportVariable('AWS_REGION', '');
|
||||
core.exportVariable('AWS_DEFAULT_REGION', '');
|
||||
}
|
||||
|
||||
export function exportRegion(region: string) {
|
||||
|
|
@ -74,8 +94,8 @@ export function reset() {
|
|||
export async function retryAndBackoff<T>(
|
||||
fn: () => Promise<T>,
|
||||
isRetryable: boolean,
|
||||
retries = 0,
|
||||
maxRetries = 12,
|
||||
retries = 0,
|
||||
base = 50
|
||||
): Promise<T> {
|
||||
try {
|
||||
|
|
@ -90,7 +110,7 @@ export async function retryAndBackoff<T>(
|
|||
if (retries === maxRetries) {
|
||||
throw err;
|
||||
}
|
||||
return await retryAndBackoff(fn, isRetryable, retries, maxRetries, base);
|
||||
return await retryAndBackoff(fn, isRetryable, maxRetries, retries, base);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
61
src/index.ts
61
src/index.ts
|
|
@ -1,7 +1,14 @@
|
|||
import * as core from '@actions/core';
|
||||
import { assumeRole } from './assumeRole';
|
||||
import { CredentialsClient } from './CredentialsClient';
|
||||
import { errorMessage, retryAndBackoff, exportRegion, exportCredentials, exportAccountId } from './helpers';
|
||||
import {
|
||||
errorMessage,
|
||||
retryAndBackoff,
|
||||
exportRegion,
|
||||
exportCredentials,
|
||||
exportAccountId,
|
||||
unsetCredentials,
|
||||
} from './helpers';
|
||||
|
||||
const DEFAULT_ROLE_DURATION = 3600; // One hour (seconds)
|
||||
const ROLE_SESSION_NAME = 'GitHubActions';
|
||||
|
|
@ -26,12 +33,18 @@ export async function run() {
|
|||
const roleSkipSessionTaggingInput = core.getInput('role-skip-session-tagging', { required: false }) || 'false';
|
||||
const roleSkipSessionTagging = roleSkipSessionTaggingInput.toLowerCase() === 'true';
|
||||
const proxyServer = core.getInput('http-proxy', { required: false });
|
||||
const disableOIDC = core.getInput('disable-oidc', { required: false });
|
||||
const inlineSessionPolicy = core.getInput('inline-session-policy', { required: false });
|
||||
const managedSessionPoliciesInput = core.getMultilineInput('managed-session-policies', { required: false });
|
||||
const managedSessionPolicies: any[] = [];
|
||||
const roleChainingInput = core.getInput('role-chaining', { required: false }) || 'false';
|
||||
const roleChaining = roleChainingInput.toLowerCase() === 'true';
|
||||
const outputCredentialsInput = core.getInput('output-credentials', { required: false }) || 'false';
|
||||
const outputCredentials = outputCredentialsInput.toLowerCase() === 'true';
|
||||
const unsetCurrentCredentialsInput = core.getInput('unset-current-credentials', { required: false }) || 'false';
|
||||
const unsetCurrentCredentials = unsetCurrentCredentialsInput.toLowerCase() === 'true';
|
||||
const disableRetryInput = core.getInput('disable-retry', { required: false }) || 'false';
|
||||
const disableRetry = disableRetryInput.toLowerCase() === 'true';
|
||||
const maxRetries = parseInt(core.getInput('retry-max-attempts', { required: false })) || 12;
|
||||
for (const managedSessionPolicy of managedSessionPoliciesInput) {
|
||||
managedSessionPolicies.push({ arn: managedSessionPolicy });
|
||||
}
|
||||
|
|
@ -41,12 +54,11 @@ export async function run() {
|
|||
// The `ACTIONS_ID_TOKEN_REQUEST_TOKEN` environment variable is set when the `id-token` permission is granted.
|
||||
// This is necessary to authenticate with OIDC, but not strictly set just for OIDC. If it is not set and all other
|
||||
// checks pass, it is likely but not guaranteed that the user needs but lacks this permission in their workflow.
|
||||
// So, we will log a warning when it is the only piece absent, as well as add an opportunity to manually disable the entire check.
|
||||
// So, we will log a warning when it is the only piece absent
|
||||
if (
|
||||
!!roleToAssume &&
|
||||
!webIdentityTokenFile &&
|
||||
!AccessKeyId &&
|
||||
!disableOIDC &&
|
||||
!process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN'] &&
|
||||
!roleChaining
|
||||
) {
|
||||
|
|
@ -59,11 +71,14 @@ export async function run() {
|
|||
!!process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN'] &&
|
||||
!AccessKeyId &&
|
||||
!webIdentityTokenFile &&
|
||||
!disableOIDC &&
|
||||
!roleChaining
|
||||
);
|
||||
};
|
||||
|
||||
if (unsetCurrentCredentials) {
|
||||
unsetCredentials();
|
||||
}
|
||||
|
||||
if (!region.match(REGION_REGEX)) {
|
||||
throw new Error(`Region is not valid: ${region}`);
|
||||
}
|
||||
|
|
@ -101,23 +116,27 @@ export async function run() {
|
|||
|
||||
// Get role credentials if configured to do so
|
||||
if (roleToAssume) {
|
||||
const roleCredentials = await retryAndBackoff(async () => {
|
||||
return assumeRole({
|
||||
credentialsClient,
|
||||
sourceAccountId,
|
||||
roleToAssume,
|
||||
roleExternalId,
|
||||
roleDuration,
|
||||
roleSessionName,
|
||||
roleSkipSessionTagging,
|
||||
webIdentityTokenFile,
|
||||
webIdentityToken,
|
||||
inlineSessionPolicy,
|
||||
managedSessionPolicies,
|
||||
});
|
||||
}, true);
|
||||
const roleCredentials = await retryAndBackoff(
|
||||
async () => {
|
||||
return assumeRole({
|
||||
credentialsClient,
|
||||
sourceAccountId,
|
||||
roleToAssume,
|
||||
roleExternalId,
|
||||
roleDuration,
|
||||
roleSessionName,
|
||||
roleSkipSessionTagging,
|
||||
webIdentityTokenFile,
|
||||
webIdentityToken,
|
||||
inlineSessionPolicy,
|
||||
managedSessionPolicies,
|
||||
});
|
||||
},
|
||||
!disableRetry,
|
||||
maxRetries
|
||||
);
|
||||
core.info(`Authenticated as assumedRoleId ${roleCredentials.AssumedRoleUser!.AssumedRoleId!}`);
|
||||
exportCredentials(roleCredentials.Credentials);
|
||||
exportCredentials(roleCredentials.Credentials, outputCredentials);
|
||||
// We need to validate the credentials in 2 of our use-cases
|
||||
// First: self-hosted runners. If the GITHUB_ACTIONS environment variable
|
||||
// is set to `true` then we are NOT in a self-hosted runner.
|
||||
|
|
|
|||
|
|
@ -23,6 +23,10 @@ const FAKE_ACCOUNT_ID = '123456789012';
|
|||
const FAKE_ROLE_ACCOUNT_ID = '111111111111';
|
||||
const ROLE_NAME = 'MY-ROLE';
|
||||
const ROLE_ARN = 'arn:aws:iam::111111111111:role/MY-ROLE';
|
||||
const MANAGED_SESSION_POLICY_INPUT = [
|
||||
'arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess',
|
||||
'arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess',
|
||||
];
|
||||
const ENVIRONMENT_VARIABLE_OVERRIDES = {
|
||||
SHOW_STACK_TRACE: 'false',
|
||||
GITHUB_REPOSITORY: 'MY-REPOSITORY-NAME',
|
||||
|
|
@ -54,6 +58,12 @@ function mockGetInput(requestResponse: Record<string, string>) {
|
|||
};
|
||||
}
|
||||
|
||||
function mockGetMultilineInput(requestResponse: Record<string, string[]>) {
|
||||
return function (name: string, _options: unknown): string[] {
|
||||
return requestResponse[name]!;
|
||||
};
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
||||
jest.mock('fs', () => ({
|
||||
...jest.requireActual('fs'),
|
||||
|
|
@ -481,6 +491,40 @@ describe('Configure AWS Credentials', () => {
|
|||
expect(mockedSTS.commandCalls(AssumeRoleWithWebIdentityCommand).length).toEqual(12);
|
||||
});
|
||||
|
||||
test('role assumption fails after one trial when disabling retry', async () => {
|
||||
process.env['GITHUB_ACTIONS'] = 'true';
|
||||
process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN'] = 'test-token';
|
||||
jest
|
||||
.spyOn(core, 'getInput')
|
||||
.mockImplementation(
|
||||
mockGetInput({ 'role-to-assume': ROLE_ARN, 'aws-region': FAKE_REGION, 'disable-retry': 'true' })
|
||||
);
|
||||
|
||||
mockedSTS.reset();
|
||||
mockedSTS.on(AssumeRoleWithWebIdentityCommand).rejects();
|
||||
|
||||
await run();
|
||||
expect(mockedSTS.commandCalls(AssumeRoleWithWebIdentityCommand).length).toEqual(1);
|
||||
});
|
||||
|
||||
test('max retries is configurable', async () => {
|
||||
process.env['GITHUB_ACTIONS'] = 'true';
|
||||
process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN'] = 'test-token';
|
||||
jest.spyOn(core, 'getInput').mockImplementation(
|
||||
mockGetInput({
|
||||
'role-to-assume': ROLE_ARN,
|
||||
'aws-region': FAKE_REGION,
|
||||
'retry-max-attempts': '15',
|
||||
})
|
||||
);
|
||||
|
||||
mockedSTS.reset();
|
||||
mockedSTS.on(AssumeRoleWithWebIdentityCommand).rejects();
|
||||
|
||||
await run();
|
||||
expect(mockedSTS.commandCalls(AssumeRoleWithWebIdentityCommand).length).toEqual(15);
|
||||
});
|
||||
|
||||
test('role external ID provided', async () => {
|
||||
jest
|
||||
.spyOn(core, 'getInput')
|
||||
|
|
@ -614,4 +658,46 @@ describe('Configure AWS Credentials', () => {
|
|||
|
||||
expect(core.exportVariable).toReturn();
|
||||
});
|
||||
|
||||
test('inline policy and managed session policies are provided in assume role calls', async () => {
|
||||
jest
|
||||
.spyOn(core, 'getInput')
|
||||
.mockImplementation(mockGetInput({ ...ASSUME_ROLE_INPUTS, 'inline-session-policy': 'inline' }));
|
||||
|
||||
jest
|
||||
.spyOn(core, 'getMultilineInput')
|
||||
.mockImplementation(mockGetMultilineInput({ 'managed-session-policies': MANAGED_SESSION_POLICY_INPUT }));
|
||||
|
||||
await run();
|
||||
|
||||
expect(mockedSTS.commandCalls(AssumeRoleCommand)[0]?.args[0].input).toEqual({
|
||||
RoleArn: ROLE_ARN,
|
||||
RoleSessionName: 'GitHubActions',
|
||||
DurationSeconds: 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: 'Commit', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_SHA },
|
||||
{ Key: 'Branch', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_REF },
|
||||
],
|
||||
Policy: 'inline',
|
||||
PolicyArns: [
|
||||
{ arn: 'arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess' },
|
||||
{ arn: 'arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess' },
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
test('unsets credentials if enabled', async () => {
|
||||
jest
|
||||
.spyOn(core, 'getInput')
|
||||
.mockImplementation(mockGetInput({ ...ASSUME_ROLE_INPUTS, 'unset-current-credentials': 'true' }));
|
||||
|
||||
await run();
|
||||
|
||||
expect(core.exportVariable).toHaveBeenCalledTimes(9);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue