aws / aws-cdk

The AWS Cloud Development Kit is a framework for defining cloud infrastructure in code
https://aws.amazon.com/cdk
Apache License 2.0
11.51k stars 3.85k forks source link

aws-cognito: CfnLogDeliveryConfiguration wrong regular expression #31241

Open AllanOricil opened 2 weeks ago

AllanOricil commented 2 weeks ago

Describe the bug

I can't create a CfnLogDeliveryConfiguration because it is not accepting my log group arn

const userpolLogsGroup = new logs.LogGroup(
      this,
      "node-ready-user-pool-logs-group",
      {
        logGroupName: "/node-ready/cognito/userpool/node-ready-user-pool",
        removalPolicy: cdk.RemovalPolicy.DESTROY,
        retention: logs.RetentionDays.ONE_WEEK,
      },
    );

    new cognito.CfnLogDeliveryConfiguration(
      this,
      "node-ready-user-pool-log-delivery-configuration",
      {
        userPoolId: this.cognitoUserPool.userPoolId,
        logConfigurations: [
          {
            cloudWatchLogsConfiguration: {
              logGroupArn: userpolLogsGroup.logGroupArn,
            },
            eventSource: "userNotification",
            logLevel: "ERROR",
          },
        ],
      },
    );

image

As you can see, the issue is with the "*" at the end, which the regular expression for CloudWatchLogsConfiguration.logGroupArn doesn't accept.

Regression Issue

https://repost.aws/questions/QUhjYRB83zR_Od3frN-PRQww/cloudformation-regex-validation-error-in-cognito-logdeliveryconfiguration-cloudwatchlogsconfiguration-loggrouparn

Last Known Working CDK Version

2.154.0

Expected Behavior

CfnLogDeliveryConfiguration.logConfigurations.cloudWatchLogsConfiguration.logGroupArn must accept Logs Group Arns that end with "*"

The official documentation for this property is also wrong, as you can see in the image below

image

source: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cognito-logdeliveryconfiguration-cloudwatchlogsconfiguration.html

Current Behavior

image

Reproduction Steps

Try to deploy a CDK V2 Stack with these constructs in it

const userpolLogsGroup = new logs.LogGroup(
      this,
      "node-ready-user-pool-logs-group",
      {
        logGroupName: "/node-ready/cognito/userpool/node-ready-user-pool",
        removalPolicy: cdk.RemovalPolicy.DESTROY,
        retention: logs.RetentionDays.ONE_WEEK,
      },
    );

    new cognito.CfnLogDeliveryConfiguration(
      this,
      "node-ready-user-pool-log-delivery-configuration",
      {
        userPoolId: this.cognitoUserPool.userPoolId,
        logConfigurations: [
          {
            cloudWatchLogsConfiguration: {
              logGroupArn: userpolLogsGroup.logGroupArn,
            },
            eventSource: "userNotification",
            logLevel: "ERROR",
          },
        ],
      },
    );

Possible Solution

Before validating the ARN, which is generated by cloudformation, split it by : , remove the last token, validate. This way you don't need to change the regex expression you currently use.

WORKAROUND

Build the arn yourself instead of relying on cloudfromation

new cognito.CfnLogDeliveryConfiguration(
      this,
      "node-ready-user-pool-log-delivery-configuration",
      {
        userPoolId: this.cognitoUserPool.userPoolId,
        logConfigurations: [
          {
            cloudWatchLogsConfiguration: {
              logGroupArn: `arn:aws:logs:${getEnvVar("CDK_DEFAULT_REGION")}:${getEnvVar("CDK_DEFAULT_ACCOUNT")}:log-group:${userpolLogsGroup.logGroupName}`,
            },
            eventSource: "userNotification",
            logLevel: "ERROR",
          },
        ],
      },
    );

Additional Information/Context

No response

CDK CLI Version

2.154.0

Framework Version

No response

Node.js Version

18.19

OS

macos

Language

TypeScript

Language Version

5.0.4

