Skip to content

core: CfnParser can't correctly parse conditional Tags #27594

@jaredlundell

Description

@jaredlundell

Describe the bug

The CfnParser class (used by the CfnInclude construct) cannot correctly parse Tag declarations that conditionally include tags. Using intrinsic functions inside the Key or Value of a Tag is fine, but if you try to declare a tag using a top-level Fn::If (which is allowed by CloudFormation), parsing using CfnParser fails.

Expected Behavior

CfnParser should be able to correctly parse Tag declarations that use Fn::If.

Current Behavior

Tag declarations that use top-level Fn::If get turned into an empty {} by CfnParser, which causes failure during synthesis when {} is rejected as an invalid Tag by validateCfnTag()

The error message looks like this:

CfnSynthesisError: Resolution error: Supplied properties not correct for "CfnLoadBalancerProps"
  tags: element 0: {} should have a 'key' and a 'value' property.
    at ValidationResult.assertSuccess (/workplace/cdkApp/node_modules/aws-cdk-lib/core/lib/runtime.js:11:1271)
    at convertCfnLoadBalancerPropsToCloudFormation (/workplace/cdkApp/node_modules/aws-cdk-lib/aws-elasticloadbalancingv2/lib/elasticloadbalancingv2.generated.js:26:80)
    at CfnLoadBalancer.renderProperties (/workplace/cdkApp/node_modules/aws-cdk-lib/aws-elasticloadbalancingv2/lib/elasticloadbalancingv2.generated.js:20:2083)
    at PostResolveToken.Resources [as processor] (/workplace/cdkApp/node_modules/aws-cdk-lib/core/lib/cfn-resource.js:1:7100)
    at PostResolveToken.postProcess (/workplace/cdkApp/node_modules/aws-cdk-lib/core/lib/util.js:1:1565)
    at Object.postProcess (/workplace/cdkApp/node_modules/aws-cdk-lib/core/lib/private/resolve.js:1:1018)
    at DefaultTokenResolver.resolveToken (/workplace/cdkApp/node_modules/aws-cdk-lib/core/lib/resolvable.js:1:1320)
    at resolve (/workplace/cdkApp/node_modules/aws-cdk-lib/core/lib/private/resolve.js:1:2510)
    at Object.resolve (/workplace/cdkApp/node_modules/aws-cdk-lib/core/lib/private/resolve.js:1:892)
    at resolve (/workplace/cdkApp/node_modules/aws-cdk-lib/core/lib/private/resolve.js:1:2787) {
  type: 'CfnSynthesisError'

Reproduction Steps

Create a CFN template with a resource containing a tag specification that looks like this:

"Tags" : [
  {
    "Fn::If" : [
      "ShouldIncludeTag",
      {"Key" : "TagName", "Value" : "TagValue"},
      {"Ref" :  "AWS::NoValue"}
    ]
  }
]

If you try to include that template into a CDK application using CfnInclude, it results in a synthesis failure.

Possible Solution

There are two places that are causing problems here. The first is the FromCloudFormation.getCfnTag() function from cfn-parse.ts. It assumes that a parsed tag will always be an object with Key and Value properties. Tags declared using Fn::If get turned into an IResolvable object instead. Adding if (isResolvableObject(tag)) { return tag } to getCfnTag() should solve that part of the problem.

The second problem is the cfnTagToCloudFormation() function from runtime.ts. It also assumes that tags are always objects with Key and Value properties. My recommended solution here would be to add if (!canInspect(x)) { return x; }, similar to what the listMapper and hashMapper functions do.

Additional Information/Context

No response

CDK CLI Version

2.94

Framework Version

No response

Node.js Version

18.16.0

OS

Linux

Language

TypeScript

Language Version

No response

Other information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    @aws-cdk/coreRelated to core CDK functionalitybugThis issue is a bug.p1

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions