-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
template.yml
275 lines (265 loc) · 9.74 KB
/
template.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
AWSTemplateFormatVersion: "2010-09-09"
Transform:
- AWS::Serverless-2016-10-31
Description: >
68publishers/image-storage - AWS Image Server
AWS application as an alternative for the local image server.
Parameters:
BasePath:
Type: String
Default: ""
Description: "A base path for cached images. For example if you set this parameter as \"foo\" then a root directory for all cached images will be \"foo\"."
ModifierSeparator:
Type: String
Default: ","
Description: "A separator for modifier definitions in a path. For example if you set this parameter as \";\" then a modifier string in a path will look like this: \"w:100;o:auto\"."
ModifierAssigner:
Type: String
Default: ":"
Description: "An assigner for modifier definitions in a path. For example if you set this parameter as \"=\" then a modifier string in a path will look like this: \"w=100,o=auto\"."
VersionParameterName:
Type: String
Default: _v
Description: "A query parameter's name used for a document's version (just for a cache)."
SignatureParameterName:
Type: String
Default: _s
Description: "A query parameter's name used for a signature token."
SignatureKey:
Type: String
Default: ""
Description: "Your private signature key used for a token encryption. Signatures in requests are checked and validated only if this parameter is set."
SignatureAlgorithm:
Type: String
Default: sha256
Description: "An algorithm used for encryption of signatures (HMAC)."
AllowedPixelDensity:
Type: CommaDelimitedList
Default: ""
Description: "A comma separated list with allowed pixel densities - modified \"pd\". Requests are validated against this list only if the list is not empty. For example \"1,2,3\"."
AllowedResolutions:
Type: CommaDelimitedList
Default: ""
Description: "A comma separated list with allowed pixel resolutions - modifiers \"w\" and \"h\". Requests are validated against this list only if the list is not empty. For example \"300x300,300x,x200\" allows requests on images with dimensions 300x300 or with 300 width and calculated height or with 200 height and calculated width."
AllowedQualities:
Type: CommaDelimitedList
Default: ""
Description: "A comma separated list with allowed qualities - modifier \"q\". Requests are validated against this list only if the list is not empty. For example: \"80,90,100\"."
EncodeQuality:
Type: Number
Default: 90
Description: "An encode quality for cached images."
SourceBucketName:
Type: String
Default: "image-storage-source"
Description: "An unique Source Bucket's name."
CacheBucketName:
Type: String
Default: "image-storage-cache"
Description: "An unique Cache Bucket's name."
CacheMaxAge:
Type: Number
Default: 31536000
Description: "The maximum cache age in seconds. The value is used for HTTP headers Cache-Control and Expires"
NoImages:
Type: CommaDelimitedList
Default: ""
Description: "Named paths for no-images in format \"name::path\". For example \"default::noimage/noapp\" is a definition for a default no-image image that is stored as noimage/noapp."
NoImagePatterns:
Type: CommaDelimitedList
Default: ""
Description: "Named patterns for no-images in format \"name::pattern\". For example if you define \"user::^userAvatar\\/\" and a path of a requested image will match regex then a no-image named \"user\" will be returned."
Resources:
# Role
GetImageResponseRole:
Type: 'AWS::IAM::Role'
Properties:
Path: /
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: sts:AssumeRole
MaxSessionDuration: 3600
Policies:
- PolicyName: !Sub "S3-${AWS::StackName}-GetImageResponseRole-cache-policy"
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource: arn:aws:logs:*:*:*
- Effect: Allow
Action: "s3:*"
Resource: "*"
# Lambda
GetImageResponseFunction:
Type: AWS::Serverless::Function
Properties:
FunctionName: !Sub "${AWS::StackName}-GetImageResponse"
CodeUri: ./lambda
Handler: index.lambdaHandler
Runtime: nodejs18.x
MemorySize: 2048
Timeout: 10
Role: !GetAtt GetImageResponseRole.Arn
Events:
GetImageResponseApi:
Type: Api
Properties:
Path: /{proxy+}
Method: get
Environment:
Variables:
HOST: !Sub "https://${CacheBucketDistribution.DomainName}"
BASE_PATH: !Ref BasePath
MODIFIER_SEPARATOR: !Ref ModifierSeparator
MODIFIER_ASSIGNER: !Ref ModifierAssigner
VERSION_PARAMETER_NAME: !Ref VersionParameterName
SIGNATURE_PARAMETER_NAME: !Ref SignatureParameterName
SIGNATURE_KEY: !Ref SignatureKey
SIGNATURE_ALGORITHM: !Ref SignatureAlgorithm
ALLOWED_PIXEL_DENSITY: !Join
- ','
- !Ref AllowedPixelDensity
ALLOWED_RESOLUTIONS: !Join
- ','
- !Ref AllowedResolutions
ALLOWED_QUALITIES: !Join
- ','
- !Ref AllowedQualities
ENCODE_QUALITY: !Ref EncodeQuality
SOURCE_BUCKET: !Ref SourceBucketName
CACHE_BUCKET: !Ref CacheBucketName
CACHE_MAX_AGE: !Ref CacheMaxAge
NO_IMAGES: !Join
- ','
- !Ref NoImages
NO_IMAGE_PATTERNS: !Join
- ','
- !Ref NoImagePatterns
# Buckets
SourceBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Ref SourceBucketName
AccessControl: Private
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
CacheBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Ref CacheBucketName
AccessControl: Private
PublicAccessBlockConfiguration:
BlockPublicPolicy: false
RestrictPublicBuckets: false
WebsiteConfiguration:
IndexDocument: index.html
RoutingRules:
- RoutingRuleCondition:
KeyPrefixEquals: ""
HttpErrorCodeReturnedEquals: 404
RedirectRule:
Protocol: https
HostName: !Sub "${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com"
ReplaceKeyPrefixWith: Prod/
HttpRedirectCode: 307
CacheBucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref CacheBucketName
PolicyDocument:
Version: 2012-10-17
Statement:
- Sid: AddPerm
Effect: Allow
Principal: "*"
Action: s3:GetObject
Resource: !Sub "${CacheBucket.Arn}/*"
# CloudFront
CacheBucketDistribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
DefaultCacheBehavior:
AllowedMethods:
- HEAD
- GET
- OPTIONS
CachedMethods:
- HEAD
- GET
- OPTIONS
TargetOriginId: !Sub "S3-${AWS::StackName}-${CacheBucketName}-id"
CachePolicyId: !Ref CloudFrontCachePolicy
ViewerProtocolPolicy: "https-only"
Enabled: true
HttpVersion: http2
IPV6Enabled: true
ViewerCertificate:
CloudFrontDefaultCertificate: true
MinimumProtocolVersion: "TLSv1"
Origins:
- Id: !Sub "S3-${AWS::StackName}-${CacheBucketName}-id"
DomainName: !Sub "${CacheBucketName}.s3-website.${AWS::Region}.amazonaws.com"
ConnectionAttempts: 3
ConnectionTimeout: 10
CustomOriginConfig:
HTTPPort: 80
HTTPSPort: 443
OriginKeepaliveTimeout: 5
OriginProtocolPolicy: "http-only"
OriginReadTimeout: 30
OriginSSLProtocols:
- TLSv1
- TLSv1.1
- TLSv1.2
CloudFrontCachePolicy:
Type: AWS::CloudFront::CachePolicy
Properties:
CachePolicyConfig:
Name: !Sub "S3-${AWS::StackName}-${CacheBucketName}-cloudfront-cache-policy"
DefaultTTL: 0
MaxTTL: 31536000 # one year
MinTTL: 0
ParametersInCacheKeyAndForwardedToOrigin:
EnableAcceptEncodingGzip: false
CookiesConfig:
CookieBehavior: "none"
QueryStringsConfig:
QueryStringBehavior: "whitelist"
QueryStrings:
- !Ref VersionParameterName
- !Ref SignatureParameterName
HeadersConfig:
HeaderBehavior: "whitelist"
Headers:
- Content-Type
- Origin
- Access-Control-Request-Headers
- Access-Control-Request-Method
Outputs:
GetImageResponseApi:
Description: "API Gateway endpoint URL for Prod stage for GetImageResponse function"
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/"
GetImageResponseFunction:
Description: "GetImageResponse Lambda Function ARN"
Value: !GetAtt GetImageResponseFunction.Arn
SourceBucket:
Description: "S3 Bucket for source images"
Value: !Ref SourceBucket
CacheBucket:
Description: "S3 Bucket for cached (modified) images"
Value: !Ref CacheBucket
CacheBucketDistribution:
Description: "CloudFront URL for cached images - use this URL for image requests"
Value: !Sub "https://${CacheBucketDistribution.DomainName}"