From 6c86a2d26b2c212a541f1a69c4c17ce48c62b918 Mon Sep 17 00:00:00 2001 From: Valentin Lab Date: Sun, 6 Dec 2015 18:44:18 +0800 Subject: [PATCH] new: [ca] completed charm. A new ``mkcrt`` script is provided handling ``--server`` and ``--altname``. --- precise/ca/hooks/install | 100 ++++++++++++++++------ precise/ca/metadata.yaml | 4 + precise/ca/src/usr/sbin/mkcrt | 155 ++++++++++++++++++++++++++++++++++ 3 files changed, 235 insertions(+), 24 deletions(-) create mode 100755 precise/ca/src/usr/sbin/mkcrt diff --git a/precise/ca/hooks/install b/precise/ca/hooks/install index 28ce7ef2..cdbdb9e0 100755 --- a/precise/ca/hooks/install +++ b/precise/ca/hooks/install @@ -2,45 +2,97 @@ set -eux # -x for verbose logging to juju debug-log +apt-get install -y --force-yes kal-manage ## this is for ``mkcrt`` -apt-get install -y --force-yes kal-manage expect ## this is for ``mkcrt`` +CA_SUBJECT=${CA_SUBJECT:-/C=FR/ST=France/O=Kalysto/CN=kal.fr/emailAddress=ca@kal.fr} -mkdir -p /etc/ssl/ca -chmod 700 /etc/ssl/ca +cat < /etc/default/ca +CA_DATA="/var/lib/ca" +CA_DIR="\$CA_DATA" ## avoid regexp chars please and '%' as it is concated in a regexp. +OPENSSL_CONF_FILE=/etc/ssl/openssl.cnf +PERL_CA_SCRIPT=/usr/lib/ssl/misc/CA.pl -## default location of files to manage the certificate of authority -sed -ri 's%./demoCA%/etc/ssl/ca%g' /etc/ssl/openssl.cnf -## default validity period for a certificate extended to 10 years -sed -ri 's%(default_days\s*= *)365%\13650%g' /etc/ssl/openssl.cnf +CA_PASSWORD_FILE="\$CA_DIR/password" -## And edit: /usr/lib/ssl/misc/CA.pl -sed -ri 's%./demoCA%/etc/ssl/ca%g' /usr/lib/ssl/misc/CA.pl -sed -ri 's%-days 365%-days 3650%g' /usr/lib/ssl/misc/CA.pl -sed -ri 's%-days 1095%-days 10950%g' /usr/lib/ssl/misc/CA.pl +## SSL subject defaults +COUNTRY=${COUNTRY:-FR} +STATE=${STATE:-France} +ORGANISATION=${ORGANISATION:-Kalysto} +## 20 years = 7300 days +## 10 years = 3650 days +## 3 years = 1095 days +DAYS=${DAYS:-3650} -ca="/etc/ssl/ca" +EOF -# from /usr/lib/ssl/misc/CA.pl -newca -mkdir $ca/{certs,crl,newcerts,private} -touch $ca/index.txt -echo "01" > $ca/crlnumber +## +## Setup CA configuration +## -## Will require to set the CA password, and some general INFO. -#openssl req -new -keyout $ca/private/cakey.pem -out $ca/careq.pem +. /etc/default/ca -## -#openssl ca -create_serial -out $ca/cacert.pem -days 10950 -batch -keyfile $ca/private/cakey.pem -selfsign -extensions v3_ca -infiles $ca/careq.pem +mkdir -p "$CA_DIR" +chmod 700 "$CA_DIR" + +## default location of files to manage the certificate of authority +sed -ri 's%./demoCA%'$CA_DATA'%g' "$OPENSSL_CONF_FILE" +## default validity period for a certificate extended to 20 years +## Gosh, this is anyway a self-signed certificate, why the hell would +## we want to go through all the hassles of re-issuing EVERY certificate +## ever signed by this authority ? +sed -ri 's%(default_days\s*= *)365%\7300%g' "$OPENSSL_CONF_FILE" + +## And edit: "$PERL_CA_SCRIPT" +sed -ri "s%./demoCA%$CA_DATA%g" "$PERL_CA_SCRIPT" +sed -ri 's%-days 365%-days 7300%g' "$PERL_CA_SCRIPT" +sed -ri 's%-days 1095%-days 7300%g' "$PERL_CA_SCRIPT" + +## Creating root CA password +CA_PASSWORD_FILE="$CA_DIR/password" +touch "$CA_PASSWORD_FILE" +chmod go-rwx "$CA_PASSWORD_FILE" +openssl rand -base64 32 | cut -c -32 > "$CA_PASSWORD_FILE" + +## from "$PERL_CA_SCRIPT" -newca +mkdir -p "$CA_DIR/"{certs,crl,newcerts,private} +touch "$CA_DIR/index.txt" +echo "01" > "$CA_DIR/crlnumber" + +## Create the request +openssl req -new \ + -keyout "$CA_DIR/private/cakey.pem" \ + -out "$CA_DIR/careq.pem" \ + -subj "$CA_SUBJECT" \ + -passout file:"$CA_PASSWORD_FILE" + +## Self-Sign request +openssl ca -create_serial \ + -out "$CA_DIR/cacert.pem" \ + -days 7300 \ + -batch \ + -keyfile "$CA_DIR/private/cakey.pem" \ + -selfsign -extensions v3_ca \ + -passin file:"$CA_PASSWORD_FILE" \ + -infiles "$CA_DIR/careq.pem" + +## Creating dh file (why ? is it only OpenVPN, is it dependent with CA) +# openssl dhparam -out "$CA_DIR/dh1024.pem" 1024 +## +## Prepare data side +## +mkdir -p "$CA_DATA/keys" +chmod 700 "$CA_DATA/keys" -R -mkdir -p /etc/ssl/keys -chmod 700 /etc/ssl/keys -R +## +## Insert a few tools +## -cd /etc/ssl/ -openssl dhparam -out dh1024.pem 1024 +cp src/usr/sbin/mkcrt /usr/sbin/mkcrt diff --git a/precise/ca/metadata.yaml b/precise/ca/metadata.yaml index cd8fc9a2..2ceaa406 100644 --- a/precise/ca/metadata.yaml +++ b/precise/ca/metadata.yaml @@ -5,3 +5,7 @@ inherit: base-0k description: | Certification Autority data-dir: /etc/ssl +config-resources: + - /etc/ssl/ca +data-resources: + - /var/lib/ca diff --git a/precise/ca/src/usr/sbin/mkcrt b/precise/ca/src/usr/sbin/mkcrt new file mode 100755 index 00000000..8a5dc6c9 --- /dev/null +++ b/precise/ca/src/usr/sbin/mkcrt @@ -0,0 +1,155 @@ +#!/bin/bash + +#:- +. /etc/shlib +#:- + +include common +include pretty + +usage="$exname [--server] [--altname ALTNAME] [--days DAYS] COMMONNAME EMAIL" + + +. /etc/default/ca + +CA_PASSWORD_FILE=${CA_PASSWORD_FILE:-$CA_CONFIG/password} + +if ! [ -e "$CA_PASSWORD_FILE" ]; then + die "Password file '$CA_PASSWORD_FILE' does not exist. Either create it or set \$CA_PASSWORD_FILE." +fi + + +## +## Arguments +## + +server_cert= +altnames=() +while [ "$1" ]; do + case "$1" in + "--server") + server_cert=true + ;; + "--altname="*) + altnames=(${altnames[@]} ${1#--altname=}) + ;; + "--altname") + altnames=(${altnames[@]} $2) + shift + ;; + "--days="*) + DAYS="${1#--altname=}" + ;; + "--days") + DAYS="${2}" + shift + ;; + *) + [ -z ${common_name+x} ] && { common_name=$1 ; shift; continue; } + [ -z ${email+x} ] && { email=$1 ; shift; continue; } + die "Unexpected argument '$1'." + ;; + esac + shift +done + +if [ -z "${common_name+x}" ] || [ -z "${email+x}" ]; then + err "Missing mandatory positional argument." + print_usage + exit 1 +fi + +for i in COUNTRY STATE ORGANISATION DAYS; do + if [ -z "${!i}" ]; then + die "Missing/Empty variable '$i'. You can add it to \`/etc/default/ca\`." + fi +done + +keyfile="$CA_DATA/keys/$common_name" + +if [ -e "$keyfile.crt+key" ]; then + warn "Keyfile '$keyfile.crt+key' already exist." + exit 0 +fi + +tmpdir=$(mktemp -d) +trap 'rm -rf "$tmpdir"' EXIT + + +## +## Subject building +## + +subject=() +[ -z "${COUNTRY+x}" ] || subject=("${subject[@]}" "C=$COUNTRY") +[ -z "${STATE+x}" ] || subject=("${subject[@]}" "ST=$STATE") +[ -z "${ORGANISATION+x}" ] || subject=("${subject[@]}" "O=$ORGANISATION") +subject=("${subject[@]}" "CN=$common_name") +subject=("${subject[@]}" "emailAddress=$email") + +SUBJECT=$(for elt in "${subject[@]}"; do echo -n "/$elt"; done) + + +## +## Openssl Options +## + +openssl_opts=() +openssl_req_opts=() +openssl_ca_opts=() +[ -z "${DAYS+x}" ] && openssl_opts=("${openssl_opts[@]}" "-days" "$DAYS") + + +if [ "$server_cert" ]; then + if ! egrep "^#\s*nsCertType\s*=\s*server\s*$" "/etc/ssl/openssl.cnf" > /dev/null 2>&1; then + err "Unexistent line about 'nsCertType' in '/etc/ssl/openssl.cnf' reference." + die "Can't activate the server certificate." + fi + [ -e "$tmpdir/openssl.cnf" ] || cp /etc/ssl/openssl.cnf "$tmpdir/openssl.cnf" + sed -ri 's/^#\s*(nsCertType\s*=\s*server\s*)$/\1/g' "$tmpdir/openssl.cnf" + new_openssl_cnf=true +fi + +if [ "${altnames[*]}" ]; then + [ -e "$tmpdir/openssl.cnf" ] || cp /etc/ssl/openssl.cnf "$tmpdir/openssl.cnf" + openssl_req_opts=("${openssl_req_opts[@]}" "-reqexts" SAN) + openssl_ca_opts=("${openssl_ca_opts[@]}" "-extensions" SAN) + cat <> "$tmpdir/openssl.cnf" +[SAN] +subjectAltName = $(for altname in "${altnames[@]}"; do echo -n "DNS:$altname,"; done | rev | cut -c 2- | rev) +EOF + new_openssl_cnf=true +fi + +[ "$new_openssl_cnf" ] && openssl_opts=("${openssl_opts[@]}" "-config" "$tmpdir/openssl.cnf") + + +## +## Okay, lets do the real work +## + +cd "$tmpdir" + +Wrap -q -d "Generating request" < "$keyfile.crt+key"