207 Commits
2.8.0 ... 2.8.1

Author SHA1 Message Date
neil
a8f0fd1fff Merge pull request #2240 from Neilpang/dev
use mutable
2019-04-29 21:59:42 +08:00
neilpang
a89d50d34e use mutable 2019-04-29 21:52:22 +08:00
neil
6489cfbce6 Merge pull request #2239 from Neilpang/dev
sync
2019-04-29 21:46:10 +08:00
neilpang
d10f40f109 fix idn issue. 2019-04-29 21:44:25 +08:00
neilpang
a7420ca3d4 typo 2019-04-27 09:17:26 +08:00
neil
4dcd1f3e65 Merge pull request #2233 from Neilpang/dev
fix https://github.com/Neilpang/acme.sh/issues/2195
2019-04-26 23:59:32 +08:00
neilpang
e46b392a8d Merge branch 'dev' of https://github.com/Neilpang/acme.sh into dev 2019-04-26 23:58:09 +08:00
neilpang
47ff768b70 fix https://github.com/Neilpang/acme.sh/issues/2195 2019-04-26 23:57:40 +08:00
neil
ba4bd3ed55 Merge pull request #2232 from Neilpang/dev
sync
2019-04-26 23:52:01 +08:00
neil
68428a5d5e Merge pull request #2205 from kirpichiki/dns_cf_invalid_domain
CloudFlare dns invalid domain
2019-04-26 23:50:50 +08:00
neil
28694e8afb Merge pull request #2207 from Kimmax/dns_hostingde_missing_templateValues
dns_hostingde.sh zoneConfig missing templateValues object
2019-04-26 23:49:41 +08:00
neil
c420a0ae2b Merge pull request #2222 from dim0x69/master
Implement Update Account Information for ACMEv2
2019-04-26 23:49:10 +08:00
neil
a85e50f465 Merge pull request #2229 from mod242/master
Create DDNSS API based on the work of helbgd
2019-04-26 23:47:19 +08:00
neilpang
4962cc3da8 fix idn issues 2019-04-26 23:44:25 +08:00
mod242
bb703281a2 Update dns_ddnss.sh 2019-04-25 16:18:52 +02:00
neilpang
52f5564122 fix image links 2019-04-25 20:58:13 +08:00
neil
1dc420ce51 Merge pull request #2139 from loonies/dns-loopia-api-endpoint
Make the Loopia API endpoint configurable
2019-04-25 20:52:38 +08:00
mod242
20af1ceb7d Cleanup comment 2019-04-24 19:38:07 +02:00
mod242
ec982ccacb Cleanup according to styleguide 2019-04-24 16:15:01 +02:00
mod242
a97e74b2d4 Update dns_ddnss.sh 2019-04-24 16:05:44 +02:00
mod242
fecc5b09f8 Removed -e and changed tail to funktion 2019-04-24 14:57:48 +02:00
mod242
d1030eb0b2 Create DDNSS API based on the work of helbgd 2019-04-24 14:03:54 +02:00
neilpang
e6df1828d9 fix https://github.com/Neilpang/acme.sh/issues/2192 2019-04-21 12:37:26 +08:00
neilpang
9ff53fea98 Merge branch 'dev' of https://github.com/Neilpang/acme.sh into dev 2019-04-21 12:23:57 +08:00
neilpang
4f1888d2ea fix https://github.com/Neilpang/acme.sh/issues/2192 2019-04-21 12:23:06 +08:00
neil
53dcd0dee9 Merge pull request #2224 from honzahommer/feat-install-noprofile
Add `--noprofile` option to `install` command
2019-04-20 13:19:27 +08:00
neil
e291ada371 Merge pull request #2226 from Neilpang/dev
sync
2019-04-20 13:09:38 +08:00
neilpang
9c9fed749a fix https://github.com/Neilpang/acme.sh/issues/2225
make NSUPDATE_SERVER can be overwritten
2019-04-20 12:49:51 +08:00
Honza Hommer
61556a54e2 feat: add --noprofile option to install command 2019-04-19 17:27:32 +02:00
dim0x69
79e2f8a2e5 implement account update for acmev2 2019-04-17 14:51:07 +02:00
neil
d1f39e6217 Merge pull request #706 from palhaland/dev
Shell script for deploying changes to a routeros server.
2019-04-10 20:49:05 +08:00
neil
d01ab227b8 Merge pull request #2209 from Neilpang/dev
sync
2019-04-06 23:06:36 +08:00
neilpang
0cfeee4ded fix format 2019-04-06 16:48:17 +08:00
neilpang
c97e43dcd6 fix format 2019-04-06 16:45:58 +08:00
neilpang
eda321954d fix https://github.com/Neilpang/acme.sh/issues/2208 2019-04-06 16:05:08 +08:00
Kimmax
64e5392788 Zone delete also needs new "templateValues" field 2019-04-02 23:29:58 +00:00
Kimmax
987f95221c Added missing "templateValues" object to "zoneConfig" on "_hostingde_getZoneConfig" 2019-04-02 23:08:39 +00:00
Gorbachev
6e917d156c Trim double quotes for email and key
Currently dns_cf generates headers like this: 'X-Auth-Email: "sample@mail.com"'. Cloudflare API responses 400 BadRequest for quoted headers with message "Invalid format for X-Auth-Email header".
2019-04-02 18:05:52 +03:00
neilpang
36e697b344 Merge branch 'dev' of https://github.com/Neilpang/acme.sh into dev 2019-03-31 21:46:45 +08:00
neilpang
c2d0d4d28c root domain as dns alias mode 2019-03-31 21:46:14 +08:00
Miodrag Tokić
aec9c3c9a4 Double quote unquoted variables
Double quote unquoted variables to prevent globbing and word splitting.
2019-03-28 16:34:13 +01:00
Miodrag Tokić
0daa225e26 Make the Loopia API endpoint configurable
Loopia provides hosting in several countries. Each hosting location has
it's own API endpoint, such as "https://api.loopia.<TLD>/RPCSERV", where
<TLD> is one of: com, no, rs, se.

The current LOOPIA_Api variable is hard-coded to ".se". This prevents
using the Loopia DNS API on other hosting locations.

This commit makes the LOOPIA_Api variable configurable and it falls back
to ".se" TLD if LOOPIA_Api is not set.

References:

 - https://www.loopia.com/api/authentication/
 - https://www.loopia.no/api/authentication/
 - https://www.loopia.rs/api/authentication/
 - https://www.loopia.se/api/authentication/
