How To: Using acme-tiny to gather Let's Encrypt Certificates for your ucs-sso-address


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.

3 Likes

This topic was automatically closed after 24 hours. New replies are no longer allowed.

Mastodon