Merge pull request #443 from pho3nixf1re/dnsimple

include dnsimple api
This commit is contained in:
neil 2017-05-03 13:15:11 +08:00 committed by GitHub
commit 347dab0c14
5 changed files with 277 additions and 35 deletions

View File

@ -292,6 +292,7 @@ You don't have to do anything manually!
1. CloudFlare.com API 1. CloudFlare.com API
1. DNSPod.cn API 1. DNSPod.cn API
1. DNSimple API
1. CloudXNS.com API 1. CloudXNS.com API
1. GoDaddy.com API 1. GoDaddy.com API
1. OVH, kimsufi, soyoustart and runabove API 1. OVH, kimsufi, soyoustart and runabove API
@ -315,6 +316,8 @@ You don't have to do anything manually!
1. ClouDNS.net API 1. ClouDNS.net API
1. Infoblox NIOS API (https://www.infoblox.com/) 1. Infoblox NIOS API (https://www.infoblox.com/)
1. VSCALE (https://vscale.io/) 1. VSCALE (https://vscale.io/)
1. Dynu API (https://www.dynu.com)
**More APIs coming soon...** **More APIs coming soon...**

View File

@ -21,8 +21,11 @@ acme.sh --deploy -d example.com --deploy-hook cpanel
## 2. Deploy ssl cert on kong proxy engine based on api. ## 2. Deploy ssl cert on kong proxy engine based on api.
Before you can deploy your cert, you must [issue the cert first](https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert). Before you can deploy your cert, you must [issue the cert first](https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert).
Currently supports Kong-v0.10.x.
(TODO) ```sh
acme.sh --deploy -d ftp.example.com --deploy-hook kong
```
## 3. Deploy the cert to remote server through SSH access. ## 3. Deploy the cert to remote server through SSH access.

View File

@ -1,13 +1,7 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# If certificate already exist it will update only cert and key not touching other parameter
# This deploy hook will deploy ssl cert on kong proxy engine based on api request_host parameter. # If certificate doesn't exist it will only upload cert and key and not set other parameter
# Note that ssl plugin should be available on Kong instance # Note that we deploy full chain
# 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> # Written by Geoffroi Genot <ggenot@voxbone.com>
######## Public functions ##################### ######## Public functions #####################
@ -31,14 +25,15 @@ kong_deploy() {
_debug _cca "$_cca" _debug _cca "$_cca"
_debug _cfullchain "$_cfullchain" _debug _cfullchain "$_cfullchain"
#Get uuid linked to the domain #Get ssl_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}') ssl_uuid=$(_get "$KONG_URL/certificates/$_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 if [ -z "$ssl_uuid" ]; then
_err "Unable to get Kong uuid for domain $_cdomain" _debug "Unable to get Kong ssl_uuid for domain $_cdomain"
_err "Make sure that KONG_URL is correctly configured" _debug "Make sure that KONG_URL is correctly configured"
_err "Make sure that a Kong api request_host match the domain" _debug "Make sure that a Kong certificate match the sni"
_err "Kong url: $KONG_URL" _debug "Kong url: $KONG_URL"
return 1 _info "No existing certificate, creating..."
#return 1
fi fi
#Save kong url if it's succesful (First run case) #Save kong url if it's succesful (First run case)
_saveaccountconf KONG_URL "$KONG_URL" _saveaccountconf KONG_URL "$KONG_URL"
@ -48,12 +43,14 @@ kong_deploy() {
#Set Header #Set Header
_H1="Content-Type: multipart/form-data; boundary=$delim" _H1="Content-Type: multipart/form-data; boundary=$delim"
#Generate data for request (Multipart/form-data with mixed content) #Generate data for request (Multipart/form-data with mixed content)
#set name to ssl if [ -z "$ssl_uuid" ]; then
content="--$delim${nl}Content-Disposition: form-data; name=\"name\"${nl}${nl}ssl" #set sni to domain
content="--$delim${nl}Content-Disposition: form-data; name=\"snis\"${nl}${nl}$_cdomain"
fi
#add key #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")" content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"key\"; filename=\"$(basename "$_ckey")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ckey")"
#Add cert #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")" content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"cert\"; filename=\"$(basename "$_cfullchain")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_cfullchain")"
#Close multipart #Close multipart
content="$content${nl}--$delim--${nl}" content="$content${nl}--$delim--${nl}"
#Convert CRLF #Convert CRLF
@ -61,17 +58,16 @@ kong_deploy() {
#DEBUG #DEBUG
_debug header "$_H1" _debug header "$_H1"
_debug content "$content" _debug content "$content"
#Check if ssl plugins is aready enabled (if not => POST else => PATCH) #Check if sslcreated (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 if [ -z "$ssl_uuid" ]; then
#Post certificate to Kong #Post certificate to Kong
response=$(_post "$content" "$KONG_URL/apis/$uuid/plugins" "" "POST") response=$(_post "$content" "$KONG_URL/certificates" "" "POST")
else else
#patch #patch
response=$(_post "$content" "$KONG_URL/apis/$uuid/plugins/$ssl_uuid" "" "PATCH") response=$(_post "$content" "$KONG_URL/certificates/$ssl_uuid" "" "PATCH")
fi fi
if ! [ "$(echo "$response" | _egrep_o "ssl")" = "ssl" ]; then if ! [ "$(echo "$response" | _egrep_o "created_at")" = "created_at" ]; then
_err "An error occurred with cert upload. Check response:" _err "An error occurred with cert upload. Check response:"
_err "$response" _err "$response"
return 1 return 1

View File

@ -422,31 +422,31 @@ acme.sh --issue --dns dns_cloudns -d example.com -d www.example.com
``` ```
## 22. Use Infoblox API ## 22. Use Infoblox API
First you need to create/obtain API credentials on your Infoblox appliance. First you need to create/obtain API credentials on your Infoblox appliance.
``` ```
export Infoblox_Creds="username:password" export Infoblox_Creds="username:password"
export Infoblox_Server="ip or fqdn of infoblox appliance" export Infoblox_Server="ip or fqdn of infoblox appliance"
``` ```
Ok, let's issue a cert now: Ok, let's issue a cert now:
``` ```
acme.sh --issue --dns dns_infoblox -d example.com -d www.example.com 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. 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. The `Infoblox_Creds` and `Infoblox_Server` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
## 23. Use VSCALE API ## 23. Use VSCALE API
First you need to create/obtain API tokens on your [settings panel](https://vscale.io/panel/settings/tokens/). First you need to create/obtain API tokens on your [settings panel](https://vscale.io/panel/settings/tokens/).
``` ```
VSCALE_API_KEY="sdfsdfsdfljlbjkljlkjsdfoiwje" VSCALE_API_KEY="sdfsdfsdfljlbjkljlkjsdfoiwje"
``` ```
Ok, let's issue a cert now: Ok, let's issue a cert now:
``` ```
acme.sh --issue --dns dns_vscale -d example.com -d www.example.com 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. 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 # Use custom API

215
dnsapi/dns_dnsimple.sh Normal file
View File

@ -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
}