support cloudxns.com api

This commit is contained in:
neil 2016-02-07 18:26:12 +08:00
parent ce56c1bbfc
commit 0809486529
4 changed files with 253 additions and 60 deletions

View File

@ -163,69 +163,21 @@ le renew aa.com
Ok, it's finished.
#Automatic dns api integeration
# Use CloudFlare domain api to automatically issue cert
If your dns provider support api access, we can use api to automatically issue certs.
You don't have do anything manually.
For now, we support clourflare integeration.
Current we support:
## Cloudflare.com api
## Dnspod.cn api
## Cloudxns.com api
First you need to login to your clourflare account to get your api key.
```
export CF_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"
export CF_Email="xxxx@sss.com"
```
Ok, let's issue cert now:
```
le.sh issue dns-cf aa.com www.aa.com
```
The `CF_Key` and `CF_Email` will be saved in `~/.le/account.conf`, when next time you use cloudflare api, it will reuse this key.
More api integerations are coming. Godaddy, etc....
# Use Dnspod.cn domain api to automatically issue cert
For now, we support dnspod.cn integeration.
First you need to login to your dnspod.cn account to get your api key and key id.
```
export DP_Id="1234"
export DP_Key="sADDsdasdgdsf"
```
Ok, let's issue cert now:
```
le.sh issue dns-dp aa.com www.aa.com
```
The `DP_Id` and `DP_Key` will be saved in `~/.le/account.conf`, when next time you use dnspod.cn api, it will reuse this key.
# Use custom api
If your api is not supported yet, you can write your own dns api.
Let's assume you want to name it 'myapi',
1. Create a bash script named `~/.le/dns-myapi.sh`,
2. In the scrypt, you must have a function named `dns-myapi-add()`. Which will be called by le.sh to add dns records.
3. Then you can use your api to issue cert like:
```
le.sh issue dns-myapi aa.com www.aa.com
```
For more details, please check our sample script: `dnsapi/dns-myapi.sh`
More apis are comming soon....
##If your dns provider is not in the supported list above, you write your own script api easily.
For more details: [How to use dns api](/Neilpang/le/blob/master/dnsapi/README.md)
#Under the Hood

234
dnsapi/dns-cx.sh Normal file
View File

