Browse Source

Merge branch 'dev' into deploy/strongswan

pull/705/head
hiska 8 years ago
committed by GitHub
parent
commit
abe957b700
  1. 28
      README.md
  2. 125
      acme.sh
  3. 10
      deploy/README.md
  4. 4
      deploy/exim4.sh
  5. 31
      deploy/keychain.sh
  6. 4
      deploy/kong.sh
  7. 4
      deploy/vsftpd.sh
  8. 91
      dnsapi/README.md
  9. 6
      dnsapi/dns_aws.sh
  10. 170
      dnsapi/dns_cloudns.sh
  11. 7
      dnsapi/dns_cx.sh
  12. 2
      dnsapi/dns_cyon.sh
  13. 205
      dnsapi/dns_dgon.sh
  14. 18
      dnsapi/dns_freedns.sh
  15. 2
      dnsapi/dns_gandi_livedns.sh
  16. 97
      dnsapi/dns_infoblox.sh
  17. 95
      dnsapi/dns_knot.sh
  18. 2
      dnsapi/dns_ovh.sh
  19. 2
      dnsapi/dns_pdns.sh

28
README.md

@ -18,6 +18,18 @@ Twitter: [@neilpangxa](https://twitter.com/neilpangxa)
# [中文说明](https://github.com/Neilpang/acme.sh/wiki/%E8%AF%B4%E6%98%8E) # [中文说明](https://github.com/Neilpang/acme.sh/wiki/%E8%AF%B4%E6%98%8E)
# Who are using **acme.sh**
- [FreeBSD.org](https://blog.crashed.org/letsencrypt-in-freebsd-org/)
- [ruby-china.org](https://ruby-china.org/topics/31983)
- [Proxmox](https://pve.proxmox.com/wiki/HTTPS_Certificate_Configuration_(Version_4.x_and_newer))
- [pfsense](https://github.com/pfsense/FreeBSD-ports/pull/89)
- [webfaction](https://community.webfaction.com/questions/19988/using-letsencrypt)
- [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)
- [Centminmod](http://centminmod.com/letsencrypt-acmetool-https.html)
- [splynx](https://forum.splynx.com/t/free-ssl-cert-for-splynx-lets-encrypt/297)
- [archlinux](https://aur.archlinux.org/packages/acme.sh-git/)
- [more...](https://github.com/Neilpang/acme.sh/wiki/Blogs-and-tutorials)
# Tested OS # Tested OS
@ -149,17 +161,17 @@ You **MUST** use this command to copy the certs to the target files, **DO NOT**
**Apache** example: **Apache** example:
```bash ```bash
acme.sh --install-cert -d example.com \ acme.sh --install-cert -d example.com \
--certpath /path/to/certfile/in/apache/cert.pem \
--keypath /path/to/keyfile/in/apache/key.pem \
--fullchainpath /path/to/fullchain/certfile/apache/fullchain.pem \
--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" --reloadcmd "service apache2 force-reload"
``` ```
**Nginx** example: **Nginx** example:
```bash ```bash
acme.sh --install-cert -d example.com \ acme.sh --install-cert -d example.com \
--keypath /path/to/keyfile/in/nginx/key.pem \
--fullchainpath /path/to/fullchain/nginx/cert.pem \
--key-file /path/to/keyfile/in/nginx/key.pem \
--fullchain-file /path/to/fullchain/nginx/cert.pem \
--reloadcmd "service nginx force-reload" --reloadcmd "service nginx force-reload"
``` ```
@ -295,6 +307,10 @@ You don't have to do anything manually!
1. cyon.ch 1. cyon.ch
1. Domain-Offensive/Resellerinterface/Domainrobot API 1. Domain-Offensive/Resellerinterface/Domainrobot API
1. Gandi LiveDNS API 1. Gandi LiveDNS API
1. Knot DNS API
1. DigitalOcean API (native)
1. ClouDNS.net API
1. Infoblox NIOS API (https://www.infoblox.com/)
**More APIs coming soon...** **More APIs coming soon...**
@ -313,7 +329,7 @@ Just set the `length` parameter with a prefix `ec-`.
For example: For example:
### Single domain ECC cerfiticate
### Single domain ECC certificate
```bash ```bash
acme.sh --issue -w /home/wwwroot/example.com -d example.com --keylength ec-256 acme.sh --issue -w /home/wwwroot/example.com -d example.com --keylength ec-256

125
acme.sh

@ -146,7 +146,7 @@ _dlg_versions() {
echo "apache:" echo "apache:"
if [ "$_APACHECTL" ] && _exists "$_APACHECTL"; then if [ "$_APACHECTL" ] && _exists "$_APACHECTL"; then
_APACHECTL -V 2>&1
$_APACHECTL -V 2>&1
else else
echo "apache doesn't exists." echo "apache doesn't exists."
fi fi
@ -299,6 +299,16 @@ _secure_debug3() {
fi fi
} }
_upper_case() {
# shellcheck disable=SC2018,SC2019
tr 'a-z' 'A-Z'
}
_lower_case() {
# shellcheck disable=SC2018,SC2019
tr 'A-Z' 'a-z'
}
_startswith() { _startswith() {
_str="$1" _str="$1"
_sub="$2" _sub="$2"
@ -330,7 +340,7 @@ _hasfield() {
_sep="," _sep=","
fi fi
for f in $(echo "$_str" | tr ',' ' '); do
for f in $(echo "$_str" | tr "$_sep" ' '); do
if [ "$f" = "$_field" ]; then if [ "$f" = "$_field" ]; then
_debug2 "'$_str' contains '$_field'" _debug2 "'$_str' contains '$_field'"
return 0 #contains ok return 0 #contains ok
@ -869,7 +879,7 @@ _sign() {
if ! _signedECText="$($_sign_openssl | $ACME_OPENSSL_BIN asn1parse -inform DER)"; then if ! _signedECText="$($_sign_openssl | $ACME_OPENSSL_BIN asn1parse -inform DER)"; then
_err "Sign failed: $_sign_openssl" _err "Sign failed: $_sign_openssl"
_err "Key file: $keyfile" _err "Key file: $keyfile"
_err "Key content:$(wc -l <"$keyfile") lises"
_err "Key content:$(wc -l <"$keyfile") lines"
return 1 return 1
fi fi
_debug3 "_signedECText" "$_signedECText" _debug3 "_signedECText" "$_signedECText"
@ -1121,8 +1131,12 @@ _ss() {
elif netstat -help 2>&1 | grep -- '-P protocol' >/dev/null; then elif netstat -help 2>&1 | grep -- '-P protocol' >/dev/null; then
#for solaris #for solaris
netstat -an -P tcp | grep "\.$_port " | grep "LISTEN" netstat -an -P tcp | grep "\.$_port " | grep "LISTEN"
else
elif netstat -help 2>&1 | grep "\-p" >/dev/null; then
#for full linux
netstat -ntpl | grep ":$_port " netstat -ntpl | grep ":$_port "
else
#for busybox (embedded linux; no pid support)
netstat -ntl 2>/dev/null | grep ":$_port "
fi fi
fi fi
return 0 return 0
@ -1279,12 +1293,12 @@ _url_replace() {
} }
_time2str() { _time2str() {
#BSD
#Linux
if date -u -d@"$1" 2>/dev/null; then if date -u -d@"$1" 2>/dev/null; then
return return
fi fi
#Linux
#BSD
if date -u -r "$1" 2>/dev/null; then if date -u -r "$1" 2>/dev/null; then
return return
fi fi
@ -1469,7 +1483,9 @@ _inithttp() {
_ACME_CURL="$_ACME_CURL --trace-ascii $_CURL_DUMP " _ACME_CURL="$_ACME_CURL --trace-ascii $_CURL_DUMP "
fi fi
if [ "$CA_BUNDLE" ]; then
if [ "$CA_PATH" ]; then
_ACME_CURL="$_ACME_CURL --capath $CA_PATH "
elif [ "$CA_BUNDLE" ]; then
_ACME_CURL="$_ACME_CURL --cacert $CA_BUNDLE " _ACME_CURL="$_ACME_CURL --cacert $CA_BUNDLE "
fi fi
@ -1480,8 +1496,10 @@ _inithttp() {
if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
_ACME_WGET="$_ACME_WGET -d " _ACME_WGET="$_ACME_WGET -d "
fi fi
if [ "$CA_BUNDLE" ]; then
_ACME_WGET="$_ACME_WGET --ca-certificate $CA_BUNDLE "
if [ "$CA_PATH" ]; then
_ACME_WGET="$_ACME_WGET --ca-directory=$CA_PATH "
elif [ "$CA_BUNDLE" ]; then
_ACME_WGET="$_ACME_WGET --ca-certificate=$CA_BUNDLE "
fi fi
fi fi
@ -2240,16 +2258,16 @@ _initpath() {
fi fi
if [ -z "$TLS_CONF" ]; then if [ -z "$TLS_CONF" ]; then
TLS_CONF="$DOMAIN_PATH/tls.valdation.conf"
TLS_CONF="$DOMAIN_PATH/tls.validation.conf"
fi fi
if [ -z "$TLS_CERT" ]; then if [ -z "$TLS_CERT" ]; then
TLS_CERT="$DOMAIN_PATH/tls.valdation.cert"
TLS_CERT="$DOMAIN_PATH/tls.validation.cert"
fi fi
if [ -z "$TLS_KEY" ]; then if [ -z "$TLS_KEY" ]; then
TLS_KEY="$DOMAIN_PATH/tls.valdation.key"
TLS_KEY="$DOMAIN_PATH/tls.validation.key"
fi fi
if [ -z "$TLS_CSR" ]; then if [ -z "$TLS_CSR" ]; then
TLS_CSR="$DOMAIN_PATH/tls.valdation.csr"
TLS_CSR="$DOMAIN_PATH/tls.validation.csr"
fi fi
} }
@ -2367,7 +2385,7 @@ _setApache() {
_debug "Backup apache config file" "$httpdconf" _debug "Backup apache config file" "$httpdconf"
if ! cp "$httpdconf" "$APACHE_CONF_BACKUP_DIR/"; then if ! cp "$httpdconf" "$APACHE_CONF_BACKUP_DIR/"; then
_err "Can not backup apache config file, so abort. Don't worry, the apache config is not changed." _err "Can not backup apache config file, so abort. Don't worry, the apache config is not changed."
_err "This might be a bug of $PROJECT_NAME , pleae report issue: $PROJECT"
_err "This might be a bug of $PROJECT_NAME , please report issue: $PROJECT"
return 1 return 1
fi fi
_info "JFYI, Config file $httpdconf is backuped to $APACHE_CONF_BACKUP_DIR/$httpdconfname" _info "JFYI, Config file $httpdconf is backuped to $APACHE_CONF_BACKUP_DIR/$httpdconfname"
@ -2462,7 +2480,7 @@ _setNginx() {
fi fi
_debug "Start detect nginx conf for $_d from:$_start_f" _debug "Start detect nginx conf for $_d from:$_start_f"
if ! _checkConf "$_d" "$_start_f"; then if ! _checkConf "$_d" "$_start_f"; then
"Can not find conf file for domain $d"
_err "Can not find conf file for domain $d"
return 1 return 1
fi fi
_info "Found conf file: $FOUND_REAL_NGINX_CONF" _info "Found conf file: $FOUND_REAL_NGINX_CONF"
@ -2546,7 +2564,7 @@ _checkConf() {
if [ ! -f "$2" ] && ! echo "$2" | grep '*$' >/dev/null && echo "$2" | grep '*' >/dev/null; then if [ ! -f "$2" ] && ! echo "$2" | grep '*$' >/dev/null && echo "$2" | grep '*' >/dev/null; then
_debug "wildcard" _debug "wildcard"
for _w_f in $2; do for _w_f in $2; do
if _checkConf "$1" "$_w_f"; then
if [ -f "$_w_f"] && _checkConf "$1" "$_w_f"; then
return 0 return 0
fi fi
done done
@ -2559,9 +2577,9 @@ _checkConf() {
FOUND_REAL_NGINX_CONF="$2" FOUND_REAL_NGINX_CONF="$2"
return 0 return 0
fi fi
if grep "^ *include *.*;" "$2" >/dev/null; then
if cat "$2" | tr "\t" " " | grep "^ *include *.*;" >/dev/null; then
_debug "Try include files" _debug "Try include files"
for included in $(grep "^ *include *.*;" "$2" | sed "s/include //" | tr -d " ;"); do
for included in $(cat "$2" | tr "\t" " " | grep "^ *include *.*;" | sed "s/include //" | tr -d " ;"); do
_debug "check included $included" _debug "check included $included"
if _checkConf "$1" "$included"; then if _checkConf "$1" "$included"; then
return 0 return 0
@ -2865,7 +2883,7 @@ _on_issue_err() {
uri=$(echo "$ventry" | cut -d "$sep" -f 3) uri=$(echo "$ventry" | cut -d "$sep" -f 3)
vtype=$(echo "$ventry" | cut -d "$sep" -f 4) vtype=$(echo "$ventry" | cut -d "$sep" -f 4)
_currentRoot=$(echo "$ventry" | cut -d "$sep" -f 5) _currentRoot=$(echo "$ventry" | cut -d "$sep" -f 5)
__trigger_validaton "$uri" "$keyauthorization"
__trigger_validation "$uri" "$keyauthorization"
done done
) )
fi fi
@ -3087,7 +3105,7 @@ __get_domain_new_authz() {
} }
#uri keyAuthorization #uri keyAuthorization
__trigger_validaton() {
__trigger_validation() {
_debug2 "tigger domain validation." _debug2 "tigger domain validation."
_t_url="$1" _t_url="$1"
_debug2 _t_url "$_t_url" _debug2 _t_url "$_t_url"
@ -3467,9 +3485,12 @@ issue() {
if [ ! "$usingApache" ]; then if [ ! "$usingApache" ]; then
if webroot_owner=$(_stat "$_currentRoot"); then if webroot_owner=$(_stat "$_currentRoot"); then
_debug "Changing owner/group of .well-known to $webroot_owner" _debug "Changing owner/group of .well-known to $webroot_owner"
chown -R "$webroot_owner" "$_currentRoot/.well-known"
if ! _exec "chown -R \"$webroot_owner\" \"$_currentRoot/.well-known\""; then
_debug "$(cat "$_EXEC_TEMP_ERR")"
_exec_err >/dev/null 2>&1
fi
else else
_debug "not chaning owner/group of webroot"
_debug "not changing owner/group of webroot"
fi fi
fi fi
@ -3510,7 +3531,7 @@ issue() {
fi fi
fi fi
if ! __trigger_validaton "$uri" "$keyauthorization"; then
if ! __trigger_validation "$uri" "$keyauthorization"; then
_err "$d:Can not get challenge: $response" _err "$d:Can not get challenge: $response"
_clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
_clearup _clearup
@ -3690,6 +3711,12 @@ issue() {
_clearaccountconf "CA_BUNDLE" _clearaccountconf "CA_BUNDLE"
fi fi
if [ "$CA_PATH" ]; then
_saveaccountconf CA_PATH "$CA_PATH"
else
_clearaccountconf "CA_PATH"
fi
if [ "$HTTPS_INSECURE" ]; then if [ "$HTTPS_INSECURE" ]; then
_saveaccountconf HTTPS_INSECURE "$HTTPS_INSECURE" _saveaccountconf HTTPS_INSECURE "$HTTPS_INSECURE"
else else
@ -4008,7 +4035,7 @@ deploy() {
installcert() { installcert() {
_main_domain="$1" _main_domain="$1"
if [ -z "$_main_domain" ]; then if [ -z "$_main_domain" ]; then
_usage "Usage: $PROJECT_ENTRY --installcert -d domain.com [--ecc] [--certpath cert-file-path] [--keypath key-file-path] [--capath ca-cert-file-path] [ --reloadCmd reloadCmd] [--fullchainpath fullchain-path]"
_usage "Usage: $PROJECT_ENTRY --installcert -d domain.com [--ecc] [--cert-file cert-file-path] [--key-file key-file-path] [--ca-file ca-cert-file-path] [ --reloadCmd reloadCmd] [--fullchain-file fullchain-path]"
return 1 return 1
fi fi
@ -4107,6 +4134,7 @@ _installcert() {
export CERT_KEY_PATH export CERT_KEY_PATH
export CA_CERT_PATH export CA_CERT_PATH
export CERT_FULLCHAIN_PATH export CERT_FULLCHAIN_PATH
export Le_Domain
cd "$DOMAIN_PATH" && eval "$_reload_cmd" cd "$DOMAIN_PATH" && eval "$_reload_cmd"
); then ); then
_info "$(__green "Reload success")" _info "$(__green "Reload success")"
@ -4618,7 +4646,7 @@ install() {
#Modify shebang #Modify shebang
if _exists bash; then if _exists bash; then
_info "Good, bash is found, so change the shebang to use bash as preferred." _info "Good, bash is found, so change the shebang to use bash as preferred."
_shebang='#!/usr/bin/env bash'
_shebang='#!'"$(env bash -c "command -v bash")"
_setShebang "$LE_WORKING_DIR/$PROJECT_ENTRY" "$_shebang" _setShebang "$LE_WORKING_DIR/$PROJECT_ENTRY" "$_shebang"
for subf in $_SUB_FOLDERS; do for subf in $_SUB_FOLDERS; do
if [ -d "$LE_WORKING_DIR/$subf" ]; then if [ -d "$LE_WORKING_DIR/$subf" ]; then
@ -4758,10 +4786,10 @@ Parameters:
These parameters are to install the cert to nginx/apache or anyother server after issue/renew a cert: These parameters are to install the cert to nginx/apache or anyother server after issue/renew a cert:
--certpath /path/to/real/cert/file After issue/renew, the cert will be copied to this path.
--keypath /path/to/real/key/file After issue/renew, the key will be copied to this path.
--capath /path/to/real/ca/file After issue/renew, the intermediate cert will be copied to this path.
--fullchainpath /path/to/fullchain/file After issue/renew, the fullchain cert will be copied to this path.
--cert-file After issue/renew, the cert will be copied to this path.
--key-file After issue/renew, the key will be copied to this path.
--ca-file After issue/renew, the intermediate cert will be copied to this path.
--fullchain-file After issue/renew, the fullchain cert will be copied to this path.
--reloadcmd \"service nginx reload\" After issue/renew, it's used to reload the server. --reloadcmd \"service nginx reload\" After issue/renew, it's used to reload the server.
@ -4779,12 +4807,13 @@ Parameters:
--listraw Only used for '--list' command, list the certs in raw format. --listraw Only used for '--list' command, list the certs in raw format.
--stopRenewOnError, -se Only valid for '--renew-all' command. Stop if one cert has error in renewal. --stopRenewOnError, -se Only valid for '--renew-all' command. Stop if one cert has error in renewal.
--insecure Do not check the server certificate, in some devices, the api server's certificate may not be trusted. --insecure Do not check the server certificate, in some devices, the api server's certificate may not be trusted.
--ca-bundle Specifices the path to the CA certificate bundle to verify api server's certificate.
--ca-bundle Specifies the path to the CA certificate bundle to verify api server's certificate.
--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.
--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.
--post-hook Command to be run after attempting to obtain/renew certificates. No matter the obain/renew is success or failed.
--post-hook Command to be run after attempting to obtain/renew certificates. No matter the obtain/renew is success or failed.
--renew-hook Command to be run once for each successfully renewed certificate. --renew-hook Command to be run once for each successfully renewed certificate.
--deploy-hook The hook file to deploy cert --deploy-hook The hook file to deploy cert
--ocsp-must-staple, --ocsp Generate ocsp must Staple extension. --ocsp-must-staple, --ocsp Generate ocsp must Staple extension.
@ -4886,10 +4915,10 @@ _process() {
_webroot="" _webroot=""
_keylength="" _keylength=""
_accountkeylength="" _accountkeylength=""
_certpath=""
_keypath=""
_capath=""
_fullchainpath=""
_cert_file=""
_key_file=""
_ca_file=""
_fullchain_file=""
_reloadcmd="" _reloadcmd=""
_password="" _password=""
_accountconf="" _accountconf=""
@ -4905,6 +4934,7 @@ _process() {
_stopRenewOnError="" _stopRenewOnError=""
#_insecure="" #_insecure=""
_ca_bundle="" _ca_bundle=""
_ca_path=""
_nocron="" _nocron=""
_ecc="" _ecc=""
_csr="" _csr=""
@ -5130,20 +5160,20 @@ _process() {
shift shift
;; ;;
--certpath)
_certpath="$2"
--cert-file | --certpath)
_cert_file="$2"
shift shift
;; ;;
--keypath)
_keypath="$2"
--key-file | --keypath)
_key_file="$2"
shift shift
;; ;;
--capath)
_capath="$2"
--ca-file | --capath)
_ca_file="$2"
shift shift
;; ;;
--fullchainpath)
_fullchainpath="$2"
--fullchain-file | --fullchainpath)
_fullchain_file="$2"
shift shift
;; ;;
--reloadcmd | --reloadCmd) --reloadcmd | --reloadCmd)
@ -5219,6 +5249,11 @@ _process() {
CA_BUNDLE="$_ca_bundle" CA_BUNDLE="$_ca_bundle"
shift shift
;; ;;
--ca-path)
_ca_path="$2"
CA_PATH="$_ca_path"
shift
;;
--nocron) --nocron)
_nocron="1" _nocron="1"
;; ;;
@ -5360,7 +5395,7 @@ _process() {
uninstall) uninstall "$_nocron" ;; uninstall) uninstall "$_nocron" ;;
upgrade) upgrade ;; upgrade) upgrade ;;
issue) issue)
issue "$_webroot" "$_domain" "$_altdomains" "$_keylength" "$_certpath" "$_keypath" "$_capath" "$_reloadcmd" "$_fullchainpath" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_address"
issue "$_webroot" "$_domain" "$_altdomains" "$_keylength" "$_cert_file" "$_key_file" "$_ca_file" "$_reloadcmd" "$_fullchain_file" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_address"
;; ;;
deploy) deploy)
deploy "$_domain" "$_deploy_hook" "$_ecc" deploy "$_domain" "$_deploy_hook" "$_ecc"
@ -5372,7 +5407,7 @@ _process() {
showcsr "$_csr" "$_domain" showcsr "$_csr" "$_domain"
;; ;;
installcert) installcert)
installcert "$_domain" "$_certpath" "$_keypath" "$_capath" "$_reloadcmd" "$_fullchainpath" "$_ecc"
installcert "$_domain" "$_cert_file" "$_key_file" "$_ca_file" "$_reloadcmd" "$_fullchain_file" "$_ecc"
;; ;;
renew) renew)
renew "$_domain" "$_ecc" renew "$_domain" "$_ecc"

10
deploy/README.md

@ -72,8 +72,14 @@ export DEPLOY_EXIM4_RELOAD="/etc/init.d/exim4 restart"
acme.sh --deploy -d ftp.example.com --deploy-hook exim4 acme.sh --deploy -d ftp.example.com --deploy-hook exim4
``` ```
## 6. Deploy the cert to local strongswan server.
## 6. Deploy the cert to OSX Keychain
```sh ```sh
acme.sh --deploy -d ftp.example.com --deploy-hook strongswan
acme.sh --deploy -d ftp.example.com --deploy-hook keychain
``` ```
## 7. Deploy the cert to local strongswan server.
```sh
acme.sh --deploy -d ftp.example.com --deploy-hook strongswan
```

4
deploy/exim4.sh

@ -79,7 +79,7 @@ exim4_deploy() {
_info "Restore conf success" _info "Restore conf success"
eval "$_reload" eval "$_reload"
else else
_err "Opps, error restore exim4 conf, please report bug to us."
_err "Oops, error restore exim4 conf, please report bug to us."
fi fi
return 1 return 1
fi fi
@ -105,7 +105,7 @@ exim4_deploy() {
_info "Restore conf success" _info "Restore conf success"
eval "$_reload" eval "$_reload"
else else
_err "Opps, error restore exim4 conf, please report bug to us."
_err "Oops, error restore exim4 conf, please report bug to us."
fi fi
return 1 return 1
fi fi

31
deploy/keychain.sh

@ -0,0 +1,31 @@
#!/usr/bin/env sh
#Here is a sample custom api script.
#This file name is "myapi.sh"
#So, here must be a method myapi_deploy()
#Which will be called by acme.sh to deploy the cert
#returns 0 means success, otherwise error.
######## Public functions #####################
#domain keyfile certfile cafile fullchain
keychain_deploy() {
_cdomain="$1"
_ckey="$2"
_ccert="$3"
_cca="$4"
_cfullchain="$5"
_debug _cdomain "$_cdomain"
_debug _ckey "$_ckey"
_debug _ccert "$_ccert"
_debug _cca "$_cca"
_debug _cfullchain "$_cfullchain"
/usr/bin/security import "$_ckey" -k "/Library/Keychains/System.keychain"
/usr/bin/security import "$_ccert" -k "/Library/Keychains/System.keychain"
/usr/bin/security import "$_cca" -k "/Library/Keychains/System.keychain"
/usr/bin/security import "$_cfullchain" -k "/Library/Keychains/System.keychain"
return 0
}

4
deploy/kong.sh

@ -43,7 +43,7 @@ kong_deploy() {
#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"
#Generate DEIM #Generate DEIM
delim="-----MultipartDelimeter$(date "+%s%N")"
delim="-----MultipartDelimiter$(date "+%s%N")"
nl="\015\012" nl="\015\012"
#Set Header #Set Header
_H1="Content-Type: multipart/form-data; boundary=$delim" _H1="Content-Type: multipart/form-data; boundary=$delim"
@ -72,7 +72,7 @@ kong_deploy() {
response=$(_post "$content" "$KONG_URL/apis/$uuid/plugins/$ssl_uuid" "" "PATCH") response=$(_post "$content" "$KONG_URL/apis/$uuid/plugins/$ssl_uuid" "" "PATCH")
fi fi
if ! [ "$(echo "$response" | _egrep_o "ssl")" = "ssl" ]; then if ! [ "$(echo "$response" | _egrep_o "ssl")" = "ssl" ]; then
_err "An error occured with cert upload. Check response:"
_err "An error occurred with cert upload. Check response:"
_err "$response" _err "$response"
return 1 return 1
fi fi

4
deploy/vsftpd.sh

@ -76,7 +76,7 @@ vsftpd_deploy() {
_info "Restore conf success" _info "Restore conf success"
eval "$_reload" eval "$_reload"
else else
_err "Opps, error restore vsftpd conf, please report bug to us."
_err "Oops, error restore vsftpd conf, please report bug to us."
fi fi
return 1 return 1
fi fi
@ -102,7 +102,7 @@ vsftpd_deploy() {
_info "Restore conf success" _info "Restore conf success"
eval "$_reload" eval "$_reload"
else else
_err "Opps, error restore vsftpd conf, please report bug to us."
_err "Oops, error restore vsftpd conf, please report bug to us."
fi fi
return 1 return 1
fi fi

91
dnsapi/README.md

@ -302,7 +302,7 @@ acme.sh --issue --dns dns_freedns -d example.com -d www.example.com
``` ```
Note that you cannot use acme.sh automatic DNS validation for FreeDNS public domains or for a subdomain that Note that you cannot use acme.sh automatic DNS validation for FreeDNS public domains or for a subdomain that
you create under a FreeDNS public domain. You must own the top level domain in order to automaitcally
you create under a FreeDNS public domain. You must own the top level domain in order to automatically
validate with acme.sh at FreeDNS. validate with acme.sh at FreeDNS.
## 16. Use cyon.ch ## 16. Use cyon.ch
@ -349,6 +349,95 @@ Ok, let's issue a cert now:
acme.sh --issue --dns dns_gandi_livedns -d example.com -d www.example.com acme.sh --issue --dns dns_gandi_livedns -d example.com -d www.example.com
``` ```
## 19. Use Knot (knsupdate) DNS API to automatically issue cert
First, generate a TSIG key for updating the zone.
```
keymgr tsig generate acme_key algorithm hmac-sha512 > /etc/knot/acme.key
```
Include this key in your knot configuration file.
```
include: /etc/knot/acme.key
```
Next, configure your zone to allow dynamic updates.
Dynamic updates for the zone are allowed via proper ACL rule with the `update` action. For in-depth instructions, please see [Knot DNS's documentation](https://www.knot-dns.cz/documentation/).
```
acl:
- id: acme_acl
address: 192.168.1.0/24
key: acme_key
action: update
zone:
- domain: example.com
file: example.com.zone
acl: acme_acl
```
Finally, make the DNS server and TSIG Key available to `acme.sh`
```
export KNOT_SERVER="dns.example.com"
export KNOT_KEY=`grep \# /etc/knot/acme.key | cut -d' ' -f2`
```
Ok, let's issue a cert now:
```
acme.sh --issue --dns dns_knot -d example.com -d www.example.com
```
The `KNOT_SERVER` and `KNOT_KEY` settings will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
## 20. Use DigitalOcean API (native)
You need to obtain a read and write capable API key from your DigitalOcean account. See: https://www.digitalocean.com/help/api/
```
export DO_API_KEY="75310dc4ca779ac39a19f6355db573b49ce92ae126553ebd61ac3a3ae34834cc"
```
Ok, let's issue a cert now:
```
acme.sh --issue --dns dns_dgon -d example.com -d www.example.com
```
## 21. Use ClouDNS.net API
You need to set the HTTP API user ID and password credentials. See: https://www.cloudns.net/wiki/article/42/
```
export CLOUDNS_AUTH_ID=XXXXX
export CLOUDNS_AUTH_PASSWORD="YYYYYYYYY"
```
Ok, let's issue a cert now:
```
acme.sh --issue --dns dns_cloudns -d example.com -d www.example.com
```
## 22. Use Infoblox API
First you need to create/obtain API credentials on your Infoblox appliance.
```
export Infoblox_Creds="username:password"
export Infoblox_Server="ip or fqdn of infoblox appliance"
```
Ok, let's issue a cert now:
```
acme.sh --issue --dns dns_infoblox -d example.com -d www.example.com
```
Note: This script will automatically create and delete the ephemeral txt record.
The `Infoblox_Creds` and `Infoblox_Server` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
# 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.

6
dnsapi/dns_aws.sh

@ -143,7 +143,7 @@ aws_rest() {
CanonicalHeaders="host:$aws_host\nx-amz-date:$RequestDate\n" CanonicalHeaders="host:$aws_host\nx-amz-date:$RequestDate\n"
SignedHeaders="host;x-amz-date" SignedHeaders="host;x-amz-date"
if [ -n "$AWS_SESSION_TOKEN" ]; then if [ -n "$AWS_SESSION_TOKEN" ]; then
export _H2="x-amz-security-token: $AWS_SESSION_TOKEN"
export _H3="x-amz-security-token: $AWS_SESSION_TOKEN"
CanonicalHeaders="${CanonicalHeaders}x-amz-security-token:$AWS_SESSION_TOKEN\n" CanonicalHeaders="${CanonicalHeaders}x-amz-security-token:$AWS_SESSION_TOKEN\n"
SignedHeaders="${SignedHeaders};x-amz-security-token" SignedHeaders="${SignedHeaders};x-amz-security-token"
fi fi
@ -204,8 +204,8 @@ aws_rest() {
Authorization="$Algorithm Credential=$AWS_ACCESS_KEY_ID/$CredentialScope, SignedHeaders=$SignedHeaders, Signature=$signature" Authorization="$Algorithm Credential=$AWS_ACCESS_KEY_ID/$CredentialScope, SignedHeaders=$SignedHeaders, Signature=$signature"
_debug2 Authorization "$Authorization" _debug2 Authorization "$Authorization"
_H3="Authorization: $Authorization"
_debug _H3 "$_H3"
_H2="Authorization: $Authorization"
_debug _H2 "$_H2"
url="$AWS_URL/$ep" url="$AWS_URL/$ep"

170
dnsapi/dns_cloudns.sh

@ -0,0 +1,170 @@
#!/usr/bin/env sh
# Author: Boyan Peychev <boyan at cloudns dot net>
# Repository: https://github.com/ClouDNS/acme.sh/
#CLOUDNS_AUTH_ID=XXXXX
#CLOUDNS_AUTH_PASSWORD="YYYYYYYYY"
CLOUDNS_API="https://api.cloudns.net"
######## Public functions #####################
#Usage: dns_cloudns_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_cloudns_add() {
_info "Using cloudns"
if ! _dns_cloudns_init_check; then
return 1
fi
zone="$(_dns_cloudns_get_zone_name "$1")"
if [ -z "$zone" ]; then
_err "Missing DNS zone at ClouDNS. Please log into your control panel and create the required DNS zone for the initial setup."
return 1
fi
host="$(echo "$1" | sed "s/\.$zone\$//")"
record=$2
record_id=$(_dns_cloudns_get_record_id "$zone" "$host")
_debug zone "$zone"
_debug host "$host"
_debug record "$record"
_debug record_id "$record_id"
if [ -z "$record_id" ]; then
_info "Adding the TXT record for $1"
_dns_cloudns_http_api_call "dns/add-record.json" "domain-name=$zone&record-type=TXT&host=$host&record=$record&ttl=60"
if ! _contains "$response" "\"status\":\"Success\""; then
_err "Record cannot be added."
return 1
fi
_info "Added."
else
_info "Updating the TXT record for $1"
_dns_cloudns_http_api_call "dns/mod-record.json" "domain-name=$zone&record-id=$record_id&record-type=TXT&host=$host&record=$record&ttl=60"
if ! _contains "$response" "\"status\":\"Success\""; then
_err "The TXT record for $1 cannot be updated."
return 1
fi
_info "Updated."
fi
return 0
}
#Usage: dns_cloudns_rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_cloudns_rm() {
_info "Using cloudns"
if ! _dns_cloudns_init_check; then
return 1
fi
if [ -z "$zone" ]; then
zone="$(_dns_cloudns_get_zone_name "$1")"
if [ -z "$zone" ]; then
_err "Missing DNS zone at ClouDNS. Please log into your control panel and create the required DNS zone for the initial setup."
return 1
fi
fi
host="$(echo "$1" | sed "s/\.$zone\$//")"
record=$2
record_id=$(_dns_cloudns_get_record_id "$zone" "$host")
_debug zone "$zone"
_debug host "$host"
_debug record "$record"
_debug record_id "$record_id"
if [ ! -z "$record_id" ]; then
_info "Deleting the TXT record for $1"
_dns_cloudns_http_api_call "dns/delete-record.json" "domain-name=$zone&record-id=$record_id"
if ! _contains "$response" "\"status\":\"Success\""; then
_err "The TXT record for $1 cannot be deleted."
return 1
fi
_info "Deleted."
fi
return 0
}
#################### Private functions below ##################################
_dns_cloudns_init_check() {
if [ ! -z "$CLOUDNS_INIT_CHECK_COMPLETED" ]; then
return 0
fi
if [ -z "$CLOUDNS_AUTH_ID" ]; then
_err "CLOUDNS_AUTH_ID is not configured"
return 1
fi
if [ -z "$CLOUDNS_AUTH_PASSWORD" ]; then
_err "CLOUDNS_AUTH_PASSWORD is not configured"
return 1
fi
_dns_cloudns_http_api_call "dns/login.json" ""
if ! _contains "$response" "\"status\":\"Success\""; then
_err "Invalid CLOUDNS_AUTH_ID or CLOUDNS_AUTH_PASSWORD. Please check your login credentials."
return 1
fi
CLOUDNS_INIT_CHECK_COMPLETED=1
return 0
}
_dns_cloudns_get_zone_name() {
i=2
while true; do
zoneForCheck=$(printf "%s" "$1" | cut -d . -f $i-100)
if [ -z "$zoneForCheck" ]; then
return 1
fi
_debug zoneForCheck "$zoneForCheck"
_dns_cloudns_http_api_call "dns/get-zone-info.json" "domain-name=$zoneForCheck"
if ! _contains "$response" "\"status\":\"Failed\""; then
echo "$zoneForCheck"
return 0
fi
i=$(_math "$i" + 1)
done
return 1
}
_dns_cloudns_get_record_id() {
_dns_cloudns_http_api_call "dns/records.json" "domain-name=$1&host=$2&type=TXT"
if _contains "$response" "\"id\":"; then
echo "$response" | cut -d '"' -f 2
return 0
fi
return 1
}
_dns_cloudns_http_api_call() {
method=$1
_debug CLOUDNS_AUTH_ID "$CLOUDNS_AUTH_ID"
_debug CLOUDNS_AUTH_PASSWORD "$CLOUDNS_AUTH_PASSWORD"
if [ -z "$2" ]; then
data="auth-id=$CLOUDNS_AUTH_ID&auth-password=$CLOUDNS_AUTH_PASSWORD"
else
data="auth-id=$CLOUDNS_AUTH_ID&auth-password=$CLOUDNS_AUTH_PASSWORD&$2"
fi
response="$(_get "$CLOUDNS_API/$method?$data")"
_debug2 response "$response"
return 0
}

7
dnsapi/dns_cx.sh

@ -209,8 +209,7 @@ _rest() {
return 1 return 1
fi fi
_debug2 response "$response" _debug2 response "$response"
if ! _contains "$response" '"message":"success"'; then
return 1
fi
return 0
_contains "$response" '"code":1'
} }

2
dnsapi/dns_cyon.sh

@ -50,7 +50,7 @@ _cyon_load_credentials() {
fi fi
if [ -z "${CY_Username}" ] || [ -z "${CY_Password}" ]; then if [ -z "${CY_Username}" ] || [ -z "${CY_Password}" ]; then
# Dummy entries to satify script checker.
# Dummy entries to satisfy script checker.
CY_Username="" CY_Username=""
CY_Password="" CY_Password=""
CY_OTP_Secret="" CY_OTP_Secret=""

205
dnsapi/dns_dgon.sh

@ -0,0 +1,205 @@
#!/usr/bin/env sh
## Will be called by acme.sh to add the txt record to your api system.
## returns 0 means success, otherwise error.
## Author: thewer <github at thewer.com>
## GitHub: https://github.com/gitwer/acme.sh
##
## Environment Variables Required:
##
## DO_API_KEY="75310dc4ca779ac39a19f6355db573b49ce92ae126553ebd61ac3a3ae34834cc"
##
##################### Public functions #####################
## Create the text record for validation.
## Usage: fulldomain txtvalue
## EG: "_acme-challenge.www.other.domain.com" "XKrxpRBosdq0HG9i01zxXp5CPBs"
dns_dgon_add() {
fulldomain="$(echo "$1" | _lower_case)"
txtvalue=$2
_info "Using digitalocean dns validation - add record"
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
## save the env vars (key and domain split location) for later automated use
_saveaccountconf DO_API_KEY "$DO_API_KEY"
## split the domain for DO API
if ! _get_base_domain "$fulldomain"; then
_err "domain not found in your account for addition"
return 1
fi
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
## Set the header with our post type and key auth key
export _H1="Content-Type: application/json"
export _H2="Authorization: Bearer $DO_API_KEY"
PURL='https://api.digitalocean.com/v2/domains/'$_domain'/records'
PBODY='{"type":"TXT","name":"'$_sub_domain'","data":"'$txtvalue'"}'
_debug PURL "$PURL"
_debug PBODY "$PBODY"
## the create request - post
## args: BODY, URL, [need64, httpmethod]
response="$(_post "$PBODY" "$PURL")"
## check response
if [ "$?" != "0" ]; then
_err "error in response: $response"
return 1
fi
_debug2 response "$response"
## finished correctly
return 0
}
## Remove the txt record after validation.
## Usage: fulldomain txtvalue
## EG: "_acme-challenge.www.other.domain.com" "XKrxpRBosdq0HG9i01zxXp5CPBs"
dns_dgon_rm() {
fulldomain="$(echo "$1" | _lower_case)"
txtvalue=$2
_info "Using digitalocean dns validation - remove record"
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
## split the domain for DO API
if ! _get_base_domain "$fulldomain"; then
_err "domain not found in your account for removal"
return 1
fi
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
## Set the header with our post type and key auth key
export _H1="Content-Type: application/json"
export _H2="Authorization: Bearer $DO_API_KEY"
## get URL for the list of domains
## may get: "links":{"pages":{"last":".../v2/domains/DOM/records?page=2","next":".../v2/domains/DOM/records?page=2"}}
GURL="https://api.digitalocean.com/v2/domains/$_domain/records"
## while we dont have a record ID we keep going
while [ -z "$record" ]; do
## 1) get the URL
## the create request - get
## args: URL, [onlyheader, timeout]
domain_list="$(_get "$GURL")"
## 2) find record
## check for what we are looing for: "type":"A","name":"$_sub_domain"
record="$(echo "$domain_list" | _egrep_o "\"id\"\s*\:\s*\"*\d+\"*[^}]*\"name\"\s*\:\s*\"$_sub_domain\"[^}]*\"data\"\s*\:\s*\"$txtvalue\"")"
## 3) check record and get next page
if [ -z "$record" ]; then
## find the next page if we dont have a match
nextpage="$(echo "$domain_list" | _egrep_o "\"links\".*" | _egrep_o "\"next\".*" | _egrep_o "http.*page\=\d+")"
if [ -z "$nextpage" ]; then
_err "no record and no nextpage in digital ocean DNS removal"
return 1
fi
_debug2 nextpage "$nextpage"
GURL="$nextpage"
fi
## we break out of the loop when we have a record
done
## we found the record
rec_id="$(echo "$record" | _egrep_o "id\"\s*\:\s*\"*\d+" | _egrep_o "\d+")"
_debug rec_id "$rec_id"
## delete the record
## delete URL for removing the one we dont want
DURL="https://api.digitalocean.com/v2/domains/$_domain/records/$rec_id"
## the create request - delete
## args: BODY, URL, [need64, httpmethod]
response="$(_post "" "$DURL" "" "DELETE")"
## check response (sort of)
if [ "$?" != "0" ]; then
_err "error in remove response: $response"
return 1
fi
_debug2 response "$response"
## finished correctly
return 0
}
##################### Private functions below #####################
## Split the domain provided into the "bade domain" and the "start prefix".
## This function searches for the longest subdomain in your account
## for the full domain given and splits it into the base domain (zone)
## and the prefix/record to be added/removed
## USAGE: fulldomain
## EG: "_acme-challenge.two.three.four.domain.com"
## returns
## _sub_domain="_acme-challenge.two"
## _domain="three.four.domain.com" *IF* zone "three.four.domain.com" exists
## if only "domain.com" exists it will return
## _sub_domain="_acme-challenge.two.three.four"
## _domain="domain.com"
_get_base_domain() {
# args
fulldomain="$(echo "$1" | tr '[:upper:]' '[:lower:]')"
_debug fulldomain "$fulldomain"
# domain max legal length = 253
MAX_DOM=255
## get a list of domains for the account to check thru
## Set the headers
export _H1="Content-Type: application/json"
export _H2="Authorization: Bearer $DO_API_KEY"
_debug DO_API_KEY "$DO_API_KEY"
## get URL for the list of domains
## havent seen this request paginated, tested with 18 domains (more requires manual requests with DO)
DOMURL="https://api.digitalocean.com/v2/domains"
## get the domain list (DO gives basically a full XFER!)
domain_list="$(_get "$DOMURL")"
## check response
if [ "$?" != "0" ]; then
_err "error in domain_list response: $domain_list"
return 1
fi
_debug2 domain_list "$domain_list"
## for each shortening of our $fulldomain, check if it exists in the $domain_list
## can never start on 1 (aka whole $fulldomain) as $fulldomain starts with "_acme-challenge"
i=2
while [ $i -gt 0 ]; do
## get next longest domain
_domain=$(printf "%s" "$fulldomain" | cut -d . -f "$i"-"$MAX_DOM")
## check we got something back from our cut (or are we at the end)
if [ -z "$_domain" ]; then
## we got to the end of the domain - invalid domain
_err "domain not found in DigitalOcean account"
return 1
fi
## we got part of a domain back - grep it out
found="$(echo "$domain_list" | _egrep_o "\"name\"\s*\:\s*\"$_domain\"")"
## check if it exists
if [ ! -z "$found" ]; then
## exists - exit loop returning the parts
sub_point=$(_math $i - 1)
_sub_domain=$(printf "%s" "$fulldomain" | cut -d . -f 1-"$sub_point")
_debug _domain "$_domain"
_debug _sub_domain "$_sub_domain"
return 0
fi
## increment cut point $i
i=$(_math $i + 1)
done
## we went through the entire domain zone list and dint find one that matched
## doesnt look like we can add in the record
_err "domain not found in DigitalOcean account, but we should never get here"
return 1
}

18
dnsapi/dns_freedns.sh

@ -10,7 +10,7 @@
# #
######## Public functions ##################### ######## Public functions #####################
# Export FreeDNS userid and password in folowing variables...
# Export FreeDNS userid and password in following variables...
# FREEDNS_User=username # FREEDNS_User=username
# FREEDNS_Password=password # FREEDNS_Password=password
# login cookie is saved in acme account config file so userid / pw # login cookie is saved in acme account config file so userid / pw
@ -53,7 +53,7 @@ dns_freedns_add() {
i="$(_math "$i" - 1)" i="$(_math "$i" - 1)"
sub_domain="$(echo "$fulldomain" | cut -d. -f -"$i")" sub_domain="$(echo "$fulldomain" | cut -d. -f -"$i")"
# Sometimes FreeDNS does not reurn the subdomain page but rather
# Sometimes FreeDNS does not return the subdomain page but rather
# returns a page regarding becoming a premium member. This usually # returns a page regarding becoming a premium member. This usually
# happens after a period of inactivity. Immediately trying again # happens after a period of inactivity. Immediately trying again
# returns the correct subdomain page. So, we will try twice to # returns the correct subdomain page. So, we will try twice to
@ -65,7 +65,7 @@ dns_freedns_add() {
htmlpage="$(_freedns_retrieve_subdomain_page "$FREEDNS_COOKIE")" htmlpage="$(_freedns_retrieve_subdomain_page "$FREEDNS_COOKIE")"
if [ "$?" != "0" ]; then if [ "$?" != "0" ]; then
if [ "$using_cached_cookies" = "true" ]; then if [ "$using_cached_cookies" = "true" ]; then
_err "Has your FreeDNS username and password channged? If so..."
_err "Has your FreeDNS username and password changed? If so..."
_err "Please export as FREEDNS_User / FREEDNS_Password and try again." _err "Please export as FREEDNS_User / FREEDNS_Password and try again."
fi fi
return 1 return 1
@ -112,7 +112,7 @@ dns_freedns_add() {
# not produce accurate results as the value field is truncated # not produce accurate results as the value field is truncated
# on this webpage. To get full value we would need to load # on this webpage. To get full value we would need to load
# another page. However we don't really need this so long as # another page. However we don't really need this so long as
# there is only one TXT record for the acme chalenge subdomain.
# there is only one TXT record for the acme challenge subdomain.
DNSvalue="$(echo "$line" | cut -d ',' -f 4 | sed 's/^[^&quot;]*&quot;//;s/&quot;.*//;s/<\/td>.*//')" DNSvalue="$(echo "$line" | cut -d ',' -f 4 | sed 's/^[^&quot;]*&quot;//;s/&quot;.*//;s/<\/td>.*//')"
if [ $found != 0 ]; then if [ $found != 0 ]; then
break break
@ -192,11 +192,11 @@ dns_freedns_rm() {
# Need to read cookie from conf file again in case new value set # Need to read cookie from conf file again in case new value set
# during login to FreeDNS when TXT record was created. # during login to FreeDNS when TXT record was created.
# acme.sh does not have a _readaccountconf() fuction
# acme.sh does not have a _readaccountconf() function
FREEDNS_COOKIE="$(_read_conf "$ACCOUNT_CONF_PATH" "FREEDNS_COOKIE")" FREEDNS_COOKIE="$(_read_conf "$ACCOUNT_CONF_PATH" "FREEDNS_COOKIE")"
_debug "FreeDNS login cookies: $FREEDNS_COOKIE" _debug "FreeDNS login cookies: $FREEDNS_COOKIE"
# Sometimes FreeDNS does not reurn the subdomain page but rather
# Sometimes FreeDNS does not return the subdomain page but rather
# returns a page regarding becoming a premium member. This usually # returns a page regarding becoming a premium member. This usually
# happens after a period of inactivity. Immediately trying again # happens after a period of inactivity. Immediately trying again
# returns the correct subdomain page. So, we will try twice to # returns the correct subdomain page. So, we will try twice to
@ -302,12 +302,12 @@ _freedns_retrieve_subdomain_page() {
export _H2="Accept-Language:en-US" export _H2="Accept-Language:en-US"
url="https://freedns.afraid.org/subdomain/" url="https://freedns.afraid.org/subdomain/"
_debug "Retrieve subdmoain page from FreeDNS"
_debug "Retrieve subdomain page from FreeDNS"
htmlpage="$(_get "$url")" htmlpage="$(_get "$url")"
if [ "$?" != "0" ]; then if [ "$?" != "0" ]; then
_err "FreeDNS retrieve subdomins failed bad RC from _get"
_err "FreeDNS retrieve subdomains failed bad RC from _get"
return 1 return 1
elif [ -z "$htmlpage" ]; then elif [ -z "$htmlpage" ]; then
_err "FreeDNS returned empty subdomain page" _err "FreeDNS returned empty subdomain page"
@ -341,7 +341,7 @@ _freedns_add_txt_record() {
return 1 return 1
elif _contains "$htmlpage" "security code was incorrect"; then elif _contains "$htmlpage" "security code was incorrect"; then
_debug "$htmlpage" _debug "$htmlpage"
_err "FreeDNS failed to add TXT record for $subdomain as FreeDNS requested seurity code"
_err "FreeDNS failed to add TXT record for $subdomain as FreeDNS requested security code"
_err "Note that you cannot use automatic DNS validation for FreeDNS public domains" _err "Note that you cannot use automatic DNS validation for FreeDNS public domains"
return 1 return 1
fi fi

2
dnsapi/dns_gandi_livedns.sh

@ -19,7 +19,7 @@ dns_gandi_livedns_add() {
txtvalue=$2 txtvalue=$2
if [ -z "$GANDI_LIVEDNS_KEY" ]; then if [ -z "$GANDI_LIVEDNS_KEY" ]; then
_err "No API key specifed for Gandi LiveDNS."
_err "No API key specified for Gandi LiveDNS."
_err "Create your key and export it as GANDI_LIVEDNS_KEY" _err "Create your key and export it as GANDI_LIVEDNS_KEY"
return 1 return 1
fi fi

97
dnsapi/dns_infoblox.sh

@ -0,0 +1,97 @@
#!/usr/bin/env sh
## Infoblox API integration by Jason Keller and Elijah Tenai
##
## Report any bugs via https://github.com/jasonkeller/acme.sh
dns_infoblox_add() {
## Nothing to see here, just some housekeeping
fulldomain=$1
txtvalue=$2
baseurlnObject="https://$Infoblox_Server/wapi/v2.2.2/record:txt?name=$fulldomain&text=$txtvalue"
_info "Using Infoblox API"
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
## Check for the credentials
if [ -z "$Infoblox_Creds" ] || [ -z "$Infoblox_Server" ]; then
Infoblox_Creds=""
Infoblox_Server=""
_err "You didn't specify the credentials or server yet (Infoblox_Creds and Infoblox_Server)."
_err "Please set them via EXPORT ([username:password] and [ip or hostname]) and try again."
return 1
fi
## Save the credentials to the account file
_saveaccountconf Infoblox_Creds "$Infoblox_Creds"
_saveaccountconf Infoblox_Server "$Infoblox_Server"
## Base64 encode the credentials
Infoblox_CredsEncoded=$(printf "%b" "$Infoblox_Creds" | _base64)
## Construct the HTTP Authorization header
export _H1="Accept-Language:en-US"
export _H2="Authorization: Basic $Infoblox_CredsEncoded"
## Add the challenge record to the Infoblox grid member
result=$(_post "" "$baseurlnObject" "" "POST")
## Let's see if we get something intelligible back from the unit
if echo "$result" | egrep 'record:txt/.*:.*/default'; then
_info "Successfully created the txt record"
return 0
else
_err "Error encountered during record addition"
_err "$result"
return 1
fi
}
dns_infoblox_rm() {
## Nothing to see here, just some housekeeping
fulldomain=$1
txtvalue=$2
_info "Using Infoblox API"
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
## Base64 encode the credentials
Infoblox_CredsEncoded=$(printf "%b" "$Infoblox_Creds" | _base64)
## Construct the HTTP Authorization header
export _H1="Accept-Language:en-US"
export _H2="Authorization: Basic $Infoblox_CredsEncoded"
## Does the record exist? Let's check.
baseurlnObject="https://$Infoblox_Server/wapi/v2.2.2/record:txt?name=$fulldomain&text=$txtvalue&_return_type=xml-pretty"
result=$(_get "$baseurlnObject")
## Let's see if we get something intelligible back from the grid
if echo "$result" | egrep 'record:txt/.*:.*/default'; then
## Extract the object reference
objRef=$(printf "%b" "$result" | _egrep_o 'record:txt/.*:.*/default')
objRmUrl="https://$Infoblox_Server/wapi/v2.2.2/$objRef"
## Delete them! All the stale records!
rmResult=$(_post "" "$objRmUrl" "" "DELETE")
## Let's see if that worked
if echo "$rmResult" | egrep 'record:txt/.*:.*/default'; then
_info "Successfully deleted $objRef"
return 0
else
_err "Error occurred during txt record delete"
_err "$rmResult"
return 1
fi
else
_err "Record to delete didn't match an existing record"
_err "$result"
return 1
fi
}
#################### Private functions below ##################################

95
dnsapi/dns_knot.sh

@ -0,0 +1,95 @@
#!/usr/bin/env sh
######## Public functions #####################
#Usage: dns_knot_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_knot_add() {
fulldomain=$1
txtvalue=$2
_checkKey || return 1
[ -n "${KNOT_SERVER}" ] || KNOT_SERVER="localhost"
# save the dns server and key to the account.conf file.
_saveaccountconf KNOT_SERVER "${KNOT_SERVER}"
_saveaccountconf KNOT_KEY "${KNOT_KEY}"
if ! _get_root "$fulldomain"; then
_err "Domain does not exist."
return 1
fi
_info "Adding ${fulldomain}. 60 TXT \"${txtvalue}\""
knsupdate -y "${KNOT_KEY}" <<EOF
server ${KNOT_SERVER}
zone ${_domain}.
update add ${fulldomain}. 60 TXT "${txtvalue}"
send
quit
EOF
if [ $? -ne 0 ]; then
_err "Error updating domain."
return 1
fi
_info "Domain TXT record successfully added."
return 0
}
#Usage: dns_knot_rm _acme-challenge.www.domain.com
dns_knot_rm() {
fulldomain=$1
_checkKey || return 1
[ -n "${KNOT_SERVER}" ] || KNOT_SERVER="localhost"
if ! _get_root "$fulldomain"; then
_err "Domain does not exist."
return 1
fi
_info "Removing ${fulldomain}. TXT"
knsupdate -y "${KNOT_KEY}" <<EOF
server ${KNOT_SERVER}
zone ${_domain}.
update del ${fulldomain}. TXT
send
quit
EOF
if [ $? -ne 0 ]; then
_err "error updating domain"
return 1
fi
_info "Domain TXT record successfully deleted."
return 0
}
#################### Private functions below ##################################
# _acme-challenge.www.domain.com
# returns
# _domain=domain.com
_get_root() {
domain=$1
i="$(echo "$fulldomain" | tr '.' ' ' | wc -w)"
i=$(_math "$i" - 1)
while true; do
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
if [ -z "$h" ]; then
return 1
fi
_domain="$h"
return 0
done
_debug "$domain not found"
return 1
}
_checkKey() {
if [ -z "${KNOT_KEY}" ]; then
_err "You must specify a TSIG key to authenticate the request."
return 1
fi
}

2
dnsapi/dns_ovh.sh

@ -1,6 +1,6 @@
#!/usr/bin/env sh #!/usr/bin/env sh
#Applcation Key
#Application Key
#OVH_AK="sdfsdfsdfljlbjkljlkjsdfoiwje" #OVH_AK="sdfsdfsdfljlbjkljlkjsdfoiwje"
# #
#Application Secret #Application Secret

2
dnsapi/dns_pdns.sh

@ -1,6 +1,6 @@
#!/usr/bin/env sh #!/usr/bin/env sh
#PowerDNS Emdedded API
#PowerDNS Embedded API
#https://doc.powerdns.com/md/httpapi/api_spec/ #https://doc.powerdns.com/md/httpapi/api_spec/
# #
#PDNS_Url="http://ns.example.com:8081" #PDNS_Url="http://ns.example.com:8081"

Loading…
Cancel
Save