Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save slawekzachcial/82062f78a0f1cb012cd63eb560bc3976 to your computer and use it in GitHub Desktop.
Save slawekzachcial/82062f78a0f1cb012cd63eb560bc3976 to your computer and use it in GitHub Desktop.
Self Signed Certificates with Custom Root CA and Root CA Key Encrypted with AWS KMS

This Gist is based on Self Signed Certificate with Custom Root CA gist.

It adds the use of AWS KMS to generate and decrypt the Root CA private key, so that this key does not need to be stored in plaintext. Instead, the key is stored encrypted, and is being decrypted using AWS KMS only when needed.

Create AWS KMS CMK - Done Once

Create symmetic CMK (customer-managed key) and give it an alias of alias/root-ca-encrypting-key that will be used later to reference to it:

aws kms create-key --description "Root CA encrypting key"
aws kms create-alias \
  --alias-name "alias/root-ca-encrypting-key" \
  --target-key-id "<key ID from create-key above>"

Source: create-key, create-alias

Create Root CA - Done Once

Create Encrypted Root Key

Create the key used to sign the certificates by our custom Root CA:

aws kms generate-data-key-pair-without-plaintext \
  --key-id "alias/root-ca-encrypting-key" \
  --key-pair-spec RSA_4096

The value of PrivateKeyCiphertextBlob in the output JSON contains Base64-encoded, CMK-encrypted key of our custom Root CA. Let's assume it was saved to encryptedRootCA.key file.

To get the plaintext value of the Root CA key the following commands will be used in the sections below:

aws kms decrypt \
  --ciphertext-blob fileb://encryptedRootCA.key \
  --key-id "alias/root-ca-encrypting-key" \
  --output text \
  --query Plaintext \
| base64 --decode

This will print the key in binary format to standard output that can be then consumed by referencing file /dev/stdin and specifying the key form as DER -keyform der.

Source: generate-data-key-pair-without-plaintext, decrypt

Create and Self-Sign the Root Certificate

Generate our custom Root CA certificate:

aws kms decrypt \
  --ciphertext-blob fileb://encryptedRootCA.key \
  --key-id "alias/root-ca-encrypting-key" \
  --output text \
  --query Plaintext \
| base64 --decode \
| openssl req -x509 -new -nodes -sha256 -days 1024 -out rootCA.crt \
    -key /dev/stdin -keyform der \
    -subj "/C=US/ST=CA/O=MyOrg, Inc./CN=My Root CA"

The first 2 commands decrypt our custom Root CA key using KMS and then pass it, using standard output, to openssl that reads it from /dev/stdin. The final command generates rootCA.crt file that contains our custom Root CA certificate.

Create Server Certificate - Done For Each Server

Create Server Certificate Key

openssl genrsa -out mydomain.com.key 2048

Create Server Certificate Signing Request (CSR)

openssl req -new -sha256 -key mydomain.com.key -out mydomain.com.csr \
  -subj "/C=US/ST=CA/O=MyOrg, Inc./CN=mydomain.com"

Generate Certificate Issued by Custom Root CA

aws kms decrypt \
  --ciphertext-blob fileb://encryptedRootCA.key \
  --key-id "alias/root-ca-encrypting-key" \
  --output text \
  --query Plaintext \
| base64 --decode \
| openssl x509 -req -in mydomain.com.csr \
    -CA rootCA.crt -CAkey /dev/stdin -CAkeyform der \
    -CAcreateserial -out mydomain.com.crt -days 500 -sha256

The command generates mydomain.com.crt certificate that was issued by our custom Root CA.

@saurav-pratik
Copy link

Hi. The steps here is for Symmetric keys. Can we use asymmetric keys and create a self signed certificate.

As per the documentation , generate-data-key-pair-without-plaintext does not work for Asymmetric keys.

@mderriey
Copy link

mderriey commented Dec 5, 2023

I'm using the AWS CLI v2.14.5 and the aws kms decrypt commands fail with the following error message:

An error occurred (InvalidCiphertextException) when calling the Decrypt operation:

I found the solution at aws/aws-cli#1043 (comment), which is to base64-decode the ciphertext blob that gets fed to the AWS CLI.

aws kms decrypt \
  --ciphertext-blob file://<(cat encryptedRootCA.key | base64 --decode) \
  [rest of parameters]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment