Merge e5ed9b1ac82bf7a2ce2aab47ad6e46c049932d24 into 61eaa44cf83d08a6060d9b11067f77bd570232f2

This commit is contained in:
Dan 2018-03-02 20:10:09 +00:00 committed by GitHub
commit f896f1ee59
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 435 additions and 624 deletions

View File

@ -2455,8 +2455,13 @@ _apachePath() {
if ! _exists apachectl; then
if _exists apache2ctl; then
_APACHECTL="apache2ctl"
elif _exists apache2; then #added
_APACHECTL="apache2" #added
elif _exists httpd; then #added
_APACHECTL="httpd" #added
else
_err "'apachectl not found. It seems that apache is not installed, or you are not root user.'"
_err "'apachectl (or apache2 or httpd) not found. It seems that apache is not installed, or you are not root user.'"
#_err "'apachectl not found. It seems that apache is not installed, or you are not root user.'"
_err "Please use webroot mode to try again."
return 1
fi

View File

@ -1,12 +1,218 @@
#!/usr/bin/env sh
# TESTING!!! #
#Here is a script to deploy cert to apache server.
#returns 0 means success, otherwise error.
#acme.sh --install-cert -d example.com \
#--cert-file /path/to/certfile/in/apache/cert.pem \
#--key-file /path/to/keyfile/in/apache/key.pem \
#--fullchain-file /path/to/fullchain/certfile/apache/fullchain.pem \
#--reloadcmd "service apache2 force-reload"
######## Public functions #####################
set -x
# get rid of _APACHECTL, and _exec after testing
_APACHECTL='httpd'
_exec() {
eval "$@"
}
## $1 : new cert location $2: cp to location
_cpCert() {
#return 0
if cp -f ${1} ${2} && chmod 600 ${2}; then
return 0
fi
return 1
}
_vhostBackupConf() {
#return 0
if cp -f "${1}" "${1}.bak"; then
return 0
fi
return 1
}
_vhostRestoreConf() {
#return 0
if cp -f "${1}.bak" "${1}"; then
return 0
fi
return 1
}
_testConf() {
if ! _exec $_APACHECTL -t; then
return 1
fi
return 0
}
## $1 : vhost config file to check and edit. $2: domain $3: port
_vhostConf() {
if ! _vhostBackupConf "$1"; then
# do something
testvar=''
fi
serverName=$(awk '/ServerName/,/$/' "$1")
serverName=$(awk -F ' ' '{print $2}' <<< ${serverName})
serverAlias=$(awk '/ServerAlias/,/$/' "$1")
serverAlias=$(awk -F ' ' '{print $2}' <<< ${serverAlias})
docRoot=$(awk '/DocumentRoot/,/$/' "$1")
docRoot=$(awk -F ' ' '{print $2}' <<< ${docRoot})
rootParent=$(dirname ${docRoot})
pri=$rootParent/ssl/private
pub=$rootParent/ssl/public
mkdir -m 700 -p ${pri:1}
mkdir -m 700 -p ${pub:1}
sslEng=$(awk '/SSLEngine/,/$/' "$1")
sslEng=$(awk -F ' ' '{print $2}' <<< ${sslEng})
sslPro=$(awk '/SSLProtocol/,/$/' "$1")
sslPro=$(awk -F ' ' '{print $2}' <<< ${sslPro})
sslCiph=$(awk '/SSLCipherSuite/,/$/' "$1")
sslCiph=$(awk -F ' ' '{print $2}' <<< ${sslCiph})
ciphOrd=$(awk '/SSLHonorCipherOrder/,/$/' "$1")
ciphOrd=$(awk -F ' ' '{print $2}' <<< ${ciphOrd})
crtFile=$(awk '/SSLCertificateFile/,/$/' "$1")
crtFile=$(awk -F ' ' '{print $2}' <<< ${crtFile})
keyFile=$(awk '/SSLCertificateKeyFile/,/$/' "$1")
keyFile=$(awk -F ' ' '{print $2}' <<< ${keyFile})
chainFile=$(awk '/SSLCertificateChainFile/,/$/' "$1")
chainFile=$(awk -F ' ' '{print $2}' <<< ${chainFile})
locSec1='<location '
locSec2='>'
locSec=$locSec1$docRoot$locSec2
dirSlash=$(awk '/DirectorySlash/,/$/' "$1")
dirSlash=$(awk -F ' ' '{print $2}' <<< ${dirSlash})
rewriteEng=$(awk '/RewriteEngine/,/$/' "$1")
rewriteEng=$(awk -F ' ' '{print $2}' <<< ${rewriteEng})
rwCond1=$(awk '/RewriteCond %{HTTPS}/,/$/' "$1")
rwCond1=$(awk -F ' ' '{print $2}' <<< ${rwCond1})
rwCond2=$(awk '/RewriteCond %{HTTP_HOST}/,/$/' "$1")
rwCond2=$(awk -F ' ' '{print $2}' <<< ${rwCond2})
rwCond3=$(awk '/RewriteCond %{REQUEST_URI}/,/$/' "$1")
rwCond3=$(awk -F ' ' '{print $2}' <<< ${rwCond3})
rwRuleSsl=$(awk '/RewriteRule .*/,/$/' "$1")
rwRuleSsl=$(awk -F ' ' '{print $2}' <<< ${rwRuleSsl})
newRwRuleSsl1='RewriteRule .* https://'
newRwRuleSsl2='/%{REQUEST_URI}/ [R=301,L,QSA]'
newRwRuleSsl=$newRwRuleSsl1$serverName$newRwRuleSsl2
if [ ! -z "${serverName}" ]; then
# it is probably an alias on a wildcard port 80
# so we will find where docroot matches and redirect there
confRoot=$(dirname "$1")
#confMatch=$(grep "$docRoot" "$configRoot/*.conf" /dev/null | head -n 1)
confMatch="$(grep "${docRoot}" "${confRoot}"/*.conf /dev/null | head -n 1 | awk -F ':' '{print $1}')"
if [ ! -z "${confMatch}" ]; then
#confMatch="$(awk -F ':' '{print $1}' <<< ${confMatch})"
matchServerName=$(awk '/ServerName/,/$/' "${confMatch}")
matchServerName=$(awk -F ' ' '{print $2}' <<< "${matchServerName}")
reWriteBlock=$(cat <<EOF
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* https://${matchServerName}/%{REQUEST_URI}/ [R=301,L,QSA]
</IfModule>
EOF
)
sed -i '/"${reWriteBlock}"/i </virtualhost>' "${confMatch}"
return 0
fi
return 1
fi
if grep -q 'SSLEngine' "$1"; then
sed -i '/SSLEngine /c\SSLEngine On' "$1"
sed -i '/SSLProtocol /c\SSLProtocol -all +TLSv1.2' "$1"
sed -i '/SSLCipherSuite /c\SSLCipherSuite ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS' "$1"
sed -i '/SSLHonorCipherOrder /c\SSLHonorCipherOrder on' "$1"
sed -i '/SSLCertificateFile /c\SSLCertificateFile ${rootParent}/ssl/public/${serverName}.crt' "$1"
sed -i '/SSLCertificateChainFile /c\SSLCertificateChainFile ${rootParent}/ssl/public/${serverName}.chain.crt' "$1"
sed -i '/SSLCertificateKeyFile /c\SSLCertificateKeyFile ${rootParent}/ssl/private/${serverName}.key' "$1"
testvar=''
else
sslBlock=$(cat <<EOF
<virtualhost *:443>
ServerName ${serverName}
DocumentRoot ${docRoot}
SSLEngine On
SSLProtocol -all +TLSv1.2
SSLCipherSuite ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS
SSLHonorCipherOrder on
SSLCertificateFile ${rootParent}/ssl/public/${serverName}.crt
SSLCertificateChainFile ${rootParent}/ssl/public/${serverName}.chain.crt
SSLCertificateKeyFile ${rootParent}/ssl/private/${serverName}.key
${locSec}
DirectorySlash On
</location>
</virtualhost>
EOF
)
echo "${sslBlock}" >> "$1"
fi
#look for a location section eg. <location /var/www/html>
if grep -q ${locSec} "$1"; then
if grep -q ${dirSlash} "$1"; then
#set dir slash on
sed -i '/DirectorySlash /c\DirectorySlash On' "$1"
testvar=''
else
#append dir slash here
sed -i '/${locSec}/a DirectorySlash On' "$1"
testvar=''
fi
else
locBlock=$(cat <<EOF
${locSec}
DirectorySlash On
</location>
EOF
)
# insert the new block here...
sed -i '/<\/virtualhost>/i ${locBlock}' "$1"
fi
#look for mod_rewrite section
modReWrite='<IfModule mod_rewrite.c>'
if grep -q ${modReWrite} "$1"; then
if grep -q "RewriteEngine On" "$1"; then
#set rewrite rules for ssl
# too many ways to redirect ssl for me to check....
testvar=''
else
#append rewrite rules for ssl
sed -i '/${modReWrite}/a RewriteEngine On' "$1"
sed -i '/RewriteEngine On/a RewriteCond %{HTTPS} !on [OR]' "$1"
sed -i '/RewriteCond %{HTTPS} !on [OR]/a RewriteCond %{HTTP_HOST} ^www\. [NC] [OR]' "$1"
sed -i '/RewriteCond %{HTTP_HOST} ^www\. [NC] [OR]/a RewriteCond %{REQUEST_URI} !(.*)/$' "$1"
sed -i '/RewriteCond %{REQUEST_URI} !(.*)/$/a ${newRwRuleSsl}' "$1"
testvar=''
fi
else
reWriteBlock=$(cat <<EOF
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} !on [OR]
RewriteCond %{HTTP_HOST} ^www\. [NC] [OR]
RewriteCond %{REQUEST_URI} !(.*)/$
${newRwRuleSsl}
</IfModule>
EOF
)
# insert the new block here...
sed -i '/<\/virtualhost>/i ${reWriteBlock}' "$1"
fi
return
}
#domain keyfile certfile cafile fullchain
apache_deploy() {
_cdomain="$1"
_ckey="$2"
@ -14,13 +220,39 @@ apache_deploy() {
_cca="$4"
_cfullchain="$5"
_debug _cdomain "$_cdomain"
_debug _ckey "$_ckey"
_debug _ccert "$_ccert"
_debug _cca "$_cca"
_debug _cfullchain "$_cfullchain"
all_hosts=$(eval "$_APACHECTL -S" | awk '/namevhost/,/\)/')
#echo "$all_hosts"
oldIFS=$IFS
IFS='
'
loopLog=''
for h in $all_hosts; do
d=$(awk -F ' ' '{print $4}' <<< "${h}")
c=$(awk -F ' ' '{print $5}' <<< "${h}")
c=$(echo "$c" | awk -v FS="(\\\\(|\\\\:)" '{print $2}')
p=$(awk -F ' ' '{print $2}' <<< "${h}")
#echo "$d $p $c"
if echo ${d} | grep -q ${_cdomain}; then
if _vhostConf "$c" "$d" "$p"; then
c1='/ssl/public/'
c2='/ssl/private/'
k='.key'
k1=$rootParent$c2$d$k
c3='.crt'
c4='.chain.crt'
c5=$rootParent$c1$d$c3
c6=$rootParent$c1$d$c4
cp -f $_ckey ${k1:1}
cp -f $_ccert ${c5:1}
cp -f $_cfullchain ${c6:1}
_err "Deploy cert to apache server, Not implemented yet"
return 1
fi
fi
done
IFS=$oldIFS
}
apache_deploy idragonfly.net /path/to/test.key /path/to/test.crt /path/to/test.cacert.crt /path/to/test.chain.crt
#echo "$testLog" >> test.log
set +x

View File

@ -92,6 +92,21 @@ acme.sh --issue --dns dns_pdns -d example.com -d www.example.com
The `PDNS_Url`, `PDNS_ServerId`, `PDNS_Token` and `PDNS_Ttl` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
## 5a. Use PowerDNS mysql backend to automatically issue cert
First you need to set your host:user:pass:database in the configuration.
Make sure the following are in your records table:
INSERT INTO `records` (`domain_id`, `name`, `type`, `content`, `ttl`, `prio`, `change_date`)
VALUES ({your domain_id}, 'example.com', 'SOA', 'ns1.example.com.net admin.example.com 1 10800 3600 604800 3600', 120, NULL, 0),
({your domain_id}, '_acme-challenge.example.com', 'A', '{ipv4 address}', 60, NULL, 0),
({your domain_id}, '_acme-challenge.example.com', 'AAAA', '{ipv6 address}', 60, NULL, NULL, 'N', 0, NULL, 0),
({your domain_id}, 'example.com', 'CAA', '0 issue "letsencrypt.org"', 60, NULL, 0);
Ok, let's issue a cert now:
```
acme.sh --issue --dns dns_pdnsMysql -d example.com -d *.example.com
```
## 6. Use OVH/kimsufi/soyoustart/runabove API to automatically issue cert

View File

@ -1,147 +0,0 @@
#!/usr/bin/env sh
#
#AD_API_KEY="sdfsdfsdfljlbjkljlkjsdfoiwje"
#This is the Alwaysdata api wrapper for acme.sh
#
#Author: Paul Koppen
#Report Bugs here: https://github.com/wpk-/acme.sh
AD_API_URL="https://$AD_API_KEY:@api.alwaysdata.com/v1"
######## Public functions #####################
#Usage: dns_myapi_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_ad_add() {
fulldomain=$1
txtvalue=$2
if [ -z "$AD_API_KEY" ]; then
AD_API_KEY=""
_err "You didn't specify the AD api key yet."
_err "Please create you key and try again."
return 1
fi
_saveaccountconf AD_API_KEY "$AD_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"
_ad_tmpl_json="{\"domain\":$_domain_id,\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"value\":\"$txtvalue\"}"
if _ad_rest POST "record/" "$_ad_tmpl_json" && [ -z "$response" ]; then
_info "txt record updated success."
return 0
fi
return 1
}
#fulldomain txtvalue
dns_ad_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"
_ad_rest GET "record/?domain=$_domain_id&name=$_sub_domain"
if [ -n "$response" ]; then
record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":\s*[0-9]+" | cut -d : -f 2 | tr -d " " | _head_n 1)
_debug record_id "$record_id"
if [ -z "$record_id" ]; then
_err "Can not get record id to remove."
return 1
fi
if _ad_rest DELETE "record/$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 _ad_rest GET "domain/"; 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
_ad_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" "$AD_API_URL/$ep" "" "$mtd")"
else
response="$(_get "$AD_API_URL/$ep")"
fi
if [ "$?" != "0" ]; then
_err "error $ep"
return 1
fi
_debug2 response "$response"
return 0
}

View File

@ -1,202 +0,0 @@
#!/usr/bin/env sh
Ali_API="https://alidns.aliyuncs.com/"
#Ali_Key="LTqIA87hOKdjevsf5"
#Ali_Secret="0p5EYueFNq501xnCPzKNbx6K51qPH2"
#Usage: dns_ali_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_ali_add() {
fulldomain=$1
txtvalue=$2
Ali_Key="${Ali_Key:-$(_readaccountconf_mutable Ali_Key)}"
Ali_Secret="${Ali_Secret:-$(_readaccountconf_mutable Ali_Secret)}"
if [ -z "$Ali_Key" ] || [ -z "$Ali_Secret" ]; then
Ali_Key=""
Ali_Secret=""
_err "You don't specify aliyun api key and secret yet."
return 1
fi
#save the api key and secret to the account conf file.
_saveaccountconf_mutable Ali_Key "$Ali_Key"
_saveaccountconf_mutable Ali_Secret "$Ali_Secret"
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
return 1
fi
_debug "Add record"
_add_record_query "$_domain" "$_sub_domain" "$txtvalue" && _ali_rest "Add record"
}
dns_ali_rm() {
fulldomain=$1
txtvalue=$2
Ali_Key="${Ali_Key:-$(_readaccountconf_mutable Ali_Key)}"
Ali_Secret="${Ali_Secret:-$(_readaccountconf_mutable Ali_Secret)}"
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
return 1
fi
_clean
}
#################### Private functions below ##################################
_get_root() {
domain=$1
i=2
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
if [ -z "$h" ]; then
#not valid
return 1
fi
_describe_records_query "$h"
if ! _ali_rest "Get root" "ignore"; then
return 1
fi
if _contains "$response" "PageNumber"; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_debug _sub_domain "$_sub_domain"
_domain="$h"
_debug _domain "$_domain"
return 0
fi
p="$i"
i=$(_math "$i" + 1)
done
return 1
}
_ali_rest() {
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"
if ! response="$(_get "$url")"; then
_err "Error <$1>"
return 1
fi
_debug2 response "$response"
if [ -z "$2" ]; then
message="$(echo "$response" | _egrep_o "\"Message\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \")"
if [ "$message" ]; then
_err "$message"
return 1
fi
fi
}
_ali_urlencode() {
_str="$1"
_str_len=${#_str}
_u_i=1
while [ "$_u_i" -le "$_str_len" ]; do
_str_c="$(printf "%s" "$_str" | cut -c "$_u_i")"
case $_str_c in [a-zA-Z0-9.~_-])
printf "%s" "$_str_c"
;;
*)
printf "%%%02X" "'$_str_c"
;;
esac
_u_i="$(_math "$_u_i" + 1)"
done
}
_ali_nonce() {
#_head_n 1 </dev/urandom | _digest "sha256" hex | cut -c 1-31
#Not so good...
date +"%s%N"
}
_check_exist_query() {
_qdomain="$1"
_qsubdomain="$2"
query=''
query=$query'AccessKeyId='$Ali_Key
query=$query'&Action=DescribeDomainRecords'
query=$query'&DomainName='$_qdomain
query=$query'&Format=json'
query=$query'&RRKeyWord='$_qsubdomain
query=$query'&SignatureMethod=HMAC-SHA1'
query=$query"&SignatureNonce=$(_ali_nonce)"
query=$query'&SignatureVersion=1.0'
query=$query'&Timestamp='$(_timestamp)
query=$query'&TypeKeyWord=TXT'
query=$query'&Version=2015-01-09'
}
_add_record_query() {
query=''
query=$query'AccessKeyId='$Ali_Key
query=$query'&Action=AddDomainRecord'
query=$query'&DomainName='$1
query=$query'&Format=json'
query=$query'&RR='$2
query=$query'&SignatureMethod=HMAC-SHA1'
query=$query"&SignatureNonce=$(_ali_nonce)"
query=$query'&SignatureVersion=1.0'
query=$query'&Timestamp='$(_timestamp)
query=$query'&Type=TXT'
query=$query'&Value='$3
query=$query'&Version=2015-01-09'
}
_delete_record_query() {
query=''
query=$query'AccessKeyId='$Ali_Key
query=$query'&Action=DeleteDomainRecord'
query=$query'&Format=json'
query=$query'&RecordId='$1
query=$query'&SignatureMethod=HMAC-SHA1'
query=$query"&SignatureNonce=$(_ali_nonce)"
query=$query'&SignatureVersion=1.0'
query=$query'&Timestamp='$(_timestamp)
query=$query'&Version=2015-01-09'
}
_describe_records_query() {
query=''
query=$query'AccessKeyId='$Ali_Key
query=$query'&Action=DescribeDomainRecords'
query=$query'&DomainName='$1
query=$query'&Format=json'
query=$query'&SignatureMethod=HMAC-SHA1'
query=$query"&SignatureNonce=$(_ali_nonce)"
query=$query'&SignatureVersion=1.0'
query=$query'&Timestamp='$(_timestamp)
query=$query'&Version=2015-01-09'
}
_clean() {
_check_exist_query "$_domain" "$_sub_domain"
if ! _ali_rest "Check exist records" "ignore"; then
return 1
fi
record_id="$(echo "$response" | tr '{' "\n" | grep "$_sub_domain" | grep "$txtvalue" | tr "," "\n" | grep RecordId | cut -d '"' -f 4)"
_debug2 record_id "$record_id"
if [ -z "$record_id" ]; then
_debug "record not found, skip"
else
_delete_record_query "$record_id"
_ali_rest "Delete record $record_id" "ignore"
fi
}
_timestamp() {
date -u +"%Y-%m-%dT%H%%3A%M%%3A%SZ"
}

