services/app-api/serverless.yml
# Refer to the README.md file in within this service directory to configure all ssm parameters required for this service.
service: app-api
frameworkVersion: "3"
package:
individually: true
plugins:
- serverless-bundle
- serverless-plugin-warmup
- serverless-associate-waf
- serverless-stack-termination-protection
- "@stratiformdigital/serverless-idempotency-helper"
- "@stratiformdigital/serverless-iam-helper"
- "@stratiformdigital/serverless-online"
- serverless-plugin-scripts
- serverless-s3-bucket-helper
- serverless-domain-manager
custom:
stage: ${opt:stage, self:provider.stage}
region: ${opt:region, self:provider.region}
invokeARNs: ${ssm:/configuration/${self:custom.stage}/macpro-platform-doc-conversion/iam/invoke-arns, ssm:/configuration/default/macpro-platform-doc-conversion/iam/invoke-arns, "arn:aws:iam::${aws:accountId}:root"}
serverlessTerminationProtection:
stages:
- master
- val
- production
webAclName: ${self:service}-${self:custom.stage}-webacl
princeLicense: ${ssm:/configuration/${self:custom.stage}/prince/license, ssm:/configuration/default/prince/license, ""}
associateWaf:
name: ${self:custom.webAclName}
version: V2
warmup:
default:
enabled: true
prewarm: true
events:
- schedule: rate(${ssm:/configuration/${self:custom.stage}/warmup/schedule, ssm:/configuration/default/warmup/schedule, "4 minutes"})
concurrency: ${ssm:/configuration/${self:custom.stage}/warmup/concurrency, ssm:/configuration/default/warmup/concurrency, 5}
scripts:
hooks:
package:initialize: |
set -e
curl -L --output lambda_layer.zip https://www.princexml.com/download/prince-14.2-aws-lambda.zip && zip lambda_layer.zip etc/fontconfig/fonts.conf
mkdir -p prince-engine/license && echo '${self:custom.princeLicense}' > prince-engine/license/license.dat
[ -s prince-engine/license/license.dat ]
[ "$?" -eq "0" ] && zip lambda_layer.zip prince-engine/license/license.dat
zip -r lambda_layer.zip fonts
domains:
production: macpro-platform-prod.cms.gov
val: macpro-platform-val.cms.gov
master: macpro-platform-dev.cms.gov
other: macpro-platform-dev.cms.gov
basePaths:
production: "doc-conv"
val: "doc-conv"
master: "doc-conv"
other: "${self:custom.stage}-doc-conv"
customDomain:
domainName: ${self:custom.domains.${self:custom.stage}, self:custom.domains.other}
basePath: ${self:custom.basePaths.${self:custom.stage}, self:custom.basePaths.other}
stage: "${self:custom.stage}"
endpointType: "regional"
createRoute53Record: true
createRoute53IPv6Record: true
securityPolicy: tls_1_2
autoDomain: true
provider:
name: aws
runtime: nodejs14.x
region: us-east-1
logs:
restApi: true
tracing:
apiGateway: true
iam:
role:
path: ${ssm:/configuration/${self:custom.stage}/iam/path, ssm:/configuration/default/iam/path, "/"}
permissionsBoundary: ${ssm:/configuration/${self:custom.stage}/iam/permissionsBoundaryPolicy, ssm:/configuration/default/iam/permissionsBoundaryPolicy, ""}
endpointType: regional
apiGateway:
resourcePolicy:
- Effect: Allow
Principal:
AWS: ${self:custom.invokeARNs}
Action: execute-api:Invoke
Resource:
- execute-api:/*
layers:
prince:
name: prince-${self:custom.stage}
package:
artifact: lambda_layer.zip
functions:
508html-to-508pdf:
handler: handlers/prince.main
timeout: 30
memorySize: 3008
maximumRetryAttempts: 0
layers:
- !Ref PrinceLambdaLayer
events:
- http:
path: 508html-to-508pdf
method: post
cors: true
authorizer: aws_iam
resources:
Resources:
GatewayResponseDefault4XX:
Type: "AWS::ApiGateway::GatewayResponse"
Properties:
ResponseParameters:
gatewayresponse.header.Access-Control-Allow-Origin: "'*'"
gatewayresponse.header.Access-Control-Allow-Headers: "'*'"
ResponseType: DEFAULT_4XX
RestApiId: !Ref ApiGatewayRestApi
GatewayResponseDefault5XX:
Type: "AWS::ApiGateway::GatewayResponse"
Properties:
ResponseParameters:
gatewayresponse.header.Access-Control-Allow-Origin: "'*'"
gatewayresponse.header.Access-Control-Allow-Headers: "'*'"
ResponseType: DEFAULT_5XX
RestApiId: !Ref ApiGatewayRestApi
ApiGwWebAcl:
Type: AWS::WAFv2::WebACL
Properties:
Name: ${self:custom.webAclName}
DefaultAction:
Block: {}
Rules:
- Name: ${self:custom.webAclName}-DDOSRateLimitRule
Priority: 0
Action:
Block: {}
Statement:
RateBasedStatement:
Limit: 5000
AggregateKeyType: IP
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: ${self:custom.webAclName}-DDOSRateLimitRuleMetric
- Name: ${self:custom.webAclName}-AWSCommonRule
Priority: 1
OverrideAction:
None: {}
Statement:
ManagedRuleGroupStatement:
VendorName: AWS
Name: AWSManagedRulesCommonRuleSet
ExcludedRules:
- Name: SizeRestrictions_BODY
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: ${self:custom.webAclName}-AWSCommonRuleMetric
- Name: ${self:custom.webAclName}-AWSManagedRulesAmazonIpReputationList
Priority: 2
OverrideAction:
None: {}
Statement:
ManagedRuleGroupStatement:
VendorName: AWS
Name: AWSManagedRulesAmazonIpReputationList
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: ${self:custom.webAclName}-AWSManagedRulesAmazonIpReputationListMetric
- Name: ${self:custom.webAclName}-AWSManagedRulesKnownBadInputsRuleSet
Priority: 3
OverrideAction:
None: {}
Statement:
ManagedRuleGroupStatement:
VendorName: AWS
Name: AWSManagedRulesKnownBadInputsRuleSet
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: ${self:custom.webAclName}-AWSManagedRulesKnownBadInputsRuleSetMetric
- Name: ${self:custom.webAclName}-allow-usa-plus-territories
Priority: 5
Action:
Allow: {}
Statement:
GeoMatchStatement:
CountryCodes:
- GU # Guam
- PR # Puerto Rico
- US # USA
- UM # US Minor Outlying Islands
- VI # US Virgin Islands
- MP # Northern Mariana Islands
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: ${self:custom.webAclName}-allow-usa-plus-territories-metric
Scope: REGIONAL
VisibilityConfig:
CloudWatchMetricsEnabled: true
SampledRequestsEnabled: true
MetricName: ${self:custom.stage}-webacl
Outputs:
ApiGatewayRestApiName:
Value: !Ref ApiGatewayRestApi
ApiGatewayRestApiUrl:
Value: !Sub https://${ApiGatewayRestApi}.execute-api.${self:provider.region}.amazonaws.com/${self:custom.stage}
Region:
Value: !Sub ${AWS::Region}