
# We have a separate Serverless config file because Lambda@Edge
# functions must be in us-east-1 and Serverless does not support
# multi-region deployments or Lambda@Edge: 
# https://github.com/serverless/serverless/issues/4123
# https://github.com/serverless/serverless/issues/3944
# Serverless also does not support customizing the yml filename,
# so we just cp the file before deploying.
# https://github.com/serverless/serverless/issues/4473
service: lambda # Important: this must be unique in AWS Cloudformation!
frameworkVersion: ">=3.24.1 <4.0.0"

provider:
  name: aws
  runtime: nodejs14.x
  region: us-west-2
  stage: ${env:SLS_STAGE, self:custom.stageDefault}
  kmsKeyArn: ${self:custom.awsKmsKeyArn}
  iamRoleStatements:
    - Effect: Allow
      Action:
        - KMS:Decrypt
      Resource: ${self:custom.awsKmsKeyArn} 
  # Let's be conservative and prevent any unexpected changes
  # to the stack. See:
  # https://github.com/gladly-team/tab/issues/582
  # Example to update policy:
  #   aws cloudformation set-stack-policy --stack-name lambda-test --region us-west-2 --stack-policy-body \
  #   '{"Statement":[
  #     {"Effect":"Allow","Principal":"*","Action":"Update:Modify","Resource":"LogicalResourceId/FirebaseAuthorizerLambdaFunction"},
  #     {"Effect":"Allow","Principal":"*","Action":"Update:*","Resource":"LogicalResourceId/FirebaseAuthorizerLambdaVersion*"},
  #     {"Effect":"Allow","Principal":"*","Action":"Update:Modify","Resource":"LogicalResourceId/FirebaseAuthorizerLogGroup"},
  #     {"Effect":"Allow","Principal":"*","Action":"Update:Modify","Resource":"LogicalResourceId/SearchRequestLoggerLambdaFunction"},
  #     {"Effect":"Allow","Principal":"*","Action":"Update:*","Resource":"LogicalResourceId/SearchRequestLoggerLambdaVersion*"},
  #     {"Effect":"Allow","Principal":"*","Action":"Update:Modify","Resource":"LogicalResourceId/SearchRequestLoggerLogGroup"},
  #     {"Effect":"Allow","Principal":"*","Action":"Update:Modify","Resource":"LogicalResourceId/IamRoleLambdaExecution"}
  #   ]}'
  stackPolicy:
    # If not specified here, Cloudformation denies updates by default.
    - Effect: Allow
      Principal: "*"
      Action: "Update:Modify"
      Resource: "LogicalResourceId/FirebaseAuthorizerLambdaFunction"
    - Effect: Allow
      Principal: "*"
      Action: "Update:*"
      Resource: "LogicalResourceId/FirebaseAuthorizerLambdaVersion*"
    - Effect: Allow
      Principal: "*"
      Action: "Update:Modify"
      Resource: "LogicalResourceId/FirebaseAuthorizerLogGroup"
    - Effect: Allow
      Principal: "*"
      Action: "Update:Modify"
      Resource: "LogicalResourceId/SearchRequestLoggerLambdaFunction"
    - Effect: Allow
      Principal: "*"
      Action: "Update:*"
      Resource: "LogicalResourceId/SearchRequestLoggerLambdaVersion*"
    - Effect: Allow
      Principal: "*"
      Action: "Update:Modify"
      Resource: "LogicalResourceId/SearchRequestLoggerLogGroup"
    - Effect: Allow
      Principal: "*"
      Action: "Update:Modify"
      Resource: "LogicalResourceId/IamRoleLambdaExecution"

custom:
  stageDefault: dev
  # TODO: make KMS key an env var
  awsKmsKeyArn: arn:aws:kms:us-west-2:167811431063:key/de8bda45-b6cd-421f-8f56-de56bfb9f97b
  prune:
    automatic: true
    number: 5

plugins:
  # https://github.com/claygregory/serverless-prune-plugin
  - serverless-prune-plugin

functions:
  firebaseAuthorizer:
    handler: build/firebase-authorizer/firebase-authorizer.handler
    environment:
      LAMBDA_FIREBASE_PROJECT_ID: ${env:LAMBDA_FIREBASE_PROJECT_ID}
      LAMBDA_FIREBASE_DATABASE_URL: ${env:LAMBDA_FIREBASE_DATABASE_URL}
      LAMBDA_FIREBASE_CLIENT_EMAIL: ${env:LAMBDA_FIREBASE_CLIENT_EMAIL}
      FIREBASE_PUBLIC_API_KEY: ${file(./src/firebase-authorizer/variables.yml):${self:provider.stage}.FIREBASE_PUBLIC_API_KEY}
      # Encrypted with AWS KMS for encryption during deploy.
      #   https://docs.aws.amazon.com/lambda/latest/dg/env_variables.html
      #   https://docs.aws.amazon.com/cli/latest/reference/kms/encrypt.html
      # Unfortunately, "Cloudformation and SAM do not currently support encryption helpers that
      #   Lambda console provides...  As of now the only way to achieve this (other than through console)
      #   is to use client side encryption - use encrypted cipher text in your variables and then decrypt
      #   them in the lambda function code."
      #   https://github.com/awslabs/serverless-application-model/issues/48#issuecomment-269663554
      # Note on encrypting/decrypting with the AWS CLI:
      #   https://github.com/aws/aws-cli/issues/1043#issuecomment-65878875
      # To encrypt:
      #   * First, make sure the item is base64 encoded. In Node:
      #     `Buffer.from(myInput, 'utf-8').toString('base64')`
      #   * Then: `aws kms encrypt --key-id [kms-key-id] --plaintext [item]`
      LAMBDA_FIREBASE_PRIVATE_KEY: ${file(./src/firebase-authorizer/variables.yml):${self:provider.stage}.LAMBDA_FIREBASE_PRIVATE_KEY}
      COOKIE_SECRET_20220711: ${file(./src/firebase-authorizer/variables.yml):${self:provider.stage}.COOKIE_SECRET_20220711}
  searchRequestLogger:
    handler: build/search-request-logger/search-request-logger.handler
    events:  ${file(./src/search-request-logger/variables.yml):${self:provider.stage}.events}
    environment:
      GRAPHQL_ENDPOINT: ${file(./src/search-request-logger/variables.yml):${self:provider.stage}.graphqlEndpoint}
