Skip to content

Commit

Permalink
Feat: Static Web Application Distribution
Browse files Browse the repository at this point in the history
  • Loading branch information
nao1215 committed Feb 23, 2024
1 parent 14fd219 commit 544c3c7
Show file tree
Hide file tree
Showing 7 changed files with 158 additions and 74 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ The s3hub command provides following features:
|[Lambda with API Gateway](./cloudformation/lambda-with-api-gw/README.md)||100%|
|[Daily Cost Notification](./cloudformation/daily-cost-notification/README.md)||100%|
|[CloudWatch Real User Monitoring (RUM)](./cloudformation/cloudwatch-rum/README.md)||100%|
|[Static Web Application Distribution](./cloudformation/static-web-site-distribution/README.md)||100%|


## LICENSE
Expand Down
9 changes: 6 additions & 3 deletions cloudformation/static-web-site-distribution/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@ help: ## Show this help message

test-deploy: ## Deploy CloudFormation Template to localstack
@echo "Deploying S3 and CloudFront Template"
aws cloudformation create-stack --endpoint-url "http://localhost:4566" --stack-name "static-web-site-distribution" \
aws cloudformation create-stack --endpoint-url "http://localhost:4566" --stack-name "static-web-site-distribution" --region ap-northeast-1 \
--template-body "file://template.yml" --parameters "file://parameters.json" --capabilities CAPABILITY_NAMED_IAM

deploy: ## Deploy CloudFormation Template
@echo "Deploying S3 and CloudFront Template"
aws cloudformation create-stack --stack-name "static-web-site-distribution" \
--template-body "file://template.yml" --parameters "file://parameters.json" --capabilities CAPABILITY_NAMED_IAM
aws cloudformation create-stack --stack-name "static-web-site-distribution" --region ap-northeast-1 \
--template-body "file://template.yml" --parameters "file://parameters.json" --capabilities CAPABILITY_NAMED_IAM

upload: ## Upload index.html
aws s3 cp ./index.html s3://content-bucket-rainbow-spa
32 changes: 30 additions & 2 deletions cloudformation/static-web-site-distribution/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Static Web Site Distribution With CloudFront and S3
## Static Web Application Distribution With CloudFront and S3
### Overview
The simplest way to deploy the static website is to store the content in Amazon S3 (Simple Storage Service) and distribute it using CloudFront (Content Delivery Network).

Expand Down Expand Up @@ -37,4 +37,32 @@ OAC also enhances security measures by supporting shorter credential durations a
3. Compliance with Legal Requirements: Some industries or legal requirements may mandate the retention of access logs and their accessibility when needed to comply with regulations.