View File

@ -1,264 +0,0 @@
#!/usr/bin/env sh
# -*- mode: sh; tab-width: 2; indent-tabs-mode: s; coding: utf-8 -*-
# This is the InternetX autoDNS xml api wrapper for acme.sh
# Author: auerswald@gmail.com
# Created: 2018-01-14
#
# export AUTODNS_USER="username"
# export AUTODNS_PASSWORD="password"
# export AUTODNS_CONTEXT="context"
#
# Usage:
# acme.sh --issue --dns dns_autodns -d example.com
AUTODNS_API="https://gateway.autodns.com"
# Arguments:
# txtdomain
# txt
dns_autodns_add() {
fulldomain="$1"
txtvalue="$2"
AUTODNS_USER="${AUTODNS_USER:-$(_readaccountconf_mutable AUTODNS_USER)}"
AUTODNS_PASSWORD="${AUTODNS_PASSWORD:-$(_readaccountconf_mutable AUTODNS_PASSWORD)}"
AUTODNS_CONTEXT="${AUTODNS_CONTEXT:-$(_readaccountconf_mutable AUTODNS_CONTEXT)}"
if [ -z "$AUTODNS_USER" ] || [ -z "$AUTODNS_CONTEXT" ] || [ -z "$AUTODNS_PASSWORD" ]; then
_err "You don't specify autodns user, password and context."
return 1
fi
_saveaccountconf_mutable AUTODNS_USER "$AUTODNS_USER"
_saveaccountconf_mutable AUTODNS_PASSWORD "$AUTODNS_PASSWORD"
_saveaccountconf_mutable AUTODNS_CONTEXT "$AUTODNS_CONTEXT"
_debug "First detect the root zone"
if ! _get_autodns_zone "$fulldomain"; then
_err "invalid domain"
return 1
fi
_debug _sub_domain "$_sub_domain"
_debug _zone "$_zone"
_debug _system_ns "$_system_ns"
_info "Adding TXT record"
autodns_response="$(_autodns_zone_update "$_zone" "$_sub_domain" "$txtvalue" "$_system_ns")"
if [ "$?" -eq "0" ]; then
_info "Added, OK"
return 0
fi
return 1
}
# Arguments:
# txtdomain
# txt
dns_autodns_rm() {
fulldomain="$1"
txtvalue="$2"
AUTODNS_USER="${AUTODNS_USER:-$(_readaccountconf_mutable AUTODNS_USER)}"
AUTODNS_PASSWORD="${AUTODNS_PASSWORD:-$(_readaccountconf_mutable AUTODNS_PASSWORD)}"
AUTODNS_CONTEXT="${AUTODNS_CONTEXT:-$(_readaccountconf_mutable AUTODNS_CONTEXT)}"
if [ -z "$AUTODNS_USER" ] || [ -z "$AUTODNS_CONTEXT" ] || [ -z "$AUTODNS_PASSWORD" ]; then
_err "You don't specify autodns user, password and context."
return 1
fi
_debug "First detect the root zone"
if ! _get_autodns_zone "$fulldomain"; then
_err "zone not found"
return 1
fi
_debug _sub_domain "$_sub_domain"
_debug _zone "$_zone"
_debug _system_ns "$_system_ns"
_info "Delete TXT record"
autodns_response="$(_autodns_zone_cleanup "$_zone" "$_sub_domain" "$txtvalue" "$_system_ns")"
if [ "$?" -eq "0" ]; then
_info "Deleted, OK"
return 0
fi
return 1
}
#################### Private functions below ##################################
# Arguments:
# fulldomain
# Returns:
# _sub_domain=_acme-challenge.www
# _zone=domain.com
# _system_ns
_get_autodns_zone() {
domain="$1"
i=2
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
_debug h "$h"
if [ -z "$h" ]; then
# not valid
return 1
fi
autodns_response="$(_autodns_zone_inquire "$h")"
if [ "$?" -ne "0" ]; then
_err "invalid domain"
return 1
fi
if _contains "$autodns_response" "<summary>1</summary>" >/dev/null; then
_zone="$(echo "$autodns_response" | _egrep_o '<name>[^<]*</name>' | cut -d '>' -f 2 | cut -d '<' -f 1)"
_system_ns="$(echo "$autodns_response" | _egrep_o '<system_ns>[^<]*</system_ns>' | cut -d '>' -f 2 | cut -d '<' -f 1)"
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
return 0
fi
p=$i
i=$(_math "$i" + 1)
done
return 1
}
_build_request_auth_xml() {
printf "<auth>
<user>%s</user>
<password>%s</password>
<context>%s</context>
</auth>" "$AUTODNS_USER" "$AUTODNS_PASSWORD" "$AUTODNS_CONTEXT"
}
# Arguments:
# zone
_build_zone_inquire_xml() {
printf "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<request>
%s
<task>
<code>0205</code>
<view>
<children>1</children>
<limit>1</limit>
</view>
<where>
<key>name</key>
<operator>eq</operator>
<value>%s</value>
</where>
</task>
</request>" "$(_build_request_auth_xml)" "$1"
}
# Arguments:
# zone
# subdomain
# txtvalue
# system_ns
_build_zone_update_xml() {
printf "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<request>
%s
<task>
<code>0202001</code>
<default>
<rr_add>
<name>%s</name>
<ttl>600</ttl>
<type>TXT</type>
<value>%s</value>
</rr_add>
</default>
<zone>
<name>%s</name>
<system_ns>%s</system_ns>
</zone>
</task>
</request>" "$(_build_request_auth_xml)" "$2" "$3" "$1" "$4"
}
# Arguments:
# zone
_autodns_zone_inquire() {
request_data="$(_build_zone_inquire_xml "$1")"
autodns_response="$(_autodns_api_call "$request_data")"
ret="$?"
printf "%s" "$autodns_response"
return "$ret"
}
# Arguments:
# zone
# subdomain
# txtvalue
# system_ns
_autodns_zone_update() {
request_data="$(_build_zone_update_xml "$1" "$2" "$3" "$4")"
autodns_response="$(_autodns_api_call "$request_data")"
ret="$?"
printf "%s" "$autodns_response"
return "$ret"
}
# Arguments:
# zone
# subdomain
# txtvalue
# system_ns
_autodns_zone_cleanup() {
request_data="$(_build_zone_update_xml "$1" "$2" "$3" "$4")"
# replace 'rr_add>' with 'rr_rem>' in request_data
request_data="$(printf -- "%s" "$request_data" | sed 's/rr_add>/rr_rem>/g')"
autodns_response="$(_autodns_api_call "$request_data")"
ret="$?"
printf "%s" "$autodns_response"
return "$ret"
}
# Arguments:
# request_data
_autodns_api_call() {
request_data="$1"
_debug request_data "$request_data"
autodns_response="$(_post "$request_data" "$AUTODNS_API")"
ret="$?"
_debug autodns_response "$autodns_response"
if [ "$ret" -ne "0" ]; then
_err "error"
return 1
fi
if _contains "$autodns_response" "<type>success</type>" >/dev/null; then
_info "success"
printf "%s" "$autodns_response"
return 0
fi
return 1
}

