Browse Source

Support views. Also, avoid hangs interrogating remote.

rdbath suggested how to implement a timeout on s_client probes.
Unfortunately, wait -n is a bash 4.3 feature.  So this requires
bash 4.3.  CHECK_CERT_TIMEOUT can be used to override the default, which
is 4 seconds.  Fallback is provided for older versions.

Views may require the 'nslookup' process to do somthing special, usually
provide a TSIG key or bind to a specific local address.  Add a
hook for that - export the VARIABLE DNS_CHECK_FUNC_OPTIONS with the
desired options._Set DNS_CHECK_FUNC to the desired command, which
must be one of the supported ones: 'dig', 'drill', 'host' or 'nslookup'.


However, this turned up the fact that the dig/drill code had the domain
and record type arguments in the wrong order on the command line.
(The domain comes first, see the man page.)  Fixed.

In some cases defining the previously undocumented PUBLIC_DNS_SERVER
may work.  This commit adds it to the template file, and exports it
for the benefit of DNS_UPDATE scripts.  Also AUTH_DNS_SERVER.

Squashed awk complaints about curl.header in some cases with debugging on.

Support older curl (--trace-time is somewhat recent)
pull/289/head
Timothe Litt 9 years ago
parent
commit
e5702045b0
2 changed files with 82 additions and 24 deletions
  1. +2
    -1
      dns_scripts/dns_godaddy
  2. +80
    -23
      getssl

+ 2
- 1
dns_scripts/dns_godaddy View File

@ -193,8 +193,9 @@ if [ -n "$TRACE" ]; then
} }
timestamp 'Info' "$PROG" "V$VERSION" 'Starting new protocol trace' timestamp 'Info' "$PROG" "V$VERSION" 'Starting new protocol trace'
timestamp 'Args' "$@" timestamp 'Args' "$@"
curl --help | grep -q -- --trace-time && CURL_TFLAGS="--trace-time" # 7.14.0
function curl { function curl {
command curl --trace-time --trace-ascii % "$@" 2>>"$TRACE"
command curl ${CURL_TFLAGS} --trace-ascii % "$@" 2>>"$TRACE"
} }
[ -n "$VERB" ] && echo "Appending protocol trace to $TRACE" [ -n "$VERB" ] && echo "Appending protocol trace to $TRACE"
fi fi


+ 80
- 23
getssl View File

