AWSTemplateFormatVersion: "2010-09-09"
Description: Lambda to call a CloudFront invalidation/refresh
Parameters:
  LambdaRuntime:
    Description: Runtime version for NodeJS
    Type: String
    Default: python3.8
Resources:
  LambdaLogGroup:
    Type: AWS::Logs::LogGroup
    Properties: 
      LogGroupName: CloudFrontInvalidate
      RetentionInDays: 30
  LambdaExecutePolicy:
    Type: AWS::IAM::ManagedPolicy
    Properties:
      Description: "Lambda@Edge ExecutePolicy for prefix/folder redirection"
      Path: "/"
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          -
            Effect: "Allow"         
            Action: "logs:CreateLogGroup"
            Resource: !Join
              - ""
              - - "arn:aws:logs:*:"
                - !Ref "AWS::AccountId"
                - ":*"
          -
            Effect: "Allow"
            Action: 
              - "logs:CreateLogStream"
              - "logs:PutLogEvents"
            Resource: !Join
              - ""
              - - !GetAtt LambdaLogGroup.Arn
                - ":*"
  LambdaRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
        - Effect: "Allow"
          Principal: 
            Service:
            - edgelambda.amazonaws.com
            - lambda.amazonaws.com
          Action: "sts:AssumeRole"
      Path: "/"
      ManagedPolicyArns:
          - !Ref LambdaExecutePolicy
  LambdaCode:
    Type: AWS::Lambda::Function
    Properties: 
      Code:
        ZipFile: |
            import json
            import boto3
            from datetime import datetime
            def handler(event, context):
                client_cf = boto3.client('cloudfront')
                client_cp = boto3.client('codepipeline')
                id = event["CodePipeline.job"]["data"]["actionConfiguration"]["configuration"]["UserParameters"]
                if id is None:
                    print("Missing DistributionId in event invokation")
                    return {
                        'statusCode': 500,
                        'body': json.dumps("Missing DistributionId in event invokation")
                    }
                ref = datetime.utcnow().isoformat()
                print("Invalidate {}".format(id))
                response_cf = client_cf.create_invalidation(
                    DistributionId=id,
                    InvalidationBatch={
                        'Paths': {
                            'Quantity': 1,
                            'Items': [
                                '/*',
                            ]
                        },
                        'CallerReference': ref
                    }
                )
                response_cp = client_cp.put_job_success_result(
                    jobId=event["CodePipeline.job"][ "id"]
                )
                return {
                    'statusCode': 200,
                    'body': json.dumps("OK")
                }
      Description: Invalidate a Cloudfront distribution
      FunctionName: !Join
        - '-'
        - - !Ref 'AWS::StackName'
          - "CloudFrontInvalidate"
      Handler: index.handler
      MemorySize: 128
      Role: !GetAtt LambdaRole.Arn
      Runtime: !Ref LambdaRuntime
      Timeout: 1
  LambdaCodeVersionPublish: 
    Type: AWS::Lambda::Version
    Properties: 
      FunctionName: !Ref LambdaCode
      Description: "A version of Default document handler"     
Outputs:
  FunctionARN:
    Description: ARN of the Function to invalidate a CloudFront Distribution
    Value: !Ref LambdaCodeVersionPublish