Last active
August 2, 2016 10:20
-
-
Save xcombelle/bd3cc124a122af23ddb22c908a34dfb8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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