Browse Source

added beta DNS validation checks

pull/1/head
srvrco 10 years ago
parent
commit
266b654804
2 changed files with 110 additions and 32 deletions
  1. +14
    -3
      README.md
  2. +96
    -29
      getssl

+ 14
- 3
README.md View File

@ -3,7 +3,7 @@ get an SSL certificate via LetsEncryot. Suitable for automating the process in
This was written as an addition to checkssl for servers to automatically renew certifictes. In addition it allows the running of this script in standard bash ( on a desktop computer, or even virtualbox) and add the checks, and certificates to a remote server ( providing you have an ssh key on the remote server with access). Potentially I can include FTP as an option for uploading as well.
getssl ver. 0.2
getssl ver. 0.8
To obtain a letsencrypt SSL cert
Usage: getssl [-h|--help] [-d|--debug] [-c] [-w working_dir] domain
@ -41,7 +41,11 @@ WORKING_DIR=~/.getssl
# the command needed to reload apache / gninx or whatever you use
#RELOAD_CMD=""
#The time period within which you want to allow renewal of a certificate - this prevents hitting some of the rate limits.
RENEW_ALLOW="30"`
RENEW_ALLOW="30"
#Use the following 3 variables if you want to validate via DNS
#VALIDATE_VIA_DNS="true"
#DNS_ADD_COMMAND=
#DNS_DEL_COMMAND=
```
then, within the **working directory** there will be a folder for each certificate (based on it's domain name). Within that folder will be a config file (again called getssl.cfg). An example of which is;
@ -75,7 +79,11 @@ SANS=www.testdomain.com
# the command needed to reload apache / gninx or whatever you use
#RELOAD_CMD="ssh:server5:service apache2 reload"
#The time period within which you want to allow renewal of a certificate - this prevents hitting some of the rate limits.
#RENEW_ALLOW="30"`
#RENEW_ALLOW="30"
#Use the following 3 variables if you want to validate via DNS
#VALIDATE_VIA_DNS=\"true\"
#DNS_ADD_COMMAND=
#DNS_DEL_COMMAND=
```
if a location for a file starts with ssh: it is assumed the next part of the file is the hostname, followed by a colon, and then the path.
@ -123,3 +131,6 @@ copying private key to ssh:server5:/home/yourdomain/ssl/domain.key
copying CA certificate to ssh:server5:/home/yourdomain/ssl/chain.crt
reloading SSL services
```
Note: Using DNS validation is still in early stages, and there are a number of issues related to it (for example I tested with cloudflare DNS which wouldn't work and with an "internal boulder sanity check" - https://github.com/letsencrypt/boulder/issues/1391

+ 96
- 29
getssl View File

@ -23,10 +23,11 @@
# 2016-01-12 corrected error on removal of token in some instances (v0.5)
# 2016-01-18 corrected issue with removing tmp if run as root with the -c option (v0.6)
# 2016-01-18 added option to upload a single PEN file ( used by cpanel) (v0.7)
# 2016-01-23 added dns challenge option (v0.8)
# ---------------------------------------------------------------------------
PROGNAME=${0##*/}
VERSION="0.7"
VERSION="0.8"
# defaults
#umask 077 # paranoid umask, as we're creating private keys
@ -37,6 +38,7 @@ ACCOUNT_KEY_LENGTH=4096
WORKING_DIR=~/.getssl
DOMAIN_KEY_LENGTH=4096
SSLCONF=/etc/ssl/openssl.cnf
VALIDATE_VIA_DNS=""
RELOAD_CMD=""
RENEW_ALLOW="30"
_CREATE_CONFIG=0
@ -275,6 +277,10 @@ WORKING_DIR=~/.getssl
#RELOAD_CMD=\"\"
#The time period within which you want to allow renewal of a certificate - this prevents hitting some of the rate limits.
RENEW_ALLOW=\"30\"
#Use the following 3 variables if you want to validate via DNS
#VALIDATE_VIA_DNS=\"true\"
#DNS_ADD_COMMAND=
#DNS_DEL_COMMAND=
" >> $WORKING_DIR/getssl.cfg
fi
if [ ! -d "$DOMAIN_DIR" ]; then
@ -325,6 +331,10 @@ SANS=${EX_SANS}
#RELOAD_CMD=\"\"
#The time period within which you want to allow renewal of a certificate - this prevents hitting some of the rate limits.
#RENEW_ALLOW=\"30\"
#Use the following 3 variables if you want to validate via DNS
#VALIDATE_VIA_DNS=\"true\"
#DNS_ADD_COMMAND=
#DNS_DEL_COMMAND=
" >> $DOMAIN_DIR/getssl.cfg
fi
@ -460,8 +470,15 @@ dn=0
for d in $alldomains; do
info "Verifing $d"
debug "domain $d has location ${ACL[$dn]}"
if [ -z "${ACL[$dn]}" ]; then
error_exit "ACL location not specified for domain $d in $DOMAIN_DIR/getssl.cfg"
if [[ $VALIDATE_VIA_DNS == "true" ]]; then
if [[ -z "$DNS_ADD_COMMAND" ]]; then
error_exit "DNS_ADD_COMMAND not defined for domain"
fi
else
if [ -z "${ACL[$dn]}" ]; then
error_exit "ACL location not specified for domain $d in $DOMAIN_DIR/getssl.cfg"
fi
fi
send_signed_request "$CA/acme/new-authz" "{\"resource\": \"new-authz\", \"identifier\": {\"type\": \"dns\", \"value\": \"$d\"}}"
@ -471,29 +488,75 @@ for d in $alldomains; do
error_exit "new-authz error: $response"
fi
http01=$(echo $response | egrep -o '{[^{]*"type":"http-01"[^}]*')
debug http01 "$http01"
if [[ $VALIDATE_VIA_DNS == "true" ]]; then # set up the correct DNS token for verification
dns01=$(echo $response | egrep -o '{[^{]*"type":"dns-01"[^}]*')
debug dns01 "$dns01"
token=$(echo "$dns01" | sed 's/,/\n'/g| grep '"token":'| cut -d : -f 2|sed 's/"//g')
debug token $token
uri=$(echo "$dns01" | sed 's/,/\n'/g| grep '"uri":'| cut -d : -f 2,3|sed 's/"//g')
debug uri $uri
keyauthorization="$token.$thumbprint"
debug keyauthorization "$keyauthorization"
auth_key=$(printf '%s' "$keyauthorization" | openssl sha -sha256 -binary | openssl base64 -e | tr -d '\n\r' | sed -e 's:=*$::g' -e 'y:+/:-_:')
debug auth_key $auth_key
$DNS_ADD_COMMAND "$DOMAIN" "$auth_key"
primary_ns=$(dig -t NS ${DOMAIN} | grep ^${DOMAIN} | awk '{print $5}' | sed 's/.$//' | head -1)
debug primary_ns $primary_ns
ntries=0
check_dns="fail"
while [[ "$check_dns" == "fail" ]]; do
token=$(echo "$http01" | sed 's/,/\n'/g| grep '"token":'| cut -d : -f 2|sed 's/"//g')
debug token $token
check_result=$(dig _acme-challenge.${DOMAIN} TXT +short @${primary_ns}| sed 's/"//g')
debug result $check_result
uri=$(echo "$http01" | sed 's/,/\n'/g| grep '"uri":'| cut -d : -f 2,3|sed 's/"//g')
debug uri $uri
if [[ "$check_result" == "$auth_key" ]]; then
check_dns="success"
debug "checking DNS ... _acme-challenge.$DOMAIN gave $check_result"
else
if [[ $ntries -lt 5 ]]; then
ntries=$(( $ntries + 1 ))
debug "try $ntries - sleep 2 secs before testiing verify again"
sleep 2
else
debug "dns check failed - removing existing value"
DNS_DEL_COMMAND $DOMAIN
error_exit "checking _acme-challenge.$DOMAIN gave $check_result not $auth_key"
fi
fi
done
else # set up the correct http token for verification
http01=$(echo $response | egrep -o '{[^{]*"type":"http-01"[^}]*')
debug http01 "$http01"
token=$(echo "$http01" | sed 's/,/\n'/g| grep '"token":'| cut -d : -f 2|sed 's/"//g')
debug token $token
keyauthorization="$token.$thumbprint"
debug keyauthorization "$keyauthorization"
uri=$(echo "$http01" | sed 's/,/\n'/g| grep '"uri":'| cut -d : -f 2,3|sed 's/"//g')
debug uri $uri
echo -n "$keyauthorization" > $TEMP_DIR/$token
chmod 755 $TEMP_DIR/$token
keyauthorization="$token.$thumbprint"
debug keyauthorization "$keyauthorization"
# copy to token to acme challenge location
copy_file_to_location $TEMP_DIR/$token ${ACL[$dn]}
echo -n "$keyauthorization" > $TEMP_DIR/$token
chmod 755 $TEMP_DIR/$token
wellknown_url="http://$d/.well-known/acme-challenge/$token"
debug wellknown_url "$wellknown_url"
# copy to token to acme challenge location
copy_file_to_location $TEMP_DIR/$token ${ACL[$dn]}
if [ ! "$(curl --silent $wellknown_url)" == "$keyauthorization" ]; then
error_exit "for some reason could not reach $wellknown_url - please check it manually"
wellknown_url="http://$d/.well-known/acme-challenge/$token"
debug wellknown_url "$wellknown_url"
if [ ! "$(curl --silent $wellknown_url)" == "$keyauthorization" ]; then
error_exit "for some reason could not reach $wellknown_url - please check it manually"
fi
fi
debug challenge "$challenge"
@ -529,18 +592,22 @@ for d in $alldomains; do
sleep 5
done
debug "remove token from ${ACL[$dn]}"
if [[ "${ACL[$dn]:0:4}" == "ssh:" ]] ; then
sshhost=$(echo "${ACL[$dn]}"| awk -F: '{print $2}')
command="rm -f ${ACL[$dn]:(( ${#sshhost} + 5))}/$token"
debug "running following comand to remove token"
debug "ssh $sshhost ${command}"
ssh $sshhost "${command}" 1>/dev/null 2>&1
rm -f $TEMP_DIR/$token
if [[ $VALIDATE_VIA_DNS == "true" ]]; then
debug "remove DNS entry"
DNS_DEL_COMMAND $DOMAIN
else
rm -f ${ACL[$dn]}/$token
debug "remove token from ${ACL[$dn]}"
if [[ "${ACL[$dn]:0:4}" == "ssh:" ]] ; then
sshhost=$(echo "${ACL[$dn]}"| awk -F: '{print $2}')
command="rm -f ${ACL[$dn]:(( ${#sshhost} + 5))}/$token"
debug "running following comand to remove token"
debug "ssh $sshhost ${command}"
ssh $sshhost "${command}" 1>/dev/null 2>&1
rm -f $TEMP_DIR/$token
else
rm -f ${ACL[$dn]}/$token
fi
fi
done
info "Verification completed, obtaining certificate."


Loading…
Cancel
Save