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