From dad4b1483902c29e16c974f549cac3238588321e Mon Sep 17 00:00:00 2001
From: Rosie Storey <rstorey@loc.gov>
Date: Tue, 15 Jan 2019 10:27:32 -0500
Subject: [PATCH 01/15] Add IAM role to bastion host instances

---
 cloudformation/infrastructure/bastion-hosts.yaml | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/cloudformation/infrastructure/bastion-hosts.yaml b/cloudformation/infrastructure/bastion-hosts.yaml
index e9b22e329..08581d7f5 100644
--- a/cloudformation/infrastructure/bastion-hosts.yaml
+++ b/cloudformation/infrastructure/bastion-hosts.yaml
@@ -22,6 +22,15 @@ Parameters:
     PublicSubnet2:
         Description: The ID of the public subnet in the second AZ
         Type: AWS::EC2::Subnet::Id
+    
+    IamInstanceProfileArn:
+        Description: IAM role ARN for the EC2 instances
+        Type: String
+        AllowedValues:
+            - arn:aws:iam::619333082511:role/ConcordiaServerTaskRole-crowd-dev
+            - arn:aws:iam::619333082511:role/ConcordiaServerTaskRole-crowd-test
+            - arn:aws:iam::619333082511:role/ConcordiaServerTaskRole-crowd-stage
+            - arn:aws:iam::619333082511:role/ConcordiaServerTaskRole-crowd-prod
 
 Mappings:
     AWSRegionToAMI:
@@ -41,6 +50,8 @@ Resources:
                 - Ref: "AWS::Region"
                 - "AMI"
             InstanceType: "t1.micro"
+            IamInstanceProfile: 
+                Ref: IamInstanceProfileArn
             KeyName: 
                 Ref: KeyPairName
             NetworkInterfaces: 
@@ -63,6 +74,8 @@ Resources:
                 - Ref: "AWS::Region"
                 - "AMI"
             InstanceType: "t1.micro"
+            IamInstanceProfile: 
+                Ref: IamInstanceProfileArn
             KeyName: 
                 Ref: KeyPairName
             NetworkInterfaces: 

From 555d152f668dd94b78fd37e15cf7639ec51853d9 Mon Sep 17 00:00:00 2001
From: Rosie Storey <rstorey@loc.gov>
Date: Tue, 15 Jan 2019 10:52:41 -0500
Subject: [PATCH 02/15] correct instance profile arns for bastion hosts

---
 cloudformation/infrastructure/bastion-hosts.yaml | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/cloudformation/infrastructure/bastion-hosts.yaml b/cloudformation/infrastructure/bastion-hosts.yaml
index 08581d7f5..c0f8395fe 100644
--- a/cloudformation/infrastructure/bastion-hosts.yaml
+++ b/cloudformation/infrastructure/bastion-hosts.yaml
@@ -27,10 +27,10 @@ Parameters:
         Description: IAM role ARN for the EC2 instances
         Type: String
         AllowedValues:
-            - arn:aws:iam::619333082511:role/ConcordiaServerTaskRole-crowd-dev
-            - arn:aws:iam::619333082511:role/ConcordiaServerTaskRole-crowd-test
-            - arn:aws:iam::619333082511:role/ConcordiaServerTaskRole-crowd-stage
-            - arn:aws:iam::619333082511:role/ConcordiaServerTaskRole-crowd-prod
+            - arn:aws:iam::619333082511:instance-profile/crowd-dev-FargateCluster-WFCY4I0U7JSM-ConcordiaInstanceProfile-RQHLRZADDM9M
+            - arn:aws:iam::619333082511:instance-profile/crowd-test-FargateCluster-1R5U1VT4HOYX2-ConcordiaInstanceProfile-1FJXY570ZM2O3
+            - arn:aws:iam::619333082511:instance-profile/crowd-stage-FargateCluster-1TBKSIZQKLJHV-ConcordiaInstanceProfile-1XG3TR3LY42ND
+            - arn:aws:iam::619333082511:instance-profile/crowd-prod-FargateCluster-1X1CI0J3HFJ9F-ConcordiaInstanceProfile-13SHE5FAB7D6Q
 
 Mappings:
     AWSRegionToAMI:

From 1e6921b48a083033822db822a3668add77251b91 Mon Sep 17 00:00:00 2001
From: Rosie Storey <rstorey@loc.gov>
Date: Tue, 15 Jan 2019 11:53:46 -0500
Subject: [PATCH 03/15] cloudformation wants IamInstanceProfile as name, not
 arn

---
 cloudformation/infrastructure/bastion-hosts.yaml | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/cloudformation/infrastructure/bastion-hosts.yaml b/cloudformation/infrastructure/bastion-hosts.yaml
index c0f8395fe..b4ce3b229 100644
--- a/cloudformation/infrastructure/bastion-hosts.yaml
+++ b/cloudformation/infrastructure/bastion-hosts.yaml
@@ -23,14 +23,14 @@ Parameters:
         Description: The ID of the public subnet in the second AZ
         Type: AWS::EC2::Subnet::Id
     
