handlers/zuora-retention/cfn.yaml (498 lines of code) (raw):
AWSTemplateFormatVersion: "2010-09-09"
Description: Finds and marks zuora accounts that are out of the retention period
Parameters:
Stage:
Description: Stage name
Type: String
AllowedValues:
- CODE
- PROD
Default: CODE
Mappings:
StageVariables:
CODE:
retentionBucketName : "zuora-retention-code"
PROD:
retentionBucketName : "zuora-retention-prod"
Resources:
RetentionBucket:
Type: "AWS::S3::Bucket"
Properties:
BucketName:
Fn::FindInMap:
- StageVariables
- Ref: Stage
- "retentionBucketName"
AccessControl: Private
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
LifecycleConfiguration:
Rules:
- Id: DeleteOldFiles
Prefix: ""
Status: Enabled
ExpirationInDays: 1
ZuoraQuerierRole:
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/zuora-retention-querier-${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}/zuoraRest-${Stage}*.json"
ZuoraResultsRole:
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/zuora-retention-jobResult-${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}/zuoraRest-${Stage}*.json"
ZuoraFileFetcherRole:
Type: AWS::IAM::Role
DependsOn: RetentionBucket
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- sts:AssumeRole
Path: /
Policies:
- PolicyName: writeToRetentionBucket
PolicyDocument:
Statement:
- Effect: Allow
Action:
- s3:PutObject
Resource: !Sub arn:aws:s3:::${RetentionBucket}/*
- 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/zuora-retention-fileFetcher-${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}/zuoraRest-${Stage}*.json"
FilterRole:
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/zuora-retention-filter-${Stage}:log-stream:*"
- PolicyName: RetentionBucket
PolicyDocument:
Statement:
- Effect: Allow
Action:
- s3:PutObject
- s3:GetObject
Resource: !Sub arn:aws:s3:::${RetentionBucket}/*
UpdaterRole:
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/zuora-retention-account-updater-${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}/zuoraRest-${Stage}*.json"
- PolicyName: ReadRetentionBucket
PolicyDocument:
Statement:
- Effect: Allow
Action:
- s3:GetObject
Resource: !Sub arn:aws:s3:::${RetentionBucket}/*
StateMachineTriggerRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service:
- events.amazonaws.com
Action:
- sts:AssumeRole
Policies:
- PolicyName: TriggerStateMchine
PolicyDocument:
Version : "2012-10-17"
Statement:
- Effect: Allow
Action:
- states:StartExecution
Resource: !Ref stateMachine
ZuoraRetentionQuerier:
Type: AWS::Lambda::Function
Properties:
Description: submit query jobs to Zuora AQuA API
FunctionName:
!Sub zuora-retention-querier-${Stage}
Code:
S3Bucket: support-service-lambdas-dist
S3Key: !Sub membership/${Stage}/zuora-retention/zuora-retention.jar
Handler: com.gu.zuora.retention.ZuoraRetentionQueryHandler::apply
Environment:
Variables:
Stage: !Ref Stage
Role:
!GetAtt ZuoraQuerierRole.Arn
MemorySize: 1536
Runtime: java21
Timeout: 300
Architectures:
- arm64
DependsOn:
- ZuoraQuerierRole
ZuoraRetentionJobResult:
Type: AWS::Lambda::Function
Properties:
Description: fetch job results from zuora
FunctionName:
!Sub zuora-retention-jobResult-${Stage}
Code:
S3Bucket: support-service-lambdas-dist
S3Key: !Sub membership/${Stage}/zuora-retention/zuora-retention.jar
Handler: com.gu.zuora.reports.handlers.FetchResultsHandler::apply
Environment:
Variables:
Stage: !Ref Stage
Role:
!GetAtt ZuoraResultsRole.Arn
MemorySize: 1536
Runtime: java21
Timeout: 300
Architectures:
- arm64
DependsOn:
- ZuoraResultsRole
ZuoraRetentionFileFetcher:
Type: AWS::Lambda::Function
Properties:
Description: fetches report files and saves them to s3
FunctionName:
!Sub zuora-retention-fileFetcher-${Stage}
Code:
S3Bucket: support-service-lambdas-dist
S3Key: !Sub membership/${Stage}/zuora-retention/zuora-retention.jar
Handler: com.gu.zuora.retention.ZuoraRetentionFetchFileHandler::apply
Environment:
Variables:
Stage: !Ref Stage
Role:
!GetAtt ZuoraFileFetcherRole.Arn
MemorySize: 1536
Runtime: java21
Timeout: 300
Architectures:
- arm64
DependsOn:
- ZuoraFileFetcherRole
ZuoraRetentionFilter:
Type: AWS::Lambda::Function
Properties:
Description: filters candidates using the exclusion list to get the final list of accounts to process
FunctionName:
!Sub zuora-retention-filter-${Stage}
Code:
S3Bucket: support-service-lambdas-dist
S3Key: !Sub membership/${Stage}/zuora-retention/zuora-retention.jar
Handler: com.gu.zuora.retention.filterCandidates.FilterCandidates::apply
Environment:
Variables:
Stage: !Ref Stage
Role:
!GetAtt FilterRole.Arn
MemorySize: 1536
Runtime: java21
Timeout: 300
Architectures:
- arm64
DependsOn:
- FilterRole
ZuoraRetentionAccountUpdater:
Type: AWS::Lambda::Function
Properties:
Description: sets the field 'ProcessingAdvice__c' to 'DoNotProcess' for a list of accounts coming from a csv file
FunctionName:
!Sub zuora-retention-account-updater-${Stage}
Code:
S3Bucket: support-service-lambdas-dist
S3Key: !Sub membership/${Stage}/zuora-retention/zuora-retention.jar
Handler: com.gu.zuora.retention.updateAccounts.Handler::apply
Environment:
Variables:
Stage: !Ref Stage
Role:
!GetAtt UpdaterRole.Arn
MemorySize: 1536
Runtime: java21
Timeout: 300
Architectures:
- arm64
DependsOn:
- UpdaterRole
StatesExecutionRole:
Type: 'AWS::IAM::Role'
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
Effect: Allow
Principal:
Service: !Sub 'states.${AWS::Region}.amazonaws.com'
Action: 'sts:AssumeRole'
Path: /
Policies:
- PolicyName: StatesExecutionPolicy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- 'lambda:InvokeFunction'
Resource: '*'
stateMachine:
Type: 'AWS::StepFunctions::StateMachine'
Properties:
StateMachineName: !Sub 'zuoraRetention-${Stage}'
RoleArn: !GetAtt
- StatesExecutionRole
- Arn
DefinitionString: !Sub
- |-
{
"StartAt":"QueryZuora",
"States":{
"QueryZuora":{
"Type":"Task",
"Resource":"${querierArn}",
"Next":"WaitSomeTime",
"Retry":[
{
"ErrorEquals":["States.ALL"],
"IntervalSeconds":30,
"MaxAttempts":3
}
]
},
"WaitSomeTime":{
"Type":"Wait",
"Seconds":60,
"Next":"FetchResults"
},
"FetchResults":{
"Type":"Task",
"Resource":"${fetcherArn}",
"Next":"checkResultsAvailable",
"Retry":[
{
"ErrorEquals":["States.ALL"],
"IntervalSeconds":30,
"MaxAttempts":3
}
]
},
"checkResultsAvailable":{
"Type":"Choice",
"Choices":[
{
"Variable":"$.status",
"StringEquals":"pending",
"Next":"WaitSomeTime"
}
],
"Default":"FetchFiles"
},
"FetchFiles":{
"Type":"Task",
"Resource":"${fetchFilesArn}",
"Next":"CheckRemainingFiles",
"Retry":[
{
"ErrorEquals":["States.ALL"],
"IntervalSeconds":30,
"MaxAttempts":3
}
]
},
"CheckRemainingFiles":{
"Type":"Choice",
"Choices":[
{
"Variable":"$.done",
"BooleanEquals":false,
"Next":"FetchFiles"
}
],
"Default":"Filter"
},
"Filter":{
"Type":"Task",
"Resource":"${filterArn}",
"Next":"isDryRun",
"Retry":[
{
"ErrorEquals":["States.ALL"],
"IntervalSeconds":30,
"MaxAttempts":3
}
]
}
,
"isDryRun":{
"Type":"Choice",
"Choices":[
{
"Variable":"$.dryRun",
"BooleanEquals":false,
"Next":"UpdateAccounts"
}
],
"Default":"done"
},
"UpdateAccounts":{
"Type":"Task",
"Resource":"${accountUpdaterArn}",
"Next":"checkRemainingAccounts",
"Retry":[
{
"ErrorEquals":["States.ALL"],
"IntervalSeconds":30,
"MaxAttempts":3
}
]
},
"checkRemainingAccounts": {
"Type":"Choice",
"Choices":[
{
"Variable":"$.done",
"BooleanEquals":false,
"Next":"UpdateAccounts"
}
],
"Default":"done"
},
"done": {
"Type": "Pass",
"End": true
}
}
}
- {
querierArn: !GetAtt [ ZuoraRetentionQuerier, Arn ],
fetcherArn: !GetAtt [ ZuoraRetentionJobResult, Arn ],
fetchFilesArn: !GetAtt [ ZuoraRetentionFileFetcher, Arn ],
filterArn: !GetAtt [ ZuoraRetentionFilter, Arn ],
accountUpdaterArn: !GetAtt [ ZuoraRetentionAccountUpdater, Arn ]
}
ScheduleRule:
Type: "AWS::Events::Rule"
Properties:
Description: "Trigger the Zuora Retention state machine every day at 03:00 GMT"
ScheduleExpression: "cron(0 3 ? * * *)"
State: "ENABLED"
Targets:
-
Arn: !Ref stateMachine
Id: !Sub 'trigger_zuoraRetention-${Stage}'
Input: |
{
"dryRun": false
}
RoleArn: !GetAtt [ StateMachineTriggerRole, Arn ]