AWSTemplateFormatVersion: 2010-09-09
Description: Deploy IMAX StreamSmart On-Air in an AWS EC2 instance
Transform: AWS::LanguageExtensions

Parameters:
  VPC:
    Description: >-
      The VPC to use when deploying your IMAX StreamSmart On-Air EC2 instance.
      You will need to use a VPC that has a public subnet with a route that allows
      inbound traffic on TCP port 443 and 22 and outbound traffic to the internet on
      TCP port 443 to the internet as described in the Installation section of the
      technical documentation.
    Type: AWS::EC2::VPC::Id
  AZ:
    Description: >-
      The Availability Zone to use when deploying your IMAX StreamSmart On-Air EC2 instance.
    Type: AWS::EC2::AvailabilityZone::Name
  HTTPSCIDRSIN:
    Description: >-
      A comma-separated list (no spaces) of CIDR blocks that encompass ALL the IP
      addresses that are allowed to access the HTTPS (port 443) interface of your
      IMAX StreamSmart On-Air Platform instance. Note that all users of the StreamSmart
      On-Air Platform need access to the HTTPS interface regardless of whether
      they use the Insights Web UI and/or the Platform REST API.
      Example: 64.183.33.44/24,64.183.30.44/32
    Type: CommaDelimitedList
  SSHCIDRS:
    Description: >-
      A comma separated list (no spaces) of CIDR blocks that includes
      ALL IP addresses that are allowed to access the SSH (port 22) interface of
      your IMAX StreamSmart On-Air instance.  Only the deployer/administrator
      requires this level of access and you are strongly encouraged to isolate a single
      IP address (i.e. x.x.x.x/32) where possible. Example: 64.183.30.44/32
    Type: CommaDelimitedList
    AllowedPattern: >-
      ^(([0-9]{1,3}\.){3}[0-9]{1,3}(\/([0-9]|[1-2][0-9]|3[0-2]))?)(,(([0-9]{1,3}\.){3}[0-9]{1,3}(\/([0-9]|[1-2][0-9]|3[0-2]))?))*$
  InstanceType:
    Description: >-
      The EC2 instance type to use with your IMAX StreamSmart On-Air instance.
      The requirements dictate using a c5.24xlarge or c5a.24xlarge instance type.
    Type: String
    Default: c5.4xlarge
    AllowedValues:
      - c5.2xlarge
      - c5a.2xlarge
      - c5.4xlarge
      - c5a.4xlarge
      - c5.9xlarge
      - c5a.9xlarge
      - c5.24xlarge
      - c5a.24xlarge
      - c7.2xlarge
      - c7a.2xlarge
  EBS:
    Description: >-
      The size (in GB) of the EBS volume to use with your IMAX StreamSmart On-Air EC2 instance.
      The default size is 50GB.
    MinValue: '50'
    Type: Number
    Default: 50
  ConfigurationBucket:
    Type: String
    Description: A readOnly S3 bucket for StreamSmart On-Air to pull configuration and License files from. Provide the ARN for the Bucket.
    AllowedPattern: >-
      ^arn:aws:s3:::(([a-z0-9.-]+))(?:/(.*))?$
  LicenseFileURL:
    Type: String
    Description: URL for the StreamSmart On-Air license file to deploy onto the EC2 instance.
    AllowedPattern: >-
      ^https://([a-z0-9.-]{3,63})\.s3\.(us|eu|ap|sa|ca|af|me)-[a-z]+-[0-9]{1}.amazonaws.com/([a-zA-Z0-9._-]+(/?[a-zA-Z0-9._/-]+)*)$
  ConfigFileURL:
    Type: String
    Description: URL for the StreamSmart On-Air configuration file contents to deploy onto the EC2 instance.

Mappings:
  AmiRegionMap:
    us-east-1:
      ImageId: ami-007edc82299320e14
    us-east-2:
      ImageId: ami-0e5015292aa3c0014
    us-west-2:
      ImageId: ami-0d49c8803ffd33303
    eu-west-1:
      ImageId: ami-09ccb63f235b7e5c5
    eu-central-1:
      ImageId: ami-00e05cba28e5d81f9
    me-central-1:
      ImageId: ami-0a38f62627f4fc5c9
    ap-northeast-3:
      ImageId: ami-07493307177a25740

Metadata:
  'AWS::CloudFormation::Interface':
    ParameterGroups:
      - Label:
          default: IMAX StreamSmart On-Air product Deployment
        Parameters:
          - AZ
          - HTTPSCIDRSIN
          - HTTPSCIDRSOUT
          - SSHCIDRS
          - VPC
          - InstanceType
          - EBS
          - ConfigurationBucket
    ParameterLabels:
      VPC:
        default: StreamSmart On-Air instance target VPC
      AZ:
        default: StreamSmart On-Air instance target availability zone (AZ)
      HTTPSCIDRSIN:
        default: StreamSmart On-Air HTTPS access allowlist
      SSHCIDRS:
        default: StreamSmart On-Air SSH access allowlist
      InstanceType:
        default: StreamSmart On-Air EC2 instance type
      EBS:
        default: StreamSmart On-Air EBS volume (in GB)
      ConfigurationBucket:
        default: Bucket to read config and license files from
      ConfigFileURL:
        default: object URL for the config file
      LicenseFileURL:
        default: object URL for the license file

