Merge branch 'dev' into patch-3
						commit
						90c70fa5bf
					
				| 
						 | 
				
			
			@ -48,5 +48,12 @@ RUN for verb in help \
 | 
			
		|||
    printf -- "%b" "#!/usr/bin/env sh\n/root/.acme.sh/acme.sh --${verb} --config-home /acme.sh \"\$@\"" >/usr/local/bin/--${verb} && chmod +x /usr/local/bin/--${verb} \
 | 
			
		||||
  ; done
 | 
			
		||||
 | 
			
		||||
ENTRYPOINT ["/root/.acme.sh/acme.sh", "--config-home", "/acme.sh"]
 | 
			
		||||
RUN printf "%b" '#!'"/usr/bin/env sh\n \
 | 
			
		||||
if [ \"\$1\" = \"daemon\" ];  then \n \
 | 
			
		||||
 crond; tail -f /dev/null;\n \
 | 
			
		||||
else \n \
 | 
			
		||||
 /root/.acme.sh/acme.sh --config-home /acme.sh \"\$@\"\n \
 | 
			
		||||
fi" >/entry.sh && chmod +x /entry.sh
 | 
			
		||||
 | 
			
		||||
ENTRYPOINT ["/entry.sh"]
 | 
			
		||||
CMD ["--help"]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,7 +9,7 @@
 | 
			
		|||
- DOES NOT require `root/sudoer` access.
 | 
			
		||||
- Docker friendly
 | 
			
		||||
 | 
			
		||||
It's probably the `easiest&smallest&smartest` shell script to automatically issue & renew the free certificates from Let's Encrypt.
 | 
			
		||||
It's probably the `easiest & smartest` shell script to automatically issue & renew the free certificates from Let's Encrypt.
 | 
			
		||||
 | 
			
		||||
Wiki: https://github.com/Neilpang/acme.sh/wiki
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -31,6 +31,7 @@ Twitter: [@neilpangxa](https://twitter.com/neilpangxa)
 | 
			
		|||
- [Centminmod](http://centminmod.com/letsencrypt-acmetool-https.html)
 | 
			
		||||
- [splynx](https://forum.splynx.com/t/free-ssl-cert-for-splynx-lets-encrypt/297)
 | 
			
		||||
- [archlinux](https://aur.archlinux.org/packages/acme.sh-git/)
 | 
			
		||||
- [opnsense.org](https://github.com/opnsense/plugins/tree/master/security/acme-client/src/opnsense/scripts/OPNsense/AcmeClient)
 | 
			
		||||
- [more...](https://github.com/Neilpang/acme.sh/wiki/Blogs-and-tutorials)
 | 
			
		||||
 | 
			
		||||
# Tested OS
 | 
			
		||||
| 
						 | 
				
			
			@ -313,6 +314,7 @@ You don't have to do anything manually!
 | 
			
		|||
1. DigitalOcean API (native)
 | 
			
		||||
1. ClouDNS.net API
 | 
			
		||||
1. Infoblox NIOS API (https://www.infoblox.com/)
 | 
			
		||||
1. VSCALE (https://vscale.io/)
 | 
			
		||||
 | 
			
		||||
**More APIs coming soon...**
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										35
									
								
								acme.sh
								
								
								
								
							
							
						
						
									
										35
									
								
								acme.sh
								
								
								
								
							| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
#!/usr/bin/env sh
 | 
			
		||||
 | 
			
		||||
VER=2.6.8
 | 
			
		||||
VER=2.6.9
 | 
			
		||||
 | 
			
		||||
PROJECT_NAME="acme.sh"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -107,7 +107,7 @@ __green() {
 | 
			
		|||
  if [ "$__INTERACTIVE" ]; then
 | 
			
		||||
    printf '\033[1;31;32m'
 | 
			
		||||
  fi
 | 
			
		||||
  printf -- "$1"
 | 
			
		||||
  printf -- "%b" "$1"
 | 
			
		||||
  if [ "$__INTERACTIVE" ]; then
 | 
			
		||||
    printf '\033[0m'
 | 
			
		||||
  fi
 | 
			
		||||
| 
						 | 
				
			
			@ -117,7 +117,7 @@ __red() {
 | 
			
		|||
  if [ "$__INTERACTIVE" ]; then
 | 
			
		||||
    printf '\033[1;31;40m'
 | 
			
		||||
  fi
 | 
			
		||||
  printf -- "$1"
 | 
			
		||||
  printf -- "%b" "$1"
 | 
			
		||||
  if [ "$__INTERACTIVE" ]; then
 | 
			
		||||
    printf '\033[0m'
 | 
			
		||||
  fi
 | 
			
		||||
| 
						 | 
				
			
			@ -1102,12 +1102,13 @@ _readKeyLengthFromCSR() {
 | 
			
		|||
  fi
 | 
			
		||||
 | 
			
		||||
  _outcsr="$(${ACME_OPENSSL_BIN:-openssl} req -noout -text -in "$_csrfile")"
 | 
			
		||||
  _debug2 _outcsr "$_outcsr"
 | 
			
		||||
  if _contains "$_outcsr" "Public Key Algorithm: id-ecPublicKey"; then
 | 
			
		||||
    _debug "ECC CSR"
 | 
			
		||||
    echo "$_outcsr" | _egrep_o "^ *ASN1 OID:.*" | cut -d ':' -f 2 | tr -d ' '
 | 
			
		||||
    echo "$_outcsr" | tr "\t" " " | _egrep_o "^ *ASN1 OID:.*" | cut -d ':' -f 2 | tr -d ' '
 | 
			
		||||
  else
 | 
			
		||||
    _debug "RSA CSR"
 | 
			
		||||
    echo "$_outcsr" | _egrep_o "(^ *|^RSA )Public.Key:.*" | cut -d '(' -f 2 | cut -d ' ' -f 1
 | 
			
		||||
    echo "$_outcsr" | tr "\t" " " | _egrep_o "(^ *|RSA )Public.Key:.*" | cut -d '(' -f 2 | cut -d ' ' -f 1
 | 
			
		||||
  fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1846,6 +1847,24 @@ _saveaccountconf() {
 | 
			
		|||
  _save_conf "$ACCOUNT_CONF_PATH" "$1" "$2"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#key  value
 | 
			
		||||
_saveaccountconf_mutable() {
 | 
			
		||||
  _save_conf "$ACCOUNT_CONF_PATH" "SAVED_$1" "$2"
 | 
			
		||||
  #remove later
 | 
			
		||||
  _clearaccountconf "$1"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#key
 | 
			
		||||
_readaccountconf() {
 | 
			
		||||
  _read_conf "$ACCOUNT_CONF_PATH" "$1"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#key
 | 
			
		||||
_readaccountconf_mutable() {
 | 
			
		||||
  _rac_key="$1"
 | 
			
		||||
  _readaccountconf "SAVED_$_rac_key"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#_clearaccountconf   key
 | 
			
		||||
_clearaccountconf() {
 | 
			
		||||
  _clear_conf "$ACCOUNT_CONF_PATH" "$1"
 | 
			
		||||
| 
						 | 
				
			
			@ -3120,6 +3139,10 @@ issue() {
 | 
			
		|||
    _usage "Usage: $PROJECT_ENTRY --issue  -d  a.com  -w /path/to/webroot/a.com/ "
 | 
			
		||||
    return 1
 | 
			
		||||
  fi
 | 
			
		||||
  if [ -z "$1" ]; then
 | 
			
		||||
    _usage "Please specify at least one validation method: '--webroot', '--standalone', '--apache', '--nginx' or '--dns' etc."
 | 
			
		||||
    return 1
 | 
			
		||||
  fi
 | 
			
		||||
  _web_roots="$1"
 | 
			
		||||
  _main_domain="$2"
 | 
			
		||||
  _alt_domains="$3"
 | 
			
		||||
| 
						 | 
				
			
			@ -3860,7 +3883,7 @@ renewAll() {
 | 
			
		|||
        return "$rc"
 | 
			
		||||
      else
 | 
			
		||||
        _ret="$rc"
 | 
			
		||||
        _err "Error renew $d, Go ahead to next one."
 | 
			
		||||
        _err "Error renew $d."
 | 
			
		||||
      fi
 | 
			
		||||
    fi
 | 
			
		||||
  done
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -468,6 +468,7 @@ acme.sh --issue --dns dns_dynu -d example.com -d www.example.com
 | 
			
		|||
 | 
			
		||||
The `Dynu_ClientId` and `Dynu_Secret` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Use custom API
 | 
			
		||||
 | 
			
		||||
If your API is not supported yet, you can write your own DNS API.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -88,6 +88,19 @@ _get_root() {
 | 
			
		|||
    while true; do
 | 
			
		||||
      h=$(printf "%s" "$domain" | cut -d . -f $i-100)
 | 
			
		||||
      if [ -z "$h" ]; then
 | 
			
		||||
        if _contains "$response" "<IsTruncated>true</IsTruncated>" && _contains "$response" "<NextMarker>"; then
 | 
			
		||||
          _debug "IsTruncated"
 | 
			
		||||
          _nextMarker="$(echo "$response" | _egrep_o "<NextMarker>.*</NextMarker>" | cut -d '>' -f 2 | cut -d '<' -f 1)"
 | 
			
		||||
          _debug "NextMarker" "$_nextMarker"
 | 
			
		||||
          if aws_rest GET "2013-04-01/hostedzone" "marker=$_nextMarker"; then
 | 
			
		||||
            _debug "Truncated request OK"
 | 
			
		||||
            i=2
 | 
			
		||||
            p=1
 | 
			
		||||
            continue
 | 
			
		||||
          else
 | 
			
		||||
            _err "Truncated request error."
 | 
			
		||||
          fi
 | 
			
		||||
        fi
 | 
			
		||||
        #not valid
 | 
			
		||||
        return 1
 | 
			
		||||
      fi
 | 
			
		||||
| 
						 | 
				
			
			@ -208,6 +221,9 @@ aws_rest() {
 | 
			
		|||
  _debug _H2 "$_H2"
 | 
			
		||||
 | 
			
		||||
  url="$AWS_URL/$ep"
 | 
			
		||||
  if [ "$qsr" ]; then
 | 
			
		||||
    url="$AWS_URL/$ep?$qsr"
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  if [ "$mtd" = "GET" ]; then
 | 
			
		||||
    response="$(_get "$url")"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,6 +14,8 @@ dns_cf_add() {
 | 
			
		|||
  fulldomain=$1
 | 
			
		||||
  txtvalue=$2
 | 
			
		||||
 | 
			
		||||
  CF_Key="${CF_Key:-$(_readaccountconf_mutable CF_Key)}"
 | 
			
		||||
  CF_Email="${CF_Email:-$(_readaccountconf_mutable CF_Email)}"
 | 
			
		||||
  if [ -z "$CF_Key" ] || [ -z "$CF_Email" ]; then
 | 
			
		||||
    CF_Key=""
 | 
			
		||||
    CF_Email=""
 | 
			
		||||
| 
						 | 
				
			
			@ -29,8 +31,8 @@ dns_cf_add() {
 | 
			
		|||
  fi
 | 
			
		||||
 | 
			
		||||
  #save the api key and email to the account conf file.
 | 
			
		||||
  _saveaccountconf CF_Key "$CF_Key"
 | 
			
		||||
  _saveaccountconf CF_Email "$CF_Email"
 | 
			
		||||
  _saveaccountconf_mutable CF_Key "$CF_Key"
 | 
			
		||||
  _saveaccountconf_mutable CF_Email "$CF_Email"
 | 
			
		||||
 | 
			
		||||
  _debug "First detect the root zone"
 | 
			
		||||
  if ! _get_root "$fulldomain"; then
 | 
			
		||||
| 
						 | 
				
			
			@ -83,6 +85,17 @@ dns_cf_add() {
 | 
			
		|||
dns_cf_rm() {
 | 
			
		||||
  fulldomain=$1
 | 
			
		||||
  txtvalue=$2
 | 
			
		||||
 | 
			
		||||
  CF_Key="${CF_Key:-$(_readaccountconf_mutable CF_Key)}"
 | 
			
		||||
  CF_Email="${CF_Email:-$(_readaccountconf_mutable CF_Email)}"
 | 
			
		||||
  if [ -z "$CF_Key" ] || [ -z "$CF_Email" ]; then
 | 
			
		||||
    CF_Key=""
 | 
			
		||||
    CF_Email=""
 | 
			
		||||
    _err "You don't specify cloudflare api key and email yet."
 | 
			
		||||
    _err "Please create you key and try again."
 | 
			
		||||
    return 1
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  _debug "First detect the root zone"
 | 
			
		||||
  if ! _get_root "$fulldomain"; then
 | 
			
		||||
    _err "invalid domain"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,216 @@
 | 
			
		|||
#!/usr/bin/env sh
 | 
			
		||||
 | 
			
		||||
#Client ID
 | 
			
		||||
#Dynu_ClientId="0b71cae7-a099-4f6b-8ddf-94571cdb760d"
 | 
			
		||||
#
 | 
			
		||||
#Secret
 | 
			
		||||
#Dynu_Secret="aCUEY4BDCV45KI8CSIC3sp2LKQ9"
 | 
			
		||||
#
 | 
			
		||||
#Token
 | 
			
		||||
Dynu_Token=""
 | 
			
		||||
#
 | 
			
		||||
#Endpoint
 | 
			
		||||
Dynu_EndPoint="https://api.dynu.com/v1"
 | 
			
		||||
#
 | 
			
		||||
#Author: Dynu Systems, Inc.
 | 
			
		||||
#Report Bugs here: https://github.com/shar0119/acme.sh
 | 
			
		||||
#
 | 
			
		||||
########  Public functions #####################
 | 
			
		||||
 | 
			
		||||
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
 | 
			
		||||
dns_dynu_add() {
 | 
			
		||||
  fulldomain=$1
 | 
			
		||||
  txtvalue=$2
 | 
			
		||||
 | 
			
		||||
  if [ -z "$Dynu_ClientId" ] || [ -z "$Dynu_Secret" ]; then
 | 
			
		||||
    Dynu_ClientId=""
 | 
			
		||||
    Dynu_Secret=""
 | 
			
		||||
    _err "Dynu client id and secret is not specified."
 | 
			
		||||
    _err "Please create you API client id and secret and try again."
 | 
			
		||||
    return 1
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  #save the client id and secret to the account conf file.
 | 
			
		||||
  _saveaccountconf Dynu_ClientId "$Dynu_ClientId"
 | 
			
		||||
  _saveaccountconf Dynu_Secret "$Dynu_Secret"
 | 
			
		||||
 | 
			
		||||
  if [ -z "$Dynu_Token" ]; then
 | 
			
		||||
    _info "Getting Dynu token."
 | 
			
		||||
    if ! _dynu_authentication; then
 | 
			
		||||
      _err "Can not get token."
 | 
			
		||||
    fi
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  _debug "Detect root zone"
 | 
			
		||||
  if ! _get_root "$fulldomain"; then
 | 
			
		||||
    _err "Invalid domain."
 | 
			
		||||
    return 1
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  _debug _node "$_node"
 | 
			
		||||
  _debug _domain_name "$_domain_name"
 | 
			
		||||
 | 
			
		||||
  _info "Creating TXT record."
 | 
			
		||||
  if ! _dynu_rest POST "dns/record/add" "{\"domain_name\":\"$_domain_name\",\"node_name\":\"$_node\",\"record_type\":\"TXT\",\"text_data\":\"$txtvalue\",\"state\":true,\"ttl\":90}"; then
 | 
			
		||||
    return 1
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  if ! _contains "$response" "text_data"; then
 | 
			
		||||
    _err "Could not add TXT record."
 | 
			
		||||
    return 1
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  return 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#Usage: rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
 | 
			
		||||
dns_dynu_rm() {
 | 
			
		||||
  fulldomain=$1
 | 
			
		||||
  txtvalue=$2
 | 
			
		||||
 | 
			
		||||
  if [ -z "$Dynu_ClientId" ] || [ -z "$Dynu_Secret" ]; then
 | 
			
		||||
    Dynu_ClientId=""
 | 
			
		||||
    Dynu_Secret=""
 | 
			
		||||
    _err "Dynu client id and secret is not specified."
 | 
			
		||||
    _err "Please create you API client id and secret and try again."
 | 
			
		||||
    return 1
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  #save the client id and secret to the account conf file.
 | 
			
		||||
  _saveaccountconf Dynu_ClientId "$Dynu_ClientId"
 | 
			
		||||
  _saveaccountconf Dynu_Secret "$Dynu_Secret"
 | 
			
		||||
 | 
			
		||||
  if [ -z "$Dynu_Token" ]; then
 | 
			
		||||
    _info "Getting Dynu token."
 | 
			
		||||
    if ! _dynu_authentication; then
 | 
			
		||||
      _err "Can not get token."
 | 
			
		||||
    fi
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  _debug "Detect root zone."
 | 
			
		||||
  if ! _get_root "$fulldomain"; then
 | 
			
		||||
    _err "Invalid domain."
 | 
			
		||||
    return 1
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  _debug _node "$_node"
 | 
			
		||||
  _debug _domain_name "$_domain_name"
 | 
			
		||||
 | 
			
		||||
  _info "Checking for TXT record."
 | 
			
		||||
  if ! _get_recordid "$fulldomain" "$txtvalue"; then
 | 
			
		||||
    _err "Could not get TXT record id."
 | 
			
		||||
    return 1
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  if [ "$_dns_record_id" = "" ]; then
 | 
			
		||||
    _err "TXT record not found."
 | 
			
		||||
    return 1
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  _info "Removing TXT record."
 | 
			
		||||
  if ! _delete_txt_record "$_dns_record_id"; then
 | 
			
		||||
    _err "Could not remove TXT record $_dns_record_id."
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  return 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
########  Private functions below ##################################
 | 
			
		||||
#_acme-challenge.www.domain.com
 | 
			
		||||
#returns
 | 
			
		||||
# _node=_acme-challenge.www
 | 
			
		||||
# _domain_name=domain.com
 | 
			
		||||
_get_root() {
 | 
			
		||||
  domain=$1
 | 
			
		||||
  if ! _dynu_rest GET "dns/getroot/$domain"; then
 | 
			
		||||
    return 1
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  if ! _contains "$response" "domain_name"; then
 | 
			
		||||
    _debug "Domain name not found."
 | 
			
		||||
    return 1
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  _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() {
 | 
			
		||||
  fulldomain=$1
 | 
			
		||||
  txtvalue=$2
 | 
			
		||||
 | 
			
		||||
  if ! _dynu_rest GET "dns/record/get?hostname=$fulldomain&rrtype=TXT"; then
 | 
			
		||||
    return 1
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  if ! _contains "$response" "$txtvalue"; then
 | 
			
		||||
    _dns_record_id=0
 | 
			
		||||
    return 0
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  _dns_record_id=$(printf "%s" "$response" | _egrep_o "{[^}]*}" | grep "\"text_data\":\"$txtvalue\"" | grep -Po '"id":\K[0-9]+')
 | 
			
		||||
 | 
			
		||||
  return 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
_delete_txt_record() {
 | 
			
		||||
  _dns_record_id=$1
 | 
			
		||||
 | 
			
		||||
  if ! _dynu_rest GET "dns/record/delete/$_dns_record_id"; then
 | 
			
		||||
    return 1
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  if ! _contains "$response" "true"; then
 | 
			
		||||
    return 1
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  return 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
_dynu_rest() {
 | 
			
		||||
  m=$1
 | 
			
		||||
  ep="$2"
 | 
			
		||||
  data="$3"
 | 
			
		||||
  _debug "$ep"
 | 
			
		||||
 | 
			
		||||
  export _H1="Authorization: Bearer $Dynu_Token"
 | 
			
		||||
  export _H2="Content-Type: application/json"
 | 
			
		||||
 | 
			
		||||
  if [ "$data" ]; then
 | 
			
		||||
    _debug data "$data"
 | 
			
		||||
    response="$(_post "$data" "$Dynu_EndPoint/$ep" "" "$m")"
 | 
			
		||||
  else
 | 
			
		||||
    _info "Getting $Dynu_EndPoint/$ep"
 | 
			
		||||
    response="$(_get "$Dynu_EndPoint/$ep")"
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  if [ "$?" != "0" ]; then
 | 
			
		||||
    _err "error $ep"
 | 
			
		||||
    return 1
 | 
			
		||||
  fi
 | 
			
		||||
  _debug2 response "$response"
 | 
			
		||||
  return 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
_dynu_authentication() {
 | 
			
		||||
  realm="$(printf "%s" "$Dynu_ClientId:$Dynu_Secret" | _base64)"
 | 
			
		||||
 | 
			
		||||
  export _H1="Authorization: Basic $realm"
 | 
			
		||||
  export _H2="Content-Type: application/json"
 | 
			
		||||
 | 
			
		||||
  response="$(_get "$Dynu_EndPoint/oauth2/token")"
 | 
			
		||||
  if [ "$?" != "0" ]; then
 | 
			
		||||
    _err "Authentication failed."
 | 
			
		||||
    return 1
 | 
			
		||||
  fi
 | 
			
		||||
  if _contains "$response" "accessToken"; then
 | 
			
		||||
    Dynu_Token=$(printf "%s" "$response" | tr -d "[]" | cut -d , -f 2 | cut -d : -f 2 | cut -d '"' -f 2)
 | 
			
		||||
  fi
 | 
			
		||||
  if _contains "$Dynu_Token" "null"; then
 | 
			
		||||
    Dynu_Token=""
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  _debug2 response "$response"
 | 
			
		||||
  return 0
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,149 @@
 | 
			
		|||
#!/usr/bin/env sh
 | 
			
		||||
 | 
			
		||||
#This is the vscale.io api wrapper for acme.sh
 | 
			
		||||
#
 | 
			
		||||
#Author: Alex Loban
 | 
			
		||||
#Report Bugs here: https://github.com/LAV45/acme.sh
 | 
			
		||||
 | 
			
		||||
#VSCALE_API_KEY="sdfsdfsdfljlbjkljlkjsdfoiwje"
 | 
			
		||||
VSCALE_API_URL="https://api.vscale.io/v1"
 | 
			
		||||
 | 
			
		||||
########  Public functions #####################
 | 
			
		||||
 | 
			
		||||
#Usage: dns_myapi_add   _acme-challenge.www.domain.com   "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
 | 
			
		||||
dns_vscale_add() {
 | 
			
		||||
  fulldomain=$1
 | 
			
		||||
  txtvalue=$2
 | 
			
		||||
 | 
			
		||||
  if [ -z "$VSCALE_API_KEY" ]; then
 | 
			
		||||
    VSCALE_API_KEY=""
 | 
			
		||||
    _err "You didn't specify the VSCALE api key yet."
 | 
			
		||||
    _err "Please create you key and try again."
 | 
			
		||||
    return 1
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  _saveaccountconf VSCALE_API_KEY "$VSCALE_API_KEY"
 | 
			
		||||
 | 
			
		||||
  _debug "First detect the root zone"
 | 
			
		||||
  if ! _get_root "$fulldomain"; then
 | 
			
		||||
    _err "invalid domain"
 | 
			
		||||
    return 1
 | 
			
		||||
  fi
 | 
			
		||||
  _debug _domain_id "$_domain_id"
 | 
			
		||||
  _debug _sub_domain "$_sub_domain"
 | 
			
		||||
  _debug _domain "$_domain"
 | 
			
		||||
 | 
			
		||||
  _vscale_tmpl_json="{\"type\":\"TXT\",\"name\":\"$_sub_domain.$_domain\",\"content\":\"$txtvalue\"}"
 | 
			
		||||
 | 
			
		||||
  if _vscale_rest POST "domains/$_domain_id/records/" "$_vscale_tmpl_json"; then
 | 
			
		||||
    response=$(printf "%s\n" "$response" | _egrep_o "{\"error\": \".+\"" | cut -d : -f 2)
 | 
			
		||||
    if [ -z "$response" ]; then
 | 
			
		||||
      _info "txt record updated success."
 | 
			
		||||
      return 0
 | 
			
		||||
    fi
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  return 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#fulldomain txtvalue
 | 
			
		||||
dns_vscale_rm() {
 | 
			
		||||
  fulldomain=$1
 | 
			
		||||
  txtvalue=$2
 | 
			
		||||
 | 
			
		||||
  _debug "First detect the root zone"
 | 
			
		||||
  if ! _get_root "$fulldomain"; then
 | 
			
		||||
    _err "invalid domain"
 | 
			
		||||
    return 1
 | 
			
		||||
  fi
 | 
			
		||||
  _debug _domain_id "$_domain_id"
 | 
			
		||||
  _debug _sub_domain "$_sub_domain"
 | 
			
		||||
  _debug _domain "$_domain"
 | 
			
		||||
 | 
			
		||||
  _debug "Getting txt records"
 | 
			
		||||
  _vscale_rest GET "domains/$_domain_id/records/"
 | 
			
		||||
 | 
			
		||||
  if [ -n "$response" ]; then
 | 
			
		||||
    record_id=$(printf "%s\n" "$response" | _egrep_o "\"TXT\", \"id\": [0-9]+, \"name\": \"$_sub_domain.$_domain\"" | cut -d : -f 2 | tr -d ", \"name\"")
 | 
			
		||||
    _debug record_id "$record_id"
 | 
			
		||||
    if [ -z "$record_id" ]; then
 | 
			
		||||
      _err "Can not get record id to remove."
 | 
			
		||||
      return 1
 | 
			
		||||
    fi
 | 
			
		||||
    if _vscale_rest DELETE "domains/$_domain_id/records/$record_id" && [ -z "$response" ]; then
 | 
			
		||||
      _info "txt record deleted success."
 | 
			
		||||
      return 0
 | 
			
		||||
    fi
 | 
			
		||||
    _debug response "$response"
 | 
			
		||||
    return 1
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  return 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
####################  Private functions below ##################################
 | 
			
		||||
#_acme-challenge.www.domain.com
 | 
			
		||||
#returns
 | 
			
		||||
# _sub_domain=_acme-challenge.www
 | 
			
		||||
# _domain=domain.com
 | 
			
		||||
# _domain_id=12345
 | 
			
		||||
_get_root() {
 | 
			
		||||
  domain=$1
 | 
			
		||||
  i=2
 | 
			
		||||
  p=1
 | 
			
		||||
 | 
			
		||||
  if _vscale_rest GET "domains/"; then
 | 
			
		||||
    response="$(echo "$response" | tr -d "\n" | sed 's/{/\n&/g')"
 | 
			
		||||
    while true; do
 | 
			
		||||
      h=$(printf "%s" "$domain" | cut -d . -f $i-100)
 | 
			
		||||
      _debug h "$h"
 | 
			
		||||
      if [ -z "$h" ]; then
 | 
			
		||||
        #not valid
 | 
			
		||||
        return 1
 | 
			
		||||
      fi
 | 
			
		||||
 | 
			
		||||
      hostedzone="$(echo "$response" | _egrep_o "{.*\"name\":\s*\"$h\".*}")"
 | 
			
		||||
      if [ "$hostedzone" ]; then
 | 
			
		||||
        _domain_id=$(printf "%s\n" "$hostedzone" | _egrep_o "\"id\":\s*[0-9]+" | _head_n 1 | cut -d : -f 2 | tr -d \ )
 | 
			
		||||
        if [ "$_domain_id" ]; then
 | 
			
		||||
          _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
 | 
			
		||||
          _domain=$h
 | 
			
		||||
          return 0
 | 
			
		||||
        fi
 | 
			
		||||
        return 1
 | 
			
		||||
      fi
 | 
			
		||||
      p=$i
 | 
			
		||||
      i=$(_math "$i" + 1)
 | 
			
		||||
    done
 | 
			
		||||
  fi
 | 
			
		||||
  return 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#method uri qstr data
 | 
			
		||||
_vscale_rest() {
 | 
			
		||||
  mtd="$1"
 | 
			
		||||
  ep="$2"
 | 
			
		||||
  data="$3"
 | 
			
		||||
 | 
			
		||||
  _debug mtd "$mtd"
 | 
			
		||||
  _debug ep "$ep"
 | 
			
		||||
 | 
			
		||||
  export _H1="Accept: application/json"
 | 
			
		||||
  export _H2="Content-Type: application/json"
 | 
			
		||||
  export _H3="X-Token: ${VSCALE_API_KEY}"
 | 
			
		||||
 | 
			
		||||
  if [ "$mtd" != "GET" ]; then
 | 
			
		||||
    # both POST and DELETE.
 | 
			
		||||
    _debug data "$data"
 | 
			
		||||
    response="$(_post "$data" "$VSCALE_API_URL/$ep" "" "$mtd")"
 | 
			
		||||
  else
 | 
			
		||||
    response="$(_get "$VSCALE_API_URL/$ep")"
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  if [ "$?" != "0" ]; then
 | 
			
		||||
    _err "error $ep"
 | 
			
		||||
    return 1
 | 
			
		||||
  fi
 | 
			
		||||
  _debug2 response "$response"
 | 
			
		||||
  return 0
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue