Setting up HTTPS on an AWS Load Balancer

Context

This was my first time setting up HTTPS using a real certificate rather than a self-signed one.  This way you get that nice lock symbol + https in your browser without the user seeing the obnoxious “do you trust this site, continue unsafely” warnings.

Steps

Generate a Key Pair

Note that for common name you should use the DNS name that you will be using for the website (or load balancer in front of the website).  This is important.  E.g. *.appname.yourcompany.com.  This one is in case of a wildcard cert to handle anything in front of the app-name as well.

openssl req -new -newkey rsa:2048 -nodes -keyout appname.key -out appname.csr

Do not lose this key pair! Store it somewhere safe and backed up.

Request a Certificate from DigiCert/etc

Go to DigiCert or whatever service your company uses.  Request a standard SSL certificate using the files you generated above.

For the case of a wild-card cert, you will want to add Subject Alternative Names (SANs) for appname.yourcompany.com and *.appname.yourcompany.com.

If you get odd failure messages, these sites tend to have something to validate your CSR.  In my case, I think it made me go remake the CSR without a password before it would accept it.  This was only obvious from the validator; the initial messages were just confusing.

Note: The server name and location fields don’t seem to matter much.  I just put AWS for location and my app name with some environment suffix for the server name (nothing exists with this name).

Add Your Certificate to the AWS Certificate Manager

Once your certificate comes back from Digicert, you can upload it to the Certificate Manager in AWS.  The body is the certificate returned to you from Digicert/etc.  The private key is the one you generated above.  The certificate chain just needed the “intermediate certificate” that Digicert returned to me along with the new certificate (and only that, don’t put your certificate in there as well).

Create Your Load Balancer

Go to EC2 and create a new network load balancer.  Add a TLS (Secure TCP) listener and on the security settings page, pick “Choose a certificate from ACM (recommended)”.  Then you can select your certificate.

Create Your DNS Name

Contact your system admins to create a DNS name for you with the name you used in your certificate request (e.g. appname.yourcompany.com from above).  Point it at the IP of the load balancer.  You will have to resolve the load balancer name to an IP for this (I’m not sure that is best practice, so you may want to read up more before following this last step).

All Done!

Assuming your load balancer points to an application now, you can use https to talk to talk to the DNS name of the load balancer, and the load balancer will take it, terminate the TLS, and forward to your application.  So, you’re good!

 

Ansible – Install AWS CLI and Log in To Amazon ECR Docker Registry via Ansible

There is probably a much cleaner way of doing this using off-the-shelf automations.  But I was just following along with the AWS installation instructions and got this working.

- name: Download AWS CLI bundle.
shell: "cd /tmp && rm -rf /tmp/awscli* && curl 'https://s3.amazonaws.com/aws-cli/awscli-bundle.zip' -o 'awscli-bundle.zip'"

- name: Update repositories cache and install "unzip" package
apt:
name: unzip
update_cache: yes

- name: Unzip AWS CLI bundle.
shell: "cd /tmp && unzip awscli-bundle.zip"

- name: Run AWS CLI installer.
shell: "/tmp/awscli-bundle/install -i /usr/local/aws -b /usr/local/bin/aws"

- name: Log into aws ecr docker registry
when: jupyterhub__notebook_registry != ''
shell: "$(/usr/local/bin/aws ecr get-login --no-include-email --region us-east-1)"

In order to do the actual login, you need to ensure your EC2 instance has an IAM role assigned to it that has reader privileges. Then you should be all good!

Resolving the ContextualVersionConflict: (cryptography 1.7.1 (/usr/lib/python2.7/dist-packages) error.

I was trying to run ansible over a debian slim docker image and I got this error, which was rather cryptic.  There wasn’t any particularly good information on google for fixing it either.

ContextualVersionConflict: (cryptography 1.7.1 (/usr/lib/python2.7/dist-packages), Requirement.parse(‘cryptography>=2.5’), set([‘paramiko’]))
ERROR! Unexpected Exception, this is probably a bug: (cryptography 1.7.1 (/usr/lib/python2.7/dist-packages), Requirement.parse(‘cryptography>=2.5’), set([‘paramiko’]))
the full traceback was:

Traceback (most recent call last):
File “/usr/local/bin/ansible-playbook”, line 97, in <module>
mycli = getattr(__import__(“ansible.cli.%s” % sub, fromlist=[myclass])…

In my case, running this before my ansible install resolved the issue.  It just forces an upgrade to a newer version which ansible is okay with.  Of course, if you were dependent on the lesser version this may not be an option.

pip install –force-reinstall cryptography==2.7

 

Git – Make File Executable in Repository

When you’re deploying code, you often want the files you have checked out of git to be executable.  For example, if you have a script for automation, you want to be able to do ./script rather than “bash script” or “python script”.  That way the #! line takes care of doing the right thing.

You can actually make a file “executable” in git by doing this command before your push:

git update-index --chmod=+x somefile.sh

 

Jenkins – su to Jenkins User

Today I was setting up a new Jenkins server to run docker image builds and pushes to Amazon ECR.

Jenkins installed fine, as did the AWS CLI, and docker.  Unfortunately, when I went to use docker against AWS from Jenkins, I had some integration issues at first (which is less than surprising).

Anyway! this required me to become the “jenkins” user which Jenkins runs as by default when installed with its normal installers.  Unfortunately, when you try to “su – jenkins”, you will find that not much happens.

I found in this stack-overflow post that this is because the jenkins user is a service account not made for interactive terminals.  Here is the quote:

Jenkins is a service account, it doesn’t have a shell by design. It is generally accepted that service accounts shouldn’t be able to log in interactively

If for some reason you want to login as jenkins, you can do so with: sudo su -s /bin/bash jenkins

So, just do the following and you’ll be fine.

sudo su -s /bin/bash jenkins