AWSTemplateFormatVersion: '2010-09-09'
Description: Managed Dataiku - Fleet Manager
Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: Basic Settings
        Parameters:
          - VPCId
          - VPCCIDR
          - SubnetId
          - AllowedCIDR
          - InstanceSSHKeyPairName
          - RoleName
          - Username
          - Password
          - sslMode
          - sslPublicKey
          - sslAWSSMSecretName
      - Label:
          default: Advanced settings
        Parameters:
          - InstanceType
          - AssociatePublicIpAddress
          - RestoreFromSnapshotID
          - CustomKMSKeyId
    ParameterLabels:
      VPCId:
        default: VPC ID
      VPCCIDR:
        default: VPC CIDR
      SubnetId:
        default: Subnet ID
      AllowedCIDR:
        default: IP addresses allowed to connect to Fleet Manager
      InstanceSSHKeyPairName:
        default: SSH KeyPair
      RoleName:
        default: Fleet Manager IAM Role
      InstanceType:
        default: Instance type
      RestoreFromSnapshotID:
        default: (Optional) Restore from this Snapshot ID
      CustomKMSKeyId:
        default: (Optional) Volume encryption Key ID
      sslMode:
        default: The SSL mode.
      sslPublicKey:
        default: The SSL public key
      sslAWSSMSecretName:
        default: The SSL secret name.
