Get your self-service free hosted private certificate authority today

How to use ACME to authenticate to AWS


Carl Tashian
Carl Tashian

AWS’s new service IAM Roles Anywhere, launched in July, lets your servers authenticate to AWS using X.509 certificates. I’m a certificate nerd, so for me this is very exciting news!

Finally, AWS has given us the ability to delegate authentication to a Certificate Authority (CA).
Finally, we can stop managing long-lived IAM credentials, and automate AWS authentication using ACME instead. (ACME is the widely supported certificate automation protocol used by Let’s Encrypt.)

What this unlocks is very powerful–especially for multi-cloud or on-prem deployments, where you need to access AWS APIs from beyond the walled garden. A workload can non-interactively get a certificate from a local ACME Certificate Authority (CA), keep it renewed, and use the cert to get temporary IAM credentials from AWS on demand.

Certificates have a few special properties that make them useful for identity management. They can be renewed and revoked. They expire, sometimes very quickly. They are tied to a private key (which can be generated and stored non-exportably in a hardware security device!). And they contain CA-signed metadata like a hostname or email address that can be used for identity and independently verified by a third-party.

And, one certificate can be used to access multiple AWS accounts!

In this post, I want to show you how to create a CA and how to set up and configure IAM Roles Anywhere.

To access AWS with certificates instead of IAM credentials, I’ll help you configure credential sourcing that will work with the aws command and with any program that uses AWS’s official SDK.

Finally, I’ll show you how to add ACME server support and help you automate the certificate management side of things.

Getting started

You’ll need a CA for this project. That’s where we come in. You can run our open-source step-ca server or, for easy mode, jump over to Certificate Manager and create a free hosted CA in a few minutes.

Run your own step-ca server…

  1. Follow our Getting Started guide to initialize your PKI and start a CA.

  2. Install our open-source step CA client, so you can get certificates.

  3. Bootstrap your client to your CA server. To do this, you’ll need the CA URL and the root certificate fingerprint that the server prints when it starts up. Now run the following, substituting these values for your own:

    step ca bootstrap --ca-url https://ca.example.com:9000 --fingerprint 702a094e239c9eec6fEXAMPLE012825c5fe3d1ae1b2fd6ee
    

…or create a Certificate Manager CA

  1. Create a team here. Once you’ve signed up, create an Authority.

  2. Install our open-source step CA client, so you can get certificates.

  3. To bootstrap your client to your CA server, you’ll need the Authority’s CA URL and root fingerprint, which appear on the Authority detail page. Run the following, substituting these values for your own:

    step ca bootstrap --ca-url https://example.team.ca.smallstep.com --fingerprint 702a094e239c9eec6fEXAMPLE012825c5fe3d1ae1b2fd6ee
    

Now you’re ready to move on to configuring AWS.

Configuring IAM Roles Anywhere

This section is a quickstart. See the IAM Roles Anywhere documentation for a deeper dive into the AWS side of the configuration.

First, we’ll configure a trust anchor in the IAM management console, so that AWS trusts our CA.

In the management console, create a trust anchor for IAM Roles Anywhere. Give it a name, and choose “External certificate bundle” as the CA source. Then, paste in the contents of your root CA certificate PEM, which you can obtain by running step ca root in your terminal.

Screenshot: Creating an IAM Roles Anywhere trust anchor in the AWS management console

Choose “Create a trust anchor” to save it.

Next, we’ll create an IAM Roles Anywhere profile. A profile is a set of IAM Roles and additional policies that will be allowed by the IAM credentials issued by Roles Anywhere. You can only add Roles to a policy if they have an established trust relationship with IAM Roles Anywhere.

  1. Go to your IAM Roles and create or choose a role that you want to associate with IAM Roles Anywhere.
  2. Follow AWS’s instructions for configuring the role’s trust policy. Note that each Role also has a configurable Maximum Session Duration of between 1-12 hours.
  3. Repeat steps 1 and 2 for any other roles you want to use in IAM Roles Anywhere.
  4. Now create a Profile in Roles Anywhere, give it a name, and attach one or more of your Roles to the Profile. Note that a given Role can only be attached to a single Profile.

Screenshot: Creating an IAM Roles Anywhere profile in the AWS management console

When you establish these policies, you can use the certificate Subject or Issuer fields in your policy conditions. So, for example, you might establish an Organizational Unit (OU) within your PKI and constrain AWS access by that field. Or you could simply constrain access by user, using the Common Name (CN) certificate field.

Once you’ve added a trust anchor and a policy, you’re ready to test out your configuration on the client side.

Getting your first certificate

We’ll start by getting a certificate with step. Run:

step ca certificate carl.step.lan step.crt step.key

Replace my hostname with your own. For now, you’ll be asked to enter your CA password to get the certificate. Later, you can configure ACME for this step.

Output:

✔ Certificate: step.crt
✔ Private Key: step.key

Finally, let’s extract the intermediate certificate, which AWS needs in a separate file. Run:

cat step.crt | awk '/BEGIN CERTIFICATE/,/END CERTIFICATE/{ if(/BEGIN CERTIFICATE/){a++}; if(a==2){out="intermediate_ca.crt"; print >out}}'

