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

aws-wafv2: Creation of webAcl with managedRuleGroupConfigs fails

Open j-jasmin opened this issue 3 years ago • 3 comments

Describe the bug

I want to create a webAcl with the managed rule group AWSManagedRulesATPRuleSet which requires additional config within managedRuleGroupConfigs. But when trying to deploy it, it keeps failing.

Expected Behavior

Actually create the resource.

Current Behavior

12:06:12 PM | CREATE_FAILED        | AWS::WAFv2::WebACL            | ATPValidationAcl
Resource handler returned message: "Error reason: EXACTLY_ONE_CONDITION_REQUIRED, field: MANAGED_RULE_GROUP_CONFIG, parameter: ManagedRuleGroupConfig (Service: Wafv2,
Status Code: 400, Request ID: 124db0d6-0590-48d6-92ff-816459c7d275, Extended Request ID: null)" (RequestToken: 21a88b2e-5ef2-e454-22df-ad8cdb6e71dd, HandlerErrorCode:
InvalidRequest)

Reproduction Steps

new CfnWebACL(this, 'ATPValidationAcl', {
      scope: 'CLOUDFRONT',
      defaultAction: {
        allow: {}
      },
      visibilityConfig: {
        cloudWatchMetricsEnabled: true,
        metricName: 'ATPValidationAcl',
        sampledRequestsEnabled: false,
      },
      rules: [{
        name: 'ATPModuleACL',
        priority: 1,
        visibilityConfig: {
          cloudWatchMetricsEnabled: true,
          metricName: 'AccountTakeOverValidationRule',
          sampledRequestsEnabled: false,
        },
        overrideAction: {
          none: {}
        },
        statement: {
          managedRuleGroupStatement: {
            name: 'AWSManagedRulesATPRuleSet',
            vendorName: 'AWS',
            excludedRules: [],
            managedRuleGroupConfigs: [
              {
                loginPath: 'login',
                passwordField: {
                  identifier: 'pwd',
                },
                payloadType: 'FORM_ENCODED',
                usernameField: {
                  identifier: 'login',
                }
              }
            ]
          },
        }
      }]
    });

Possible Solution

No response

Additional Information/Context

No response

CDK CLI Version

2.41.0

Framework Version

No response

Node.js Version

v18.7.0

OS

macOS 12.5.1

Language

Typescript

Language Version

No response

Other information

No response

j-jasmin avatar Sep 14 '22 10:09 j-jasmin

Hi @j-jasmin! Thanks for opening the issue. I've never used CfnWebACL before, but I suspect your issue has to do with how you are defining your managedRuleGroupConfigs. The type of managedRuleGroupConfigs is an object with a few properties. However, you have defined it as a list of objects, which javascript doesn't find problematic because lists are also objects. I think if you change it up a bit you'll fix your error:

managedRuleGroupStatement: {
    name: 'AWSManagedRulesATPRuleSet',
    vendorName: 'AWS',
    excludedRules: [],
    managedRuleGroupConfigs: {
      loginPath: 'login',
      passwordField: {
        identifier: 'pwd',
      },
      payloadType: 'FORM_ENCODED',
      usernameField: {
        identifier: 'login',
      },
    },
},

Let me know if that works / if you have other questions!

kaizencc avatar Sep 14 '22 17:09 kaizencc

hi @kaizencc! thanks for your quick response. that doesn't work either:

TSError: ⨯ Unable to compile TypeScript:
lib/waf-stack.ts:40:15 - error TS2322: Type '{ loginPath: string; passwordField: { identifier: string; }; payloadType: string; usernameField: { identifier: string; }; }' is not assignable to type 'IResolvable | (IResolvable | ManagedRuleGroupConfigProperty)[] | undefined'.
  Object literal may only specify known properties, and 'loginPath' does not exist in type 'IResolvable | (IResolvable | ManagedRuleGroupConfigProperty)[]'.

But I actually tried to do a synth (template looks the same as in this example) and deploy it with cloudformation - which gives me the same error. So I guess that's rather an issue on their side? 🤔

ghost avatar Sep 15 '22 07:09 ghost

Hello.

The issue is in the CDK I'm afraid. The generated CF code is not correct.

I've got an AWS support case and the engineer pointed out that the output definition should look like below

"ManagedRuleGroupStatement": {
	"ManagedRuleGroupConfigs": [{
			"LoginPath": "/portal/login"
		},
		{
			"PasswordField": {
				"Identifier": "LoginPasswordInputField"
			}
		},
		{
			"PayloadType": "FORM_ENCODED"
		},
		{
			"UsernameField": {
				"Identifier": "LoginIdInputField"
			}
		}
	],
	"Name": "AWSManagedRulesATPRuleSet",
	"VendorName": "AWS"
}

instead of:

"ManagedRuleGroupStatement": {
	"ManagedRuleGroupConfigs": [{
		"LoginPath": "/portal/login",
		"PasswordField": {
			"Identifier": "LoginPasswordInputField"
		},
		"PayloadType": "FORM_ENCODED",
		"UsernameField": {
			"Identifier": "LoginIdInputField"
		}
	}],
	"Name": "AWSManagedRulesATPRuleSet",
	"VendorName": "AWS"
}

airmonitor avatar Sep 21 '22 09:09 airmonitor

ManagedRuleGroupConfigs takes an array of properties, you can specify it exactly how the engineer said it should be specified if you separate your input into multiple arrays

        statement: {
          managedRuleGroupStatement: {
            name: 'AWSManagedRulesATPRuleSet',
            vendorName: 'AWS',
            excludedRules: [],
            managedRuleGroupConfigs: [
              {
                loginPath: 'login',
              },
              {
                passwordField: {
                  identifier: 'pwd',
                },
              },
              {
                payloadType: 'FORM_ENCODED',
              },
              {
                usernameField: {
                  identifier: 'login',
                }
              }
            ]
          },
        }

