From aae47d2c260f6025617ed0cd9e38447fdd9f407e Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Thu, 14 May 2020 17:05:20 +0100 Subject: [PATCH 1/6] Add --notify-valid --- getssl | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/getssl b/getssl index 1a14ac8..1807249 100755 --- a/getssl +++ b/getssl @@ -277,6 +277,7 @@ _CREATE_CONFIG=0 _FORCE_RENEW=0 _KEEP_VERSIONS="" _MUTE=0 +_NOTIFY_VALID=0 _QUIET=0 _RECREATE_CSR=0 _REVOKE=0 @@ -1496,8 +1497,10 @@ get_signing_params() { # get signing parameters from key } graceful_exit() { # normal exit function. + exit_code=$1 clean_up - exit + # shellcheck disable=SC2086 + exit $exit_code } help_message() { # print out the help message @@ -2230,30 +2233,33 @@ while [[ -n ${1+defined} ]]; do -h | --help) help_message; graceful_exit ;; -d | --debug) - _USE_DEBUG=1 ;; + _USE_DEBUG=1 ;; -c | --create) - _CREATE_CONFIG=1 ;; + _CREATE_CONFIG=1 ;; -f | --force) - _FORCE_RENEW=1 ;; + _FORCE_RENEW=1 ;; + --notify-valid) + # Exit 2 if certificate is valid and doesn't need renewing + _NOTIFY_VALID=2 ;; -a | --all) - _CHECK_ALL=1 ;; + _CHECK_ALL=1 ;; -k | --keep) - shift; _KEEP_VERSIONS="$1";; + shift; _KEEP_VERSIONS="$1";; -q | --quiet) - _QUIET=1 ;; + _QUIET=1 ;; -Q | --mute) - _QUIET=1 - _MUTE=1 ;; + _QUIET=1 + _MUTE=1 ;; -r | --revoke) - _REVOKE=1 - shift - REVOKE_CERT="$1" - shift - REVOKE_KEY="$1" - shift - REVOKE_CA="$1" ;; + _REVOKE=1 + shift + REVOKE_CERT="$1" + shift + REVOKE_KEY="$1" + shift + REVOKE_CA="$1" ;; -u | --upgrade) - _UPGRADE=1 ;; + _UPGRADE=1 ;; -U | --nocheck) _UPGRADE_CHECK=0 ;; -i | --install) @@ -2630,8 +2636,8 @@ if [[ -s "$CERT_FILE" ]]; then debug "upgrading from fake cert to real" else info "${DOMAIN}: certificate is valid for more than $RENEW_ALLOW days (until $enddate)" - # everything is OK, so exit. - graceful_exit + # everything is OK, so exit, if requested with the --notify-valid, exit with code 2 + graceful_exit $_NOTIFY_VALID fi else debug "${DOMAIN}: certificate needs renewal" From 2287057e386996666184b07049d93e1dec9d2aa5 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Thu, 14 May 2020 17:05:55 +0100 Subject: [PATCH 2/6] Add test for --notify-valid --- test/13-notify-valid.bats | 45 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 test/13-notify-valid.bats diff --git a/test/13-notify-valid.bats b/test/13-notify-valid.bats new file mode 100644 index 0000000..ac1a50c --- /dev/null +++ b/test/13-notify-valid.bats @@ -0,0 +1,45 @@ +#! /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() { + export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt +} + + +@test "Create certificate to check valid exit code" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + CONFIG_FILE="getssl-http01.cfg" + setup_environment + init_getssl + create_certificate + assert_success + check_output_for_errors +} + + +@test "Check no-renewal needed exits with normal exit code" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + run ${CODE_DIR}/getssl $GETSSL_HOST + assert_success + check_output_for_errors +} + + +@test "Check no-renewal needed returns 2 if requested" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + run ${CODE_DIR}/getssl --notify-valid $GETSSL_HOST + assert [ $status == 2 ] + check_output_for_errors + cleanup_environment +} From db316d0d16b998a470a45bd18f0bb410b793a643 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sat, 23 May 2020 20:58:44 +0100 Subject: [PATCH 3/6] Fix --revoke --- getssl | 93 +++++++++++++++++++++++++++++++++------------------------- 1 file changed, 53 insertions(+), 40 deletions(-) diff --git a/getssl b/getssl index 1807249..710fba4 100755 --- a/getssl +++ b/getssl @@ -1743,6 +1743,45 @@ json_get() { # get values from json fi } +obtain_ca_resource_locations() +{ + # Obtain CA resource locations + ca_all_loc=$(curl --user-agent "$CURL_USERAGENT" "${CA}" 2>/dev/null) + debug "ca_all_loc from ${CA} gives $ca_all_loc" + # APIv1 + URL_new_reg=$(echo "$ca_all_loc" | grep "new-reg" | awk -F'"' '{print $4}') + URL_new_authz=$(echo "$ca_all_loc" | grep "new-authz" | awk -F'"' '{print $4}') + URL_new_cert=$(echo "$ca_all_loc" | grep "new-cert" | awk -F'"' '{print $4}') + #API v2 + URL_newAccount=$(echo "$ca_all_loc" | grep "newAccount" | awk -F'"' '{print $4}') + URL_newNonce=$(echo "$ca_all_loc" | grep "newNonce" | awk -F'"' '{print $4}') + URL_newOrder=$(echo "$ca_all_loc" | grep "newOrder" | awk -F'"' '{print $4}') + URL_revoke=$(echo "$ca_all_loc" | grep "revokeCert" | awk -F'"' '{print $4}') + + if [[ -z "$URL_new_reg" ]] && [[ -z "$URL_newAccount" ]]; then + ca_all_loc=$(curl --user-agent "$CURL_USERAGENT" "${CA}/directory" 2>/dev/null) + debug "ca_all_loc from ${CA}/directory gives $ca_all_loc" + # APIv1 + URL_new_reg=$(echo "$ca_all_loc" | grep "new-reg" | awk -F'"' '{print $4}') + URL_new_authz=$(echo "$ca_all_loc" | grep "new-authz" | awk -F'"' '{print $4}') + URL_new_cert=$(echo "$ca_all_loc" | grep "new-cert" | awk -F'"' '{print $4}') + #API v2 + URL_newAccount=$(echo "$ca_all_loc" | grep "newAccount" | awk -F'"' '{print $4}') + URL_newNonce=$(echo "$ca_all_loc" | grep "newNonce" | awk -F'"' '{print $4}') + URL_newOrder=$(echo "$ca_all_loc" | grep "newOrder" | awk -F'"' '{print $4}') + fi + + if [[ -n "$URL_new_reg" ]]; then + API=1 + elif [[ -n "$URL_newAccount" ]]; then + API=2 + else + info "unknown API version" + graceful_exit + fi + debug "Using API v$API" +} + os_esed() { # Use different sed version for different os types (extended regex) if [[ "$os" == "bsd" ]]; then # BSD requires -E flag for extended regex sed -E "${@}" @@ -1807,9 +1846,9 @@ revoke_certificate() { # revoke a certificate # need to set the revoke key as "account_key" since it's used in send_signed_request. get_signing_params "$REVOKE_KEY" TEMP_DIR=$(mktemp -d 2>/dev/null || mktemp -d -t getssl) - debug "revoking from $CA" - rcertdata=$(openssl x509 -in "$REVOKE_CERT" -inform PEM -outform DER | urlbase64) - send_signed_request "$URL_revoke" "{\"resource\": \"revoke-cert\", \"certificate\": \"$rcertdata\"}" + debug "revoking from $URL_revoke" + rcertdata=$(sed '1d;$d' "$REVOKE_CERT" | tr -d "\r\n" | tr '/+' '_-' | tr -d '= ') + send_signed_request "$URL_revoke" "{\"certificate\": \"$rcertdata\",\"reason\": $REVOKE_REASON}" if [[ $code -eq "200" ]]; then info "certificate revoked" else @@ -1959,15 +1998,18 @@ send_signed_request() { # Sends a request to the ACME server, signed with your p while [[ "$code" -eq 500 ]]; do if [[ "$outfile" ]] ; then $CURL -X POST -H "Content-Type: application/jose+json" --data "$body" "$url" > "$outfile" + errcode=$? response=$(cat "$outfile") elif [[ "$needbase64" ]] ; then response=$($CURL -X POST -H "Content-Type: application/jose+json" --data "$body" "$url" | urlbase64) + errcode=$? else response=$($CURL -X POST -H "Content-Type: application/jose+json" --data "$body" "$url") + errcode=$? fi - if [[ "$response" == "" ]]; then - error_exit "ERROR curl \"$url\" returned nothing" + if [[ $errcode -gt 0 || ( "$response" == "" && $url != *"revoke"* ) ]]; then + error_exit "ERROR curl \"$url\" failed with $errcode and returned $response" fi responseHeaders=$(cat "$CURL_HEADER") @@ -2257,7 +2299,9 @@ while [[ -n ${1+defined} ]]; do shift REVOKE_KEY="$1" shift - REVOKE_CA="$1" ;; + CA="$1" + REVOKE_CA="$1" + REVOKE_REASON=0 ;; -u | --upgrade) _UPGRADE=1 ;; -U | --nocheck) @@ -2324,7 +2368,8 @@ if [[ $_REVOKE -eq 1 ]]; then else CA=$REVOKE_CA fi - URL_revoke=$(curl --user-agent "$CURL_USERAGENT" "${CA}/directory" 2>/dev/null | grep "revoke-cert" | awk -F'"' '{print $4}') + + obtain_ca_resource_locations revoke_certificate graceful_exit fi @@ -2508,39 +2553,7 @@ if [[ -e "$DOMAIN_DIR/FORCE_RENEWAL" ]]; then info "${DOMAIN}: forcing renewal (due to FORCE_RENEWAL file)" fi -# Obtain CA resource locations -ca_all_loc=$(curl --user-agent "$CURL_USERAGENT" "${CA}" 2>/dev/null) -debug "ca_all_loc from ${CA} gives $ca_all_loc" -# APIv1 -URL_new_reg=$(echo "$ca_all_loc" | grep "new-reg" | awk -F'"' '{print $4}') -URL_new_authz=$(echo "$ca_all_loc" | grep "new-authz" | awk -F'"' '{print $4}') -URL_new_cert=$(echo "$ca_all_loc" | grep "new-cert" | awk -F'"' '{print $4}') -#API v2 -URL_newAccount=$(echo "$ca_all_loc" | grep "newAccount" | awk -F'"' '{print $4}') -URL_newNonce=$(echo "$ca_all_loc" | grep "newNonce" | awk -F'"' '{print $4}') -URL_newOrder=$(echo "$ca_all_loc" | grep "newOrder" | awk -F'"' '{print $4}') -if [[ -z "$URL_new_reg" ]] && [[ -z "$URL_newAccount" ]]; then - ca_all_loc=$(curl --user-agent "$CURL_USERAGENT" "${CA}/directory" 2>/dev/null) - debug "ca_all_loc from ${CA}/directory gives $ca_all_loc" - # APIv1 - URL_new_reg=$(echo "$ca_all_loc" | grep "new-reg" | awk -F'"' '{print $4}') - URL_new_authz=$(echo "$ca_all_loc" | grep "new-authz" | awk -F'"' '{print $4}') - URL_new_cert=$(echo "$ca_all_loc" | grep "new-cert" | awk -F'"' '{print $4}') - #API v2 - URL_newAccount=$(echo "$ca_all_loc" | grep "newAccount" | awk -F'"' '{print $4}') - URL_newNonce=$(echo "$ca_all_loc" | grep "newNonce" | awk -F'"' '{print $4}') - URL_newOrder=$(echo "$ca_all_loc" | grep "newOrder" | awk -F'"' '{print $4}') -fi - -if [[ -n "$URL_new_reg" ]]; then - API=1 -elif [[ -n "$URL_newAccount" ]]; then - API=2 -else - info "unknown API version" - graceful_exit -fi -debug "Using API v$API" +obtain_ca_resource_locations # Check if awk supports json_awk (required for ACMEv2) if [[ $API -eq 2 ]]; then From fc4add8747d46be2398734ffbe616e93d7c2ad88 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sat, 23 May 2020 21:00:04 +0100 Subject: [PATCH 4/6] Test --revoke --- test/14-test-revoke.bats | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 test/14-test-revoke.bats diff --git a/test/14-test-revoke.bats b/test/14-test-revoke.bats new file mode 100644 index 0000000..ac056c2 --- /dev/null +++ b/test/14-test-revoke.bats @@ -0,0 +1,37 @@ +#! /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() { + export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt +} + + +@test "Create certificate to check revoke" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + CONFIG_FILE="getssl-http01.cfg" + setup_environment + init_getssl + create_certificate + assert_success + check_output_for_errors +} + + +@test "Check we can revoke a certificate" { + if [ -n "$STAGING" ]; then + skip "Using staging server, skipping internal test" + fi + CERT=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt + KEY=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.key + CA="https://pebble:14000/dir" + run ${CODE_DIR}/getssl -d --revoke $CERT $KEY $CA + assert_success + check_output_for_errors +} From d568e15563ea7353173a940374ccc4470f1e5b32 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sat, 23 May 2020 21:28:32 +0100 Subject: [PATCH 5/6] Update test to test using staging server --- test/14-test-revoke.bats | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/test/14-test-revoke.bats b/test/14-test-revoke.bats index ac056c2..2e95e0d 100644 --- a/test/14-test-revoke.bats +++ b/test/14-test-revoke.bats @@ -13,9 +13,11 @@ setup() { @test "Create certificate to check revoke" { if [ -n "$STAGING" ]; then - skip "Using staging server, skipping internal test" + CONFIG_FILE="getssl-staging-dns01.cfg" + else + CONFIG_FILE="getssl-http01.cfg" fi - CONFIG_FILE="getssl-http01.cfg" + . "${CODE_DIR}/test/test-config/${CONFIG_FILE}" setup_environment init_getssl create_certificate @@ -26,11 +28,14 @@ setup() { @test "Check we can revoke a certificate" { if [ -n "$STAGING" ]; then - skip "Using staging server, skipping internal test" + CONFIG_FILE="getssl-staging-dns01.cfg" + else + CONFIG_FILE="getssl-http01.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 - CA="https://pebble:14000/dir" + run ${CODE_DIR}/getssl -d --revoke $CERT $KEY $CA assert_success check_output_for_errors From 86b365b2c35508cd4421763adc5d96ecffc38418 Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Sun, 24 May 2020 09:46:13 +0100 Subject: [PATCH 6/6] Update revision history and version number --- getssl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/getssl b/getssl index 710fba4..371906f 100755 --- a/getssl +++ b/getssl @@ -229,11 +229,13 @@ # 2020-04-26 Fixed ipv4 confirmation with nslookup - Cyber1000 # 2020-04-29 Fix ftp/sftp problems if challenge starts with a dash # 2020-05-06 Fix missing fullchain.ec.crt when creating dual certificates (2.27) +# 2020-05-14 Add --notify-valid option (exit 2 if certificate is valid) +# 2020-05-23 Fix --revoke (didn't work with ACMEv02) (2.28) # ---------------------------------------------------------------------------------------- PROGNAME=${0##*/} PROGDIR="$(cd "$(dirname "$0")" || exit; pwd -P;)" -VERSION="2.27" +VERSION="2.28" # defaults ACCOUNT_KEY_LENGTH=4096