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
