aws / aws/aws-cdk

s3/kms: IAM IResourcePolicyFactory, function in object

Open
#38,452 12 comments 0 reactions 0 assignees View on GitHub
@aws-cdk/aws-iam documentation effort/medium p2
Dominant language
TypeScript
Stars
12.9k
Forks
4.6k
Avg merge
2d 3h
Merged PRs (30d)
83

Description

### Describe the issue

Whilst working on the Ruby documentation I noticed the following issue which could probably do with some investigation, the S3[1] and KMS[2] docs when referencing IResourcePolicyFactory were generating the following in Ruby:

```ruby
require 'aws-cdk-lib'
require 'constructs'

scope = nil # Constructs::Construct
class MyFactory
include AWSCDK::IAM::IResourcePolicyFactory
def for_resource(resource)
return {
env: resource.env,
def add_to_resource_policy(statement)
# custom implementation to add the statement to the resource policy
return {statement_added: true, policy_dependable: resource}
end,
}
end
end

AWSCDK::IAM::ResourceWithPolicies.register(scope, "AWS::S3::Bucket", MyFactory.new)
```

The backing TypeScript[3] is:

```typescript
import { CfnResource } from 'aws-cdk-lib';
import { IResourcePolicyFactory, IResourceWithPolicyV2, PolicyStatement, ResourceWithPolicies } from 'aws-cdk-lib/aws-iam';
import { Construct, IConstruct } from 'constructs';

declare const scope: Construct;
class MyFactory implements IResourcePolicyFactory {
forResource(resource: CfnResource): IResourceWithPolicyV2 {
return {
env: resource.env,
addToResourcePolicy(statement: PolicyStatement) {
// custom implementation to add the statement to the resource policy
return { statementAdded: true, policyDependable: resource };
}
}
}
}

ResourceWithPolicies.register(scope, 'AWS::S3::Bucket', new MyFactory());
```

There are a few issues here:

- Python documentation[4] and Java documentation[5] are similarly broken
- How exactly should we handle this?

In Java we have

```java
import software.amazon.awscdk.CfnResource;
import software.amazon.awscdk.services.iam.IResourcePolicyFactory;
import software.amazon.awscdk.services.iam.IResourceWithPolicyV2;
import software.amazon.awscdk.services.iam.PolicyStatement;
import software.amazon.awscdk.services.iam.ResourceWithPolicies;
import software.constructs.Construct;
import software.constructs.IConstruct;

Construct scope;
public class MyFactory implements IResourcePolicyFactory {
public IResourceWithPolicyV2 forResource(CfnResource resource) {
return Map.of(
"env", resource.getEnv(),
public Map addToResourcePolicy(PolicyStatement statement) {
// custom implementation to add the statement to the resource policy
return AddToResourcePolicyResult.builder()"statementAdded", true"policyDependable", resource.build();
});
}
}

ResourceWithPolicies.register(scope, "AWS::S3::Bucket", new MyFactory());
```

In Python, we have:

```python
from aws_cdk.aws_iam import AddToResourcePolicyResult
from aws_cdk import CfnResource
from aws_cdk.aws_iam import IResourcePolicyFactory, IResourceWithPolicyV2, PolicyStatement, ResourceWithPolicies
from constructs import Construct, IConstruct

# scope: Construct
@jsii.implements(IResourcePolicyFactory)
class MyFactory:
def for_resource(self, resource):
return {
"env": resource.env,
def add_to_resource_policy(self, statement):
# custom implementation to add the statement to the resource policy
return AddToResourcePolicyResult("statement_added"=True, "policy_dependable"=resource)
}

ResourceWithPolicies.register(scope, "AWS::S3::Bucket", MyFactory())
```

A potential fix for something comparable in Ruby would be:

```ruby
class MyFactory
include AWSCDK::IAM::IResourcePolicyFactory
def for_resource(resource)
return Class.new do
include AWSCDK::IAM::IResourceWithPolicyV2
define_method(:env) { resource.env }
define_method(:add_to_resource_policy) do |statement|
return {statement_added: true, policy_dependable: resource}
end
end.new
end
end
```

However this doesn't look great and introduces meta-programming like smells (both `Class.new {}.new` and `define_method`), a stabby proc `->(statement) { return { ... } }` is not acceptable here because to execute, we would have to use h[:add_to_resource_policy].call(statement) which is not what the CDK does.

### Links

[1] https://rubygems.omarqureshi.net/docs/AWSCDK/S3/index.html
[2] https://rubygems.omarqureshi.net/docs/AWSCDK/KMS/index.html
[3] https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3-readme.html
[4] https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk.aws_s3/README.html
[5] https://docs.aws.amazon.com/cdk/api/v2/java/software/amazon/awscdk/services/s3/package-summary.html

Contributor guide

Open the contributing guide

Research direction

Start by comparing the generated S3 and KMS documentation linked in [1]-[5] with the TypeScript IResourcePolicyFactory example in [3]. Determine how the documentation generation should represent callback-bearing interfaces in Ruby, Python, and Java; done means the affected examples are valid and consistent across those languages.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, python, ruby, typescript
Domain
documentation
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.