#!/bin/bash
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
source /etc/ulibauto || exit 1
urequire install

function display_help() {
    uecho "$scriptname: gérer les certificats de docker-machine

Les certificats créés par docker-machine ont une durée trop courte à mon goût.
Ce script permet de les recréer avec une durée de 30 ans pour le CA et le
certificat client, et de 10 ans pour chaque machine

USAGE
    $scriptname [host]"
}

args=(
    --help '$exit_with display_help'
)
parse_args "$@"; set -- "${args[@]}"

dmdir="$HOME/.docker/machine"

cadir="$dmdir/dmcerts"
cakey="$cadir/dmca.key"
cacsr="$cadir/dmca.csr"
cacrt="$cadir/dmca.crt"
cacrl="$cadir/dmca.crl"
if [ ! -d "$cadir" ]; then
    enote "Le répertoire $cadir va être créé. Ne faites cela que si c'est la première fois. Sinon, récupérez le répertoire déjà créé par ailleurs"
    ask_yesno "Voulez-vous continuer?" N || die
    
    mkdir "$cadir"
    chmod 700 "$cadir"
    mkdir "$cadir"/{openssl,newcerts}
    touch "$cadir/index.txt"
    echo 01 >"$cadir/serial"

    for src in "$scriptdir"/lib/dmcerts_openssl_*.cnf; do
        dest="$cadir/openssl/${src#$scriptdir/lib/dmcerts_openssl_}"
        cp "$src" "$dest"
    done
    sed -i "s/^dir = .*/dir = ${cadir//\//\\\/}/" "$cadir/openssl/"*.cnf

    openssl req -config "$cadir/openssl/ca.cnf" -batch -new -nodes -keyout "$cakey" -out "$cacsr" &&
        openssl ca -config "$cadir/openssl/ca.cnf" -batch -notext -out "$cacrt" -days 10950 -keyfile "$cakey" -selfsign -extensions v3_ca -infiles "$cacsr" &&
        openssl ca -config "$cadir/openssl/ca.cnf" -batch -gencrl -out "$cacrl" ||
            die "Une erreur s'est produite. Veuillez supprimer $cadir et recommencer"
fi

clientkey="$cadir/dmclient.key"
clientcsr="$cadir/dmclient.csr"
clientcrt="$cadir/dmclient.crt"
clientcnf="$cadir/openssl/client.cnf"
if [ ! -f "$clientcrt" ]; then
    #sed -i "s/^dir = .*/dir = ${cadir//\//\\\/}/" "$clientcnf"

    subj="/countryName=FR/stateOrProvinceName=La Reunion/localityName=Sainte Clotilde/organizationName=jclain/CN=dmclient/"
    openssl req -config "$clientcnf" -batch -new -nodes -subj "$subj" -keyout "$clientkey" -out "$clientcsr" &&
        openssl ca -config "$clientcnf" -batch -keyfile "$cakey" -notext -out "$clientcrt" -infiles "$clientcsr" &&
        chmod 644 "$clientcrt" &&
        chmod 600 "$clientkey" &&
        rm -f "$clientcsr" ||
            die "Une erreur s'est produite pendant la génération du certificat client"
fi

estep "Vérification certificats locaux"
copy_update "$cacrt" "$dmdir/certs/ca.pem"
copy_update "$cakey" "$dmdir/certs/ca-key.pem"
copy_update "$clientcrt" "$dmdir/certs/cert.pem"
copy_update "$clientkey" "$dmdir/certs/key.pem"

first=1
for host in "$@"; do
    if [ -n "$first" ]; then
        servercnf="$cadir/openssl/server.cnf"
        #sed -i "s/^dir = .*/dir = ${cadir//\//\\\/}/" "$servercnf"
    else
        first=
    fi

    etitle "$host"
    machine="${host%%.*}"
    machinedir="$dmdir/machines/$machine"
    if [ ! -d "$machinedir" ]; then
        eerror "$machine: machine inexistante"
    fi

    serverkey="${machine}-server.key"
    servercsr="${machine}-server.csr"
    servercrt="${machine}-server.crt"
    if [ ! -f "$servercrt" ]; then
        subj="/countryName=FR/stateOrProvinceName=La Reunion/localityName=Sainte Clotilde/organizationName=jclain/CN=dmserver-$host/"
        sans="DNS:$host,DNS:localhost"
        sed -i "s/^subjectAltName = .*/subjectAltName = $sans/" "$servercnf"
        openssl req -config "$servercnf" -batch -new -nodes -subj "$subj" -keyout "$serverkey" -out "$servercsr" &&
            openssl ca -config "$servercnf" -batch -keyfile "$cakey" -notext -out "$servercrt" -infiles "$servercsr" &&
            chmod 644 "$servercrt" &&
            chmod 600 "$serverkey" &&
            rm -f "$servercsr" ||
                die "Une erreur s'est produite pendant la génération du certificat serveur"
    fi

    estep "machine: $machine"
    ask_yesno "Voulez-vous remplacer les certificats distants et locaux?" O || continue

    estep "Copie distante"
    scp "$cacrt" "root@$host:/etc/docker/ca.pem" || die
    scp "$servercrt" "root@$host:/etc/docker/server.pem" || die
    scp "$serverkey" "root@$host:/etc/docker/server-key.pem" || die

    estep "Redémarrage docker distant"
    ssh "root@$host" "service docker restart" || die

    estep "Copie locale"
    copy_update "$cacrt" "$machinedir/ca.pem"
    copy_update "$cakey" "$machinedir/ca-key.pem"
    copy_update "$clientcrt" "$machinedir/cert.pem"
    copy_update "$clientkey" "$machinedir/key.pem"
    copy_update "$servercrt" "$machinedir/server.pem"
    copy_update "$serverkey" "$machinedir/server-key.pem"

    estep "Test de l'accès au serveur"
    setx env=docker-machine env "$machine" || die
    eval "$env"
    echo "$machine docker version: $(docker system info -f '{{.ServerVersion}}')"

    estep "Suppression des fichiers temporaires"
    rm -f "$servercrt" "$serverkey"
done

enote "N'oubliez pas de re-exporter les docker-machines qui ont été regénérées"