-    IamInstanceProfileArn:
-        Description: IAM role ARN for the EC2 instances
+    IamInstanceProfileName:
+        Description: IAM role Name for the EC2 instances
         Type: String
         AllowedValues:
-            - arn:aws:iam::619333082511:instance-profile/crowd-dev-FargateCluster-WFCY4I0U7JSM-ConcordiaInstanceProfile-RQHLRZADDM9M
-            - arn:aws:iam::619333082511:instance-profile/crowd-test-FargateCluster-1R5U1VT4HOYX2-ConcordiaInstanceProfile-1FJXY570ZM2O3
-            - arn:aws:iam::619333082511:instance-profile/crowd-stage-FargateCluster-1TBKSIZQKLJHV-ConcordiaInstanceProfile-1XG3TR3LY42ND
-            - arn:aws:iam::619333082511:instance-profile/crowd-prod-FargateCluster-1X1CI0J3HFJ9F-ConcordiaInstanceProfile-13SHE5FAB7D6Q
+            - crowd-dev-FargateCluster-WFCY4I0U7JSM-ConcordiaInstanceProfile-RQHLRZADDM9M
+            - crowd-test-FargateCluster-1R5U1VT4HOYX2-ConcordiaInstanceProfile-1FJXY570ZM2O3
+            - crowd-stage-FargateCluster-1TBKSIZQKLJHV-ConcordiaInstanceProfile-1XG3TR3LY42ND
+            - crowd-prod-FargateCluster-1X1CI0J3HFJ9F-ConcordiaInstanceProfile-13SHE5FAB7D6Q
 
 Mappings:
     AWSRegionToAMI:
@@ -51,7 +51,7 @@ Resources:
                 - "AMI"
             InstanceType: "t1.micro"
             IamInstanceProfile: 
-                Ref: IamInstanceProfileArn
+                Ref: IamInstanceProfileName
             KeyName: 
                 Ref: KeyPairName
             NetworkInterfaces: 
@@ -75,7 +75,7 @@ Resources:
                 - "AMI"
             InstanceType: "t1.micro"
             IamInstanceProfile: 
-                Ref: IamInstanceProfileArn
+                Ref: IamInstanceProfileName
             KeyName: 
                 Ref: KeyPairName
             NetworkInterfaces: 

From 21f8b4b0440120ffe9c68efffc065e54e39e7920 Mon Sep 17 00:00:00 2001
From: Rosie Storey <rstorey@loc.gov>
Date: Tue, 15 Jan 2019 15:00:17 -0500
Subject: [PATCH 04/15] Use mapping in bastion host template to simplify
 parameters

---
 cloudformation/create_bastion_hosts.sh        |  5 ++
 .../infrastructure/bastion-hosts.yaml         | 89 +++++++++++++------
 2 files changed, 65 insertions(+), 29 deletions(-)
 create mode 100755 cloudformation/create_bastion_hosts.sh

diff --git a/cloudformation/create_bastion_hosts.sh b/cloudformation/create_bastion_hosts.sh
new file mode 100755
index 000000000..4c04909a7
--- /dev/null
+++ b/cloudformation/create_bastion_hosts.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+export ENV_NAME=dev
+
+aws cloudformation create-stack --stack-name "${ENV_NAME}-bastionhosts"  --template-url https://s3.amazonaws.com/crowd-deployment/infrastructure/bastion-hosts.yaml --parameters "ParameterKey=EnvironmentName,ParameterValue=${ENV_NAME}" ParameterKey=KeyPairName,ParameterValue=rstorey@loc.gov
\ No newline at end of file
diff --git a/cloudformation/infrastructure/bastion-hosts.yaml b/cloudformation/infrastructure/bastion-hosts.yaml
index b4ce3b229..f899c4594 100644
--- a/cloudformation/infrastructure/bastion-hosts.yaml
+++ b/cloudformation/infrastructure/bastion-hosts.yaml
@@ -6,38 +6,51 @@ Parameters:
     EnvironmentName:
         Description: An environment name that will be prefixed to resource names
         Type: String
-
-    BastionHostsSecurityGroup:
-        Description: The security group for bastion hosts
-        Type: AWS::EC2::SecurityGroup::Id
+        AllowedValues:
+          - dev
+          - test
+          - stage
+          - prod
     
     KeyPairName:
         Description: key pair (within this region) for ECS instances access
         Type: String
 