2019-03-27 13:58:23 +01:00
Miodrag Tokić
85be2b85fd Fix error message language 2019-03-27 13:58:23 +01:00
Miodrag Tokić
a7d6146169 Extract configuration saving code to function 2019-03-27 13:58:23 +01:00
Miodrag Tokić
978ec91107 Extract configuration loading code to function 2019-03-27 13:58:23 +01:00
neil
297859c5bc Merge pull request #2191 from temoffey/gcore_cdn_deploy
fix gcore_cdn_deploy
2019-03-23 21:46:40 +08:00
temoffey
bea52aa743 remove use grep -E 2019-03-23 16:29:33 +03:00
neil
54f1be69c7 Merge pull request #2190 from Neilpang/dev
sync
2019-03-23 16:51:40 +08:00
neil
a4cc9ef2cc Merge pull request #2178 from temoffey/gcore_cdn_deploy
Gcore cdn deploy
2019-03-23 11:06:16 +08:00
neil
4f47594b6d Merge pull request #2189 from scj643/master
Fixed Digital Ocean dns api
2019-03-23 10:57:39 +08:00
Charles Surett
189a7766d4 Made dns_dgon.sh use _lower_case
Fixed private function which breaks on embedded systems before.
2019-03-22 18:43:06 -04:00
temoffey
df9174577a remove check jq 2019-03-22 23:00:47 +03:00
temoffey
bd1bb7a71b fix syntax 2019-03-22 20:08:35 +03:00
temoffey
4b6e7e6c37 remove use while, [[ ]], array 2019-03-22 20:02:59 +03:00
temoffey
8896642e25 fix syntax 2019-03-22 20:01:39 +03:00
temoffey
0ecb5a3fec fix syntax 2019-03-22 04:31:58 +03:00
temoffey
d289b0b450 fix syntax 2019-03-22 04:21:41 +03:00
temoffey
b8489464b3 remove use awk, jq, curl 2019-03-22 03:41:26 +03:00
Pål Håland
ebaa3f39e4 Merge remote-tracking branch 'origin/dev' into dev 2019-03-21 15:54:02 +01:00
Pål Håland
e19753dcde Moved documentation from deploy/README.md to deploy/routeros.sh 2019-03-21 15:53:11 +01:00
neil
13255a3762 Merge pull request #2185 from Neilpang/dev
syc
2019-03-21 22:26:24 +08:00
neil
15ce2a3d67 Merge pull request #2161 from sotux/dev
dnsapi: add deSEC.io api support
2019-03-21 20:02:24 +08:00
James Qian
3bb97b81de dnsapi: add deSEC.io api support
Signed-off-by: James Qian <sotux82@gmail.com>
2019-03-21 10:58:13 +08:00
neil
37161d3017 Merge pull request #2105 from TheLastProject/feature/dns-openprovider
Add OpenProvider support
2019-03-20 23:18:43 +08:00
Sylvia van Os
4532037e4f Merge branch 'dev' into feature/dns-openprovider 2019-03-20 16:12:57 +01:00
Sylvia van Os
0fe08e1b33 Merge branch 'dev' into feature/dns-openprovider 2019-03-20 16:12:08 +01:00
neilpang
236acbd6e8 move to wiki 2019-03-20 23:11:13 +08:00
temoffey
16b0704acc remove readme 2019-03-20 18:10:53 +03:00
neilpang
61bcd67a5d move to wiki 2019-03-20 23:03:49 +08:00
neilpang
0629c2a086 move to wiki 2019-03-20 23:01:24 +08:00
neilpang
fbdc5a0eb5 fix https://github.com/Neilpang/acme.sh/issues/2179 2019-03-20 22:52:40 +08:00
neil
68a8d81b6a Merge pull request #2177 from vbrandl/feature/deploy-mailcow
Add deploy hook for mailcow
2019-03-20 21:13:26 +08:00
neil
a368301dbf Merge pull request #2176 from bz-heilig/patch-1
Update README.md
2019-03-20 20:40:49 +08:00
temoffey
89989adcad fix syntax 2019-03-20 14:05:18 +03:00
temoffey
95cdb4b2bc fix syntax 2019-03-20 14:02:11 +03:00
temoffey
228c835466 gcore_cdn_deploy 2019-03-20 03:03:10 +03:00
Valentin Brandl
d604166194 Fix formatting 2019-03-19 19:15:31 +01:00
Valentin Brandl
d643a2ff13 Check if mailcow path is set and fix directory check 2019-03-19 19:09:25 +01:00
Valentin Brandl
b581a171f0 Add documentation for mailcow deploy hook 2019-03-19 18:43:07 +01:00
Valentin Brandl
307336cfc4 Add deploy hook for mailcow
This hook will copy the key and certificate chain to the specified
mailcow installation (as described in
https://mailcow.github.io/mailcow-dockerized-docs/firststeps-ssl/#use-own-certificates)
and restarts the containers, that are using the certificates.

The hook has 2 parameters:

* `DEPLOY_MAILCOW_PATH`: The path to the mailcow installation (required)
* `DEPLOY_MAILCOW_RELOAD`: The reload command, defaults to `docker-compose restart postfix-mailcow dovecot-mailcow nginx-mailcow`
2019-03-19 18:42:47 +01:00
neil
fc30171725 Merge pull request #2175 from loial/dns_gdnsdk_fix
dns_gdnsdk: Fixed stupid regex error, want literal "-", not a range
2019-03-19 22:20:15 +08:00
bz-heilig
34be7e99f0 Update README.md
Added links for do.de API token creation and documentation of API.
2019-03-19 15:04:37 +01:00
Herman Sletteng
7679df062c dns_gdnsdk: Fixed stupid regex error, want literal "-", not a range 2019-03-19 14:16:13 +01:00
Sylvia van Os
71cfd874ae Fix SC2116 2019-03-18 16:10:58 +01:00
Sylvia van Os
08be0c374a Merge branch 'feature/dns-openprovider' of https://github.com/TheLastProject/acme.sh into feature/dns-openprovider 2019-03-18 15:59:08 +01:00
Sylvia van Os
7decce9718 Resolve comments on pull request 2019-03-18 15:43:52 +01:00
Sylvia van Os
22bab90a90 Merge branch 'dev' into feature/dns-openprovider 2019-03-18 12:54:19 +01:00
neil
02882fb327 Merge pull request #2168 from Neilpang/dev
sync
2019-03-17 23:33:02 +08:00
neilpang
c74d597c84 add debug info 2019-03-16 18:34:44 +08:00
neilpang
653c77e852 update 2019-03-16 15:09:49 +08:00
neilpang
2b36f4f57f update 2019-03-16 15:07:34 +08:00
neilpang
82b0ebb787 minor, remove dns records only when it's added success 2019-03-16 14:53:02 +08:00
neilpang
3f35006c26 fix error message 2019-03-16 14:35:33 +08:00
neilpang
2ffd8637e1 fix standalone content 2019-03-16 14:28:24 +08:00
neil
44c1572b8f Merge pull request #2166 from Neilpang/dev
sync
2019-03-16 14:18:49 +08:00
neilpang
d0d749074e fix for solaris 2019-03-16 14:00:15 +08:00
neilpang
dbc44c08df fix for solaris 2019-03-16 13:38:17 +08:00
Steven M. Miano
46fbd7f1e1 support ultradns.com api (#2117)
support ultradns.com api (#2117)
2019-03-14 20:41:13 +08:00
tambetliiv
5048c6c22a Add zone.ee (zone.eu) DNS API (#2151)
* add zone.ee (zone.eu) dns api
2019-03-14 20:20:39 +08:00
neil
709d82e764 sync
sync
2019-03-13 21:32:10 +08:00
neil
9d64b35ed8 Merge pull request #2157 from hosting-de/fix/read-endpoint
hosting.de: reading endpoint
2019-03-13 21:29:59 +08:00
neil
0f00862e5e support windows scheduler (#2158)
* support Windows scheduler. fix https://github.com/Neilpang/acme.sh/issues/2145
2019-03-13 21:28:30 +08:00
Oliver Dick
532e79c7d0 Fix reading endpoint 2019-03-13 14:14:40 +01:00
neilpang
4ebad10557 fix format 2019-03-13 21:11:59 +08:00
neilpang
0b04a7f17f fix format 2019-03-13 20:49:26 +08:00
neilpang
77f96b386e support Windows scheduler. fix https://github.com/Neilpang/acme.sh/issues/2145 2019-03-13 20:42:02 +08:00
Sylvia van Os
ea86ddc693 Merge branch 'dev' into feature/dns-openprovider 2019-03-13 10:22:40 +01:00
neil
e3e43d0ba0 Merge pull request #2155 from Neilpang/dev
sync
2019-03-12 22:20:00 +08:00
neil
b10929fe23 Merge pull request #2154 from Neilpang/vv
use acme v2 as default
2019-03-12 22:17:35 +08:00
neil
f512cb8e35 Merge pull request #2081 from nederhost/master
Add support for NederHost DNS API
2019-03-12 22:06:47 +08:00
Sebastiaan Hoogeveen
4f240f538d Merge branch 'master' of https://github.com/nederhost/acme.sh 2019-03-12 14:39:26 +01:00
Sebastiaan Hoogeveen
db6db6a4e9 Removed overwriting of the HTTP header file before sending a request. 2019-03-12 14:36:42 +01:00
neilpang
f2add8de94 use acme v2 as default 2019-03-12 21:16:15 +08:00
Sebastiaan Hoogeveen
88c6621cfe Merge branch 'dev' into master 2019-03-12 11:59:13 +01:00
neil
c152b6f0ad Merge pull request #2152 from Neilpang/dev
sync
2019-03-11 21:32:28 +08:00
neilpang
53c0188248 fix https://github.com/Neilpang/acme.sh/issues/2150 2019-03-11 21:30:24 +08:00
neilpang
725addafda fix format 2019-03-09 09:13:49 +08:00
Sylvia van Os
19628c4732 Merge branch 'dev' into feature/dns-openprovider 2019-03-08 16:44:36 +01:00
Sylvia van Os
04eaf7f175 Add OpenProvider support 2019-03-08 16:42:52 +01:00
neilpang
f5850d0c08 fix format 2019-03-08 22:20:56 +08:00
neil
855eb8355a Merge pull request #2143 from 5ll/core-networks-support
Adding Support for Core-Networks API
2019-03-08 22:14:41 +08:00
neil
fdbb7fd30f Merge pull request #2144 from Neilpang/dev
fix https://github.com/Neilpang/acme.sh/issues/2141
2019-03-08 22:09:12 +08:00
5ll
30d0ac0784 Updated README with Core-Networks support 2019-03-08 10:48:06 +01:00
5ll
3d5c75420a Changed Order 2019-03-08 10:46:35 +01:00
5ll
1d5967d143 Updated README with Core-Networks support 2019-03-08 10:45:36 +01:00
5ll
110a41d18d initial commit
DNS API for acme.sh for Core-Networks (https://beta.api.core-networks.de/doc/)
2019-03-08 10:33:09 +01:00
neil
a3d8b9935a fix https://github.com/Neilpang/acme.sh/issues/2141 2019-03-08 14:31:11 +08:00
neil
08357e3cb0 Merge pull request #2137 from Neilpang/dev
Dev
2019-03-05 21:50:47 +08:00
neil
162a445a50 Merge pull request #2136 from Neilpang/cmd
Cmd
2019-03-05 21:47:50 +08:00
neilpang
c7257bcf46 base64 hooks, fix https://github.com/Neilpang/acme.sh/issues/1969 2019-03-05 21:44:34 +08:00
neilpang
dfca8c09e0 fix format 2019-03-05 21:22:03 +08:00
neilpang
7690f73e81 base64 encode reloadcmd.
fix https://github.com/Neilpang/acme.sh/issues/2134
2019-03-05 21:05:10 +08:00
Pål Håland
86fbb5952e Use env sh 2019-03-02 16:39:41 +01:00
Sebastiaan Hoogeveen
78c92642e4 Merge branch 'dev' into master 2019-03-02 13:58:56 +01:00
neilpang
b3f6129718 fix https://github.com/Neilpang/acme.sh/issues/2122 2019-03-02 20:44:08 +08:00
neil
2a52603b7e Merge pull request #2128 from the729/fix-qiniu-base64
fix deploy/qiniu.sh base64
2019-03-01 22:44:23 +08:00
neil
e6f9f258ec Merge pull request #2129 from the729/fix-qiniu-doc
fix doc of qiniu deploy script
2019-03-01 22:40:45 +08:00
tianji
22e7b4c911 fix doc of qiniu deploy script
A leading dot should be included when updating wildcard domains.
2019-02-28 23:51:43 +08:00
tianji
af5f7a7779 fix deploy/qiniu.sh base64
According to the doc (https://developer.qiniu.com/kodo/manual/1231/appendix#1), we should use URL-safe base64 instead of plain base64 for token calculation.
2019-02-28 23:43:58 +08:00
neil
693d692a47 sync (#2127)
* Support for MyDevil.net (#2076)

support mydevil

* Fix verification for namecheap domains not *owned* by the calling user (#2106)

* Peb (#2126)

* support pebble
* support async finalize order

* add Pebble
2019-02-27 20:41:50 +08:00
neilpang
81f0189d23 add Pebble 2019-02-27 20:40:10 +08:00
neil
e7f7e96d58 Peb (#2126)
* support pebble
* support async finalize order
2019-02-27 20:36:13 +08:00
Pål Håland
1dab2ac7d3 Updated with latest changes from Neilpang/dev 2019-02-26 17:41:24 +01:00
Timothy Nelson
ec54074392 Fix verification for namecheap domains not *owned* by the calling user (#2106) 2019-02-25 19:19:36 +08:00
Marcin Konicki
16a0f40ac2 Support for MyDevil.net (#2076)
support mydevil
2019-02-20 09:40:36 +08:00
neil
f84103918a Merge pull request #2101 from Neilpang/dev
Doh (#2100)
2019-02-19 22:01:39 +08:00
neil
b5ca9bbab2 Doh (#2100)
support doh to poll dns status
fix https://github.com/Neilpang/acme.sh/issues/2015
2019-02-19 21:39:06 +08:00
neil
ff38d2bba6 Merge pull request #2099 from Neilpang/dev
Dev
2019-02-18 21:20:35 +08:00
neil
8f2a8a0051 Merge pull request #1357 from martgras/patch-1
avoid side effects in _printargs
2019-02-18 21:16:14 +08:00
neilpang
97147b594b fix https://github.com/Neilpang/acme.sh/issues/2096 2019-02-18 20:57:13 +08:00
neilpang
a0ec5b18e7 fx format 2019-02-17 14:26:27 +08:00
neilpang
f2acdd27fd fix tr err for Mac 2019-02-17 14:19:14 +08:00
neil
4ade446b55 Merge pull request #2095 from Augustin-FL/dev
Add online.net DNS API
2019-02-15 22:30:26 +08:00
Augustin-FL
ec6569fbea fix travis 2019-02-15 08:56:09 +00:00
Augustin-FL
1ad6742dbc fix travis 2019-02-15 08:43:07 +00:00
Augustin-FL
63ea3e8d27 acme.sh does not follow Location: headers when using wget 2019-02-15 08:29:44 +00:00
Augustin-FL
9ace7db216 simplify online_rest 2019-02-15 08:08:32 +00:00
Augustin-FL
841513501a update get_root 2019-02-15 08:08:32 +00:00
Augustin-FL
5c94147603 use read/saveconf_mutable, not readconf from OVH 2019-02-15 08:08:10 +00:00
Augustin-FL
02f6d4cb66 use read/saveconf_mutable, not readconf from OVH 2019-02-15 07:56:13 +00:00
Augustin-FL
ec5fad433c Add online.net DNS API 2019-02-14 08:34:21 +01:00
neil
b4fa97fd54 Merge pull request #2090 from ianw/rackdns
Rackspace Cloud DNS
2019-02-13 09:24:35 +08:00
Tom Cocca
d30b441ede Rackspace Cloud DNS
Support Rackspace Cloud DNS

This commit is based on the original pull request by tcocca
  https://github.com/Neilpang/acme.sh/pull/1297

Addtional cleanup was provided by senseisimple in
  https://github.com/Neilpang/acme.sh/pull/1999

This pull request has squashed the changes for review, fixed a minor
(but breaking) problem with the field ordering in the response, and
added documenation per the API guide.

Co-Author: Chris <chris@chrisnovoa.com>
Co-Author: Ian Wienand <ian@wienand.org>
2019-02-13 12:00:05 +11:00
neil
dda29f7e2f Merge pull request #2082 from laszlof/nw_dns_api
Add support for Thermo, Nexcess, and Futurehosting DNS APIs
2019-02-11 23:00:14 +08:00
neil
952e281993 Merge pull request #2077 from hosting-de/fix/better-parsing-of-responses
hosting.de: better parsing of json responses
2019-02-11 22:47:08 +08:00
Oliver Dick
1fa026b9c7 using ' ' instead of '[:space:]' for tr 2019-02-11 11:47:48 +01:00
neil
e8c91e6e12 Merge pull request #2083 from siwyd/ns1-dns-ttl
Set NS1 DNS record TTL to 0
2019-02-10 23:03:07 +08:00
neil
41425f7f74 Merge pull request #2086 from christianbur/patch-3
Update Dockerfile (apline 3.9 and tzdata)
2019-02-10 23:02:19 +08:00
Christian Burmeister
2cf01c23a2 Update Dockerfile 2019-02-09 19:38:32 +01:00
Simon Wydooghe
ebc90f6ab8 Set NS1 DNS record TTL to 0
Default of a zone might be high, which is annoying when testing
with the ACME staging API. I think setting the TTL to 0 makes sense
as acme.sh is the only one checking this, so having an always up
to date response seems desirable.
2019-02-06 21:49:17 +01:00
Frank Laszlo
84d80e93bc Add support for Thermo, Nexcess, and Futurehosting DNS APIs 2019-02-06 10:42:11 -05:00
Sebastiaan Hoogeveen
b7e92dbced Documentation update. 2019-02-06 14:27:26 +01:00
Sebastiaan Hoogeveen
44dcb0d0a9 Make Travis happy; fixed formatting of return statements. 2019-02-06 11:46:47 +01:00
Sebastiaan Hoogeveen
b3e3e080a9 Cleaned up some of the comments from shellcheck. 2019-02-05 16:37:08 +01:00
Sebastiaan Hoogeveen
1167cdcaec Added DNS API support for NederHost (https://www.nederhost.nl/) 2019-02-05 16:32:41 +01:00
Oliver Dick
4eda39a31d making shellcheck happy 2019-02-04 15:40:45 +01:00
Oliver Dick
759b75ca48 better parsing of json responses
fixes an error if customer does not have access to dns-groups
2019-02-04 11:27:04 +01:00
neil
55e862a4a4 Merge pull request #2068 from Neilpang/dev
fix https://github.com/Neilpang/acme.sh/pull/1979
2019-01-30 20:14:10 +08:00
neilpang
227547f826 fix https://github.com/Neilpang/acme.sh/pull/1979 2019-01-30 20:13:23 +08:00
neil
7c41dd5e31 Merge pull request #2064 from Neilpang/dev
fix https://github.com/Neilpang/acme.sh/issues/1364#issuecomment-4580…
2019-01-28 19:24:09 +08:00
neilpang
a964646803 fix https://github.com/Neilpang/acme.sh/issues/1364#issuecomment-458035330 2019-01-28 19:11:45 +08:00
neil
9dac02ba5d Merge pull request #2063 from Neilpang/dev
sync
2019-01-27 13:42:50 +08:00
neilpang
43877d2647 fix rm method to urlencode the existing txt records.
fix https://github.com/Neilpang/acme.sh/issues/2052
2019-01-26 20:27:53 +08:00
neilpang
cc6159b39b urlencode the existing txt record value
fix https://github.com/Neilpang/acme.sh/issues/2052
2019-01-26 19:15:13 +08:00
neilpang
43ff787b04 remove tls-sni 2019-01-26 18:32:11 +08:00
neilpang
3633598462 Lets start 2.8.1 2019-01-25 22:39:22 +08:00
neil
94922f2df6 Merge pull request #2053 from Manawyrm/dev
Added dns_doapi.sh
2019-01-25 22:38:11 +08:00
Tobias Mädel
75fe022f96 Changed order in readme, added do.de 2019-01-25 15:26:41 +01:00
Tobias Mädel
bc839569fb Merge branch 'dev' into dev 2019-01-25 14:38:35 +01:00
Tobias Mädel
e2f1338f94 Added documentation 2019-01-24 17:05:01 +01:00
Tobias Mädel
5f9b57d300 Cleaned up dns_doapi.sh 2019-01-24 17:00:37 +01:00
Tobias Mädel
ddf77f10e9 Cleaned up dns_doapi.sh 2019-01-24 16:59:36 +01:00
Tobias Mädel
127532c226 Added dns_doapi.sh 2019-01-24 16:53:03 +01:00
Pål Håland
8d38cf4d1f Use allchain instead of ca an cert, add documentation after review 2018-03-26 22:00:01 +02:00
Pål Håland
d698c1093a remove spaces around assignment 2018-03-26 08:24:04 +02:00
Pål Håland
7b327d47c0 Fix documentation 2018-03-26 08:21:31 +02:00
Pål Håland
e629985cf4 Use _cdomain if ROUTER_OS_HOST is missing 2018-03-26 07:41:56 +02:00
Pål Håland
aa875f1147 Merge branch 'master' into dev 2018-03-25 22:50:58 +02:00
martgras
65a7d56957 remove local keyword 2018-03-14 09:52:58 +01:00
martgras
52351d7dc8 avoid side effects in _printargs
A possible fix for https://github.com/Neilpang/acme.sh/issues/1356
2018-03-13 12:43:07 +01:00
Pål Håland
8c56356459 Merge remote-tracking branch 'upstream/dev' into dev 2017-05-03 21:49:55 +02:00
Pål Håland
400661d432 Merge remote-tracking branch 'upstream/dev' into dev 2017-03-21 20:14:31 +01:00
Pål Håland
e4e60ed654 Merge remote-tracking branch 'upstream/dev' into dev 2017-03-19 21:17:21 +01:00
Pål Håland
ff90a5d321 Merge branch 'dev' of github.com:Neilpang/acme.sh into dev 2017-03-14 20:20:36 +01:00
palhaland
cee0ab87fc Merge branch 'dev' into dev 2017-03-08 15:06:23 +01:00
Pål Håland
8a604bd2a1 Fixing syntax for schell script checking 2017-03-06 19:39:55 +01:00
Pål Håland
b8a8e2280d Added deploy script to deploy to the routeros system 2017-03-05 13:43:01 +01:00
35 changed files with 3104 additions and 1915 deletions

View File

@@ -1,4 +1,4 @@
FROM alpine:3.6
FROM alpine:3.9
RUN apk update -f \
&& apk --no-cache add -f \
@@ -7,6 +7,7 @@ RUN apk update -f \
bind-tools \
curl \
socat \
tzdata \
&& rm -rf /var/cache/apk/*
ENV LE_CONFIG_HOME /acme.sh

115
README.md
View File

@@ -45,25 +45,25 @@ Twitter: [@neilpangxa](https://twitter.com/neilpangxa)
| 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
|2|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/debian-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)| Debian
|3|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/centos-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|CentOS
|4|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/windows-cygwin.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Windows (cygwin with curl, openssl and crontab included)
|5|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/freebsd.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|FreeBSD
|6|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/pfsense.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|pfsense
|7|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/opensuse-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|openSUSE
|8|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/alpine-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Alpine Linux (with curl)
|9|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/base-archlinux.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Archlinux
|10|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/fedora-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|fedora
|11|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/kalilinux-kali-linux-docker.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Kali Linux
|12|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/oraclelinux-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Oracle Linux
|13|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/proxmox.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)| Proxmox https://pve.proxmox.com/wiki/HTTPSCertificateConfiguration#Let.27s_Encrypt_using_acme.sh
|1|[![](https://neilpang.github.io/acmetest/status/ubuntu-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)| Ubuntu
|2|[![](https://neilpang.github.io/acmetest/status/debian-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)| Debian
|3|[![](https://neilpang.github.io/acmetest/status/centos-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|CentOS
|4|[![](https://neilpang.github.io/acmetest/status/windows-cygwin.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Windows (cygwin with curl, openssl and crontab included)
|5|[![](https://neilpang.github.io/acmetest/status/freebsd.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|FreeBSD
|6|[![](https://neilpang.github.io/acmetest/status/pfsense.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|pfsense
|7|[![](https://neilpang.github.io/acmetest/status/opensuse-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|openSUSE
|8|[![](https://neilpang.github.io/acmetest/status/alpine-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Alpine Linux (with curl)
|9|[![](https://neilpang.github.io/acmetest/status/base-archlinux.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Archlinux
|10|[![](https://neilpang.github.io/acmetest/status/fedora-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|fedora
|11|[![](https://neilpang.github.io/acmetest/status/kalilinux-kali-linux-docker.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Kali Linux
|12|[![](https://neilpang.github.io/acmetest/status/oraclelinux-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Oracle Linux
|13|[![](https://neilpang.github.io/acmetest/status/proxmox.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)| Proxmox https://pve.proxmox.com/wiki/HTTPSCertificateConfiguration#Let.27s_Encrypt_using_acme.sh
|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
|16|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/mageia.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Mageia
|15|[![](https://neilpang.github.io/acmetest/status/openbsd.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|OpenBSD
|16|[![](https://neilpang.github.io/acmetest/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
|18|[![](https://neilpang.github.io/acmetest/status/solaris.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|SunOS/Solaris
|19|[![](https://neilpang.github.io/acmetest/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 [weekly build project](https://github.com/Neilpang/acmetest):
@@ -74,6 +74,7 @@ https://github.com/Neilpang/acmetest
- Letsencrypt.org CA(default)
- [BuyPass.com CA](https://github.com/Neilpang/acme.sh/wiki/BuyPass.com-CA)
- [Pebble strict Mode](https://github.com/letsencrypt/pebble)
# Supported modes
@@ -253,7 +254,7 @@ Just set string "apache" as the second argument and it will force use of apache
acme.sh --issue --apache -d example.com -d www.example.com -d cp.example.com
```
**This apache mode is only to issue the cert, it will not change your apache config files.
**This apache mode is only to issue the cert, it will not change your apache config files.
You will need to configure your website config files to use the cert by yourself.
We don't want to mess your apache server, don't worry.**
@@ -277,7 +278,7 @@ So, the config is not changed.
acme.sh --issue --nginx -d example.com -d www.example.com -d cp.example.com
```
**This nginx mode is only to issue the cert, it will not change your nginx config files.
**This nginx mode is only to issue the cert, it will not change your nginx config files.
You will need to configure your website config files to use the cert by yourself.
We don't want to mess your nginx server, don't worry.**
@@ -289,79 +290,9 @@ If your DNS provider supports API access, we can use that API to automatically i
You don't have to do anything manually!
### Currently acme.sh supports:
### Currently acme.sh supports most of the dns providers:
1. CloudFlare.com API
1. DNSPod.cn API
1. CloudXNS.com API
1. GoDaddy.com API
1. PowerDNS.com API
1. OVH, kimsufi, soyoustart and runabove API
1. nsupdate API
1. LuaDNS.com API
1. DNSMadeEasy.com API
1. AWS Route 53
1. aliyun.com(阿里云) API
1. ISPConfig 3.1 API
1. Alwaysdata.com API
1. Linode.com API
1. FreeDNS (https://freedns.afraid.org/)
1. cyon.ch
1. Domain-Offensive/Resellerinterface/Domainrobot API
1. Gandi LiveDNS API
1. Knot DNS API
1. DigitalOcean API (native)
1. ClouDNS.net API
1. Infoblox NIOS API (https://www.infoblox.com/)
1. VSCALE (https://vscale.io/)
1. Dynu API (https://www.dynu.com)
1. DNSimple API
1. NS1.com API
1. DuckDNS.org API
1. Name.com API
1. Dyn Managed DNS API
1. Yandex PDD API (https://pdd.yandex.ru)
1. Hurricane Electric DNS service (https://dns.he.net)
1. UnoEuro API (https://www.unoeuro.com/)
1. INWX (https://www.inwx.de/)
1. Servercow (https://servercow.de)
1. Namesilo (https://www.namesilo.com)
1. InternetX autoDNS API (https://internetx.com)
1. Azure DNS
1. selectel.com(selectel.ru) DNS API
1. zonomi.com DNS API
1. DreamHost.com API
1. DirectAdmin API
1. KingHost (https://www.kinghost.com.br/)
1. Zilore (https://zilore.com)
1. Loopia.se API
1. acme-dns (https://github.com/joohoi/acme-dns)
1. TELE3 (https://www.tele3.cz)
1. EUSERV.EU (https://www.euserv.eu)
1. DNSPod.com API (https://www.dnspod.com)
1. Google Cloud DNS API
1. ConoHa (https://www.conoha.jp)
1. netcup DNS API (https://www.netcup.de)
1. GratisDNS.dk (https://gratisdns.dk)
1. Namecheap API (https://www.namecheap.com/)
1. MyDNS.JP API (https://www.mydns.jp/)
1. hosting.de (https://www.hosting.de)
1. Neodigit.net API (https://www.neodigit.net)
1. Exoscale.com API (https://www.exoscale.com/)
1. PointDNS API (https://pointhq.com/)
1. Active24.cz API (https://www.active24.cz/)
And:
**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.)**
**More APIs 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.
For more details: [How to use DNS API](dnsapi)
https://github.com/Neilpang/acme.sh/wiki/dnsapi
# 9. Use DNS manual mode:
@@ -527,5 +458,5 @@ Please Star and Fork me.
Your donation makes **acme.sh** better:
1. PayPal/Alipay(支付宝)/Wechat(微信): [https://donate.acme.sh/](https://donate.acme.sh/)
[Donate List](https://github.com/Neilpang/acme.sh/wiki/Donate-list)

716
acme.sh

File diff suppressed because it is too large Load Diff

View File

@@ -1,383 +1,6 @@
# Using deploy api
Before you can deploy your cert, you must [issue the cert first](https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert).
deploy hook usage:
Here are the scripts to deploy the certs/key to the server/services.
https://github.com/Neilpang/acme.sh/wiki/deployhooks
## 1. Deploy the certs to your cpanel host
If you want to deploy using cpanel UAPI see 7.
(cpanel deploy hook is not finished yet, this is just an example.)
Then you can deploy now:
```sh
export DEPLOY_CPANEL_USER=myusername
export DEPLOY_CPANEL_PASSWORD=PASSWORD
acme.sh --deploy -d example.com --deploy-hook cpanel
```
## 2. Deploy ssl cert on kong proxy engine based on api
Before you can deploy your cert, you must [issue the cert first](https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert).
Currently supports Kong-v0.10.x.
```sh
acme.sh --deploy -d ftp.example.com --deploy-hook kong
```
## 3. Deploy the cert to remote server through SSH access
The ssh deploy plugin allows you to deploy certificates to a remote host
using SSH command to connect to the remote server. The ssh plugin is invoked
with the following command...
```sh
acme.sh --deploy -d example.com --deploy-hook ssh
```
Prior to running this for the first time you must tell the plugin where
and how to deploy the certificates. This is done by exporting the following
environment variables. This is not required for subsequent runs as the
values are stored by acme.sh in the domain configuration files.
Required...
```
export DEPLOY_SSH_USER=username
```
Optional...
```
export DEPLOY_SSH_CMD=custom ssh command
export DEPLOY_SSH_SERVER=url or ip address of remote host
export DEPLOY_SSH_KEYFILE=filename for private key
export DEPLOY_SSH_CERTFILE=filename for certificate file
export DEPLOY_SSH_CAFILE=filename for intermediate CA file
export DEPLOY_SSH_FULLCHAIN=filename for fullchain file
export DEPLOY_SSH_REMOTE_CMD=command to execute on remote host
export DEPLOY_SSH_BACKUP=yes or no
```
**DEPLOY_SSH_USER**
Username at the remote host that SSH will login with. Note that
SSH must be able to login to remote host without a password... SSH Keys
must have been exchanged with the remote host. Validate and test that you
can login to USER@URL from the host running acme.sh before using this script.
The USER@URL at the remote server must also have has permissions to write to
the target location of the certificate files and to execute any commands
(e.g. to stop/start services).
**DEPLOY_SSH_CMD**
You can customize the ssh command used to connect to the remote host. For example
if you need to connect to a specific port at the remote server you can set this
to, for example, "ssh -p 22" or to use `sshpass` to provide password inline
instead of exchanging ssh keys (this is not recommended, using keys is
more secure).
**DEPLOY_SSH_SERVER**
URL or IP Address of the remote server. If not provided then the domain
name provided on the acme.sh --deploy command line is used.
**DEPLOY_SSH_KEYFILE**
Target filename for the private key issued by LetsEncrypt.
**DEPLOY_SSH_CERTFILE**
Target filename for the certificate issued by LetsEncrypt.
If this is the same as the previous filename (for keyfile) then it is
appended to the same file.
**DEPLOY_SSH_CAFILE**
Target filename for the CA intermediate certificate issued by LetsEncrypt.
If this is the same as a previous filename (for keyfile or certfile) then
it is appended to the same file.
**DEPLOY_SSH_FULLCHAIN**
Target filename for the fullchain certificate issued by LetsEncrypt.
If this is the same as a previous filename (for keyfile, certfile or
cafile) then it is appended to the same file.
**DEPLOY_SSH_REMOTE_CMD**
Command to execute on the remote server after copying any certificates. This
could be any additional command required for example to stop and restart
the service.
**DEPLOY_SSH_BACKUP**
Before writing a certificate file to the remote server the existing
certificate will be copied to a backup directory on the remote server.
These are placed in a hidden directory in the home directory of the SSH
user
```sh
~/.acme_ssh_deploy/[domain name]-backup-[timestamp]
```
Any backups older than 180 days will be deleted when new certificates
are deployed. This defaults to "yes" set to "no" to disable backup.
###Examples using SSH deploy
The following example illustrates deploying certificates to a QNAP NAS
(tested with QTS version 4.2.3)
```sh
export DEPLOY_SSH_USER="admin"
export DEPLOY_SSH_KEYFILE="/etc/stunnel/stunnel.pem"
export DEPLOY_SSH_CERTFILE="/etc/stunnel/stunnel.pem"
export DEPLOY_SSH_CAFILE="/etc/stunnel/uca.pem"
export DEPLOY_SSH_REMOTE_CMD="/etc/init.d/stunnel.sh restart"
acme.sh --deploy -d qnap.example.com --deploy-hook ssh
```
Note how in this example both the private key and certificate point to
the same file. This will result in the certificate being appended
to the same file as the private key... a common requirement of several
services.
The next example illustrates deploying certificates to a Unifi
Controller (tested with version 5.4.11).
```sh
export DEPLOY_SSH_USER="root"
export DEPLOY_SSH_KEYFILE="/var/lib/unifi/unifi.example.com.key"
export DEPLOY_SSH_FULLCHAIN="/var/lib/unifi/unifi.example.com.cer"
export DEPLOY_SSH_REMOTE_CMD="openssl pkcs12 -export \
-inkey /var/lib/unifi/unifi.example.com.key \
-in /var/lib/unifi/unifi.example.com.cer \
-out /var/lib/unifi/unifi.example.com.p12 \
-name ubnt -password pass:temppass \
&& keytool -importkeystore -deststorepass aircontrolenterprise \
-destkeypass aircontrolenterprise \
-destkeystore /var/lib/unifi/keystore \
-srckeystore /var/lib/unifi/unifi.example.com.p12 \
-srcstoretype PKCS12 -srcstorepass temppass -alias ubnt -noprompt \
&& service unifi restart"
acme.sh --deploy -d unifi.example.com --deploy-hook ssh
```
In this example we execute several commands on the remote host
after the certificate files have been copied... to generate a pkcs12 file
compatible with Unifi, to import it into the Unifi keystore and then finally
to restart the service.
Note also that once the certificate is imported
into the keystore the individual certificate files are no longer
required. We could if we desired delete those files immediately. If we
do that then we should disable backup at the remote host (as there are
no files to backup -- they were erased during deployment). For example...
```sh
export DEPLOY_SSH_BACKUP=no
# modify the end of the remote command...
&& rm /var/lib/unifi/unifi.example.com.key \
/var/lib/unifi/unifi.example.com.cer \
/var/lib/unifi/unifi.example.com.p12 \
&& service unifi restart
```
## 4. Deploy the cert to local vsftpd server
```sh
acme.sh --deploy -d ftp.example.com --deploy-hook vsftpd
```
The default vsftpd conf file is `/etc/vsftpd.conf`, if your vsftpd conf is not in the default location, you can specify one:
```sh
export DEPLOY_VSFTPD_CONF="/etc/vsftpd.conf"
acme.sh --deploy -d ftp.example.com --deploy-hook vsftpd
```
The default command to restart vsftpd server is `service vsftpd restart`, if it doesn't work, you can specify one:
```sh
export DEPLOY_VSFTPD_RELOAD="/etc/init.d/vsftpd restart"
acme.sh --deploy -d ftp.example.com --deploy-hook vsftpd
```
## 5. Deploy the cert to local exim4 server
```sh
acme.sh --deploy -d ftp.example.com --deploy-hook exim4
```
The default exim4 conf file is `/etc/exim/exim.conf`, if your exim4 conf is not in the default location, you can specify one:
```sh
export DEPLOY_EXIM4_CONF="/etc/exim4/exim4.conf.template"
acme.sh --deploy -d ftp.example.com --deploy-hook exim4
```
The default command to restart exim4 server is `service exim4 restart`, if it doesn't work, you can specify one:
```sh
export DEPLOY_EXIM4_RELOAD="/etc/init.d/exim4 restart"
acme.sh --deploy -d ftp.example.com --deploy-hook exim4
```
## 6. Deploy the cert to OSX Keychain
```sh
acme.sh --deploy -d ftp.example.com --deploy-hook keychain
```
## 7. Deploy to cpanel host using UAPI
This hook is using UAPI and works in cPanel & WHM version 56 or newer.
```
acme.sh --deploy -d example.com --deploy-hook cpanel_uapi
```
DEPLOY_CPANEL_USER is required only if you run the script as root and it should contain cpanel username.
```sh
export DEPLOY_CPANEL_USER=username
acme.sh --deploy -d example.com --deploy-hook cpanel_uapi
```
Please note, that the cpanel_uapi hook will deploy only the first domain when your certificate will automatically renew. Therefore you should issue a separate certificate for each domain.
## 8. Deploy the cert to your FRITZ!Box router
You must specify the credentials that have administrative privileges on the FRITZ!Box in order to deploy the certificate, plus the URL of your FRITZ!Box, through the following environment variables:
```sh
$ export DEPLOY_FRITZBOX_USERNAME=my_username
$ export DEPLOY_FRITZBOX_PASSWORD=the_password
$ export DEPLOY_FRITZBOX_URL=https://fritzbox.example.com
```
After the first deployment, these values will be stored in your $HOME/.acme.sh/account.conf. You may now deploy the certificate like this:
```sh
acme.sh --deploy -d fritzbox.example.com --deploy-hook fritzbox
```
## 9. Deploy the cert to strongswan
```sh
acme.sh --deploy -d ftp.example.com --deploy-hook strongswan
```
## 10. Deploy the cert to HAProxy
You must specify the path where you want the concatenated key and certificate chain written.
```sh
export DEPLOY_HAPROXY_PEM_PATH=/etc/haproxy
```
You may optionally define the command to reload HAProxy. The value shown below will be used as the default if you don't set this environment variable.
```sh
export DEPLOY_HAPROXY_RELOAD="/usr/sbin/service haproxy restart"
```
You can then deploy the certificate as follows
```sh
acme.sh --deploy -d haproxy.example.com --deploy-hook haproxy
```
The path for the PEM file will be stored with the domain configuration and will be available when renewing, so that deploy will happen automatically when renewed.
## 11. Deploy your cert to Gitlab pages
You must define the API key and the informations for the project and Gitlab page you are updating the certificate for.
```sh
# The token can be created in your user settings under "Access Tokens"
export GITLAB_TOKEN="xxxxxxxxxxx"
# The project ID is displayed on the home page of the project
export GITLAB_PROJECT_ID=12345678
# The domain must match the one defined for the Gitlab page, without "https://"
export GITLAB_DOMAIN="www.mydomain.com"
```
You can then deploy the certificate as follows
```sh
acme.sh --deploy -d www.mydomain.com --deploy-hook gitlab
```
## 12. Deploy your cert to Hashicorp Vault
```sh
export VAULT_PREFIX="acme"
```
You can then deploy the certificate as follows
```sh
acme.sh --deploy -d www.mydomain.com --deploy-hook vault_cli
```
Your certs will be saved in Vault using this structure:
```sh
vault write "${VAULT_PREFIX}/${domain}/cert.pem" value=@"..."
vault write "${VAULT_PREFIX}/${domain}/cert.key" value=@"..."
vault write "${VAULT_PREFIX}/${domain}/chain.pem" value=@"..."
vault write "${VAULT_PREFIX}/${domain}/fullchain.pem" value=@"..."
```
You might be using Fabio load balancer (which can get certs from
Vault). It needs a bit different structure of your certs in Vault. It
gets certs only from keys that were saved in `prefix/domain`, like this:
```bash
vault write <PREFIX>/www.domain.com cert=@cert.pem key=@key.pem
```
If you want to save certs in Vault this way just set "FABIO" env
variable to anything (ex: "1") before running `acme.sh`:
```sh
export FABIO="1"
```
## 13. Deploy your certificate to Qiniu.com
使用 acme.sh 部署到七牛之前,需要确保部署的域名已打开 HTTPS 功能,您可以访问[融合 CDN - 域名管理](https://portal.qiniu.com/cdn/domain) 设置。
另外还需要先导出 AK/SK 环境变量,您可以访问[密钥管理](https://portal.qiniu.com/user/key) 获得。
```sh
$ export QINIU_AK="foo"
$ export QINIU_SK="bar"
```
完成准备工作之后,您就可以通过下面的命令开始部署 SSL 证书到七牛上:
```sh
$ acme.sh --deploy -d example.com --deploy-hook qiniu
```
假如您部署的证书为泛域名证书,您还需要设置 `QINIU_CDN_DOMAIN` 变量,指定实际需要部署的域名:
```sh
$ export QINIU_CDN_DOMAIN="cdn.example.com"
$ acme.sh --deploy -d example.com --deploy-hook qiniu
```
### English version
You should create AccessKey/SecretKey pair in https://portal.qiniu.com/user/key
before deploying your certificate, and please ensure you have enabled HTTPS for
your domain name. You can enable it in https://portal.qiniu.com/cdn/domain.
```sh
$ export QINIU_AK="foo"
$ export QINIU_SK="bar"
```
then you can deploy certificate by following command:
```sh
$ acme.sh --deploy -d example.com --deploy-hook qiniu
```
(Optional), If you are using wildcard certificate,
you may need export `QINIU_CDN_DOMAIN` to specify which domain
you want to update:
```sh
$ export QINIU_CDN_DOMAIN="cdn.example.com"
$ acme.sh --deploy -d example.com --deploy-hook qiniu
```

140
deploy/gcore_cdn.sh Normal file
View File

@@ -0,0 +1,140 @@
#!/usr/bin/env sh
# Here is the script to deploy the cert to G-Core CDN service (https://gcorelabs.com/ru/) using the G-Core Labs API (https://docs.gcorelabs.com/cdn/).
# Uses command line curl for send requests and jq for parse responses.
# Returns 0 when success.
#
# Written by temoffey <temofffey@gmail.com>
# Public domain, 2019
#export DEPLOY_GCORE_CDN_USERNAME=myusername
#export DEPLOY_GCORE_CDN_PASSWORD=mypassword
######## Public functions #####################
#domain keyfile certfile cafile fullchain
gcore_cdn_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"
_fullchain=$(tr '\n\r' '@#' <"$_cfullchain" | sed 's/@/\\n/g;s/#/\\r/g')
_key=$(tr '\n\r' '@#' <"$_ckey" | sed 's/@/\\n/g;s/#/\\r/g')
_debug _fullchain "$_fullchain"
_debug _key "$_key"
if [ -z "$DEPLOY_GCORE_CDN_USERNAME" ]; then
if [ -z "$Le_Deploy_gcore_cdn_username" ]; then
_err "Please define the target username: export DEPLOY_GCORE_CDN_USERNAME=username"
return 1
fi
else
Le_Deploy_gcore_cdn_username="$DEPLOY_GCORE_CDN_USERNAME"
_savedomainconf Le_Deploy_gcore_cdn_username "$Le_Deploy_gcore_cdn_username"
fi
if [ -z "$DEPLOY_GCORE_CDN_PASSWORD" ]; then
if [ -z "$Le_Deploy_gcore_cdn_password" ]; then
_err "Please define the target password: export DEPLOY_GCORE_CDN_PASSWORD=password"
return 1
fi
else
Le_Deploy_gcore_cdn_password="$DEPLOY_GCORE_CDN_PASSWORD"
_savedomainconf Le_Deploy_gcore_cdn_password "$Le_Deploy_gcore_cdn_password"
fi
_info "Get authorization token"
_request="{\"username\":\"$Le_Deploy_gcore_cdn_username\",\"password\":\"$Le_Deploy_gcore_cdn_password\"}"
_debug _request "$_request"
export _H1="Content-Type:application/json"
_response=$(_post "$_request" "https://api.gcdn.co/auth/signin")
_debug _response "$_response"
_regex=".*\"token\":\"\([-._0-9A-Za-z]*\)\".*$"
_debug _regex "$_regex"
_token=$(echo "$_response" | sed -n "s/$_regex/\1/p")
_debug _token "$_token"
if [ -z "$_token" ]; then
_err "Error G-Core Labs API authorization"
return 1
fi
_info "Find CDN resource with cname $_cdomain"
export _H2="Authorization:Token $_token"
_response=$(_get "https://api.gcdn.co/resources")
_debug _response "$_response"
_regex=".*(\"id\".*?\"cname\":\"$_cdomain\".*?})"
_regex="^.*\"cname\":\"$_cdomain\".*$"
_debug _regex "$_regex"
_resource=$(echo "$_response" | sed 's/},{/},\n{/g' | _egrep_o "$_regex")
_debug _resource "$_resource"
_regex=".*\"id\":\([0-9]*\),.*$"
_debug _regex "$_regex"
_resourceId=$(echo "$_resource" | sed -n "s/$_regex/\1/p")
_debug _resourceId "$_resourceId"
_regex=".*\"sslData\":\([0-9]*\)}.*$"
_debug _regex "$_regex"
_sslDataOld=$(echo "$_resource" | sed -n "s/$_regex/\1/p")
_debug _sslDataOld "$_sslDataOld"
_regex=".*\"originGroup\":\([0-9]*\),.*$"
_debug _regex "$_regex"
_originGroup=$(echo "$_resource" | sed -n "s/$_regex/\1/p")
_debug _originGroup "$_originGroup"
if [ -z "$_resourceId" ] || [ -z "$_originGroup" ]; then
_err "Not found CDN resource with cname $_cdomain"
return 1
fi
_info "Add new SSL certificate"
_date=$(date "+%d.%m.%Y %H:%M:%S")
_request="{\"name\":\"$_cdomain ($_date)\",\"sslCertificate\":\"$_fullchain\",\"sslPrivateKey\":\"$_key\"}"
_debug _request "$_request"
_response=$(_post "$_request" "https://api.gcdn.co/sslData")
_debug _response "$_response"
_regex=".*\"id\":\([0-9]*\),.*$"
_debug _regex "$_regex"
_sslDataAdd=$(echo "$_response" | sed -n "s/$_regex/\1/p")
_debug _sslDataAdd "$_sslDataAdd"
if [ -z "$_sslDataAdd" ]; then
_err "Error new SSL certificate add"
return 1
fi
_info "Update CDN resource"
_request="{\"originGroup\":$_originGroup,\"sslData\":$_sslDataAdd}"
_debug _request "$_request"
_response=$(_post "$_request" "https://api.gcdn.co/resources/$_resourceId" '' "PUT")
_debug _response "$_response"
_regex=".*\"sslData\":\([0-9]*\)}.*$"
_debug _regex "$_regex"
_sslDataNew=$(echo "$_response" | sed -n "s/$_regex/\1/p")
_debug _sslDataNew "$_sslDataNew"
if [ "$_sslDataNew" != "$_sslDataAdd" ]; then
_err "Error CDN resource update"
return 1
fi
if [ -z "$_sslDataOld" ] || [ "$_sslDataOld" = "null" ]; then
_info "Not found old SSL certificate"
else
_info "Delete old SSL certificate"
_response=$(_post '' "https://api.gcdn.co/sslData/$_sslDataOld" '' "DELETE")
_debug _response "$_response"
fi
_info "Certificate successfully deployed"
return 0
}

58
deploy/mailcow.sh Normal file
View File

@@ -0,0 +1,58 @@
#!/usr/bin/env sh
#Here is a script to deploy cert to mailcow.
#returns 0 means success, otherwise error.
######## Public functions #####################
#domain keyfile certfile cafile fullchain
mailcow_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"
_mailcow_path="${DEPLOY_MAILCOW_PATH}"
if [ -z "$_mailcow_path" ]; then
_err "Mailcow path is not found, please define DEPLOY_MAILCOW_PATH."
return 1
fi
_ssl_path="${_mailcow_path}/data/assets/ssl/"
if [ ! -d "$_ssl_path" ]; then
_err "Cannot find mailcow ssl path: $_ssl_path"
return 1
fi
_info "Copying key and cert"
_real_key="$_ssl_path/key.pem"
if ! cat "$_ckey" >"$_real_key"; then
_err "Error: write key file to: $_real_key"
return 1
fi
_real_fullchain="$_ssl_path/cert.pem"
if ! cat "$_cfullchain" >"$_real_fullchain"; then
_err "Error: write cert file to: $_real_fullchain"
return 1
fi
DEFAULT_MAILCOW_RELOAD="cd ${_mailcow_path} && docker-compose restart postfix-mailcow dovecot-mailcow nginx-mailcow"
_reload="${DEPLOY_MAILCOW_RELOAD:-$DEFAULT_MAILCOW_RELOAD}"
_info "Run reload: $_reload"
if eval "$_reload"; then
_info "Reload success!"
fi
return 0
}

59
deploy/mydevil.sh Executable file
View File

@@ -0,0 +1,59 @@
#!/usr/bin/env sh
# MyDevil.net API (2019-02-03)
#
# MyDevil.net already supports automatic Let's Encrypt certificates,
# except for wildcard domains.
#
# This script depends on `devil` command that MyDevil.net provides,
# which means that it works only on server side.
#
# Author: Marcin Konicki <https://ahwayakchih.neoni.net>
#
######## Public functions #####################
# Usage: mydevil_deploy domain keyfile certfile cafile fullchain
mydevil_deploy() {
_cdomain="$1"
_ckey="$2"
_ccert="$3"
_cca="$4"
_cfullchain="$5"
ip=""
_debug _cdomain "$_cdomain"
_debug _ckey "$_ckey"
_debug _ccert "$_ccert"
_debug _cca "$_cca"
_debug _cfullchain "$_cfullchain"
if ! _exists "devil"; then
_err "Could not find 'devil' command."
return 1
fi
ip=$(mydevil_get_ip "$_cdomain")
if [ -z "$ip" ]; then
_err "Could not find IP for domain $_cdomain."
return 1
fi
# Delete old certificate first
_info "Removing old certificate for $_cdomain at $ip"
devil ssl www del "$ip" "$_cdomain"
# Add new certificate
_info "Adding new certificate for $_cdomain at $ip"
devil ssl www add "$ip" "$_cfullchain" "$_ckey" "$_cdomain" || return 1
return 0
}
#################### Private functions below ##################################
# Usage: ip=$(mydevil_get_ip domain.com)
# echo $ip
mydevil_get_ip() {
devil dns list "$1" | cut -w -s -f 3,7 | grep "^A$(printf '\t')" | cut -w -s -f 2 || return 1
return 0
}

View File

@@ -87,6 +87,6 @@ qiniu_deploy() {
}
_make_access_token() {
_token="$(printf "%s\n" "$1" | _hmac "sha1" "$(printf "%s" "$QINIU_SK" | _hex_dump | tr -d " ")" | _base64)"
_token="$(printf "%s\n" "$1" | _hmac "sha1" "$(printf "%s" "$QINIU_SK" | _hex_dump | tr -d " ")" | _base64 | tr -- '+/' '-_')"
echo "$QINIU_AK:$_token"
}

114
deploy/routeros.sh Normal file
View File

@@ -0,0 +1,114 @@
#!/usr/bin/env sh
# Here is a script to deploy cert to routeros router.
# Deploy the cert to remote routeros
#
# ```sh
# acme.sh --deploy -d ftp.example.com --deploy-hook routeros
# ```
#
# Before you can deploy the certificate to router os, you need
# to add the id_rsa.pub key to the routeros and assign a user
# to that key.
#
# The user need to have access to ssh, ftp, read and write.
#
# There are no need to enable ftp service for the script to work,
# as they are transmitted over SCP, however ftp is needed to store
# the files on the router.
#
# Then you need to set the environment variables for the
# deploy script to work.
#
# ```sh
# export ROUTER_OS_USERNAME=certuser
# export ROUTER_OS_HOST=router.example.com
#
# acme.sh --deploy -d ftp.example.com --deploy-hook routeros
# ```
#
# The deploy script will remove previously deployed certificates,
# and it does this with an assumption on how RouterOS names imported
# certificates, adding a "cer_0" suffix at the end. This is true for
# versions 6.32 -> 6.41.3, but it is not guaranteed that it will be
# true for future versions when upgrading.
#
# If the router have other certificates with the same name as the one
# beeing deployed, then this script will remove those certificates.
#
# At the end of the script, the services that use those certificates
# could be updated. Currently only the www-ssl service is beeing
# updated, but more services could be added.
#
# For instance:
# ```sh
# export ROUTER_OS_ADDITIONAL_SERVICES="/ip service set api-ssl certificate=$_cdomain.cer_0"
# ```
#
# One optional thing to do as well is to create a script that updates
# all the required services and run that script in a single command.
#
# returns 0 means success, otherwise error.
######## Public functions #####################
#domain keyfile certfile cafile fullchain
routeros_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"
if [ -z "$ROUTER_OS_HOST" ]; then
_debug "Using _cdomain as ROUTER_OS_HOST, please set if not correct."
ROUTER_OS_HOST="$_cdomain"
fi
if [ -z "$ROUTER_OS_USERNAME" ]; then
_err "Need to set the env variable ROUTER_OS_USERNAME"
return 1
fi
if [ -z "$ROUTER_OS_ADDITIONAL_SERVICES" ]; then
_debug "Not enabling additional services"
ROUTER_OS_ADDITIONAL_SERVICES=""
fi
_info "Trying to push key '$_ckey' to router"
scp "$_ckey" "$ROUTER_OS_USERNAME@$ROUTER_OS_HOST:$_cdomain.key"
_info "Trying to push cert '$_cfullchain' to router"
scp "$_cfullchain" "$ROUTER_OS_USERNAME@$ROUTER_OS_HOST:$_cdomain.cer"
# shellcheck disable=SC2029
ssh "$ROUTER_OS_USERNAME@$ROUTER_OS_HOST" bash -c "'
/certificate remove $_cdomain.cer_0
/certificate remove $_cdomain.cer_1
delay 1
/certificate import file-name=$_cdomain.cer passphrase=\"\"
/certificate import file-name=$_cdomain.key passphrase=\"\"
delay 1
/file remove $_cdomain.cer
/file remove $_cdomain.key
delay 2
/ip service set www-ssl certificate=$_cdomain.cer_0
$ROUTER_OS_ADDITIONAL_SERVICES
'"
return 0
}

File diff suppressed because it is too large Load Diff

View File

@@ -58,7 +58,7 @@ dns_cf_add() {
# if [ "$count" = "0" ]; then
_info "Adding record"
if _cf_rest POST "zones/$_domain_id/dns_records" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":120}"; then
if _contains "$response" "$fulldomain"; then
if _contains "$response" "$txtvalue"; then
_info "Added, OK"
return 0
elif _contains "$response" "The record already exists"; then
@@ -147,7 +147,7 @@ dns_cf_rm() {
# _domain_id=sdjkglgdfewsdfg
_get_root() {
domain=$1
i=2
i=1
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
@@ -182,8 +182,11 @@ _cf_rest() {
data="$3"
_debug "$ep"
export _H1="X-Auth-Email: $CF_Email"
export _H2="X-Auth-Key: $CF_Key"
email_trimmed=$(echo $CF_Email | tr -d '"')
key_trimmed=$(echo $CF_Key | tr -d '"')
export _H1="X-Auth-Email: $email_trimmed"
export _H2="X-Auth-Key: $key_trimmed"
export _H3="Content-Type: application/json"
if [ "$m" != "GET" ]; then

157
dnsapi/dns_cn.sh Normal file
View File

@@ -0,0 +1,157 @@
#!/usr/bin/env sh
# DNS API for acme.sh for Core-Networks (https://beta.api.core-networks.de/doc/).
# created by 5ll and francis
CN_API="https://beta.api.core-networks.de"
######## Public functions #####################
dns_cn_add() {
fulldomain=$1
txtvalue=$2
if ! _cn_login; then
_err "login failed"
return 1
fi
_debug "First detect the root zone"
if ! _cn_get_root "$fulldomain"; then
_err "invalid domain"
return 1
fi
_debug "_sub_domain $_sub_domain"
_debug "_domain $_domain"
_info "Adding record"
curData="{\"name\":\"$_sub_domain\",\"ttl\":120,\"type\":\"TXT\",\"data\":\"$txtvalue\"}"
curResult="$(_post "${curData}" "${CN_API}/dnszones/${_domain}/records/")"
_debug "curData $curData"
_debug "curResult $curResult"
if _contains "$curResult" ""; then
_info "Added, OK"
if ! _cn_commit; then
_err "commiting changes failed"
return 1
fi
return 0
else
_err "Add txt record error."
_debug "curData is $curData"
_debug "curResult is $curResult"
_err "error adding text record, response was $curResult"
return 1
fi
}
dns_cn_rm() {
fulldomain=$1
txtvalue=$2
if ! _cn_login; then
_err "login failed"
return 1
fi
_debug "First detect the root zone"
if ! _cn_get_root "$fulldomain"; then
_err "invalid domain"
return 1
fi
_info "Deleting record"
curData="{\"name\":\"$_sub_domain\",\"data\":\"$txtvalue\"}"
curResult="$(_post "${curData}" "${CN_API}/dnszones/${_domain}/records/delete")"
_debug curData is "$curData"
_info "commiting changes"
if ! _cn_commit; then
_err "commiting changes failed"
return 1
fi
_info "Deletet txt record"
return 0
}
################### Private functions below ##################################
_cn_login() {
CN_User="${CN_User:-$(_readaccountconf_mutable CN_User)}"
CN_Password="${CN_Password:-$(_readaccountconf_mutable CN_Password)}"
if [ -z "$CN_User" ] || [ -z "$CN_Password" ]; then
CN_User=""
CN_Password=""
_err "You must export variables: CN_User and CN_Password"
return 1
fi
#save the config variables to the account conf file.
_saveaccountconf_mutable CN_User "$CN_User"
_saveaccountconf_mutable CN_Password "$CN_Password"
_info "Getting an AUTH-Token"
curData="{\"login\":\"${CN_User}\",\"password\":\"${CN_Password}\"}"
curResult="$(_post "${curData}" "${CN_API}/auth/token")"
_debug "Calling _CN_login: '${curData}' '${CN_API}/auth/token'"
if _contains "${curResult}" '"token":"'; then
authToken=$(echo "${curResult}" | cut -d ":" -f2 | cut -d "," -f1 | sed 's/^.\(.*\).$/\1/')
export _H1="Authorization: Bearer $authToken"
_info "Successfully acquired AUTH-Token"
_debug "AUTH-Token: '${authToken}'"
_debug "_H1 '${_H1}'"
else
_err "Couldn't acquire an AUTH-Token"
return 1
fi
}
# Commit changes
_cn_commit() {
_info "Commiting changes"
_post "" "${CN_API}/dnszones/$h/records/commit"
}
_cn_get_root() {
domain=$1
i=2
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
_debug h "$h"
_debug _H1 "${_H1}"
if [ -z "$h" ]; then
#not valid
return 1
fi
_cn_zonelist="$(_get ${CN_API}/dnszones/)"
_debug _cn_zonelist "${_cn_zonelist}"
if [ "$?" != "0" ]; then
_err "something went wrong while getting the zone list"
return 1
fi
if _contains "$_cn_zonelist" "\"name\":\"$h\"" >/dev/null; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_domain=$h
return 0
else
_debug "Zonelist does not contain domain - iterating "
fi
p=$i
i=$(_math "$i" + 1)
done
_err "Zonelist does not contain domain - exiting"
return 1
}

View File

@@ -16,6 +16,8 @@ dns_cx_add() {
fulldomain=$1
txtvalue=$2
CX_Key="${CX_Key:-$(_readaccountconf_mutable CX_Key)}"
CX_Secret="${CX_Secret:-$(_readaccountconf_mutable CX_Secret)}"
if [ -z "$CX_Key" ] || [ -z "$CX_Secret" ]; then
CX_Key=""
CX_Secret=""
@@ -27,8 +29,8 @@ dns_cx_add() {
REST_API="$CX_Api"
#save the api key and email to the account conf file.
_saveaccountconf CX_Key "$CX_Key"
_saveaccountconf CX_Secret "$CX_Secret"
_saveaccountconf_mutable CX_Key "$CX_Key"
_saveaccountconf_mutable CX_Secret "$CX_Secret"
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
@@ -43,6 +45,8 @@ dns_cx_add() {
dns_cx_rm() {
fulldomain=$1
txtvalue=$2
CX_Key="${CX_Key:-$(_readaccountconf_mutable CX_Key)}"
CX_Secret="${CX_Secret:-$(_readaccountconf_mutable CX_Secret)}"
REST_API="$CX_Api"
if _get_root "$fulldomain"; then
record_id=""

130
dnsapi/dns_ddnss.sh Normal file
View File

@@ -0,0 +1,130 @@
#!/usr/bin/env sh
#Created by RaidenII, to use DuckDNS's API to add/remove text records
#modified by helbgd @ 03/13/2018 to support ddnss.de
#modified by mod242 @ 04/24/2018 to support different ddnss domains
#Please note: the Wildcard Feature must be turned on for the Host record
#and the checkbox for TXT needs to be enabled
# Pass credentials before "acme.sh --issue --dns dns_ddnss ..."
# --
# export DDNSS_Token="aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
# --
#
DDNSS_DNS_API="https://ddnss.de/upd.php"
######## Public functions #####################
#Usage: dns_ddnss_add _acme-challenge.domain.ddnss.de "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_ddnss_add() {
fulldomain=$1
txtvalue=$2
DDNSS_Token="${DDNSS_Token:-$(_readaccountconf_mutable DDNSS_Token)}"
if [ -z "$DDNSS_Token" ]; then
_err "You must export variable: DDNSS_Token"
_err "The token for your DDNSS account is necessary."
_err "You can look it up in your DDNSS account."
return 1
fi
# Now save the credentials.
_saveaccountconf_mutable DDNSS_Token "$DDNSS_Token"
# Unfortunately, DDNSS does not seems to support lookup domain through API
# So I assume your credentials (which are your domain and token) are correct
# If something goes wrong, we will get a KO response from DDNSS
if ! _ddnss_get_domain; then
return 1
fi
# Now add the TXT record to DDNSS DNS
_info "Trying to add TXT record"
if _ddnss_rest GET "key=$DDNSS_Token&host=$_ddnss_domain&txtm=1&txt=$txtvalue"; then
if [ "$response" = "Updated 1 hostname." ]; then
_info "TXT record has been successfully added to your DDNSS domain."
_info "Note that all subdomains under this domain uses the same TXT record."
return 0
else
_err "Errors happened during adding the TXT record, response=$response"
return 1
fi
else
_err "Errors happened during adding the TXT record."
return 1
fi
}
#Usage: fulldomain txtvalue
#Remove the txt record after validation.
dns_ddnss_rm() {
fulldomain=$1
txtvalue=$2
DDNSS_Token="${DDNSS_Token:-$(_readaccountconf_mutable DDNSS_Token)}"
if [ -z "$DDNSS_Token" ]; then
_err "You must export variable: DDNSS_Token"
_err "The token for your DDNSS account is necessary."
_err "You can look it up in your DDNSS account."
return 1
fi
if ! _ddnss_get_domain; then
return 1
fi
# Now remove the TXT record from DDNS DNS
_info "Trying to remove TXT record"
if _ddnss_rest GET "key=$DDNSS_Token&host=$_ddnss_domain&txtm=1&txt=."; then
if [ "$response" = "Updated 1 hostname." ]; then
_info "TXT record has been successfully removed from your DDNSS domain."
return 0
else
_err "Errors happened during removing the TXT record, response=$response"
return 1
fi
else
_err "Errors happened during removing the TXT record."
return 1
fi
}
#################### Private functions below ##################################
#fulldomain=_acme-challenge.domain.ddnss.de
#returns
# _ddnss_domain=domain
_ddnss_get_domain() {
# We'll extract the domain/username from full domain
_ddnss_domain="$(echo "$fulldomain" | _lower_case | _egrep_o '[.][^.][^.]*[.](ddnss|dyn-ip24|dyndns|dyn|dyndns1|home-webserver|myhome-server|dynip)\..*' | cut -d . -f 2-)"
if [ -z "$_ddnss_domain" ]; then
_err "Error extracting the domain."
return 1
fi
return 0
}
#Usage: method URI
_ddnss_rest() {
method=$1
param="$2"
_debug param "$param"
url="$DDNSS_DNS_API?$param"
_debug url "$url"
# DDNSS uses GET to update domain info
if [ "$method" = "GET" ]; then
response="$(_get "$url" | sed 's/<[^>]*>//g;/</N;//ba' | _tail_n 1)"
else
_err "Unsupported method"
return 1
fi
_debug2 response "$response"
return 0
}

204
dnsapi/dns_desec.sh Normal file
View File

@@ -0,0 +1,204 @@
#!/usr/bin/env sh
#
# deSEC.io Domain API
#
# Author: Zheng Qian
#
# deSEC API doc
# https://desec.readthedocs.io/en/latest/
REST_API="https://desec.io/api/v1/domains"
######## Public functions #####################
#Usage: dns_desec_add _acme-challenge.foobar.dedyn.io "d41d8cd98f00b204e9800998ecf8427e"
dns_desec_add() {
fulldomain=$1
txtvalue=$2
_info "Using desec.io api"
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
DEDYN_TOKEN="${DEDYN_TOKEN:-$(_readaccountconf_mutable DEDYN_TOKEN)}"
DEDYN_NAME="${DEDYN_NAME:-$(_readaccountconf_mutable DEDYN_NAME)}"
if [ -z "$DEDYN_TOKEN" ] || [ -z "$DEDYN_NAME" ]; then
DEDYN_TOKEN=""
DEDYN_NAME=""
_err "You don't specify DEDYN_TOKEN and DEDYN_NAME yet."
_err "Please create you key and try again."
_err "e.g."
_err "export DEDYN_TOKEN=d41d8cd98f00b204e9800998ecf8427e"
_err "export DEDYN_NAME=foobar.dedyn.io"
return 1
fi
#save the api token and name to the account conf file.
_saveaccountconf_mutable DEDYN_TOKEN "$DEDYN_TOKEN"
_saveaccountconf_mutable DEDYN_NAME "$DEDYN_NAME"
_debug "First detect the root zone"
if ! _get_root "$fulldomain" "$REST_API/"; then
_err "invalid domain"
return 1
fi
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
# Get existing TXT record
_debug "Getting txt records"
txtvalues="\"\\\"$txtvalue\\\"\""
_desec_rest GET "$REST_API/$DEDYN_NAME/rrsets/$_sub_domain/TXT/"
if [ "$_code" = "200" ]; then
oldtxtvalues="$(echo "$response" | _egrep_o "\"records\":\\[\"\\S*\"\\]" | cut -d : -f 2 | tr -d "[]\\\\\"" | sed "s/,/ /g")"
_debug "existing TXT found"
_debug oldtxtvalues "$oldtxtvalues"
if [ -n "$oldtxtvalues" ]; then
for oldtxtvalue in $oldtxtvalues; do
txtvalues="$txtvalues, \"\\\"$oldtxtvalue\\\"\""
done
fi
fi
_debug txtvalues "$txtvalues"
_info "Adding record"
body="[{\"subname\":\"$_sub_domain\", \"type\":\"TXT\", \"records\":[$txtvalues], \"ttl\":60}]"
if _desec_rest PUT "$REST_API/$DEDYN_NAME/rrsets/" "$body"; then
if _contains "$response" "$txtvalue"; then
_info "Added, OK"
return 0
else
_err "Add txt record error."
return 1
fi
fi
_err "Add txt record error."
return 1
}
#Usage: fulldomain txtvalue
#Remove the txt record after validation.
dns_desec_rm() {
fulldomain=$1
txtvalue=$2
_info "Using desec.io api"
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
DEDYN_TOKEN="${DEDYN_TOKEN:-$(_readaccountconf_mutable DEDYN_TOKEN)}"
DEDYN_NAME="${DEDYN_NAME:-$(_readaccountconf_mutable DEDYN_NAME)}"
if [ -z "$DEDYN_TOKEN" ] || [ -z "$DEDYN_NAME" ]; then
DEDYN_TOKEN=""
DEDYN_NAME=""
_err "You don't specify DEDYN_TOKEN and DEDYN_NAME yet."
_err "Please create you key and try again."
_err "e.g."
_err "export DEDYN_TOKEN=d41d8cd98f00b204e9800998ecf8427e"
_err "export DEDYN_NAME=foobar.dedyn.io"
return 1
fi
_debug "First detect the root zone"
if ! _get_root "$fulldomain" "$REST_API/"; then
_err "invalid domain"
return 1
fi
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
# Get existing TXT record
_debug "Getting txt records"
txtvalues=""
_desec_rest GET "$REST_API/$DEDYN_NAME/rrsets/$_sub_domain/TXT/"
if [ "$_code" = "200" ]; then
oldtxtvalues="$(echo "$response" | _egrep_o "\"records\":\\[\"\\S*\"\\]" | cut -d : -f 2 | tr -d "[]\\\\\"" | sed "s/,/ /g")"
_debug "existing TXT found"
_debug oldtxtvalues "$oldtxtvalues"
if [ -n "$oldtxtvalues" ]; then
for oldtxtvalue in $oldtxtvalues; do
if [ "$txtvalue" != "$oldtxtvalue" ]; then
txtvalues="$txtvalues, \"\\\"$oldtxtvalue\\\"\""
fi
done
fi
fi
txtvalues="$(echo "$txtvalues" | cut -c3-)"
_debug txtvalues "$txtvalues"
_info "Deleting record"
body="[{\"subname\":\"$_sub_domain\", \"type\":\"TXT\", \"records\":[$txtvalues], \"ttl\":60}]"
_desec_rest PUT "$REST_API/$DEDYN_NAME/rrsets/" "$body"
if [ "$_code" = "200" ]; then
_info "Deleted, OK"
return 0
fi
_err "Delete txt record error."
return 1
}
#################### Private functions below ##################################
_desec_rest() {
m="$1"
ep="$2"
data="$3"
export _H1="Authorization: Token $DEDYN_TOKEN"
export _H2="Accept: application/json"
export _H3="Content-Type: application/json"
if [ "$m" != "GET" ]; then
_secure_debug2 data "$data"
response="$(_post "$data" "$ep" "" "$m")"
else
response="$(_get "$ep")"
fi
_ret="$?"
_code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")"
_debug "http response code $_code"
_secure_debug2 response "$response"
if [ "$_ret" != "0" ]; then
_err "error $ep"
return 1
fi
response="$(printf "%s" "$response" | _normalizeJson)"
return 0
}
#_acme-challenge.www.domain.com
#returns
# _sub_domain=_acme-challenge.www
# _domain=domain.com
_get_root() {
domain="$1"
ep="$2"
i=2
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
_debug h "$h"
if [ -z "$h" ]; then
#not valid
return 1
fi
if ! _desec_rest GET "$ep"; then
return 1
fi
if _contains "$response" "\"name\":\"$h\"" >/dev/null; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_domain=$h
return 0
fi
p=$i
i=$(_math "$i" + 1)
done
return 1
}

View File

@@ -178,7 +178,7 @@ dns_dgon_rm() {
## _domain="domain.com"
_get_base_domain() {
# args
fulldomain="$(echo "$1" | tr '[:upper:]' '[:lower:]')"
fulldomain="$(echo "$1" | _lower_case)"
_debug fulldomain "$fulldomain"
# domain max legal length = 253

59
dnsapi/dns_doapi.sh Executable file
View File

@@ -0,0 +1,59 @@
#!/usr/bin/env sh
# Official Let's Encrypt API for do.de / Domain-Offensive
#
# This is different from the dns_do adapter, because dns_do is only usable for enterprise customers
# This API is also available to private customers/individuals
#
# Provide the required LetsEncrypt token like this:
# DO_LETOKEN="FmD408PdqT1E269gUK57"
DO_API="https://www.do.de/api/letsencrypt"
######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_doapi_add() {
fulldomain=$1
txtvalue=$2
DO_LETOKEN="${DO_LETOKEN:-$(_readaccountconf_mutable DO_LETOKEN)}"
if [ -z "$DO_LETOKEN" ]; then
DO_LETOKEN=""
_err "You didn't configure a do.de API token yet."
_err "Please set DO_LETOKEN and try again."
return 1
fi
_saveaccountconf_mutable DO_LETOKEN "$DO_LETOKEN"
_info "Adding TXT record to ${fulldomain}"
response="$(_get "$DO_API?token=$DO_LETOKEN&domain=${fulldomain}&value=${txtvalue}")"
if _contains "${response}" 'success'; then
return 0
fi
_err "Could not create resource record, check logs"
_err "${response}"
return 1
}
dns_doapi_rm() {
fulldomain=$1
DO_LETOKEN="${DO_LETOKEN:-$(_readaccountconf_mutable DO_LETOKEN)}"
if [ -z "$DO_LETOKEN" ]; then
DO_LETOKEN=""
_err "You didn't configure a do.de API token yet."
_err "Please set DO_LETOKEN and try again."
return 1
fi
_saveaccountconf_mutable DO_LETOKEN "$DO_LETOKEN"
_info "Deleting resource record $fulldomain"
response="$(_get "$DO_API?token=$DO_LETOKEN&domain=${fulldomain}&action=delete")"
if _contains "${response}" 'success'; then
return 0
fi
_err "Could not delete resource record, check logs"
_err "${response}"
return 1
}

View File

@@ -63,7 +63,7 @@ dns_dp_rm() {
return 0
fi
record_id=$(echo "$response" | _egrep_o '{[^{]*"value":"'"$txtvalue"'"' | cut -d , -f 1 | cut -d : -f 2 | tr -d \")
record_id=$(echo "$response" | tr "{" "\n" | grep "$txtvalue" | grep '^"id"' | cut -d : -f 2 | cut -d '"' -f 2)
_debug record_id "$record_id"
if [ -z "$record_id" ]; then
_err "Can not get record id."

View File

@@ -137,7 +137,7 @@ _mypost() {
_get_domain() {
_myget 'action=dns_primarydns'
_domains=$(echo "$_result" | _egrep_o ' domain="[[:alnum:].-_]+' | sed 's/^.*"//')
_domains=$(echo "$_result" | _egrep_o ' domain="[[:alnum:]._-]+' | sed 's/^.*"//')
if [ -z "$_domains" ]; then
_err "Primary domain list not found!"
return 1

View File

@@ -13,6 +13,7 @@ dns_hostingde_add() {
txtvalue="${2}"
_debug "Calling: _hostingde_addRecord() '${fulldomain}' '${txtvalue}'"
_hostingde_apiKey && _hostingde_getZoneConfig && _hostingde_addRecord
return $?
}
dns_hostingde_rm() {
@@ -20,12 +21,14 @@ dns_hostingde_rm() {
txtvalue="${2}"
_debug "Calling: _hostingde_removeRecord() '${fulldomain}' '${txtvalue}'"
_hostingde_apiKey && _hostingde_getZoneConfig && _hostingde_removeRecord
return $?
}
#################### own Private functions below ##################################
_hostingde_apiKey() {
HOSTINGDE_APIKEY="${HOSTINGDE_APIKEY:-$(_readaccountconf_mutable HOSTINGDE_APIKEY)}"
HOSTINGDE_ENDPOINT="${HOSTINGDE_ENDPOINT:-$(_readaccountconf_mutable HOSTINGDE_ENDPOINT)}"
if [ -z "$HOSTINGDE_APIKEY" ] || [ -z "$HOSTINGDE_ENDPOINT" ]; then
HOSTINGDE_APIKEY=""
HOSTINGDE_ENDPOINT=""
@@ -38,6 +41,30 @@ _hostingde_apiKey() {
_saveaccountconf_mutable HOSTINGDE_ENDPOINT "$HOSTINGDE_ENDPOINT"
}
_hostingde_parse() {
find="${1}"
if [ "${2}" ]; then
notfind="${2}"
fi
if [ "${notfind}" ]; then
_egrep_o \""${find}\":.*" | grep -v "${notfind}" | cut -d ':' -f 2 | cut -d ',' -f 1 | tr -d ' '
else
_egrep_o \""${find}\":.*" | cut -d ':' -f 2 | cut -d ',' -f 1 | tr -d ' '
fi
}
_hostingde_parse_no_strip_whitespace() {
find="${1}"
if [ "${2}" ]; then
notfind="${2}"
fi
if [ "${notfind}" ]; then
_egrep_o \""${find}\":.*" | grep -v "${notfind}" | cut -d ':' -f 2 | cut -d ',' -f 1
else
_egrep_o \""${find}\":.*" | cut -d ':' -f 2 | cut -d ',' -f 1
fi
}
_hostingde_getZoneConfig() {
_info "Getting ZoneConfig"
curZone="${fulldomain#*.}"
@@ -59,18 +86,34 @@ _hostingde_getZoneConfig() {
if _contains "${curResult}" '"totalEntries": 1'; then
_info "Retrieved zone data."
_debug "Zone data: '${curResult}'"
zoneConfigId=$(echo "${curResult}" | _egrep_o '"id":.*' | cut -d ':' -f 2 | cut -d '"' -f 2)
zoneConfigName=$(echo "${curResult}" | _egrep_o '"name":.*' | cut -d ':' -f 2 | cut -d '"' -f 2)
zoneConfigType=$(echo "${curResult}" | grep -v "FindZoneConfigsResult" | _egrep_o '"type":.*' | cut -d ':' -f 2 | cut -d '"' -f 2)
zoneConfigExpire=$(echo "${curResult}" | _egrep_o '"expire":.*' | cut -d ':' -f 2 | cut -d '"' -f 2 | cut -d ',' -f 1)
zoneConfigNegativeTtl=$(echo "${curResult}" | _egrep_o '"negativeTtl":.*' | cut -d ':' -f 2 | cut -d '"' -f 2 | cut -d ',' -f 1)
zoneConfigRefresh=$(echo "${curResult}" | _egrep_o '"refresh":.*' | cut -d ':' -f 2 | cut -d '"' -f 2 | cut -d ',' -f 1)
zoneConfigRetry=$(echo "${curResult}" | _egrep_o '"retry":.*' | cut -d ':' -f 2 | cut -d '"' -f 2 | cut -d ',' -f 1)
zoneConfigTtl=$(echo "${curResult}" | _egrep_o '"ttl":.*' | cut -d ':' -f 2 | cut -d '"' -f 2 | cut -d ',' -f 1)
zoneConfigDnsServerGroupId=$(echo "${curResult}" | _egrep_o '"dnsServerGroupId":.*' | cut -d ':' -f 2 | cut -d '"' -f 2)
zoneConfigEmailAddress=$(echo "${curResult}" | _egrep_o '"emailAddress":.*' | cut -d ':' -f 2 | cut -d '"' -f 2)
zoneConfigDnsSecMode=$(echo "${curResult}" | _egrep_o '"dnsSecMode":.*' | cut -d ':' -f 2 | cut -d '"' -f 2)
if [ "${zoneConfigType}" != "NATIVE" ]; then
zoneConfigId=$(echo "${curResult}" | _hostingde_parse "id")
zoneConfigName=$(echo "${curResult}" | _hostingde_parse "name")
zoneConfigType=$(echo "${curResult}" | _hostingde_parse "type" "FindZoneConfigsResult")
zoneConfigExpire=$(echo "${curResult}" | _hostingde_parse "expire")
zoneConfigNegativeTtl=$(echo "${curResult}" | _hostingde_parse "negativeTtl")
zoneConfigRefresh=$(echo "${curResult}" | _hostingde_parse "refresh")
zoneConfigRetry=$(echo "${curResult}" | _hostingde_parse "retry")
zoneConfigTtl=$(echo "${curResult}" | _hostingde_parse "ttl")
zoneConfigDnsServerGroupId=$(echo "${curResult}" | _hostingde_parse "dnsServerGroupId")
zoneConfigEmailAddress=$(echo "${curResult}" | _hostingde_parse "emailAddress")
zoneConfigDnsSecMode=$(echo "${curResult}" | _hostingde_parse "dnsSecMode")
zoneConfigTemplateValues=$(echo "${curResult}" | _hostingde_parse_no_strip_whitespace "templateValues")
if [ "$zoneConfigTemplateValues" != "null" ]; then
_debug "Zone is tied to a template."
zoneConfigTemplateValuesTemplateId=$(echo "${curResult}" | _hostingde_parse "templateId")
zoneConfigTemplateValuesTemplateName=$(echo "${curResult}" | _hostingde_parse_no_strip_whitespace "templateName")
zoneConfigTemplateValuesTemplateReplacementsIPv4=$(echo "${curResult}" | _hostingde_parse "ipv4Replacement")
zoneConfigTemplateValuesTemplateReplacementsIPv6=$(echo "${curResult}" | _hostingde_parse "ipv6Replacement")
zoneConfigTemplateValuesTemplateReplacementsMailIPv4=$(echo "${curResult}" | _hostingde_parse "mailIpv4Replacement")
zoneConfigTemplateValuesTemplateReplacementsMailIPv6=$(echo "${curResult}" | _hostingde_parse "mailIpv6Replacement")
zoneConfigTemplateValuesTemplateTieToTemplate=$(echo "${curResult}" | _hostingde_parse "tieToTemplate")
zoneConfigTemplateValues="{\"templateId\":${zoneConfigTemplateValuesTemplateId},\"templateName\":${zoneConfigTemplateValuesTemplateName},\"templateReplacements\":{\"ipv4Replacement\":${zoneConfigTemplateValuesTemplateReplacementsIPv4},\"ipv6Replacement\":${zoneConfigTemplateValuesTemplateReplacementsIPv6},\"mailIpv4Replacement\":${zoneConfigTemplateValuesTemplateReplacementsMailIPv4},\"mailIpv6Replacement\":${zoneConfigTemplateValuesTemplateReplacementsMailIPv6}},\"tieToTemplate\":${zoneConfigTemplateValuesTemplateTieToTemplate}}"
_debug "Template values: '{$zoneConfigTemplateValues}'"
fi
if [ "${zoneConfigType}" != "\"NATIVE\"" ]; then
_err "Zone is not native"
returnCode=1
break
@@ -89,11 +132,11 @@ _hostingde_getZoneConfig() {
_hostingde_getZoneStatus() {
_debug "Checking Zone status"
curData="{\"filter\":{\"field\":\"zoneConfigId\",\"value\":\"${zoneConfigId}\"},\"limit\":1,\"authToken\":\"${HOSTINGDE_APIKEY}\"}"
curData="{\"filter\":{\"field\":\"zoneConfigId\",\"value\":${zoneConfigId}},\"limit\":1,\"authToken\":\"${HOSTINGDE_APIKEY}\"}"
curResult="$(_post "${curData}" "${HOSTINGDE_ENDPOINT}/api/dns/v1/json/zonesFind")"
_debug "Calling zonesFind '${curData}' '${HOSTINGDE_ENDPOINT}/api/dns/v1/json/zonesFind'"
_debug "Result of zonesFind '$curResult'"
zoneStatus=$(echo "${curResult}" | grep -v success | _egrep_o '"status":.*' | cut -d ':' -f 2 | cut -d '"' -f 2)
zoneStatus=$(echo "${curResult}" | _hostingde_parse "status" "success")
_debug "zoneStatus '${zoneStatus}'"
return 0
}
@@ -102,12 +145,12 @@ _hostingde_addRecord() {
_info "Adding record to zone"
_hostingde_getZoneStatus
_debug "Result of zoneStatus: '${zoneStatus}'"
while [ "${zoneStatus}" != "active" ]; do
while [ "${zoneStatus}" != "\"active\"" ]; do
_sleep 5
_hostingde_getZoneStatus
_debug "Result of zoneStatus: '${zoneStatus}'"
done
curData="{\"authToken\":\"${HOSTINGDE_APIKEY}\",\"zoneConfig\":{\"id\":\"${zoneConfigId}\",\"name\":\"${zoneConfigName}\",\"type\":\"${zoneConfigType}\",\"dnsServerGroupId\":\"${zoneConfigDnsServerGroupId}\",\"dnsSecMode\":\"${zoneConfigDnsSecMode}\",\"emailAddress\":\"${zoneConfigEmailAddress}\",\"soaValues\":{\"expire\":${zoneConfigExpire},\"negativeTtl\":${zoneConfigNegativeTtl},\"refresh\":${zoneConfigRefresh},\"retry\":${zoneConfigRetry},\"ttl\":${zoneConfigTtl}}},\"recordsToAdd\":[{\"name\":\"${fulldomain}\",\"type\":\"TXT\",\"content\":\"\\\"${txtvalue}\\\"\",\"ttl\":3600}]}"
curData="{\"authToken\":\"${HOSTINGDE_APIKEY}\",\"zoneConfig\":{\"id\":${zoneConfigId},\"name\":${zoneConfigName},\"type\":${zoneConfigType},\"dnsServerGroupId\":${zoneConfigDnsServerGroupId},\"dnsSecMode\":${zoneConfigDnsSecMode},\"emailAddress\":${zoneConfigEmailAddress},\"soaValues\":{\"expire\":${zoneConfigExpire},\"negativeTtl\":${zoneConfigNegativeTtl},\"refresh\":${zoneConfigRefresh},\"retry\":${zoneConfigRetry},\"ttl\":${zoneConfigTtl}},\"templateValues\":${zoneConfigTemplateValues}},\"recordsToAdd\":[{\"name\":\"${fulldomain}\",\"type\":\"TXT\",\"content\":\"\\\"${txtvalue}\\\"\",\"ttl\":3600}]}"
curResult="$(_post "${curData}" "${HOSTINGDE_ENDPOINT}/api/dns/v1/json/zoneUpdate")"
_debug "Calling zoneUpdate: '${curData}' '${HOSTINGDE_ENDPOINT}/api/dns/v1/json/zoneUpdate'"
_debug "Result of zoneUpdate: '$curResult'"
@@ -126,12 +169,12 @@ _hostingde_removeRecord() {
_info "Removing record from zone"
_hostingde_getZoneStatus
_debug "Result of zoneStatus: '$zoneStatus'"
while [ "$zoneStatus" != "active" ]; do
while [ "$zoneStatus" != "\"active\"" ]; do
_sleep 5
_hostingde_getZoneStatus
_debug "Result of zoneStatus: '$zoneStatus'"
done
curData="{\"authToken\":\"${HOSTINGDE_APIKEY}\",\"zoneConfig\":{\"id\":\"${zoneConfigId}\",\"name\":\"${zoneConfigName}\",\"type\":\"${zoneConfigType}\",\"dnsServerGroupId\":\"${zoneConfigDnsServerGroupId}\",\"dnsSecMode\":\"${zoneConfigDnsSecMode}\",\"emailAddress\":\"${zoneConfigEmailAddress}\",\"soaValues\":{\"expire\":${zoneConfigExpire},\"negativeTtl\":${zoneConfigNegativeTtl},\"refresh\":${zoneConfigRefresh},\"retry\":${zoneConfigRetry},\"ttl\":${zoneConfigTtl}}},\"recordsToDelete\":[{\"name\":\"${fulldomain}\",\"type\":\"TXT\",\"content\":\"\\\"${txtvalue}\\\"\"}]}"
curData="{\"authToken\":\"${HOSTINGDE_APIKEY}\",\"zoneConfig\":{\"id\":${zoneConfigId},\"name\":${zoneConfigName},\"type\":${zoneConfigType},\"dnsServerGroupId\":${zoneConfigDnsServerGroupId},\"dnsSecMode\":${zoneConfigDnsSecMode},\"emailAddress\":${zoneConfigEmailAddress},\"soaValues\":{\"expire\":${zoneConfigExpire},\"negativeTtl\":${zoneConfigNegativeTtl},\"refresh\":${zoneConfigRefresh},\"retry\":${zoneConfigRetry},\"ttl\":${zoneConfigTtl}},\"templateValues\":${zoneConfigTemplateValues}},\"recordsToDelete\":[{\"name\":\"${fulldomain}\",\"type\":\"TXT\",\"content\":\"\\\"${txtvalue}\\\"\"}]}"
curResult="$(_post "${curData}" "${HOSTINGDE_ENDPOINT}/api/dns/v1/json/zoneUpdate")"
_debug "Calling zoneUpdate: '${curData}' '${HOSTINGDE_ENDPOINT}/api/dns/v1/json/zoneUpdate'"
_debug "Result of zoneUpdate: '$curResult'"

View File

@@ -8,7 +8,7 @@ LINODE_V4_API_URL="https://api.linode.com/v4/domains"
######## Public functions #####################
#Usage: dns_linode_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_linode_add() {
dns_linode_v4_add() {
fulldomain="${1}"
txtvalue="${2}"
@@ -51,7 +51,7 @@ dns_linode_add() {
}
#Usage: dns_linode_rm _acme-challenge.www.domain.com
dns_linode_rm() {
dns_linode_v4_rm() {
fulldomain="${1}"
if ! _Linode_API; then

View File

@@ -4,8 +4,10 @@
#LOOPIA_User="username"
#
#LOOPIA_Password="password"
#
#LOOPIA_Api="https://api.loopia.<TLD>/RPCSERV"
LOOPIA_Api="https://api.loopia.se/RPCSERV"
LOOPIA_Api_Default="https://api.loopia.se/RPCSERV"
######## Public functions #####################
@@ -14,19 +16,11 @@ dns_loopia_add() {
fulldomain=$1
txtvalue=$2
LOOPIA_User="${LOOPIA_User:-$(_readaccountconf_mutable LOOPIA_User)}"
LOOPIA_Password="${LOOPIA_Password:-$(_readaccountconf_mutable LOOPIA_Password)}"
if [ -z "$LOOPIA_User" ] || [ -z "$LOOPIA_Password" ]; then
LOOPIA_User=""
LOOPIA_Password=""
_err "You don't specify loopia user and password yet."
_err "Please create you key and try again."
if ! _loopia_load_config; then
return 1
fi
#save the api key and email to the account conf file.
_saveaccountconf_mutable LOOPIA_User "$LOOPIA_User"
_saveaccountconf_mutable LOOPIA_Password "$LOOPIA_Password"
_loopia_save_config
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
@@ -47,19 +41,11 @@ dns_loopia_rm() {
fulldomain=$1
txtvalue=$2
LOOPIA_User="${LOOPIA_User:-$(_readaccountconf_mutable LOOPIA_User)}"
LOOPIA_Password="${LOOPIA_Password:-$(_readaccountconf_mutable LOOPIA_Password)}"
if [ -z "$LOOPIA_User" ] || [ -z "$LOOPIA_Password" ]; then
LOOPIA_User=""
LOOPIA_Password=""
_err "You don't specify LOOPIA user and password yet."
_err "Please create you key and try again."
if ! _loopia_load_config; then
return 1
fi
#save the api key and email to the account conf file.
_saveaccountconf_mutable LOOPIA_User "$LOOPIA_User"
_saveaccountconf_mutable LOOPIA_Password "$LOOPIA_Password"
_loopia_save_config
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
@@ -84,7 +70,7 @@ dns_loopia_rm() {
<value><string>%s</string></value>
</param>
</params>
</methodCall>' $LOOPIA_User $LOOPIA_Password "$_domain" "$_sub_domain")
</methodCall>' "$LOOPIA_User" "$LOOPIA_Password" "$_domain" "$_sub_domain")
response="$(_post "$xml_content" "$LOOPIA_Api" "" "POST")"
@@ -96,6 +82,36 @@ dns_loopia_rm() {
#################### Private functions below ##################################
_loopia_load_config() {
LOOPIA_Api="${LOOPIA_Api:-$(_readaccountconf_mutable LOOPIA_Api)}"
LOOPIA_User="${LOOPIA_User:-$(_readaccountconf_mutable LOOPIA_User)}"
LOOPIA_Password="${LOOPIA_Password:-$(_readaccountconf_mutable LOOPIA_Password)}"
if [ -z "$LOOPIA_Api" ]; then
LOOPIA_Api="$LOOPIA_Api_Default"
fi
if [ -z "$LOOPIA_User" ] || [ -z "$LOOPIA_Password" ]; then
LOOPIA_User=""
LOOPIA_Password=""
_err "A valid Loopia API user and password not provided."
_err "Please provide a valid API user and try again."
return 1
fi
return 0
}
_loopia_save_config() {
if [ "$LOOPIA_Api" != "$LOOPIA_Api_Default" ]; then
_saveaccountconf_mutable LOOPIA_Api "$LOOPIA_Api"
fi
_saveaccountconf_mutable LOOPIA_User "$LOOPIA_User"
_saveaccountconf_mutable LOOPIA_Password "$LOOPIA_Password"
}
_loopia_get_records() {
domain=$1
sub_domain=$2

97
dnsapi/dns_mydevil.sh Executable file
View File

@@ -0,0 +1,97 @@
#!/usr/bin/env sh
# MyDevil.net API (2019-02-03)
#
# MyDevil.net already supports automatic Let's Encrypt certificates,
# except for wildcard domains.
#
# This script depends on `devil` command that MyDevil.net provides,
# which means that it works only on server side.
#
# Author: Marcin Konicki <https://ahwayakchih.neoni.net>
#
######## Public functions #####################
#Usage: dns_mydevil_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_mydevil_add() {
fulldomain=$1
txtvalue=$2
domain=""
if ! _exists "devil"; then
_err "Could not find 'devil' command."
return 1
fi
_info "Using mydevil"
domain=$(mydevil_get_domain "$fulldomain")
if [ -z "$domain" ]; then
_err "Invalid domain name: could not find root domain of $fulldomain."
return 1
fi
# No need to check if record name exists, `devil` always adds new record.
# In worst case scenario, we end up with multiple identical records.
_info "Adding $fulldomain record for domain $domain"
if devil dns add "$domain" "$fulldomain" TXT "$txtvalue"; then
_info "Successfully added TXT record, ready for validation."
return 0
else
_err "Unable to add DNS record."
return 1
fi
}
#Usage: fulldomain txtvalue
#Remove the txt record after validation.
dns_mydevil_rm() {
fulldomain=$1
txtvalue=$2
domain=""
if ! _exists "devil"; then
_err "Could not find 'devil' command."
return 1
fi
_info "Using mydevil"
domain=$(mydevil_get_domain "$fulldomain")
if [ -z "$domain" ]; then
_err "Invalid domain name: could not find root domain of $fulldomain."
return 1
fi
# catch one or more numbers
num='[0-9][0-9]*'
# catch one or more whitespace
w=$(printf '[\t ][\t ]*')
# catch anything, except newline
any='.*'
# filter to make sure we do not delete other records
validRecords="^${num}${w}${fulldomain}${w}TXT${w}${any}${txtvalue}$"
for id in $(devil dns list "$domain" | tail -n+2 | grep "${validRecords}" | cut -w -s -f 1); do
_info "Removing record $id from domain $domain"
devil dns del "$domain" "$id" || _err "Could not remove DNS record."
done
}
#################### Private functions below ##################################
# Usage: domain=$(mydevil_get_domain "_acme-challenge.www.domain.com" || _err "Invalid domain name")
# echo $domain
mydevil_get_domain() {
fulldomain=$1
domain=""
for domain in $(devil dns list | cut -w -s -f 1 | tail -n+2); do
if _endswith "$fulldomain" "$domain"; then
printf -- "%s" "$domain"
return 0
fi
done
return 1
}

View File

@@ -3,16 +3,15 @@
# Namecheap API
# https://www.namecheap.com/support/api/intro.aspx
#
# Requires Namecheap API key set in NAMECHEAP_API_KEY, NAMECHEAP_SOURCEIP and NAMECHEAP_USERNAME set as environment variable
# Requires Namecheap API key set in
#NAMECHEAP_API_KEY,
#NAMECHEAP_USERNAME,
#NAMECHEAP_SOURCEIP
# Due to Namecheap's API limitation all the records of your domain will be read and re applied, make sure to have a backup of your records you could apply if any issue would arise.
######## Public functions #####################
if [ "$STAGE" -eq 1 ]; then
NAMECHEAP_API="https://api.sandbox.namecheap.com/xml.response"
else
NAMECHEAP_API="https://api.namecheap.com/xml.response"
fi
NAMECHEAP_API="https://api.namecheap.com/xml.response"
#Usage: dns_namecheap_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_namecheap_add() {
@@ -77,6 +76,22 @@ dns_namecheap_rm() {
# _sub_domain=_acme-challenge.www
# _domain=domain.com
_get_root() {
fulldomain=$1
if ! _get_root_by_getList "$fulldomain"; then
_debug "Failed domain lookup via domains.getList api call. Trying domain lookup via domains.dns.getHosts api."
# The above "getList" api will only return hosts *owned* by the calling user. However, if the calling
# user is not the owner, but still has administrative rights, we must query the getHosts api directly.
# See this comment and the official namecheap response: http://disq.us/p/1q6v9x9
if ! _get_root_by_getHosts "$fulldomain"; then
return 1
fi
fi
return 0
}
_get_root_by_getList() {
domain=$1
if ! _namecheap_post "namecheap.domains.getList"; then
@@ -95,6 +110,10 @@ _get_root() {
#not valid
return 1
fi
if ! _contains "$h" "\\."; then
#not valid
return 1
fi
if ! _contains "$response" "$h"; then
_debug "$h not found"
@@ -109,6 +128,31 @@ _get_root() {
return 1
}
_get_root_by_getHosts() {
i=100
p=99
while [ $p -ne 0 ]; do
h=$(printf "%s" "$1" | cut -d . -f $i-100)
if [ -n "$h" ]; then
if _contains "$h" "\\."; then
_debug h "$h"
if _namecheap_set_tld_sld "$h"; then
_sub_domain=$(printf "%s" "$1" | cut -d . -f 1-$p)
_domain="$h"
return 0
else
_debug "$h not found"
fi
fi
fi
i="$p"
p=$(_math "$p" - 1)
done
return 1
}
_namecheap_set_publicip() {
if [ -z "$NAMECHEAP_SOURCEIP" ]; then
@@ -144,7 +188,7 @@ _namecheap_set_publicip() {
_namecheap_post() {
command=$1
data="ApiUser=${NAMECHEAP_USERNAME}&ApiKey=${NAMECHEAP_API_KEY}&ClientIp=${_publicip}&UserName=${NAMECHEAP_USERNAME}&Command=${command}"
_debug2 "_namecheap_post data" "$data"
response="$(_post "$data" "$NAMECHEAP_API" "" "POST")"
_debug2 response "$response"
@@ -224,6 +268,12 @@ _set_namecheap_TXT() {
while read -r host; do
if _contains "$host" "<host"; then
_namecheap_parse_host "$host"
_debug2 _hostname "_hostname"
_debug2 _hosttype "_hosttype"
_debug2 _hostaddress "_hostaddress"
_debug2 _hostmxpref "_hostmxpref"
_hostaddress="$(printf "%s" "$_hostaddress" | _url_encode)"
_debug2 "encoded _hostaddress" "_hostaddress"
_namecheap_add_host "$_hostname" "$_hosttype" "$_hostaddress" "$_hostmxpref" "$_hostttl"
fi
done <<EOT
@@ -278,6 +328,7 @@ _del_namecheap_TXT() {
_debug "TXT entry found"
found=1
else
_hostaddress="$(printf "%s" "$_hostaddress" | _url_encode)"
_namecheap_add_host "$_hostname" "$_hosttype" "$_hostaddress" "$_hostmxpref" "$_hostttl"
fi
fi

View File

@@ -13,6 +13,8 @@ dns_namecom_add() {
fulldomain=$1
txtvalue=$2
Namecom_Username="${Namecom_Username:-$(_readaccountconf_mutable Namecom_Username)}"
Namecom_Token="${Namecom_Token:-$(_readaccountconf_mutable Namecom_Token)}"
# First we need name.com credentials.
if [ -z "$Namecom_Username" ]; then
Namecom_Username=""
@@ -27,10 +29,11 @@ dns_namecom_add() {
_err "Please specify that in your environment variable."
return 1
fi
_debug Namecom_Username "$Namecom_Username"
_secure_debug Namecom_Token "$Namecom_Token"
# Save them in configuration.
_saveaccountconf Namecom_Username "$Namecom_Username"
_saveaccountconf Namecom_Token "$Namecom_Token"
_saveaccountconf_mutable Namecom_Username "$Namecom_Username"
_saveaccountconf_mutable Namecom_Token "$Namecom_Token"
# Login in using API
if ! _namecom_login; then
@@ -46,7 +49,7 @@ dns_namecom_add() {
# Add TXT record.
_namecom_addtxt_json="{\"host\":\"$_sub_domain\",\"type\":\"TXT\",\"answer\":\"$txtvalue\",\"ttl\":\"300\"}"
if _namecom_rest POST "domains/$_domain/records" "$_namecom_addtxt_json"; then
_retvalue=$(printf "%s\n" "$response" | _egrep_o "\"$_sub_domain\"")
_retvalue=$(echo "$response" | _egrep_o "\"$_sub_domain\"")
if [ "$_retvalue" ]; then
_info "Successfully added TXT record, ready for validation."
return 0
@@ -63,6 +66,8 @@ dns_namecom_rm() {
fulldomain=$1
txtvalue=$2
Namecom_Username="${Namecom_Username:-$(_readaccountconf_mutable Namecom_Username)}"
Namecom_Token="${Namecom_Token:-$(_readaccountconf_mutable Namecom_Token)}"
if ! _namecom_login; then
return 1
fi
@@ -75,7 +80,7 @@ dns_namecom_rm() {
# Get the record id.
if _namecom_rest GET "domains/$_domain/records"; then
_record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[0-9]+,\"domainName\":\"$_domain\",\"host\":\"$_sub_domain\",\"fqdn\":\"$fulldomain.\",\"type\":\"TXT\",\"answer\":\"$txtvalue\"" | cut -d \" -f 3 | _egrep_o [0-9]+)
_record_id=$(echo "$response" | _egrep_o "\"id\":[0-9]+,\"domainName\":\"$_domain\",\"host\":\"$_sub_domain\",\"fqdn\":\"$fulldomain.\",\"type\":\"TXT\",\"answer\":\"$txtvalue\"" | cut -d \" -f 3 | _egrep_o [0-9]+)
_debug record_id "$_record_id"
if [ "$_record_id" ]; then
_info "Successfully retrieved the record id for ACME challenge."
@@ -126,10 +131,12 @@ _namecom_login() {
_namecom_auth=$(printf "%s:%s" "$Namecom_Username" "$Namecom_Token" | _base64)
if _namecom_rest GET "hello"; then
retcode=$(printf "%s\n" "$response" | _egrep_o "\"username\"\:\"$Namecom_Username\"")
retcode=$(echo "$response" | _egrep_o "\"username\"\:\"$Namecom_Username\"")
if [ "$retcode" ]; then
_info "Successfully logged in."
else
_err "$response"
_err "Please add your ip to api whitelist"
_err "Logging in failed."
return 1
fi

131
dnsapi/dns_nederhost.sh Executable file
View File

@@ -0,0 +1,131 @@
#!/usr/bin/env sh
#NederHost_Key="sdfgikogfdfghjklkjhgfcdcfghjk"
NederHost_Api="https://api.nederhost.nl/dns/v1"
######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_nederhost_add() {
fulldomain=$1
txtvalue=$2
NederHost_Key="${NederHost_Key:-$(_readaccountconf_mutable NederHost_Key)}"
if [ -z "$NederHost_Key" ]; then
NederHost_Key=""
_err "You didn't specify a NederHost api key."
_err "You can get yours from https://www.nederhost.nl/mijn_nederhost"
return 1
fi
#save the api key and email to the account conf file.
_saveaccountconf_mutable NederHost_Key "$NederHost_Key"
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"
return 1
fi
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
_info "Adding record"
if _nederhost_rest PATCH "zones/$_domain/records/$fulldomain/TXT" "[{\"content\":\"$txtvalue\",\"ttl\":60}]"; then
if _contains "$response" "$fulldomain"; then
_info "Added, OK"
return 0
else
_err "Add txt record error."
return 1
fi
fi
_err "Add txt record error."
return 1
}
#fulldomain txtvalue
dns_nederhost_rm() {
fulldomain=$1
txtvalue=$2
NederHost_Key="${NederHost_Key:-$(_readaccountconf_mutable NederHost_Key)}"
if [ -z "$NederHost_Key" ]; then
NederHost_Key=""
_err "You didn't specify a NederHost api key."
_err "You can get yours from https://www.nederhost.nl/mijn_nederhost"
return 1
fi
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"
return 1
fi
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
_debug "Removing txt record"
_nederhost_rest DELETE "zones/${_domain}/records/$fulldomain/TXT?content=$txtvalue"
}
#################### Private functions below ##################################
#_acme-challenge.www.domain.com
#returns
# _sub_domain=_acme-challenge.www
# _domain=domain.com
_get_root() {
domain=$1
i=2
p=1
while true; do
_domain=$(printf "%s" "$domain" | cut -d . -f $i-100)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_debug _domain "$_domain"
if [ -z "$_domain" ]; then
#not valid
return 1
fi
if _nederhost_rest GET "zones/${_domain}"; then
if [ "${_code}" = "204" ]; then
return 0
fi
else
return 1
fi
p=$i
i=$(_math "$i" + 1)
done
return 1
}
_nederhost_rest() {
m=$1
ep="$2"
data="$3"
_debug "$ep"
export _H1="Authorization: Bearer $NederHost_Key"
export _H2="Content-Type: application/json"
if [ "$m" != "GET" ]; then
_debug data "$data"
response="$(_post "$data" "$NederHost_Api/$ep" "" "$m")"
else
response="$(_get "$NederHost_Api/$ep")"
fi
_code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")"
_debug "http response code $_code"
if [ "$?" != "0" ]; then
_err "error $ep"
return 1
fi
_debug2 response "$response"
return 0
}

View File

@@ -8,6 +8,7 @@ end="https://ccp.netcup.net/run/webservice/servers/endpoint.php?JSON"
client=""
dns_netcup_add() {
_debug NC_Apikey "$NC_Apikey"
login
if [ "$NC_Apikey" = "" ] || [ "$NC_Apipw" = "" ] || [ "$NC_CID" = "" ]; then
_err "No Credentials given"

View File

@@ -46,7 +46,7 @@ dns_nsone_add() {
if [ "$count" = "0" ]; then
_info "Adding record"
if _nsone_rest PUT "zones/$_domain/$fulldomain/TXT" "{\"answers\":[{\"answer\":[\"$txtvalue\"]}],\"type\":\"TXT\",\"domain\":\"$fulldomain\",\"zone\":\"$_domain\"}"; then
if _nsone_rest PUT "zones/$_domain/$fulldomain/TXT" "{\"answers\":[{\"answer\":[\"$txtvalue\"]}],\"type\":\"TXT\",\"domain\":\"$fulldomain\",\"zone\":\"$_domain\",\"ttl\":0}"; then
if _contains "$response" "$fulldomain"; then
_info "Added"
#todo: check if the record takes effect
@@ -62,7 +62,7 @@ dns_nsone_add() {
prev_txt=$(printf "%s\n" "$response" | _egrep_o "\"domain\":\"$fulldomain\",\"short_answers\":\[\"[^,]*\]" | _head_n 1 | cut -d: -f3 | cut -d, -f1)
_debug "prev_txt" "$prev_txt"
_nsone_rest POST "zones/$_domain/$fulldomain/TXT" "{\"answers\": [{\"answer\": [\"$txtvalue\"]},{\"answer\": $prev_txt}],\"type\": \"TXT\",\"domain\":\"$fulldomain\",\"zone\": \"$_domain\"}"
_nsone_rest POST "zones/$_domain/$fulldomain/TXT" "{\"answers\": [{\"answer\": [\"$txtvalue\"]},{\"answer\": $prev_txt}],\"type\": \"TXT\",\"domain\":\"$fulldomain\",\"zone\": \"$_domain\",\"ttl\":0}"
if [ "$?" = "0" ] && _contains "$response" "$fulldomain"; then
_info "Updated!"
#todo: check if the record takes effect

View File

@@ -6,14 +6,22 @@
dns_nsupdate_add() {
fulldomain=$1
txtvalue=$2
NSUPDATE_SERVER="${NSUPDATE_SERVER:-$(_readaccountconf_mutable NSUPDATE_SERVER)}"
NSUPDATE_SERVER_PORT="${NSUPDATE_SERVER_PORT:-$(_readaccountconf_mutable NSUPDATE_SERVER_PORT)}"
NSUPDATE_KEY="${NSUPDATE_KEY:-$(_readaccountconf_mutable NSUPDATE_KEY)}"
NSUPDATE_ZONE="${NSUPDATE_ZONE:-$(_readaccountconf_mutable NSUPDATE_ZONE)}"
_checkKeyFile || return 1
# save the dns server and key to the account conf file.
_saveaccountconf_mutable NSUPDATE_SERVER "${NSUPDATE_SERVER}"
_saveaccountconf_mutable NSUPDATE_SERVER_PORT "${NSUPDATE_SERVER_PORT}"
_saveaccountconf_mutable NSUPDATE_KEY "${NSUPDATE_KEY}"
_saveaccountconf_mutable NSUPDATE_ZONE "${NSUPDATE_ZONE}"
[ -n "${NSUPDATE_SERVER}" ] || NSUPDATE_SERVER="localhost"
[ -n "${NSUPDATE_SERVER_PORT}" ] || NSUPDATE_SERVER_PORT=53
# save the dns server and key to the account conf file.
_saveaccountconf NSUPDATE_SERVER "${NSUPDATE_SERVER}"
_saveaccountconf NSUPDATE_SERVER_PORT "${NSUPDATE_SERVER_PORT}"
_saveaccountconf NSUPDATE_KEY "${NSUPDATE_KEY}"
_saveaccountconf NSUPDATE_ZONE "${NSUPDATE_ZONE}"
_info "adding ${fulldomain}. 60 in txt \"${txtvalue}\""
[ -n "$DEBUG" ] && [ "$DEBUG" -ge "$DEBUG_LEVEL_1" ] && nsdebug="-d"
[ -n "$DEBUG" ] && [ "$DEBUG" -ge "$DEBUG_LEVEL_2" ] && nsdebug="-D"
@@ -42,6 +50,12 @@ EOF
#Usage: dns_nsupdate_rm _acme-challenge.www.domain.com
dns_nsupdate_rm() {
fulldomain=$1
NSUPDATE_SERVER="${NSUPDATE_SERVER:-$(_readaccountconf_mutable NSUPDATE_SERVER)}"
NSUPDATE_SERVER_PORT="${NSUPDATE_SERVER_PORT:-$(_readaccountconf_mutable NSUPDATE_SERVER_PORT)}"
NSUPDATE_KEY="${NSUPDATE_KEY:-$(_readaccountconf_mutable NSUPDATE_KEY)}"
NSUPDATE_ZONE="${NSUPDATE_ZONE:-$(_readaccountconf_mutable NSUPDATE_ZONE)}"
_checkKeyFile || return 1
[ -n "${NSUPDATE_SERVER}" ] || NSUPDATE_SERVER="localhost"
[ -n "${NSUPDATE_SERVER_PORT}" ] || NSUPDATE_SERVER_PORT=53

211
dnsapi/dns_nw.sh Normal file
View File

@@ -0,0 +1,211 @@
#!/usr/bin/env sh
########################################################################
# NocWorx script for acme.sh
#
# Handles DNS Updates for the Following vendors:
# - Nexcess.net
# - Thermo.io
# - Futurehosting.com
#
# Environment variables:
#
# - NW_API_TOKEN (Your API Token)
# - NW_API_ENDPOINT (One of the following listed below)
#
# Endpoints:
# - https://portal.nexcess.net (default)
# - https://core.thermo.io
# - https://my.futurehosting.com
#
# Note: If you do not have an API token, one can be generated at one
# of the following URLs:
# - https://portal.nexcess.net/api-token
# - https://core.thermo.io/api-token
# - https://my.futurehosting.com/api-token
#
# Author: Frank Laszlo <flaszlo@nexcess.net>
NW_API_VERSION="0"
# dns_nw_add() - Add TXT record
# Usage: dns_nw_add _acme-challenge.subdomain.domain.com "XyZ123..."
dns_nw_add() {
host="${1}"
txtvalue="${2}"
_debug host "${host}"
_debug txtvalue "${txtvalue}"
if ! _check_nw_api_creds; then
return 1
fi
_info "Using NocWorx (${NW_API_ENDPOINT})"
_debug "Calling: dns_nw_add() '${host}' '${txtvalue}'"
_debug "Detecting root zone"
if ! _get_root "${host}"; then
_err "Zone for domain does not exist."
return 1
fi
_debug _zone_id "${_zone_id}"
_debug _sub_domain "${_sub_domain}"
_debug _domain "${_domain}"
_post_data="{\"zone_id\": \"${_zone_id}\", \"type\": \"TXT\", \"host\": \"${host}\", \"target\": \"${txtvalue}\", \"ttl\": \"300\"}"
if _rest POST "dns-record" "${_post_data}" && [ -n "${response}" ]; then
_record_id=$(printf "%s\n" "${response}" | _egrep_o "\"record_id\": *[0-9]+" | cut -d : -f 2 | tr -d " " | _head_n 1)
_debug _record_id "${_record_id}"
if [ -z "$_record_id" ]; then
_err "Error adding the TXT record."
return 1
fi
_info "TXT record successfully added."
return 0
fi
return 1
}
# dns_nw_rm() - Remove TXT record
# Usage: dns_nw_rm _acme-challenge.subdomain.domain.com "XyZ123..."
dns_nw_rm() {
host="${1}"
txtvalue="${2}"
_debug host "${host}"
_debug txtvalue "${txtvalue}"
if ! _check_nw_api_creds; then
return 1
fi
_info "Using NocWorx (${NW_API_ENDPOINT})"
_debug "Calling: dns_nw_rm() '${host}'"
_debug "Detecting root zone"
if ! _get_root "${host}"; then
_err "Zone for domain does not exist."
return 1
fi
_debug _zone_id "${_zone_id}"
_debug _sub_domain "${_sub_domain}"
_debug _domain "${_domain}"
_parameters="?zone_id=${_zone_id}"
if _rest GET "dns-record" "${_parameters}" && [ -n "${response}" ]; then
response="$(echo "${response}" | tr -d "\n" | sed 's/^\[\(.*\)\]$/\1/' | sed -e 's/{"record_id":/|"record_id":/g' | sed 's/|/&{/g' | tr "|" "\n")"
_debug response "${response}"
record="$(echo "${response}" | _egrep_o "{.*\"host\": *\"${_sub_domain}\", *\"target\": *\"${txtvalue}\".*}")"
_debug record "${record}"
if [ "${record}" ]; then
_record_id=$(printf "%s\n" "${record}" | _egrep_o "\"record_id\": *[0-9]+" | _head_n 1 | cut -d : -f 2 | tr -d \ )
if [ "${_record_id}" ]; then
_debug _record_id "${_record_id}"
_rest DELETE "dns-record/${_record_id}"
_info "TXT record successfully deleted."
return 0
fi
return 1
fi
return 0
fi
return 1
}
_check_nw_api_creds() {
NW_API_TOKEN="${NW_API_TOKEN:-$(_readaccountconf_mutable NW_API_TOKEN)}"
NW_API_ENDPOINT="${NW_API_ENDPOINT:-$(_readaccountconf_mutable NW_API_ENDPOINT)}"
if [ -z "${NW_API_ENDPOINT}" ]; then
NW_API_ENDPOINT="https://portal.nexcess.net"
fi
if [ -z "${NW_API_TOKEN}" ]; then
_err "You have not defined your NW_API_TOKEN."
_err "Please create your token and try again."
_err "If you need to generate a new token, please visit one of the following URLs:"
_err " - https://portal.nexcess.net/api-token"
_err " - https://core.thermo.io/api-token"
_err " - https://my.futurehosting.com/api-token"
return 1
fi
_saveaccountconf_mutable NW_API_TOKEN "${NW_API_TOKEN}"
_saveaccountconf_mutable NW_API_ENDPOINT "${NW_API_ENDPOINT}"
}
_get_root() {
domain="${1}"
i=2
p=1
if _rest GET "dns-zone"; then
response="$(echo "${response}" | tr -d "\n" | sed 's/^\[\(.*\)\]$/\1/' | sed -e 's/{"zone_id":/|"zone_id":/g' | sed 's/|/&{/g' | tr "|" "\n")"
_debug response "${response}"
while true; do
h=$(printf "%s" "${domain}" | cut -d . -f $i-100)
_debug h "${h}"
if [ -z "${h}" ]; then
#not valid
return 1
fi
hostedzone="$(echo "${response}" | _egrep_o "{.*\"domain\": *\"${h}\".*}")"
if [ "${hostedzone}" ]; then
_zone_id=$(printf "%s\n" "${hostedzone}" | _egrep_o "\"zone_id\": *[0-9]+" | _head_n 1 | cut -d : -f 2 | tr -d \ )
if [ "${_zone_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
}
_rest() {
method="${1}"
ep="/${2}"
data="${3}"
_debug method "${method}"
_debug ep "${ep}"
export _H1="Accept: application/json"
export _H2="Content-Type: application/json"
export _H3="Api-Version: ${NW_API_VERSION}"
export _H4="User-Agent: NW-ACME-CLIENT"
export _H5="Authorization: Bearer ${NW_API_TOKEN}"
if [ "${method}" != "GET" ]; then
_debug data "${data}"
response="$(_post "${data}" "${NW_API_ENDPOINT}${ep}" "" "${method}")"
else
response="$(_get "${NW_API_ENDPOINT}${ep}${data}")"
fi
if [ "${?}" != "0" ]; then
_err "error ${ep}"
return 1
fi
_debug2 response "${response}"
return 0
}

217
dnsapi/dns_online.sh Executable file
View File

@@ -0,0 +1,217 @@
#!/usr/bin/env sh
# Online API
# https://console.online.net/en/api/
#
# Requires Online API key set in ONLINE_API_KEY
######## Public functions #####################
ONLINE_API="https://api.online.net/api/v1"
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_online_add() {
fulldomain=$1
txtvalue=$2
if ! _online_check_config; then
return 1
fi
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"
return 1
fi
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
_debug _real_dns_version "$_real_dns_version"
_info "Creating temporary zone version"
_online_create_temporary_zone_version
_info "Enabling temporary zone version"
_online_enable_zone "$_temporary_dns_version"
_info "Adding record"
_online_create_TXT_record "$_real_dns_version" "$_sub_domain" "$txtvalue"
_info "Disabling temporary version"
_online_enable_zone "$_real_dns_version"
_info "Destroying temporary version"
_online_destroy_zone "$_temporary_dns_version"
_info "Record added."
return 0
}
#fulldomain
dns_online_rm() {
fulldomain=$1
txtvalue=$2
if ! _online_check_config; then
return 1
fi
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"
return 1
fi
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
_debug _real_dns_version "$_real_dns_version"
_debug "Getting txt records"
if ! _online_rest GET "domain/$_domain/version/active"; then
return 1
fi
rid=$(echo "$response" | _egrep_o "\"id\":[0-9]+,\"name\":\"$_sub_domain\",\"data\":\"\\\u0022$txtvalue\\\u0022\"" | cut -d ':' -f 2 | cut -d ',' -f 1)
_debug rid "$rid"
if [ -z "$rid" ]; then
return 1
fi
_info "Creating temporary zone version"
_online_create_temporary_zone_version
_info "Enabling temporary zone version"
_online_enable_zone "$_temporary_dns_version"
_info "Removing DNS record"
_online_rest DELETE "domain/$_domain/version/$_real_dns_version/zone/$rid"
_info "Disabling temporary version"
_online_enable_zone "$_real_dns_version"
_info "Destroying temporary version"
_online_destroy_zone "$_temporary_dns_version"
return 0
}
#################### Private functions below ##################################
_online_check_config() {
ONLINE_API_KEY="${ONLINE_API_KEY:-$(_readaccountconf_mutable ONLINE_API_KEY)}"
if [ -z "$ONLINE_API_KEY" ]; then
_err "No API key specified for Online API."
_err "Create your key and export it as ONLINE_API_KEY"
return 1
fi
if ! _online_rest GET "domain/"; then
_err "Invalid API key specified for Online API."
return 1
fi
_saveaccountconf_mutable ONLINE_API_KEY "$ONLINE_API_KEY"
return 0
}
#_acme-challenge.www.domain.com
#returns
# _sub_domain=_acme-challenge.www
# _domain=domain.com
_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
_online_rest GET "domain/$h/version/active"
if ! _contains "$response" "Domain not found" >/dev/null; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_domain="$h"
_real_dns_version=$(echo "$response" | _egrep_o '"uuid_ref":.*' | cut -d ':' -f 2 | cut -d '"' -f 2)
return 0
fi
p=$i
i=$(_math "$i" + 1)
done
_err "Unable to retrive DNS zone matching this domain"
return 1
}
# this function create a temporary zone version
# as online.net does not allow updating an active version
_online_create_temporary_zone_version() {
_online_rest POST "domain/$_domain/version" "name=acme.sh"
if [ "$?" != "0" ]; then
return 1
fi
_temporary_dns_version=$(echo "$response" | _egrep_o '"uuid_ref":.*' | cut -d ':' -f 2 | cut -d '"' -f 2)
# Creating a dummy record in this temporary version, because online.net doesn't accept enabling an empty version
_online_create_TXT_record "$_temporary_dns_version" "dummy.acme.sh" "dummy"
return 0
}
_online_destroy_zone() {
version_id=$1
_online_rest DELETE "domain/$_domain/version/$version_id"
if [ "$?" != "0" ]; then
return 1
fi
return 0
}
_online_enable_zone() {
version_id=$1
_online_rest PATCH "domain/$_domain/version/$version_id/enable"
if [ "$?" != "0" ]; then
return 1
fi
return 0
}
_online_create_TXT_record() {
version=$1
txt_name=$2
txt_value=$3
_online_rest POST "domain/$_domain/version/$version/zone" "type=TXT&name=$txt_name&data=%22$txt_value%22&ttl=60&priority=0"
# Note : the normal, expected response SHOULD be "Unknown method".
# this happens because the API HTTP response contains a Location: header, that redirect
# to an unknown online.net endpoint.
if [ "$?" != "0" ] || _contains "$response" "Unknown method" || _contains "$response" "\$ref"; then
return 0
else
_err "error $response"
return 1
fi
}
_online_rest() {
m=$1
ep="$2"
data="$3"
_debug "$ep"
_online_url="$ONLINE_API/$ep"
_debug2 _online_url "$_online_url"
export _H1="Authorization: Bearer $ONLINE_API_KEY"
export _H2="X-Pretty-JSON: 1"
if [ "$data" ] || [ "$m" != "GET" ]; then
_debug data "$data"
response="$(_post "$data" "$_online_url" "" "$m")"
else
response="$(_get "$_online_url")"
fi
if [ "$?" != "0" ] || _contains "$response" "invalid_grant" || _contains "$response" "Method not allowed"; then
_err "error $response"
return 1
fi
_debug2 response "$response"
return 0
}

244
dnsapi/dns_openprovider.sh Executable file
View File

@@ -0,0 +1,244 @@
#!/usr/bin/env sh
# This is the OpenProvider API wrapper for acme.sh
#
# Author: Sylvia van Os
# Report Bugs here: https://github.com/Neilpang/acme.sh/issues/2104
#
# export OPENPROVIDER_USER="username"
# export OPENPROVIDER_PASSWORDHASH="hashed_password"
#
# Usage:
# acme.sh --issue --dns dns_openprovider -d example.com
OPENPROVIDER_API="https://api.openprovider.eu/"
#OPENPROVIDER_API="https://api.cte.openprovider.eu/" # Test API
######## Public functions #####################
#Usage: dns_openprovider_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_openprovider_add() {
fulldomain="$1"
txtvalue="$2"
OPENPROVIDER_USER="${OPENPROVIDER_USER:-$(_readaccountconf_mutable OPENPROVIDER_USER)}"
OPENPROVIDER_PASSWORDHASH="${OPENPROVIDER_PASSWORDHASH:-$(_readaccountconf_mutable OPENPROVIDER_PASSWORDHASH)}"
if [ -z "$OPENPROVIDER_USER" ] || [ -z "$OPENPROVIDER_PASSWORDHASH" ]; then
_err "You didn't specify the openprovider user and/or password hash."
return 1
fi
# save the username and password to the account conf file.
_saveaccountconf_mutable OPENPROVIDER_USER "$OPENPROVIDER_USER"
_saveaccountconf_mutable OPENPROVIDER_PASSWORDHASH "$OPENPROVIDER_PASSWORDHASH"
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"
return 1
fi
_debug _domain_name "$_domain_name"
_debug _domain_extension "$_domain_extension"
_debug "Getting current records"
existing_items=""
results_retrieved=0
while true; do
_openprovider_request "$(printf '<searchZoneRecordDnsRequest><name>%s.%s</name><offset>%s</offset></searchZoneRecordDnsRequest>' "$_domain_name" "$_domain_extension" "$results_retrieved")"
items="$response"
while true; do
item="$(echo "$items" | _egrep_o '<openXML>.*<\/openXML>' | sed -n 's/.*\(<item>.*<\/item>\).*/\1/p')"
_debug existing_items "$existing_items"
_debug results_retrieved "$results_retrieved"
_debug item "$item"
if [ -z "$item" ]; then
break
fi
items="$(echo "$items" | sed "s|${item}||")"
results_retrieved="$(_math "$results_retrieved" + 1)"
new_item="$(echo "$item" | sed -n 's/.*<item>.*\(<name>\(.*\)\.'"$_domain_name"'\.'"$_domain_extension"'<\/name>.*\(<type>.*<\/type>\).*\(<value>.*<\/value>\).*\(<prio>.*<\/prio>\).*\(<ttl>.*<\/ttl>\)\).*<\/item>.*/<item><name>\2<\/name>\3\4\5\6<\/item>/p')"
if [ -z "$new_item" ]; then
# Base record
new_item="$(echo "$item" | sed -n 's/.*<item>.*\(<name>\(.*\)'"$_domain_name"'\.'"$_domain_extension"'<\/name>.*\(<type>.*<\/type>\).*\(<value>.*<\/value>\).*\(<prio>.*<\/prio>\).*\(<ttl>.*<\/ttl>\)\).*<\/item>.*/<item><name>\2<\/name>\3\4\5\6<\/item>/p')"
fi
if [ -z "$(echo "$new_item" | _egrep_o ".*<type>(A|AAAA|CNAME|MX|SPF|SRV|TXT|TLSA|SSHFP|CAA)<\/type>.*")" ]; then
_debug "not an allowed record type, skipping" "$new_item"
continue
fi
existing_items="$existing_items$new_item"
done
total="$(echo "$response" | _egrep_o '<total>.*?<\/total>' | sed -n 's/.*<total>\(.*\)<\/total>.*/\1/p')"
_debug total "$total"
if [ "$results_retrieved" -eq "$total" ]; then
break
fi
done
_debug "Creating acme record"
acme_record="$(echo "$fulldomain" | sed -e "s/.$_domain_name.$_domain_extension$//")"
_openprovider_request "$(printf '<modifyZoneDnsRequest><domain><name>%s</name><extension>%s</extension></domain><type>master</type><records><array>%s<item><name>%s</name><type>TXT</type><value>%s</value><ttl>86400</ttl></item></array></records></modifyZoneDnsRequest>' "$_domain_name" "$_domain_extension" "$existing_items" "$acme_record" "$txtvalue")"
return 0
}
#Usage: fulldomain txtvalue
#Remove the txt record after validation.
dns_openprovider_rm() {
fulldomain="$1"
txtvalue="$2"
OPENPROVIDER_USER="${OPENPROVIDER_USER:-$(_readaccountconf_mutable OPENPROVIDER_USER)}"
OPENPROVIDER_PASSWORDHASH="${OPENPROVIDER_PASSWORDHASH:-$(_readaccountconf_mutable OPENPROVIDER_PASSWORDHASH)}"
if [ -z "$OPENPROVIDER_USER" ] || [ -z "$OPENPROVIDER_PASSWORDHASH" ]; then
_err "You didn't specify the openprovider user and/or password hash."
return 1
fi
# save the username and password to the account conf file.
_saveaccountconf_mutable OPENPROVIDER_USER "$OPENPROVIDER_USER"
_saveaccountconf_mutable OPENPROVIDER_PASSWORDHASH "$OPENPROVIDER_PASSWORDHASH"
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"
return 1
fi
_debug _domain_name "$_domain_name"
_debug _domain_extension "$_domain_extension"
_debug "Getting current records"
existing_items=""
results_retrieved=0
while true; do
_openprovider_request "$(printf '<searchZoneRecordDnsRequest><name>%s.%s</name><offset>%s</offset></searchZoneRecordDnsRequest>' "$_domain_name" "$_domain_extension" "$results_retrieved")"
# Remove acme records from items
items="$response"
while true; do
item="$(echo "$items" | _egrep_o '<openXML>.*<\/openXML>' | sed -n 's/.*\(<item>.*<\/item>\).*/\1/p')"
_debug existing_items "$existing_items"
_debug results_retrieved "$results_retrieved"
_debug item "$item"
if [ -z "$item" ]; then
break
fi
items="$(echo "$items" | sed "s|${item}||")"
results_retrieved="$(_math "$results_retrieved" + 1)"
if ! echo "$item" | grep -v "$fulldomain"; then
_debug "acme record, skipping" "$item"
continue
fi
new_item="$(echo "$item" | sed -n 's/.*<item>.*\(<name>\(.*\)\.'"$_domain_name"'\.'"$_domain_extension"'<\/name>.*\(<type>.*<\/type>\).*\(<value>.*<\/value>\).*\(<prio>.*<\/prio>\).*\(<ttl>.*<\/ttl>\)\).*<\/item>.*/<item><name>\2<\/name>\3\4\5\6<\/item>/p')"
if [ -z "$new_item" ]; then
# Base record
new_item="$(echo "$item" | sed -n 's/.*<item>.*\(<name>\(.*\)'"$_domain_name"'\.'"$_domain_extension"'<\/name>.*\(<type>.*<\/type>\).*\(<value>.*<\/value>\).*\(<prio>.*<\/prio>\).*\(<ttl>.*<\/ttl>\)\).*<\/item>.*/<item><name>\2<\/name>\3\4\5\6<\/item>/p')"
fi
if [ -z "$(echo "$new_item" | _egrep_o ".*<type>(A|AAAA|CNAME|MX|SPF|SRV|TXT|TLSA|SSHFP|CAA)<\/type>.*")" ]; then
_debug "not an allowed record type, skipping" "$new_item"
continue
fi
existing_items="$existing_items$new_item"
done
total="$(echo "$response" | _egrep_o '<total>.*?<\/total>' | sed -n 's/.*<total>\(.*\)<\/total>.*/\1/p')"
_debug total "$total"
if [ "$results_retrieved" -eq "$total" ]; then
break
fi
done
_debug "Removing acme record"
_openprovider_request "$(printf '<modifyZoneDnsRequest><domain><name>%s</name><extension>%s</extension></domain><type>master</type><records><array>%s</array></records></modifyZoneDnsRequest>' "$_domain_name" "$_domain_extension" "$existing_items")"
return 0
}
#################### Private functions below ##################################
#_acme-challenge.www.domain.com
#returns
# _domain_name=domain
# _domain_extension=com
_get_root() {
domain=$1
i=2
results_retrieved=0
while true; do
h=$(echo "$domain" | cut -d . -f $i-100)
_debug h "$h"
if [ -z "$h" ]; then
#not valid
return 1
fi
_openprovider_request "$(printf '<searchDomainRequest><domainNamePattern>%s</domainNamePattern><offset>%s</offset></searchDomainRequest>' "$(echo "$h" | cut -d . -f 1)" "$results_retrieved")"
items="$response"
while true; do
item="$(echo "$items" | _egrep_o '<openXML>.*<\/openXML>' | sed -n 's/.*\(<domain>.*<\/domain>\).*/\1/p')"
_debug existing_items "$existing_items"
_debug results_retrieved "$results_retrieved"
_debug item "$item"
if [ -z "$item" ]; then
break
fi
items="$(echo "$items" | sed "s|${item}||")"
results_retrieved="$(_math "$results_retrieved" + 1)"
_domain_name="$(echo "$item" | sed -n 's/.*<domain>.*<name>\(.*\)<\/name>.*<\/domain>.*/\1/p')"
_domain_extension="$(echo "$item" | sed -n 's/.*<domain>.*<extension>\(.*\)<\/extension>.*<\/domain>.*/\1/p')"
_debug _domain_name "$_domain_name"
_debug _domain_extension "$_domain_extension"
if [ "$_domain_name.$_domain_extension" = "$h" ]; then
return 0
fi
done
total="$(echo "$response" | _egrep_o '<total>.*?<\/total>' | sed -n 's/.*<total>\(.*\)<\/total>.*/\1/p')"
_debug total "$total"
if [ "$results_retrieved" -eq "$total" ]; then
results_retrieved=0
i="$(_math "$i" + 1)"
fi
done
return 1
}
_openprovider_request() {
request_xml=$1
xml_prefix='<?xml version="1.0" encoding="UTF-8"?>'
xml_content=$(printf '<openXML><credentials><username>%s</username><hash>%s</hash></credentials>%s</openXML>' "$OPENPROVIDER_USER" "$OPENPROVIDER_PASSWORDHASH" "$request_xml")
response="$(_post "$(echo "$xml_prefix$xml_content" | tr -d '\n')" "$OPENPROVIDER_API" "" "POST" "application/xml")"
_debug response "$response"
if ! _contains "$response" "<openXML><reply><code>0</code>.*</reply></openXML>"; then
_err "API request failed."
return 1
fi
}

207
dnsapi/dns_rackspace.sh Normal file
View File

@@ -0,0 +1,207 @@
#!/usr/bin/env sh
#
#
#RACKSPACE_Username=""
#
#RACKSPACE_Apikey=""
RACKSPACE_Endpoint="https://dns.api.rackspacecloud.com/v1.0"
# 20190213 - The name & id fields swapped in the API response; fix sed
# 20190101 - Duplicating file for new pull request to dev branch
# Original - tcocca:rackspace_dnsapi https://github.com/Neilpang/acme.sh/pull/1297
######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_rackspace_add() {
fulldomain="$1"
_debug fulldomain="$fulldomain"
txtvalue="$2"
_debug txtvalue="$txtvalue"
_rackspace_check_auth || return 1
_rackspace_check_rootzone || return 1
_info "Creating TXT record."
if ! _rackspace_rest POST "$RACKSPACE_Tenant/domains/$_domain_id/records" "{\"records\":[{\"name\":\"$fulldomain\",\"type\":\"TXT\",\"data\":\"$txtvalue\",\"ttl\":300}]}"; then
return 1
fi
_debug2 response "$response"
if ! _contains "$response" "$txtvalue" >/dev/null; then
_err "Could not add TXT record."
return 1
fi
return 0
}
#fulldomain txtvalue
dns_rackspace_rm() {
fulldomain=$1
_debug fulldomain="$fulldomain"
txtvalue=$2
_debug txtvalue="$txtvalue"
_rackspace_check_auth || return 1
_rackspace_check_rootzone || return 1
_info "Checking for TXT record."
if ! _get_recordid "$_domain_id" "$fulldomain" "$txtvalue"; then
_err "Could not get TXT record id."
return 1
fi
if [ "$_dns_record_id" = "" ]; then
_err "TXT record not found."
return 1
fi
_info "Removing TXT record."
if ! _delete_txt_record "$_domain_id" "$_dns_record_id"; then
_err "Could not remove TXT record $_dns_record_id."
fi
return 0
}
#################### Private functions below ##################################
#_acme-challenge.www.domain.com
#returns
# _sub_domain=_acme-challenge.www
# _domain=domain.com
# _domain_id=sdjkglgdfewsdfg
_get_root_zone() {
domain="$1"
i=2
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
_debug h "$h"
if [ -z "$h" ]; then
#not valid
return 1
fi
if ! _rackspace_rest GET "$RACKSPACE_Tenant/domains"; then
return 1
fi
_debug2 response "$response"
if _contains "$response" "\"name\":\"$h\"" >/dev/null; then
# Response looks like:
# {"ttl":300,"accountId":12345,"id":1111111,"name":"example.com","emailAddress": ...<and so on>
_domain_id=$(echo "$response" | sed -n "s/^.*\"id\":\([^,]*\),\"name\":\"$h\",.*/\1/p")
_debug2 domain_id "$_domain_id"
if [ -n "$_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
return 1
}
_get_recordid() {
domainid="$1"
fulldomain="$2"
txtvalue="$3"
if ! _rackspace_rest GET "$RACKSPACE_Tenant/domains/$domainid/records?name=$fulldomain&type=TXT"; then
return 1
fi
_debug response "$response"
if ! _contains "$response" "$txtvalue"; then
_dns_record_id=0
return 0
fi
_dns_record_id=$(echo "$response" | tr '{' "\n" | grep "\"data\":\"$txtvalue\"" | sed -n 's/^.*"id":"\([^"]*\)".*/\1/p')
_debug _dns_record_id "$_dns_record_id"
return 0
}
_delete_txt_record() {
domainid="$1"
_dns_record_id="$2"
if ! _rackspace_rest DELETE "$RACKSPACE_Tenant/domains/$domainid/records?id=$_dns_record_id"; then
return 1
fi
_debug response "$response"
if ! _contains "$response" "RUNNING"; then
return 1
fi
return 0
}
_rackspace_rest() {
m="$1"
ep="$2"
data="$3"
_debug ep "$ep"
export _H1="Accept: application/json"
export _H2="X-Auth-Token: $RACKSPACE_Token"
export _H3="X-Project-Id: $RACKSPACE_Tenant"
export _H4="Content-Type: application/json"
if [ "$m" != "GET" ]; then
_debug data "$data"
response="$(_post "$data" "$RACKSPACE_Endpoint/$ep" "" "$m")"
retcode=$?
else
_info "Getting $RACKSPACE_Endpoint/$ep"
response="$(_get "$RACKSPACE_Endpoint/$ep")"
retcode=$?
fi
if [ "$retcode" != "0" ]; then
_err "error $ep"
return 1
fi
_debug2 response "$response"
return 0
}
_rackspace_authorization() {
export _H1="Content-Type: application/json"
data="{\"auth\":{\"RAX-KSKEY:apiKeyCredentials\":{\"username\":\"$RACKSPACE_Username\",\"apiKey\":\"$RACKSPACE_Apikey\"}}}"
_debug data "$data"
response="$(_post "$data" "https://identity.api.rackspacecloud.com/v2.0/tokens" "" "POST")"
retcode=$?
_debug2 response "$response"
if [ "$retcode" != "0" ]; then
_err "Authentication failed."
return 1
fi
if _contains "$response" "token"; then
RACKSPACE_Token="$(echo "$response" | _normalizeJson | sed -n 's/^.*"token":{.*,"id":"\([^"]*\)",".*/\1/p')"
RACKSPACE_Tenant="$(echo "$response" | _normalizeJson | sed -n 's/^.*"token":{.*,"id":"\([^"]*\)"}.*/\1/p')"
_debug RACKSPACE_Token "$RACKSPACE_Token"
_debug RACKSPACE_Tenant "$RACKSPACE_Tenant"
fi
return 0
}
_rackspace_check_auth() {
# retrieve the rackspace creds
RACKSPACE_Username="${RACKSPACE_Username:-$(_readaccountconf_mutable RACKSPACE_Username)}"
RACKSPACE_Apikey="${RACKSPACE_Apikey:-$(_readaccountconf_mutable RACKSPACE_Apikey)}"
# check their vals for null
if [ -z "$RACKSPACE_Username" ] || [ -z "$RACKSPACE_Apikey" ]; then
RACKSPACE_Username=""
RACKSPACE_Apikey=""
_err "You didn't specify a Rackspace username and api key."
_err "Please set those values and try again."
return 1
fi
# save the username and api key to the account conf file.
_saveaccountconf_mutable RACKSPACE_Username "$RACKSPACE_Username"
_saveaccountconf_mutable RACKSPACE_Apikey "$RACKSPACE_Apikey"
if [ -z "$RACKSPACE_Token" ]; then
_info "Getting authorization token."
if ! _rackspace_authorization; then
_err "Can not get token."
fi
fi
}
_rackspace_check_rootzone() {
_debug "First detect the root zone"
if ! _get_root_zone "$fulldomain"; then
_err "invalid domain"
return 1
fi
_debug _domain_id "$_domain_id"
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
}

164
dnsapi/dns_ultra.sh Normal file
View File

@@ -0,0 +1,164 @@
#!/usr/bin/env sh
#
# ULTRA_USR="your_user_goes_here"
#
# ULTRA_PWD="some_password_goes_here"
ULTRA_API="https://restapi.ultradns.com/v2/"
#Usage: add _acme-challenge.www.domain.com "some_long_string_of_characters_go_here_from_lets_encrypt"
dns_ultra_add() {
fulldomain=$1
txtvalue=$2
export txtvalue
ULTRA_USR="${ULTRA_USR:-$(_readaccountconf_mutable ULTRA_USR)}"
ULTRA_PWD="${ULTRA_PWD:-$(_readaccountconf_mutable ULTRA_PWD)}"
if [ -z "$ULTRA_USR" ] || [ -z "$ULTRA_PWD" ]; then
ULTRA_USR=""
ULTRA_PWD=""
_err "You didn't specify an UltraDNS username and password yet"
return 1
fi
# save the username and password to the account conf file.
_saveaccountconf_mutable ULTRA_USR "$ULTRA_USR"
_saveaccountconf_mutable ULTRA_PWD "$ULTRA_PWD"
_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"
_ultra_rest GET "zones/${_domain_id}/rrsets/TXT?q=value:${fulldomain}"
if printf "%s" "$response" | grep \"totalCount\" >/dev/null; then
_err "Error, it would appear that this record already exists. Please review existing TXT records for this domain."
return 1
fi
_info "Adding record"
if _ultra_rest POST "zones/$_domain_id/rrsets/TXT/${_sub_domain}" '{"ttl":300,"rdata":["'"${txtvalue}"'"]}'; then
if _contains "$response" "Successful"; then
_info "Added, OK"
return 0
elif _contains "$response" "Resource Record of type 16 with these attributes already exists"; then
_info "Already exists, OK"
return 0
else
_err "Add txt record error."
return 1
fi
fi
_err "Add txt record error."
}
dns_ultra_rm() {
fulldomain=$1
txtvalue=$2
export txtvalue
ULTRA_USR="${ULTRA_USR:-$(_readaccountconf_mutable ULTRA_USR)}"
ULTRA_PWD="${ULTRA_PWD:-$(_readaccountconf_mutable ULTRA_PWD)}"
if [ -z "$ULTRA_USR" ] || [ -z "$ULTRA_PWD" ]; then
ULTRA_USR=""
ULTRA_PWD=""
_err "You didn't specify an UltraDNS username and password yet"
return 1
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}"
_debug "Getting TXT records"
_ultra_rest GET "zones/${_domain_id}/rrsets?q=kind:RECORDS+owner:${_sub_domain}"
if ! printf "%s" "$response" | grep \"resultInfo\" >/dev/null; then
_err "There was an error in obtaining the resource records for ${_domain_id}"
return 1
fi
count=$(echo "$response" | _egrep_o "\"returnedCount\":[^,]*" | cut -d: -f2 | cut -d'}' -f1)
_debug count "${count}"
if [ "${count}" = "" ]; then
_info "Text record is not present, will not delete anything."
else
if ! _ultra_rest DELETE "zones/$_domain_id/rrsets/TXT/${_sub_domain}" '{"ttl":300,"rdata":["'"${txtvalue}"'"]}'; then
_err "Deleting the record did not succeed, please verify/check."
return 1
fi
_contains "$response" ""
fi
}
#################### Private functions below ##################################
#_acme-challenge.www.domain.com
#returns
# _sub_domain=_acme-challenge.www
# _domain=domain.com
# _domain_id=sdjkglgdfewsdfg
_get_root() {
domain=$1
i=2
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
_debug h "$h"
_debug response "$response"
if [ -z "$h" ]; then
#not valid
return 1
fi
if ! _ultra_rest GET "zones"; then
return 1
fi
if _contains "${response}" "${h}." >/dev/null; then
_domain_id=$(echo "$response" | _egrep_o "${h}")
if [ "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_domain="${h}"
_debug sub_domain "${_sub_domain}"
_debug domain "${_domain}"
return 0
fi
return 1
fi
p=$i
i=$(_math "$i" + 1)
done
return 1
}
_ultra_rest() {
m=$1
ep="$2"
data="$3"
_debug "$ep"
_debug TOKEN "${AUTH_TOKEN}"
_ultra_login
export _H1="Content-Type: application/json"
export _H2="Authorization: Bearer ${AUTH_TOKEN}"
if [ "$m" != "GET" ]; then
_debug data "${data}"
response="$(_post "${data}" "${ULTRA_API}"/"${ep}" "" "${m}")"
else
response="$(_get "$ULTRA_API/$ep")"
fi
}
_ultra_login() {
export _H1=""
export _H2=""
AUTH_TOKEN=$(_post "grant_type=password&username=${ULTRA_USR}&password=${ULTRA_PWD}" "${ULTRA_API}authorization/token" | cut -d, -f3 | cut -d\" -f4)
export AUTH_TOKEN
}

149
dnsapi/dns_zone.sh Executable file
View File

@@ -0,0 +1,149 @@
#!/usr/bin/env sh
# Zone.ee dns API
# https://help.zone.eu/kb/zoneid-api-v2/
# required ZONE_Username and ZONE_Key
ZONE_Api="https://api.zone.eu/v2"
######## Public functions #####################
#Usage: dns_zone_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_zone_add() {
fulldomain=$1
txtvalue=$2
_info "Using zone.ee dns api"
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
ZONE_Username="${ZONE_Username:-$(_readaccountconf_mutable ZONE_Username)}"
ZONE_Key="${ZONE_Key:-$(_readaccountconf_mutable ZONE_Key)}"
if [ -z "$ZONE_Username" ] || [ -z "$ZONE_Key" ]; then
ZONE_Username=""
ZONE_Key=""
_err "Zone api key and username must be present."
return 1
fi
_saveaccountconf_mutable ZONE_Username "$ZONE_Username"
_saveaccountconf_mutable ZONE_Key "$ZONE_Key"
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"
return 1
fi
_debug "Adding txt record"
if _zone_rest POST "dns/${_domain}/txt" "{\"name\": \"$fulldomain\", \"destination\": \"$txtvalue\"}"; then
if printf -- "%s" "$response" | grep "$fulldomain" >/dev/null; then
_info "Added, OK"
return 0
else
_err "Adding txt record error."
return 1
fi
else
_err "Adding txt record error."
fi
}
#Usage: fulldomain txtvalue
#Remove the txt record after validation.
dns_zone_rm() {
fulldomain=$1
txtvalue=$2
_info "Using zone.ee dns api"
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
ZONE_Username="${ZONE_Username:-$(_readaccountconf_mutable ZONE_Username)}"
ZONE_Key="${ZONE_Key:-$(_readaccountconf_mutable ZONE_Key)}"
if [ -z "$ZONE_Username" ] || [ -z "$ZONE_Key" ]; then
ZONE_Username=""
ZONE_Key=""
_err "Zone api key and username must be present."
return 1
fi
_saveaccountconf_mutable ZONE_Username "$ZONE_Username"
_saveaccountconf_mutable ZONE_Key "$ZONE_Key"
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"
return 1
fi
_debug "Getting txt records"
_debug _domain "$_domain"
_zone_rest GET "dns/${_domain}/txt"
if printf "%s" "$response" | grep \"error\" >/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 "Nothing to remove."
else
record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":\"[^\"]*\",\"resource_url\":\"[^\"]*\",\"name\":\"$fulldomain\"," | cut -d : -f2 | cut -d , -f1 | tr -d \" | _head_n 1)
if [ -z "$record_id" ]; then
_err "No id found to remove."
return 1
fi
if ! _zone_rest DELETE "dns/${_domain}/txt/$record_id"; then
_err "Record deleting error."
return 1
fi
_info "Record deleted"
return 0
fi
}
#################### Private functions below ##################################
_zone_rest() {
m=$1
ep="$2"
data="$3"
_debug "$ep"
realm="$(printf "%s" "$ZONE_Username:$ZONE_Key" | _base64)"
export _H1="Authorization: Basic $realm"
export _H2="Content-Type: application/json"
if [ "$m" != "GET" ]; then
_debug data "$data"
response="$(_post "$data" "$ZONE_Api/$ep" "" "$m")"
else
response="$(_get "$ZONE_Api/$ep")"
fi
if [ "$?" != "0" ]; then
_err "error $ep"
return 1
fi
_debug2 response "$response"
return 0
}
_get_root() {
domain=$1
i=2
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
_debug h "$h"
if [ -z "$h" ]; then
return 1
fi
if ! _zone_rest GET "dns/$h/a"; then
return 1
fi
if _contains "$response" "\"name\":\"$h\"" >/dev/null; then
_domain=$h
return 0
fi
i=$(_math "$i" + 1)
done
return 0
}