feat: add config option for special character handling (#795)

This commit is contained in:
Tom Keller
2023-08-24 13:05:29 -07:00
committed by GitHub
parent ef93a73b13
commit fbbf385657
6 changed files with 105 additions and 74 deletions
+1 -4
View File
@@ -5,7 +5,7 @@ import * as core from '@actions/core';
import type { AssumeRoleCommandInput, STSClient, Tag } from '@aws-sdk/client-sts';
import { AssumeRoleCommand, AssumeRoleWithWebIdentityCommand } from '@aws-sdk/client-sts';
import type { CredentialsClient } from './CredentialsClient';
import { errorMessage, isDefined, sanitizeGitHubVariables, verifyKeys } from './helpers';
import { errorMessage, isDefined, sanitizeGitHubVariables } from './helpers';
async function assumeRoleWithOIDC(params: AssumeRoleCommandInput, client: STSClient, webIdentityToken: string) {
delete params.Tags;
@@ -17,7 +17,6 @@ async function assumeRoleWithOIDC(params: AssumeRoleCommandInput, client: STSCli
WebIdentityToken: webIdentityToken,
})
);
verifyKeys(creds.Credentials);
return creds;
} catch (error) {
throw new Error(`Could not assume role with OIDC: ${errorMessage(error)}`);
@@ -49,7 +48,6 @@ async function assumeRoleWithWebIdentityTokenFile(
WebIdentityToken: webIdentityToken,
})
);
verifyKeys(creds.Credentials);
return creds;
} catch (error) {
throw new Error(`Could not assume role with web identity token file: ${errorMessage(error)}`);
@@ -60,7 +58,6 @@ async function assumeRoleWithCredentials(params: AssumeRoleCommandInput, client:
core.info('Assuming role with user credentials');
try {
const creds = await client.send(new AssumeRoleCommand({ ...params }));
verifyKeys(creds.Credentials);
return creds;
} catch (error) {
throw new Error(`Could not assume role with user credentials: ${errorMessage(error)}`);
+6 -3
View File
@@ -93,18 +93,21 @@ export function reset() {
export function verifyKeys(creds: Partial<Credentials> | undefined) {
if (!creds) {
return;
return false;
}
if (creds.AccessKeyId) {
if (SPECIAL_CHARS_REGEX.test(creds.AccessKeyId)) {
throw new Error('AccessKeyId contains special characters.');
core.debug('AccessKeyId contains special characters.');
return false;
}
}
if (creds.SecretAccessKey) {
if (SPECIAL_CHARS_REGEX.test(creds.SecretAccessKey)) {
throw new Error('SecretAccessKey contains special characters.');
core.debug('SecretAccessKey contains special characters.');
return false;
}
}
return true;
}
// Retries the promise with exponential backoff if the error isRetryable up to maxRetries time.
+40 -22
View File
@@ -1,4 +1,5 @@
import * as core from '@actions/core';
import type { AssumeRoleCommandOutput } from '@aws-sdk/client-sts';
import { assumeRole } from './assumeRole';
import { CredentialsClient } from './CredentialsClient';
import {
@@ -8,6 +9,7 @@ import {
exportCredentials,
exportAccountId,
unsetCredentials,
verifyKeys,
} from './helpers';
const DEFAULT_ROLE_DURATION = 3600; // One hour (seconds)
@@ -43,10 +45,20 @@ export async function run() {
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';
let disableRetry = disableRetryInput.toLowerCase() === 'true';
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;
if (maxRetries < 1) {
maxRetries = 1;
switch (true) {
case specialCharacterWorkaround:
// 😳
maxRetries = Number.MAX_SAFE_INTEGER;
disableRetry = false;
break;
case maxRetries < 1:
maxRetries = 1;
break;
}
for (const managedSessionPolicy of managedSessionPoliciesInput) {
managedSessionPolicies.push({ arn: managedSessionPolicy });
@@ -129,25 +141,30 @@ 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,
});
},
!disableRetry,
maxRetries
);
let roleCredentials: AssumeRoleCommandOutput;
do {
// eslint-disable-next-line no-await-in-loop
roleCredentials = await retryAndBackoff(
async () => {
return assumeRole({
credentialsClient,
sourceAccountId,
roleToAssume,
roleExternalId,
roleDuration,
roleSessionName,
roleSkipSessionTagging,
webIdentityTokenFile,
webIdentityToken,
inlineSessionPolicy,
managedSessionPolicies,
});
},
!disableRetry,
maxRetries
);
// eslint-disable-next-line no-unmodified-loop-condition
} while (specialCharacterWorkaround && !verifyKeys(roleCredentials.Credentials));
core.info(`Authenticated as assumedRoleId ${roleCredentials.AssumedRoleUser!.AssumedRoleId!}`);
exportCredentials(roleCredentials.Credentials, outputCredentials);
// We need to validate the credentials in 2 of our use-cases
@@ -173,6 +190,7 @@ export async function run() {
}
/* c8 ignore start */
/* istanbul ignore next */
if (require.main === module) {
(async () => {
await run();