diff --git a/packages/amplify-category-function/src/provider-utils/awscloudformation/secrets/ssmClientWrapper.ts b/packages/amplify-category-function/src/provider-utils/awscloudformation/secrets/ssmClientWrapper.ts index e5979795d0a..00a08df2b27 100644 --- a/packages/amplify-category-function/src/provider-utils/awscloudformation/secrets/ssmClientWrapper.ts +++ b/packages/amplify-category-function/src/provider-utils/awscloudformation/secrets/ssmClientWrapper.ts @@ -102,8 +102,15 @@ export class SSMClientWrapper { const getSSMClient = async (context: $TSContext) => { const spinner = ora('Initializing SSM Client'); - spinner.start(); - const { client } = await context.amplify.invokePluginMethod(context, 'awscloudformation', undefined, 'getConfiguredSSMClient', [context]); - spinner.stop(); - return client as aws.SSM; + try { + spinner.start(); + + const { client } = await context.amplify.invokePluginMethod(context, 'awscloudformation', undefined, 'getConfiguredSSMClient', [ + context, + ]); + + return client as aws.SSM; + } finally { + spinner.stop(); + } }; diff --git a/packages/amplify-cli/src/extensions/amplify-helpers/delete-project.ts b/packages/amplify-cli/src/extensions/amplify-helpers/delete-project.ts index c46f38dcb47..e76ef9d19c2 100644 --- a/packages/amplify-cli/src/extensions/amplify-helpers/delete-project.ts +++ b/packages/amplify-cli/src/extensions/amplify-helpers/delete-project.ts @@ -35,10 +35,10 @@ export async function deleteProject(context) { } } } catch (ex) { - spinner.fail('Project delete failed'); + spinner.fail('Project delete failed.'); throw ex; } - spinner.succeed('Project deleted in the cloud'); + spinner.succeed('Project deleted in the cloud.'); // Remove amplify dir const { frontend } = context.amplify.getProjectConfig(); const frontendPlugins = getFrontendPlugins(context); diff --git a/packages/amplify-cli/src/extensions/amplify-helpers/remove-env-from-cloud.ts b/packages/amplify-cli/src/extensions/amplify-helpers/remove-env-from-cloud.ts index 5c1b82792fd..92b1da9de63 100644 --- a/packages/amplify-cli/src/extensions/amplify-helpers/remove-env-from-cloud.ts +++ b/packages/amplify-cli/src/extensions/amplify-helpers/remove-env-from-cloud.ts @@ -8,7 +8,7 @@ export async function removeEnvFromCloud(context, envName, deleteS3) { const providerPlugins = getProviderPlugins(context); const providerPromises: (() => Promise)[] = []; context.print.info(''); - context.print.info(`Deleting env:${envName}`); + context.print.info(`Deleting env: ${envName}.`); // Pinpoint attaches an IAM policy to several roles, which blocks CFN from // deleting the roles. Work around that by deleting Pinpoint first. @@ -28,7 +28,7 @@ export async function removeEnvFromCloud(context, envName, deleteS3) { await raiseIntenralOnlyPostEnvRemoveEvent(context, envName); } catch (e) { context.print.info(''); - context.print.error(`Error in deleting env:${envName}`); + context.print.error(`Error occurred while deleting env: ${envName}.`); context.print.info(e.message); throw e; } diff --git a/packages/amplify-cli/src/init-steps/preInitSetup.ts b/packages/amplify-cli/src/init-steps/preInitSetup.ts index 31da845c098..51cd0d4a103 100644 --- a/packages/amplify-cli/src/init-steps/preInitSetup.ts +++ b/packages/amplify-cli/src/init-steps/preInitSetup.ts @@ -1,4 +1,4 @@ -import { $TSContext, exitOnNextTick, getPackageManager, NonEmptyDirectoryError } from 'amplify-cli-core'; +import { $TSContext, exitOnNextTick, getPackageManager, NonEmptyDirectoryError, pathManager } from 'amplify-cli-core'; import { execSync } from 'child_process'; import * as fs from 'fs-extra'; import * as url from 'url'; @@ -12,6 +12,7 @@ export async function preInitSetup(context: $TSContext) { await validateGithubRepo(context, repoUrl); await cloneRepo(context, repoUrl); + cleanAmplifyArtifacts(); await installPackage(); await setLocalEnvDefaults(context); } @@ -93,5 +94,18 @@ async function setLocalEnvDefaults(context: $TSContext) { context.exeInfo.inputParams.amplify.envName = envName; - await generateLocalEnvInfoFile(context); + generateLocalEnvInfoFile(context); +} + +/** + * After cloning a project, remove the environment specific, perhaps accidentally checked in Amplify state files + * to make sure further commands will run correctly, like 'amplify delete' + */ +function cleanAmplifyArtifacts() { + const projectPath = process.cwd(); + + fs.removeSync(pathManager.getAmplifyMetaFilePath(projectPath)); + fs.removeSync(pathManager.getTeamProviderInfoFilePath(projectPath)); + fs.removeSync(pathManager.getLocalAWSInfoFilePath(projectPath)); + fs.removeSync(pathManager.getLocalEnvFilePath(projectPath)); } diff --git a/packages/amplify-provider-awscloudformation/src/amplify-service-manager.js b/packages/amplify-provider-awscloudformation/src/amplify-service-manager.js index 03dd70c8a55..d72fb0b80d2 100644 --- a/packages/amplify-provider-awscloudformation/src/amplify-service-manager.js +++ b/packages/amplify-provider-awscloudformation/src/amplify-service-manager.js @@ -12,13 +12,13 @@ const { loadConfigurationForEnv } = require('./configuration-manager'); const logger = fileLogger('amplify-service-manager'); async function init(amplifyServiceParams) { - const { context, awsConfig, projectName, envName, stackName } = amplifyServiceParams; + const { context, awsConfigInfo, projectName, envName, stackName } = amplifyServiceParams; let amplifyAppId; let verifiedStackName = stackName; let deploymentBucketName = `${stackName}-deployment`; - const amplifyClient = await getConfiguredAmplifyClient(context, awsConfig); + const amplifyClient = await getConfiguredAmplifyClient(context, awsConfigInfo); if (!amplifyClient) { // This happens when the Amplify service is not available in the region return { @@ -74,7 +74,7 @@ async function init(amplifyServiceParams) { for (let env of envList) { if ( env !== envName && - teamProviderInfo[env][ProviderName].Region === awsConfig.region && + teamProviderInfo[env][ProviderName].Region === awsConfigInfo.region && teamProviderInfo[env][ProviderName][AmplifyAppIdLabel] && !appIdsInTheSameLocalProjectAndRegion.includes(teamProviderInfo[env][ProviderName][AmplifyAppIdLabel]) ) { @@ -108,7 +108,7 @@ async function init(amplifyServiceParams) { if (appIdsInTheSameLocalProjectAndRegion.length === 1) { amplifyAppId = appIdsInTheSameLocalProjectAndRegion[0]; // eslint-disable-line } else if (appIdsInTheSameLocalProjectAndRegion.length > 1) { - context.print.info(`Your project is associated with multiple Amplify Service Apps in the region ${awsConfig.region}`); + context.print.info(`Your project is associated with multiple Amplify Service Apps in the region ${awsConfigInfo.region}`); amplifyAppId = await SelectFromExistingAppId(context, appIdsInTheSameLocalProjectAndRegion); } } @@ -204,7 +204,7 @@ async function init(amplifyServiceParams) { }; } -async function deleteEnv(context, envName, awsConfig) { +async function deleteEnv(context, envName, awsConfigInfo) { if (stateManager.teamProviderInfoExists()) { const teamProviderInfo = stateManager.getTeamProviderInfo(); if ( @@ -213,7 +213,7 @@ async function deleteEnv(context, envName, awsConfig) { teamProviderInfo[envName][ProviderName][AmplifyAppIdLabel] ) { const envConfig = await loadConfigurationForEnv(context, envName); - const amplifyClient = await getConfiguredAmplifyClient(context, { ...awsConfig, ...envConfig }); + const amplifyClient = await getConfiguredAmplifyClient(context, { ...awsConfigInfo, ...envConfig }); if (!amplifyClient) { // This happens when the Amplify service is not available in the region return; @@ -235,7 +235,12 @@ async function deleteEnv(context, envName, awsConfig) { await amplifyClient.deleteBackendEnvironment(deleteEnvParams).promise(); } catch (ex) { log(ex); - throw ex; + + if (ex.code === 'NotFoundException') { + context.print.warning(ex.message); + } else { + throw ex; + } } } } diff --git a/packages/amplify-provider-awscloudformation/src/amplify-service-migrate.js b/packages/amplify-provider-awscloudformation/src/amplify-service-migrate.js index 4152d65e860..ff2f00ba4df 100644 --- a/packages/amplify-provider-awscloudformation/src/amplify-service-migrate.js +++ b/packages/amplify-provider-awscloudformation/src/amplify-service-migrate.js @@ -11,7 +11,7 @@ async function run(context) { let projectDetails; let currentAmplifyMetaFilePath; let currentAmplifyMeta; - let awsConfig; + let awsConfigInfo; let isProjectFullySetUp = false; @@ -19,7 +19,7 @@ async function run(context) { projectDetails = context.amplify.getProjectDetails(); currentAmplifyMetaFilePath = context.amplify.pathManager.getCurrentAmplifyMetaFilePath(); currentAmplifyMeta = context.amplify.readJsonFile(currentAmplifyMetaFilePath); - awsConfig = await configurationManager.getAwsConfig(context); + awsConfigInfo = await configurationManager.getAwsConfig(context); isProjectFullySetUp = true; } catch (e) { isProjectFullySetUp = false; @@ -38,10 +38,10 @@ async function run(context) { return; } - const amplifyClient = await getConfiguredAmplifyClient(context, awsConfig); + const amplifyClient = await getConfiguredAmplifyClient(context, awsConfigInfo); if (!amplifyClient) { // This happens when the Amplify service is not available in the region - const message = `Amplify service is not available in the region ${awsConfig.region ? awsConfig.region : ''}`; + const message = `Amplify service is not available in the region ${awsConfigInfo.region ? awsConfigInfo.region : ''}`; context.print.error(message); throw new Error(message); } diff --git a/packages/amplify-provider-awscloudformation/src/attach-backend.js b/packages/amplify-provider-awscloudformation/src/attach-backend.js index ba56cfacb52..e423a526775 100644 --- a/packages/amplify-provider-awscloudformation/src/attach-backend.js +++ b/packages/amplify-provider-awscloudformation/src/attach-backend.js @@ -18,7 +18,7 @@ const logger = fileLogger('attach-backend'); async function run(context) { let appId; - let awsConfig; + let awsConfigInfo; let isAdminApp = false; try { appId = resolveAppId(context); @@ -44,20 +44,20 @@ async function run(context) { } if (isAdminApp) { - context.exeInfo.awsConfig = { + context.exeInfo.awsConfigInfo = { configLevel: 'amplifyAdmin', config: {}, }; - awsConfig = await configurationManager.loadConfigurationForEnv(context, envName, appId); + awsConfigInfo = await configurationManager.loadConfigurationForEnv(context, envName, appId); } else { await configurationManager.init(context); - awsConfig = await configurationManager.getAwsConfig(context); + awsConfigInfo = await configurationManager.getAwsConfig(context); } - const amplifyClient = await getConfiguredAmplifyClient(context, awsConfig); + const amplifyClient = await getConfiguredAmplifyClient(context, awsConfigInfo); if (!amplifyClient) { // This happens when the Amplify service is not available in the region - const region = awsConfig && awsConfig.region ? awsConfig.region : ''; + const region = awsConfigInfo && awsConfigInfo.region ? awsConfigInfo.region : ''; const message = `Amplify service is not available in the region ${region}`; context.print.error(message); throw new Error(message); @@ -74,15 +74,15 @@ async function run(context) { const backendEnv = await getBackendEnv(context, amplifyClient, amplifyApp); - await downloadBackend(context, backendEnv, awsConfig); - const currentAmplifyMeta = await ensureAmplifyMeta(context, amplifyApp, awsConfig); + await downloadBackend(context, backendEnv, awsConfigInfo); + const currentAmplifyMeta = await ensureAmplifyMeta(context, amplifyApp, awsConfigInfo); context.exeInfo.projectConfig.projectName = amplifyApp.name; context.exeInfo.localEnvInfo.envName = backendEnv.environmentName; context.exeInfo.teamProviderInfo[backendEnv.environmentName] = currentAmplifyMeta.providers; } -async function ensureAmplifyMeta(context, amplifyApp, awsConfig) { +async function ensureAmplifyMeta(context, amplifyApp, awsConfigInfo) { // check if appId is present in the provider section of the metadata // if not, it's a migration case and we need to // 1. insert the appId @@ -99,15 +99,15 @@ async function ensureAmplifyMeta(context, amplifyApp, awsConfig) { fs.writeFileSync(amplifyMetaFilePath, jsonString, 'utf8'); const { DeploymentBucketName } = currentAmplifyMeta.providers[constants.ProviderName]; - await storeArtifactsForAmplifyService(context, awsConfig, DeploymentBucketName); + await storeArtifactsForAmplifyService(context, awsConfigInfo, DeploymentBucketName); } return currentAmplifyMeta; } -async function storeArtifactsForAmplifyService(context, awsConfig, deploymentBucketName) { +async function storeArtifactsForAmplifyService(context, awsConfigInfo, deploymentBucketName) { const projectPath = process.cwd(); - const s3Client = new aws.S3(awsConfig); + const s3Client = new aws.S3(awsConfigInfo); const amplifyMetaFilePath = context.amplify.pathManager.getCurrentAmplifyMetaFilePath(projectPath); const backendConfigFilePath = context.amplify.pathManager.getCurrentBackendConfigFilePath(projectPath); await uploadFile(s3Client, deploymentBucketName, amplifyMetaFilePath); @@ -297,7 +297,7 @@ async function getBackendEnv(context, amplifyClient, amplifyApp) { throw ex; } -async function downloadBackend(context, backendEnv, awsConfig) { +async function downloadBackend(context, backendEnv, awsConfigInfo) { if (!backendEnv) { return; } @@ -308,7 +308,7 @@ async function downloadBackend(context, backendEnv, awsConfig) { const backendDir = context.amplify.pathManager.getBackendDirPath(projectPath); const zipFileName = constants.S3BackendZipFileName; - const s3Client = new aws.S3(awsConfig); + const s3Client = new aws.S3(awsConfigInfo); const deploymentBucketName = backendEnv.deploymentArtifacts; const params = { diff --git a/packages/amplify-provider-awscloudformation/src/configuration-manager.ts b/packages/amplify-provider-awscloudformation/src/configuration-manager.ts index ecd5df7b444..99152eb3b97 100644 --- a/packages/amplify-provider-awscloudformation/src/configuration-manager.ts +++ b/packages/amplify-provider-awscloudformation/src/configuration-manager.ts @@ -64,6 +64,11 @@ export async function init(context: $TSContext) { configLevel: 'project', config: { useProfile: false }, }; + } else if (authTypeConfig.type === 'general') { + context.exeInfo.awsConfigInfo = { + configLevel: 'general', + config: {}, + }; } else { context.exeInfo.awsConfigInfo = { configLevel: 'project', @@ -522,7 +527,7 @@ function getCurrentConfig(context: $TSContext) { } function getConfigForEnv(context: $TSContext, envName: string) { - const projectConfigInfo: ProjectConfig = context?.exeInfo?.awsConfig || { + const projectConfigInfo: ProjectConfig = context?.exeInfo?.awsConfigInfo || { configLevel: 'general', config: {}, }; @@ -599,11 +604,13 @@ function loadConfigFromPath(profilePath: string): AwsSdkConfig { export async function loadConfigurationForEnv(context: $TSContext, env: string, appId?: string): Promise { const { awsConfigInfo } = context.exeInfo || {}; + if (awsConfigInfo?.config?.accessKeyId && awsConfigInfo?.config?.secretAccessKey) { // Already loaded config if (!awsConfigInfo.region) { awsConfigInfo.region = resolveRegion(); } + return awsConfigInfo.config; } @@ -614,6 +621,7 @@ export async function loadConfigurationForEnv(context: $TSContext, env: string, if (authType.type === 'admin') { projectConfigInfo.configLevel = 'amplifyAdmin'; appId = appId || authType.appId; + try { awsConfig = await getTempCredsWithAdminTokens(context, appId); } catch (e) { @@ -632,6 +640,7 @@ export async function loadConfigurationForEnv(context: $TSContext, env: string, } else if (authType.type === 'accessKeys') { awsConfig = loadConfigFromPath(projectConfigInfo.config.awsConfigFilePath); } + return awsConfig; } @@ -649,6 +658,7 @@ export function resolveRegion(): string { // For details of how aws region is set, check the following link // https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/setting-region.html let region: string; + if (process.env.AWS_REGION) { region = process.env.AWS_REGION; } @@ -659,6 +669,7 @@ export function resolveRegion(): string { const profileName = process.env.AWS_PROFILE || 'default'; region = systemConfigManager.getProfileRegion(profileName); } + return region; } @@ -694,6 +705,7 @@ async function newUserCheck(context: $TSContext) { function scanConfig(context: $TSContext) { let configSource: string = getConfigLevel(context); + if (!configSource) { const namedProfiles: $TSAny = systemConfigManager.getNamedProfiles(); if (namedProfiles && Object.keys(namedProfiles).length > 0) { @@ -715,6 +727,7 @@ function scanConfig(context: $TSContext) { function getConfigLevel(context: $TSContext): ProjectType { let configLevel: ProjectType; + try { const namedProfiles = systemConfigManager.getNamedProfiles(); const configInfoFilePath = pathManager.getLocalAWSInfoFilePath(); @@ -738,6 +751,7 @@ function getConfigLevel(context: $TSContext): ProjectType { } catch (e) { // no need to do anything } + return configLevel; } @@ -745,18 +759,19 @@ export async function getAwsConfig(context: $TSContext): Promise { const { awsConfigInfo } = context.exeInfo; const httpProxy = process.env.HTTP_PROXY || process.env.HTTPS_PROXY; - let awsConfig: AwsSdkConfig; + let resultAWSConfigInfo: AwsSdkConfig; + if (awsConfigInfo.configLevel === 'project') { if (awsConfigInfo.config.useProfile) { try { - awsConfig = await systemConfigManager.getProfiledAwsConfig(context, awsConfigInfo.config.profileName); + resultAWSConfigInfo = await systemConfigManager.getProfiledAwsConfig(context, awsConfigInfo.config.profileName); } catch (e) { context.print.error(`Failed to get profile: ${e.message || e}`); await context.usageData.emitError(e); exitOnNextTick(1); } } else { - awsConfig = { + resultAWSConfigInfo = { accessKeyId: awsConfigInfo.config.accessKeyId, secretAccessKey: awsConfigInfo.config.secretAccessKey, region: awsConfigInfo.config.region, @@ -765,7 +780,7 @@ export async function getAwsConfig(context: $TSContext): Promise { } else if (awsConfigInfo.configLevel === 'amplifyAdmin') { const appId = resolveAppId(context); try { - awsConfig = await getTempCredsWithAdminTokens(context, appId); + resultAWSConfigInfo = await getTempCredsWithAdminTokens(context, appId); } catch (err) { context.print.error('Failed to fetch Amplify Admin credentials'); throw new Error(err); @@ -773,13 +788,13 @@ export async function getAwsConfig(context: $TSContext): Promise { } if (httpProxy) { - awsConfig = { - ...awsConfig, + resultAWSConfigInfo = { + ...resultAWSConfigInfo, httpOptions: { agent: proxyAgent(httpProxy) }, }; } - return awsConfig; + return resultAWSConfigInfo; } async function determineAuthFlow(context: $TSContext, projectConfig?: ProjectConfig): Promise { @@ -807,6 +822,12 @@ async function determineAuthFlow(context: $TSContext, projectConfig?: ProjectCon useProfile = useProfile ?? projectConfig?.config?.useProfile; profileName = profileName ?? projectConfig?.config?.profileName; + const generalCreds = projectConfig?.configLevel === 'general'; + + if (generalCreds) { + return { type: 'general' }; + } + if (useProfile && profileName) { return { type: 'profile', profileName }; } @@ -816,8 +837,8 @@ async function determineAuthFlow(context: $TSContext, projectConfig?: ProjectCon } if (projectConfig?.config?.awsConfigFilePath) { - const awsConfig = loadConfigFromPath(projectConfig.config.awsConfigFilePath); - return { ...awsConfig, type: 'accessKeys' }; + const awsConfigInfo = loadConfigFromPath(projectConfig.config.awsConfigFilePath); + return { ...awsConfigInfo, type: 'accessKeys' }; } let appId: string; diff --git a/packages/amplify-provider-awscloudformation/src/initializer.ts b/packages/amplify-provider-awscloudformation/src/initializer.ts index 03ddb87225a..80bd8fc6d9e 100644 --- a/packages/amplify-provider-awscloudformation/src/initializer.ts +++ b/packages/amplify-provider-awscloudformation/src/initializer.ts @@ -29,13 +29,13 @@ export async function run(context) { const timeStamp = `${moment().format('Hmmss')}`; const { envName = '' } = context.exeInfo.localEnvInfo; let stackName = normalizeStackName(`amplify-${projectName}-${envName}-${timeStamp}`); - const awsConfig = await configurationManager.getAwsConfig(context); + const awsConfigInfo = await configurationManager.getAwsConfig(context); await configurePermissionsBoundaryForInit(context); const amplifyServiceParams = { context, - awsConfig, + awsConfigInfo, projectName, envName, stackName, @@ -80,7 +80,7 @@ export async function run(context) { spinner.start('Initializing project in the cloud...'); try { - const cfnItem = await new Cloudformation(context, 'init', awsConfig); + const cfnItem = await new Cloudformation(context, 'init', awsConfigInfo); const stackDescriptionData = await cfnItem.createResourceStack(params); processStackCreationData(context, amplifyAppId, stackDescriptionData); diff --git a/packages/amplify-provider-awscloudformation/src/setup-new-user.js b/packages/amplify-provider-awscloudformation/src/setup-new-user.js index 3a55a972da9..210c1c62d57 100644 --- a/packages/amplify-provider-awscloudformation/src/setup-new-user.js +++ b/packages/amplify-provider-awscloudformation/src/setup-new-user.js @@ -9,7 +9,7 @@ const { open } = require('amplify-cli-core'); const isOnWsl = require('is-wsl'); async function run(context) { - const awsConfig = { + const awsConfigInfo = { accessKeyId: constants.DefaultAWSAccessKeyId, secretAccessKey: constants.DefaultAWSSecretAccessKey, region: constants.DefaultAWSRegion, @@ -30,10 +30,10 @@ async function run(context) { name: 'region', message: 'region: ', choices: awsRegions, - default: awsConfig.region, + default: awsConfigInfo.region, }, ]); - awsConfig.region = answers.region; + awsConfigInfo.region = answers.region; context.print.info('Specify the username of the new IAM user:'); const { userName } = await inquirer.prompt([ { @@ -44,7 +44,7 @@ async function run(context) { }, ]); - let deepLinkURL = constants.AWSCreateIAMUsersUrl.replace('{userName}', userName).replace('{region}', awsConfig.region); + let deepLinkURL = constants.AWSCreateIAMUsersUrl.replace('{userName}', userName).replace('{region}', awsConfigInfo.region); const isOnWindows = process.platform === 'win32'; if (isOnWindows || isOnWsl) { deepLinkURL = deepLinkURL.replace('$new', '`$new'); @@ -61,7 +61,7 @@ async function run(context) { mask: '*', name: 'accessKeyId', message: 'accessKeyId: ', - default: awsConfig.accessKeyId, + default: awsConfigInfo.accessKeyId, transformer: obfuscationUtil.transform, validate: input => { if (input === constants.DefaultAWSAccessKeyId || input.length < 16 || input.length > 128 || !/^[\w]+$/.test(input)) { @@ -83,7 +83,7 @@ async function run(context) { mask: '*', name: 'secretAccessKey', message: 'secretAccessKey: ', - default: awsConfig.secretAccessKey, + default: awsConfigInfo.secretAccessKey, transformer: obfuscationUtil.transform, validate: input => { if (input === constants.DefaultAWSSecretAccessKey || input.trim().length === 0) { @@ -95,13 +95,13 @@ async function run(context) { ]); if (accountDetails.accessKeyId) { - awsConfig.accessKeyId = accountDetails.accessKeyId.trim(); + awsConfigInfo.accessKeyId = accountDetails.accessKeyId.trim(); } if (accountDetails.secretAccessKey) { - awsConfig.secretAccessKey = accountDetails.secretAccessKey.trim(); + awsConfigInfo.secretAccessKey = accountDetails.secretAccessKey.trim(); } - if (validateAWSConfig(awsConfig)) { + if (validateAWSConfig(awsConfigInfo)) { let profileName = 'default'; context.print.warning('This would update/create the AWS Profile in your local machine'); const profileDetails = await inquirer.prompt([ @@ -115,7 +115,7 @@ async function run(context) { profileName = profileDetails.pn.trim(); - systemConfigManager.setProfile(awsConfig, profileName); + systemConfigManager.setProfile(awsConfigInfo, profileName); context.print.info(''); context.print.success('Successfully set up the new user.'); return profileName; @@ -125,8 +125,10 @@ async function run(context) { throw new Error('New user setup failed.'); } -function validateAWSConfig(awsConfig) { - return awsConfig.accessKeyId !== constants.DefaultAWSAccessKeyId && awsConfig.secretAccessKey !== constants.DefaultAWSSecretAccessKey; +function validateAWSConfig(awsConfigInfo) { + return ( + awsConfigInfo.accessKeyId !== constants.DefaultAWSAccessKeyId && awsConfigInfo.secretAccessKey !== constants.DefaultAWSSecretAccessKey + ); } module.exports = { diff --git a/packages/amplify-provider-awscloudformation/src/system-config-manager.ts b/packages/amplify-provider-awscloudformation/src/system-config-manager.ts index ec2b1d5c447..92188e63bc7 100644 --- a/packages/amplify-provider-awscloudformation/src/system-config-manager.ts +++ b/packages/amplify-provider-awscloudformation/src/system-config-manager.ts @@ -13,7 +13,7 @@ const logger = fileLogger('system-config-manager'); const credentialsFilePath = pathManager.getAWSCredentialsFilePath(); const configFilePath = pathManager.getAWSConfigFilePath(); -export function setProfile(awsConfig: $TSAny, profileName: string) { +export function setProfile(awsConfigInfo: $TSAny, profileName: string) { fs.ensureDirSync(pathManager.getDotAWSDirPath()); let credentials = {}; @@ -34,15 +34,15 @@ export function setProfile(awsConfig: $TSAny, profileName: string) { Object.keys(credentials).forEach(key => { const keyName = key.trim(); if (profileName === keyName) { - credentials[key].aws_access_key_id = awsConfig.accessKeyId; - credentials[key].aws_secret_access_key = awsConfig.secretAccessKey; + credentials[key].aws_access_key_id = awsConfigInfo.accessKeyId; + credentials[key].aws_secret_access_key = awsConfigInfo.secretAccessKey; isCredSet = true; } }); if (!isCredSet) { credentials[profileName] = { - aws_access_key_id: awsConfig.accessKeyId, - aws_secret_access_key: awsConfig.secretAccessKey, + aws_access_key_id: awsConfigInfo.accessKeyId, + aws_secret_access_key: awsConfigInfo.secretAccessKey, }; } @@ -50,14 +50,14 @@ export function setProfile(awsConfig: $TSAny, profileName: string) { Object.keys(config).forEach(key => { const keyName = key.replace('profile', '').trim(); if (profileName === keyName) { - config[key].region = awsConfig.region; + config[key].region = awsConfigInfo.region; isConfigSet = true; } }); if (!isConfigSet) { const keyName = profileName === 'default' ? 'default' : `profile ${profileName}`; config[keyName] = { - region: awsConfig.region, + region: awsConfigInfo.region, }; } logger('setProfile.writecredetialsFilePath', [credentialsFilePath])(); @@ -66,7 +66,7 @@ export function setProfile(awsConfig: $TSAny, profileName: string) { } export async function getProfiledAwsConfig(context: $TSContext, profileName: string, isRoleSourceProfile?: boolean) { - let awsConfig; + let awsConfigInfo; const httpProxy = process.env.HTTP_PROXY || process.env.HTTPS_PROXY; const profileConfig = getProfileConfig(profileName); if (profileConfig) { @@ -75,18 +75,18 @@ export async function getProfiledAwsConfig(context: $TSContext, profileName: str const roleCredentials = await getRoleCredentials(context, profileName, profileConfig); delete profileConfig.role_arn; delete profileConfig.source_profile; - awsConfig = { + awsConfigInfo = { ...profileConfig, ...roleCredentials, }; } else { logger('getProfiledAwsConfig.getProfileCredentials', [profileName]); const profileCredentials = getProfileCredentials(profileName); - awsConfig = { + awsConfigInfo = { ...profileConfig, ...profileCredentials, }; - validateCredentials(awsConfig, profileName); + validateCredentials(awsConfigInfo, profileName); } } else { const err = new Error(`Profile configuration is missing for: ${profileName}`); @@ -95,13 +95,13 @@ export async function getProfiledAwsConfig(context: $TSContext, profileName: str } if (httpProxy) { - awsConfig = { - ...awsConfig, + awsConfigInfo = { + ...awsConfigInfo, httpOptions: { agent: proxyAgent(httpProxy) }, }; } - return awsConfig; + return awsConfigInfo; } function makeFileOwnerReadWrite(filePath: string) { @@ -232,7 +232,8 @@ function isCredentialsExpired(roleCredentials: $TSAny) { } export async function resetCache(context: $TSContext, profileName: string) { - let awsConfig; + let awsConfigInfo; + const profileConfig = getProfileConfig(profileName); const cacheFilePath = getCacheFilePath(); if (profileConfig && profileConfig.role_arn && fs.existsSync(cacheFilePath)) { @@ -251,7 +252,8 @@ export async function resetCache(context: $TSContext, profileName: string) { context.print.info(' No temp credentials are cached for the project.'); context.print.info(''); } - return awsConfig; + + return awsConfigInfo; } function getCacheFilePath() { diff --git a/packages/amplify-provider-awscloudformation/src/utils/admin-helpers.ts b/packages/amplify-provider-awscloudformation/src/utils/admin-helpers.ts index b4482b963f6..1bbc2a42859 100644 --- a/packages/amplify-provider-awscloudformation/src/utils/admin-helpers.ts +++ b/packages/amplify-provider-awscloudformation/src/utils/admin-helpers.ts @@ -35,8 +35,10 @@ export async function getTempCredsWithAdminTokens(context: $TSContext, appId: st const authConfig = await getRefreshedTokens(context, appId); const { idToken, IdentityId, region } = authConfig; // use tokens to get creds and assign to config - const awsConfig = await getAdminCognitoCredentials(idToken, IdentityId, region); - aws.config.update(awsConfig); + const awsConfigInfo = await getAdminCognitoCredentials(idToken, IdentityId, region); + + aws.config.update(awsConfigInfo); + // need to use Cognito creds to get STS creds - otherwise // users will not be able to provision Cognito resources return await getAdminStsCredentials(idToken, region); diff --git a/packages/amplify-provider-awscloudformation/src/utils/auth-types.ts b/packages/amplify-provider-awscloudformation/src/utils/auth-types.ts index 500e31bd6e0..af2e9303e93 100644 --- a/packages/amplify-provider-awscloudformation/src/utils/auth-types.ts +++ b/packages/amplify-provider-awscloudformation/src/utils/auth-types.ts @@ -1,6 +1,6 @@ import { $TSAny } from 'amplify-cli-core'; -export type AuthFlow = 'admin' | 'profile' | 'accessKeys'; +export type AuthFlow = 'admin' | 'profile' | 'accessKeys' | 'general'; export interface AuthFlowConfig extends Partial { type: AuthFlow; appId?: string; diff --git a/packages/amplify-util-mock/src/utils/lambda/populate-lambda-mock-env-vars.ts b/packages/amplify-util-mock/src/utils/lambda/populate-lambda-mock-env-vars.ts index 3449c31f43b..dc4b06882be 100644 --- a/packages/amplify-util-mock/src/utils/lambda/populate-lambda-mock-env-vars.ts +++ b/packages/amplify-util-mock/src/utils/lambda/populate-lambda-mock-env-vars.ts @@ -28,11 +28,11 @@ const getAwsCredentials = async (_, context: $TSContext): Promise