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

Use Origin Access Control instead of deprecated OAI #298

Merged
merged 1 commit into from
Nov 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,29 @@ When following this route, also provide parameter `AlternateDomainNames` upon de

## I already have an S3 bucket, I want to use that one

You can use a pre-existing S3 bucket (e.g. from another region), by providing the buckets regional endpoint domain through parameter "S3OriginDomainName" upon deploying. In this case it's a good practice to also use a CloudFront Origin Access Identity, so you don't have to make your bucket public. If you indeed have a CloudFront Origin Access Identity (make sure to grant it access in the bucket policy), specify its ID in parameter "OriginAccessIdentity".
You can use a pre-existing S3 bucket (e.g. from another region) by specifying the bucket's regional endpoint domain in the parameter `S3OriginDomainName`. An Origin Access Control will automatically be configured for the CloudFront distribution. We recommend applying an S3 bucket policy that restricts requests only from CloudFront, such as:

```
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowCloudFrontServicePrincipal",
"Effect": "Allow",
"Principal": {
"Service": "cloudfront.amazonaws.com"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::<bucket-name>/*",
"Condition": {
"StringEquals": {
"AWS:SourceArn": "arn:aws:cloudfront::123456789012:distribution/<distribution-id>"
}
}
}
]
}
```

Alternatively, go for the more barebone deployment, so you can do more yourself––i.e. reuse your bucket. Refer to scenario: [I already have a CloudFront distribution, I just want to add auth](#i-already-have-a-cloudfront-distribution-i-just-want-to-add-auth).

Expand Down
101 changes: 62 additions & 39 deletions template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -182,8 +182,7 @@ Parameters:
Default: index.html
S3OriginDomainName:
Description: >
The S3 origin you want to front with CloudFront. Specify the bucket's region specific hostname, i.e. <bucket-name>.s3.<region>.amazonaws.com,
and (optionally) also specify the parameter OriginAccessIdentity.
The S3 origin you want to front with CloudFront. Specify the bucket's region specific hostname, in the form of <bucket-name>.s3.<region>.amazonaws.com.
If you don't provide an origin, and "CreateCloudFrontDistribution" is set to "true" (the default), then an S3 bucket will be created for you.
Type: String
Default: ""
Expand All @@ -205,12 +204,18 @@ Parameters:
Only of use if you are also specifying parameter "CustomOriginDomainName".
Type: String
Default: ""
OriginAccessIdentity:
Description: The Origin Access Identity you want to associate with your S3 origin, e.g. 'ABCDEFGHIJKLMN'.
CreateCloudFrontAccessLogsBucket:
Description: >
Set to "true" to create a CloudFront access logs bucket and deliver logs to it. Ignored if CloudFrontAccessLogsBucket is also specified.
Type: String
Default: ""
Default: "false"
AllowedValues:
- "true"
- "false"
CloudFrontAccessLogsBucket:
Description: The (pre-existing) Amazon S3 bucket to store CloudFront access logs in, for example, myawslogbucket.s3.amazonaws.com. Only of use if "CreateCloudFrontDistribution" is set to "true" (the default).
Description: >
The (pre-existing) Amazon S3 bucket to store CloudFront access logs in, for example, myawslogbucket.s3.amazonaws.com. Only of use if "CreateCloudFrontDistribution" is set to "true" (the default).
This bucket must have ACLs enabled. If this value is unset and CreateCloudFrontAccessLogsBucket is set to "true", a bucket will be created.
Type: String
Default: ""
ResourceSuffix:
Expand Down Expand Up @@ -263,12 +268,6 @@ Conditions:
- !Equals [!Ref CreateCloudFrontDistribution, "true"]
- !Equals [!Ref CustomOriginDomainName, ""]
- !Equals [!Ref S3OriginDomainName, ""]
CreateOriginAccessIdentity: !And
- !Equals [!Ref CreateCloudFrontDistribution, "true"]
- !Equals [!Ref CustomOriginDomainName, ""]
- !Equals [!Ref S3OriginDomainName, ""]
- !Equals [!Ref OriginAccessIdentity, ""]
OriginAccessIdentityProvided: !Not [!Equals [!Ref OriginAccessIdentity, ""]]
UseS3Origin: !And
- !Equals [!Ref CreateCloudFrontDistribution, "true"]
- !Equals [!Ref CustomOriginDomainName, ""]
Expand All @@ -287,6 +286,9 @@ Conditions:
- !Condition StaticSiteMode
- !Condition NoExistingUserPoolProvidedOrExistingUserPoolIsInThisAccount
- !Equals [!Ref UserPoolClientSecret, ""]
CreateCloudFrontAccessLogsBucket: !And
- !Equals [!Ref CreateCloudFrontAccessLogsBucket, "true"]
- !Not [!Condition CloudFrontAccessLogsBucketProvided]

Globals:
Function:
Expand All @@ -307,6 +309,18 @@ Resources:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256

AccessLogsBucket:
Type: AWS::S3::Bucket
Condition: CreateCloudFrontAccessLogsBucket
Properties:
OwnershipControls:
Rules:
- ObjectOwnership: BucketOwnerPreferred
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256

CheckAuthHandler:
Type: AWS::Serverless::Function
Properties:
Expand Down Expand Up @@ -548,7 +562,10 @@ Resources:
Logging: !If
- CloudFrontAccessLogsBucketProvided
- Bucket: !Ref CloudFrontAccessLogsBucket
- !Ref AWS::NoValue
- !If
- CreateCloudFrontAccessLogsBucket
- Bucket: !GetAtt AccessLogsBucket.DomainName
- !Ref AWS::NoValue
Origins:
- DomainName: !If
- UseS3Origin
Expand All @@ -570,15 +587,16 @@ Resources:
- - HeaderName: !Ref CustomOriginHeaderName
HeaderValue: !Ref CustomOriginHeaderValue
- !Ref AWS::NoValue
OriginAccessControlId: !If
- UseS3Origin
- !GetAtt CloudFrontOriginAccessControl.Id
- !Ref AWS::NoValue
S3OriginConfig: !If
- UseS3Origin
- OriginAccessIdentity: !If
- CreateOriginAccessIdentity
- !Sub "origin-access-identity/cloudfront/${CloudFrontOriginAccessIdentity}"
- !If
- OriginAccessIdentityProvided
- !Sub "origin-access-identity/cloudfront/${OriginAccessIdentity}"
- !Ref AWS::NoValue
# If you're using origin access control (OAC) instead of origin access identity,
# specify an empty OriginAccessIdentity element. For more information, see
# Restricting access to an AWS in the Amazon CloudFront Developer Guide.
- OriginAccessIdentity: ""
- !Ref AWS::NoValue
- DomainName: will-never-be-reached.org
Id: dummy-origin
Expand All @@ -592,39 +610,44 @@ Resources:
ResponsePagePath: /index.html
- !Ref AWS::NoValue

CloudFrontOriginAccessIdentity:
Type: AWS::CloudFront::CloudFrontOriginAccessIdentity
Condition: CreateOriginAccessIdentity
CloudFrontOriginAccessControl:
Type: AWS::CloudFront::OriginAccessControl
Condition: UseS3Origin
Properties:
CloudFrontOriginAccessIdentityConfig:
Comment: "CloudFront OAI"
OriginAccessControlConfig:
Name: !If [CreateS3Bucket, !GetAtt S3Bucket.DomainName, !Ref S3OriginDomainName]
OriginAccessControlOriginType: s3
SigningBehavior: always
SigningProtocol: sigv4

CloudfrontBucketPolicy:
CloudFrontBucketPolicy:
Type: AWS::S3::BucketPolicy
Condition: CreateS3Bucket
Properties:
Bucket: !Ref S3Bucket
PolicyDocument:
Version: "2012-10-17"
Statement:
- Action:
- Sid: AllowCloudFrontDistributionToGetObjects
Action:
- "s3:GetObject"
Effect: "Allow"
Resource: !Join ["/", [!GetAtt S3Bucket.Arn, "*"]]
Resource: !Sub "${S3Bucket.Arn}/*"
Principal:
CanonicalUser: !If
- CreateOriginAccessIdentity
- !GetAtt CloudFrontOriginAccessIdentity.S3CanonicalUserId
- !Ref OriginAccessIdentity
- Action:
Service: cloudfront.amazonaws.com
Condition:
StringEquals:
"AWS:SourceArn": !Sub "arn:${AWS::Partition}:cloudfront::${AWS::AccountId}:distribution/${CloudFrontDistribution}"
- Sid: AllowCloudFrontDistributionToListBucket
Action:
- "s3:ListBucket"
Effect: "Allow"
Resource: !GetAtt S3Bucket.Arn
Principal:
CanonicalUser: !If
- CreateOriginAccessIdentity
- !GetAtt CloudFrontOriginAccessIdentity.S3CanonicalUserId
- !Ref OriginAccessIdentity
Service: cloudfront.amazonaws.com
Condition:
StringEquals:
"AWS:SourceArn": !Sub "arn:${AWS::Partition}:cloudfront::${AWS::AccountId}:distribution/${CloudFrontDistribution}"

UserPool:
Type: AWS::Cognito::UserPool
Expand Down Expand Up @@ -1059,7 +1082,7 @@ Resources:
- >
{
"userPoolArn": "${UserPoolArn}",
"jwks": ${FetchedJwks.Jwks},
"jwks": ${FetchedJwks.Jwks},
"clientId": "${ClientId}",
"clientSecret": "${ClientSecret}",
"oauthScopes": ${OAuthScopesJsonArray},
Expand Down Expand Up @@ -1122,7 +1145,7 @@ Resources:
- >
{
"userPoolArn": "${UserPoolArn}",
"jwks": ${FetchedJwks.Jwks},
"jwks": ${FetchedJwks.Jwks},
"clientId": "${ClientId}",
"clientSecret": "${ClientSecret}",
"oauthScopes": ${OAuthScopesJsonArray},
Expand Down