You should have a file called intermediate_ca.crt that contains your Intermediate CA certificate:

step certificate inspect intermediate_ca.crt --short

Output:

X.509v3 Intermediate CA Certificate (ECDSA P-256) [Serial: 5123...6024]
  Subject:     Smallstep Intermediate CA
  Issuer:      Smallstep Root CA
  Valid from:  2022-07-10T23:44:53Z
          to:  2032-07-08T23:44:53Z

Now you’re ready to put the pieces together.

Using your certificate to get IAM Credentials

Now it’s time to configure AWS authentication. For this step, you’ll need to install the aws CLI tool.

For this piece, AWS provides a credential helper program that takes the cert and key as input, and outputs the temporary IAM credentials.

  1. Download the credential helper for your platform

  2. Test it out with the following command:

    ./aws_signing_helper credential-process \
          --intermediates intermediate_ca.crt \
          --certificate step.crt \
          --private-key step.key \
          --trust-anchor-arn arn:aws:rolesanywhere:region:account:trust-anchor/TA_ID \
          --profile-arn arn:aws:rolesanywhere:region:account:profile/PROFILE_ID \
          --role-arn arn:aws:iam::account:role/role-name-with-path
    

    Substitute the ARNs here for your trust anchor, profile, and desired role that you established earlier.

  3. If it works, you’ll see some IAM credentials output to the terminal.

  4. Now create an ~/.aws/config config file for AWS, to use the credential helper. Add the following:

    [default]
        credential_process = ./aws_signing_helper credential-process --certificate /path/to/step.crt --private-key /path/to/step.key --intermediates /path/to/intermediate_ca.crt --trust-anchor-arn arn:aws:rolesanywhere:region:account:trust-anchor/TA_ID --profile-arn arn:aws:rolesanywhere:region:account:profile/PROFILE_ID --role-arn arn:aws:iam::account:role/role-name-with-path
    

    Note: If you want to use the credential helper to access multiple roles or AWS accounts, you’ll just need to add additional profiles to this config file.

  5. Try running an aws CLI command. If your role supports it, the command should run successfully.

Your setup is complete. Most software that uses the AWS SDK will follow the credential flow we just set up, without any additional configuration.

Automating it for non-interactive workloads

At this point, you have the basic setup. When you automate this flow, you’ll need to tailor the automation to your workload’s environment. But, the general steps are the same for any environment:

  1. Add an ACME provisioner to your CA. See ACME Basics for details on how ACME works, and how to set it up on your CA.

  2. Configure your workload so that it gets a certificate via ACME when it is deployed/started, via step ca certificate or using any ACME-compatible client.

    It’s worth noting here that you could, with a few lines of Bash, wrap certificate automation around the aws_signing_helper. You could check if the current cert is missing or expired, and get a new one on demand:

    #!/bin/bash
    
    ACME_HOSTNAME=carl.step.lan
    CERT_LOCATION=/path/to/step.crt
    KEY_LOCATION=/path/to/step.key
    INTERMEDIATE_CA_PEM_LOCATION=/path/to/intermediate_ca.crt
    PROVISIONER_NAME=acme
    TRUST_ANCHOR_ARN=arn:aws:rolesanywhere:region:account:trust-anchor/TA_ID
    PROFILE_ARN=arn:aws:rolesanywhere:region:account:profile/PROFILE_ID
    ROLE_ARN=arn:aws:iam::account:role/role-name-with-path
    
    if ! [[ -f $CERT_LOCATION || -f $KEY_LOCATION ]]; then
      issue_cert=true
    else
      set +e
      step certificate needs-renewal $CERT_LOCATION --expires-in 0m 2> /dev/null
      retVal=$?
      if [[ "$retVal" = 0 || "$retVal" = 255 ]]; then
        issue_cert=true
      fi
      set -e
    fi
    
    if [ "$issue_cert" = true ]; then
      step ca certificate $ACME_HOSTNAME $CERT_LOCATION $KEY_LOCATION \
          --provisioner $PROVISIONER_NAME \
          --force
    fi
    
    /path/to/aws_signing_helper credential-process \
       --intermediates $INTERMEDIATE_CA_PEM_LOCATION \
       --certificate $CERT_LOCATION \
       --private-key $KEY_LOCATION \
       --trust-anchor-arn $TRUST_ANCHOR_ARN \
       --profile-arn $PROFILE_ARN \
       --role-arn $ROLE_ARN
    

    Just run this script as your credential process, instead of running aws_signing_helper directly.

  3. Or, if it doesn’t make sense in your case to wrap the credential process in a script, you can configure automated certificate renewal so that your cert is always valid when AWS needs it. We have several options for automated renewal in our documentation; which one you choose will depend on your environment.

  4. Of course, you could roll this all out with an IT automation tool.

Carl Tashian (LinkedIn, Twitter) has a couple decades of experience as an engineer, writer, and founder. Before Smallstep, he co-founded and built the engineering team at Trove. He also wrote the code that opens your Zipcar. These days he can be found down all the best PKI rabbit holes, chasing information to help you secure your infrastructure.

cta-icon
Subscribe to updates
Unsubscribe anytime, see Privacy Policy