mirror of
https://github.com/plantroon/acme.sh.git
synced 2024-12-25 06:31:42 +00:00
Merge remote-tracking branch 'upstream/master' into ssh-deploy
This commit is contained in:
commit
070a141601
14
README.md
14
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
|
||||||
|
|
||||||
@ -295,6 +307,8 @@ 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)
|
||||||
|
|
||||||
**More APIs coming soon...**
|
**More APIs coming soon...**
|
||||||
|
|
||||||
|
20
acme.sh
20
acme.sh
@ -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"
|
||||||
@ -2462,7 +2472,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 +2556,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 +2569,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
|
||||||
@ -4618,7 +4628,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
|
||||||
|
@ -210,3 +210,9 @@ 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 OSX Keychain
|
||||||
|
|
||||||
|
```sh
|
||||||
|
acme.sh --deploy -d ftp.example.com --deploy-hook keychain
|
||||||
|
```
|
||||||
|
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
|
||||||
|
}
|
@ -349,6 +349,64 @@ 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
|
||||||
|
```
|
||||||
|
|
||||||
# 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.
|
||||||
|
@ -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"
|
_H2="Authorization: $Authorization"
|
||||||
_debug _H3 "$_H3"
|
_debug _H2 "$_H2"
|
||||||
|
|
||||||
url="$AWS_URL/$ep"
|
url="$AWS_URL/$ep"
|
||||||
|
|
||||||
|
@ -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
|
_contains "$response" '"code":1'
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
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 requres 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
|
||||||
|
}
|
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
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user