UNPKG

@cloud-copilot/iam-collect

Version:

Collect IAM information from AWS Accounts

133 lines 5.86 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.now = now; exports.getNewCredentials = getNewCredentials; exports.getNewInitialCredentials = getNewInitialCredentials; exports.buildRoleArn = buildRoleArn; const credential_providers_1 = require("@aws-sdk/credential-providers"); const log_1 = require("@cloud-copilot/log"); const strings_js_1 = require("../utils/strings.js"); const tokens_js_1 = require("./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 */ 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 */ async function getNewCredentials(accountId, authConfig) { const cacheKey = await (0, strings_js_1.shortHash)(JSON.stringify({ accountId, authConfig })); const baseCredentials = await getNewInitialCredentials(authConfig, { accountId }); let credentials = baseCredentials; if (authConfig?.role) { const roleArn = buildRoleArn(baseCredentials.partition, accountId, authConfig.role.pathAndName); log_1.log.trace({ accountId, roleArn, sourceAccount: baseCredentials.accountId }, 'Assuming role for account with credentials'); const roleProvider = (0, credential_providers_1.fromTemporaryCredentials)({ masterCredentials: baseCredentials.provider, params: { RoleArn: roleArn, ExternalId: authConfig.role.externalId, RoleSessionName: authConfig.role.sessionName || `iam-collect-${(0, strings_js_1.randomCharacters)()}` } }); credentials = { cacheKey, provider: roleProvider, 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_1.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 */ async function getNewInitialCredentials(authConfig, logInfo = {}) { let provider; let credentials; const cacheKey = await (0, strings_js_1.shortHash)(JSON.stringify({ authConfig })); if (authConfig?.profile) { log_1.log.trace({ ...logInfo, profile: authConfig.profile }, 'Using profile for credentials'); provider = (0, credential_providers_1.fromIni)({ profile: authConfig.profile }); credentials = await provider(); } else { log_1.log.trace(logInfo, 'Using default SDK credential chain'); provider = (0, credential_providers_1.fromNodeProviderChain)(); credentials = await provider(); } let tokenInfo = await (0, tokens_js_1.getTokenInfo)(credentials); log_1.log.trace('initial credentials', tokenInfo); if (authConfig?.initialRole) { let roleArn; if ('arn' in authConfig?.initialRole) { roleArn = authConfig.initialRole.arn; } else { roleArn = buildRoleArn(tokenInfo.partition, tokenInfo.accountId, authConfig.initialRole.pathAndName); } log_1.log.trace({ roleArn, sourceAccount: tokenInfo.accountId, ...logInfo }, 'Assuming initial role for account with credentials'); const roleProvider = (0, credential_providers_1.fromTemporaryCredentials)({ masterCredentials: credentials, params: { RoleArn: roleArn, ExternalId: authConfig.initialRole.externalId, RoleSessionName: authConfig.initialRole.sessionName || `iam-collect-${(0, strings_js_1.randomCharacters)()}` } }); provider = roleProvider; credentials = await roleProvider(); tokenInfo = await (0, tokens_js_1.getTokenInfo)(credentials); } return { cacheKey, provider, accountId: tokenInfo.accountId, partition: tokenInfo.partition }; } /** * Get the ARN for an IAM role. * * @param partition The partition the role is in (e.g. "aws", "aws-us-gov", "aws-cn"). * @param accountId The ID of the account the role is in. * @param rolePathAndName The path and name of the role. * @returns The ARN of the role. */ function buildRoleArn(partition, accountId, rolePathAndName) { if (!rolePathAndName.startsWith('/')) { rolePathAndName = `/${rolePathAndName}`; } return `arn:${partition}:iam::${accountId}:role${rolePathAndName}`; } //# sourceMappingURL=coreAuth.js.map