AWSTemplateFormatVersion: 2010-09-09
Description: Check Point CloudGuard Dome9 unified onboarding
Metadata:
  Version: 5.36.4
Parameters:
  OnboardingId:
    Description: The id of the onboarding process
    Type: String
  ApiBaseUrl:
    Description: The base url of the CloudGuard web API
    Type: String
  CloudGuardApiKeyId:
    Description: The CloudGuard service account API Key Id
    Type: String
  CloudGuardApiKeySecret:
    Description: The CloudGuard service account API Key secret
    Type: String
  Version:
    Description: The CloudGuard onboarding version
    Type: String
  EnableRemoteStackModify:
    Description: Whether CloudGuard have permissions to update or delete the stack
    Type: String
    Default: true
    AllowedValues:
      - true
      - false
  UniqueSuffix:
    Description: An optional suffix for all resources
    Type: String
    Default: ''
    MaxLength: 19
  DeleteInnerResources:
    Description: Whether to delete Lambda inner resources
    Type: String
    Default: false
    AllowedValues:
      - true
      - false
  UseAwsReadOnlyPolicy:
    Description: >-
      When enabled, CloudGuard uses the AWS ReadOnlyAccess policy that grants
      CloudGuard permissions to support new services in the future
    Type: String
    AllowedValues:
      - Enable
      - Disable
    Default: Enable
Conditions:
  RemoteStackModifyEnabled: !Equals 
    - !Ref EnableRemoteStackModify
    - true
  DeleteEvent: !Equals 
    - !Ref DeleteInnerResources
    - true
  UseReadOnlyPolicy: !Equals 
    - !Ref UseAwsReadOnlyPolicy
    - Enable
