From e925b293c5eecb57678f3b65b4b5d1e5d93b370f Mon Sep 17 00:00:00 2001 From: Markus Germeier Date: Fri, 8 Jan 2016 22:09:27 +0100 Subject: [PATCH] add support for dns-01 challenge - try 2 --- README.md | 7 +++++++ config.sh.example | 3 +++ letsencrypt.sh | 48 +++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 50 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 4ddf04e..d8774e6 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,7 @@ Parameters: --privkey (-p) path/to/key.pem Use specified private key instead of account key (useful for revocation) --config (-f) path/to/config.sh Use specified config file --hook (-k) path/to/hook.sh Use specified script for hooks + --challenge (-t) http-01|dns-01 Which challenge should be used? Currently http-01 and dns-01 are supported ``` ### domains.txt @@ -79,6 +80,12 @@ WELLKNOWN="/var/www/letsencrypt" An alternative to setting the WELLKNOWN variable would be to create a symlink to the default location next to the script (or BASEDIR): `ln -s /var/www/letsencrypt .acme-challenges` +### dns-01 challenge + +This script also supports the new `dns-01`-type verification. Be aware that at the moment this is not available on the production servers from letsencrypt. Please read `https://community.letsencrypt.org/t/dns-challenge-is-in-staging/8322` for the current state of `dns-01` support. + +You need a hook script that deploys the challenge to your DNS server! + ## Import ### import-account.pl diff --git a/config.sh.example b/config.sh.example index 55559d2..bdbeea6 100644 --- a/config.sh.example +++ b/config.sh.example @@ -19,6 +19,9 @@ # Path to license agreement (default: https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf) #LICENSE="https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf" +# Which challenge should be used? Currently http-01 and dns-01 are supported +#CHALLENGETYPE="http-01" + # Base directory for account key, generated certificates and list of domains (default: $SCRIPTDIR -- uses config directory if undefined) #BASEDIR=$SCRIPTDIR diff --git a/letsencrypt.sh b/letsencrypt.sh index f2f297b..38c4e95 100755 --- a/letsencrypt.sh +++ b/letsencrypt.sh @@ -21,6 +21,7 @@ load_config() { # Default values CA="https://acme-v01.api.letsencrypt.org/directory" LICENSE="https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf" + CHALLENGETYPE="http-01" HOOK= RENEW_DAYS="30" PRIVATE_KEY="${BASEDIR}/private_key.pem" @@ -64,6 +65,20 @@ load_config() { if [[ -n "${PARAM_HOOK:-}" ]]; then HOOK="${PARAM_HOOK}" fi + + if [[ -n "${PARAM_CHALLENGETYPE:-}" ]]; then + CHALLENGETYPE="${PARAM_CHALLENGETYPE}" + fi + + case "${CHALLENGETYPE}" in + http-01|dns-01) ;; # We suppport these types + *) echo "Unknown challenge type ${CHALLENGETYPE} ... can not continue"; exit 1;; + esac + + if [[ "${CHALLENGETYPE}" = "dns-01" ]] && [[ -z "${HOOK}" ]]; then + echo "Challenge type dns-01 needs a hook script for deployment ... can not continue" + exit 1 + fi } # Initialize system @@ -269,7 +284,7 @@ sign_domain() { challenges="$(printf '%s\n' "${response}" | grep -Eo '"challenges":[^\[]*\[[^]]*]')" repl=$'\n''{' # fix syntax highlighting in Vim - challenge="$(printf "%s" "${challenges//\{/${repl}}" | grep 'http-01')" + challenge="$(printf "%s" "${challenges//\{/${repl}}" | grep \""${CHALLENGETYPE}"\")" challenge_token="$(printf '%s' "${challenge}" | get_json_string_value token | sed 's/[^A-Za-z0-9_\-]/_/g')" challenge_uri="$(printf '%s' "${challenge}" | get_json_string_value uri)" @@ -280,12 +295,19 @@ sign_domain() { # Challenge response consists of the challenge token and the thumbprint of our public certificate keyauth="${challenge_token}.${thumbprint}" - # Store challenge response in well-known location and make world-readable (so that a webserver can access it) - printf '%s' "${keyauth}" > "${WELLKNOWN}/${challenge_token}" - chmod a+r "${WELLKNOWN}/${challenge_token}" + if [[ "${CHALLENGETYPE}" = "http-01" ]]; then + # Store challenge response in well-known location and make world-readable (so that a webserver can access it) + printf '%s' "${keyauth}" > "${WELLKNOWN}/${challenge_token}" + chmod a+r "${WELLKNOWN}/${challenge_token}" + fi + + keyauth_hook="${keyauth}" + if [[ "${CHALLENGETYPE}" = "dns-01" ]]; then + keyauth_hook="$(printf '%s' "${keyauth}" | openssl sha -sha256 -binary | urlbase64)" + fi # Wait for hook script to deploy the challenge if used - [[ -n "${HOOK}" ]] && ${HOOK} "deploy_challenge" "${altname}" "${challenge_token}" "${keyauth}" + [[ -n "${HOOK}" ]] && ${HOOK} "deploy_challenge" "${altname}" "${challenge_token}" "${keyauth_hook}" # Ask the acme-server to verify our challenge and wait until it is no longer pending echo " + Responding to challenge for ${altname}..." @@ -298,11 +320,13 @@ sign_domain() { status="$(http_request get "${challenge_uri}" | get_json_string_value status)" done - rm -f "${WELLKNOWN}/${challenge_token}" + if [[ "${CHALLENGETYPE}" = "http-01" ]]; then + rm -f "${WELLKNOWN}/${challenge_token}" + fi # Wait for hook script to clean the challenge if used if [[ -n "${HOOK}" ]] && [[ -n "${challenge_token}" ]]; then - ${HOOK} "clean_challenge" "${altname}" "${challenge_token}" "${keyauth}" + ${HOOK} "clean_challenge" "${altname}" "${challenge_token}" "${keyauth_hook}" fi if [[ "${status}" = "valid" ]]; then @@ -478,7 +502,7 @@ command_help() { command_env() { echo "# letsencrypt.sh configuration" load_config - typeset -p CA LICENSE HOOK RENEW_DAYS PRIVATE_KEY KEYSIZE WELLKNOWN PRIVATE_KEY_RENEW OPENSSL_CNF CONTACT_EMAIL LOCKFILE + typeset -p CA LICENSE CHALLENGETYPE HOOK RENEW_DAYS PRIVATE_KEY KEYSIZE WELLKNOWN PRIVATE_KEY_RENEW OPENSSL_CNF CONTACT_EMAIL LOCKFILE } # Main method (parses script arguments and calls command_* methods) @@ -565,6 +589,14 @@ main() { PARAM_HOOK="${1}" ;; + # PARAM_Usage: --challenge (-t) http-01|dns-01 + # PARAM_Description: Which challenge should be used? Currently http-01 and dns-01 are supported + --challenge|-t) + shift 1 + check_parameters "${1:-}" + PARAM_CHALLENGETYPE="${1}" + ;; + *) echo "Unknown parameter detected: ${1}" >&2 echo >&2 -- 2.47.2