Compare commits

..
0 Commits
20 changed files with 620 additions and 1733 deletions

No files matched your search

-9
View File
@@ -1,9 +0,0 @@
<!--
Do NOT send pull request to `master` branch.
Please send to `dev` branch instead.
Any PR to `master` branch will NOT be merged.
-->
+11 -54
View File
@@ -1,54 +1,11 @@
language: shell language: bash
sudo: required
env:
os: global:
- linux - SHFMT_URL=https://github.com/mvdan/sh/releases/download/v0.4.0/shfmt_v0.4.0_linux_amd64
- osx
script:
env: - curl -sSL $SHFMT_URL -o ~/shfmt
global: - chmod +x ~/shfmt
- SHFMT_URL=https://github.com/mvdan/sh/releases/download/v0.4.0/shfmt_v0.4.0_linux_amd64 - ~/shfmt -l -w -i 2 .
- git diff --exit-code || (echo "Run shfmt to fix the formatting issues" && false)
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
+98 -120
View File
@@ -1,23 +1,21 @@
# An ACME Shell script: acme.sh [![Build Status](https://travis-ci.org/Neilpang/acme.sh.svg?branch=master)](https://travis-ci.org/Neilpang/acme.sh) # An ACME Shell script: acme.sh [![Build Status](https://travis-ci.org/Neilpang/acme.sh.svg?branch=master)](https://travis-ci.org/Neilpang/acme.sh)
- An ACME protocol client written purely in Shell (Unix shell) language. - An ACME protocol client written purely in Shell (Unix shell) language.
- Full ACME protocol implementation. - Fully ACME protocol implementation.
- Simple, powerful and very easy to use. You only need 3 minutes to learn it. - Simple, powerful and very easy to use. You only need 3 minutes to learn.
- Bash, dash and sh compatible. - Bash, dash and sh compatible.
- Simplest shell script for Let's Encrypt free certificate client. - Simplest shell script for Let's Encrypt free certificate client.
- Purely written in Shell with no dependencies on python or the official Let's Encrypt 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. - Just one script, to issue, renew and install your certificates automatically.
- DOES NOT require `root/sudoer` access. - 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. 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
Wiki: https://github.com/Neilpang/acme.sh/wiki
# [中文说明](https://github.com/Neilpang/acme.sh/wiki/%E8%AF%B4%E6%98%8E) # [中文说明](https://github.com/Neilpang/acme.sh/wiki/%E8%AF%B4%E6%98%8E)
#Tested OS
# Tested OS
| NO | Status| Platform| | NO | Status| Platform|
|----|-------|---------| |----|-------|---------|
|1|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/ubuntu-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)| Ubuntu |1|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/ubuntu-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)| Ubuntu
@@ -39,41 +37,42 @@ 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) |17|-----| OpenWRT: Tested and working. See [wiki page](https://github.com/Neilpang/acme.sh/wiki/How-to-run-on-OpenWRT)
|18|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/solaris.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|SunOS/Solaris |18|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/solaris.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|SunOS/Solaris
|19|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/gentoo-stage3-amd64.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Gentoo Linux |19|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/gentoo-stage3-amd64.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Gentoo Linux
|20|[![Build Status](https://travis-ci.org/Neilpang/acme.sh.svg?branch=master)](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 https://github.com/Neilpang/acmetest
# Supported Mode
# Supported modes 1. Webroot mode
2. Standalone mode
3. Apache mode
4. Dns mode
- Webroot mode
- Standalone mode
- Apache mode
- DNS mode
# 1. How to install # 1. How to install
### 1. Install online ### 1. Install online:
Check this project: https://github.com/Neilpang/get.acme.sh Check this project: https://github.com/Neilpang/get.acme.sh
```bash ```bash
curl https://get.acme.sh | sh curl https://get.acme.sh | sh
``` ```
Or: Or:
```bash ```bash
wget -O - https://get.acme.sh | sh wget -O - https://get.acme.sh | sh
``` ```
### 2. Or, Install from git ### 2. Or, Install from git:
Clone this project and launch installation: Clone this project:
```bash ```bash
git clone https://github.com/Neilpang/acme.sh.git git clone https://github.com/Neilpang/acme.sh.git
@@ -83,14 +82,14 @@ cd ./acme.sh
You `don't have to be root` then, although `it is recommended`. 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: The installer will perform 3 actions:
1. Create and copy `acme.sh` to your home dir (`$HOME`): `~/.acme.sh/`. 1. Create and copy `acme.sh` to your home dir (`$HOME`): `~/.acme.sh/`.
All certs will be placed in this folder too. All certs will be placed in this folder.
2. Create alias for: `acme.sh=~/.acme.sh/acme.sh`. 2. Create alias for: `acme.sh=~/.acme.sh/acme.sh`.
3. Create daily cron job to check and renew the certs if needed. 3. Create everyday cron job to check and renew the cert if needed.
Cron entry example: Cron entry example:
@@ -98,17 +97,18 @@ Cron entry example:
0 0 * * * "/home/user/.acme.sh"/acme.sh --cron --home "/home/user/.acme.sh" > /dev/null 0 0 * * * "/home/user/.acme.sh"/acme.sh --cron --home "/home/user/.acme.sh" > /dev/null
``` ```
After the installation, you must close the current terminal and reopen it to make the alias take effect. After the installation, you must close current terminal and reopen again 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: Show help message:
```
root@v1:~# acme.sh -h
``` ```
# 2. Just issue a cert root@v1:~# acme.sh -h
```
# 2. Just issue a cert:
**Example 1:** Single domain. **Example 1:** Single domain.
@@ -119,59 +119,56 @@ acme.sh --issue -d example.com -w /home/wwwroot/example.com
**Example 2:** Multiple domains in the same cert. **Example 2:** Multiple domains in the same cert.
```bash ```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. 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 the cert for. Second argument **"example.com"** is the main domain you want to issue cert for.
You must have at least one domain there. You must have at least a domain there.
You must point and bind all the domains to the same webroot dir: `/home/wwwroot/example.com`. You must point and bind all the domains to the same webroot dir: `/home/wwwroot/example.com`.
Generated/issued certs will be placed in `~/.acme.sh/example.com/` Generate/issued certs will be placed in `~/.acme.sh/example.com/`
The issued cert will be renewed automatically every **60** days. The issued cert will be renewed every **60** days automatically.
More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert 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 Apache/Nginx or other servers. 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 the future. 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.
**Apache** example: **nginx** example
```bash ```bash
acme.sh --installcert -d example.com \ acme.sh --installcert -d example.com \
--certpath /path/to/certfile/in/apache/cert.pem \ --keypath /path/to/keyfile/in/nginx/key.pem \
--keypath /path/to/keyfile/in/apache/key.pem \ --fullchainpath path/to/fullchain/nginx/cert.pem \
--fullchainpath /path/to/fullchain/certfile/apache/fullchain.pem \ --reloadcmd "service nginx restart"
--reloadcmd "service apache2 force-reload"
``` ```
**Nginx** example: **apache** example
```bash ```bash
acme.sh --installcert -d example.com \ acme.sh --installcert -d example.com \
--keypath /path/to/keyfile/in/nginx/key.pem \ --certpath /path/to/certfile/in/apache/cert.pem \
--fullchainpath /path/to/fullchain/nginx/cert.pem \ --keypath /path/to/keyfile/in/apache/key.pem \
--reloadcmd "service nginx force-reload" --fullchainpath path/to/fullchain/certfile/apache/fullchain.pem \
--reloadcmd "service apache2 restart"
``` ```
Only the domain is required, all the other parameters are optional. Only the domain is required, all the other parameters are optional.
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.
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 # 4. Use Standalone server to issue cert
**(requires you to be root/sudoer or have permission to listen on port 80 (TCP))** **(requires you be root/sudoer, or you have permission to listen tcp 80 port)**
Port `80` (TCP) **MUST** be free to listen on, otherwise you will be prompted to free it and try again. The tcp `80` port **MUST** be free to listen, otherwise you will be prompted to free the `80` port and try again.
```bash ```bash
acme.sh --issue --standalone -d example.com -d www.example.com -d cp.example.com acme.sh --issue --standalone -d example.com -d www.example.com -d cp.example.com
@@ -179,14 +176,13 @@ 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 More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert
# 5. Use Standalone tls server to issue cert
# 5. Use Standalone TLS server to issue cert **(requires you be root/sudoer, or you have permission to listen tcp 443 port)**
**(requires you to be root/sudoer or have permission to listen on port 443 (TCP))**
acme.sh supports `tls-sni-01` validation. acme.sh supports `tls-sni-01` validation.
Port `443` (TCP) **MUST** be free to listen on, otherwise you will be prompted to free it and try again. The tcp `443` port **MUST** be free to listen, otherwise you will be prompted to free the `443` port and try again.
```bash ```bash
acme.sh --issue --tls -d example.com -d www.example.com -d cp.example.com acme.sh --issue --tls -d example.com -d www.example.com -d cp.example.com
@@ -194,33 +190,31 @@ 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 More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert
# 6. Use Apache mode # 6. Use Apache mode
**(requires you to be root/sudoer, since it is required to interact with Apache server)** **(requires you 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 and it will force use of apache plugin automatically. Just set string "apache" as the second argument, it will force use of apache plugin automatically.
``` ```
acme.sh --issue --apache -d example.com -d www.example.com -d cp.example.com acme.sh --issue --apache -d example.com -d www.example.com -d user.example.com
``` ```
More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert
# 7. Use DNS mode: # 7. Use DNS mode:
Support the `dns-01` challenge. Support the `dns-01` challenge.
```bash ```bash
acme.sh --issue --dns -d example.com -d www.example.com -d cp.example.com acme.sh --issue --dns -d example.com -d www.example.com -d user.example.com
``` ```
You should get an output like below: You should get the output like below:
``` ```
Add the following txt record: Add the following txt record:
@@ -232,6 +226,7 @@ Domain:_acme-challenge.www.example.com
Txt value:9ihDbjxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Txt value:9ihDbjxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Please add those txt records to the domains. Waiting for the dns to take effect. Please add those txt records to the domains. Waiting for the dns to take effect.
``` ```
Then just rerun with `renew` argument: Then just rerun with `renew` argument:
@@ -242,58 +237,52 @@ acme.sh --renew -d example.com
Ok, it's finished. Ok, it's finished.
# 8. Automatic DNS API integration # 8. Automatic DNS API integration
If your DNS provider supports API access, we can use that API to automatically issue the certs. If your DNS provider supports API access, we can use API to automatically issue the certs.
You don't have to do anything manually! You don't have do anything manually!
### Currently acme.sh supports: ### Currently acme.sh supports:
1. CloudFlare.com API 1. Cloudflare.com API
1. DNSPod.cn API 2. Dnspod.cn API
1. CloudXNS.com API 3. Cloudxns.com API
1. GoDaddy.com API 4. Godaddy.com API
1. OVH, kimsufi, soyoustart and runabove API 5. OVH, kimsufi, soyoustart and runabove API
1. AWS Route 53 6. AWS Route 53, see: https://github.com/Neilpang/acme.sh/issues/65
1. PowerDNS.com API 7. PowerDNS API
1. lexicon DNS API: https://github.com/Neilpang/acme.sh/wiki/How-to-use-lexicon-dns-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.) (DigitalOcean, DNSimple, DnsMadeEasy, DNSPark, EasyDNS, Namesilo, NS1, PointHQ, Rage4 and Vultr etc.)
1. LuaDNS.com API 9. LuaDNS.com API
1. DNSMadeEasy.com API 10. DNSMadeEasy.com API
1. nsupdate API
1. aliyun.com(阿里云) API
1. ISPConfig 3.1 API
1. Alwaysdata.com API
**More APIs coming soon...** ##### More APIs are coming soon...
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. 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.
For more details: [How to use DNS API](dnsapi) For more details: [How to use dns api](dnsapi)
# 9. Issue ECC certificate:
# 9. Issue ECC certificates `Let's Encrypt` now can issue **ECDSA** certificates.
`Let's Encrypt` can now issue **ECDSA** certificates. And we also support it.
And we support them too!
Just set the `length` parameter with a prefix `ec-`. Just set the `length` parameter with a prefix `ec-`.
For example: For example:
### Single domain ECC cerfiticate ### Single domain ECC cerfiticate:
```bash ```bash
acme.sh --issue -w /home/wwwroot/example.com -d example.com --keylength ec-256 acme.sh --issue -w /home/wwwroot/example.com -d example.com --keylength ec-256
``` ```
### SAN multi domain ECC certificate SAN multi domain ECC certificate:
```bash ```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. Please look at the last parameter above.
@@ -305,48 +294,40 @@ Valid values are:
3. **ec-521 (secp521r1, "ECDSA P-521", which is not supported by Let's Encrypt yet.)** 3. **ec-521 (secp521r1, "ECDSA P-521", which is not supported by Let's Encrypt yet.)**
# 10. How to renew the issued certs # 10. How to renew the cert
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: 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: 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` # 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: You can update acme.sh to the latest code:
``` ```
acme.sh --upgrade acme.sh --upgrade
``` ```
You can also enable auto upgrade: You can 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: Disable auto upgrade:
``` ```
acme.sh --upgrade --auto-upgrade 0 acme.sh --upgrade --auto-upgrade 0
``` ```
# 12. Issue a cert from an existing CSR # 12. Issue a cert from an existing CSR
https://github.com/Neilpang/acme.sh/wiki/Issue-a-cert-from-existing-CSR https://github.com/Neilpang/acme.sh/wiki/Issue-a-cert-from-existing-CSR
@@ -358,25 +339,22 @@ Speak ACME language using shell, directly to "Let's Encrypt".
TODO: TODO:
# Acknowledgment
# Acknowledgments
1. Acme-tiny: https://github.com/diafygi/acme-tiny 1. Acme-tiny: https://github.com/diafygi/acme-tiny
2. ACME protocol: https://github.com/ietf-wg-acme/acme 2. ACME protocol: https://github.com/ietf-wg-acme/acme
3. Certbot: https://github.com/certbot/certbot 3. Certbot: https://github.com/certbot/certbot
# License & Others # License & Others
License is GPLv3 License is GPLv3
Please Star and Fork me. Please Star and Fork me.
[Issues](https://github.com/Neilpang/acme.sh/issues) and [pull requests](https://github.com/Neilpang/acme.sh/pulls) are welcome. [Issues](https://github.com/Neilpang/acme.sh/issues) and [pull requests](https://github.com/Neilpang/acme.sh/pulls) are welcomed.
# Donate # Donate
1. PayPal: donate@acme.sh
1. PayPal: donate@acme.sh
[Donate List](https://github.com/Neilpang/acme.sh/wiki/Donate-list) [Donate List](https://github.com/Neilpang/acme.sh/wiki/Donate-list)
+214 -234
View File
File diff suppressed because it is too large. Load diff
+68 -171
View File
@@ -1,80 +1,99 @@
# How to use DNS API # How to use dns api
## 1. Use CloudFlare domain API to automatically issue cert ## Use CloudFlare domain api to automatically issue cert
First you need to login to your CloudFlare account to get your API key. For now, we support clourflare integeration.
First you need to login to your clourflare account to get your api key.
``` ```
export CF_Key="sdfsdfsdfljlbjkljlkjsdfoiwje" export CF_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"
export CF_Email="xxxx@sss.com" export CF_Email="xxxx@sss.com"
``` ```
Ok, let's issue a cert now: Ok, let's issue 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` and will be reused when needed. 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.
## 2. Use DNSPod.cn domain API to automatically issue cert
First you need to login to your DNSPod account to get your API Key and ID. ## 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.
``` ```
export DP_Id="1234" export DP_Id="1234"
export DP_Key="sADDsdasdgdsf" export DP_Key="sADDsdasdgdsf"
``` ```
Ok, let's issue a cert now: Ok, let's issue 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` and will be reused when needed. 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.
## 3. Use CloudXNS.com domain API to automatically issue cert ## Use Cloudxns.com domain api to automatically issue cert
First you need to login to your CloudXNS account to get your API Key and Secret. 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.
``` ```
export CX_Key="1234" export CX_Key="1234"
export CX_Secret="sADDsdasdgdsf" export CX_Secret="sADDsdasdgdsf"
``` ```
Ok, let's issue a cert now: Ok, let's issue 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` and will be reused when needed. 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.
## 4. Use GoDaddy.com domain API to automatically issue cert ## Use Godaddy.com domain api to automatically issue cert
First you need to login to your GoDaddy account to get your API Key and Secret. We support Godaddy integration.
First you need to login to your Godaddy account to get your api key and api secret.
https://developer.godaddy.com/keys/ 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_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"
export GD_Secret="asdfsdafdsfdsfdsfdsfdsafd" export GD_Secret="asdfsdafdsfdsfdsfdsfdsafd"
``` ```
Ok, let's issue a cert now: Ok, let's issue 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` and will be reused when needed. 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.
## Use PowerDNS embedded api to automatically issue cert
## 5. Use PowerDNS embedded API to automatically issue cert We support PowerDNS embedded API integration.
First you need to login to your PowerDNS account to enable the API and set your API-Token in the configuration. First you need to enable api and set your api-token in PowerDNS configuration.
https://doc.powerdns.com/md/httpapi/README/ https://doc.powerdns.com/md/httpapi/README/
@@ -83,197 +102,75 @@ export PDNS_Url="http://ns.example.com:8081"
export PDNS_ServerId="localhost" export PDNS_ServerId="localhost"
export PDNS_Token="0123456789ABCDEF" export PDNS_Token="0123456789ABCDEF"
export PDNS_Ttl=60 export PDNS_Ttl=60
``` ```
Ok, let's issue a cert now: Ok, let's issue 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` and will be reused when needed. The `PDNS_Url`, `PDNS_ServerId`, `PDNS_Token` and `PDNS_Ttl` will be saved in `~/.acme.sh/account.conf`.
## 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 https://github.com/Neilpang/acme.sh/wiki/How-to-use-OVH-domain-api
# Use custom api
## 7. Use nsupdate to automatically issue cert If your api is not supported yet, you can write your own dns api.
First, generate a key for updating the zone Let's assume you want to name it 'myapi',
```
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}
```
Include this key in your named configuration 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.
include "/etc/named/keys/update.key"; 3. Then you can use your api to issue cert like:
```
Next, configure your zone to allow dynamic updates.
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.;
};
}
```
Finally, make the DNS server and update Key available to `acme.sh`
``` ```
export NSUPDATE_SERVER="dns.example.com" acme.sh --issue --dns dns_myapi -d example.com -d www.example.com
export NSUPDATE_KEY="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=="
``` ```
Ok, let's issue a cert now: For more details, please check our sample script: [dns_myapi.sh](dns_myapi.sh)
```
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. # Use lexicon dns api
https://github.com/Neilpang/acme.sh/wiki/How-to-use-lexicon-dns-api
## 8. Use LuaDNS domain API ## Use LuaDNS domain API
Get your API token at https://api.luadns.com/settings Get your API token at https://api.luadns.com/settings
``` ```
export LUA_Key="sdfsdfsdfljlbjkljlkjsdfoiwje" export LUA_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"
export LUA_Email="xxxx@sss.com" export LUA_Email="xxxx@sss.com"
``` ```
To issue a cert: To issue a cert:
``` ```
acme.sh --issue --dns dns_lua -d example.com -d www.example.com acme.sh --issue --dns dns_lua --dnssleep 3 -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 Get your API credentials at https://cp.dnsmadeeasy.com/account/info
``` ```
export ME_Key="sdfsdfsdfljlbjkljlkjsdfoiwje" export ME_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"
export ME_Secret="qdfqsdfkjdskfj" export ME_Secret="qdfqsdfkjdskfj"
``` ```
To issue a cert: To issue a cert:
``` ```
acme.sh --issue --dns dns_me -d example.com -d www.example.com acme.sh --issue --dns dns_me --dnssleep 3 -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
View File
@@ -1,147 +0,0 @@
#!/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
View File
@@ -1,187 +0,0 @@
#!/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
View File
@@ -1,227 +0,0 @@
#!/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"
}
+26 -66
View File
@@ -15,25 +15,17 @@ dns_cf_add() {
txtvalue=$2 txtvalue=$2
if [ -z "$CF_Key" ] || [ -z "$CF_Email" ]; then if [ -z "$CF_Key" ] || [ -z "$CF_Email" ]; then
CF_Key=""
CF_Email=""
_err "You don't specify cloudflare api key and email yet." _err "You don't specify cloudflare api key and email yet."
_err "Please create you key and try again." _err "Please create you key and try again."
return 1 return 1
fi 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. #save the api key and email to the account conf file.
_saveaccountconf CF_Key "$CF_Key" _saveaccountconf CF_Key "$CF_Key"
_saveaccountconf CF_Email "$CF_Email" _saveaccountconf CF_Email "$CF_Email"
_debug "First detect the root zone" _debug "First detect the root zone"
if ! _get_root "$fulldomain"; then if ! _get_root $fulldomain; then
_err "invalid domain" _err "invalid domain"
return 1 return 1
fi fi
@@ -44,18 +36,20 @@ dns_cf_add() {
_debug "Getting txt records" _debug "Getting txt records"
_cf_rest GET "zones/${_domain_id}/dns_records?type=TXT&name=$fulldomain" _cf_rest GET "zones/${_domain_id}/dns_records?type=TXT&name=$fulldomain"
if ! printf "%s" "$response" | grep \"success\":true >/dev/null; then if ! printf "$response" | grep \"success\":true >/dev/null; then
_err "Error" _err "Error"
return 1 return 1
fi 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" _debug count "$count"
if [ "$count" = "0" ]; then if [ "$count" = "0" ]; then
_info "Adding record" _info "Adding record"
if _cf_rest POST "zones/$_domain_id/dns_records" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":120}"; then 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 if printf -- "%s" "$response" | grep $fulldomain >/dev/null; then
_info "Added, OK" _info "Added, sleeping 10 seconds"
sleep 10
#todo: check if the record takes effect
return 0 return 0
else else
_err "Add txt record error." _err "Add txt record error."
@@ -65,12 +59,14 @@ dns_cf_add() {
_err "Add txt record error." _err "Add txt record error."
else else
_info "Updating record" _info "Updating record"
record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | head -n 1) record_id=$(printf "%s\n" "$response" | _egrep_o \"id\":\"[^\"]*\" | cut -d : -f 2 | tr -d \" | head -n 1)
_debug "record_id" "$record_id" _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\"}" _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 if [ "$?" = "0" ]; then
_info "Updated, OK" _info "Updated, sleeping 10 seconds"
sleep 10
#todo: check if the record takes effect
return 0 return 0
fi fi
_err "Update error" _err "Update error"
@@ -79,48 +75,13 @@ dns_cf_add() {
} }
#fulldomain txtvalue #fulldomain
dns_cf_rm() { dns_cf_rm() {
fulldomain=$1 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 below ################################## #################### Private functions bellow ##################################
#_acme-challenge.www.domain.com #_acme-challenge.www.domain.com
#returns #returns
# _sub_domain=_acme-challenge.www # _sub_domain=_acme-challenge.www
@@ -130,9 +91,8 @@ _get_root() {
domain=$1 domain=$1
i=2 i=2
p=1 p=1
while true; do while [ '1' ]; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100) h=$(printf $domain | cut -d . -f $i-100)
_debug h "$h"
if [ -z "$h" ]; then if [ -z "$h" ]; then
#not valid #not valid
return 1 return 1
@@ -142,17 +102,17 @@ _get_root() {
return 1 return 1
fi fi
if _contains "$response" "\"name\":\"$h\"" >/dev/null; then 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 \") _domain_id=$(printf "%s\n" "$response" | _egrep_o \"id\":\"[^\"]*\" | head -n 1 | cut -d : -f 2 | tr -d \")
if [ "$_domain_id" ]; then if [ "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) _sub_domain=$(printf $domain | cut -d . -f 1-$p)
_domain=$h _domain=$h
return 0 return 0
fi fi
return 1 return 1
fi fi
p=$i p=$i
i=$(_math "$i" + 1) i=$(expr $i + 1)
done done
return 1 return 1
} }
@@ -161,15 +121,15 @@ _cf_rest() {
m=$1 m=$1
ep="$2" ep="$2"
data="$3" data="$3"
_debug "$ep" _debug $ep
export _H1="X-Auth-Email: $CF_Email" _H1="X-Auth-Email: $CF_Email"
export _H2="X-Auth-Key: $CF_Key" _H2="X-Auth-Key: $CF_Key"
export _H3="Content-Type: application/json" _H3="Content-Type: application/json"
if [ "$m" != "GET" ]; then if [ "$data" ]; then
_debug data "$data" _debug data "$data"
response="$(_post "$data" "$CF_Api/$ep" "" "$m")" response="$(_post "$data" "$CF_Api/$ep" "" $m)"
else else
response="$(_get "$CF_Api/$ep")" response="$(_get "$CF_Api/$ep")"
fi fi
+33 -43
View File
@@ -17,26 +17,24 @@ dns_cx_add() {
txtvalue=$2 txtvalue=$2
if [ -z "$CX_Key" ] || [ -z "$CX_Secret" ]; then 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 "You don't specify cloudxns.com api key or secret yet."
_err "Please create you key and try again." _err "Please create you key and try again."
return 1 return 1
fi fi
REST_API="$CX_Api" REST_API=$CX_Api
#save the api key and email to the account conf file. #save the api key and email to the account conf file.
_saveaccountconf CX_Key "$CX_Key" _saveaccountconf CX_Key "$CX_Key"
_saveaccountconf CX_Secret "$CX_Secret" _saveaccountconf CX_Secret "$CX_Secret"
_debug "First detect the root zone" _debug "First detect the root zone"
if ! _get_root "$fulldomain"; then if ! _get_root $fulldomain; then
_err "invalid domain" _err "invalid domain"
return 1 return 1
fi fi
existing_records "$_domain" "$_sub_domain" existing_records $_domain $_sub_domain
_debug count "$count" _debug count "$count"
if [ "$?" != "0" ]; then if [ "$?" != "0" ]; then
_err "Error get existing records." _err "Error get existing records."
@@ -44,9 +42,9 @@ dns_cx_add() {
fi fi
if [ "$count" = "0" ]; then if [ "$count" = "0" ]; then
add_record "$_domain" "$_sub_domain" "$txtvalue" add_record $_domain $_sub_domain $txtvalue
else else
update_record "$_domain" "$_sub_domain" "$txtvalue" update_record $_domain $_sub_domain $txtvalue
fi fi
if [ "$?" = "0" ]; then if [ "$?" = "0" ]; then
@@ -58,15 +56,7 @@ dns_cx_add() {
#fulldomain #fulldomain
dns_cx_rm() { dns_cx_rm() {
fulldomain=$1 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 #usage: root sub
@@ -77,20 +67,20 @@ existing_records() {
_debug "Getting txt records" _debug "Getting txt records"
root=$1 root=$1
sub=$2 sub=$2
count=0
if ! _rest GET "record/$_domain_id?:domain_id?host_id=0&offset=0&row_num=100"; then if ! _rest GET "record/$_domain_id?:domain_id?host_id=0&offset=0&row_num=100"; then
return 1 return 1
fi 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" _debug seg "$seg"
if [ -z "$seg" ]; then if [ -z "$seg" ]; then
return 0 return 0
fi fi
if printf "%s" "$response" | grep '"type":"TXT"' >/dev/null; then if printf "$response" | grep '"type":"TXT"' >/dev/null; then
count=1 count=1
record_id=$(printf "%s\n" "$seg" | _egrep_o '"record_id":"[^"]*"' | cut -d : -f 2 | tr -d \" | _head_n 1) record_id=$(printf "%s\n" "$seg" | _egrep_o \"record_id\":\"[^\"]*\" | cut -d : -f 2 | tr -d \")
_debug record_id "$record_id" _debug record_id "$record_id"
return 0 return 0
fi fi
@@ -103,7 +93,7 @@ add_record() {
root=$1 root=$1
sub=$2 sub=$2
txtvalue=$3 txtvalue=$3
fulldomain="$sub.$root" fulldomain=$sub.$root
_info "Adding record" _info "Adding record"
@@ -120,7 +110,7 @@ update_record() {
root=$1 root=$1
sub=$2 sub=$2
txtvalue=$3 txtvalue=$3
fulldomain="$sub.$root" fulldomain=$sub.$root
_info "Updating record" _info "Updating record"
@@ -131,7 +121,7 @@ update_record() {
return 1 return 1
} }
#################### Private functions below ################################## #################### Private functions bellow ##################################
#_acme-challenge.www.domain.com #_acme-challenge.www.domain.com
#returns #returns
# _sub_domain=_acme-challenge.www # _sub_domain=_acme-challenge.www
@@ -146,30 +136,30 @@ _get_root() {
return 1 return 1
fi fi
while true; do while [ '1' ]; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100) h=$(printf $domain | cut -d . -f $i-100)
_debug h "$h" _debug h "$h"
if [ -z "$h" ]; then if [ -z "$h" ]; then
#not valid #not valid
return 1 return 1
fi fi
if _contains "$response" "$h."; then if printf "$response" | grep "$h." >/dev/null; then
seg=$(printf "%s\n" "$response" | _egrep_o '[^{]*"'"$h"'."[^}]*}') seg=$(printf "%s" "$response" | _egrep_o "\{[^\{]*\"$h\.\"[^\}]*\}")
_debug seg "$seg" _debug seg "$seg"
_domain_id=$(printf "%s\n" "$seg" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \") _domain_id=$(printf "%s" "$seg" | _egrep_o \"id\":\"[^\"]*\" | cut -d : -f 2 | tr -d \")
_debug _domain_id "$_domain_id" _debug _domain_id "$_domain_id"
if [ "$_domain_id" ]; then if [ "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) _sub_domain=$(printf $domain | cut -d . -f 1-$p)
_debug _sub_domain "$_sub_domain" _debug _sub_domain $_sub_domain
_domain="$h" _domain=$h
_debug _domain "$_domain" _debug _domain $_domain
return 0 return 0
fi fi
return 1 return 1
fi fi
p="$i" p=$i
i=$(_math "$i" + 1) i=$(expr $i + 1)
done done
return 1 return 1
} }
@@ -178,7 +168,7 @@ _get_root() {
_rest() { _rest() {
m=$1 m=$1
ep="$2" ep="$2"
_debug ep "$ep" _debug $ep
url="$REST_API/$ep" url="$REST_API/$ep"
_debug url "$url" _debug url "$url"
@@ -190,16 +180,16 @@ _rest() {
sec="$CX_Key$url$data$cdate$CX_Secret" sec="$CX_Key$url$data$cdate$CX_Secret"
_debug sec "$sec" _debug sec "$sec"
hmac=$(printf "%s" "$sec" | _digest md5 hex) hmac=$(printf "$sec" | openssl md5 | cut -d " " -f 2)
_debug hmac "$hmac" _debug hmac "$hmac"
export _H1="API-KEY: $CX_Key" _H1="API-KEY: $CX_Key"
export _H2="API-REQUEST-DATE: $cdate" _H2="API-REQUEST-DATE: $cdate"
export _H3="API-HMAC: $hmac" _H3="API-HMAC: $hmac"
export _H4="Content-Type: application/json" _H4="Content-Type: application/json"
if [ "$data" ]; then if [ "$data" ]; then
response="$(_post "$data" "$url" "" "$m")" response="$(_post "$data" "$url" "" $m)"
else else
response="$(_get "$url")" response="$(_get "$url")"
fi fi
@@ -209,7 +199,7 @@ _rest() {
return 1 return 1
fi fi
_debug2 response "$response" _debug2 response "$response"
if ! _contains "$response" '"message":"success"'; then if ! printf "$response" | grep '"message":"success"' >/dev/null; then
return 1 return 1
fi fi
return 0 return 0
+34 -64
View File
@@ -6,8 +6,9 @@
# #
#DP_Key="sADDsdasdgdsf" #DP_Key="sADDsdasdgdsf"
REST_API="https://dnsapi.cn" DP_Api="https://dnsapi.cn"
#REST_API
######## Public functions ##################### ######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" #Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
@@ -16,24 +17,24 @@ dns_dp_add() {
txtvalue=$2 txtvalue=$2
if [ -z "$DP_Id" ] || [ -z "$DP_Key" ]; then 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 "You don't specify dnspod api key and key id yet."
_err "Please create you key and try again." _err "Please create you key and try again."
return 1 return 1
fi fi
REST_API=$DP_Api
#save the api key and email to the account conf file. #save the api key and email to the account conf file.
_saveaccountconf DP_Id "$DP_Id" _saveaccountconf DP_Id "$DP_Id"
_saveaccountconf DP_Key "$DP_Key" _saveaccountconf DP_Key "$DP_Key"
_debug "First detect the root zone" _debug "First detect the root zone"
if ! _get_root "$fulldomain"; then if ! _get_root $fulldomain; then
_err "invalid domain" _err "invalid domain"
return 1 return 1
fi fi
existing_records "$_domain" "$_sub_domain" existing_records $_domain $_sub_domain
_debug count "$count" _debug count "$count"
if [ "$?" != "0" ]; then if [ "$?" != "0" ]; then
_err "Error get existing records." _err "Error get existing records."
@@ -41,45 +42,15 @@ dns_dp_add() {
fi fi
if [ "$count" = "0" ]; then if [ "$count" = "0" ]; then
add_record "$_domain" "$_sub_domain" "$txtvalue" add_record $_domain $_sub_domain $txtvalue
else else
update_record "$_domain" "$_sub_domain" "$txtvalue" update_record $_domain $_sub_domain $txtvalue
fi fi
} }
#fulldomain txtvalue #fulldomain
dns_dp_rm() { dns_dp_rm() {
fulldomain=$1 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"
} }
@@ -96,15 +67,14 @@ existing_records() {
return 1 return 1
fi fi
if _contains "$response" 'No records'; then if printf "$response" | grep 'No records'; then
count=0 count=0
return 0 return 0
fi fi
if _contains "$response" "Action completed successful"; then if printf "$response" | grep "Action completed successful" >/dev/null; then
count=$(printf "%s" "$response" | grep -c '<type>TXT</type>' | tr -d ' ') count=$(printf "$response" | grep '<type>TXT</type>' | wc -l)
record_id=$(printf "%s" "$response" | grep '^<id>' | tail -1 | cut -d '>' -f 2 | cut -d '<' -f 1) record_id=$(printf "$response" | grep '^<id>' | tail -1 | cut -d '>' -f 2 | cut -d '<' -f 1)
_debug record_id "$record_id"
return 0 return 0
else else
_err "get existing records error." _err "get existing records error."
@@ -120,7 +90,7 @@ add_record() {
root=$1 root=$1
sub=$2 sub=$2
txtvalue=$3 txtvalue=$3
fulldomain="$sub.$root" fulldomain=$sub.$root
_info "Adding record" _info "Adding record"
@@ -128,7 +98,7 @@ add_record() {
return 1 return 1
fi fi
if _contains "$response" "Action completed successful"; then if printf "$response" | grep "Action completed successful"; then
return 0 return 0
fi fi
@@ -142,7 +112,7 @@ update_record() {
root=$1 root=$1
sub=$2 sub=$2
txtvalue=$3 txtvalue=$3
fulldomain="$sub.$root" fulldomain=$sub.$root
_info "Updating record" _info "Updating record"
@@ -150,7 +120,7 @@ update_record() {
return 1 return 1
fi fi
if _contains "$response" "Action completed successful"; then if printf "$response" | grep "Action completed successful"; then
return 0 return 0
fi fi
@@ -158,7 +128,7 @@ update_record() {
return 1 #error return 1 #error
} }
#################### Private functions below ################################## #################### Private functions bellow ##################################
#_acme-challenge.www.domain.com #_acme-challenge.www.domain.com
#returns #returns
# _sub_domain=_acme-challenge.www # _sub_domain=_acme-challenge.www
@@ -168,8 +138,8 @@ _get_root() {
domain=$1 domain=$1
i=2 i=2
p=1 p=1
while true; do while [ '1' ]; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100) h=$(printf $domain | cut -d . -f $i-100)
if [ -z "$h" ]; then if [ -z "$h" ]; then
#not valid #not valid
return 1 return 1
@@ -179,39 +149,39 @@ _get_root() {
return 1 return 1
fi fi
if _contains "$response" "Action completed successful"; then 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 \") _domain_id=$(printf "%s\n" "$response" | _egrep_o \"id\":\"[^\"]*\" | cut -d : -f 2 | tr -d \")
_debug _domain_id "$_domain_id" _debug _domain_id "$_domain_id"
if [ "$_domain_id" ]; then if [ "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) _sub_domain=$(printf $domain | cut -d . -f 1-$p)
_debug _sub_domain "$_sub_domain" _debug _sub_domain $_sub_domain
_domain="$h" _domain=$h
_debug _domain "$_domain" _debug _domain $_domain
return 0 return 0
fi fi
return 1 return 1
fi fi
p="$i" p=$i
i=$(_math "$i" + 1) i=$(expr $i + 1)
done done
return 1 return 1
} }
#Usage: method URI data #Usage: method URI data
_rest() { _rest() {
m="$1" m=$1
ep="$2" ep="$2"
data="$3" data="$3"
_debug "$ep" _debug $ep
url="$REST_API/$ep" url="$REST_API/$ep"
_debug url "$url" _debug url "$url"
if [ "$m" = "GET" ]; then if [ "$data" ]; then
response="$(_get "$url" | tr -d '\r')"
else
_debug2 data "$data" _debug2 data "$data"
response="$(_post "$data" "$url" | tr -d '\r')" response="$(_post $data "$url")"
else
response="$(_get "$url")"
fi fi
if [ "$?" != "0" ]; then if [ "$?" != "0" ]; then
+15 -16
View File
@@ -16,8 +16,6 @@ dns_gd_add() {
txtvalue=$2 txtvalue=$2
if [ -z "$GD_Key" ] || [ -z "$GD_Secret" ]; then if [ -z "$GD_Key" ] || [ -z "$GD_Secret" ]; then
GD_Key=""
GD_Secret=""
_err "You don't specify godaddy api key and secret yet." _err "You don't specify godaddy api key and secret yet."
_err "Please create you key and try again." _err "Please create you key and try again."
return 1 return 1
@@ -28,11 +26,11 @@ dns_gd_add() {
_saveaccountconf GD_Secret "$GD_Secret" _saveaccountconf GD_Secret "$GD_Secret"
_debug "First detect the root zone" _debug "First detect the root zone"
if ! _get_root "$fulldomain"; then if ! _get_root $fulldomain; then
_err "invalid domain" _err "invalid domain"
return 1 return 1
fi fi
_debug _domain_id "$_domain_id"
_debug _sub_domain "$_sub_domain" _debug _sub_domain "$_sub_domain"
_debug _domain "$_domain" _debug _domain "$_domain"
@@ -59,17 +57,18 @@ dns_gd_rm() {
} }
#################### Private functions below ################################## #################### Private functions bellow ##################################
#_acme-challenge.www.domain.com #_acme-challenge.www.domain.com
#returns #returns
# _sub_domain=_acme-challenge.www # _sub_domain=_acme-challenge.www
# _domain=domain.com # _domain=domain.com
# _domain_id=sdjkglgdfewsdfg
_get_root() { _get_root() {
domain=$1 domain=$1
i=2 i=2
p=1 p=1
while true; do while [ '1' ]; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100) h=$(printf $domain | cut -d . -f $i-100)
if [ -z "$h" ]; then if [ -z "$h" ]; then
#not valid #not valid
return 1 return 1
@@ -79,15 +78,15 @@ _get_root() {
return 1 return 1
fi fi
if _contains "$response" '"code":"NOT_FOUND"'; then if printf "$response" | grep '"code":"NOT_FOUND"' >/dev/null; then
_debug "$h not found" _debug "$h not found"
else else
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) _sub_domain=$(printf $domain | cut -d . -f 1-$p)
_domain="$h" _domain=$h
return 0 return 0
fi fi
p="$i" p=$i
i=$(_math "$i" + 1) i=$(expr $i + 1)
done done
return 1 return 1
} }
@@ -96,14 +95,14 @@ _gd_rest() {
m=$1 m=$1
ep="$2" ep="$2"
data="$3" data="$3"
_debug "$ep" _debug $ep
export _H1="Authorization: sso-key $GD_Key:$GD_Secret" _H1="Authorization: sso-key $GD_Key:$GD_Secret"
export _H2="Content-Type: application/json" _H2="Content-Type: application/json"
if [ "$data" ]; then if [ "$data" ]; then
_debug data "$data" _debug data "$data"
response="$(_post "$data" "$GD_Api/$ep" "" "$m")" response="$(_post "$data" "$GD_Api/$ep" "" $m)"
else else
response="$(_get "$GD_Api/$ep")" response="$(_get "$GD_Api/$ep")"
fi fi
-177
View File
@@ -1,177 +0,0 @@
#!/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
}
+20 -26
View File
@@ -2,7 +2,7 @@
# dns api wrapper of lexicon for acme.sh # dns api wrapper of lexicon for acme.sh
# https://github.com/AnalogJ/lexicon lexicon_url="https://github.com/AnalogJ/lexicon"
lexicon_cmd="lexicon" lexicon_cmd="lexicon"
wiki="https://github.com/Neilpang/acme.sh/wiki/How-to-use-lexicon-dns-api" wiki="https://github.com/Neilpang/acme.sh/wiki/How-to-use-lexicon-dns-api"
@@ -14,15 +14,14 @@ dns_lexicon_add() {
fulldomain=$1 fulldomain=$1
txtvalue=$2 txtvalue=$2
domain=$(printf "%s" "$fulldomain" | cut -d . -f 2-999) domain=$(printf "$fulldomain" | cut -d . -f 2-999)
if ! _exists "$lexicon_cmd"; then if ! _exists $lexicon_cmd; then
_err "Please install $lexicon_cmd first: $wiki" _err "Please install $lexicon_cmd first: $wiki"
return 1 return 1
fi fi
if [ -z "$PROVIDER" ]; then if [ -z "$PROVIDER" ]; then
PROVIDER=""
_err "Please define env PROVIDER first: $wiki" _err "Please define env PROVIDER first: $wiki"
return 1 return 1
fi fi
@@ -30,44 +29,39 @@ dns_lexicon_add() {
_savedomainconf PROVIDER "$PROVIDER" _savedomainconf PROVIDER "$PROVIDER"
export PROVIDER export PROVIDER
# e.g. busybox-ash does not know [:upper:] Lx_name=$(echo LEXICON_${PROVIDER}_USERNAME | tr [a-z] [A-Z])
# shellcheck disable=SC2018,SC2019 eval Lx_name_v="\$$Lx_name"
Lx_name=$(echo LEXICON_"${PROVIDER}"_USERNAME | tr 'a-z' 'A-Z')
Lx_name_v=$(eval echo \$"$Lx_name")
_debug "$Lx_name" "$Lx_name_v" _debug "$Lx_name" "$Lx_name_v"
if [ "$Lx_name_v" ]; then if [ "$Lx_name_v" ]; then
_saveaccountconf "$Lx_name" "$Lx_name_v" _saveaccountconf $Lx_name "$Lx_name_v"
eval export "$Lx_name" export "$Lx_name"
fi fi
# shellcheck disable=SC2018,SC2019 Lx_token=$(echo LEXICON_${PROVIDER}_TOKEN | tr [a-z] [A-Z])
Lx_token=$(echo LEXICON_"${PROVIDER}"_TOKEN | tr 'a-z' 'A-Z') eval Lx_token_v="\$$Lx_token"
Lx_token_v=$(eval echo \$"$Lx_token")
_debug "$Lx_token" "$Lx_token_v" _debug "$Lx_token" "$Lx_token_v"
if [ "$Lx_token_v" ]; then if [ "$Lx_token_v" ]; then
_saveaccountconf "$Lx_token" "$Lx_token_v" _saveaccountconf $Lx_token "$Lx_token_v"
eval export "$Lx_token" export "$Lx_token"
fi fi
# shellcheck disable=SC2018,SC2019 Lx_password=$(echo LEXICON_${PROVIDER}_PASSWORD | tr [a-z] [A-Z])
Lx_password=$(echo LEXICON_"${PROVIDER}"_PASSWORD | tr 'a-z' 'A-Z') eval Lx_password_v="\$$Lx_password"
Lx_password_v=$(eval echo \$"$Lx_password")
_debug "$Lx_password" "$Lx_password_v" _debug "$Lx_password" "$Lx_password_v"
if [ "$Lx_password_v" ]; then if [ "$Lx_password_v" ]; then
_saveaccountconf "$Lx_password" "$Lx_password_v" _saveaccountconf $Lx_password "$Lx_password_v"
eval export "$Lx_password" export "$Lx_password"
fi fi
# shellcheck disable=SC2018,SC2019 Lx_domaintoken=$(echo LEXICON_${PROVIDER}_DOMAINTOKEN | tr [a-z] [A-Z])
Lx_domaintoken=$(echo LEXICON_"${PROVIDER}"_DOMAINTOKEN | tr 'a-z' 'A-Z') eval Lx_domaintoken_v="\$$Lx_domaintoken"
Lx_domaintoken_v=$(eval echo \$"$Lx_domaintoken")
_debug "$Lx_domaintoken" "$Lx_domaintoken_v" _debug "$Lx_domaintoken" "$Lx_domaintoken_v"
if [ "$Lx_domaintoken_v" ]; then if [ "$Lx_domaintoken_v" ]; then
eval export "$Lx_domaintoken" export "$Lx_domaintoken"
_saveaccountconf "$Lx_domaintoken" "$Lx_domaintoken_v" _saveaccountconf $Lx_domaintoken "$Lx_domaintoken_v"
fi 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}"
} }
+19 -21
View File
@@ -8,7 +8,7 @@
#LUA_Email="user@luadns.net" #LUA_Email="user@luadns.net"
LUA_Api="https://api.luadns.com/v1" LUA_Api="https://api.luadns.com/v1"
LUA_auth=$(printf "%s" "$LUA_Email:$LUA_Key" | _base64) LUA_auth=$(printf $LUA_Email:$LUA_Key | _base64)
######## Public functions ##################### ######## Public functions #####################
@@ -18,8 +18,6 @@ dns_lua_add() {
txtvalue=$2 txtvalue=$2
if [ -z "$LUA_Key" ] || [ -z "$LUA_Email" ]; then if [ -z "$LUA_Key" ] || [ -z "$LUA_Email" ]; then
LUA_Key=""
LUA_Email=""
_err "You don't specify luadns api key and email yet." _err "You don't specify luadns api key and email yet."
_err "Please create you key and try again." _err "Please create you key and try again."
return 1 return 1
@@ -30,7 +28,7 @@ dns_lua_add() {
_saveaccountconf LUA_Email "$LUA_Email" _saveaccountconf LUA_Email "$LUA_Email"
_debug "First detect the root zone" _debug "First detect the root zone"
if ! _get_root "$fulldomain"; then if ! _get_root $fulldomain; then
_err "invalid domain" _err "invalid domain"
return 1 return 1
fi fi
@@ -41,17 +39,17 @@ dns_lua_add() {
_debug "Getting txt records" _debug "Getting txt records"
_LUA_rest GET "zones/${_domain_id}/records" _LUA_rest GET "zones/${_domain_id}/records"
if ! _contains "$response" "\"id\":"; then if ! printf "$response" | grep \"id\": >/dev/null; then
_err "Error" _err "Error"
return 1 return 1
fi 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" _debug count "$count"
if [ "$count" = "0" ]; then if [ "$count" = "0" ]; then
_info "Adding record" _info "Adding record"
if _LUA_rest POST "zones/$_domain_id/records" "{\"type\":\"TXT\",\"name\":\"$fulldomain.\",\"content\":\"$txtvalue\",\"ttl\":120}"; then 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" _info "Added"
#todo: check if the record takes effect #todo: check if the record takes effect
return 0 return 0
@@ -63,8 +61,8 @@ dns_lua_add() {
_err "Add txt record error." _err "Add txt record error."
else else
_info "Updating record" _info "Updating record"
record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[^,]*,\"name\":\"$fulldomain.\",\"type\":\"TXT\"" | cut -d: -f2 | cut -d, -f1) record_id=$(printf "%s\n" "$response" | _egrep_o \"id\":[^,]*,\"name\":\"$fulldomain.\",\"type\":\"TXT\" | cut -d: -f2 | cut -d, -f1)
_debug "record_id" "$record_id" _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}" _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 if [ "$?" = "0" ]; then
@@ -84,7 +82,7 @@ dns_lua_rm() {
} }
#################### Private functions below ################################## #################### Private functions bellow ##################################
#_acme-challenge.www.domain.com #_acme-challenge.www.domain.com
#returns #returns
# _sub_domain=_acme-challenge.www # _sub_domain=_acme-challenge.www
@@ -97,24 +95,24 @@ _get_root() {
if ! _LUA_rest GET "zones"; then if ! _LUA_rest GET "zones"; then
return 1 return 1
fi fi
while true; do while [ '1' ]; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100) h=$(printf $domain | cut -d . -f $i-100)
if [ -z "$h" ]; then if [ -z "$h" ]; then
#not valid #not valid
return 1 return 1
fi fi
if _contains "$response" "\"name\":\"$h\""; then 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) _domain_id=$(printf "%s\n" "$response" | _egrep_o \"id\":[^,]*,\"name\":\"$h\" | cut -d : -f 2 | cut -d , -f 1)
if [ "$_domain_id" ]; then if [ "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) _sub_domain=$(printf $domain | cut -d . -f 1-$p)
_domain="$h" _domain=$h
return 0 return 0
fi fi
return 1 return 1
fi fi
p=$i p=$i
i=$(_math "$i" + 1) i=$(expr $i + 1)
done done
return 1 return 1
} }
@@ -123,13 +121,13 @@ _LUA_rest() {
m=$1 m=$1
ep="$2" ep="$2"
data="$3" data="$3"
_debug "$ep" _debug $ep
export _H1="Accept: application/json" _H1="Accept: application/json"
export _H2="Authorization: Basic $LUA_auth" _H2="Authorization: Basic $LUA_auth"
if [ "$data" ]; then if [ "$data" ]; then
_debug data "$data" _debug data "$data"
response="$(_post "$data" "$LUA_Api/$ep" "" "$m")" response="$(_post "$data" "$LUA_Api/$ep" "" $m)"
else else
response="$(_get "$LUA_Api/$ep")" response="$(_get "$LUA_Api/$ep")"
fi fi
+19 -21
View File
@@ -15,8 +15,6 @@ dns_me_add() {
txtvalue=$2 txtvalue=$2
if [ -z "$ME_Key" ] || [ -z "$ME_Secret" ]; then if [ -z "$ME_Key" ] || [ -z "$ME_Secret" ]; then
ME_Key=""
ME_Secret=""
_err "You didn't specify DNSMadeEasy api key and secret yet." _err "You didn't specify DNSMadeEasy api key and secret yet."
_err "Please create you key and try again." _err "Please create you key and try again."
return 1 return 1
@@ -27,7 +25,7 @@ dns_me_add() {
_saveaccountconf ME_Secret "$ME_Secret" _saveaccountconf ME_Secret "$ME_Secret"
_debug "First detect the root zone" _debug "First detect the root zone"
if ! _get_root "$fulldomain"; then if ! _get_root $fulldomain; then
_err "invalid domain" _err "invalid domain"
return 1 return 1
fi fi
@@ -38,12 +36,12 @@ dns_me_add() {
_debug "Getting txt records" _debug "Getting txt records"
_me_rest GET "${_domain_id}/records?recordName=$_sub_domain&type=TXT" _me_rest GET "${_domain_id}/records?recordName=$_sub_domain&type=TXT"
if ! _contains "$response" "\"totalRecords\":"; then if ! printf "$response" | grep \"totalRecords\": >/dev/null; then
_err "Error" _err "Error"
return 1 return 1
fi 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" _debug count "$count"
if [ "$count" = "0" ]; then if [ "$count" = "0" ]; then
_info "Adding record" _info "Adding record"
@@ -60,8 +58,8 @@ dns_me_add() {
_err "Add txt record error." _err "Add txt record error."
else else
_info "Updating record" _info "Updating record"
record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[^,]*" | cut -d : -f 2 | head -n 1) record_id=$(printf "%s\n" "$response" | _egrep_o \"id\":[^,]* | cut -d : -f 2 | head -n 1)
_debug "record_id" "$record_id" _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}" _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 if [ "$?" = "0" ]; then
@@ -81,7 +79,7 @@ dns_me_rm() {
} }
#################### Private functions below ################################## #################### Private functions bellow ##################################
#_acme-challenge.www.domain.com #_acme-challenge.www.domain.com
#returns #returns
# _sub_domain=_acme-challenge.www # _sub_domain=_acme-challenge.www
@@ -91,8 +89,8 @@ _get_root() {
domain=$1 domain=$1
i=2 i=2
p=1 p=1
while true; do while [ '1' ]; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100) h=$(printf $domain | cut -d . -f $i-100)
if [ -z "$h" ]; then if [ -z "$h" ]; then
#not valid #not valid
return 1 return 1
@@ -102,17 +100,17 @@ _get_root() {
return 1 return 1
fi fi
if _contains "$response" "\"name\":\"$h\""; then 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 '}') _domain_id=$(printf "%s\n" "$response" | _egrep_o \"id\":[^,]* | head -n 1 | cut -d : -f 2)
if [ "$_domain_id" ]; then if [ "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) _sub_domain=$(printf $domain | cut -d . -f 1-$p)
_domain="$h" _domain=$h
return 0 return 0
fi fi
return 1 return 1
fi fi
p=$i p=$i
i=$(_math "$i" + 1) i=$(expr $i + 1)
done done
return 1 return 1
} }
@@ -121,18 +119,18 @@ _me_rest() {
m=$1 m=$1
ep="$2" ep="$2"
data="$3" data="$3"
_debug "$ep" _debug $ep
cdate=$(date -u +"%a, %d %b %Y %T %Z") cdate=$(date -u +"%a, %d %b %Y %T %Z")
hmac=$(printf "%s" "$cdate" | _hmac sha1 "$(_hex "$ME_Secret")" hex) hmac=$(printf "$cdate" | _hmac sha1 "$ME_Secret" 1)
export _H1="x-dnsme-apiKey: $ME_Key" _H1="x-dnsme-apiKey: $ME_Key"
export _H2="x-dnsme-requestDate: $cdate" _H2="x-dnsme-requestDate: $cdate"
export _H3="x-dnsme-hmac: $hmac" _H3="x-dnsme-hmac: $hmac"
if [ "$data" ]; then if [ "$data" ]; then
_debug data "$data" _debug data "$data"
response="$(_post "$data" "$ME_Api/$ep" "" "$m")" response="$(_post "$data" "$ME_Api/$ep" "" $m)"
else else
response="$(_get "$ME_Api/$ep")" response="$(_get "$ME_Api/$ep")"
fi fi
+31 -14
View File
@@ -5,31 +5,48 @@
#So, here must be a method dns_myapi_add() #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. #Which will be called by acme.sh to add the txt record to your api system.
#returns 0 means success, otherwise error. #returns 0 means success, otherwise error.
#
#Author: Neilpang
#Report Bugs here: https://github.com/Neilpang/acme.sh
#
######## Public functions ##################### ######## Public functions #####################
#Usage: dns_myapi_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" #Usage: dns_myapi_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_myapi_add() { dns_myapi_add() {
fulldomain=$1 fulldomain=$1
txtvalue=$2 txtvalue=$2
_info "Using myapi"
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
_err "Not implemented!" _err "Not implemented!"
return 1 return 1
} }
#Usage: fulldomain txtvalue #fulldomain
#Remove the txt record after validation.
dns_myapi_rm() { dns_myapi_rm() {
fulldomain=$1 fulldomain=$1
txtvalue=$2
_info "Using myapi"
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
} }
#################### Private functions below ################################## #################### 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
}
-58
View File
@@ -1,58 +0,0 @@
#!/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
}
+17 -18
View File
@@ -86,8 +86,6 @@ dns_ovh_add() {
txtvalue=$2 txtvalue=$2
if [ -z "$OVH_AK" ] || [ -z "$OVH_AS" ]; then 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 "You don't specify OVH application key and application secret yet."
_err "Please create you key and try again." _err "Please create you key and try again."
return 1 return 1
@@ -129,11 +127,11 @@ dns_ovh_add() {
_info "Consumer key is ok." _info "Consumer key is ok."
_debug "First detect the root zone" _debug "First detect the root zone"
if ! _get_root "$fulldomain"; then if ! _get_root $fulldomain; then
_err "invalid domain" _err "invalid domain"
return 1 return 1
fi fi
_debug _domain_id "$_domain_id"
_debug _sub_domain "$_sub_domain" _debug _sub_domain "$_sub_domain"
_debug _domain "$_domain" _debug _domain "$_domain"
@@ -159,7 +157,7 @@ dns_ovh_add() {
_err "Can not get record id." _err "Can not get record id."
return 1 return 1
fi 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 _ovh_rest PUT "domain/zone/$_domain/record/$record_id" "{\"target\":\"$txtvalue\",\"subDomain\":\"$_sub_domain\",\"ttl\":60}"; then
if _contains "$response" "null"; then if _contains "$response" "null"; then
@@ -182,7 +180,7 @@ dns_ovh_rm() {
} }
#################### Private functions below ################################## #################### Private functions bellow ##################################
_ovh_authentication() { _ovh_authentication() {
@@ -223,12 +221,13 @@ _ovh_authentication() {
#returns #returns
# _sub_domain=_acme-challenge.www # _sub_domain=_acme-challenge.www
# _domain=domain.com # _domain=domain.com
# _domain_id=sdjkglgdfewsdfg
_get_root() { _get_root() {
domain=$1 domain=$1
i=2 i=2
p=1 p=1
while true; do while [ '1' ]; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100) h=$(printf $domain | cut -d . -f $i-100)
if [ -z "$h" ]; then if [ -z "$h" ]; then
#not valid #not valid
return 1 return 1
@@ -239,12 +238,12 @@ _get_root() {
fi fi
if ! _contains "$response" "This service does not exist" >/dev/null; then if ! _contains "$response" "This service does not exist" >/dev/null; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) _sub_domain=$(printf $domain | cut -d . -f 1-$p)
_domain="$h" _domain=$h
return 0 return 0
fi fi
p=$i p=$i
i=$(_math "$i" + 1) i=$(expr $i + 1)
done done
return 1 return 1
} }
@@ -262,7 +261,7 @@ _ovh_rest() {
m=$1 m=$1
ep="$2" ep="$2"
data="$3" data="$3"
_debug "$ep" _debug $ep
_ovh_url="$OVH_API/$ep" _ovh_url="$OVH_API/$ep"
_debug2 _ovh_url "$_ovh_url" _debug2 _ovh_url "$_ovh_url"
@@ -273,15 +272,15 @@ _ovh_rest() {
_ovh_hex="$(printf "%s" "$_ovh_p" | _digest sha1 hex)" _ovh_hex="$(printf "%s" "$_ovh_p" | _digest sha1 hex)"
_debug2 _ovh_hex "$_ovh_hex" _debug2 _ovh_hex "$_ovh_hex"
export _H1="X-Ovh-Application: $OVH_AK" _H1="X-Ovh-Application: $OVH_AK"
export _H2="X-Ovh-Signature: \$1\$$_ovh_hex" _H2="X-Ovh-Signature: \$1\$$_ovh_hex"
_debug2 _H2 "$_H2" _debug2 _H2 "$_H2"
export _H3="X-Ovh-Timestamp: $_ovh_t" _H3="X-Ovh-Timestamp: $_ovh_t"
export _H4="X-Ovh-Consumer: $OVH_CK" _H4="X-Ovh-Consumer: $OVH_CK"
export _H5="Content-Type: application/json;charset=utf-8" _H5="Content-Type: application/json;charset=utf-8"
if [ "$data" ] || [ "$m" = "POST" ] || [ "$m" = "PUT" ]; then if [ "$data" ] || [ "$m" = "POST" ] || [ "$m" = "PUT" ]; then
_debug data "$data" _debug data "$data"
response="$(_post "$data" "$_ovh_url" "" "$m")" response="$(_post "$data" "$_ovh_url" "" $m)"
else else
response="$(_get "$_ovh_url")" response="$(_get "$_ovh_url")"
fi fi
+15 -60
View File
@@ -12,35 +12,30 @@ DEFAULT_PDNS_TTL=60
######## Public functions ##################### ######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "123456789ABCDEF0000000000000000000000000000000000000" #Usage: add _acme-challenge.www.domain.com "123456789ABCDEF0000000000000000000000000000000000000"
#fulldomain
#txtvalue
dns_pdns_add() { dns_pdns_add() {
fulldomain=$1 fulldomain=$1
txtvalue=$2 txtvalue=$2
if [ -z "$PDNS_Url" ]; then if [ -z "$PDNS_Url" ]; then
PDNS_Url=""
_err "You don't specify PowerDNS address." _err "You don't specify PowerDNS address."
_err "Please set PDNS_Url and try again." _err "Please set PDNS_Url and try again."
return 1 return 1
fi fi
if [ -z "$PDNS_ServerId" ]; then if [ -z "$PDNS_ServerId" ]; then
PDNS_ServerId=""
_err "You don't specify PowerDNS server id." _err "You don't specify PowerDNS server id."
_err "Please set you PDNS_ServerId and try again." _err "Please set you PDNS_ServerId and try again."
return 1 return 1
fi fi
if [ -z "$PDNS_Token" ]; then if [ -z "$PDNS_Token" ]; then
PDNS_Token=""
_err "You don't specify PowerDNS token." _err "You don't specify PowerDNS token."
_err "Please create you PDNS_Token and try again." _err "Please create you PDNS_Token and try again."
return 1 return 1
fi fi
if [ -z "$PDNS_Ttl" ]; then if [ -z "$PDNS_Ttl" ]; then
PDNS_Ttl="$DEFAULT_PDNS_TTL" PDNS_Ttl=$DEFAULT_PDNS_TTL
fi fi
#save the api addr and key to the account conf file. #save the api addr and key to the account conf file.
@@ -52,8 +47,8 @@ dns_pdns_add() {
_saveaccountconf PDNS_Ttl "$PDNS_Ttl" _saveaccountconf PDNS_Ttl "$PDNS_Ttl"
fi fi
_debug "Detect root zone" _debug "First detect the root zone"
if ! _get_root "$fulldomain"; then if ! _get_root $fulldomain; then
_err "invalid domain" _err "invalid domain"
return 1 return 1
fi fi
@@ -70,18 +65,6 @@ dns_pdns_add() {
dns_pdns_rm() { dns_pdns_rm() {
fulldomain=$1 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() { set_record() {
@@ -90,73 +73,45 @@ set_record() {
full=$2 full=$2
txtvalue=$3 txtvalue=$3
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 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
_err "Set txt record error." _err "Set txt record error."
return 1 return 1
fi fi
if ! notify_slaves "$root"; then
return 1
fi
return 0
}
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 if ! _pdns_rest "PUT" "/api/v1/servers/$PDNS_ServerId/zones/$root./notify"; then
_err "Notify slaves error." _err "Notify servers error."
return 1 return 1
fi fi
return 0 return 0
} }
#################### Private functions below ################################## #################### Private functions bellow ##################################
#_acme-challenge.www.domain.com #_acme-challenge.www.domain.com
#returns #returns
# _domain=domain.com # _domain=domain.com
_get_root() { _get_root() {
domain=$1 domain=$1
i=1 i=1
p=1
if _pdns_rest "GET" "/api/v1/servers/$PDNS_ServerId/zones"; then if _pdns_rest "GET" "/api/v1/servers/$PDNS_ServerId/zones"; then
_zones_response="$response" _zones_response=$response
fi fi
while true; do while [ '1' ]; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100) h=$(printf $domain | cut -d . -f $i-100)
if [ -z "$h" ]; then if [ -z "$h" ]; then
return 1 return 1
fi fi
if _contains "$_zones_response" "\"name\": \"$h.\""; then if printf "$_zones_response" | grep "\"name\": \"$h.\"" >/dev/null; then
_domain="$h" _domain=$h
return 0 return 0
fi fi
i=$(_math $i + 1) p=$i
i=$(expr $i + 1)
done done
_debug "$domain not found" _debug "$domain not found"
return 1 return 1
} }
@@ -165,7 +120,7 @@ _pdns_rest() {
ep=$2 ep=$2
data=$3 data=$3
export _H1="X-API-Key: $PDNS_Token" _H1="X-API-Key: $PDNS_Token"
if [ ! "$method" = "GET" ]; then if [ ! "$method" = "GET" ]; then
_debug data "$data" _debug data "$data"
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.