diff --git a/cm.sh b/cm.sh index d62dc31eaefb86d422569046e70c320a170eba46..e3dc9da5411eca435a95fdac1262d8ceacb69317 100755 --- a/cm.sh +++ b/cm.sh @@ -26,6 +26,7 @@ # 2021-12-23 <axel.hahn@iml.unibe.ch> added param --trace as 1st param to generate a trace log # 2022-01-10 <axel.hahn@iml.unibe.ch> _wait_for_free_slot: exclude ssh calls # 2022-03-30 <axel.hahn@iml.unibe.ch> remove usage of csr and generation of key file +# 2022-03-31 <axel.hahn@iml.unibe.ch> dns authentication with alias domain # ====================================================================== @@ -39,7 +40,8 @@ logdir="./log" touchfile="$logdir/lastchange.txt" logfile="$logdir/certmanager.log" -csrfile="./templates/csr.txt" +# CSR USAGE WAS REMOVED +# csrfile="./templates/csr.txt" line="_______________________________________________________________________________" @@ -85,12 +87,12 @@ function _certMustExist(){ # the script will be aborted # param string FQDN function _certMustNotExist(){ - _certExists - if [ $? -eq 0 ]; then - echo "WARNING: cert ${CM_fqdn} was added already." - # exit 1 - echo "Press Ctrl+C to abort within the next 10 sec..." - sleep 10 + if _certExists + then + echo "ERROR: cert ${CM_fqdn} was added already." + exit 1 + # echo "Press Ctrl+C to abort within the next 10 sec..." + # sleep 10 fi } @@ -135,15 +137,17 @@ function _certTransfer(){ fi } -# internal function; show md5 hashsums for certificate, csr and key +# internal function; show md5 hashsums for certificate and key # for visual comparison if the match function _certMatching(){ + # CSR USAGE WAS REMOVED # local md5_csr=$( test -f ${CM_filecsr} && openssl req -noout -modulus -in ${CM_filecsr} | openssl md5 | cut -f 2 -d " " ) local md5_key=$( test -f ${CM_outfile_key} && openssl rsa -noout -modulus -in ${CM_outfile_key} | openssl md5 | cut -f 2 -d " " ) local md5_cert=$( test -f ${CM_outfile_cert} && openssl x509 -noout -modulus -in ${CM_outfile_cert} | openssl md5 | cut -f 2 -d " " ) echo echo "--- compare hashes" + # CSR USAGE WAS REMOVED # echo "csr : $md5_csr (used for creation of cert)" echo "key : $md5_key" echo "cert : $md5_cert" @@ -158,18 +162,19 @@ function _certMatching(){ # internal function: dig for given fqdn. # Function stops if fqdn was not found in DNS. # If dig is not found the function skips the DNS check. -# This function is used in _gencsr +# This function is used in _dnsCheck # param string fqdn to check # param string type of dns entry; one of a|cname +# param string optional filter on output of dig (regex) function _checkDig(){ local myfqdn=$1 local _type=${2:-"a"} - # local _verify=${3:-"."} + local _verify=${3:-"."} if which dig >/dev/null then # _wd "[$myfqdn] exists as type [$_type] in DNS?" - if ! dig "${myfqdn}" "${_type}" | grep "^${myfqdn}" # | grep "${_verify}" + if ! dig "${myfqdn}" "${_type}" | grep "^${myfqdn}" | grep -E "${_verify}" then echo "ERROR: [$myfqdn] was not found. Maybe there is a typo in the hostname or it does not exist in DNS." exit 2 @@ -182,6 +187,12 @@ function _checkDig(){ } +# internal function: check DNS entries +# - the hostname to be added in the certificate must exist +# - if a hostname does not match and CM_challenge_alias was set: +# - _acme-challenge.FQDN must be a cname to _acme-challenge.${CM_challenge_alias} +# Function stops if a fqdn was not found in DNS. +# param string fqdn(s) that are part of the certificate function _dnsCheck(){ local altdns= local _mydomain= @@ -190,50 +201,50 @@ function _dnsCheck(){ for _mydomain in $* do _wd "dig check - domain for cert" - _checkDig "$_mydomain" "a" + _checkDig "$_mydomain" "a" "IN.*(A|CNAME)" # matches A and CNAME records if [ -n "${CM_challenge_alias}" ] && ! echo "$_mydomain" | grep "${CM_certmatch}" >/dev/null then - # _wd "Host is not matching ${CM_certmatch} ... using dns alias" - # _wd "dig check - domain with api access $_subdomain... " - # _checkDig "${_subdomain}.${CM_challenge_alias}" "a" - _wd "dig check - cname ${_subdomain}.${_mydomain} must point to ${_subdomain}.${CM_challenge_alias}" + _wd "dig check - cname ${_subdomain}.${_mydomain} must exist" _checkDig "${_subdomain}.${_mydomain}" "cname" + _wd "dig check - cname ${_subdomain}.${_mydomain} must point to ${_subdomain}.${CM_challenge_alias}" + _checkDig "${_subdomain}.${_mydomain}" "cname" "${_subdomain}.${CM_challenge_alias}" fi done } +# CSR USAGE WAS REMOVED # internal function; generate a csr file before creating a new certifcate # this function is used in public_add -function _gencsr(){ +# function _UNUSED_gencsr(){ - local altdns= +# local altdns= - for myalt in $* - do - altdns="${altdns}DNS:$myalt," - done - altdns=$( echo $altdns | sed "s#,\$##" ) - _wd "--- $CM_fqdn" - _wd "DNS alternative names: $altdns" +# for myalt in $* +# do +# altdns="${altdns}DNS:$myalt," +# done +# altdns=$( echo $altdns | sed "s#,\$##" ) +# _wd "--- $CM_fqdn" +# _wd "DNS alternative names: $altdns" - rm -f $CM_filecnf $CM_filekey $CM_filecsr - mkdir -p "${CM_dircsr}" 2>/dev/null +# rm -f $CM_filecnf $CM_filekey $CM_filecsr +# mkdir -p "${CM_dircsr}" 2>/dev/null - cat $csrfile \ - | sed "s#__FQDN__#$CM_fqdn#g" \ - | sed "s#__ALTNAMES__#$altdns#g" \ - > $CM_filecnf || exit 1 +# cat $csrfile \ +# | sed "s#__FQDN__#$CM_fqdn#g" \ +# | sed "s#__ALTNAMES__#$altdns#g" \ +# > $CM_filecnf || exit 1 - # generate csr - _wd "creating key and csr" - openssl req -new -config $CM_filecnf -keyout $CM_filekey -out $CM_filecsr || exit 1 +# # generate csr +# _wd "creating key and csr" +# openssl req -new -config $CM_filecnf -keyout $CM_filekey -out $CM_filecsr || exit 1 - # view csr - # openssl req -noout -text -in $CM_filecsr - ls -ltr $CM_filecnf $CM_filekey $CM_filecsr -} +# # view csr +# # openssl req -noout -text -in $CM_filecsr +# ls -ltr $CM_filecnf $CM_filekey $CM_filecsr +# } # internal function; get a sorted list of DNS aliases in the current cert function _getAliases(){ @@ -318,6 +329,8 @@ function _wd(){ # param string FQDN function _setenv(){ CM_fqdn=$1 + # CSR USAGE WAS REMOVED + # keeping vars to delete files of existing certs that used a csr CM_filecsr="${CM_dircsr}/${CM_fqdn}.csr" CM_filecnf="${CM_dircsr}/${CM_fqdn}.cnf" CM_filekey="${CM_dircsr}/${CM_fqdn}.key" @@ -370,7 +383,7 @@ function public_add(){ _requiresFqdn _certMustNotExist - # _dnsCheck $CM_fqdn $* + _dnsCheck $CM_fqdn $* for _mydomain in $CM_fqdn $* do @@ -386,11 +399,6 @@ function public_add(){ mkdir -p "${CM_dircerts}" 2>/dev/null _wd "--- create certificate" - # echo $ACME --signcsr --csr $CM_filecsr $ACME_Params - # $ACME --signcsr --csr $CM_filecsr $ACME_Params - - - echo $ACME --issue $_params $ACME_Params if ! $ACME --issue $_params $ACME_Params then @@ -406,42 +414,43 @@ function public_add(){ _update "added $CM_fqdn $*" } -function OLD__public_add(){ - _wait_for_free_slot - _requiresFqdn - _certMustNotExist - - for myhost in $( echo $CM_fqdn $*) - do - echo $myhost | grep "$CM_certmatch" >/dev/null - if [ $? -ne 0 ]; then - echo "ERROR: host $myhost does not match [$CM_certmatch]." - exit 1 - fi - done - _gencsr $CM_fqdn $* - - _wd "--- create output dir $dircerts" - mkdir -p "${CM_dircerts}" 2>/dev/null - - _wd "--- csr data" - $ACME --showcsr --csr $CM_filecsr || exit 1 - - _wd "--- create certificate" - echo $ACME --signcsr --csr $CM_filecsr $ACME_Params - $ACME --signcsr --csr $CM_filecsr $ACME_Params - if [ $? -ne 0 ]; then - echo "ERROR: adding cert failed. Trying to delete internal data ..." - public_delete $CM_fqdn - exit 1 - fi - # $ACME --issue -d $CM_fqdn $ACME_Params || exit 1 - - _certTransfer - _certMatching - - _update "added $CM_fqdn $*" -} +# CSR USAGE WAS REMOVED +# function OLD__public_add(){ +# _wait_for_free_slot +# _requiresFqdn +# _certMustNotExist + +# for myhost in $( echo $CM_fqdn $*) +# do +# echo $myhost | grep "$CM_certmatch" >/dev/null +# if [ $? -ne 0 ]; then +# echo "ERROR: host $myhost does not match [$CM_certmatch]." +# exit 1 +# fi +# done +# _gencsr $CM_fqdn $* + +# _wd "--- create output dir $dircerts" +# mkdir -p "${CM_dircerts}" 2>/dev/null + +# _wd "--- csr data" +# $ACME --showcsr --csr $CM_filecsr || exit 1 + +# _wd "--- create certificate" +# echo $ACME --signcsr --csr $CM_filecsr $ACME_Params +# $ACME --signcsr --csr $CM_filecsr $ACME_Params +# if [ $? -ne 0 ]; then +# echo "ERROR: adding cert failed. Trying to delete internal data ..." +# public_delete $CM_fqdn +# exit 1 +# fi +# # $ACME --issue -d $CM_fqdn $ACME_Params || exit 1 + +# _certTransfer +# _certMatching + +# _update "added $CM_fqdn $*" +# } # # pulic function ADD OR RENEW certificate @@ -486,6 +495,8 @@ function public_delete(){ _wd "--- delete ACME.SH data" $ACME --remove -d ${CM_fqdn} $ACME_Params _wd "--- delete local data" + + # CSR USAGE WAS REMOVED rm -rf ${CM_dircerts} ${CM_filecnf} ${CM_filekey} ${CM_filecsr} ~/.acme.sh/${CM_fqdn} && echo OK _update "deleted ${CM_fqdn}" } @@ -567,7 +578,7 @@ function public_selftest(){ echo echo --- dependencies - _selftestItem "which openssl" "opemssl was found" + _selftestItem "which openssl" "openssl was found" _selftestItem "which curl" "curl was found" echo @@ -581,15 +592,16 @@ function public_selftest(){ _selftestItem "test -w ~/.acme.sh/" "it is writable" echo - echo --- csr template - _selftestItem "ls -ld ${csrfile}" "csr base template exists" - _selftestItem "test -r ${csrfile}" "it is readable" - echo - - echo --- output directory for csr and key - _selftestItem "ls -ld ${CM_dircsr}" "data dir for csr exists" - _selftestItem "test -w ${CM_dircsr}" "it is writable" - echo + # CSR USAGE WAS REMOVED + # echo --- csr template + # _selftestItem "ls -ld ${csrfile}" "csr base template exists" + # _selftestItem "test -r ${csrfile}" "it is readable" + # echo + # + # echo --- output directory for csr and key + # _selftestItem "ls -ld ${CM_dircsr}" "data dir for csr exists" + # _selftestItem "test -w ${CM_dircsr}" "it is writable" + # echo echo --- output dir for centralized place of certificates _selftestItem "ls -ld ${CM_diracme}" "central output dir for certificate data exists" @@ -617,11 +629,15 @@ function public_show(){ _requiresFqdn _certMustExist - ls -l ${CM_filecsr} ${CM_dircerts}/* + # CSR USAGE WAS REMOVED + # ls -l ${CM_filecsr} ${CM_dircerts}/* + ls -l ${CM_dircerts}/* _certMatching - echo $line - echo CSR $CM_filecsr - openssl req -noout -text -in $CM_filecsr | grep -E "(Subject:|DNS:)" | sed "s#^\ *##g" + + # CSR USAGE WAS REMOVED + # echo $line + # echo CSR $CM_filecsr + # openssl req -noout -text -in $CM_filecsr | grep -E "(Subject:|DNS:)" | sed "s#^\ *##g" for myfile in ${CM_outfile_cert} ${CM_outfile_haproxy} do @@ -745,7 +761,7 @@ The ACTIONs for SINGLE certificate handlings are: and update files in ${CM_diracme} show FQDN - show place of csr + certificate data and show basic certificate data + show place of certificate data and show basic certificate data (issuer, subject, aliases, ending date) transfer FQDN diff --git a/inc_config.sh.dist b/inc_config.sh.dist index 3e546aef86e9b667202b938de557d305363775d6..cf41e8a36c95e7dc3dffdda2ceca1096561f868b 100644 --- a/inc_config.sh.dist +++ b/inc_config.sh.dist @@ -43,6 +43,8 @@ export ACME=../acme.sh/acme.sh # have no permission # export CM_certmatch="\.example\.com" +# if a host is not matching CM_certmatch we will use authentication +# with an alias domain # export CM_challenge_alias="example.com" # optional: force a user to execute cm.sh