-    PublicSubnet1:
-        Description: The ID of the public subnet in the first AZ
-        Type: AWS::EC2::Subnet::Id
-    
-    PublicSubnet2:
-        Description: The ID of the public subnet in the second AZ
-        Type: AWS::EC2::Subnet::Id
-    
-    IamInstanceProfileName:
-        Description: IAM role Name for the EC2 instances
-        Type: String
-        AllowedValues:
-            - crowd-dev-FargateCluster-WFCY4I0U7JSM-ConcordiaInstanceProfile-RQHLRZADDM9M
-            - crowd-test-FargateCluster-1R5U1VT4HOYX2-ConcordiaInstanceProfile-1FJXY570ZM2O3
-            - crowd-stage-FargateCluster-1TBKSIZQKLJHV-ConcordiaInstanceProfile-1XG3TR3LY42ND
-            - crowd-prod-FargateCluster-1X1CI0J3HFJ9F-ConcordiaInstanceProfile-13SHE5FAB7D6Q
-
 Mappings:
     AWSRegionToAMI:
-        us-east-2:
-            AMI: ami-0cf31d971a3ca20d6
         us-east-1:
             AMI: ami-04681a1dbd79675a5
+    
+    EnvironmentMapping:
+        IamInstanceProfileName:
+            dev: crowd-dev-FargateCluster-WFCY4I0U7JSM-ConcordiaInstanceProfile-RQHLRZADDM9M
+            test: crowd-test-FargateCluster-1R5U1VT4HOYX2-ConcordiaInstanceProfile-1FJXY570ZM2O3
+            stage: crowd-stage-FargateCluster-1TBKSIZQKLJHV-ConcordiaInstanceProfile-1XG3TR3LY42ND
+            prod: crowd-prod-FargateCluster-1X1CI0J3HFJ9F-ConcordiaInstanceProfile-13SHE5FAB7D6Q
+
+        # The ID of the public subnet in the first AZ
+        # Type: AWS::EC2::Subnet::Id
+        PublicSubnet1:
+            dev: subnet-079b5dd4f9acf44e6
+            test: subnet-06f443ea589879e8d
+            stage: subnet-06f40e2fc8d891692
+            prod: subnet-09fdaf1c5c73f588f
+    
+        # The ID of the public subnet in the second AZ
+        # Type: AWS::EC2::Subnet::Id
+        PublicSubnet2:
+            dev: subnet-01d6614725c7dabd6
+            test: subnet-05a15c6058ebdf54f
+            stage: subnet-0a022eb0c614b0b00
+            prod: subnet-01580e2a4d6d42b52
+
+        # The security group for bastion hosts
+        # Type: AWS::EC2::SecurityGroup::Id
+        BastionHostsSecurityGroup:
+            dev: sg-062afe8941ace25ad
+            test: sg-0208b0df704b66c3c
+            stage: sg-0a2175a2df32a4332
+            prod: sg-066c68e77787b2a10
 
 Resources:
 
@@ -51,16 +64,25 @@ Resources:
                 - "AMI"
             InstanceType: "t1.micro"
             IamInstanceProfile: 
-                Ref: IamInstanceProfileName
+                Fn::FindInMap: 
+                    - EnvironmentMapping
+                    - IamInstanceProfileName
+                    - Ref: EnvironmentName
             KeyName: 
                 Ref: KeyPairName
             NetworkInterfaces: 
                 - AssociatePublicIpAddress: true
                   DeviceIndex: "0"
                   GroupSet: 
-                    - Ref: BastionHostsSecurityGroup
+                    - Fn::FindInMap: 
+                        - EnvironmentMapping
+                        - BastionHostsSecurityGroup
+                        - Ref: EnvironmentName
                   SubnetId: 
-                    Ref: PublicSubnet1
+                    Fn::FindInMap: 
+                        - EnvironmentMapping
+                        - PublicSubnet1
+                        - Ref: EnvironmentName
             Tags:
                 - Key: Name
                   Value: !Sub ${EnvironmentName}-BastionHost-1     
@@ -75,16 +97,25 @@ Resources:
                 - "AMI"
             InstanceType: "t1.micro"
             IamInstanceProfile: 
-                Ref: IamInstanceProfileName
+                Fn::FindInMap: 
+                    - EnvironmentMapping
+                    - IamInstanceProfileName
+                    - Ref: EnvironmentName
             KeyName: 
                 Ref: KeyPairName
             NetworkInterfaces: 
                 - AssociatePublicIpAddress: true
                   DeviceIndex: "0"
                   GroupSet: 
-                    - Ref: BastionHostsSecurityGroup
+                    - Fn::FindInMap: 
+                        - EnvironmentMapping
+                        - BastionHostsSecurityGroup
+                        - Ref: EnvironmentName
                   SubnetId: 
-                    Ref: PublicSubnet2
+                    Fn::FindInMap: 
+                        - EnvironmentMapping
+                        - PublicSubnet2
+                        - Ref: EnvironmentName
             Tags:
                 - Key: Name
                   Value: !Sub ${EnvironmentName}-BastionHost-2

From 0ebbad7e794ba49f8534b5938940f6213f769e2c Mon Sep 17 00:00:00 2001
From: Rosie Storey <rstorey@loc.gov>
Date: Tue, 15 Jan 2019 15:41:40 -0500
Subject: [PATCH 05/15] Update the AMI used for bastion hosts

---
 cloudformation/infrastructure/bastion-hosts.yaml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/cloudformation/infrastructure/bastion-hosts.yaml b/cloudformation/infrastructure/bastion-hosts.yaml
index f899c4594..dd6f87577 100644
--- a/cloudformation/infrastructure/bastion-hosts.yaml
+++ b/cloudformation/infrastructure/bastion-hosts.yaml
@@ -19,7 +19,7 @@ Parameters:
 Mappings:
     AWSRegionToAMI:
         us-east-1:
-            AMI: ami-04681a1dbd79675a5
+            AMI: ami-0080e4c5bc078760e
     
     EnvironmentMapping:
         IamInstanceProfileName:

From 8db1ba0fc325c5eb5bad35070287f9d33520cc64 Mon Sep 17 00:00:00 2001
From: Rosie Storey <rstorey@loc.gov>
Date: Tue, 15 Jan 2019 16:16:08 -0500
Subject: [PATCH 06/15] Download latest database dump to bastion hosts
 automatically on launch

---
 cloudformation/infrastructure/bastion-hosts.yaml | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/cloudformation/infrastructure/bastion-hosts.yaml b/cloudformation/infrastructure/bastion-hosts.yaml
index dd6f87577..4ae620f9a 100644
--- a/cloudformation/infrastructure/bastion-hosts.yaml
+++ b/cloudformation/infrastructure/bastion-hosts.yaml
@@ -83,6 +83,14 @@ Resources:
                         - EnvironmentMapping
                         - PublicSubnet1
                         - Ref: EnvironmentName
+            UserData:
+                Fn::Base64: !Join ["", [
+                  "#!/bin/bash -xe\n",
+                  "yum -y update\n",
+                  "yum -y install https://download.postgresql.org/pub/repos/yum/9.6/redhat/rhel-6-x86_64/pgdg-ami201503-96-9.6-2.noarch.rpm\n",
+                  "yum -y install postgresql96\n",
+                  "aws s3 cp s3://crowd-deployment/database-dumps/concordia.latest.dmp concordia.dmp\n"
+                ]]
             Tags:
                 - Key: Name
                   Value: !Sub ${EnvironmentName}-BastionHost-1     
@@ -116,6 +124,14 @@ Resources:
                         - EnvironmentMapping
                         - PublicSubnet2
                         - Ref: EnvironmentName
+            UserData:
+                Fn::Base64: !Join ["", [
+                  "#!/bin/bash -xe\n",
+                  "yum -y update\n",
+                  "yum -y install https://download.postgresql.org/pub/repos/yum/9.6/redhat/rhel-6-x86_64/pgdg-ami201503-96-9.6-2.noarch.rpm\n",
+                  "yum -y install postgresql96\n",
+                  "aws s3 cp s3://crowd-deployment/database-dumps/concordia.latest.dmp concordia.dmp\n"
+                ]]
             Tags:
                 - Key: Name
                   Value: !Sub ${EnvironmentName}-BastionHost-2

From 0112747521d2750162df4478439408f84b720f46 Mon Sep 17 00:00:00 2001
From: Rosie Storey <rstorey@loc.gov>
Date: Tue, 15 Jan 2019 16:21:54 -0500
Subject: [PATCH 07/15] UserData only works with Sub, not Join, in YAML format,
 and cfn-lint complains about Sub if you use it redundantly

---
 .../infrastructure/bastion-hosts.yaml         | 29 ++++++++++---------
 1 file changed, 15 insertions(+), 14 deletions(-)

diff --git a/cloudformation/infrastructure/bastion-hosts.yaml b/cloudformation/infrastructure/bastion-hosts.yaml
index 4ae620f9a..9647e64f4 100644
--- a/cloudformation/infrastructure/bastion-hosts.yaml
+++ b/cloudformation/infrastructure/bastion-hosts.yaml
@@ -84,13 +84,14 @@ Resources:
                         - PublicSubnet1
                         - Ref: EnvironmentName
             UserData:
-                Fn::Base64: !Join ["", [
-                  "#!/bin/bash -xe\n",
-                  "yum -y update\n",
-                  "yum -y install https://download.postgresql.org/pub/repos/yum/9.6/redhat/rhel-6-x86_64/pgdg-ami201503-96-9.6-2.noarch.rpm\n",
-                  "yum -y install postgresql96\n",
-                  "aws s3 cp s3://crowd-deployment/database-dumps/concordia.latest.dmp concordia.dmp\n"
-                ]]
+                Fn::Base64: !Sub |
+                  #!/bin/bash -xe
+                  echo "Running userdata for ${EnvironmentName}"
+                  yum -y update
+                  yum -y install https://download.postgresql.org/pub/repos/yum/9.6/redhat/rhel-6-x86_64/pgdg-ami201503-96-9.6-2.noarch.rpm
+                  yum -y install postgresql96
+                  aws s3 cp s3://crowd-deployment/database-dumps/concordia.latest.dmp concordia.dmp
+                
             Tags:
                 - Key: Name
                   Value: !Sub ${EnvironmentName}-BastionHost-1     
