Browse Source

Merge pull request #819 from Neilpang/dev

Dev
neil 8 years ago
parent
commit
c4cdcf44c5
4 changed files with 250 additions and 9 deletions
  1. 1 0
      README.md
  2. 32 7
      dnsapi/README.md
  3. 215 0
      dnsapi/dns_dnsimple.sh
  4. 2 2
      dnsapi/dns_ovh.sh

+ 1 - 0
README.md

@@ -292,6 +292,7 @@ You don't have to do anything manually!
 
 1. CloudFlare.com API
 1. DNSPod.cn API
+1. DNSimple API
 1. CloudXNS.com API
 1. GoDaddy.com API
 1. OVH, kimsufi, soyoustart and runabove API

+ 32 - 7
dnsapi/README.md

@@ -422,31 +422,31 @@ acme.sh --issue --dns dns_cloudns -d example.com -d www.example.com
 ```
 
 ## 22. Use Infoblox API
- 
+
 First you need to create/obtain API credentials on your Infoblox appliance.
- 
+
 ```
 export Infoblox_Creds="username:password"
 export Infoblox_Server="ip or fqdn of infoblox appliance"
 ```
- 
+
 Ok, let's issue a cert now:
 ```
 acme.sh --issue --dns dns_infoblox -d example.com -d www.example.com
 ```
- 
+
 Note: This script will automatically create and delete the ephemeral txt record.
 The `Infoblox_Creds` and `Infoblox_Server` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
 
 
 ## 23. Use VSCALE API
- 
+
 First you need to create/obtain API tokens on your [settings panel](https://vscale.io/panel/settings/tokens/).
- 
+
 ```
 VSCALE_API_KEY="sdfsdfsdfljlbjkljlkjsdfoiwje"
 ```
- 
+
 Ok, let's issue a cert now:
 ```
 acme.sh --issue --dns dns_vscale -d example.com -d www.example.com
@@ -468,6 +468,31 @@ 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.
 
+## 25. Use DNSimple API
+
+First you need to login to your DNSimple account and generate a new oauth token.
+
+https://dnsimple.com/a/{your account id}/account/access_tokens
+
+Note that this is an _account_ token and not a user token. The account token is
+needed to infer the `account_id` used in requests. A user token will not be able
+to determine the correct account to use.
+
+```
+export DNSimple_OAUTH_TOKEN="sdfsdfsdfljlbjkljlkjsdfoiwje"
+```
+
+To issue the cert just specify the `dns_dnsimple` API.
+
+```
+acme.sh --issue --dns dns_dnsimple -d example.com
+```
+
+The `DNSimple_OAUTH_TOKEN` will be saved in `~/.acme.sh/account.conf` and will
+be reused when needed.
+
+If you have any issues with this integration please report them to
+https://github.com/pho3nixf1re/acme.sh/issues.
 
 # Use custom API
 

+ 215 - 0
dnsapi/dns_dnsimple.sh

