Browse Source

Merge remote-tracking branch 'upstream/master' into ssh-deploy

dkerr64 7 years ago
parent
commit
19aa2ccf4d
7 changed files with 218 additions and 76 deletions
  1. 1 1
      Dockerfile
  2. 2 2
      README.md
  3. 178 53
      acme.sh
  4. 1 1
      dnsapi/README.md
  5. 22 10
      dnsapi/dns_dynu.sh
  6. 13 8
      dnsapi/dns_infoblox.sh
  7. 1 1
      dnsapi/dns_ovh.sh

+ 1 - 1
Dockerfile

@@ -50,7 +50,7 @@ RUN for verb in help \
 
 RUN printf "%b" '#!'"/usr/bin/env sh\n \
 if [ \"\$1\" = \"daemon\" ];  then \n \
- crond; tail -f /dev/null;\n \
+ crond -f\n \
 else \n \
  /root/.acme.sh/acme.sh --config-home /acme.sh \"\$@\"\n \
 fi" >/entry.sh && chmod +x /entry.sh

+ 2 - 2
README.md

@@ -62,7 +62,7 @@ Twitter: [@neilpangxa](https://twitter.com/neilpangxa)
 |19|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/gentoo-stage3-amd64.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Gentoo Linux
 |20|[![Build Status](https://travis-ci.org/Neilpang/acme.sh.svg?branch=master)](https://travis-ci.org/Neilpang/acme.sh)|Mac OSX
 
-For all build statuses, check our [daily build project](https://github.com/Neilpang/acmetest):
+For all build statuses, check our [weekly build project](https://github.com/Neilpang/acmetest):
 
 https://github.com/Neilpang/acmetest
 
@@ -199,7 +199,7 @@ The ownership and permission info of existing files are preserved. You may want
 
 Install/copy the issued cert/key to the production Apache or Nginx path.
 
-The cert will be `renewed every **60** days by default` (which is configurable). Once the cert is renewed, the Apache/Nginx service will be restarted automatically by the command: `service apache2 restart` or `service nginx restart`.
+The cert will be renewed every **60** days by default (which is configurable). Once the cert is renewed, the Apache/Nginx service will be reloaded automatically by the command: `service apache2 force-reload` or `service nginx force-reload`.
 
 
 # 4. Use Standalone server to issue cert

+ 178 - 53
acme.sh

@@ -1,6 +1,6 @@
 #!/usr/bin/env sh
 
-VER=2.6.9
+VER=2.7.3
 
 PROJECT_NAME="acme.sh"
 
@@ -13,7 +13,8 @@ _SCRIPT_="$0"
 
 _SUB_FOLDERS="dnsapi deploy"
 
-DEFAULT_CA="https://acme-v01.api.letsencrypt.org"
+_OLD_CA_HOST="https://acme-v01.api.letsencrypt.org"
+DEFAULT_CA="https://acme-v01.api.letsencrypt.org/directory"
 DEFAULT_AGREEMENT="https://letsencrypt.org/documents/LE-SA-v1.1.1-August-1-2016.pdf"
 
 DEFAULT_USER_AGENT="$PROJECT_NAME/$VER ($PROJECT)"
@@ -24,7 +25,8 @@ DEFAULT_DOMAIN_KEY_LENGTH=2048
 
 DEFAULT_OPENSSL_BIN="openssl"
 
-STAGE_CA="https://acme-staging.api.letsencrypt.org"
+STAGE_CA="https://acme-staging.api.letsencrypt.org/directory"
+_OLD_STAGE_CA_HOST="https://acme-staging.api.letsencrypt.org"
 
 VTYPE_HTTP="http-01"
 VTYPE_DNS="dns-01"
@@ -104,21 +106,21 @@ if [ -t 1 ]; then
 fi
 
 __green() {
-  if [ "$__INTERACTIVE" ]; then
+  if [ "$__INTERACTIVE${ACME_NO_COLOR}" = "1" ]; then
     printf '\033[1;31;32m'
   fi
   printf -- "%b" "$1"
-  if [ "$__INTERACTIVE" ]; then
+  if [ "$__INTERACTIVE${ACME_NO_COLOR}" = "1" ]; then
     printf '\033[0m'
   fi
 }
 
 __red() {
-  if [ "$__INTERACTIVE" ]; then
+  if [ "$__INTERACTIVE${ACME_NO_COLOR}" = "1" ]; then
     printf '\033[1;31;40m'
   fi
   printf -- "%b" "$1"
-  if [ "$__INTERACTIVE" ]; then
+  if [ "$__INTERACTIVE${ACME_NO_COLOR}" = "1" ]; then
     printf '\033[0m'
   fi
 }
@@ -151,6 +153,13 @@ _dlg_versions() {
     echo "apache doesn't exists."
   fi
 
+  echo "nginx:"
+  if _exists "nginx"; then
+    nginx -V 2>&1
+  else
+    echo "nginx doesn't exists."
+  fi
+
   echo "nc:"
   if _exists "nc"; then
     nc -h 2>&1
@@ -443,6 +452,11 @@ if [ "$(printf '\x41')" != 'A' ]; then
   _URGLY_PRINTF=1
 fi
 
+_ESCAPE_XARGS=""
+if [ "$(printf %s '\\x41' | xargs printf)" = 'A' ]; then
+  _ESCAPE_XARGS=1
+fi
+
 _h2b() {
   if _exists xxd; then
     xxd -r -p
@@ -450,31 +464,33 @@ _h2b() {
   fi
 
   hex=$(cat)
-  i=1
-  j=2
+  ic=""
+  jc=""
   _debug2 _URGLY_PRINTF "$_URGLY_PRINTF"
   if [ -z "$_URGLY_PRINTF" ]; then
-    while true; do
-      h="$(printf "%s" "$hex" | cut -c $i-$j)"
-      if [ -z "$h" ]; then
-        break
-      fi
-      printf "\x$h%s"
-      i="$(_math "$i" + 2)"
-      j="$(_math "$j" + 2)"
-    done
+    if [ "$_ESCAPE_XARGS" ] && _exists xargs; then
+      _debug2 "xargs"
+      echo "$hex" | _upper_case | sed 's/\([0-9A-F]\{2\}\)/\\\\\\x\1/g' | xargs printf
+    else
+      for h in $(echo "$hex" | _upper_case | sed 's/\([0-9A-F]\{2\}\)/ \1/g'); do
+        if [ -z "$h" ]; then
+          break
+        fi
+        printf "\x$h%s"
+      done
+    fi
   else
-    while true; do
-      ic="$(printf "%s" "$hex" | cut -c $i)"
-      jc="$(printf "%s" "$hex" | cut -c $j)"
-      if [ -z "$ic$jc" ]; then
-        break
+    for c in $(echo "$hex" | _upper_case | sed 's/\([0-9A-F]\)/ \1/g'); do
+      if [ -z "$ic" ]; then
+        ic=$c
+        continue
       fi
+      jc=$c
       ic="$(_h_char_2_dec "$ic")"
       jc="$(_h_char_2_dec "$jc")"
       printf '\'"$(printf "%o" "$(_math "$ic" \* 16 + $jc)")""%s"
-      i="$(_math "$i" + 2)"
-      j="$(_math "$j" + 2)"
+      ic=""
+      jc=""
     done
   fi
 
@@ -1079,7 +1095,7 @@ _readSubjectFromCSR() {
     _usage "_readSubjectFromCSR mycsr.csr"
     return 1
   fi
-  ${ACME_OPENSSL_BIN:-openssl} req -noout -in "$_csrfile" -subject | _egrep_o "CN *=.*" | cut -d = -f 2 | cut -d / -f 1 | tr -d '\n'
+  ${ACME_OPENSSL_BIN:-openssl} req -noout -in "$_csrfile" -subject | tr ',' "\n" | _egrep_o "CN *=.*" | cut -d = -f 2 | cut -d / -f 1 | tr -d ' \n'
 }
 
 #_csrfile
@@ -1122,7 +1138,7 @@ _readKeyLengthFromCSR() {
     echo "$_outcsr" | tr "\t" " " | _egrep_o "^ *ASN1 OID:.*" | cut -d ':' -f 2 | tr -d ' '
   else
     _debug "RSA CSR"
-    echo "$_outcsr" | tr "\t" " " | _egrep_o "(^ *|RSA )Public.Key:.*" | cut -d '(' -f 2 | cut -d ' ' -f 1
+    echo "$_outcsr" | tr "\t" " " | (_egrep_o "^ *Public.Key:.*" || _egrep_o "RSA Public.Key:.*") | cut -d '(' -f 2 | cut -d ' ' -f 1
   fi
 }
 
@@ -1700,9 +1716,19 @@ _send_signed_request() {
   while [ "${_request_retry_times}" -lt "$MAX_REQUEST_RETRY_TIMES" ]; do
     _debug3 _request_retry_times "$_request_retry_times"
     if [ -z "$_CACHED_NONCE" ]; then
-      _debug2 "Get nonce."
-      nonceurl="$API/directory"
-      _headers="$(_get "$nonceurl" "onlyheader")"
+      _headers=""
+      if [ "$ACME_NEW_NONCE" ]; then
+        _debug2 "Get nonce. ACME_NEW_NONCE" "$ACME_NEW_NONCE"
+        nonceurl="$ACME_NEW_NONCE"
+        if _post "" "$nonceurl" "" "HEAD"; then
+          _headers="$(cat "$HTTP_HEADER")"
+        fi
+      fi
+      if [ -z "$_headers" ]; then
+        _debug2 "Get nonce. ACME_DIRECTORY" "$ACME_DIRECTORY"
+        nonceurl="$ACME_DIRECTORY"
+        _headers="$(_get "$nonceurl" "onlyheader")"
+      fi
 
       if [ "$?" != "0" ]; then
         _err "Can not connect to $nonceurl to get nonce."
@@ -1719,7 +1745,7 @@ _send_signed_request() {
     nonce="$_CACHED_NONCE"
     _debug2 nonce "$nonce"
 
-    protected="$JWK_HEADERPLACE_PART1$nonce$JWK_HEADERPLACE_PART2"
+    protected="$JWK_HEADERPLACE_PART1$nonce\", \"url\": \"${url}$JWK_HEADERPLACE_PART2"
     _debug3 protected "$protected"
 
     protected64="$(printf "%s" "$protected" | _base64 | _url_replace)"
@@ -2155,6 +2181,62 @@ __initHome() {
   fi
 }
 
+#server
+_initAPI() {
+  _api_server="${1:-$ACME_DIRECTORY}"
+  _debug "_init api for server: $_api_server"
+
+  if [ "$_api_server" = "$DEFAULT_CA" ]; then
+    #just for performance, hardcode the default entry points
+    export ACME_KEY_CHANGE="https://acme-v01.api.letsencrypt.org/acme/key-change"
+    export ACME_NEW_AUTHZ="https://acme-v01.api.letsencrypt.org/acme/new-authz"
+    export ACME_NEW_ORDER="https://acme-v01.api.letsencrypt.org/acme/new-cert"
+    export ACME_NEW_ACCOUNT="https://acme-v01.api.letsencrypt.org/acme/new-reg"
+    export ACME_REVOKE_CERT="https://acme-v01.api.letsencrypt.org/acme/revoke-cert"
+  fi
+
+  if [ -z "$ACME_NEW_ACCOUNT" ]; then
+    response=$(_get "$_api_server")
+    if [ "$?" != "0" ]; then
+      _debug2 "response" "$response"
+      _err "Can not init api."
+      return 1
+    fi
+    _debug2 "response" "$response"
+
+    ACME_KEY_CHANGE=$(echo "$response" | _egrep_o 'key-change" *: *"[^"]*"' | cut -d '"' -f 3)
+    export ACME_KEY_CHANGE
+
+    ACME_NEW_AUTHZ=$(echo "$response" | _egrep_o 'new-authz" *: *"[^"]*"' | cut -d '"' -f 3)
+    export ACME_NEW_AUTHZ
+
+    ACME_NEW_ORDER=$(echo "$response" | _egrep_o 'new-cert" *: *"[^"]*"' | cut -d '"' -f 3)
+    if [ -z "$ACME_NEW_ORDER" ]; then
+      ACME_NEW_ORDER=$(echo "$response" | _egrep_o 'new-order" *: *"[^"]*"' | cut -d '"' -f 3)
+    fi
+    export ACME_NEW_ORDER
+
+    ACME_NEW_ACCOUNT=$(echo "$response" | _egrep_o 'new-reg" *: *"[^"]*"' | cut -d '"' -f 3)
+    if [ -z "$ACME_NEW_ACCOUNT" ]; then
+      ACME_NEW_ACCOUNT=$(echo "$response" | _egrep_o 'new-account" *: *"[^"]*"' | cut -d '"' -f 3)
+    fi
+    export ACME_NEW_ACCOUNT
+
+    ACME_REVOKE_CERT=$(echo "$response" | _egrep_o 'revoke-cert" *: *"[^"]*"' | cut -d '"' -f 3)
+    export ACME_REVOKE_CERT
+
+    ACME_NEW_NONCE=$(echo "$response" | _egrep_o 'new-nonce" *: *"[^"]*"' | cut -d '"' -f 3)
+    export ACME_NEW_NONCE
+
+  fi
+
+  _debug "ACME_KEY_CHANGE" "$ACME_KEY_CHANGE"
+  _debug "ACME_NEW_AUTHZ" "$ACME_NEW_AUTHZ"
+  _debug "ACME_NEW_ORDER" "$ACME_NEW_ORDER"
+  _debug "ACME_NEW_ACCOUNT" "$ACME_NEW_ACCOUNT"
+  _debug "ACME_REVOKE_CERT" "$ACME_REVOKE_CERT"
+}
+
 #[domain]  [keylength]
 _initpath() {
 
@@ -2175,17 +2257,19 @@ _initpath() {
     CA_HOME="$DEFAULT_CA_HOME"
   fi
 
-  if [ -z "$API" ]; then
+  if [ -z "$ACME_DIRECTORY" ]; then
     if [ -z "$STAGE" ]; then
-      API="$DEFAULT_CA"
+      ACME_DIRECTORY="$DEFAULT_CA"
     else
-      API="$STAGE_CA"
-      _info "Using stage api:$API"
+      ACME_DIRECTORY="$STAGE_CA"
+      _info "Using stage ACME_DIRECTORY: $ACME_DIRECTORY"
     fi
   fi
 
-  _API_HOST="$(echo "$API" | cut -d : -f 2 | tr -d '/')"
-  CA_DIR="$CA_HOME/$_API_HOST"
+  _ACME_SERVER_HOST="$(echo "$ACME_DIRECTORY" | cut -d : -f 2 | tr -s / | cut -d / -f 2)"
+  _debug2 "_ACME_SERVER_HOST" "$_ACME_SERVER_HOST"
+
+  CA_DIR="$CA_HOME/$_ACME_SERVER_HOST"
 
   _DEFAULT_CA_CONF="$CA_DIR/ca.conf"
 
@@ -2572,7 +2656,7 @@ location ~ \"^/\.well-known/acme-challenge/([-_a-zA-Z0-9]+)\$\" {
     _err "write nginx conf error, but don't worry, the file is restored."
     return 1
   fi
-
+  _debug3 "Modified config:$(cat $FOUND_REAL_NGINX_CONF)"
   _info "nginx conf is done, let's check it again."
   if ! _exec "nginx -t" >/dev/null; then
     _exec_err
@@ -2658,12 +2742,14 @@ _isRealNginxConf() {
 
         _debug "_seg_n" "$_seg_n"
 
-        if [ "$(echo "$_seg_n" | _egrep_o "^ *ssl  *on *;")" ]; then
+        if [ "$(echo "$_seg_n" | _egrep_o "^ *ssl  *on *;")" ] \
+          || [ "$(echo "$_seg_n" | _egrep_o "listen .* ssl[ |;]")" ]; then
           _debug "ssl on, skip"
-          return 1
+        else
+          FOUND_REAL_NGINX_CONF_LN=$_fln
+          _debug3 "found FOUND_REAL_NGINX_CONF_LN" "$FOUND_REAL_NGINX_CONF_LN"
+          return 0
         fi
-        FOUND_REAL_NGINX_CONF_LN=$_fln
-        return 0
       fi
     done
   fi
@@ -2714,7 +2800,7 @@ _clearup() {
 _clearupdns() {
   _debug "_clearupdns"
   if [ "$dnsadded" != 1 ] || [ -z "$vlist" ]; then
-    _debug "Dns not added, skip."
+    _debug "skip dns."
     return
   fi
 
@@ -3004,7 +3090,7 @@ _regAccount() {
   if ! _calcjwk "$ACCOUNT_KEY_PATH"; then
     return 1
   fi
-
+  _initAPI
   _updateTos=""
   _reg_res="new-reg"
   while true; do
@@ -3019,7 +3105,7 @@ _regAccount() {
     if [ -z "$_updateTos" ]; then
       _info "Registering account"
 
-      if ! _send_signed_request "$API/acme/new-reg" "$regjson"; then
+      if ! _send_signed_request "${ACME_NEW_ACCOUNT}" "$regjson"; then
         _err "Register account Error: $response"
         return 1
       fi
@@ -3105,12 +3191,12 @@ _findHook() {
 __get_domain_new_authz() {
   _gdnd="$1"
   _info "Getting new-authz for domain" "$_gdnd"
-
+  _initAPI
   _Max_new_authz_retry_times=5
   _authz_i=0
   while [ "$_authz_i" -lt "$_Max_new_authz_retry_times" ]; do
     _debug "Try new-authz for the $_authz_i time."
-    if ! _send_signed_request "$API/acme/new-authz" "{\"resource\": \"new-authz\", \"identifier\": {\"type\": \"dns\", \"value\": \"$(_idn "$_gdnd")\"}}"; then
+    if ! _send_signed_request "${ACME_NEW_AUTHZ}" "{\"resource\": \"new-authz\", \"identifier\": {\"type\": \"dns\", \"value\": \"$(_idn "$_gdnd")\"}}"; then
       _err "Can not get domain new authz."
       return 1
     fi
@@ -3188,13 +3274,16 @@ issue() {
   if [ "$_web_roots" = "dns-cx" ]; then
     _web_roots="dns_cx"
   fi
-  _debug "Using api: $API"
 
   if [ ! "$IS_RENEW" ]; then
     _initpath "$_main_domain" "$_key_length"
     mkdir -p "$DOMAIN_PATH"
   fi
 
+  _debug "Using ACME_DIRECTORY: $ACME_DIRECTORY"
+
+  _initAPI
+
   if [ -f "$DOMAIN_CONF" ]; then
     Le_NextRenewTime=$(_readdomainconf Le_NextRenewTime)
     _debug Le_NextRenewTime "$Le_NextRenewTime"
@@ -3228,7 +3317,7 @@ issue() {
     _cleardomainconf "Le_LocalAddress"
   fi
 
-  Le_API="$API"
+  Le_API="$ACME_DIRECTORY"
   _savedomainconf "Le_API" "$Le_API"
 
   if [ "$_alt_domains" = "$NO_VALUE" ]; then
@@ -3667,7 +3756,7 @@ issue() {
   _info "Verify finished, start to sign."
   der="$(_getfile "${CSR_PATH}" "${BEGIN_CSR}" "${END_CSR}" | tr -d "\r\n" | _url_replace)"
 
-  if ! _send_signed_request "$API/acme/new-cert" "{\"resource\": \"new-cert\", \"csr\": \"$der\"}" "needbase64"; then
+  if ! _send_signed_request "${ACME_NEW_ORDER}" "{\"resource\": \"new-cert\", \"csr\": \"$der\"}" "needbase64"; then
     _err "Sign failed."
     _on_issue_err "$_post_hook"
     return 1
@@ -3720,7 +3809,8 @@ issue() {
 
   Le_LinkIssuer=$(grep -i '^Link' "$HTTP_HEADER" | _head_n 1 | cut -d " " -f 2 | cut -d ';' -f 1 | tr -d '<>')
   if ! _contains "$Le_LinkIssuer" ":"; then
-    Le_LinkIssuer="$API$Le_LinkIssuer"
+    _info "$(__red "Relative issuer link found.")"
+    Le_LinkIssuer="$_ACME_SERVER_HOST$Le_LinkIssuer"
   fi
   _debug Le_LinkIssuer "$Le_LinkIssuer"
   _savedomainconf "Le_LinkIssuer" "$Le_LinkIssuer"
@@ -3836,7 +3926,15 @@ renew() {
   . "$DOMAIN_CONF"
 
   if [ "$Le_API" ]; then
-    API="$Le_API"
+    if [ "$_OLD_CA_HOST" = "$Le_API" ]; then
+      export Le_API="$DEFAULT_CA"
+      _savedomainconf Le_API "$Le_API"
+    fi
+    if [ "$_OLD_STAGE_CA_HOST" = "$Le_API" ]; then
+      export Le_API="$STAGE_CA"
+      _savedomainconf Le_API "$Le_API"
+    fi
+    export ACME_DIRECTORY="$Le_API"
     #reload ca configs
     ACCOUNT_KEY_PATH=""
     ACCOUNT_JSON_PATH=""
@@ -3924,6 +4022,10 @@ signcsr() {
     return 1
   fi
   _debug _csrsubj "$_csrsubj"
+  if _contains "$_csrsubj" ' ' || ! _contains "$_csrsubj" '.'; then
+    _info "It seems that the subject: $_csrsubj is not a valid domain name. Drop it."
+    _csrsubj=""
+  fi
 
   _csrdomainlist=$(_readSubjectAltNamesFromCSR "$_csrfile")
   if [ "$?" != "0" ]; then
@@ -4299,8 +4401,10 @@ revoke() {
     return 1
   fi
 
+  _initAPI
+
   data="{\"resource\": \"revoke-cert\", \"certificate\": \"$cert\"}"
-  uri="$API/acme/revoke-cert"
+  uri="${ACME_REVOKE_CERT}"
 
   if [ -f "$CERT_KEY_PATH" ]; then
     _info "Try domain key first."
@@ -4432,6 +4536,7 @@ deactivate() {
   _d_domain_list="$1"
   _d_type="$2"
   _initpath
+  _initAPI
   _debug _d_domain_list "$_d_domain_list"
   if [ -z "$(echo $_d_domain_list | cut -d , -f 1)" ]; then
     _usage "Usage: $PROJECT_ENTRY --deactivate -d domain.com [-d domain.com]"
@@ -4631,6 +4736,11 @@ install() {
     return 1
   fi
 
+  if [ -z "$_c_home" ] && [ "$LE_CONFIG_HOME" != "$LE_WORKING_DIR" ]; then
+    _info "Using config home: $LE_CONFIG_HOME"
+    _c_home="$LE_CONFIG_HOME"
+  fi
+
   #convert from le
   if [ -d "$HOME/.le" ]; then
     for envfile in "le.env" "le.sh.env"; do
@@ -4854,6 +4964,7 @@ Parameters:
 
   --reloadcmd \"service nginx reload\" After issue/renew, it's used to reload the server.
 
+  --server SERVER                   ACME Directory Resource URI. (default: https://acme-v01.api.letsencrypt.org/directory)
   --accountconf                     Specifies a customized account config file.
   --home                            Specifies the home dir for $PROJECT_NAME .
   --cert-home                       Specifies the home dir to save all the certs, only valid for '--install' command.
@@ -4871,6 +4982,7 @@ Parameters:
   --ca-bundle                       Specifies the path to the CA certificate bundle to verify api server's certificate.
   --ca-path                         Specifies directory containing CA certificates in PEM format, used by wget or curl.
   --nocron                          Only valid for '--install' command, which means: do not install the default cron job. In this case, the certs will not be renewed automatically.
+  --no-color                        Do not output color text.
   --ecc                             Specifies to use the ECC cert. Valid for '--install-cert', '--renew', '--revoke', '--toPkcs' and '--createCSR'
   --csr                             Specifies the input csr.
   --pre-hook                        Command to be run before obtaining any certificates.
@@ -5013,6 +5125,7 @@ _process() {
   _openssl_bin=""
   _syslog=""
   _use_wget=""
+  _server=""
   while [ ${#} -gt 0 ]; do
     case "${1}" in
 
@@ -5129,6 +5242,12 @@ _process() {
       --staging | --test)
         STAGE="1"
         ;;
+      --server)
+        ACME_DIRECTORY="$2"
+        _server="$ACME_DIRECTORY"
+        export ACME_DIRECTORY
+        shift
+        ;;
       --debug)
         if [ -z "$2" ] || _startswith "$2" "-"; then
           DEBUG="$DEBUG_LEVEL_DEFAULT"
@@ -5318,6 +5437,9 @@ _process() {
       --nocron)
         _nocron="1"
         ;;
+      --no-color)
+        export ACME_NO_COLOR=1
+        ;;
       --ecc)
         _ecc="isEcc"
         ;;
@@ -5449,6 +5571,9 @@ _process() {
 
   if [ "$DEBUG" ]; then
     version
+    if [ "$_server" ]; then
+      _debug "Using server: $_server"
+    fi
   fi
 
   case "${_CMD}" in

+ 1 - 1
dnsapi/README.md

@@ -140,7 +140,7 @@ Finally, make the DNS server and update Key available to `acme.sh`
 
 ```
 export NSUPDATE_SERVER="dns.example.com"
-export NSUPDATE_KEY="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=="
+export NSUPDATE_KEY="/path/to/your/nsupdate.key"
 ```
 
 Ok, let's issue a cert now:

+ 22 - 10
dnsapi/dns_dynu.sh

@@ -122,18 +122,30 @@ dns_dynu_rm() {
 # _domain_name=domain.com
 _get_root() {
   domain=$1
-  if ! _dynu_rest GET "dns/getroot/$domain"; then
-    return 1
-  fi
+  i=2
+  p=1
+  while true; do
+    h=$(printf "%s" "$domain" | cut -d . -f $i-100)
+    _debug h "$h"
+    if [ -z "$h" ]; then
+      #not valid
+      return 1
+    fi
 
-  if ! _contains "$response" "domain_name"; then
-    _debug "Domain name not found."
-    return 1
-  fi
+    if ! _dynu_rest GET "dns/get/$h"; then
+      return 1
+    fi
+
+    if _contains "$response" "\"name\":\"$h\"" >/dev/null; then
+      _domain_name=$h
+      _node=$(printf "%s" "$domain" | cut -d . -f 1-$p)
+      return 0
+    fi
+    p=$i
+    i=$(_math "$i" + 1)
+  done
+  return 1
 
-  _domain_name=$(printf "%s" "$response" | tr -d "{}" | cut -d , -f 1 | cut -d : -f 2 | cut -d '"' -f 2)
-  _node=$(printf "%s" "$response" | tr -d "{}" | cut -d , -f 3 | cut -d : -f 2 | cut -d '"' -f 2)
-  return 0
 }
 
 _get_recordid() {

+ 13 - 8
dnsapi/dns_infoblox.sh

@@ -9,7 +9,7 @@ dns_infoblox_add() {
   ## Nothing to see here, just some housekeeping
   fulldomain=$1
   txtvalue=$2
-  baseurlnObject="https://$Infoblox_Server/wapi/v2.2.2/record:txt?name=$fulldomain&text=$txtvalue"
+  baseurlnObject="https://$Infoblox_Server/wapi/v2.2.2/record:txt?name=$fulldomain&text=$txtvalue&view=$Infoblox_View"
 
   _info "Using Infoblox API"
   _debug fulldomain "$fulldomain"
@@ -19,14 +19,19 @@ dns_infoblox_add() {
   if [ -z "$Infoblox_Creds" ] || [ -z "$Infoblox_Server" ]; then
     Infoblox_Creds=""
     Infoblox_Server=""
-    _err "You didn't specify the credentials or server yet (Infoblox_Creds and Infoblox_Server)."
-    _err "Please set them via EXPORT ([username:password] and [ip or hostname]) and try again."
+    _err "You didn't specify the credentials, server or infoblox view yet (Infoblox_Creds, Infoblox_Server and Infoblox_View)."
+    _err "Please set them via EXPORT ([username:password], [ip or hostname]) and try again."
     return 1
   fi
 
+  if [ -z "$Infoblox_View" ]; then
+    Infoblox_View="default"
+  fi
+
   ## Save the credentials to the account file
   _saveaccountconf Infoblox_Creds "$Infoblox_Creds"
   _saveaccountconf Infoblox_Server "$Infoblox_Server"
+  _saveaccountconf Infoblox_View "$Infoblox_View"
 
   ## Base64 encode the credentials
   Infoblox_CredsEncoded=$(printf "%b" "$Infoblox_Creds" | _base64)
@@ -39,7 +44,7 @@ dns_infoblox_add() {
   result=$(_post "" "$baseurlnObject" "" "POST")
 
   ## Let's see if we get something intelligible back from the unit
-  if echo "$result" | egrep 'record:txt/.*:.*/default'; then
+  if echo "$result" | egrep "record:txt/.*:.*/$Infoblox_View"; then
     _info "Successfully created the txt record"
     return 0
   else
@@ -68,18 +73,18 @@ dns_infoblox_rm() {
   export _H2="Authorization: Basic $Infoblox_CredsEncoded"
 
   ## Does the record exist?  Let's check.
-  baseurlnObject="https://$Infoblox_Server/wapi/v2.2.2/record:txt?name=$fulldomain&text=$txtvalue&_return_type=xml-pretty"
+  baseurlnObject="https://$Infoblox_Server/wapi/v2.2.2/record:txt?name=$fulldomain&text=$txtvalue&view=$Infoblox_View&_return_type=xml-pretty"
   result=$(_get "$baseurlnObject")
 
   ## Let's see if we get something intelligible back from the grid
-  if echo "$result" | egrep 'record:txt/.*:.*/default'; then
+  if echo "$result" | egrep "record:txt/.*:.*/$Infoblox_View"; then
     ## Extract the object reference
-    objRef=$(printf "%b" "$result" | _egrep_o 'record:txt/.*:.*/default')
+    objRef=$(printf "%b" "$result" | _egrep_o "record:txt/.*:.*/$Infoblox_View")
     objRmUrl="https://$Infoblox_Server/wapi/v2.2.2/$objRef"
     ## Delete them! All the stale records!
     rmResult=$(_post "" "$objRmUrl" "" "DELETE")
     ## Let's see if that worked
-    if echo "$rmResult" | egrep 'record:txt/.*:.*/default'; then
+    if echo "$rmResult" | egrep "record:txt/.*:.*/$Infoblox_View"; then
       _info "Successfully deleted $objRef"
       return 0
     else

+ 1 - 1
dnsapi/dns_ovh.sh

@@ -238,7 +238,7 @@ _get_root() {
       return 1
     fi
 
-    if ! _contains "$response" "This service does not exist" >/dev/null; then
+    if ! _contains "$response" "This service does not exist" >/dev/null && ! _contains "$response" "NOT_GRANTED_CALL" >/dev/null; then
       _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
       _domain="$h"
       return 0