Parameters:
  VPCId:
    Description: VPC where Fleet Manager will be deployed
    Type: AWS::EC2::VPC::Id
  VPCCIDR:
    Description: CIDR of the above VPC (in X.X.X.X/X form)
    Type: String
    ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/x
    AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$
  SubnetId:
    Description: Subnet where Fleet Manager will be deployed
    Type: AWS::EC2::Subnet::Id
  AllowedCIDR:
    Description: Please set CIDR to 0.0.0.0/0 to allow all IP addresses access, or
      another CIDR range to restrict it.
    Type: String
    ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/x
    AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$
  InstanceSSHKeyPairName:
    Description: SSH keypair that is allowed to connect to Fleet Manager
    Type: AWS::EC2::KeyPair::KeyName
  RoleName:
    Description: IAM Role name for running Fleet Manager. Please refer to the documentation
      for required permissions
    Type: String
  Username:
    Description: Fleet Manager user name
    Type: String
    Default: admin
    AllowedPattern: ^[^`\\'"\$]+$
    ConstraintDescription: |
      User name cannot be empty and cannot contain the following characters: ` ' " \ $
  Password:
    Description: Fleet Manager user password
    Type: String
    NoEcho: true
    MinLength: 1
    AllowedPattern: ^[^`\\'"\$]+$
    ConstraintDescription: |
      Password cannot be empty and cannot contain the following characters: ` ' " \ $
  InstanceType:
    Description: Instance type to deploy Fleet Manager
    Type: String
    Default: t3.medium
  RestoreFromSnapshotID:
    Description: An optional Snapshot ID from a previous Fleet Manager data volume
    Type: String
    Default: 'null'
  CustomKMSKeyId:
    Description: An optional custom KMS Key ID to use for root and data volume encryption
    Type: String
    Default: 'null'
  AssociatePublicIpAddress:
    Description: Associate a public IP address to the Fleet Manager
    Type: String
    Default: 'True'
    AllowedValues:
      - 'True'
      - 'False'
  sslMode:
    Description: The SSL mode. SELF_SIGNED | SECRET_MANAGER. Default is SELF_SIGNED
    Type: String
    Default: SELF_SIGNED
  sslPublicKey:
    Description: The SSL public key base64 encoded. Only required if SSL mode is SECRET_MANAGER
    Type: String
    Default: 'null'
  sslAWSSMSecretName:
    Description: The SSL secret name. Only required if SSL mode is SECRET_MANAGER
    Type: String
    Default: 'null'
Mappings:
  AWSAMIRegionMap:
    ap-east-1:
      FleetManagerAmi: ami-0b889d6be207ba258
    ap-northeast-1:
      FleetManagerAmi: ami-0bb6c31881234b167
    ap-northeast-2:
      FleetManagerAmi: ami-0da53bb9cac1e0184
    ap-northeast-3:
      FleetManagerAmi: ami-0b1625a3646b68aa3
    ap-south-1:
      FleetManagerAmi: ami-073eea6d185edc9fa
    ap-southeast-1:
      FleetManagerAmi: ami-04790da7d4ffbbb98
    ap-southeast-2:
      FleetManagerAmi: ami-0a11421d138696d15
    ca-central-1:
      FleetManagerAmi: ami-0dad566a9d5e0d466
    eu-central-1:
      FleetManagerAmi: ami-09f1dd9d05a0fb877
    eu-north-1:
      FleetManagerAmi: ami-0a3a5645c35abb09a
    eu-south-1:
      FleetManagerAmi: ami-00c24afe6f043baa2
    eu-west-1:
      FleetManagerAmi: ami-08c094798cf2c838a
    eu-west-2:
      FleetManagerAmi: ami-0b2611067406de211
    eu-west-3:
      FleetManagerAmi: ami-02e5d818d4cddef59
    me-south-1:
      FleetManagerAmi: ami-0a7265e7ac4fc93d0
    sa-east-1:
      FleetManagerAmi: ami-07a78149ecf18bc8c
    us-east-1:
      FleetManagerAmi: ami-087acacf056f1ddf4
    us-east-2:
      FleetManagerAmi: ami-017a9d91b8d5a346c
    us-west-1:
      FleetManagerAmi: ami-030acb92a1513457b
    us-west-2:
      FleetManagerAmi: ami-0d4e3e9c36c216dba
Conditions:
  StartFromSnapshot: !Not
    - !Equals
      - !Ref 'RestoreFromSnapshotID'
      - 'null'
  CustomKMSKey: !Not
    - !Equals
      - !Ref 'CustomKMSKeyId'
      - 'null'
  AssociatePublicIpAddress: !Equals
    - !Ref 'AssociatePublicIpAddress'
    - 'True'
Resources:
  InstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Roles:
        - !Ref 'RoleName'
  InstanceSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Enables SSH/HTTP/HTTPS access to Fleet Manager Instance
      VpcId: !Ref 'VPCId'
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: !Ref 'AllowedCIDR'
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: !Ref 'AllowedCIDR'
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: !Ref 'AllowedCIDR'
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: !Ref 'VPCCIDR'
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: !Ref 'VPCCIDR'
      SecurityGroupEgress:
        - IpProtocol: '-1'
          CidrIp: 0.0.0.0/0
      Tags:
        - Key: Name
          Value: !Sub '${AWS::StackName}-sg'
  Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !FindInMap
        - AWSAMIRegionMap
        - !Ref 'AWS::Region'
        - FleetManagerAmi
      InstanceType: !Ref 'InstanceType'
      NetworkInterfaces:
        - AssociatePublicIpAddress: !If
            - AssociatePublicIpAddress
            - true
            - false
          DeviceIndex: '0'
          SubnetId: !Ref 'SubnetId'
          GroupSet:
            - !Ref 'InstanceSecurityGroup'
      IamInstanceProfile: !Ref 'InstanceProfile'
      KeyName: !Ref 'InstanceSSHKeyPairName'
      BlockDeviceMappings:
        - DeviceName: /dev/sda1
          Ebs:
            VolumeType: gp2
            VolumeSize: 30
            Encrypted: true
            KmsKeyId: !If
              - CustomKMSKey
              - !Ref 'CustomKMSKeyId'
              - !Ref 'AWS::NoValue'
      Tags:
        - Key: Name
          Value: !Sub '${AWS::StackName}'
      UserData: !Base64
        Fn::Sub: |
          #!/bin/bash
          export FM_CLOUD="AWS"
          export FM_SERVER_CIDR="$(curl http://169.254.169.254/latest/meta-data/network/interfaces/macs/$(curl http://169.254.169.254/latest/meta-data/mac)/subnet-ipv4-cidr-block)"
          export FM_SERVER_REGION="${AWS::Region}"
          export FM_SERVER_VPCID="${VPCId}"
          export FM_SERVER_URL="$(curl http://169.254.169.254/latest/meta-data/local-ipv4)"
          export SkipRootVolumeTag="False"
          export CloudTags="null"
          export DSSStartupRoleArn="null"
          export DSSRuntimeRoleArn="null"
          export CMKId="null"
          export User="${Username}"
          export Password="${Password}"
          export ADMIN_USER_NAME=centos

          export SSL_MODE="${sslMode}"
          export SSL_PUBLIC_KEY="${sslPublicKey}"
          export SSL_AWS_SM_SECRET_NAME="${sslAWSSMSecretName}"

          /opt/dataiku/bin/fm-userdata.sh
  DataVolume:
    Type: AWS::EC2::Volume
    Properties:
      AvailabilityZone: !GetAtt 'Instance.AvailabilityZone'
      Size: !If
        - StartFromSnapshot
        - !Ref 'AWS::NoValue'
        - 50
      SnapshotId: !If
        - StartFromSnapshot
        - !Ref 'RestoreFromSnapshotID'
        - !Ref 'AWS::NoValue'
      Tags:
        - Key: Name
          Value: !Sub '${AWS::StackName}-data-volume'
      VolumeType: gp2
      Encrypted: true
      KmsKeyId: !If
        - CustomKMSKey
        - !Ref 'CustomKMSKeyId'
        - !Ref 'AWS::NoValue'
  DataVolumeAttachment:
    Type: AWS::EC2::VolumeAttachment
    Properties:
      Device: /dev/sdf
      InstanceId: !Ref 'Instance'
      VolumeId: !Ref 'DataVolume'
  DLMRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub '${AWS::StackName}-dlm-role'
      Description: IAM Role needed for Fleet Manager daily backups
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - dlm.amazonaws.com
            Action:
              - sts:AssumeRole
      Policies:
        - PolicyName: !Sub '${AWS::StackName}-dlm-policy'
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - ec2:CreateSnapshot
                  - ec2:CreateSnapshots
                  - ec2:DeleteSnapshot
                Resource:
                  - arn:aws:ec2:*::snapshot/*
                  - !Sub 'arn:aws:ec2:*:${AWS::AccountId}:instance/${Instance}'
                  - !Sub 'arn:aws:ec2:*:${AWS::AccountId}:volume/${DataVolume}'
              - Effect: Allow
                Action:
                  - ec2:DescribeVolumes
                  - ec2:DescribeInstances
                  - ec2:DescribeSnapshots
                Resource:
                  - '*'
              - Effect: Allow
                Action:
                  - ec2:CreateTags
                Resource:
                  - arn:aws:ec2:*::snapshot/*
  DailyBackupPolicy:
    Type: AWS::DLM::LifecyclePolicy
    Properties:
      Description: Policy to backup Fleet Manager data volume daily
      State: ENABLED
      ExecutionRoleArn: !GetAtt 'DLMRole.Arn'
      PolicyDetails:
        ResourceTypes:
          - VOLUME
        TargetTags:
          - Key: Name
            Value: !Sub '${AWS::StackName}-data-volume'
        Schedules:
          - Name: Daily Snapshots
            TagsToAdd:
              - Key: type
                Value: Dataiku Fleet Manager DailySnapshot
            CreateRule:
              Interval: 24
              IntervalUnit: HOURS
              Times:
                - 01:00
            RetainRule:
              Count: 14
            CopyTags: true
Outputs:
  Instance:
    Description: Fleet Manager instance ID
    Value: !Ref 'Instance'
  InstanceDNSName:
    Description: Fleet Manager host name
    Value: !GetAtt 'Instance.PublicDnsName'
