aws-amplify / amplify-cli

The AWS Amplify CLI is a toolchain for simplifying serverless web and mobile development.
Apache License 2.0
2.8k stars 819 forks source link

How to correctly add customEmailSender in the auth override.ts #12833

Open Robsonwd opened 1 year ago

Robsonwd commented 1 year ago

How did you install the Amplify CLI?

npm install -g @aws-amplify/cli

If applicable, what version of Node.js are you using?

v14.20.1

Amplify CLI Version

10.7.2

What operating system are you using?

Mac

Did you make any manual changes to the cloud resources managed by Amplify? Please describe the changes made.

No

Describe the bug

I am getting an error: Parameters: [customkmsKmsKeyArn] do not exist in the template on deployment. When I'm checking the AWS Cloudformation events, I see that this error in Cloudformation is AuthTriggerCustomLambdaStack.

I was following this issue to set this up: https://github.com/aws-amplify/amplify-cli/issues/11824

override.ts for auth category:

export function override(resources: AmplifyAuthCognitoStackTemplate) {
    // START - Custom Email Sender
    const parameter = 'customkmsKmsKeyArn'
    resources.addCfnParameter(
        {
            type: 'String',
            description: 'my kms key arn',
            default: 'NONE',
        },
        parameter
    )

    resources.userPool.addPropertyOverride('LambdaConfig', {
        ...resources.userPool.lambdaConfig,
        KMSKeyID: {
            Ref: parameter,
        }
    })

    const customEmailSenderLambdaConfig = {
        ...resources.userPool.lambdaConfig
    }

    customEmailSenderLambdaConfig["customEmailSender"] = {
        lambdaVersion: 'V1_0',
        lambdaArn: {
            "Fn::Sub": "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:amplifyapp-CognitoCustomEmailSender-${env}"
        }
    }

    resources.userPool.lambdaConfig = customEmailSenderLambdaConfig

    // START - Lambda Triggers
    const newLambdaConfig = {
        ...resources.userPool.lambdaConfig,
    }

    if(!newLambdaConfig["postConfirmation"]) {
        newLambdaConfig["postConfirmation"] = {
            "Fn::Sub": "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${env}-amplifyapp-PostConfirmation-965f9a74965f9a74",
        }
    }
    if(!newLambdaConfig["preSignup"]) {
        newLambdaConfig["preSignup"] = {
            "Fn::Sub": "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${env}-amplifyapp-PreSignup-965f9a74965f9a74",
        }
    }

    resources.userPool.lambdaConfig = newLambdaConfig
    // END - Lambda Triggers

    // START - Email Configuration
    const newEmailConfiguration = {
        ...resources.userPool.emailConfiguration,
    }

    newEmailConfiguration["sourceArn"] = {
        "Fn::Sub": "arn:aws:ses:${AWS::Region}:${AWS::AccountId}:identity/support@amplifyapp.com",
    }

    resources.userPool.emailConfiguration = newEmailConfiguration
    // END - Email Configuration

    // START - Custom Attributes
    const resourcesUserPoolSchema = resources.userPool.schema as SchemaAttributeProperty[]

    const customAttribute = {
        "attributeDataType": 'String',
        "developerOnlyAttribute": false,
        "mutable": true,
        "name": 'app_customer_id',
        "required": false
    }

    resourcesUserPoolSchema.push(customAttribute)
    // END - Custom Attributes

}

custom/kms/kms-cloudformation-template.json

{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Parameters": {
    "env": {
      "Type": "String"
    }
  },
  "Resources": {
    "CognitoCustomEmailSenderKmsKey": {
      "Type": "AWS::KMS::Key",
      "Properties": {
        "Description": {
          "Fn::Sub": [
            "KMS key for amplifyappCognitoCustomEmailSender-${env}",
            {
              "env": {
                "Ref": "env"
              }
            }
          ]
        },
        "KeyPolicy": {
          "Version": "2012-10-17",
          "Id": "key-default-1",
          "Statement": [
            {
              "Sid": "Enable IAM User Permissions",
              "Effect": "Allow",
              "Principal": {
                "AWS": {
                  "Fn::Sub": "arn:aws:iam::${AWS::AccountId}:root"
                }
              },
              "Action": "kms:*",
              "Resource": "*"
            }
          ]
        }
      }
    },
    "CognitoCustomEmailSenderKmsKeyAlias": {
      "Type": "AWS::KMS::Alias",
      "Properties": {
        "AliasName": {
          "Fn::Sub": [
            "alias/${env}/amplifyappCognitoCustomEmailSenderKmsKey",
            {
              "env": {
                "Ref": "env"
              }
            }
          ]
        },
        "TargetKeyId": {
          "Ref": "CognitoCustomEmailSenderKmsKey"
        }
      }
    }
  },
  "Outputs": {
    "KmsKeyArn": {
      "Description": "The ARN of the KMS key",
      "Value": {
        "Fn::GetAtt": [
          "CognitoCustomEmailSenderKmsKey",
          "Arn"
        ]
      }
    }
  },
  "Description": "{\"createdOn\":\"Mac\",\"createdBy\":\"Amplify\",\"createdWith\":\"10.7.2\",\"stackType\":\"custom-customCloudformation\",\"metadata\":{}}"
}