Other information

No response

ashishdhingra commented 2 weeks ago

Using the below code:

import * as cdk from 'aws-cdk-lib';
import * as cognito from 'aws-cdk-lib/aws-cognito';
import * as logs from 'aws-cdk-lib/aws-logs';

export class CdktestStack extends cdk.Stack {
  constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const cognitoUserPool = new cognito.UserPool(this, 'CognitoPool', {
      userPoolName: 'TestCDKCognitoPool',
      selfSignUpEnabled: true,
      signInCaseSensitive: false,
      signInAliases: {
        email: true,
        phone: true,
      },
      autoVerify: {
        email: true,
      },
      userVerification: {
        emailSubject: 'Hello from My Cool App!',
        emailBody: 'Hello, Thanks for registering in My cool app! Verification code is {####}.',
        emailStyle: cognito.VerificationEmailStyle.CODE
      },
      standardAttributes: {
        fullname: {
          required: true,
          mutable: true,
        },
        email: {
          required: true,
          mutable: true,
        }
      },
      customAttributes: {
        company: new cognito.StringAttribute({ mutable: true }),
      },
      passwordPolicy: {
        minLength: 8,
        requireLowercase: true,
        requireDigits: true,
        requireSymbols: true,
      },
      accountRecovery: cognito.AccountRecovery.EMAIL_AND_PHONE_WITHOUT_MFA,
      removalPolicy: cdk.RemovalPolicy.DESTROY,
    });

    const userpoolLogsGroup = new logs.LogGroup(
      this,
      "node-ready-user-pool-logs-group",
      {
        logGroupName: "/node-ready/cognito/userpool/node-ready-user-pool",
        removalPolicy: cdk.RemovalPolicy.DESTROY,
        retention: logs.RetentionDays.ONE_WEEK,
      },
    );

    new cognito.CfnLogDeliveryConfiguration(
      this,
      "node-ready-user-pool-log-delivery-configuration",
      {
        userPoolId: cognitoUserPool.userPoolId,
        logConfigurations: [
          {
            cloudWatchLogsConfiguration: {
              logGroupArn: userpoolLogsGroup.logGroupArn,
            },
            eventSource: "userNotification",
            logLevel: "ERROR",
          },
        ],
      },
    );
  }
}

Running cdk synth emits the below CFN template:

