mirror of
https://github.com/dehydrated-io/dehydrated.git
synced 2026-05-17 12:26:55 +02:00
EAB + ZeroSSL support
This commit is contained in:
+85
-6
@@ -318,7 +318,7 @@ load_config() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Preset
|
# Preset
|
||||||
CA_ZEROSSL=""
|
CA_ZEROSSL="https://acme.zerossl.com/v2/DV90"
|
||||||
CA_LETSENCRYPT="https://acme-v02.api.letsencrypt.org/directory"
|
CA_LETSENCRYPT="https://acme-v02.api.letsencrypt.org/directory"
|
||||||
|
|
||||||
# Default values
|
# Default values
|
||||||
@@ -424,6 +424,11 @@ load_config() {
|
|||||||
# Check BASEDIR and set default variables
|
# Check BASEDIR and set default variables
|
||||||
[[ -d "${BASEDIR}" ]] || _exiterr "BASEDIR does not exist: ${BASEDIR}"
|
[[ -d "${BASEDIR}" ]] || _exiterr "BASEDIR does not exist: ${BASEDIR}"
|
||||||
|
|
||||||
|
# Check for ca cli parameter
|
||||||
|
if [ -n "${PARAM_CA:-}" ]; then
|
||||||
|
CA="${PARAM_CA}"
|
||||||
|
fi
|
||||||
|
|
||||||
# Preset CAs
|
# Preset CAs
|
||||||
if [ "${CA}" = "letsencrypt" ]; then
|
if [ "${CA}" = "letsencrypt" ]; then
|
||||||
CA="{$CA_LETSENCRYPT}"
|
CA="{$CA_LETSENCRYPT}"
|
||||||
@@ -527,7 +532,8 @@ init_system() {
|
|||||||
CA_NEW_ORDER="$(printf "%s" "${CA_DIRECTORY}" | get_json_string_value newOrder)" &&
|
CA_NEW_ORDER="$(printf "%s" "${CA_DIRECTORY}" | get_json_string_value newOrder)" &&
|
||||||
CA_NEW_NONCE="$(printf "%s" "${CA_DIRECTORY}" | get_json_string_value newNonce)" &&
|
CA_NEW_NONCE="$(printf "%s" "${CA_DIRECTORY}" | get_json_string_value newNonce)" &&
|
||||||
CA_NEW_ACCOUNT="$(printf "%s" "${CA_DIRECTORY}" | get_json_string_value newAccount)" &&
|
CA_NEW_ACCOUNT="$(printf "%s" "${CA_DIRECTORY}" | get_json_string_value newAccount)" &&
|
||||||
CA_TERMS="$(printf "%s" "${CA_DIRECTORY}" | get_json_string_value termsOfService)" &&
|
CA_TERMS="$(printf "%s" "${CA_DIRECTORY}" | get_json_string_value -p '"meta","termsOfService"')" &&
|
||||||
|
CA_REQUIRES_EAB="$(printf "%s" "${CA_DIRECTORY}" | get_json_bool_value -p '"meta","externalAccountRequired"' || echo false)" &&
|
||||||
CA_REVOKE_CERT="$(printf "%s" "${CA_DIRECTORY}" | get_json_string_value revokeCert)" ||
|
CA_REVOKE_CERT="$(printf "%s" "${CA_DIRECTORY}" | get_json_string_value revokeCert)" ||
|
||||||
_exiterr "Problem retrieving ACME/CA-URLs, check if your configured CA points to the directory entrypoint."
|
_exiterr "Problem retrieving ACME/CA-URLs, check if your configured CA points to the directory entrypoint."
|
||||||
# Since acct URI is missing from directory we will assume it is the same as CA_NEW_ACCOUNT without the new part
|
# Since acct URI is missing from directory we will assume it is the same as CA_NEW_ACCOUNT without the new part
|
||||||
@@ -539,6 +545,7 @@ init_system() {
|
|||||||
|
|
||||||
# Checking for private key ...
|
# Checking for private key ...
|
||||||
register_new_key="no"
|
register_new_key="no"
|
||||||
|
generated="false"
|
||||||
if [[ -n "${PARAM_ACCOUNT_KEY:-}" ]]; then
|
if [[ -n "${PARAM_ACCOUNT_KEY:-}" ]]; then
|
||||||
# a private key was specified from the command line so use it for this run
|
# a private key was specified from the command line so use it for this run
|
||||||
echo "Using private key ${PARAM_ACCOUNT_KEY} instead of account key"
|
echo "Using private key ${PARAM_ACCOUNT_KEY} instead of account key"
|
||||||
@@ -557,6 +564,7 @@ init_system() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
echo "+ Generating account key..."
|
echo "+ Generating account key..."
|
||||||
|
generated="true"
|
||||||
local tmp_account_key="$(_mktemp)"
|
local tmp_account_key="$(_mktemp)"
|
||||||
_openssl genrsa -out "${tmp_account_key}" "${KEYSIZE}"
|
_openssl genrsa -out "${tmp_account_key}" "${KEYSIZE}"
|
||||||
cat "${tmp_account_key}" > "${ACCOUNT_KEY}"
|
cat "${tmp_account_key}" > "${ACCOUNT_KEY}"
|
||||||
@@ -582,6 +590,35 @@ init_system() {
|
|||||||
FAILED=true
|
FAILED=true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# ZeroSSL special sauce
|
||||||
|
if [[ "${CA}" = "${CA_ZEROSSL}" ]]; then
|
||||||
|
if [[ -z "${EAB_KID:-}" ]] || [[ -z "${EAB_HMAC_KEY:-}" ]]; then
|
||||||
|
if [[ -z "${CONTACT_EMAIL}" ]]; then
|
||||||
|
echo "ZeroSSL requires contact email to be set or EAB_KID/EAB_HMAC_KEY to be manually configured"
|
||||||
|
FAILED=true
|
||||||
|
else
|
||||||
|
zeroapi="$(curl -s "https://api.zerossl.com/acme/eab-credentials-email" -d "email=${CONTACT_EMAIL}" | jsonsh)"
|
||||||
|
EAB_KID="$(printf "%s" "${zeroapi}" | get_json_string_value eab_kid)"
|
||||||
|
EAB_HMAC_KEY="$(printf "%s" "${zeroapi}" | get_json_string_value eab_hmac_key)"
|
||||||
|
if [[ -z "${EAB_KID:-}" ]] || [[ -z "${EAB_HMAC_KEY:-}" ]]; then
|
||||||
|
echo "Unknown error retrieving ZeroSSL API credentials"
|
||||||
|
echo "${zeroapi}"
|
||||||
|
FAILED=true
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if external account is required
|
||||||
|
if [[ "${FAILED}" = "false" ]]; then
|
||||||
|
if [[ "${CA_REQUIRES_EAB}" = "true" ]]; then
|
||||||
|
if [[ -z "${EAB_KID:-}" ]] || [[ -z "${EAB_HMAC_KEY:-}" ]]; then
|
||||||
|
FAILED=true
|
||||||
|
echo "This CA requires an external account but no EAB_KID/EAB_HMAC_KEY has been configured"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# If an email for the contact has been provided then adding it to the registration request
|
# If an email for the contact has been provided then adding it to the registration request
|
||||||
if [[ "${FAILED}" = "false" ]]; then
|
if [[ "${FAILED}" = "false" ]]; then
|
||||||
if [[ ${API} -eq 1 ]]; then
|
if [[ ${API} -eq 1 ]]; then
|
||||||
@@ -591,11 +628,26 @@ init_system() {
|
|||||||
(signed_request "${CA_NEW_REG}" '{"resource": "new-reg", "agreement": "'"${CA_TERMS}"'"}' > "${ACCOUNT_KEY_JSON}") || FAILED=true
|
(signed_request "${CA_NEW_REG}" '{"resource": "new-reg", "agreement": "'"${CA_TERMS}"'"}' > "${ACCOUNT_KEY_JSON}") || FAILED=true
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
if [[ -n "${CONTACT_EMAIL}" ]]; then
|
if [[ -n "${EAB_KID:-}" ]] && [[ -n "${EAB_HMAC_KEY:-}" ]]; then
|
||||||
(signed_request "${CA_NEW_ACCOUNT}" '{"contact":["mailto:'"${CONTACT_EMAIL}"'"], "termsOfServiceAgreed": true}' > "${ACCOUNT_KEY_JSON}") || FAILED=true
|
eab_url="${CA_NEW_ACCOUNT}"
|
||||||
|
eab_protected64="$(printf '{"alg":"HS256","kid":"%s","url":"%s"}' "${EAB_KID}" "${eab_url}" | urlbase64)"
|
||||||
|
eab_payload64="$(printf "%s" '{"e": "'"${pubExponent64}"'", "kty": "RSA", "n": "'"${pubMod64}"'"}' | urlbase64)"
|
||||||
|
eab_key="$(printf "%s" "${EAB_HMAC_KEY}" | deurlbase64)"
|
||||||
|
eab_signed64="$(printf '%s' "${eab_protected64}.${eab_payload64}" | "${OPENSSL}" dgst -binary -sha256 -hmac "${eab_key}" | urlbase64)"
|
||||||
|
|
||||||
|
if [[ -n "${CONTACT_EMAIL}" ]]; then
|
||||||
|
regjson='{"contact":["mailto:'"${CONTACT_EMAIL}"'"], "termsOfServiceAgreed": true, "externalAccountBinding": {"protected": "'"${eab_protected64}"'", "payload": "'"${eab_payload64}"'", "signature": "'"${eab_signed64}"'"}}'
|
||||||
|
else
|
||||||
|
regjson='{"termsOfServiceAgreed": true, "externalAccountBinding": {"protected": "'"${eab_protected64}"'", "payload": "'"${eab_payload64}"'", "signature": "'"${eab_signed64}"'"}}'
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
(signed_request "${CA_NEW_ACCOUNT}" '{"termsOfServiceAgreed": true}' > "${ACCOUNT_KEY_JSON}") || FAILED=true
|
if [[ -n "${CONTACT_EMAIL}" ]]; then
|
||||||
|
regjson='{"contact":["mailto:'"${CONTACT_EMAIL}"'"], "termsOfServiceAgreed": true}'
|
||||||
|
else
|
||||||
|
regjson='{"termsOfServiceAgreed": true}'
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
(signed_request "${CA_NEW_ACCOUNT}" "${regjson}" > "${ACCOUNT_KEY_JSON}") || FAILED=true
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -603,7 +655,10 @@ init_system() {
|
|||||||
echo >&2
|
echo >&2
|
||||||
echo >&2
|
echo >&2
|
||||||
echo "Error registering account key. See message above for more information." >&2
|
echo "Error registering account key. See message above for more information." >&2
|
||||||
rm "${ACCOUNT_KEY}" "${ACCOUNT_KEY_JSON}"
|
if [[ "${generated}" = "true" ]]; then
|
||||||
|
rm "${ACCOUNT_KEY}"
|
||||||
|
fi
|
||||||
|
rm -f "${ACCOUNT_KEY_JSON}"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
elif [[ "${COMMAND:-}" = "register" ]]; then
|
elif [[ "${COMMAND:-}" = "register" ]]; then
|
||||||
@@ -669,12 +724,27 @@ urlbase64() {
|
|||||||
"${OPENSSL}" base64 -e | tr -d '\n\r' | _sed -e 's:=*$::g' -e 'y:+/:-_:'
|
"${OPENSSL}" base64 -e | tr -d '\n\r' | _sed -e 's:=*$::g' -e 'y:+/:-_:'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Decode data from url-safe formatted base64
|
||||||
|
deurlbase64() {
|
||||||
|
data="$(cat | tr -d ' \n\r')"
|
||||||
|
modlen=$((${#data} % 4))
|
||||||
|
padding=""
|
||||||
|
if [[ "${modlen}" = "2" ]]; then padding="==";
|
||||||
|
elif [[ "${modlen}" = "3" ]]; then padding="="; fi
|
||||||
|
printf "%s%s" "${data}" "${padding}" | tr -d '\n\r' | _sed -e 'y:-_:+/:' | "${OPENSSL}" base64 -d -A
|
||||||
|
}
|
||||||
|
|
||||||
# Convert hex string to binary data
|
# Convert hex string to binary data
|
||||||
hex2bin() {
|
hex2bin() {
|
||||||
# Remove spaces, add leading zero, escape as hex string and parse with printf
|
# Remove spaces, add leading zero, escape as hex string and parse with printf
|
||||||
printf -- "$(cat | _sed -e 's/[[:space:]]//g' -e 's/^(.(.{2})*)$/0\1/' -e 's/(.{2})/\\x\1/g')"
|
printf -- "$(cat | _sed -e 's/[[:space:]]//g' -e 's/^(.(.{2})*)$/0\1/' -e 's/(.{2})/\\x\1/g')"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Convert binary data to hex string
|
||||||
|
bin2hex() {
|
||||||
|
hexdump | _sed 's/^[^ ]*//' | tr -d ' \n\r'
|
||||||
|
}
|
||||||
|
|
||||||
# OpenSSL writes to stderr/stdout even when there are no errors. So just
|
# OpenSSL writes to stderr/stdout even when there are no errors. So just
|
||||||
# display the output if the exit code was != 0 to simplify debugging.
|
# display the output if the exit code was != 0 to simplify debugging.
|
||||||
_openssl() {
|
_openssl() {
|
||||||
@@ -1873,6 +1943,15 @@ main() {
|
|||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
# PARAM_Usage: --ca url/preset
|
||||||
|
# PARAM_Description: Use specified CA URL or preset
|
||||||
|
--ca)
|
||||||
|
shift 1
|
||||||
|
check_parameters "${1:-}"
|
||||||
|
[[ -n "${PARAM_CA:-}" ]] && _exiterr "CA can only be specified once!"
|
||||||
|
PARAM_CA="${1}"
|
||||||
|
;;
|
||||||
|
|
||||||
# PARAM_Usage: --alias certalias
|
# PARAM_Usage: --alias certalias
|
||||||
# PARAM_Description: Use specified name for certificate directory (and per-certificate config) instead of the primary domain (only used if --domain is specified)
|
# PARAM_Description: Use specified name for certificate directory (and per-certificate config) instead of the primary domain (only used if --domain is specified)
|
||||||
--alias)
|
--alias)
|
||||||
|
|||||||
Reference in New Issue
Block a user