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

(custom-resources): AwsCustomResourcePolicy.fromSdkCalls does not work with v3 command format #27255

Closed
luxaritas opened this issue Sep 22, 2023 · 2 comments · Fixed by #27313
Labels
@aws-cdk/custom-resources Related to AWS CDK Custom Resources bug This issue is a bug. effort/medium Medium work item – several days of effort p2

Comments

@luxaritas
Copy link
Contributor

luxaritas commented Sep 22, 2023

Describe the bug

Creating an AwsCustomResource with a service/action using the AWS CDK v3 format and a policy AwsCustomResourcePolicy.fromSdkCalls fails

Expected Behavior

A policy is correctly created

Current Behavior

Error: Action '@aws-sdk/client-ec2:ModifyInstanceMetadataOptionsCommand' is invalid. An action string consists of a service namespace, a colon, and the name of an action. Action names can include wildcards.
    at PolicyStatement.validatePolicyActions (/home/jonathan/Development/eterna/infra/node_modules/aws-cdk-lib/aws-iam/lib/policy-statement.js:2:3414)
    at PolicyStatement.addActions (/home/jonathan/Development/eterna/infra/node_modules/aws-cdk-lib/aws-iam/lib/policy-statement.js:2:1290)
    at new PolicyStatement (/home/jonathan/Development/eterna/infra/node_modules/aws-cdk-lib/aws-iam/lib/policy-statement.js:2:579)
    at new AwsCustomResource (/home/jonathan/Development/eterna/infra/node_modules/aws-cdk-lib/custom-resources/lib/aws-custom-resource/aws-custom-resource.js:1:5701

Reproduction Steps

The call I'm currently running into this with:

new AwsCustomResource(instance, `enableMetadataTags`, {
  onCreate: {
    service: '@aws-sdk/client-ec2',
    action: 'ModifyInstanceMetadataOptionsCommand',
    parameters: {
      InstanceId: instance.instanceId,
      InstanceMetadataTags: 'enabled'
    },
    physicalResourceId: PhysicalResourceId.of('EnableMetadataTags')
  },
  onDelete: {
    service: '@aws-sdk/client-ec2',
    action: 'ModifyInstanceMetadataOptionsCommand',
    parameters: {
      InstanceId: instance.instanceId,
      InstanceMetadataTags: 'disabled'
    }
  },
  policy: AwsCustomResourcePolicy.fromSdkCalls({
    resources: AwsCustomResourcePolicy.ANY_RESOURCE
  })
});

Possible Solution

I'm assuming to construct the correct policy, the service name needs to strip @aws-sdk/client- and the action needs to strip Command

Additional Information/Context

No response

CDK CLI Version

2.94.0 (build 987c329)

Framework Version

No response

Node.js Version

v18.17.1

OS

Linux

Language

Typescript

Language Version

No response

Other information

If my assessment is correct, this should be easy for me to submit a PR for if that would be helpful!

@luxaritas luxaritas added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Sep 22, 2023
@github-actions github-actions bot added the @aws-cdk/custom-resources Related to AWS CDK Custom Resources label Sep 22, 2023
@khushail khushail added investigating This issue is being investigated and/or work is in progress to resolve the issue. and removed needs-triage This issue or PR still needs to be triaged. labels Sep 22, 2023
@khushail
Copy link
Contributor

Hi @luxaritas , thanks for reporting this.

@WinterYukky , thanks for submitting PR.

@khushail khushail added p2 effort/medium Medium work item – several days of effort and removed investigating This issue is being investigated and/or work is in progress to resolve the issue. labels Sep 25, 2023
rix0rrr added a commit that referenced this issue Sep 27, 2023
In the `AwsCustomResource` and the `Assertions` libraries, we advertise
accepting all of the following service name formats:

* The SDKv3 service name: `api-gateway`
* The full SDKv3 package name: `@aws-sdk/client-api-gateway`
* The SDKv2 constructor name: `APIGateway`
* The SDKv2 constructor name in all lower case: `apigateway`

And the following action name formats:

* The API call name: `GetRestApi`
* The API call name with a lowercase starting letter method name: `getRestApi`
* The SDKv3 command class name: `GetRestApiCommand`

However, the code that was taking care of mapping service names into an
IAM name was not handling all cases correctly. There was also an issue
with some commands that end in the word `"Command"`, like ECS's
`ExecuteCommand`, which according to the rules above should work both
written as `ExecuteCommand` as well as `ExecuteCommandCommand`: we did
not have enough information to know if we saw the string
`ExecuteCommand`, whether we should interpret it as `Execute` or
`ExecuteCommand`.

Also, we were recommending to use the full SDKv3 package name and class
name formats:

```
{
  service: '@aws-sdk/client-api-gateway',
  action: 'GetRestApiCommand',
}
```

Which looks ugly (imo) and leaks too many of the underlying
implementation details.

This PR changes the following:

- Deprecate the `sdk-api-metadata.json` we extracted from SDKv2.
- From SDKv3 models, extract a new `sdk-v3-metadata.json` which contains
  the following information:
  - IAM prefix for every service
  - A list of APIs that end in the word `Command`, so we can
    disambiguate around these.
- From `aws-sdk-codemod`, extract a mapping from SDKv2 service names to
  SDKv3 service names (replacing the copy/pasted code we used to have
  with a build-time extraction).
- Unfortunately, both of these mappings are duplicated: once for the
  construct library, and once for the handlers. I did not want to go
  into deduplicating between these for now.
- At runtime, we now map a potential V2 service name to a V3 service
  name, then look up the V3 metadata to determine the IAM prefix and
  the normalized action name.
- There was a lot of duplication between the `assertions` handler and
  the `AwsCustomResource` handler. Introduce a new `ApiCall` class that
  unifies the behavior between these two call sites.
- Change the recommendation in the README from using SDKv3 names to
  using shorter form names (`api-gateway` and `GetRestApi`).

Fixes #27255, closes #27268, closes #27270.
@mergify mergify bot closed this as completed in #27313 Oct 5, 2023
mergify bot pushed a commit that referenced this issue Oct 5, 2023
In the `AwsCustomResource` and the `Assertions` libraries, we advertise accepting all of the following service name formats:

* The SDKv3 service name: `api-gateway`
* The full SDKv3 package name: `@aws-sdk/client-api-gateway`
* The SDKv2 constructor name: `APIGateway`
* The SDKv2 constructor name in all lower case: `apigateway`

And the following action name formats:

* The API call name: `GetRestApi`
* The API call name with a lowercase starting letter method name: `getRestApi`
* The SDKv3 command class name: `GetRestApiCommand`

However, the code that was taking care of mapping service names into an IAM name was not handling all cases correctly. There was also an issue with some commands that end in the word `"Command"`, like ECS's `ExecuteCommand`, which according to the rules above should work both written as `ExecuteCommand` as well as `ExecuteCommandCommand`: we did not have enough information to know if we saw the string `ExecuteCommand`, whether we should interpret it as `Execute` or `ExecuteCommand`.

Also, we were recommending to use the full SDKv3 package name and class name formats:

```
{
  service: '@aws-sdk/client-api-gateway',
  action: 'GetRestApiCommand',
}
```

Which looks ugly (imo) and leaks too many of the underlying implementation details.

This PR changes the following:

- Deprecate the `sdk-api-metadata.json` we extracted from SDKv2.
- From SDKv3 models, extract a new `sdk-v3-metadata.json` which contains the following information:
  - IAM prefix for every service
  - A list of APIs that end in the word `Command`, so we can disambiguate around these.
- From `aws-sdk-codemod`, extract a mapping from SDKv2 service names to SDKv3 service names (replacing the copy/pasted code we used to have with a build-time extraction).
- Unfortunately, both of these mappings are duplicated: once for the construct library, and once for the handlers. I did not want to go into deduplicating between these for now.
- At runtime, we now map a potential V2 service name to a V3 service name, then look up the V3 metadata to determine the IAM prefix and the normalized action name.
- There was a lot of duplication between the `assertions` handler and the `AwsCustomResource` handler (and to a lesser degree, the `events.ApiCall` handler), around loading SDKs and coercing values. Introduce a new `ApiCall` class that unifies the behavior between these call sites.
- Change the recommendation in the README from using SDKv3 names to using shorter form names (`api-gateway` and `GetRestApi`).
- Add "dynamic reuqire" protection to the `esbuild` commands for custom resources. 

Fixes #27255, closes #27268, closes #27270, closes #27395.

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
@github-actions
Copy link

github-actions bot commented Oct 5, 2023

⚠️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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
@aws-cdk/custom-resources Related to AWS CDK Custom Resources bug This issue is a bug. effort/medium Medium work item – several days of effort p2
Projects
None yet
2 participants