From a13e41036381a76de1e77a6ddd3d30170d445d6d Mon Sep 17 00:00:00 2001 From: crza Date: Mon, 17 Oct 2016 22:40:03 +0200 Subject: [PATCH] Basic implementation for private key rollover (#294) * initial commit for PRIVATE_KEY_ROLLOVER * fix if syntax * rolloverkey without timestamps * update example config: PRIVATE_KEY_ROLLOVER * rolloverkey creation logic updated * updated tests. untested. * added cleanup for rolloverkeys: if disabled, delete privkey.roll.pem --- dehydrated | 23 ++++++++++++++++++++++- docs/examples/config | 3 +++ test.sh | 20 ++++++++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/dehydrated b/dehydrated index 63e3fc3..f740890 100755 --- a/dehydrated +++ b/dehydrated @@ -118,6 +118,7 @@ load_config() { KEYSIZE="4096" WELLKNOWN= PRIVATE_KEY_RENEW="yes" + PRIVATE_KEY_ROLLOVER="no" KEY_ALGO=rsa OPENSSL_CNF="$(openssl version -d | cut -d\" -f2)/openssl.cnf" CONTACT_EMAIL= @@ -596,6 +597,26 @@ sign_domain() { prime256v1|secp384r1) _openssl ecparam -genkey -name "${KEY_ALGO}" -out "${CERTDIR}/${domain}/privkey-${timestamp}.pem";; esac fi + # move rolloverkey into position (if any) + if [[ -r "${CERTDIR}/${domain}/privkey.pem" && -r "${CERTDIR}/${domain}/privkey.roll.pem" && "${PRIVATE_KEY_RENEW}" = "yes" && "${PRIVATE_KEY_ROLLOVER}" = "yes" ]]; then + echo " + Moving Rolloverkey into position.... " + mv "${CERTDIR}/${domain}/privkey.roll.pem" "${CERTDIR}/${domain}/privkey-tmp.pem" + mv "${CERTDIR}/${domain}/privkey-${timestamp}.pem" "${CERTDIR}/${domain}/privkey.roll.pem" + mv "${CERTDIR}/${domain}/privkey-tmp.pem" "${CERTDIR}/${domain}/privkey-${timestamp}.pem" + fi + # generate a new private rollover key if we need or want one + if [[ ! -r "${CERTDIR}/${domain}/privkey.roll.pem" && "${PRIVATE_KEY_ROLLOVER}" = "yes" && "${PRIVATE_KEY_RENEW}" = "yes" ]]; then + echo " + Generating private rollover key..." + case "${KEY_ALGO}" in + rsa) _openssl genrsa -out "${CERTDIR}/${domain}/privkey.roll.pem" "${KEYSIZE}";; + prime256v1|secp384r1) _openssl ecparam -genkey -name "${KEY_ALGO}" -out "${CERTDIR}/${domain}/privkey.roll.pem";; + esac + fi + # delete rolloverkeys if disabled + if [[ -r "${CERTDIR}/${domain}/privkey.roll.pem" && ! "${PRIVATE_KEY_ROLLOVER}" = "yes" ]]; then + echo " + Removing Rolloverkey (feature disabled)..." + rm -f "${CERTDIR}/${domain}/privkey.roll.pem" + fi # Generate signing request config and the actual signing request echo " + Generating signing request..." @@ -709,7 +730,7 @@ command_sign_domains() { config_var="$(echo "${cfgline:1}" | cut -d'=' -f1)" config_value="$(echo "${cfgline:1}" | cut -d'=' -f2-)" case "${config_var}" in - KEY_ALGO|OCSP_MUST_STAPLE|PRIVATE_KEY_RENEW|KEYSIZE|CHALLENGETYPE|HOOK|WELLKNOWN|HOOK_CHAIN|OPENSSL_CNF|RENEW_DAYS) + KEY_ALGO|OCSP_MUST_STAPLE|PRIVATE_KEY_RENEW|PRIVATE_KEY_ROLLOVER|KEYSIZE|CHALLENGETYPE|HOOK|WELLKNOWN|HOOK_CHAIN|OPENSSL_CNF|RENEW_DAYS) echo " + ${config_var} = ${config_value}" declare -- "${config_var}=${config_value}" ;; diff --git a/docs/examples/config b/docs/examples/config index 17621d2..92b2b83 100644 --- a/docs/examples/config +++ b/docs/examples/config @@ -72,6 +72,9 @@ # Regenerate private keys instead of just signing new certificates on renewal (default: yes) #PRIVATE_KEY_RENEW="yes" +# Create an extra private key for rollover (default: no) +#PRIVATE_KEY_ROLLOVER="no" + # Which public key algorithm should be used? Supported: rsa, prime256v1 and secp384r1 #KEY_ALGO=rsa diff --git a/test.sh b/test.sh index 430dd1d..8044049 100755 --- a/test.sh +++ b/test.sh @@ -209,6 +209,26 @@ _CHECK_LOG "Done." _CHECK_FILE "certs/${TMP_URL}/${REAL_CERT}-revoked" _CHECK_ERRORLOG +# Enable private key renew +echo 'PRIVATE_KEY_RENEW="yes"' >> config +echo 'PRIVATE_KEY_ROLLOVER="yes"' >> config + +# Check if Rolloverkey creation works +_TEST "Testing Rolloverkeys..." +_SUBTEST "First Run: Creating rolloverkey" +./dehydrated --cron --domain "${TMP2_URL}" > tmplog 2> errorlog || _FAIL "Script execution failed" +CERT_ROLL_HASH=$(openssl rsa -in certs/${TMP2_URL}/privkey.roll.pem -outform DER -pubout 2>/dev/null | openssl sha256) +_CHECK_LOG "Generating private key" +_CHECK_LOG "Generating private rollover key" +_SUBTEST "Second Run: Force Renew, Use rolloverkey" +./dehydrated --cron --force --domain "${TMP2_URL}" > tmplog 2> errorlog || _FAIL "Script execution failed" +CERT_NEW_HASH=$(openssl rsa -in certs/${TMP2_URL}/privkey.pem -outform DER -pubout 2>/dev/null | openssl sha256) +_CHECK_LOG "Generating private key" +_CHECK_LOG "Moving Rolloverkey into position" +_SUBTEST "Verifying Hash Rolloverkey and private key second run" +[[ "${CERT_ROLL_HASH}" = "${CERT_NEW_HASH}" ]] && _PASS || _FAIL +_CHECK_ERRORLOG + # Test cleanup command _TEST "Cleaning up certificates" ./dehydrated --cleanup > tmplog 2> errorlog || _FAIL "Script execution failed" -- 2.39.5