-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcloudformation.yml
352 lines (352 loc) · 11.3 KB
/
cloudformation.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
---
AWSTemplateFormatVersion: "2010-09-09"
Description: Pipeline using CodePipeline and CodeBuild for continuous delivery of a single-page progressive web application to S3
Parameters:
SiteBucketName:
Type: String
Description: Name of bucket to create to host the website
SiteHostedZoneId:
Type: String
Description: Route 53 hosted zone ID that might look something like KVN49DWYBF5E8M
GitHubOwner:
Type: String
Default: FluxAugur
Description: GitHub user or organization
GitHubRepo:
Type: String
Default: nathanialmcconnell.name
Description: Name (not URL) of the GitHub repo to pull from
GitHubBranch:
Type: String
Default: master
Description: GitHub branch to pull from
GitHubToken:
Type: String
Description: Secret GitHub OAuth2 token with repo access that might look something like 9b189a1654643522561f7b3ebd44a1531a4287af
NoEcho: True
BuildType:
Type: String
Default: "LINUX_CONTAINER"
Description: The build container type to use for building the app
BuildComputeType:
Type: String
Default: "BUILD_GENERAL1_SMALL"
Description: The build compute type to use for building the app
BuildImage:
Type: String
Default: "aws/codebuild/nodejs:8.11.0"
Description: The build image to use for building the app
AlgoliaAppId:
Type: String
Description: Algolia app identifier
AlgoliaSearchOnlyApiKey:
Type: String
Description: Algolia search API access key
AlgoliaAdminApiKey:
Type: String
Description: Algolia admin API access key
AlgoliaIndexName:
Type: String
Description: Algolia index name
Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
- Label:
default: Site Configuration
Parameters:
- SiteBucketName
- SiteHostedZoneId
- Label:
default: GitHub Configuration
Parameters:
- GitHubOwner
- GitHubRepo
- GitHubBranch
- GitHubToken
- Label:
default: Build Configuration
Parameters:
- BuildType
- BuildComputeType
- BuildImage
- Label:
default: Search Configuration
Parameters:
- AlgoliaAppId
- AlgoliaSearchOnlyApiKey
- AlgoliaAdminApiKey
- AlgoliaIndexName
ParameterLabels:
SiteBucketName:
default: Name of S3 bucket to create for website hosting
SiteHostedZoneId:
default: ID of Route 53 hosted zone
GitHubOwner:
default: GitHub user or organization name
GitHubRepo:
default: GitHub repository name
GitHubBranch:
default: GitHub branch name
GitHubToken:
default: GitHub OAuth2 token
BuildType:
default: CodeBuild type
BuildComputeType:
default: CodeBuild instance type
BuildImage:
default: CodeBuild image
AlgoliaAppId:
default: Algolia application identifier
AlgoliaSearchOnlyApiKey:
default: Algolia API key for search only
AlgoliaAdminApiKey:
default: Algolia API key for admin only
AlgoliaIndexName:
default: Algolia index name
Resources:
CodeBuildRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub ${SiteBucketName}.CodeBuildRole
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service:
- codebuild.amazonaws.com
Action:
- sts:AssumeRole
Path: "/service-role/"
Policies:
- PolicyName: codebuild-service
PolicyDocument:
Statement:
- Effect: Allow
Action:
- s3:GetObject
- s3:GetObjectVerion
- s3:GetBucketVersioning
- s3:PutObject
Resource:
- !GetAtt PipelineBucket.Arn
- !Join ["", [!GetAtt PipelineBucket.Arn, "/*"]]
- Effect: Allow
Action:
- s3:GetObject
- s3:GetObjectVersion
- s3:GetBucketVersioning
- s3:PutObject
- s3:PutObjectAcl
Resource:
- !GetAtt SiteBucket.Arn
- !Join ["", [!GetAtt SiteBucket.Arn, "/*"]]
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
- cloudfront:CreateInvalidation
Resource: "*"
CodePipelineRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub ${SiteBucketName}.CodePipelineRole
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service:
- codepipeline.amazonaws.com
Action:
- sts:AssumeRole
Path: "/service-role/"
Policies:
- PolicyName: codepipeline-service
PolicyDocument:
Statement:
- Effect: Allow
Action:
- s3:GetObject
- s3:getObjectVersion
- s3:GetBucketVersioning
Resource:
- !GetAtt PipelineBucket.Arn
- !Join ["", [!GetAtt PipelineBucket.Arn, "/*"]]
- Effect: Allow
Action:
- s3:PutObject
Resource:
- arn:aws:s3:::codepipeline*
- Effect: Allow
Action:
- codebuild:BatchGetBuilds
- codebuild:StartBuild
Resource: "*"
- Effect: Allow
Action:
- s3:*
- cloudformation:*
- iam:PassRole
Resource: "*"
SiteBucket:
Type: AWS::S3::Bucket
DeletionPolicy: Delete
Properties:
AccessControl: PublicRead
BucketName: !Ref SiteBucketName
WebsiteConfiguration:
IndexDocument: index.html
PipelineBucket:
Type: AWS::S3::Bucket
DeletionPolicy: Delete
Properties:
BucketName: !Sub ${SiteBucketName}.Pipeline
CodeBuildDeploySite:
Type: AWS::CodeBuild::Project
DependsOn: CodeBuildRole
Properties:
Name: !Sub ${SiteBucketName}.DeploySite
Description: Deploy site to S3
ServiceRole: !GetAtt CodeBuildRole.Arn
Artifacts:
Type: CODEPIPELINE
Environment:
Type: !Ref BuildType
ComputeType: !Ref BuildComputeType
Image: !Sub ${BuildImage}
EnvironmentVariables:
- Name: ALGOLIA_APP_ID
Value: !Ref AlgoliaAppId
- Name: ALGOLIA_SEARCH_ONLY_API_KEY
Value: !Ref AlgoliaSearchOnlyApiKey
- Name: ALGOLIA_ADMIN_API_KEY
Value: !Ref AlgoliaAdminApiKey
- Name: ALGOLIA_INDEX_NAME
Value: !Ref AlgoliaIndexName
Source:
Type: CODEPIPELINE
BuildSpec: !Sub |
version: 0.2
phases:
pre_build:
commands:
- echo Installing source NPM dependencies...
- npm install
- echo Cleaning project...
- npm run clean
build:
commands:
- echo Build started on `date`
- npm run build
post_build:
commands:
- aws s3 sync --acl public-read public s3://${SiteBucketName}/
- aws s3 cp --acl public-read --cache-control='max-age=0, no-cache, no-store, must-revalidate' ./public/service-worker.js s3://${SiteBucketName}/
- aws s3 cp --acl public-read --cache-control='max-age=0, no-cache, no-store, must-revalidate' ./public/index.html s3://${SiteBucketName}/
- aws cloudfront create-invalidation --distribution-id ${Distribution} --paths /index.html /service-worker.js
artifacts:
files:
- '**/*'
base-directory: public
TimeoutInMinutes: 10
Pipeline:
Type: AWS::CodePipeline::Pipeline
Properties:
Name: !Sub ${SiteBucketName}.Pipeline
RoleArn: !GetAtt CodePipelineRole.Arn
Stages:
- Name: Source
Actions:
- InputArtifacts: []
Name: Source
ActionTypeId:
Category: Source
Owner: ThirdParty
Version: "1"
Provider: GitHub
OutputArtifacts:
- Name: SourceArtifacts
Configuration:
Owner: !Ref GitHubOwner
Repo: !Ref GitHubRepo
Branch: !Ref GitHubBranch
OAuthToken: !Ref GitHubToken
RunOrder: 1
- Name: Deploy
Actions:
- Name: Artifact
ActionTypeId:
Category: Build
Owner: AWS
Version: "1"
Provider: CodeBuild
InputArtifacts:
- Name: SourceArtifacts
OutputArtifacts:
- Name: DeploymentArtifacts
Configuration:
ProjectName: !Ref CodeBuildDeploySite
RunOrder: 1
ArtifactStore:
Type: S3
Location: !Ref PipelineBucket
Distribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Enabled: true
DefaultRootObject: index.html
Origins:
- DomainName: !GetAtt SiteBucket.DomainName
Id: !Ref SiteBucketName
S3OriginConfig:
OriginAccessIdentity: ""
Aliases:
- CNAME: !GetAtt SiteBucket.DomainName
Quantity: 1
HttpVersion: http2
IPV6Enabled: true
DefaultCacheBehavior:
MinTTL: 86400
MaxTTL: 31536000
ForwardedValues:
QueryString: true
TargetOriginId: !Ref SiteBucketName
ViewerProtocolPolicy: redirect-to-https
ViewerCertificate:
SslSupportMethod: sni-only
AcmCertificateArn: arn:aws:acm:us-east-1:096188391785:certificate/2ab36cf4-10d7-4a14-bb81-79b6555df0f8
SiteDNS:
Type: AWS::Route53::RecordSetGroup
Properties:
HostedZoneId: !Ref SiteHostedZoneId
RecordSets:
- Name: !GetAtt SiteBucket.DomainName
Type: A
AliasTarget:
HostedZoneId: Z3GHCWB8V7K4G7
DNSName: !GetAtt Distribution.DistributionConfig.Origin.DomainName
- Name: !GetAtt SiteBucket.DomainName
Type: AAAA
AliasTarget:
HostedZoneId: Z3GHCWB8V7K4G7
DNSName: !GetAtt Distribution.DistributionConfig.Origin.DomainName
- Name: !Join [".", ["www", !Ref SiteHostedZoneId]]
Type: CNAME
TTL: "900"
ResourceRecords:
- !GetAtt SiteBucket.DomainName
ForceRemoveBucket:
Type: Custom::cfnCliWrapper
Properties:
ServiceToken: arn:aws:lambda:us-east-1:096188391785:function:cli2cloudformation-dev
CliCommandDelete: aws s3 rb s3://${SiteBucketName} --force
Outputs:
PipelineUrl:
Value: !Sub https://console.aws.amazon.com/codepipeline/home?region=${AWS::Region}#/view/${Pipeline}
Description: CodePipeline URL
SiteUrl:
Value: !GetAtt [SiteBucket, WebsiteURL]
Description: S3 Website URL