Skip to content

Commit 3017879

Browse files
clareliguoririx0rrr
authored andcommitted
feat: include DNS-validated ACM certificate and S3 bucket deployment for static site (#118)
1 parent 34467c2 commit 3017879

File tree

6 files changed

+42
-38
lines changed

6 files changed

+42
-38
lines changed

typescript/static-site/README.md

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,39 +8,24 @@
88
>
99
> This examples does is built on Construct Libraries marked "Experimental" and may not be updated for latest breaking changes.
1010
>
11-
> If build is unsuccessful, please create an [issue](https://github.com/aws-samples/aws-cdk-examples/issues/new) so that we may debug the problem
11+
> If build is unsuccessful, please create an [issue](https://github.com/aws-samples/aws-cdk-examples/issues/new) so that we may debug the problem
1212
1313
---
1414
<!--END STABILITY BANNER-->
1515

16-
This example creates the infrastructure for a static site, which uses an S3 bucket for storing the content.
16+
This example creates the infrastructure for a static site, which uses an S3 bucket for storing the content. The site contents (located in the 'site-contents' sub-directory) are deployed to the bucket.
1717

1818
The site redirects from HTTP to HTTPS, using a CloudFront distribution, Route53 alias record, and ACM certificate.
1919

2020
## Prep
2121

22-
The ACM certificate is expected to be created and validated outside of the CDK, with the certificate ARN stored in an AWS Systems Manager Parameter Store parameter.
22+
The domain for the static site (i.e. mystaticsite.com) must be configured as a hosted zone in Route53 prior to deploying this example. For instructions on configuring Route53 as the DNS service for your domain, see the [Route53 documentation](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/dns-configuring.html).
2323

24-
```
25-
$ aws ssm put-parameter --region us-east-1 --name CertificateArn-www.mystaticsite.com --type String --value arn:aws:acm:...
26-
```
27-
28-
## Deploy Infrastructure
24+
## Deploy
2925

3026
```
3127
$ npm install -g aws-cdk
3228
$ npm install
3329
$ npm run build
3430
$ cdk deploy -c domain=mystaticsite.com -c subdomain=www
3531
```
36-
37-
## Deploy Site Content
38-
39-
During the infrastructure deployment, you will see an output named something like "StaticSiteBucket34E5D9AF". The value is the bucket name where you can upload the static site content.
40-
41-
You will also see an output named something like "StaticSiteDistributionId8C64EF2A". This value is the distribution ID for the CloudFront distribution, which needs to be invalidated each time new content is uploaded to the bucket.
42-
43-
```
44-
$ aws s3 sync . s3://$STATIC_SITE_BUCKET
45-
$ aws cloudfront create-invalidation --distribution-id $DISTRIBUTION_ID --paths "/*"
46-
```

typescript/static-site/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ class MyStaticSiteStack extends cdk.Stack {
2626

2727
const app = new cdk.App();
2828

29-
new MyStaticSiteStack(app, 'MyStaticSite', { env: { region: 'us-east-1' } });
29+
new MyStaticSiteStack(app, 'MyStaticSite', { env: {
30+
// Stack must be in us-east-1, because the ACM certificate for a
31+
// global CloudFront distribution must be requested in us-east-1.
32+
region: 'us-east-1'
33+
}});
3034

3135
app.synth();

typescript/static-site/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"@aws-cdk/aws-route53": "*",
2525
"@aws-cdk/aws-route53-targets": "*",
2626
"@aws-cdk/aws-s3": "*",
27+
"@aws-cdk/aws-s3-deployment": "*",
2728
"@aws-cdk/core": "*",
2829
"aws-cdk": "*"
2930
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<html>
2+
<header><title>Hello world: Error</title></header>
3+
<body>
4+
Uh oh, you reached the error page!
5+
</body>
6+
</html>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<html>
2+
<header><title>Hello world</title></header>
3+
<body>
4+
Hello, world!
5+
</body>
6+
</html>
Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
#!/usr/bin/env node
22
import cloudfront = require('@aws-cdk/aws-cloudfront');
3-
import route53 = require('@aws-cdk/aws-route53');
3+
import route53 = require('@aws-cdk/aws-route53');
44
import s3 = require('@aws-cdk/aws-s3');
5+
import s3deploy = require('@aws-cdk/aws-s3-deployment');
56
import acm = require('@aws-cdk/aws-certificatemanager');
67
import cdk = require('@aws-cdk/core');
7-
import targets = require('@aws-cdk/aws-route53-targets/lib');
8+
import targets = require('@aws-cdk/aws-route53-targets/lib');
89
import { Construct } from '@aws-cdk/core';
910

1011
export interface StaticSiteProps {
@@ -13,19 +14,18 @@ export interface StaticSiteProps {
1314
}
1415

1516
/**
16-
* Static site infrastructure, which uses an S3 bucket for the content.
17+
* Static site infrastructure, which deploys site content to an S3 bucket.
1718
*
1819
* The site redirects from HTTP to HTTPS, using a CloudFront distribution,
1920
* Route53 alias record, and ACM certificate.
20-
*
21-
* The ACM certificate is expected to be created and validated outside of the CDK,
22-
* with the certificate ARN stored in an SSM Parameter.
2321
*/
2422
export class StaticSite extends Construct {
2523
constructor(parent: Construct, name: string, props: StaticSiteProps) {
2624
super(parent, name);
2725

26+
const zone = route53.HostedZone.fromLookup(this, 'Zone', { domainName: props.domainName });
2827
const siteDomain = props.siteSubDomain + '.' + props.domainName;
28+
new cdk.CfnOutput(this, 'Site', { value: 'https://' + siteDomain });
2929

3030
// Content bucket
3131
const siteBucket = new s3.Bucket(this, 'SiteBucket', {
@@ -35,16 +35,18 @@ export class StaticSite extends Construct {
3535
publicReadAccess: true,
3636

3737
// The default removal policy is RETAIN, which means that cdk destroy will not attempt to delete
38-
// the new bucket, and it will remain in your account until manually deleted. By setting the policy to
38+
// the new bucket, and it will remain in your account until manually deleted. By setting the policy to
3939
// DESTROY, cdk destroy will attempt to delete the bucket, but will error if the bucket is not empty.
4040
removalPolicy: cdk.RemovalPolicy.DESTROY, // NOT recommended for production code
4141
});
4242
new cdk.CfnOutput(this, 'Bucket', { value: siteBucket.bucketName });
4343

44-
// Pre-existing ACM certificate, with the ARN stored in an SSM Parameter
45-
const certificateArn = new acm.Certificate(this, 'ArnParameter', {
46-
domainName: props.domainName
44+
// TLS certificate
45+
const certificateArn = new acm.DnsValidatedCertificate(this, 'SiteCertificate', {
46+
domainName: siteDomain,
47+
hostedZone: zone
4748
}).certificateArn;
49+
new cdk.CfnOutput(this, 'Certificate', { value: certificateArn });
4850

4951
// CloudFront distribution that provides HTTPS
5052
const distribution = new cloudfront.CloudFrontWebDistribution(this, 'SiteDistribution', {
@@ -65,19 +67,19 @@ export class StaticSite extends Construct {
6567
});
6668
new cdk.CfnOutput(this, 'DistributionId', { value: distribution.distributionId });
6769

68-
/**
69-
* NOTE: the code below is not transpiling properly to JavaScript
70-
* Pending review by AWS team
71-
*/
72-
7370
// Route53 alias record for the CloudFront distribution
74-
const zone = new route53.HostedZone(this, 'MyHostedZone', {
75-
zoneName: props.domainName
76-
});
7771
new route53.ARecord(this, 'SiteAliasRecord', {
7872
recordName: siteDomain,
7973
target: route53.AddressRecordTarget.fromAlias(new targets.CloudFrontTarget(distribution)),
8074
zone
8175
});
76+
77+
// Deploy site contents to S3 bucket
78+
new s3deploy.BucketDeployment(this, 'DeployWithInvalidation', {
79+
source: s3deploy.Source.asset('./site-contents'),
80+
destinationBucket: siteBucket,
81+
distribution,
82+
distributionPaths: ['/*'],
83+
});
8284
}
8385
}

0 commit comments

Comments
 (0)