---
## Amazon DocumentDB Sagemaker Canvas Integration
## Creates VPC and Networking components, DocumentDB Cluster, Sagemaker Domain and Required Components
##
## Changelog:
##
## Dependencies: TBD
##
## This sample code is made available under the MIT-0 license. See the LICENSE file.

AWSTemplateFormatVersion: "2010-09-09"
Description: Amazon DocumentDB Sagemaker Canvas Integration

## Parameters
Parameters:
  TemplateName:
    Type: String
    Description: Name used for different elements created.
  DocDBSGName:
    Type: String
    Description: DocumentDB Security Group Name
    Default : "Doc-DB-SG"
  DocDBUser:
    Description: Default user for DocumentDB
    Type: String
    Default: labuser
  DocDBPassword:
    Description: Password for DocumentDB Cluster
    Type: String
    MinLength: 8
    NoEcho: true
    AllowedPattern: "[a-zA-Z0-9]{8,}"

## Mappings
Mappings:
  NetworkSettings:
    global:
      vpcCidr: 10.0.0.0/20

## Resources
Resources:
## The VPC
  MainVPC:
    Type: AWS::EC2::VPC
    Properties:
      EnableDnsSupport: true
      EnableDnsHostnames: true
      InstanceTenancy: default
      CidrBlock: !FindInMap [ NetworkSettings, global, vpcCidr ]
      Tags:
        - Key: Name
          Value:  !Sub ${TemplateName}-VPC
  PrivateSubnetA:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref MainVPC
      CidrBlock: !Select [ 0, !Cidr [ !GetAtt MainVPC.CidrBlock, 6, 5]]
      AvailabilityZone: !Select [ 0, !GetAZs ]    # Get the first AZ in the list
      Tags:
      - Key: Name
        Value: !Sub ${TemplateName}-PrivateA
  PrivateSubnetB:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref MainVPC
      CidrBlock: !Select [ 1, !Cidr [ !GetAtt MainVPC.CidrBlock, 6, 5]]
      AvailabilityZone: !Select [ 1, !GetAZs ]    # Get the second AZ in the list
      Tags:
      - Key: Name
        Value: !Sub ${TemplateName}-PrivateB
  PrivateSubnetC:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref MainVPC
      CidrBlock: !Select [ 2, !Cidr [ !GetAtt MainVPC.CidrBlock, 6, 5]]
      AvailabilityZone: !Select [ 2, !GetAZs ]    # Get the third AZ in the list
      Tags:
      - Key: Name
        Value: !Sub ${TemplateName}-PrivateC
