-
Notifications
You must be signed in to change notification settings - Fork 4k
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
(aws-cdk-lib/aws-s3): Too many BucketPolicy resources defined when defining/attaching BucketPolicy constructs to Buckets #30148
Comments
Hi @climbertjh2 , Thanks for reaching out. Could you please provide the minimum sample code for repro of this issue ? |
This issue has not received a response in a while. If you want to keep this issue open, please leave a comment below and auto-close will be canceled. |
@khushail - I will try to create a small sample. (I left instructions above in the description). |
I have tried to re-create without success. Closing this one. |
|
@khushail - correction - I have been able to re-create this. Re-opening the issue. |
Pasting in an example to re-create - with some commentary: import { Stack, StackProps, RemovalPolicy, aws_s3 as s3, aws_iam as iam } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { resourceUsage } from 'process';
// import * as sqs from 'aws-cdk-lib/aws-sqs';
export class CdkBug30148Stack extends Stack {
private bucket01: s3.Bucket;
private bucketPolicy01: s3.CfnBucketPolicy;
private bucket02: s3.Bucket;
private bucketPolicy02: s3.CfnBucketPolicy;
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
// The code that defines your stack goes here
const bucket01Name="my-favorite-bucket-name-01";
this.bucket01 = new s3.Bucket(this, "Bucket01", {
bucketName: bucket01Name,
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
encryption: s3.BucketEncryption.S3_MANAGED,
// enforceSSL: true,
versioned: true,
removalPolicy: RemovalPolicy.RETAIN,
})
// Instead of using enforceSSL: true, set the bucket policy explicitily
// This creates a AWS::S3::BucketPolicy resource in the CloudFormation template
this.bucketPolicy01 = new s3.CfnBucketPolicy( this, "BucketPolicy01", {
bucket: bucket01Name,
policyDocument: {
Statement: [
{
Effect: "Deny",
Action: [
"s3:*"
],
Principal: {
"AWS": "*"
},
Resource: [
// `arn:aws:s3:::${bucket01Name}`,
// `arn:aws:s3:::${bucket01Name}/*`,
this.bucket01.bucketArn,
`${this.bucket01.bucketArn}/*`,
],
Condition: {
"Bool": {
"aws:SecureTransport": false
}
}
},
{
Effect: "Deny",
Action: [
"s3:PutObject"
],
Principal: {
"AWS": "*"
},
Resource: [
// `arn:aws:s3:::${bucket01Name}`,
// `arn:aws:s3:::${bucket01Name}/*`,
this.bucket01.bucketArn,
`${this.bucket01.bucketArn}/*`,
]
}
]
}
})
const bucket02Name="my-favorite-bucket-name-02";
this.bucket02 = new s3.Bucket(this, "Bucket02", {
bucketName: bucket02Name,
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
encryption: s3.BucketEncryption.S3_MANAGED,
// enforceSSL: true,
versioned: true,
removalPolicy: RemovalPolicy.RETAIN,
// The addition of this property has the SIDE-EFFECT of adding (and overwriting)
// the BucketPolicy that was associated with bucket01 above.
//
// The net result is that there are 3 AWS::S3::BucketPolicy resources defined
// in the CloudFormation template, and only the "last" one created
// (the one associated with setting up a bucket policy for the Logging service
// to write to the Access Logs bucket) is what is associated with bucket01.
serverAccessLogsBucket: this.bucket01
})
// Instead of using enforceSSL: true, set the bucket policy explicitily
// This creates a AWS::S3::BucketPolicy resource in the CloudFormation template
this.bucketPolicy02 = new s3.CfnBucketPolicy( this, "BucketPolicy02", {
bucket: bucket02Name,
policyDocument: {
Statement: [
{
Effect: "Deny",
Action: [
"s3:*"
],
Principal: {
"AWS": "*"
},
Resource: [
// `arn:aws:s3:::${bucket02Name}`,
// `arn:aws:s3:::${bucket02Name}/*`,
this.bucket02.bucketArn,
`${this.bucket02.bucketArn}/*`,
],
Condition: {
Bool: {
"aws:SecureTransport": false
}
}
}
]
}
})
}
} The net result, after deploying that Stack, is that 3 BucketPolicies are created, but only 2 of them are in effect. The explicit BucketPolicy associated with |
NOTE - I also noticed something else while re-creating this issue. IF This seems like a way around the **IF |
Hey @climbertjh2 , thanks for sharing the code and having patience! I repro'd the issue and here is my observation -
Resources
[+] AWS::S3::Bucket Bucket0001 Bucket00014CEA8A3F
[+] AWS::S3::BucketPolicy BucketPolicy0001 BucketPolicy0001
[+] AWS::S3::Bucket Bucket0002 Bucket0002E47E4676
[+] AWS::S3::BucketPolicy BucketPolicy0002 BucketPolicy0002
Resources
[+] AWS::S3::BucketPolicy Bucket0001/Policy Bucket0001Policy335FA23C
[~] AWS::S3::Bucket Bucket0002 Bucket0002E47E4676
└─ [+] LoggingConfiguration
└─ {"DestinationBucketName":{"Ref":"Bucket00014CEA8A3F"}}
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "logging.s3.amazonaws.com"
},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::my-favorite-bucket-0001/*",
"Condition": {
"StringEquals": {
"aws:SourceAccount": "*************"
},
"ArnLike": {
"aws:SourceArn": "arn:aws:s3:::my-favorite-bucket-name-0002"
}
}
}
So yes, your point is absolutely Correct. The last bucket policy overwrites the existing one. Also enabling Checking the CDK code, I think this might be the Custom policy overwrites the existing one - aws-cdk/packages/aws-cdk-lib/aws-s3/lib/bucket.ts Line 2472 in 8d55d86
and this is where its called - aws-cdk/packages/aws-cdk-lib/aws-s3/lib/bucket.ts Line 1976 in 8d55d86
Thanks for reporting this! |
I didn't look at the code - but just considering the situation, it feels like the L2 construct isn't checking whether a L1 CfnBucketPolicy is associated with the bucket prior to creating a bucket policy (in this example, to add the access logging permissions). This mixing of L2 and L1 constructs may be discouraged - but it is possible. |
This should not be classified as
or additionally you can
|
I agree that this is not |
Yes, you're right. And I believe this is the correct behaviour and L2 should not check for the existence of L1 constructs. If we start doing this here, there are plenty more places to check. For this issue, I think what I can do is to update the S3 documentation and explains the limitation and suggest the workarounds like above, either using |
@GavinZZ - I'm OK with that resolution - update the documentation to point out not mixing L2 and L1 constructs - or if doing so, suggest the alternatives as noted. |
Comments on closed issues and PRs are hard for our team to see. |
1 similar comment
Comments on closed issues and PRs are hard for our team to see. |
Describe the bug
Situation:
Bucket
constructs in aStack
BucketPolicy
constructs in the sameStack
Result:
AWS::S3::BucketPolicy
CloudFormation resources are synthesizedStack
is deployedBucketPolicy
(not the UNION of theBucketPolicy
constructs) "wins"BucketPolicy
does not match what is defined in the CDK application.Expected Behavior
Expected Behavior is either:
BucketPolicy
is createdBucketPolicy
and the explicitly createdBucketPolicy
is what is synthesized/deployedBucketPolicy
would NOT be appropriate if it lacks the necessary permissions (in this case, allowing the AWS logging service to be able to write to the identified access logging bucket)Current Behavior
Result:
AWS::S3::BucketPolicy
CloudFormation resources are synthesizedStack
is deployedBucketPolicy
(not the UNION of theBucketPolicy
constructs) "wins"BucketPolicy
does not match what is defined in the CDK application.Reproduction Steps
See above.
Possible Solution
Suggested Behavior:
BucketPolicy
is NOT appropriate since it lacks the necessary permissions (in this case, allowing the AWS logging service to be able to write to the identified access logging bucket)Or a recommendation to use
.addToResourcePolicy()
rather than creating explicitBucketPolicy
constructs.Additional Information/Context
Sample code can be provided on request.
CDK CLI Version
2.141.0
Framework Version
[email protected]
Node.js Version
v20.12.2
OS
MacOS
Language
TypeScript
Language Version
[email protected]
Other information
No response
The text was updated successfully, but these errors were encountered: