aws / aws-cdk

The AWS Cloud Development Kit is a framework for defining cloud infrastructure in code
https://aws.amazon.com/cdk
Apache License 2.0
11.59k stars 3.89k forks source link

CloudFront S3Origin: The origin access identity is not being applied #22451

Closed rupe120 closed 1 year ago

rupe120 commented 2 years ago

Describe the bug

The origin access identity is not being applied to the origin when CloudFormation is synth'd

Expected Behavior

The origin access identity is referenced in the origin configuration in CloudFormation.

Current Behavior

The origin access identity is created as a resource but not associated to the origin.

Reproduction Steps

import { Stack } from "aws-cdk-lib";
import { Certificate, CertificateValidation } from "aws-cdk-lib/aws-certificatemanager";
import { AllowedMethods, Distribution, OriginAccessIdentity, ViewerProtocolPolicy } from "aws-cdk-lib/aws-cloudfront";
import { S3Origin } from "aws-cdk-lib/aws-cloudfront-origins";
import { AccountPrincipal, Role } from "aws-cdk-lib/aws-iam";
import { Key } from "aws-cdk-lib/aws-kms";
import { CrossAccountZoneDelegationRecord, HostedZone, RecordSet, RecordTarget, RecordType } from "aws-cdk-lib/aws-route53";
import { Bucket, BucketEncryption } from "aws-cdk-lib/aws-s3";
import { Construct } from "constructs";
import { Route53Info, S3StackProps } from "./interface";
import _route53Info from "../../config/route53Info.json";
import { CloudFrontTarget } from "aws-cdk-lib/aws-route53-targets";

export class S3Stack extends Stack {
  public bucket: Bucket;

  constructor(
    scope: Construct,
    id: string,
    props: S3StackProps
  ) {
    super(scope, id, props);

    const bucketKey = Key.fromKeyArn(this, 'bucket-key', props.kmsKeyArn!!);
    // The hosting bucket
    this.bucket = new Bucket(this, "s3-bucket", {
      bucketName: `${props.deployEnvironment}-snt-frontend`,
      encryption: BucketEncryption.KMS,
      encryptionKey: bucketKey,
      websiteIndexDocument: "index.html"
    });

    this.bucket.grantReadWrite(new AccountPrincipal(props.pipelineEnvironment.account!!))

    const route53Info = _route53Info as Route53Info;
    const route53Role = Role.fromRoleArn(this, "Route53DelegationRole", route53Info.route53RoleArn);

    const hostedZone = new HostedZone(this, `${props.deployEnvironment}-snt-hosted-zone`, 
    {
      zoneName: props.environmentDomainName
    });

    new CrossAccountZoneDelegationRecord(this, 'delegate',
    {
      delegatedZone: hostedZone,
      parentHostedZoneName: route53Info.hostedZoneName,
      delegationRole: route53Role
    })

    const cert = new Certificate(this, 'certificate',
    {
      domainName: props.environmentDomainName,
      validation: CertificateValidation.fromDns(hostedZone)
    })

    const originAccessIdentity = new OriginAccessIdentity(this, `${props.deployEnvironment}-origin-access-identity`,
    {
      comment: `${props.deployEnvironment} origin access identity`
    })

    this.bucket.grantRead(originAccessIdentity);
    bucketKey.grantDecrypt(originAccessIdentity);

    const cloudFrontDistribution = new Distribution(this, "distro",
    {
      defaultBehavior: {
        origin: new S3Origin(this.bucket, {
          originAccessIdentity: originAccessIdentity
        }
        ),
        viewerProtocolPolicy: ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
        allowedMethods: AllowedMethods.ALLOW_GET_HEAD
      },
      certificate: cert,
      domainNames: [props.environmentDomainName],
      defaultRootObject: "index.html"
    });

    new RecordSet(this, 'recordset',
    {
      recordType: RecordType.A,
      zone: hostedZone,
      target: RecordTarget.fromAlias(new CloudFrontTarget(cloudFrontDistribution))
    });

  }
}