@ -192,16 +192,20 @@ VERSION="2.10"
# defaults # defaults
ACCOUNT_KEY_LENGTH=4096 ACCOUNT_KEY_LENGTH=4096
ACCOUNT_KEY_TYPE="rsa" ACCOUNT_KEY_TYPE="rsa"
export AUTH_DNS_SERVER=""
CA="https://acme-staging.api.letsencrypt.org" CA="https://acme-staging.api.letsencrypt.org"
CA_CERT_LOCATION="" CA_CERT_LOCATION=""
CHALLENGE_CHECK_TYPE="http" CHALLENGE_CHECK_TYPE="http"
CHECK_ALL_AUTH_DNS="false" CHECK_ALL_AUTH_DNS="false"
CHECK_CERT_TIMEOUT="4"
CHECK_REMOTE="true" CHECK_REMOTE="true"
CHECK_REMOTE_WAIT=0 CHECK_REMOTE_WAIT=0
CODE_LOCATION="https://raw.githubusercontent.com/srvrco/getssl/master/getssl" CODE_LOCATION="https://raw.githubusercontent.com/srvrco/getssl/master/getssl"
CSR_SUBJECT="/" CSR_SUBJECT="/"
DEACTIVATE_AUTH="false" DEACTIVATE_AUTH="false"
DEFAULT_REVOKE_CA="https://acme-v01.api.letsencrypt.org" DEFAULT_REVOKE_CA="https://acme-v01.api.letsencrypt.org"
DNS_CHECK_FUNC=""
DNS_CHECK_OPTIONS=""
DNS_EXTRA_WAIT="" DNS_EXTRA_WAIT=""
DNS_WAIT=10 DNS_WAIT=10
DOMAIN_KEY_LENGTH=4096 DOMAIN_KEY_LENGTH=4096
@ -212,7 +216,7 @@ IGNORE_DIRECTORY_DOMAIN="false"
ORIG_UMASK=$(umask) ORIG_UMASK=$(umask)
PREVIOUSLY_VALIDATED="true" PREVIOUSLY_VALIDATED="true"
PRIVATE_KEY_ALG="rsa" PRIVATE_KEY_ALG="rsa"
PUBLIC_DNS_SERVER=""
export PUBLIC_DNS_SERVER=""
RELOAD_CMD="" RELOAD_CMD=""
RENEW_ALLOW="30" RENEW_ALLOW="30"
REUSE_PRIVATE_KEY="true" REUSE_PRIVATE_KEY="true"
@ -389,14 +393,14 @@ check_config() { # check the config files for all obvious errors
config_errors=true config_errors=true
fi fi
# check domain exist # check domain exist
if [[ "$DNS_CHECK_FUNC" == "drill" ]] || [[ "$DNS_CHECK_FUNC" == "dig" ]]; then
if [[ "$DNS_CHECK_FUNC" =~ ^drill ]] || [[ "$DNS_CHECK_FUNC" =~ ^dig ]]; then
if [[ "$($DNS_CHECK_FUNC "${d}" SOA|grep -c "^${d}")" -ge 1 ]]; then if [[ "$($DNS_CHECK_FUNC "${d}" SOA|grep -c "^${d}")" -ge 1 ]]; then
debug "found IP for ${d}" debug "found IP for ${d}"
else else
info "${DOMAIN}: DNS lookup failed for ${d}" info "${DOMAIN}: DNS lookup failed for ${d}"
config_errors=true config_errors=true
fi fi
elif [[ "$DNS_CHECK_FUNC" == "host" ]]; then
elif [[ "$DNS_CHECK_FUNC" =~ ^host ]]; then
if [[ "$($DNS_CHECK_FUNC "${d}" |grep -c "^${d}")" -ge 1 ]]; then if [[ "$($DNS_CHECK_FUNC "${d}" |grep -c "^${d}")" -ge 1 ]]; then
debug "found IP for ${d}" debug "found IP for ${d}"
else else
@ -716,20 +720,19 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n
primary_ns="$all_auth_dns_servers" primary_ns="$all_auth_dns_servers"
return return
fi fi
if [[ "$DNS_CHECK_FUNC" == "drill" ]] || [[ "$DNS_CHECK_FUNC" == "dig" ]]; then
if [[ "$DNS_CHECK_FUNC" =~ ^drill ]] || [[ "$DNS_CHECK_FUNC" =~ ^dig ]]; then
if [[ -z "$gad_s" ]]; then #checking for CNAMEs if [[ -z "$gad_s" ]]; then #checking for CNAMEs
res=$($DNS_CHECK_FUNC CNAME "$gad_d"| grep "^$gad_d")
res=$($DNS_CHECK_FUNC "$gad_d" CNAME| grep "^$gad_d")
else else
res=$($DNS_CHECK_FUNC CNAME "$gad_d" "@$gad_s"| grep "^$gad_d")
res=$($DNS_CHECK_FUNC "$gad_d" CNAME "@$gad_s"| grep "^$gad_d")
fi fi
if [[ ! -z "$res" ]]; then # domain is a CNAME so get main domain if [[ ! -z "$res" ]]; then # domain is a CNAME so get main domain
gad_d=$(echo "$res"| awk '{print $5}' |sed 's/\.$//g') gad_d=$(echo "$res"| awk '{print $5}' |sed 's/\.$//g')
fi fi
if [[ -z "$gad_s" ]]; then #checking for CNAMEs if [[ -z "$gad_s" ]]; then #checking for CNAMEs
res=$($DNS_CHECK_FUNC NS "$gad_d"| grep "^$gad_d")
res=$($DNS_CHECK_FUNC "$gad_d" NS| grep "^$gad_d")
else else
res=$($DNS_CHECK_FUNC NS "$gad_d" "@$gad_s"| grep "^$gad_d")
res=$($DNS_CHECK_FUNC "$gad_d" NS "@$gad_s"| grep "^$gad_d")
fi fi
if [[ -z "$res" ]]; then if [[ -z "$res" ]]; then
error_exit "couldn't find primary DNS server - please set AUTH_DNS_SERVER in config" error_exit "couldn't find primary DNS server - please set AUTH_DNS_SERVER in config"
@ -744,7 +747,7 @@ get_auth_dns() { # get the authoritative dns server for a domain (sets primary_n
return return
fi fi
if [[ "$DNS_CHECK_FUNC" == "host" ]]; then
if [[ "$DNS_CHECK_FUNC" =~ ^host ]]; then
if [[ -z "$gad_s" ]]; then if [[ -z "$gad_s" ]]; then
res=$($DNS_CHECK_FUNC -t NS "$gad_d"| grep "name server") res=$($DNS_CHECK_FUNC -t NS "$gad_d"| grep "name server")
else else
@ -1178,6 +1181,7 @@ send_signed_request() { # Sends a request to the ACME server, signed with your p
response=$($CURL -X POST --data "$body" "$url") response=$($CURL -X POST --data "$body" "$url")
fi fi
touch "$CURL_HEADER"
responseHeaders=$(cat "$CURL_HEADER") responseHeaders=$(cat "$CURL_HEADER")
debug responseHeaders "$responseHeaders" debug responseHeaders "$responseHeaders"
debug response "$response" debug response "$response"
@ -1325,6 +1329,21 @@ write_domain_template() { # write out a template file for a domain.
# an update to confirm correct certificate is running (if CHECK_REMOTE) is set to true # an update to confirm correct certificate is running (if CHECK_REMOTE) is set to true
#SERVER_TYPE="https" #SERVER_TYPE="https"
#CHECK_REMOTE="true" #CHECK_REMOTE="true"
# Unusual configurations (especially split views) may require these.
# If these (or any variable) apply to all your domains, put them in
# the per-domain getssl.cfg.
#
# If you must use an external DNS Server (e.g. due to split views)
# Specify it here. Otherwise, the default is to find the zone master.
# The default will usually work.
# PUBLIC_DNS_SERVER="8.8.8.8"
# If getssl is unable to determine the authoritative nameserver for a domain
# it will as you to enter AUTH_DNS_SERVER. This is the primary server that
# getssl will use to check for the acme tokens. It must be visible externally
# as well as internally. It need not be "authoritiative" in the RFC1035 sense.
# AUTH_DNS_SERVER="8.8.8.8"
_EOF_domain_ _EOF_domain_
} }
@ -1364,6 +1383,19 @@ write_getssl_template() { # write out the main template file
#VALIDATE_VIA_DNS="true" #VALIDATE_VIA_DNS="true"
#DNS_ADD_COMMAND= #DNS_ADD_COMMAND=
#DNS_DEL_COMMAND= #DNS_DEL_COMMAND=
# Unusual configurations (especially split views) may require these.
# If you have a mixture, these can go in the per-domain getssl.cfg.
#
# If you must use an external DNS Server (e.g. due to split views)
# Specify it here. Otherwise, the default is to find the zone master.
# The default will usually work.
# PUBLIC_DNS_SERVER="8.8.8.8"
# If getssl is unable to determine the authoritative nameserver for a domain
# it will as you to enter AUTH_DNS_SERVER. This is a server that
# can answer queries for the zone - a master or a slave, not a recursive server.
# AUTH_DNS_SERVER="10.0.0.14"
_EOF_getssl_ _EOF_getssl_
} }
@ -1446,7 +1478,6 @@ get_os
requires which requires which
requires openssl requires openssl
requires curl requires curl
requires nslookup drill dig host DNS_CHECK_FUNC
requires awk requires awk
requires tr requires tr
requires date requires date
@ -1497,6 +1528,12 @@ if [[ -s "$WORKING_DIR/getssl.cfg" ]]; then
. "$WORKING_DIR/getssl.cfg" . "$WORKING_DIR/getssl.cfg"
fi fi
if [[ -n "$DNS_CHECK_FUNC" ]]; then
requires "${DNS_CHECK_FUNC}"
else
requires nslookup drill dig host DNS_CHECK_FUNC
fi
# Define defaults for variables not set in the main config. # Define defaults for variables not set in the main config.
ACCOUNT_KEY="${ACCOUNT_KEY:=$WORKING_DIR/account.key}" ACCOUNT_KEY="${ACCOUNT_KEY:=$WORKING_DIR/account.key}"
DOMAIN_STORAGE="${DOMAIN_STORAGE:=$WORKING_DIR}" DOMAIN_STORAGE="${DOMAIN_STORAGE:=$WORKING_DIR}"
@ -1569,11 +1606,17 @@ if [[ ${_CREATE_CONFIG} -eq 1 ]]; then
if [[ -s "$DOMAIN_DIR/getssl.cfg" ]]; then if [[ -s "$DOMAIN_DIR/getssl.cfg" ]]; then
info "domain config already exists $DOMAIN_DIR/getssl.cfg" info "domain config already exists $DOMAIN_DIR/getssl.cfg"
else else
info "creating domain config file in $DOMAIN_DIR/getssl.cfg"
# if domain has an existing cert, copy from domain and use to create defaults.
EX_CERT=$(echo \
| openssl s_client -servername "${DOMAIN}" -connect "${DOMAIN}:443" 2>/dev/null \
| openssl x509 2>/dev/null)
info "Contacting ${DOMAIN} to inspect current certificate"
EX_CERT=$( {
if [[ "${BASH_VERSINFO[0]}${BASH_VERSINFO[1]}" -ge 43 ]]; then
openssl s_client -servername "$DOMAIN" -connect "$DOMAIN":443 </dev/null 2>/dev/null & PID=$!
sleep ${CHECK_CERT_TIMEOUT} & PIDW=$!
wait -n # Requires bash 4.3+
kill -9 "$PID" "$PIDW" 2>/dev/null
else
openssl s_client -servername "$DOMAIN" -connect "$DOMAIN":443 </dev/null 2>/dev/null
fi
} | openssl x509 2>/dev/null)
EX_SANS="www.${DOMAIN}" EX_SANS="www.${DOMAIN}"
if [[ ! -z "${EX_CERT}" ]]; then if [[ ! -z "${EX_CERT}" ]]; then
EX_SANS=$(echo "$EX_CERT" \ EX_SANS=$(echo "$EX_CERT" \
@ -1582,6 +1625,7 @@ if [[ ${_CREATE_CONFIG} -eq 1 ]]; then
EX_SANS=${EX_SANS//$'\n'/','} EX_SANS=${EX_SANS//$'\n'/','}
fi fi
write_domain_template "$DOMAIN_DIR/getssl.cfg" write_domain_template "$DOMAIN_DIR/getssl.cfg"
info "created domain config file in $DOMAIN_DIR/getssl.cfg"
fi fi
TEMP_DIR="$DOMAIN_DIR/tmp" TEMP_DIR="$DOMAIN_DIR/tmp"
# end of "-c|--create" option, so exit # end of "-c|--create" option, so exit
@ -1609,6 +1653,11 @@ if [[ -s "$DOMAIN_DIR/getssl.cfg" ]]; then
. "$DOMAIN_DIR/getssl.cfg" . "$DOMAIN_DIR/getssl.cfg"
fi fi
# In case special options are needed for DNS_CHECK_FUNC, add them
# to the command. E.G. if a TSIG key or bound local IP is required...
DNS_CHECK_FUNC="${DNS_CHECK_FUNC} ${DNS_CHECK_OPTIONS}"
# from SERVER_TYPE set REMOTE_PORT and REMOTE_EXTRA # from SERVER_TYPE set REMOTE_PORT and REMOTE_EXTRA
set_server_type set_server_type
@ -1629,11 +1678,19 @@ URL_new_cert=$(echo "$ca_all_loc" | grep "new-cert" | awk -F'"' '{print $4}')
# if check_remote is true then connect and obtain the current certificate (if not forcing renewal) # if check_remote is true then connect and obtain the current certificate (if not forcing renewal)
if [[ "${CHECK_REMOTE}" == "true" ]] && [[ $_FORCE_RENEW -eq 0 ]]; then if [[ "${CHECK_REMOTE}" == "true" ]] && [[ $_FORCE_RENEW -eq 0 ]]; then
debug "getting certificate for $DOMAIN from remote server"
info "Contacting $DOMAIN on port ${REMOTE_PORT} to inspect current certificate"
# shellcheck disable=SC2086 # shellcheck disable=SC2086
EX_CERT=$(echo \
| openssl s_client -servername "${DOMAIN}" -connect "${DOMAIN}:${REMOTE_PORT}" ${REMOTE_EXTRA} 2>/dev/null \
| openssl x509 2>/dev/null)
EX_CERT=$( {
if [[ "${BASH_VERSINFO[0]}${BASH_VERSINFO[1]}" -ge 43 ]]; then
echo | openssl s_client -servername "${DOMAIN}" -connect "${DOMAIN}:${REMOTE_PORT}" ${REMOTE_EXTRA} 2>/dev/null & PID=$!
sleep ${CHECK_CERT_TIMEOUT} & PIDW=$!
wait -n # Requires bash 4.3+
kill -9 "$PID" "$PIDW" 2>/dev/null
else
echo | openssl s_client -servername "${DOMAIN}" -connect "${DOMAIN}:${REMOTE_PORT}" ${REMOTE_EXTRA} 2>/dev/null
fi
} | openssl x509 2>/dev/null )
if [[ ! -z "$EX_CERT" ]]; then # if obtained a cert if [[ ! -z "$EX_CERT" ]]; then # if obtained a cert
if [[ -s "$CERT_FILE" ]]; then # if local exists if [[ -s "$CERT_FILE" ]]; then # if local exists
CERT_LOCAL=$(openssl x509 -noout -fingerprint < "$CERT_FILE" 2>/dev/null) CERT_LOCAL=$(openssl x509 -noout -fingerprint < "$CERT_FILE" 2>/dev/null)
@ -1980,10 +2037,10 @@ if [[ $VALIDATE_VIA_DNS == "true" ]]; then
check_result=$(nslookup -type=txt "_acme-challenge.${d}" "${ns}" \ check_result=$(nslookup -type=txt "_acme-challenge.${d}" "${ns}" \
| grep ^_acme -A2\ | grep ^_acme -A2\
| grep '"'|awk -F'"' '{ print $2}') | grep '"'|awk -F'"' '{ print $2}')
elif [[ "$DNS_CHECK_FUNC" == "drill" ]] || [[ "$DNS_CHECK_FUNC" == "dig" ]]; then
check_result=$($DNS_CHECK_FUNC TXT "_acme-challenge.${d}" "@${ns}" \
elif [[ "$DNS_CHECK_FUNC" =~ ^drill ]] || [[ "$DNS_CHECK_FUNC" =~ ^dig ]]; then
check_result=$($DNS_CHECK_FUNC "_acme-challenge.${d}" TXT "@${ns}" \
| grep ^_acme|awk -F'"' '{ print $2}') | grep ^_acme|awk -F'"' '{ print $2}')
elif [[ "$DNS_CHECK_FUNC" == "host" ]]; then
elif [[ "$DNS_CHECK_FUNC" =~ ^host ]]; then
check_result=$($DNS_CHECK_FUNC -t TXT "_acme-challenge.${d}" "${ns}" \ check_result=$($DNS_CHECK_FUNC -t TXT "_acme-challenge.${d}" "${ns}" \
| grep ^_acme|awk -F'"' '{ print $2}') | grep ^_acme|awk -F'"' '{ print $2}')
else else


Loading…
Cancel
Save