@ -0,0 +1,234 @@
#!/bin/bash
# Cloudxns.com Domain api
#
#CX_Key="1234"
#
#CX_Secret="sADDsdasdgdsf"
CX_Api="https://www.cloudxns.net/api2"
#REST_API
######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns-cx-add() {
fulldomain=$1
txtvalue=$2
if [ -z "$CX_Key" ] || [ -z "$CX_Secret" ] ; then
_err "You don't specify cloudxns.com api key or secret yet."
_err "Please create you key and try again."
return 1
fi
REST_API=$CX_Api
#save the api key and email to the account conf file.
_saveaccountconf CX_Key "$CX_Key"
_saveaccountconf CX_Secret "$CX_Secret"
_debug "First detect the root zone"
if ! _get_root $fulldomain ; then
_err "invalid domain"
return 1
fi
existing_records $_domain $_sub_domain
_debug count "$count"
if [ "$?" != "0" ] ; then
_err "Error get existing records."
return 1
fi
if [ "$count" == "0" ] ; then
add_record $_domain $_sub_domain $txtvalue
else
update_record $_domain $_sub_domain $txtvalue
fi
if [ "$?" == "0" ] ; then
return 0
fi
return 1
}
#usage: root sub
#return if the sub record already exists.
#echos the existing records count.
# '0' means doesn't exist
existing_records() {
_debug "Getting txt records"
root=$1
sub=$2
if ! _rest GET "record/$_domain_id?:domain_id?host_id=0&offset=0&row_num=100" ; then
return 1
fi
count=0
seg=$(printf "$response" | grep -o "{[^{]*host\":\"$_sub_domain[^}]*}")
_debug seg "$seg"
if [ -z "$seg" ] ; then
return 0
fi
if printf "$response" | grep '"type":"TXT"' > /dev/null ; then
count=1
record_id=$(printf "$seg" | grep -o \"record_id\":\"[^\"]*\" | cut -d : -f 2 | tr -d \")
_debug record_id "$record_id"
return 0
fi
}
#add the txt record.
#usage: root sub txtvalue
add_record() {
root=$1
sub=$2
txtvalue=$3
fulldomain=$sub.$root
_info "Adding record"
if ! _rest POST "record" "{\"domain_id\": $_domain_id, \"host\":\"$_sub_domain\", \"value\":\"$txtvalue\", \"type\":\"TXT\",\"ttl\":600, \"line_id\":1}"; then
return 1
fi
return 0
}
#update the txt record
#Usage: root sub txtvalue
update_record() {
root=$1
sub=$2
txtvalue=$3
fulldomain=$sub.$root
_info "Updating record"
if _rest PUT "record/$record_id" "{\"domain_id\": $_domain_id, \"host\":\"$_sub_domain\", \"value\":\"$txtvalue\", \"type\":\"TXT\",\"ttl\":600, \"line_id\":1}" ; then
return 0
fi
return 1
}
#################### Private functions bellow ##################################
#_acme-challenge.www.domain.com
#returns
# _sub_domain=_acme-challenge.www
# _domain=domain.com
# _domain_id=sdjkglgdfewsdfg
_get_root() {
domain=$1
i=2
p=1
if ! _rest GET "domain" ; then
return 1
fi
while [ '1' ] ; do
h=$(printf $domain | cut -d . -f $i-100)
_debug h "$h"
if [ -z "$h" ] ; then
#not valid
return 1;
fi
if printf "$response" | grep "$h." ; then
seg=$(printf "$response" | grep -o "{[^{]*$h\.[^}]*\}" )
_debug seg "$seg"
_domain_id=$(printf "$seg" | grep -o \"id\":\"[^\"]*\" | cut -d : -f 2 | tr -d \")
_debug _domain_id "$_domain_id"
if [ "$_domain_id" ] ; then
_sub_domain=$(printf $domain | cut -d . -f 1-$p)
_debug _sub_domain $_sub_domain
_domain=$h
_debug _domain $_domain
return 0
fi
return 1
fi
p=$i
let "i+=1"
done
return 1
}
#Usage: method URI data
_rest() {
m=$1
ep="$2"
_debug $ep
url="$REST_API/$ep"
_debug url "$url"
cdate=$(date -u "+%Y-%m-%d %H:%M:%S UTC")
_debug cdate "$cdate"
data="$3"
_debug data "$data"
sec="$CX_Key$url$data$cdate$CX_Secret"
_debug sec "$sec"
hmac=$(printf "$sec"| openssl md5 |cut -d " " -f 2)
_debug hmac "$hmac"
if [ "$3" ] ; then
response="$(curl --silent -X $m "$url" -H "API-KEY: $CX_Key" -H "API-REQUEST-DATE: $cdate" -H "API-HMAC: $hmac" -H 'Content-Type: application/json' -d "$data")"
else
response="$(curl --silent -X $m "$url" -H "API-KEY: $CX_Key" -H "API-REQUEST-DATE: $cdate" -H "API-HMAC: $hmac" -H 'Content-Type: application/json')"
fi
if [ "$?" != "0" ] ; then
_err "error $ep"
return 1
fi
_debug response "$response"
if ! printf "$response" | grep '"message":"success"' > /dev/null ; then
return 1
fi
return 0
}
_debug() {
if [ -z "$DEBUG" ] ; then
return
fi
if [ -z "$2" ] ; then
echo $1
else
echo "$1"="$2"
fi
}
_info() {
if [ -z "$2" ] ; then
echo "$1"
else
echo "$1"="$2"
fi
}
_err() {
if [ -z "$2" ] ; then
echo "$1" >&2
else
echo "$1"="$2" >&2
fi
}

View File

@ -89,7 +89,7 @@ add_record() {
root=$1
sub=$2
txtvalue=$3
fulldomain=$sub.$$root
fulldomain=$sub.$root
_info "Adding record"

9
le.sh
View File

@ -1,5 +1,5 @@
#!/bin/bash
VER=1.1.4
VER=1.1.5
PROJECT="https://github.com/Neilpang/le"
DEFAULT_CA="https://acme-v01.api.letsencrypt.org"
@ -1066,6 +1066,7 @@ _initconf() {
#STAGE=1 # Use the staging api
#FORCE=1 # Force to issue cert
#DEBUG=1 # Debug mode
#dns api
#######################
@ -1082,6 +1083,12 @@ _initconf() {
#api key
#DP_Key="sADDsdasdgdsf"
#######################
#Cloudxns.com:
#CX_Key="1234"
#
#CX_Secret="sADDsdasdgdsf"
" > $ACCOUNT_CONF_PATH
fi
}