handlers/identity-retention/cfn.yaml (214 lines of code) (raw):
AWSTemplateFormatVersion: "2010-09-09"
Description: Performs a reader revenue check to determine whether an identity account should be retained
Parameters:
Stage:
Description: Stage name
Type: String
AllowedValues:
- PROD
- CODE
Default: CODE
Conditions:
CreateProdMonitoring: !Equals [ !Ref Stage, PROD ]
Mappings:
StageMap:
CODE:
ApiName: identity-retention-api-CODE
DomainName: supporter-relationship-code.membership.guardianapis.com
CertificateId: e4e6431e-08b9-4315-b997-75f2f9569d6c
ApiGatewayTargetDomainName: d-zjtpjur7zj.execute-api.eu-west-1.amazonaws.com
PROD:
ApiName: identity-retention-api-PROD
DomainName: supporter-relationship-prod.membership.guardianapis.com
CertificateId: c1e85179-09e3-4222-adee-e4ee77e73304
ApiGatewayTargetDomainName: d-1lv8q5nggh.execute-api.eu-west-1.amazonaws.com
Resources:
IdentityRetentionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- sts:AssumeRole
Path: /
Policies:
- PolicyName: LambdaPolicy
PolicyDocument:
Statement:
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
- lambda:InvokeFunction
Resource: !Sub "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/identity-retention-${Stage}:log-stream:*"
- PolicyName: ReadPrivateCredentials
PolicyDocument:
Statement:
- Effect: Allow
Action: s3:GetObject
Resource:
- !Sub arn:aws:s3:::gu-reader-revenue-private/membership/support-service-lambdas/${Stage}/bigQuery-${Stage}.*.json
- !Sub arn:aws:s3:::gu-reader-revenue-private/membership/support-service-lambdas/${Stage}/trustedApi-${Stage}.*.json
IdentityRetentionLambda:
Type: AWS::Lambda::Function
Properties:
Description: Check whether an identity account is attached to an active billing account in Zuora
FunctionName:
!Sub identity-retention-${Stage}
Code:
S3Bucket: support-service-lambdas-dist
S3Key: !Sub membership/${Stage}/identity-retention/identity-retention.jar
Handler: com.gu.identityRetention.Handler::apply
Environment:
Variables:
Stage: !Ref Stage
Role:
Fn::GetAtt:
- "IdentityRetentionRole"
- Arn
MemorySize: 1536
Runtime: java21
Timeout: 300
Architectures:
- arm64
DependsOn:
- "IdentityRetentionRole"
IdentityRetentionAPIPermission:
Type: AWS::Lambda::Permission
Properties:
Action: lambda:invokeFunction
FunctionName: !Sub identity-retention-${Stage}
Principal: apigateway.amazonaws.com
DependsOn: IdentityRetentionLambda
IdentityRetentionProxyResource:
Type: AWS::ApiGateway::Resource
Properties:
RestApiId: !Ref IdentityRetentionAPI
ParentId: !GetAtt [IdentityRetentionAPI, RootResourceId]
PathPart: retention-status
DependsOn: IdentityRetentionAPI
IdentityRetentionMethod:
Type: AWS::ApiGateway::Method
Properties:
AuthorizationType: NONE
ApiKeyRequired: true
RestApiId: !Ref IdentityRetentionAPI
ResourceId: !Ref IdentityRetentionProxyResource
HttpMethod: GET
RequestParameters:
method.request.querystring.identityId: true
Integration:
Type: AWS_PROXY
IntegrationHttpMethod: POST # this for the interaction between API Gateway and Lambda and MUST be POST
Uri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${IdentityRetentionLambda.Arn}/invocations
DependsOn:
- IdentityRetentionAPI
- IdentityRetentionLambda
- IdentityRetentionProxyResource
IdentityRetentionAPI:
Type: "AWS::ApiGateway::RestApi"
Properties:
Description: Identity call this API as part of a clean-up process for dormant identity accounts
Name: !FindInMap [StageMap, !Ref Stage, ApiName]
IdentityRetentionAPIStage:
Type: AWS::ApiGateway::Stage
Properties:
Description: Stage for identity-retention-api
RestApiId: !Ref IdentityRetentionAPI
DeploymentId: !Ref IdentityRetentionAPIDeployment
StageName: !Sub ${Stage}
DependsOn: IdentityRetentionMethod
IdentityRetentionAPIDeployment:
Type: AWS::ApiGateway::Deployment
Properties:
Description: Deploys identity-retention-api into an environment/stage
RestApiId: !Ref IdentityRetentionAPI
DependsOn: IdentityRetentionMethod
IdentityRetentionAPIKey:
Type: AWS::ApiGateway::ApiKey
Properties:
Description: Key required to call identity retention API
Enabled: true
Name: !Sub identity-retention-api-key-${Stage}
StageKeys:
- RestApiId: !Ref IdentityRetentionAPI
StageName: !Sub ${Stage}
DependsOn:
- IdentityRetentionAPI
- IdentityRetentionAPIStage
IdentityRetentionUsagePlan:
Type: "AWS::ApiGateway::UsagePlan"
Properties:
UsagePlanName: !Sub identity-retention-api-usage-plan-${Stage}
ApiStages:
- ApiId: !Ref IdentityRetentionAPI
Stage: !Ref IdentityRetentionAPIStage
DependsOn:
- IdentityRetentionAPI
- IdentityRetentionAPIStage
IdentityRetentionUsagePlanKey:
Type: "AWS::ApiGateway::UsagePlanKey"
Properties:
KeyId: !Ref IdentityRetentionAPIKey
KeyType: API_KEY
UsagePlanId: !Ref IdentityRetentionUsagePlan
DependsOn:
- IdentityRetentionAPIKey
- IdentityRetentionUsagePlan
IdentityRetentionDomainName:
Type: "AWS::ApiGateway::DomainName"
Properties:
RegionalCertificateArn: !Sub
- arn:aws:acm:${AWS::Region}:${AWS::AccountId}:certificate/${CertificateId}
- { CertificateId: !FindInMap [ StageMap, !Ref Stage, CertificateId ] }
DomainName: !FindInMap [ StageMap, !Ref Stage, DomainName ]
EndpointConfiguration:
Types:
- REGIONAL
IdentityRetentionBasePathMapping:
Type: "AWS::ApiGateway::BasePathMapping"
Properties:
RestApiId: !Ref IdentityRetentionAPI
DomainName: !Ref IdentityRetentionDomainName
Stage: !Sub ${Stage}
DependsOn:
- IdentityRetentionAPI
- IdentityRetentionDomainName
IdentityRetentionDNSRecord:
Type: AWS::Route53::RecordSet
Properties:
HostedZoneName: membership.guardianapis.com.
Name: !FindInMap [ StageMap, !Ref Stage, DomainName ]
Comment: !Sub CNAME for identity-retention API ${Stage}
Type: CNAME
TTL: '120'
ResourceRecords:
- !FindInMap [ StageMap, !Ref Stage, ApiGatewayTargetDomainName ]
5xxApiAlarm:
Type: AWS::CloudWatch::Alarm
Condition: CreateProdMonitoring
Properties:
AlarmActions:
- !Sub arn:aws:sns:${AWS::Region}:${AWS::AccountId}:alarms-handler-topic-PROD
AlarmName:
!Sub
- 5XX rate from ${ApiName}
- { ApiName: !FindInMap [StageMap, !Ref Stage, ApiName] }
ComparisonOperator: GreaterThanThreshold
Dimensions:
- Name: ApiName
Value: !FindInMap [StageMap, !Ref Stage, ApiName]
- Name: Stage
Value: !Sub ${Stage}
EvaluationPeriods: 1
MetricName: 5XXError
Namespace: AWS/ApiGateway
Period: 3600
Statistic: Sum
Threshold: 10
TreatMissingData: notBreaching