backend-config.json

  "auth": {
    "amplifyapp965f9a74965f9a74": {
      "customAuth": false,
      "dependsOn": [
        {
          "attributes": [
            "Arn",
            "Name"
          ],
          "category": "function",
          "resourceName": "amplifyapp965f9a74965f9a74PostConfirmation",
          "triggerProvider": "Cognito"
        },
        {
          "attributes": [
            "Arn",
            "Name"
          ],
          "category": "function",
          "resourceName": "amplifyapp965f9a74965f9a74PreSignup",
          "triggerProvider": "Cognito"
        },
        {
          "attributes": [
            "KmsKeyArn"
          ],
          "category": "custom",
          "resourceName": "kms"
        }
      ],
      ...

Many thanks for help solving this.

Expected behavior

AWS Amplify deployment works without issues and customEmailSender in lambda config is correctly set with KMS Key ID.

Reproduction steps

  1. add custom kms cloudformation with cloudformation for KMS and alias
  2. add kms key arn attribute to the backend-config.json auth dependency
  3. try to add kms key arn parameter to the override.ts and set customEmailSender for lambdaConfig

Project Identifier

No response

Log output

``` # Put your logs below this line ```

Additional information

No response

Before submitting, please confirm:

josefaidt commented 1 year ago

Hey @Robsonwd :wave: thanks for raising this! The setup looks good! In between steps 2 and 3, you'll want to run amplify env checkout <current-env-name>. This will lift the changes made to the git-tracked backend-config.json file into the ignored amplify-meta.json file, which will then pass the KmsKeyArn output into the auth stack. To debug you can run amplify build and inspect the auth CloudFormation template to ensure overrides are being applied as expected (this setup looks good so this shouldn't be an issue), and inspect the root stack's CloudFormation template in amplify/backend/awscloudformation/build/root-cloudformation-stack.json or amplify/#current-cloud-backend/awscloudformation/build/root-cloudformation-stack.json to ensure the parameter is passed from the custom resource to the auth stack.

Robsonwd commented 1 year ago

Hey @josefaidt I tried this as well but I've got the same error in the Cloudformation for AuthTriggerCustomLambdaStack. Auth and user pools in the Cloudformation say "UPDATE_COMPLETE", the only AuthTriggerCustomLambdaStack fails somehow.

There is:

{
          "attributes": [
            "KmsKeyArn"
          ],
          "category": "custom",
          "resourceName": "kms"
        },

created in amplify-meta.json

There is also:

"customkmsKmsKeyArn": {
            "Fn::GetAtt": [
              "customkms",
              "Outputs.KmsKeyArn"
            ]
          },

in amplify/backend/awscloudformation/build/root-cloudformation-stack.json for auth parameters and also for AuthTriggerCustomLambdaStack parameters.

josefaidt commented 1 year ago

Hey @Robsonwd thanks for checking on that, and the snippets look good! What is the error coming from the AuthTriggerCustomLambdaStack? You may need to view the error in the AWS CloudFormation console for this nested stack if it is not printed to the terminal

Robsonwd commented 1 year ago

@josefaidt Yea, I double-checked everything, names, values. All things look correct. For the AuthTriggerCustomLambdaStack it's just the same error: Parameters: [customkmsKmsKeyArn] do not exist in the template

I'm wondering if custom cognito triggers for PostConfirmation and PreSignup might breaking something here 🤔

Screenshot 2023-06-20 at 19 46 59
josefaidt commented 1 year ago

Hey @Robsonwd apologies for the delay here but unfortunately I have not been able to find a suitable workaround for this. Here's what's happening:

Furthermore, we are unable to modify this template with auth overrides, project overrides, or a post-build hook (it does not appear to be invoked during the build that occurs on push).

I'll mark this as a bug

kennyd-reacthealth commented 7 months ago

Any updates on this bug?

cunneen commented 1 month ago

In case it helps anyone, I've been playing around with a related issue and discovered something interesting:

  1. The feature flag auth.breakcirculardependency determines whether the "sibling stack for auth triggers" (AuthTriggerCustomLambdaStack) gets created and used.
  2. If you set the flag to false and delete the template for that stack from amplify/backend/auth/my-auth/build, the config for the lambda triggers (and your overrides) are applied to the main template.

Of course, the feature flag exists for a reason: if you have a circular dependency, you'll have to deal with it manually. E.g. in my case I had to remove the strong dependency the user pool has on the triggers, and then in your override add the trigger ARNs back as strings (rather than refs).