add output-env-credentials flag (defaults to true)

This commit is contained in:
Michael Lehmann
2025-06-04 14:04:20 -07:00
parent 151e7fee89
commit 308756d6c3
5 changed files with 59 additions and 41 deletions
+2 -1
View File
@@ -111,7 +111,8 @@ See [action.yml](./action.yml) for more detail.
| role-skip-session-tagging | Skips session tagging if set. | No | | role-skip-session-tagging | Skips session tagging if set. | No |
| inline-session-policy | You may further restrict the assumed role policy by defining an inline policy here. | No | | inline-session-policy | You may further restrict the assumed role policy by defining an inline policy here. | No |
| managed-session-policies | You may further restrict the assumed role policy by specifying a managed policy here. | No | | managed-session-policies | You may further restrict the assumed role policy by specifying a managed policy here. | No |
| output-credentials | When set, outputs fetched credentials as action step output. (Outputs access-key-id, secret-access-key, session-token, and expiration). Defaults to false. | No | | output-credentials | When set, outputs fetched credentials as action step output. (Outputs access-key-id, secret-access-key, session-token, and expiration). Defaults to false. | No |
| output-env-credentials | When set, exports fetched credentials as environment variables (AWS_REGION, AWS_DEFAULT_REGION, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN). Defaults to true. Set to false if you need to avoid setting/changing env variables. (You'd probably want to use output-credentials if you disable this). | No |
| unset-current-credentials | When set, attempts to unset any existing credentials in your action runner. | No | | unset-current-credentials | When set, attempts to unset any existing credentials in your action runner. | No |
| disable-retry | Disabled retry/backoff logic for assume role calls. By default, retries are enabled. | No | | disable-retry | Disabled retry/backoff logic for assume role calls. By default, retries are enabled. | No |
| retry-max-attempts | Limits the number of retry attempts before giving up. Defaults to 12. | No | | retry-max-attempts | Limits the number of retry attempts before giving up. Defaults to 12. | No |
+6
View File
@@ -61,6 +61,10 @@ inputs:
output-credentials: output-credentials:
description: Whether to set credentials as step output description: Whether to set credentials as step output
required: false required: false
output-env-credentials:
description: Whether to export credentials as environment variables. If you set this to false, you probably want to use output-credentials.
required: false
default: true
unset-current-credentials: unset-current-credentials:
description: Whether to unset the existing credentials in your runner. May be useful if you run this action multiple times in the same job description: Whether to unset the existing credentials in your runner. May be useful if you run this action multiple times in the same job
required: false required: false
@@ -84,3 +88,5 @@ outputs:
description: The AWS secret access key for the provided credentials description: The AWS secret access key for the provided credentials
aws-session-token: aws-session-token:
description: The AWS session token for the provided credentials description: The AWS session token for the provided credentials
aws-expiration:
description: The expiration time for the provided credentials
+15 -12
View File
@@ -13,18 +13,21 @@ import { errorMessage } from '../helpers';
*/ */
export function cleanup() { export function cleanup() {
try { const outputEnvCredentialsInput = core.getInput('output-env-credentials', { required: false }) || 'true';
// The GitHub Actions toolkit does not have an option to completely unset if (outputEnvCredentialsInput === 'true') {
// environment variables, so we overwrite the current value with an empty try {
// string. The AWS CLI and AWS SDKs will behave correctly: they treat an // The GitHub Actions toolkit does not have an option to completely unset
// empty string value as if the environment variable does not exist. // environment variables, so we overwrite the current value with an empty
core.exportVariable('AWS_ACCESS_KEY_ID', ''); // string. The AWS CLI and AWS SDKs will behave correctly: they treat an
core.exportVariable('AWS_SECRET_ACCESS_KEY', ''); // empty string value as if the environment variable does not exist.
core.exportVariable('AWS_SESSION_TOKEN', ''); core.exportVariable('AWS_ACCESS_KEY_ID', '');
core.exportVariable('AWS_DEFAULT_REGION', ''); core.exportVariable('AWS_SECRET_ACCESS_KEY', '');
core.exportVariable('AWS_REGION', ''); core.exportVariable('AWS_SESSION_TOKEN', '');
} catch (error) { core.exportVariable('AWS_DEFAULT_REGION', '');
core.setFailed(errorMessage(error)); core.exportVariable('AWS_REGION', '');
} catch (error) {
core.setFailed(errorMessage(error));
}
} }
} }
/* c8 ignore start */ /* c8 ignore start */
+30 -24
View File
@@ -39,23 +39,25 @@ export function translateEnvVariables() {
// Configure the AWS CLI and AWS SDKs using environment variables and set them as secrets. // 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 // Setting the credentials as secrets masks them in Github Actions logs
export function exportCredentials(creds?: Partial<Credentials>, outputCredentials?: boolean) { export function exportCredentials(creds?: Partial<Credentials>, outputCredentials?: boolean, outputEnvCredentials?: boolean) {
if (creds?.AccessKeyId) { if (outputEnvCredentials) {
core.setSecret(creds.AccessKeyId); if (creds?.AccessKeyId) {
core.exportVariable('AWS_ACCESS_KEY_ID', creds.AccessKeyId); core.setSecret(creds.AccessKeyId);
} core.exportVariable('AWS_ACCESS_KEY_ID', creds.AccessKeyId);
}
if (creds?.SecretAccessKey) { if (creds?.SecretAccessKey) {
core.setSecret(creds.SecretAccessKey); core.setSecret(creds.SecretAccessKey);
core.exportVariable('AWS_SECRET_ACCESS_KEY', creds.SecretAccessKey); core.exportVariable('AWS_SECRET_ACCESS_KEY', creds.SecretAccessKey);
} }
if (creds?.SessionToken) { if (creds?.SessionToken) {
core.setSecret(creds.SessionToken); core.setSecret(creds.SessionToken);
core.exportVariable('AWS_SESSION_TOKEN', 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 // clear session token from previous credentials action
core.exportVariable('AWS_SESSION_TOKEN', ''); core.exportVariable('AWS_SESSION_TOKEN', '');
}
} }
if (outputCredentials) { if (outputCredentials) {
@@ -74,17 +76,21 @@ export function exportCredentials(creds?: Partial<Credentials>, outputCredential
} }
} }
export function unsetCredentials() { export function unsetCredentials(outputEnvCredentials?: boolean) {
core.exportVariable('AWS_ACCESS_KEY_ID', ''); if (outputEnvCredentials) {
core.exportVariable('AWS_SECRET_ACCESS_KEY', ''); core.exportVariable('AWS_ACCESS_KEY_ID', '');
core.exportVariable('AWS_SESSION_TOKEN', ''); core.exportVariable('AWS_SECRET_ACCESS_KEY', '');
core.exportVariable('AWS_REGION', ''); core.exportVariable('AWS_SESSION_TOKEN', '');
core.exportVariable('AWS_DEFAULT_REGION', ''); core.exportVariable('AWS_REGION', '');
core.exportVariable('AWS_DEFAULT_REGION', '');
}
} }
export function exportRegion(region: string) { export function exportRegion(region: string, outputEnvCredentials?: boolean) {
core.exportVariable('AWS_DEFAULT_REGION', region); if (outputEnvCredentials) {
core.exportVariable('AWS_REGION', region); core.exportVariable('AWS_DEFAULT_REGION', region);
core.exportVariable('AWS_REGION', region);
}
} }
// Obtains account ID from STS Client and sets it as output // Obtains account ID from STS Client and sets it as output
+6 -4
View File
@@ -56,6 +56,8 @@ export async function run() {
const roleChaining = roleChainingInput.toLowerCase() === 'true'; const roleChaining = roleChainingInput.toLowerCase() === 'true';
const outputCredentialsInput = core.getInput('output-credentials', { required: false }) || 'false'; const outputCredentialsInput = core.getInput('output-credentials', { required: false }) || 'false';
const outputCredentials = outputCredentialsInput.toLowerCase() === 'true'; const outputCredentials = outputCredentialsInput.toLowerCase() === 'true';
const outputEnvCredentialsInput = core.getInput('output-env-credentials', { required: false }) || 'true';
const outputEnvCredentials = outputEnvCredentialsInput.toLowerCase() === 'true';
const unsetCurrentCredentialsInput = core.getInput('unset-current-credentials', { required: false }) || 'false'; const unsetCurrentCredentialsInput = core.getInput('unset-current-credentials', { required: false }) || 'false';
const unsetCurrentCredentials = unsetCurrentCredentialsInput.toLowerCase() === 'true'; const unsetCurrentCredentials = unsetCurrentCredentialsInput.toLowerCase() === 'true';
const disableRetryInput = core.getInput('disable-retry', { required: false }) || 'false'; const disableRetryInput = core.getInput('disable-retry', { required: false }) || 'false';
@@ -108,13 +110,13 @@ export async function run() {
}; };
if (unsetCurrentCredentials) { if (unsetCurrentCredentials) {
unsetCredentials(); unsetCredentials(outputEnvCredentials);
} }
if (!region.match(REGION_REGEX)) { if (!region.match(REGION_REGEX)) {
throw new Error(`Region is not valid: ${region}`); throw new Error(`Region is not valid: ${region}`);
} }
exportRegion(region); exportRegion(region, outputEnvCredentials);
// Instantiate credentials client // Instantiate credentials client
const credentialsClient = new CredentialsClient({ region, proxyServer }); const credentialsClient = new CredentialsClient({ region, proxyServer });
@@ -153,7 +155,7 @@ export async function run() {
// Plus, in the assume role case, if the AssumeRole call fails, we want // Plus, in the assume role case, if the AssumeRole call fails, we want
// the source credentials to already be masked as secrets // the source credentials to already be masked as secrets
// in any error messages. // in any error messages.
exportCredentials({ AccessKeyId, SecretAccessKey, SessionToken }); exportCredentials({ AccessKeyId, SecretAccessKey, SessionToken }, outputCredentials, outputEnvCredentials);
} else if (!webIdentityTokenFile && !roleChaining) { } else if (!webIdentityTokenFile && !roleChaining) {
// Proceed only if credentials can be picked up // Proceed only if credentials can be picked up
await credentialsClient.validateCredentials(); await credentialsClient.validateCredentials();
@@ -193,7 +195,7 @@ export async function run() {
); );
} while (specialCharacterWorkaround && !verifyKeys(roleCredentials.Credentials)); } 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); exportCredentials(roleCredentials.Credentials, outputCredentials, outputEnvCredentials);
// We need to validate the credentials in 2 of our use-cases // We need to validate the credentials in 2 of our use-cases
// First: self-hosted runners. If the GITHUB_ACTIONS environment variable // First: self-hosted runners. If the GITHUB_ACTIONS environment variable
// is set to `true` then we are NOT in a self-hosted runner. // is set to `true` then we are NOT in a self-hosted runner.