Resources:
  CognitoPoolsmsRole554FA026:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Action: sts:AssumeRole
            Condition:
              StringEquals:
                sts:ExternalId: CdktestStackCognitoPoolFC4B558A
            Effect: Allow
            Principal:
              Service: cognito-idp.amazonaws.com
        Version: "2012-10-17"
      Policies:
        - PolicyDocument:
            Statement:
              - Action: sns:Publish
                Effect: Allow
                Resource: "*"
            Version: "2012-10-17"
          PolicyName: sns-publish
    Metadata:
      aws:cdk:path: CdktestStack/CognitoPool/smsRole/Resource
  CognitoPool2F2E48AB:
    Type: AWS::Cognito::UserPool
    Properties:
      AccountRecoverySetting:
        RecoveryMechanisms:
          - Name: verified_email
            Priority: 1
          - Name: verified_phone_number
            Priority: 2
      AdminCreateUserConfig:
        AllowAdminCreateUserOnly: false
      AutoVerifiedAttributes:
        - email
      EmailVerificationMessage: Hello, Thanks for registering in My cool app! Verification code is {####}.
      EmailVerificationSubject: Hello from My Cool App!
      Policies:
        PasswordPolicy:
          MinimumLength: 8
          RequireLowercase: true
          RequireNumbers: true
          RequireSymbols: true
      Schema:
        - Mutable: true
          Name: name
          Required: true
        - Mutable: true
          Name: email
          Required: true
        - AttributeDataType: String
          Mutable: true
          Name: company
      SmsConfiguration:
        ExternalId: CdktestStackCognitoPoolFC4B558A
        SnsCallerArn:
          Fn::GetAtt:
            - CognitoPoolsmsRole554FA026
            - Arn
      SmsVerificationMessage: The verification code to your new account is {####}
      UserPoolName: TestCDKCognitoPool
      UsernameAttributes:
        - email
        - phone_number
      UsernameConfiguration:
        CaseSensitive: false
      VerificationMessageTemplate:
        DefaultEmailOption: CONFIRM_WITH_CODE
        EmailMessage: Hello, Thanks for registering in My cool app! Verification code is {####}.
        EmailSubject: Hello from My Cool App!
        SmsMessage: The verification code to your new account is {####}
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Metadata:
      aws:cdk:path: CdktestStack/CognitoPool/Resource
  nodereadyuserpoollogsgroup22DB6865:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: /node-ready/cognito/userpool/node-ready-user-pool
      RetentionInDays: 7
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Metadata:
      aws:cdk:path: CdktestStack/node-ready-user-pool-logs-group/Resource
  nodereadyuserpoollogdeliveryconfiguration:
    Type: AWS::Cognito::LogDeliveryConfiguration
    Properties:
      LogConfigurations:
        - CloudWatchLogsConfiguration:
            LogGroupArn:
              Fn::GetAtt:
                - nodereadyuserpoollogsgroup22DB6865
                - Arn
          EventSource: userNotification
          LogLevel: ERROR
      UserPoolId:
        Ref: CognitoPool2F2E48AB
    Metadata:
      aws:cdk:path: CdktestStack/node-ready-user-pool-log-delivery-configuration
  CDKMetadata:
    Type: AWS::CDK::Metadata
    Properties:
      Analytics: v2:deflate64:H4sIAAAAAAAA/02Lyw6CMBBFv4V9GYVo/ABM3LggGNemltIMlI7pA2Oa/rsgLFzdk5tzSiiOBygy/na5aIdc4xPizXMxsPl6REHKoCeIdydtTaRZ1Zl/vpI6S42TtJ+KTIcqWO6RTGLIR4gNabloyyamSTmIc3KxFF5b/uOUWCMdBStWfePEDLUSerebyhJOsM96h5jbYDyOEpp1v7R801jFAAAA
    Metadata:
      aws:cdk:path: CdktestStack/CDKMetadata/Default
Parameters:
  BootstrapVersion:
    Type: AWS::SSM::Parameter::Value<String>
    Default: /cdk-bootstrap/hnb659fds/version
    Description: Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]

Take a note that LogGroupArn is set using Fn::GetAtt: on the created log group's nodereadyuserpoollogsgroup22DB6865 property Arn.

The error is thrown by CloudFormation upon deployment.

CdktestStack: deploying... [1/1]
CdktestStack: creating CloudFormation changeset...
11:32:26 AM | CREATE_FAILED        | AWS::Cognito::LogDeliveryConfiguration | nodereadyuserpooll...iveryconfiguration
Resource handler returned message: "1 validation error detected: Value 'arn:aws:logs:us-east-2:<<REDACTED>>:log-group:/node-ready/cognito/userpool/node-ready-user
-pool:*' at 'logConfigurations.1.member.cloudWatchLogsConfiguration.logGroupArn' failed to satisfy constraint: Member must satisfy regular expression pattern: arn
:[\w+=/,.@-]+:[\w+=/,.@-]+:([\w+=/,.@-]*)?:[0-9]+:[\w+=/,.@-]+(:[\w+=/,.@-]+)?(:[\w+=/,.@-]+)? (Service: CognitoIdentityProvider, Status Code: 400, Request ID: 6d
8e39b8-9c6f-4912-a9ee-57850577b3b1)" (RequestToken: 2f8b49cf-1892-3a39-2638-3decd4e6f880, HandlerErrorCode: InvalidRequest)

 ❌  CdktestStack failed: Error: The stack named CdktestStack failed creation, it may need to be manually deleted from the AWS console: ROLLBACK_COMPLETE: Resource handler returned message: "1 validation error detected: Value 'arn:aws:logs:us-east-2:<<REDACTED>>:log-group:/node-ready/cognito/userpool/node-ready-user-pool:*' at 'logConfigurations.1.member.cloudWatchLogsConfiguration.logGroupArn' failed to satisfy constraint: Member must satisfy regular expression pattern: arn:[\w+=/,.@-]+:[\w+=/,.@-]+:([\w+=/,.@-]*)?:[0-9]+:[\w+=/,.@-]+(:[\w+=/,.@-]+)?(:[\w+=/,.@-]+)? (Service: CognitoIdentityProvider, Status Code: 400, Request ID: 6d8e39b8-9c6f-4912-a9ee-57850577b3b1)" (RequestToken: 2f8b49cf-1892-3a39-2638-3decd4e6f880, HandlerErrorCode: InvalidRequest)
    at FullCloudFormationDeployment.monitorDeployment (/opt/homebrew/lib/node_modules/aws-cdk/lib/index.js:447:10567)
    at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
    at async Object.deployStack2 [as deployStack] (/opt/homebrew/lib/node_modules/aws-cdk/lib/index.js:450:200276)
    at async /opt/homebrew/lib/node_modules/aws-cdk/lib/index.js:450:181698

 ❌ Deployment failed: Error: The stack named CdktestStack failed creation, it may need to be manually deleted from the AWS console: ROLLBACK_COMPLETE: Resource handler returned message: "1 validation error detected: Value 'arn:aws:logs:us-east-2:<<REDACTED>>:log-group:/node-ready/cognito/userpool/node-ready-user-pool:*' at 'logConfigurations.1.member.cloudWatchLogsConfiguration.logGroupArn' failed to satisfy constraint: Member must satisfy regular expression pattern: arn:[\w+=/,.@-]+:[\w+=/,.@-]+:([\w+=/,.@-]*)?:[0-9]+:[\w+=/,.@-]+(:[\w+=/,.@-]+)?(:[\w+=/,.@-]+)? (Service: CognitoIdentityProvider, Status Code: 400, Request ID: 6d8e39b8-9c6f-4912-a9ee-57850577b3b1)" (RequestToken: 2f8b49cf-1892-3a39-2638-3decd4e6f880, HandlerErrorCode: InvalidRequest)
    at FullCloudFormationDeployment.monitorDeployment (/opt/homebrew/lib/node_modules/aws-cdk/lib/index.js:447:10567)
    at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
    at async Object.deployStack2 [as deployStack] (/opt/homebrew/lib/node_modules/aws-cdk/lib/index.js:450:200276)
    at async /opt/homebrew/lib/node_modules/aws-cdk/lib/index.js:450:181698

The stack named CdktestStack failed creation, it may need to be manually deleted from the AWS console: ROLLBACK_COMPLETE: Resource handler returned message: "1 validation error detected: Value 'arn:aws:logs:us-east-2:<<REDACTED>>:log-group:/node-ready/cognito/userpool/node-ready-user-pool:*' at 'logConfigurations.1.member.cloudWatchLogsConfiguration.logGroupArn' failed to satisfy constraint: Member must satisfy regular expression pattern: arn:[\w+=/,.@-]+:[\w+=/,.@-]+:([\w+=/,.@-]*)?:[0-9]+:[\w+=/,.@-]+(:[\w+=/,.@-]+)?(:[\w+=/,.@-]+)? (Service: CognitoIdentityProvider, Status Code: 400, Request ID: 6d8e39b8-9c6f-4912-a9ee-57850577b3b1)" (RequestToken: 2f8b49cf-1892-3a39-2638-3decd4e6f880, HandlerErrorCode: InvalidRequest)

Skipping CfnLogDeliveryConfiguration creation creates log group successfully:

Screenshot 2024-08-29 at 11 39 29 AM

Most likely this is a CloudFormation issue.

Thanks, Ashish

ashishdhingra commented 2 weeks ago

Internal tracking ticket: P151524663