Resources:
  StreamSmartOnAirKeyPair:
    Type: AWS::EC2::KeyPair
    Properties:
      KeyName:
        !Join
        - '-'
        - - 'imax-stream-smart-on-air-keypair'
          - !Select [4, !Split ['-', !Select [2, !Split ['/', !Ref AWS::StackId]]]]

  StreamSmartOnAirInstanceSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName:
        !Join
        - '-'
        - - 'imax-stream-smart-on-air-sg'
          - !Select [4, !Split ['-', !Select [2, !Split ['/', !Ref AWS::StackId]]]]
      GroupDescription: >-
        Allow HTTPS and SSH inbound and HTTPS outbound traffic for IMAX StreamSmart On-Air instance
      VpcId: !Ref VPC

  'Fn::ForEach::HTTPSSecurityGroupIngresses':
    - ParmName
    - !Ref HTTPSCIDRSIN
    - 'HTTPSInRule&{ParmName}':
        Type: AWS::EC2::SecurityGroupIngress
        Properties:
          GroupId: !Ref StreamSmartOnAirInstanceSecurityGroup
          Description: HTTPS access needed for all users of IMAX StreamSmart On-Air Platform
          IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: !Sub '${ParmName}'

  'Fn::ForEach::SSHSecurityGroupIngresses':
    - ParmName
    - !Ref SSHCIDRS
    - 'SSHRule&{ParmName}':
        Type: AWS::EC2::SecurityGroupIngress
        Properties:
          GroupId: !Ref StreamSmartOnAirInstanceSecurityGroup
          Description: SSH access needed for StreamSmart On-Air deployment/troubleshooting
          IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: !Sub '${ParmName}'

  StreamSmartOnAirS3ReadOnlyPolicy:
      Type: 'AWS::IAM::ManagedPolicy'
      Properties:
        PolicyDocument:
          Version: 2012-10-17
          Statement:
            - Action:
                - ec2:DescribeTags
                - ec2:DescribeVolumes
                - ec2:DescribeInstances
              Effect: Allow
              Resource: "*"
            - Action:
                - 's3:ListBucket'
              Effect: Allow
              Resource: !Ref ConfigurationBucket
            - Action:
                - 's3:GetObject'
              Effect: Allow
              Resource: !Join
                      - '/'
                      - - !Ref ConfigurationBucket
                        - "*"
        Description: >-
          The IAM policy created to grant the IMAX StreamSmart On-Air instance read-only
          access to the your S3 bucket(s).
        ManagedPolicyName: !Join
                - '-'
                - - 'imax-stream-smart-on-air-ami-s3-ro'
                  - !Select [4, !Split ['-', !Select [2, !Split ['/', !Ref AWS::StackId]]]]
        Roles:
          - !Ref StreamSmartOnAirRole

  StreamSmartOnAirRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
          {
            "Version": "2012-10-17",
            "Statement": [
              {
                "Effect": "Allow",
                "Principal": {
                  "Service": "ec2.amazonaws.com"
                },
                "Action": "sts:AssumeRole"
              }
            ]
          }
      RoleName: !Join
              - '-'
              - - 'imax-stream-smart-on-air-role'
                - !Select [4, !Split ['-', !Select [2, !Split ['/', !Ref AWS::StackId]]]]
      Path: /
      Description: >-
        The role intended for use with the IMAX StreamSmart On-Air product.

  StreamSmartOnAirInstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      InstanceProfileName: !Join
                          - '-'
                          - - 'imax-stream-smart-on-air-instance-profile'
                            - !Select [4, !Split ['-', !Select [2, !Split ['/', !Ref AWS::StackId]]]]
      Path: "/"
      Roles:
        -
          Ref: "StreamSmartOnAirRole"


  StreamSmartOnAirInstance:
    DependsOn: StreamSmartOnAirInstanceSecurityGroup
    Type: AWS::EC2::Instance
    Metadata:
      AWS::CloudFormation::Authentication:
        S3AccessCreds:
          type: "S3"
          buckets: !Ref ConfigurationBucket
          roleName: !Ref StreamSmartOnAirRole
      AWS::CloudFormation::Init:
        configSets:
            init:
                - repoKey
        repoKey:
            files:
                "/default_run_config/config.json":
                    mode: '000644'
                    owner: root
                    group: root
                    source: !Ref ConfigFileURL
                    authentication: S3AccessCreds
                "/default_run_config/features.lic":
                    mode: '000644'
                    owner: root
                    group: root
                    source: !Ref LicenseFileURL
                    authentication: S3AccessCreds
    Properties:
      AvailabilityZone: !Ref AZ
      ImageId: !FindInMap [AmiRegionMap, !Ref "AWS::Region", ImageId]
      InstanceType: !Ref InstanceType
      IamInstanceProfile: !Ref StreamSmartOnAirInstanceProfile
      KeyName: !Ref StreamSmartOnAirKeyPair
      SecurityGroupIds:
        - !Ref StreamSmartOnAirInstanceSecurityGroup
      Tags:
          - {Key: Name, Value: IMAX StreamSmart On-Air }
      BlockDeviceMappings:
        - DeviceName: /dev/sdc
          Ebs:
            VolumeSize: !Ref EBS
            VolumeType: gp3
            DeleteOnTermination: true
            Encrypted: true
      UserData:
              Fn::Base64: !Sub |
                        #!/bin/bash -xe
                        cfn-init -v --stack ${AWS::StackName} --region ${AWS::Region} --resource StreamSmartOnAirInstance --configsets init

Outputs:
  PublicDNS:
    Description: >-
      Public DNS name of the newly created IMAX StreamSmart On-Air EC2 instance.  Use this
      value as your <ec2_public_dns> and continue with the installation instructions.
    Value: !GetAtt [StreamSmartOnAirInstance, PublicDnsName]
  PublicIP:
    Description: Public IP address of the newly created IMAX StreamSmart On-Air EC2 instance
    Value: !GetAtt [StreamSmartOnAirInstance, PublicIp]

