AWSTemplateFormatVersion: "2010-09-09"

Description: "The AWS CloudFormation template for deployment of the AWS Data Lake storage resources"

Mappings:
    RegionMap:
        us-east-1:
            "InstanceType": "m4.large.elasticsearch"
            "DedicatedMasterType": "t2.small.elasticsearch"
        us-east-2:
            "InstanceType": "m4.large.elasticsearch"
            "DedicatedMasterType": "t2.small.elasticsearch"
        us-west-2:
            "InstanceType": "m4.large.elasticsearch"
            "DedicatedMasterType": "t2.small.elasticsearch"
        eu-west-1:
            "InstanceType": "m4.large.elasticsearch"
            "DedicatedMasterType": "t2.small.elasticsearch"
        eu-west-2:
            "InstanceType": "m4.large.elasticsearch"
            "DedicatedMasterType": "t2.small.elasticsearch"
        eu-central-1:
            "InstanceType": "m4.large.elasticsearch"
            "DedicatedMasterType": "t2.small.elasticsearch"
        ap-northeast-1:
            "InstanceType": "m4.large.elasticsearch"
            "DedicatedMasterType": "t2.small.elasticsearch"
        ap-northeast-2:
            "InstanceType": "m4.large.elasticsearch"
            "DedicatedMasterType": "t2.small.elasticsearch"
        ap-southeast-2:
            "InstanceType": "m4.large.elasticsearch"
            "DedicatedMasterType": "t2.small.elasticsearch"
        ap-south-1:
            "InstanceType": "m4.large.elasticsearch"
            "DedicatedMasterType": "t2.small.elasticsearch"
        ap-southeast-1:
            "InstanceType": "m4.large.elasticsearch"
            "DedicatedMasterType": "t2.small.elasticsearch"
        sa-east-1:
            "InstanceType": "m4.large.elasticsearch"
            "DedicatedMasterType": "t2.small.elasticsearch"
        ca-central-1:
            "InstanceType": "m4.large.elasticsearch"
            "DedicatedMasterType": "t2.small.elasticsearch"
        us-west-1:
            "InstanceType": "m4.large.elasticsearch"
            "DedicatedMasterType": "t2.small.elasticsearch"
        eu-west-3:
            "InstanceType": "r4.large.elasticsearch"
            "DedicatedMasterType": "t2.small.elasticsearch"

