mirror of
https://github.com/acmesh-official/acme.sh.git
synced 2025-12-26 21:52:09 +08:00
Compare commits
115 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
50d7b8452d | ||
|
|
d88f8e862b | ||
|
|
fd72cced13 | ||
|
|
a6feb0a887 | ||
|
|
cd9c3a79e5 | ||
|
|
f3685bdef9 | ||
|
|
e2edf20833 | ||
|
|
31e39f1f6d | ||
|
|
d47c5eaf60 | ||
|
|
b8e515a738 | ||
|
|
0984585d58 | ||
|
|
f3e0eb705b | ||
|
|
04e0f87c03 | ||
|
|
8ccfcd272f | ||
|
|
ba69062a36 | ||
|
|
cea24b5f70 | ||
|
|
f3a71f62a1 | ||
|
|
4e4a6d8397 | ||
|
|
d8beaf727f | ||
|
|
c961c865ee | ||
|
|
34f25fa590 | ||
|
|
7af1155c11 | ||
|
|
c9d7daab70 | ||
|
|
981077516b | ||
|
|
7c488b5913 | ||
|
|
0e44f587a5 | ||
|
|
e593d86b80 | ||
|
|
339a8ad610 | ||
|
|
d1190febec | ||
|
|
5d2c5b01a8 | ||
|
|
0f954c20ff | ||
|
|
d6edff3182 | ||
|
|
dba26c3240 | ||
|
|
0ca5b7996c | ||
|
|
63e1d3610c | ||
|
|
b4325026b1 | ||
|
|
b072ef2e82 | ||
|
|
562a4c056e | ||
|
|
bb8248556d | ||
|
|
b22b085b50 | ||
|
|
a50252382a | ||
|
|
9bdb799b41 | ||
|
|
259cefab72 | ||
|
|
09ed421948 | ||
|
|
87f5ec5be5 | ||
|
|
f78b656f5f | ||
|
|
e6b940e247 | ||
|
|
50a9680f17 | ||
|
|
f2a6dc4dfd | ||
|
|
67e3dd36b3 | ||
|
|
6c4cc357b5 | ||
|
|
94965a418f | ||
|
|
40e6ba1100 | ||
|
|
0aed065a75 | ||
|
|
70b63a5ed4 | ||
|
|
1476a9ecf1 | ||
|
|
600a235140 | ||
|
|
ffa9f104db | ||
|
|
b807ec0956 | ||
|
|
5f8daeeb6d | ||
|
|
aec8307417 | ||
|
|
e96a1b01b9 | ||
|
|
d78ba322bf | ||
|
|
ab5c1b0a3a | ||
|
|
53fa16d39f | ||
|
|
05cf405cb5 | ||
|
|
5d833336d3 | ||
|
|
13be9d8d79 | ||
|
|
bb6326f4d4 | ||
|
|
c070407ab2 | ||
|
|
6b27bdadcd | ||
|
|
1c22c2f76a | ||
|
|
aa262d4124 | ||
|
|
646c0bfcb9 | ||
|
|
da68775472 | ||
|
|
bcf96608d1 | ||
|
|
dd17ac5045 | ||
|
|
59182dbc97 | ||
|
|
11df7187b3 | ||
|
|
0899803294 | ||
|
|
4742e0951c | ||
|
|
c3b1eb0837 | ||
|
|
542d7977db | ||
|
|
11927a768e | ||
|
|
ecd5bcec0c | ||
|
|
911a2084d4 | ||
|
|
839bf0e2c9 | ||
|
|
25555b8c3e | ||
|
|
cd7ac94f35 | ||
|
|
68aea3af9e | ||
|
|
cdb3216cc9 | ||
|
|
78f0201dfa | ||
|
|
2cd47b0240 | ||
|
|
be83a6a37a | ||
|
|
8ca99e85b0 | ||
|
|
f5b546b3c8 | ||
|
|
50c9d17830 | ||
|
|
d87af4788e | ||
|
|
0f21537f14 | ||
|
|
0533bde9f2 | ||
|
|
32b3717c32 | ||
|
|
d950f801af | ||
|
|
a8ab028b84 | ||
|
|
2aff36e74b | ||
|
|
db7e4bf940 | ||
|
|
ee20015d44 | ||
|
|
80941f8413 | ||
|
|
cf909db159 | ||
|
|
27dbe77fad | ||
|
|
38f2334360 | ||
|
|
5fe91d6577 | ||
|
|
753d0e7df7 | ||
|
|
e2cc350fbc | ||
|
|
07feb87dee | ||
|
|
1699e94f0f |
4
.github/ISSUE_TEMPLATE.md
vendored
4
.github/ISSUE_TEMPLATE.md
vendored
@@ -1,4 +1,6 @@
|
||||
<!--
|
||||
请确保已经更新到最新的代码, 然后贴上来 `--debug 2` 的调试输出. 没有调试输出,我帮不了你.
|
||||
如何调试 https://github.com/Neilpang/acme.sh/wiki/How-to-debug-acme.sh
|
||||
|
||||
If it is a bug report:
|
||||
- make sure you are able to repro it on the latest released version.
|
||||
@@ -8,13 +10,11 @@ You can install the latest version by: `acme.sh --upgrade`
|
||||
- Refer to the [WIKI](https://wiki.acme.sh).
|
||||
- Debug info [Debug](https://github.com/Neilpang/acme.sh/wiki/How-to-debug-acme.sh).
|
||||
|
||||
|
||||
-->
|
||||
|
||||
Steps to reproduce
|
||||
------------------
|
||||
|
||||
|
||||
Debug log
|
||||
-----------------
|
||||
|
||||
|
||||
@@ -33,7 +33,6 @@ install:
|
||||
fi
|
||||
|
||||
script:
|
||||
- echo "TEST_LOCAL=$TEST_LOCAL"
|
||||
- echo "NGROK_TOKEN=$(echo "$NGROK_TOKEN" | wc -c)"
|
||||
- command -V openssl && openssl version
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then curl -sSL $SHFMT_URL -o ~/shfmt ; fi
|
||||
@@ -44,8 +43,8 @@ script:
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then shellcheck **/*.sh && echo "shellcheck OK" ; fi
|
||||
- cd ..
|
||||
- git clone https://github.com/Neilpang/acmetest.git && cp -r acme.sh acmetest/ && cd acmetest
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" -a "$NGROK_TOKEN" ]; then sudo NGROK_TOKEN="$NGROK_TOKEN" ./letest.sh ; fi
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" -a "$NGROK_TOKEN" ]; then sudo NGROK_TOKEN="$NGROK_TOKEN" OPENSSL_BIN="$OPENSSL_BIN" ./letest.sh ; fi
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" -a "$NGROK_TOKEN" ]; then sudo TEST_LOCAL="$TEST_LOCAL" NGROK_TOKEN="$NGROK_TOKEN" ./letest.sh ; fi
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" -a "$NGROK_TOKEN" ]; then sudo TEST_LOCAL="$TEST_LOCAL" NGROK_TOKEN="$NGROK_TOKEN" OPENSSL_BIN="$OPENSSL_BIN" ./letest.sh ; fi
|
||||
|
||||
|
||||
matrix:
|
||||
|
||||
10
README.md
10
README.md
@@ -13,6 +13,9 @@ It's probably the `easiest&smallest&smartest` shell script to automatically issu
|
||||
Wiki: https://github.com/Neilpang/acme.sh/wiki
|
||||
|
||||
|
||||
Twitter: [@neilpangxa](https://twitter.com/neilpangxa)
|
||||
|
||||
|
||||
# [中文说明](https://github.com/Neilpang/acme.sh/wiki/%E8%AF%B4%E6%98%8E)
|
||||
|
||||
|
||||
@@ -52,6 +55,7 @@ https://github.com/Neilpang/acmetest
|
||||
- Standalone mode
|
||||
- Apache mode
|
||||
- DNS mode
|
||||
- [Stateless mode](https://github.com/Neilpang/acme.sh/wiki/Stateless-Mode)
|
||||
|
||||
|
||||
# 1. How to install
|
||||
@@ -143,7 +147,7 @@ You **MUST** use this command to copy the certs to the target files, **DO NOT**
|
||||
|
||||
**Apache** example:
|
||||
```bash
|
||||
acme.sh --installcert -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 \
|
||||
@@ -152,7 +156,7 @@ acme.sh --installcert -d example.com \
|
||||
|
||||
**Nginx** example:
|
||||
```bash
|
||||
acme.sh --installcert -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 \
|
||||
--reloadcmd "service nginx force-reload"
|
||||
@@ -266,6 +270,8 @@ You don't have to do anything manually!
|
||||
1. aliyun.com(阿里云) API
|
||||
1. ISPConfig 3.1 API
|
||||
1. Alwaysdata.com API
|
||||
1. Linode.com API
|
||||
1. FreeDNS (https://freedns.afraid.org/)
|
||||
|
||||
**More APIs coming soon...**
|
||||
|
||||
|
||||
30
deploy/README.md
Normal file
30
deploy/README.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# Using deploy api
|
||||
|
||||
Here are the scripts to deploy the certs/key to the server/services.
|
||||
|
||||
## 1. Deploy the certs to your cpanel host.
|
||||
|
||||
(cpanel deploy hook is not finished yet, this is just an example.)
|
||||
|
||||
Before you can deploy your cert, you must [issue the cert first](https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert).
|
||||
|
||||
Then you can deploy now:
|
||||
|
||||
```sh
|
||||
export DEPLOY_CPANEL_USER=myusername
|
||||
export DEPLOY_CPANEL_PASSWORD=PASSWORD
|
||||
acme.sh --deploy -d example.com --deploy --deploy-hook cpanel
|
||||
```
|
||||
|
||||
## 2. Deploy ssl cert on kong proxy engine based on api.
|
||||
|
||||
Before you can deploy your cert, you must [issue the cert first](https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert).
|
||||
|
||||
(TODO)
|
||||
|
||||
## 3. Deploy the cert to remote server through SSH access.
|
||||
|
||||
(TODO)
|
||||
|
||||
|
||||
|
||||
29
deploy/cpanel.sh
Normal file
29
deploy/cpanel.sh
Normal file
@@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#Here is the script to deploy the cert to your cpanel account by the cpanel APIs.
|
||||
|
||||
#returns 0 means success, otherwise error.
|
||||
|
||||
#export DEPLOY_CPANEL_USER=myusername
|
||||
#export DEPLOY_CPANEL_PASSWORD=PASSWORD
|
||||
|
||||
######## Public functions #####################
|
||||
|
||||
#domain keyfile certfile cafile fullchain
|
||||
cpanel_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"
|
||||
|
||||
_err "Not implemented yet"
|
||||
return 1
|
||||
|
||||
}
|
||||
81
deploy/kong.sh
Executable file
81
deploy/kong.sh
Executable file
@@ -0,0 +1,81 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
# This deploy hook will deploy ssl cert on kong proxy engine based on api request_host parameter.
|
||||
# Note that ssl plugin should be available on Kong instance
|
||||
# The hook will match cdomain to request_host, in case of multiple domain it will always take the first
|
||||
# one (acme.sh behaviour).
|
||||
# If ssl config already exist it will update only cert and key not touching other parameter
|
||||
# If ssl config doesn't exist it will only upload cert and key and not set other parameter
|
||||
# Not that we deploy full chain
|
||||
# See https://getkong.org/plugins/dynamic-ssl/ for other options
|
||||
# Written by Geoffroi Genot <ggenot@voxbone.com>
|
||||
|
||||
######## Public functions #####################
|
||||
|
||||
#domain keyfile certfile cafile fullchain
|
||||
kong_deploy() {
|
||||
_cdomain="$1"
|
||||
_ckey="$2"
|
||||
_ccert="$3"
|
||||
_cca="$4"
|
||||
_cfullchain="$5"
|
||||
_info "Deploying certificate on Kong instance"
|
||||
if [ -z "$KONG_URL" ]; then
|
||||
_debug "KONG_URL Not set, using default http://localhost:8001"
|
||||
KONG_URL="http://localhost:8001"
|
||||
fi
|
||||
|
||||
_debug _cdomain "$_cdomain"
|
||||
_debug _ckey "$_ckey"
|
||||
_debug _ccert "$_ccert"
|
||||
_debug _cca "$_cca"
|
||||
_debug _cfullchain "$_cfullchain"
|
||||
|
||||
#Get uuid linked to the domain
|
||||
uuid=$(_get "$KONG_URL/apis?request_host=$_cdomain" | _normalizeJson | _egrep_o '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}')
|
||||
if [ -z "$uuid" ]; then
|
||||
_err "Unable to get Kong uuid for domain $_cdomain"
|
||||
_err "Make sure that KONG_URL is correctly configured"
|
||||
_err "Make sure that a Kong api request_host match the domain"
|
||||
_err "Kong url: $KONG_URL"
|
||||
return 1
|
||||
fi
|
||||
#Save kong url if it's succesful (First run case)
|
||||
_saveaccountconf KONG_URL "$KONG_URL"
|
||||
#Generate DEIM
|
||||
delim="-----MultipartDelimeter$(date "+%s%N")"
|
||||
nl="\015\012"
|
||||
#Set Header
|
||||
_H1="Content-Type: multipart/form-data; boundary=$delim"
|
||||
#Generate data for request (Multipart/form-data with mixed content)
|
||||
#set name to ssl
|
||||
content="--$delim${nl}Content-Disposition: form-data; name=\"name\"${nl}${nl}ssl"
|
||||
#add key
|
||||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"config.key\"; filename=\"$(basename "$_ckey")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ckey")"
|
||||
#Add cert
|
||||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"config.cert\"; filename=\"$(basename "$_cfullchain")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_cfullchain")"
|
||||
#Close multipart
|
||||
content="$content${nl}--$delim--${nl}"
|
||||
#Convert CRLF
|
||||
content=$(printf %b "$content")
|
||||
#DEBUG
|
||||
_debug header "$_H1"
|
||||
_debug content "$content"
|
||||
#Check if ssl plugins is aready enabled (if not => POST else => PATCH)
|
||||
ssl_uuid=$(_get "$KONG_URL/apis/$uuid/plugins" | _egrep_o '"id":"[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"[a-zA-Z0-9\-\,\"_\:]*"name":"ssl"' | _egrep_o '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}')
|
||||
_debug ssl_uuid "$ssl_uuid"
|
||||
if [ -z "$ssl_uuid" ]; then
|
||||
#Post certificate to Kong
|
||||
response=$(_post "$content" "$KONG_URL/apis/$uuid/plugins" "" "POST")
|
||||
else
|
||||
#patch
|
||||
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 "$response"
|
||||
return 1
|
||||
fi
|
||||
_debug response "$response"
|
||||
_info "Certificate successfully deployed"
|
||||
}
|
||||
0
deploy/myapi.sh
Normal file → Executable file
0
deploy/myapi.sh
Normal file → Executable file
@@ -257,6 +257,54 @@ acme.sh --issue --dns dns_ad -d example.com -d www.example.com
|
||||
The `AD_API_KEY` will be saved in `~/.acme.sh/account.conf` and will be reused
|
||||
when needed.
|
||||
|
||||
## 14. Use Linode domain API
|
||||
|
||||
First you need to login to your Linode account to get your API Key.
|
||||
[https://manager.linode.com/profile/api](https://manager.linode.com/profile/api)
|
||||
|
||||
Then add an API key with label *ACME* and copy the new key.
|
||||
|
||||
```sh
|
||||
export LINODE_API_KEY="..."
|
||||
```
|
||||
|
||||
Due to the reload time of any changes in the DNS records, we have to use the `dnssleep` option to wait at least 15 minutes for the changes to take effect.
|
||||
|
||||
Ok, let's issue a cert now:
|
||||
|
||||
```sh
|
||||
acme.sh --issue --dns dns_linode --dnssleep 900 -d example.com -d www.example.com
|
||||
```
|
||||
|
||||
The `LINODE_API_KEY` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
|
||||
|
||||
## 15. Use FreeDNS
|
||||
|
||||
FreeDNS (https://freedns.afraid.org/) does not provide an API to update DNS records (other than IPv4 and IPv6
|
||||
dynamic DNS addresses). The acme.sh plugin therefore retrieves and updates domain TXT records by logging
|
||||
into the FreeDNS website to read the HTML and posting updates as HTTP. The plugin needs to know your
|
||||
userid and password for the FreeDNS website.
|
||||
|
||||
```sh
|
||||
export FREEDNS_User="..."
|
||||
export FREEDNS_Password="..."
|
||||
```
|
||||
|
||||
You need only provide this the first time you run the acme.sh client with FreeDNS validation and then again
|
||||
whenever you change your password at the FreeDNS site. The acme.sh FreeDNS plugin does not store your userid
|
||||
or password but rather saves an authentication token returned by FreeDNS in `~/.acme.sh/account.conf` and
|
||||
reuses that when needed.
|
||||
|
||||
Now you can issue a certificate.
|
||||
|
||||
```sh
|
||||
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
|
||||
validate with acme.sh at FreeDNS.
|
||||
|
||||
# Use custom API
|
||||
|
||||
If your API is not supported yet, you can write your own DNS API.
|
||||
|
||||
0
dnsapi/dns_ad.sh
Normal file → Executable file
0
dnsapi/dns_ad.sh
Normal file → Executable file
2
dnsapi/dns_ali.sh
Normal file → Executable file
2
dnsapi/dns_ali.sh
Normal file → Executable file
@@ -67,7 +67,7 @@ _get_root() {
|
||||
}
|
||||
|
||||
_ali_rest() {
|
||||
signature=$(printf "%s" "GET&%2F&$(_ali_urlencode "$query")" | _hmac "sha1" "$(_hex "$Ali_Secret&")" | _base64)
|
||||
signature=$(printf "%s" "GET&%2F&$(_ali_urlencode "$query")" | _hmac "sha1" "$(printf "%s" "$Ali_Secret&" | _hex_dump | tr -d " ")" | _base64)
|
||||
signature=$(_ali_urlencode "$signature")
|
||||
url="$Ali_API?$query&Signature=$signature"
|
||||
|
||||
|
||||
4
dnsapi/dns_aws.sh
Normal file → Executable file
4
dnsapi/dns_aws.sh
Normal file → Executable file
@@ -93,7 +93,7 @@ _get_root() {
|
||||
fi
|
||||
|
||||
if _contains "$response" "<Name>$h.</Name>"; then
|
||||
hostedzone="$(echo "$response" | sed 's/<HostedZone>/\n&/g' | _egrep_o "<HostedZone>.*?<Name>$h.<.Name>.*?<.HostedZone>")"
|
||||
hostedzone="$(echo "$response" | sed 's/<HostedZone>/#&/g' | tr '#' '\n' | _egrep_o "<HostedZone><Id>[^<]*<.Id><Name>$h.<.Name>.*<.HostedZone>")"
|
||||
_debug hostedzone "$hostedzone"
|
||||
if [ -z "$hostedzone" ]; then
|
||||
_err "Error, can not get hostedzone."
|
||||
@@ -183,7 +183,7 @@ aws_rest() {
|
||||
|
||||
_debug2 kSecret "$kSecret"
|
||||
|
||||
kSecretH="$(_hex "$kSecret")"
|
||||
kSecretH="$(printf "%s" "$kSecret" | _hex_dump | tr -d " ")"
|
||||
_debug2 kSecretH "$kSecretH"
|
||||
|
||||
kDateH="$(printf "$RequestDateOnly%s" | _hmac "$Hash" "$kSecretH" hex)"
|
||||
|
||||
@@ -82,7 +82,7 @@ existing_records() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
seg=$(printf "%s\n" "$response" | _egrep_o '[^{]*host":"'"$_sub_domain"'"[^}]*\}')
|
||||
seg=$(printf "%s\n" "$response" | _egrep_o '"record_id":[^{]*host":"'"$_sub_domain"'"[^}]*\}')
|
||||
_debug seg "$seg"
|
||||
if [ -z "$seg" ]; then
|
||||
return 0
|
||||
@@ -155,7 +155,7 @@ _get_root() {
|
||||
fi
|
||||
|
||||
if _contains "$response" "$h."; then
|
||||
seg=$(printf "%s\n" "$response" | _egrep_o '[^{]*"'"$h"'."[^}]*}')
|
||||
seg=$(printf "%s\n" "$response" | _egrep_o '"id":[^{]*"'"$h"'."[^}]*}')
|
||||
_debug seg "$seg"
|
||||
_domain_id=$(printf "%s\n" "$seg" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \")
|
||||
_debug _domain_id "$_domain_id"
|
||||
|
||||
375
dnsapi/dns_freedns.sh
Executable file
375
dnsapi/dns_freedns.sh
Executable file
@@ -0,0 +1,375 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#This file name is "dns_freedns.sh"
|
||||
#So, here must be a method dns_freedns_add()
|
||||
#Which will be called by acme.sh to add the txt record to your api system.
|
||||
#returns 0 means success, otherwise error.
|
||||
#
|
||||
#Author: David Kerr
|
||||
#Report Bugs here: https://github.com/dkerr64/acme.sh
|
||||
#
|
||||
######## Public functions #####################
|
||||
|
||||
# Export FreeDNS userid and password in folowing variables...
|
||||
# FREEDNS_User=username
|
||||
# FREEDNS_Password=password
|
||||
# login cookie is saved in acme account config file so userid / pw
|
||||
# need to be set only when changed.
|
||||
|
||||
#Usage: dns_freedns_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
dns_freedns_add() {
|
||||
fulldomain="$1"
|
||||
txtvalue="$2"
|
||||
|
||||
_info "Add TXT record using FreeDNS"
|
||||
_debug "fulldomain: $fulldomain"
|
||||
_debug "txtvalue: $txtvalue"
|
||||
|
||||
if [ -z "$FREEDNS_User" ] || [ -z "$FREEDNS_Password" ]; then
|
||||
FREEDNS_User=""
|
||||
FREEDNS_Password=""
|
||||
if [ -z "$FREEDNS_COOKIE" ]; then
|
||||
_err "You did not specify the FreeDNS username and password yet."
|
||||
_err "Please export as FREEDNS_User / FREEDNS_Password and try again."
|
||||
return 1
|
||||
fi
|
||||
using_cached_cookies="true"
|
||||
else
|
||||
FREEDNS_COOKIE="$(_freedns_login "$FREEDNS_User" "$FREEDNS_Password")"
|
||||
if [ -z "$FREEDNS_COOKIE" ]; then
|
||||
return 1
|
||||
fi
|
||||
using_cached_cookies="false"
|
||||
fi
|
||||
|
||||
_debug "FreeDNS login cookies: $FREEDNS_COOKIE (cached = $using_cached_cookies)"
|
||||
|
||||
_saveaccountconf FREEDNS_COOKIE "$FREEDNS_COOKIE"
|
||||
|
||||
# split our full domain name into two parts...
|
||||
i="$(echo "$fulldomain" | tr '.' ' ' | wc -w)"
|
||||
i="$(_math "$i" - 1)"
|
||||
top_domain="$(echo "$fulldomain" | cut -d. -f "$i"-100)"
|
||||
i="$(_math "$i" - 1)"
|
||||
sub_domain="$(echo "$fulldomain" | cut -d. -f -"$i")"
|
||||
|
||||
# Sometimes FreeDNS does not reurn 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
|
||||
# load the page and obtain our domain ID
|
||||
attempts=2
|
||||
while [ "$attempts" -gt "0" ]; do
|
||||
attempts="$(_math "$attempts" - 1)"
|
||||
|
||||
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 "Please export as FREEDNS_User / FREEDNS_Password and try again."
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Now convert the tables in the HTML to CSV. This litte gem from
|
||||
# http://stackoverflow.com/questions/1403087/how-can-i-convert-an-html-table-to-csv
|
||||
subdomain_csv="$(echo "$htmlpage" \
|
||||
| grep -i -e '</\?TABLE\|</\?TD\|</\?TR\|</\?TH' \
|
||||
| sed 's/^[\ \t]*//g' \
|
||||
| tr -d '\n' \
|
||||
| sed 's/<\/TR[^>]*>/\n/Ig' \
|
||||
| sed 's/<\/\?\(TABLE\|TR\)[^>]*>//Ig' \
|
||||
| sed 's/^<T[DH][^>]*>\|<\/\?T[DH][^>]*>$//Ig' \
|
||||
| sed 's/<\/T[DH][^>]*><T[DH][^>]*>/,/Ig' \
|
||||
| grep 'edit.php?' \
|
||||
| grep "$top_domain")"
|
||||
# The above beauty ends with striping out rows that do not have an
|
||||
# href to edit.php and do not have the top domain we are looking for.
|
||||
# So all we should be left with is CSV of table of subdomains we are
|
||||
# interested in.
|
||||
|
||||
# Now we have to read through this table and extract the data we need
|
||||
lines="$(echo "$subdomain_csv" | wc -l)"
|
||||
nl='
|
||||
'
|
||||
i=0
|
||||
found=0
|
||||
while [ "$i" -lt "$lines" ]; do
|
||||
i="$(_math "$i" + 1)"
|
||||
line="$(echo "$subdomain_csv" | cut -d "$nl" -f "$i")"
|
||||
tmp="$(echo "$line" | cut -d ',' -f 1)"
|
||||
if [ $found = 0 ] && _startswith "$tmp" "<td>$top_domain"; then
|
||||
# this line will contain DNSdomainid for the top_domain
|
||||
DNSdomainid="$(echo "$line" | cut -d ',' -f 2 | sed 's/^.*domain_id=//;s/>.*//')"
|
||||
found=1
|
||||
else
|
||||
# lines contain DNS records for all subdomains
|
||||
DNSname="$(echo "$line" | cut -d ',' -f 2 | sed 's/^[^>]*>//;s/<\/a>.*//')"
|
||||
DNStype="$(echo "$line" | cut -d ',' -f 3)"
|
||||
if [ "$DNSname" = "$fulldomain" ] && [ "$DNStype" = "TXT" ]; then
|
||||
DNSdataid="$(echo "$line" | cut -d ',' -f 2 | sed 's/^.*data_id=//;s/>.*//')"
|
||||
# Now get current value for the TXT record. This method may
|
||||
# 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.
|
||||
DNSvalue="$(echo "$line" | cut -d ',' -f 4 | sed 's/^[^"]*"//;s/".*//;s/<\/td>.*//')"
|
||||
if [ $found != 0 ]; then
|
||||
break
|
||||
# we are breaking out of the loop at the first match of DNS name
|
||||
# and DNS type (if we are past finding the domainid). This assumes
|
||||
# that there is only ever one TXT record for the LetsEncrypt/acme
|
||||
# challenge subdomain. This seems to be a reasonable assumption
|
||||
# as the acme client deletes the TXT record on successful validation.
|
||||
fi
|
||||
else
|
||||
DNSname=""
|
||||
DNStype=""
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
_debug "DNSname: $DNSname DNStype: $DNStype DNSdomainid: $DNSdomainid DNSdataid: $DNSdataid"
|
||||
_debug "DNSvalue: $DNSvalue"
|
||||
|
||||
if [ -z "$DNSdomainid" ]; then
|
||||
# If domain ID is empty then something went wrong (top level
|
||||
# domain not found at FreeDNS).
|
||||
if [ "$attempts" = "0" ]; then
|
||||
# exhausted maximum retry attempts
|
||||
_debug "$htmlpage"
|
||||
_debug "$subdomain_csv"
|
||||
_err "Domain $top_domain not found at FreeDNS"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
# break out of the 'retry' loop... we have found our domain ID
|
||||
break
|
||||
fi
|
||||
_info "Domain $top_domain not found at FreeDNS"
|
||||
_info "Retry loading subdomain page ($attempts attempts remaining)"
|
||||
done
|
||||
|
||||
if [ -z "$DNSdataid" ]; then
|
||||
# If data ID is empty then specific subdomain does not exist yet, need
|
||||
# to create it this should always be the case as the acme client
|
||||
# deletes the entry after domain is validated.
|
||||
_freedns_add_txt_record "$FREEDNS_COOKIE" "$DNSdomainid" "$sub_domain" "$txtvalue"
|
||||
return $?
|
||||
else
|
||||
if [ "$txtvalue" = "$DNSvalue" ]; then
|
||||
# if value in TXT record matches value requested then DNS record
|
||||
# does not need to be updated. But...
|
||||
# Testing value match fails. Website is truncating the value field.
|
||||
# So for now we will always go down the else path. Though in theory
|
||||
# should never come here anyway as the acme client deletes
|
||||
# the TXT record on successful validation, so we should not even
|
||||
# have found a TXT record !!
|
||||
_info "No update necessary for $fulldomain at FreeDNS"
|
||||
return 0
|
||||
else
|
||||
# Delete the old TXT record (with the wrong value)
|
||||
_freedns_delete_txt_record "$FREEDNS_COOKIE" "$DNSdataid"
|
||||
if [ "$?" = "0" ]; then
|
||||
# And add in new TXT record with the value provided
|
||||
_freedns_add_txt_record "$FREEDNS_COOKIE" "$DNSdomainid" "$sub_domain" "$txtvalue"
|
||||
fi
|
||||
return $?
|
||||
fi
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
#Usage: fulldomain txtvalue
|
||||
#Remove the txt record after validation.
|
||||
dns_freedns_rm() {
|
||||
fulldomain="$1"
|
||||
txtvalue="$2"
|
||||
|
||||
_info "Delete TXT record using FreeDNS"
|
||||
_debug "fulldomain: $fulldomain"
|
||||
_debug "txtvalue: $txtvalue"
|
||||
|
||||
# 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
|
||||
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
|
||||
# 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
|
||||
# load the page and obtain our TXT record.
|
||||
attempts=2
|
||||
while [ "$attempts" -gt "0" ]; do
|
||||
attempts="$(_math "$attempts" - 1)"
|
||||
|
||||
htmlpage="$(_freedns_retrieve_subdomain_page "$FREEDNS_COOKIE")"
|
||||
if [ "$?" != "0" ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Now convert the tables in the HTML to CSV. This litte gem from
|
||||
# http://stackoverflow.com/questions/1403087/how-can-i-convert-an-html-table-to-csv
|
||||
subdomain_csv="$(echo "$htmlpage" \
|
||||
| grep -i -e '</\?TABLE\|</\?TD\|</\?TR\|</\?TH' \
|
||||
| sed 's/^[\ \t]*//g' \
|
||||
| tr -d '\n' \
|
||||
| sed 's/<\/TR[^>]*>/\n/Ig' \
|
||||
| sed 's/<\/\?\(TABLE\|TR\)[^>]*>//Ig' \
|
||||
| sed 's/^<T[DH][^>]*>\|<\/\?T[DH][^>]*>$//Ig' \
|
||||
| sed 's/<\/T[DH][^>]*><T[DH][^>]*>/,/Ig' \
|
||||
| grep 'edit.php?' \
|
||||
| grep "$fulldomain")"
|
||||
# The above beauty ends with striping out rows that do not have an
|
||||
# href to edit.php and do not have the domain name we are looking for.
|
||||
# So all we should be left with is CSV of table of subdomains we are
|
||||
# interested in.
|
||||
|
||||
# Now we have to read through this table and extract the data we need
|
||||
lines="$(echo "$subdomain_csv" | wc -l)"
|
||||
nl='
|
||||
'
|
||||
i=0
|
||||
found=0
|
||||
while [ "$i" -lt "$lines" ]; do
|
||||
i="$(_math "$i" + 1)"
|
||||
line="$(echo "$subdomain_csv" | cut -d "$nl" -f "$i")"
|
||||
DNSname="$(echo "$line" | cut -d ',' -f 2 | sed 's/^[^>]*>//;s/<\/a>.*//')"
|
||||
DNStype="$(echo "$line" | cut -d ',' -f 3)"
|
||||
if [ "$DNSname" = "$fulldomain" ] && [ "$DNStype" = "TXT" ]; then
|
||||
DNSdataid="$(echo "$line" | cut -d ',' -f 2 | sed 's/^.*data_id=//;s/>.*//')"
|
||||
DNSvalue="$(echo "$line" | cut -d ',' -f 4 | sed 's/^[^"]*"//;s/".*//;s/<\/td>.*//')"
|
||||
_debug "DNSvalue: $DNSvalue"
|
||||
# if [ "$DNSvalue" = "$txtvalue" ]; then
|
||||
# Testing value match fails. Website is truncating the value
|
||||
# field. So for now we will assume that there is only one TXT
|
||||
# field for the sub domain and just delete it. Currently this
|
||||
# is a safe assumption.
|
||||
_freedns_delete_txt_record "$FREEDNS_COOKIE" "$DNSdataid"
|
||||
return $?
|
||||
# fi
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
# If we get this far we did not find a match (after two attempts)
|
||||
# Not necessarily an error, but log anyway.
|
||||
_debug2 "$subdomain_csv"
|
||||
_info "Cannot delete TXT record for $fulldomain/$txtvalue. Does not exist at FreeDNS"
|
||||
return 0
|
||||
}
|
||||
|
||||
#################### Private functions below ##################################
|
||||
|
||||
# usage: _freedns_login username password
|
||||
# print string "cookie=value" etc.
|
||||
# returns 0 success
|
||||
_freedns_login() {
|
||||
export _H1="Accept-Language:en-US"
|
||||
username="$1"
|
||||
password="$2"
|
||||
url="https://freedns.afraid.org/zc.php?step=2"
|
||||
|
||||
_debug "Login to FreeDNS as user $username"
|
||||
|
||||
htmlpage="$(_post "username=$(printf '%s' "$username" | _url_encode)&password=$(printf '%s' "$password" | _url_encode)&submit=Login&action=auth" "$url")"
|
||||
|
||||
if [ "$?" != "0" ]; then
|
||||
_err "FreeDNS login failed for user $username bad RC from _post"
|
||||
return 1
|
||||
fi
|
||||
|
||||
cookies="$(grep -i '^Set-Cookie.*dns_cookie.*$' "$HTTP_HEADER" | _head_n 1 | tr -d "\r\n" | cut -d " " -f 2)"
|
||||
|
||||
# if cookies is not empty then logon successful
|
||||
if [ -z "$cookies" ]; then
|
||||
_debug "$htmlpage"
|
||||
_err "FreeDNS login failed for user $username. Check $HTTP_HEADER file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
printf "%s" "$cookies"
|
||||
return 0
|
||||
}
|
||||
|
||||
# usage _freedns_retrieve_subdomain_page login_cookies
|
||||
# echo page retrieved (html)
|
||||
# returns 0 success
|
||||
_freedns_retrieve_subdomain_page() {
|
||||
export _H1="Cookie:$1"
|
||||
export _H2="Accept-Language:en-US"
|
||||
url="https://freedns.afraid.org/subdomain/"
|
||||
|
||||
_debug "Retrieve subdmoain page from FreeDNS"
|
||||
|
||||
htmlpage="$(_get "$url")"
|
||||
|
||||
if [ "$?" != "0" ]; then
|
||||
_err "FreeDNS retrieve subdomins failed bad RC from _get"
|
||||
return 1
|
||||
elif [ -z "$htmlpage" ]; then
|
||||
_err "FreeDNS returned empty subdomain page"
|
||||
return 1
|
||||
fi
|
||||
|
||||
_debug2 "$htmlpage"
|
||||
|
||||
printf "%s" "$htmlpage"
|
||||
return 0
|
||||
}
|
||||
|
||||
# usage _freedns_add_txt_record login_cookies domain_id subdomain value
|
||||
# returns 0 success
|
||||
_freedns_add_txt_record() {
|
||||
export _H1="Cookie:$1"
|
||||
export _H2="Accept-Language:en-US"
|
||||
domain_id="$2"
|
||||
subdomain="$3"
|
||||
value="$(printf '%s' "$4" | _url_encode)"
|
||||
url="http://freedns.afraid.org/subdomain/save.php?step=2"
|
||||
|
||||
htmlpage="$(_post "type=TXT&domain_id=$domain_id&subdomain=$subdomain&address=%22$value%22&send=Save%21" "$url")"
|
||||
|
||||
if [ "$?" != "0" ]; then
|
||||
_err "FreeDNS failed to add TXT record for $subdomain bad RC from _post"
|
||||
return 1
|
||||
elif ! grep "200 OK" "$HTTP_HEADER" >/dev/null; then
|
||||
_debug "$htmlpage"
|
||||
_err "FreeDNS failed to add TXT record for $subdomain. Check $HTTP_HEADER file"
|
||||
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 "Note that you cannot use automatic DNS validation for FreeDNS public domains"
|
||||
return 1
|
||||
fi
|
||||
|
||||
_debug2 "$htmlpage"
|
||||
_info "Added acme challenge TXT record for $fulldomain at FreeDNS"
|
||||
return 0
|
||||
}
|
||||
|
||||
# usage _freedns_delete_txt_record login_cookies data_id
|
||||
# returns 0 success
|
||||
_freedns_delete_txt_record() {
|
||||
export _H1="Cookie:$1"
|
||||
export _H2="Accept-Language:en-US"
|
||||
data_id="$2"
|
||||
url="https://freedns.afraid.org/subdomain/delete2.php"
|
||||
|
||||
htmlheader="$(_get "$url?data_id%5B%5D=$data_id&submit=delete+selected" "onlyheader")"
|
||||
|
||||
if [ "$?" != "0" ]; then
|
||||
_err "FreeDNS failed to delete TXT record for $data_id bad RC from _get"
|
||||
return 1
|
||||
elif ! _contains "$htmlheader" "200 OK"; then
|
||||
_debug "$htmlheader"
|
||||
_err "FreeDNS failed to delete TXT record $data_id"
|
||||
return 1
|
||||
fi
|
||||
|
||||
_info "Deleted acme challenge TXT record for $fulldomain at FreeDNS"
|
||||
return 0
|
||||
}
|
||||
183
dnsapi/dns_linode.sh
Executable file
183
dnsapi/dns_linode.sh
Executable file
@@ -0,0 +1,183 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#Author: Philipp Grosswiler <philipp.grosswiler@swiss-design.net>
|
||||
|
||||
LINODE_API_URL="https://api.linode.com/?api_key=$LINODE_API_KEY&api_action="
|
||||
|
||||
######## Public functions #####################
|
||||
|
||||
#Usage: dns_linode_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
dns_linode_add() {
|
||||
fulldomain="${1}"
|
||||
txtvalue="${2}"
|
||||
|
||||
if ! _Linode_API; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
_info "Using Linode"
|
||||
_debug "Calling: dns_linode_add() '${fulldomain}' '${txtvalue}'"
|
||||
|
||||
_debug "First detect the root zone"
|
||||
if ! _get_root "$fulldomain"; then
|
||||
_err "Domain does not exist."
|
||||
return 1
|
||||
fi
|
||||
_debug _domain_id "$_domain_id"
|
||||
_debug _sub_domain "$_sub_domain"
|
||||
_debug _domain "$_domain"
|
||||
|
||||
_parameters="&DomainID=$_domain_id&Type=TXT&Name=$_sub_domain&Target=$txtvalue"
|
||||
|
||||
if _rest GET "domain.resource.create" "$_parameters" && [ -n "$response" ]; then
|
||||
_resource_id=$(printf "%s\n" "$response" | _egrep_o "\"ResourceID\":\s*[0-9]+" | cut -d : -f 2 | tr -d " " | _head_n 1)
|
||||
_debug _resource_id "$_resource_id"
|
||||
|
||||
if [ -z "$_resource_id" ]; then
|
||||
_err "Error adding the domain resource."
|
||||
return 1
|
||||
fi
|
||||
|
||||
_info "Domain resource successfully added."
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
#Usage: dns_linode_rm _acme-challenge.www.domain.com
|
||||
dns_linode_rm() {
|
||||
fulldomain="${1}"
|
||||
|
||||
if ! _Linode_API; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
_info "Using Linode"
|
||||
_debug "Calling: dns_linode_rm() '${fulldomain}'"
|
||||
|
||||
_debug "First detect the root zone"
|
||||
if ! _get_root "$fulldomain"; then
|
||||
_err "Domain does not exist."
|
||||
return 1
|
||||
fi
|
||||
_debug _domain_id "$_domain_id"
|
||||
_debug _sub_domain "$_sub_domain"
|
||||
_debug _domain "$_domain"
|
||||
|
||||
_parameters="&DomainID=$_domain_id"
|
||||
|
||||
if _rest GET "domain.resource.list" "$_parameters" && [ -n "$response" ]; then
|
||||
response="$(echo "$response" | tr -d "\n" | sed 's/{/\n&/g')"
|
||||
|
||||
resource="$(echo "$response" | _egrep_o "{.*\"NAME\":\s*\"$_sub_domain\".*}")"
|
||||
if [ "$resource" ]; then
|
||||
_resource_id=$(printf "%s\n" "$resource" | _egrep_o "\"RESOURCEID\":\s*[0-9]+" | _head_n 1 | cut -d : -f 2 | tr -d \ )
|
||||
if [ "$_resource_id" ]; then
|
||||
_debug _resource_id "$_resource_id"
|
||||
|
||||
_parameters="&DomainID=$_domain_id&ResourceID=$_resource_id"
|
||||
|
||||
if _rest GET "domain.resource.delete" "$_parameters" && [ -n "$response" ]; then
|
||||
_resource_id=$(printf "%s\n" "$response" | _egrep_o "\"ResourceID\":\s*[0-9]+" | cut -d : -f 2 | tr -d " " | _head_n 1)
|
||||
_debug _resource_id "$_resource_id"
|
||||
|
||||
if [ -z "$_resource_id" ]; then
|
||||
_err "Error deleting the domain resource."
|
||||
return 1
|
||||
fi
|
||||
|
||||
_info "Domain resource successfully deleted."
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
#################### Private functions below ##################################
|
||||
|
||||
_Linode_API() {
|
||||
if [ -z "$LINODE_API_KEY" ]; then
|
||||
LINODE_API_KEY=""
|
||||
|
||||
_err "You didn't specify the Linode API key yet."
|
||||
_err "Please create your key and try again."
|
||||
|
||||
return 1
|
||||
fi
|
||||
|
||||
_saveaccountconf LINODE_API_KEY "$LINODE_API_KEY"
|
||||
}
|
||||
|
||||
#################### Private functions below ##################################
|
||||
#_acme-challenge.www.domain.com
|
||||
#returns
|
||||
# _sub_domain=_acme-challenge.www
|
||||
# _domain=domain.com
|
||||
# _domain_id=12345
|
||||
_get_root() {
|
||||
domain=$1
|
||||
i=2
|
||||
p=1
|
||||
|
||||
if _rest GET "domain.list"; then
|
||||
response="$(echo "$response" | tr -d "\n" | sed 's/{/\n&/g')"
|
||||
while true; do
|
||||
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
||||
_debug h "$h"
|
||||
if [ -z "$h" ]; then
|
||||
#not valid
|
||||
return 1
|
||||
fi
|
||||
|
||||
hostedzone="$(echo "$response" | _egrep_o "{.*\"DOMAIN\":\s*\"$h\".*}")"
|
||||
if [ "$hostedzone" ]; then
|
||||
_domain_id=$(printf "%s\n" "$hostedzone" | _egrep_o "\"DOMAINID\":\s*[0-9]+" | _head_n 1 | cut -d : -f 2 | tr -d \ )
|
||||
if [ "$_domain_id" ]; then
|
||||
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
|
||||
_domain=$h
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
p=$i
|
||||
i=$(_math "$i" + 1)
|
||||
done
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
#method method action data
|
||||
_rest() {
|
||||
mtd="$1"
|
||||
ep="$2"
|
||||
data="$3"
|
||||
|
||||
_debug mtd "$mtd"
|
||||
_debug ep "$ep"
|
||||
|
||||
export _H1="Accept: application/json"
|
||||
export _H2="Content-Type: application/json"
|
||||
|
||||
if [ "$mtd" != "GET" ]; then
|
||||
# both POST and DELETE.
|
||||
_debug data "$data"
|
||||
response="$(_post "$data" "$LINODE_API_URL$ep" "" "$mtd")"
|
||||
else
|
||||
response="$(_get "$LINODE_API_URL$ep$data")"
|
||||
fi
|
||||
|
||||
if [ "$?" != "0" ]; then
|
||||
_err "error $ep"
|
||||
return 1
|
||||
fi
|
||||
_debug2 response "$response"
|
||||
return 0
|
||||
}
|
||||
@@ -46,12 +46,12 @@ dns_lua_add() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
count=$(printf "%s\n" "$response" | _egrep_o "\"name\":\"$fulldomain\"" | wc -l)
|
||||
count=$(printf "%s\n" "$response" | _egrep_o "\"name\":\"$fulldomain.\",\"type\":\"TXT\"" | wc -l | tr -d " ")
|
||||
_debug count "$count"
|
||||
if [ "$count" = "0" ]; then
|
||||
_info "Adding record"
|
||||
if _LUA_rest POST "zones/$_domain_id/records" "{\"type\":\"TXT\",\"name\":\"$fulldomain.\",\"content\":\"$txtvalue\",\"ttl\":120}"; then
|
||||
if printf -- "%s" "$response" | grep "$fulldomain" >/dev/null; then
|
||||
if _contains "$response" "$fulldomain"; then
|
||||
_info "Added"
|
||||
#todo: check if the record takes effect
|
||||
return 0
|
||||
@@ -63,11 +63,11 @@ dns_lua_add() {
|
||||
_err "Add txt record error."
|
||||
else
|
||||
_info "Updating record"
|
||||
record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[^,]*,\"name\":\"$fulldomain.\",\"type\":\"TXT\"" | cut -d: -f2 | cut -d, -f1)
|
||||
record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[^,]*,\"name\":\"$fulldomain.\",\"type\":\"TXT\"" | _head_n 1 | cut -d: -f2 | cut -d, -f1)
|
||||
_debug "record_id" "$record_id"
|
||||
|
||||
_LUA_rest PUT "zones/$_domain_id/records/$record_id" "{\"id\":\"$record_id\",\"type\":\"TXT\",\"name\":\"$fulldomain.\",\"content\":\"$txtvalue\",\"zone_id\":\"$_domain_id\",\"ttl\":120}"
|
||||
if [ "$?" = "0" ]; then
|
||||
_LUA_rest PUT "zones/$_domain_id/records/$record_id" "{\"id\":$record_id,\"type\":\"TXT\",\"name\":\"$fulldomain.\",\"content\":\"$txtvalue\",\"zone_id\":$_domain_id,\"ttl\":120}"
|
||||
if [ "$?" = "0" ] && _contains "$response" "updated_at"; then
|
||||
_info "Updated!"
|
||||
#todo: check if the record takes effect
|
||||
return 0
|
||||
@@ -99,6 +99,7 @@ _get_root() {
|
||||
fi
|
||||
while true; do
|
||||
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
||||
_debug h "$h"
|
||||
if [ -z "$h" ]; then
|
||||
#not valid
|
||||
return 1
|
||||
@@ -106,6 +107,7 @@ _get_root() {
|
||||
|
||||
if _contains "$response" "\"name\":\"$h\""; then
|
||||
_domain_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[^,]*,\"name\":\"$h\"" | cut -d : -f 2 | cut -d , -f 1)
|
||||
_debug _domain_id "$_domain_id"
|
||||
if [ "$_domain_id" ]; then
|
||||
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
|
||||
_domain="$h"
|
||||
|
||||
@@ -124,7 +124,7 @@ _me_rest() {
|
||||
_debug "$ep"
|
||||
|
||||
cdate=$(date -u +"%a, %d %b %Y %T %Z")
|
||||
hmac=$(printf "%s" "$cdate" | _hmac sha1 "$(_hex "$ME_Secret")" hex)
|
||||
hmac=$(printf "%s" "$cdate" | _hmac sha1 "$(printf "%s" "$ME_Secret" | _hex_dump | tr -d " ")" hex)
|
||||
|
||||
export _H1="x-dnsme-apiKey: $ME_Key"
|
||||
export _H2="x-dnsme-requestDate: $cdate"
|
||||
|
||||
Reference in New Issue
Block a user