handlers/contact-us-api/cfn.yaml (327 lines of code) (raw):

--- Parameters: Stage: Description: Stage name Type: String AllowedValues: - PROD - CODE Default: CODE Mappings: StageMap: PROD: authDomain: gnmtouchpoint.my.salesforce.com reqDomain: gnmtouchpoint.my.salesforce.com SalesforceStage: PROD AppName: TouchpointUpdate AppSecretsVersion: d338b761-cb81-4adf-aca4-163678e65a59 UserSecretsVersion: dfbf9eba-5215-4cb8-91f1-ff5bcbbf5201 DomainName: contact-us-api.support.guardianapis.com CODE: authDomain: test.salesforce.com reqDomain: gnmtouchpoint--DEV1.sandbox.my.salesforce.com SalesforceStage: CODE AppName: AwsConnectorSandbox AppSecretsVersion: abaa595b-e6c8-4d13-81e0-2d02627536c7 UserSecretsVersion: 4a0eabf6-7940-47ef-87d0-36c3ef7f5741 DomainName: contact-us-api-code.support.guardianapis.com Resources: ContactUsApiGateway: Type: AWS::ApiGateway::RestApi Properties: Body: info: version: '1.0' title: Ref: AWS::StackName paths: "/": post: x-amazon-apigateway-integration: httpMethod: POST type: aws_proxy uri: Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ContactUsLambda.Arn}/invocations security: - api_key: [] responses: {} swagger: '2.0' securityDefinitions: api_key: type: apiKey name: x-api-key in: header Name: Fn::Sub: contact-us-api-${Stage}-ApiGateway ContactUsApiGatewayDeployment18d4f4d63b: Type: AWS::ApiGateway::Deployment Properties: Description: 'RestApi deployment id: 18d4f4d63b13b7bad95a556b1a598aebc104f418' RestApiId: Ref: ContactUsApiGateway 4xxApiAlarm: Type: AWS::CloudWatch::Alarm Condition: IsProd DependsOn: - ContactUsApiGateway Properties: AlarmActions: - !Sub arn:aws:sns:${AWS::Region}:${AWS::AccountId}:alarms-handler-topic-PROD AlarmName: Fn::Sub: 4XX rate from contact-us-api-${Stage} AlarmDescription: 'See https://github.com/guardian/support-service-lambdas/blob/main/handlers/contact-us-api/README.md#4XX-Errors for possible causes, impacts and fixes. ' ComparisonOperator: GreaterThanThreshold Dimensions: - Name: ApiName Value: Fn::Sub: contact-us-api-${Stage}-ApiGateway - Name: Stage Value: Fn::Sub: "${Stage}" EvaluationPeriods: 1 MetricName: 4XXError Namespace: AWS/ApiGateway Period: 3600 Statistic: Sum Threshold: 1 TreatMissingData: notBreaching 5xxApiAlarm: Type: AWS::CloudWatch::Alarm Condition: IsProd DependsOn: - ContactUsApiGateway Properties: AlarmActions: - !Sub arn:aws:sns:${AWS::Region}:${AWS::AccountId}:alarms-handler-topic-PROD AlarmName: Fn::Sub: 5XX rate from contact-us-api-${Stage} AlarmDescription: 'See https://github.com/guardian/support-service-lambdas/blob/main/handlers/contact-us-api/README.md#5XX-Errors for possible causes, impacts and fixes. ' ComparisonOperator: GreaterThanThreshold Dimensions: - Name: ApiName Value: Fn::Sub: contact-us-api-${Stage}-ApiGateway - Name: Stage Value: Fn::Sub: "${Stage}" EvaluationPeriods: 1 MetricName: 5XXError Namespace: AWS/ApiGateway Period: 3600 Statistic: Sum Threshold: 1 TreatMissingData: notBreaching ContactUsLambda: Type: AWS::Lambda::Function DependsOn: - ContactUsLambdaRole Properties: Code: S3Bucket: support-service-lambdas-dist S3Key: Fn::Sub: membership/${Stage}/contact-us-api/contact-us-api.jar FunctionName: Fn::Sub: contact-us-api-${Stage} Handler: com.gu.contact_us_api.Handler MemorySize: 1024 Role: Fn::GetAtt: - ContactUsLambdaRole - Arn Runtime: java21 Timeout: 60 Environment: Variables: stage: Ref: Stage authDomain: Fn::FindInMap: - StageMap - Ref: Stage - authDomain reqDomain: Fn::FindInMap: - StageMap - Ref: Stage - reqDomain Tags: - Key: lambda:createdBy Value: SAM Architectures: - arm64 ContactUsLambdaApiEventPermissionStage: Type: AWS::Lambda::Permission Properties: Action: lambda:InvokeFunction FunctionName: Ref: ContactUsLambda Principal: apigateway.amazonaws.com SourceArn: Fn::Sub: - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/POST/ - __ApiId__: Ref: ContactUsApiGateway __Stage__: "*" ContactUsApiGatewayUsagePlan: Type: AWS::ApiGateway::UsagePlan DependsOn: - ContactUsApiGateway Properties: ApiStages: - ApiId: Ref: ContactUsApiGateway Stage: Ref: ContactUsApiGatewayStage Description: Fn::Sub: Usage plan for contact-us-api-PROD UsagePlanName: Fn::Sub: contact-us-api-PROD-UsagePlan ContactUsApiGatewayStage: Type: AWS::ApiGateway::Stage Properties: DeploymentId: Ref: ContactUsApiGatewayDeployment18d4f4d63b RestApiId: Ref: ContactUsApiGateway StageName: Fn::Sub: "${Stage}" ContactUsApiGatewayApiKey: Type: AWS::ApiGateway::ApiKey DependsOn: - ContactUsApiGatewayUsagePlan Properties: Enabled: true StageKeys: - RestApiId: Ref: ContactUsApiGateway StageName: Ref: ContactUsApiGatewayStage ContactUsApiGatewayUsagePlanKey: Type: AWS::ApiGateway::UsagePlanKey DependsOn: - ContactUsApiGatewayApiKey Properties: KeyId: Ref: ContactUsApiGatewayApiKey KeyType: API_KEY UsagePlanId: Ref: ContactUsApiGatewayUsagePlan noRequestsAlarm: Type: AWS::CloudWatch::Alarm Condition: IsProd DependsOn: - ContactUsApiGateway Properties: AlarmActions: - !Sub arn:aws:sns:${AWS::Region}:${AWS::AccountId}:alarms-handler-topic-PROD AlarmName: Fn::Sub: No requests coming into contact-us-api-${Stage} AlarmDescription: 'This is a last line catch-all alarm. It means no requests were received in the last 6 hours. It might mean something''s (silently) gone wrong with a part of the system that sends these requests (eg. MMA client or server-side). Or it could mean our users are happy and don''t need to contact us. :) ' ComparisonOperator: LessThanThreshold Threshold: 1 EvaluationPeriods: 12 Metrics: - Id: actualCount Expression: FILL(rawCount, 0) - Id: rawCount ReturnData: false MetricStat: Metric: MetricName: Count Namespace: AWS/ApiGateway Dimensions: - Name: ApiName Value: Fn::Sub: contact-us-api-${Stage}-ApiGateway - Name: Stage Value: Fn::Sub: "${Stage}" Period: 3600 Stat: Sum Unit: Count TreatMissingData: breaching ContactUsLambdaRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Statement: - Action: sts:AssumeRole Effect: Allow Principal: Service: lambda.amazonaws.com Version: '2012-10-17' Tags: - Key: App Value: contact-us-api - Key: Stage Value: Ref: Stage - Key: Stack Value: membership Path: "/" Policies: - PolicyName: ContactUsLambdaPolicy PolicyDocument: Statement: - Effect: Allow Action: - lambda:InvokeFunction - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents Resource: Fn::Sub: arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/contact-us-api-${Stage}:log-stream:* - PolicyName: ReadFromSecretsManagerPolicy PolicyDocument: Statement: - Effect: Allow Action: - secretsmanager:DescribeSecret - secretsmanager:GetSecretValue Resource: - arn:aws:secretsmanager:eu-west-1:865473395570:secret:PROD/Salesforce/ConnectedApp/TouchpointUpdate-lolLqP - arn:aws:secretsmanager:eu-west-1:865473395570:secret:CODE/Salesforce/ConnectedApp/AwsConnectorSandbox-jaCgRl - arn:aws:secretsmanager:eu-west-1:865473395570:secret:PROD/Salesforce/User/MembersDataAPI-1wX7Rg - arn:aws:secretsmanager:eu-west-1:865473395570:secret:CODE/Salesforce/User/MembersDataAPI-xpUthA ContactUsApiDomainName: Type: "AWS::ApiGateway::DomainName" Properties: RegionalCertificateArn: # only for *.support.guardianapis.com !Sub arn:aws:acm:${AWS::Region}:${AWS::AccountId}:certificate/b384a6a0-2f54-4874-b99b-96eeff96c009 DomainName: !FindInMap [ StageMap, !Ref Stage, DomainName ] EndpointConfiguration: Types: - REGIONAL ContactUsApiBasePathMapping: Type: "AWS::ApiGateway::BasePathMapping" Properties: RestApiId: !Ref ContactUsApiGateway DomainName: !Ref ContactUsApiDomainName Stage: !Sub ${Stage} DependsOn: - ContactUsApiGateway - ContactUsApiDomainName - ContactUsApiGatewayStage ContactUsApiDNSRecord: Type: AWS::Route53::RecordSet Properties: HostedZoneName: support.guardianapis.com. Name: !FindInMap [ StageMap, !Ref Stage, DomainName ] Type: CNAME TTL: '120' ResourceRecords: - !GetAtt ContactUsApiDomainName.RegionalDomainName Conditions: IsProd: Fn::Equals: - Ref: Stage - PROD