peterwoodworth avatar Sep 26 '22 23:09 peterwoodworth

ManagedRuleGroupConfigs takes an array of properties, you can specify it exactly how the engineer said it should be specified if you separate your input into multiple arrays

        statement: {
          managedRuleGroupStatement: {
            name: 'AWSManagedRulesATPRuleSet',
            vendorName: 'AWS',
            excludedRules: [],
            managedRuleGroupConfigs: [
              {
                loginPath: 'login',
              },
              {
                passwordField: {
                  identifier: 'pwd',
                },
              },
              {
                payloadType: 'FORM_ENCODED',
              },
              {
                usernameField: {
                  identifier: 'login',
                }
              }
            ]
          },
        }

I'm afraid that this is not possible in CDK

The managed rule group configs accept the below method that requires login_path, password_field, and username_field. I can't place 3 different ManagedRuleGroupConfigProperty there.

                         wafv2.CfnWebACL.ManagedRuleGroupConfigProperty(
                                login_path=aws_account_takeover_prevention["login_path"],  # type: ignore
                                password_field=wafv2.CfnWebACL.FieldIdentifierProperty(
                                    identifier=aws_account_takeover_prevention["password_field"]  # type: ignore
                                ),
                                payload_type="FORM_ENCODED",
                                username_field=wafv2.CfnWebACL.FieldIdentifierProperty(
                                    identifier=aws_account_takeover_prevention["username_field"]  # type: ignore
                                ),
                            )

airmonitor avatar Sep 27 '22 07:09 airmonitor

I'm afraid that this is not possible in CDK

The managed rule group configs accept the below method that requires login_path, password_field, and username_field. I can't place 3 different ManagedRuleGroupConfigProperty there.

I'm sorry, I'm not super sure what you mean by this. You pass in a list of ManagedRuleGroupConfigProperty when creating the statement. The example I gave in my previous comment synthesizes to your expected output in TypeScript

peterwoodworth avatar Sep 27 '22 21:09 peterwoodworth

No worry Peter.

The short story is that the python method enforces to use login, and password in one construct. That's mandatory. I can't split it into multiple objects as you presented in TS.

airmonitor avatar Sep 28 '22 07:09 airmonitor

hi @peterwoodworth! that did the trick - thank you! then you might wanna update the examples in the docs:

  • https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_wafv2.CfnWebACL.ManagedRuleGroupConfigProperty.html
  • https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_wafv2.CfnWebACL.html

ghost avatar Oct 04 '22 06:10 ghost

Hey @peterwoodworth.

Yes, I agree with @j-jasmin if you can add an example using native cdk constructs (not raw JSON) also in python I would be very grateful.

airmonitor avatar Oct 04 '22 07:10 airmonitor

I'm not sure where the docs are incorrect here. Everything on the pages you've linked that are relevant to this topic seems accurate to me. Could you be more specific please?

@airmonitor you can see a python example of using these constructs and properties here or here

peterwoodworth avatar Oct 04 '22 18:10 peterwoodworth

@peterwoodworth

Sadly bug is still there.

I copied the example provided by you from here

and I'm still getting errors during deployment:

Resource handler returned message: "Error reason: EXACTLY_ONE_CONDITION_REQUIRED, field: MANAGED_RULE_GROUP_CONFIG, parameter: ManagedRuleGroupConfig (Service: Wafv2, Status Code: 400, Request ID: c72b9398-3a3a-4711-8699-3bc10061032f, Extended Request ID: null)" (RequestTo
ken: 4969f147-6941-c4a9-95cb-838686a0638f, HandlerErrorCode: InvalidRequest)

airmonitor avatar Oct 04 '22 20:10 airmonitor

@airmonitor You need to create multiple values in your array being input for managed_rule_group_configs. The docs do not show this because the docs are autogenerated and so cannot be privy to the implementation details under CloudFormation's hood that prevent the generated example from being a deployable template. The docs are there to provide an example of values you can pass in, not meant to be deployable snippets.

This will work:

                statement=wafv2.CfnWebACL.StatementProperty(
                    managed_rule_group_statement=wafv2.CfnWebACL.ManagedRuleGroupStatementProperty(
                        managed_rule_group_configs=[
                            wafv2.CfnWebACL.ManagedRuleGroupConfigProperty(
                                login_path="loginPath"
                            ),
                            wafv2.CfnWebACL.ManagedRuleGroupConfigProperty(
                                password_field=wafv2.CfnWebACL.FieldIdentifierProperty(
                                    identifier="identifier"
                                )
                            ),
                            wafv2.CfnWebACL.ManagedRuleGroupConfigProperty(
                                payload_type="payloadType"
                            ),
                            wafv2.CfnWebACL.ManagedRuleGroupConfigProperty(
                                username_field=wafv2.CfnWebACL.FieldIdentifierProperty(
                                    identifier="identifier"
                                )
                            )
                        ],
                        name='name',
                        vendor_name='vendorname'
                    )
                ),

peterwoodworth avatar Oct 04 '22 20:10 peterwoodworth

⚠️COMMENT VISIBILITY WARNING⚠️

Comments on closed issues are hard for our team to see. If you need more assistance, please either tag a team member or open a new issue that references this one. If you wish to keep having a conversation with other community members under this issue feel free to do so.

github-actions[bot] avatar Oct 04 '22 20:10 github-actions[bot]