#Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
#SPDX-License-Identifier: MIT-0
#
#Permission is hereby granted, free of charge, to any person obtaining a copy of this
#software and associated documentation files (the "Software"), to deal in the Software
#without restriction, including without limitation the rights to use, copy, modify,
#merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
#permit persons to whom the Software is furnished to do so.
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
#INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
#PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
#HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
#OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
#SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

AWSTemplateFormatVersion: '2010-09-09'
Description: >
  Deploys resources to create support cases for enterprise support on CT Lifecycle Events

Metadata:
  'AWS::CloudFormation::Interface':
    ParameterGroups:
      - Label:
          default: 'Resource Options'
        Parameters:
          - pSnsTopicName
          - pS3Bucket
          - pObjectKey
          - pAssumeRoleName
          - pRegionList
      - Label:
          default: 'Service Quotas Information'
        Parameters:
          - pServiceCode
          - pQuotasCode
          - pDesiredLimit

    ParameterLabels:
      pSnsTopicName:
        default: SNS Topic Name
      pS3Bucket:
        default: S3 Bucket
      pObjectKey:
        default: Lambda Package S3 Key
      pAssumeRoleName:
        default: IAM Role to Assume in Child Account
      pRegionList:
        default: Region List to Deploy to
      pServiceCode:
        default: Service Quotas Service Code
      pQuotasCode:
        default: Service Quotas Code
      pDesiredLimit:
        default: Service Quotas Desired Limit
    
Parameters:
  
  pSnsTopicName:
    Type: String
    Default: control-tower-lifecycle-event-quotas

  pS3Bucket:
    Type: String
    Description: S3 bucket where lambda package is stored
    Default: marketplace-sa-resources-ct

  pObjectKey:
    Type: String
    Default: ct-blogs-content/service_quota_request.py.zip

  pAssumeRoleName:
    Type: String
    Default: AWSControlTowerExecution

  pRegionList:
    Type: CommaDelimitedList
    Default: 'us-east-1,us-east-2'

  pServiceCode:
    Type: String

  pQuotasCode:
    Type: String

  pDesiredLimit:
    Type: Number



Resources:

# Cloudwatch Event Rule for Lifecycle Event (LE): triggered by LE events and send events to SNS
  rControlTowerLifecycleEventRule:
    Type: AWS::Events::Rule
    Properties:
      Description: Custom Control Tower - Rule for lifecycle events from Control Tower Service 
      EventPattern:
        {
          "detail-type": [
            "AWS Service Event via CloudTrail"
          ],
          "source": [
              "aws.controltower"
          ],
          "detail": {
              "eventName": [
                  "CreateManagedAccount"
              ],
              "serviceEventDetails": {
                "createManagedAccountStatus": {
                  "state": [
                    "SUCCEEDED"
                  ]
                }
              }
          }
        }
      State: ENABLED
      Targets:
        - Arn: !Ref rControlTowerLifecycleNotificationSns
          Id: "Control_Tower_Lifecycle_Event"

  rControlTowerLifecycleNotificationSns:
    Type: AWS::SNS::Topic
    Properties:
      TopicName: !Sub '${pSnsTopicName}-${AWS::AccountId}-${AWS::Region}'

  rControlTowerSnsAccessPolicy:
    Type: AWS::SNS::TopicPolicy
    Properties: 
      PolicyDocument:
        Statement:
          - Sid: __default_statement_ID
            Effect: Allow
            Principal:
              AWS: !Ref AWS::AccountId
            Action:
            - SNS:GetTopicAttributes
            - SNS:SetTopicAttributes
            - SNS:AddPermission
            - SNS:RemovePermission
            - SNS:DeleteTopic
            - SNS:Subscribe
            - SNS:ListSubscriptionsByTopic
            - SNS:Publish
            - SNS:Receive
            Resource: !Ref rControlTowerLifecycleNotificationSns
            Condition:
              StringEquals:
                AWS:SourceOwner: !Ref AWS::AccountId
          - Sid: CloudWatchSnsPublish
            Effect: Allow
            Principal:
              Service: events.amazonaws.com
            Action: sns:Publish
            Resource: !Ref rControlTowerLifecycleNotificationSns
      Topics: 
        - !Ref rControlTowerLifecycleNotificationSns

  rLambdaExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      # RoleName: lambda_basic_execution
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
        - Effect: Allow
          Principal:
            Service:
            - lambda.amazonaws.com
          Action:
          - sts:AssumeRole
      Path: "/"
      # ManagedPolicyArns:
      #   - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
      Policies:
        - PolicyName: ServiceQuotasLambdaPolicy
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Sid: LambdaLogging
                Effect: Allow
                Action:
                  - logs:CreateLogGroup
                  - logs:CreateLogStream
                  - logs:PutLogEvents
                Resource: "*"
              - Sid: RoleGet
                Effect: Allow
                Action:
                  - 'iam:GetRole'
                Resource: '*'
              - Sid: RoleAssume
                Effect: Allow
                Action:
                  - 'sts:AssumeRole'
                Resource: !Sub 'arn:aws:iam::*:role/${pAssumeRoleName}'

  rQuotaIncreaseLambda: 
    Type: "AWS::Lambda::Function"
    Properties: 
      Handler: "service_quota_request.lambda_handler"
      FunctionName: Quota-Increase-Request
      Role: !GetAtt rLambdaExecutionRole.Arn
      Code: 
        S3Bucket: !Sub ${pS3Bucket}-${AWS::Region}
        S3Key: !Ref pObjectKey
      Runtime: python3.8
      Timeout: 300
      Environment:
        Variables:
          ServiceCode: !Ref pServiceCode
          QuotasCode: !Ref pQuotasCode
          DesiredLimit: !Ref pDesiredLimit
          RoleName: !Ref pAssumeRoleName
          Regions: !Join
            - ','
            - !Ref pRegionList

  rLifecycleSnsSubscription:
    Type: AWS::SNS::Subscription
    Properties: 
      Endpoint: !GetAtt rQuotaIncreaseLambda.Arn
      Protocol: lambda
      TopicArn: !Ref rControlTowerLifecycleNotificationSns

  rSnsLambdaInvokePermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: 'lambda:InvokeFunction'
      FunctionName: !Ref rQuotaIncreaseLambda
      Principal: sns.amazonaws.com


Outputs:

  oControlTowerLifecycleNotificationSns:
    Description: Target SNS topic for Cloudwatch Event generated on CT account creation succeeding
    Value: !Ref rControlTowerLifecycleNotificationSns
    Export:
      Name: ControlTower-Lifecycle-Quotas-Sns

  oLambdaArn:
    Description: The Arn value of the CT Service Quota Increase Function
    Value: !GetAtt rQuotaIncreaseLambda.Arn
    Export:
      Name: Quota-Increase-Lambda
