Certificates
Table of contents
- Add and configure the ACME provisioner to the Intermediate CA
- Install step cli tool on the freeradius instance and “connect” it to our intermediate
- Create a template for the server certificate
- Request a certificate using ACME
- Renew a Certificate using ACME
The next step is to set up certificates.
We won’t use freeradius bundled openssl to generate our PKI, we already have our own.
Here are all the steps involved:
- Add and configure the ACME provisioner to the Intermediate CA
- Install step cli tool on the freeradius instance and “connect” it to our intermediate
- Create a template for the server certificate
- Request a certificate using ACME
- Set up automated renewal with systemd timers
Before we start, we need to provide our radius server the “full chain of trust”, that means providing all the intermediates to build back the chain until the root CA.
In short, we need to copy over the certs for our root CA, the intermediate CA which will sign the radius server cert and the intermediate CA used for SCEP client certificates.
Put all these certs in the /etc/freeradius/certs/ folder.
Add and configure the ACME provisioner to the Intermediate CA
Let’s now set up the ACME provisioner on our intermediate CA.
We are going to use the most simple challenge available (http-01), which is safe enough since we are on an internal domain and we are controlling DNS.
What that means is that our radius server, to prove its identity, needs to make a specific file available at a specific location on its web server.
The step client will take care of this by itself.
Here’s our command on the intermediate:
step ca provisioner add <name> --type=ACME --force-cn --challenge=http-01
Here’s the schema if you prefer to manually edit your ca.json file.
Install step cli tool on the freeradius instance and “connect” it to our intermediate
Now let’s head over to our radius server and install the step command tool (check for the latest version available first and adjust the command accordingly).
wget https://github.com/smallstep/cli/releases/download/v0.24.4/step-cli_0.24.4_amd64.deb
dpkg -i step-cli_0.24.4_amd64.deb
Let’s bootstrap the connection with the CA
step ca bootstrap --ca-url [CA URL] --fingerprint [CA fingerprint]
Create a template for the server certificate
Head back to your intermediate CA and create the $STEPPATH/templates/certs/x509 directory.
When you’re into the just created directory, run:
cat <<EOF > server_leaf.tpl
{
"subject": {
"country": "US",
"organization": "My Org",
"commonName": {{ toJson .Subject.CommonName }}
},
"sans": {{ toJson .SANs }},
"keyUsage": ["keyEncipherment", "digitalSignature"],
"extKeyUsage": ["serverAuth", "clientAuth"],
"policyIdentifiers" : ["1.3.6.1.4.1.40808.1.3.2"]
}
EOF
Notice that we add both the serverAuth and clientAuth keys, otherwise we won’t be able to renew this cert as the ACME client will use that same cert to authenticate as a CLIENT to the ACME server. If we only authorize this as a server certificate, the ACME server will refuse to establish a TLS connection with the client and won’t renew the certificate.
To know more about the policyIdentifiers object that we added, read here.
Country and Organization are not mandatory, I just like to have them there, but feel free to skip them or to add more properties. Just be aware that the ACME provisioner doesn’t support the –set and –set-file keys, so you can’t set those variables with the request.
Now we need to add this template to our provisioner
step ca provisioner update acme --x509-template=$(step path)/templates/certs/x509/server_leaf.tpl
Otherwise you can, as usually, edit the ca.json config file. Find the options key inside the ACME provisioner and edit it to look like this:
"options": {
"x509": {
"templateFile": "templates/certs/x509/server_leaf.tpl"
},
"ssh": {}
}
Just be aware that in this case, all servers using this provisioner, will get a certificate based upon this template.
Request a certificate using ACME
Ok, it’s time to get our certificate. Head back to your freeradius server and put the password you’ve chosen (a strong one, as always) for your private key in a txt file.
Now run the following command.
step ca certificate <common_name> \
/etc/freeradius/certs/server.pem \
/etc/freeradius/certs/server.key \
--provisioner=acme --kty=RSA \
--password-file password_file.txt
Use your FQDN as commonName for this cert.
And now we have obtained a server.pem certificate for our radius server.
There are just two steps that we need to take:
Adjust the file permissions:
chmod g+r server.pem server.key
Create symbolic links for all your certs using their hashed values as file names. This is as simple as running the c_rehash command:
c_rehash /etc/freeradius/certs/
The purpose of this is to allow the ssl library to find the required public_key in the certificate folder whenever it needs to verify a chain.
Renew a Certificate using ACME
Renewing a certificate is done with the following command
step ca renew /etc/freeradius/certs/server.pem /etc/freeradius/certs/server.key -f
After this we’d have to rehash the certificate and restart freeradius.
Of course we don’t really want to bother doing this manually every time, let’s follow the smallstep guide to automate all of this using systemd timers.
First of all, the cert renewer service.
Head to /etc/systemd/system/ and create the cert-renewer@.service file
Put this in your file and save it.
Next step is to create an override file specific for freeradius.
Let’s first create the /etc/systemd/system/cert-renewer@freeradius.service.d/ directory.
Create an override.conf file in that directory and add this content to the file.
[Service]
Environment=CERT_LOCATION=/etc/freeradius/certs/server.pem \
KEY_LOCATION=/etc/freeradius/certs/server.key
ExecStartPost=
ExecStartPost=/usr/bin/c_rehash /etc/freeradius/certs/
ExecStartPost=/usr/bin/env sh -c "! systemctl --quiet is-active %i.service || systemctl restart %i"
In case your files are in a different directory or have a different name, adjust the file accordingly. Be sure to check $STEPPATH as well, in my case it was still pointing at the .scep/ folder in my home dir.
The reason why we are restarting the freeradius service is to pick up the new certificate. A simple reload (SIGHUP) won’t load the certificate.
Last step is to create and start the timer.
Create the /etc/systemd/system/cert-renewer@.timer file and paste this in.
Now save the file and run this command to enable the timer for our service:
systemctl enable --now cert-renewer@freeradius.timer
And, we’re done. Our server certificate (which by default is valid for 24hours only) will automatically renew around 8 hours before its expiration.