async createNativeAdminUser()

in addons/addon-base-post-deployment/packages/base-post-deployment/lib/steps/create-root-user-service.js [98:232]


  async createNativeAdminUser() {
    if (!this.settings.getBoolean(settingKeys.enableNativeUserPoolUsers)) {
      this.log.info('Cognito Native User Pool is turned off for this installation. Skipping initial admin creation');
      return;
    }

    const nativeAdminUserEmail = this.settings.get(settingKeys.rootUserEmail);
    const nativeAdminUserFirstName = this.settings.get(settingKeys.rootUserFirstName);
    const nativeAdminUserLastName = this.settings.get(settingKeys.rootUserLastName);
    const nativeAdminPasswordParamName = this.settings.get(settingKeys.nativeAdminPasswordParamName);
    const solutionName = this.settings.get(settingKeys.solutionName);
    const awsRegion = this.settings.get(settingKeys.awsRegion);
    const envName = this.settings.get(settingKeys.envName);

    const aws = await this.service('aws');
    const cognitoIdentityServiceProvider = new aws.sdk.CognitoIdentityServiceProvider();
    const result = await cognitoIdentityServiceProvider.listUserPools({ MaxResults: '60' }).promise();
    const userPoolName = `${envName}-${solutionName}-userPool`;
    const userPool = _.find(result.UserPools, { Name: userPoolName });

    if (!userPool) {
      // TODO - future: When we deprecate internal authentication, code inside this if block should throw an error
      this.log.info(
        'Cognito User Pool is not available. This means only internal authentication provider is being used',
      );
      return;
    }

    // Auto-generate password for the native admin user
    const nativeAdminPassword = this.generatePassword();

    const userPoolId = userPool.Id;

    try {
      await this.createUser({
        username: nativeAdminUserEmail,
        authenticationProviderId: `https://cognito-idp.${awsRegion}.amazonaws.com/${userPoolId}`,
        identityProviderName: 'Cognito Native Pool',
        firstName: nativeAdminUserFirstName,
        lastName: nativeAdminUserLastName,
        email: nativeAdminUserEmail,
        isAdmin: true,
        status: 'active',
        userRole: 'admin',
      });
    } catch (err) {
      if (err.code === 'alreadyExists') {
        // The native admin already exists. Nothing to do.
        this.log.info(
          `The user with user name = ${nativeAdminUserEmail} already exists. Did NOT overwrite that user's information.`,
        );
      } else {
        // In case of any other error let it bubble up
        throw this.boom.internalError(
          `There was a problem creating the default native user in DDB. Username: ${nativeAdminUserEmail}. Error code: ${err.code}`,
          true,
        );
      }
    }

    try {
      await cognitoIdentityServiceProvider
        .adminGetUser({ Username: nativeAdminUserEmail, UserPoolId: userPoolId })
        .promise();
      this.log.info(
        `The native cognito user ${nativeAdminUserEmail} already exists in user pool ${userPoolId}. Not creating a new one.`,
      );
    } catch (err) {
      if (err.code === 'UserNotFoundException') {
        this.log.info(
          `User with username ${nativeAdminUserEmail} not found in native user pool ${userPoolId}. Creating a new one.`,
        );
        const nativeAdminParams = {
          TemporaryPassword: nativeAdminPassword,
          UserAttributes: [
            {
              Name: 'family_name',
              Value: nativeAdminUserLastName,
            },
            {
              Name: 'name',
              Value: nativeAdminUserFirstName,
            },
            {
              Name: 'given_name',
              Value: nativeAdminUserFirstName,
            },
            // These two attributes help users leverage Cognito native user pool's Forgot Password feature
            {
              Name: 'email',
              Value: nativeAdminUserEmail,
            },
            {
              Name: 'email_verified',
              Value: 'true',
            },
          ],
          Username: nativeAdminUserEmail,
          UserPoolId: userPoolId,
        };
        await cognitoIdentityServiceProvider.adminCreateUser(nativeAdminParams).promise();
        this.log.info(`Created native pool user with user name = ${nativeAdminUserEmail}`);
      } else {
        throw this.boom.internalError(
          `There was a problem getting the default native pool user. Username: ${nativeAdminUserEmail} UserPoolId: ${userPoolId}. Error code: ${err.code}`,
          true,
        );
      }
    }

    try {
      await this.getSsmParam({ Name: nativeAdminPasswordParamName, WithDecryption: true });
      // TODO - future: If cognito user's UserStatus === 'CONFIRMED', we can safely remove the SSM parameter value
    } catch (err) {
      if (err.code === 'ParameterNotFound') {
        // Create parameter if not available yet
        await this.putSsmParam({
          Name: nativeAdminPasswordParamName,
          Type: 'SecureString',
          Value: nativeAdminPassword,
          Description: `Temporary Cognito native pool user password for the ${solutionName}`,
          Overwrite: true,
        });

        this.log.info(
          `Please find the native pool user temporary password in parameter store at ${nativeAdminPasswordParamName}`,
        );
      } else {
        throw this.boom.internalError(
          `There was a problem setting the native pool user temporary password. SSM param: ${nativeAdminPasswordParamName}. Error code: ${err.code}`,
          true,
        );
      }
    }
  }