@@ -125,13 +126,13 @@ Resources:
                         - PublicSubnet2
                         - Ref: EnvironmentName
             UserData:
-                Fn::Base64: !Join ["", [
-                  "#!/bin/bash -xe\n",
-                  "yum -y update\n",
-                  "yum -y install https://download.postgresql.org/pub/repos/yum/9.6/redhat/rhel-6-x86_64/pgdg-ami201503-96-9.6-2.noarch.rpm\n",
-                  "yum -y install postgresql96\n",
-                  "aws s3 cp s3://crowd-deployment/database-dumps/concordia.latest.dmp concordia.dmp\n"
-                ]]
+                Fn::Base64: !Sub |
+                  #!/bin/bash -xe
+                  echo "Running userdata for ${EnvironmentName}"
+                  yum -y update
+                  yum -y install https://download.postgresql.org/pub/repos/yum/9.6/redhat/rhel-6-x86_64/pgdg-ami201503-96-9.6-2.noarch.rpm
+                  yum -y install postgresql96
+                  aws s3 cp s3://crowd-deployment/database-dumps/concordia.latest.dmp concordia.dmp
             Tags:
                 - Key: Name
                   Value: !Sub ${EnvironmentName}-BastionHost-2

From 267765833cfbe9e2212479841331b1052321b155 Mon Sep 17 00:00:00 2001
From: Rosie Storey <rstorey@loc.gov>
Date: Tue, 15 Jan 2019 16:31:59 -0500
Subject: [PATCH 08/15] Allow Jenkins to set ENV_NAME for creating bastion
 hosts

---
 cloudformation/create_bastion_hosts.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/cloudformation/create_bastion_hosts.sh b/cloudformation/create_bastion_hosts.sh
index 4c04909a7..bf8dd8102 100755
--- a/cloudformation/create_bastion_hosts.sh
+++ b/cloudformation/create_bastion_hosts.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
 
-export ENV_NAME=dev
+export ENV_NAME=${ENV_NAME:-dev}
 
 aws cloudformation create-stack --stack-name "${ENV_NAME}-bastionhosts"  --template-url https://s3.amazonaws.com/crowd-deployment/infrastructure/bastion-hosts.yaml --parameters "ParameterKey=EnvironmentName,ParameterValue=${ENV_NAME}" ParameterKey=KeyPairName,ParameterValue=rstorey@loc.gov
\ No newline at end of file

From f306a82288dd2f9998088d572336440a9a39c19e Mon Sep 17 00:00:00 2001
From: Rosie Storey <rstorey@loc.gov>
Date: Wed, 16 Jan 2019 14:23:47 -0500
Subject: [PATCH 09/15] Use secretsmanager to look up DB password instead of
 providing at stack creation

---
 cloudformation/master.yaml | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/cloudformation/master.yaml b/cloudformation/master.yaml
index 76c5563da..cb40f3a3a 100644
--- a/cloudformation/master.yaml
+++ b/cloudformation/master.yaml
@@ -66,11 +66,6 @@ Parameters:
         Description: which version of the docker images to deploy
         Type: String
         Default: latest
-
-    MyDbPassword:
-        Description: Master database password to use for RDS
-        Type: String
-        NoEcho: true
     
     EnvName:
         Description: which type of environment we are setting up
@@ -143,7 +138,7 @@ Resources:
         Properties:
             TemplateURL: "https://s3.amazonaws.com/crowd-deployment/infrastructure/rds.yaml"
             Parameters:
-                DbPassword: !Ref MyDbPassword
+                DbPassword: !Sub '{{resolve:secretsmanager:crowd/${EnvName}/DB/MasterUserPassword:SecretString:password}}'
                 DatabaseSecurityGroup: !GetAtt SecurityGroups.Outputs.DatabaseSecurityGroup
                 PrivateSubnet1: !GetAtt VPC.Outputs.PrivateSubnet1
                 PrivateSubnet2: !GetAtt VPC.Outputs.PrivateSubnet2

From 431cdec4465d23c83d0bcf28753becba3e4f4a45 Mon Sep 17 00:00:00 2001
From: Rosie Storey <rstorey@loc.gov>
Date: Wed, 16 Jan 2019 14:24:14 -0500
Subject: [PATCH 10/15] Separate cloudformation template for host used for data
 load

---
 cloudformation/infrastructure/data-load.yaml | 108 +++++++++++++++++++
 1 file changed, 108 insertions(+)
 create mode 100644 cloudformation/infrastructure/data-load.yaml

