Compare commits

..
241 Commits
16 changed files with 4159 additions and 1459 deletions
+25
View File
@@ -0,0 +1,25 @@
<!--
If it is a bug report:
- make sure you are able to repro it on the latest released version.
You can install the latest version by: `acme.sh --upgrade`
- Search the existing issues.
- Refer to the [WIKI](https://wiki.acme.sh).
- Debug info [Debug](https://github.com/Neilpang/acme.sh/wiki/How-to-debug-acme.sh).
-->
Steps to reproduce
------------------
Debug log
-----------------
```
acme.sh --issue ..... --debug 2
```
+11
View File
@@ -0,0 +1,11 @@
language: bash
env:
global:
- SHFMT_URL=https://github.com/mvdan/sh/releases/download/v0.4.0/shfmt_v0.4.0_linux_amd64
script:
- curl -sSL $SHFMT_URL -o ~/shfmt
- chmod +x ~/shfmt
- ~/shfmt -l -w -i 2 .
- git diff --exit-code || (echo "Run shfmt to fix the formatting issues" && false)
+101 -46
View File
@@ -1,4 +1,4 @@
# An ACME Shell script: 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.
- Fully ACME protocol implementation. - Fully ACME protocol implementation.
- Simple, powerful and very easy to use. You only need 3 minutes to learn. - Simple, powerful and very easy to use. You only need 3 minutes to learn.
@@ -13,6 +13,8 @@ It's probably the `easiest&smallest&smartest` shell script to automatically issu
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)
#Tested OS #Tested OS
| NO | Status| Platform| | NO | Status| Platform|
|----|-------|---------| |----|-------|---------|
@@ -32,6 +34,9 @@ Wiki: https://github.com/Neilpang/acme.sh/wiki
|14|-----| Cloud Linux https://github.com/Neilpang/le/issues/111 |14|-----| Cloud Linux https://github.com/Neilpang/le/issues/111
|15|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/openbsd.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|OpenBSD |15|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/openbsd.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|OpenBSD
|16|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/mageia.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Mageia |16|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/mageia.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Mageia
|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
|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
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):
@@ -44,17 +49,9 @@ https://github.com/Neilpang/acmetest
3. Apache mode 3. Apache mode
4. Dns mode 4. Dns mode
# Upgrade from 1.x to 2.x
You can simply uninstall 1.x and re-install 2.x.
2.x is 100% compatible to 1.x. You will feel right at home as if nothing has changed.
# le.sh renamed to acme.sh NOW! # 1. How to install
All configurations are 100% compatible between `le.sh` and `acme.sh`. You just need to uninstall `le.sh` and re-install `acme.sh` again.
Nothing will be broken during the process.
# How to install
### 1. Install online: ### 1. Install online:
@@ -111,66 +108,75 @@ root@v1:~# acme.sh -h
``` ```
# Just issue a cert: # 2. Just issue a cert:
**Example 1:** Single domain. **Example 1:** Single domain.
```bash ```bash
acme.sh --issue -d aa.com -w /home/wwwroot/aa.com 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 aa.com -d www.aa.com -d cp.aa.com -w /home/wwwroot/aa.com acme.sh --issue -d example.com -d www.example.com -d cp.example.com -w /home/wwwroot/example.com
``` ```
The parameter `/home/wwwroot/aa.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 **"aa.com"** is the main domain you want to issue cert for. Second argument **"example.com"** is the main domain you want to issue cert for.
You must have at least a 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/aa.com`. You must point and bind all the domains to the same webroot dir: `/home/wwwroot/example.com`.
Generate/issued certs will be placed in `~/.acme.sh/aa.com/` Generate/issued certs will be placed in `~/.acme.sh/example.com/`
The issued cert will be renewed every 80 days automatically. 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
# Install 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 the cert with your nginx/apache or other servers you may be using. After you issue a cert, you probably want to install/copy the cert to your nginx/apache or other servers.
You **MUST** use this command to copy the certs to the target files, **Do NOT** use the certs files in **.acme.sh/** folder, they are for internal use only, the folder structure may change in future.
**nginx** example
```bash ```bash
acme.sh --installcert -d aa.com \ acme.sh --installcert -d example.com \
--certpath /path/to/certfile/in/apache/nginx \ --keypath /path/to/keyfile/in/nginx/key.pem \
--keypath /path/to/keyfile/in/apache/nginx \ --fullchainpath path/to/fullchain/nginx/cert.pem \
--capath /path/to/ca/certfile/apache/nginx \ --reloadcmd "service nginx restart"
--fullchainpath path/to/fullchain/certfile/apache/nginx \ ```
--reloadcmd "service apache2|nginx reload"
**apache** example
```bash
acme.sh --installcert -d example.com \
--certpath /path/to/certfile/in/apache/cert.pem \
--keypath /path/to/keyfile/in/apache/key.pem \
--fullchainpath path/to/fullchain/certfile/apache/fullchain.pem \
--reloadcmd "service apache2 restart"
``` ```
Only the domain is required, all the other parameters are optional. Only the domain is required, all the other parameters are optional.
Install 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 80 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`. 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`.
# Use Standalone server to issue cert # 4. Use Standalone server to issue cert
**(requires you be root/sudoer, or you have permission to listen tcp 80 port)** **(requires you be root/sudoer, or you have permission to listen tcp 80 port)**
The tcp `80` port **MUST** be free to listen, otherwise you will be prompted to free the `80` port 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 aa.com -d www.aa.com -d cp.aa.com 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
# 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 be root/sudoer, or you have permission to listen tcp 443 port)**
@@ -179,12 +185,12 @@ acme.sh supports `tls-sni-01` validation.
The tcp `443` port **MUST** be free to listen, otherwise you will be prompted to free the `443` port and try again. 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 aa.com -d www.aa.com -d cp.aa.com 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
# Use Apache mode # 6. Use Apache mode
**(requires you 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)**
@@ -195,28 +201,28 @@ Particularly, if you are running an apache server, you should use apache mode in
Just set string "apache" as the second argument, 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 aa.com -d www.aa.com -d user.aa.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
# Use DNS mode: # 7. Use DNS mode:
Support the `dns-01` challenge. Support the `dns-01` challenge.
```bash ```bash
acme.sh --issue --dns -d aa.com -d www.aa.com -d user.aa.com acme.sh --issue --dns -d example.com -d www.example.com -d user.example.com
``` ```
You should get the output like below: You should get the output like below:
``` ```
Add the following txt record: Add the following txt record:
Domain:_acme-challenge.aa.com Domain:_acme-challenge.example.com
Txt value:9ihDbjYfTExAYeDs4DBUeuTo18KBzwvTEjUnSwd32-c Txt value:9ihDbjYfTExAYeDs4DBUeuTo18KBzwvTEjUnSwd32-c
Add the following txt record: Add the following txt record:
Domain:_acme-challenge.www.aa.com 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.
@@ -226,12 +232,12 @@ 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:
```bash ```bash
acme.sh --renew -d aa.com acme.sh --renew -d example.com
``` ```
Ok, it's finished. Ok, it's finished.
# Automatic DNS API integration # 8. Automatic DNS API integration
If your DNS provider supports API access, we can use API to automatically issue the certs. If your DNS provider supports API access, we can use API to automatically issue the certs.
@@ -242,9 +248,14 @@ You don't have do anything manually!
1. Cloudflare.com API 1. Cloudflare.com API
2. Dnspod.cn API 2. Dnspod.cn API
3. Cloudxns.com API 3. Cloudxns.com API
4. AWS Route 53, see: https://github.com/Neilpang/acme.sh/issues/65 4. Godaddy.com API
5. lexicon dns api: https://github.com/Neilpang/acme.sh/wiki/How-to-use-lexicon-dns-api 5. OVH, kimsufi, soyoustart and runabove API
6. AWS Route 53, see: https://github.com/Neilpang/acme.sh/issues/65
7. PowerDNS API
8. lexicon dns api: https://github.com/Neilpang/acme.sh/wiki/How-to-use-lexicon-dns-api
(DigitalOcean, DNSimple, DnsMadeEasy, DNSPark, EasyDNS, Namesilo, NS1, PointHQ, Rage4 and Vultr etc.) (DigitalOcean, DNSimple, DnsMadeEasy, DNSPark, EasyDNS, Namesilo, NS1, PointHQ, Rage4 and Vultr etc.)
9. LuaDNS.com API
10. DNSMadeEasy.com API
##### More APIs are coming soon... ##### More APIs are coming soon...
@@ -252,7 +263,7 @@ If your DNS provider is not on the supported list above, you can write your own
For more details: [How to use dns api](dnsapi) For more details: [How to use dns api](dnsapi)
# Issue ECC certificate: # 9. Issue ECC certificate:
`Let's Encrypt` now can issue **ECDSA** certificates. `Let's Encrypt` now can issue **ECDSA** certificates.
@@ -265,13 +276,13 @@ For example:
### Single domain ECC cerfiticate: ### Single domain ECC cerfiticate:
```bash ```bash
acme.sh --issue -w /home/wwwroot/aa.com -d aa.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/aa.com -d aa.com -d www.aa.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.
@@ -282,6 +293,46 @@ Valid values are:
2. **ec-384 (secp384r1, "ECDSA P-384")** 2. **ec-384 (secp384r1, "ECDSA P-384")**
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 cert
No, you don't need to renew the certs manually. All the certs will be renewed automatically every **60** days.
However, you can also force to renew any cert:
```
acme.sh --renew -d example.com --force
```
or, for ECC cert:
```
acme.sh --renew -d example.com --force --ecc
```
# 11. How to upgrade `acme.sh`
acme.sh is in developing, it's strongly recommended to use the latest code.
You can update acme.sh to the latest code:
```
acme.sh --upgrade
```
You can enable auto upgrade:
```
acme.sh --upgrade --auto-upgrade
```
Then **acme.sh** will keep up to date automatically.
Disable auto upgrade:
```
acme.sh --upgrade --auto-upgrade 0
```
# 12. Issue a cert from an existing CSR
https://github.com/Neilpang/acme.sh/wiki/Issue-a-cert-from-existing-CSR
# Under the Hood # Under the Hood
Speak ACME language using shell, directly to "Let's Encrypt". Speak ACME language using shell, directly to "Let's Encrypt".
@@ -293,7 +344,7 @@ TODO:
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 & Other # License & Others
License is GPLv3 License is GPLv3
@@ -302,4 +353,8 @@ Please Star and Fork me.
[Issues](https://github.com/Neilpang/acme.sh/issues) and [pull requests](https://github.com/Neilpang/acme.sh/pulls) are welcomed. [Issues](https://github.com/Neilpang/acme.sh/issues) and [pull requests](https://github.com/Neilpang/acme.sh/pulls) are welcomed.
# Donate
1. PayPal: donate@acme.sh
[Donate List](https://github.com/Neilpang/acme.sh/wiki/Donate-list)
+2722 -1054
View File
File diff suppressed because it is too large Load Diff
+28
View File
@@ -0,0 +1,28 @@
#!/usr/bin/env sh
#Here is a sample custom api script.
#This file name is "myapi.sh"
#So, here must be a method myapi_deploy()
#Which will be called by acme.sh to deploy the cert
#returns 0 means success, otherwise error.
######## Public functions #####################
#domain keyfile certfile cafile fullchain
myapi_deploy() {
_cdomain="$1"
_ckey="$2"
_ccert="$3"
_cca="$4"
_cfullchain="$5"
_debug _cdomain "$_cdomain"
_debug _ckey "$_ckey"
_debug _ccert "$_ccert"
_debug _cca "$_cca"
_debug _cfullchain "$_cfullchain"
_err "Not implemented yet"
return 1
}
+93 -7
View File
@@ -15,7 +15,7 @@ export CF_Email="xxxx@sss.com"
Ok, let's issue cert now: Ok, let's issue cert now:
``` ```
acme.sh --issue --dns dns_cf -d aa.com -d www.aa.com acme.sh --issue --dns dns_cf -d example.com -d www.example.com
``` ```
The `CF_Key` and `CF_Email` will be saved in `~/.acme.sh/account.conf`, when next time you use cloudflare api, it will reuse this key. The `CF_Key` and `CF_Email` will be saved in `~/.acme.sh/account.conf`, when next time you use cloudflare api, it will reuse this key.
@@ -37,7 +37,7 @@ export DP_Key="sADDsdasdgdsf"
Ok, let's issue cert now: Ok, let's issue cert now:
``` ```
acme.sh --issue --dns dns_dp -d aa.com -d www.aa.com acme.sh --issue --dns dns_dp -d example.com -d www.example.com
``` ```
The `DP_Id` and `DP_Key` will be saved in `~/.acme.sh/account.conf`, when next time you use dnspod.cn api, it will reuse this key. The `DP_Id` and `DP_Key` will be saved in `~/.acme.sh/account.conf`, when next time you use dnspod.cn api, it will reuse this key.
@@ -58,12 +58,63 @@ export CX_Secret="sADDsdasdgdsf"
Ok, let's issue cert now: Ok, let's issue cert now:
``` ```
acme.sh --issue --dns dns_cx -d aa.com -d www.aa.com acme.sh --issue --dns dns_cx -d example.com -d www.example.com
``` ```
The `CX_Key` and `CX_Secret` will be saved in `~/.acme.sh/account.conf`, when next time you use Cloudxns.com api, it will reuse this key. The `CX_Key` and `CX_Secret` will be saved in `~/.acme.sh/account.conf`, when next time you use Cloudxns.com api, it will reuse this key.
## Use Godaddy.com domain api to automatically issue cert
We support Godaddy integration.
First you need to login to your Godaddy account to get your api key and api secret.
https://developer.godaddy.com/keys/
Please Create a Production key, instead of a Test key.
```
export GD_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"
export GD_Secret="asdfsdafdsfdsfdsfdsfdsafd"
```
Ok, let's issue cert now:
```
acme.sh --issue --dns dns_gd -d example.com -d www.example.com
```
The `GD_Key` and `GD_Secret` will be saved in `~/.acme.sh/account.conf`, when next time you use cloudflare api, it will reuse this key.
## Use PowerDNS embedded api to automatically issue cert
We support PowerDNS embedded API integration.
First you need to enable api and set your api-token in PowerDNS configuration.
https://doc.powerdns.com/md/httpapi/README/
```
export PDNS_Url="http://ns.example.com:8081"
export PDNS_ServerId="localhost"
export PDNS_Token="0123456789ABCDEF"
export PDNS_Ttl=60
```
Ok, let's issue cert now:
```
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`.
## Use OVH/kimsufi/soyoustart/runabove API
https://github.com/Neilpang/acme.sh/wiki/How-to-use-OVH-domain-api
# Use custom api # Use custom api
@@ -72,19 +123,54 @@ If your api is not supported yet, you can write your own dns api.
Let's assume you want to name it 'myapi', Let's assume you want to name it 'myapi',
1. Create a bash script named `~/.acme.sh/dns_myapi.sh`, 1. Create a bash script named `~/.acme.sh/dns_myapi.sh`,
2. In the scrypt, you must have a function named `dns_myapi_add()`. Which will be called by acme.sh to add dns records. 2. In the script, you must have a function named `dns_myapi_add()`. Which will be called by acme.sh to add dns records.
3. Then you can use your api to issue cert like: 3. Then you can use your api to issue cert like:
``` ```
acme.sh --issue --dns dns_myapi -d aa.com -d www.aa.com 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) For more details, please check our sample script: [dns_myapi.sh](dns_myapi.sh)
# Use lexicon dns api # Use lexicon dns api
https://github.com/Neilpang/acme.sh/wiki/How-to-use-lexicon-dns-api https://github.com/Neilpang/acme.sh/wiki/How-to-use-lexicon-dns-api
## Use LuaDNS domain API
Get your API token at https://api.luadns.com/settings
```
export LUA_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"
export LUA_Email="xxxx@sss.com"
```
To issue a cert:
```
acme.sh --issue --dns dns_lua --dnssleep 3 -d example.com -d www.example.com
```
The `LUA_Key` and `LUA_Email` will be saved in `~/.acme.sh/account.conf`, and will be reused when needed.
## Use DNSMadeEasy domain API
Get your API credentials at https://cp.dnsmadeeasy.com/account/info
```
export ME_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"
export ME_Secret="qdfqsdfkjdskfj"
```
To issue a cert:
```
acme.sh --issue --dns dns_me --dnssleep 3 -d example.com -d www.example.com
```
The `ME_Key` and `ME_Secret` will be saved in `~/.acme.sh/account.conf`, and will be reused when needed.
+26 -28
View File
@@ -1,22 +1,20 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# #
#CF_Key="sdfsdfsdfljlbjkljlkjsdfoiwje" #CF_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"
# #
#CF_Email="xxxx@sss.com" #CF_Email="xxxx@sss.com"
CF_Api="https://api.cloudflare.com/client/v4" CF_Api="https://api.cloudflare.com/client/v4"
######## Public functions ##################### ######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" #Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_cf_add(){ dns_cf_add() {
fulldomain=$1 fulldomain=$1
txtvalue=$2 txtvalue=$2
if [ -z "$CF_Key" ] || [ -z "$CF_Email" ] ; then if [ -z "$CF_Key" ] || [ -z "$CF_Email" ]; then
_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
@@ -27,7 +25,7 @@ dns_cf_add(){
_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
@@ -38,17 +36,17 @@ 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 "$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 "$response" | grep -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 $response | grep $fulldomain > /dev/null ; then if printf -- "%s" "$response" | grep $fulldomain >/dev/null; then
_info "Added, sleeping 10 seconds" _info "Added, sleeping 10 seconds"
sleep 10 sleep 10
#todo: check if the record takes effect #todo: check if the record takes effect
@@ -61,15 +59,15 @@ dns_cf_add(){
_err "Add txt record error." _err "Add txt record error."
else else
_info "Updating record" _info "Updating record"
record_id=$(printf "$response" | grep -o \"id\":\"[^\"]*\" | cut -d : -f 2 | tr -d \"| head -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, sleeping 10 seconds" _info "Updated, sleeping 10 seconds"
sleep 10 sleep 10
#todo: check if the record takes effect #todo: check if the record takes effect
return 0; return 0
fi fi
_err "Update error" _err "Update error"
return 1 return 1
@@ -77,9 +75,11 @@ dns_cf_add(){
} }
#fulldomain
dns_cf_rm() {
fulldomain=$1
}
#################### Private functions bellow ################################## #################### Private functions bellow ##################################
#_acme-challenge.www.domain.com #_acme-challenge.www.domain.com
@@ -91,20 +91,20 @@ _get_root() {
domain=$1 domain=$1
i=2 i=2
p=1 p=1
while [ '1' ] ; do while [ '1' ]; do
h=$(printf $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;
fi
if ! _cf_rest GET "zones?name=$h" ; then
return 1 return 1
fi fi
if printf $response | grep \"name\":\"$h\" >/dev/null ; then if ! _cf_rest GET "zones?name=$h"; then
_domain_id=$(printf "$response" | grep -o \"id\":\"[^\"]*\" | head -1 | cut -d : -f 2 | tr -d \") return 1
if [ "$_domain_id" ] ; then fi
if printf $response | grep \"name\":\"$h\" >/dev/null; then
_domain_id=$(printf "%s\n" "$response" | _egrep_o \"id\":\"[^\"]*\" | head -n 1 | cut -d : -f 2 | tr -d \")
if [ "$_domain_id" ]; then
_sub_domain=$(printf $domain | cut -d . -f 1-$p) _sub_domain=$(printf $domain | cut -d . -f 1-$p)
_domain=$h _domain=$h
return 0 return 0
@@ -127,19 +127,17 @@ _cf_rest() {
_H2="X-Auth-Key: $CF_Key" _H2="X-Auth-Key: $CF_Key"
_H3="Content-Type: application/json" _H3="Content-Type: application/json"
if [ "$data" ] ; 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
if [ "$?" != "0" ] ; then if [ "$?" != "0" ]; then
_err "error $ep" _err "error $ep"
return 1 return 1
fi fi
_debug2 response "$response" _debug2 response "$response"
return 0 return 0
} }
+31 -34
View File
@@ -6,10 +6,8 @@
# #
#CX_Secret="sADDsdasdgdsf" #CX_Secret="sADDsdasdgdsf"
CX_Api="https://www.cloudxns.net/api2" CX_Api="https://www.cloudxns.net/api2"
#REST_API #REST_API
######## Public functions ##################### ######## Public functions #####################
@@ -18,7 +16,7 @@ dns_cx_add() {
fulldomain=$1 fulldomain=$1
txtvalue=$2 txtvalue=$2
if [ -z "$CX_Key" ] || [ -z "$CX_Secret" ] ; then if [ -z "$CX_Key" ] || [ -z "$CX_Secret" ]; then
_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
@@ -30,32 +28,37 @@ dns_cx_add() {
_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."
return 1 return 1
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
return 0 return 0
fi fi
return 1 return 1
} }
#fulldomain
dns_cx_rm() {
fulldomain=$1
}
#usage: root sub #usage: root sub
#return if the sub record already exists. #return if the sub record already exists.
#echos the existing records count. #echos the existing records count.
@@ -65,19 +68,19 @@ existing_records() {
root=$1 root=$1
sub=$2 sub=$2
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 count=0
seg=$(printf "$response" | grep -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 "$response" | grep '"type":"TXT"' > /dev/null ; then if printf "$response" | grep '"type":"TXT"' >/dev/null; then
count=1 count=1
record_id=$(printf "$seg" | grep -o \"record_id\":\"[^\"]*\" | cut -d : -f 2 | tr -d \") record_id=$(printf "%s\n" "$seg" | _egrep_o \"record_id\":\"[^\"]*\" | cut -d : -f 2 | tr -d \")
_debug record_id "$record_id" _debug record_id "$record_id"
return 0 return 0
fi fi
@@ -111,16 +114,13 @@ update_record() {
_info "Updating record" _info "Updating record"
if _rest PUT "record/$record_id" "{\"domain_id\": $_domain_id, \"host\":\"$_sub_domain\", \"value\":\"$txtvalue\", \"type\":\"TXT\",\"ttl\":600, \"line_id\":1}" ; then if _rest PUT "record/$record_id" "{\"domain_id\": $_domain_id, \"host\":\"$_sub_domain\", \"value\":\"$txtvalue\", \"type\":\"TXT\",\"ttl\":600, \"line_id\":1}"; then
return 0 return 0
fi fi
return 1 return 1
} }
#################### Private functions bellow ################################## #################### Private functions bellow ##################################
#_acme-challenge.www.domain.com #_acme-challenge.www.domain.com
#returns #returns
@@ -132,24 +132,24 @@ _get_root() {
i=2 i=2
p=1 p=1
if ! _rest GET "domain" ; then if ! _rest GET "domain"; then
return 1 return 1
fi fi
while [ '1' ] ; do while [ '1' ]; do
h=$(printf $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 printf "$response" | grep "$h." >/dev/null ; then if printf "$response" | grep "$h." >/dev/null; then
seg=$(printf "$response" | grep -o "{[^{]*$h\.[^}]*\}" ) seg=$(printf "%s" "$response" | _egrep_o "\{[^\{]*\"$h\.\"[^\}]*\}")
_debug seg "$seg" _debug seg "$seg"
_domain_id=$(printf "$seg" | grep -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 $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
@@ -164,7 +164,6 @@ _get_root() {
return 1 return 1
} }
#Usage: method URI data #Usage: method URI data
_rest() { _rest() {
m=$1 m=$1
@@ -173,7 +172,7 @@ _rest() {
url="$REST_API/$ep" url="$REST_API/$ep"
_debug url "$url" _debug url "$url"
cdate=$(date -u "+%Y-%m-%d %H:%M:%S UTC") cdate=$(date -u "+%Y-%m-%d %H:%M:%S UTC")
_debug cdate "$cdate" _debug cdate "$cdate"
data="$3" data="$3"
@@ -181,7 +180,7 @@ _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 "$sec"| openssl md5 |cut -d " " -f 2) hmac=$(printf "$sec" | openssl md5 | cut -d " " -f 2)
_debug hmac "$hmac" _debug hmac "$hmac"
_H1="API-KEY: $CX_Key" _H1="API-KEY: $CX_Key"
@@ -189,21 +188,19 @@ _rest() {
_H3="API-HMAC: $hmac" _H3="API-HMAC: $hmac"
_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
if [ "$?" != "0" ] ; then if [ "$?" != "0" ]; then
_err "error $ep" _err "error $ep"
return 1 return 1
fi fi
_debug2 response "$response" _debug2 response "$response"
if ! printf "$response" | grep '"message":"success"' > /dev/null ; then if ! printf "$response" | grep '"message":"success"' >/dev/null; then
return 1 return 1
fi fi
return 0 return 0
} }
+26 -31
View File
@@ -6,10 +6,8 @@
# #
#DP_Key="sADDsdasdgdsf" #DP_Key="sADDsdasdgdsf"
DP_Api="https://dnsapi.cn" DP_Api="https://dnsapi.cn"
#REST_API #REST_API
######## Public functions ##################### ######## Public functions #####################
@@ -18,7 +16,7 @@ dns_dp_add() {
fulldomain=$1 fulldomain=$1
txtvalue=$2 txtvalue=$2
if [ -z "$DP_Id" ] || [ -z "$DP_Key" ] ; then if [ -z "$DP_Id" ] || [ -z "$DP_Key" ]; then
_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
@@ -30,27 +28,32 @@ dns_dp_add() {
_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."
return 1 return 1
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
dns_dp_rm() {
fulldomain=$1
}
#usage: root sub #usage: root sub
#return if the sub record already exists. #return if the sub record already exists.
#echos the existing records count. #echos the existing records count.
@@ -61,15 +64,15 @@ existing_records() {
sub=$2 sub=$2
if ! _rest POST "Record.List" "login_token=$DP_Id,$DP_Key&domain_id=$_domain_id&sub_domain=$_sub_domain"; then if ! _rest POST "Record.List" "login_token=$DP_Id,$DP_Key&domain_id=$_domain_id&sub_domain=$_sub_domain"; then
return 1 return 1
fi fi
if printf "$response" | grep 'No records' ; then if printf "$response" | grep 'No records'; then
count=0; count=0
return 0 return 0
fi fi
if printf "$response" | grep "Action completed successful" >/dev/null ; then if printf "$response" | grep "Action completed successful" >/dev/null; then
count=$(printf "$response" | grep '<type>TXT</type>' | wc -l) count=$(printf "$response" | grep '<type>TXT</type>' | wc -l)
record_id=$(printf "$response" | grep '^<id>' | tail -1 | cut -d '>' -f 2 | cut -d '<' -f 1) record_id=$(printf "$response" | grep '^<id>' | tail -1 | cut -d '>' -f 2 | cut -d '<' -f 1)
return 0 return 0
@@ -78,7 +81,6 @@ existing_records() {
return 1 return 1
fi fi
count=0 count=0
} }
@@ -96,12 +98,11 @@ add_record() {
return 1 return 1
fi fi
if printf "$response" | grep "Action completed successful" ; then if printf "$response" | grep "Action completed successful"; then
return 0 return 0
fi fi
return 1 #error return 1 #error
} }
@@ -119,7 +120,7 @@ update_record() {
return 1 return 1
fi fi
if printf "$response" | grep "Action completed successful" ; then if printf "$response" | grep "Action completed successful"; then
return 0 return 0
fi fi
@@ -127,9 +128,6 @@ update_record() {
return 1 #error return 1 #error
} }
#################### Private functions bellow ################################## #################### Private functions bellow ##################################
#_acme-challenge.www.domain.com #_acme-challenge.www.domain.com
#returns #returns
@@ -140,21 +138,21 @@ _get_root() {
domain=$1 domain=$1
i=2 i=2
p=1 p=1
while [ '1' ] ; do while [ '1' ]; do
h=$(printf $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 ! _rest POST "Domain.Info" "login_token=$DP_Id,$DP_Key&format=json&domain=$h"; then if ! _rest POST "Domain.Info" "login_token=$DP_Id,$DP_Key&format=json&domain=$h"; then
return 1 return 1
fi fi
if printf "$response" | grep "Action completed successful" >/dev/null ; then if printf "$response" | grep "Action completed successful" >/dev/null; then
_domain_id=$(printf "$response" | grep -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 $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
@@ -169,7 +167,6 @@ _get_root() {
return 1 return 1
} }
#Usage: method URI data #Usage: method URI data
_rest() { _rest() {
m=$1 m=$1
@@ -180,19 +177,17 @@ _rest() {
_debug url "$url" _debug url "$url"
if [ "$data" ] ; then if [ "$data" ]; then
_debug2 data "$data" _debug2 data "$data"
response="$(_post $data "$url")" response="$(_post $data "$url")"
else else
response="$(_get "$url")" response="$(_get "$url")"
fi fi
if [ "$?" != "0" ] ; then if [ "$?" != "0" ]; then
_err "error $ep" _err "error $ep"
return 1 return 1
fi fi
_debug2 response "$response" _debug2 response "$response"
return 0 return 0
} }
+116
View File
@@ -0,0 +1,116 @@
#!/usr/bin/env sh
#Godaddy domain api
#
#GD_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"
#
#GD_Secret="asdfsdfsfsdfsdfdfsdf"
GD_Api="https://api.godaddy.com/v1"
######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_gd_add() {
fulldomain=$1
txtvalue=$2
if [ -z "$GD_Key" ] || [ -z "$GD_Secret" ]; then
_err "You don't specify godaddy api key and secret yet."
_err "Please create you key and try again."
return 1
fi
#save the api key and email to the account conf file.
_saveaccountconf GD_Key "$GD_Key"
_saveaccountconf GD_Secret "$GD_Secret"
_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"
_info "Adding record"
if _gd_rest PUT "domains/$_domain/records/TXT/$_sub_domain" "[{\"data\":\"$txtvalue\"}]"; then
if [ "$response" = "{}" ]; then
_info "Added, sleeping 10 seconds"
sleep 10
#todo: check if the record takes effect
return 0
else
_err "Add txt record error."
_err "$response"
return 1
fi
fi
_err "Add txt record error."
}
#fulldomain
dns_gd_rm() {
fulldomain=$1
}
#################### Private functions bellow ##################################
#_acme-challenge.www.domain.com
#returns
# _sub_domain=_acme-challenge.www
# _domain=domain.com
# _domain_id=sdjkglgdfewsdfg
_get_root() {
domain=$1
i=2
p=1
while [ '1' ]; do
h=$(printf $domain | cut -d . -f $i-100)
if [ -z "$h" ]; then
#not valid
return 1
fi
if ! _gd_rest GET "domains/$h"; then
return 1
fi
if printf "$response" | grep '"code":"NOT_FOUND"' >/dev/null; then
_debug "$h not found"
else
_sub_domain=$(printf $domain | cut -d . -f 1-$p)
_domain=$h
return 0
fi
p=$i
i=$(expr $i + 1)
done
return 1
}
_gd_rest() {
m=$1
ep="$2"
data="$3"
_debug $ep
_H1="Authorization: sso-key $GD_Key:$GD_Secret"
_H2="Content-Type: application/json"
if [ "$data" ]; then
_debug data "$data"
response="$(_post "$data" "$GD_Api/$ep" "" $m)"
else
response="$(_get "$GD_Api/$ep")"
fi
if [ "$?" != "0" ]; then
_err "error $ep"
return 1
fi
_debug2 response "$response"
return 0
}
+14 -11
View File
@@ -16,12 +16,12 @@ dns_lexicon_add() {
domain=$(printf "$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
_err "Please define env PROVIDER first: $wiki" _err "Please define env PROVIDER first: $wiki"
return 1 return 1
fi fi
@@ -29,34 +29,34 @@ dns_lexicon_add() {
_savedomainconf PROVIDER "$PROVIDER" _savedomainconf PROVIDER "$PROVIDER"
export PROVIDER export PROVIDER
Lx_name=$(echo LEXICON_${PROVIDER}_USERNAME | tr [a-z] [A-Z]) Lx_name=$(echo LEXICON_${PROVIDER}_USERNAME | tr [a-z] [A-Z])
eval Lx_name_v="\$$Lx_name" eval Lx_name_v="\$$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"
export "$Lx_name" export "$Lx_name"
fi fi
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" eval Lx_token_v="\$$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"
export "$Lx_token" export "$Lx_token"
fi fi
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" eval Lx_password_v="\$$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"
export "$Lx_password" export "$Lx_password"
fi fi
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" eval Lx_domaintoken_v="\$$Lx_domaintoken"
_debug "$Lx_domaintoken" "$Lx_domaintoken_v" _debug "$Lx_domaintoken" "$Lx_domaintoken_v"
if [ "$Lx_domaintoken_v" ] ; then if [ "$Lx_domaintoken_v" ]; then
export "$Lx_domaintoken" export "$Lx_domaintoken"
_saveaccountconf $Lx_domaintoken "$Lx_domaintoken_v" _saveaccountconf $Lx_domaintoken "$Lx_domaintoken_v"
fi fi
@@ -65,5 +65,8 @@ dns_lexicon_add() {
} }
#fulldomain
dns_lexicon_rm() {
fulldomain=$1
}
+141
View File
@@ -0,0 +1,141 @@
#!/usr/bin/env sh
# bug reports to dev@1e.ca
#
#LUA_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"
#
#LUA_Email="user@luadns.net"
LUA_Api="https://api.luadns.com/v1"
LUA_auth=$(printf $LUA_Email:$LUA_Key | _base64)
######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_lua_add() {
fulldomain=$1
txtvalue=$2
if [ -z "$LUA_Key" ] || [ -z "$LUA_Email" ]; then
_err "You don't specify luadns api key and email yet."
_err "Please create you key and try again."
return 1
fi
#save the api key and email to the account conf file.
_saveaccountconf LUA_Key "$LUA_Key"
_saveaccountconf LUA_Email "$LUA_Email"
_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"
_LUA_rest GET "zones/${_domain_id}/records"
if ! printf "$response" | grep \"id\": >/dev/null; then
_err "Error"
return 1
fi
count=$(printf "%s\n" "$response" | _egrep_o \"name\":\"$fulldomain\" | wc -l)
_debug count "$count"
if [ "$count" = "0" ]; then
_info "Adding record"
if _LUA_rest POST "zones/$_domain_id/records" "{\"type\":\"TXT\",\"name\":\"$fulldomain.\",\"content\":\"$txtvalue\",\"ttl\":120}"; then
if printf -- "%s" "$response" | grep $fulldomain >/dev/null; then
_info "Added"
#todo: check if the record takes effect
return 0
else
_err "Add txt record error."
return 1
fi
fi
_err "Add txt record error."
else
_info "Updating record"
record_id=$(printf "%s\n" "$response" | _egrep_o \"id\":[^,]*,\"name\":\"$fulldomain.\",\"type\":\"TXT\" | cut -d: -f2 | cut -d, -f1)
_debug "record_id" $record_id
_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
_info "Updated!"
#todo: check if the record takes effect
return 0
fi
_err "Update error"
return 1
fi
}
#fulldomain
dns_lua_rm() {
fulldomain=$1
}
#################### Private functions bellow ##################################
#_acme-challenge.www.domain.com
#returns
# _sub_domain=_acme-challenge.www
# _domain=domain.com
# _domain_id=sdjkglgdfewsdfg
_get_root() {
domain=$1
i=2
p=1
if ! _LUA_rest GET "zones"; then
return 1
fi
while [ '1' ]; do
h=$(printf $domain | cut -d . -f $i-100)
if [ -z "$h" ]; then
#not valid
return 1
fi
if printf $response | grep \"name\":\"$h\" >/dev/null; then
_domain_id=$(printf "%s\n" "$response" | _egrep_o \"id\":[^,]*,\"name\":\"$h\" | cut -d : -f 2 | cut -d , -f 1)
if [ "$_domain_id" ]; then
_sub_domain=$(printf $domain | cut -d . -f 1-$p)
_domain=$h
return 0
fi
return 1
fi
p=$i
i=$(expr $i + 1)
done
return 1
}
_LUA_rest() {
m=$1
ep="$2"
data="$3"
_debug $ep
_H1="Accept: application/json"
_H2="Authorization: Basic $LUA_auth"
if [ "$data" ]; then
_debug data "$data"
response="$(_post "$data" "$LUA_Api/$ep" "" $m)"
else
response="$(_get "$LUA_Api/$ep")"
fi
if [ "$?" != "0" ]; then
_err "error $ep"
return 1
fi
_debug2 response "$response"
return 0
}
+144
View File
@@ -0,0 +1,144 @@
#!/usr/bin/env sh
# bug reports to dev@1e.ca
# ME_Key=qmlkdjflmkqdjf
# ME_Secret=qmsdlkqmlksdvnnpae
ME_Api=https://api.dnsmadeeasy.com/V2.0/dns/managed
######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_me_add() {
fulldomain=$1
txtvalue=$2
if [ -z "$ME_Key" ] || [ -z "$ME_Secret" ]; then
_err "You didn't specify DNSMadeEasy api key and secret yet."
_err "Please create you key and try again."
return 1
fi
#save the api key and email to the account conf file.
_saveaccountconf ME_Key "$ME_Key"
_saveaccountconf ME_Secret "$ME_Secret"
_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"
_me_rest GET "${_domain_id}/records?recordName=$_sub_domain&type=TXT"
if ! printf "$response" | grep \"totalRecords\": >/dev/null; then
_err "Error"
return 1
fi
count=$(printf "%s\n" "$response" | _egrep_o \"totalRecords\":[^,]* | cut -d : -f 2)
_debug count "$count"
if [ "$count" = "0" ]; then
_info "Adding record"
if _me_rest POST "$_domain_id/records/" "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"value\":\"$txtvalue\",\"gtdLocation\":\"DEFAULT\",\"ttl\":120}"; then
if printf -- "%s" "$response" | grep \"id\": >/dev/null; then
_info "Added"
#todo: check if the record takes effect
return 0
else
_err "Add txt record error."
return 1
fi
fi
_err "Add txt record error."
else
_info "Updating record"
record_id=$(printf "%s\n" "$response" | _egrep_o \"id\":[^,]* | cut -d : -f 2 | head -n 1)
_debug "record_id" $record_id
_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
_info "Updated"
#todo: check if the record takes effect
return 0
fi
_err "Update error"
return 1
fi
}
#fulldomain
dns_me_rm() {
fulldomain=$1
}
#################### Private functions bellow ##################################
#_acme-challenge.www.domain.com
#returns
# _sub_domain=_acme-challenge.www
# _domain=domain.com
# _domain_id=sdjkglgdfewsdfg
_get_root() {
domain=$1
i=2
p=1
while [ '1' ]; do
h=$(printf $domain | cut -d . -f $i-100)
if [ -z "$h" ]; then
#not valid
return 1
fi
if ! _me_rest GET "name?domainname=$h"; then
return 1
fi
if printf $response | grep \"name\":\"$h\" >/dev/null; then
_domain_id=$(printf "%s\n" "$response" | _egrep_o \"id\":[^,]* | head -n 1 | cut -d : -f 2)
if [ "$_domain_id" ]; then
_sub_domain=$(printf $domain | cut -d . -f 1-$p)
_domain=$h
return 0
fi
return 1
fi
p=$i
i=$(expr $i + 1)
done
return 1
}
_me_rest() {
m=$1
ep="$2"
data="$3"
_debug $ep
cdate=$(date -u +"%a, %d %b %Y %T %Z")
hmac=$(printf "$cdate" | _hmac sha1 "$ME_Secret" 1)
_H1="x-dnsme-apiKey: $ME_Key"
_H2="x-dnsme-requestDate: $cdate"
_H3="x-dnsme-hmac: $hmac"
if [ "$data" ]; then
_debug data "$data"
response="$(_post "$data" "$ME_Api/$ep" "" $m)"
else
response="$(_get "$ME_Api/$ep")"
fi
if [ "$?" != "0" ]; then
_err "error $ep"
return 1
fi
_debug2 response "$response"
return 0
}
+8 -8
View File
@@ -6,8 +6,6 @@
#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.
######## 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"
@@ -15,16 +13,18 @@ dns_myapi_add() {
fulldomain=$1 fulldomain=$1
txtvalue=$2 txtvalue=$2
_err "Not implemented!" _err "Not implemented!"
return 1; return 1
} }
#fulldomain
dns_myapi_rm() {
fulldomain=$1
}
#################### Private functions bellow ################################## #################### Private functions bellow ##################################
_info() { _info() {
if [ -z "$2" ] ; then if [ -z "$2" ]; then
echo "[$(date)] $1" echo "[$(date)] $1"
else else
echo "[$(date)] $1='$2'" echo "[$(date)] $1='$2'"
@@ -37,7 +37,7 @@ _err() {
} }
_debug() { _debug() {
if [ -z "$DEBUG" ] ; then if [ -z "$DEBUG" ]; then
return return
fi fi
_err "$@" _err "$@"
@@ -45,7 +45,7 @@ _debug() {
} }
_debug2() { _debug2() {
if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ] ; then if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
_debug "$@" _debug "$@"
fi fi
return return
+294
View File
@@ -0,0 +1,294 @@
#!/usr/bin/env sh
#Applcation Key
#OVH_AK="sdfsdfsdfljlbjkljlkjsdfoiwje"
#
#Application Secret
#OVH_AS="sdfsafsdfsdfdsfsdfsa"
#
#Consumer Key
#OVH_CK="sdfsdfsdfsdfsdfdsf"
#OVH_END_POINT=ovh-eu
#'ovh-eu'
OVH_EU='https://eu.api.ovh.com/1.0'
#'ovh-ca':
OVH_CA='https://ca.api.ovh.com/1.0'
#'kimsufi-eu'
KSF_EU='https://eu.api.kimsufi.com/1.0'
#'kimsufi-ca'
KSF_CA='https://ca.api.kimsufi.com/1.0'
#'soyoustart-eu'
SYS_EU='https://eu.api.soyoustart.com/1.0'
#'soyoustart-ca'
SYS_CA='https://ca.api.soyoustart.com/1.0'
#'runabove-ca'
RAV_CA='https://api.runabove.com/1.0'
wiki="https://github.com/Neilpang/acme.sh/wiki/How-to-use-OVH-domain-api"
ovh_success="https://github.com/Neilpang/acme.sh/wiki/OVH-Success"
_ovh_get_api() {
_ogaep="$1"
case "${_ogaep}" in
ovh-eu | ovheu)
printf "%s" $OVH_EU
return
;;
ovh-ca | ovhca)
printf "%s" $OVH_CA
return
;;
kimsufi-eu | kimsufieu)
printf "%s" $KSF_EU
return
;;
kimsufi-ca | kimsufica)
printf "%s" $KSF_CA
return
;;
soyoustart-eu | soyoustarteu)
printf "%s" $SYS_EU
return
;;
soyoustart-ca | soyoustartca)
printf "%s" $SYS_CA
return
;;
runabove-ca | runaboveca)
printf "%s" $RAV_CA
return
;;
*)
_err "Unknown parameter : $1"
return 1
;;
esac
}
######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_ovh_add() {
fulldomain=$1
txtvalue=$2
if [ -z "$OVH_AK" ] || [ -z "$OVH_AS" ]; then
_err "You don't specify OVH application key and application secret yet."
_err "Please create you key and try again."
return 1
fi
#save the api key and email to the account conf file.
_saveaccountconf OVH_AK "$OVH_AK"
_saveaccountconf OVH_AS "$OVH_AS"
if [ -z "$OVH_END_POINT" ]; then
OVH_END_POINT="ovh-eu"
fi
_info "Using OVH endpoint: $OVH_END_POINT"
if [ "$OVH_END_POINT" != "ovh-eu" ]; then
_saveaccountconf OVH_END_POINT "$OVH_END_POINT"
fi
OVH_API="$(_ovh_get_api $OVH_END_POINT)"
_debug OVH_API "$OVH_API"
if [ -z "$OVH_CK" ]; then
_info "OVH consumer key is empty, Let's get one:"
if ! _ovh_authentication; then
_err "Can not get consumer key."
fi
#return and wait for retry.
return 1
fi
_info "Checking authentication"
response="$(_ovh_rest GET "domain/")"
if _contains "$response" "INVALID_CREDENTIAL"; then
_err "The consumer key is invalid: $OVH_CK"
_err "Please retry to create a new one."
_clearaccountconf OVH_CK
return 1
fi
_info "Consumer key is ok."
_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"
_ovh_rest GET "domain/zone/$_domain/record?fieldType=TXT&subDomain=$_sub_domain"
if _contains "$response" '\[\]' || _contains "$response" "This service does not exist"; then
_info "Adding record"
if _ovh_rest POST "domain/zone/$_domain/record" "{\"fieldType\":\"TXT\",\"subDomain\":\"$_sub_domain\",\"target\":\"$txtvalue\",\"ttl\":60}"; then
if _contains "$response" "$txtvalue"; then
_ovh_rest POST "domain/zone/$_domain/refresh"
_debug "Refresh:$response"
_info "Added, sleeping 10 seconds"
sleep 10
return 0
fi
fi
_err "Add txt record error."
else
_info "Updating record"
record_id=$(printf "%s" "$response" | tr -d "[]" | cut -d , -f 1)
if [ -z "$record_id" ]; then
_err "Can not get record id."
return 1
fi
_debug "record_id" $record_id
if _ovh_rest PUT "domain/zone/$_domain/record/$record_id" "{\"target\":\"$txtvalue\",\"subDomain\":\"$_sub_domain\",\"ttl\":60}"; then
if _contains "$response" "null"; then
_ovh_rest POST "domain/zone/$_domain/refresh"
_debug "Refresh:$response"
_info "Updated, sleeping 10 seconds"
sleep 10
return 0
fi
fi
_err "Update error"
return 1
fi
}
#fulldomain
dns_ovh_rm() {
fulldomain=$1
}
#################### Private functions bellow ##################################
_ovh_authentication() {
_H1="X-Ovh-Application: $OVH_AK"
_H2="Content-type: application/json"
_H3=""
_H4=""
_ovhdata='{"accessRules": [{"method": "GET","path": "/*"},{"method": "POST","path": "/*"},{"method": "PUT","path": "/*"},{"method": "DELETE","path": "/*"}],"redirection":"'$ovh_success'"}'
response="$(_post "$_ovhdata" "$OVH_API/auth/credential")"
_debug3 response "$response"
validationUrl="$(echo "$response" | _egrep_o "validationUrl\":\"[^\"]*\"" | _egrep_o "http.*\"" | tr -d '"')"
if [ -z "$validationUrl" ]; then
_err "Unable to get validationUrl"
return 1
fi
_debug validationUrl "$validationUrl"
consumerKey="$(echo "$response" | _egrep_o "consumerKey\":\"[^\"]*\"" | cut -d : -f 2 | tr -d '"')"
if [ -z "$consumerKey" ]; then
_err "Unable to get consumerKey"
return 1
fi
_debug consumerKey "$consumerKey"
OVH_CK="$consumerKey"
_saveaccountconf OVH_CK "$OVH_CK"
_info "Please open this link to do authentication: $(__green "$validationUrl")"
_info "Here is a guide for you: $(__green "$wiki")"
_info "Please retry after the authentication is done."
}
#_acme-challenge.www.domain.com
#returns
# _sub_domain=_acme-challenge.www
# _domain=domain.com
# _domain_id=sdjkglgdfewsdfg
_get_root() {
domain=$1
i=2
p=1
while [ '1' ]; do
h=$(printf $domain | cut -d . -f $i-100)
if [ -z "$h" ]; then
#not valid
return 1
fi
if ! _ovh_rest GET "domain/zone/$h"; then
return 1
fi
if ! _contains "$response" "This service does not exist" >/dev/null; then
_sub_domain=$(printf $domain | cut -d . -f 1-$p)
_domain=$h
return 0
fi
p=$i
i=$(expr $i + 1)
done
return 1
}
_ovh_timestamp() {
_H1=""
_H2=""
_H3=""
_H4=""
_H5=""
_get "$OVH_API/auth/time" "" 30
}
_ovh_rest() {
m=$1
ep="$2"
data="$3"
_debug $ep
_ovh_url="$OVH_API/$ep"
_debug2 _ovh_url "$_ovh_url"
_ovh_t="$(_ovh_timestamp)"
_debug2 _ovh_t "$_ovh_t"
_ovh_p="$OVH_AS+$OVH_CK+$m+$_ovh_url+$data+$_ovh_t"
_debug _ovh_p "$_ovh_p"
_ovh_hex="$(printf "%s" "$_ovh_p" | _digest sha1 hex)"
_debug2 _ovh_hex "$_ovh_hex"
_H1="X-Ovh-Application: $OVH_AK"
_H2="X-Ovh-Signature: \$1\$$_ovh_hex"
_debug2 _H2 "$_H2"
_H3="X-Ovh-Timestamp: $_ovh_t"
_H4="X-Ovh-Consumer: $OVH_CK"
_H5="Content-Type: application/json;charset=utf-8"
if [ "$data" ] || [ "$m" = "POST" ] || [ "$m" = "PUT" ]; then
_debug data "$data"
response="$(_post "$data" "$_ovh_url" "" $m)"
else
response="$(_get "$_ovh_url")"
fi
if [ "$?" != "0" ]; then
_err "error $ep"
return 1
fi
_debug2 response "$response"
return 0
}
+139
View File
@@ -0,0 +1,139 @@
#!/usr/bin/env sh
#PowerDNS Emdedded API
#https://doc.powerdns.com/md/httpapi/api_spec/
#
#PDNS_Url="http://ns.example.com:8081"
#PDNS_ServerId="localhost"
#PDNS_Token="0123456789ABCDEF"
#PDNS_Ttl=60
DEFAULT_PDNS_TTL=60
######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "123456789ABCDEF0000000000000000000000000000000000000"
dns_pdns_add() {
fulldomain=$1
txtvalue=$2
if [ -z "$PDNS_Url" ]; then
_err "You don't specify PowerDNS address."
_err "Please set PDNS_Url and try again."
return 1
fi
if [ -z "$PDNS_ServerId" ]; then
_err "You don't specify PowerDNS server id."
_err "Please set you PDNS_ServerId and try again."
return 1
fi
if [ -z "$PDNS_Token" ]; then
_err "You don't specify PowerDNS token."
_err "Please create you PDNS_Token and try again."
return 1
fi
if [ -z "$PDNS_Ttl" ]; then
PDNS_Ttl=$DEFAULT_PDNS_TTL
fi
#save the api addr and key to the account conf file.
_saveaccountconf PDNS_Url "$PDNS_Url"
_saveaccountconf PDNS_ServerId "$PDNS_ServerId"
_saveaccountconf PDNS_Token "$PDNS_Token"
if [ "$PDNS_Ttl" != "$DEFAULT_PDNS_TTL" ]; then
_saveaccountconf PDNS_Ttl "$PDNS_Ttl"
fi
_debug "First detect the root zone"
if ! _get_root $fulldomain; then
_err "invalid domain"
return 1
fi
_debug _domain "$_domain"
if ! set_record "$_domain" "$fulldomain" "$txtvalue"; then
return 1
fi
return 0
}
#fulldomain
dns_pdns_rm() {
fulldomain=$1
}
set_record() {
_info "Adding record"
root=$1
full=$2
txtvalue=$3
if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root." "{\"rrsets\": [{\"name\": \"$full.\", \"changetype\": \"REPLACE\", \"type\": \"TXT\", \"ttl\": $PDNS_Ttl, \"records\": [{\"name\": \"$full.\", \"type\": \"TXT\", \"content\": \"\\\"$txtvalue\\\"\", \"disabled\": false, \"ttl\": $PDNS_Ttl}]}]}"; then
_err "Set txt record error."
return 1
fi
if ! _pdns_rest "PUT" "/api/v1/servers/$PDNS_ServerId/zones/$root./notify"; then
_err "Notify servers error."
return 1
fi
return 0
}
#################### Private functions bellow ##################################
#_acme-challenge.www.domain.com
#returns
# _domain=domain.com
_get_root() {
domain=$1
i=1
p=1
if _pdns_rest "GET" "/api/v1/servers/$PDNS_ServerId/zones"; then
_zones_response=$response
fi
while [ '1' ]; do
h=$(printf $domain | cut -d . -f $i-100)
if [ -z "$h" ]; then
return 1
fi
if printf "$_zones_response" | grep "\"name\": \"$h.\"" >/dev/null; then
_domain=$h
return 0
fi
p=$i
i=$(expr $i + 1)
done
_debug "$domain not found"
return 1
}
_pdns_rest() {
method=$1
ep=$2
data=$3
_H1="X-API-Key: $PDNS_Token"
if [ ! "$method" = "GET" ]; then
_debug data "$data"
response="$(_post "$data" "$PDNS_Url$ep" "" "$method")"
else
response="$(_get "$PDNS_Url$ep")"
fi
if [ "$?" != "0" ]; then
_err "error $ep"
return 1
fi
_debug2 response "$response"
return 0
}