Resources:

    DataLakeSettingsDynamo:
        Type: "AWS::DynamoDB::Table"
        DeletionPolicy: "Delete"
        Properties:
            AttributeDefinitions:
                -
                    AttributeName: "setting_id"
                    AttributeType: "S"
            KeySchema:
                -
                    AttributeName: "setting_id"
                    KeyType: "HASH"
            ProvisionedThroughput:
                ReadCapacityUnits: 5
                WriteCapacityUnits: 5
            TableName: "data-lake-settings"

    DataLakePackagesDynamo:
        Type: "AWS::DynamoDB::Table"
        DeletionPolicy: "Delete"
        Properties:
            AttributeDefinitions:
                -
                    AttributeName: "package_id"
                    AttributeType: "S"
            KeySchema:
                -
                    AttributeName: "package_id"
                    KeyType: "HASH"
            ProvisionedThroughput:
                ReadCapacityUnits: 5
                WriteCapacityUnits: 5
            TableName: "data-lake-packages"

    DataLakeMetadataDynamo:
        Type: "AWS::DynamoDB::Table"
        DeletionPolicy: "Delete"
        Properties:
            AttributeDefinitions:
                -
                    AttributeName: "package_id"
                    AttributeType: "S"
                -
                    AttributeName: "metadata_id"
                    AttributeType: "S"
            KeySchema:
                -
                    AttributeName: "package_id"
                    KeyType: "HASH"
                -
                    AttributeName: "metadata_id"
                    KeyType: "RANGE"
            ProvisionedThroughput:
                ReadCapacityUnits: 5
                WriteCapacityUnits: 5
            TableName: "data-lake-metadata"

    DataLakeKeysDynamo:
        Type: "AWS::DynamoDB::Table"
        DeletionPolicy: "Delete"
        Properties:
            AttributeDefinitions:
                -
                    AttributeName: "access_key_id"
                    AttributeType: "S"
                -
                    AttributeName: "user_id"
                    AttributeType: "S"
            KeySchema:
                -
                    AttributeName: "access_key_id"
                    KeyType: "HASH"
                -
                    AttributeName: "user_id"
                    KeyType: "RANGE"
            ProvisionedThroughput:
                ReadCapacityUnits: 5
                WriteCapacityUnits: 5
            TableName: "data-lake-keys"

    DataLakeDatasetsDynamo:
        Type: "AWS::DynamoDB::Table"
        DeletionPolicy: "Delete"
        Properties:
            AttributeDefinitions:
                -
                    AttributeName: "package_id"
                    AttributeType: "S"
                -
                    AttributeName: "dataset_id"
                    AttributeType: "S"
            KeySchema:
                -
                    AttributeName: "package_id"
                    KeyType: "HASH"
                -
                    AttributeName: "dataset_id"
                    KeyType: "RANGE"
            ProvisionedThroughput:
                ReadCapacityUnits: 5
                WriteCapacityUnits: 5
            TableName: "data-lake-datasets"

    DataLakeCartDynamo:
        Type: "AWS::DynamoDB::Table"
        DeletionPolicy: "Delete"
        Properties:
            AttributeDefinitions:
                -
                    AttributeName: "user_id"
                    AttributeType: "S"
                -
                    AttributeName: "item_id"
                    AttributeType: "S"
            KeySchema:
                -
                    AttributeName: "user_id"
                    KeyType: "HASH"
                -
                    AttributeName: "item_id"
                    KeyType: "RANGE"
            ProvisionedThroughput:
                ReadCapacityUnits: 5
                WriteCapacityUnits: 5
            TableName: "data-lake-cart"

    DataLakeESLogGroup:
        Type: AWS::Logs::LogGroup
        Properties:
            LogGroupName: "/datalake/es-log"

    CognitoKibanaIdentityPool:
        Type: AWS::Cognito::IdentityPool
        Properties:
            IdentityPoolName: "data lake kibana"
            AllowUnauthenticatedIdentities: true

    CognitoKibanaConfigureRole:
        Type: "AWS::IAM::Role"
        Properties:
            RoleName: !Join ["-", ["data-lake-kibana-configure-role", Ref: "AWS::Region" ]]
            ManagedPolicyArns:
                - arn:aws:iam::aws:policy/AmazonESCognitoAccess
            AssumeRolePolicyDocument:
                Version: "2012-10-17"
                Statement:
                    -
                        Effect: "Allow"
                        Principal:
                            Service: "es.amazonaws.com"
                        Action:
                            - "sts:AssumeRole"

    CognitoKibanaAccessRole:
        Type: "AWS::IAM::Role"
        Properties:
            RoleName: !Join ["-", ["data-lake-kibana-access-role", Ref: "AWS::Region" ]]
            AssumeRolePolicyDocument:
                Version: "2012-10-17"
                Statement:
                    -
                        Effect: "Allow"
                        Principal:
                            Federated: "cognito-identity.amazonaws.com"
                        Action:
                            - "sts:AssumeRoleWithWebIdentity"
                        Condition:
                            StringEquals:
                                "cognito-identity.amazonaws.com:aud": !Ref CognitoKibanaIdentityPool
                            "ForAnyValue:StringLike":
                                "cognito-identity.amazonaws.com:amr": authenticated

    CognitoKibanaAccessRoleAttachment:
        Type: AWS::Cognito::IdentityPoolRoleAttachment
        Properties:
            IdentityPoolId: !Ref CognitoKibanaIdentityPool
            Roles:
                authenticated: !GetAtt CognitoKibanaAccessRole.Arn
                unauthenticated: !GetAtt CognitoKibanaAccessRole.Arn

    DataLakeElasticsearchCluster:
        Type: "AWS::Elasticsearch::Domain"
        Properties:
            DomainName: "data-lake"
            ElasticsearchVersion: "6.2"
            ElasticsearchClusterConfig:
                DedicatedMasterEnabled: true
                InstanceCount: 2
                ZoneAwarenessEnabled: true
                InstanceType: !FindInMap ["RegionMap", Ref: "AWS::Region", "InstanceType"]
                DedicatedMasterType: !FindInMap ["RegionMap", Ref: "AWS::Region", "DedicatedMasterType"]
                DedicatedMasterCount: 3
            EBSOptions:
                EBSEnabled: true
                Iops: 0
                VolumeSize: 50
                VolumeType: "gp2"
            SnapshotOptions:
                AutomatedSnapshotStartHour: 1
            AccessPolicies:
                Version: "2012-10-17"
                Statement:
                    -
                        Effect: "Allow"
                        Principal:
                            AWS:
                                - !GetAtt CognitoKibanaAccessRole.Arn
                        Action:
                                - "es:*"
                        Resource:
                            !Join ["", ["arn:aws:es:", Ref: "AWS::Region", ":", Ref: "AWS::AccountId", ":domain/data-lake/*"]]
            AdvancedOptions:
                rest.action.multi.allow_explicit_index: true

Outputs:
    EsCluster:
        Description: "Elasticsearch cluster domain endpoint"
        Value: !GetAtt DataLakeElasticsearchCluster.DomainEndpoint

    ConfigureRoleArn:
        Description: "Kibana Configuration Role ARN"
        Value: !GetAtt CognitoKibanaConfigureRole.Arn

    DataLakeESLogGroup:
        Description: "Elasticsearch Cluster Log Group ARN"
        Value: !GetAtt DataLakeESLogGroup.Arn

    CognitoKibanaIdentityPool:
        Description: "Cognito kibana identity pool"
        Value: !Ref CognitoKibanaIdentityPool
