@ -62,12 +62,11 @@
# 2016-05-30 Improvements to auto-upgrade (0.44)
# 2016-05-31 Improved comments - no structural changes
# 2016-05-31 After running for nearly 6 months, final testing prior to a 1.00 stable version. (0.90)
# 2016-06-01 Reorder functions alphabetically as part of code tidy. (0.91)
# ---------------------------------------------------------------------------
PROGNAME=${0##*/}
VERSION="0.90"
ORIGCMD="$0 $*"
VERSION="0.91"
# defaults
CODE_LOCATION="https://raw.githubusercontent.com/srvrco/getssl/master/getssl"
@ -94,59 +93,64 @@ _FORCE_RENEW=0
_QUIET=0
_UPGRADE=0
clean_up() { # Perform pre-exit housekeeping
umask "$ORIG_UMASK"
if [ ! -z "$DOMAIN_DIR" ]; then
rm -rf "${TEMP_DIR:?}"
fi
if [[ $VALIDATE_VIA_DNS == "true" ]]; then
if [[ ! -z "$DNS_DEL_COMMAND" ]]; then
$DNS_DEL_COMMAND "$d"
fi
fi
}
# store copy of original command in case of upgrading script and re-running
ORIGCMD="$0 $*"
error_exit() { # give error message on error exit
echo -e "${PROGNAME}: ${1:-"Unknown Error"}" >&2
clean_up
exit 1
cert_archive() { # Archive certificate file by copying with dates at end.
certfile=$1
enddate=$(openssl x509 -in "$certfile" -noout -enddate 2>/dev/null| cut -d= -f 2-)
formatted_enddate=$(date -d "${enddate}" +%F)
startdate=$(openssl x509 -in "$certfile" -noout -startdate 2>/dev/null| cut -d= -f 2-)
formatted_startdate=$(date -d "${startdate}" +%F)
mv "${certfile}" "${certfile}_${formatted_startdate}_${formatted_enddate}"
info "archiving old certificate file to ${certfile}_${formatted_startdate}_${formatted_enddate}"
}
graceful_exit() { # normal exit function.
clean_up
exit
}
check_challenge_completion() { # checks with the ACME server if our challenge is OK
uri=$1
domain=$2
keyauthorization=$3
signal_exit() { # Handle trapped signals
case $1 in
INT)
error_exit "Program interrupted by user" ;;
TERM)
echo -e "\n$PROGNAME: Program terminated" >&2
graceful_exit ;;
*)
error_exit "$PROGNAME: Terminating on unknown signal" ;;
esac
}
debug "sending request to ACME server saying we're ready for challenge"
send_signed_request "$uri" "{\"resource\": \"challenge\", \"keyAuthorization\": \"$keyauthorization\"}"
usage() { # program usage
echo "Usage: $PROGNAME [-h|--help] [-d|--debug] [-c|--create] [-f|--force] [-a|--all] [-q|--quiet] [-u|--upgrade] [-w working_dir] domain"
}
# check respose from our request to perform challenge
if [ ! -z "$code" ] && [ ! "$code" == '202' ] ; then
error_exit "$domain:Challenge error: $code"
fi
log() { # write info to log file with date / time stamp
echo "[$(date +%Y-%m-%d\ %H:%M:%S)] $*" >> "${PROGNAME}.log"
}
# loop "forever" to keep checking for a response from the ACME server.
# shellcheck disable=SC2078
while [ "1" ] ; do
debug "checking"
if ! getcr "$uri" ; then
error_exit "$domain:Verify error:$code"
fi
debug() { # write out debug info if the debug flag has been set
if [ ${_USE_DEBUG} -eq 1 ]; then
echo "$@"
fi
}
# shellcheck disable=SC2086
status=$(echo $response | grep -Po '"status":[ ]*"[^"]+"' | cut -d '"' -f 4)
info() { # write out info as long as the quiet flag has not been set.
if [ ${_QUIET} -eq 0 ]; then
echo "$@"
fi
# If ACME respose is valid, then break out of loop
if [ "$status" == "valid" ] ; then
info "Verified $domain"
break;
fi
# if ACME response is that their check gave an invalid response, error exit
if [ "$status" == "invalid" ] ; then
error=$(echo "$response" | grep -Po '"error":[ ]*{[^}]*}' | grep -o '"detail":"[^"]*"' | cut -d '"' -f 4)
error_exit "$domain:Verify error:$error"
fi
# if ACME response is pending ( they haven't completed checks yet) then wait and try again.
if [ "$status" == "pending" ] ; then
info "Pending"
else
error_exit "$domain:Verify error:$response"
fi
debug "sleep 5 secs before testing verify again"
sleep 5
done
}
check_upgrade() { # check if a more recent version of code is available available
@ -176,14 +180,145 @@ check_upgrade() { # check if a more recent version of code is available availabl
fi
}
urlbase64() { # urlbase64: base64 encoded string with '+' replaced with '-' and '/' replaced with '_'
openssl base64 -e | tr -d '\n\r' | os_sed -e 's:=*$::g' -e 'y:+/:-_:'
clean_up() { # Perform pre-exit housekeeping
umask "$ORIG_UMASK"
if [ ! -z "$DOMAIN_DIR" ]; then
rm -rf "${TEMP_DIR:?}"
fi
if [[ $VALIDATE_VIA_DNS == "true" ]]; then
if [[ ! -z "$DNS_DEL_COMMAND" ]]; then
$DNS_DEL_COMMAND "$d"
fi
fi
}
copy_file_to_location() { # copies a file, using scp if required.
cert=$1 # descriptive name, just used for display
from=$2 # current file location
to=$3 # location to move file to.
if [ ! -z "$to" ]; then
info "copying $cert to $to"
debug "copying from $from to $to"
if [[ "${to:0:4}" == "ssh:" ]] ; then
debug "using scp scp -q $from ${to:4}"
scp -q "$from" "${to:4}" >/dev/null 2>&1
if [ $? -gt 0 ]; then
error_exit "problem copying file to the server using scp.
scp $from ${to:4}"
fi
elif [[ "${to:0:4}" == "ftp:" ]] ; then
if [[ "$cert" != "challenge token" ]] ; then
error_exit "ftp is not a sercure method for copying certificates or keys"
fi
debug "using ftp to copy the file from $from"
ftpuser=$(echo "$to"| awk -F: '{print $2}')
ftppass=$(echo "$to"| awk -F: '{print $3}')
ftphost=$(echo "$to"| awk -F: '{print $4}')
ftplocn=$(echo "$to"| awk -F: '{print $5}')
ftpdirn=$(dirname "$ftplocn")
ftpfile=$(basename "$ftplocn")
fromdir=$(dirname "$from")
fromfile=$(basename "$from")
debug "ftp user=$ftpuser - pass=$ftppass - host=$ftphost dir=$ftpdirn file=$ftpfile"
debug "from dir=$fromdir file=$fromfile"
ftp -n <<- _EOF
open $ftphost
user $ftpuser $ftppass
cd $ftpdirn
lcd $fromdir
put $fromfile
_EOF
elif [[ "${to:0:5}" == "sftp:" ]] ; then
debug "using sftp to copy the file from $from"
ftpuser=$(echo "$to"| awk -F: '{print $2}')
ftppass=$(echo "$to"| awk -F: '{print $3}')
ftphost=$(echo "$to"| awk -F: '{print $4}')
ftplocn=$(echo "$to"| awk -F: '{print $5}')
ftpdirn=$(dirname "$ftplocn")
ftpfile=$(basename "$ftplocn")
fromdir=$(dirname "$from")
fromfile=$(basename "$from")
debug "sftp user=$ftpuser - pass=$ftppass - host=$ftphost dir=$ftpdirn file=$ftpfile"
debug "from dir=$fromdir file=$fromfile"
sshpass -p "$ftppass" sftp "$ftpuser@$ftphost" <<- _EOF
cd $ftpdirn
lcd $fromdir
put $fromfile
_EOF
else
mkdir -p "$(dirname "$to")"
if [ $? -gt 0 ]; then
error_exit "cannot create ACL directory $(basename "$to")"
fi
cp "$from" "$to"
if [ $? -ne 0 ]; then
error_exit "cannot copy $from to $to"
fi
fi
debug "copied $from to $to"
fi
}
debug() { # write out debug info if the debug flag has been set
if [ ${_USE_DEBUG} -eq 1 ]; then
echo "$@"
fi
}
error_exit() { # give error message on error exit
echo -e "${PROGNAME}: ${1:-"Unknown Error"}" >&2
clean_up
exit 1
}
getcr() { # get curl response
url="$1"
debug url "$url"
response=$(curl --silent "$url")
ret=$?
debug response "$response"
# shellcheck disable=SC2086
code=$(echo $response | grep -Eo '"status":[ ]*[0-9]*' | cut -d : -f 2)
debug code "$code"
debug getcr return code $ret
return $ret
}
graceful_exit() { # normal exit function.
clean_up
exit
}
help_message() { # print out the help message
cat <<- _EOF_
$PROGNAME ver. $VERSION
Obtain SSL certificates from the letsencrypt.org ACME server
$(usage)
Options:
-h, --help Display this help message and exit
-d, --debug Outputs debug information
-c, --create Create default config files
-f, --force Force renewal of cert (overrides expiry checks)
-a, --all Check all certificates
-q, --quiet Quiet mode (only outputs on error)
-u, --upgrade Upgrade getssl if a more recent version is available
-w working_dir Working directory
_EOF_
}
hex2bin() { # Remove spaces, add leading zero, escape as hex string and parse with printf
printf -- "$(cat | os_sed -e 's/[[:space:]]//g' -e 's/^(.(.{2})*)$/0\1/' -e 's/(.{2})/\\x\1/g')"
}
info() { # write out info as long as the quiet flag has not been set.
if [ ${_QUIET} -eq 0 ]; then
echo "$@"
fi
}
os_sed() { # Use different sed version for different os types...
if [[ "$OSTYPE" == "linux-gnu" ]]; then
sed -r "${@}"
@ -192,54 +327,104 @@ os_sed() { # Use different sed version for different os types...
fi
}
write_openssl_conf() { # write out a minimal openssl conf
cat > "$1" <<- _EOF_openssl_conf_
# minimal openssl.cnf file
distinguished_name = req_distinguished_name
[ req_distinguished_name ]
[v3_req]
[v3_ca]
_EOF_openssl_conf_
reload_service() { # Runs a command to reload services ( via ssh if needed)
if [ ! -z "$RELOAD_CMD" ]; then
info "reloading SSL services"
if [[ "${RELOAD_CMD:0:4}" == "ssh:" ]] ; then
sshhost=$(echo "$RELOAD_CMD"| awk -F: '{print $2}')
command=${RELOAD_CMD:(( ${#sshhost} + 5))}
debug "running following comand to reload cert"
debug "ssh $sshhost ${command}"
# shellcheck disable=SC2029
ssh "$sshhost" "${command}" 1>/dev/null 2>&1
# allow 2 seconds for services to restart
sleep 2
else
debug "running reload command $RELOAD_CMD"
$RELOAD_CMD
fi
fi
}
write_getssl_template() { # write out the main template file
cat > "$1" <<- _EOF_getssl_
# Uncomment and modify any variables you need
# The staging server is best for testing (hence set as default)
CA="https://acme-staging.api.letsencrypt.org"
# This server issues full certificates, however has rate limits
#CA="https://acme-v01.api.letsencrypt.org"
requires() { # check if required function is availab le
result=$(which "$1" 2>/dev/null)
debug "checking for required $1 ... $result"
if [ -z "$result" ]; then
error_exit "This script requires $1 installed "
fi
}
AGREEMENT="https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf"
send_signed_request() { # Sends a request to the ACME server, signed with your private key.
url=$1
payload=$2
needbase64=$3
# Set an email address associated with your account - generally set at account level rather than domain.
#ACCOUNT_EMAIL="me@example.com"
ACCOUNT_KEY_LENGTH=4096
ACCOUNT_KEY="$WORKING_DIR/account.key"
PRIVATE_KEY_ALG="rsa"
debug url "$url"
debug payload "$payload"
# The command needed to reload apache / nginx 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"
CURL_HEADER="$TEMP_DIR/curl.header"
dp="$TEMP_DIR/curl.dump"
CURL="curl --silent --dump-header $CURL_HEADER "
if [ ${_USE_DEBUG} -eq 1 ]; then
CURL="$CURL --trace-ascii $dp "
fi
# Define the server type. This can either be a webserver, ldaps or a port number which
# will be checked for certificate expiry and also will be checked after
# an update to confirm correct certificate is running (if CHECK_REMOTE) is set to true
SERVER_TYPE="webserver"
CHECK_REMOTE="true"
# convert payload to url base 64
payload64="$(printf '%s' "${payload}" | urlbase64)"
debug payload64 "$payload64"
# openssl config file. The default should work in most cases.
SSLCONF="$SSLCONF"
# get nonce from ACME server
nonceurl="$CA/directory"
nonce=$($CURL -I $nonceurl | grep "^Replay-Nonce:" | sed s/\\r//|sed s/\\n//| cut -d ' ' -f 2)
# Use the following 3 variables if you want to validate via DNS
#VALIDATE_VIA_DNS="true"
#DNS_ADD_COMMAND=
#DNS_DEL_COMMAND=
# If your DNS-server needs extra time to make sure your DNS changes are readable by the ACME-server (time in seconds)
#DNS_EXTRA_WAIT=60
_EOF_getssl_
debug nonce "$nonce"
# Build header with just our public key and algorithm information
header='{"alg": "RS256", "jwk": {"e": "'"${pub_exp64}"'", "kty": "RSA", "n": "'"${pub_mod64}"'"}}'
# Build another header which also contains the previously received nonce and encode it as urlbase64
protected='{"alg": "RS256", "jwk": {"e": "'"${pub_exp64}"'", "kty": "RSA", "n": "'"${pub_mod64}"'"}, "nonce": "'"${nonce}"'"}'
protected64="$(printf '%s' "${protected}" | urlbase64)"
debug protected "$protected"
# Sign header with nonce and our payload with our private key and encode signature as urlbase64
signed64="$(printf '%s' "${protected64}.${payload64}" | openssl dgst -sha256 -sign "${ACCOUNT_KEY}" | urlbase64)"
# Send header + extended header + payload + signature to the acme-server
body='{"header": '"${header}"', "protected": "'"${protected64}"'", "payload": "'"${payload64}"'", "signature": "'"${signed64}"'"}'
debug "data for account registration = $body"
if [ "$needbase64" ] ; then
response=$($CURL -X POST --data "$body" "$url" | urlbase64)
else
response=$($CURL -X POST --data "$body" "$url")
fi
responseHeaders=$(sed 's/\r//g' "$CURL_HEADER")
debug responseHeaders "$responseHeaders"
debug response "$response"
code=$(grep ^HTTP "$CURL_HEADER" | tail -1 | cut -d " " -f 2)
debug code "$code"
}
signal_exit() { # Handle trapped signals
case $1 in
INT)
error_exit "Program interrupted by user" ;;
TERM)
echo -e "\n$PROGNAME: Program terminated" >&2
graceful_exit ;;
*)
error_exit "$PROGNAME: Terminating on unknown signal" ;;
esac
}
urlbase64() { # urlbase64: base64 encoded string with '+' replaced with '-' and '/' replaced with '_'
openssl base64 -e | tr -d '\n\r' | os_sed -e 's:=*$::g' -e 'y:+/:-_:'
}
usage() { # program usage
echo "Usage: $PROGNAME [-h|--help] [-d|--debug] [-c|--create] [-f|--force] [-a|--all] [-q|--quiet] [-u|--upgrade] [-w working_dir] domain"
}
write_domain_template() { # write out a template file for a domain.
@ -299,241 +484,54 @@ write_domain_template() { # write out a template file for a domain.
_EOF_domain_
}
send_signed_request() { # Sends a request to the ACME server, signed with your private key.
url=$1
payload=$2
needbase64=$3
debug url "$url"
debug payload "$payload"
CURL_HEADER="$TEMP_DIR/curl.header"
dp="$TEMP_DIR/curl.dump"
CURL="curl --silent --dump-header $CURL_HEADER "
if [ ${_USE_DEBUG} -eq 1 ]; then
CURL="$CURL --trace-ascii $dp "
fi
# convert payload to url base 64
payload64="$(printf '%s' "${payload}" | urlbase64)"
debug payload64 "$payload64"
# get nonce from ACME server
nonceurl="$CA/directory"
nonce=$($CURL -I $nonceurl | grep "^Replay-Nonce:" | sed s/\\r//|sed s/\\n//| cut -d ' ' -f 2)
debug nonce "$nonce"
# Build header with just our public key and algorithm information
header='{"alg": "RS256", "jwk": {"e": "'"${pub_exp64}"'", "kty": "RSA", "n": "'"${pub_mod64}"'"}}'
# Build another header which also contains the previously received nonce and encode it as urlbase64
protected='{"alg": "RS256", "jwk": {"e": "'"${pub_exp64}"'", "kty": "RSA", "n": "'"${pub_mod64}"'"}, "nonce": "'"${nonce}"'"}'
protected64="$(printf '%s' "${protected}" | urlbase64)"
debug protected "$protected"
# Sign header with nonce and our payload with our private key and encode signature as urlbase64
signed64="$(printf '%s' "${protected64}.${payload64}" | openssl dgst -sha256 -sign "${ACCOUNT_KEY}" | urlbase64)"
# Send header + extended header + payload + signature to the acme-server
body='{"header": '"${header}"', "protected": "'"${protected64}"'", "payload": "'"${payload64}"'", "signature": "'"${signed64}"'"}'
debug "data for account registration = $body"
if [ "$needbase64" ] ; then
response=$($CURL -X POST --data "$body" "$url" | urlbase64)
else
response=$($CURL -X POST --data "$body" "$url")
fi
responseHeaders=$(sed 's/\r//g' "$CURL_HEADER")
debug responseHeaders "$responseHeaders"
debug response "$response"
code=$(grep ^HTTP "$CURL_HEADER" | tail -1 | cut -d " " -f 2)
debug code "$code"
}
check_challenge_completion() { # checks with the ACME server if our challenge is OK
uri=$1
domain=$2
keyauthorization=$3
debug "sending request to ACME server saying we're ready for challenge"
send_signed_request "$uri" "{\"resource\": \"challenge\", \"keyAuthorization\": \"$keyauthorization\"}"
# check respose from our request to perform challenge
if [ ! -z "$code" ] && [ ! "$code" == '202' ] ; then
error_exit "$domain:Challenge error: $code"
fi
# loop "forever" to keep checking for a response from the ACME server.
# shellcheck disable=SC2078
while [ "1" ] ; do
debug "checking"
if ! getcr "$uri" ; then
error_exit "$domain:Verify error:$code"
fi
# shellcheck disable=SC2086
status=$(echo $response | grep -Po '"status":[ ]*"[^"]+"' | cut -d '"' -f 4)
# If ACME respose is valid, then break out of loop
if [ "$status" == "valid" ] ; then
info "Verified $domain"
break;
fi
# if ACME response is that their check gave an invalid response, error exit
if [ "$status" == "invalid" ] ; then
error=$(echo "$response" | grep -Po '"error":[ ]*{[^}]*}' | grep -o '"detail":"[^"]*"' | cut -d '"' -f 4)
error_exit "$domain:Verify error:$error"
fi
write_getssl_template() { # write out the main template file
cat > "$1" <<- _EOF_getssl_
# Uncomment and modify any variables you need
# The staging server is best for testing (hence set as default)
CA="https://acme-staging.api.letsencrypt.org"
# This server issues full certificates, however has rate limits
#CA="https://acme-v01.api.letsencrypt.org"
# if ACME response is pending ( they haven't completed checks yet) then wait and try again.
if [ "$status" == "pending" ] ; then
info "Pending"
else
error_exit "$domain:Verify error:$response"
fi
debug "sleep 5 secs before testing verify again"
sleep 5
done
}
AGREEMENT="https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf"
copy_file_to_location() { # copies a file, using scp if required.
cert=$1 # descriptive name, just used for display
from=$2 # current file location
to=$3 # location to move file to.
if [ ! -z "$to" ]; then
info "copying $cert to $to"
debug "copying from $from to $to"
if [[ "${to:0:4}" == "ssh:" ]] ; then
debug "using scp scp -q $from ${to:4}"
scp -q "$from" "${to:4}" >/dev/null 2>&1
if [ $? -gt 0 ]; then
error_exit "problem copying file to the server using scp.
scp $from ${to:4}"
fi
elif [[ "${to:0:4}" == "ftp:" ]] ; then
if [[ "$cert" != "challenge token" ]] ; then
error_exit "ftp is not a sercure method for copying certificates or keys"
fi
debug "using ftp to copy the file from $from"
ftpuser=$(echo "$to"| awk -F: '{print $2}')
ftppass=$(echo "$to"| awk -F: '{print $3}')
ftphost=$(echo "$to"| awk -F: '{print $4}')
ftplocn=$(echo "$to"| awk -F: '{print $5}')
ftpdirn=$(dirname "$ftplocn")
ftpfile=$(basename "$ftplocn")
fromdir=$(dirname "$from")
fromfile=$(basename "$from")
debug "ftp user=$ftpuser - pass=$ftppass - host=$ftphost dir=$ftpdirn file=$ftpfile"
debug "from dir=$fromdir file=$fromfile"
ftp -n <<- _EOF
open $ftphost
user $ftpuser $ftppass
cd $ftpdirn
lcd $fromdir
put $fromfile
_EOF
elif [[ "${to:0:5}" == "sftp:" ]] ; then
debug "using sftp to copy the file from $from"
ftpuser=$(echo "$to"| awk -F: '{print $2}')
ftppass=$(echo "$to"| awk -F: '{print $3}')
ftphost=$(echo "$to"| awk -F: '{print $4}')
ftplocn=$(echo "$to"| awk -F: '{print $5}')
ftpdirn=$(dirname "$ftplocn")
ftpfile=$(basename "$ftplocn")
fromdir=$(dirname "$from")
fromfile=$(basename "$from")
debug "sftp user=$ftpuser - pass=$ftppass - host=$ftphost dir=$ftpdirn file=$ftpfile"
debug "from dir=$fromdir file=$fromfile"
sshpass -p "$ftppass" sftp "$ftpuser@$ftphost" <<- _EOF
cd $ftpdirn
lcd $fromdir
put $fromfile
_EOF
else
mkdir -p "$(dirname "$to")"
if [ $? -gt 0 ]; then
error_exit "cannot create ACL directory $(basename "$to")"
fi
cp "$from" "$to"
if [ $? -ne 0 ]; then
error_exit "cannot copy $from to $to"
fi
fi
debug "copied $from to $to"
fi
}
# Set an email address associated with your account - generally set at account level rather than domain.
#ACCOUNT_EMAIL="me@example.com"
ACCOUNT_KEY_LENGTH=4096
ACCOUNT_KEY="$WORKING_DIR/account.key"
PRIVATE_KEY_ALG="rsa"
getcr() { # get curl response
url="$1"
debug url "$url"
response=$(curl --silent "$url")
ret=$?
debug response "$response"
# shellcheck disable=SC2086
code=$(echo $response | grep -Eo '"status":[ ]*[0-9]*' | cut -d : -f 2)
debug code "$code"
debug getcr return code $ret
return $ret
}
# The command needed to reload apache / nginx 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"
_requires() { # check if required function is available
result=$(which "$1" 2>/dev/null)
debug "checking for required $1 ... $result"
if [ -z "$result" ]; then
error_exit "This script requires $1 installed"
fi
}
# Define the server type. This can either be a webserver, ldaps or a port number which
# will be checked for certificate expiry and also will be checked after
# an update to confirm correct certificate is running (if CHECK_REMOTE) is set to true
SERVER_TYPE="webserver"
CHECK_REMOTE="true"
cert_archive() { # Archive certificate file by copying with dates at end.
certfile=$1
enddate=$(openssl x509 -in "$certfile" -noout -enddate 2>/dev/null| cut -d= -f 2-)
formatted_enddate=$(date -d "${enddate}" +%F)
startdate=$(openssl x509 -in "$certfile" -noout -startdate 2>/dev/null| cut -d= -f 2-)
formatted_startdate=$(date -d "${startdate}" +%F)
mv "${certfile}" "${certfile}_${formatted_startdate}_${formatted_enddate}"
info "archiving old certificate file to ${certfile}_${formatted_startdate}_${formatted_enddate}"
}
# openssl config file. The default should work in most cases.
SSLCONF="$SSLCONF"
reload_service() { # Runs a command to reload services ( via ssh if needed)
if [ ! -z "$RELOAD_CMD" ]; then
info "reloading SSL services"
if [[ "${RELOAD_CMD:0:4}" == "ssh:" ]] ; then
sshhost=$(echo "$RELOAD_CMD"| awk -F: '{print $2}')
command=${RELOAD_CMD:(( ${#sshhost} + 5))}
debug "running following comand to reload cert"
debug "ssh $sshhost ${command}"
# shellcheck disable=SC2029
ssh "$sshhost" "${command}" 1>/dev/null 2>&1
# allow 2 seconds for services to restart
sleep 2
else
debug "running reload command $RELOAD_CMD"
$RELOAD_CMD
fi
fi
# Use the following 3 variables if you want to validate via DNS
#VALIDATE_VIA_DNS="true"
#DNS_ADD_COMMAND=
#DNS_DEL_COMMAND=
# If your DNS-server needs extra time to make sure your DNS changes are readable by the ACME-server (time in seconds)
#DNS_EXTRA_WAIT=60
_EOF_getssl_
}
help_message() { # print out the help message
cat <<- _EOF_
$PROGNAME ver. $VERSION
Obtain SSL certificates from the letsencrypt.org ACME server
$(usage)
Options:
-h, --help Display this help message and exit
-d, --debug Outputs debug information
-c, --create Create default config files
-f, --force Force renewal of cert (overrides expiry checks)
-a, --all Check all certificates
-q, --quiet Quiet mode (only outputs on error)
-u, --upgrade Upgrade getssl if a more recent version is available
-w working_dir Working directory
_EOF_
write_openssl_conf() { # write out a minimal openssl conf
cat > "$1" <<- _EOF_openssl_conf_
# minimal openssl.cnf file
distinguished_name = req_distinguished_name
[ req_distinguished_name ]
[v3_req]
[v3_ca]
_EOF_openssl_conf_
}
# Trap signals
@ -572,13 +570,13 @@ done
#check if required applications are included
_ requires openssl
_ requires curl
_ requires nslookup
_ requires sed
_ requires grep
_ requires awk
_ requires tr
requires openssl
requires curl
requires nslookup
requires sed
requires grep
requires awk
requires tr
# Check if upgrades are available
check_upgrade