mirror of
https://github.com/aws-actions/configure-aws-credentials.git
synced 2026-09-02 05:55:10 +09:00
chore: migrate to biomejs (#1167)
* chore: migrate to biomejs * chore: migrate to biomejs * chore: migrate from jest to vitest * chore: error on lint warnings * chore: remove obsolete depedencies
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { info } from '@actions/core';
|
||||
import { STSClient } from '@aws-sdk/client-sts';
|
||||
import type { AwsCredentialIdentity } from '@aws-sdk/types';
|
||||
import { NodeHttpHandler } from '@smithy/node-http-handler';
|
||||
import { HttpsProxyAgent } from 'https-proxy-agent';
|
||||
import { errorMessage } from './helpers';
|
||||
@@ -40,7 +41,7 @@ export class CredentialsClient {
|
||||
}
|
||||
|
||||
public async validateCredentials(expectedAccessKeyId?: string, roleChaining?: boolean) {
|
||||
let credentials;
|
||||
let credentials: AwsCredentialIdentity;
|
||||
try {
|
||||
credentials = await this.loadCredentials();
|
||||
if (!credentials.accessKeyId) {
|
||||
@@ -55,7 +56,7 @@ export class CredentialsClient {
|
||||
|
||||
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'
|
||||
'Unexpected failure: Credentials loaded by the SDK do not match the access key ID configured by the action',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+19
-15
@@ -1,6 +1,6 @@
|
||||
import assert from 'assert';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import assert from 'node:assert';
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import * as core from '@actions/core';
|
||||
import type { AssumeRoleCommandInput, STSClient, Tag } from '@aws-sdk/client-sts';
|
||||
import { AssumeRoleCommand, AssumeRoleWithWebIdentityCommand } from '@aws-sdk/client-sts';
|
||||
@@ -15,7 +15,7 @@ async function assumeRoleWithOIDC(params: AssumeRoleCommandInput, client: STSCli
|
||||
new AssumeRoleWithWebIdentityCommand({
|
||||
...params,
|
||||
WebIdentityToken: webIdentityToken,
|
||||
})
|
||||
}),
|
||||
);
|
||||
return creds;
|
||||
} catch (error) {
|
||||
@@ -27,10 +27,10 @@ async function assumeRoleWithWebIdentityTokenFile(
|
||||
params: AssumeRoleCommandInput,
|
||||
client: STSClient,
|
||||
webIdentityTokenFile: string,
|
||||
workspace: string
|
||||
workspace: string,
|
||||
) {
|
||||
core.debug(
|
||||
'webIdentityTokenFile provided. Will call sts:AssumeRoleWithWebIdentity and take session tags from token contents.'
|
||||
'webIdentityTokenFile provided. Will call sts:AssumeRoleWithWebIdentity and take session tags from token contents.',
|
||||
);
|
||||
const webIdentityTokenFilePath = path.isAbsolute(webIdentityTokenFile)
|
||||
? webIdentityTokenFile
|
||||
@@ -46,7 +46,7 @@ async function assumeRoleWithWebIdentityTokenFile(
|
||||
new AssumeRoleWithWebIdentityCommand({
|
||||
...params,
|
||||
WebIdentityToken: webIdentityToken,
|
||||
})
|
||||
}),
|
||||
);
|
||||
return creds;
|
||||
} catch (error) {
|
||||
@@ -75,7 +75,7 @@ export interface assumeRoleParams {
|
||||
webIdentityTokenFile?: string;
|
||||
webIdentityToken?: string;
|
||||
inlineSessionPolicy?: string;
|
||||
managedSessionPolicies?: any[];
|
||||
managedSessionPolicies?: { arn: string }[];
|
||||
}
|
||||
|
||||
export async function assumeRole(params: assumeRoleParams) {
|
||||
@@ -108,8 +108,11 @@ export async function assumeRole(params: assumeRoleParams) {
|
||||
{ Key: 'Actor', Value: sanitizeGitHubVariables(GITHUB_ACTOR) },
|
||||
{ Key: 'Commit', Value: GITHUB_SHA },
|
||||
];
|
||||
if (process.env['GITHUB_REF']) {
|
||||
tagArray.push({ Key: 'Branch', Value: sanitizeGitHubVariables(process.env['GITHUB_REF']) });
|
||||
if (process.env.GITHUB_REF) {
|
||||
tagArray.push({
|
||||
Key: 'Branch',
|
||||
Value: sanitizeGitHubVariables(process.env.GITHUB_REF),
|
||||
});
|
||||
}
|
||||
const tags = roleSkipSessionTagging ? undefined : tagArray;
|
||||
if (!tags) {
|
||||
@@ -123,7 +126,7 @@ export async function assumeRole(params: assumeRoleParams) {
|
||||
if (!roleArn.startsWith('arn:aws')) {
|
||||
assert(
|
||||
isDefined(sourceAccountId),
|
||||
'Source Account ID is needed if the Role Name is provided and not the Role Arn.'
|
||||
'Source Account ID is needed if the Role Name is provided and not the Role Arn.',
|
||||
);
|
||||
roleArn = `arn:aws:iam::${sourceAccountId}:role/${roleArn}`;
|
||||
}
|
||||
@@ -139,6 +142,7 @@ export async function assumeRole(params: assumeRoleParams) {
|
||||
PolicyArns: managedSessionPolicies?.length ? managedSessionPolicies : undefined,
|
||||
};
|
||||
const keys = Object.keys(commonAssumeRoleParams) as Array<keyof typeof commonAssumeRoleParams>;
|
||||
// biome-ignore lint/complexity/noForEach: Legacy code
|
||||
keys.forEach((k) => commonAssumeRoleParams[k] === undefined && delete commonAssumeRoleParams[k]);
|
||||
|
||||
// Instantiate STS client
|
||||
@@ -147,14 +151,14 @@ export async function assumeRole(params: assumeRoleParams) {
|
||||
// Assume role using one of three methods
|
||||
if (!!webIdentityToken) {
|
||||
return assumeRoleWithOIDC(commonAssumeRoleParams, stsClient, webIdentityToken);
|
||||
} else if (!!webIdentityTokenFile) {
|
||||
}
|
||||
if (!!webIdentityTokenFile) {
|
||||
return assumeRoleWithWebIdentityTokenFile(
|
||||
commonAssumeRoleParams,
|
||||
stsClient,
|
||||
webIdentityTokenFile,
|
||||
GITHUB_WORKSPACE
|
||||
GITHUB_WORKSPACE,
|
||||
);
|
||||
} else {
|
||||
return assumeRoleWithCredentials(commonAssumeRoleParams, stsClient);
|
||||
}
|
||||
return assumeRoleWithCredentials(commonAssumeRoleParams, stsClient);
|
||||
}
|
||||
|
||||
+4
-3
@@ -23,7 +23,7 @@ export function exportCredentials(creds?: Partial<Credentials>, outputCredential
|
||||
if (creds?.SessionToken) {
|
||||
core.setSecret(creds.SessionToken);
|
||||
core.exportVariable('AWS_SESSION_TOKEN', creds.SessionToken);
|
||||
} else if (process.env['AWS_SESSION_TOKEN']) {
|
||||
} else if (process.env.AWS_SESSION_TOKEN) {
|
||||
// clear session token from previous credentials action
|
||||
core.exportVariable('AWS_SESSION_TOKEN', '');
|
||||
}
|
||||
@@ -116,7 +116,7 @@ export async function retryAndBackoff<T>(
|
||||
isRetryable: boolean,
|
||||
maxRetries = 12,
|
||||
retries = 0,
|
||||
base = 50
|
||||
base = 50,
|
||||
): Promise<T> {
|
||||
try {
|
||||
return await fn();
|
||||
@@ -125,7 +125,8 @@ export async function retryAndBackoff<T>(
|
||||
throw err;
|
||||
}
|
||||
// It's retryable, so sleep and retry.
|
||||
await sleep(Math.random() * (Math.pow(2, retries) * base));
|
||||
await sleep(Math.random() * (2 ** retries * base));
|
||||
// biome-ignore lint/style/noParameterAssign: This is a loop variable
|
||||
retries += 1;
|
||||
if (retries >= maxRetries) {
|
||||
throw err;
|
||||
|
||||
+31
-22
@@ -1,13 +1,13 @@
|
||||
import * as core from '@actions/core';
|
||||
import type { AssumeRoleCommandOutput } from '@aws-sdk/client-sts';
|
||||
import { assumeRole } from './assumeRole';
|
||||
import { CredentialsClient } from './CredentialsClient';
|
||||
import { assumeRole } from './assumeRole';
|
||||
import {
|
||||
errorMessage,
|
||||
retryAndBackoff,
|
||||
exportRegion,
|
||||
exportCredentials,
|
||||
exportAccountId,
|
||||
exportCredentials,
|
||||
exportRegion,
|
||||
retryAndBackoff,
|
||||
unsetCredentials,
|
||||
verifyKeys,
|
||||
} from './helpers';
|
||||
@@ -20,24 +20,35 @@ export async function run() {
|
||||
try {
|
||||
// Get inputs
|
||||
const AccessKeyId = core.getInput('aws-access-key-id', { required: false });
|
||||
const SecretAccessKey = core.getInput('aws-secret-access-key', { required: false });
|
||||
const sessionTokenInput = core.getInput('aws-session-token', { required: false });
|
||||
const SecretAccessKey = core.getInput('aws-secret-access-key', {
|
||||
required: false,
|
||||
});
|
||||
const sessionTokenInput = core.getInput('aws-session-token', {
|
||||
required: false,
|
||||
});
|
||||
const SessionToken = sessionTokenInput === '' ? undefined : sessionTokenInput;
|
||||
const region = core.getInput('aws-region', { required: true });
|
||||
const roleToAssume = core.getInput('role-to-assume', { required: false });
|
||||
const audience = core.getInput('audience', { required: false });
|
||||
const maskAccountIdInput = core.getInput('mask-aws-account-id', { required: false }) || 'false';
|
||||
const maskAccountId = maskAccountIdInput.toLowerCase() === 'true';
|
||||
const roleExternalId = core.getInput('role-external-id', { required: false });
|
||||
const webIdentityTokenFile = core.getInput('web-identity-token-file', { required: false });
|
||||
const roleDuration = parseInt(core.getInput('role-duration-seconds', { required: false })) || DEFAULT_ROLE_DURATION;
|
||||
const roleExternalId = core.getInput('role-external-id', {
|
||||
required: false,
|
||||
});
|
||||
const webIdentityTokenFile = core.getInput('web-identity-token-file', {
|
||||
required: false,
|
||||
});
|
||||
const roleDuration =
|
||||
Number.parseInt(core.getInput('role-duration-seconds', { required: false })) || DEFAULT_ROLE_DURATION;
|
||||
const roleSessionName = core.getInput('role-session-name', { required: false }) || ROLE_SESSION_NAME;
|
||||
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 inlineSessionPolicy = core.getInput('inline-session-policy', { required: false });
|
||||
const inlineSessionPolicy = core.getInput('inline-session-policy', {
|
||||
required: false,
|
||||
});
|
||||
const managedSessionPoliciesInput = core.getMultilineInput('managed-session-policies', { required: false });
|
||||
const managedSessionPolicies: any[] = [];
|
||||
const managedSessionPolicies: { arn: string }[] = [];
|
||||
const roleChainingInput = core.getInput('role-chaining', { required: false }) || 'false';
|
||||
const roleChaining = roleChainingInput.toLowerCase() === 'true';
|
||||
const outputCredentialsInput = core.getInput('output-credentials', { required: false }) || 'false';
|
||||
@@ -49,7 +60,7 @@ export async function run() {
|
||||
const specialCharacterWorkaroundInput =
|
||||
core.getInput('special-characters-workaround', { required: false }) || 'false';
|
||||
const specialCharacterWorkaround = specialCharacterWorkaroundInput.toLowerCase() === 'true';
|
||||
let maxRetries = parseInt(core.getInput('retry-max-attempts', { required: false })) || 12;
|
||||
let maxRetries = Number.parseInt(core.getInput('retry-max-attempts', { required: false })) || 12;
|
||||
switch (true) {
|
||||
case specialCharacterWorkaround:
|
||||
// 😳
|
||||
@@ -74,17 +85,17 @@ export async function run() {
|
||||
!!roleToAssume &&
|
||||
!webIdentityTokenFile &&
|
||||
!AccessKeyId &&
|
||||
!process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN'] &&
|
||||
!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? ' +
|
||||
'If you are not trying to authenticate with OIDC and the action is working successfully, you can ignore this message.'
|
||||
'If you are not trying to authenticate with OIDC and the action is working successfully, you can ignore this message.',
|
||||
);
|
||||
}
|
||||
return (
|
||||
!!roleToAssume &&
|
||||
!!process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN'] &&
|
||||
!!process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN &&
|
||||
!AccessKeyId &&
|
||||
!webIdentityTokenFile &&
|
||||
!roleChaining
|
||||
@@ -114,7 +125,7 @@ export async function run() {
|
||||
return core.getIDToken(audience);
|
||||
},
|
||||
!disableRetry,
|
||||
maxRetries
|
||||
maxRetries,
|
||||
);
|
||||
} catch (error) {
|
||||
throw new Error(`getIDToken call failed: ${errorMessage(error)}`);
|
||||
@@ -146,7 +157,6 @@ export async function run() {
|
||||
if (roleToAssume) {
|
||||
let roleCredentials: AssumeRoleCommandOutput;
|
||||
do {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
roleCredentials = await retryAndBackoff(
|
||||
async () => {
|
||||
return assumeRole({
|
||||
@@ -164,17 +174,16 @@ export async function run() {
|
||||
});
|
||||
},
|
||||
!disableRetry,
|
||||
maxRetries
|
||||
maxRetries,
|
||||
);
|
||||
// eslint-disable-next-line no-unmodified-loop-condition
|
||||
} while (specialCharacterWorkaround && !verifyKeys(roleCredentials.Credentials));
|
||||
core.info(`Authenticated as assumedRoleId ${roleCredentials.AssumedRoleUser!.AssumedRoleId!}`);
|
||||
core.info(`Authenticated as assumedRoleId ${roleCredentials.AssumedRoleUser?.AssumedRoleId}`);
|
||||
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.
|
||||
// Second: Customer provided credentials manually (IAM User keys stored in GH Secrets)
|
||||
if (!process.env['GITHUB_ACTIONS'] || AccessKeyId) {
|
||||
if (!process.env.GITHUB_ACTIONS || AccessKeyId) {
|
||||
await credentialsClient.validateCredentials(roleCredentials.Credentials?.AccessKeyId);
|
||||
}
|
||||
await exportAccountId(credentialsClient, maskAccountId);
|
||||
@@ -184,7 +193,7 @@ export async function run() {
|
||||
} catch (error) {
|
||||
core.setFailed(errorMessage(error));
|
||||
|
||||
const showStackTrace = process.env['SHOW_STACK_TRACE'];
|
||||
const showStackTrace = process.env.SHOW_STACK_TRACE;
|
||||
|
||||
if (showStackTrace === 'true') {
|
||||
throw error;
|
||||
|
||||
Reference in New Issue
Block a user