mirror of
https://github.com/acmesh-official/acme.sh.git
synced 2025-12-25 21:02:10 +08:00
Compare commits
255 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6489a48e1f | ||
|
|
ca24d1762e | ||
|
|
2f4b84c074 | ||
|
|
6ae810a1fa | ||
|
|
3e3f695536 | ||
|
|
3ca93f4a4c | ||
|
|
f2d9930773 | ||
|
|
2fbf399156 | ||
|
|
8a1e335bf5 | ||
|
|
5413bf8753 | ||
|
|
c4c5ecd03d | ||
|
|
3b67cf4378 | ||
|
|
f3c937f9ed | ||
|
|
671a699472 | ||
|
|
cc4fa1c6bd | ||
|
|
d11d476126 | ||
|
|
1ce06c7cdd | ||
|
|
800f02ba38 | ||
|
|
79964b0e85 | ||
|
|
0924d11bbf | ||
|
|
3cf85634eb | ||
|
|
ec01175d37 | ||
|
|
5bb518ff0f | ||
|
|
5415381cf4 | ||
|
|
129ae06354 | ||
|
|
058e5d5f4b | ||
|
|
2ec493f033 | ||
|
|
a33e8a8509 | ||
|
|
7b4be7be40 | ||
|
|
b90917a529 | ||
|
|
180f05f6f0 | ||
|
|
b2686e5b6d | ||
|
|
831b95f13a | ||
|
|
331b599a81 | ||
|
|
3ef817ebc2 | ||
|
|
d0f7c309ab | ||
|
|
e5079b9dad | ||
|
|
9e773c9143 | ||
|
|
fe600441c9 | ||
|
|
291b56db93 | ||
|
|
ec9975c3d9 | ||
|
|
9e57161941 | ||
|
|
20444bf253 | ||
|
|
e428c4402e | ||
|
|
15af89d51c | ||
|
|
ed95865696 | ||
|
|
8c71bd57e7 | ||
|
|
d204be4b2c | ||
|
|
4743171b4f | ||
|
|
1fb800f7a7 | ||
|
|
3a3b0dd5c1 | ||
|
|
2959281d42 | ||
|
|
e2c939fb97 | ||
|
|
51d0e4325e | ||
|
|
08b6cf0231 | ||
|
|
059147b74a | ||
|
|
c96ceeb1bd | ||
|
|
0a3b6c4813 | ||
|
|
8636a15695 | ||
|
|
96db9362c5 | ||
|
|
f81f93e9c3 | ||
|
|
a3a04b5f76 | ||
|
|
329174b6d9 | ||
|
|
b171aff418 | ||
|
|
1f6ffa3e88 | ||
|
|
24d2a8b9d5 | ||
|
|
4d8b99a307 | ||
|
|
f9085fedd7 | ||
|
|
c4236e58d1 | ||
|
|
eb91f9575a | ||
|
|
947d14ffeb | ||
|
|
b3f915b5b2 | ||
|
|
03d3f3afc3 | ||
|
|
2728170c01 | ||
|
|
c107f3632a | ||
|
|
7d1c5fca0b | ||
|
|
e71887e1a8 | ||
|
|
39d1eeda23 | ||
|
|
b482f3ce94 | ||
|
|
122cc48c29 | ||
|
|
c7c57cfa0e | ||
|
|
1f9ca20dfd | ||
|
|
5efbaa4849 | ||
|
|
c6f55bc4ab | ||
|
|
b28a3db3d6 | ||
|
|
b9ece28f68 | ||
|
|
79b4907cb9 | ||
|
|
dfbc244b00 | ||
|
|
b23d5e26e2 | ||
|
|
f1f3074306 | ||
|
|
f162ad193f | ||
|
|
5254f300f9 | ||
|
|
c0d0100ca8 | ||
|
|
21f201e371 | ||
|
|
bbc378ed8f | ||
|
|
e2d494321c | ||
|
|
c2df8043db | ||
|
|
df62150b5a | ||
|
|
eea52a5fa6 | ||
|
|
2d9015b840 | ||
|
|
187ef29914 | ||
|
|
c12be766e9 | ||
|
|
2168458f11 | ||
|
|
8cf0725593 | ||
|
|
8379f015d7 | ||
|
|
f08c01800f | ||
|
|
a62706678e | ||
|
|
e4468562d2 | ||
|
|
7316bf7bc5 | ||
|
|
3747b7d930 | ||
|
|
5be3f22d06 | ||
|
|
c572ce946b | ||
|
|
d69f0289ca | ||
|
|
048e5210f7 | ||
|
|
219e9115c0 | ||
|
|
b43416af97 | ||
|
|
6d84da588b | ||
|
|
569d6c557c | ||
|
|
58bb94d7c7 | ||
|
|
4f8f775e69 | ||
|
|
5eed02f7e9 | ||
|
|
983f1f28ca | ||
|
|
192ede5e64 | ||
|
|
803a7aa878 | ||
|
|
93f3098aec | ||
|
|
dbd94d047b | ||
|
|
be39ab32d1 | ||
|
|
8b1fb3cb0c | ||
|
|
9e04222ee6 | ||
|
|
72349507c4 | ||
|
|
79db8daddd | ||
|
|
b967f83f20 | ||
|
|
74a7592b4b | ||
|
|
486f23538f | ||
|
|
df86ff2191 | ||
|
|
41266f05e9 | ||
|
|
d2aa331838 | ||
|
|
670cb9d223 | ||
|
|
a205762bf0 | ||
|
|
2ffab66d97 | ||
|
|
10a6aec998 | ||
|
|
7cbe31baad | ||
|
|
8a09dc1b9b | ||
|
|
fa6e174651 | ||
|
|
8dee328eae | ||
|
|
340155e6a6 | ||
|
|
7fe19a030a | ||
|
|
11e0ccdc91 | ||
|
|
e55b2f4f8d | ||
|
|
d78c1f695e | ||
|
|
cfbb3e86b3 | ||
|
|
fa6234e417 | ||
|
|
9eeae9ad7e | ||
|
|
28688488ff | ||
|
|
41d804719f | ||
|
|
bc18168662 | ||
|
|
1fadae82c7 | ||
|
|
791c62ca64 | ||
|
|
4441a6ff59 | ||
|
|
63a7002477 | ||
|
|
a746139c53 | ||
|
|
697a060132 | ||
|
|
7834c25253 | ||
|
|
2e7cbfcff5 | ||
|
|
5b771039fc | ||
|
|
2f1bc5864f | ||
|
|
16d79ebaac | ||
|
|
e009ec8b93 | ||
|
|
738ece513f | ||
|
|
5a7b7b51c5 | ||
|
|
5bba9bddfd | ||
|
|
a3c0c7546d | ||
|
|
05d7ae4efa | ||
|
|
44483dba21 | ||
|
|
3498a5856a | ||
|
|
cd79b0343a | ||
|
|
abba00d595 | ||
|
|
88a8d7d901 | ||
|
|
d5c00071d3 | ||
|
|
c7a6cf5463 | ||
|
|
2ce2a15fc6 | ||
|
|
ce4be4e91e | ||
|
|
82dc2244c0 | ||
|
|
ab45b7783f | ||
|
|
4a56b2406b | ||
|
|
e0cd2cdb9c | ||
|
|
7575094cf3 | ||
|
|
40a3ae04b6 | ||
|
|
ac26f84170 | ||
|
|
fa574fe833 | ||
|
|
9a6e18ce80 | ||
|
|
8f9034fc8b | ||
|
|
3e5b102445 | ||
|
|
d8b1a8d439 | ||
|
|
54ae008dd7 | ||
|
|
9c1747581f | ||
|
|
ae4f7b6d7a | ||
|
|
c947322a69 | ||
|
|
14db45215f | ||
|
|
d20831e41a | ||
|
|
1bb902984b | ||
|
|
09f1c58872 | ||
|
|
7f944c2c8b | ||
|
|
1c02b85802 | ||
|
|
a2801649b4 | ||
|
|
15777732d3 | ||
|
|
b875037150 | ||
|
|
a6d583cb5e | ||
|
|
9882f3429a | ||
|
|
29d47c4de2 | ||
|
|
ce38ecb966 | ||
|
|
13ffa17048 | ||
|
|
a387682dfb | ||
|
|
f6ed197cd3 | ||
|
|
243593cdaa | ||
|
|
1e2d559859 | ||
|
|
20ea859183 | ||
|
|
86b24ea059 | ||
|
|
07af42476d | ||
|
|
87edf71e93 | ||
|
|
e3ea2ed420 | ||
|
|
8f9a1881a4 | ||
|
|
a8c6111197 | ||
|
|
3de8570022 | ||
|
|
a0311b0134 | ||
|
|
158a628c0e | ||
|
|
422e5026d6 | ||
|
|
797cbb9b20 | ||
|
|
be68fbd4f5 | ||
|
|
e440223b40 | ||
|
|
5766250288 | ||
|
|
870274ad9d | ||
|
|
9d6abcd9be | ||
|
|
432771dfe3 | ||
|
|
69925ce823 | ||
|
|
e9f9f515bd | ||
|
|
efd96153d8 | ||
|
|
c7b8f223ee | ||
|
|
a0636d5a87 | ||
|
|
c7b16249b8 | ||
|
|
031e885e4d | ||
|
|
796e2cc156 | ||
|
|
7af784adce | ||
|
|
a988a91e2e | ||
|
|
a8b564fa64 | ||
|
|
b97e140389 | ||
|
|
e51bef6d12 | ||
|
|
4bd31f4967 | ||
|
|
7ff7a7c527 | ||
|
|
c4a375b3a5 | ||
|
|
e3698edd19 | ||
|
|
e591d5cfe4 | ||
|
|
54d61bdc4a | ||
|
|
2d279c4c5c | ||
|
|
0fb206fe15 |
9
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
9
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
<!--
|
||||
|
||||
Do NOT send pull request to `master` branch.
|
||||
|
||||
Please send to `dev` branch instead.
|
||||
|
||||
Any PR to `master` branch will NOT be merged.
|
||||
|
||||
-->
|
||||
65
.travis.yml
65
.travis.yml
@@ -1,11 +1,54 @@
|
||||
language: bash
|
||||
|
||||
env:
|
||||
global:
|
||||
- SHFMT_URL=https://github.com/mvdan/sh/releases/download/v0.4.0/shfmt_v0.4.0_linux_amd64
|
||||
|
||||
script:
|
||||
- curl -sSL $SHFMT_URL -o ~/shfmt
|
||||
- chmod +x ~/shfmt
|
||||
- ~/shfmt -l -w -i 2 .
|
||||
- git diff --exit-code || (echo "Run shfmt to fix the formatting issues" && false)
|
||||
language: shell
|
||||
sudo: required
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
||||
env:
|
||||
global:
|
||||
- SHFMT_URL=https://github.com/mvdan/sh/releases/download/v0.4.0/shfmt_v0.4.0_linux_amd64
|
||||
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- debian-sid # Grab shellcheck from the Debian repo (o_O)
|
||||
packages:
|
||||
- shellcheck
|
||||
|
||||
install:
|
||||
- if [ "$TRAVIS_OS_NAME" = 'osx' ]; then
|
||||
brew update && brew install openssl;
|
||||
brew info openssl;
|
||||
ln -s /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/;
|
||||
ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/;
|
||||
ln -s /usr/local/Cellar/openssl/1.0.2j/bin/openssl /usr/local/openssl;
|
||||
_old_path="$PATH";
|
||||
echo "PATH=$PATH";
|
||||
export PATH="";
|
||||
export OPENSSL_BIN="/usr/local/openssl";
|
||||
openssl version 2>&1 || true;
|
||||
$OPENSSL_BIN version 2>&1 || true;
|
||||
export PATH="$_old_path";
|
||||
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
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then chmod +x ~/shfmt ; fi
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then ~/shfmt -l -w -i 2 . ; fi
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then git diff --exit-code && echo "shfmt OK" ; fi
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then shellcheck -V ; fi
|
||||
- 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
|
||||
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
|
||||
|
||||
|
||||
216
README.md
216
README.md
@@ -1,21 +1,23 @@
|
||||
# An ACME Shell script: acme.sh [](https://travis-ci.org/Neilpang/acme.sh)
|
||||
- An ACME protocol client written purely in Shell (Unix shell) language.
|
||||
- Fully ACME protocol implementation.
|
||||
- Simple, powerful and very easy to use. You only need 3 minutes to learn.
|
||||
- Bash, dash and sh compatible.
|
||||
- Full ACME protocol implementation.
|
||||
- Simple, powerful and very easy to use. You only need 3 minutes to learn it.
|
||||
- Bash, dash and sh compatible.
|
||||
- Simplest shell script for Let's Encrypt free certificate client.
|
||||
- Purely written in Shell with no dependencies on python or Let's Encrypt official client.
|
||||
- Just one script, to issue, renew and install your certificates automatically.
|
||||
- Purely written in Shell with no dependencies on python or the official Let's Encrypt client.
|
||||
- Just one script to issue, renew and install your certificates automatically.
|
||||
- DOES NOT require `root/sudoer` access.
|
||||
|
||||
It's probably the `easiest&smallest&smartest` shell script to automatically issue & renew the free certificates from Let's Encrypt.
|
||||
|
||||
|
||||
Wiki: https://github.com/Neilpang/acme.sh/wiki
|
||||
|
||||
|
||||
# [中文说明](https://github.com/Neilpang/acme.sh/wiki/%E8%AF%B4%E6%98%8E)
|
||||
|
||||
#Tested OS
|
||||
|
||||
# Tested OS
|
||||
|
||||
| NO | Status| Platform|
|
||||
|----|-------|---------|
|
||||
|1|[](https://github.com/Neilpang/letest#here-are-the-latest-status)| Ubuntu
|
||||
@@ -37,42 +39,41 @@ Wiki: https://github.com/Neilpang/acme.sh/wiki
|
||||
|17|-----| OpenWRT: Tested and working. See [wiki page](https://github.com/Neilpang/acme.sh/wiki/How-to-run-on-OpenWRT)
|
||||
|18|[](https://github.com/Neilpang/letest#here-are-the-latest-status)|SunOS/Solaris
|
||||
|19|[](https://github.com/Neilpang/letest#here-are-the-latest-status)|Gentoo Linux
|
||||
|20|[](https://travis-ci.org/Neilpang/acme.sh)|Mac OSX
|
||||
|
||||
For all build statuses, check our [daily build project](https://github.com/Neilpang/acmetest):
|
||||
For all build statuses, check our [daily build project](https://github.com/Neilpang/acmetest):
|
||||
|
||||
https://github.com/Neilpang/acmetest
|
||||
|
||||
# Supported Mode
|
||||
|
||||
1. Webroot mode
|
||||
2. Standalone mode
|
||||
3. Apache mode
|
||||
4. Dns mode
|
||||
# Supported modes
|
||||
|
||||
- Webroot mode
|
||||
- Standalone mode
|
||||
- Apache mode
|
||||
- DNS mode
|
||||
|
||||
|
||||
# 1. How to install
|
||||
|
||||
### 1. Install online:
|
||||
### 1. Install online
|
||||
|
||||
Check this project: https://github.com/Neilpang/get.acme.sh
|
||||
|
||||
```bash
|
||||
curl https://get.acme.sh | sh
|
||||
|
||||
```
|
||||
|
||||
Or:
|
||||
|
||||
```bash
|
||||
wget -O - https://get.acme.sh | sh
|
||||
|
||||
```
|
||||
|
||||
|
||||
### 2. Or, Install from git:
|
||||
### 2. Or, Install from git
|
||||
|
||||
Clone this project:
|
||||
Clone this project and launch installation:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/Neilpang/acme.sh.git
|
||||
@@ -82,14 +83,14 @@ cd ./acme.sh
|
||||
|
||||
You `don't have to be root` then, although `it is recommended`.
|
||||
|
||||
Advanced Installation: https://github.com/Neilpang/acme.sh/wiki/How-to-install
|
||||
Advanced Installation: https://github.com/Neilpang/acme.sh/wiki/How-to-install
|
||||
|
||||
The installer will perform 3 actions:
|
||||
|
||||
1. Create and copy `acme.sh` to your home dir (`$HOME`): `~/.acme.sh/`.
|
||||
All certs will be placed in this folder.
|
||||
2. Create alias for: `acme.sh=~/.acme.sh/acme.sh`.
|
||||
3. Create everyday cron job to check and renew the cert if needed.
|
||||
1. Create and copy `acme.sh` to your home dir (`$HOME`): `~/.acme.sh/`.
|
||||
All certs will be placed in this folder too.
|
||||
2. Create alias for: `acme.sh=~/.acme.sh/acme.sh`.
|
||||
3. Create daily cron job to check and renew the certs if needed.
|
||||
|
||||
Cron entry example:
|
||||
|
||||
@@ -97,18 +98,17 @@ Cron entry example:
|
||||
0 0 * * * "/home/user/.acme.sh"/acme.sh --cron --home "/home/user/.acme.sh" > /dev/null
|
||||
```
|
||||
|
||||
After the installation, you must close current terminal and reopen again to make the alias take effect.
|
||||
After the installation, you must close the current terminal and reopen it to make the alias take effect.
|
||||
|
||||
Ok, you are ready to issue certs now.
|
||||
|
||||
Ok, you are ready to issue cert now.
|
||||
Show help message:
|
||||
|
||||
```
|
||||
|
||||
root@v1:~# acme.sh -h
|
||||
|
||||
```
|
||||
|
||||
# 2. Just issue a cert:
|
||||
|
||||
# 2. Just issue a cert
|
||||
|
||||
**Example 1:** Single domain.
|
||||
|
||||
@@ -119,56 +119,59 @@ acme.sh --issue -d example.com -w /home/wwwroot/example.com
|
||||
**Example 2:** Multiple domains in the same cert.
|
||||
|
||||
```bash
|
||||
acme.sh --issue -d example.com -d www.example.com -d cp.example.com -w /home/wwwroot/example.com
|
||||
acme.sh --issue -d example.com -d www.example.com -d cp.example.com -w /home/wwwroot/example.com
|
||||
```
|
||||
|
||||
The parameter `/home/wwwroot/example.com` is the web root folder. You **MUST** have `write access` to this folder.
|
||||
|
||||
Second argument **"example.com"** is the main domain you want to issue cert for.
|
||||
You must have at least a domain there.
|
||||
Second argument **"example.com"** is the main domain you want to issue the cert for.
|
||||
You must have at least one domain there.
|
||||
|
||||
You must point and bind all the domains to the same webroot dir: `/home/wwwroot/example.com`.
|
||||
|
||||
Generate/issued certs will be placed in `~/.acme.sh/example.com/`
|
||||
Generated/issued certs will be placed in `~/.acme.sh/example.com/`
|
||||
|
||||
The issued cert will be renewed every **60** days automatically.
|
||||
The issued cert will be renewed automatically every **60** days.
|
||||
|
||||
More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert
|
||||
|
||||
|
||||
# 3. Install the issued cert to apache/nginx etc.
|
||||
# 3. Install the issued cert to Apache/Nginx etc.
|
||||
|
||||
After you issue a cert, you probably want to install/copy the cert to your nginx/apache or other servers.
|
||||
You **MUST** use this command to copy the certs to the target files, **Do NOT** use the certs files in **.acme.sh/** folder, they are for internal use only, the folder structure may change in future.
|
||||
After you issue a cert, you probably want to install/copy the cert to your Apache/Nginx or other servers.
|
||||
You **MUST** use this command to copy the certs to the target files, **DO NOT** use the certs files in **~/.acme.sh/** folder, they are for internal use only, the folder structure may change in the future.
|
||||
|
||||
**nginx** example
|
||||
**Apache** example:
|
||||
```bash
|
||||
acme.sh --installcert -d example.com \
|
||||
--keypath /path/to/keyfile/in/nginx/key.pem \
|
||||
--fullchainpath path/to/fullchain/nginx/cert.pem \
|
||||
--reloadcmd "service nginx restart"
|
||||
--certpath /path/to/certfile/in/apache/cert.pem \
|
||||
--keypath /path/to/keyfile/in/apache/key.pem \
|
||||
--fullchainpath /path/to/fullchain/certfile/apache/fullchain.pem \
|
||||
--reloadcmd "service apache2 force-reload"
|
||||
```
|
||||
|
||||
**apache** example
|
||||
**Nginx** example:
|
||||
```bash
|
||||
acme.sh --installcert -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 \
|
||||
--reloadcmd "service apache2 restart"
|
||||
--keypath /path/to/keyfile/in/nginx/key.pem \
|
||||
--fullchainpath /path/to/fullchain/nginx/cert.pem \
|
||||
--reloadcmd "service nginx force-reload"
|
||||
```
|
||||
|
||||
Only the domain is required, all the other parameters are optional.
|
||||
|
||||
Install/copy the issued cert/key to the production apache or nginx path.
|
||||
The ownership and permission info of existing files are preserved. You may want to precreate the files to have defined ownership and permission.
|
||||
|
||||
Install/copy the issued cert/key to the production Apache or Nginx path.
|
||||
|
||||
The cert will be `renewed every **60** days by default` (which is configurable). Once the cert is renewed, the Apache/Nginx service will be restarted automatically by the command: `service apache2 restart` or `service nginx restart`.
|
||||
|
||||
The cert will be `renewed every **60** days by default` (which is configurable). Once the cert is renewed, the apache/nginx will be automatically reloaded by the command: `service apache2 reload` or `service nginx reload`.
|
||||
|
||||
# 4. Use Standalone server to issue cert
|
||||
|
||||
**(requires you be root/sudoer, or you have permission to listen tcp 80 port)**
|
||||
**(requires you to be root/sudoer or have permission to listen on port 80 (TCP))**
|
||||
|
||||
The tcp `80` port **MUST** be free to listen, otherwise you will be prompted to free the `80` port and try again.
|
||||
Port `80` (TCP) **MUST** be free to listen on, otherwise you will be prompted to free it and try again.
|
||||
|
||||
```bash
|
||||
acme.sh --issue --standalone -d example.com -d www.example.com -d cp.example.com
|
||||
@@ -176,13 +179,14 @@ acme.sh --issue --standalone -d example.com -d www.example.com -d cp.example.com
|
||||
|
||||
More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert
|
||||
|
||||
# 5. Use Standalone tls server to issue cert
|
||||
|
||||
**(requires you be root/sudoer, or you have permission to listen tcp 443 port)**
|
||||
# 5. Use Standalone TLS server to issue cert
|
||||
|
||||
**(requires you to be root/sudoer or have permission to listen on port 443 (TCP))**
|
||||
|
||||
acme.sh supports `tls-sni-01` validation.
|
||||
|
||||
The tcp `443` port **MUST** be free to listen, otherwise you will be prompted to free the `443` port and try again.
|
||||
Port `443` (TCP) **MUST** be free to listen on, otherwise you will be prompted to free it and try again.
|
||||
|
||||
```bash
|
||||
acme.sh --issue --tls -d example.com -d www.example.com -d cp.example.com
|
||||
@@ -190,31 +194,33 @@ acme.sh --issue --tls -d example.com -d www.example.com -d cp.example.com
|
||||
|
||||
More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert
|
||||
|
||||
|
||||
# 6. Use Apache mode
|
||||
|
||||
**(requires you be root/sudoer, since it is required to interact with apache server)**
|
||||
**(requires you to be root/sudoer, since it is required to interact with Apache server)**
|
||||
|
||||
If you are running a web server, apache or nginx, it is recommended to use the `Webroot mode`.
|
||||
If you are running a web server, Apache or Nginx, it is recommended to use the `Webroot mode`.
|
||||
|
||||
Particularly, if you are running an apache server, you should use apache mode instead. This mode doesn't write any files to your web root folder.
|
||||
Particularly, if you are running an Apache server, you should use Apache mode instead. This mode doesn't write any files to your web root folder.
|
||||
|
||||
Just set string "apache" as the second argument, it will force use of apache plugin automatically.
|
||||
Just set string "apache" as the second argument and it will force use of apache plugin automatically.
|
||||
|
||||
```
|
||||
acme.sh --issue --apache -d example.com -d www.example.com -d user.example.com
|
||||
acme.sh --issue --apache -d example.com -d www.example.com -d cp.example.com
|
||||
```
|
||||
|
||||
More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert
|
||||
|
||||
|
||||
# 7. Use DNS mode:
|
||||
|
||||
Support the `dns-01` challenge.
|
||||
|
||||
```bash
|
||||
acme.sh --issue --dns -d example.com -d www.example.com -d user.example.com
|
||||
acme.sh --issue --dns -d example.com -d www.example.com -d cp.example.com
|
||||
```
|
||||
|
||||
You should get the output like below:
|
||||
You should get an output like below:
|
||||
|
||||
```
|
||||
Add the following txt record:
|
||||
@@ -226,7 +232,6 @@ Domain:_acme-challenge.www.example.com
|
||||
Txt value:9ihDbjxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
|
||||
Please add those txt records to the domains. Waiting for the dns to take effect.
|
||||
|
||||
```
|
||||
|
||||
Then just rerun with `renew` argument:
|
||||
@@ -237,52 +242,58 @@ acme.sh --renew -d example.com
|
||||
|
||||
Ok, it's finished.
|
||||
|
||||
|
||||
# 8. Automatic DNS API integration
|
||||
|
||||
If your DNS provider supports API access, we can use API to automatically issue the certs.
|
||||
If your DNS provider supports API access, we can use that API to automatically issue the certs.
|
||||
|
||||
You don't have do anything manually!
|
||||
You don't have to do anything manually!
|
||||
|
||||
### Currently acme.sh supports:
|
||||
|
||||
1. Cloudflare.com API
|
||||
2. Dnspod.cn API
|
||||
3. Cloudxns.com API
|
||||
4. Godaddy.com API
|
||||
5. OVH, kimsufi, soyoustart and runabove API
|
||||
6. AWS Route 53, see: https://github.com/Neilpang/acme.sh/issues/65
|
||||
7. PowerDNS API
|
||||
8. lexicon dns api: https://github.com/Neilpang/acme.sh/wiki/How-to-use-lexicon-dns-api
|
||||
(DigitalOcean, DNSimple, DnsMadeEasy, DNSPark, EasyDNS, Namesilo, NS1, PointHQ, Rage4 and Vultr etc.)
|
||||
9. LuaDNS.com API
|
||||
10. DNSMadeEasy.com API
|
||||
1. CloudFlare.com API
|
||||
1. DNSPod.cn API
|
||||
1. CloudXNS.com API
|
||||
1. GoDaddy.com API
|
||||
1. OVH, kimsufi, soyoustart and runabove API
|
||||
1. AWS Route 53
|
||||
1. PowerDNS.com API
|
||||
1. lexicon DNS API: https://github.com/Neilpang/acme.sh/wiki/How-to-use-lexicon-dns-api
|
||||
(DigitalOcean, DNSimple, DNSMadeEasy, DNSPark, EasyDNS, Namesilo, NS1, PointHQ, Rage4 and Vultr etc.)
|
||||
1. LuaDNS.com API
|
||||
1. DNSMadeEasy.com API
|
||||
1. nsupdate API
|
||||
1. aliyun.com(阿里云) API
|
||||
1. ISPConfig 3.1 API
|
||||
1. Alwaysdata.com API
|
||||
|
||||
##### More APIs are coming soon...
|
||||
**More APIs coming soon...**
|
||||
|
||||
If your DNS provider is not on the supported list above, you can write your own script API easily. If you do please consider submitting a [Pull Request](https://github.com/Neilpang/acme.sh/pulls) and contribute to the project.
|
||||
If your DNS provider is not on the supported list above, you can write your own DNS API script easily. If you do, please consider submitting a [Pull Request](https://github.com/Neilpang/acme.sh/pulls) and contribute it to the project.
|
||||
|
||||
For more details: [How to use dns api](dnsapi)
|
||||
For more details: [How to use DNS API](dnsapi)
|
||||
|
||||
# 9. Issue ECC certificate:
|
||||
|
||||
`Let's Encrypt` now can issue **ECDSA** certificates.
|
||||
# 9. Issue ECC certificates
|
||||
|
||||
And we also support it.
|
||||
`Let's Encrypt` can now issue **ECDSA** certificates.
|
||||
|
||||
And we support them too!
|
||||
|
||||
Just set the `length` parameter with a prefix `ec-`.
|
||||
|
||||
For example:
|
||||
|
||||
### Single domain ECC cerfiticate:
|
||||
### Single domain ECC cerfiticate
|
||||
|
||||
```bash
|
||||
acme.sh --issue -w /home/wwwroot/example.com -d example.com --keylength ec-256
|
||||
acme.sh --issue -w /home/wwwroot/example.com -d example.com --keylength ec-256
|
||||
```
|
||||
|
||||
SAN multi domain ECC certificate:
|
||||
### SAN multi domain ECC certificate
|
||||
|
||||
```bash
|
||||
acme.sh --issue -w /home/wwwroot/example.com -d example.com -d www.example.com --keylength ec-256
|
||||
acme.sh --issue -w /home/wwwroot/example.com -d example.com -d www.example.com --keylength ec-256
|
||||
```
|
||||
|
||||
Please look at the last parameter above.
|
||||
@@ -294,40 +305,48 @@ Valid values are:
|
||||
3. **ec-521 (secp521r1, "ECDSA P-521", which is not supported by Let's Encrypt yet.)**
|
||||
|
||||
|
||||
# 10. How to renew the cert
|
||||
# 10. How to renew the issued certs
|
||||
|
||||
No, you don't need to renew the certs manually. All the certs will be renewed automatically every **60** days.
|
||||
No, you don't need to renew the certs manually. All the certs will be renewed automatically every **60** days.
|
||||
|
||||
However, you can also force to renew any cert:
|
||||
|
||||
```
|
||||
acme.sh --renew -d example.com --force
|
||||
acme.sh --renew -d example.com --force
|
||||
```
|
||||
|
||||
or, for ECC cert:
|
||||
|
||||
```
|
||||
acme.sh --renew -d example.com --force --ecc
|
||||
acme.sh --renew -d example.com --force --ecc
|
||||
```
|
||||
|
||||
|
||||
# 11. How to upgrade `acme.sh`
|
||||
acme.sh is in developing, it's strongly recommended to use the latest code.
|
||||
|
||||
acme.sh is in constant development, so it's strongly recommended to use the latest code.
|
||||
|
||||
You can update acme.sh to the latest code:
|
||||
|
||||
```
|
||||
acme.sh --upgrade
|
||||
```
|
||||
|
||||
You can enable auto upgrade:
|
||||
You can also enable auto upgrade:
|
||||
|
||||
```
|
||||
acme.sh --upgrade --auto-upgrade
|
||||
acme.sh --upgrade --auto-upgrade
|
||||
```
|
||||
Then **acme.sh** will keep up to date automatically.
|
||||
|
||||
Then **acme.sh** will be kept up to date automatically.
|
||||
|
||||
Disable auto upgrade:
|
||||
|
||||
```
|
||||
acme.sh --upgrade --auto-upgrade 0
|
||||
acme.sh --upgrade --auto-upgrade 0
|
||||
```
|
||||
|
||||
|
||||
# 12. Issue a cert from an existing CSR
|
||||
|
||||
https://github.com/Neilpang/acme.sh/wiki/Issue-a-cert-from-existing-CSR
|
||||
@@ -339,22 +358,25 @@ Speak ACME language using shell, directly to "Let's Encrypt".
|
||||
|
||||
TODO:
|
||||
|
||||
# Acknowledgment
|
||||
|
||||
# Acknowledgments
|
||||
|
||||
1. Acme-tiny: https://github.com/diafygi/acme-tiny
|
||||
2. ACME protocol: https://github.com/ietf-wg-acme/acme
|
||||
3. Certbot: https://github.com/certbot/certbot
|
||||
|
||||
|
||||
# License & Others
|
||||
|
||||
License is GPLv3
|
||||
|
||||
Please Star and Fork me.
|
||||
|
||||
[Issues](https://github.com/Neilpang/acme.sh/issues) and [pull requests](https://github.com/Neilpang/acme.sh/pulls) are welcomed.
|
||||
[Issues](https://github.com/Neilpang/acme.sh/issues) and [pull requests](https://github.com/Neilpang/acme.sh/pulls) are welcome.
|
||||
|
||||
|
||||
# Donate
|
||||
1. PayPal: donate@acme.sh
|
||||
|
||||
1. PayPal: donate@acme.sh
|
||||
|
||||
[Donate List](https://github.com/Neilpang/acme.sh/wiki/Donate-list)
|
||||
|
||||
|
||||
243
dnsapi/README.md
243
dnsapi/README.md
@@ -1,99 +1,80 @@
|
||||
# How to use dns api
|
||||
# How to use DNS API
|
||||
|
||||
## Use CloudFlare domain api to automatically issue cert
|
||||
## 1. Use CloudFlare domain API to automatically issue cert
|
||||
|
||||
For now, we support clourflare integeration.
|
||||
|
||||
First you need to login to your clourflare account to get your api key.
|
||||
First you need to login to your CloudFlare account to get your API key.
|
||||
|
||||
```
|
||||
export CF_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"
|
||||
|
||||
export CF_Email="xxxx@sss.com"
|
||||
|
||||
```
|
||||
|
||||
Ok, let's issue cert now:
|
||||
Ok, let's issue a cert now:
|
||||
```
|
||||
acme.sh --issue --dns dns_cf -d example.com -d www.example.com
|
||||
acme.sh --issue --dns dns_cf -d example.com -d www.example.com
|
||||
```
|
||||
|
||||
The `CF_Key` and `CF_Email` will be saved in `~/.acme.sh/account.conf`, when next time you use cloudflare api, it will reuse this key.
|
||||
The `CF_Key` and `CF_Email` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
|
||||
|
||||
|
||||
## 2. Use DNSPod.cn domain API to automatically issue cert
|
||||
|
||||
## Use Dnspod.cn domain api to automatically issue cert
|
||||
|
||||
For now, we support dnspod.cn integeration.
|
||||
|
||||
First you need to login to your dnspod.cn account to get your api key and key id.
|
||||
First you need to login to your DNSPod account to get your API Key and ID.
|
||||
|
||||
```
|
||||
export DP_Id="1234"
|
||||
|
||||
export DP_Key="sADDsdasdgdsf"
|
||||
|
||||
```
|
||||
|
||||
Ok, let's issue cert now:
|
||||
Ok, let's issue a cert now:
|
||||
```
|
||||
acme.sh --issue --dns dns_dp -d example.com -d www.example.com
|
||||
acme.sh --issue --dns dns_dp -d example.com -d www.example.com
|
||||
```
|
||||
|
||||
The `DP_Id` and `DP_Key` will be saved in `~/.acme.sh/account.conf`, when next time you use dnspod.cn api, it will reuse this key.
|
||||
The `DP_Id` and `DP_Key` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
|
||||
|
||||
|
||||
## Use Cloudxns.com domain api to automatically issue cert
|
||||
## 3. Use CloudXNS.com domain API to automatically issue cert
|
||||
|
||||
For now, we support Cloudxns.com integeration.
|
||||
|
||||
First you need to login to your Cloudxns.com account to get your api key and key secret.
|
||||
First you need to login to your CloudXNS account to get your API Key and Secret.
|
||||
|
||||
```
|
||||
export CX_Key="1234"
|
||||
|
||||
export CX_Secret="sADDsdasdgdsf"
|
||||
|
||||
```
|
||||
|
||||
Ok, let's issue cert now:
|
||||
Ok, let's issue a cert now:
|
||||
```
|
||||
acme.sh --issue --dns dns_cx -d example.com -d www.example.com
|
||||
acme.sh --issue --dns dns_cx -d example.com -d www.example.com
|
||||
```
|
||||
|
||||
The `CX_Key` and `CX_Secret` will be saved in `~/.acme.sh/account.conf`, when next time you use Cloudxns.com api, it will reuse this key.
|
||||
The `CX_Key` and `CX_Secret` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
|
||||
|
||||
|
||||
## Use Godaddy.com domain api to automatically issue cert
|
||||
## 4. Use GoDaddy.com domain API to automatically issue cert
|
||||
|
||||
We support Godaddy integration.
|
||||
|
||||
First you need to login to your Godaddy account to get your api key and api secret.
|
||||
First you need to login to your GoDaddy account to get your API Key and Secret.
|
||||
|
||||
https://developer.godaddy.com/keys/
|
||||
|
||||
Please Create a Production key, instead of a Test key.
|
||||
|
||||
Please create a Production key, instead of a Test key.
|
||||
|
||||
```
|
||||
export GD_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"
|
||||
|
||||
export GD_Secret="asdfsdafdsfdsfdsfdsfdsafd"
|
||||
|
||||
```
|
||||
|
||||
Ok, let's issue cert now:
|
||||
Ok, let's issue a cert now:
|
||||
```
|
||||
acme.sh --issue --dns dns_gd -d example.com -d www.example.com
|
||||
acme.sh --issue --dns dns_gd -d example.com -d www.example.com
|
||||
```
|
||||
|
||||
The `GD_Key` and `GD_Secret` will be saved in `~/.acme.sh/account.conf`, when next time you use cloudflare api, it will reuse this key.
|
||||
The `GD_Key` and `GD_Secret` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
|
||||
|
||||
## Use PowerDNS embedded api to automatically issue cert
|
||||
|
||||
We support PowerDNS embedded API integration.
|
||||
## 5. Use PowerDNS embedded API to automatically issue cert
|
||||
|
||||
First you need to enable api and set your api-token in PowerDNS configuration.
|
||||
First you need to login to your PowerDNS account to enable the API and set your API-Token in the configuration.
|
||||
|
||||
https://doc.powerdns.com/md/httpapi/README/
|
||||
|
||||
@@ -102,75 +83,197 @@ export PDNS_Url="http://ns.example.com:8081"
|
||||
export PDNS_ServerId="localhost"
|
||||
export PDNS_Token="0123456789ABCDEF"
|
||||
export PDNS_Ttl=60
|
||||
|
||||
```
|
||||
|
||||
Ok, let's issue cert now:
|
||||
Ok, let's issue a cert now:
|
||||
```
|
||||
acme.sh --issue --dns dns_pdns -d example.com -d www.example.com
|
||||
acme.sh --issue --dns dns_pdns -d example.com -d www.example.com
|
||||
```
|
||||
|
||||
The `PDNS_Url`, `PDNS_ServerId`, `PDNS_Token` and `PDNS_Ttl` will be saved in `~/.acme.sh/account.conf`.
|
||||
The `PDNS_Url`, `PDNS_ServerId`, `PDNS_Token` and `PDNS_Ttl` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
|
||||
|
||||
## Use OVH/kimsufi/soyoustart/runabove API
|
||||
|
||||
## 6. Use OVH/kimsufi/soyoustart/runabove API to automatically issue cert
|
||||
|
||||
https://github.com/Neilpang/acme.sh/wiki/How-to-use-OVH-domain-api
|
||||
|
||||
# Use custom api
|
||||
|
||||
If your api is not supported yet, you can write your own dns api.
|
||||
|
||||
Let's assume you want to name it 'myapi',
|
||||
|
||||
1. Create a bash script named `~/.acme.sh/dns_myapi.sh`,
|
||||
2. In the script, you must have a function named `dns_myapi_add()`. Which will be called by acme.sh to add dns records.
|
||||
3. Then you can use your api to issue cert like:
|
||||
## 7. Use nsupdate to automatically issue cert
|
||||
|
||||
First, generate a key for updating the zone
|
||||
```
|
||||
acme.sh --issue --dns dns_myapi -d example.com -d www.example.com
|
||||
b=$(dnssec-keygen -a hmac-sha512 -b 512 -n USER -K /tmp foo)
|
||||
cat > /etc/named/keys/update.key <<EOF
|
||||
key "update" {
|
||||
algorithm hmac-sha512;
|
||||
secret "$(awk '/^Key/{print $2}' /tmp/$b.private)";
|
||||
};
|
||||
EOF
|
||||
rm -f /tmp/$b.{private,key}
|
||||
```
|
||||
|
||||
For more details, please check our sample script: [dns_myapi.sh](dns_myapi.sh)
|
||||
Include this key in your named configuration
|
||||
```
|
||||
include "/etc/named/keys/update.key";
|
||||
```
|
||||
|
||||
# Use lexicon dns api
|
||||
Next, configure your zone to allow dynamic updates.
|
||||
|
||||
https://github.com/Neilpang/acme.sh/wiki/How-to-use-lexicon-dns-api
|
||||
Depending on your named version, use either
|
||||
```
|
||||
zone "example.com" {
|
||||
type master;
|
||||
allow-update { key "update"; };
|
||||
};
|
||||
```
|
||||
or
|
||||
```
|
||||
zone "example.com" {
|
||||
type master;
|
||||
update-policy {
|
||||
grant update subdomain example.com.;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Use LuaDNS domain API
|
||||
Finally, make the DNS server and update Key available to `acme.sh`
|
||||
|
||||
```
|
||||
export NSUPDATE_SERVER="dns.example.com"
|
||||
export NSUPDATE_KEY="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=="
|
||||
```
|
||||
|
||||
Ok, let's issue a cert now:
|
||||
```
|
||||
acme.sh --issue --dns dns_nsupdate -d example.com -d www.example.com
|
||||
```
|
||||
|
||||
The `NSUPDATE_SERVER` and `NSUPDATE_KEY` settings will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
|
||||
|
||||
|
||||
## 8. Use LuaDNS domain API
|
||||
|
||||
Get your API token at https://api.luadns.com/settings
|
||||
|
||||
```
|
||||
export LUA_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"
|
||||
|
||||
export LUA_Email="xxxx@sss.com"
|
||||
|
||||
```
|
||||
|
||||
To issue a cert:
|
||||
```
|
||||
acme.sh --issue --dns dns_lua --dnssleep 3 -d example.com -d www.example.com
|
||||
acme.sh --issue --dns dns_lua -d example.com -d www.example.com
|
||||
```
|
||||
|
||||
The `LUA_Key` and `LUA_Email` will be saved in `~/.acme.sh/account.conf`, and will be reused when needed.
|
||||
The `LUA_Key` and `LUA_Email` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
|
||||
|
||||
## Use DNSMadeEasy domain API
|
||||
|
||||
## 9. Use DNSMadeEasy domain API
|
||||
|
||||
Get your API credentials at https://cp.dnsmadeeasy.com/account/info
|
||||
|
||||
```
|
||||
export ME_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"
|
||||
|
||||
export ME_Secret="qdfqsdfkjdskfj"
|
||||
|
||||
```
|
||||
|
||||
To issue a cert:
|
||||
```
|
||||
acme.sh --issue --dns dns_me --dnssleep 3 -d example.com -d www.example.com
|
||||
acme.sh --issue --dns dns_me -d example.com -d www.example.com
|
||||
```
|
||||
|
||||
The `ME_Key` and `ME_Secret` will be saved in `~/.acme.sh/account.conf`, and will be reused when needed.
|
||||
The `ME_Key` and `ME_Secret` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
|
||||
|
||||
|
||||
## 10. Use Amazon Route53 domain API
|
||||
|
||||
https://github.com/Neilpang/acme.sh/wiki/How-to-use-Amazon-Route53-API
|
||||
|
||||
```
|
||||
export AWS_ACCESS_KEY_ID=XXXXXXXXXX
|
||||
export AWS_SECRET_ACCESS_KEY=XXXXXXXXXXXXXXX
|
||||
```
|
||||
|
||||
To issue a cert:
|
||||
```
|
||||
acme.sh --issue --dns dns_aws -d example.com -d www.example.com
|
||||
```
|
||||
|
||||
The `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
|
||||
|
||||
## 11. Use Aliyun domain API to automatically issue cert
|
||||
|
||||
First you need to login to your Aliyun account to get your API key.
|
||||
[https://ak-console.aliyun.com/#/accesskey](https://ak-console.aliyun.com/#/accesskey)
|
||||
|
||||
```
|
||||
export Ali_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"
|
||||
export Ali_Secret="jlsdflanljkljlfdsaklkjflsa"
|
||||
```
|
||||
|
||||
Ok, let's issue a cert now:
|
||||
```
|
||||
acme.sh --issue --dns dns_ali -d example.com -d www.example.com
|
||||
```
|
||||
|
||||
The `Ali_Key` and `Ali_Secret` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
|
||||
|
||||
## 12. Use ISPConfig 3.1 API
|
||||
|
||||
This only works for ISPConfig 3.1 (and newer).
|
||||
|
||||
Create a Remote User in the ISPConfig Control Panel. The Remote User must have access to at least `DNS zone functions` and `DNS txt functions`.
|
||||
|
||||
```
|
||||
export ISPC_User="xxx"
|
||||
export ISPC_Password="xxx"
|
||||
export ISPC_Api="https://ispc.domain.tld:8080/remote/json.php"
|
||||
export ISPC_Api_Insecure=1
|
||||
```
|
||||
If you have installed ISPConfig on a different port, then alter the 8080 accordingly.
|
||||
Leaver ISPC_Api_Insecure set to 1 if you have not a valid ssl cert for your installation. Change it to 0 if you have a valid ssl cert.
|
||||
|
||||
To issue a cert:
|
||||
```
|
||||
acme.sh --issue --dns dns_ispconfig -d example.com -d www.example.com
|
||||
```
|
||||
|
||||
The `ISPC_User`, `ISPC_Password`, `ISPC_Api`and `ISPC_Api_Insecure` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
|
||||
|
||||
## 13. Use Alwaysdata domain API
|
||||
|
||||
First you need to login to your Alwaysdata account to get your API Key.
|
||||
|
||||
```sh
|
||||
export AD_API_KEY="myalwaysdataapikey"
|
||||
```
|
||||
|
||||
Ok, let's issue a cert now:
|
||||
|
||||
```sh
|
||||
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.
|
||||
|
||||
# Use custom API
|
||||
|
||||
If your API is not supported yet, you can write your own DNS API.
|
||||
|
||||
Let's assume you want to name it 'myapi':
|
||||
|
||||
1. Create a bash script named `~/.acme.sh/dns_myapi.sh`,
|
||||
2. In the script you must have a function named `dns_myapi_add()` which will be called by acme.sh to add the DNS records.
|
||||
3. Then you can use your API to issue cert like this:
|
||||
|
||||
```
|
||||
acme.sh --issue --dns dns_myapi -d example.com -d www.example.com
|
||||
```
|
||||
|
||||
For more details, please check our sample script: [dns_myapi.sh](dns_myapi.sh)
|
||||
|
||||
|
||||
# Use lexicon DNS API
|
||||
|
||||
https://github.com/Neilpang/acme.sh/wiki/How-to-use-lexicon-dns-api
|
||||
|
||||
147
dnsapi/dns_ad.sh
Normal file
147
dnsapi/dns_ad.sh
Normal file
@@ -0,0 +1,147 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#
|
||||
#AD_API_KEY="sdfsdfsdfljlbjkljlkjsdfoiwje"
|
||||
|
||||
#This is the Alwaysdata api wrapper for acme.sh
|
||||
#
|
||||
#Author: Paul Koppen
|
||||
#Report Bugs here: https://github.com/wpk-/acme.sh
|
||||
|
||||
AD_API_URL="https://$AD_API_KEY:@api.alwaysdata.com/v1"
|
||||
|
||||
######## Public functions #####################
|
||||
|
||||
#Usage: dns_myapi_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
dns_ad_add() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
|
||||
if [ -z "$AD_API_KEY" ]; then
|
||||
AD_API_KEY=""
|
||||
_err "You didn't specify the AD api key yet."
|
||||
_err "Please create you key and try again."
|
||||
return 1
|
||||
fi
|
||||
|
||||
_saveaccountconf AD_API_KEY "$AD_API_KEY"
|
||||
|
||||
_debug "First detect the root zone"
|
||||
if ! _get_root "$fulldomain"; then
|
||||
_err "invalid domain"
|
||||
return 1
|
||||
fi
|
||||
_debug _domain_id "$_domain_id"
|
||||
_debug _sub_domain "$_sub_domain"
|
||||
_debug _domain "$_domain"
|
||||
|
||||
_ad_tmpl_json="{\"domain\":$_domain_id,\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"value\":\"$txtvalue\"}"
|
||||
|
||||
if _ad_rest POST "record/" "$_ad_tmpl_json" && [ -z "$response" ]; then
|
||||
_info "txt record updated success."
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
#fulldomain txtvalue
|
||||
dns_ad_rm() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
|
||||
_debug "First detect the root zone"
|
||||
if ! _get_root "$fulldomain"; then
|
||||
_err "invalid domain"
|
||||
return 1
|
||||
fi
|
||||
_debug _domain_id "$_domain_id"
|
||||
_debug _sub_domain "$_sub_domain"
|
||||
_debug _domain "$_domain"
|
||||
|
||||
_debug "Getting txt records"
|
||||
_ad_rest GET "record/?domain=$_domain_id&name=$_sub_domain"
|
||||
|
||||
if [ -n "$response" ]; then
|
||||
record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":\s*[0-9]+" | cut -d : -f 2 | tr -d " " | _head_n 1)
|
||||
_debug record_id "$record_id"
|
||||
if [ -z "$record_id" ]; then
|
||||
_err "Can not get record id to remove."
|
||||
return 1
|
||||
fi
|
||||
if _ad_rest DELETE "record/$record_id/" && [ -z "$response" ]; then
|
||||
_info "txt record deleted success."
|
||||
return 0
|
||||
fi
|
||||
_debug response "$response"
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
#################### 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 _ad_rest GET "domain/"; 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 "{.*\"name\":\s*\"$h\".*}")"
|
||||
if [ "$hostedzone" ]; then
|
||||
_domain_id=$(printf "%s\n" "$hostedzone" | _egrep_o "\"id\":\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 uri qstr data
|
||||
_ad_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" "$AD_API_URL/$ep" "" "$mtd")"
|
||||
else
|
||||
response="$(_get "$AD_API_URL/$ep")"
|
||||
fi
|
||||
|
||||
if [ "$?" != "0" ]; then
|
||||
_err "error $ep"
|
||||
return 1
|
||||
fi
|
||||
_debug2 response "$response"
|
||||
return 0
|
||||
}
|
||||
187
dnsapi/dns_ali.sh
Normal file
187
dnsapi/dns_ali.sh
Normal file
@@ -0,0 +1,187 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
Ali_API="https://alidns.aliyuncs.com/"
|
||||
|
||||
#Ali_Key="LTqIA87hOKdjevsf5"
|
||||
#Ali_Secret="0p5EYueFNq501xnCPzKNbx6K51qPH2"
|
||||
|
||||
#Usage: dns_ali_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
dns_ali_add() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
|
||||
if [ -z "$Ali_Key" ] || [ -z "$Ali_Secret" ]; then
|
||||
Ali_Key=""
|
||||
Ali_Secret=""
|
||||
_err "You don't specify aliyun api key and secret yet."
|
||||
return 1
|
||||
fi
|
||||
|
||||
#save the api key and secret to the account conf file.
|
||||
_saveaccountconf Ali_Key "$Ali_Key"
|
||||
_saveaccountconf Ali_Secret "$Ali_Secret"
|
||||
|
||||
_debug "First detect the root zone"
|
||||
if ! _get_root "$fulldomain"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
_debug "Add record"
|
||||
_add_record_query "$_domain" "$_sub_domain" "$txtvalue" && _ali_rest "Add record"
|
||||
}
|
||||
|
||||
dns_ali_rm() {
|
||||
fulldomain=$1
|
||||
_clean
|
||||
}
|
||||
|
||||
#################### Private functions below ##################################
|
||||
|
||||
_get_root() {
|
||||
domain=$1
|
||||
i=2
|
||||
p=1
|
||||
while true; do
|
||||
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
||||
if [ -z "$h" ]; then
|
||||
#not valid
|
||||
return 1
|
||||
fi
|
||||
|
||||
_describe_records_query "$h"
|
||||
if ! _ali_rest "Get root" "ignore"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if _contains "$response" "PageNumber"; then
|
||||
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
|
||||
_debug _sub_domain "$_sub_domain"
|
||||
_domain="$h"
|
||||
_debug _domain "$_domain"
|
||||
return 0
|
||||
fi
|
||||
p="$i"
|
||||
i=$(_math "$i" + 1)
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
_ali_rest() {
|
||||
signature=$(printf "%s" "GET&%2F&$(_ali_urlencode "$query")" | _hmac "sha1" "$(_hex "$Ali_Secret&")" | _base64)
|
||||
signature=$(_ali_urlencode "$signature")
|
||||
url="$Ali_API?$query&Signature=$signature"
|
||||
|
||||
if ! response="$(_get "$url")"; then
|
||||
_err "Error <$1>"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ -z "$2" ]; then
|
||||
message="$(printf "%s" "$response" | _egrep_o "\"Message\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \")"
|
||||
if [ -n "$message" ]; then
|
||||
_err "$message"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
_debug2 response "$response"
|
||||
return 0
|
||||
}
|
||||
|
||||
_ali_urlencode() {
|
||||
_str="$1"
|
||||
_str_len=${#_str}
|
||||
_u_i=1
|
||||
while [ "$_u_i" -le "$_str_len" ]; do
|
||||
_str_c="$(printf "%s" "$_str" | cut -c "$_u_i")"
|
||||
case $_str_c in [a-zA-Z0-9.~_-])
|
||||
printf "%s" "$_str_c"
|
||||
;;
|
||||
*)
|
||||
printf "%%%02X" "'$_str_c"
|
||||
;;
|
||||
esac
|
||||
_u_i="$(_math "$_u_i" + 1)"
|
||||
done
|
||||
}
|
||||
|
||||
_ali_nonce() {
|
||||
#_head_n 1 </dev/urandom | _digest "sha256" hex | cut -c 1-31
|
||||
#Not so good...
|
||||
date +"%s%N"
|
||||
}
|
||||
|
||||
_check_exist_query() {
|
||||
query=''
|
||||
query=$query'AccessKeyId='$Ali_Key
|
||||
query=$query'&Action=DescribeDomainRecords'
|
||||
query=$query'&DomainName='$1
|
||||
query=$query'&Format=json'
|
||||
query=$query'&RRKeyWord=_acme-challenge'
|
||||
query=$query'&SignatureMethod=HMAC-SHA1'
|
||||
query=$query"&SignatureNonce=$(_ali_nonce)"
|
||||
query=$query'&SignatureVersion=1.0'
|
||||
query=$query'&Timestamp='$(_timestamp)
|
||||
query=$query'&TypeKeyWord=TXT'
|
||||
query=$query'&Version=2015-01-09'
|
||||
}
|
||||
|
||||
_add_record_query() {
|
||||
query=''
|
||||
query=$query'AccessKeyId='$Ali_Key
|
||||
query=$query'&Action=AddDomainRecord'
|
||||
query=$query'&DomainName='$1
|
||||
query=$query'&Format=json'
|
||||
query=$query'&RR='$2
|
||||
query=$query'&SignatureMethod=HMAC-SHA1'
|
||||
query=$query"&SignatureNonce=$(_ali_nonce)"
|
||||
query=$query'&SignatureVersion=1.0'
|
||||
query=$query'&Timestamp='$(_timestamp)
|
||||
query=$query'&Type=TXT'
|
||||
query=$query'&Value='$3
|
||||
query=$query'&Version=2015-01-09'
|
||||
}
|
||||
|
||||
_delete_record_query() {
|
||||
query=''
|
||||
query=$query'AccessKeyId='$Ali_Key
|
||||
query=$query'&Action=DeleteDomainRecord'
|
||||
query=$query'&Format=json'
|
||||
query=$query'&RecordId='$1
|
||||
query=$query'&SignatureMethod=HMAC-SHA1'
|
||||
query=$query"&SignatureNonce=$(_ali_nonce)"
|
||||
query=$query'&SignatureVersion=1.0'
|
||||
query=$query'&Timestamp='$(_timestamp)
|
||||
query=$query'&Version=2015-01-09'
|
||||
}
|
||||
|
||||
_describe_records_query() {
|
||||
query=''
|
||||
query=$query'AccessKeyId='$Ali_Key
|
||||
query=$query'&Action=DescribeDomainRecords'
|
||||
query=$query'&DomainName='$1
|
||||
query=$query'&Format=json'
|
||||
query=$query'&SignatureMethod=HMAC-SHA1'
|
||||
query=$query"&SignatureNonce=$(_ali_nonce)"
|
||||
query=$query'&SignatureVersion=1.0'
|
||||
query=$query'&Timestamp='$(_timestamp)
|
||||
query=$query'&Version=2015-01-09'
|
||||
}
|
||||
|
||||
_clean() {
|
||||
_check_exist_query "$_domain"
|
||||
if ! _ali_rest "Check exist records" "ignore"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
records="$(echo "$response" -n | _egrep_o "\"RecordId\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \")"
|
||||
printf "%s" "$records" \
|
||||
| while read -r record_id; do
|
||||
_delete_record_query "$record_id"
|
||||
_ali_rest "Delete record $record_id" "ignore"
|
||||
done
|
||||
}
|
||||
|
||||
_timestamp() {
|
||||
date -u +"%Y-%m-%dT%H%%3A%M%%3A%SZ"
|
||||
}
|
||||
227
dnsapi/dns_aws.sh
Normal file
227
dnsapi/dns_aws.sh
Normal file
@@ -0,0 +1,227 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#
|
||||
#AWS_ACCESS_KEY_ID="sdfsdfsdfljlbjkljlkjsdfoiwje"
|
||||
#
|
||||
#AWS_SECRET_ACCESS_KEY="xxxxxxx"
|
||||
|
||||
#This is the Amazon Route53 api wrapper for acme.sh
|
||||
|
||||
AWS_HOST="route53.amazonaws.com"
|
||||
AWS_URL="https://$AWS_HOST"
|
||||
|
||||
AWS_WIKI="https://github.com/Neilpang/acme.sh/wiki/How-to-use-Amazon-Route53-API"
|
||||
|
||||
######## Public functions #####################
|
||||
|
||||
#Usage: dns_myapi_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
dns_aws_add() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
|
||||
if [ -z "$AWS_ACCESS_KEY_ID" ] || [ -z "$AWS_SECRET_ACCESS_KEY" ]; then
|
||||
AWS_ACCESS_KEY_ID=""
|
||||
AWS_SECRET_ACCESS_KEY=""
|
||||
_err "You don't specify aws route53 api key id and and api key secret yet."
|
||||
_err "Please create you key and try again. see $(__green $AWS_WIKI)"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ -z "$AWS_SESSION_TOKEN" ]; then
|
||||
_saveaccountconf AWS_ACCESS_KEY_ID "$AWS_ACCESS_KEY_ID"
|
||||
_saveaccountconf AWS_SECRET_ACCESS_KEY "$AWS_SECRET_ACCESS_KEY"
|
||||
fi
|
||||
|
||||
_debug "First detect the root zone"
|
||||
if ! _get_root "$fulldomain"; then
|
||||
_err "invalid domain"
|
||||
return 1
|
||||
fi
|
||||
_debug _domain_id "$_domain_id"
|
||||
_debug _sub_domain "$_sub_domain"
|
||||
_debug _domain "$_domain"
|
||||
|
||||
_aws_tmpl_xml="<ChangeResourceRecordSetsRequest xmlns=\"https://route53.amazonaws.com/doc/2013-04-01/\"><ChangeBatch><Changes><Change><Action>UPSERT</Action><ResourceRecordSet><Name>$fulldomain</Name><Type>TXT</Type><TTL>300</TTL><ResourceRecords><ResourceRecord><Value>\"$txtvalue\"</Value></ResourceRecord></ResourceRecords></ResourceRecordSet></Change></Changes></ChangeBatch></ChangeResourceRecordSetsRequest>"
|
||||
|
||||
if aws_rest POST "2013-04-01$_domain_id/rrset/" "" "$_aws_tmpl_xml" && _contains "$response" "ChangeResourceRecordSetsResponse"; then
|
||||
_info "txt record updated success."
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
#fulldomain txtvalue
|
||||
dns_aws_rm() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
|
||||
_debug "First detect the root zone"
|
||||
if ! _get_root "$fulldomain"; then
|
||||
_err "invalid domain"
|
||||
return 1
|
||||
fi
|
||||
_debug _domain_id "$_domain_id"
|
||||
_debug _sub_domain "$_sub_domain"
|
||||
_debug _domain "$_domain"
|
||||
|
||||
_aws_tmpl_xml="<ChangeResourceRecordSetsRequest xmlns=\"https://route53.amazonaws.com/doc/2013-04-01/\"><ChangeBatch><Changes><Change><Action>DELETE</Action><ResourceRecordSet><ResourceRecords><ResourceRecord><Value>\"$txtvalue\"</Value></ResourceRecord></ResourceRecords><Name>$fulldomain.</Name><Type>TXT</Type><TTL>300</TTL></ResourceRecordSet></Change></Changes></ChangeBatch></ChangeResourceRecordSetsRequest>"
|
||||
|
||||
if aws_rest POST "2013-04-01$_domain_id/rrset/" "" "$_aws_tmpl_xml" && _contains "$response" "ChangeResourceRecordSetsResponse"; then
|
||||
_info "txt record deleted success."
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
|
||||
}
|
||||
|
||||
#################### Private functions below ##################################
|
||||
|
||||
_get_root() {
|
||||
domain=$1
|
||||
i=2
|
||||
p=1
|
||||
|
||||
if aws_rest GET "2013-04-01/hostedzone"; then
|
||||
_debug "response" "$response"
|
||||
while true; do
|
||||
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
||||
if [ -z "$h" ]; then
|
||||
#not valid
|
||||
return 1
|
||||
fi
|
||||
|
||||
if _contains "$response" "<Name>$h.</Name>"; then
|
||||
hostedzone="$(echo "$response" | sed 's/<HostedZone>/\n&/g' | _egrep_o "<HostedZone>.*?<Name>$h.<.Name>.*?<.HostedZone>")"
|
||||
_debug hostedzone "$hostedzone"
|
||||
if [ -z "$hostedzone" ]; then
|
||||
_err "Error, can not get hostedzone."
|
||||
return 1
|
||||
fi
|
||||
_domain_id=$(printf "%s\n" "$hostedzone" | _egrep_o "<Id>.*<.Id>" | head -n 1 | _egrep_o ">.*<" | 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 uri qstr data
|
||||
aws_rest() {
|
||||
mtd="$1"
|
||||
ep="$2"
|
||||
qsr="$3"
|
||||
data="$4"
|
||||
|
||||
_debug mtd "$mtd"
|
||||
_debug ep "$ep"
|
||||
_debug qsr "$qsr"
|
||||
_debug data "$data"
|
||||
|
||||
CanonicalURI="/$ep"
|
||||
_debug2 CanonicalURI "$CanonicalURI"
|
||||
|
||||
CanonicalQueryString="$qsr"
|
||||
_debug2 CanonicalQueryString "$CanonicalQueryString"
|
||||
|
||||
RequestDate="$(date -u +"%Y%m%dT%H%M%SZ")"
|
||||
_debug2 RequestDate "$RequestDate"
|
||||
|
||||
#RequestDate="20161120T141056Z" ##############
|
||||
|
||||
export _H1="x-amz-date: $RequestDate"
|
||||
|
||||
aws_host="$AWS_HOST"
|
||||
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"
|
||||
CanonicalHeaders="${CanonicalHeaders}x-amz-security-token:$AWS_SESSION_TOKEN\n"
|
||||
SignedHeaders="${SignedHeaders};x-amz-security-token"
|
||||
fi
|
||||
_debug2 CanonicalHeaders "$CanonicalHeaders"
|
||||
_debug2 SignedHeaders "$SignedHeaders"
|
||||
|
||||
RequestPayload="$data"
|
||||
_debug2 RequestPayload "$RequestPayload"
|
||||
|
||||
Hash="sha256"
|
||||
|
||||
CanonicalRequest="$mtd\n$CanonicalURI\n$CanonicalQueryString\n$CanonicalHeaders\n$SignedHeaders\n$(printf "%s" "$RequestPayload" | _digest "$Hash" hex)"
|
||||
_debug2 CanonicalRequest "$CanonicalRequest"
|
||||
|
||||
HashedCanonicalRequest="$(printf "$CanonicalRequest%s" | _digest "$Hash" hex)"
|
||||
_debug2 HashedCanonicalRequest "$HashedCanonicalRequest"
|
||||
|
||||
Algorithm="AWS4-HMAC-SHA256"
|
||||
_debug2 Algorithm "$Algorithm"
|
||||
|
||||
RequestDateOnly="$(echo "$RequestDate" | cut -c 1-8)"
|
||||
_debug2 RequestDateOnly "$RequestDateOnly"
|
||||
|
||||
Region="us-east-1"
|
||||
Service="route53"
|
||||
|
||||
CredentialScope="$RequestDateOnly/$Region/$Service/aws4_request"
|
||||
_debug2 CredentialScope "$CredentialScope"
|
||||
|
||||
StringToSign="$Algorithm\n$RequestDate\n$CredentialScope\n$HashedCanonicalRequest"
|
||||
|
||||
_debug2 StringToSign "$StringToSign"
|
||||
|
||||
kSecret="AWS4$AWS_SECRET_ACCESS_KEY"
|
||||
|
||||
#kSecret="wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY" ############################
|
||||
|
||||
_debug2 kSecret "$kSecret"
|
||||
|
||||
kSecretH="$(_hex "$kSecret")"
|
||||
_debug2 kSecretH "$kSecretH"
|
||||
|
||||
kDateH="$(printf "$RequestDateOnly%s" | _hmac "$Hash" "$kSecretH" hex)"
|
||||
_debug2 kDateH "$kDateH"
|
||||
|
||||
kRegionH="$(printf "$Region%s" | _hmac "$Hash" "$kDateH" hex)"
|
||||
_debug2 kRegionH "$kRegionH"
|
||||
|
||||
kServiceH="$(printf "$Service%s" | _hmac "$Hash" "$kRegionH" hex)"
|
||||
_debug2 kServiceH "$kServiceH"
|
||||
|
||||
kSigningH="$(printf "aws4_request%s" | _hmac "$Hash" "$kServiceH" hex)"
|
||||
_debug2 kSigningH "$kSigningH"
|
||||
|
||||
signature="$(printf "$StringToSign%s" | _hmac "$Hash" "$kSigningH" hex)"
|
||||
_debug2 signature "$signature"
|
||||
|
||||
Authorization="$Algorithm Credential=$AWS_ACCESS_KEY_ID/$CredentialScope, SignedHeaders=$SignedHeaders, Signature=$signature"
|
||||
_debug2 Authorization "$Authorization"
|
||||
|
||||
_H3="Authorization: $Authorization"
|
||||
_debug _H3 "$_H3"
|
||||
|
||||
url="$AWS_URL/$ep"
|
||||
|
||||
if [ "$mtd" = "GET" ]; then
|
||||
response="$(_get "$url")"
|
||||
else
|
||||
response="$(_post "$data" "$url")"
|
||||
fi
|
||||
|
||||
_ret="$?"
|
||||
if [ "$_ret" = "0" ]; then
|
||||
if _contains "$response" "<ErrorResponse"; then
|
||||
_err "Response error:$response"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
return "$_ret"
|
||||
}
|
||||
@@ -15,17 +15,25 @@ dns_cf_add() {
|
||||
txtvalue=$2
|
||||
|
||||
if [ -z "$CF_Key" ] || [ -z "$CF_Email" ]; then
|
||||
CF_Key=""
|
||||
CF_Email=""
|
||||
_err "You don't specify cloudflare api key and email yet."
|
||||
_err "Please create you key and try again."
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! _contains "$CF_Email" "@"; then
|
||||
_err "It seems that the CF_Email=$CF_Email is not a valid email address."
|
||||
_err "Please check and retry."
|
||||
return 1
|
||||
fi
|
||||
|
||||
#save the api key and email to the account conf file.
|
||||
_saveaccountconf CF_Key "$CF_Key"
|
||||
_saveaccountconf CF_Email "$CF_Email"
|
||||
|
||||
_debug "First detect the root zone"
|
||||
if ! _get_root $fulldomain; then
|
||||
if ! _get_root "$fulldomain"; then
|
||||
_err "invalid domain"
|
||||
return 1
|
||||
fi
|
||||
@@ -36,20 +44,18 @@ dns_cf_add() {
|
||||
_debug "Getting txt records"
|
||||
_cf_rest GET "zones/${_domain_id}/dns_records?type=TXT&name=$fulldomain"
|
||||
|
||||
if ! printf "$response" | grep \"success\":true >/dev/null; then
|
||||
if ! printf "%s" "$response" | grep \"success\":true >/dev/null; then
|
||||
_err "Error"
|
||||
return 1
|
||||
fi
|
||||
|
||||
count=$(printf "%s\n" "$response" | _egrep_o \"count\":[^,]* | cut -d : -f 2)
|
||||
count=$(printf "%s\n" "$response" | _egrep_o "\"count\":[^,]*" | cut -d : -f 2)
|
||||
_debug count "$count"
|
||||
if [ "$count" = "0" ]; then
|
||||
_info "Adding record"
|
||||
if _cf_rest POST "zones/$_domain_id/dns_records" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":120}"; then
|
||||
if printf -- "%s" "$response" | grep $fulldomain >/dev/null; then
|
||||
_info "Added, sleeping 10 seconds"
|
||||
sleep 10
|
||||
#todo: check if the record takes effect
|
||||
if printf -- "%s" "$response" | grep "$fulldomain" >/dev/null; then
|
||||
_info "Added, OK"
|
||||
return 0
|
||||
else
|
||||
_err "Add txt record error."
|
||||
@@ -59,14 +65,12 @@ dns_cf_add() {
|
||||
_err "Add txt record error."
|
||||
else
|
||||
_info "Updating record"
|
||||
record_id=$(printf "%s\n" "$response" | _egrep_o \"id\":\"[^\"]*\" | cut -d : -f 2 | tr -d \" | head -n 1)
|
||||
_debug "record_id" $record_id
|
||||
record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | head -n 1)
|
||||
_debug "record_id" "$record_id"
|
||||
|
||||
_cf_rest PUT "zones/$_domain_id/dns_records/$record_id" "{\"id\":\"$record_id\",\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"zone_id\":\"$_domain_id\",\"zone_name\":\"$_domain\"}"
|
||||
if [ "$?" = "0" ]; then
|
||||
_info "Updated, sleeping 10 seconds"
|
||||
sleep 10
|
||||
#todo: check if the record takes effect
|
||||
_info "Updated, OK"
|
||||
return 0
|
||||
fi
|
||||
_err "Update error"
|
||||
@@ -75,13 +79,48 @@ dns_cf_add() {
|
||||
|
||||
}
|
||||
|
||||
#fulldomain
|
||||
#fulldomain txtvalue
|
||||
dns_cf_rm() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
_debug "First detect the root zone"
|
||||
if ! _get_root "$fulldomain"; then
|
||||
_err "invalid domain"
|
||||
return 1
|
||||
fi
|
||||
_debug _domain_id "$_domain_id"
|
||||
_debug _sub_domain "$_sub_domain"
|
||||
_debug _domain "$_domain"
|
||||
|
||||
_debug "Getting txt records"
|
||||
_cf_rest GET "zones/${_domain_id}/dns_records?type=TXT&name=$fulldomain&content=$txtvalue"
|
||||
|
||||
if ! printf "%s" "$response" | grep \"success\":true >/dev/null; then
|
||||
_err "Error"
|
||||
return 1
|
||||
fi
|
||||
|
||||
count=$(printf "%s\n" "$response" | _egrep_o "\"count\":[^,]*" | cut -d : -f 2)
|
||||
_debug count "$count"
|
||||
if [ "$count" = "0" ]; then
|
||||
_info "Don't need to remove."
|
||||
else
|
||||
record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | head -n 1)
|
||||
_debug "record_id" "$record_id"
|
||||
if [ -z "$record_id" ]; then
|
||||
_err "Can not get record id to remove."
|
||||
return 1
|
||||
fi
|
||||
if ! _cf_rest DELETE "zones/$_domain_id/dns_records/$record_id"; then
|
||||
_err "Delete record error."
|
||||
return 1
|
||||
fi
|
||||
_contains "$response" '"success":true'
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
#################### Private functions bellow ##################################
|
||||
#################### Private functions below ##################################
|
||||
#_acme-challenge.www.domain.com
|
||||
#returns
|
||||
# _sub_domain=_acme-challenge.www
|
||||
@@ -91,8 +130,9 @@ _get_root() {
|
||||
domain=$1
|
||||
i=2
|
||||
p=1
|
||||
while [ '1' ]; do
|
||||
h=$(printf $domain | cut -d . -f $i-100)
|
||||
while true; do
|
||||
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
||||
_debug h "$h"
|
||||
if [ -z "$h" ]; then
|
||||
#not valid
|
||||
return 1
|
||||
@@ -102,17 +142,17 @@ _get_root() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
if printf $response | grep \"name\":\"$h\" >/dev/null; then
|
||||
_domain_id=$(printf "%s\n" "$response" | _egrep_o \"id\":\"[^\"]*\" | head -n 1 | cut -d : -f 2 | tr -d \")
|
||||
if _contains "$response" "\"name\":\"$h\"" >/dev/null; then
|
||||
_domain_id=$(printf "%s\n" "$response" | _egrep_o "\[.\"id\":\"[^\"]*\"" | head -n 1 | cut -d : -f 2 | tr -d \")
|
||||
if [ "$_domain_id" ]; then
|
||||
_sub_domain=$(printf $domain | cut -d . -f 1-$p)
|
||||
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
|
||||
_domain=$h
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
p=$i
|
||||
i=$(expr $i + 1)
|
||||
i=$(_math "$i" + 1)
|
||||
done
|
||||
return 1
|
||||
}
|
||||
@@ -121,15 +161,15 @@ _cf_rest() {
|
||||
m=$1
|
||||
ep="$2"
|
||||
data="$3"
|
||||
_debug $ep
|
||||
_debug "$ep"
|
||||
|
||||
_H1="X-Auth-Email: $CF_Email"
|
||||
_H2="X-Auth-Key: $CF_Key"
|
||||
_H3="Content-Type: application/json"
|
||||
export _H1="X-Auth-Email: $CF_Email"
|
||||
export _H2="X-Auth-Key: $CF_Key"
|
||||
export _H3="Content-Type: application/json"
|
||||
|
||||
if [ "$data" ]; then
|
||||
if [ "$m" != "GET" ]; then
|
||||
_debug data "$data"
|
||||
response="$(_post "$data" "$CF_Api/$ep" "" $m)"
|
||||
response="$(_post "$data" "$CF_Api/$ep" "" "$m")"
|
||||
else
|
||||
response="$(_get "$CF_Api/$ep")"
|
||||
fi
|
||||
|
||||
@@ -17,24 +17,26 @@ dns_cx_add() {
|
||||
txtvalue=$2
|
||||
|
||||
if [ -z "$CX_Key" ] || [ -z "$CX_Secret" ]; then
|
||||
CX_Key=""
|
||||
CX_Secret=""
|
||||
_err "You don't specify cloudxns.com api key or secret yet."
|
||||
_err "Please create you key and try again."
|
||||
return 1
|
||||
fi
|
||||
|
||||
REST_API=$CX_Api
|
||||
REST_API="$CX_Api"
|
||||
|
||||
#save the api key and email to the account conf file.
|
||||
_saveaccountconf CX_Key "$CX_Key"
|
||||
_saveaccountconf CX_Secret "$CX_Secret"
|
||||
|
||||
_debug "First detect the root zone"
|
||||
if ! _get_root $fulldomain; then
|
||||
if ! _get_root "$fulldomain"; then
|
||||
_err "invalid domain"
|
||||
return 1
|
||||
fi
|
||||
|
||||
existing_records $_domain $_sub_domain
|
||||
existing_records "$_domain" "$_sub_domain"
|
||||
_debug count "$count"
|
||||
if [ "$?" != "0" ]; then
|
||||
_err "Error get existing records."
|
||||
@@ -42,9 +44,9 @@ dns_cx_add() {
|
||||
fi
|
||||
|
||||
if [ "$count" = "0" ]; then
|
||||
add_record $_domain $_sub_domain $txtvalue
|
||||
add_record "$_domain" "$_sub_domain" "$txtvalue"
|
||||
else
|
||||
update_record $_domain $_sub_domain $txtvalue
|
||||
update_record "$_domain" "$_sub_domain" "$txtvalue"
|
||||
fi
|
||||
|
||||
if [ "$?" = "0" ]; then
|
||||
@@ -56,7 +58,15 @@ dns_cx_add() {
|
||||
#fulldomain
|
||||
dns_cx_rm() {
|
||||
fulldomain=$1
|
||||
|
||||
REST_API="$CX_Api"
|
||||
if _get_root "$fulldomain"; then
|
||||
record_id=""
|
||||
existing_records "$_domain" "$_sub_domain"
|
||||
if ! [ "$record_id" = "" ]; then
|
||||
_rest DELETE "record/$record_id/$_domain_id" "{}"
|
||||
_info "Deleted record ${fulldomain}"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
#usage: root sub
|
||||
@@ -67,20 +77,20 @@ existing_records() {
|
||||
_debug "Getting txt records"
|
||||
root=$1
|
||||
sub=$2
|
||||
|
||||
count=0
|
||||
if ! _rest GET "record/$_domain_id?:domain_id?host_id=0&offset=0&row_num=100"; then
|
||||
return 1
|
||||
fi
|
||||
count=0
|
||||
seg=$(printf "%s\n" "$response" | _egrep_o "{[^\{]*host\":\"$_sub_domain\"[^\}]*\}")
|
||||
|
||||
seg=$(printf "%s\n" "$response" | _egrep_o '[^{]*host":"'"$_sub_domain"'"[^}]*\}')
|
||||
_debug seg "$seg"
|
||||
if [ -z "$seg" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
if printf "$response" | grep '"type":"TXT"' >/dev/null; then
|
||||
if printf "%s" "$response" | grep '"type":"TXT"' >/dev/null; then
|
||||
count=1
|
||||
record_id=$(printf "%s\n" "$seg" | _egrep_o \"record_id\":\"[^\"]*\" | cut -d : -f 2 | tr -d \")
|
||||
record_id=$(printf "%s\n" "$seg" | _egrep_o '"record_id":"[^"]*"' | cut -d : -f 2 | tr -d \" | _head_n 1)
|
||||
_debug record_id "$record_id"
|
||||
return 0
|
||||
fi
|
||||
@@ -93,7 +103,7 @@ add_record() {
|
||||
root=$1
|
||||
sub=$2
|
||||
txtvalue=$3
|
||||
fulldomain=$sub.$root
|
||||
fulldomain="$sub.$root"
|
||||
|
||||
_info "Adding record"
|
||||
|
||||
@@ -110,7 +120,7 @@ update_record() {
|
||||
root=$1
|
||||
sub=$2
|
||||
txtvalue=$3
|
||||
fulldomain=$sub.$root
|
||||
fulldomain="$sub.$root"
|
||||
|
||||
_info "Updating record"
|
||||
|
||||
@@ -121,7 +131,7 @@ update_record() {
|
||||
return 1
|
||||
}
|
||||
|
||||
#################### Private functions bellow ##################################
|
||||
#################### Private functions below ##################################
|
||||
#_acme-challenge.www.domain.com
|
||||
#returns
|
||||
# _sub_domain=_acme-challenge.www
|
||||
@@ -136,30 +146,30 @@ _get_root() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
while [ '1' ]; do
|
||||
h=$(printf $domain | cut -d . -f $i-100)
|
||||
while true; do
|
||||
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
||||
_debug h "$h"
|
||||
if [ -z "$h" ]; then
|
||||
#not valid
|
||||
return 1
|
||||
fi
|
||||
|
||||
if printf "$response" | grep "$h." >/dev/null; then
|
||||
seg=$(printf "%s" "$response" | _egrep_o "\{[^\{]*\"$h\.\"[^\}]*\}")
|
||||
if _contains "$response" "$h."; then
|
||||
seg=$(printf "%s\n" "$response" | _egrep_o '[^{]*"'"$h"'."[^}]*}')
|
||||
_debug seg "$seg"
|
||||
_domain_id=$(printf "%s" "$seg" | _egrep_o \"id\":\"[^\"]*\" | cut -d : -f 2 | tr -d \")
|
||||
_domain_id=$(printf "%s\n" "$seg" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \")
|
||||
_debug _domain_id "$_domain_id"
|
||||
if [ "$_domain_id" ]; then
|
||||
_sub_domain=$(printf $domain | cut -d . -f 1-$p)
|
||||
_debug _sub_domain $_sub_domain
|
||||
_domain=$h
|
||||
_debug _domain $_domain
|
||||
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
|
||||
_debug _sub_domain "$_sub_domain"
|
||||
_domain="$h"
|
||||
_debug _domain "$_domain"
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
p=$i
|
||||
i=$(expr $i + 1)
|
||||
p="$i"
|
||||
i=$(_math "$i" + 1)
|
||||
done
|
||||
return 1
|
||||
}
|
||||
@@ -168,7 +178,7 @@ _get_root() {
|
||||
_rest() {
|
||||
m=$1
|
||||
ep="$2"
|
||||
_debug $ep
|
||||
_debug ep "$ep"
|
||||
url="$REST_API/$ep"
|
||||
_debug url "$url"
|
||||
|
||||
@@ -180,16 +190,16 @@ _rest() {
|
||||
|
||||
sec="$CX_Key$url$data$cdate$CX_Secret"
|
||||
_debug sec "$sec"
|
||||
hmac=$(printf "$sec" | openssl md5 | cut -d " " -f 2)
|
||||
hmac=$(printf "%s" "$sec" | _digest md5 hex)
|
||||
_debug hmac "$hmac"
|
||||
|
||||
_H1="API-KEY: $CX_Key"
|
||||
_H2="API-REQUEST-DATE: $cdate"
|
||||
_H3="API-HMAC: $hmac"
|
||||
_H4="Content-Type: application/json"
|
||||
export _H1="API-KEY: $CX_Key"
|
||||
export _H2="API-REQUEST-DATE: $cdate"
|
||||
export _H3="API-HMAC: $hmac"
|
||||
export _H4="Content-Type: application/json"
|
||||
|
||||
if [ "$data" ]; then
|
||||
response="$(_post "$data" "$url" "" $m)"
|
||||
response="$(_post "$data" "$url" "" "$m")"
|
||||
else
|
||||
response="$(_get "$url")"
|
||||
fi
|
||||
@@ -199,7 +209,7 @@ _rest() {
|
||||
return 1
|
||||
fi
|
||||
_debug2 response "$response"
|
||||
if ! printf "$response" | grep '"message":"success"' >/dev/null; then
|
||||
if ! _contains "$response" '"message":"success"'; then
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
|
||||
@@ -6,9 +6,8 @@
|
||||
#
|
||||
#DP_Key="sADDsdasdgdsf"
|
||||
|
||||
DP_Api="https://dnsapi.cn"
|
||||
REST_API="https://dnsapi.cn"
|
||||
|
||||
#REST_API
|
||||
######## Public functions #####################
|
||||
|
||||
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
@@ -17,24 +16,24 @@ dns_dp_add() {
|
||||
txtvalue=$2
|
||||
|
||||
if [ -z "$DP_Id" ] || [ -z "$DP_Key" ]; then
|
||||
DP_Id=""
|
||||
DP_Key=""
|
||||
_err "You don't specify dnspod api key and key id yet."
|
||||
_err "Please create you key and try again."
|
||||
return 1
|
||||
fi
|
||||
|
||||
REST_API=$DP_Api
|
||||
|
||||
#save the api key and email to the account conf file.
|
||||
_saveaccountconf DP_Id "$DP_Id"
|
||||
_saveaccountconf DP_Key "$DP_Key"
|
||||
|
||||
_debug "First detect the root zone"
|
||||
if ! _get_root $fulldomain; then
|
||||
if ! _get_root "$fulldomain"; then
|
||||
_err "invalid domain"
|
||||
return 1
|
||||
fi
|
||||
|
||||
existing_records $_domain $_sub_domain
|
||||
existing_records "$_domain" "$_sub_domain"
|
||||
_debug count "$count"
|
||||
if [ "$?" != "0" ]; then
|
||||
_err "Error get existing records."
|
||||
@@ -42,15 +41,45 @@ dns_dp_add() {
|
||||
fi
|
||||
|
||||
if [ "$count" = "0" ]; then
|
||||
add_record $_domain $_sub_domain $txtvalue
|
||||
add_record "$_domain" "$_sub_domain" "$txtvalue"
|
||||
else
|
||||
update_record $_domain $_sub_domain $txtvalue
|
||||
update_record "$_domain" "$_sub_domain" "$txtvalue"
|
||||
fi
|
||||
}
|
||||
|
||||
#fulldomain
|
||||
#fulldomain txtvalue
|
||||
dns_dp_rm() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
_debug "First detect the root zone"
|
||||
if ! _get_root "$fulldomain"; then
|
||||
_err "invalid domain"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! _rest POST "Record.List" "login_token=$DP_Id,$DP_Key&format=json&domain_id=$_domain_id&sub_domain=$_sub_domain"; then
|
||||
_err "Record.Lis error."
|
||||
return 1
|
||||
fi
|
||||
|
||||
if _contains "$response" 'No records'; then
|
||||
_info "Don't need to remove."
|
||||
return 0
|
||||
fi
|
||||
|
||||
record_id=$(echo "$response" | _egrep_o '{[^{]*"value":"'"$txtvalue"'"' | cut -d , -f 1 | cut -d : -f 2 | tr -d \")
|
||||
_debug record_id "$record_id"
|
||||
if [ -z "$record_id" ]; then
|
||||
_err "Can not get record id."
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! _rest POST "Record.Remove" "login_token=$DP_Id,$DP_Key&format=json&domain_id=$_domain_id&record_id=$record_id"; then
|
||||
_err "Record.Remove error."
|
||||
return 1
|
||||
fi
|
||||
|
||||
_contains "$response" "Action completed successful"
|
||||
|
||||
}
|
||||
|
||||
@@ -67,14 +96,15 @@ existing_records() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
if printf "$response" | grep 'No records'; then
|
||||
if _contains "$response" 'No records'; then
|
||||
count=0
|
||||
return 0
|
||||
fi
|
||||
|
||||
if printf "$response" | grep "Action completed successful" >/dev/null; then
|
||||
count=$(printf "$response" | grep '<type>TXT</type>' | wc -l)
|
||||
record_id=$(printf "$response" | grep '^<id>' | tail -1 | cut -d '>' -f 2 | cut -d '<' -f 1)
|
||||
if _contains "$response" "Action completed successful"; then
|
||||
count=$(printf "%s" "$response" | grep -c '<type>TXT</type>' | tr -d ' ')
|
||||
record_id=$(printf "%s" "$response" | grep '^<id>' | tail -1 | cut -d '>' -f 2 | cut -d '<' -f 1)
|
||||
_debug record_id "$record_id"
|
||||
return 0
|
||||
else
|
||||
_err "get existing records error."
|
||||
@@ -90,7 +120,7 @@ add_record() {
|
||||
root=$1
|
||||
sub=$2
|
||||
txtvalue=$3
|
||||
fulldomain=$sub.$root
|
||||
fulldomain="$sub.$root"
|
||||
|
||||
_info "Adding record"
|
||||
|
||||
@@ -98,7 +128,7 @@ add_record() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
if printf "$response" | grep "Action completed successful"; then
|
||||
if _contains "$response" "Action completed successful"; then
|
||||
|
||||
return 0
|
||||
fi
|
||||
@@ -112,7 +142,7 @@ update_record() {
|
||||
root=$1
|
||||
sub=$2
|
||||
txtvalue=$3
|
||||
fulldomain=$sub.$root
|
||||
fulldomain="$sub.$root"
|
||||
|
||||
_info "Updating record"
|
||||
|
||||
@@ -120,7 +150,7 @@ update_record() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
if printf "$response" | grep "Action completed successful"; then
|
||||
if _contains "$response" "Action completed successful"; then
|
||||
|
||||
return 0
|
||||
fi
|
||||
@@ -128,7 +158,7 @@ update_record() {
|
||||
return 1 #error
|
||||
}
|
||||
|
||||
#################### Private functions bellow ##################################
|
||||
#################### Private functions below ##################################
|
||||
#_acme-challenge.www.domain.com
|
||||
#returns
|
||||
# _sub_domain=_acme-challenge.www
|
||||
@@ -138,8 +168,8 @@ _get_root() {
|
||||
domain=$1
|
||||
i=2
|
||||
p=1
|
||||
while [ '1' ]; do
|
||||
h=$(printf $domain | cut -d . -f $i-100)
|
||||
while true; do
|
||||
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
||||
if [ -z "$h" ]; then
|
||||
#not valid
|
||||
return 1
|
||||
@@ -149,39 +179,39 @@ _get_root() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
if printf "$response" | grep "Action completed successful" >/dev/null; then
|
||||
_domain_id=$(printf "%s\n" "$response" | _egrep_o \"id\":\"[^\"]*\" | cut -d : -f 2 | tr -d \")
|
||||
if _contains "$response" "Action completed successful"; then
|
||||
_domain_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \")
|
||||
_debug _domain_id "$_domain_id"
|
||||
if [ "$_domain_id" ]; then
|
||||
_sub_domain=$(printf $domain | cut -d . -f 1-$p)
|
||||
_debug _sub_domain $_sub_domain
|
||||
_domain=$h
|
||||
_debug _domain $_domain
|
||||
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
|
||||
_debug _sub_domain "$_sub_domain"
|
||||
_domain="$h"
|
||||
_debug _domain "$_domain"
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
p=$i
|
||||
i=$(expr $i + 1)
|
||||
p="$i"
|
||||
i=$(_math "$i" + 1)
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
#Usage: method URI data
|
||||
_rest() {
|
||||
m=$1
|
||||
m="$1"
|
||||
ep="$2"
|
||||
data="$3"
|
||||
_debug $ep
|
||||
_debug "$ep"
|
||||
url="$REST_API/$ep"
|
||||
|
||||
_debug url "$url"
|
||||
|
||||
if [ "$data" ]; then
|
||||
_debug2 data "$data"
|
||||
response="$(_post $data "$url")"
|
||||
if [ "$m" = "GET" ]; then
|
||||
response="$(_get "$url" | tr -d '\r')"
|
||||
else
|
||||
response="$(_get "$url")"
|
||||
_debug2 data "$data"
|
||||
response="$(_post "$data" "$url" | tr -d '\r')"
|
||||
fi
|
||||
|
||||
if [ "$?" != "0" ]; then
|
||||
|
||||
@@ -16,6 +16,8 @@ dns_gd_add() {
|
||||
txtvalue=$2
|
||||
|
||||
if [ -z "$GD_Key" ] || [ -z "$GD_Secret" ]; then
|
||||
GD_Key=""
|
||||
GD_Secret=""
|
||||
_err "You don't specify godaddy api key and secret yet."
|
||||
_err "Please create you key and try again."
|
||||
return 1
|
||||
@@ -26,11 +28,11 @@ dns_gd_add() {
|
||||
_saveaccountconf GD_Secret "$GD_Secret"
|
||||
|
||||
_debug "First detect the root zone"
|
||||
if ! _get_root $fulldomain; then
|
||||
if ! _get_root "$fulldomain"; then
|
||||
_err "invalid domain"
|
||||
return 1
|
||||
fi
|
||||
_debug _domain_id "$_domain_id"
|
||||
|
||||
_debug _sub_domain "$_sub_domain"
|
||||
_debug _domain "$_domain"
|
||||
|
||||
@@ -57,18 +59,17 @@ dns_gd_rm() {
|
||||
|
||||
}
|
||||
|
||||
#################### Private functions bellow ##################################
|
||||
#################### Private functions below ##################################
|
||||
#_acme-challenge.www.domain.com
|
||||
#returns
|
||||
# _sub_domain=_acme-challenge.www
|
||||
# _domain=domain.com
|
||||
# _domain_id=sdjkglgdfewsdfg
|
||||
_get_root() {
|
||||
domain=$1
|
||||
i=2
|
||||
p=1
|
||||
while [ '1' ]; do
|
||||
h=$(printf $domain | cut -d . -f $i-100)
|
||||
while true; do
|
||||
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
||||
if [ -z "$h" ]; then
|
||||
#not valid
|
||||
return 1
|
||||
@@ -78,15 +79,15 @@ _get_root() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
if printf "$response" | grep '"code":"NOT_FOUND"' >/dev/null; then
|
||||
if _contains "$response" '"code":"NOT_FOUND"'; then
|
||||
_debug "$h not found"
|
||||
else
|
||||
_sub_domain=$(printf $domain | cut -d . -f 1-$p)
|
||||
_domain=$h
|
||||
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
|
||||
_domain="$h"
|
||||
return 0
|
||||
fi
|
||||
p=$i
|
||||
i=$(expr $i + 1)
|
||||
p="$i"
|
||||
i=$(_math "$i" + 1)
|
||||
done
|
||||
return 1
|
||||
}
|
||||
@@ -95,14 +96,14 @@ _gd_rest() {
|
||||
m=$1
|
||||
ep="$2"
|
||||
data="$3"
|
||||
_debug $ep
|
||||
_debug "$ep"
|
||||
|
||||
_H1="Authorization: sso-key $GD_Key:$GD_Secret"
|
||||
_H2="Content-Type: application/json"
|
||||
export _H1="Authorization: sso-key $GD_Key:$GD_Secret"
|
||||
export _H2="Content-Type: application/json"
|
||||
|
||||
if [ "$data" ]; then
|
||||
_debug data "$data"
|
||||
response="$(_post "$data" "$GD_Api/$ep" "" $m)"
|
||||
response="$(_post "$data" "$GD_Api/$ep" "" "$m")"
|
||||
else
|
||||
response="$(_get "$GD_Api/$ep")"
|
||||
fi
|
||||
|
||||
177
dnsapi/dns_ispconfig.sh
Executable file
177
dnsapi/dns_ispconfig.sh
Executable file
@@ -0,0 +1,177 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
# ISPConfig 3.1 API
|
||||
# User must provide login data and URL to the ISPConfig installation incl. port. The remote user in ISPConfig must have access to:
|
||||
# - DNS zone Functions
|
||||
# - DNS txt Functions
|
||||
|
||||
# Report bugs to https://github.com/sjau/acme.sh
|
||||
|
||||
# Values to export:
|
||||
# export ISPC_User="remoteUser"
|
||||
# export ISPC_Password="remotePassword"
|
||||
# export ISPC_Api="https://ispc.domain.tld:8080/remote/json.php"
|
||||
# export ISPC_Api_Insecure=1 # Set 1 for insecure and 0 for secure -> difference is whether ssl cert is checked for validity (0) or whether it is just accepted (1)
|
||||
|
||||
######## Public functions #####################
|
||||
|
||||
#Usage: dns_myapi_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
dns_ispconfig_add() {
|
||||
fulldomain="${1}"
|
||||
txtvalue="${2}"
|
||||
_debug "Calling: dns_ispconfig_add() '${fulldomain}' '${txtvalue}'"
|
||||
_ISPC_credentials && _ISPC_login && _ISPC_getZoneInfo && _ISPC_addTxt
|
||||
}
|
||||
|
||||
#Usage: dns_myapi_rm _acme-challenge.www.domain.com
|
||||
dns_ispconfig_rm() {
|
||||
fulldomain="${1}"
|
||||
_debug "Calling: dns_ispconfig_rm() '${fulldomain}'"
|
||||
_ISPC_credentials && _ISPC_login && _ISPC_rmTxt
|
||||
}
|
||||
|
||||
#################### Private functions below ##################################
|
||||
|
||||
_ISPC_credentials() {
|
||||
if [ -z "${ISPC_User}" ] || [ -z "$ISPC_Password" ] || [ -z "${ISPC_Api}" ] || [ -z "${ISPC_Api_Insecure}" ]; then
|
||||
ISPC_User=""
|
||||
ISPC_Password=""
|
||||
ISPC_Api=""
|
||||
ISPC_Api_Insecure=""
|
||||
_err "You haven't specified the ISPConfig Login data, URL and whether you want check the ISPC SSL cert. Please try again."
|
||||
return 1
|
||||
else
|
||||
_saveaccountconf ISPC_User "${ISPC_User}"
|
||||
_saveaccountconf ISPC_Password "${ISPC_Password}"
|
||||
_saveaccountconf ISPC_Api "${ISPC_Api}"
|
||||
_saveaccountconf ISPC_Api_Insecure "${ISPC_Api_Insecure}"
|
||||
# Set whether curl should use secure or insecure mode
|
||||
export HTTPS_INSECURE="${ISPC_Api_Insecure}"
|
||||
fi
|
||||
}
|
||||
|
||||
_ISPC_login() {
|
||||
_info "Getting Session ID"
|
||||
curData="{\"username\":\"${ISPC_User}\",\"password\":\"${ISPC_Password}\",\"client_login\":false}"
|
||||
curResult="$(_post "${curData}" "${ISPC_Api}?login")"
|
||||
_debug "Calling _ISPC_login: '${curData}' '${ISPC_Api}?login'"
|
||||
_debug "Result of _ISPC_login: '$curResult'"
|
||||
if _contains "${curResult}" '"code":"ok"'; then
|
||||
sessionID=$(echo "${curResult}" | _egrep_o "response.*" | cut -d ':' -f 2 | cut -d '"' -f 2)
|
||||
_info "Retrieved Session ID."
|
||||
_debug "Session ID: '${sessionID}'"
|
||||
else
|
||||
_err "Couldn't retrieve the Session ID."
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
_ISPC_getZoneInfo() {
|
||||
_info "Getting Zoneinfo"
|
||||
zoneEnd=false
|
||||
curZone="${fulldomain}"
|
||||
while [ "${zoneEnd}" = false ]; do
|
||||
# we can strip the first part of the fulldomain, since it's just the _acme-challenge string
|
||||
curZone="${curZone#*.}"
|
||||
# suffix . needed for zone -> domain.tld.
|
||||
curData="{\"session_id\":\"${sessionID}\",\"primary_id\":{\"origin\":\"${curZone}.\"}}"
|
||||
curResult="$(_post "${curData}" "${ISPC_Api}?dns_zone_get")"
|
||||
_debug "Calling _ISPC_getZoneInfo: '${curData}' '${ISPC_Api}?login'"
|
||||
_debug "Result of _ISPC_getZoneInfo: '$curResult'"
|
||||
if _contains "${curResult}" '"id":"'; then
|
||||
zoneFound=true
|
||||
zoneEnd=true
|
||||
_info "Retrieved zone data."
|
||||
_debug "Zone data: '${curResult}'"
|
||||
fi
|
||||
if [ "${curZone#*.}" != "$curZone" ]; then
|
||||
_debug2 "$curZone still contains a '.' - so we can check next higher level"
|
||||
else
|
||||
zoneEnd=true
|
||||
_err "Couldn't retrieve zone data."
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
if [ "${zoneFound}" ]; then
|
||||
server_id=$(echo "${curResult}" | _egrep_o "server_id.*" | cut -d ':' -f 2 | cut -d '"' -f 2)
|
||||
_debug "Server ID: '${server_id}'"
|
||||
case "${server_id}" in
|
||||
'' | *[!0-9]*)
|
||||
_err "Server ID is not numeric."
|
||||
return 1
|
||||
;;
|
||||
*) _info "Retrieved Server ID" ;;
|
||||
esac
|
||||
zone=$(echo "${curResult}" | _egrep_o "\"id.*" | cut -d ':' -f 2 | cut -d '"' -f 2)
|
||||
_debug "Zone: '${zone}'"
|
||||
case "${zone}" in
|
||||
'' | *[!0-9]*)
|
||||
_err "Zone ID is not numeric."
|
||||
return 1
|
||||
;;
|
||||
*) _info "Retrieved Zone ID" ;;
|
||||
esac
|
||||
client_id=$(echo "${curResult}" | _egrep_o "sys_userid.*" | cut -d ':' -f 2 | cut -d '"' -f 2)
|
||||
_debug "Client ID: '${client_id}'"
|
||||
case "${client_id}" in
|
||||
'' | *[!0-9]*)
|
||||
_err "Client ID is not numeric."
|
||||
return 1
|
||||
;;
|
||||
*) _info "Retrieved Client ID." ;;
|
||||
esac
|
||||
zoneFound=""
|
||||
zoneEnd=""
|
||||
fi
|
||||
}
|
||||
|
||||
_ISPC_addTxt() {
|
||||
curSerial="$(date +%s)"
|
||||
curStamp="$(date +'%F %T')"
|
||||
params="\"server_id\":\"${server_id}\",\"zone\":\"${zone}\",\"name\":\"${fulldomain}.\",\"type\":\"txt\",\"data\":\"${txtvalue}\",\"aux\":\"0\",\"ttl\":\"3600\",\"active\":\"y\",\"stamp\":\"${curStamp}\",\"serial\":\"${curSerial}\""
|
||||
curData="{\"session_id\":\"${sessionID}\",\"client_id\":\"${client_id}\",\"params\":{${params}}}"
|
||||
curResult="$(_post "${curData}" "${ISPC_Api}?dns_txt_add")"
|
||||
_debug "Calling _ISPC_addTxt: '${curData}' '${ISPC_Api}?dns_txt_add'"
|
||||
_debug "Result of _ISPC_addTxt: '$curResult'"
|
||||
record_id=$(echo "${curResult}" | _egrep_o "\"response.*" | cut -d ':' -f 2 | cut -d '"' -f 2)
|
||||
_debug "Record ID: '${record_id}'"
|
||||
case "${record_id}" in
|
||||
'' | *[!0-9]*)
|
||||
_err "Couldn't add ACME Challenge TXT record to zone."
|
||||
return 1
|
||||
;;
|
||||
*) _info "Added ACME Challenge TXT record to zone." ;;
|
||||
esac
|
||||
}
|
||||
|
||||
_ISPC_rmTxt() {
|
||||
# Need to get the record ID.
|
||||
curData="{\"session_id\":\"${sessionID}\",\"primary_id\":{\"name\":\"${fulldomain}.\",\"type\":\"TXT\"}}"
|
||||
curResult="$(_post "${curData}" "${ISPC_Api}?dns_txt_get")"
|
||||
_debug "Calling _ISPC_rmTxt: '${curData}' '${ISPC_Api}?dns_txt_get'"
|
||||
_debug "Result of _ISPC_rmTxt: '$curResult'"
|
||||
if _contains "${curResult}" '"code":"ok"'; then
|
||||
record_id=$(echo "${curResult}" | _egrep_o "\"id.*" | cut -d ':' -f 2 | cut -d '"' -f 2)
|
||||
_debug "Record ID: '${record_id}'"
|
||||
case "${record_id}" in
|
||||
'' | *[!0-9]*)
|
||||
_err "Record ID is not numeric."
|
||||
return 1
|
||||
;;
|
||||
*)
|
||||
unset IFS
|
||||
_info "Retrieved Record ID."
|
||||
curData="{\"session_id\":\"${sessionID}\",\"primary_id\":\"${record_id}\"}"
|
||||
curResult="$(_post "${curData}" "${ISPC_Api}?dns_txt_delete")"
|
||||
_debug "Calling _ISPC_rmTxt: '${curData}' '${ISPC_Api}?dns_txt_delete'"
|
||||
_debug "Result of _ISPC_rmTxt: '$curResult'"
|
||||
if _contains "${curResult}" '"code":"ok"'; then
|
||||
_info "Removed ACME Challenge TXT record from zone."
|
||||
else
|
||||
_err "Couldn't remove ACME Challenge TXT record from zone."
|
||||
return 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
# dns api wrapper of lexicon for acme.sh
|
||||
|
||||
lexicon_url="https://github.com/AnalogJ/lexicon"
|
||||
# https://github.com/AnalogJ/lexicon
|
||||
lexicon_cmd="lexicon"
|
||||
|
||||
wiki="https://github.com/Neilpang/acme.sh/wiki/How-to-use-lexicon-dns-api"
|
||||
@@ -14,14 +14,15 @@ dns_lexicon_add() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
|
||||
domain=$(printf "$fulldomain" | cut -d . -f 2-999)
|
||||
domain=$(printf "%s" "$fulldomain" | cut -d . -f 2-999)
|
||||
|
||||
if ! _exists $lexicon_cmd; then
|
||||
if ! _exists "$lexicon_cmd"; then
|
||||
_err "Please install $lexicon_cmd first: $wiki"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ -z "$PROVIDER" ]; then
|
||||
PROVIDER=""
|
||||
_err "Please define env PROVIDER first: $wiki"
|
||||
return 1
|
||||
fi
|
||||
@@ -29,39 +30,44 @@ dns_lexicon_add() {
|
||||
_savedomainconf PROVIDER "$PROVIDER"
|
||||
export PROVIDER
|
||||
|
||||
Lx_name=$(echo LEXICON_${PROVIDER}_USERNAME | tr [a-z] [A-Z])
|
||||
eval Lx_name_v="\$$Lx_name"
|
||||
# e.g. busybox-ash does not know [:upper:]
|
||||
# shellcheck disable=SC2018,SC2019
|
||||
Lx_name=$(echo LEXICON_"${PROVIDER}"_USERNAME | tr 'a-z' 'A-Z')
|
||||
Lx_name_v=$(eval echo \$"$Lx_name")
|
||||
_debug "$Lx_name" "$Lx_name_v"
|
||||
if [ "$Lx_name_v" ]; then
|
||||
_saveaccountconf $Lx_name "$Lx_name_v"
|
||||
export "$Lx_name"
|
||||
_saveaccountconf "$Lx_name" "$Lx_name_v"
|
||||
eval export "$Lx_name"
|
||||
fi
|
||||
|
||||
Lx_token=$(echo LEXICON_${PROVIDER}_TOKEN | tr [a-z] [A-Z])
|
||||
eval Lx_token_v="\$$Lx_token"
|
||||
# shellcheck disable=SC2018,SC2019
|
||||
Lx_token=$(echo LEXICON_"${PROVIDER}"_TOKEN | tr 'a-z' 'A-Z')
|
||||
Lx_token_v=$(eval echo \$"$Lx_token")
|
||||
_debug "$Lx_token" "$Lx_token_v"
|
||||
if [ "$Lx_token_v" ]; then
|
||||
_saveaccountconf $Lx_token "$Lx_token_v"
|
||||
export "$Lx_token"
|
||||
_saveaccountconf "$Lx_token" "$Lx_token_v"
|
||||
eval export "$Lx_token"
|
||||
fi
|
||||
|
||||
Lx_password=$(echo LEXICON_${PROVIDER}_PASSWORD | tr [a-z] [A-Z])
|
||||
eval Lx_password_v="\$$Lx_password"
|
||||
# shellcheck disable=SC2018,SC2019
|
||||
Lx_password=$(echo LEXICON_"${PROVIDER}"_PASSWORD | tr 'a-z' 'A-Z')
|
||||
Lx_password_v=$(eval echo \$"$Lx_password")
|
||||
_debug "$Lx_password" "$Lx_password_v"
|
||||
if [ "$Lx_password_v" ]; then
|
||||
_saveaccountconf $Lx_password "$Lx_password_v"
|
||||
export "$Lx_password"
|
||||
_saveaccountconf "$Lx_password" "$Lx_password_v"
|
||||
eval export "$Lx_password"
|
||||
fi
|
||||
|
||||
Lx_domaintoken=$(echo LEXICON_${PROVIDER}_DOMAINTOKEN | tr [a-z] [A-Z])
|
||||
eval Lx_domaintoken_v="\$$Lx_domaintoken"
|
||||
# shellcheck disable=SC2018,SC2019
|
||||
Lx_domaintoken=$(echo LEXICON_"${PROVIDER}"_DOMAINTOKEN | tr 'a-z' 'A-Z')
|
||||
Lx_domaintoken_v=$(eval echo \$"$Lx_domaintoken")
|
||||
_debug "$Lx_domaintoken" "$Lx_domaintoken_v"
|
||||
if [ "$Lx_domaintoken_v" ]; then
|
||||
export "$Lx_domaintoken"
|
||||
_saveaccountconf $Lx_domaintoken "$Lx_domaintoken_v"
|
||||
eval export "$Lx_domaintoken"
|
||||
_saveaccountconf "$Lx_domaintoken" "$Lx_domaintoken_v"
|
||||
fi
|
||||
|
||||
$lexicon_cmd "$PROVIDER" create ${domain} TXT --name="_acme-challenge.${domain}." --content="${txtvalue}"
|
||||
$lexicon_cmd "$PROVIDER" create "${domain}" TXT --name="_acme-challenge.${domain}." --content="${txtvalue}"
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#LUA_Email="user@luadns.net"
|
||||
|
||||
LUA_Api="https://api.luadns.com/v1"
|
||||
LUA_auth=$(printf $LUA_Email:$LUA_Key | _base64)
|
||||
LUA_auth=$(printf "%s" "$LUA_Email:$LUA_Key" | _base64)
|
||||
|
||||
######## Public functions #####################
|
||||
|
||||
@@ -18,6 +18,8 @@ dns_lua_add() {
|
||||
txtvalue=$2
|
||||
|
||||
if [ -z "$LUA_Key" ] || [ -z "$LUA_Email" ]; then
|
||||
LUA_Key=""
|
||||
LUA_Email=""
|
||||
_err "You don't specify luadns api key and email yet."
|
||||
_err "Please create you key and try again."
|
||||
return 1
|
||||
@@ -28,7 +30,7 @@ dns_lua_add() {
|
||||
_saveaccountconf LUA_Email "$LUA_Email"
|
||||
|
||||
_debug "First detect the root zone"
|
||||
if ! _get_root $fulldomain; then
|
||||
if ! _get_root "$fulldomain"; then
|
||||
_err "invalid domain"
|
||||
return 1
|
||||
fi
|
||||
@@ -39,17 +41,17 @@ dns_lua_add() {
|
||||
_debug "Getting txt records"
|
||||
_LUA_rest GET "zones/${_domain_id}/records"
|
||||
|
||||
if ! printf "$response" | grep \"id\": >/dev/null; then
|
||||
if ! _contains "$response" "\"id\":"; then
|
||||
_err "Error"
|
||||
return 1
|
||||
fi
|
||||
|
||||
count=$(printf "%s\n" "$response" | _egrep_o \"name\":\"$fulldomain\" | wc -l)
|
||||
count=$(printf "%s\n" "$response" | _egrep_o "\"name\":\"$fulldomain\"" | wc -l)
|
||||
_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 printf -- "%s" "$response" | grep "$fulldomain" >/dev/null; then
|
||||
_info "Added"
|
||||
#todo: check if the record takes effect
|
||||
return 0
|
||||
@@ -61,8 +63,8 @@ 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)
|
||||
_debug "record_id" $record_id
|
||||
record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[^,]*,\"name\":\"$fulldomain.\",\"type\":\"TXT\"" | 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
|
||||
@@ -82,7 +84,7 @@ dns_lua_rm() {
|
||||
|
||||
}
|
||||
|
||||
#################### Private functions bellow ##################################
|
||||
#################### Private functions below ##################################
|
||||
#_acme-challenge.www.domain.com
|
||||
#returns
|
||||
# _sub_domain=_acme-challenge.www
|
||||
@@ -95,24 +97,24 @@ _get_root() {
|
||||
if ! _LUA_rest GET "zones"; then
|
||||
return 1
|
||||
fi
|
||||
while [ '1' ]; do
|
||||
h=$(printf $domain | cut -d . -f $i-100)
|
||||
while true; do
|
||||
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
||||
if [ -z "$h" ]; then
|
||||
#not valid
|
||||
return 1
|
||||
fi
|
||||
|
||||
if printf $response | grep \"name\":\"$h\" >/dev/null; then
|
||||
_domain_id=$(printf "%s\n" "$response" | _egrep_o \"id\":[^,]*,\"name\":\"$h\" | cut -d : -f 2 | cut -d , -f 1)
|
||||
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)
|
||||
if [ "$_domain_id" ]; then
|
||||
_sub_domain=$(printf $domain | cut -d . -f 1-$p)
|
||||
_domain=$h
|
||||
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
|
||||
_domain="$h"
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
p=$i
|
||||
i=$(expr $i + 1)
|
||||
i=$(_math "$i" + 1)
|
||||
done
|
||||
return 1
|
||||
}
|
||||
@@ -121,13 +123,13 @@ _LUA_rest() {
|
||||
m=$1
|
||||
ep="$2"
|
||||
data="$3"
|
||||
_debug $ep
|
||||
_debug "$ep"
|
||||
|
||||
_H1="Accept: application/json"
|
||||
_H2="Authorization: Basic $LUA_auth"
|
||||
export _H1="Accept: application/json"
|
||||
export _H2="Authorization: Basic $LUA_auth"
|
||||
if [ "$data" ]; then
|
||||
_debug data "$data"
|
||||
response="$(_post "$data" "$LUA_Api/$ep" "" $m)"
|
||||
response="$(_post "$data" "$LUA_Api/$ep" "" "$m")"
|
||||
else
|
||||
response="$(_get "$LUA_Api/$ep")"
|
||||
fi
|
||||
|
||||
@@ -15,6 +15,8 @@ dns_me_add() {
|
||||
txtvalue=$2
|
||||
|
||||
if [ -z "$ME_Key" ] || [ -z "$ME_Secret" ]; then
|
||||
ME_Key=""
|
||||
ME_Secret=""
|
||||
_err "You didn't specify DNSMadeEasy api key and secret yet."
|
||||
_err "Please create you key and try again."
|
||||
return 1
|
||||
@@ -25,7 +27,7 @@ dns_me_add() {
|
||||
_saveaccountconf ME_Secret "$ME_Secret"
|
||||
|
||||
_debug "First detect the root zone"
|
||||
if ! _get_root $fulldomain; then
|
||||
if ! _get_root "$fulldomain"; then
|
||||
_err "invalid domain"
|
||||
return 1
|
||||
fi
|
||||
@@ -36,12 +38,12 @@ dns_me_add() {
|
||||
_debug "Getting txt records"
|
||||
_me_rest GET "${_domain_id}/records?recordName=$_sub_domain&type=TXT"
|
||||
|
||||
if ! printf "$response" | grep \"totalRecords\": >/dev/null; then
|
||||
if ! _contains "$response" "\"totalRecords\":"; then
|
||||
_err "Error"
|
||||
return 1
|
||||
fi
|
||||
|
||||
count=$(printf "%s\n" "$response" | _egrep_o \"totalRecords\":[^,]* | cut -d : -f 2)
|
||||
count=$(printf "%s\n" "$response" | _egrep_o "\"totalRecords\":[^,]*" | cut -d : -f 2)
|
||||
_debug count "$count"
|
||||
if [ "$count" = "0" ]; then
|
||||
_info "Adding record"
|
||||
@@ -58,8 +60,8 @@ dns_me_add() {
|
||||
_err "Add txt record error."
|
||||
else
|
||||
_info "Updating record"
|
||||
record_id=$(printf "%s\n" "$response" | _egrep_o \"id\":[^,]* | cut -d : -f 2 | head -n 1)
|
||||
_debug "record_id" $record_id
|
||||
record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[^,]*" | cut -d : -f 2 | head -n 1)
|
||||
_debug "record_id" "$record_id"
|
||||
|
||||
_me_rest PUT "$_domain_id/records/$record_id/" "{\"id\":\"$record_id\",\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"value\":\"$txtvalue\",\"gtdLocation\":\"DEFAULT\",\"ttl\":120}"
|
||||
if [ "$?" = "0" ]; then
|
||||
@@ -79,7 +81,7 @@ dns_me_rm() {
|
||||
|
||||
}
|
||||
|
||||
#################### Private functions bellow ##################################
|
||||
#################### Private functions below ##################################
|
||||
#_acme-challenge.www.domain.com
|
||||
#returns
|
||||
# _sub_domain=_acme-challenge.www
|
||||
@@ -89,8 +91,8 @@ _get_root() {
|
||||
domain=$1
|
||||
i=2
|
||||
p=1
|
||||
while [ '1' ]; do
|
||||
h=$(printf $domain | cut -d . -f $i-100)
|
||||
while true; do
|
||||
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
||||
if [ -z "$h" ]; then
|
||||
#not valid
|
||||
return 1
|
||||
@@ -100,17 +102,17 @@ _get_root() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
if printf $response | grep \"name\":\"$h\" >/dev/null; then
|
||||
_domain_id=$(printf "%s\n" "$response" | _egrep_o \"id\":[^,]* | head -n 1 | cut -d : -f 2)
|
||||
if _contains "$response" "\"name\":\"$h\""; then
|
||||
_domain_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[^,]*" | head -n 1 | cut -d : -f 2 | tr -d '}')
|
||||
if [ "$_domain_id" ]; then
|
||||
_sub_domain=$(printf $domain | cut -d . -f 1-$p)
|
||||
_domain=$h
|
||||
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
|
||||
_domain="$h"
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
p=$i
|
||||
i=$(expr $i + 1)
|
||||
i=$(_math "$i" + 1)
|
||||
done
|
||||
return 1
|
||||
}
|
||||
@@ -119,18 +121,18 @@ _me_rest() {
|
||||
m=$1
|
||||
ep="$2"
|
||||
data="$3"
|
||||
_debug $ep
|
||||
_debug "$ep"
|
||||
|
||||
cdate=$(date -u +"%a, %d %b %Y %T %Z")
|
||||
hmac=$(printf "$cdate" | _hmac sha1 "$ME_Secret" 1)
|
||||
hmac=$(printf "%s" "$cdate" | _hmac sha1 "$(_hex "$ME_Secret")" hex)
|
||||
|
||||
_H1="x-dnsme-apiKey: $ME_Key"
|
||||
_H2="x-dnsme-requestDate: $cdate"
|
||||
_H3="x-dnsme-hmac: $hmac"
|
||||
export _H1="x-dnsme-apiKey: $ME_Key"
|
||||
export _H2="x-dnsme-requestDate: $cdate"
|
||||
export _H3="x-dnsme-hmac: $hmac"
|
||||
|
||||
if [ "$data" ]; then
|
||||
_debug data "$data"
|
||||
response="$(_post "$data" "$ME_Api/$ep" "" $m)"
|
||||
response="$(_post "$data" "$ME_Api/$ep" "" "$m")"
|
||||
else
|
||||
response="$(_get "$ME_Api/$ep")"
|
||||
fi
|
||||
|
||||
@@ -5,48 +5,31 @@
|
||||
#So, here must be a method dns_myapi_add()
|
||||
#Which will be called by acme.sh to add the txt record to your api system.
|
||||
#returns 0 means success, otherwise error.
|
||||
|
||||
#
|
||||
#Author: Neilpang
|
||||
#Report Bugs here: https://github.com/Neilpang/acme.sh
|
||||
#
|
||||
######## Public functions #####################
|
||||
|
||||
#Usage: dns_myapi_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
dns_myapi_add() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
_info "Using myapi"
|
||||
_debug fulldomain "$fulldomain"
|
||||
_debug txtvalue "$txtvalue"
|
||||
_err "Not implemented!"
|
||||
return 1
|
||||
}
|
||||
|
||||
#fulldomain
|
||||
#Usage: fulldomain txtvalue
|
||||
#Remove the txt record after validation.
|
||||
dns_myapi_rm() {
|
||||
fulldomain=$1
|
||||
|
||||
txtvalue=$2
|
||||
_info "Using myapi"
|
||||
_debug fulldomain "$fulldomain"
|
||||
_debug txtvalue "$txtvalue"
|
||||
}
|
||||
|
||||
#################### Private functions bellow ##################################
|
||||
_info() {
|
||||
if [ -z "$2" ]; then
|
||||
echo "[$(date)] $1"
|
||||
else
|
||||
echo "[$(date)] $1='$2'"
|
||||
fi
|
||||
}
|
||||
|
||||
_err() {
|
||||
_info "$@" >&2
|
||||
return 1
|
||||
}
|
||||
|
||||
_debug() {
|
||||
if [ -z "$DEBUG" ]; then
|
||||
return
|
||||
fi
|
||||
_err "$@"
|
||||
return 0
|
||||
}
|
||||
|
||||
_debug2() {
|
||||
if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
|
||||
_debug "$@"
|
||||
fi
|
||||
return
|
||||
}
|
||||
#################### Private functions below ##################################
|
||||
|
||||
58
dnsapi/dns_nsupdate.sh
Executable file
58
dnsapi/dns_nsupdate.sh
Executable file
@@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
######## Public functions #####################
|
||||
|
||||
#Usage: dns_nsupdate_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
dns_nsupdate_add() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
_checkKeyFile || return 1
|
||||
[ -n "${NSUPDATE_SERVER}" ] || NSUPDATE_SERVER="localhost"
|
||||
# save the dns server and key to the account conf file.
|
||||
_saveaccountconf NSUPDATE_SERVER "${NSUPDATE_SERVER}"
|
||||
_saveaccountconf NSUPDATE_KEY "${NSUPDATE_KEY}"
|
||||
_info "adding ${fulldomain}. 60 in txt \"${txtvalue}\""
|
||||
nsupdate -k "${NSUPDATE_KEY}" <<EOF
|
||||
server ${NSUPDATE_SERVER}
|
||||
update add ${fulldomain}. 60 in txt "${txtvalue}"
|
||||
send
|
||||
EOF
|
||||
if [ $? -ne 0 ]; then
|
||||
_err "error updating domain"
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
#Usage: dns_nsupdate_rm _acme-challenge.www.domain.com
|
||||
dns_nsupdate_rm() {
|
||||
fulldomain=$1
|
||||
_checkKeyFile || return 1
|
||||
[ -n "${NSUPDATE_SERVER}" ] || NSUPDATE_SERVER="localhost"
|
||||
_info "removing ${fulldomain}. txt"
|
||||
nsupdate -k "${NSUPDATE_KEY}" <<EOF
|
||||
server ${NSUPDATE_SERVER}
|
||||
update delete ${fulldomain}. txt
|
||||
send
|
||||
EOF
|
||||
if [ $? -ne 0 ]; then
|
||||
_err "error updating domain"
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
#################### Private functions below ##################################
|
||||
|
||||
_checkKeyFile() {
|
||||
if [ -z "${NSUPDATE_KEY}" ]; then
|
||||
_err "you must specify a path to the nsupdate key file"
|
||||
return 1
|
||||
fi
|
||||
if [ ! -r "${NSUPDATE_KEY}" ]; then
|
||||
_err "key ${NSUPDATE_KEY} is unreadable"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
@@ -86,6 +86,8 @@ dns_ovh_add() {
|
||||
txtvalue=$2
|
||||
|
||||
if [ -z "$OVH_AK" ] || [ -z "$OVH_AS" ]; then
|
||||
OVH_AK=""
|
||||
OVH_AS=""
|
||||
_err "You don't specify OVH application key and application secret yet."
|
||||
_err "Please create you key and try again."
|
||||
return 1
|
||||
@@ -127,11 +129,11 @@ dns_ovh_add() {
|
||||
_info "Consumer key is ok."
|
||||
|
||||
_debug "First detect the root zone"
|
||||
if ! _get_root $fulldomain; then
|
||||
if ! _get_root "$fulldomain"; then
|
||||
_err "invalid domain"
|
||||
return 1
|
||||
fi
|
||||
_debug _domain_id "$_domain_id"
|
||||
|
||||
_debug _sub_domain "$_sub_domain"
|
||||
_debug _domain "$_domain"
|
||||
|
||||
@@ -157,7 +159,7 @@ dns_ovh_add() {
|
||||
_err "Can not get record id."
|
||||
return 1
|
||||
fi
|
||||
_debug "record_id" $record_id
|
||||
_debug "record_id" "$record_id"
|
||||
|
||||
if _ovh_rest PUT "domain/zone/$_domain/record/$record_id" "{\"target\":\"$txtvalue\",\"subDomain\":\"$_sub_domain\",\"ttl\":60}"; then
|
||||
if _contains "$response" "null"; then
|
||||
@@ -180,7 +182,7 @@ dns_ovh_rm() {
|
||||
|
||||
}
|
||||
|
||||
#################### Private functions bellow ##################################
|
||||
#################### Private functions below ##################################
|
||||
|
||||
_ovh_authentication() {
|
||||
|
||||
@@ -221,13 +223,12 @@ _ovh_authentication() {
|
||||
#returns
|
||||
# _sub_domain=_acme-challenge.www
|
||||
# _domain=domain.com
|
||||
# _domain_id=sdjkglgdfewsdfg
|
||||
_get_root() {
|
||||
domain=$1
|
||||
i=2
|
||||
p=1
|
||||
while [ '1' ]; do
|
||||
h=$(printf $domain | cut -d . -f $i-100)
|
||||
while true; do
|
||||
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
||||
if [ -z "$h" ]; then
|
||||
#not valid
|
||||
return 1
|
||||
@@ -238,12 +239,12 @@ _get_root() {
|
||||
fi
|
||||
|
||||
if ! _contains "$response" "This service does not exist" >/dev/null; then
|
||||
_sub_domain=$(printf $domain | cut -d . -f 1-$p)
|
||||
_domain=$h
|
||||
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
|
||||
_domain="$h"
|
||||
return 0
|
||||
fi
|
||||
p=$i
|
||||
i=$(expr $i + 1)
|
||||
i=$(_math "$i" + 1)
|
||||
done
|
||||
return 1
|
||||
}
|
||||
@@ -261,7 +262,7 @@ _ovh_rest() {
|
||||
m=$1
|
||||
ep="$2"
|
||||
data="$3"
|
||||
_debug $ep
|
||||
_debug "$ep"
|
||||
|
||||
_ovh_url="$OVH_API/$ep"
|
||||
_debug2 _ovh_url "$_ovh_url"
|
||||
@@ -272,15 +273,15 @@ _ovh_rest() {
|
||||
_ovh_hex="$(printf "%s" "$_ovh_p" | _digest sha1 hex)"
|
||||
_debug2 _ovh_hex "$_ovh_hex"
|
||||
|
||||
_H1="X-Ovh-Application: $OVH_AK"
|
||||
_H2="X-Ovh-Signature: \$1\$$_ovh_hex"
|
||||
export _H1="X-Ovh-Application: $OVH_AK"
|
||||
export _H2="X-Ovh-Signature: \$1\$$_ovh_hex"
|
||||
_debug2 _H2 "$_H2"
|
||||
_H3="X-Ovh-Timestamp: $_ovh_t"
|
||||
_H4="X-Ovh-Consumer: $OVH_CK"
|
||||
_H5="Content-Type: application/json;charset=utf-8"
|
||||
export _H3="X-Ovh-Timestamp: $_ovh_t"
|
||||
export _H4="X-Ovh-Consumer: $OVH_CK"
|
||||
export _H5="Content-Type: application/json;charset=utf-8"
|
||||
if [ "$data" ] || [ "$m" = "POST" ] || [ "$m" = "PUT" ]; then
|
||||
_debug data "$data"
|
||||
response="$(_post "$data" "$_ovh_url" "" $m)"
|
||||
response="$(_post "$data" "$_ovh_url" "" "$m")"
|
||||
else
|
||||
response="$(_get "$_ovh_url")"
|
||||
fi
|
||||
|
||||
@@ -12,30 +12,35 @@ DEFAULT_PDNS_TTL=60
|
||||
|
||||
######## Public functions #####################
|
||||
#Usage: add _acme-challenge.www.domain.com "123456789ABCDEF0000000000000000000000000000000000000"
|
||||
#fulldomain
|
||||
#txtvalue
|
||||
dns_pdns_add() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
|
||||
if [ -z "$PDNS_Url" ]; then
|
||||
PDNS_Url=""
|
||||
_err "You don't specify PowerDNS address."
|
||||
_err "Please set PDNS_Url and try again."
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ -z "$PDNS_ServerId" ]; then
|
||||
PDNS_ServerId=""
|
||||
_err "You don't specify PowerDNS server id."
|
||||
_err "Please set you PDNS_ServerId and try again."
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ -z "$PDNS_Token" ]; then
|
||||
PDNS_Token=""
|
||||
_err "You don't specify PowerDNS token."
|
||||
_err "Please create you PDNS_Token and try again."
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ -z "$PDNS_Ttl" ]; then
|
||||
PDNS_Ttl=$DEFAULT_PDNS_TTL
|
||||
PDNS_Ttl="$DEFAULT_PDNS_TTL"
|
||||
fi
|
||||
|
||||
#save the api addr and key to the account conf file.
|
||||
@@ -47,8 +52,8 @@ dns_pdns_add() {
|
||||
_saveaccountconf PDNS_Ttl "$PDNS_Ttl"
|
||||
fi
|
||||
|
||||
_debug "First detect the root zone"
|
||||
if ! _get_root $fulldomain; then
|
||||
_debug "Detect root zone"
|
||||
if ! _get_root "$fulldomain"; then
|
||||
_err "invalid domain"
|
||||
return 1
|
||||
fi
|
||||
@@ -65,6 +70,18 @@ dns_pdns_add() {
|
||||
dns_pdns_rm() {
|
||||
fulldomain=$1
|
||||
|
||||
_debug "Detect root zone"
|
||||
if ! _get_root "$fulldomain"; then
|
||||
_err "invalid domain"
|
||||
return 1
|
||||
fi
|
||||
_debug _domain "$_domain"
|
||||
|
||||
if ! rm_record "$_domain" "$fulldomain"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
set_record() {
|
||||
@@ -73,45 +90,73 @@ set_record() {
|
||||
full=$2
|
||||
txtvalue=$3
|
||||
|
||||
if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root." "{\"rrsets\": [{\"name\": \"$full.\", \"changetype\": \"REPLACE\", \"type\": \"TXT\", \"ttl\": $PDNS_Ttl, \"records\": [{\"name\": \"$full.\", \"type\": \"TXT\", \"content\": \"\\\"$txtvalue\\\"\", \"disabled\": false, \"ttl\": $PDNS_Ttl}]}]}"; then
|
||||
if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root." "{\"rrsets\": [{\"changetype\": \"REPLACE\", \"name\": \"$full.\", \"type\": \"TXT\", \"ttl\": $PDNS_Ttl, \"records\": [{\"name\": \"$full.\", \"type\": \"TXT\", \"content\": \"\\\"$txtvalue\\\"\", \"disabled\": false, \"ttl\": $PDNS_Ttl}]}]}"; then
|
||||
_err "Set txt record error."
|
||||
return 1
|
||||
fi
|
||||
if ! _pdns_rest "PUT" "/api/v1/servers/$PDNS_ServerId/zones/$root./notify"; then
|
||||
_err "Notify servers error."
|
||||
|
||||
if ! notify_slaves "$root"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
#################### Private functions bellow ##################################
|
||||
rm_record() {
|
||||
_info "Remove record"
|
||||
root=$1
|
||||
full=$2
|
||||
|
||||
if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root." "{\"rrsets\": [{\"changetype\": \"DELETE\", \"name\": \"$full.\", \"type\": \"TXT\"}]}"; then
|
||||
_err "Delete txt record error."
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! notify_slaves "$root"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
notify_slaves() {
|
||||
root=$1
|
||||
|
||||
if ! _pdns_rest "PUT" "/api/v1/servers/$PDNS_ServerId/zones/$root./notify"; then
|
||||
_err "Notify slaves error."
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
#################### Private functions below ##################################
|
||||
#_acme-challenge.www.domain.com
|
||||
#returns
|
||||
# _domain=domain.com
|
||||
_get_root() {
|
||||
domain=$1
|
||||
i=1
|
||||
p=1
|
||||
|
||||
if _pdns_rest "GET" "/api/v1/servers/$PDNS_ServerId/zones"; then
|
||||
_zones_response=$response
|
||||
_zones_response="$response"
|
||||
fi
|
||||
|
||||
while [ '1' ]; do
|
||||
h=$(printf $domain | cut -d . -f $i-100)
|
||||
while true; do
|
||||
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
||||
if [ -z "$h" ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if printf "$_zones_response" | grep "\"name\": \"$h.\"" >/dev/null; then
|
||||
_domain=$h
|
||||
if _contains "$_zones_response" "\"name\": \"$h.\""; then
|
||||
_domain="$h"
|
||||
return 0
|
||||
fi
|
||||
|
||||
p=$i
|
||||
i=$(expr $i + 1)
|
||||
i=$(_math $i + 1)
|
||||
done
|
||||
_debug "$domain not found"
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
@@ -120,7 +165,7 @@ _pdns_rest() {
|
||||
ep=$2
|
||||
data=$3
|
||||
|
||||
_H1="X-API-Key: $PDNS_Token"
|
||||
export _H1="X-API-Key: $PDNS_Token"
|
||||
|
||||
if [ ! "$method" = "GET" ]; then
|
||||
_debug data "$data"
|
||||
|
||||
Reference in New Issue
Block a user