Skip to content

Instantly share code, notes, and snippets.

@justinstoller
Forked from chadh/README.md
Created December 17, 2019 22:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save justinstoller/470f9f95dfdde4be3e8ee1c619707c7c to your computer and use it in GitHub Desktop.
Save justinstoller/470f9f95dfdde4be3e8ee1c619707c7c to your computer and use it in GitHub Desktop.
Puppet Server with AWS Certificate Manager as External Root CA

Here are the set of steps I ultimately came up with when trying to set up Puppet 6 servers in AWS using an ACM private CA for the Root.

  1. Create Private CA in AWS Certificate Manager

    • Type: Root
    • Common Name: domain.int (whatever you want)
    • Key Algorithm: RSA 2048
    • provide S3 Bucket for storing CRL
  2. Generate Private Key and CSR for each Puppet Server’s Intermediate CA certificate:

    • configuration for openssl command (certreq.cnf):
[ req ]
prompt = no

distinguished_name = req_distinguished_name
req_extensions = v3_req

[ req_distinguished_name ]
commonName             = "puppetserver1"

[ v3_req ]
subjectAltName = @alt_names

[alt_names]
DNS.1 = puppetserver1.domain.int
EOF
  • openssl req -config certreq.cnf -nodes -new -newkey rsa:2048 -days 3650 -keyout key.pem -out csr.pem
  1. Request a certificate from the Private CA from step 1. Note that you’ll need to provide the arn and region of the CA in the below command.
cert_arn=$(aws acm-pca issue-certificate --certificate-authority-arn "$CA_ARN" --template-arn arn:aws:acm-pca:::template/SubordinateCACertificate_PathLen0/V1 --csr "file:///$(pwd)/csr.pem" --signing-algorithm "SHA256WITHRSA" --validity Value=3650,Type="DAYS" --idempotency-token "$RANDOM" --region "$CA_REGION" | jq -r .CertificateArn)
  1. Using the certificate ARN and private CA, retrieve the x509 certificate chain containing the certificate issued in step 3 as well as the Root CA certificate:
aws acm-pca get-certificate --certificate-authority-arn "$CA_ARN" --certificate-arn "$cert_arn" --region "$CA_REGION" --output text | tr '\t' '\n' > certchain.pem
  1. Retrieve the Root CA CRL and reformat to PEM format
$ aws s3 cp "s3://<crl bucket for PCA>/crl/$(cut -d':' -f6 <<<"$CA_ARN" | cut -d'/' -f2).crl" raw.crl
$ openssl crl -inform DER -in raw.crl -outform PEM -out root_crl.pem
  1. Create a CRL for the new intermediate CA certificate:
    • configuration for openssl command (cacrl.cnf):
[ ca ]
default_ca = CA_default

[ CA_default ]
database = ./index.txt
crlnumber = ./crlnumber
default_md = sha256
crl_extensions = crl_ext
default_crl_days = 5475

[ crl_ext ]
authorityKeyIdentifier=keyid:always
  • create a couple requisite files and generate the CRL using stuff generated in previous commands:
touch index.txt
echo -ne "00" > crlnumber
openssl ca -config cacrl.cnf -keyfile key.pem -cert certchain.pem -gencrl -out int_crl.pem`
  1. At this point we have the following files associated with the intermediate CA:

    • key.pem - private key for intermediate CA
    • certchain.pem - certificate for intermediate CA + root CA
    • root_crl.pem - Root CRL
    • int_crl.pem - Empty intermediate CA CRL
  2. If there will be multiple Puppet servers issuing certificates to agents, then then every server will need to have the intermediate certificate and CRL of the other servers. It’s kind of hard to explain in words. The certchain.pem looks like this using the above process:

-----BEGIN CERTIFICATE-----
<encoded intermediate CA cert>
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
<encoded root CA cert>
-----END CERTIFICATE-----

If there are multiple puppet servers, the certchain.pem should be modified to look like this:

-----BEGIN CERTIFICATE-----
<endoded intermediate CA cert of puppetserver 1>
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
<encoded intermediate CA cert of puppetserver 2>
-----END CERTIFICATE-----
...
-----BEGIN CERTIFICATE-----
<encoded root CA cert>
-----END CERTIFICATE-----

The crl files need to be similarly merged (all int_crl.pem files concatenated with root_crl.pem at the very end.

  1. Finally the key, cert chain, and crl chain can be imported into Puppet:
puppetserver ca import --private-key "$tmpfile" --cert-bundle site-modules/profile/files/puppet/certs/ca.pem --crl-chain site-modules/profile/files/puppet/certs/crl.pem --certname puppetserver1 --subject-alt-names puppetserver1.domain.int
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment