aws-cdk icon indicating copy to clipboard operation
aws-cdk copied to clipboard

(aws_cloudtrail >> Trail): (Invalid request provided: Incorrect S3 bucket policy is detected for bucket)

Open ayrawat17 opened this issue 1 year ago • 2 comments

Describe the bug

Unable to create Organization Trail in management account when using the i.e as per the doc : ++++++++++++++++++++++++++++++++++++++++ new cloudtrail.Trail(this, 'OrganizationTrail', { isOrganizationTrail: true, orgId: "o-xxxxxxxxx", }); ++++++++++++++++++++++++++++++++++++++++ This fail with the "Invalid request provided: Incorrect S3 bucket policy is detected for bucket" every-time.

Only when we add the trailName property explicitly to some string name it is then we are somehow able to mitigate the "Invalid request provided: Incorrect S3 bucket policy is detected for bucket" ++++++++++++++++++++++++++++++++++++++++ new cloudtrail.Trail(this, 'OrganizationTrail', { isOrganizationTrail: true, orgId: "o-xxxxxxxxx", trailName: "trailname123" }); ++++++++++++++++++++++++++++++++++++++++

Regression Issue

  • [ ] Select this option if this issue appears to be a regression.

Last Known Working CDK Version

2.157.0

Expected Behavior

To work without explicitly passing the trailName: property .

Current Behavior

CreateTrial API fails with the "Invalid request provided: Incorrect S3 bucket policy is detected for bucket" when using the following code to create Organization Trail: ++++++++++++++++++++++++++++++++++++++++ new cloudtrail.Trail(this, 'OrganizationTrail', { isOrganizationTrail: true, orgId: "o-xxxxxxxxx", }); ++++++++++++++++++++++++++++++++++++++++

Reproduction Steps

Use : ++++++++++++++++++++++++++++++++++++++++ new cloudtrail.Trail(this, 'OrganizationTrail', { isOrganizationTrail: true, orgId: "o-xxxxxxxxx", }); ++++++++++++++++++++++++++++++++++++++++

Possible Solution

To add trailName property explicitly

Additional Information/Context

NA

CDK CLI Version

2.157.0

Framework Version

No response

Node.js Version

v16.14.2

OS

MAC

Language

TypeScript

Language Version

No response

Other information

No response

ayrawat17 avatar Sep 11 '24 04:09 ayrawat17

Hi @ayrawat17 , thanks for reaching out.

The issue is reproducible. Sharing the observation -

    const cldtrail = new cloudtrail.Trail(this, 'cloudtrail001', {
      trailName: 'cloudtrail001',
      isOrganizationTrail: true,
    });

this is the snippet of synthesized bucket policy PutObject created -

      {
       "Action": "s3:PutObject",
       "Condition": {
        "StringEquals": {
         "s3:x-amz-acl": "bucket-owner-full-control",
         "aws:SourceArn": {
          "Fn::Join": [
           "",
           [
            "arn:",
            {
             "Ref": "AWS::Partition"
            },
            ":cloudtrail:",
            {
             "Ref": "AWS::Region"
            },
            ":",
            {
             "Ref": "AWS::AccountId"
            },
            ":trail/undefined"
           ]
          ]
         }
        }
       },

where ":trail/undefined" is worth concerning.

Ideally it should not have been undefined and expected to be like this. So when you add trailName , it gets updated to -

       "Action": "s3:PutObject",
       "Condition": {
        "StringEquals": {
         "s3:x-amz-acl": "bucket-owner-full-control",
         "aws:SourceArn": {
          "Fn::Join": [
           "",
           [
            "arn:",
            {
             "Ref": "AWS::Partition"
            },
            ":cloudtrail:",
            {
             "Ref": "AWS::Region"
            },
            ":",
            {
             "Ref": "AWS::AccountId"
            },
            ":trail/cloudtrail001"
           ]
          ]

Now according to CDK, this trailName should be generated by AWS Cloudformation but is left blank and unchecked

https://github.com/aws/aws-cdk/blob/95c49abdfa4ad77a0c0fcb82a230778dcc2ea59a/packages/aws-cdk-lib/aws-cloudtrail/lib/cloudtrail.ts#L100C1-L105C31

  /**
   * The name of the trail. We recommend customers do not set an explicit name.
   *
   * @default - AWS CloudFormation generated name.
   */
  readonly trailName?: string;

Referring further, it looks like the trailName is passed onto Bucket Policy which seems to be leading to error when left blank -

https://github.com/aws/aws-cdk/blob/95c49abdfa4ad77a0c0fcb82a230778dcc2ea59a/packages/aws-cdk-lib/aws-cloudtrail/lib/cloudtrail.ts#L278C1-L287C6

https://github.com/aws/aws-cdk/blob/95c49abdfa4ad77a0c0fcb82a230778dcc2ea59a/packages/aws-cdk-lib/aws-cloudtrail/lib/cloudtrail.ts#L283

So yes, this is pretty much an issue when Trailname is left blank. Thanks for reporting this. I am marking this as P3 as it has a workaround. Marking it as such means it won't be immediately addressed by the team but its on team's radar. Anyone from the community or team is welcome to work on it.

khushail avatar Sep 17 '24 02:09 khushail

It seems that simply using CfnTrail.attrArn would suffice, but since the CfnTrail itself already has a dependency on the S3 Bucket Policy, it results in a circular reference.

 const trail = new CfnTrail(this, 'Resource', {...});

    if (props.isOrganizationTrail) {
      this.s3bucket.addToResourcePolicy(new iam.PolicyStatement({
        resources: [this.s3bucket.arnForObjects(
          `AWSLogs/${props.orgId}/*`,
        )],
        actions: ['s3:PutObject'],
        principals: [cloudTrailPrincipal],
        conditions: {
          StringEquals: {
            's3:x-amz-acl': 'bucket-owner-full-control',
            'aws:SourceArn': trail.attrArn,  // updated
          },
        },
      }));
    }

    // This dependency has already existed.
    if (this.s3bucket.policy) {
      trail.node.addDependency(this.s3bucket.policy);
    }

Result:

Template is undeployable, these resources have a dependency cycle: OrganizationTrailS3Policy140E0681 -> OrganizationTrail7F291DBA -> OrganizationTrailS3Policy140E0681:

{
      "OrganizationTrailS3Policy140E0681": {
        "Type": "AWS::S3::BucketPolicy",
        "Properties": {
          "Bucket": {
            "Ref": "OrganizationTrailS39966E64E"
          },
          "PolicyDocument": {
            "Statement": [
...
              {
                "Action": "s3:PutObject",
                "Condition": {
                  "StringEquals": {
                    "s3:x-amz-acl": "bucket-owner-full-control",
                    "aws:SourceArn": {
                      "Fn::GetAtt": [
                        "OrganizationTrail7F291DBA",
                        "Arn"
                      ]
                    }
                  }
                },
                "Effect": "Allow",
                "Principal": {
                  "Service": "cloudtrail.amazonaws.com"
                },
                "Resource": {
                  "Fn::Join": [
                    "",
                    [
                      {
                        "Fn::GetAtt": [
                          "OrganizationTrailS39966E64E",
                          "Arn"
                        ]
                      },
                      "/AWSLogs/undefined/*"
                    ]
                  ]
                }
              }
            ],
            "Version": "2012-10-17"
          }
        }
      },
      "OrganizationTrail7F291DBA": {
        "Type": "AWS::CloudTrail::Trail",
        "Properties": {
          "EnableLogFileValidation": true,
          "EventSelectors": [],
          "IncludeGlobalServiceEvents": true,
          "IsLogging": true,
          "IsMultiRegionTrail": true,
          "IsOrganizationTrail": true,
          "S3BucketName": {
            "Ref": "OrganizationTrailS39966E64E"
          }
        },
        "DependsOn": [
          "OrganizationTrailS3Policy140E0681"
        ]
      }
    }

Therefore, it seems challenging to create a correct Source Arn that includes the TrailName when props.trailName is undefined.

badmintoncryer avatar Oct 19 '24 13:10 badmintoncryer

Same problem here, failing to create the Org Cloudtrail. Any news on the fix?

rafcio19 avatar Mar 13 '25 09:03 rafcio19