Possible Solution

Looking at the s3-origin.ts code I really don't understand why this would be.

Additional Information/Context

No response

CDK CLI Version

2.45.0 (build af1fb7c)

Framework Version

No response

Node.js Version

v16.16.0

OS

Windows 10 Pro 19043.1889

Language

Typescript

Language Version

TypeScript 4.8.3

Other information

The template created is below. Search for devoriginaccessidentity86C478E2

{
 "Resources": {
  "s3bucket64CB25AF": {
   "Type": "AWS::S3::Bucket",
   "Properties": {
    "BucketEncryption": {
     "ServerSideEncryptionConfiguration": [
      {
       "ServerSideEncryptionByDefault": {
        "KMSMasterKeyID": "arn:aws:kms:us-east-1:852211398058:key/mrk-e31838ed3ec84b689724be98a03e7327",
        "SSEAlgorithm": "aws:kms"
       }
      }
     ]
    },
    "BucketName": "dev-snt-frontend",
    "WebsiteConfiguration": {
     "IndexDocument": "index.html"
    }
   },
   "UpdateReplacePolicy": "Retain",
   "DeletionPolicy": "Retain",
   "Metadata": {
    "aws:cdk:path": "SnTInfraPipelineStack/SnTS3InfraStage/snt-infra-s3-stack-dev/s3-bucket/Resource"
   }
  },
  "s3bucketPolicyF7E91061": {
   "Type": "AWS::S3::BucketPolicy",
   "Properties": {
    "Bucket": {
     "Ref": "s3bucket64CB25AF"
    },
    "PolicyDocument": {
     "Statement": [
      {
       "Action": [
        "s3:GetObject*",
        "s3:GetBucket*",
        "s3:List*",
        "s3:DeleteObject*",
        "s3:PutObject",
        "s3:PutObjectLegalHold",
        "s3:PutObjectRetention",
        "s3:PutObjectTagging",
        "s3:PutObjectVersionTagging",
        "s3:Abort*"
       ],
       "Effect": "Allow",
       "Principal": {
        "AWS": {
         "Fn::Join": [
          "",
          [
           "arn:",
           {
            "Ref": "AWS::Partition"
           },
           ":iam::852211398058:root"
          ]
         ]
        }
       },
       "Resource": [
        {
         "Fn::GetAtt": [
          "s3bucket64CB25AF",
          "Arn"
         ]
        },
        {
         "Fn::Join": [
          "",
          [
           {
            "Fn::GetAtt": [
             "s3bucket64CB25AF",
             "Arn"
            ]
           },
           "/*"
          ]
         ]
        }
       ]
      },
      {
       "Action": [
        "s3:GetObject*",
        "s3:GetBucket*",
        "s3:List*"
       ],
       "Effect": "Allow",
       "Principal": {
        "CanonicalUser": {
         "Fn::GetAtt": [
          "devoriginaccessidentity86C478E2",
          "S3CanonicalUserId"
         ]
        }
       },
       "Resource": [
        {
         "Fn::GetAtt": [
          "s3bucket64CB25AF",
          "Arn"
         ]
        },
        {
         "Fn::Join": [
          "",
          [
           {
            "Fn::GetAtt": [
             "s3bucket64CB25AF",
             "Arn"
            ]
           },
           "/*"
          ]
         ]
        }
       ]
      }
     ],
     "Version": "2012-10-17"
    }
   },
   "Metadata": {
    "aws:cdk:path": "SnTInfraPipelineStack/SnTS3InfraStage/snt-infra-s3-stack-dev/s3-bucket/Policy/Resource"
   }
  },
  "devsnthostedzone032D676F": {
   "Type": "AWS::Route53::HostedZone",
   "Properties": {
    "Name": "dev1.spotandtango.com."
   },
   "Metadata": {
    "aws:cdk:path": "SnTInfraPipelineStack/SnTS3InfraStage/snt-infra-s3-stack-dev/dev-snt-hosted-zone/Resource"
   }
  },
  "delegatecrossaccountzonedelegationhandlerrolePolicyE53A3C62": {
   "Type": "AWS::IAM::Policy",
   "Properties": {
    "PolicyDocument": {
     "Statement": [
      {
       "Action": "sts:AssumeRole",
       "Effect": "Allow",
       "Resource": "arn:aws:iam::394222643837:role/Route53CrossAccountUpdateRole"
      }
     ],
     "Version": "2012-10-17"
    },
    "PolicyName": "delegatecrossaccountzonedelegationhandlerrolePolicyE53A3C62",
    "Roles": [
     {
      "Fn::Select": [
       1,
       {
        "Fn::Split": [
         "/",
         {
          "Fn::Select": [
           5,
           {
            "Fn::Split": [
             ":",
             {
              "Fn::GetAtt": [
               "CustomCrossAccountZoneDelegationCustomResourceProviderRoleED64687B",
               "Arn"
              ]
             }
            ]
           }
          ]
         }
        ]
       }
      ]
     }
    ]
   },
   "Metadata": {
    "aws:cdk:path": "SnTInfraPipelineStack/SnTS3InfraStage/snt-infra-s3-stack-dev/delegate/cross-account-zone-delegation-handler-role/Policy/Resource"
   }
  },
  "delegateCrossAccountZoneDelegationCustomResource23BD590B": {
   "Type": "Custom::CrossAccountZoneDelegation",
   "Properties": {
    "ServiceToken": {
     "Fn::GetAtt": [
      "CustomCrossAccountZoneDelegationCustomResourceProviderHandler44A84265",
      "Arn"
     ]
    },
    "AssumeRoleArn": "arn:aws:iam::394222643837:role/Route53CrossAccountUpdateRole",
    "ParentZoneName": "spotandtango.com",
    "DelegatedZoneName": "dev1.spotandtango.com",
    "DelegatedZoneNameServers": {
     "Fn::GetAtt": [
      "devsnthostedzone032D676F",
      "NameServers"
     ]
    },
    "TTL": 172800
   },
   "DependsOn": [
    "delegatecrossaccountzonedelegationhandlerrolePolicyE53A3C62"
   ],
   "UpdateReplacePolicy": "Delete",
   "DeletionPolicy": "Delete",
   "Metadata": {
    "aws:cdk:path": "SnTInfraPipelineStack/SnTS3InfraStage/snt-infra-s3-stack-dev/delegate/CrossAccountZoneDelegationCustomResource/Default"
   }
  },
  "CustomCrossAccountZoneDelegationCustomResourceProviderRoleED64687B": {
   "Type": "AWS::IAM::Role",
   "Properties": {
    "AssumeRolePolicyDocument": {
     "Version": "2012-10-17",
     "Statement": [
      {
       "Action": "sts:AssumeRole",
       "Effect": "Allow",
       "Principal": {
        "Service": "lambda.amazonaws.com"
       }
      }
     ]
    },
    "ManagedPolicyArns": [
     {
      "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
     }
    ]
   },
   "Metadata": {
    "aws:cdk:path": "SnTInfraPipelineStack/SnTS3InfraStage/snt-infra-s3-stack-dev/Custom::CrossAccountZoneDelegationCustomResourceProvider/Role"
   }
  },
  "CustomCrossAccountZoneDelegationCustomResourceProviderHandler44A84265": {
   "Type": "AWS::Lambda::Function",
   "Properties": {
    "Code": {
     "S3Bucket": "cdk-hnb659fds-assets-852211398058-us-east-1",
     "S3Key": "80a0e73221c7861d62f8071ac8ba7d543bf43d4e3d662a30e039930d70e94567.zip"
    },
    "Timeout": 900,
    "MemorySize": 128,
    "Handler": "__entrypoint__.handler",
    "Role": {
     "Fn::GetAtt": [
      "CustomCrossAccountZoneDelegationCustomResourceProviderRoleED64687B",
      "Arn"
     ]
    },
    "Runtime": "nodejs14.x"
   },
   "DependsOn": [
    "CustomCrossAccountZoneDelegationCustomResourceProviderRoleED64687B"
   ],
   "Metadata": {
    "aws:cdk:path": "SnTInfraPipelineStack/SnTS3InfraStage/snt-infra-s3-stack-dev/Custom::CrossAccountZoneDelegationCustomResourceProvider/Handler",
    "aws:asset:path": "../asset.80a0e73221c7861d62f8071ac8ba7d543bf43d4e3d662a30e039930d70e94567",
    "aws:asset:property": "Code"
   }
  },
  "certificateEC031123": {
   "Type": "AWS::CertificateManager::Certificate",
   "Properties": {
    "DomainName": "dev1.spotandtango.com",
    "DomainValidationOptions": [
     {
      "DomainName": "dev1.spotandtango.com",
      "HostedZoneId": {
       "Ref": "devsnthostedzone032D676F"
      }
     }
    ],
    "ValidationMethod": "DNS"
   },
   "Metadata": {
    "aws:cdk:path": "SnTInfraPipelineStack/SnTS3InfraStage/snt-infra-s3-stack-dev/certificate/Resource"
   }
  },
  "devoriginaccessidentity86C478E2": {
   "Type": "AWS::CloudFront::CloudFrontOriginAccessIdentity",
   "Properties": {
    "CloudFrontOriginAccessIdentityConfig": {
     "Comment": "dev origin access identity"
    }
   },
   "Metadata": {
    "aws:cdk:path": "SnTInfraPipelineStack/SnTS3InfraStage/snt-infra-s3-stack-dev/dev-origin-access-identity/Resource"
   }
  },
  "distro40218A07": {
   "Type": "AWS::CloudFront::Distribution",
   "Properties": {
    "DistributionConfig": {
     "Aliases": [
      "dev1.spotandtango.com"
     ],
     "DefaultCacheBehavior": {
      "AllowedMethods": [
       "GET",
       "HEAD"
      ],
      "CachePolicyId": "658327ea-f89d-4fab-a63d-7e88639e58f6",
      "Compress": true,
      "TargetOriginId": "SnTInfraPipelineStackSnTS3InfraStagesntinfras3stackdevdistroOrigin166F15300",
      "ViewerProtocolPolicy": "redirect-to-https"
     },
     "DefaultRootObject": "index.html",
     "Enabled": true,
     "HttpVersion": "http2",
     "IPV6Enabled": true,
     "Origins": [
      {
       "CustomOriginConfig": {
        "OriginProtocolPolicy": "http-only",
        "OriginSSLProtocols": [
         "TLSv1.2"
        ]
       },
       "DomainName": {
        "Fn::Select": [
         2,
         {
          "Fn::Split": [
           "/",
           {
            "Fn::GetAtt": [
             "s3bucket64CB25AF",
             "WebsiteURL"
            ]
           }
          ]
         }
        ]
       },
       "Id": "SnTInfraPipelineStackSnTS3InfraStagesntinfras3stackdevdistroOrigin166F15300"
      }
     ],
     "ViewerCertificate": {
      "AcmCertificateArn": {
       "Ref": "certificateEC031123"
      },
      "MinimumProtocolVersion": "TLSv1.2_2021",
      "SslSupportMethod": "sni-only"
     }
    }
   },
   "Metadata": {
    "aws:cdk:path": "SnTInfraPipelineStack/SnTS3InfraStage/snt-infra-s3-stack-dev/distro/Resource"
   }
  },
  "recordsetA5DF64C5": {
   "Type": "AWS::Route53::RecordSet",
   "Properties": {
    "Name": "dev1.spotandtango.com.",
    "Type": "A",
    "AliasTarget": {
     "DNSName": {
      "Fn::GetAtt": [
       "distro40218A07",
       "DomainName"
      ]
     },
     "HostedZoneId": {
      "Fn::FindInMap": [
       "AWSCloudFrontPartitionHostedZoneIdMap",
       {
        "Ref": "AWS::Partition"
       },
       "zoneId"
      ]
     }
    },
    "HostedZoneId": {
     "Ref": "devsnthostedzone032D676F"
    }
   },
   "Metadata": {
    "aws:cdk:path": "SnTInfraPipelineStack/SnTS3InfraStage/snt-infra-s3-stack-dev/recordset/Resource"
   }
  },
  "CDKMetadata": {
   "Type": "AWS::CDK::Metadata",
   "Properties": {
    "Analytics": "v2:deflate64:H4sIAAAAAAAA/22RwW7CMAyGn4V7yAaDw46saNoO0xDcdplC4laGNkaxwzRVffcldNBO2sn+7S/5HWeuF0t9PzFfPLXuOK1xr9udGHtUW2CKwYJKvc+WH3T7FO0RRBWl/836sKEa7fdQ7nWnAkWBZTr3QizgPshDhsYqEPPKWopecmENNVRGkPwWLAWn+rDrTW+iU2ga3Q6+V0cLQbBEawQa400FQbfFUMvoSCa+pujKQF50+x6wQp+GAeZXB15QLncXmXnOzL/EGlkC7mMeOuNj3XWqiCzU3FZ5ecU1/9PaBDqjg6BWzCDpB5JVlfk3czqltFOeHOgD351nCz171PPJgRGnIa0OG9DbPv4A2NzmP88BAAA="
   },
   "Metadata": {
    "aws:cdk:path": "SnTInfraPipelineStack/SnTS3InfraStage/snt-infra-s3-stack-dev/CDKMetadata/Default"
   }
  }
 },
 "Mappings": {
  "AWSCloudFrontPartitionHostedZoneIdMap": {
   "aws": {
    "zoneId": "Z2FDTNDATAQYW2"
   },
   "aws-cn": {
    "zoneId": "Z3RFFRIM2A3IF5"
   }
  }
 },
 "Outputs": {
  "ExportsOutputFnGetAtts3bucket64CB25AFArn698093FD": {
   "Value": {
    "Fn::GetAtt": [
     "s3bucket64CB25AF",
     "Arn"
    ]
   },
   "Export": {
    "Name": "snt-infra-s3-stack-dev:ExportsOutputFnGetAtts3bucket64CB25AFArn698093FD"
   }
  }
 },
 "Parameters": {
  "BootstrapVersion": {
   "Type": "AWS::SSM::Parameter::Value<String>",
   "Default": "/cdk-bootstrap/hnb659fds/version",
   "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]"
  }
 },
 "Rules": {
  "CheckBootstrapVersion": {
   "Assertions": [
    {
     "Assert": {
      "Fn::Not": [
       {
        "Fn::Contains": [
         [
          "1",
          "2",
          "3",
          "4",
          "5"
         ],
         {
          "Ref": "BootstrapVersion"
         }
        ]
       }
      ]
     },
     "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI."
    }
   ]
  }
 }
}
rupe120 commented 2 years ago

Here is a basic repo that demonstrates it https://github.com/rupe120/cdk-cloudfront-test

peterwoodworth commented 1 year ago

This is happening because the S3Origin class will use an HttpOrigin if the bucket is configured as a website. Your bucket is configured as a website, so it is going to be using an HttpOrigin which doesn't make use of an OAI. Either you can remove the website configuration from the bucket to let the OAI do the work, or you can move forward with the HttpOrigin option. 🙂

github-actions[bot] commented 1 year ago

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