@cloud-copilot/iam-collect
Version:
Collect IAM information from AWS Accounts
108 lines • 4.74 kB
JavaScript
import { fromIni, fromNodeProviderChain, fromTemporaryCredentials } from '@aws-sdk/credential-providers';
import { log } from '../utils/log.js';
import { randomCharacters } from '../utils/strings.js';
import { getTokenInfo } from './tokens.js';
/**
* What time is it now?
*
* This exists to make unit tests of caching behavior easier.
*
* @returns the current timestamp in milliseconds since the Unix epoch
*/
export function now() {
return Date.now();
}
/**
* Get brand new credentials for the given account ID and auth configuration.
*
* DO NOT USE THIS DIRECTLY. Use `getCredentials` in `auth.ts` instead
*
* @param accountId the AWS account ID for which to get credentials
* @param authConfig the authentication configuration to use for the account
* @returns new credentials based on the provided account ID and auth configuration
*/
export async function getNewCredentials(accountId, authConfig) {
const baseCredentials = await getNewInitialCredentials(authConfig, {
accountId
});
let credentials = baseCredentials;
if (authConfig?.role) {
const roleArn = `arn:${baseCredentials.partition}:iam::${accountId}:role/${authConfig.role.pathAndName}`;
log.trace({ accountId, roleArn, sourceAccount: baseCredentials.accountId }, 'Assuming role for account with credentials');
const roleProvider = fromTemporaryCredentials({
masterCredentials: baseCredentials,
params: {
RoleArn: roleArn,
ExternalId: authConfig.role.externalId,
RoleSessionName: authConfig.role.sessionName || `iam-collect-${randomCharacters()}`
}
});
const roleCredentials = await roleProvider();
credentials = {
...roleCredentials,
accountId: accountId,
partition: baseCredentials.partition
};
}
else if (baseCredentials.accountId != accountId) {
// If the account ID from the credentials doesn't match the expected account ID and no role is specified
// throw an error to indicate that the credentials do not match the expected account
log.error('Auth config, account mismatch', {
desiredAccountId: accountId,
currentAccountId: baseCredentials.accountId
});
throw new Error(`The credentials provided do not match the expected account ID ${accountId}. Found ${baseCredentials.accountId}. Please check your auth configuration.`);
}
return credentials;
}
/**
* This gets a new set of initial credentials for an auth configuration. These are the initial
* credentials that are the default credentials are used to then assume a role if one is specified.
* There are very few cases where this should be used directly, and in most cases you should use
* getNewCredentials instead.
*
* @param authConfig the authentication configuration to use
* @param logInfo any additional information to log while getting the credentials
* @returns new credentials based on the provided auth configuration
*/
export async function getNewInitialCredentials(authConfig, logInfo = {}) {
let credentials;
if (authConfig?.profile) {
log.trace({ ...logInfo, profile: authConfig.profile }, 'Using profile for credentials');
const provider = fromIni({ profile: authConfig.profile });
credentials = await provider();
}
else {
log.trace(logInfo, 'Using default SDK credential chain');
const provider = fromNodeProviderChain();
credentials = await provider();
}
let tokenInfo = await getTokenInfo(credentials);
log.trace('initial credentials', tokenInfo);
if (authConfig?.initialRole) {
let roleArn;
if ('arn' in authConfig?.initialRole) {
roleArn = authConfig.initialRole.arn;
}
else {
roleArn = `arn:${tokenInfo.partition}:iam::${tokenInfo.accountId}:role/${authConfig.initialRole.pathAndName}`;
}
log.trace({ roleArn, sourceAccount: tokenInfo.accountId, ...logInfo }, 'Assuming initial role for account with credentials');
const roleProvider = fromTemporaryCredentials({
masterCredentials: credentials,
params: {
RoleArn: roleArn,
ExternalId: authConfig.initialRole.externalId,
RoleSessionName: authConfig.initialRole.sessionName || `iam-collect-${randomCharacters()}`
}
});
credentials = await roleProvider();
tokenInfo = await getTokenInfo(credentials);
}
return {
...credentials,
accountId: tokenInfo.accountId,
partition: tokenInfo.partition
};
}
//# sourceMappingURL=coreAuth.js.map