@@ -0,0 +1,215 @@
+#!/usr/bin/env sh
+
+# DNSimple domain api
+# https://github.com/pho3nixf1re/acme.sh/issues
+#
+# This is your oauth token which can be acquired on the account page. Please
+# note that this must be an _account_ token and not a _user_ token.
+# https://dnsimple.com/a/<your account id>/account/access_tokens
+# DNSimple_OAUTH_TOKEN="sdfsdfsdfljlbjkljlkjsdfoiwje"
+
+DNSimple_API="https://api.dnsimple.com/v2"
+
+########  Public functions #####################
+
+# Usage: add  _acme-challenge.www.domain.com   "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
+dns_dnsimple_add() {
+  fulldomain=$1
+  txtvalue=$2
+
+  if [ -z "$DNSimple_OAUTH_TOKEN" ]; then
+    DNSimple_OAUTH_TOKEN=""
+    _err "You have not set the dnsimple oauth token yet."
+    _err "Please visit https://dnsimple.com/user to generate it."
+    return 1
+  fi
+
+  # save the oauth token for later
+  _saveaccountconf DNSimple_OAUTH_TOKEN "$DNSimple_OAUTH_TOKEN"
+
+  if ! _get_account_id; then
+    _err "failed to retrive account id"
+    return 1
+  fi
+
+  if ! _get_root "$fulldomain"; then
+    _err "invalid domain"
+    return 1
+  fi
+
+  _get_records "$_account_id" "$_domain" "$_sub_domain"
+
+  if [ "$_records_count" = "0" ]; then
+    _info "Adding record"
+    if _dnsimple_rest POST "$_account_id/zones/$_domain/records" "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"content\":\"$txtvalue\",\"ttl\":120}"; then
+      if printf -- "%s" "$response" | grep "\"name\":\"$_sub_domain\"" >/dev/null; then
+        _info "Added"
+        return 0
+      else
+        _err "Unexpected response while adding text record."
+        return 1
+      fi
+    fi
+    _err "Add txt record error."
+  else
+    _info "Updating record"
+    _extract_record_id "$_records" "$_sub_domain"
+
+    if _dnsimple_rest \
+      PATCH \
+      "$_account_id/zones/$_domain/records/$_record_id" \
+      "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"content\":\"$txtvalue\",\"ttl\":120}"; then
+
+      _info "Updated!"
+      return 0
+    fi
+
+    _err "Update error"
+    return 1
+  fi
+}
+
+# fulldomain
+dns_dnsimple_rm() {
+  fulldomain=$1
+
+  if ! _get_account_id; then
+    _err "failed to retrive account id"
+    return 1
+  fi
+
+  if ! _get_root "$fulldomain"; then
+    _err "invalid domain"
+    return 1
+  fi
+
+  _get_records "$_account_id" "$_domain" "$_sub_domain"
+  _extract_record_id "$_records" "$_sub_domain"
+
+  if [ "$_record_id" ]; then
+
+    if _dnsimple_rest DELETE "$_account_id/zones/$_domain/records/$_record_id"; then
+      _info "removed record" "$_record_id"
+      return 0
+    fi
+  fi
+
+  _err "failed to remove record" "$_record_id"
+  return 1
+
+}
+
+####################  Private functions bellow ##################################
+# _acme-challenge.www.domain.com
+# returns
+#   _sub_domain=_acme-challenge.www
+#   _domain=domain.com
+_get_root() {
+  domain=$1
+  i=2
+  previous=1
+  while true; do
+    h=$(printf "%s" "$domain" | cut -d . -f $i-100)
+    if [ -z "$h" ]; then
+      # not valid
+      return 1
+    fi
+
+    if ! _dnsimple_rest GET "$_account_id/zones/$h"; then
+      return 1
+    fi
+
+    if _contains "$response" 'not found'; then
+      _debug "$h not found"
+    else
+      _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$previous)
+      _domain="$h"
+
+      _debug _domain "$_domain"
+      _debug _sub_domain "$_sub_domain"
+
+      return 0
+    fi
+
+    previous="$i"
+    i=$(_math "$i" + 1)
+  done
+  return 1
+}
+
+# returns _account_id
+_get_account_id() {
+  _debug "retrive account id"
+  if ! _dnsimple_rest GET "whoami"; then
+    return 1
+  fi
+
+  if _contains "$response" "\"account\":null"; then
+    _err "no account associated with this token"
+    return 1
+  fi
+
+  if _contains "$response" "timeout"; then
+    _err "timeout retrieving account id"
+    return 1
+  fi
+
+  _account_id=$(printf "%s" "$response" | _egrep_o "\"id\":[^,]*,\"email\":" | cut -d: -f2 | cut -d, -f1)
+  _debug _account_id "$_account_id"
+
+  return 0
+}
+
+# returns
+#   _records
+#   _records_count
+_get_records() {
+  account_id=$1
+  domain=$2
+  sub_domain=$3
+
+  _debug "fetching txt records"
+  _dnsimple_rest GET "$account_id/zones/$domain/records?per_page=100"
+
+  if ! _contains "$response" "\"id\":"; then
+    _err "failed to retrieve records"
+    return 1
+  fi
+
+  _records_count=$(printf "%s" "$response" | _egrep_o "\"name\":\"$sub_domain\"" | wc -l | _egrep_o "[0-9]+")
+  _records=$response
+  _debug _records_count "$_records_count"
+}
+
+# returns _record_id
+_extract_record_id() {
+  _record_id=$(printf "%s" "$_records" | _egrep_o "\"id\":[^,]*,\"zone_id\":\"[^,]*\",\"parent_id\":null,\"name\":\"$_sub_domain\"" | cut -d: -f2 | cut -d, -f1)
+  _debug "_record_id" "$_record_id"
+}
+
+# returns response
+_dnsimple_rest() {
+  method=$1
+  path="$2"
+  data="$3"
+  request_url="$DNSimple_API/$path"
+  _debug "$path"
+
+  export _H1="Accept: application/json"
+  export _H2="Authorization: Bearer $DNSimple_OAUTH_TOKEN"
+
+  if [ "$data" ] || [ "$method" = "DELETE" ]; then
+    _H1="Content-Type: application/json"
+    _debug data "$data"
+    response="$(_post "$data" "$request_url" "" "$method")"
+  else
+    response="$(_get "$request_url" "" "" "$method")"
+  fi
+
+  if [ "$?" != "0" ]; then
+    _err "error $request_url"
+    return 1
+  fi
+  _debug2 response "$response"
+  return 0
+}

+ 2 - 2
dnsapi/dns_ovh.sh

@@ -119,7 +119,7 @@ dns_ovh_add() {
 
   _info "Checking authentication"
 
-  response="$(_ovh_rest GET "domain/")"
+  response="$(_ovh_rest GET "domain")"
   if _contains "$response" "INVALID_CREDENTIAL"; then
     _err "The consumer key is invalid: $OVH_CK"
     _err "Please retry to create a new one."
@@ -191,7 +191,7 @@ _ovh_authentication() {
   _H3=""
   _H4=""
 
-  _ovhdata='{"accessRules": [{"method": "GET","path": "/*"},{"method": "POST","path": "/*"},{"method": "PUT","path": "/*"},{"method": "DELETE","path": "/*"}],"redirection":"'$ovh_success'"}'
+  _ovhdata='{"accessRules": [{"method": "GET","path": "/auth/time"},{"method": "GET","path": "/domain"},{"method": "GET","path": "/domain/zone/*"},{"method": "GET","path": "/domain/zone/*/record"},{"method": "POST","path": "/domain/zone/*/record"},{"method": "POST","path": "/domain/zone/*/refresh"},{"method": "PUT","path": "/domain/zone/*/record/*"}],"redirection":"'$ovh_success'"}'
 
   response="$(_post "$_ovhdata" "$OVH_API/auth/credential")"
   _debug3 response "$response"