diff --git a/getssl b/getssl index 1998d82..dac2d2d 100755 --- a/getssl +++ b/getssl @@ -2972,14 +2972,26 @@ if [[ "${CHECK_REMOTE}" == "true" ]] && [[ $_FORCE_RENEW -eq 0 ]]; then fi # end of .... check_remote is true then connect and obtain the current certificate +#create SAN +if [[ -z "$SANS" ]]; then + SANLIST="subjectAltName=DNS:${DOMAIN}" +elif [[ "$IGNORE_DIRECTORY_DOMAIN" == "true" ]]; then + SANLIST="subjectAltName=DNS:${SANS//[, ]/,DNS:}" +else + SANLIST="subjectAltName=DNS:${DOMAIN},DNS:${SANS//[, ]/,DNS:}" +fi +debug "created SAN list = $SANLIST" + # if there is an existing certificate file, check details. if [[ -s "$CERT_FILE" ]]; then debug "certificate $CERT_FILE exists" enddate=$(openssl x509 -in "$CERT_FILE" -noout -enddate 2>/dev/null| cut -d= -f 2-) debug "local cert is valid until $enddate" + existing_sanlist=$(openssl x509 -in "$CERT_FILE" -noout -text | grep "DNS:" | sed 's/^ *//g') + debug "local cert is for domains: ${existing_sanlist}" if [[ "$enddate" != "-" ]]; then enddate_s=$(date_epoc "$enddate") - if [[ $(date_renew) -lt "$enddate_s" ]] && [[ $_FORCE_RENEW -ne 1 ]]; then + if [[ $(date_renew) -lt "$enddate_s" ]] && [[ $_FORCE_RENEW -ne 1 ]] && [[ "subjectAltName=$existing_sanlist" == "$SANLIST" ]]; then issuer=$(openssl x509 -in "$CERT_FILE" -noout -issuer 2>/dev/null) if [[ "$issuer" == *"Fake LE Intermediate"* ]] && [[ "$CA" == "https://acme-v02.api.letsencrypt.org" ]]; then debug "upgrading from fake cert to real" @@ -2989,6 +3001,9 @@ if [[ -s "$CERT_FILE" ]]; then graceful_exit $_NOTIFY_VALID fi else + if [[ "subjectAltName=$existing_sanlist" != "$SANLIST" ]]; then + info "Domain list in existing certificate ($existing_sanlist) does not match domains requested ($SANLIST), so recreating certificate" + fi debug "${DOMAIN}: certificate needs renewal" fi fi @@ -3027,16 +3042,6 @@ else fi # End of creating domain keys. -#create SAN -if [[ -z "$SANS" ]]; then - SANLIST="subjectAltName=DNS:${DOMAIN}" -elif [[ "$IGNORE_DIRECTORY_DOMAIN" == "true" ]]; then - SANLIST="subjectAltName=DNS:${SANS//[, ]/,DNS:}" -else - SANLIST="subjectAltName=DNS:${DOMAIN},DNS:${SANS//[, ]/,DNS:}" -fi -debug "created SAN list = $SANLIST" - #create CSR's if [[ "$DUAL_RSA_ECDSA" == "false" ]]; then create_csr "$DOMAIN_DIR/${DOMAIN}.csr" "$DOMAIN_DIR/${DOMAIN}.key" diff --git a/test/19-test-add-to-sans.bats b/test/19-test-add-to-sans.bats index da9deb7..f00bb4e 100644 --- a/test/19-test-add-to-sans.bats +++ b/test/19-test-add-to-sans.bats @@ -10,31 +10,24 @@ setup() { if [ -z "$STAGING" ]; then export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt curl --silent -X POST -d '{"host":"a.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a - curl --silent -X POST -d '{"host":"b.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a fi } teardown() { if [ -z "$STAGING" ]; then curl --silent -X POST -d '{"host":"a.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/clear-a - curl --silent -X POST -d '{"host":"b.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/clear-a fi } @test "Create certificate to check can add to SANS" { - skip "FIXME: Certificate is not recreated when SANS is updated" if [ -n "$STAGING" ]; then skip "Not trying on staging server yet" - CONFIG_FILE="getssl-dns01.cfg" - else - CONFIG_FILE="getssl-dns01-add-to-sans-1.cfg" fi - . "${CODE_DIR}/test/test-config/${CONFIG_FILE}" + CONFIG_FILE="getssl-dns01.cfg" setup_environment - - init_getssl + create_certificate assert_success check_output_for_errors @@ -42,23 +35,34 @@ teardown() { @test "Check we can add a new domain to SANS" { - skip "FIXME: Certificate is not recreated when SANS is updated" if [ -n "$STAGING" ]; then skip "Not trying on staging server yet" - CONFIG_FILE="getssl-dns01.cfg" - else - CONFIG_FILE="getssl-dns01-add-to-sans-2.cfg" fi - # . "${CODE_DIR}/test/test-config/${CONFIG_FILE}" - # CERT=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt - # KEY=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.key - # cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl.cfg" + CONFIG_FILE="getssl-dns01.cfg" + + cat <<- EOF > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg +SANS="a.${GETSSL_HOST}" +EOF + + . "${CODE_DIR}/test/test-config/${CONFIG_FILE}" + CERT=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt create_certificate assert_success check_output_for_errors # As the SANS list changed, a new certificate is needed + assert_line --partial "does not match domains requested" + assert_line --partial "does not have the same domains as the config - re-create-csr" assert_line --partial "certificate installed OK on server" refute_line --partial 'certificate is valid for more than' + + # Check that the SAN list in the certificate matches the expected value + SAN_IN_CERT=$(openssl x509 -in "$CERT" -noout -text | grep "DNS:" | sed 's/^ *//g') + SAN_EXPECTED="DNS:${GETSSL_HOST}, DNS:a.${GETSSL_HOST}" + if [[ "$SAN_IN_CERT" != "$SAN_EXPECTED" ]]; then + echo "# SAN_IN_CERT=$SAN_IN_CERT" + echo "# SAN_EXPECTED=$SAN_EXPECTED" + fi + [ "${SAN_IN_CERT}" = "$SAN_EXPECTED" ] } diff --git a/test/7-test-renewal.bats b/test/7-test-renewal.bats new file mode 100644 index 0000000..074f882 --- /dev/null +++ b/test/7-test-renewal.bats @@ -0,0 +1,96 @@ +#! /usr/bin/env bats + +load '/bats-support/load.bash' +load '/bats-assert/load.bash' +load '/getssl/test/test_helper.bash' + + +# This is run for every test +setup() { + if [ -z "$STAGING" ]; then + export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt + curl --silent -X POST -d '{"host":"a.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a + curl --silent -X POST -d '{"host":"b.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a + fi +} + +teardown() { + if [ -z "$STAGING" ]; then + curl --silent -X POST -d '{"host":"a.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/clear-a + curl --silent -X POST -d '{"host":"b.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/clear-a + fi +} + + +@test "Create certificate to check renewal" { + if [ -n "$STAGING" ]; then + skip "Not testing renewal on staging server" + fi + CONFIG_FILE="getssl-dns01.cfg" + setup_environment + init_getssl + + create_certificate + assert_success + check_output_for_errors +} + + +@test "Check that trying to renew a certificate which doesn't need renewing doesn't do anything" { + if [ -n "$STAGING" ]; then + skip "Not trying on staging server yet" + fi + + CONFIG_FILE="getssl-dns01.cfg" + . "${CODE_DIR}/test/test-config/${CONFIG_FILE}" + CERT=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt + ORIGINAL_ENDDATE=$(openssl x509 -in "$CERT" -noout -enddate 2>/dev/null| cut -d= -f 2-) + + create_certificate + assert_success + check_output_for_errors + + # Check that getssl didn't renew the certificate + refute_line --partial "certificate needs renewal" + assert_line --partial 'certificate is valid for more than' + + # Check that the end date in the certificate hasn't changed + UPDATED_ENDDATE=$(openssl x509 -in "$CERT" -noout -enddate 2>/dev/null| cut -d= -f 2-) + if [[ "$ORIGINAL_ENDDATE" != "$UPDATED_ENDDATE" ]]; then + echo "# ORIGINAL_ENDDATE=$ORIGINAL_ENDDATE" + echo "# UPDATED_ENDDATE =$UPDATED_ENDDATE" + fi + [[ "$ORIGINAL_ENDDATE" = "$UPDATED_ENDDATE" ]] +} + + + +@test "Check that we can renew a certificate which does need renewing" { + if [ -n "$STAGING" ]; then + skip "Not trying on staging server yet" + fi + + CONFIG_FILE="getssl-dns01.cfg" + cat <<- EOF > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg +RENEW_ALLOW=2000 +EOF + + . "${CODE_DIR}/test/test-config/${CONFIG_FILE}" + CERT=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt + ORIGINAL_ENDDATE=$(openssl x509 -in "$CERT" -noout -enddate 2>/dev/null| cut -d= -f 2-) + + create_certificate + assert_success + check_output_for_errors + + # Check that getssl didn't renew the certificate + refute_line --partial 'certificate is valid for more than' + + # Check that the end date in the certificate hasn't changed + UPDATED_ENDDATE=$(openssl x509 -in "$CERT" -noout -enddate 2>/dev/null| cut -d= -f 2-) + if [[ "$ORIGINAL_ENDDATE" = "$UPDATED_ENDDATE" ]]; then + echo "# ORIGINAL_ENDDATE=$ORIGINAL_ENDDATE" + echo "# UPDATED_ENDDATE =$UPDATED_ENDDATE" + fi + [[ "$ORIGINAL_ENDDATE" != "$UPDATED_ENDDATE" ]] +} diff --git a/test/test-config/getssl-dns01-add-to-sans-1.cfg b/test/test-config/getssl-dns01-add-to-sans-1.cfg deleted file mode 100644 index ddb514a..0000000 --- a/test/test-config/getssl-dns01-add-to-sans-1.cfg +++ /dev/null @@ -1,37 +0,0 @@ -# Uncomment and modify any variables you need -# see https://github.com/srvrco/getssl/wiki/Config-variables for details -# see https://github.com/srvrco/getssl/wiki/Example-config-files for example configs -# -CA="https://pebble:14000/dir" - -VALIDATE_VIA_DNS=true -DNS_ADD_COMMAND="/getssl/dns_scripts/dns_add_challtestsrv" -DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_challtestsrv" -AUTH_DNS_SERVER=10.30.50.3 - -# Speed up the test by reducing the number or retries and the wait between retries. -DNS_WAIT=2 -DNS_WAIT_COUNT=11 -DNS_EXTRA_WAIT=0 - -# Additional domains - this could be multiple domains / subdomains in a comma separated list -SANS="a.${GETSSL_HOST}" - -# Location for all your certs, these can either be on the server (full path name) -# or using ssh /sftp as for the ACL -DOMAIN_CERT_LOCATION="/etc/nginx/pki/server.crt" -DOMAIN_KEY_LOCATION="/etc/nginx/pki/private/server.key" -CA_CERT_LOCATION="/etc/nginx/pki/chain.crt" -DOMAIN_CHAIN_LOCATION="" # this is the domain cert and CA cert -DOMAIN_PEM_LOCATION="" # this is the domain_key, domain cert and CA cert - -# The command needed to reload apache / nginx or whatever you use -RELOAD_CMD="cp /getssl/test/test-config/nginx-ubuntu-ssl ${NGINX_CONFIG} && /getssl/test/restart-nginx" - -# Define the server type and confirm correct certificate is installed -SERVER_TYPE="https" -CHECK_REMOTE="true" -IGNORE_DIRECTORY_DOMAIN="true" - -#_USE_DEBUG=1 -#_RUNNING_TEST=1 diff --git a/test/test-config/getssl-dns01-add-to-sans-2.cfg b/test/test-config/getssl-dns01-add-to-sans-2.cfg deleted file mode 100644 index 9196905..0000000 --- a/test/test-config/getssl-dns01-add-to-sans-2.cfg +++ /dev/null @@ -1,37 +0,0 @@ -# Uncomment and modify any variables you need -# see https://github.com/srvrco/getssl/wiki/Config-variables for details -# see https://github.com/srvrco/getssl/wiki/Example-config-files for example configs -# -CA="https://pebble:14000/dir" - -VALIDATE_VIA_DNS=true -DNS_ADD_COMMAND="/getssl/dns_scripts/dns_add_challtestsrv" -DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_challtestsrv" -AUTH_DNS_SERVER=10.30.50.3 - -# Speed up the test by reducing the number or retries and the wait between retries. -DNS_WAIT=2 -DNS_WAIT_COUNT=11 -DNS_EXTRA_WAIT=0 - -# Additional domains - this could be multiple domains / subdomains in a comma separated list -SANS="b.${GETSSL_HOST}, a.${GETSSL_HOST}" - -# Location for all your certs, these can either be on the server (full path name) -# or using ssh /sftp as for the ACL -DOMAIN_CERT_LOCATION="/etc/nginx/pki/server.crt" -DOMAIN_KEY_LOCATION="/etc/nginx/pki/private/server.key" -CA_CERT_LOCATION="/etc/nginx/pki/chain.crt" -DOMAIN_CHAIN_LOCATION="" # this is the domain cert and CA cert -DOMAIN_PEM_LOCATION="" # this is the domain_key, domain cert and CA cert - -# The command needed to reload apache / nginx or whatever you use -RELOAD_CMD="cp /getssl/test/test-config/nginx-ubuntu-ssl ${NGINX_CONFIG} && /getssl/test/restart-nginx" - -# Define the server type and confirm correct certificate is installed -SERVER_TYPE="https" -CHECK_REMOTE="false" -IGNORE_DIRECTORY_DOMAIN="true" - -#_USE_DEBUG=1 -#_RUNNING_TEST=1