From 8a5abc08c66084d9b03dd4edb0752ea66dae0fc7 Mon Sep 17 00:00:00 2001 From: Bob Belnap Date: Mon, 26 Feb 2018 13:01:25 -0500 Subject: [PATCH] add deploy class, check_cert.sh, cron setup --- files/check_cert.sh | 85 ++++++++++++++++++++++++++++++++++++++++++ manifests/common.pp | 9 +++++ manifests/deploy.pp | 32 ++++++++++++++++ manifests/params.pp | 6 ++- manifests/requestor.pp | 1 - 5 files changed, 130 insertions(+), 3 deletions(-) create mode 100644 files/check_cert.sh diff --git a/files/check_cert.sh b/files/check_cert.sh new file mode 100644 index 0000000..23639ba --- /dev/null +++ b/files/check_cert.sh @@ -0,0 +1,85 @@ +#!/bin/bash + +# this script compares the existing cert against the new cert in vault, and +# replaces existing cert only if it is newer and valid. + +# function defs +get_fingerprint() { + openssl x509 -noout -fingerprint -in <(echo "$1") | awk -F= '{print $2}' +} + +get_enddate() { + date --date="$(openssl x509 -noout -enddate -in <(echo "$1")| awk -F= '{print $2}')" --iso-8601 +} + +# arguments +DOMAIN=$1 +CERT_PREFIX=$2 +EXISTING_CERT_DIR="${CERT_PREFIX}/${DOMAIN}" +EXISTING_CERT_PATH="${EXISTING_CERT_DIR}/cert.pem" +EXISTING_KEY_PATH="${EXISTING_CERT_DIR}/cert.key" + +# variables +ONE_WEEK=604800 +TODAY=$(date --iso-8601) + + +NEWCERT_VAULT_PATH="/secret/letsencrypt/${DOMAIN}/cert.pem" +NEWKEY_VAULT_PATH="/secret/letsencrypt/${DOMAIN}/cert.key" + +# Get new cert info +NEWCERT=$(vault read -field=value $NEWCERT_VAULT_PATH) || exit -1 +NEWKEY=$(vault read -field=value $NEWKEY_VAULT_PATH) || exit -1 +NEWCERT_FINGERPRINT=$(get_fingerprint "$NEWCERT") +NEWCERT_ENDDATE=$(get_enddate "$NEWCERT") + +# we need to bail right away if we don't have a valid new cert +if [ "$NEWCERT_FINGERPRINT" == "" ] +then + echo "no valid new cert found!" + exit -1 +fi + +#echo "new fingerprint: $NEWCERT_FINGERPRINT" +#echo "new enddate: $NEWCERT_ENDDATE" + +# Get existing cert info +EXISTING_CERT=$(cat $EXISTING_CERT_PATH) +EXISTING_CERT_FINGERPRINT=$(get_fingerprint "$EXISTING_CERT") +EXISTING_CERT_ENDDATE=$(get_enddate "$EXISTING_CERT") + +#echo "existing fingerprint: $EXISTING_CERT_FINGERPRINT" +#echo "existing enddate: $EXISTING_CERT_ENDDATE" + + +# check that new cert is different +# if it is the same, exit normally, this will be the common case +if [ "$NEWCERT_FINGERPRINT" == "$EXISTING_CERT_FINGERPRINT" ] +then + exit -1 +fi + +# check that new cert is newer than current cert +if [ "$EXISTING_CERT_ENDDATE" \> "$NEWCERT_ENDDATE" ] +then + echo "existing cert expiration is older, exiting" + exit -1 +fi + +# check that new cert is not expired +if [ "$NEWCERT_ENDDATE" \< "$TODAY" ] +then + echo "new cert is expired, exiting" + exit -1 +fi + +# if we made it this far, the cert looks good, replace it +echo "replacing cert at $EXISTING_CERT_PATH" +mkdir $EXISTING_CERT_DIR || true +echo "$NEWCERT" > $EXISTING_CERT_PATH +echo "$NEWKEY" > $EXISTING_KEY_PATH + + +#openssl x509 -in <(vault read -field=value /secret/apidb.org/cert.pem) -noout -checkend 8640000 + + diff --git a/manifests/common.pp b/manifests/common.pp index d4fc38b..aca5a0b 100644 --- a/manifests/common.pp +++ b/manifests/common.pp @@ -2,6 +2,7 @@ class acme_vault::common ( $user = $::acme_vault::params::user, $group = $::acme_vault::params::group, $home_dir = $::acme_vault::params::home_dir, + $contact_email = $::acme_vault::params::contact_email, $vault_token = $::acme_vault::params::vault_token, $vault_addr = $::acme_vault::params::vault_addr, @@ -59,6 +60,14 @@ END order => "01", } + # common dummy cron job to set MAILTO + cron { "dummy_mailto": + command => "/bin/true", + user => $user, + month => 7, + environment => "MAILTO=${contact_email}", + } + # file { "$home_dir/.bashrc": # ensure => present, # owner => $user, diff --git a/manifests/deploy.pp b/manifests/deploy.pp index c58f2c7..2b7780d 100644 --- a/manifests/deploy.pp +++ b/manifests/deploy.pp @@ -5,8 +5,40 @@ class acme_vault::deploy( $cert_destination_path = $::acme_vault::params::cert_destination_path, $domains = $::acme_vault::params::domains, + $restart = $::acme_vault::params::restart, + $restart_command = $::acme_vault::params::restart_command, ) inherits acme_vault::params { + include acme_vault::common + + # copy down cert check script + file {"${home_dir}/check_cert.sh": + ensure => present, + owner => $user, + group => $group, + mode => "0750", + source => "puppet:///modules/acme_vault/check_cert.sh", + } + + if $restart { + $cron_command = "${home_dir}/check_cert.sh $domain $cert_destination_path && $restart_command" + } else { + $cron_command = "${home_dir}/check_cert.sh $domain $cert_destination_path" + } + + + notice($user) + $domains.each |$domain| { + cron { "${domain}_deploy": + command => $cron_command, + user => $user, + weekday => 2, + } + } + + + + } diff --git a/manifests/params.pp b/manifests/params.pp index 8f5f559..fe1c0f0 100644 --- a/manifests/params.pp +++ b/manifests/params.pp @@ -8,14 +8,13 @@ class acme_vault::params { $staging = true $staging_url = 'https://acme-staging-v02.api.letsencrypt.org/directory' $prod_url = 'https://acme-v02.api.letsencrypt.org/directory' + #TODO configurue email $contact_email = '' $acme_revision = 'HEAD' $acme_repo_path = "$home_dir/acme.sh" $acme_script = "$acme_repo_path/acme.sh" $vault_prefix = '/secret/letsencrypt/' - # domains list TODO should be a mapping name -> domains - $domains = '' # authentication @@ -32,4 +31,7 @@ class acme_vault::params { $cert_destination_path = '/etc/acme/' + $restart = false + $restart_command = "echo restart!" + } diff --git a/manifests/requestor.pp b/manifests/requestor.pp index 54f511d..cb4acac 100644 --- a/manifests/requestor.pp +++ b/manifests/requestor.pp @@ -74,7 +74,6 @@ END command => "${home_dir}/${domain}.sh", user => $user, weekday => 1, - environment => "MAILTO=${contact_email}", } }