Introduction
The current version 1.2.2-8 of the Univention Let’s Encrypt App is a very handy tool to get SSL certificates for your domain, but unfortunately it does not support to request a certificate for ‘‘ucs-sso.domain.example’’.
This is because the Apache Site-Configurations ‘‘letsencrypt.conf’’ and ‘‘univention-saml.conf’’ tread on each other’s toes.
Luckily our Let’s Encrypt App uses acme-tiny script for the request and update of the certificates.
Note: This article is a quick adaption for UCS of the Readme of acme-tiny, so you can gather Let’s Encrypt Certificates for your ‘‘ucs-sso.domain.example’’ address without having the Let’s Encrypt App installed.
Requirements
SSO does only work fully supported on UCS Master- and UCS BackUp-systems.
Find a directory, where to store the acme-tiny script, and another one for the certificate files etc. In this article, we create a new certificate, therefore we use:
# location acme-tiny
/usr/local/bin/acme-tiny/
# location of certificate files etc.
/etc/univention/letsencrypt/
Step 1 - Create a Let’s Encrypt account private key (if you haven’t already).
You must have a public key registered with Let’s Encrypt and sign your requests with the corresponding private key. If you don’t understand what I just said, this script likely isn’t for you! Please use the official Let’s Encrypt client. To accomplish this you need to initially create a key, that can be used by acme-tiny, to register an account for you and sign all following requests.
openssl genrsa 4096 > account.key
Step 2 - Create a certificate signing request (CSR) for your domains.
The ACME protocol (what Let’s Encrypt uses) requires a CSR file to be submitted to it, even for renewals. You can use the same CSR for multiple renewals. NOTE: you can’t use your account private key as your domain private key!
# Generate a domain private key in step 1 (if you haven't already)
openssl genrsa 4096 > domain.key
Then create the CSR
# For a single domain
openssl req -new -sha256 -key domain.key -subj "/CN=ucs-sso.domain.example" > domain.csr
Step 3 - Make your website host challenge files for UCS Apache Server.
You must prove you own the domains you want a certificate for, so Let’s Encrypt requires you host some files on them. This script will generate and write those files in the folder you specify, so all you need to do is make sure that this folder is served under the “.well-known/acme-challenge/” url path. NOTE: Let’s Encrypt will perform a plain HTTP request to port 80 on your server, so you must serve the challenge files via HTTP (a redirect to HTTPS is fine too).
# the ucs apache challange folder some challenge folder, i.e.:
mkdir -p /var/www/.well-known/acme-challenge/
Step 4 - Get a signed certificate.
Now that you have setup your server and generated all the needed files, run this script on your server with the permissions needed to write to the above folder and read your private account key and CSR.
# Run the script on your server
python /usr/local/bin/acme-tiny/acme_tiny.py --account-key /etc/univention/letsencrypt/account.key --csr /etc/univention/letsencrypt/domain.csr --acme-dir /var/www/.well-known/acme-challenge/ > /etc/univention/letsencrypt/signed_chain.crt
Step 5 - Installation of the certificate: configuration of UCS and Apache univention-saml.conf
.
Now we are almost ready to go. Some more steps need to be done, to get things working.
# Download the letsencrypt CA certificate
wget -c https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem.txt -O letsencryptCA.pem
Make sure, your idp-server is set properly:
ucr search umc/saml/idp-server
umc/saml/idp-server: https://ucs-sso.domain.example/simplesamlphp/saml2/idp/metadata.php
To configure the univention-saml.conf
by the help of the UCR variables:
# set the UCR variables ...
ucr set saml/apache2/ssl/ca="/etc/univention/letsencrypt/letsencryptCA.pem" \
saml/apache2/ssl/certificate="/etc/univention/letsencrypt/signed_chain.crt" \
saml/apache2/ssl/key="/etc/univention/letsencrypt/domain.key"
# ... and reload apache2.service
systemctl reload apache2.service
The univention-saml.conf
should now look like this (extract):
<VirtualHost *:443>
IncludeOptional /etc/apache2/sso-vhost.conf.d/*.conf
SSLEngine on
SSLProxyEngine on
ServerName ucs-sso.domain.example
SSLCertificateFile /etc/univention/letsencrypt/signed_chain.crt
SSLCertificateKeyFile /etc/univention/letsencrypt/domain.key
SSLCACertificateFile /etc/univention/letsencrypt/letsencryptCA.pem
DocumentRoot /var/www/
RedirectMatch ^/$ /simplesamlphp/
ScriptAlias /saml-bin /var/www/saml
SuexecUserGroup samlcgi samlcgi
# simplesamlphp uses this header to decide which idp config to use.
# This decision is case sensitive. Setting the HOST header here, ensures the right case.
RequestHeader set HOST ucs-sso.domain.example
RewriteEngine on
RewriteCond %{HTTP:Authorization} !^$
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
Include /etc/apache2/sites-available/univention-proxy.conf
</VirtualHost>
Step 6 - Setup an auto-renew cronjob.
Yay! You are ready to go and encrypted. Unfortunately, Let’s Encrypt certificates only last for 90 days, so you need to renew them often. No worries! It’s automated! Just make a shell script and create an UCR cronjob (see below for example script).
#!/bin/sh
python /usr/local/bin/acme-tiny/acme_tiny.py --account-key /etc/univention/letsencrypt/account.key --csr /etc/univention/letsencrypt/domain.csr --acme-dir /var/www/.well-known/acme-challenge/ > /etc/univention/letsencrypt/signed_chain.crt.tmp || exit
mv /etc/univention/letsencrypt/signed_chain.crt.tmp /etc/univention/letsencrypt/signed_chain.crt
systemctl reload apache2
And to update this certificate, you can easily create a UCR cronjob, i.e. like below. This will run once per month and will be stored in /etc/cron.d/univention-ucr-cronjobs
ucr set cron/renew-letsencrypt-certificate/command="/usr/local/bin/acme-tiny/renew_cert.sh 2>> /var/log/acme_tiny.log" \
cron/renew-letsencrypt-certificate/time="0 0 1 * *" \
cron/renew-letsencrypt-certificate/user="root" \
cron/renew-letsencrypt-certificate/description="cronjob to renew letsencrypt certificate for ucs-sso.domain.example"
Permissions
The biggest problem you’ll likely come across while setting up and running this script is permissions. You want to limit access to your account private key and challenge web folder as much as possible. I’d recommend creating a user specifically for handling this script, the account private key, and the challenge folder. Then add the ability for that user to write to your installed certificate file (e.g. /path/to/signed_chain.crt
) and reload apache2. That way, the cron script will do its thing, overwrite your old certificate, and reload your webserver without having permission to do anything else.
Be sure to:
- Backup your account.key
and private.key
(e.g. account.key)
- Don’t allow this script to be able to read your domain private key!
- Don’t allow this script to be run as root!
Debugging
When you get an error while requesting the certificate (see step 4). Take a look at https://tools.letsdebug.net/cert-search and check your weekly request limit by searching after your domain.