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 ]