feat: support account id allowlist (#1456)

* feat: support account id allowlist

* chore: update readme

---------

Co-authored-by: Michael Lehmann <lehmanmj@amazon.com>
This commit is contained in:
Tom Keller
2025-09-02 10:38:09 -07:00
committed by GitHub
parent c5a43c32e1
commit c4be498953
6 changed files with 202 additions and 14 deletions
+22 -4
View File
@@ -3,7 +3,7 @@ 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';
import { errorMessage, getCallerIdentity } from './helpers';
const USER_AGENT = 'configure-aws-credentials-for-github-actions';
@@ -40,7 +40,11 @@ export class CredentialsClient {
return this._stsClient;
}
public async validateCredentials(expectedAccessKeyId?: string, roleChaining?: boolean) {
public async validateCredentials(
expectedAccessKeyId?: string,
roleChaining?: boolean,
expectedAccountIds?: string[],
) {
let credentials: AwsCredentialIdentity;
try {
credentials = await this.loadCredentials();
@@ -50,13 +54,27 @@ export class CredentialsClient {
} catch (error) {
throw new Error(`Credentials could not be loaded, please check your action inputs: ${errorMessage(error)}`);
}
if (expectedAccountIds && expectedAccountIds.length > 0 && expectedAccountIds[0] !== '') {
let callerIdentity: Awaited<ReturnType<typeof getCallerIdentity>>;
try {
callerIdentity = await getCallerIdentity(this.stsClient);
} catch (error) {
throw new Error(`Could not validate account ID of credentials: ${errorMessage(error)}`);
}
if (!callerIdentity.Account || !expectedAccountIds.includes(callerIdentity.Account)) {
throw new Error(
`The account ID of the provided credentials (${
callerIdentity.Account ?? 'unknown'
}) does not match any of the expected account IDs: ${expectedAccountIds.join(', ')}`,
);
}
}
if (!roleChaining) {
const actualAccessKeyId = credentials.accessKeyId;
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',
'Credentials loaded by the SDK do not match the expected access key ID configured by the action',
);
}
}