Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trigger: Token strings not resolving #28017

Closed
Daniel-ZA opened this issue Nov 15, 2023 · 9 comments · Fixed by #31457 or softwaremill/tapir#4137 · May be fixed by #31443, NOUIY/aws-solutions-constructs#135 or NOUIY/aws-solutions-constructs#136
Closed
Assignees
Labels
@aws-cdk/core Related to core CDK functionality @aws-cdk/triggers Related to the triggers package bug This issue is a bug. effort/medium Medium work item – several days of effort p1

Comments

@Daniel-ZA
Copy link

Describe the bug

Hi Team,

Just opening this ticket where the "Token" strings are not resolving during deployment and stays as "Token" strings ${Token[TOKEN.664]}. This results in the error below:

 "3 validation errors detected: Value '${Token[TOKEN.664]}' at 'tags.1.member.value' failed to satisfy constraint: Member must satisfy regular expression pattern: [\p{L}\p{Z}\p{N}_.:/=+\-@]*;

The error above is thrown against the "AWS::IAM::Role" which the Trigger construct creates because the value of its tag is a token string ${Token[TOKEN.664]} which did not resolve during deployment and is not a valid value for a Tag.

For context, the setup here is that stack-level tags are being applied to the resources in the CDK stack (see code below) where its Tag value is retrieved from a resolvable token SSM parameter.

    const stringValue = ssm.StringParameter.fromStringParameterAttributes(this, 'MyValue', {
      parameterName: 'StringParameter',
      // 'version' can be specified but is optional.
    }).stringValue;

    const func = new lambda.Function(this, 'MyFunction', {
      handler: 'index.handler',
      runtime: lambda.Runtime.NODEJS_18_X,
      code: lambda.Code.fromInline('foo'),
    });
    
    const trigger = new triggers.Trigger(this, 'MyTrigger', {
      handler: func,
      timeout: cdk.Duration.minutes(10),
      invocationType: triggers.InvocationType.EVENT,
    });

    # Apply stack-level tags where value come from the SSM parameter
    cdk.Tags.of(this).add("test", stringValue)

The value of these tags come from an SSM parameter stringValue which is a resolvable token. This error seems to occur when creating the IAM role that the parent construct Trigger creates:

    * AWS::IAM::Role
    * AWS::Lambda::Version
    * AWS::Lambda::Function
    * Custom::Trigger

Comparing this with a similar parent construct AwsCustomResource, the token strings are resolving during deployment and the tags are appropriately propagating to its child resources (AWS::IAM::Role, AWS::Lambda::Function).

    const stringValue = ssm.StringParameter.fromStringParameterAttributes(this, 'MyValue', {
      parameterName: 'StringParameter',
      // 'version' can be specified but is optional.
    }).stringValue;

    const getParameter = new cr.AwsCustomResource(this, 'GetParameter', {
      onUpdate: { // will also be called for a CREATE event
        service: 'SSM',
        action: 'getParameter',
        parameters: {
          Name: 'my-parameter',
          WithDecryption: true,
        },
        physicalResourceId: cr.PhysicalResourceId.of(Date.now().toString()), // Update physical id to always fetch the latest version
      },
      policy: cr.AwsCustomResourcePolicy.fromSdkCalls({
        resources: cr.AwsCustomResourcePolicy.ANY_RESOURCE,
      }),
    });

    cdk.Tags.of(this).add("test", stringValue)

Hence, I'm presuming there is an issue with the Trigger construct such that token strings passed to its child resources are not resolving during deployment. I also noticed within the template that the "Tags" are not propagating to the child resources (Role, Lambda Function) during synthesis when compared to AwsCustomResources where "Tags" are visible in the synthesized template.

I also did some additional testing and this time just passing tag values as a simple string instead of SSM parameters and the deployment went through for Trigger and propagated the tags to the child resources but this wasn't still visible in the template.

Are you able to give me an idea to why this happens, perhaps there is a gap with the Trigger construct? Is this a bug?

Expected Behavior

Token strings of stack-level tags applied on child resources of Trigger not resolved during deployment

Current Behavior

Token strings of stack-level tags applied on child resources of Trigger to be resolved during deployment

Reproduction Steps

Possible Solution

No response

Additional Information/Context

No response

CDK CLI Version

2.88.0

Framework Version

No response

Node.js Version

v18.7.0

OS

Windows

Language

TypeScript