diff --git a/cloudformation/infrastructure/data-load.yaml b/cloudformation/infrastructure/data-load.yaml
new file mode 100644
index 000000000..e2f80de62
--- /dev/null
+++ b/cloudformation/infrastructure/data-load.yaml
@@ -0,0 +1,108 @@
+Description:
+  This template deploys a bastion host in each of the public subnets.
+
+Parameters:
+
+    EnvironmentName:
+        Description: An environment name that will be prefixed to resource names
+        Type: String
+        AllowedValues:
+          - dev
+          - test
+          - stage
+          - prod
+    
+    KeyPairName:
+        Description: key pair (within this region) for ECS instances access
+        Type: String
+
+    PostgresqlHost:
+        Description: the end point of the RDS database host to restore
+        Type: String
+
+    PostgresqlPassword:
+        Description: the password for the RDS endpoint to restore
+        Type: String
+        NoEcho: true        
+
+Mappings:
+    AWSRegionToAMI:
+        us-east-1:
+            AMI: ami-0080e4c5bc078760e
+    
+    EnvironmentMapping:
+        IamInstanceProfileName:
+            dev: crowd-dev-FargateCluster-WFCY4I0U7JSM-ConcordiaInstanceProfile-RQHLRZADDM9M
+            test: crowd-test-FargateCluster-1R5U1VT4HOYX2-ConcordiaInstanceProfile-1FJXY570ZM2O3
+            stage: crowd-stage-FargateCluster-1TBKSIZQKLJHV-ConcordiaInstanceProfile-1XG3TR3LY42ND
+            prod: crowd-prod-FargateCluster-1X1CI0J3HFJ9F-ConcordiaInstanceProfile-13SHE5FAB7D6Q
+
+        # The ID of the public subnet in the first AZ
+        # Type: AWS::EC2::Subnet::Id
+        PublicSubnet1:
+            dev: subnet-079b5dd4f9acf44e6
+            test: subnet-06f443ea589879e8d
+            stage: subnet-06f40e2fc8d891692
+            prod: subnet-09fdaf1c5c73f588f
+    
+        # The ID of the public subnet in the second AZ
+        # Type: AWS::EC2::Subnet::Id
+        PublicSubnet2:
+            dev: subnet-01d6614725c7dabd6
+            test: subnet-05a15c6058ebdf54f
+            stage: subnet-0a022eb0c614b0b00
+            prod: subnet-01580e2a4d6d42b52
+
+        # The security group for bastion hosts
+        # Type: AWS::EC2::SecurityGroup::Id
+        BastionHostsSecurityGroup:
+            dev: sg-062afe8941ace25ad
+            test: sg-0208b0df704b66c3c
+            stage: sg-0a2175a2df32a4332
+            prod: sg-066c68e77787b2a10
+
+Resources:
+
+    DataLoadHost:
+        Type: AWS::EC2::Instance
+        Properties: 
+            ImageId: 
+                Fn::FindInMap: 
+                - AWSRegionToAMI
+                - Ref: "AWS::Region"
+                - "AMI"
+            InstanceType: "t1.micro"
+            IamInstanceProfile: 
+                Fn::FindInMap: 
+                    - EnvironmentMapping
+                    - IamInstanceProfileName
+                    - Ref: EnvironmentName
+            KeyName: 
+                Ref: KeyPairName
+            NetworkInterfaces: 
+                - AssociatePublicIpAddress: true
+                  DeviceIndex: "0"
+                  GroupSet: 
+                    - Fn::FindInMap: 
+                        - EnvironmentMapping
+                        - BastionHostsSecurityGroup
+                        - Ref: EnvironmentName
+                  SubnetId: 
+                    Fn::FindInMap: 
+                        - EnvironmentMapping
+                        - PublicSubnet1
+                        - Ref: EnvironmentName
+            UserData:
+                Fn::Base64: !Sub |
+                  #!/bin/bash -xe
+                  echo "Running userdata for ${EnvironmentName}"
+                  yum -y update
+                  yum -y install https://download.postgresql.org/pub/repos/yum/9.6/redhat/rhel-6-x86_64/pgdg-ami201503-96-9.6-2.noarch.rpm
+                  yum -y install postgresql96
+                  aws s3 cp s3://crowd-deployment/database-dumps/concordia.latest.dmp concordia.dmp
+                  echo "${PostgresqlHost}:5432:*:concordia:${PostgresqlPassword}" >> /root/.pgpass
+                  chmod 0600 /root/.pgpass
+                  pg_restore --create --clean -Fc -U concordia -h ${PostgresqlHost} --dbname=postgres --no-password --no-owner --no-acl concordia.dmp
+            Tags:
+                - Key: Name
+                  Value: !Sub ${EnvironmentName}-DataLoadHost

From a6f870b9ecbea9bc1eb8b8bd214e29122598372e Mon Sep 17 00:00:00 2001
From: Rosie Storey <rstorey@loc.gov>
Date: Thu, 17 Jan 2019 10:47:20 -0500
Subject: [PATCH 11/15] Remove keypair name since no need to access the data
 load host, add priority for subdomain listener rule because it must be unique

---
 cloudformation/featurebranch.yaml               | 17 ++++++++++++++++-
 cloudformation/infrastructure/data-load.yaml    |  6 ------
 .../infrastructure/fargate-featurebranch.yaml   |  7 ++++++-
 3 files changed, 22 insertions(+), 8 deletions(-)

