AWSTemplateFormatVersion: 2010-09-09
Description: Stack to enable sending emails to customers with a recurring payment plan whos card is about to expire or failed

Parameters:
  Stage:
    Description: environment name
    Type: String
    AllowedValues:
      - CODE
      - PROD
  IdentityPaymentFailureTopic:
    Description: Arn of topic that membership workflow publishes payment failure events to
    Type: String
  IdentityApiEndpoint:
    Description: endpoint for the identity API
    Type: String
    AllowedValues:
      - https://idapi.theguardian.com
      - https://idapi.code.dev-theguardian.com
  IdentityAPIKey:
    Description: key used to authenticate against the identity API
    Type: String
  BrazeAPIEndpoint:
    Description: endpoint for the Braze API
    Type: String
    Default: https://rest.fra-01.braze.eu
  BrazeAPIKey:
    Description: key used to authenticate against the Braze API
    Type: String
  SQSQueueUrl:
    Description: url of the queue that contains payment failure messages
    Type: String
  AlarmEmailAddress:
    Description: Contact email for alarms
    Type: String

Conditions:
  IsProd: !Equals
    - !Ref 'Stage'
    - PROD
Resources:
  TopicSendEmail:
    Type: AWS::SNS::Topic
    Properties:
      DisplayName: SendEmailTopic
      Subscription:
        - Endpoint: !Ref 'AlarmEmailAddress'
          Protocol: email
  PaymentFailureLambdaRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
        - Effect: Allow
          Principal:
            Service:
            - lambda.amazonaws.com
          Action:
          - sts:AssumeRole
      Policies:
      - PolicyName: PaymentFailureLambdaPolicy
        PolicyDocument:
          Statement:
            Effect: Allow
            Action:
            - lambda:InvokeFunction
            Resource: !Sub arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:PaymentFailureLambda-${Stage}
      - PolicyName: PaymentFailureLambdaLoggingPolicy
        PolicyDocument:
          Statement:
            Effect: Allow
            Action:
            - logs:CreateLogGroup
            - logs:CreateLogStream
            - logs:PutLogEvents
            Resource: !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/PaymentFailureLambda-${Stage}:log-stream:*
      - PolicyName: PaymentFailureQueueReadPolicy
        PolicyDocument:
          Statement:
            Effect: Allow
            Action:
            - sqs:ReceiveMessage
            - sqs:DeleteMessage
            - sqs:GetQueueAttributes
            Resource: !GetAtt PaymentFailureQueue.Arn

  PaymentFailureLambda:
    Type: AWS::Lambda::Function
    Properties:
      Code:
        S3Bucket: identity-lambda
        S3Key: !Sub identity/${Stage}/payment-failure-lambda/main.jar
      Description: Lambda to send emails to customers with a recurring payment plan whos card is about to expire or failed
      Environment:
        Variables:
          idapiHost: !Sub ${IdentityApiEndpoint}
          idapiAccessToken: !Sub ${IdentityAPIKey}
          brazeApiHost: !Sub ${BrazeAPIEndpoint}
          brazeApiKey: !Sub ${BrazeAPIKey}
          sqsQueueUrl: !Sub ${SQSQueueUrl}
      FunctionName: !Sub PaymentFailureLambda-${Stage}
      Handler: com.gu.identity.paymentfailure.Lambda::handler
      Role: !GetAtt PaymentFailureLambdaRole.Arn
      Runtime: java11
      Timeout: 30
      MemorySize: 1024

  PaymentFailureLambdaLogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Sub /aws/lambda/${PaymentFailureLambda}
      RetentionInDays: 14

  PaymentFailureDeadLetterQueue:
    Type: AWS::SQS::Queue
    Properties:
      QueueName: !Sub ${Stage}-payment-failure-dead-letter

  PaymentFailureQueue:
    Type: AWS::SQS::Queue
    Properties:
      QueueName: !Sub ${Stage}-payment-failure
      RedrivePolicy:
        deadLetterTargetArn: !GetAtt PaymentFailureDeadLetterQueue.Arn
        maxReceiveCount: 5
      DelaySeconds: 120

  PaymentFailureSqsWriteRole:
    Type: AWS::SQS::QueuePolicy
    Properties:
      Queues:
      - !Ref PaymentFailureQueue
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Action: sqs:SendMessage
            Principal:
              AWS: '*'
            Resource: !GetAtt PaymentFailureQueue.Arn
            Condition:
              ArnEquals:
                aws:SourceArn: !Ref IdentityPaymentFailureTopic

  PaymentFailureLambdaEventSource:
    Type: AWS::Lambda::EventSourceMapping
    Properties:
      EventSourceArn: !GetAtt PaymentFailureQueue.Arn
      FunctionName: !GetAtt PaymentFailureLambda.Arn

  PaymentFailureDeadLetterQueueAlert:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmName: !Sub 'payment-failure-lambda-${Stage} Message added to payment failure dead letter queue'
      AlarmDescription: Alarm if payment failure dead letter queue grows beyond 1 message
      Namespace: AWS/SQS
      MetricName: ApproximateNumberOfMessagesVisible
      Dimensions:
        - Name: QueueName
          Value: !GetAtt 'PaymentFailureDeadLetterQueue.QueueName'
      Statistic: Sum
      Period: '300'
      EvaluationPeriods: '1'
      Threshold: '0'
      ComparisonOperator: GreaterThanThreshold
      AlarmActions:
      - !If [IsProd, !Ref 'TopicSendEmail', !Ref 'AWS::NoValue']

  PaymentFailureQueueLengthAlert:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmName: !Sub 'payment-failure-lambda-${Stage} Too many messages on the payment failure queue'
      AlarmDescription: Alarm if payment failure queue grows beyond 300 messages
      Namespace: AWS/SQS
      MetricName: ApproximateNumberOfMessagesVisible
      Dimensions:
        - Name: QueueName
          Value: !GetAtt 'PaymentFailureQueue.QueueName'
      Statistic: Sum
      Period: '60'
      EvaluationPeriods: '10'
      Threshold: '300'
      ComparisonOperator: GreaterThanThreshold
      AlarmActions:
      - !If [IsProd, !Ref 'TopicSendEmail', !Ref 'AWS::NoValue']
