aws-cdk icon indicating copy to clipboard operation
aws-cdk copied to clipboard

Amazon.CDK.AWS.Lex: Property that used to be untyped and is now typed is easy to misuse

Open jordialemany opened this issue 9 months ago • 3 comments

Describe the bug

It seems that there is a PascalCase / camelCase issue when deploying a new Lex Bot using the CfnBot class. There is a mandatory property called "DataPrivacy". This property must be of type "CfnBot.DataPrivacyProperty", which also contains a mandatory property called "ChildDirected". Even this property has been set to "true", when deploying the stack it throws an error like this:

UPDATE_ROLLBACK_COMPLETE: Properties validation failed for resource MyResourceA629FA55 with message: [#/DataPrivacy: extraneous key [childDirected] is not permitted]

Regression Issue

  • [ ] Select this option if this issue appears to be a regression.

Last Known Working CDK Version

No response

Expected Behavior

It should deploy the Lex bot without any issues.

Current Behavior

The deployment of the Lex bot is failing, so the entire changeset gets rolled back.

Reproduction Steps

Define a CfnBot like this:

            var bot = new CfnBot(this, $"{id}-{botName}", new CfnBotProps
            {
                Name = $"{botName}",
                RoleArn = lexRole.RoleArn,
                DataPrivacy = new CfnBot.DataPrivacyProperty
                {
                    ChildDirected = false
                },
                IdleSessionTtlInSeconds = 300, // 5 minutes
                Description = $"Bot for the {id} application.",
                BotFileS3Location = new CfnBot.S3LocationProperty
                {
                    S3Bucket = importBucket.BucketName,
                    S3ObjectKey = botKey,
                }
            });

Possible Solution

Fix the JsiiProperty attribute of the property ChildDirected of the class Amazon.CDK.AWS.Lex.CfnBot.DataPrivacyProperty by changing its name from "childDirected" to "ChildDirected".

Additional Information/Context

No response

CDK CLI Version

2.1003.0 (build b242c23)

Framework Version

.net 8

Node.js Version

v20.9.0

OS

Windows 11 23H2

Language

.NET

Language Version

No response

Other information

No response

jordialemany avatar Mar 07 '25 15:03 jordialemany

Reproducible. It synthesizes into below CFN template (for example):

Resources:
  CdktestDotnetStackTestBot:
    Type: AWS::Lex::Bot
    Properties:
      BotFileS3Location:
        S3Bucket: testbucket
        S3ObjectKey: testkey
      DataPrivacy:
        childDirected: false
      Description: Bot for the CdktestDotnetStack application.
      IdleSessionTTLInSeconds: 300
      Name: TestBot
      RoleArn: arn:aws:iam::<<ACCOUNT-ID>>:role/TestEC2ReadOnlyRole
    Metadata:
      aws:cdk:path: CdktestDotnetStack/CdktestDotnetStack-TestBot
...

Refer AWS::Lex::Bot DataPrivacy, there is a casing difference.

This appears to be JSII issue.

ashishdhingra avatar Mar 07 '25 21:03 ashishdhingra

This is not a jsii bug, but an unfortunate side effect of CloudFormation type refinement that we have to fix in CDK.

There is a mandatory property called "DataPrivacy". This property must be of type "CfnBot.DataPrivacyProperty",

You would expect so, but unfortunately it must not be of type CfnBot.DataPrivacyProperty.

Untyped data

At some point in the past, the CloudFormation schema defined the type of dataPrivacy to be "an arbitray JSON object".

In CDK, this leads to dataPrivacy being typed as any (or in the case of .NET, object).

That means we cannot know what fields are expected by CloudFormation. So when you write:

{ 
  childDirected: true
}

We can't know if it's actually childDirected or intended to be ChildDirected. We have to be conservative, and emit properties of untyped objects as the same input that we receive.

Refining types

At some time after that, the Lex team introduced types for DataPrivacy. Yay...

Backwards compatibility

...except we can't change the type of dataPrivacy: any into dataPrivacy: DataPrivacyProperty, because it would change the meaning of existing programs!

new CfnBot(..., {
  dataPrivacy: {
    ChildDirected: true,  // <-- ❌ is now a compilation error because the property is named childDirected
  },
})

To make matters worse

To make matters worse, we are emitting type definitions for the new DataPrivacyProperty type, and that's the definitions you are using... but we're not accepting properties of that type anywhere...

...except that in .NET the type is public object DataPrivacy, which accepts any object including DataPrivacyProperty, which renders over the jsii wire to { childDirected: true } (notice the lowercase), because that is what a field that would have expected a DataPrivacyProperty type to have rendered to.

Bottom line

The bottom line is that dataPrivacy is actually of type Map<string, object>, and it expects literal keys.

The long-term solution would be to recognize these situations when typing is added onto an object whose properties used to have been typed as any, and render the following instead:

interface CfnBotProps {
  /** @deprecated use dataPrivacyV2 instead */
  dataPrivacy?: any;

  dataPrivacyV2?: DataPrivacyProperty;
}

rix0rrr avatar Apr 01 '25 12:04 rix0rrr

Hi, @rix0rrr, do you know if this issue is going to be fixed in the near future?

Many thanks,

Jordi

jordialemany avatar Jun 17 '25 09:06 jordialemany