diff --git a/cloudformation/featurebranch.yaml b/cloudformation/featurebranch.yaml
index 12e17bd93..5336bbc90 100644
--- a/cloudformation/featurebranch.yaml
+++ b/cloudformation/featurebranch.yaml
@@ -17,7 +17,12 @@ Parameters:
         Description: an abbreviation used for creating short-named cloudformation resources
         Type: String
         Default: rel
-            
+    
+    Priority:
+        Type: Number
+        Description: Priority of the subdomain listener rule, must be unique in the set of listener rules
+        Default: 100
+
 Resources:
 
     RDS:
@@ -30,6 +35,15 @@ Resources:
                 PrivateSubnet1: 'subnet-0aa55b322229b945a'
                 PrivateSubnet2: 'subnet-0f65558b319b2d4dc'
 
+    DataLoadHost:
+        Type: AWS::CloudFormation::Stack
+        Properties:
+            TemplateURL: 'https://s3.amazonaws.com/crowd-deployment/infrastructure/data-load.yaml'
+            Parameters:
+                PostgresqlHost: !GetAtt RDS.Outputs.DatabaseHostName
+                PostgresqlPassword: '{{resolve:secretsmanager:crowd/test/DB/MasterUserPassword:SecretString:password}}'
+                EnvironmentName: 'test'
+
     ElastiCache:
         Type: AWS::CloudFormation::Stack
         Properties:
@@ -56,3 +70,4 @@ Resources:
                 MemcachedAddress: !GetAtt ElastiCache.Outputs.MemcachedAddress
                 MemcachedPort: !GetAtt ElastiCache.Outputs.MemcachedPort
                 DatabaseEndpoint: !GetAtt RDS.Outputs.DatabaseHostName
+                Priority: !Ref Priority
diff --git a/cloudformation/infrastructure/data-load.yaml b/cloudformation/infrastructure/data-load.yaml
index e2f80de62..38fa00e4e 100644
--- a/cloudformation/infrastructure/data-load.yaml
+++ b/cloudformation/infrastructure/data-load.yaml
@@ -11,10 +11,6 @@ Parameters:
           - test
           - stage
           - prod
-    
-    KeyPairName:
-        Description: key pair (within this region) for ECS instances access
-        Type: String
 
     PostgresqlHost:
         Description: the end point of the RDS database host to restore
@@ -77,8 +73,6 @@ Resources:
                     - EnvironmentMapping
                     - IamInstanceProfileName
                     - Ref: EnvironmentName
-            KeyName: 
-                Ref: KeyPairName
             NetworkInterfaces: 
                 - AssociatePublicIpAddress: true
                   DeviceIndex: "0"
diff --git a/cloudformation/infrastructure/fargate-featurebranch.yaml b/cloudformation/infrastructure/fargate-featurebranch.yaml
index e95aaf342..59c7d84d8 100644
--- a/cloudformation/infrastructure/fargate-featurebranch.yaml
+++ b/cloudformation/infrastructure/fargate-featurebranch.yaml
@@ -67,6 +67,11 @@ Parameters:
         Type: String
         Description: name of the S3 bucket (public) where exported transcriptions will be stored
 
+    Priority:
+        Type: Number
+        Description: Priority of the subdomain listener rule, must be unique in the set of listener rules
+        Default: 100
+
 
 Resources:
 
@@ -102,7 +107,7 @@ Resources:
           Values:
             - !Ref CanonicalHostName
       ListenerArn: arn:aws:elasticloadbalancing:us-east-1:619333082511:listener/app/crowd-test/81e4820e354ea810/187fd94e534ad833
-      Priority: 100
+      Priority: !Ref Priority
 
   ConcordiaTask:
     Type: AWS::ECS::TaskDefinition

From 109f4203dd609c76bcfa945f2c36a875a1c9c468 Mon Sep 17 00:00:00 2001
From: Rosie Storey <rstorey@loc.gov>
Date: Thu, 17 Jan 2019 10:56:11 -0500
Subject: [PATCH 12/15] Remove unused create bastion hosts script

---
 cloudformation/create_bastion_hosts.sh | 5 -----
 1 file changed, 5 deletions(-)
 delete mode 100755 cloudformation/create_bastion_hosts.sh

diff --git a/cloudformation/create_bastion_hosts.sh b/cloudformation/create_bastion_hosts.sh
deleted file mode 100755
index bf8dd8102..000000000
--- a/cloudformation/create_bastion_hosts.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/bash
-
-export ENV_NAME=${ENV_NAME:-dev}
-
-aws cloudformation create-stack --stack-name "${ENV_NAME}-bastionhosts"  --template-url https://s3.amazonaws.com/crowd-deployment/infrastructure/bastion-hosts.yaml --parameters "ParameterKey=EnvironmentName,ParameterValue=${ENV_NAME}" ParameterKey=KeyPairName,ParameterValue=rstorey@loc.gov
\ No newline at end of file

