mirror of
https://github.com/dehydrated-io/dehydrated.git
synced 2026-05-08 08:03:30 +02:00
Add DNS-PERSIST-01 challenge support
- Add dns-persist-01 to allowed challenge types in verify_config() - Implement dns-persist-01 case in challenge preparation (no dynamic token) - Skip deployment and cleanup for dns-persist-01 - Update help text and documentation - Add man page and README updates - Update CHANGELOG
This commit is contained in:
committed by
Lukas Schauer
parent
c63d1cb528
commit
cfd637d769
@@ -9,6 +9,7 @@ This file contains a log of major changes in dehydrated
|
||||
## Added
|
||||
- Added a configuration parameter to allow for timeouts during domain validation processing (`VALIDATION_TIMEOUT`, defaults to 0 = no timeout)
|
||||
- Added documentation for IP certificates
|
||||
- Added support for DNS-PERSIST-01 challenge type
|
||||
|
||||
## Changed
|
||||
- Only validate existance of wellknown directory or hook script when actually needed
|
||||
|
||||
@@ -86,7 +86,7 @@ Parameters:
|
||||
--preferred-chain issuer-cn Use alternative certificate chain identified by issuer CN
|
||||
--out (-o) certs/directory Output certificates into the specified directory
|
||||
--alpn alpn-certs/directory Output alpn verification certificates into the specified directory
|
||||
--challenge (-t) http-01|dns-01|tls-alpn-01 Which challenge should be used? Currently http-01, dns-01, and tls-alpn-01 are supported
|
||||
--challenge (-t) http-01|dns-01|dns-persist-01|tls-alpn-01 Which challenge should be used? Currently http-01, dns-01, dns-persist-01 and tls-alpn-01 are supported
|
||||
--algo (-a) rsa|prime256v1|secp384r1 Which public key algorithm should be used? Supported: rsa, prime256v1 and secp384r1
|
||||
--acme-profile profile_name Use specified ACME profile
|
||||
--order-timeout seconds Amount of seconds to wait for processing of order until erroring out
|
||||
|
||||
70
dehydrated
70
dehydrated
@@ -366,7 +366,7 @@ hookscript_bricker_hook() {
|
||||
|
||||
# verify configuration values
|
||||
verify_config() {
|
||||
[[ "${CHALLENGETYPE}" == "http-01" || "${CHALLENGETYPE}" == "dns-01" || "${CHALLENGETYPE}" == "tls-alpn-01" ]] || _exiterr "Unknown challenge type ${CHALLENGETYPE}... cannot continue."
|
||||
[[ "${CHALLENGETYPE}" == "http-01" || "${CHALLENGETYPE}" == "dns-01" || "${CHALLENGETYPE}" == "dns-persist-01" || "${CHALLENGETYPE}" == "tls-alpn-01" ]] || _exiterr "Unknown challenge type ${CHALLENGETYPE}... cannot continue."
|
||||
if [[ "${COMMAND:-}" =~ sign_domains|sign_csr ]]; then
|
||||
if [[ "${CHALLENGETYPE}" = "dns-01" ]] && [[ -z "${HOOK}" ]]; then
|
||||
_exiterr "Challenge type dns-01 needs a hook script for deployment... cannot continue."
|
||||
@@ -1283,6 +1283,10 @@ sign_csr() {
|
||||
# Generate DNS entry content for dns-01 validation
|
||||
keyauth_hook="$(printf '%s' "${keyauth}" | "${OPENSSL}" dgst -sha256 -binary | urlbase64)"
|
||||
;;
|
||||
"dns-persist-01")
|
||||
# Pre-existing persistent DNS record is expected; no deploy/cleanup by dehydrated.
|
||||
keyauth_hook=""
|
||||
;;
|
||||
"tls-alpn-01")
|
||||
keyauth_hook="$(printf '%s' "${keyauth}" | "${OPENSSL}" dgst -sha256 -c -hex | awk '{print $NF}')"
|
||||
generate_alpn_certificate "${identifier}" "${identifier_type}" "${keyauth_hook}"
|
||||
@@ -1303,18 +1307,20 @@ sign_csr() {
|
||||
|
||||
# Deploy challenge tokens
|
||||
if [[ ${num_pending_challenges} -ne 0 ]]; then
|
||||
echo " + Deploying challenge tokens..."
|
||||
if [[ -n "${HOOK}" ]] && [[ "${HOOK_CHAIN}" = "yes" ]]; then
|
||||
# shellcheck disable=SC2068
|
||||
"${HOOK}" "deploy_challenge" ${deploy_args[@]} || _exiterr 'deploy_challenge hook returned with non-zero exit code'
|
||||
elif [[ -n "${HOOK}" ]]; then
|
||||
# Run hook script to deploy the challenge token
|
||||
local idx=0
|
||||
while [ ${idx} -lt ${num_pending_challenges} ]; do
|
||||
# shellcheck disable=SC2086
|
||||
"${HOOK}" "deploy_challenge" ${deploy_args[${idx}]} || _exiterr 'deploy_challenge hook returned with non-zero exit code'
|
||||
idx=$((idx+1))
|
||||
done
|
||||
if [[ "${CHALLENGETYPE}" != "dns-persist-01" ]]; then
|
||||
echo " + Deploying challenge tokens..."
|
||||
if [[ -n "${HOOK}" ]] && [[ "${HOOK_CHAIN}" = "yes" ]]; then
|
||||
# shellcheck disable=SC2068
|
||||
"${HOOK}" "deploy_challenge" ${deploy_args[@]} || _exiterr 'deploy_challenge hook returned with non-zero exit code'
|
||||
elif [[ -n "${HOOK}" ]]; then
|
||||
# Run hook script to deploy the challenge token
|
||||
local idx=0
|
||||
while [ ${idx} -lt ${num_pending_challenges} ]; do
|
||||
# shellcheck disable=SC2086
|
||||
"${HOOK}" "deploy_challenge" ${deploy_args[${idx}]} || _exiterr 'deploy_challenge hook returned with non-zero exit code'
|
||||
idx=$((idx+1))
|
||||
done
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -1361,24 +1367,26 @@ sign_csr() {
|
||||
done
|
||||
|
||||
if [[ ${num_pending_challenges} -ne 0 ]]; then
|
||||
echo " + Cleaning challenge tokens..."
|
||||
if [[ "${CHALLENGETYPE}" != "dns-persist-01" ]]; then
|
||||
echo " + Cleaning challenge tokens..."
|
||||
|
||||
# Clean challenge tokens using chained hook
|
||||
# shellcheck disable=SC2068
|
||||
[[ -n "${HOOK}" ]] && [[ "${HOOK_CHAIN}" = "yes" ]] && ("${HOOK}" "clean_challenge" ${deploy_args[@]} || _exiterr 'clean_challenge hook returned with non-zero exit code')
|
||||
# Clean challenge tokens using chained hook
|
||||
# shellcheck disable=SC2068
|
||||
[[ -n "${HOOK}" ]] && [[ "${HOOK_CHAIN}" = "yes" ]] && ("${HOOK}" "clean_challenge" ${deploy_args[@]} || _exiterr 'clean_challenge hook returned with non-zero exit code')
|
||||
|
||||
# Clean remaining challenge tokens if validation has failed
|
||||
local idx=0
|
||||
while [ ${idx} -lt ${num_pending_challenges} ]; do
|
||||
# Delete challenge file
|
||||
[[ "${CHALLENGETYPE}" = "http-01" ]] && rm -f "${WELLKNOWN}/${challenge_tokens[${idx}]}"
|
||||
# Delete alpn verification certificates
|
||||
[[ "${CHALLENGETYPE}" = "tls-alpn-01" ]] && rm -f "${ALPNCERTDIR}/${challenge_names[${idx}]}.crt.pem" "${ALPNCERTDIR}/${challenge_names[${idx}]}.key.pem"
|
||||
# Clean challenge token using non-chained hook
|
||||
# shellcheck disable=SC2086
|
||||
[[ -n "${HOOK}" ]] && [[ "${HOOK_CHAIN}" != "yes" ]] && ("${HOOK}" "clean_challenge" ${deploy_args[${idx}]} || _exiterr 'clean_challenge hook returned with non-zero exit code')
|
||||
idx=$((idx+1))
|
||||
done
|
||||
# Clean remaining challenge tokens if validation has failed
|
||||
local idx=0
|
||||
while [ ${idx} -lt ${num_pending_challenges} ]; do
|
||||
# Delete challenge file
|
||||
[[ "${CHALLENGETYPE}" = "http-01" ]] && rm -f "${WELLKNOWN}/${challenge_tokens[${idx}]}"
|
||||
# Delete alpn verification certificates
|
||||
[[ "${CHALLENGETYPE}" = "tls-alpn-01" ]] && rm -f "${ALPNCERTDIR}/${challenge_names[${idx}]}.crt.pem" "${ALPNCERTDIR}/${challenge_names[${idx}]}.key.pem"
|
||||
# Clean challenge token using non-chained hook
|
||||
# shellcheck disable=SC2086
|
||||
[[ -n "${HOOK}" ]] && [[ "${HOOK_CHAIN}" != "yes" ]] && ("${HOOK}" "clean_challenge" ${deploy_args[${idx}]} || _exiterr 'clean_challenge hook returned with non-zero exit code')
|
||||
idx=$((idx+1))
|
||||
done
|
||||
fi
|
||||
|
||||
if [[ "${reqstatus}" != "valid" ]]; then
|
||||
echo " + Challenge validation has failed :("
|
||||
@@ -2506,8 +2514,8 @@ main() {
|
||||
PARAM_ALPNCERTDIR="${1}"
|
||||
;;
|
||||
|
||||
# PARAM_Usage: --challenge (-t) http-01|dns-01|tls-alpn-01
|
||||
# PARAM_Description: Which challenge should be used? Currently http-01, dns-01, and tls-alpn-01 are supported
|
||||
# PARAM_Usage: --challenge (-t) http-01|dns-01|dns-persist-01|tls-alpn-01
|
||||
# PARAM_Description: Which challenge should be used? Currently http-01, dns-01, dns-persist-01 and tls-alpn-01 are supported
|
||||
--challenge|-t)
|
||||
shift 1
|
||||
check_parameters "${1:-}"
|
||||
|
||||
@@ -29,3 +29,24 @@ Or when you do have a DNS API, pass the details accordingly to achieve the same
|
||||
You can delete the TXT record when called with operation `clean_challenge`, when $2 is also the domain name.
|
||||
|
||||
Here are some examples: [Examples for DNS-01 hooks](https://github.com/dehydrated-io/dehydrated/wiki)
|
||||
|
||||
### dns-persist-01 challenge
|
||||
|
||||
This script also supports the `dns-persist-01`-type verification. This type of verification requires you to create a persistent `TXT` DNS record containing your Let's Encrypt account information.
|
||||
|
||||
Unlike `dns-01`, which requires dynamic DNS record updates for each certificate request, `dns-persist-01` uses a single persistent record that remains in place indefinitely.
|
||||
|
||||
You need to create a TXT record named `_validation-persist` in the domain for which you want to request certificates. The record should contain your account URI and other metadata.
|
||||
|
||||
Example record:
|
||||
```
|
||||
_validation-persist.example.com. IN TXT (
|
||||
"letsencrypt.org;"
|
||||
" accounturi=https://acme-v02.api.letsencrypt.org/acme/acct/1234567890;"
|
||||
" policy=wildcard"
|
||||
)
|
||||
```
|
||||
|
||||
The account URI can be obtained by running `dehydrated --register --accept-terms` and checking the account registration response, or by examining the `accounts/*/registration.json` file after registration.
|
||||
|
||||
This record should be set up once and left in place. No hook script is required for `dns-persist-01` as dehydrated does not perform any dynamic DNS updates for this challenge type.
|
||||
|
||||
@@ -26,7 +26,7 @@ single certificate valid for both "example.net" and "example.com" through the \f
|
||||
Alternative Name\fR (SAN) field.
|
||||
|
||||
For the next step, one way of verifying domain name ownership needs to be
|
||||
configured. Dehydrated implements \fIhttp-01\fR and \fIdns-01\fR verification.
|
||||
configured. Dehydrated implements \fIhttp-01\fR, \fIdns-01\fR, and \fIdns-persist-01\fR verification.
|
||||
|
||||
The \fIhttp-01\fR verification provides proof of ownership by providing a
|
||||
challenge token. In order to do that, the directory referenced in the
|
||||
@@ -44,6 +44,12 @@ the software or the DNS provider at hand, there are many third party hooks
|
||||
available for dehydrated. See \fIdns-verification.md\fR for hooks for popular
|
||||
DNS servers and DNS hosters.
|
||||
|
||||
The \fIdns-persist-01\fR verification works by providing a persistent DNS record
|
||||
containing account information. Unlike \fIdns-01\fR, this requires setting up a
|
||||
static TXT record once that remains in place indefinitely. No dynamic DNS
|
||||
updates are performed during certificate requests. See \fIdns-verification.md\fR
|
||||
for details on setting up the required DNS record.
|
||||
|
||||
Finally, the certificates need to be requested and updated on a regular basis.
|
||||
This can happen through a cron job or a timer. Initially, you may enforce this
|
||||
by invoking \fIdehydrated -c\fR manually.
|
||||
|
||||
Reference in New Issue
Block a user