Skip to content

Commit

Permalink
Merge pull request srvrco#507 from srvrco/dual-rsa-ecdsa-2-locations
Browse files Browse the repository at this point in the history
Fix bug srvrco#505 with DUAL_RSA_ECDSA and multiple locations
  • Loading branch information
timkimber committed Feb 14, 2020
2 parents 7bf1475 + 74f4bbe commit 304ef0a
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 19 deletions.
37 changes: 25 additions & 12 deletions getssl
Original file line number Diff line number Diff line change
Expand Up @@ -211,10 +211,11 @@
# 2020-02-12 Fix for DUAL_RSA_ECDSA not working with ACMEv2 (#334, #474, #502)
# 2020-02-12 Fix #424 - Sporadic "error in EC signing couldn't get R from ..." (2.18)
# 2020-02-12 Fix "Registration key already in use" (2.19)
# 2020-02-13 Fix bug with copying to all locations when creating RSA and ECDSA certs (2.20)
# ----------------------------------------------------------------------------------------

PROGNAME=${0##*/}
VERSION="2.19"
VERSION="2.20"

# defaults
ACCOUNT_KEY_LENGTH=4096
Expand Down Expand Up @@ -549,8 +550,12 @@ copy_file_to_location() { # copies a file, using scp, sftp or ftp if required.
cert=$1 # descriptive name, just used for display
from=$2 # current file location
to=$3 # location to move file to.
suffix=$4 # (optional) optional suffix for DUAL_RSA_ECDSA, i.e. save to private.key becomes save to private.ec.key
IFS=\; read -r -a copy_locations <<<"$3"
for to in "${copy_locations[@]}"; do
if [[ -n "$suffix" ]]; then
to="${to%.*}.${suffix}.${to##*.}"
fi
info "copying $cert to $to"
if [[ "${to:0:4}" == "ssh:" ]] ; then
debug "using scp -q $SCP_OPTS $from ${to:4}"
Expand Down Expand Up @@ -1823,6 +1828,9 @@ sign_string() { # sign a string with a given key and algorithm and return urlbas
elif [[ "${signed:4:4}" == "0231" ]]; then #sha384 which needs trimming
R=$(echo "$signed" | cut -c 11-106)
part2=$(echo "$signed" | cut -c 107-)
elif [[ "${signed:6:4}" == "0240" ]]; then #sha512 which needs padding
R=$(echo -n 00;echo "$signed" | cut -c 9-138)
part2=$(echo "$signed" | cut -c 141-)
elif [[ "${signed:6:4}" == "0241" ]]; then #sha512 which needs padding
R=$(echo -n 00;echo "$signed" | cut -c 11-140)
part2=$(echo "$signed" | cut -c 141-)
Expand All @@ -1846,6 +1854,8 @@ sign_string() { # sign a string with a given key and algorithm and return urlbas
S=$(echo "$part2" | cut -c 5-100)
elif [[ "${part2:0:4}" == "0231" ]]; then #sha384
S=$(echo "$part2" | cut -c 7-102)
elif [[ "${part2:0:4}" == "0240" ]]; then #sha512 with padding
S=$(echo -n 00;echo "$part2" | cut -c 5-)
elif [[ "${part2:0:4}" == "0241" ]]; then #sha512 with padding
S=$(echo -n 00;echo "$part2" | cut -c 5-)
elif [[ "${part2:0:4}" == "0242" ]]; then #sha512
Expand Down Expand Up @@ -2545,17 +2555,20 @@ if [[ "$DUAL_RSA_ECDSA" == "true" ]]; then
if [[ -n "$DOMAIN_CERT_LOCATION" ]]; then
copy_file_to_location "ec domain certificate" \
"${CERT_FILE%.*}.ec.crt" \
"${DOMAIN_CERT_LOCATION%.*}.ec.crt"
"${DOMAIN_CERT_LOCATION}" \
"ec"
fi
if [[ -n "$DOMAIN_KEY_LOCATION" ]]; then
copy_file_to_location "ec private key" \
"$DOMAIN_DIR/${DOMAIN}.ec.key" \
"${DOMAIN_KEY_LOCATION%.*}.ec.key"
copy_file_to_location "ec private key" \
"$DOMAIN_DIR/${DOMAIN}.ec.key" \
"${DOMAIN_KEY_LOCATION}" \
"ec"
fi
if [[ -n "$CA_CERT_LOCATION" ]]; then
copy_file_to_location "ec CA certificate" \
"${CA_CERT%.*}.ec.crt" \
"${CA_CERT_LOCATION%.*}.ec.crt"
copy_file_to_location "ec CA certificate" \
"${CA_CERT%.*}.ec.crt" \
"${CA_CERT_LOCATION%.*}.crt" \
"ec"
fi
fi

Expand All @@ -2570,7 +2583,7 @@ if [[ -n "$DOMAIN_CHAIN_LOCATION" ]]; then
copy_file_to_location "full chain" "$TEMP_DIR/${DOMAIN}_chain.pem" "$to_location"
if [[ "$DUAL_RSA_ECDSA" == "true" ]]; then
cat "${CERT_FILE%.*}.ec.crt" "${CA_CERT%.*}.ec.crt" > "$TEMP_DIR/${DOMAIN}_chain.pem.ec"
copy_file_to_location "full chain" "$TEMP_DIR/${DOMAIN}_chain.pem.ec" "${to_location%.*}.ec.${to_location##*.}"
copy_file_to_location "full chain" "$TEMP_DIR/${DOMAIN}_chain.pem.ec" "${to_location}" "ec"
fi
fi
# if DOMAIN_KEY_CERT_LOCATION is not blank, then create and copy file.
Expand All @@ -2583,8 +2596,8 @@ if [[ -n "$DOMAIN_KEY_CERT_LOCATION" ]]; then
cat "$DOMAIN_DIR/${DOMAIN}.key" "$CERT_FILE" > "$TEMP_DIR/${DOMAIN}_K_C.pem"
copy_file_to_location "private key and domain cert pem" "$TEMP_DIR/${DOMAIN}_K_C.pem" "$to_location"
if [[ "$DUAL_RSA_ECDSA" == "true" ]]; then
cat "$DOMAIN_DIR/${DOMAIN}.ec.key" "${CERT_FILE%.*}.ec.crt" > "$TEMP_DIR/${DOMAIN}_K_C.pem.ec"
copy_file_to_location "private ec key and domain cert pem" "$TEMP_DIR/${DOMAIN}_K_C.pem.ec" "${to_location%.*}.ec.${to_location##*.}"
cat "$DOMAIN_DIR/${DOMAIN}.ec.key" "${CERT_FILE%.*}.ec.crt" > "$TEMP_DIR/${DOMAIN}_K_C.pem.ec"
copy_file_to_location "private ec key and domain cert pem" "$TEMP_DIR/${DOMAIN}_K_C.pem.ec" "${to_location}" "ec"
fi
fi
# if DOMAIN_PEM_LOCATION is not blank, then create and copy file.
Expand All @@ -2598,7 +2611,7 @@ if [[ -n "$DOMAIN_PEM_LOCATION" ]]; then
copy_file_to_location "full key, cert and chain pem" "$TEMP_DIR/${DOMAIN}.pem" "$to_location"
if [[ "$DUAL_RSA_ECDSA" == "true" ]]; then
cat "$DOMAIN_DIR/${DOMAIN}.ec.key" "${CERT_FILE%.*}.ec.crt" "${CA_CERT%.*}.ec.crt" > "$TEMP_DIR/${DOMAIN}.pem.ec"
copy_file_to_location "full ec key, cert and chain pem" "$TEMP_DIR/${DOMAIN}.pem.ec" "${to_location%.*}.ec.${to_location##*.}"
copy_file_to_location "full ec key, cert and chain pem" "$TEMP_DIR/${DOMAIN}.pem.ec" "${to_location}" "ec"
fi
fi
# end of copying certs.
Expand Down
4 changes: 2 additions & 2 deletions test/4-more-than-10-hosts.bats
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ setup() {

# Add 11 hosts to DNS (also need to be added as aliases in docker-compose.yml)
for prefix in a b c d e f g h i j k; do
curl -X POST -d '{"host":"'$prefix.$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' https://10.30.50.3:8055/add-a
curl --silent -X POST -d '{"host":"'$prefix.$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' https://10.30.50.3:8055/add-a
done

init_getssl
Expand All @@ -39,6 +39,6 @@ setup() {
# Remove all the dns aliases
cleanup_environment
for prefix in a b c d e f g h i j k; do
curl -X POST -d '{"host":"'$prefix.$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' https://10.30.50.3:8055/del-a
curl --silent -X POST -d '{"host":"'$prefix.$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' https://10.30.50.3:8055/del-a
done
}
40 changes: 40 additions & 0 deletions test/6-dual-rsa-ecdsa-copy-2-locations.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#! /usr/bin/env bats

load '/bats-support/load.bash'
load '/bats-assert/load.bash'
load '/getssl/test/test_helper.bash'


# These are run for every test, not once per file
setup() {
export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt
curl --silent -X POST -d '{"host":"'a.$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' https://10.30.50.3:8055/add-a
}


teardown() {
curl --silent -X POST -d '{"host":"'a.$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' https://10.30.50.3:8055/del-a
}


@test "Create dual certificates and copy RSA and ECDSA chain and key to two locations" {
CONFIG_FILE="getssl-http01-dual-rsa-ecdsa-2-locations.cfg"
setup_environment
mkdir -p /root/a.${GETSSL_HOST}

init_getssl
create_certificate
assert_success

# Check that the RSA chain and key have been copied to both locations
assert [ -e "/etc/nginx/pki/domain-chain.crt" ]
assert [ -e "/root/a.${GETSSL_HOST}/domain-chain.crt" ]
assert [ -e "/etc/nginx/pki/private/server.key" ]
assert [ -e "/root/a.${GETSSL_HOST}/server.key" ]

# Check that the ECDSA chain and key have been copied to both locations
assert [ -e "/etc/nginx/pki/domain-chain.ec.crt" ]
assert [ -e "/root/a.${GETSSL_HOST}/domain-chain.ec.crt" ]
assert [ -e "/etc/nginx/pki/private/server.ec.key" ]
assert [ -e "/root/a.${GETSSL_HOST}/server.ec.key" ]
}
14 changes: 12 additions & 2 deletions test/debug-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,22 @@
# This runs getssl outside of the BATS framework for debugging, etc, against pebble
# Usage: /getssl/test/debug-test.sh getssl-http01.cfg

DEBUG=""
if [ $# -eq 2 ]; then
DEBUG=$1
shift
fi

CONFIG_FILE=$1
if [ ! -e "$CONFIG_FILE" ]; then
CONFIG_FILE=${CODE_DIR}/test/test-config/${CONFIG_FILE}
fi
source /getssl/test/test_helper.bash

setup_environment 3>&1
export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt

"${CODE_DIR}/getssl" -c "$GETSSL_HOST" 3>&1
cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/${GETSSL_HOST}/getssl.cfg"
"${CODE_DIR}/getssl" -f "$GETSSL_HOST" 3>&1
cp "${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/${GETSSL_HOST}/getssl.cfg"
# shellcheck disable=SC2086
"${CODE_DIR}/getssl" ${DEBUG} -f "$GETSSL_HOST" 3>&1
5 changes: 5 additions & 0 deletions test/run-all-tests.cmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
docker exec -it getssl-alpine bats /getssl/test
docker exec -it getssl-centos6 bats /getssl/test
docker exec -it getssl-debian bats /getssl/test
docker exec -it getssl-ubuntu bats /getssl/test
docker exec -it getssl-ubuntu18 bats /getssl/test
32 changes: 32 additions & 0 deletions test/test-config/getssl-http01-dual-rsa-ecdsa-2-locations.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Test that more than one location can be specified for CERT and KEY locations and that the
# files are copied to both locations when both RSA and ECDSA certificates are created
#
CA="https://pebble:14000/dir"

DUAL_RSA_ECDSA="true"
ACCOUNT_KEY_TYPE="prime256v1"
PRIVATE_KEY_ALG="prime256v1"

# Additional domains - this could be multiple domains / subdomains in a comma separated list
SANS="a.${GETSSL_HOST}"

# Acme Challenge Location.
ACL=('/var/www/html/.well-known/acme-challenge')

#Set USE_SINGLE_ACL="true" to use a single ACL for all checks
USE_SINGLE_ACL="true"

# 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;/root/a.${GETSSL_HOST}/server.key"
CA_CERT_LOCATION="/etc/nginx/pki/chain.crt"
DOMAIN_CHAIN_LOCATION="/etc/nginx/pki/domain-chain.crt;/root/a.${GETSSL_HOST}/domain-chain.crt" # 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"
6 changes: 3 additions & 3 deletions test/test_helper.bash
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,22 @@ setup_environment() {
fi

if [ ! -f ${INSTALL_DIR}/pebble.minica.pem ]; then
wget --no-clobber https://raw.githubusercontent.com/letsencrypt/pebble/master/test/certs/pebble.minica.pem 2>&1
wget --quiet --no-clobber https://raw.githubusercontent.com/letsencrypt/pebble/master/test/certs/pebble.minica.pem 2>&1
CERT_FILE=/etc/ssl/certs/ca-certificates.crt
if [ ! -f $CERT_FILE ]; then
CERT_FILE=/etc/pki/tls/certs/ca-bundle.crt
fi
cat $CERT_FILE ${INSTALL_DIR}/pebble.minica.pem > ${INSTALL_DIR}/pebble-ca-bundle.crt
fi

curl -X POST -d '{"host":"'"$GETSSL_HOST"'", "addresses":["'"$GETSSL_IP"'"]}' https://10.30.50.3:8055/add-a
curl --silent -X POST -d '{"host":"'"$GETSSL_HOST"'", "addresses":["'"$GETSSL_IP"'"]}' https://10.30.50.3:8055/add-a
cp ${CODE_DIR}/test/test-config/nginx-ubuntu-no-ssl "${NGINX_CONFIG}"
/getssl/test/restart-nginx
}


cleanup_environment() {
curl -X POST -d '{"host":"'"$GETSSL_HOST"'", "addresses":["'"$GETSSL_IP"'"]}' https://10.30.50.3:8055/del-a
curl --silent -X POST -d '{"host":"'"$GETSSL_HOST"'", "addresses":["'"$GETSSL_IP"'"]}' https://10.30.50.3:8055/del-a
}


Expand Down

0 comments on commit 304ef0a

Please sign in to comment.