Compare commits

...
91 Commits
19 changed files with 1034 additions and 83 deletions
+1 -10
View File
@@ -13,12 +13,6 @@ env:
global: global:
- SHFMT_URL=https://github.com/mvdan/sh/releases/download/v0.4.0/shfmt_v0.4.0_linux_amd64 - SHFMT_URL=https://github.com/mvdan/sh/releases/download/v0.4.0/shfmt_v0.4.0_linux_amd64
addons:
apt:
sources:
- debian-sid # Grab shellcheck from the Debian repo (o_O)
packages:
- shellcheck
install: install:
- if [ "$TRAVIS_OS_NAME" = 'osx' ]; then - if [ "$TRAVIS_OS_NAME" = 'osx' ]; then
@@ -29,9 +23,7 @@ install:
script: script:
- echo "NGROK_TOKEN=$(echo "$NGROK_TOKEN" | wc -c)" - echo "NGROK_TOKEN=$(echo "$NGROK_TOKEN" | wc -c)"
- command -V openssl && openssl version - command -V openssl && openssl version
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then curl -sSL $SHFMT_URL -o ~/shfmt ; fi - if [ "$TRAVIS_OS_NAME" = "linux" ]; then curl -sSL $SHFMT_URL -o ~/shfmt && chmod +x ~/shfmt && ~/shfmt -l -w -i 2 . ; fi
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then chmod +x ~/shfmt ; fi
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then ~/shfmt -l -w -i 2 . ; fi
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then git diff --exit-code && echo "shfmt OK" ; fi - if [ "$TRAVIS_OS_NAME" = "linux" ]; then git diff --exit-code && echo "shfmt OK" ; fi
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then shellcheck -V ; fi - if [ "$TRAVIS_OS_NAME" = "linux" ]; then shellcheck -V ; fi
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then shellcheck -e SC2181 **/*.sh && echo "shellcheck OK" ; fi - if [ "$TRAVIS_OS_NAME" = "linux" ]; then shellcheck -e SC2181 **/*.sh && echo "shellcheck OK" ; fi
@@ -40,7 +32,6 @@ script:
- if [ "$TRAVIS_OS_NAME" = "linux" -a "$NGROK_TOKEN" ]; then sudo TEST_LOCAL="$TEST_LOCAL" NGROK_TOKEN="$NGROK_TOKEN" ./rundocker.sh testplat ubuntu:latest ; fi - if [ "$TRAVIS_OS_NAME" = "linux" -a "$NGROK_TOKEN" ]; then sudo TEST_LOCAL="$TEST_LOCAL" NGROK_TOKEN="$NGROK_TOKEN" ./rundocker.sh testplat ubuntu:latest ; fi
- if [ "$TRAVIS_OS_NAME" = "osx" -a "$NGROK_TOKEN" ]; then sudo TEST_LOCAL="$TEST_LOCAL" NGROK_TOKEN="$NGROK_TOKEN" ACME_OPENSSL_BIN="$ACME_OPENSSL_BIN" ./letest.sh ; fi - if [ "$TRAVIS_OS_NAME" = "osx" -a "$NGROK_TOKEN" ]; then sudo TEST_LOCAL="$TEST_LOCAL" NGROK_TOKEN="$NGROK_TOKEN" ACME_OPENSSL_BIN="$ACME_OPENSSL_BIN" ./letest.sh ; fi
matrix: matrix:
fast_finish: true fast_finish: true
+1
View File
@@ -3,6 +3,7 @@ FROM alpine:3.6
RUN apk update -f \ RUN apk update -f \
&& apk --no-cache add -f \ && apk --no-cache add -f \
openssl \ openssl \
coreutils \
curl \ curl \
socat \ socat \
&& rm -rf /var/cache/apk/* && rm -rf /var/cache/apk/*
+5 -2
View File
@@ -33,7 +33,7 @@ Twitter: [@neilpangxa](https://twitter.com/neilpangxa)
- [webfaction](https://community.webfaction.com/questions/19988/using-letsencrypt) - [webfaction](https://community.webfaction.com/questions/19988/using-letsencrypt)
- [Loadbalancer.org](https://www.loadbalancer.org/blog/loadbalancer-org-with-lets-encrypt-quick-and-dirty) - [Loadbalancer.org](https://www.loadbalancer.org/blog/loadbalancer-org-with-lets-encrypt-quick-and-dirty)
- [discourse.org](https://meta.discourse.org/t/setting-up-lets-encrypt/40709) - [discourse.org](https://meta.discourse.org/t/setting-up-lets-encrypt/40709)
- [Centminmod](http://centminmod.com/letsencrypt-acmetool-https.html) - [Centminmod](https://centminmod.com/letsencrypt-acmetool-https.html)
- [splynx](https://forum.splynx.com/t/free-ssl-cert-for-splynx-lets-encrypt/297) - [splynx](https://forum.splynx.com/t/free-ssl-cert-for-splynx-lets-encrypt/297)
- [archlinux](https://aur.archlinux.org/packages/acme.sh-git/) - [archlinux](https://aur.archlinux.org/packages/acme.sh-git/)
- [opnsense.org](https://github.com/opnsense/plugins/tree/master/security/acme-client/src/opnsense/scripts/OPNsense/AcmeClient) - [opnsense.org](https://github.com/opnsense/plugins/tree/master/security/acme-client/src/opnsense/scripts/OPNsense/AcmeClient)
@@ -317,7 +317,10 @@ You don't have to do anything manually!
1. DirectAdmin API 1. DirectAdmin API
1. KingHost (https://www.kinghost.com.br/) 1. KingHost (https://www.kinghost.com.br/)
1. Zilore (https://zilore.com) 1. Zilore (https://zilore.com)
1. Loopia.se API
1. acme-dns (https://github.com/joohoi/acme-dns)
1. TELE3 (https://www.tele3.cz)
1. EUSERV.EU (https://www.euserv.eu)
And: And:
+29 -19
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env sh #!/usr/bin/env sh
VER=2.7.8 VER=2.7.9
PROJECT_NAME="acme.sh" PROJECT_NAME="acme.sh"
@@ -124,21 +124,21 @@ if [ -t 1 ]; then
fi fi
__green() { __green() {
if [ "$__INTERACTIVE${ACME_NO_COLOR}" = "1" ]; then if [ "$__INTERACTIVE${ACME_NO_COLOR}" = "1" -o "${ACME_FORCE_COLOR}" = "1" ]; then
printf '\033[1;31;32m' printf '\033[1;31;32m'
fi fi
printf -- "%b" "$1" printf -- "%b" "$1"
if [ "$__INTERACTIVE${ACME_NO_COLOR}" = "1" ]; then if [ "$__INTERACTIVE${ACME_NO_COLOR}" = "1" -o "${ACME_FORCE_COLOR}" = "1" ]; then
printf '\033[0m' printf '\033[0m'
fi fi
} }
__red() { __red() {
if [ "$__INTERACTIVE${ACME_NO_COLOR}" = "1" ]; then if [ "$__INTERACTIVE${ACME_NO_COLOR}" = "1" -o "${ACME_FORCE_COLOR}" = "1" ]; then
printf '\033[1;31;40m' printf '\033[1;31;40m'
fi fi
printf -- "%b" "$1" printf -- "%b" "$1"
if [ "$__INTERACTIVE${ACME_NO_COLOR}" = "1" ]; then if [ "$__INTERACTIVE${ACME_NO_COLOR}" = "1" -o "${ACME_FORCE_COLOR}" = "1" ]; then
printf '\033[0m' printf '\033[0m'
fi fi
} }
@@ -1607,7 +1607,7 @@ _inithttp() {
} }
# body url [needbase64] [POST|PUT] [ContentType] # body url [needbase64] [POST|PUT|DELETE] [ContentType]
_post() { _post() {
body="$1" body="$1"
_post_url="$2" _post_url="$2"
@@ -1897,7 +1897,7 @@ _send_signed_request() {
_debug3 _body "$_body" _debug3 _body "$_body"
fi fi
if _contains "$_body" "JWS has invalid anti-replay nonce"; then if _contains "$_body" "JWS has invalid anti-replay nonce" || _contains "$_body" "JWS has an invalid anti-replay nonce"; then
_info "It seems the CA server is busy now, let's wait and retry." _info "It seems the CA server is busy now, let's wait and retry."
_sleep 5 _sleep 5
continue continue
@@ -4287,20 +4287,21 @@ $_authorizations_map"
Le_NextRenewTime=$(_math "$Le_NextRenewTime" - 86400) Le_NextRenewTime=$(_math "$Le_NextRenewTime" - 86400)
_savedomainconf "Le_NextRenewTime" "$Le_NextRenewTime" _savedomainconf "Le_NextRenewTime" "$Le_NextRenewTime"
if ! _on_issue_success "$_post_hook" "$_renew_hook"; then
_err "Call hook error."
return 1
fi
if [ "$_real_cert$_real_key$_real_ca$_reload_cmd$_real_fullchain" ]; then if [ "$_real_cert$_real_key$_real_ca$_reload_cmd$_real_fullchain" ]; then
_savedomainconf "Le_RealCertPath" "$_real_cert" _savedomainconf "Le_RealCertPath" "$_real_cert"
_savedomainconf "Le_RealCACertPath" "$_real_ca" _savedomainconf "Le_RealCACertPath" "$_real_ca"
_savedomainconf "Le_RealKeyPath" "$_real_key" _savedomainconf "Le_RealKeyPath" "$_real_key"
_savedomainconf "Le_ReloadCmd" "$_reload_cmd" _savedomainconf "Le_ReloadCmd" "$_reload_cmd"
_savedomainconf "Le_RealFullChainPath" "$_real_fullchain" _savedomainconf "Le_RealFullChainPath" "$_real_fullchain"
_installcert "$_main_domain" "$_real_cert" "$_real_key" "$_real_ca" "$_real_fullchain" "$_reload_cmd" if ! _installcert "$_main_domain" "$_real_cert" "$_real_key" "$_real_ca" "$_real_fullchain" "$_reload_cmd"; then
return 1
fi
fi fi
if ! _on_issue_success "$_post_hook" "$_renew_hook"; then
_err "Call hook error."
return 1
fi
} }
#domain [isEcc] #domain [isEcc]
@@ -4675,19 +4676,19 @@ _installcert() {
if [ -f "$_real_cert" ] && [ ! "$IS_RENEW" ]; then if [ -f "$_real_cert" ] && [ ! "$IS_RENEW" ]; then
cp "$_real_cert" "$_backup_path/cert.bak" cp "$_real_cert" "$_backup_path/cert.bak"
fi fi
cat "$CERT_PATH" >"$_real_cert" cat "$CERT_PATH" >"$_real_cert" || return 1
fi fi
if [ "$_real_ca" ]; then if [ "$_real_ca" ]; then
_info "Installing CA to:$_real_ca" _info "Installing CA to:$_real_ca"
if [ "$_real_ca" = "$_real_cert" ]; then if [ "$_real_ca" = "$_real_cert" ]; then
echo "" >>"$_real_ca" echo "" >>"$_real_ca"
cat "$CA_CERT_PATH" >>"$_real_ca" cat "$CA_CERT_PATH" >>"$_real_ca" || return 1
else else
if [ -f "$_real_ca" ] && [ ! "$IS_RENEW" ]; then if [ -f "$_real_ca" ] && [ ! "$IS_RENEW" ]; then
cp "$_real_ca" "$_backup_path/ca.bak" cp "$_real_ca" "$_backup_path/ca.bak"
fi fi
cat "$CA_CERT_PATH" >"$_real_ca" cat "$CA_CERT_PATH" >"$_real_ca" || return 1
fi fi
fi fi
@@ -4697,9 +4698,9 @@ _installcert() {
cp "$_real_key" "$_backup_path/key.bak" cp "$_real_key" "$_backup_path/key.bak"
fi fi
if [ -f "$_real_key" ]; then if [ -f "$_real_key" ]; then
cat "$CERT_KEY_PATH" >"$_real_key" cat "$CERT_KEY_PATH" >"$_real_key" || return 1
else else
cat "$CERT_KEY_PATH" >"$_real_key" cat "$CERT_KEY_PATH" >"$_real_key" || return 1
chmod 600 "$_real_key" chmod 600 "$_real_key"
fi fi
fi fi
@@ -4709,7 +4710,7 @@ _installcert() {
if [ -f "$_real_fullchain" ] && [ ! "$IS_RENEW" ]; then if [ -f "$_real_fullchain" ] && [ ! "$IS_RENEW" ]; then
cp "$_real_fullchain" "$_backup_path/fullchain.bak" cp "$_real_fullchain" "$_backup_path/fullchain.bak"
fi fi
cat "$CERT_FULLCHAIN_PATH" >"$_real_fullchain" cat "$CERT_FULLCHAIN_PATH" >"$_real_fullchain" || return 1
fi fi
if [ "$_reload_cmd" ]; then if [ "$_reload_cmd" ]; then
@@ -5500,6 +5501,7 @@ Parameters:
--ca-path Specifies directory containing CA certificates in PEM format, used by wget or curl. --ca-path Specifies directory containing CA certificates in PEM format, used by wget or curl.
--nocron Only valid for '--install' command, which means: do not install the default cron job. In this case, the certs will not be renewed automatically. --nocron Only valid for '--install' command, which means: do not install the default cron job. In this case, the certs will not be renewed automatically.
--no-color Do not output color text. --no-color Do not output color text.
--force-color Force output of color text. Useful for non-interactive use with the aha tool for HTML E-Mails.
--ecc Specifies to use the ECC cert. Valid for '--install-cert', '--renew', '--revoke', '--toPkcs' and '--createCSR' --ecc Specifies to use the ECC cert. Valid for '--install-cert', '--renew', '--revoke', '--toPkcs' and '--createCSR'
--csr Specifies the input csr. --csr Specifies the input csr.
--pre-hook Command to be run before obtaining any certificates. --pre-hook Command to be run before obtaining any certificates.
@@ -5514,6 +5516,7 @@ Parameters:
--openssl-bin Specifies a custom openssl bin location. --openssl-bin Specifies a custom openssl bin location.
--use-wget Force to use wget, if you have both curl and wget installed. --use-wget Force to use wget, if you have both curl and wget installed.
--yes-I-know-dns-manual-mode-enough-go-ahead-please Force to use dns manual mode: $_DNS_MANUAL_WIKI --yes-I-know-dns-manual-mode-enough-go-ahead-please Force to use dns manual mode: $_DNS_MANUAL_WIKI
--branch, -b Only valid for '--upgrade' command, specifies the branch name to upgrade to.
" "
} }
@@ -5964,6 +5967,9 @@ _process() {
--no-color) --no-color)
export ACME_NO_COLOR=1 export ACME_NO_COLOR=1
;; ;;
--force-color)
export ACME_FORCE_COLOR=1
;;
--ecc) --ecc)
_ecc="isEcc" _ecc="isEcc"
;; ;;
@@ -6058,6 +6064,10 @@ _process() {
_use_wget="1" _use_wget="1"
ACME_USE_WGET="1" ACME_USE_WGET="1"
;; ;;
--branch | -b)
export BRANCH="$2"
shift
;;
*) *)
_err "Unknown parameter : $1" _err "Unknown parameter : $1"
return 1 return 1
+20
View File
@@ -255,3 +255,23 @@ acme.sh --deploy -d fritzbox.example.com --deploy-hook fritzbox
```sh ```sh
acme.sh --deploy -d ftp.example.com --deploy-hook strongswan acme.sh --deploy -d ftp.example.com --deploy-hook strongswan
``` ```
## 10. Deploy the cert to HAProxy
You must specify the path where you want the concatenated key and certificate chain written.
```sh
export DEPLOY_HAPROXY_PEM_PATH=/etc/haproxy
```
You may optionally define the command to reload HAProxy. The value shown below will be used as the default if you don't set this environment variable.
```sh
export DEPLOY_HAPROXY_RELOAD="/usr/sbin/service haproxy restart"
```
You can then deploy the certificate as follows
```sh
acme.sh --deploy -d haproxy.example.com --deploy-hook haproxy
```
The path for the PEM file will be stored with the domain configuration and will be available when renewing, so that deploy will happen automatically when renewed.
+8 -10
View File
@@ -2,8 +2,12 @@
# Here is the script to deploy the cert to your cpanel using the cpanel API. # Here is the script to deploy the cert to your cpanel using the cpanel API.
# Uses command line uapi. --user option is needed only if run as root. # Uses command line uapi. --user option is needed only if run as root.
# Returns 0 when success. # Returns 0 when success.
# Written by Santeri Kannisto <santeri.kannisto@2globalnomads.info> #
# Public domain, 2017 # Please note that I am no longer using Github. If you want to report an issue
# or contact me, visit https://forum.webseodesigners.com/web-design-seo-and-hosting-f16/
#
# Written by Santeri Kannisto <santeri.kannisto@webseodesigners.com>
# Public domain, 2017-2018
#export DEPLOY_CPANEL_USER=myusername #export DEPLOY_CPANEL_USER=myusername
@@ -28,15 +32,9 @@ cpanel_uapi_deploy() {
_err "The command uapi is not found." _err "The command uapi is not found."
return 1 return 1
fi fi
if ! _exists php; then
_err "The command php is not found."
return 1
fi
# read cert and key files and urlencode both # read cert and key files and urlencode both
_certstr=$(cat "$_ccert") _cert=$(_url_encode <"$_ccert")
_keystr=$(cat "$_ckey") _key=$(_url_encode <"$_ckey")
_cert=$(php -r "echo urlencode(\"$_certstr\");")
_key=$(php -r "echo urlencode(\"$_keystr\");")
_debug _cert "$_cert" _debug _cert "$_cert"
_debug _key "$_key" _debug _key "$_key"
+34 -2
View File
@@ -20,7 +20,39 @@ haproxy_deploy() {
_debug _cca "$_cca" _debug _cca "$_cca"
_debug _cfullchain "$_cfullchain" _debug _cfullchain "$_cfullchain"
_err "deploy cert to haproxy server, Not implemented yet" # handle reload preference
return 1 DEFAULT_HAPROXY_RELOAD="/usr/sbin/service haproxy restart"
if [ -z "${DEPLOY_HAPROXY_RELOAD}" ]; then
_reload="${DEFAULT_HAPROXY_RELOAD}"
_cleardomainconf DEPLOY_HAPROXY_RELOAD
else
_reload="${DEPLOY_HAPROXY_RELOAD}"
_savedomainconf DEPLOY_HAPROXY_RELOAD "$DEPLOY_HAPROXY_RELOAD"
fi
_savedomainconf DEPLOY_HAPROXY_PEM_PATH "$DEPLOY_HAPROXY_PEM_PATH"
# work out the path where the PEM file should go
_pem_path="${DEPLOY_HAPROXY_PEM_PATH}"
if [ -z "$_pem_path" ]; then
_err "Path to save PEM file not found. Please define DEPLOY_HAPROXY_PEM_PATH."
return 1
fi
_pem_full_path="$_pem_path/$_cdomain.pem"
_info "Full path to PEM $_pem_full_path"
# combine the key and fullchain into a single pem and install
cat "$_cfullchain" "$_ckey" >"$_pem_full_path"
chmod 600 "$_pem_full_path"
_info "Certificate successfully deployed"
# restart HAProxy
_info "Run reload: $_reload"
if eval "$_reload"; then
_info "Reload success!"
return 0
else
_err "Reload error"
return 1
fi
} }
+85 -2
View File
@@ -1,5 +1,9 @@
# How to use DNS API # How to use DNS API
If your dns provider doesn't provide api access, you can use our dns alias mode:
https://github.com/Neilpang/acme.sh/wiki/DNS-alias-mode
## 1. Use CloudFlare domain API to automatically issue cert ## 1. Use CloudFlare domain API to automatically issue cert
First you need to login to your CloudFlare account to get your API key. First you need to login to your CloudFlare account to get your API key.
@@ -641,6 +645,14 @@ acme.sh --issue --dns dns_inwx -d example.com -d www.example.com
The `INWX_User` and `INWX_Password` settings will be saved in `~/.acme.sh/account.conf` and will be reused when needed. The `INWX_User` and `INWX_Password` settings will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
If your account is secured by mobile tan you have also defined the shared secret.
```
export INWX_Shared_Secret="shared secret"
```
You may need to re-enable the mobile tan to gain the shared secret.
## 34. User Servercow API v1 ## 34. User Servercow API v1
Create a new user from the servercow control center. Don't forget to activate **DNS API** for this user. Create a new user from the servercow control center. Don't forget to activate **DNS API** for this user.
@@ -753,7 +765,7 @@ DNS API keys may be created at https://panel.dreamhost.com/?tree=home.api.
Ensure the created key has add and remove privelages. Ensure the created key has add and remove privelages.
``` ```
export DH_API_Key="<api key>" export DH_API_KEY="<api key>"
acme.sh --issue --dns dns_dreamhost -d example.com -d www.example.com acme.sh --issue --dns dns_dreamhost -d example.com -d www.example.com
``` ```
@@ -814,6 +826,77 @@ acme.sh --issue --dns dns_zilore -d example.com -d *.example.com
The `Zilore_Key` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. The `Zilore_Key` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
## 44. Use Loopia.se API
User must provide login credentials to the Loopia API.
The user needs the following permissions:
- addSubdomain
- updateZoneRecord
- getDomains
- removeSubdomain
Set the login credentials:
```
export LOOPIA_User="user@loopiaapi"
export LOOPIA_Password="password"
```
And to issue a cert:
```
acme.sh --issue --dns dns_loopia -d example.com -d *.example.com
```
The username and password will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
## 45. Use ACME DNS API
ACME DNS is a limited DNS server with RESTful HTTP API to handle ACME DNS challenges easily and securely.
https://github.com/joohoi/acme-dns
```
export ACMEDNS_UPDATE_URL="https://auth.acme-dns.io/update"
export ACMEDNS_USERNAME="<username>"
export ACMEDNS_PASSWORD="<password>"
export ACMEDNS_SUBDOMAIN="<subdomain>"
acme.sh --issue --dns dns_acmedns -d example.com -d www.example.com
```
The credentials will be saved in `~/.acme.sh/account.conf` and will
be reused when needed.
## 46. Use TELE3 API
First you need to login to your TELE3 account to set your API-KEY.
https://www.tele3.cz/system-acme-api.html
```
export TELE3_Key="MS2I4uPPaI..."
export TELE3_Secret="kjhOIHGJKHg"
acme.sh --issue --dns dns_tele3 -d example.com -d *.example.com
```
The TELE3_Key and TELE3_Secret will be saved in ~/.acme.sh/account.conf and will be reused when needed.
## 47. Use Euserv.eu API
First you need to login to your euserv.eu account and activate your API Administration (API Verwaltung).
[https://support.euserv.com](https://support.euserv.com)
Once you've activate, login to your API Admin Interface and create an API account.
Please specify the scope (active groups: domain) and assign the allowed IPs.
```
export EUSERV_Username="99999.user123"
export EUSERV_Password="Asbe54gHde"
```
Ok, let's issue a cert now: (Be aware to use the `--insecure` flag, cause euserv.eu is still using self-signed certificates!)
```
acme.sh --issue --dns dns_euserv -d example.com -d *.example.com --insecure
```
The `EUSERV_Username` and `EUSERV_Password` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
Please report any issues to https://github.com/initit/acme.sh or to <github@initit.de>
# Use custom API # Use custom API
If your API is not supported yet, you can write your own DNS API. If your API is not supported yet, you can write your own DNS API.
@@ -834,4 +917,4 @@ See: https://github.com/Neilpang/acme.sh/wiki/DNS-API-Dev-Guide
# Use lexicon DNS API # Use lexicon DNS API
https://github.com/Neilpang/acme.sh/wiki/How-to-use-lexicon-dns-api https://github.com/Neilpang/acme.sh/wiki/How-to-use-lexicon-dns-api
+55
View File
@@ -0,0 +1,55 @@
#!/usr/bin/env sh
#
#Author: Wolfgang Ebner
#Report Bugs here: https://github.com/webner/acme.sh
#
######## Public functions #####################
#Usage: dns_acmedns_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_acmedns_add() {
fulldomain=$1
txtvalue=$2
_info "Using acme-dns"
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
ACMEDNS_UPDATE_URL="${ACMEDNS_UPDATE_URL:-$(_readaccountconf_mutable ACMEDNS_UPDATE_URL)}"
ACMEDNS_USERNAME="${ACMEDNS_USERNAME:-$(_readaccountconf_mutable ACMEDNS_USERNAME)}"
ACMEDNS_PASSWORD="${ACMEDNS_PASSWORD:-$(_readaccountconf_mutable ACMEDNS_PASSWORD)}"
ACMEDNS_SUBDOMAIN="${ACMEDNS_SUBDOMAIN:-$(_readaccountconf_mutable ACMEDNS_SUBDOMAIN)}"
if [ "$ACMEDNS_UPDATE_URL" = "" ]; then
ACMEDNS_UPDATE_URL="https://auth.acme-dns.io/update"
fi
_saveaccountconf_mutable ACMEDNS_UPDATE_URL "$ACMEDNS_UPDATE_URL"
_saveaccountconf_mutable ACMEDNS_USERNAME "$ACMEDNS_USERNAME"
_saveaccountconf_mutable ACMEDNS_PASSWORD "$ACMEDNS_PASSWORD"
_saveaccountconf_mutable ACMEDNS_SUBDOMAIN "$ACMEDNS_SUBDOMAIN"
export _H1="X-Api-User: $ACMEDNS_USERNAME"
export _H2="X-Api-Key: $ACMEDNS_PASSWORD"
data="{\"subdomain\":\"$ACMEDNS_SUBDOMAIN\", \"txt\": \"$txtvalue\"}"
_debug data "$data"
response="$(_post "$data" "$ACMEDNS_UPDATE_URL" "" "POST")"
_debug response "$response"
if ! echo "$response" | grep "\"$txtvalue\"" >/dev/null; then
_err "invalid response of acme-dns"
return 1
fi
}
#Usage: fulldomain txtvalue
#Remove the txt record after validation.
dns_acmedns_rm() {
fulldomain=$1
txtvalue=$2
_info "Using acme-dns"
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
}
#################### Private functions below ##################################
+12 -7
View File
@@ -76,10 +76,10 @@ dns_azure_add() {
values="{\"value\":[\"$txtvalue\"]}" values="{\"value\":[\"$txtvalue\"]}"
timestamp="$(_time)" timestamp="$(_time)"
if [ "$_code" = "200" ]; then if [ "$_code" = "200" ]; then
vlist="$(echo "$response" | _egrep_o "\"value\"\s*:\s*\[\s*\"[^\"]*\"\s*]" | cut -d : -f 2 | tr -d "[]\"")" vlist="$(echo "$response" | _egrep_o "\"value\"\\s*:\\s*\\[\\s*\"[^\"]*\"\\s*]" | cut -d : -f 2 | tr -d "[]\"")"
_debug "existing TXT found" _debug "existing TXT found"
_debug "$vlist" _debug "$vlist"
existingts="$(echo "$response" | _egrep_o "\"acmetscheck\"\s*:\s*\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d "\"")" existingts="$(echo "$response" | _egrep_o "\"acmetscheck\"\\s*:\\s*\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d "\"")"
if [ -z "$existingts" ]; then if [ -z "$existingts" ]; then
# the record was not created by acme.sh. Copy the exisiting entires # the record was not created by acme.sh. Copy the exisiting entires
existingts=$timestamp existingts=$timestamp
@@ -172,7 +172,7 @@ dns_azure_rm() {
_azure_rest GET "$acmeRecordURI" "" "$accesstoken" _azure_rest GET "$acmeRecordURI" "" "$accesstoken"
timestamp="$(_time)" timestamp="$(_time)"
if [ "$_code" = "200" ]; then if [ "$_code" = "200" ]; then
vlist="$(echo "$response" | _egrep_o "\"value\"\s*:\s*\[\s*\"[^\"]*\"\s*]" | cut -d : -f 2 | tr -d "[]\"" | grep -v "$txtvalue")" vlist="$(echo "$response" | _egrep_o "\"value\"\\s*:\\s*\\[\\s*\"[^\"]*\"\\s*]" | cut -d : -f 2 | tr -d "[]\"" | grep -v "$txtvalue")"
values="" values=""
comma="" comma=""
for v in $vlist; do for v in $vlist; do
@@ -230,7 +230,7 @@ _azure_rest() {
fi fi
_ret="$?" _ret="$?"
_secure_debug2 "response $response" _secure_debug2 "response $response"
_code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\r\n")" _code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")"
_debug "http response code $_code" _debug "http response code $_code"
if [ "$_code" = "401" ]; then if [ "$_code" = "401" ]; then
# we have an invalid access token set to expired # we have an invalid access token set to expired
@@ -308,7 +308,7 @@ _get_root() {
domain=$1 domain=$1
subscriptionId=$2 subscriptionId=$2
accesstoken=$3 accesstoken=$3
i=2 i=1
p=1 p=1
## Ref: https://docs.microsoft.com/en-us/rest/api/dns/zones/list ## Ref: https://docs.microsoft.com/en-us/rest/api/dns/zones/list
@@ -328,9 +328,14 @@ _get_root() {
fi fi
if _contains "$response" "\"name\":\"$h\"" >/dev/null; then if _contains "$response" "\"name\":\"$h\"" >/dev/null; then
_domain_id=$(echo "$response" | _egrep_o "\{\"id\":\"[^\"]*$h\"" | head -n 1 | cut -d : -f 2 | tr -d \") _domain_id=$(echo "$response" | _egrep_o "\\{\"id\":\"[^\"]*$h\"" | head -n 1 | cut -d : -f 2 | tr -d \")
if [ "$_domain_id" ]; then if [ "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) if [ "$i" = 1 ]; then
#create the record at the domain apex (@) if only the domain name was provided as --domain-alias
_sub_domain="@"
else
_sub_domain=$(echo "$domain" | cut -d . -f 1-$p)
fi
_domain=$h _domain=$h
return 0 return 0
fi fi
+358
View File
@@ -0,0 +1,358 @@
#!/usr/bin/env sh
#This is the euserv.eu api wrapper for acme.sh
#
#Author: Michael Brueckner
#Report Bugs: https://www.github.com/initit/acme.sh or mbr@initit.de
#
#EUSERV_Username="username"
#
#EUSERV_Password="password"
#
# Dependencies:
# -------------
# - none -
EUSERV_Api="https://api.euserv.net"
######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_euserv_add() {
fulldomain="$(echo "$1" | _lower_case)"
txtvalue=$2
EUSERV_Username="${EUSERV_Username:-$(_readaccountconf_mutable EUSERV_Username)}"
EUSERV_Password="${EUSERV_Password:-$(_readaccountconf_mutable EUSERV_Password)}"
if [ -z "$EUSERV_Username" ] || [ -z "$EUSERV_Password" ]; then
EUSERV_Username=""
EUSERV_Password=""
_err "You don't specify euserv user and password yet."
_err "Please create your key and try again."
return 1
fi
#save the user and email to the account conf file.
_saveaccountconf_mutable EUSERV_Username "$EUSERV_Username"
_saveaccountconf_mutable EUSERV_Password "$EUSERV_Password"
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"
return 1
fi
_debug "_sub_domain" "$_sub_domain"
_debug "_domain" "$_domain"
_info "Adding record"
if ! _euserv_add_record "$_domain" "$_sub_domain" "$txtvalue"; then
return 1
fi
}
#fulldomain txtvalue
dns_euserv_rm() {
fulldomain="$(echo "$1" | _lower_case)"
txtvalue=$2
EUSERV_Username="${EUSERV_Username:-$(_readaccountconf_mutable EUSERV_Username)}"
EUSERV_Password="${EUSERV_Password:-$(_readaccountconf_mutable EUSERV_Password)}"
if [ -z "$EUSERV_Username" ] || [ -z "$EUSERV_Password" ]; then
EUSERV_Username=""
EUSERV_Password=""
_err "You don't specify euserv user and password yet."
_err "Please create your key and try again."
return 1
fi
#save the user and email to the account conf file.
_saveaccountconf_mutable EUSERV_Username "$EUSERV_Username"
_saveaccountconf_mutable EUSERV_Password "$EUSERV_Password"
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"
return 1
fi
_debug "_sub_domain" "$_sub_domain"
_debug "_domain" "$_domain"
_debug "Getting txt records"
xml_content=$(printf '<?xml version="1.0" encoding="UTF-8"?>
<methodCall>
<methodName>domain.dns_get_active_records</methodName>
<params>
<param>
<value>
<struct>
<member>
<name>login</name>
<value>
<string>%s</string>
</value>
</member>
<member>
<name>password</name>
<value>
<string>%s</string>
</value>
</member>
<member>
<name>domain_id</name>
<value>
<int>%s</int>
</value>
</member>
</struct>
</value>
</param>
</params>
</methodCall>' "$EUSERV_Username" "$EUSERV_Password" "$_euserv_domain_id")
export _H1="Content-Type: text/xml"
response="$(_post "$xml_content" "$EUSERV_Api" "" "POST")"
if ! _contains "$response" "<member><name>status</name><value><i4>100</i4></value></member>"; then
_err "Error could not get txt records"
_debug "xml_content" "$xml_content"
_debug "response" "$response"
return 1
fi
if ! echo "$response" | grep '>dns_record_content<.*>'"$txtvalue"'<' >/dev/null; then
_info "Do not need to delete record"
else
# find XML block where txtvalue is in. The record_id is allways prior this line!
_endLine=$(echo "$response" | grep -n '>dns_record_content<.*>'"$txtvalue"'<' | cut -d ':' -f 1)
# record_id is the last <name> Tag with a number before the row _endLine, identified by </name><value><struct>
_record_id=$(echo "$response" | sed -n '1,'"$_endLine"'p' | grep '</name><value><struct>' | _tail_n 1 | sed 's/.*<name>\([0-9]*\)<\/name>.*/\1/')
_info "Deleting record"
_euserv_delete_record "$_record_id"
fi
}
#################### Private functions below ##################################
_get_root() {
domain=$1
_debug "get root"
# Just to read the domain_orders once
domain=$1
i=2
p=1
if ! _euserv_get_domain_orders; then
return 1
fi
# Get saved response with domain_orders
response="$_euserv_domain_orders"
while true; do
h=$(echo "$domain" | cut -d . -f $i-100)
_debug h "$h"
if [ -z "$h" ]; then
#not valid
return 1
fi
if _contains "$response" "$h"; then
_sub_domain=$(echo "$domain" | cut -d . -f 1-$p)
_domain="$h"
if ! _euserv_get_domain_id "$_domain"; then
_err "invalid domain"
return 1
fi
return 0
fi
p=$i
i=$(_math "$i" + 1)
done
return 1
}
_euserv_get_domain_orders() {
# returns: _euserv_domain_orders
_debug "get domain_orders"
xml_content=$(printf '<?xml version="1.0" encoding="UTF-8"?>
<methodCall>
<methodName>domain.get_domain_orders</methodName>
<params>
<param>
<value>
<struct>
<member>
<name>login</name>
<value><string>%s</string></value>
</member>
<member>
<name>password</name>
<value><string>%s</string></value>
</member>
</struct>
</value>
</param>
</params>
</methodCall>' "$EUSERV_Username" "$EUSERV_Password")
export _H1="Content-Type: text/xml"
response="$(_post "$xml_content" "$EUSERV_Api" "" "POST")"
if ! _contains "$response" "<member><name>status</name><value><i4>100</i4></value></member>"; then
_err "Error could not get domain orders"
_debug "xml_content" "$xml_content"
_debug "response" "$response"
return 1
fi
# save response to reduce API calls
_euserv_domain_orders="$response"
return 0
}
_euserv_get_domain_id() {
# returns: _euserv_domain_id
domain=$1
_debug "get domain_id"
# find line where the domain name is within the $response
_startLine=$(echo "$_euserv_domain_orders" | grep -n '>domain_name<.*>'"$domain"'<' | cut -d ':' -f 1)
# next occurency of domain_id after the domain_name is the correct one
_euserv_domain_id=$(echo "$_euserv_domain_orders" | sed -n "$_startLine"',$p' | grep '>domain_id<' | _head_n 1 | sed 's/.*<i4>\([0-9]*\)<\/i4>.*/\1/')
if [ -z "$_euserv_domain_id" ]; then
_err "Could not find domain_id for domain $domain"
_debug "_euserv_domain_orders" "$_euserv_domain_orders"
return 1
fi
return 0
}
_euserv_delete_record() {
record_id=$1
xml_content=$(printf '<?xml version="1.0" encoding="UTF-8"?>
<methodCall>
<methodName>domain.dns_delete_record</methodName>
<params>
<param>
<value>
<struct>
<member>
<name>login</name>
<value>
<string>%s</string>
</value>
</member>
<member>
<name>password</name>
<value>
<string>%s</string>
</value>
</member>
<member>
<name>dns_record_id</name>
<value>
<int>%s</int>
</value>
</member>
</struct>
</value>
</param>
</params>
</methodCall>' "$EUSERV_Username" "$EUSERV_Password" "$record_id")
export _H1="Content-Type: text/xml"
response="$(_post "$xml_content" "$EUSERV_Api" "" "POST")"
if ! _contains "$response" "<member><name>status</name><value><i4>100</i4></value></member>"; then
_err "Error deleting record"
_debug "xml_content" "$xml_content"
_debug "response" "$response"
return 1
fi
return 0
}
_euserv_add_record() {
domain=$1
sub_domain=$2
txtval=$3
xml_content=$(printf '<?xml version="1.0" encoding="UTF-8"?>
<methodCall>
<methodName>domain.dns_create_record</methodName>
<params>
<param>
<value>
<struct>
<member>
<name>login</name>
<value>
<string>%s</string>
</value>
</member>
<member>
<name>password</name>
<value>
<string>%s</string></value>
</member>
<member>
<name>domain_id</name>
<value>
<int>%s</int>
</value>
</member>
<member>
<name>dns_record_subdomain</name>
<value>
<string>%s</string>
</value>
</member>
<member>
<name>dns_record_type</name>
<value>
<string>TXT</string>
</value>
</member>
<member>
<name>dns_record_value</name>
<value>
<string>%s</string>
</value>
</member>
<member>
<name>dns_record_ttl</name>
<value>
<int>300</int>
</value>
</member>
</struct>
</value>
</param>
</params>
</methodCall>' "$EUSERV_Username" "$EUSERV_Password" "$_euserv_domain_id" "$sub_domain" "$txtval")
export _H1="Content-Type: text/xml"
response="$(_post "$xml_content" "$EUSERV_Api" "" "POST")"
if ! _contains "$response" "<member><name>status</name><value><i4>100</i4></value></member>"; then
_err "Error could not create record"
_debug "xml_content" "$xml_content"
_debug "response" "$response"
return 1
fi
return 0
}
+9 -11
View File
@@ -59,19 +59,13 @@ dns_gd_add() {
_info "Adding record" _info "Adding record"
if _gd_rest PUT "domains/$_domain/records/TXT/$_sub_domain" "[$_add_data]"; then if _gd_rest PUT "domains/$_domain/records/TXT/$_sub_domain" "[$_add_data]"; then
if [ "$response" = "{}" ]; then _info "Added, sleeping 10 seconds"
_info "Added, sleeping 10 seconds" _sleep 10
_sleep 10 #todo: check if the record takes effect
#todo: check if the record takes effect return 0
return 0
else
_err "Add txt record error."
_err "$response"
return 1
fi
fi fi
_err "Add txt record error." _err "Add txt record error."
return 1
} }
#fulldomain #fulldomain
@@ -174,5 +168,9 @@ _gd_rest() {
return 1 return 1
fi fi
_debug2 response "$response" _debug2 response "$response"
if _contains "$response" "UNABLE_TO_AUTHENTICATE"; then
_err "It seems that your api key or secret is not correct."
return 1
fi
return 0 return 0
} }
+13 -4
View File
@@ -33,8 +33,9 @@ dns_he_add() {
# Fills in the $_zone_id # Fills in the $_zone_id
_find_zone "$_full_domain" || return 1 _find_zone "$_full_domain" || return 1
_debug "Zone id \"$_zone_id\" will be used." _debug "Zone id \"$_zone_id\" will be used."
username_encoded="$(printf "%s" "${HE_Username}" | _url_encode)"
body="email=${HE_Username}&pass=${HE_Password}" password_encoded="$(printf "%s" "${HE_Password}" | _url_encode)"
body="email=${username_encoded}&pass=${password_encoded}"
body="$body&account=" body="$body&account="
body="$body&menu=edit_zone" body="$body&menu=edit_zone"
body="$body&Type=TXT" body="$body&Type=TXT"
@@ -71,7 +72,9 @@ dns_he_rm() {
_debug "Zone id \"$_zone_id\" will be used." _debug "Zone id \"$_zone_id\" will be used."
# Find the record id to clean # Find the record id to clean
body="email=${HE_Username}&pass=${HE_Password}" username_encoded="$(printf "%s" "${HE_Username}" | _url_encode)"
password_encoded="$(printf "%s" "${HE_Password}" | _url_encode)"
body="email=${username_encoded}&pass=${password_encoded}"
body="$body&hosted_dns_zoneid=$_zone_id" body="$body&hosted_dns_zoneid=$_zone_id"
body="$body&menu=edit_zone" body="$body&menu=edit_zone"
body="$body&hosted_dns_editzone=" body="$body&hosted_dns_editzone="
@@ -112,9 +115,15 @@ dns_he_rm() {
_find_zone() { _find_zone() {
_domain="$1" _domain="$1"
body="email=${HE_Username}&pass=${HE_Password}" username_encoded="$(printf "%s" "${HE_Username}" | _url_encode)"
password_encoded="$(printf "%s" "${HE_Password}" | _url_encode)"
body="email=${username_encoded}&pass=${password_encoded}"
response="$(_post "$body" "https://dns.he.net/")" response="$(_post "$body" "https://dns.he.net/")"
_debug2 response "$response" _debug2 response "$response"
if _contains "$response" '>Incorrect<'; then
_err "Unable to login to dns.he.net please check username and password"
return 1
fi
_table="$(echo "$response" | tr -d "#" | sed "s/<table/#<table/g" | tr -d "\n" | tr "#" "\n" | grep 'id="domains_table"')" _table="$(echo "$response" | tr -d "#" | sed "s/<table/#<table/g" | tr -d "\n" | tr "#" "\n" | grep 'id="domains_table"')"
_debug2 _table "$_table" _debug2 _table "$_table"
_matches="$(echo "$_table" | sed "s/<tr/#<tr/g" | tr "#" "\n" | grep 'alt="edit"' | tr -d " " | sed "s/<td/#<td/g" | tr "#" "\n" | grep 'hosted_dns_zoneid')" _matches="$(echo "$_table" | sed "s/<tr/#<tr/g" | tr "#" "\n" | grep 'alt="edit"' | tr -d " " | sed "s/<td/#<td/g" | tr "#" "\n" | grep 'hosted_dns_zoneid')"
+47 -3
View File
@@ -4,6 +4,10 @@
#INWX_User="username" #INWX_User="username"
# #
#INWX_Password="password" #INWX_Password="password"
#
# Dependencies:
# -------------
# - oathtool (When using 2 Factor Authentication)
INWX_Api="https://api.domrobot.com/xmlrpc/" INWX_Api="https://api.domrobot.com/xmlrpc/"
@@ -16,6 +20,7 @@ dns_inwx_add() {
INWX_User="${INWX_User:-$(_readaccountconf_mutable INWX_User)}" INWX_User="${INWX_User:-$(_readaccountconf_mutable INWX_User)}"
INWX_Password="${INWX_Password:-$(_readaccountconf_mutable INWX_Password)}" INWX_Password="${INWX_Password:-$(_readaccountconf_mutable INWX_Password)}"
INWX_Shared_Secret="${INWX_Shared_Secret:-$(_readaccountconf_mutable INWX_Shared_Secret)}"
if [ -z "$INWX_User" ] || [ -z "$INWX_Password" ]; then if [ -z "$INWX_User" ] || [ -z "$INWX_Password" ]; then
INWX_User="" INWX_User=""
INWX_Password="" INWX_Password=""
@@ -27,6 +32,7 @@ dns_inwx_add() {
#save the api key and email to the account conf file. #save the api key and email to the account conf file.
_saveaccountconf_mutable INWX_User "$INWX_User" _saveaccountconf_mutable INWX_User "$INWX_User"
_saveaccountconf_mutable INWX_Password "$INWX_Password" _saveaccountconf_mutable INWX_Password "$INWX_Password"
_saveaccountconf_mutable INWX_Shared_Secret "$INWX_Shared_Secret"
_debug "First detect the root zone" _debug "First detect the root zone"
if ! _get_root "$fulldomain"; then if ! _get_root "$fulldomain"; then
@@ -148,8 +154,46 @@ _inwx_login() {
</methodCall>' $INWX_User $INWX_Password) </methodCall>' $INWX_User $INWX_Password)
response="$(_post "$xml_content" "$INWX_Api" "" "POST")" response="$(_post "$xml_content" "$INWX_Api" "" "POST")"
_H1=$(printf "Cookie: %s" "$(grep "domrobot=" "$HTTP_HEADER" | grep "^Set-Cookie:" | _tail_n 1 | _egrep_o 'domrobot=[^;]*;' | tr -d ';')")
export _H1
printf "Cookie: %s" "$(grep "domrobot=" "$HTTP_HEADER" | grep "^Set-Cookie:" | _tail_n 1 | _egrep_o 'domrobot=[^;]*;' | tr -d ';')" #https://github.com/inwx/php-client/blob/master/INWX/Domrobot.php#L71
if _contains "$response" "tfa"; then
if [ -z "$INWX_Shared_Secret" ]; then
_err "Mobile TAN detected."
_err "Please define a shared secret."
return 1
fi
if ! _exists oathtool; then
_err "Please install oathtool to use 2 Factor Authentication."
_err ""
return 1
fi
tan="$(oathtool --base32 --totp "${INWX_Shared_Secret}" 2>/dev/null)"
xml_content=$(printf '<?xml version="1.0" encoding="UTF-8"?>
<methodCall>
<methodName>account.unlock</methodName>
<params>
<param>
<value>
<struct>
<member>
<name>tan</name>
<value>
<string>%s</string>
</value>
</member>
</struct>
</value>
</param>
</params>
</methodCall>' "$tan")
response="$(_post "$xml_content" "$INWX_Api" "" "POST")"
fi
} }
@@ -161,8 +205,8 @@ _get_root() {
i=2 i=2
p=1 p=1
_H1=$(_inwx_login) _inwx_login
export _H1
xml_content='<?xml version="1.0" encoding="UTF-8"?> xml_content='<?xml version="1.0" encoding="UTF-8"?>
<methodCall> <methodCall>
<methodName>nameserver.list</methodName> <methodName>nameserver.list</methodName>
+2 -2
View File
@@ -128,7 +128,7 @@ _ISPC_addTxt() {
curSerial="$(date +%s)" curSerial="$(date +%s)"
curStamp="$(date +'%F %T')" curStamp="$(date +'%F %T')"
params="\"server_id\":\"${server_id}\",\"zone\":\"${zone}\",\"name\":\"${fulldomain}.\",\"type\":\"txt\",\"data\":\"${txtvalue}\",\"aux\":\"0\",\"ttl\":\"3600\",\"active\":\"y\",\"stamp\":\"${curStamp}\",\"serial\":\"${curSerial}\"" params="\"server_id\":\"${server_id}\",\"zone\":\"${zone}\",\"name\":\"${fulldomain}.\",\"type\":\"txt\",\"data\":\"${txtvalue}\",\"aux\":\"0\",\"ttl\":\"3600\",\"active\":\"y\",\"stamp\":\"${curStamp}\",\"serial\":\"${curSerial}\""
curData="{\"session_id\":\"${sessionID}\",\"client_id\":\"${client_id}\",\"params\":{${params}}}" curData="{\"session_id\":\"${sessionID}\",\"client_id\":\"${client_id}\",\"params\":{${params}},\"update_serial\":true}"
curResult="$(_post "${curData}" "${ISPC_Api}?dns_txt_add")" curResult="$(_post "${curData}" "${ISPC_Api}?dns_txt_add")"
_debug "Calling _ISPC_addTxt: '${curData}' '${ISPC_Api}?dns_txt_add'" _debug "Calling _ISPC_addTxt: '${curData}' '${ISPC_Api}?dns_txt_add'"
_debug "Result of _ISPC_addTxt: '$curResult'" _debug "Result of _ISPC_addTxt: '$curResult'"
@@ -160,7 +160,7 @@ _ISPC_rmTxt() {
*) *)
unset IFS unset IFS
_info "Retrieved Record ID." _info "Retrieved Record ID."
curData="{\"session_id\":\"${sessionID}\",\"primary_id\":\"${record_id}\"}" curData="{\"session_id\":\"${sessionID}\",\"primary_id\":\"${record_id}\",\"update_serial\":true}"
curResult="$(_post "${curData}" "${ISPC_Api}?dns_txt_delete")" curResult="$(_post "${curData}" "${ISPC_Api}?dns_txt_delete")"
_debug "Calling _ISPC_rmTxt: '${curData}' '${ISPC_Api}?dns_txt_delete'" _debug "Calling _ISPC_rmTxt: '${curData}' '${ISPC_Api}?dns_txt_delete'"
_debug "Result of _ISPC_rmTxt: '$curResult'" _debug "Result of _ISPC_rmTxt: '$curResult'"
+227
View File
@@ -0,0 +1,227 @@
#!/usr/bin/env sh
#
#LOOPIA_User="username"
#
#LOOPIA_Password="password"
LOOPIA_Api="https://api.loopia.se/RPCSERV"
######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_loopia_add() {
fulldomain=$1
txtvalue=$2
LOOPIA_User="${LOOPIA_User:-$(_readaccountconf_mutable LOOPIA_User)}"
LOOPIA_Password="${LOOPIA_Password:-$(_readaccountconf_mutable LOOPIA_Password)}"
if [ -z "$LOOPIA_User" ] || [ -z "$LOOPIA_Password" ]; then
LOOPIA_User=""
LOOPIA_Password=""
_err "You don't specify loopia user and password yet."
_err "Please create you key and try again."
return 1
fi
#save the api key and email to the account conf file.
_saveaccountconf_mutable LOOPIA_User "$LOOPIA_User"
_saveaccountconf_mutable LOOPIA_Password "$LOOPIA_Password"
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"
return 1
fi
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
_info "Adding record"
_loopia_add_record "$_domain" "$_sub_domain"
_loopia_update_record "$_domain" "$_sub_domain" "$txtvalue"
}
dns_loopia_rm() {
fulldomain=$1
txtvalue=$2
LOOPIA_User="${LOOPIA_User:-$(_readaccountconf_mutable LOOPIA_User)}"
LOOPIA_Password="${LOOPIA_Password:-$(_readaccountconf_mutable LOOPIA_Password)}"
if [ -z "$LOOPIA_User" ] || [ -z "$LOOPIA_Password" ]; then
LOOPIA_User=""
LOOPIA_Password=""
_err "You don't specify LOOPIA user and password yet."
_err "Please create you key and try again."
return 1
fi
#save the api key and email to the account conf file.
_saveaccountconf_mutable LOOPIA_User "$LOOPIA_User"
_saveaccountconf_mutable LOOPIA_Password "$LOOPIA_Password"
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"
return 1
fi
xml_content=$(printf '<?xml version="1.0" encoding="UTF-8"?>
<methodCall>
<methodName>removeSubdomain</methodName>
<params>
<param>
<value><string>%s</string></value>
</param>
<param>
<value><string>%s</string></value>
</param>
<param>
<value><string>%s</string></value>
</param>
<param>
<value><string>%s</string></value>
</param>
</params>
</methodCall>' $LOOPIA_User $LOOPIA_Password "$_domain" "$_sub_domain")
response="$(_post "$xml_content" "$LOOPIA_Api" "" "POST")"
if ! _contains "$response" "OK"; then
_err "Error could not get txt records"
return 1
fi
}
#################### Private functions below ##################################
_get_root() {
domain=$1
_debug "get root"
domain=$1
i=2
p=1
xml_content=$(printf '<?xml version="1.0" encoding="UTF-8"?>
<methodCall>
<methodName>getDomains</methodName>
<params>
<param>
<value><string>%s</string></value>
</param>
<param>
<value><string>%s</string></value>
</param>
</params>
</methodCall>' $LOOPIA_User $LOOPIA_Password)
response="$(_post "$xml_content" "$LOOPIA_Api" "" "POST")"
while true; do
h=$(echo "$domain" | cut -d . -f $i-100)
if [ -z "$h" ]; then
#not valid
return 1
fi
if _contains "$response" "$h"; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_domain="$h"
return 0
fi
p=$i
i=$(_math "$i" + 1)
done
return 1
}
_loopia_update_record() {
domain=$1
sub_domain=$2
txtval=$3
xml_content=$(printf '<?xml version="1.0" encoding="UTF-8"?>
<methodCall>
<methodName>updateZoneRecord</methodName>
<params>
<param>
<value><string>%s</string></value>
</param>
<param>
<value><string>%s</string></value>
</param>
<param>
<value><string>%s</string></value>
</param>
<param>
<value><string>%s</string></value>
</param>
<param>
<struct>
<member>
<name>type</name>
<value><string>TXT</string></value>
</member>
<member>
<name>priority</name>
<value><int>0</int></value>
</member>
<member>
<name>ttl</name>
<value><int>60</int></value>
</member>
<member>
<name>rdata</name>
<value><string>%s</string></value>
</member>
<member>
<name>record_id</name>
<value><int>0</int></value>
</member>
</struct>
</param>
</params>
</methodCall>' $LOOPIA_User $LOOPIA_Password "$domain" "$sub_domain" "$txtval")
response="$(_post "$xml_content" "$LOOPIA_Api" "" "POST")"
if ! _contains "$response" "OK"; then
_err "Error"
return 1
fi
return 0
}
_loopia_add_record() {
domain=$1
sub_domain=$2
xml_content=$(printf '<?xml version="1.0" encoding="UTF-8"?>
<methodCall>
<methodName>addSubdomain</methodName>
<params>
<param>
<value><string>%s</string></value>
</param>
<param>
<value><string>%s</string></value>
</param>
<param>
<value><string>%s</string></value>
</param>
<param>
<value><string>%s</string></value>
</param>
</params>
</methodCall>' $LOOPIA_User $LOOPIA_Password "$domain" "$sub_domain")
response="$(_post "$xml_content" "$LOOPIA_Api" "" "POST")"
if ! _contains "$response" "OK"; then
_err "Error"
return 1
fi
return 0
}
+5 -2
View File
@@ -8,12 +8,14 @@ dns_nsupdate_add() {
txtvalue=$2 txtvalue=$2
_checkKeyFile || return 1 _checkKeyFile || return 1
[ -n "${NSUPDATE_SERVER}" ] || NSUPDATE_SERVER="localhost" [ -n "${NSUPDATE_SERVER}" ] || NSUPDATE_SERVER="localhost"
[ -n "${NSUPDATE_SERVER_PORT}" ] || NSUPDATE_SERVER_PORT=53
# save the dns server and key to the account conf file. # save the dns server and key to the account conf file.
_saveaccountconf NSUPDATE_SERVER "${NSUPDATE_SERVER}" _saveaccountconf NSUPDATE_SERVER "${NSUPDATE_SERVER}"
_saveaccountconf NSUPDATE_SERVER_PORT "${NSUPDATE_SERVER_PORT}"
_saveaccountconf NSUPDATE_KEY "${NSUPDATE_KEY}" _saveaccountconf NSUPDATE_KEY "${NSUPDATE_KEY}"
_info "adding ${fulldomain}. 60 in txt \"${txtvalue}\"" _info "adding ${fulldomain}. 60 in txt \"${txtvalue}\""
nsupdate -k "${NSUPDATE_KEY}" <<EOF nsupdate -k "${NSUPDATE_KEY}" <<EOF
server ${NSUPDATE_SERVER} server ${NSUPDATE_SERVER} ${NSUPDATE_SERVER_PORT}
update add ${fulldomain}. 60 in txt "${txtvalue}" update add ${fulldomain}. 60 in txt "${txtvalue}"
send send
EOF EOF
@@ -30,9 +32,10 @@ dns_nsupdate_rm() {
fulldomain=$1 fulldomain=$1
_checkKeyFile || return 1 _checkKeyFile || return 1
[ -n "${NSUPDATE_SERVER}" ] || NSUPDATE_SERVER="localhost" [ -n "${NSUPDATE_SERVER}" ] || NSUPDATE_SERVER="localhost"
[ -n "${NSUPDATE_SERVER_PORT}" ] || NSUPDATE_SERVER_PORT=53
_info "removing ${fulldomain}. txt" _info "removing ${fulldomain}. txt"
nsupdate -k "${NSUPDATE_KEY}" <<EOF nsupdate -k "${NSUPDATE_KEY}" <<EOF
server ${NSUPDATE_SERVER} server ${NSUPDATE_SERVER} ${NSUPDATE_SERVER_PORT}
update delete ${fulldomain}. txt update delete ${fulldomain}. txt
send send
EOF EOF
+54 -9
View File
@@ -69,15 +69,21 @@ dns_pdns_add() {
#fulldomain #fulldomain
dns_pdns_rm() { dns_pdns_rm() {
fulldomain=$1 fulldomain=$1
txtvalue=$2
if [ -z "$PDNS_Ttl" ]; then
PDNS_Ttl="$DEFAULT_PDNS_TTL"
fi
_debug "Detect root zone" _debug "Detect root zone"
if ! _get_root "$fulldomain"; then if ! _get_root "$fulldomain"; then
_err "invalid domain" _err "invalid domain"
return 1 return 1
fi fi
_debug _domain "$_domain" _debug _domain "$_domain"
if ! rm_record "$_domain" "$fulldomain"; then if ! rm_record "$_domain" "$fulldomain" "$txtvalue"; then
return 1 return 1
fi fi
@@ -88,9 +94,16 @@ set_record() {
_info "Adding record" _info "Adding record"
root=$1 root=$1
full=$2 full=$2
txtvalue=$3 new_challenge=$3
if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root" "{\"rrsets\": [{\"changetype\": \"REPLACE\", \"name\": \"$full.\", \"type\": \"TXT\", \"ttl\": $PDNS_Ttl, \"records\": [{\"name\": \"$full.\", \"type\": \"TXT\", \"content\": \"\\\"$txtvalue\\\"\", \"disabled\": false, \"ttl\": $PDNS_Ttl}]}]}"; then _record_string=""
_build_record_string "$new_challenge"
_list_existingchallenges
for oldchallenge in $_existing_challenges; do
_build_record_string "$oldchallenge"
done
if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root" "{\"rrsets\": [{\"changetype\": \"REPLACE\", \"name\": \"$full.\", \"type\": \"TXT\", \"ttl\": $PDNS_Ttl, \"records\": [$_record_string]}]}"; then
_err "Set txt record error." _err "Set txt record error."
return 1 return 1
fi fi
@@ -106,14 +119,37 @@ rm_record() {
_info "Remove record" _info "Remove record"
root=$1 root=$1
full=$2 full=$2
txtvalue=$3
if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root" "{\"rrsets\": [{\"changetype\": \"DELETE\", \"name\": \"$full.\", \"type\": \"TXT\"}]}"; then #Enumerate existing acme challenges
_err "Delete txt record error." _list_existingchallenges
return 1
fi
if ! notify_slaves "$root"; then if _contains "$_existing_challenges" "$txtvalue"; then
return 1 #Delete all challenges (PowerDNS API does not allow to delete content)
if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root" "{\"rrsets\": [{\"changetype\": \"DELETE\", \"name\": \"$full.\", \"type\": \"TXT\"}]}"; then
_err "Delete txt record error."
return 1
fi
_record_string=""
#If the only existing challenge was the challenge to delete: nothing to do
if ! [ "$_existing_challenges" = "$txtvalue" ]; then
for oldchallenge in $_existing_challenges; do
#Build up the challenges to re-add, ommitting the one what should be deleted
if ! [ "$oldchallenge" = "$txtvalue" ]; then
_build_record_string "$oldchallenge"
fi
done
#Recreate the existing challenges
if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root" "{\"rrsets\": [{\"changetype\": \"REPLACE\", \"name\": \"$full.\", \"type\": \"TXT\", \"ttl\": $PDNS_Ttl, \"records\": [$_record_string]}]}"; then
_err "Set txt record error."
return 1
fi
fi
if ! notify_slaves "$root"; then
return 1
fi
else
_info "Record not found, nothing to remove"
fi fi
return 0 return 0
@@ -185,3 +221,12 @@ _pdns_rest() {
return 0 return 0
} }
_build_record_string() {
_record_string="${_record_string:+${_record_string}, }{\"content\": \"\\\"${1}\\\"\", \"disabled\": false}"
}
_list_existingchallenges() {
_pdns_rest "GET" "/api/v1/servers/$PDNS_ServerId/zones/$root"
_existing_challenges=$(echo "$response" | _normalizeJson | _egrep_o "\"name\":\"${fulldomain}[^]]*}" | _egrep_o 'content\":\"\\"[^\\]*' | sed -n 's/^content":"\\"//p')
}
+69
View File
@@ -0,0 +1,69 @@
#!/usr/bin/env sh
#
# tele3.cz DNS API
#
# Author: Roman Blizik
# Report Bugs here: https://github.com/par-pa/acme.sh
#
# --
# export TELE3_Key="MS2I4uPPaI..."
# export TELE3_Secret="kjhOIHGJKHg"
# --
TELE3_API="https://www.tele3.cz/acme/"
######## Public functions #####################
dns_tele3_add() {
_info "Using TELE3 DNS"
data="\"ope\":\"add\", \"domain\":\"$1\", \"value\":\"$2\""
if ! _tele3_call; then
_err "Publish zone failed"
return 1
fi
_info "Zone published"
}
dns_tele3_rm() {
_info "Using TELE3 DNS"
data="\"ope\":\"rm\", \"domain\":\"$1\", \"value\":\"$2\""
if ! _tele3_call; then
_err "delete TXT record failed"
return 1
fi
_info "TXT record successfully deleted"
}
#################### Private functions below ##################################
_tele3_init() {
TELE3_Key="${TELE3_Key:-$(_readaccountconf_mutable TELE3_Key)}"
TELE3_Secret="${TELE3_Secret:-$(_readaccountconf_mutable TELE3_Secret)}"
if [ -z "$TELE3_Key" ] || [ -z "$TELE3_Secret" ]; then
TELE3_Key=""
TELE3_Secret=""
_err "You must export variables: TELE3_Key and TELE3_Secret"
return 1
fi
#save the config variables to the account conf file.
_saveaccountconf_mutable TELE3_Key "$TELE3_Key"
_saveaccountconf_mutable TELE3_Secret "$TELE3_Secret"
}
_tele3_call() {
_tele3_init
data="{\"key\":\"$TELE3_Key\", \"secret\":\"$TELE3_Secret\", $data}"
_debug data "$data"
response="$(_post "$data" "$TELE3_API" "" "POST")"
_debug response "$response"
if [ "$response" != "success" ]; then
_err "$response"
return 1
fi
}