(Editor’s note: the past two posts, Mother Of Invention, Edge Case, and this one form a trilogy of sorts, all related to a particular project I’ve been digging into).
When I first needed a way to get access to AWS from a non-cloud-based computer, I implemented 3 options: hard-coded IAM user credentials (generally bad), user-based Cognito (okay but not super scalable), and X.509 via IoT (good technology, but cumbersome to set up).
This week I had a similar authentication need within an on-premises cluster, and was happy for the chance to learn the most up-to-date approach: IAM Roles Anywhere. I really appreciate the authors of these two blog posts who captured the step-by-step quite a bit better than the official documentation:
I used my own certificate authority because AWS Private CA is too dang expensive; $400 a month doesn’t grow on trees, ya know? Here’s the bash
script to create the root CA:
mkdir -p root-ca/certs # New Certificates issued are stored here
mkdir -p root-ca/db # Openssl managed database
mkdir -p root-ca/private # Private key dir for the CA
chmod 700 root-ca/private
touch root-ca/db/index
# Give our root-ca a unique identifier
openssl rand -hex 16 > root-ca/db/serial
# Create the certificate signing request
openssl req -new -config root-ca.conf -out root-ca.csr -keyout root-ca/private/root-ca.key
# Sign our request
openssl ca -selfsign -config root-ca.conf -in root-ca.csr -out root-ca.crt -extensions ca_ext
# Print out information about the created cert
openssl x509 -in root-ca.crt -text -noout
The output from the above is what’s used to create the Trust Anchor. Then here’s a script to create a certificate for the process that will be authenticating:
# Provide a name for the output files as a parameter
entity_name=$1
# Make your private key specific to your end entity
openssl genpkey -out $entity_name.key -algorithm RSA -pkeyopt rsa_keygen_bits:2048
# Using your newly generated private key make a certificate signing request
openssl req -new -key $entity_name.key -out $entity_name.csr
# Print out information about the created request
openssl req -text -noout -verify -in $entity_name.csr
# Sign the above cert
openssl ca -config root-ca.conf -in $entity_name.csr -out $entity_name.crt -extensions client_ext
# Print out information about the created cert
openssl x509 -in $entity_name.crt -text -noout
Special thanks also to the creator of iam-rolesanywhere-session, a Python package that makes it easy to create refreshable boto3 Session with IAM Roles Anywhere. Seriously, could it be easier?
from iam_rolesanywhere_session import IAMRolesAnywhereSession
roles_anywhere_session = IAMRolesAnywhereSession(
trust_anchor_arn=my_trust_anchor_arn,
profile_arn=my_profile_arn,
role_arn=my_role_arn,
certificate='my_certificate.crt',
private_key='my_certificate.key',
)
boto3_session = roles_anywhere_session.get_session()
s3_client = boto3_session.client('s3')
print(s3_client.list_buckets())
This was a good reminder that technology marches ever onward, and what made sense yesterday might not be the best approach today. It was also a reminder that, like DNS, TLS and PKI are some of those things that every technologist ought to know (I’ve queued up this book in my Goodreads for a deeper dive). This isn’t the first time I’ve had to write code to create certificates, but it’s now the last, because I’ll have this reference post plus its associated code repository. And so will you.