mirror of
https://github.com/acmesh-official/acme.sh.git
synced 2025-07-03 00:22:47 +00:00
Merge branch 'dev' into deploy/strongswan
This commit is contained in:
commit
abe957b700
28
README.md
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)
|
||||
|
||||
# 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
|
||||
|
||||
@ -149,17 +161,17 @@ You **MUST** use this command to copy the certs to the target files, **DO NOT**
|
||||
**Apache** example:
|
||||
```bash
|
||||
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"
|
||||
```
|
||||
|
||||
**Nginx** example:
|
||||
```bash
|
||||
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"
|
||||
```
|
||||
|
||||
@ -295,6 +307,10 @@ You don't have to do anything manually!
|
||||
1. cyon.ch
|
||||
1. Domain-Offensive/Resellerinterface/Domainrobot 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...**
|
||||
|
||||
@ -313,7 +329,7 @@ Just set the `length` parameter with a prefix `ec-`.
|
||||
|
||||
For example:
|
||||
|
||||
### Single domain ECC cerfiticate
|
||||
### Single domain ECC certificate
|
||||
|
||||
```bash
|
||||
acme.sh --issue -w /home/wwwroot/example.com -d example.com --keylength ec-256
|
||||
|
125
acme.sh
125
acme.sh
@ -146,7 +146,7 @@ _dlg_versions() {
|
||||
|
||||
echo "apache:"
|
||||
if [ "$_APACHECTL" ] && _exists "$_APACHECTL"; then
|
||||
_APACHECTL -V 2>&1
|
||||
$_APACHECTL -V 2>&1
|
||||
else
|
||||
echo "apache doesn't exists."
|
||||
fi
|
||||
@ -299,6 +299,16 @@ _secure_debug3() {
|
||||
fi
|
||||
}
|
||||
|
||||
_upper_case() {
|
||||
# shellcheck disable=SC2018,SC2019
|
||||
tr 'a-z' 'A-Z'
|
||||
}
|
||||
|
||||
_lower_case() {
|
||||
# shellcheck disable=SC2018,SC2019
|
||||
tr 'A-Z' 'a-z'
|
||||
}
|
||||
|
||||
_startswith() {
|
||||
_str="$1"
|
||||
_sub="$2"
|
||||
@ -330,7 +340,7 @@ _hasfield() {
|
||||
_sep=","
|
||||
fi
|
||||
|
||||
for f in $(echo "$_str" | tr ',' ' '); do
|
||||
for f in $(echo "$_str" | tr "$_sep" ' '); do
|
||||
if [ "$f" = "$_field" ]; then
|
||||
_debug2 "'$_str' contains '$_field'"
|
||||
return 0 #contains ok
|
||||
@ -869,7 +879,7 @@ _sign() {
|
||||
if ! _signedECText="$($_sign_openssl | $ACME_OPENSSL_BIN asn1parse -inform DER)"; then
|
||||
_err "Sign failed: $_sign_openssl"
|
||||
_err "Key file: $keyfile"
|
||||
_err "Key content:$(wc -l <"$keyfile") lises"
|
||||
_err "Key content:$(wc -l <"$keyfile") lines"
|
||||
return 1
|
||||
fi
|
||||
_debug3 "_signedECText" "$_signedECText"
|
||||
@ -1121,8 +1131,12 @@ _ss() {
|
||||
elif netstat -help 2>&1 | grep -- '-P protocol' >/dev/null; then
|
||||
#for solaris
|
||||
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 "
|
||||
else
|
||||
#for busybox (embedded linux; no pid support)
|
||||
netstat -ntl 2>/dev/null | grep ":$_port "
|
||||
fi
|
||||
fi
|
||||
return 0
|
||||
@ -1279,12 +1293,12 @@ _url_replace() {
|
||||
}
|
||||
|
||||
_time2str() {
|
||||
#BSD
|
||||
#Linux
|
||||
if date -u -d@"$1" 2>/dev/null; then
|
||||
return
|
||||
fi
|
||||
|
||||
#Linux
|
||||
#BSD
|
||||
if date -u -r "$1" 2>/dev/null; then
|
||||
return
|
||||
fi
|
||||
@ -1469,7 +1483,9 @@ _inithttp() {
|
||||
_ACME_CURL="$_ACME_CURL --trace-ascii $_CURL_DUMP "
|
||||
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 "
|
||||
fi
|
||||
|
||||
@ -1480,8 +1496,10 @@ _inithttp() {
|
||||
if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
|
||||
_ACME_WGET="$_ACME_WGET -d "
|
||||
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
|
||||
|
||||
@ -2240,16 +2258,16 @@ _initpath() {
|
||||
fi
|
||||
|
||||
if [ -z "$TLS_CONF" ]; then
|
||||
TLS_CONF="$DOMAIN_PATH/tls.valdation.conf"
|
||||
TLS_CONF="$DOMAIN_PATH/tls.validation.conf"
|
||||
fi
|
||||
if [ -z "$TLS_CERT" ]; then
|
||||
TLS_CERT="$DOMAIN_PATH/tls.valdation.cert"
|
||||
TLS_CERT="$DOMAIN_PATH/tls.validation.cert"
|
||||
fi
|
||||
if [ -z "$TLS_KEY" ]; then
|
||||
TLS_KEY="$DOMAIN_PATH/tls.valdation.key"
|
||||
TLS_KEY="$DOMAIN_PATH/tls.validation.key"
|
||||
fi
|
||||
if [ -z "$TLS_CSR" ]; then
|
||||
TLS_CSR="$DOMAIN_PATH/tls.valdation.csr"
|
||||
TLS_CSR="$DOMAIN_PATH/tls.validation.csr"
|
||||
fi
|
||||
|
||||
}
|
||||
@ -2367,7 +2385,7 @@ _setApache() {
|
||||
_debug "Backup apache config file" "$httpdconf"
|
||||
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 "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
|
||||
fi
|
||||
_info "JFYI, Config file $httpdconf is backuped to $APACHE_CONF_BACKUP_DIR/$httpdconfname"
|
||||
@ -2462,7 +2480,7 @@ _setNginx() {
|
||||
fi
|
||||
_debug "Start detect nginx conf for $_d from:$_start_f"
|
||||
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
|
||||
fi
|
||||
_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
|
||||
_debug "wildcard"
|
||||
for _w_f in $2; do
|
||||
if _checkConf "$1" "$_w_f"; then
|
||||
if [ -f "$_w_f"] && _checkConf "$1" "$_w_f"; then
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
@ -2559,9 +2577,9 @@ _checkConf() {
|
||||
FOUND_REAL_NGINX_CONF="$2"
|
||||
return 0
|
||||
fi
|
||||
if grep "^ *include *.*;" "$2" >/dev/null; then
|
||||
if cat "$2" | tr "\t" " " | grep "^ *include *.*;" >/dev/null; then
|
||||
_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"
|
||||
if _checkConf "$1" "$included"; then
|
||||
return 0
|
||||
@ -2865,7 +2883,7 @@ _on_issue_err() {
|
||||
uri=$(echo "$ventry" | cut -d "$sep" -f 3)
|
||||
vtype=$(echo "$ventry" | cut -d "$sep" -f 4)
|
||||
_currentRoot=$(echo "$ventry" | cut -d "$sep" -f 5)
|
||||
__trigger_validaton "$uri" "$keyauthorization"
|
||||
__trigger_validation "$uri" "$keyauthorization"
|
||||
done
|
||||
)
|
||||
fi
|
||||
@ -3087,7 +3105,7 @@ __get_domain_new_authz() {
|
||||
}
|
||||
|
||||
#uri keyAuthorization
|
||||
__trigger_validaton() {
|
||||
__trigger_validation() {
|
||||
_debug2 "tigger domain validation."
|
||||
_t_url="$1"
|
||||
_debug2 _t_url "$_t_url"
|
||||
@ -3467,9 +3485,12 @@ issue() {
|
||||
if [ ! "$usingApache" ]; then
|
||||
if webroot_owner=$(_stat "$_currentRoot"); then
|
||||
_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
|
||||
_debug "not chaning owner/group of webroot"
|
||||
_debug "not changing owner/group of webroot"
|
||||
fi
|
||||
fi
|
||||
|
||||
@ -3510,7 +3531,7 @@ issue() {
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! __trigger_validaton "$uri" "$keyauthorization"; then
|
||||
if ! __trigger_validation "$uri" "$keyauthorization"; then
|
||||
_err "$d:Can not get challenge: $response"
|
||||
_clearupwebbroot "$_currentRoot" "$removelevel" "$token"
|
||||
_clearup
|
||||
@ -3690,6 +3711,12 @@ issue() {
|
||||
_clearaccountconf "CA_BUNDLE"
|
||||
fi
|
||||
|
||||
if [ "$CA_PATH" ]; then
|
||||
_saveaccountconf CA_PATH "$CA_PATH"
|
||||
else
|
||||
_clearaccountconf "CA_PATH"
|
||||
fi
|
||||
|
||||
if [ "$HTTPS_INSECURE" ]; then
|
||||
_saveaccountconf HTTPS_INSECURE "$HTTPS_INSECURE"
|
||||
else
|
||||
@ -4008,7 +4035,7 @@ deploy() {
|
||||
installcert() {
|
||||
_main_domain="$1"
|
||||
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
|
||||
fi
|
||||
|
||||
@ -4107,6 +4134,7 @@ _installcert() {
|
||||
export CERT_KEY_PATH
|
||||
export CA_CERT_PATH
|
||||
export CERT_FULLCHAIN_PATH
|
||||
export Le_Domain
|
||||
cd "$DOMAIN_PATH" && eval "$_reload_cmd"
|
||||
); then
|
||||
_info "$(__green "Reload success")"
|
||||
@ -4618,7 +4646,7 @@ install() {
|
||||
#Modify shebang
|
||||
if _exists bash; then
|
||||
_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"
|
||||
for subf in $_SUB_FOLDERS; do
|
||||
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:
|
||||
|
||||
--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.
|
||||
|
||||
@ -4779,12 +4807,13 @@ Parameters:
|
||||
--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.
|
||||
--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.
|
||||
--ecc Specifies to use the ECC cert. Valid for '--install-cert', '--renew', '--revoke', '--toPkcs' and '--createCSR'
|
||||
--csr Specifies the input csr.
|
||||
--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.
|
||||
--deploy-hook The hook file to deploy cert
|
||||
--ocsp-must-staple, --ocsp Generate ocsp must Staple extension.
|
||||
@ -4886,10 +4915,10 @@ _process() {
|
||||
_webroot=""
|
||||
_keylength=""
|
||||
_accountkeylength=""
|
||||
_certpath=""
|
||||
_keypath=""
|
||||
_capath=""
|
||||
_fullchainpath=""
|
||||
_cert_file=""
|
||||
_key_file=""
|
||||
_ca_file=""
|
||||
_fullchain_file=""
|
||||
_reloadcmd=""
|
||||
_password=""
|
||||
_accountconf=""
|
||||
@ -4905,6 +4934,7 @@ _process() {
|
||||
_stopRenewOnError=""
|
||||
#_insecure=""
|
||||
_ca_bundle=""
|
||||
_ca_path=""
|
||||
_nocron=""
|
||||
_ecc=""
|
||||
_csr=""
|
||||
@ -5130,20 +5160,20 @@ _process() {
|
||||
shift
|
||||
;;
|
||||
|
||||
--certpath)
|
||||
_certpath="$2"
|
||||
--cert-file | --certpath)
|
||||
_cert_file="$2"
|
||||
shift
|
||||
;;
|
||||
--keypath)
|
||||
_keypath="$2"
|
||||
--key-file | --keypath)
|
||||
_key_file="$2"
|
||||
shift
|
||||
;;
|
||||
--capath)
|
||||
_capath="$2"
|
||||
--ca-file | --capath)
|
||||
_ca_file="$2"
|
||||
shift
|
||||
;;
|
||||
--fullchainpath)
|
||||
_fullchainpath="$2"
|
||||
--fullchain-file | --fullchainpath)
|
||||
_fullchain_file="$2"
|
||||
shift
|
||||
;;
|
||||
--reloadcmd | --reloadCmd)
|
||||
@ -5219,6 +5249,11 @@ _process() {
|
||||
CA_BUNDLE="$_ca_bundle"
|
||||
shift
|
||||
;;
|
||||
--ca-path)
|
||||
_ca_path="$2"
|
||||
CA_PATH="$_ca_path"
|
||||
shift
|
||||
;;
|
||||
--nocron)
|
||||
_nocron="1"
|
||||
;;
|
||||
@ -5360,7 +5395,7 @@ _process() {
|
||||
uninstall) uninstall "$_nocron" ;;
|
||||
upgrade) upgrade ;;
|
||||
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 "$_domain" "$_deploy_hook" "$_ecc"
|
||||
@ -5372,7 +5407,7 @@ _process() {
|
||||
showcsr "$_csr" "$_domain"
|
||||
;;
|
||||
installcert)
|
||||
installcert "$_domain" "$_certpath" "$_keypath" "$_capath" "$_reloadcmd" "$_fullchainpath" "$_ecc"
|
||||
installcert "$_domain" "$_cert_file" "$_key_file" "$_ca_file" "$_reloadcmd" "$_fullchain_file" "$_ecc"
|
||||
;;
|
||||
renew)
|
||||
renew "$_domain" "$_ecc"
|
||||
|
@ -72,7 +72,13 @@ export DEPLOY_EXIM4_RELOAD="/etc/init.d/exim4 restart"
|
||||
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
|
||||
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
|
||||
|
@ -79,7 +79,7 @@ exim4_deploy() {
|
||||
_info "Restore conf success"
|
||||
eval "$_reload"
|
||||
else
|
||||
_err "Opps, error restore exim4 conf, please report bug to us."
|
||||
_err "Oops, error restore exim4 conf, please report bug to us."
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
@ -105,7 +105,7 @@ exim4_deploy() {
|
||||
_info "Restore conf success"
|
||||
eval "$_reload"
|
||||
else
|
||||
_err "Opps, error restore exim4 conf, please report bug to us."
|
||||
_err "Oops, error restore exim4 conf, please report bug to us."
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
|
31
deploy/keychain.sh
Normal file
31
deploy/keychain.sh
Normal file
@ -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
|
||||
}
|
@ -43,7 +43,7 @@ kong_deploy() {
|
||||
#Save kong url if it's succesful (First run case)
|
||||
_saveaccountconf KONG_URL "$KONG_URL"
|
||||
#Generate DEIM
|
||||
delim="-----MultipartDelimeter$(date "+%s%N")"
|
||||
delim="-----MultipartDelimiter$(date "+%s%N")"
|
||||
nl="\015\012"
|
||||
#Set Header
|
||||
_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")
|
||||
fi
|
||||
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"
|
||||
return 1
|
||||
fi
|
||||
|
@ -76,7 +76,7 @@ vsftpd_deploy() {
|
||||
_info "Restore conf success"
|
||||
eval "$_reload"
|
||||
else
|
||||
_err "Opps, error restore vsftpd conf, please report bug to us."
|
||||
_err "Oops, error restore vsftpd conf, please report bug to us."
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
@ -102,7 +102,7 @@ vsftpd_deploy() {
|
||||
_info "Restore conf success"
|
||||
eval "$_reload"
|
||||
else
|
||||
_err "Opps, error restore vsftpd conf, please report bug to us."
|
||||
_err "Oops, error restore vsftpd conf, please report bug to us."
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
|
@ -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
|
||||
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.
|
||||
|
||||
## 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
|
||||
```
|
||||
|
||||
## 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
|
||||
|
||||
If your API is not supported yet, you can write your own DNS API.
|
||||
|
@ -143,7 +143,7 @@ aws_rest() {
|
||||
CanonicalHeaders="host:$aws_host\nx-amz-date:$RequestDate\n"
|
||||
SignedHeaders="host;x-amz-date"
|
||||
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"
|
||||
SignedHeaders="${SignedHeaders};x-amz-security-token"
|
||||
fi
|
||||
@ -204,8 +204,8 @@ aws_rest() {
|
||||
Authorization="$Algorithm Credential=$AWS_ACCESS_KEY_ID/$CredentialScope, SignedHeaders=$SignedHeaders, Signature=$signature"
|
||||
_debug2 Authorization "$Authorization"
|
||||
|
||||
_H3="Authorization: $Authorization"
|
||||
_debug _H3 "$_H3"
|
||||
_H2="Authorization: $Authorization"
|
||||
_debug _H2 "$_H2"
|
||||
|
||||
url="$AWS_URL/$ep"
|
||||
|
||||
|
170
dnsapi/dns_cloudns.sh
Executable file
170
dnsapi/dns_cloudns.sh
Executable file
@ -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
|
||||
}
|
@ -209,8 +209,7 @@ _rest() {
|
||||
return 1
|
||||
fi
|
||||
_debug2 response "$response"
|
||||
if ! _contains "$response" '"message":"success"'; then
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
|
||||
_contains "$response" '"code":1'
|
||||
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ _cyon_load_credentials() {
|
||||
fi
|
||||
|
||||
if [ -z "${CY_Username}" ] || [ -z "${CY_Password}" ]; then
|
||||
# Dummy entries to satify script checker.
|
||||
# Dummy entries to satisfy script checker.
|
||||
CY_Username=""
|
||||
CY_Password=""
|
||||
CY_OTP_Secret=""
|
||||
|
205
dnsapi/dns_dgon.sh
Executable file
205
dnsapi/dns_dgon.sh
Executable file
@ -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
|
||||
}
|
@ -10,7 +10,7 @@
|
||||
#
|
||||
######## Public functions #####################
|
||||
|
||||
# Export FreeDNS userid and password in folowing variables...
|
||||
# Export FreeDNS userid and password in following variables...
|
||||
# FREEDNS_User=username
|
||||
# FREEDNS_Password=password
|
||||
# login cookie is saved in acme account config file so userid / pw
|
||||
@ -53,7 +53,7 @@ dns_freedns_add() {
|
||||
i="$(_math "$i" - 1)"
|
||||
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
|
||||
# happens after a period of inactivity. Immediately trying again
|
||||
# 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")"
|
||||
if [ "$?" != "0" ]; 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."
|
||||
fi
|
||||
return 1
|
||||
@ -112,7 +112,7 @@ dns_freedns_add() {
|
||||
# not produce accurate results as the value field is truncated
|
||||
# on this webpage. To get full value we would need to load
|
||||
# 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/^[^"]*"//;s/".*//;s/<\/td>.*//')"
|
||||
if [ $found != 0 ]; then
|
||||
break
|
||||
@ -192,11 +192,11 @@ dns_freedns_rm() {
|
||||
|
||||
# Need to read cookie from conf file again in case new value set
|
||||
# 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")"
|
||||
_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
|
||||
# happens after a period of inactivity. Immediately trying again
|
||||
# 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"
|
||||
url="https://freedns.afraid.org/subdomain/"
|
||||
|
||||
_debug "Retrieve subdmoain page from FreeDNS"
|
||||
_debug "Retrieve subdomain page from FreeDNS"
|
||||
|
||||
htmlpage="$(_get "$url")"
|
||||
|
||||
if [ "$?" != "0" ]; then
|
||||
_err "FreeDNS retrieve subdomins failed bad RC from _get"
|
||||
_err "FreeDNS retrieve subdomains failed bad RC from _get"
|
||||
return 1
|
||||
elif [ -z "$htmlpage" ]; then
|
||||
_err "FreeDNS returned empty subdomain page"
|
||||
@ -341,7 +341,7 @@ _freedns_add_txt_record() {
|
||||
return 1
|
||||
elif _contains "$htmlpage" "security code was incorrect"; then
|
||||
_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"
|
||||
return 1
|
||||
fi
|
||||
|
@ -19,7 +19,7 @@ dns_gandi_livedns_add() {
|
||||
txtvalue=$2
|
||||
|
||||
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"
|
||||
return 1
|
||||
fi
|
||||
|
97
dnsapi/dns_infoblox.sh
Normal file
97
dnsapi/dns_infoblox.sh
Normal file
@ -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
Normal file
95
dnsapi/dns_knot.sh
Normal file
@ -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
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#Applcation Key
|
||||
#Application Key
|
||||
#OVH_AK="sdfsdfsdfljlbjkljlkjsdfoiwje"
|
||||
#
|
||||
#Application Secret
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#PowerDNS Emdedded API
|
||||
#PowerDNS Embedded API
|
||||
#https://doc.powerdns.com/md/httpapi/api_spec/
|
||||
#
|
||||
#PDNS_Url="http://ns.example.com:8081"
|
||||
|
Loading…
x
Reference in New Issue
Block a user