diff --git a/dmcerts b/dmcerts new file mode 100755 index 0000000..57fc687 --- /dev/null +++ b/dmcerts @@ -0,0 +1,128 @@ +#!/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 + +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.$machine/CN=jclain/" + 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.$machine/CN=$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" diff --git a/lib/dmcerts_openssl_ca.cnf b/lib/dmcerts_openssl_ca.cnf new file mode 100644 index 0000000..9275819 --- /dev/null +++ b/lib/dmcerts_openssl_ca.cnf @@ -0,0 +1,106 @@ +# -*- coding: utf-8 mode: conf -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 + +[ca] +default_ca = dmca + +[dmca] +dir = @@cadir@@ +certs = $dir/certs +crl_dir = $dir/crl +database = $dir/index.txt +unique_subject = no +new_certs_dir = $dir/newcerts + +certificate = $dir/dmca.crt +serial = $dir/serial +crl = $dir/dmca.crl +private_key = $dir/dmca.key +RANDFILE = $dir/private/.rand + +x509_extensions = usr_cert + +name_opt = ca_default +cert_opt = ca_default + +default_days = 10950 +default_crl_days = 30 +default_md = sha256 +preserve = no + +policy = policy_match + +[policy_match] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +[req] +default_bits = 2048 +default_md = sha256 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca +string_mask = utf8only + +[req_distinguished_name] +countryName = Country Name (2 letter code) +countryName_default = FR +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = La Reunion + +localityName = Locality Name (eg, city) +localityName_default = Sainte-Clotilde + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = jclain + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = + +commonName = Common Name (eg, your name or your server\'s hostname) +commonName_default = dmca +commonName_max = 64 + +emailAddress = Email Address +emailAddress_default = jephte.clain@univ-reunion.fr +emailAddress_max = 64 + +[req_attributes] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = dmca + +[usr_cert] + +basicConstraints=CA:FALSE + +nsComment = "dmca certificate" + +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +[v3_req] + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation,digitalSignature,keyEncipherment + +[v3_ca] + +#subjectKeyIdentifier=hash +#authorityKeyIdentifier=keyid:always,issuer +basicConstraints = critical,CA:true +keyUsage = critical,keyCertSign,digitalSignature,keyEncipherment,keyAgreement + +[crl_ext] + +#issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always diff --git a/lib/dmcerts_openssl_client.cnf b/lib/dmcerts_openssl_client.cnf new file mode 100644 index 0000000..fd5066b --- /dev/null +++ b/lib/dmcerts_openssl_client.cnf @@ -0,0 +1,99 @@ +# -*- coding: utf-8 mode: conf -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 + +[ca] +default_ca = dmca + +[dmca] +dir = @@cadir@@ +certs = $dir/certs +crl_dir = $dir/crl +database = $dir/index.txt +unique_subject = no +new_certs_dir = $dir/newcerts + +certificate = $dir/dmca.crt +serial = $dir/serial +crl = $dir/dmca.crl +private_key = $dir/dmca.key +RANDFILE = $dir/private/.rand + +x509_extensions = usr_ext + +name_opt = ca_default +cert_opt = ca_default + +copy_extensions = copy + +default_days = 3650 +default_crl_days = 30 +default_md = sha256 +preserve = no + +policy = policy_match + +[policy_match] +#countryName = match +#stateOrProvinceName = match +#organizationName = match +countryName = supplied +stateOrProvinceName = supplied +organizationName = supplied +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +[req] +default_bits = 2048 +default_md = sha256 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = usr_ext +string_mask = utf8only + +#input_password = secret +#output_password = secret + +[req_distinguished_name] +countryName = Country Name (2 letter code) +countryName_default = FR +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = La Reunion + +localityName = Locality Name (eg, city) +localityName_default = Sainte-Clotilde + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = jclain + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = + +commonName = Common Name (eg, your name or your server\'s hostname) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +[req_attributes] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = jclain + +[usr_ext] + +basicConstraints=critical,CA:FALSE +#subjectKeyIdentifier=hash +#authorityKeyIdentifier=keyid,issuer:always +keyUsage = critical,digitalSignature +extendedKeyUsage = clientAuth + +[crl_ext] + +#issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always diff --git a/lib/dmcerts_openssl_server.cnf b/lib/dmcerts_openssl_server.cnf new file mode 100644 index 0000000..ddcb5cc --- /dev/null +++ b/lib/dmcerts_openssl_server.cnf @@ -0,0 +1,101 @@ +# -*- coding: utf-8 mode: conf -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 + +[ca] +default_ca = dmca + +[dmca] +dir = @@cadir@@ +certs = $dir/certs +crl_dir = $dir/crl +database = $dir/index.txt +unique_subject = no +new_certs_dir = $dir/newcerts + +certificate = $dir/dmca.crt +serial = $dir/serial +crl = $dir/dmca.crl +private_key = $dir/dmca.key +RANDFILE = $dir/private/.rand + +x509_extensions = usr_ext + +name_opt = ca_default +cert_opt = ca_default + +copy_extensions = copy + +default_days = 3650 +default_crl_days = 30 +default_md = sha256 +preserve = no + +policy = policy_match + +[policy_match] +#countryName = match +#stateOrProvinceName = match +#organizationName = match +countryName = supplied +stateOrProvinceName = supplied +organizationName = supplied +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +[req] +default_bits = 2048 +default_md = sha256 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = usr_ext +string_mask = utf8only + +#input_password = secret +#output_password = secret + +[req_distinguished_name] +countryName = Country Name (2 letter code) +countryName_default = FR +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = La Reunion + +localityName = Locality Name (eg, city) +localityName_default = Sainte-Clotilde + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = jclain + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = + +commonName = Common Name (eg, your name or your server\'s hostname) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +[req_attributes] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = jclain + +[usr_ext] + +basicConstraints = critical,CA:FALSE +#subjectKeyIdentifier=hash +#authorityKeyIdentifier=keyid,issuer:always +keyUsage = critical,digitalSignature,keyEncipherment,keyAgreement +extendedKeyUsage = serverAuth + +subjectAltName = DNS:localhost + +[crl_ext] + +#issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always