cfn.yaml (180 lines of code) (raw):

Transform: AWS::Serverless-2016-10-31 Description: Source code in https://github.com/guardian/payment-failure-comms Parameters: Stage: Description: Stage name Type: String AllowedValues: - PROD - CODE - DEV Default: DEV AppName: Type: String Default: payment-failure-comms Conditions: IsProd: !Equals [ !Ref Stage, PROD ] Mappings: StageMap: PROD: Schedule: 'rate(20 minutes)' SalesforceStage: PROD SalesforceUserName: pfCommsAPIUser SalesforceAppName: PfComms IdapiInstanceUrl: idapi.theguardian.com IdapiStage: PROD BrazeInstanceUrl: rest.fra-01.braze.eu BrazeAppGroup: LIVE CODE: Schedule: 'rate(365 days)' SalesforceStage: UAT SalesforceUserName: pfCommsAPIUser SalesforceAppName: AwsConnectorSandbox IdapiInstanceUrl: idapi.code.dev-theguardian.com IdapiStage: CODE BrazeInstanceUrl: rest.fra-01.braze.eu BrazeAppGroup: DEV DEV: Schedule: 'rate(365 days)' SalesforceStage: DEV SalesforceUserName: pfCommsAPIUser SalesforceAppName: AwsConnectorSandbox IdapiInstanceUrl: idapi.code.dev-theguardian.com IdapiStage: CODE BrazeInstanceUrl: rest.fra-01.braze.eu BrazeAppGroup: DEV Resources: LogGroup: Type: AWS::Logs::LogGroup Properties: LogGroupName: !Sub /aws/lambda/${AppName}-${Stage} RetentionInDays: 90 PaymentFailureCommsLambda: Type: AWS::Serverless::Function DependsOn: LogGroup Properties: FunctionName: !Sub ${AppName}-${Stage} Handler: payment_failure_comms.Handler::handleRequest Runtime: java8.al2 CodeUri: Bucket: membership-dist Key: !Sub membership/${Stage}/${AppName}/${AppName}.jar Timeout: 120 MemorySize: 256 Environment: Variables: stage: !Ref Stage salesforceApiVersion: v46.0 salesforceInstanceUrl: !Sub - '{{resolve:secretsmanager:${SalesforceStage}/Salesforce/ConnectedApp/${SalesforceAppName}:SecretString:authUrl}}' - SalesforceStage: !FindInMap [ StageMap, !Ref Stage, SalesforceStage ] SalesforceAppName: !FindInMap [ StageMap, !Ref Stage, SalesforceAppName ] salesforceClientId: !Sub - '{{resolve:secretsmanager:${SalesforceStage}/Salesforce/ConnectedApp/${SalesforceAppName}:SecretString:clientId}}' - SalesforceStage: !FindInMap [ StageMap, !Ref Stage, SalesforceStage ] SalesforceAppName: !FindInMap [ StageMap, !Ref Stage, SalesforceAppName ] salesforceClientSecret: !Sub - '{{resolve:secretsmanager:${SalesforceStage}/Salesforce/ConnectedApp/${SalesforceAppName}:SecretString:clientSecret}}' - SalesforceStage: !FindInMap [ StageMap, !Ref Stage, SalesforceStage ] SalesforceAppName: !FindInMap [ StageMap, !Ref Stage, SalesforceAppName ] salesforceUserName: !Sub - '{{resolve:secretsmanager:${SalesforceStage}/Salesforce/User/${SalesforceUserName}:SecretString:userName}}' - SalesforceStage: !FindInMap [ StageMap, !Ref Stage, SalesforceStage ] SalesforceUserName: !FindInMap [ StageMap, !Ref Stage, SalesforceUserName ] salesforcePassword: !Sub - '{{resolve:secretsmanager:${SalesforceStage}/Salesforce/User/${SalesforceUserName}:SecretString:password}}' - SalesforceStage: !FindInMap [ StageMap, !Ref Stage, SalesforceStage ] SalesforceUserName: !FindInMap [ StageMap, !Ref Stage, SalesforceUserName ] salesforceToken: !Sub - '{{resolve:secretsmanager:${SalesforceStage}/Salesforce/User/${SalesforceUserName}:SecretString:token}}' - SalesforceStage: !FindInMap [ StageMap, !Ref Stage, SalesforceStage ] SalesforceUserName: !FindInMap [ StageMap, !Ref Stage, SalesforceUserName ] idapiInstanceUrl: !FindInMap [ StageMap, !Ref Stage, IdapiInstanceUrl ] idapiBearerToken: !Sub - '{{resolve:secretsmanager:${IdapiStage}/Identity/${AppName}:SecretString:bearerToken}}' - IdapiStage: !FindInMap [ StageMap, !Ref Stage, IdapiStage ] brazeInstanceUrl: !FindInMap [ StageMap, !Ref Stage, BrazeInstanceUrl ] brazeApiKey: !Sub - '{{resolve:secretsmanager:${BrazeAppGroup}/Braze/${AppName}:SecretString:apiKey}}' - BrazeAppGroup: !FindInMap [ StageMap, !Ref Stage, BrazeAppGroup ] appIdForBraze: !Sub - '{{resolve:secretsmanager:${BrazeAppGroup}/Braze/${AppName}:SecretString:appId}}' - BrazeAppGroup: !FindInMap [ StageMap, !Ref Stage, BrazeAppGroup ] Events: ScheduledRun: Type: Schedule Properties: Description: Send payment failure communications Schedule: !FindInMap [ StageMap, !Ref Stage, Schedule ] RetryPolicy: # As process runs every 20 mins anyway, there's no point in retrying on failure MaximumRetryAttempts: 0 Enabled: True Policies: - Statement: - Effect: Allow Action: cloudwatch:PutMetricData Resource: "*" EventInvokeConfig: MaximumRetryAttempts: 0 FailureAlarm: Type: AWS::CloudWatch::Alarm Condition: IsProd DependsOn: PaymentFailureCommsLambda Properties: AlarmName: "payment-failure-comms record syncing job is consistently failing to complete" AlarmDescription: > IMPACT: Until the job is repaired, new payment-failure events will not be communicated to customers. For resolution steps, see https://github.com/guardian/payment-failure-comms/blob/main/README.md#alarms. AlarmActions: - !Sub arn:aws:sns:${AWS::Region}:${AWS::AccountId}:alarms-handler-topic-PROD Metrics: - Id: errors Expression: "FILL(m1,0)" Label: ErrorsCount - Id: m1 ReturnData: false MetricStat: Metric: MetricName: Errors Namespace: AWS/Lambda Dimensions: - Name: FunctionName Value: !Ref PaymentFailureCommsLambda Stat: Sum Period: 60 Unit: Count ComparisonOperator: GreaterThanOrEqualToThreshold Threshold: 1 EvaluationPeriods: 90 DatapointsToAlarm: 5 TreatMissingData: ignore FailureLimitReachedAlarm: Type: AWS::CloudWatch::Alarm Condition: IsProd DependsOn: PaymentFailureCommsLambda Properties: AlarmName: "Action required - payment-failure-comms: failure limit reached for some records" AlarmDescription: > IMPACT: At least one payment-failure event will not be communicated to the customer. For resolution steps, see https://github.com/guardian/payment-failure-comms/blob/main/README.md#alarms. AlarmActions: - !Sub arn:aws:sns:${AWS::Region}:${AWS::AccountId}:alarms-handler-topic-PROD MetricName: failure-limit-reached Namespace: payment-failure-comms Dimensions: - Name: Stage Value: !Ref Stage ComparisonOperator: GreaterThanOrEqualToThreshold Threshold: 5 Statistic: Sum Period: 3600 EvaluationPeriods: 1 TreatMissingData: notBreaching