CMSgov/macpro-platform-doc-conversion

View on GitHub
services/app-api/serverless.yml

Summary

Maintainability
Test Coverage
# 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}