mirror of
https://github.com/protomaps/PMTiles.git
synced 2026-02-04 02:41:09 +00:00
198 lines
6.4 KiB
YAML
198 lines
6.4 KiB
YAML
AWSTemplateFormatVersion: '2010-09-09'
|
|
Description: Serve Z/X/Y tiles through CloudFront + Lambda from an existing S3 bucket.
|
|
Parameters:
|
|
BucketName:
|
|
Description: 'Name of an existing S3 bucket with .pmtiles tilesets. Should be in the same region as your CloudFormation stack. Can be a RequesterPays bucket in another account.'
|
|
Type: String
|
|
MinLength: 1
|
|
|
|
DefaultTTL:
|
|
Description: Default time-to-live for cached tiles in the CloudFront distribution.
|
|
Type: Number
|
|
Default: 86400
|
|
|
|
AllowedOrigins:
|
|
Description: 'Comma-separated list of domains (e.g. example.com) allowed by browser CORS policy, or * for all origins.'
|
|
Type: List<String>
|
|
Default: "*"
|
|
|
|
PublicHostname:
|
|
Description: 'Optional. Replace *.cloudfront.net in TileJSON with a custom hostname (e.g. example.com). See docs on how this value is cached.'
|
|
Type: String
|
|
|
|
Outputs:
|
|
CloudFrontDistributionUrl:
|
|
Description: 'URL of the CloudFront distribution for cached tiles.'
|
|
Value: !Sub "https://${CloudFrontDistribution.DomainName}"
|
|
Export:
|
|
Name: !Sub "${AWS::StackName}-CloudFrontDistributionURL"
|
|
|
|
|
|
Conditions:
|
|
IsPublicHostnameProvided:
|
|
Fn::Not:
|
|
- Fn::Equals:
|
|
- Ref: PublicHostname
|
|
- ''
|
|
Resources:
|
|
LogGroup:
|
|
Type: AWS::Logs::LogGroup
|
|
Properties:
|
|
LogGroupName: !Sub "/aws/lambda/${AWS::StackName}"
|
|
RetentionInDays: 7
|
|
|
|
LambdaExecutionRole:
|
|
Type: 'AWS::IAM::Role'
|
|
Properties:
|
|
AssumeRolePolicyDocument:
|
|
Version: '2012-10-17'
|
|
Statement:
|
|
- Effect: Allow
|
|
Principal:
|
|
Service: lambda.amazonaws.com
|
|
Action: sts:AssumeRole
|
|
Policies:
|
|
- PolicyName: !Sub "${AWS::StackName}-LambdaLoggingPolicy"
|
|
PolicyDocument:
|
|
Version: '2012-10-17'
|
|
Statement:
|
|
- Effect: Allow
|
|
Action:
|
|
- logs:CreateLogStream
|
|
- logs:PutLogEvents
|
|
Resource: !Sub "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${AWS::StackName}:log-stream:*"
|
|
- PolicyName: !Sub "${AWS::StackName}-LambdaS3AccessPolicy"
|
|
PolicyDocument:
|
|
Version: '2012-10-17'
|
|
Statement:
|
|
- Effect: Allow
|
|
Action: s3:GetObject
|
|
Resource: !Sub arn:aws:s3:::${BucketName}/*
|
|
|
|
|
|
LambdaFunctionUrl:
|
|
Type: 'AWS::Lambda::Url'
|
|
Properties:
|
|
AuthType: NONE
|
|
TargetFunctionArn: !GetAtt LambdaFunction.Arn
|
|
InvokeMode: BUFFERED
|
|
|
|
LambdaFunctionUrlPermissionInvokeUrl:
|
|
Type: AWS::Lambda::Permission
|
|
Properties:
|
|
Action: lambda:InvokeFunctionUrl
|
|
FunctionName: !Ref LambdaFunction
|
|
Principal: '*'
|
|
FunctionUrlAuthType: NONE
|
|
|
|
LambdaFunctionUrlPermissionInvokeFunction:
|
|
Type: AWS::Lambda::Permission
|
|
Properties:
|
|
Action: lambda:InvokeFunction
|
|
FunctionName: !Ref LambdaFunction
|
|
Principal: '*'
|
|
|
|
ViewerRequestCloudFrontFunction:
|
|
Type: AWS::CloudFront::Function
|
|
Properties:
|
|
Name: !Sub "${AWS::StackName}-ViewerRequestCloudFrontFunction"
|
|
AutoPublish: true
|
|
FunctionCode: |
|
|
function handler(event) {
|
|
const request = event.request;
|
|
request.headers['x-distribution-domain-name'] = { value: event.context.distributionDomainName };
|
|
return request;
|
|
}
|
|
FunctionConfig:
|
|
Comment: 'Add x-distribution-domain header.'
|
|
Runtime: cloudfront-js-2.0
|
|
|
|
CloudFrontDistribution:
|
|
Type: 'AWS::CloudFront::Distribution'
|
|
DeletionPolicy: Delete
|
|
Properties:
|
|
DistributionConfig:
|
|
Origins:
|
|
- Id: LambdaOrigin
|
|
DomainName: !Select [2, !Split ["/", !GetAtt LambdaFunctionUrl.FunctionUrl]]
|
|
CustomOriginConfig:
|
|
OriginProtocolPolicy: https-only
|
|
DefaultCacheBehavior:
|
|
TargetOriginId: LambdaOrigin
|
|
ViewerProtocolPolicy: redirect-to-https
|
|
CachePolicyId: !Ref CachePolicyId
|
|
ResponseHeadersPolicyId: !Ref ResponseHeadersPolicyId
|
|
OriginRequestPolicyId: b689b0a8-53d0-40ab-baf2-68738e2966ac
|
|
FunctionAssociations:
|
|
Fn::If:
|
|
- IsPublicHostnameProvided
|
|
- !Ref "AWS::NoValue"
|
|
-
|
|
- EventType: viewer-request
|
|
FunctionARN: !GetAtt ViewerRequestCloudFrontFunction.FunctionARN
|
|
Enabled: true
|
|
HttpVersion: http2and3
|
|
Comment: "CloudFront Distribution"
|
|
PriceClass: PriceClass_All # Change this to save cost and distribute to fewer countries. Check https://aws.amazon.com/cloudfront/pricing/
|
|
|
|
CachePolicyId:
|
|
Type: 'AWS::CloudFront::CachePolicy'
|
|
Properties:
|
|
CachePolicyConfig:
|
|
Name: !Sub "${AWS::StackName}-CachePolicyConfig"
|
|
DefaultTTL: !Ref DefaultTTL
|
|
MaxTTL: 31536000
|
|
MinTTL: 0
|
|
ParametersInCacheKeyAndForwardedToOrigin:
|
|
EnableAcceptEncodingBrotli: true
|
|
EnableAcceptEncodingGzip: true
|
|
HeadersConfig:
|
|
HeaderBehavior: none
|
|
CookiesConfig:
|
|
CookieBehavior: none
|
|
QueryStringsConfig:
|
|
QueryStringBehavior: none
|
|
|
|
ResponseHeadersPolicyId:
|
|
Type: 'AWS::CloudFront::ResponseHeadersPolicy'
|
|
# DeletionPolicy: Delete
|
|
Properties:
|
|
ResponseHeadersPolicyConfig:
|
|
Name: !Sub "${AWS::StackName}-ResponseHeadersPolicyConfig"
|
|
CorsConfig:
|
|
AccessControlAllowOrigins:
|
|
Items: !Ref AllowedOrigins
|
|
AccessControlAllowHeaders:
|
|
Items:
|
|
- '*'
|
|
AccessControlAllowMethods:
|
|
Items:
|
|
- GET
|
|
- HEAD
|
|
- OPTIONS
|
|
AccessControlExposeHeaders:
|
|
Items:
|
|
- ETag
|
|
AccessControlAllowCredentials: false # Set to true if you want to include credentials
|
|
OriginOverride: true
|
|
Comment: 'CORS policy for Protomaps'
|
|
|
|
LambdaFunction:
|
|
Type: 'AWS::Lambda::Function'
|
|
Properties:
|
|
FunctionName: !Sub "${AWS::StackName}-LambdaFunction"
|
|
Runtime: nodejs22.x
|
|
Architectures: [arm64]
|
|
Role: !GetAtt LambdaExecutionRole.Arn
|
|
Handler: index.handler
|
|
MemorySize: 512
|
|
LoggingConfig:
|
|
LogGroup: !Ref LogGroup
|
|
Environment:
|
|
Variables:
|
|
BUCKET: !Ref BucketName
|
|
PUBLIC_HOSTNAME: !Ref PublicHostname
|
|
Code:
|
|
S3Bucket: !Ref BucketName
|
|
S3Key: lambda_function.zip
|