From 532e942e19b194133f14b7f9f1c0608d1b215898 Mon Sep 17 00:00:00 2001
From: Rosie Storey <rstorey@loc.gov>
Date: Thu, 17 Jan 2019 11:05:30 -0500
Subject: [PATCH 13/15] Use private subnet for data load host

---
 cloudformation/infrastructure/data-load.yaml | 22 ++++++--------------
 1 file changed, 6 insertions(+), 16 deletions(-)

diff --git a/cloudformation/infrastructure/data-load.yaml b/cloudformation/infrastructure/data-load.yaml
index 38fa00e4e..5188c35ed 100644
--- a/cloudformation/infrastructure/data-load.yaml
+++ b/cloudformation/infrastructure/data-load.yaml
@@ -33,21 +33,11 @@ Mappings:
             stage: crowd-stage-FargateCluster-1TBKSIZQKLJHV-ConcordiaInstanceProfile-1XG3TR3LY42ND
             prod: crowd-prod-FargateCluster-1X1CI0J3HFJ9F-ConcordiaInstanceProfile-13SHE5FAB7D6Q
 
-        # The ID of the public subnet in the first AZ
-        # Type: AWS::EC2::Subnet::Id
-        PublicSubnet1:
-            dev: subnet-079b5dd4f9acf44e6
-            test: subnet-06f443ea589879e8d
-            stage: subnet-06f40e2fc8d891692
-            prod: subnet-09fdaf1c5c73f588f
-    
-        # The ID of the public subnet in the second AZ
-        # Type: AWS::EC2::Subnet::Id
-        PublicSubnet2:
-            dev: subnet-01d6614725c7dabd6
-            test: subnet-05a15c6058ebdf54f
-            stage: subnet-0a022eb0c614b0b00
-            prod: subnet-01580e2a4d6d42b52
+        PrivateSubnet1:
+            dev: subnet-0c95a830ce007fa65
+            test: subnet-0aa55b322229b945a
+            stage: subnet-0f7c7d66b66d6dd90
+            prod: subnet-0da84976b66c32ce4
 
         # The security group for bastion hosts
         # Type: AWS::EC2::SecurityGroup::Id
@@ -84,7 +74,7 @@ Resources:
                   SubnetId: 
                     Fn::FindInMap: 
                         - EnvironmentMapping
-                        - PublicSubnet1
+                        - PrivateSubnet1
                         - Ref: EnvironmentName
             UserData:
                 Fn::Base64: !Sub |

From 06ec64884d92643022c3bdf2f6f814031dfca725 Mon Sep 17 00:00:00 2001
From: Rosie Storey <rstorey@loc.gov>
Date: Thu, 17 Jan 2019 11:28:56 -0500
Subject: [PATCH 14/15] Update template description for data load

---
 cloudformation/infrastructure/data-load.yaml | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/cloudformation/infrastructure/data-load.yaml b/cloudformation/infrastructure/data-load.yaml
index 5188c35ed..c7a13a84a 100644
--- a/cloudformation/infrastructure/data-load.yaml
+++ b/cloudformation/infrastructure/data-load.yaml
@@ -1,6 +1,7 @@
 Description:
-  This template deploys a bastion host in each of the public subnets.
-
+  This template deploys a host in a private subnet and loads the most recent
+  database dump to the specified database server.
+  
 Parameters:
 
     EnvironmentName:

From 32d42b3e6d1837ff82737a4796ea74fdc1e1c776 Mon Sep 17 00:00:00 2001
From: Rosie Storey <rstorey@loc.gov>
Date: Thu, 17 Jan 2019 13:36:57 -0500
Subject: [PATCH 15/15] Shutdown data load host when restore process is done,
 and terminate the instance

---
 cloudformation/infrastructure/data-load.yaml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/cloudformation/infrastructure/data-load.yaml b/cloudformation/infrastructure/data-load.yaml
index c7a13a84a..b889d5107 100644
--- a/cloudformation/infrastructure/data-load.yaml
+++ b/cloudformation/infrastructure/data-load.yaml
@@ -64,6 +64,7 @@ Resources:
                     - EnvironmentMapping
                     - IamInstanceProfileName
                     - Ref: EnvironmentName
+            InstanceInitiatedShutdownBehavior: terminate
             NetworkInterfaces: 
                 - AssociatePublicIpAddress: true
                   DeviceIndex: "0"
@@ -88,6 +89,7 @@ Resources:
                   echo "${PostgresqlHost}:5432:*:concordia:${PostgresqlPassword}" >> /root/.pgpass
                   chmod 0600 /root/.pgpass
                   pg_restore --create --clean -Fc -U concordia -h ${PostgresqlHost} --dbname=postgres --no-password --no-owner --no-acl concordia.dmp
+                  shutdown -h now
             Tags:
                 - Key: Name
                   Value: !Sub ${EnvironmentName}-DataLoadHost