# Here is a private route table:
  PrivateRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref MainVPC
      Tags:
      - Key: Name
        Value: !Sub ${TemplateName}-private-rtb
  PrivateSubnetARouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnetA
      RouteTableId: !Ref PrivateRouteTable
  PrivateSubnetBRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnetB
      RouteTableId: !Ref PrivateRouteTable
  PrivateSubnetCRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnetC
      RouteTableId: !Ref PrivateRouteTable
  SGforDocDB:
    Type: AWS::EC2::SecurityGroup
    Properties:
        GroupName: !Ref DocDBSGName
        GroupDescription: Allow http to client host
        VpcId: !Ref MainVPC
        SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0
        - IpProtocol: tcp
          FromPort: 27017
          ToPort: 27017
          CidrIp: !Select [ 3, !Cidr [ !GetAtt MainVPC.CidrBlock, 6, 5]]
        SecurityGroupEgress:
        - IpProtocol: tcp
          FromPort: 0
          ToPort: 65535
          CidrIp: 0.0.0.0/0
  DOCDBSGIngress:
    Type: 'AWS::EC2::SecurityGroupIngress'
    DependsOn: SGforDocDB
    Properties:
      GroupId: !Ref SGforDocDB
      IpProtocol: tcp
      FromPort: 0
      ToPort: 65535
      SourceSecurityGroupId: !Ref SGforDocDB
  DocDBInstance1:
    DependsOn: DocDBCluster
    Type: AWS::DocDB::DBInstance
    Properties:
      DBClusterIdentifier: !Ref DocDBCluster
      DBInstanceClass: db.r5.large
      DBInstanceIdentifier: documentdb-sagemaker
  DocDBCluster:
    DependsOn: 
      - DocDBSubnetGroup
      - MainVPC
    Type: AWS::DocDB::DBCluster
    Properties:
        BackupRetentionPeriod : 7
        DBClusterIdentifier : documentdb-sagemaker
        DBSubnetGroupName : !Ref DocDBSubnetGroup
        MasterUsername : !Ref DocDBUser
        MasterUserPassword : !Ref DocDBPassword
        Port : 27017
        PreferredBackupWindow : 01:00-02:00
        PreferredMaintenanceWindow : sat:03:30-sat:05:00
        DeletionProtection: false
        VpcSecurityGroupIds:
          - !GetAtt SGforDocDB.GroupId
  DocDBSubnetGroup:
    Type: AWS::DocDB::DBSubnetGroup
    Properties:
      DBSubnetGroupName: 'docdb-subnet-group'
      DBSubnetGroupDescription: 'Subnet Group for DocumentDB'
      SubnetIds: 
        - !Ref PrivateSubnetA
        - !Ref PrivateSubnetB
        - !Ref PrivateSubnetC
  
  SecretsManagerVPCEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties: 
      PrivateDnsEnabled: true
      ServiceName: !Sub com.amazonaws.${AWS::Region}.secretsmanager
      SubnetIds: 
        - !Ref PrivateSubnetA
        - !Ref PrivateSubnetB
        - !Ref PrivateSubnetC
      VpcEndpointType: Interface
      VpcId: !Ref MainVPC
      SecurityGroupIds:
        - !Ref SGforDocDB
  AthenaVPCEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties: 
      PrivateDnsEnabled: true
      ServiceName: !Sub com.amazonaws.${AWS::Region}.athena
      SubnetIds: 
        - !Ref PrivateSubnetA
        - !Ref PrivateSubnetB
        - !Ref PrivateSubnetC
      VpcEndpointType: Interface
      VpcId: !Ref MainVPC
      SecurityGroupIds:
        - !Ref SGforDocDB
  SagemakerApiVPCEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties: 
      PrivateDnsEnabled: true
      ServiceName: !Sub com.amazonaws.${AWS::Region}.sagemaker.api
      SubnetIds: 
        - !Ref PrivateSubnetA
        - !Ref PrivateSubnetB
        - !Ref PrivateSubnetC
      VpcEndpointType: Interface
      VpcId: !Ref MainVPC
      SecurityGroupIds:
        - !Ref SGforDocDB
  SagemakerRuntimeVPCEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties: 
      PrivateDnsEnabled: true
      ServiceName: !Sub com.amazonaws.${AWS::Region}.sagemaker.runtime
      SubnetIds: 
        - !Ref PrivateSubnetA
        - !Ref PrivateSubnetB
        - !Ref PrivateSubnetC
      VpcEndpointType: Interface
      VpcId: !Ref MainVPC
      SecurityGroupIds:
        - !Ref SGforDocDB
  SagemakerNotebookVPCEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties: 
      PrivateDnsEnabled: true
      ServiceName: !Sub aws.sagemaker.${AWS::Region}.notebook
      SubnetIds: 
        - !Ref PrivateSubnetA
        - !Ref PrivateSubnetB
        - !Ref PrivateSubnetC
      VpcEndpointType: Interface
      VpcId: !Ref MainVPC
      SecurityGroupIds:
        - !Ref SGforDocDB
  STSVPCEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties: 
      PrivateDnsEnabled: true
      ServiceName: !Sub com.amazonaws.${AWS::Region}.sts
      SubnetIds: 
        - !Ref PrivateSubnetA
        - !Ref PrivateSubnetB
        - !Ref PrivateSubnetC
      VpcEndpointType: Interface
      VpcId: !Ref MainVPC
      SecurityGroupIds:
        - !Ref SGforDocDB
  EcrApiVPCEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties: 
      PrivateDnsEnabled: true
      ServiceName: !Sub com.amazonaws.${AWS::Region}.ecr.api
      SubnetIds: 
        - !Ref PrivateSubnetA
        - !Ref PrivateSubnetB
        - !Ref PrivateSubnetC
      VpcEndpointType: Interface
      VpcId: !Ref MainVPC
      SecurityGroupIds:
        - !Ref SGforDocDB
  EcrDkrVPCEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties: 
      PrivateDnsEnabled: true
      ServiceName: !Sub com.amazonaws.${AWS::Region}.ecr.dkr
      SubnetIds: 
        - !Ref PrivateSubnetA
        - !Ref PrivateSubnetB
        - !Ref PrivateSubnetC
      VpcEndpointType: Interface
      VpcId: !Ref MainVPC
      SecurityGroupIds:
        - !Ref SGforDocDB
  EC2VPCEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties: 
      PrivateDnsEnabled: true
      ServiceName: !Sub com.amazonaws.${AWS::Region}.ec2
      SubnetIds: 
        - !Ref PrivateSubnetA
        - !Ref PrivateSubnetB
        - !Ref PrivateSubnetC
      VpcEndpointType: Interface
      VpcId: !Ref MainVPC
      SecurityGroupIds:
        - !Ref SGforDocDB
  S3VPCEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties: 
      ServiceName: !Sub com.amazonaws.${AWS::Region}.s3
      VpcEndpointType: Gateway
      VpcId: !Ref MainVPC
      RouteTableIds:
        - !Ref PrivateRouteTable
  RedshiftDataVPCEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties: 
      PrivateDnsEnabled: true
      ServiceName: !Sub com.amazonaws.${AWS::Region}.redshift-data
      SubnetIds: 
        - !Ref PrivateSubnetA
        - !Ref PrivateSubnetB
        - !Ref PrivateSubnetC
      VpcEndpointType: Interface
      VpcId: !Ref MainVPC
      SecurityGroupIds:
        - !Ref SGforDocDB
  SSMEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties: 
      PrivateDnsEnabled: true
      ServiceName: !Sub com.amazonaws.${AWS::Region}.ssm
      SubnetIds: 
        - !Ref PrivateSubnetA
        - !Ref PrivateSubnetB
        - !Ref PrivateSubnetC
      VpcEndpointType: Interface
      VpcId: !Ref MainVPC
      SecurityGroupIds:
        - !Ref SGforDocDB
  MonitoringEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties: 
      PrivateDnsEnabled: true
      ServiceName: !Sub com.amazonaws.${AWS::Region}.monitoring
      SubnetIds: 
        - !Ref PrivateSubnetA
        - !Ref PrivateSubnetB
        - !Ref PrivateSubnetC
      VpcEndpointType: Interface
      VpcId: !Ref MainVPC
      SecurityGroupIds:
        - !Ref SGforDocDB
  LogsVPCEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties: 
      PrivateDnsEnabled: true
      ServiceName: !Sub com.amazonaws.${AWS::Region}.logs
      SubnetIds: 
        - !Ref PrivateSubnetA
        - !Ref PrivateSubnetB
        - !Ref PrivateSubnetC
      VpcEndpointType: Interface
      VpcId: !Ref MainVPC
      SecurityGroupIds:
        - !Ref SGforDocDB
  ForecastVPCEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties: 
      PrivateDnsEnabled: true
      ServiceName: !Sub com.amazonaws.${AWS::Region}.forecast
      SubnetIds: 
        - !Ref PrivateSubnetA
        - !Ref PrivateSubnetB
        - !Ref PrivateSubnetC
      VpcEndpointType: Interface
      VpcId: !Ref MainVPC
      SecurityGroupIds:
        - !Ref SGforDocDB
  ForecastQueryEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties: 
      PrivateDnsEnabled: true
      ServiceName: !Sub com.amazonaws.${AWS::Region}.forecastquery
      SubnetIds: 
        - !Ref PrivateSubnetA
        - !Ref PrivateSubnetB
        - !Ref PrivateSubnetC
      VpcEndpointType: Interface
      VpcId: !Ref MainVPC
      SecurityGroupIds:
        - !Ref SGforDocDB
  GlueVPCEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties: 
      PrivateDnsEnabled: true
      ServiceName: !Sub com.amazonaws.${AWS::Region}.glue
      SubnetIds: 
        - !Ref PrivateSubnetA
        - !Ref PrivateSubnetB
        - !Ref PrivateSubnetC
      VpcEndpointType: Interface
      VpcId: !Ref MainVPC
      SecurityGroupIds:
        - !Ref SGforDocDB
  ApplicationAutoscalingVPCEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties: 
      PrivateDnsEnabled: true
      ServiceName: !Sub com.amazonaws.${AWS::Region}.application-autoscaling
      SubnetIds: 
        - !Ref PrivateSubnetA
        - !Ref PrivateSubnetB
        - !Ref PrivateSubnetC
      VpcEndpointType: Interface
      VpcId: !Ref MainVPC
      SecurityGroupIds:
        - !Ref SGforDocDB
  RDSVPCEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties: 
      PrivateDnsEnabled: true
      ServiceName: !Sub com.amazonaws.${AWS::Region}.rds
      SubnetIds: 
        - !Ref PrivateSubnetA
        - !Ref PrivateSubnetB
        - !Ref PrivateSubnetC
      VpcEndpointType: Interface
      VpcId: !Ref MainVPC
      SecurityGroupIds:
        - !Ref SGforDocDB
  BedrockRuntimeVPCEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties: 
      PrivateDnsEnabled: true
      ServiceName: !Sub com.amazonaws.${AWS::Region}.bedrock-runtime
      SubnetIds: 
        - !Ref PrivateSubnetA
        - !Ref PrivateSubnetB
        - !Ref PrivateSubnetC
      VpcEndpointType: Interface
      VpcId: !Ref MainVPC
      SecurityGroupIds:
        - !Ref SGforDocDB
  KendraVPCEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties: 
      PrivateDnsEnabled: true
      ServiceName: !Sub com.amazonaws.${AWS::Region}.kendra
      SubnetIds: 
        - !Ref PrivateSubnetA
        - !Ref PrivateSubnetB
        - !Ref PrivateSubnetC
      VpcEndpointType: Interface
      VpcId: !Ref MainVPC
      SecurityGroupIds:
        - !Ref SGforDocDB
  SageMakerRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub ${TemplateName}-SagemakerFullAccessRole
      Description: Role for Sagemaker Canvas and DocumentDB
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonSageMakerCanvasAIServicesAccess
        - arn:aws:iam::aws:policy/AmazonSageMakerCanvasFullAccess
        - arn:aws:iam::aws:policy/AmazonSageMakerFullAccess
        - !Ref SagemakerPolicy
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
        - Effect: Allow
          Principal:
            Service: 
            - sagemaker.amazonaws.com
          Action:
          - 'sts:AssumeRole'
  SagemakerPolicy:
    Type: AWS::IAM::ManagedPolicy
    Properties:
      ManagedPolicyName: SagemakerVPCEPolicy
      Description: Managed policy for Sagemaker access to VPC endpoint
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Action:
              - 'ec2:DescribeVpcEndpointServices'
            Resource: '*'
  SageMakerDomain:
    Type: AWS::SageMaker::Domain
    Properties:
      AppNetworkAccessType: VpcOnly
      AppSecurityGroupManagement: Customer
      AuthMode: IAM
      DefaultUserSettings: 
        ExecutionRole: !GetAtt SageMakerRole.Arn
        SecurityGroups:
          - !Ref SGforDocDB
      DomainName: DocumentDBSagemakerDomain
      SubnetIds: 
        - !Ref PrivateSubnetA
        - !Ref PrivateSubnetB
        - !Ref PrivateSubnetC
      VpcId: !Ref MainVPC
  SageMakerUser:
    Type: AWS::SageMaker::UserProfile
    Properties:
      DomainId: !Ref SageMakerDomain
      UserProfileName: SagemakerUserProfile
      UserSettings: 
        ExecutionRole: !GetAtt SageMakerRole.Arn
  
  PublicSubnetA:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref MainVPC
      CidrBlock: !Select [ 3, !Cidr [ !GetAtt MainVPC.CidrBlock, 6, 5]]
      AvailabilityZone: !Select [ 0, !GetAZs ]    # Get the first AZ in the list
      MapPublicIpOnLaunch: true
      Tags:
      - Key: Name
        Value: !Sub ${TemplateName}-PublicA
  InternetGateway:
    Type: AWS::EC2::InternetGateway
    DependsOn: MainVPC
    Properties:
      Tags:
        - Key: Name
          Value: !Sub ${TemplateName}-igw
  attachIGW:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref MainVPC
      InternetGatewayId: !Ref InternetGateway
  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref MainVPC
  PublicRoute:
    Type: AWS::EC2::Route
    DependsOn: attachIGW
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway
  PublicSubnetARouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnetA
      RouteTableId: !Ref PublicRouteTable

  Cloud9Instance:
    Type: AWS::Cloud9::EnvironmentEC2
    Properties:
      Name: !Sub ${TemplateName}-Cloud9-IDE
      Description: !Sub ${TemplateName}-Cloud9-IDE
      ImageId: amazonlinux-2-x86_64
      AutomaticStopTimeMinutes: 240
      SubnetId: !Ref PublicSubnetA
      InstanceType: m5.large
     #  OwnerArn:
     #    !If [isInEE, !Sub 'arn:aws:sts::${AWS::AccountId}:assumed-role/TeamRole/MasterKey', !Ref "AWS::NoValue"]
     # 