#### CloudFront Cache
- [Understanding AWS CloudFront Caching: A Guide for Beginners](https://aws.plainenglish.io/understanding-aws-cloudfront-caching-a-guide-for-beginners-ce0169d3c724)
- [Understanding AWS CloudFront Caching: A Guide for Beginners](https://aws.plainenglish.io/understanding-aws-cloudfront-caching-a-guide-for-beginners-ce0169d3c724)

### How to deploy
> [!NOTE]
> Before running `make deploy`, ensure you have configured AWS credentials and set the correct region. Otherwise, you use single sign-on (SSO).
```shell
$ make deploy
```

If you want to upload the content of the static website to S3, you can use the following command:

```shell
aws s3 cp ./static-website s3://<your-bucket-name> --recursive
```

For example, if you upload the index.html file to the S3 bucket, you can use the following command:

```shell
aws s3 cp ./index.html s3://content-bucket-rainbow-spa
```

After deployment, you can access the static website. The URL syntax for the CloudFront distribution is as follows:

```
https://<distribution-id>.cloudfront.net
```

![spa](./spa.png)
12 changes: 12 additions & 0 deletions cloudformation/static-web-site-distribution/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Simple Page</title>
</head>
<body>
<h1>Hello, World!</h1>
<p>This is a simple HTML page.</p>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[
{
"ParameterKey" : "ContentBucketName",
"ParameterValue" : "ContentBucketNameRainbow"
"ParameterValue" : "content-bucket-rainbow-spa"
}
]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
176 changes: 108 additions & 68 deletions cloudformation/static-web-site-distribution/template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,9 @@ Resources:
UpdateReplacePolicy: Retain
DeletionPolicy: Retain
Properties:
BucketName: !Ref ContentBucketName
BucketName: !Sub "${ContentBucketName}"
VersioningConfiguration:
Status: Enabled
ObjectLockConfiguration:
ObjectLockEnabled: Enabled
Rule:
DefaultRetention:
Days: 1
Mode: GOVERNANCE
ObjectLockEnabled: true
OwnershipControls:
Rules:
Expand All @@ -33,16 +27,6 @@ Resources:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
ReplicationConfiguration:
Role: !GetAtt ContentBucketReplicationRole.Arn
Rules:
- Destination:
Bucket: !Ref ContentS3BucketReplica
Status: Enabled
Prefix: "replicated/"
LoggingConfiguration:
DestinationBucketName: !Ref ContentS3BucketReplica
LogFilePrefix: "logs/"

ContentBucketPolicy:
Type: AWS::S3::BucketPolicy
Expand All @@ -51,38 +35,47 @@ Resources:
PolicyDocument:
Version: "2012-10-17"
Statement:
- Action: "s3:*"
- Sid: "DenyNonSecureConnections"
Action: "s3:*"
Effect: Deny
Principal: "*"
Resource: "*"
Resource:
- !Sub "arn:aws:s3:::${ContentBucketName}/*"
- !Sub "arn:aws:s3:::${ContentBucketName}"
Condition:
Bool:
"aws:SecureTransport": false

ContentBucketReplicationRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub "${AWS::StackName}-bucket-source-role-${AWS::Region}"
Description: "Role For S3"
Path: "/service/"
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
- Sid: "AllowCloudFrontToGetContent"
Effect: Allow
Principal:
Service:
- s3.amazonaws.com
Action:
- sts:AssumeRole
ManagedPolicyArns:
- "arn:aws:iam::aws:policy/AmazonS3FullAccess"
Service: "cloudfront.amazonaws.com"
Action:
- "s3:GetObject"
- "s3:ListBucket"
Resource:
- !Sub "arn:aws:s3:::${ContentBucketName}/*"
- !Sub "arn:aws:s3:::${ContentBucketName}"
Condition:
Bool:
"aws:SecureTransport": true

ContentS3BucketReplica:
LogBucket:
Type: "AWS::S3::Bucket"
UpdateReplacePolicy: Retain
DeletionPolicy: Retain
Properties:
BucketName: "content-s3-bucket-replica"
BucketName: !Sub "${ContentBucketName}-log"
VersioningConfiguration:
Status: Enabled
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
ObjectLockConfiguration:
ObjectLockEnabled: Enabled
Rule:
Expand All @@ -92,35 +85,82 @@ Resources:
ObjectLockEnabled: true
OwnershipControls:
Rules:
- ObjectOwnership: BucketOwnerEnforced
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
VersioningConfiguration:
Status: Enabled
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
Metadata:
guard:
SuppressedRules:
- S3_BUCKET_REPLICATION_ENABLED
- S3_BUCKET_LOGGING_ENABLED
- ObjectOwnership: ObjectWriter

ContentBucketReplicaPolicy:
Type: AWS::S3::BucketPolicy
CloufFrontDistribution:
Type: "AWS::CloudFront::Distribution"
Properties:
Bucket: !Ref ContentS3BucketReplica
PolicyDocument:
Version: "2012-10-17"
Statement:
- Action: "s3:*"
Effect: Deny
Principal: "*"
Resource: "*"
Condition:
Bool:
"aws:SecureTransport": false
DistributionConfig:
Comment: "CloudFront Distribution"
Origins:
- DomainName: !GetAtt ContentBucket.RegionalDomainName
Id: "S3Origin"
OriginAccessControlId: !Ref CloudFrontOriginAccessControl
S3OriginConfig:
OriginAccessIdentity: ""
DefaultRootObject: "index.html"
Enabled: true
DefaultCacheBehavior:
TargetOriginId: "S3Origin"
CachePolicyId: !Ref OriginCachePolicy
OriginRequestPolicyId: !Ref OriginRequestPolicy
AllowedMethods:
- GET
- HEAD
- OPTIONS
ForwardedValues:
QueryString: false
ViewerProtocolPolicy: "redirect-to-https"
DefaultTTL: 1
MaxTTL: 1
MinTTL: 1
PriceClass: "PriceClass_100"
Logging:
Bucket: !GetAtt LogBucket.DomainName
IncludeCookies: false
Prefix: "logs/"
HttpVersion: "http2and3"
IPV6Enabled: true
ViewerCertificate:
CloudFrontDefaultCertificate: true

CloudFrontOriginAccessControl:
Type: "AWS::CloudFront::OriginAccessControl"
Properties:
OriginAccessControlConfig:
Name: "Origin Accress Control for S3 bucket"
OriginAccessControlOriginType: s3
SigningBehavior: always
SigningProtocol: sigv4

OriginRequestPolicy:
Type: "AWS::CloudFront::OriginRequestPolicy"
Properties:
OriginRequestPolicyConfig:
Name: !Sub "${AWS::StackName}-cloudfront-request-policy"
Comment: "Origin Request Policy for S3 bucket"
CookiesConfig:
CookieBehavior: none
HeadersConfig:
HeaderBehavior: none
QueryStringsConfig:
QueryStringBehavior: none

OriginCachePolicy:
Type: "AWS::CloudFront::CachePolicy"
Properties:
CachePolicyConfig:
Name: !Sub "${AWS::StackName}-cloudfront-cache-policy"
Comment: "Cache Policy for S3 bucket"
DefaultTTL: 1
MaxTTL: 1
MinTTL: 1
ParametersInCacheKeyAndForwardedToOrigin:
CookiesConfig:
CookieBehavior: none
HeadersConfig:
HeaderBehavior: none
QueryStringsConfig:
QueryStringBehavior: none
EnableAcceptEncodingGzip: true
EnableAcceptEncodingBrotli: true

0 comments on commit 544c3c7

Please sign in to comment.