Language Version

TypeScript

Other information

No response

@Daniel-ZA Daniel-ZA added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Nov 15, 2023
@github-actions github-actions bot added the @aws-cdk/triggers Related to the triggers package label Nov 15, 2023
@pahud
Copy link
Contributor

pahud commented Nov 16, 2023

Yes I can reproduce this but can't find the root cause off the top of my head. We'll review this issue in the next few days.

@sheridansmall
Copy link

I get the same issue adding the parameter cleanup=aws_synthetics.Cleanup.LAMBDA to aws_synthetics.Canary() with a tag added from a SSM parameter.

@aodale
Copy link

aodale commented Apr 12, 2024

Any updates on this issue version 2.137

Member must satisfy regular expression pattern:

CREATE_FAILED | AWS::IAM::Role | Custom::S3AutoDeleteObjectsCustomResourceProvider/Role (CustomS3AutoDeleteObjectsCustomResourceProviderRole3B1BD092) Resource handler returned message: "1 validation error detected: Value '${Token[AWS.Region.11]}' at 'tags.3.member.value' failed to satisfy constraint: Member must satisfy regular expression pattern: [\p{L}\p{Z}\p{N}_.:/=+-@]* (Service: Iam, Status Code: 400, ...)

@pahud pahud added the @aws-cdk/core Related to core CDK functionality label Apr 17, 2024
@comcalvi
Copy link
Contributor

This is not an issue with triggers, it's a duplicate of #29424.

The culprit is

cdk.Tags.of(this).add("test", stringValue)

The this references the entire stack, meaning that this gets added as a stack tag. The problem is that stack tags cannot be resolved by CloudFormation, because they are passed over the SDK call as parameters to UpdateStack or CreateStack. The CLI makes that call, which means it would have to resolve that token; but it can't, only CFN does that (outside of hotswapping), so this will not work.

@comcalvi
Copy link
Contributor

You can reference the SSM parameter value in a tag if you apply it at the construct level, and not on the stack itself.

@comcalvi
Copy link
Contributor

We also can't throw an error here, because users could have unresolved stack tags on stacks that have resources that happen to allow unresolved tokens.

@rix0rrr
Copy link
Contributor

rix0rrr commented Sep 13, 2024

The behavior of stack tags is undesirable. Let's fix it.

@rix0rrr rix0rrr self-assigned this Sep 13, 2024
rix0rrr added a commit that referenced this issue Sep 13, 2024
Stacks are considered taggable, and so `Tags.of(this).add('key',
'value')` used to add tags to Stacks in scope. Usually this happens if
`this` is an instance of `Stack`, which it commonly is in user code.

Since `Tags.of(...)` walks the construct tree, it will add tags to the
stack *and* to all the resources in the stack. Then, come deploy time,
CloudFormation will also try and apply all the stack tags to the
resources again. This is silly and unnecessary.

In #28017, someone tries to use a CloudFormation intrisinc in a tag
applied using `Tags.of(this)`; that will work for resources as the tags
are rendered into the template, but it will not work for the stack
tags as those are passed via an API call, and intrinsics don't work
there.

IN THIS CHANGE

The *correct* solution to tagging all resources with an intrinsic
would be to tag each of them individually, as tagging a Stack
with an intrinsic is not possible. That's a poor user experience.

Resolve both the silly duplicate work as well as the "tagging with
an intrinsic" use case as follows:

- Stacks no longer participate in the hierarchical `Tags.of(...)`
  tagging.
- Instead, only tags explicitly applied at the stack level (using
  the `tags` constructor property) are renderd as stack tags.

This requires a user to make a conscious decision between resource-level
and stack-level tagging: either apply tags to the stack, which will
apply it to all resources; or apply tags to (groups of) resources inside
the template.
rix0rrr added a commit that referenced this issue Sep 16, 2024
Stack tags are not rendered to the template, but instead are passed via
API call.

Verify that stack tags do not contain unresolved values, as they won't
work.

Closes #28017.
@mergify mergify bot closed this as completed in #31457 Sep 25, 2024
@mergify mergify bot closed this as completed in abd1768 Sep 25, 2024
Copy link

Comments on closed issues and PRs are hard for our team to see.
If you need help, please open a new issue that references this one.

1 similar comment
Copy link

Comments on closed issues and PRs are hard for our team to see.
If you need help, please open a new issue that references this one.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Sep 25, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.