Resources:
  CloudGuardOnboardingStackModifyCrossAccountUser:
    Type: AWS::IAM::User
    Condition: RemoteStackModifyEnabled
    Properties:
      UserName: !Sub CloudGuard-Onboarding-StackModify-user${UniqueSuffix}
      Policies:
        - PolicyName: !Sub CloudGuard-Lambda-StackModify-policy${UniqueSuffix}
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Sid: DeleteUserPolicy
                Effect: Allow
                Action:
                  - iam:GetUser
                  - iam:DeleteUserPolicy
                  - iam:DeleteUser
                  - iam:DeleteAccessKey
                  - iam:ListAccessKeys
                  - iam:PutUserPolicy
                Resource: !Sub >-
                  arn:${AWS::Partition}:iam::${AWS::AccountId}:user/CloudGuard-Onboarding-StackModify-user${UniqueSuffix}
              - Sid: DeleteSecret
                Effect: Allow
                Action:
                  - secretsmanager:DeleteSecret
                Resource: !Sub >-
                  arn:${AWS::Partition}:secretsmanager:*:*:secret:CloudGuardStackModifyCrossAccountUserCredentials*
              - Sid: ModifyStack
                Effect: Allow
                Action:
                  - cloudformation:DescribeStacks
                  - cloudformation:UpdateStack
                  - cloudformation:DeleteStack
                Resource: !Ref AWS::StackId
              - Sid: ModifyFunction
                Effect: Allow
                Action:
                  - lambda:UpdateFunctionCode
                  - lambda:InvokeFunction
                  - lambda:DeleteFunction
                  - lambda:RemovePermission
                  - lambda:GetFunction
                  - lambda:CreateFunction
                  - lambda:RemovePermission
                  - lambda:AddPermission
                  - lambda:UpdateFunctionConfiguration
                Resource:
                  - !Sub >-
                    arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:CloudGuardOnboardingOrchestrator*
              - Sid: ModifyRole
                Effect: Allow
                Action:
                  - iam:GetRole
                  - iam:DeleteRole
                  - iam:DetachRolePolicy
                  - iam:DeleteRolePolicy
                  - iam:PutRolePolicy
                  - iam:PassRole
                Resource:
                  - !Sub >-
                    arn:${AWS::Partition}:iam::${AWS::AccountId}:role/CloudGuard-Onboarding-Orchestrator-role${UniqueSuffix}
                  - !Sub >-
                    arn:${AWS::Partition}:iam::${AWS::AccountId}:role/CloudGuard-Onboarding-Orchestrator-helper-role${UniqueSuffix}
              - Sid: GetLambdaCode
                Effect: Allow
                Action:
                  - s3:GetObject
                Resource: !Sub arn:${AWS::Partition}:s3:::cloudguard-unified-onboarding*
              - Sid: ModifySns
                Effect: Allow
                Action:
                  - SNS:DeleteTopic
                  - SNS:Unsubscribe
                  - SNS:SetTopicAttributes
                  - SNS:GetTopicAttributes
                  - SNS:Subscribe
                  - SNS:Publish
                Resource: !Sub >-
                  arn:${AWS::Partition}:sns:${AWS::Region}:${AWS::AccountId}:CloudGuardOnboardingOrchestrator${UniqueSuffix}
  StackModifyCrossAccountUserCredentials:
    Type: AWS::IAM::AccessKey
    Condition: RemoteStackModifyEnabled
    Properties:
      Status: Active
      UserName: !Ref CloudGuardOnboardingStackModifyCrossAccountUser
  CloudGuardOnboardingStackModifyPermissions:
    Type: AWS::SecretsManager::Secret
    Condition: RemoteStackModifyEnabled
    Properties:
      Name: CloudGuardStackModifyCrossAccountUserCredentials
      SecretString: !Sub >-
        {"ACCESS_KEY":"${StackModifyCrossAccountUserCredentials}","SECRET_KEY":"${StackModifyCrossAccountUserCredentials.SecretAccessKey}"}
  CloudGuardOnboardingSns:
    Type: AWS::SNS::Topic
    Properties:
      DisplayName: !Sub CloudGuardOnboardingOrchestrator${UniqueSuffix}
      TopicName: !Sub CloudGuardOnboardingOrchestrator${UniqueSuffix}
      Tags:
        - Key: ConditionalDependsOn
          Value: !If 
            - RemoteStackModifyEnabled
            - !Ref CloudGuardOnboardingStackModifyPermissions
            - Ignored
  CloudGuardOnboardingSnsPolicy:
    Type: AWS::SNS::TopicPolicy
    Properties:
      PolicyDocument:
        Id: !Sub CloudGuardOnboardingOrchestratorSnsPolicy
        Version: 2012-10-17
        Statement:
          - Sid: AllowCFTInvokeSNS
            Effect: Allow
            Principal:
              Service: cloudformation.amazonaws.com
            Action: sns:Publish
            Resource: !Ref CloudGuardOnboardingSns
            Condition:
              ArnEquals:
                aws:SourceArn: !Ref AWS::StackId
      Topics:
        - !Ref CloudGuardOnboardingSns
  CloudGuardOrchestratorRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub CloudGuard-Onboarding-Orchestrator-role${UniqueSuffix}
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - sts:AssumeRole
      Policies:
        - PolicyName: !Sub CloudGuard-Onboarding-Orchestrator-policy${UniqueSuffix}
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Sid: CloudGuardOnboardingOrchestratorCloudformation
                Action:
                  - cloudformation:CreateStack
                  - cloudformation:DescribeStacks
                  - cloudformation:DeleteStack
                  - cloudformation:CreateChangeSet
                  - cloudformation:ExecuteChangeSet
                  - cloudformation:DeleteChangeSet
                  - cloudformation:DescribeChangeSet
                Effect: Allow
                Resource:
                  - !Sub >-
                    arn:${AWS::Partition}:cloudformation:*:${AWS::AccountId}:stack/CloudGuard-Onboarding*
              - Sid: CloudGuardOnboardingOrchestratorCloudformationList
                Action:
                  - cloudformation:ListStacks
                Effect: Allow
                Resource: !Sub >-
                  arn:${AWS::Partition}:cloudformation:*:${AWS::AccountId}:stack/*/*
              - Sid: CloudGuardOnboardingOrchestratorIamListAccount
                Action:
                  - iam:ListAccountAliases
                Effect: Allow
                Resource: '*'
              - Sid: CloudGuardOnboardingOrchestratorSelfDistruction
                Action:
                  - lambda:DeleteFunction
                Effect: Allow
                Resource: !Join 
                  - '-'
                  - - !Sub >-
                      arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:CloudGuardOnboardingOrchestrator
                    - !If 
                      - DeleteEvent
                      - Delete
                      - ''
                    - !Select 
                      - 3
                      - !Split 
                        - '-'
                        - !Ref CloudGuardApiKeyId
              - Sid: >-
                  CloudGuardOnboardingOrchestratorSelfDistructionDeleteSubscription
                Action:
                  - SNS:Unsubscribe
                Effect: Allow
                Resource: !Ref CloudGuardOnboardingSns
              - Sid: GetTemplate
                Effect: Allow
                Action:
                  - s3:GetObject
                Resource: !Sub >-
                  arn:${AWS::Partition}:s3:::cloudguard-unified-onboarding-${AWS::Region}/*
              - Sid: CloudGuardOnboardingOrchestratorIamPolicy
                Action:
                  - iam:GetPolicy
                  - iam:CreatePolicy
                  - iam:DeletePolicy
                  - iam:ListPolicyVersions
                  - iam:CreatePolicyVersion
                  - iam:DeletePolicyVersion
                Effect: Allow
                Resource:
                  - !Sub >-
                    arn:${AWS::Partition}:iam::${AWS::AccountId}:policy/CloudGuard-Connect-RO-policy${UniqueSuffix}
                  - !Sub >-
                    arn:${AWS::Partition}:iam::${AWS::AccountId}:policy/CloudGuard-Connect-RO-policy-2-${UniqueSuffix}
                  - !Sub >-
                    arn:${AWS::Partition}:iam::${AWS::AccountId}:policy/CloudGuard-Connect-RW-policy${UniqueSuffix}
              - Sid: CloudGuardOnboardingOrchestratorIam
                Action:
                  - iam:GetUser
                  - iam:CreateUser
                  - iam:DeleteUser
                  - iam:PutUserPolicy
                  - iam:DetachUserPolicy
                  - iam:AttachUserPolicy
                  - iam:DeleteUserPolicy
                  - iam:getUserPolicy
                  - iam:CreateAccessKey
                  - iam:DeleteAccessKey
                  - iam:ListAccessKeys
                Effect: Allow
                Resource:
                  - !Sub >-
                    arn:${AWS::Partition}:iam::${AWS::AccountId}:user/CloudGuard-Connect-RO-user${UniqueSuffix}
                  - !Sub >-
                    arn:${AWS::Partition}:iam::${AWS::AccountId}:user/CloudGuard-Connect-RW-user${UniqueSuffix}
              - Sid: CloudGuardOnboardingOrchestratorSecretsmanagerList
                Action:
                  - secretsmanager:ListSecrets
                Effect: Allow
                Resource: '*'
              - Sid: CloudGuardOnboardingOrchestratorSecretsmanager
                Action:
                  - secretsmanager:GetSecretValue
                  - secretsmanager:CreateSecret
                  - secretsmanager:DeleteSecret
                Effect: Allow
                Resource:
                  - !Sub >-
                    arn:${AWS::Partition}:secretsmanager:${AWS::Region}:${AWS::AccountId}:secret:CloudGuardCrossAccountUserCredentials-*
                  - !Sub >-
                    arn:${AWS::Partition}:secretsmanager:${AWS::Region}:${AWS::AccountId}:secret:CloudGuardStackModifyCrossAccountUserCredentials-*
      ManagedPolicyArns:
        - !Sub >-
          arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
      Tags:
        - Key: ConditionalDependsOn
          Value: !If 
            - RemoteStackModifyEnabled
            - !Ref CloudGuardOnboardingStackModifyPermissions
            - Ignored
  CloudGuardOnboardingOrchestrator:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName: !Join 
        - '-'
        - - CloudGuardOnboardingOrchestrator
          - !If 
            - DeleteEvent
            - Delete
            - ''
          - !Select 
            - 3
            - !Split 
              - '-'
              - !Ref CloudGuardApiKeyId
      Runtime: dotnet8
      Role: !GetAtt CloudGuardOrchestratorRole.Arn
      Handler: >-
        Dome9.CloudGuardOnboarding.Orchestrator::Dome9.CloudGuardOnboarding.Orchestrator.Function::FunctionHandler
      Timeout: 900
      Code:
        S3Bucket: !Sub cloudguard-unified-onboarding-${AWS::Region}
        S3Key: !Sub ${Version}/lambda/orchestrator/publish.zip
      Description: Invoke a function during stack creation
  OrchestratorInvokePermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunction
      Principal: sns.amazonaws.com
      SourceArn: !Ref CloudGuardOnboardingSns
      FunctionName: !Ref CloudGuardOnboardingOrchestrator
  OrchestratorSubscription:
    Type: AWS::SNS::Subscription
    Properties:
      Endpoint: !GetAtt CloudGuardOnboardingOrchestrator.Arn
      Protocol: lambda
      TopicArn: !Ref CloudGuardOnboardingSns
  CloudGuardOrchestratorHelperRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub CloudGuard-Onboarding-Orchestrator-helper-role${UniqueSuffix}
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - sts:AssumeRole
      Policies:
        - PolicyName: !Sub CloudGuard-Onboarding-Orchestrator-helper-policy${UniqueSuffix}
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Sid: CreateLogGroup
                Effect: Allow
                Resource:
                  - '*'
                Action:
                  - logs:CreateLogGroup
              - Sid: LoggingLogs
                Effect: Allow
                Resource:
                  - !Sub >-
                    arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/CloudGuardOnboardingOrchestrator-Helper${UniqueSuffix}:*
                Action:
                  - logs:CreateLogStream
                  - logs:PutLogEvents
      Tags:
        - Key: ConditionalDependsOn
          Value: !If 
            - RemoteStackModifyEnabled
            - !Ref CloudGuardOnboardingStackModifyPermissions
            - Ignored
  CloudGuardOrchestratorHelper:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName: !Sub CloudGuardOnboardingOrchestrator-Helper${UniqueSuffix}
      Runtime: nodejs18.x
      Role: !GetAtt CloudGuardOrchestratorHelperRole.Arn
      Handler: index.handler
      Timeout: 300
      Code:
        S3Bucket: !Sub cloudguard-unified-onboarding-${AWS::Region}
        S3Key: !Sub ${Version}/lambda/orchestrator/helper/publish.zip
  OrchestratorHelperInvokePermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunction
      Principal: sns.amazonaws.com
      SourceArn: !Ref CloudGuardOnboardingSns
      FunctionName: !Ref CloudGuardOrchestratorHelper
  OrchestratorHelperSubscription:
    Type: AWS::SNS::Subscription
    Properties:
      Endpoint: !GetAtt CloudGuardOrchestratorHelper.Arn
      Protocol: lambda
      TopicArn: !Ref CloudGuardOnboardingSns
  CloudGuardOnboardingOrchestratorInvoke:
    Type: AWS::CloudFormation::CustomResource
    DependsOn:
      - CloudGuardOnboardingSnsPolicy
      - OrchestratorInvokePermission
      - OrchestratorSubscription
      - OrchestratorHelperInvokePermission
      - OrchestratorHelperSubscription
    Properties:
      ServiceToken: !Ref CloudGuardOnboardingSns
      OnboardingId: !Ref OnboardingId
      ApiBaseUrl: !Ref ApiBaseUrl
      CloudGuardApiKeyId: !Ref CloudGuardApiKeyId
      CloudGuardApiKeySecret: !Ref CloudGuardApiKeySecret
      AwsAccountId: !Ref AWS::AccountId
      AwsPartition: !Ref AWS::Partition
      S3BucketName: !Sub cloudguard-unified-onboarding-${AWS::Region}
      AwsAccountRegion: !Ref AWS::Region
      EnableRemoteStackModify: !Ref EnableRemoteStackModify
      RootStackId: !Ref AWS::StackId
      Version: !Ref Version
      UniqueSuffix: !Ref UniqueSuffix
      Self: !GetAtt CloudGuardOnboardingOrchestrator.Arn
      Subscription: !Ref OrchestratorSubscription
      DeleteInnerResources: !Ref DeleteInnerResources
      UseAwsReadOnlyPolicy: !Ref UseAwsReadOnlyPolicy
      OnboardingType: User
