Skip to content

Instantly share code, notes, and snippets.

@xcombelle
Last active August 2, 2016 10:20
Show Gist options
  • Save xcombelle/bd3cc124a122af23ddb22c908a34dfb8 to your computer and use it in GitHub Desktop.
Save xcombelle/bd3cc124a122af23ddb22c908a34dfb8 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
#################
# Configuration #
#################
# TODO: à migrer dans un fichier de config ?
# Clé privée principale, utilisée pour générer la CSR
private_master_key="/etc/ssl/private/slaanesh.org.key"
# Clé privée utilisée par let's encrypt
private_account_key="/etc/ssl/private/slaanesh.org_letsencrypt.key"
# Liste des domaines
domains=[
"mail.slaanesh.org",
"pma.slaanesh.org",
"rss.slaanesh.org"]
# Dossier utilisé pour les challenges let's encrypt
html_challenge="/var/www/letsencrypt_challenge"
# Dossier où sont stockés les clés privés
certificates_path="/etc/ssl/certs/letsencrypt"
# Liste des services à redémarrer
services=[
"nginx",
"postfix",
"dovecot"]
# format_domains_for_openssl_config
# Génère une châine de caractère
# params...: les domaines
#
# exemple :
# > format_domains_for_openssl_config bli bla blo
# < DNS:bli,DNS:bla,DNS:blo
def format_domains_for_openssl_config (*domains)
return ",".join("DNS:{}".format(domain) for domain in domains)
# certificate_end_date_validity
# Récupère la date de fin de validité du certificat
# param 1: chemin vers le certificat
#TODO: convert to python
function certificate_end_date_validity {
local certificate_path="$1"
openssl x509 -in "${certificate_path}" -enddate -noout | awk 'BEGIN {FS = "="} {print $2}'
}
# is_certificate_still_valid
# Vérifie si un certificat est toujours valide
# Un certificat est considéré comme valide si il existe et qu'il n'est pas périmé
# param 1: chemin vers le certificat
# param 2:
#TODO: convert to python
function is_certificate_still_valid {
local certificate_path="$1"
local treshold="$2"
if [[ ! -e "${certificate_path}" ]]; then
return 1
fi
local enddate=$(certificate_end_date_validity "${certificate_path}")
local enddate_timestamp=$(date -d "${enddate}" "+%s")
local now_timestamp=$(date "+%s")
local diff_timestamp=$(( ${enddate_timestamp} - ${now_timestamp} ))
if [[ "${diff_timestamp}" -lt "${treshold}" ]]; then
return 1
fi
return 0
}
########
# Main #
########
# Création d'un dossier temporaire de travail
# et d'un callback pour le supprimer automatiquement à fin du script
temp_folder=$(mktemp -dt "$(basename $0).XXXXXXXXXX")
function finish {
rm -rf "${temp_folder}"
}
trap finish EXIT
# Vérifie l'existance des clés privées
if [[ ! -f "${private_master_key}" ]]; then
echo "Error: private master key ${private_master_key} not found"
exit 1
fi
if [[ ! -f "${private_account_key}" ]]; then
echo "Error: private account key ${private_account_key} not found"
exit 1
fi
# Récupération du certificat de la CA
ca_certificate_path="${temp_folder}/intermediate.pem"
curl -L -o "${ca_certificate_path}" https://letsencrypt.org/certs/lets-encrypt-x1-cross-signed.pem
for domain in ${domains[@]}; do
certificate_name="${domain}.pem"
certificate_path="${certificates_path}/${certificate_name}"
if is_certificate_still_valid "${certificate_path}" 86400; then
echo "Certificate for domain ${domain} is still valid"
continue
fi
echo "Generate certificate for domain ${domain}"
# Création de la requête de signature du certificat
csr_path="${temp_folder}/${domain}.csr"
openssl \
req \
-new \
-sha256 \
-key "${private_master_key}" \
-subj "/CN=${domain}" \
> "${csr_path}"
# Création du certificat
signed_certificate_path="${temp_folder}/${domain}_signed.pem"
acme_tiny \
--account-key "${private_account_key}" \
--csr "${csr_path}" \
--acme-dir "${html_challenge}" \
> "${signed_certificate_path}"
if [[ $? != 0 ]]; then
echo "Error: cannot generate certificate(s)"
exit 1
fi
# Génération du certificat "complet"
chained_certificate_path="${temp_folder}/${domain}_chained.pem"
cat "${signed_certificate_path}" "${ca_certificate_path}" > "${chained_certificate_path}"
# Copie du certificat
cp "${chained_certificate_path}" "${certificate_path}"
done
# Re-démarrage des services
for service in ${services[@]}; do
systemctl restart "${service}"
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment