So, I happened upon a particularly tricky issue. I am using the AWS Beijing Region (cn-north-1
) and I wanted to create a CloudFormation template of our environment. Amazon provides a template called CloudFormer in their CloudFormation page
What this does is create an EC2 instance based on that template as well as the resoruces below:
Once the stack is created, on the Outputs tab in CloudFormation, you can see the endpoint URL that you use to access the application.
If you try to access this, it doesn’t work. The reason is due to China regulations, the default web application ports of 80 and 443 are blocked. So how do we access CloudFormer to generate our stack? Well, we change the default port for our application from 443 to another one, say 8443. To do so, we’d need to ssh into the EC2 instance, change the ports and we should be good. Easy, right? Well, not quite.
Add SSH Key to EC2 machine
First, what is the SSH key associated with this instance? Well it seems there are no keys associated with this instance - because the creators of this template didn’t need to provide one. There’s no need to, but we need access. So we’d need to find a way to add a key to an existing EC2 instance. Researching this line - it seemed a bit of work. An easier way would be if we could have the CloudFormer template to associate a key with the EC2 instance while it was creating this stack.
Edit the CloudFormer template
Note: You can skip this section and download the edited CloudFormation template from this pastebin. If you’re interested on the how, read on:
Grab the template JSON from the Template tab.
Edit this to add a key parameter under the Parameters
node:
"KeyName": {
"Type": "String",
"Description": "Keyname for the keypair that to login to EC2 instances",
"Default": "My Key Pair"
}
so that it looks like so:
And associate this key with the EC2 instance. Search for the node Properties
under WebServer
and add this node
"KeyName": {
"Ref": "KeyName"
},
Set the Default
value for the KeyName
to your key (which can be found under Key Pairs)
Now delete the earlier CloudFormer stack (if you have one).
And generate a new stack by pointing to this edited template
Add Incoming ports to Security Group
Now before logging in you need to add incoming port 22 to the Security Group the EC2 is part of. You can find this out, by clicking:
Edit to add port 22 Inbound from your IP (rather than 0.0.0.0/0)
Login to the EC2 to change Ports
You now have an EC2 machine with a key to login to.
Now, I had no idea what webserver this was on, it wasn’t Apache. Looking at htop for services LISTENing on port 443 we see
This provides a clue - “thin server”. Googling for “thin server”, I see that it’s a Ruby webserver. Since this auto starts with the EC2 server, we look at /etc/rc.d/rc.local
(this script file is run once, before all other scripts have run but before the logon prompt appears) to see the command that starts the Ruby webserver. We see:
[ec2-user@ip-172-31-4-114 ~]$ more /etc/rc.d/rc.local
#!/bin/sh
#
# This script will be executed *after* all the other init scripts.
# You can put your own initialization stuff in here if you don't
# want to do the full Sys V style init stuff.
touch /var/lock/subsys/local
/usr/bin/cloudformer
Looking at the contents of the startup script /usr/bin/cloudformer
, we see:
[ec2-user@ip-172-31-4-114 ~]$ more /usr/bin/cloudformer
#!/usr/bin/env bash
cd /home/ec2-user/cloudformer
/usr/local/bin/thin start -p 443 -e production -d --ssl --ssl-key-file /home/ec2-user/cloudformer/.ssl/server.key --ssl-cert-file /home/ec2-user/cloudformer/.ssl/server.crt
We’ve finally reached the place where the port is specified! We can see that it’s 443. Hence, we edit /usr/bin/cloudformer
to change it to a port, say 8443. Now as before, edit your Security Group to add this port in the Incoming port section.
Access AWS CloudFormer
Reboot the EC2 instance and access the URL like so: https://<your_ec2_hostname>:8443/
. You do get a certificate error, but ignore and proceed. You can now create a CloudFormation template of your environment!