{
  "AWSTemplateFormatVersion" : "2010-09-09",

  "Description" : "AWS CloudFormation template that sets up CloudTrail, a secure S3 bucket, and a VPC appropriate for analyzing dbGaP data using Elastic MapReduce",

  "Mappings" : {
    "SubnetConfig" : {
      "VPC"     : { "CIDR" : "10.0.0.0/24" },
      "Public"  : { "CIDR" : "10.0.0.0/24" }
    }
  },

  "Parameters" : {
    "SecureBucket": {
      "Description": "Name of secure bucket to which Rail's intermediate data and output as well as CloudTrail's output are written.",
      "Type": "String"
    }
  },

  "Resources" : {

    "S3Bucket": {
      "DeletionPolicy" : "Retain",
      "Type" : "AWS::S3::Bucket",
      "Properties": {
        "BucketName" : {"Ref" : "SecureBucket"}
      }
    },
    "BucketPolicy" : {
      "Type" : "AWS::S3::BucketPolicy",
      "Properties" : {
        "Bucket" : {"Ref" : "S3Bucket"},
        "PolicyDocument" : {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Sid": "AWSCloudTrailAclCheck",
              "Effect": "Allow",
              "Principal": {
                "AWS": [
                  "arn:aws:iam::903692715234:root",
                  "arn:aws:iam::859597730677:root",
                  "arn:aws:iam::814480443879:root",
                  "arn:aws:iam::216624486486:root",
                  "arn:aws:iam::086441151436:root",
                  "arn:aws:iam::388731089494:root",
                  "arn:aws:iam::284668455005:root",
                  "arn:aws:iam::113285607260:root"
                ]
              },
              "Action": "s3:GetBucketAcl",
              "Resource": { "Fn::Join" : ["", ["arn:aws:s3:::", {"Ref":"S3Bucket"}]]}
            },
            {
              "Sid": "AWSCloudTrailWrite",
              "Effect": "Allow",
              "Principal": {
                "AWS": [
                  "arn:aws:iam::903692715234:root",
                  "arn:aws:iam::859597730677:root",
                  "arn:aws:iam::814480443879:root",
                  "arn:aws:iam::216624486486:root",
                  "arn:aws:iam::086441151436:root",
                  "arn:aws:iam::388731089494:root",
                  "arn:aws:iam::284668455005:root",
                  "arn:aws:iam::113285607260:root"
                ]
              },
              "Action": "s3:PutObject",
              "Resource": { "Fn::Join" : ["", ["arn:aws:s3:::", {"Ref":"S3Bucket"}, "/AWSLogs/", {"Ref":"AWS::AccountId"}, "/*"]]},
              "Condition": {
                "StringEquals": {
                  "s3:x-amz-acl": "bucket-owner-full-control"
                }
              }
            },
            {
               "Sid":"DenyUnEncryptedObjectUploads",
               "Effect":"Deny",
               "Principal":"*",
               "Action":"s3:PutObject",
               "Resource":{ "Fn::Join" : ["", ["arn:aws:s3:::", {"Ref":"S3Bucket"}, "/*"]]},
               "Condition":{
                  "StringNotEquals":{
                     "s3:x-amz-server-side-encryption":"AES256"
                  }
               }
            }
          ]
        }
      }
    },
    "secureTrail" : {
      "DependsOn" : ["BucketPolicy"],
      "Type" : "AWS::CloudTrail::Trail",
      "Properties" : {
        "S3BucketName" : {"Ref":"S3Bucket"},
        "IsLogging" : true
      }
    },

    "VPC" : {
      "Type" : "AWS::EC2::VPC",
      "Properties" : {
        "EnableDnsSupport" : "true",
        "EnableDnsHostnames" : "true",
        "CidrBlock" : { "Fn::FindInMap" : [ "SubnetConfig", "VPC", "CIDR" ]},
        "Tags" : [
          { "Key" : "Application", "Value" : { "Ref" : "AWS::StackName" } },
          { "Key" : "Network", "Value" : "Public" }
        ]
      }
    },

    "PublicSubnet" : {
      "Type" : "AWS::EC2::Subnet",
      "Properties" : {
        "VpcId" : { "Ref" : "VPC" },
        "CidrBlock" : { "Fn::FindInMap" : [ "SubnetConfig", "Public", "CIDR" ]},
        "Tags" : [
          { "Key" : "Application", "Value" : { "Ref" : "AWS::StackName" } },
          { "Key" : "Network", "Value" : "Public" }
        ]
      }
    },

    "InternetGateway" : {
      "Type" : "AWS::EC2::InternetGateway",
      "Properties" : {
        "Tags" : [
          { "Key" : "Application", "Value" : { "Ref" : "AWS::StackName" } },
          { "Key" : "Network", "Value" : "Public" }
        ]
      }
    },

    "GatewayToInternet" : {
       "Type" : "AWS::EC2::VPCGatewayAttachment",
       "Properties" : {
         "VpcId" : { "Ref" : "VPC" },
         "InternetGatewayId" : { "Ref" : "InternetGateway" }
       }
    },

    "PublicRouteTable" : {
      "Type" : "AWS::EC2::RouteTable",
      "Properties" : {
        "VpcId" : { "Ref" : "VPC" },
        "Tags" : [
          { "Key" : "Application", "Value" : { "Ref" : "AWS::StackName" } },
          { "Key" : "Network", "Value" : "Public" }
        ]
      }
    },

    "PublicRoute" : {
      "Type" : "AWS::EC2::Route",
      "DependsOn" : "GatewayToInternet",
      "Properties" : {
        "RouteTableId" : { "Ref" : "PublicRouteTable" },
        "DestinationCidrBlock" : "0.0.0.0/0",
        "GatewayId" : { "Ref" : "InternetGateway" }
      }
    },

    "PublicSubnetRouteTableAssociation" : {
      "Type" : "AWS::EC2::SubnetRouteTableAssociation",
      "Properties" : {
        "SubnetId" : { "Ref" : "PublicSubnet" },
        "RouteTableId" : { "Ref" : "PublicRouteTable" }
      }
    },

    "PublicNetworkAcl" : {
      "Type" : "AWS::EC2::NetworkAcl",
      "Properties" : {
        "VpcId" : { "Ref" : "VPC" },
        "Tags" : [
          { "Key" : "Application", "Value" : { "Ref" : "AWS::StackName" } },
          { "Key" : "Network", "Value" : "Public" }
        ]
      }
    },

    "InboundHTTPPublicNetworkAclEntry" : {
      "Type" : "AWS::EC2::NetworkAclEntry",
      "Properties" : {
        "NetworkAclId" : { "Ref" : "PublicNetworkAcl" },
        "RuleNumber" : "100",
        "Protocol" : "6",
        "RuleAction" : "allow",
        "Egress" : "false",
        "CidrBlock" : "0.0.0.0/0",
        "PortRange" : { "From" : "80", "To" : "80" }
      }
    },

    "InboundHTTPSPublicNetworkAclEntry" : {
      "Type" : "AWS::EC2::NetworkAclEntry",
      "Properties" : {
        "NetworkAclId" : { "Ref" : "PublicNetworkAcl" },
        "RuleNumber" : "101",
        "Protocol" : "6",
        "RuleAction" : "allow",
        "Egress" : "false",
        "CidrBlock" : "0.0.0.0/0",
        "PortRange" : { "From" : "443", "To" : "443" }
      }
    },

    "InboundEphemeralPublicNetworkAclEntry" : {
      "Type" : "AWS::EC2::NetworkAclEntry",
      "Properties" : {
        "NetworkAclId" : { "Ref" : "PublicNetworkAcl" },
        "RuleNumber" : "103",
        "Protocol" : "6",
        "RuleAction" : "allow",
        "Egress" : "false",
        "CidrBlock" : "0.0.0.0/0",
        "PortRange" : { "From" : "1024", "To" : "65535" }
      }
    },

    "OutboundPublicNetworkAclEntry" : {
      "Type" : "AWS::EC2::NetworkAclEntry",
      "Properties" : {
        "NetworkAclId" : { "Ref" : "PublicNetworkAcl" },
        "RuleNumber" : "100",
        "Protocol" : "6",
        "RuleAction" : "allow",
        "Egress" : "true",
        "CidrBlock" : "0.0.0.0/0",
        "PortRange" : { "From" : "0", "To" : "65535" }
      }
    },

    "PublicSubnetNetworkAclAssociation" : {
      "Type" : "AWS::EC2::SubnetNetworkAclAssociation",
      "Properties" : {
        "SubnetId" : { "Ref" : "PublicSubnet" },
        "NetworkAclId" : { "Ref" : "PublicNetworkAcl" }
      }
    },

    "EC2MasterSecurityGroup" : {
      "Type" : "AWS::EC2::SecurityGroup",
      "Properties" : {
        "GroupDescription" : "Block all of internet ingress; Amazon pokes necessary holes",
        "VpcId" : { "Ref" : "VPC" },
        "SecurityGroupIngress" : [],
        "SecurityGroupEgress": []
      }
    },

    "EC2SlaveSecurityGroup" : {
      "Type" : "AWS::EC2::SecurityGroup",
      "Properties" : {
        "GroupDescription" : "Block all of internet ingress; Amazon pokes necessary holes",
        "VpcId" : { "Ref" : "VPC" },
        "SecurityGroupIngress" : [],
        "SecurityGroupEgress" : []
      }
    },

    "S3Endpoint" : {
      "Type" : "AWS::EC2::VPCEndpoint",
      "Properties" : {
        "PolicyDocument" : {
          "Version":"2012-10-17",
          "Statement":[{
            "Effect":"Allow",
            "Principal": "*",
            "Action": "*",
            "Resource": "*"
          }]
        },
        "RouteTableIds" : [ { "Ref" : "PublicRouteTable" } ],
        "ServiceName" : { "Fn::Join": [ "", [ "com.amazonaws.", { "Ref": "AWS::Region" }, ".s3" ] ] },
        "VpcId" : {"Ref" : "VPC"}
      }
    }

  },

  "Outputs" : {
    "PublicSubnetId" : {
      "Description" : "ID of subnet into which secure Rail-RNA job flows should be launched",
      "Value" :  { "Ref" : "PublicSubnet" }
    },
    "MasterSecurityGroupId" : {
      "Description" : "ID of security group that should be applied to MASTER EMR instances for all job flows when analyzing dbGaP data",
      "Value" :  { "Ref" : "EC2MasterSecurityGroup" }
    },
    "SlaveSecurityGroupId" : {
      "Description" : "ID of security group that should be applied to SLAVE EMR instances for all job flows when analyzing dbGaP data",
      "Value" :  { "Ref" : "EC2SlaveSecurityGroup" }
    },
    "SecureBucketName" : {
      "Description" : "Name of secure S3 bucket associated with stack; Rail-RNA job flows should write intermediate and output data to this bucket",
      "Value" : { "Ref" : "S3Bucket" }
    }
  }
}