mirror of
https://github.com/dehydrated-io/dehydrated.git
synced 2026-05-13 02:19:48 +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
|
||||||
- Added a configuration parameter to allow for timeouts during domain validation processing (`VALIDATION_TIMEOUT`, defaults to 0 = no timeout)
|
- 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 documentation for IP certificates
|
||||||
|
- Added support for DNS-PERSIST-01 challenge type
|
||||||
|
|
||||||
## Changed
|
## Changed
|
||||||
- Only validate existance of wellknown directory or hook script when actually needed
|
- 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
|
--preferred-chain issuer-cn Use alternative certificate chain identified by issuer CN
|
||||||
--out (-o) certs/directory Output certificates into the specified directory
|
--out (-o) certs/directory Output certificates into the specified directory
|
||||||
--alpn alpn-certs/directory Output alpn verification 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
|
--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
|
--acme-profile profile_name Use specified ACME profile
|
||||||
--order-timeout seconds Amount of seconds to wait for processing of order until erroring out
|
--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 configuration values
|
||||||
verify_config() {
|
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 [[ "${COMMAND:-}" =~ sign_domains|sign_csr ]]; then
|
||||||
if [[ "${CHALLENGETYPE}" = "dns-01" ]] && [[ -z "${HOOK}" ]]; then
|
if [[ "${CHALLENGETYPE}" = "dns-01" ]] && [[ -z "${HOOK}" ]]; then
|
||||||
_exiterr "Challenge type dns-01 needs a hook script for deployment... cannot continue."
|
_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
|
# Generate DNS entry content for dns-01 validation
|
||||||
keyauth_hook="$(printf '%s' "${keyauth}" | "${OPENSSL}" dgst -sha256 -binary | urlbase64)"
|
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")
|
"tls-alpn-01")
|
||||||
keyauth_hook="$(printf '%s' "${keyauth}" | "${OPENSSL}" dgst -sha256 -c -hex | awk '{print $NF}')"
|
keyauth_hook="$(printf '%s' "${keyauth}" | "${OPENSSL}" dgst -sha256 -c -hex | awk '{print $NF}')"
|
||||||
generate_alpn_certificate "${identifier}" "${identifier_type}" "${keyauth_hook}"
|
generate_alpn_certificate "${identifier}" "${identifier_type}" "${keyauth_hook}"
|
||||||
@@ -1303,18 +1307,20 @@ sign_csr() {
|
|||||||
|
|
||||||
# Deploy challenge tokens
|
# Deploy challenge tokens
|
||||||
if [[ ${num_pending_challenges} -ne 0 ]]; then
|
if [[ ${num_pending_challenges} -ne 0 ]]; then
|
||||||
echo " + Deploying challenge tokens..."
|
if [[ "${CHALLENGETYPE}" != "dns-persist-01" ]]; then
|
||||||
if [[ -n "${HOOK}" ]] && [[ "${HOOK_CHAIN}" = "yes" ]]; then
|
echo " + Deploying challenge tokens..."
|
||||||
# shellcheck disable=SC2068
|
if [[ -n "${HOOK}" ]] && [[ "${HOOK_CHAIN}" = "yes" ]]; then
|
||||||
"${HOOK}" "deploy_challenge" ${deploy_args[@]} || _exiterr 'deploy_challenge hook returned with non-zero exit code'
|
# shellcheck disable=SC2068
|
||||||
elif [[ -n "${HOOK}" ]]; then
|
"${HOOK}" "deploy_challenge" ${deploy_args[@]} || _exiterr 'deploy_challenge hook returned with non-zero exit code'
|
||||||
# Run hook script to deploy the challenge token
|
elif [[ -n "${HOOK}" ]]; then
|
||||||
local idx=0
|
# Run hook script to deploy the challenge token
|
||||||
while [ ${idx} -lt ${num_pending_challenges} ]; do
|
local idx=0
|
||||||
# shellcheck disable=SC2086
|
while [ ${idx} -lt ${num_pending_challenges} ]; do
|
||||||
"${HOOK}" "deploy_challenge" ${deploy_args[${idx}]} || _exiterr 'deploy_challenge hook returned with non-zero exit code'
|
# shellcheck disable=SC2086
|
||||||
idx=$((idx+1))
|
"${HOOK}" "deploy_challenge" ${deploy_args[${idx}]} || _exiterr 'deploy_challenge hook returned with non-zero exit code'
|
||||||
done
|
idx=$((idx+1))
|
||||||
|
done
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -1361,24 +1367,26 @@ sign_csr() {
|
|||||||
done
|
done
|
||||||
|
|
||||||
if [[ ${num_pending_challenges} -ne 0 ]]; then
|
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
|
# Clean challenge tokens using chained hook
|
||||||
# shellcheck disable=SC2068
|
# shellcheck disable=SC2068
|
||||||
[[ -n "${HOOK}" ]] && [[ "${HOOK_CHAIN}" = "yes" ]] && ("${HOOK}" "clean_challenge" ${deploy_args[@]} || _exiterr 'clean_challenge hook returned with non-zero exit code')
|
[[ -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
|
# Clean remaining challenge tokens if validation has failed
|
||||||
local idx=0
|
local idx=0
|
||||||
while [ ${idx} -lt ${num_pending_challenges} ]; do
|
while [ ${idx} -lt ${num_pending_challenges} ]; do
|
||||||
# Delete challenge file
|
# Delete challenge file
|
||||||
[[ "${CHALLENGETYPE}" = "http-01" ]] && rm -f "${WELLKNOWN}/${challenge_tokens[${idx}]}"
|
[[ "${CHALLENGETYPE}" = "http-01" ]] && rm -f "${WELLKNOWN}/${challenge_tokens[${idx}]}"
|
||||||
# Delete alpn verification certificates
|
# Delete alpn verification certificates
|
||||||
[[ "${CHALLENGETYPE}" = "tls-alpn-01" ]] && rm -f "${ALPNCERTDIR}/${challenge_names[${idx}]}.crt.pem" "${ALPNCERTDIR}/${challenge_names[${idx}]}.key.pem"
|
[[ "${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
|
# Clean challenge token using non-chained hook
|
||||||
# shellcheck disable=SC2086
|
# shellcheck disable=SC2086
|
||||||
[[ -n "${HOOK}" ]] && [[ "${HOOK_CHAIN}" != "yes" ]] && ("${HOOK}" "clean_challenge" ${deploy_args[${idx}]} || _exiterr 'clean_challenge hook returned with non-zero exit code')
|
[[ -n "${HOOK}" ]] && [[ "${HOOK_CHAIN}" != "yes" ]] && ("${HOOK}" "clean_challenge" ${deploy_args[${idx}]} || _exiterr 'clean_challenge hook returned with non-zero exit code')
|
||||||
idx=$((idx+1))
|
idx=$((idx+1))
|
||||||
done
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ "${reqstatus}" != "valid" ]]; then
|
if [[ "${reqstatus}" != "valid" ]]; then
|
||||||
echo " + Challenge validation has failed :("
|
echo " + Challenge validation has failed :("
|
||||||
@@ -2506,8 +2514,8 @@ main() {
|
|||||||
PARAM_ALPNCERTDIR="${1}"
|
PARAM_ALPNCERTDIR="${1}"
|
||||||
;;
|
;;
|
||||||
|
|
||||||
# PARAM_Usage: --challenge (-t) http-01|dns-01|tls-alpn-01
|
# 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, and tls-alpn-01 are supported
|
# PARAM_Description: Which challenge should be used? Currently http-01, dns-01, dns-persist-01 and tls-alpn-01 are supported
|
||||||
--challenge|-t)
|
--challenge|-t)
|
||||||
shift 1
|
shift 1
|
||||||
check_parameters "${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.
|
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)
|
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.
|
Alternative Name\fR (SAN) field.
|
||||||
|
|
||||||
For the next step, one way of verifying domain name ownership needs to be
|
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
|
The \fIhttp-01\fR verification provides proof of ownership by providing a
|
||||||
challenge token. In order to do that, the directory referenced in the
|
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
|
available for dehydrated. See \fIdns-verification.md\fR for hooks for popular
|
||||||
DNS servers and DNS hosters.
|
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.
|
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
|
This can happen through a cron job or a timer. Initially, you may enforce this
|
||||||
by invoking \fIdehydrated -c\fR manually.
|
by invoking \fIdehydrated -c\fR manually.
|
||||||
|
|||||||
Reference in New Issue
Block a user