172
dnsapi/dns_pdnsMysql.sh Normal file
View File

@ -0,0 +1,172 @@
#!/usr/bin/env sh
#PowerDNS Mysql backend
#
#
PDNS_Host="example.com"
PDNS_Port=3306
PDNS_User="username"
PDNS_Pass="password"
PDNS_Database="powerdns"
PDNS_Ttl=60
DEFAULT_PDNS_TTL=60
######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "123456789ABCDEF0000000000000000000000000000000000000"
#fulldomain
#txtvalue
dns_pdnsMysql_add() {
fulldomain=$1
txtvalue=$2
if [ -z "$PDNS_Host" ]; then
PDNS_Url=""
_err "You didn't specify PowerDNS Mysql address."
_err "Please set PDNS_Host and try again."
return 1
fi
if [ -z "$PDNS_Port" ]; then
PDNS_Url=""
_err "You didn't specify PowerDNS Mysql Port."
_err "Please set PDNS_Port and try again."
return 1
fi
if [ -z "$PDNS_User" ]; then
PDNS_User=""
_err "You didn't specify PowerDNS Mysql username."
_err "Please set PDNS_User and try again."
return 1
fi
if [ -z "$PDNS_Pass" ]; then
PDNS_Pass=""
_err "You didn't specify PowerDNS Mysql password."
_err "Please set PDNS_Pass and try again."
return 1
fi
if [ -z "$PDNS_Database" ]; then
PDNS_Database=""
_err "You didn't specify PowerDNS Mysql database."
_err "Please set PDNS_Database and try again."
return 1
fi
if [ -z "$PDNS_Ttl" ]; then
PDNS_Ttl="$DEFAULT_PDNS_TTL"
fi
#save the api addr and key to the account conf file.
_saveaccountconf PDNS_Host "$PDNS_Host"
_saveaccountconf PDNS_Port "$PDNS_Port"
_saveaccountconf PDNS_User "$PDNS_User"
_saveaccountconf PDNS_Pass "$PDNS_Pass"
_saveaccountconf PDNS_Database "$PDNS_Database"
if [ "$PDNS_Ttl" != "$DEFAULT_PDNS_TTL" ]; then
_saveaccountconf PDNS_Ttl "$PDNS_Ttl"
fi
_debug "Detect root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"
return 1
fi
_debug _domain "$_domain"
if ! set_record "$_domain" "$fulldomain" "$txtvalue"; then
return 1
fi
return 0
}
#fulldomain
dns_pdnsMysql_rm() {
fulldomain=$1
_debug "Detect root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"
return 1
fi
_debug _domain "$_domain"
if ! rm_record "$_domain" "$fulldomain"; then
return 1
fi
return 0
}
set_record() {
_info "Adding record"
root=$1
full=$2
txtvalue=$3
_domain_id=$(mysql -ss "-h${PDNS_Host}" "-P${PDNS_Port}" "-u${PDNS_User}" "-p${PDNS_Pass}" -e "SELECT id FROM ${PDNS_Database}.domains WHERE name='${root}'")
# insert challenge.
mysql -ss "-h${PDNS_Host}" "-P${PDNS_Port}" "-u${PDNS_User}" "-p${PDNS_Pass}" -e "INSERT INTO ${PDNS_Database}.records (domain_id,name, content, type,ttl,prio) VALUES \
(${_domain_id},'${full}','${txtvalue}','TXT',60,NULL);"
if ! notify_slaves "$root"; then
return 1
fi
return 0
}
rm_record() {
_info "Remove record"
root=$1
full=$2
mysql -ss "-h${PDNS_Host}" "-P${PDNS_Port}" "-u${PDNS_User}" "-p${PDNS_Pass}" -e "DELETE FROM ${PDNS_Database}.records WHERE name='${full}' AND type='TXT';"
if ! notify_slaves "$root"; then
return 1
fi
return 0
}
notify_slaves() {
root=$1
# hack set last_check to null to force update. #
mysql -ss "-h${PDNS_Host}" "-P${PDNS_Port}" "-u${PDNS_User}" "-p${PDNS_Pass}" -e "UPDATE ${PDNS_Database}.domains SET last_check=NULL WHERE name='${root}';"
return 0
}
#################### Private functions below ##################################
#_acme-challenge.www.domain.com
#returns
# _domain=domain.com
_get_root() {
domain=$1
i=1
_pdns_domains=$(mysql -ss "-h${PDNS_Host}" "-P${PDNS_Port}" "-u${PDNS_User}" "-p${PDNS_Pass}" -e "SELECT name FROM ${PDNS_Database}.domains")
if [ -z "$_pdns_domains" ]; then
return 1
fi
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
if [ -z "$h" ]; then
return 1
fi
if _contains "$_pdns_domains" "$h"; then
_domain="$h"
return 0
fi
i=$(_math $i + 1)
done
_debug "$domain not found"
return 1
}