Merge branch 'dev' of https://github.com/Neilpang/acme.sh into dev
						commit
						67e3dd36b3
					
				| 
						 | 
				
			
			@ -13,6 +13,9 @@ It's probably the `easiest&smallest&smartest` shell script to automatically issu
 | 
			
		|||
Wiki: https://github.com/Neilpang/acme.sh/wiki
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Twitter: [@neilpangxa](https://twitter.com/neilpangxa)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# [中文说明](https://github.com/Neilpang/acme.sh/wiki/%E8%AF%B4%E6%98%8E)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -266,6 +269,7 @@ You don't have to do anything manually!
 | 
			
		|||
1. aliyun.com(阿里云) API
 | 
			
		||||
1. ISPConfig 3.1 API
 | 
			
		||||
1. Alwaysdata.com API
 | 
			
		||||
1. Linode.com API
 | 
			
		||||
 | 
			
		||||
**More APIs coming soon...**
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										268
									
								
								acme.sh
								
								
								
								
							
							
						
						
									
										268
									
								
								acme.sh
								
								
								
								
							| 
						 | 
				
			
			@ -336,15 +336,241 @@ _h2b() {
 | 
			
		|||
  done
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#hex string
 | 
			
		||||
_hex() {
 | 
			
		||||
  _str="$1"
 | 
			
		||||
  _str_len=${#_str}
 | 
			
		||||
  _h_i=1
 | 
			
		||||
  while [ "$_h_i" -le "$_str_len" ]; do
 | 
			
		||||
    _str_c="$(printf "%s" "$_str" | cut -c "$_h_i")"
 | 
			
		||||
    printf "%02x" "'$_str_c"
 | 
			
		||||
    _h_i="$(_math "$_h_i" + 1)"
 | 
			
		||||
_is_solaris() {
 | 
			
		||||
  _contains "${__OS__:=$(uname -a)}" "solaris" || _contains "${__OS__:=$(uname -a)}" "SunOS"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#stdin  output hexstr splited by one space
 | 
			
		||||
#input:"abc"
 | 
			
		||||
#output: " 61 62 63"
 | 
			
		||||
_hex_dump() {
 | 
			
		||||
  od -A n -v -t x1 | tr -d "\r\t" | tr -s " " | sed "s/ $//" | tr -d "\n"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#url encode, no-preserved chars
 | 
			
		||||
#A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  Q  R  S  T  U  V  W  X  Y  Z
 | 
			
		||||
#41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a
 | 
			
		||||
 | 
			
		||||
#a  b  c  d  e  f  g  h  i  j  k  l  m  n  o  p  q  r  s  t  u  v  w  x  y  z
 | 
			
		||||
#61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a
 | 
			
		||||
 | 
			
		||||
#0  1  2  3  4  5  6  7  8  9  -  _  .  ~
 | 
			
		||||
#30 31 32 33 34 35 36 37 38 39 2d 5f 2e 7e
 | 
			
		||||
 | 
			
		||||
#stdin stdout
 | 
			
		||||
_url_encode() {
 | 
			
		||||
  _hex_str=$(_hex_dump)
 | 
			
		||||
  _debug3 "_url_encode"
 | 
			
		||||
  _debug3 "_hex_str" "$_hex_str"
 | 
			
		||||
  for _hex_code in $_hex_str; do
 | 
			
		||||
    #upper case
 | 
			
		||||
    case "${_hex_code}" in
 | 
			
		||||
      "41")
 | 
			
		||||
        printf "%s" "A"
 | 
			
		||||
        ;;
 | 
			
		||||
      "42")
 | 
			
		||||
        printf "%s" "B"
 | 
			
		||||
        ;;
 | 
			
		||||
      "43")
 | 
			
		||||
        printf "%s" "C"
 | 
			
		||||
        ;;
 | 
			
		||||
      "44")
 | 
			
		||||
        printf "%s" "D"
 | 
			
		||||
        ;;
 | 
			
		||||
      "45")
 | 
			
		||||
        printf "%s" "E"
 | 
			
		||||
        ;;
 | 
			
		||||
      "46")
 | 
			
		||||
        printf "%s" "F"
 | 
			
		||||
        ;;
 | 
			
		||||
      "47")
 | 
			
		||||
        printf "%s" "G"
 | 
			
		||||
        ;;
 | 
			
		||||
      "48")
 | 
			
		||||
        printf "%s" "H"
 | 
			
		||||
        ;;
 | 
			
		||||
      "49")
 | 
			
		||||
        printf "%s" "I"
 | 
			
		||||
        ;;
 | 
			
		||||
      "4a")
 | 
			
		||||
        printf "%s" "J"
 | 
			
		||||
        ;;
 | 
			
		||||
      "4b")
 | 
			
		||||
        printf "%s" "K"
 | 
			
		||||
        ;;
 | 
			
		||||
      "4c")
 | 
			
		||||
        printf "%s" "L"
 | 
			
		||||
        ;;
 | 
			
		||||
      "4d")
 | 
			
		||||
        printf "%s" "M"
 | 
			
		||||
        ;;
 | 
			
		||||
      "4e")
 | 
			
		||||
        printf "%s" "N"
 | 
			
		||||
        ;;
 | 
			
		||||
      "4f")
 | 
			
		||||
        printf "%s" "O"
 | 
			
		||||
        ;;
 | 
			
		||||
      "50")
 | 
			
		||||
        printf "%s" "P"
 | 
			
		||||
        ;;
 | 
			
		||||
      "51")
 | 
			
		||||
        printf "%s" "Q"
 | 
			
		||||
        ;;
 | 
			
		||||
      "52")
 | 
			
		||||
        printf "%s" "R"
 | 
			
		||||
        ;;
 | 
			
		||||
      "53")
 | 
			
		||||
        printf "%s" "S"
 | 
			
		||||
        ;;
 | 
			
		||||
      "54")
 | 
			
		||||
        printf "%s" "T"
 | 
			
		||||
        ;;
 | 
			
		||||
      "55")
 | 
			
		||||
        printf "%s" "U"
 | 
			
		||||
        ;;
 | 
			
		||||
      "56")
 | 
			
		||||
        printf "%s" "V"
 | 
			
		||||
        ;;
 | 
			
		||||
      "57")
 | 
			
		||||
        printf "%s" "W"
 | 
			
		||||
        ;;
 | 
			
		||||
      "58")
 | 
			
		||||
        printf "%s" "X"
 | 
			
		||||
        ;;
 | 
			
		||||
      "59")
 | 
			
		||||
        printf "%s" "Y"
 | 
			
		||||
        ;;
 | 
			
		||||
      "5a")
 | 
			
		||||
        printf "%s" "Z"
 | 
			
		||||
        ;;
 | 
			
		||||
 | 
			
		||||
      #lower case
 | 
			
		||||
      "61")
 | 
			
		||||
        printf "%s" "a"
 | 
			
		||||
        ;;
 | 
			
		||||
      "62")
 | 
			
		||||
        printf "%s" "b"
 | 
			
		||||
        ;;
 | 
			
		||||
      "63")
 | 
			
		||||
        printf "%s" "c"
 | 
			
		||||
        ;;
 | 
			
		||||
      "64")
 | 
			
		||||
        printf "%s" "d"
 | 
			
		||||
        ;;
 | 
			
		||||
      "65")
 | 
			
		||||
        printf "%s" "e"
 | 
			
		||||
        ;;
 | 
			
		||||
      "66")
 | 
			
		||||
        printf "%s" "f"
 | 
			
		||||
        ;;
 | 
			
		||||
      "67")
 | 
			
		||||
        printf "%s" "g"
 | 
			
		||||
        ;;
 | 
			
		||||
      "68")
 | 
			
		||||
        printf "%s" "h"
 | 
			
		||||
        ;;
 | 
			
		||||
      "69")
 | 
			
		||||
        printf "%s" "i"
 | 
			
		||||
        ;;
 | 
			
		||||
      "6a")
 | 
			
		||||
        printf "%s" "j"
 | 
			
		||||
        ;;
 | 
			
		||||
      "6b")
 | 
			
		||||
        printf "%s" "k"
 | 
			
		||||
        ;;
 | 
			
		||||
      "6c")
 | 
			
		||||
        printf "%s" "l"
 | 
			
		||||
        ;;
 | 
			
		||||
      "6d")
 | 
			
		||||
        printf "%s" "m"
 | 
			
		||||
        ;;
 | 
			
		||||
      "6e")
 | 
			
		||||
        printf "%s" "n"
 | 
			
		||||
        ;;
 | 
			
		||||
      "6f")
 | 
			
		||||
        printf "%s" "o"
 | 
			
		||||
        ;;
 | 
			
		||||
      "70")
 | 
			
		||||
        printf "%s" "p"
 | 
			
		||||
        ;;
 | 
			
		||||
      "71")
 | 
			
		||||
        printf "%s" "q"
 | 
			
		||||
        ;;
 | 
			
		||||
      "72")
 | 
			
		||||
        printf "%s" "r"
 | 
			
		||||
        ;;
 | 
			
		||||
      "73")
 | 
			
		||||
        printf "%s" "s"
 | 
			
		||||
        ;;
 | 
			
		||||
      "74")
 | 
			
		||||
        printf "%s" "t"
 | 
			
		||||
        ;;
 | 
			
		||||
      "75")
 | 
			
		||||
        printf "%s" "u"
 | 
			
		||||
        ;;
 | 
			
		||||
      "76")
 | 
			
		||||
        printf "%s" "v"
 | 
			
		||||
        ;;
 | 
			
		||||
      "77")
 | 
			
		||||
        printf "%s" "w"
 | 
			
		||||
        ;;
 | 
			
		||||
      "78")
 | 
			
		||||
        printf "%s" "x"
 | 
			
		||||
        ;;
 | 
			
		||||
      "79")
 | 
			
		||||
        printf "%s" "y"
 | 
			
		||||
        ;;
 | 
			
		||||
      "7a")
 | 
			
		||||
        printf "%s" "z"
 | 
			
		||||
        ;;
 | 
			
		||||
      #numbers
 | 
			
		||||
      "30")
 | 
			
		||||
        printf "%s" "0"
 | 
			
		||||
        ;;
 | 
			
		||||
      "31")
 | 
			
		||||
        printf "%s" "1"
 | 
			
		||||
        ;;
 | 
			
		||||
      "32")
 | 
			
		||||
        printf "%s" "2"
 | 
			
		||||
        ;;
 | 
			
		||||
      "33")
 | 
			
		||||
        printf "%s" "3"
 | 
			
		||||
        ;;
 | 
			
		||||
      "34")
 | 
			
		||||
        printf "%s" "4"
 | 
			
		||||
        ;;
 | 
			
		||||
      "35")
 | 
			
		||||
        printf "%s" "5"
 | 
			
		||||
        ;;
 | 
			
		||||
      "36")
 | 
			
		||||
        printf "%s" "6"
 | 
			
		||||
        ;;
 | 
			
		||||
      "37")
 | 
			
		||||
        printf "%s" "7"
 | 
			
		||||
        ;;
 | 
			
		||||
      "38")
 | 
			
		||||
        printf "%s" "8"
 | 
			
		||||
        ;;
 | 
			
		||||
      "39")
 | 
			
		||||
        printf "%s" "9"
 | 
			
		||||
        ;;
 | 
			
		||||
      "2d")
 | 
			
		||||
        printf "%s" "-"
 | 
			
		||||
        ;;
 | 
			
		||||
      "5f")
 | 
			
		||||
        printf "%s" "_"
 | 
			
		||||
        ;;
 | 
			
		||||
      "2e")
 | 
			
		||||
        printf "%s" "."
 | 
			
		||||
        ;;
 | 
			
		||||
      "7e")
 | 
			
		||||
        printf "%s" "~"
 | 
			
		||||
        ;;
 | 
			
		||||
      #other hex  
 | 
			
		||||
      *)
 | 
			
		||||
        printf '%%%s' "$_hex_code"
 | 
			
		||||
        ;;
 | 
			
		||||
    esac
 | 
			
		||||
  done
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -868,7 +1094,7 @@ createCSR() {
 | 
			
		|||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
_urlencode() {
 | 
			
		||||
_url_replace() {
 | 
			
		||||
  tr '/+' '_-' | tr -d '= '
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -935,7 +1161,7 @@ _calcjwk() {
 | 
			
		|||
 | 
			
		||||
    modulus=$($OPENSSL_BIN rsa -in "$keyfile" -modulus -noout | cut -d '=' -f 2)
 | 
			
		||||
    _debug3 modulus "$modulus"
 | 
			
		||||
    n="$(printf "%s" "$modulus" | _h2b | _base64 | _urlencode)"
 | 
			
		||||
    n="$(printf "%s" "$modulus" | _h2b | _base64 | _url_replace)"
 | 
			
		||||
    _debug3 n "$n"
 | 
			
		||||
 | 
			
		||||
    jwk='{"e": "'$e'", "kty": "RSA", "n": "'$n'"}'
 | 
			
		||||
| 
						 | 
				
			
			@ -990,14 +1216,14 @@ _calcjwk() {
 | 
			
		|||
    x="$(printf "%s" "$pubtext" | cut -d : -f 2-"$xend")"
 | 
			
		||||
    _debug3 x "$x"
 | 
			
		||||
 | 
			
		||||
    x64="$(printf "%s" "$x" | tr -d : | _h2b | _base64 | _urlencode)"
 | 
			
		||||
    x64="$(printf "%s" "$x" | tr -d : | _h2b | _base64 | _url_replace)"
 | 
			
		||||
    _debug3 x64 "$x64"
 | 
			
		||||
 | 
			
		||||
    xend=$(_math "$xend" + 1)
 | 
			
		||||
    y="$(printf "%s" "$pubtext" | cut -d : -f "$xend"-10000)"
 | 
			
		||||
    _debug3 y "$y"
 | 
			
		||||
 | 
			
		||||
    y64="$(printf "%s" "$y" | tr -d : | _h2b | _base64 | _urlencode)"
 | 
			
		||||
    y64="$(printf "%s" "$y" | tr -d : | _h2b | _base64 | _url_replace)"
 | 
			
		||||
    _debug3 y64 "$y64"
 | 
			
		||||
 | 
			
		||||
    jwk='{"crv": "'$crv'", "kty": "EC", "x": "'$x64'", "y": "'$y64'"}'
 | 
			
		||||
| 
						 | 
				
			
			@ -1241,7 +1467,7 @@ _send_signed_request() {
 | 
			
		|||
    return 1
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  payload64=$(printf "%s" "$payload" | _base64 | _urlencode)
 | 
			
		||||
  payload64=$(printf "%s" "$payload" | _base64 | _url_replace)
 | 
			
		||||
  _debug3 payload64 "$payload64"
 | 
			
		||||
 | 
			
		||||
  if [ -z "$_CACHED_NONCE" ]; then
 | 
			
		||||
| 
						 | 
				
			
			@ -1267,7 +1493,7 @@ _send_signed_request() {
 | 
			
		|||
  protected="$JWK_HEADERPLACE_PART1$nonce$JWK_HEADERPLACE_PART2"
 | 
			
		||||
  _debug3 protected "$protected"
 | 
			
		||||
 | 
			
		||||
  protected64="$(printf "%s" "$protected" | _base64 | _urlencode)"
 | 
			
		||||
  protected64="$(printf "%s" "$protected" | _base64 | _url_replace)"
 | 
			
		||||
  _debug3 protected64 "$protected64"
 | 
			
		||||
 | 
			
		||||
  if ! _sig_t="$(printf "%s" "$protected64.$payload64" | _sign "$keyfile" "sha256")"; then
 | 
			
		||||
| 
						 | 
				
			
			@ -1276,7 +1502,7 @@ _send_signed_request() {
 | 
			
		|||
  fi
 | 
			
		||||
  _debug3 _sig_t "$_sig_t"
 | 
			
		||||
 | 
			
		||||
  sig="$(printf "%s" "$_sig_t" | _urlencode)"
 | 
			
		||||
  sig="$(printf "%s" "$_sig_t" | _url_replace)"
 | 
			
		||||
  _debug3 sig "$sig"
 | 
			
		||||
 | 
			
		||||
  body="{\"header\": $JWK_HEADER, \"protected\": \"$protected64\", \"payload\": \"$payload64\", \"signature\": \"$sig\"}"
 | 
			
		||||
| 
						 | 
				
			
			@ -2009,7 +2235,7 @@ _clearupdns() {
 | 
			
		|||
    keyauthorization=$(echo "$ventry" | cut -d "$sep" -f 2)
 | 
			
		||||
    vtype=$(echo "$ventry" | cut -d "$sep" -f 4)
 | 
			
		||||
    _currentRoot=$(echo "$ventry" | cut -d "$sep" -f 5)
 | 
			
		||||
    txt="$(printf "%s" "$keyauthorization" | _digest "sha256" | _urlencode)"
 | 
			
		||||
    txt="$(printf "%s" "$keyauthorization" | _digest "sha256" | _url_replace)"
 | 
			
		||||
    _debug txt "$txt"
 | 
			
		||||
    if [ "$keyauthorization" = "$STATE_VERIFIED" ]; then
 | 
			
		||||
      _info "$d is already verified, skip $vtype."
 | 
			
		||||
| 
						 | 
				
			
			@ -2553,7 +2779,7 @@ issue() {
 | 
			
		|||
 | 
			
		||||
      if [ -z "$thumbprint" ]; then
 | 
			
		||||
        accountkey_json=$(printf "%s" "$jwk" | tr -d ' ')
 | 
			
		||||
        thumbprint=$(printf "%s" "$accountkey_json" | _digest "sha256" | _urlencode)
 | 
			
		||||
        thumbprint=$(printf "%s" "$accountkey_json" | _digest "sha256" | _url_replace)
 | 
			
		||||
      fi
 | 
			
		||||
 | 
			
		||||
      entry="$(printf "%s\n" "$response" | _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*')"
 | 
			
		||||
| 
						 | 
				
			
			@ -2604,7 +2830,7 @@ issue() {
 | 
			
		|||
        dnsadded='0'
 | 
			
		||||
        txtdomain="_acme-challenge.$d"
 | 
			
		||||
        _debug txtdomain "$txtdomain"
 | 
			
		||||
        txt="$(printf "%s" "$keyauthorization" | _digest "sha256" | _urlencode)"
 | 
			
		||||
        txt="$(printf "%s" "$keyauthorization" | _digest "sha256" | _url_replace)"
 | 
			
		||||
        _debug txt "$txt"
 | 
			
		||||
 | 
			
		||||
        d_api="$(_findHook "$d" dnsapi "$_currentRoot")"
 | 
			
		||||
| 
						 | 
				
			
			@ -2879,7 +3105,7 @@ issue() {
 | 
			
		|||
 | 
			
		||||
  _clearup
 | 
			
		||||
  _info "Verify finished, start to sign."
 | 
			
		||||
  der="$(_getfile "${CSR_PATH}" "${BEGIN_CSR}" "${END_CSR}" | tr -d "\r\n" | _urlencode)"
 | 
			
		||||
  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
 | 
			
		||||
    _err "Sign failed."
 | 
			
		||||
| 
						 | 
				
			
			@ -3457,7 +3683,7 @@ revoke() {
 | 
			
		|||
    return 1
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  cert="$(_getfile "${CERT_PATH}" "${BEGIN_CERT}" "${END_CERT}" | tr -d "\r\n" | _urlencode)"
 | 
			
		||||
  cert="$(_getfile "${CERT_PATH}" "${BEGIN_CERT}" "${END_CERT}" | tr -d "\r\n" | _url_replace)"
 | 
			
		||||
 | 
			
		||||
  if [ -z "$cert" ]; then
 | 
			
		||||
    _err "Cert for $Le_Domain is empty found, skip."
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
#Using deploy api
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,81 @@
 | 
			
		|||
#!/usr/bin/env sh
 | 
			
		||||
 | 
			
		||||
# This deploy hook will deploy ssl cert on kong proxy engine based on api request_host parameter.
 | 
			
		||||
# Note that ssl plugin should be available on Kong instance
 | 
			
		||||
# The hook will match cdomain to request_host, in case of multiple domain it will always take the first
 | 
			
		||||
# one (acme.sh behaviour).
 | 
			
		||||
# If ssl config already exist it will update only cert and key not touching other parameter
 | 
			
		||||
# If ssl config doesn't exist it will only upload cert and key and not set other parameter
 | 
			
		||||
# Not that we deploy full chain
 | 
			
		||||
# See https://getkong.org/plugins/dynamic-ssl/ for other options
 | 
			
		||||
# Written by Geoffroi Genot <ggenot@voxbone.com>
 | 
			
		||||
 | 
			
		||||
########  Public functions #####################
 | 
			
		||||
 | 
			
		||||
#domain keyfile certfile cafile fullchain
 | 
			
		||||
kong_deploy() {
 | 
			
		||||
  _cdomain="$1"
 | 
			
		||||
  _ckey="$2"
 | 
			
		||||
  _ccert="$3"
 | 
			
		||||
  _cca="$4"
 | 
			
		||||
  _cfullchain="$5"
 | 
			
		||||
  _info "Deploying certificate on Kong instance"
 | 
			
		||||
  if [ -z "$KONG_URL" ]; then
 | 
			
		||||
    _debug "KONG_URL Not set, using default http://localhost:8001"
 | 
			
		||||
    KONG_URL="http://localhost:8001"
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  _debug _cdomain "$_cdomain"
 | 
			
		||||
  _debug _ckey "$_ckey"
 | 
			
		||||
  _debug _ccert "$_ccert"
 | 
			
		||||
  _debug _cca "$_cca"
 | 
			
		||||
  _debug _cfullchain "$_cfullchain"
 | 
			
		||||
 | 
			
		||||
  #Get uuid linked to the domain
 | 
			
		||||
  uuid=$(_get "$KONG_URL/apis?request_host=$_cdomain" | _normalizeJson | _egrep_o '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}')
 | 
			
		||||
  if [ -z "$uuid" ]; then
 | 
			
		||||
    _err "Unable to get Kong uuid for domain $_cdomain"
 | 
			
		||||
    _err "Make sure that KONG_URL is correctly configured"
 | 
			
		||||
    _err "Make sure that a Kong api request_host match the domain"
 | 
			
		||||
    _err "Kong url: $KONG_URL"
 | 
			
		||||
    return 1
 | 
			
		||||
  fi
 | 
			
		||||
  #Save kong url if it's succesful (First run case)
 | 
			
		||||
  _saveaccountconf KONG_URL "$KONG_URL"
 | 
			
		||||
  #Generate DEIM
 | 
			
		||||
  delim="-----MultipartDelimeter$(date "+%s%N")"
 | 
			
		||||
  nl="\015\012"
 | 
			
		||||
  #Set Header
 | 
			
		||||
  _H1="Content-Type: multipart/form-data; boundary=$delim"
 | 
			
		||||
  #Generate data for request (Multipart/form-data with mixed content)
 | 
			
		||||
  #set name to ssl
 | 
			
		||||
  content="--$delim${nl}Content-Disposition: form-data; name=\"name\"${nl}${nl}ssl"
 | 
			
		||||
  #add key
 | 
			
		||||
  content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"config.key\"; filename=\"$(basename "$_ckey")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ckey")"
 | 
			
		||||
  #Add cert
 | 
			
		||||
  content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"config.cert\"; filename=\"$(basename "$_cfullchain")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_cfullchain")"
 | 
			
		||||
  #Close multipart
 | 
			
		||||
  content="$content${nl}--$delim--${nl}"
 | 
			
		||||
  #Convert CRLF
 | 
			
		||||
  content=$(printf %b "$content")
 | 
			
		||||
  #DEBUG
 | 
			
		||||
  _debug header "$_H1"
 | 
			
		||||
  _debug content "$content"
 | 
			
		||||
  #Check if ssl plugins is aready enabled (if not => POST else => PATCH)
 | 
			
		||||
  ssl_uuid=$(_get "$KONG_URL/apis/$uuid/plugins" | _egrep_o '"id":"[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"[a-zA-Z0-9\-\,\"_\:]*"name":"ssl"' | _egrep_o '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}')
 | 
			
		||||
  _debug ssl_uuid "$ssl_uuid"
 | 
			
		||||
  if [ -z "$ssl_uuid" ]; then
 | 
			
		||||
    #Post certificate to Kong
 | 
			
		||||
    response=$(_post "$content" "$KONG_URL/apis/$uuid/plugins" "" "POST")
 | 
			
		||||
  else
 | 
			
		||||
    #patch
 | 
			
		||||
    response=$(_post "$content" "$KONG_URL/apis/$uuid/plugins/$ssl_uuid" "" "PATCH")
 | 
			
		||||
  fi
 | 
			
		||||
  if ! [ "$(echo "$response" | _egrep_o "ssl")" = "ssl" ]; then
 | 
			
		||||
    _err "An error occured with cert upload. Check response:"
 | 
			
		||||
    _err "$response"
 | 
			
		||||
    return 1
 | 
			
		||||
  fi
 | 
			
		||||
  _debug response "$response"
 | 
			
		||||
  _info "Certificate successfully deployed"
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -257,6 +257,27 @@ acme.sh --issue --dns dns_ad -d example.com -d www.example.com
 | 
			
		|||
The `AD_API_KEY` will be saved in `~/.acme.sh/account.conf` and will be reused
 | 
			
		||||
when needed.
 | 
			
		||||
 | 
			
		||||
## 14. Use Linode domain API
 | 
			
		||||
 | 
			
		||||
First you need to login to your Linode account to get your API Key.
 | 
			
		||||
[https://manager.linode.com/profile/api](https://manager.linode.com/profile/api)
 | 
			
		||||
 | 
			
		||||
Then add an API key with label *ACME* and copy the new key.
 | 
			
		||||
 | 
			
		||||
```sh
 | 
			
		||||
export LINODE_API_KEY="..."
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Due to the reload time of any changes in the DNS records, we have to use the `dnssleep` option to wait at least 15 minutes for the changes to take effect.
 | 
			
		||||
 | 
			
		||||
Ok, let's issue a cert now:
 | 
			
		||||
 | 
			
		||||
```sh
 | 
			
		||||
acme.sh --issue --dns dns_linode --dnssleep 900 -d example.com -d www.example.com
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The `LINODE_API_KEY` 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.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -67,7 +67,7 @@ _get_root() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
_ali_rest() {
 | 
			
		||||
  signature=$(printf "%s" "GET&%2F&$(_ali_urlencode "$query")" | _hmac "sha1" "$(_hex "$Ali_Secret&")" | _base64)
 | 
			
		||||
  signature=$(printf "%s" "GET&%2F&$(_ali_urlencode "$query")" | _hmac "sha1" "$(printf "%s" "$Ali_Secret&" | _hex_dump | tr -d " ")" | _base64)
 | 
			
		||||
  signature=$(_ali_urlencode "$signature")
 | 
			
		||||
  url="$Ali_API?$query&Signature=$signature"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -93,7 +93,7 @@ _get_root() {
 | 
			
		|||
      fi
 | 
			
		||||
 | 
			
		||||
      if _contains "$response" "<Name>$h.</Name>"; then
 | 
			
		||||
        hostedzone="$(echo "$response" | sed 's/<HostedZone>/\n&/g' | _egrep_o "<HostedZone>.*?<Name>$h.<.Name>.*?<.HostedZone>")"
 | 
			
		||||
        hostedzone="$(echo "$response" | _egrep_o "<HostedZone><Id>[^<]*<.Id><Name>$h.<.Name>.*<.HostedZone>")"
 | 
			
		||||
        _debug hostedzone "$hostedzone"
 | 
			
		||||
        if [ -z "$hostedzone" ]; then
 | 
			
		||||
          _err "Error, can not get hostedzone."
 | 
			
		||||
| 
						 | 
				
			
			@ -183,7 +183,7 @@ aws_rest() {
 | 
			
		|||
 | 
			
		||||
  _debug2 kSecret "$kSecret"
 | 
			
		||||
 | 
			
		||||
  kSecretH="$(_hex "$kSecret")"
 | 
			
		||||
  kSecretH="$(printf "%s" "$kSecret" | _hex_dump | tr -d " ")"
 | 
			
		||||
  _debug2 kSecretH "$kSecretH"
 | 
			
		||||
 | 
			
		||||
  kDateH="$(printf "$RequestDateOnly%s" | _hmac "$Hash" "$kSecretH" hex)"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -82,7 +82,7 @@ existing_records() {
 | 
			
		|||
    return 1
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  seg=$(printf "%s\n" "$response" | _egrep_o '[^{]*host":"'"$_sub_domain"'"[^}]*\}')
 | 
			
		||||
  seg=$(printf "%s\n" "$response" | _egrep_o '"record_id":[^{]*host":"'"$_sub_domain"'"[^}]*\}')
 | 
			
		||||
  _debug seg "$seg"
 | 
			
		||||
  if [ -z "$seg" ]; then
 | 
			
		||||
    return 0
 | 
			
		||||
| 
						 | 
				
			
			@ -155,7 +155,7 @@ _get_root() {
 | 
			
		|||
    fi
 | 
			
		||||
 | 
			
		||||
    if _contains "$response" "$h."; then
 | 
			
		||||
      seg=$(printf "%s\n" "$response" | _egrep_o '[^{]*"'"$h"'."[^}]*}')
 | 
			
		||||
      seg=$(printf "%s\n" "$response" | _egrep_o '"id":[^{]*"'"$h"'."[^}]*}')
 | 
			
		||||
      _debug seg "$seg"
 | 
			
		||||
      _domain_id=$(printf "%s\n" "$seg" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \")
 | 
			
		||||
      _debug _domain_id "$_domain_id"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,183 @@
 | 
			
		|||
#!/usr/bin/env sh
 | 
			
		||||
 | 
			
		||||
#Author: Philipp Grosswiler <philipp.grosswiler@swiss-design.net>
 | 
			
		||||
 | 
			
		||||
LINODE_API_URL="https://api.linode.com/?api_key=$LINODE_API_KEY&api_action="
 | 
			
		||||
 | 
			
		||||
########  Public functions #####################
 | 
			
		||||
 | 
			
		||||
#Usage: dns_linode_add   _acme-challenge.www.domain.com   "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
 | 
			
		||||
dns_linode_add() {
 | 
			
		||||
  fulldomain="${1}"
 | 
			
		||||
  txtvalue="${2}"
 | 
			
		||||
 | 
			
		||||
  if ! _Linode_API; then
 | 
			
		||||
    return 1
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  _info "Using Linode"
 | 
			
		||||
  _debug "Calling: dns_linode_add() '${fulldomain}' '${txtvalue}'"
 | 
			
		||||
 | 
			
		||||
  _debug "First detect the root zone"
 | 
			
		||||
  if ! _get_root "$fulldomain"; then
 | 
			
		||||
    _err "Domain does not exist."
 | 
			
		||||
    return 1
 | 
			
		||||
  fi
 | 
			
		||||
  _debug _domain_id "$_domain_id"
 | 
			
		||||
  _debug _sub_domain "$_sub_domain"
 | 
			
		||||
  _debug _domain "$_domain"
 | 
			
		||||
 | 
			
		||||
  _parameters="&DomainID=$_domain_id&Type=TXT&Name=$_sub_domain&Target=$txtvalue"
 | 
			
		||||
 | 
			
		||||
  if _rest GET "domain.resource.create" "$_parameters" && [ -n "$response" ]; then
 | 
			
		||||
    _resource_id=$(printf "%s\n" "$response" | _egrep_o "\"ResourceID\":\s*[0-9]+" | cut -d : -f 2 | tr -d " " | _head_n 1)
 | 
			
		||||
    _debug _resource_id "$_resource_id"
 | 
			
		||||
 | 
			
		||||
    if [ -z "$_resource_id" ]; then
 | 
			
		||||
      _err "Error adding the domain resource."
 | 
			
		||||
      return 1
 | 
			
		||||
    fi
 | 
			
		||||
 | 
			
		||||
    _info "Domain resource successfully added."
 | 
			
		||||
    return 0
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  return 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#Usage: dns_linode_rm   _acme-challenge.www.domain.com
 | 
			
		||||
dns_linode_rm() {
 | 
			
		||||
  fulldomain="${1}"
 | 
			
		||||
 | 
			
		||||
  if ! _Linode_API; then
 | 
			
		||||
    return 1
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  _info "Using Linode"
 | 
			
		||||
  _debug "Calling: dns_linode_rm() '${fulldomain}'"
 | 
			
		||||
 | 
			
		||||
  _debug "First detect the root zone"
 | 
			
		||||
  if ! _get_root "$fulldomain"; then
 | 
			
		||||
    _err "Domain does not exist."
 | 
			
		||||
    return 1
 | 
			
		||||
  fi
 | 
			
		||||
  _debug _domain_id "$_domain_id"
 | 
			
		||||
  _debug _sub_domain "$_sub_domain"
 | 
			
		||||
  _debug _domain "$_domain"
 | 
			
		||||
 | 
			
		||||
  _parameters="&DomainID=$_domain_id"
 | 
			
		||||
 | 
			
		||||
  if _rest GET "domain.resource.list" "$_parameters" && [ -n "$response" ]; then
 | 
			
		||||
    response="$(echo "$response" | tr -d "\n" | sed 's/{/\n&/g')"
 | 
			
		||||
 | 
			
		||||
    resource="$(echo "$response" | _egrep_o "{.*\"NAME\":\s*\"$_sub_domain\".*}")"
 | 
			
		||||
    if [ "$resource" ]; then
 | 
			
		||||
      _resource_id=$(printf "%s\n" "$resource" | _egrep_o "\"RESOURCEID\":\s*[0-9]+" | _head_n 1 | cut -d : -f 2 | tr -d \ )
 | 
			
		||||
      if [ "$_resource_id" ]; then
 | 
			
		||||
        _debug _resource_id "$_resource_id"
 | 
			
		||||
 | 
			
		||||
        _parameters="&DomainID=$_domain_id&ResourceID=$_resource_id"
 | 
			
		||||
 | 
			
		||||
        if _rest GET "domain.resource.delete" "$_parameters" && [ -n "$response" ]; then
 | 
			
		||||
          _resource_id=$(printf "%s\n" "$response" | _egrep_o "\"ResourceID\":\s*[0-9]+" | cut -d : -f 2 | tr -d " " | _head_n 1)
 | 
			
		||||
          _debug _resource_id "$_resource_id"
 | 
			
		||||
 | 
			
		||||
          if [ -z "$_resource_id" ]; then
 | 
			
		||||
            _err "Error deleting the domain resource."
 | 
			
		||||
            return 1
 | 
			
		||||
          fi
 | 
			
		||||
 | 
			
		||||
          _info "Domain resource successfully deleted."
 | 
			
		||||
          return 0
 | 
			
		||||
        fi
 | 
			
		||||
      fi
 | 
			
		||||
 | 
			
		||||
      return 1
 | 
			
		||||
    fi
 | 
			
		||||
 | 
			
		||||
    return 0
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  return 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
####################  Private functions below ##################################
 | 
			
		||||
 | 
			
		||||
_Linode_API() {
 | 
			
		||||
  if [ -z "$LINODE_API_KEY" ]; then
 | 
			
		||||
    LINODE_API_KEY=""
 | 
			
		||||
 | 
			
		||||
    _err "You didn't specify the Linode API key yet."
 | 
			
		||||
    _err "Please create your key and try again."
 | 
			
		||||
 | 
			
		||||
    return 1
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  _saveaccountconf LINODE_API_KEY "$LINODE_API_KEY"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
####################  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 _rest GET "domain.list"; 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 "{.*\"DOMAIN\":\s*\"$h\".*}")"
 | 
			
		||||
      if [ "$hostedzone" ]; then
 | 
			
		||||
        _domain_id=$(printf "%s\n" "$hostedzone" | _egrep_o "\"DOMAINID\":\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 method action data
 | 
			
		||||
_rest() {
 | 
			
		||||
  mtd="$1"
 | 
			
		||||
  ep="$2"
 | 
			
		||||
  data="$3"
 | 
			
		||||
 | 
			
		||||
  _debug mtd "$mtd"
 | 
			
		||||
  _debug ep "$ep"
 | 
			
		||||
 | 
			
		||||
  export _H1="Accept: application/json"
 | 
			
		||||
  export _H2="Content-Type: application/json"
 | 
			
		||||
 | 
			
		||||
  if [ "$mtd" != "GET" ]; then
 | 
			
		||||
    # both POST and DELETE.
 | 
			
		||||
    _debug data "$data"
 | 
			
		||||
    response="$(_post "$data" "$LINODE_API_URL$ep" "" "$mtd")"
 | 
			
		||||
  else
 | 
			
		||||
    response="$(_get "$LINODE_API_URL$ep$data")"
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  if [ "$?" != "0" ]; then
 | 
			
		||||
    _err "error $ep"
 | 
			
		||||
    return 1
 | 
			
		||||
  fi
 | 
			
		||||
  _debug2 response "$response"
 | 
			
		||||
  return 0
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -46,12 +46,12 @@ dns_lua_add() {
 | 
			
		|||
    return 1
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  count=$(printf "%s\n" "$response" | _egrep_o "\"name\":\"$fulldomain\"" | wc -l)
 | 
			
		||||
  count=$(printf "%s\n" "$response" | _egrep_o "\"name\":\"$fulldomain.\",\"type\":\"TXT\"" | wc -l | tr -d " ")
 | 
			
		||||
  _debug count "$count"
 | 
			
		||||
  if [ "$count" = "0" ]; then
 | 
			
		||||
    _info "Adding record"
 | 
			
		||||
    if _LUA_rest POST "zones/$_domain_id/records" "{\"type\":\"TXT\",\"name\":\"$fulldomain.\",\"content\":\"$txtvalue\",\"ttl\":120}"; then
 | 
			
		||||
      if printf -- "%s" "$response" | grep "$fulldomain" >/dev/null; then
 | 
			
		||||
      if _contains "$response" "$fulldomain"; then
 | 
			
		||||
        _info "Added"
 | 
			
		||||
        #todo: check if the record takes effect
 | 
			
		||||
        return 0
 | 
			
		||||
| 
						 | 
				
			
			@ -63,11 +63,11 @@ dns_lua_add() {
 | 
			
		|||
    _err "Add txt record error."
 | 
			
		||||
  else
 | 
			
		||||
    _info "Updating record"
 | 
			
		||||
    record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[^,]*,\"name\":\"$fulldomain.\",\"type\":\"TXT\"" | cut -d: -f2 | cut -d, -f1)
 | 
			
		||||
    record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[^,]*,\"name\":\"$fulldomain.\",\"type\":\"TXT\"" | _head_n 1 | cut -d: -f2 | cut -d, -f1)
 | 
			
		||||
    _debug "record_id" "$record_id"
 | 
			
		||||
 | 
			
		||||
    _LUA_rest PUT "zones/$_domain_id/records/$record_id" "{\"id\":\"$record_id\",\"type\":\"TXT\",\"name\":\"$fulldomain.\",\"content\":\"$txtvalue\",\"zone_id\":\"$_domain_id\",\"ttl\":120}"
 | 
			
		||||
    if [ "$?" = "0" ]; then
 | 
			
		||||
    _LUA_rest PUT "zones/$_domain_id/records/$record_id" "{\"id\":$record_id,\"type\":\"TXT\",\"name\":\"$fulldomain.\",\"content\":\"$txtvalue\",\"zone_id\":$_domain_id,\"ttl\":120}"
 | 
			
		||||
    if [ "$?" = "0" ] && _contains "$response" "updated_at"; then
 | 
			
		||||
      _info "Updated!"
 | 
			
		||||
      #todo: check if the record takes effect
 | 
			
		||||
      return 0
 | 
			
		||||
| 
						 | 
				
			
			@ -99,6 +99,7 @@ _get_root() {
 | 
			
		|||
  fi
 | 
			
		||||
  while true; do
 | 
			
		||||
    h=$(printf "%s" "$domain" | cut -d . -f $i-100)
 | 
			
		||||
    _debug h "$h"
 | 
			
		||||
    if [ -z "$h" ]; then
 | 
			
		||||
      #not valid
 | 
			
		||||
      return 1
 | 
			
		||||
| 
						 | 
				
			
			@ -106,6 +107,7 @@ _get_root() {
 | 
			
		|||
 | 
			
		||||
    if _contains "$response" "\"name\":\"$h\""; then
 | 
			
		||||
      _domain_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[^,]*,\"name\":\"$h\"" | cut -d : -f 2 | cut -d , -f 1)
 | 
			
		||||
      _debug _domain_id "$_domain_id"
 | 
			
		||||
      if [ "$_domain_id" ]; then
 | 
			
		||||
        _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
 | 
			
		||||
        _domain="$h"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -124,7 +124,7 @@ _me_rest() {
 | 
			
		|||
  _debug "$ep"
 | 
			
		||||
 | 
			
		||||
  cdate=$(date -u +"%a, %d %b %Y %T %Z")
 | 
			
		||||
  hmac=$(printf "%s" "$cdate" | _hmac sha1 "$(_hex "$ME_Secret")" hex)
 | 
			
		||||
  hmac=$(printf "%s" "$cdate" | _hmac sha1 "$(printf "%s" "$ME_Secret" | _hex_dump | tr -d " ")" hex)
 | 
			
		||||
 | 
			
		||||
  export _H1="x-dnsme-apiKey: $ME_Key"
 | 
			
		||||
  export _H2="x-dnsme-requestDate: $cdate"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue