Compare commits

..

566 Commits
2.7.2 ... 2.7.7

Author SHA1 Message Date
neil
8ab8a6eefb Merge pull request #1362 from Neilpang/dev
sync
2018-03-14 09:41:03 +08:00
neilpang
a5a0e564dd fix https://github.com/Neilpang/acme.sh/issues/1322 2018-03-10 10:33:33 +08:00
neil
b8c94fc7cf Merge pull request #1343 from dkerr64/Support-acme-v2-in-freedns
Adding support for API v2 (multiple TXT records)
2018-03-10 08:59:20 +08:00
David Kerr
62dd3a5380 Fix Travis CI errors. 2018-03-09 16:54:42 -05:00
David Kerr
e3ddb677e1 Adding support for API v2 (multiple TXT records) 2018-03-09 16:39:08 -05:00
neilpang
716f727753 fix https://github.com/Neilpang/acme.sh/issues/1105 2018-03-09 20:14:41 +08:00
neilpang
7e381f8e5d fix format 2018-03-09 08:09:32 +08:00
neilpang
183063a244 add more safe check 2018-03-09 08:06:42 +08:00
neilpang
ef871775b7 fix https://github.com/Neilpang/acme.sh/issues/1336 for wget 2018-03-08 21:27:52 +08:00
neilpang
45e386b26d fix https://github.com/Neilpang/acme.sh/issues/1336 2018-03-08 19:49:53 +08:00
neilpang
e1db5db8ac fix https://github.com/Neilpang/acme.sh/issues/1105 2018-03-07 21:25:07 +08:00
neil
c3a289cebc Merge pull request #1332 from Neilpang/dev
sync
2018-03-07 09:38:54 +08:00
neil
20e51f0b4d Merge pull request #1319 from TigerP/master
Add support for DirectAdmin
2018-03-07 09:34:36 +08:00
neil
464dc93751 Merge pull request #1331 from jim-p/acme-fix-1330
Test ACME v2 before copying certificate to fullchain (again)
2018-03-07 09:33:39 +08:00
jim-p
7445a3be59 Add ACME v2 test around cert copy. Fixes #1330
Without this, the work done a few lines above is clobbered, leaving
the fullchain.cer containing only the certificate, not the CA and
certificate chain.
2018-03-06 17:00:57 -05:00
TigerP
2bbc25c1eb Add DirectAdmin to the main README 2018-03-06 17:00:19 +01:00
neil
fd56fe6eb2 Merge pull request #1318 from raidenii/master
New DNS plugin for name.com for new API.
2018-03-06 20:25:29 +08:00
neil
92dfa8becc Merge pull request #1324 from jwilk-forks/spelling
Fix typos
2018-03-05 09:44:57 +08:00
neil
ae8f9561ad Merge pull request #1248 from skid9000/patch-1
Fix the command to generate tsig key for knot api
2018-03-05 09:36:42 +08:00
raidenii
3052ba433a Fix an obvious stupidity. 2018-03-04 17:27:34 -05:00
raidenii
508012342d Make sure the removal of DNS record is the desired one (i.e., by txtvalue) 2018-03-04 17:22:13 -05:00
raidenii
9fa207e613 Move code to fit DNS API dev guide. 2018-03-04 14:13:14 -05:00
Jakub Wilk
2d7b9817cb Fix typos 2018-03-03 16:27:17 +01:00
TigerP
e8d808d708 Remove empty line at the end 2018-03-03 14:40:23 +01:00
neil
d71595fc75 Merge pull request #1320 from Neilpang/dev
sync
2018-03-02 09:02:36 +08:00
TigerP
399d6592b8 Fix some quotes and a check 2018-03-01 21:25:24 +01:00
raidenii
628a6ffa07 Tried to fix some weird problems 2018-03-01 15:03:28 -05:00
raidenii
3e1a94cbcd Yet another fix. 2018-03-01 14:43:08 -05:00
raidenii
a6c2d4b0e2 Another fix. 2018-03-01 14:38:49 -05:00
raidenii
19277aec87 Use printf instead of echo, hopefully fix SC2039. 2018-03-01 14:29:14 -05:00
TigerP
14c2755436 Add support for DirectAdmin 2018-03-01 20:19:55 +01:00
raidenii
50a9145386 Rewrote to adapt the new name.com v4 API. 2018-03-01 14:19:43 -05:00
raidenii
9046509b95 Merge remote-tracking branch 'upstream/master' 2018-03-01 14:09:36 -05:00
neil
61eaa44cf8 Merge pull request #1316 from Neilpang/alias
Alias
2018-03-01 22:38:05 +08:00
neilpang
2d1e9abb60 Merge branch 'dev' of https://github.com/Neilpang/acme.sh into dev 2018-03-01 22:01:11 +08:00
neilpang
d064260bf1 fix https://github.com/Neilpang/acme.sh/issues/1315 2018-03-01 21:59:46 +08:00
neil
a19ad3fd1d Merge pull request #1305 from justmwa/master
DNSMadeEasy ACMEv2 support
2018-02-27 13:43:05 +08:00
nytral
3bc59a0327 first attempt to fix CI errors 2018-02-26 21:47:51 +01:00
nytral
5a883889a2 fixes 2018-02-26 14:53:31 +01:00
neil
fbaa7a4d67 Merge pull request #586 from dkerr64/ssh-deploy
Ssh deploy
2018-02-25 22:56:09 +08:00
nytral
6baa6d488b Merge remote-tracking branch 'upstream/master' 2018-02-24 09:09:00 +01:00
nytral
e26f9b8095 DNSMadeEasy ACMEv2 support 2018-02-24 09:08:44 +01:00
neil
f92fae7625 Merge pull request #1291 from ClouDNS/master
Update dns api to support v2 wildcard cert #1261
2018-02-23 20:05:00 +08:00
neil
3d0e269241 Merge pull request #1287 from martgras/dev
Azure DNS API- support for ACME v2
2018-02-23 20:02:57 +08:00
neil
c17c47f18a Merge pull request #1300 from mal/aws-use-container-role
Pull AWS creds from container role
2018-02-23 19:56:01 +08:00
David Kerr
98b8bfb3fa Merge branch 'dev' of https://github.com/Neilpang/acme.sh into ssh-deploy 2018-02-22 11:46:34 -05:00
martgras
83b1a98db1 Azure DNS API - support for ACME v2 and reliability improvments
support adding 2 txt records
Adding retry logic for REST API calls
Reusing bearer token removes 50% of required REST calls
2018-02-22 12:32:42 +01:00
Mal Graty
f49f55f4a5 Pull AWS creds from container role
Extend the AWS DNS API driver to support ECS container metadata by using
the special environment variable ECS sets in containers.
2018-02-21 11:49:03 +00:00
neil
e58d19b420 Merge pull request #1299 from hebbet/patch-2
small typo
2018-02-21 16:13:15 +08:00
hebbet
58f753136a small typo 2018-02-21 09:01:56 +01:00
neil
22d827adf1 Merge pull request #1292 from mal/aws-use-instance-role
Let AWS DNS API driver pull creds from instance metadata
2018-02-21 10:20:35 +08:00
neil
d3de50e0f9 Merge pull request #1270 from rbelnap/vault-deploy
Vault deploy
2018-02-21 10:17:27 +08:00
neil
432037d20d Merge pull request #1298 from Neilpang/dev
sync
2018-02-21 10:08:17 +08:00
neilpang
86ef0a2609 fix https://github.com/Neilpang/acme.sh/issues/1295 2018-02-21 10:05:27 +08:00
neilpang
bae50da799 fix https://github.com/Neilpang/acme.sh/issues/1266 2018-02-21 09:45:36 +08:00
Bob Belnap
2c45f27356 rename deploy hook vault to vault_cli 2018-02-20 09:11:45 -05:00
Mal Graty
759f4f2c62 Make the instance metadata fetcher self-contained
This is to provide a clean path to future extension work such as adding
a _use_container_role function to offer similar support for ECS
containers.

The $_using_role flag has also been made generic so that future role
providers can also make use of it.
2018-02-20 12:40:24 +00:00
Boyan Peychev
28355335f8 Update dns api to support v2 wildcard cert #1261 2018-02-20 11:22:06 +02:00
Boyan Peychev
9f6832d636 Update dns api to support v2 wildcard cert #1261 2018-02-20 11:16:42 +02:00
Boyan Peychev
5309afc347 Update dns api to support v2 wildcard cert #1261 2018-02-20 11:09:37 +02:00
Mal Graty
693627a858 Emulate Boto when using role metadata
Use the behavior established in the botocore python library to inform
how and when instance metadata is fetched in an attempt to acquire valid
AWS credentials.

- Use it as a fallback when no other credentials are provided
- Set the timeout of metadata requests to 1 second
2018-02-20 00:34:55 +00:00
Mal Graty
48eaa0e5bf Let AWS DNS API code pull creds from instance role
Add option (AWS_USE_INSTANCE_ROLE) to have the AWS DNS API driver pull
the necessary credentials from the AWS EC2 instance metadata endpoint
when required.

This is a non-breaking change as it only takes effect when explicitly
turned on via the environment variable, and fails safe back to the
normal code path.
2018-02-19 19:03:29 +00:00
neilpang
9ad7ac632a fix https://github.com/Neilpang/acme.sh/issues/1284#issuecomment-366616855 2018-02-19 21:07:01 +08:00
Boyan Peychev
41e3ecad46 Update dns api to support v2 wildcard cert #1261 2018-02-19 14:14:08 +02:00
neilpang
d6f8d63742 fix https://github.com/Neilpang/acme.sh/issues/1286 2018-02-19 12:43:56 +08:00
neil
28b0929554 Merge pull request #1283 from justmwa/master
Fixes
2018-02-19 12:34:18 +08:00
nytral
55787ff7b9 other fixes 2018-02-17 15:12:19 +01:00
nytral
b00919c692 various fixes 2018-02-17 15:08:13 +01:00
neil
d43392628b Merge pull request #1273 from jlduran/add-strongswan-freebsd
Add support for strongSwan deploys in FreeBSD
2018-02-17 11:43:42 +08:00
neil
aa831fee5b Merge pull request #1279 from Neilpang/1277
https://github.com/Neilpang/acme.sh/issues/1277
2018-02-17 10:45:44 +08:00
neilpang
5c568d6999 https://github.com/Neilpang/acme.sh/issues/1277 2018-02-17 10:31:34 +08:00
neilpang
d84665cb64 fix https://github.com/Neilpang/acme.sh/issues/1271 2018-02-17 10:16:04 +08:00
neil
4bb5d27c59 Merge pull request #1218 from hcouplet/standalone-listen-address-fix
Standalone listen address fix. #1217
2018-02-17 10:14:12 +08:00
neil
11a9f1d1f0 Merge pull request #1274 from jlduran/add-account-key-permissions
Set the account key file permissions
2018-02-17 10:04:06 +08:00
Jose Luis Duran
123e8f21b5 Set the account key file permissions 2018-02-16 15:42:32 -02:00
neilpang
6d6b2efdb5 fix he for solaris 2018-02-16 23:16:25 +08:00
Boyan Peychev
94b925f5ef Merge branch 'dev' of https://github.com/Neilpang/acme.sh 2018-02-16 16:36:32 +02:00
Bob Belnap
c86755f1ab format fix 2018-02-16 09:19:47 -05:00
Bob Belnap
b8418ced44 syntax fixes 2018-02-16 09:01:26 -05:00
Jose Luis Duran
fac0beaa0a Add support for strongSwan deploys in FreeBSD
Related to 8ea800205c
2018-02-16 11:29:10 -02:00
neilpang
c1f5229906 update doc 2018-02-16 11:21:14 +08:00
neilpang
d5865989cf update doc 2018-02-16 10:48:25 +08:00
Bob Belnap
90e587a974 add vault deploy hook script 2018-02-15 15:34:47 -05:00
neil
4a6b31fbe2 Merge pull request #1268 from Neilpang/dev
fix format
2018-02-15 21:16:41 +08:00
neilpang
a63766a005 fix format 2018-02-15 21:04:53 +08:00
neil
47359c1a3b Merge pull request #1267 from Neilpang/dev
sync
2018-02-15 20:37:15 +08:00
neilpang
abd0dad2bf fix https://github.com/Neilpang/acme.sh/issues/1145#issuecomment-365863118 2018-02-15 20:35:31 +08:00
neilpang
54a52f7048 Merge branch 'dev' of https://github.com/Neilpang/acme.sh into dev 2018-02-15 12:39:06 +08:00
neilpang
f213215c81 fix lua 2018-02-15 12:38:45 +08:00
neil
96cde120b4 Merge pull request #1258 from wickerwaka/dreamhost_dns
Added DreamHost DNS API
2018-02-15 12:35:37 +08:00
neilpang
0096ef4ddb fix ali 2018-02-15 12:26:35 +08:00
neilpang
ce6c7d4b59 fix dp 2018-02-15 10:51:13 +08:00
neilpang
b51ed9bbb7 https://github.com/Neilpang/acme.sh/issues/1251 2018-02-15 10:29:03 +08:00
neil
5c6af92a0d Merge pull request #1264 from Neilpang/dev
sync
2018-02-14 22:56:13 +08:00
neilpang
d8eb08e214 fix format 2018-02-14 22:36:17 +08:00
neilpang
c6f5c7f1a3 fix gd 2018-02-14 22:31:02 +08:00
neilpang
a6b6e31cda fix dp 2018-02-14 20:52:06 +08:00
neilpang
28145a9deb fix ovh 2018-02-14 20:40:49 +08:00
neilpang
fa991c8501 Merge branch 'dev' of https://github.com/Neilpang/acme.sh into dev 2018-02-14 19:40:16 +08:00
neilpang
5f345d2089 fix https://github.com/Neilpang/acme.sh/issues/1262 2018-02-14 19:39:47 +08:00
Boyan Peychev
520c454f22 Merge branch 'dev' of https://github.com/Neilpang/acme.sh 2018-02-14 13:29:36 +02:00
neil
cc81668c8f Merge pull request #1094 from Daniel15/cloudns-sub
[cloudns] Add support for sub user IDs
2018-02-14 19:23:07 +08:00
neil
6426e044d6 Merge pull request #1263 from jlduran/fix-key-file-permissions
Fix key file permissions
2018-02-14 17:31:40 +08:00
Jose Luis Duran
7b92371a03 Fix key file permissions
Introduced in 8201458332.

Related to #1256.
2018-02-14 06:46:48 -02:00
Martin Donlon
6105d4a4e6 Merge branch 'dev' into dreamhost_dns 2018-02-13 21:04:09 -08:00
Martin Donlon
84649e9d20 Addressing PR feedback
Replace printf with echo
Move dreamhost to bottom of DNS API list
2018-02-13 21:02:38 -08:00
neilpang
1f7df33e28 fix format 2018-02-13 22:26:36 +08:00
neilpang
3c394f08b0 fix format 2018-02-13 22:23:36 +08:00
neilpang
64f07d9bf3 fix aws for acme v2 2018-02-13 22:17:20 +08:00
neilpang
849a6c12be fix for acme v2 2018-02-13 20:08:05 +08:00
neilpang
9144ce746e fix for v2 wildcard 2018-02-13 19:30:54 +08:00
neilpang
64821ad4f5 support "--domain-alias" 2018-02-12 21:49:22 +08:00
neilpang
2655e726c9 update dns he 2018-02-12 20:40:24 +08:00
neil
de2970d7ef Merge pull request #1259 from Neilpang/dev
sync
2018-02-12 20:07:57 +08:00
neilpang
012dd6986b nginx 2018-02-12 20:01:40 +08:00
Martin Donlon
2ef9904d00 Merge branch 'dev' into dreamhost_dns 2018-02-11 07:54:10 -08:00
Martin Donlon
2c83224f07 Fixup dns_dreamhost travis failures 2018-02-11 07:37:15 -08:00
neilpang
0c63090a23 fix format 2018-02-10 23:34:34 +08:00
neilpang
0159277dbf fix format 2018-02-10 23:24:43 +08:00
neilpang
6ca5f3d8f6 support Zonomi.com dns api: https://github.com/Neilpang/acme.sh/issues/1255 2018-02-10 23:23:31 +08:00
neilpang
875625b147 Support domain alias mode 2018-02-10 10:45:29 +08:00
neilpang
da0bd5a9dc begin 2.7.7 2018-02-10 09:03:55 +08:00
neil
ce02ad641b Merge pull request #1257 from Neilpang/dev
minor, fix error message
2018-02-10 08:54:37 +08:00
neilpang
78915896d5 minor, fix error message 2018-02-07 23:49:08 +08:00
neil
4a5d2e16d0 Merge pull request #1249 from Neilpang/dev
sync
2018-02-07 22:31:03 +08:00
neilpang
3e3161c747 fix format 2018-02-07 22:18:04 +08:00
neilpang
694af4aeb1 fix https://github.com/Neilpang/acme.sh/issues/1234 2018-02-07 21:12:49 +08:00
Skid
7f59d7ea48 Fix the command to generate tsig key for knot api 2018-02-07 14:07:14 +01:00
neilpang
52b945164c fix https://github.com/Neilpang/acme.sh/issues/1247 2018-02-07 20:54:05 +08:00
neilpang
584fb2904b fix https://github.com/Neilpang/acme.sh/issues/1191
https://github.com/Neilpang/acme.sh/issues/1246
2018-02-06 21:23:08 +08:00
neil
71013b372d Merge pull request #1245 from jim-p/acme-fix-1243
Add braces around ACCOUNT_URL when forming the protected parameters. Fixes #1243
2018-02-06 09:29:56 +08:00
neil
338b3ba590 Merge pull request #1244 from jim-p/acme-fix-1242
Consider a 200 final response code as an account that already exists. Fixes #1242
2018-02-06 09:28:22 +08:00
jim-p
6b798b01a8 Add braces around ACCOUNT_URL when forming the protected= line. Fixes #1243 2018-02-05 16:38:42 -05:00
jim-p
7df20e5049 When registering, consider a 200 final response code as an account that already exists. Fixes #1242 2018-02-05 16:37:57 -05:00
neil
7128d79935 Merge pull request #1239 from Neilpang/dev
sync
2018-02-05 22:10:37 +08:00
neilpang
e27dfbb0bb update doc 2018-02-05 21:19:48 +08:00
neilpang
a51f109930 fix https://github.com/Neilpang/acme.sh/issues/1234 2018-02-05 20:28:50 +08:00
neil
3e101521dd Merge pull request #1232 from Neilpang/dev
sync
2018-02-02 22:29:56 +08:00
neil
726c7a4d32 Merge pull request #1225 from Neilpang/2
merge v2
2018-02-02 22:20:50 +08:00
neil
767f05cfa7 Merge pull request #1231 from fwolfst/1137-doc_cert_removal
1137 doc cert removal
2018-02-02 09:16:51 +08:00
Felix Wolfsteller
47b49f1be9 Slightly improved --help output, fixes #1137 . 2018-02-01 18:07:29 +01:00
Felix Wolfsteller
a4964b9073 Add Readme-section about cert removal (#1137) 2018-02-01 18:06:26 +01:00
neil
40e2ec3ae9 Merge pull request #1229 from Neilpang/dev
sync
2018-02-01 09:16:08 +08:00
neilpang
120cde169b fix format 2018-01-27 17:20:38 +08:00
neilpang
1c35f46b45 fix https://github.com/Neilpang/acme.sh/issues/1212 2018-01-26 21:37:30 +08:00
neilpang
eea713eed2 Merge branch 'dev' into 2 2018-01-26 21:05:36 +08:00
neilpang
8c88757451 fix format 2018-01-26 20:39:41 +08:00
neilpang
dd171ca44a fix format 2018-01-26 20:14:51 +08:00
neil
cfd086a140 Merge pull request #1224 from martgras/patch-1
dns_azure - spelling  mistake in error message
2018-01-26 14:58:05 +08:00
martgras
72fe7396d6 spelling mistake in error message 2018-01-26 07:53:47 +01:00
neilpang
03140865f0 fix for existing record 2018-01-25 23:25:50 +08:00
neilpang
a4fc802d1b Add selectel.com(selectel.ru) DNS API. fix https://github.com/Neilpang/acme.sh/issues/1220 2018-01-25 23:18:37 +08:00
neil
b6d760b903 Merge pull request #1219 from martgras/master
Add Azure DNS API
2018-01-25 23:11:00 +08:00
neil
e4b24d20ac Update dns_azure.sh 2018-01-25 23:08:56 +08:00
neil
91607bb2a1 Update dns_azure.sh 2018-01-25 22:58:11 +08:00
neil
fce8223663 Merge pull request #1222 from Neilpang/dev
fix https://github.com/Neilpang/acme.sh/issues/1193#issuecomment-3600…
2018-01-25 21:17:43 +08:00
neilpang
d1067c60bf fix https://github.com/Neilpang/acme.sh/issues/1193#issuecomment-360025170 2018-01-25 21:08:20 +08:00
martgras
441c26dd32 Update dns_azure.sh 2018-01-25 07:40:35 +01:00
martgras
00781dd4e1 Update README.md 2018-01-25 07:06:42 +01:00
martgras
c7b8debb6e fix travis issues 2018-01-25 07:01:39 +01:00
martgras
d51c383866 remove unused code and fix error handling 2018-01-24 15:08:06 +01:00
martgras
f7d4698ef0 improve error checking 2018-01-24 13:39:38 +01:00
martgras
3fdbbafcb5 fix getroot with multiple dns zones 2018-01-24 09:59:05 +01:00
martgras
c82cd90ed6 Relative link to Azure DNS wiki page 2018-01-23 18:46:59 +01:00
martgras
b6fc8398cf Usage instructions for Azure DNS 2018-01-23 18:25:52 +01:00
martgras
e90f3b84c1 Add support for Azure DNS
Adding support for Azure DNS 
See https://docs.microsoft.com/en-us/azure/dns/
2018-01-23 18:24:08 +01:00
Herve Couplet
9134b6ea98 if local-address is present, bind to that ip instead of 0.0.0.0 2018-01-23 17:53:40 +01:00
neil
4a380ad7fc Merge pull request #1216 from Neilpang/dev
fx format
2018-01-23 19:50:20 +08:00
neilpang
c05eb0b1b2 fx format 2018-01-23 19:42:57 +08:00
neil
66feebfc0e Merge pull request #1211 from Neilpang/dev
Dev
2018-01-21 20:22:36 +08:00
neilpang
04a609b51f fix https://github.com/Neilpang/acme.sh/issues/1209 2018-01-21 20:20:54 +08:00
neilpang
258cf20c92 minor 2018-01-19 22:48:06 +08:00
neil
41c8d88217 Merge pull request #1206 from Neilpang/dev
Dev
2018-01-19 22:42:48 +08:00
neilpang
37f39c0870 minor 2018-01-19 22:41:42 +08:00
neilpang
6ba4f8b54c fix https://github.com/Neilpang/acme.sh/issues/1204 2018-01-18 21:04:06 +08:00
neil
97893d293b Merge pull request #1201 from hmb/dev
fix bug in the --ca-bundle param of passing -f to _readlink
2018-01-18 09:28:51 +08:00
Holger Böhnke
78d1cfb464 fix bug in the --ca-bundle param of passing -f to _readlink
When _readlink is called the -f param must not be passed. _readlink (with
leading underscore) is a wrapper around readlink (without leading
underscore). _readlink already passes -f to readlink, that's why it must
not be passed to _readlink.
2018-01-17 19:21:14 +01:00
neilpang
b5fdfe27d5 Merge branch '2' of https://github.com/Neilpang/acme.sh into 2 2018-01-16 21:31:28 +08:00
neilpang
cd9fb3b635 fix https://github.com/Neilpang/acme.sh/issues/1189 2018-01-16 21:29:53 +08:00
neilpang
9e9f839d96 support only one wildcard domain.
fix https://github.com/Neilpang/acme.sh/issues/1188#issuecomment-357684744
2018-01-16 21:29:52 +08:00
neilpang
60814ecfe1 typo 2018-01-16 21:29:52 +08:00
neilpang
0170c20e9a fix format 2018-01-16 21:29:51 +08:00
neilpang
01cc2e13d8 add more sleep for ovh 2018-01-16 21:29:51 +08:00
neilpang
f823f170e6 fix ovh 2018-01-16 21:29:50 +08:00
neilpang
be186bd39b support dns_ovh_rm() 2018-01-16 21:29:50 +08:00
neilpang
ea25492c28 we should not use "updating" to support wildcard 2018-01-16 21:29:49 +08:00
neilpang
79a2bed640 update doc for v2 2018-01-16 21:29:49 +08:00
neilpang
cd8fc35968 fix dns manual mode. 2018-01-16 21:29:48 +08:00
neilpang
d2cde379ad fix ACME v2: deactivate/deactivate-account/revoke 2018-01-16 21:29:48 +08:00
neilpang
506c41cb15 fix format 2018-01-16 21:29:47 +08:00
neilpang
72f54ca6c1 support ACME v2 wildcard cert 2018-01-16 21:29:47 +08:00
neilpang
f8d22c486e fix format 2018-01-16 21:29:46 +08:00
neilpang
c1151b0d45 first version to support ACME v2 2018-01-16 21:29:45 +08:00
neil
0e65fdd6f7 Merge pull request #1196 from Neilpang/dev
sync
2018-01-16 21:28:43 +08:00
neilpang
3164b5ab13 fix https://github.com/Neilpang/acme.sh/issues/1189 2018-01-16 20:55:07 +08:00
neilpang
e6cda79ee8 support only one wildcard domain.
fix https://github.com/Neilpang/acme.sh/issues/1188#issuecomment-357684744
2018-01-15 21:55:40 +08:00
neil
45e21d5000 Merge pull request #1187 from auerswald/dev
Add InternetX autoDNS dns api support
2018-01-15 20:17:19 +08:00
neilpang
7e212c4d40 typo 2018-01-15 19:48:57 +08:00
AA
775aae7082 Update README.md 2018-01-15 11:15:26 +01:00
AA
a01da2fd92 Update README.md 2018-01-15 11:00:44 +01:00
AA
cd2fe698bb Create dns_autodns.sh 2018-01-15 10:59:50 +01:00
neil
4f209e8992 Merge pull request #1182 from meowthink/dev
Add namesilo.com dns api support
2018-01-15 11:16:33 +08:00
Meowthink
eb207322d3 Add namesilo.com dns api support 2018-01-14 18:52:44 +08:00
neilpang
06a2e5fc82 fix format 2018-01-09 23:05:55 +08:00
neilpang
a8ae23d0a2 add more sleep for ovh 2018-01-09 22:47:01 +08:00
neilpang
2befb5e784 fix ovh 2018-01-09 22:04:03 +08:00
neilpang
6d5e7826ae support dns_ovh_rm() 2018-01-09 21:36:48 +08:00
neilpang
c99d4948b7 we should not use "updating" to support wildcard 2018-01-09 20:43:23 +08:00
neilpang
ee6f78805f update doc for v2 2018-01-07 12:12:40 +08:00
neil
9a419bd63f Merge pull request #1167 from Neilpang/dev
sync
2018-01-07 12:07:44 +08:00
neilpang
4a139934f6 fix dns manual mode. 2018-01-06 21:50:57 +08:00
neilpang
2823306810 fix ACME v2: deactivate/deactivate-account/revoke 2018-01-06 21:33:27 +08:00
neilpang
4f3b3a273f fix format 2018-01-06 19:42:29 +08:00
neilpang
6ae3911972 support ACME v2 wildcard cert 2018-01-06 17:39:15 +08:00
neilpang
136aebc009 fix format 2018-01-06 13:57:35 +08:00
neilpang
6541492a55 first version to support ACME v2 2018-01-06 12:45:24 +08:00
neil
59e9750602 Merge pull request #1161 from hiskang/deploy/strongswan
support both debian and redhat
2018-01-05 14:15:08 +08:00
hiska
8ea800205c support both debian and redhat 2018-01-04 19:01:57 +09:00
neil
59bb9268a1 Merge pull request #1159 from sjau/master
dns_ispconfig.sh: Remove unnecessary permission in api user
2018-01-03 13:26:59 +08:00
sjau
a582e7c2fb dns_ispconfig.sh: remove unnecessary permission in api user 2018-01-02 15:05:26 +01:00
sjau
6e2669ed1d Merge pull request #1 from Neilpang/master
Update from original
2018-01-02 15:03:02 +01:00
neil
7b8a82ce90 Merge pull request #1144 from Neilpang/dev
Dev
2017-12-12 20:18:20 +08:00
neil
a8bad622ff Merge pull request #1140 from jhartlep/dev
added dns api support for servercow
2017-12-12 20:08:42 +08:00
Jens
a95ccc7e4c Update dns_servercow.sh
... didn't see this line in spellcheck ... :S
2017-12-09 20:22:09 +01:00
Jens
8101aceab5 Update dns_servercow.sh
fixed remaining issues from shellcheck
2017-12-09 20:18:05 +01:00
Jens
1c9b19833c Update dns_servercow.sh
replaced tab with space
2017-12-09 20:14:46 +01:00
Jens
488745f378 Update README.md 2017-12-09 20:05:05 +01:00
Jens Hartlep
b140e2553b added Servercow to supported list 2017-12-09 19:33:48 +01:00
Jens Hartlep
ae29929714 added dns api for servercow 2017-12-09 19:32:53 +01:00
neilpang
9f80909f6a Merge branch 'dev' of https://github.com/Neilpang/acme.sh into dev 2017-12-09 21:51:10 +08:00
neilpang
8201458332 fix https://github.com/Neilpang/acme.sh/issues/1123 2017-12-09 21:50:45 +08:00
neil
7a88d80a10 Merge pull request #1138 from Neilpang/dev
Dev
2017-12-09 21:28:12 +08:00
neil
3ced411769 Merge pull request #1134 from speedmann/master
Add support for inwx.de API
2017-12-09 21:23:25 +08:00
speedmann
f7c346de09 Fix order in README and add link to inwx.de and apidocs 2017-12-09 14:20:36 +01:00
speedmann
731ed6952f Fix shebang 2017-12-09 14:13:05 +01:00
speedmann
454ad6f8bd Merge branch 'dev' into master 2017-12-09 14:10:01 +01:00
neil
8a3b6bf0e6 Merge pull request #1132 from Aarup/master
Added support for UnoEuro API
2017-12-08 21:11:25 +08:00
Aarup
fb6e0658cf update README 2017-12-08 14:09:04 +01:00
Aarup
f9b8d7a9d8 renamed uno_user and uno_key 2017-12-08 13:22:17 +01:00
Aarup
f763e1edd7 fix contains usage 2017-12-08 13:20:25 +01:00
Aarup
dbc3ad1304 use _math 2017-12-08 12:59:02 +01:00
neilpang
4249e13eb4 fix format 2017-12-08 19:54:25 +08:00
neilpang
ca7ebd9333 fix typo 2017-12-08 19:49:18 +08:00
Aarup
3f1e6c128f Try again 2017-12-08 08:31:24 +01:00
Aarup
1f635b90e7 Try to fix build 2017-12-08 08:26:52 +01:00
JAA
db3043553c Also don't use sed 2017-12-07 14:52:09 +01:00
neilpang
f87890cb4b v2.7.6 fix ECC 384 signature
https://github.com/Neilpang/acme.sh/issues/1130
https://github.com/Neilpang/acme.sh/issues/990
2017-12-07 21:32:17 +08:00
speedmann
5911594906 Fix egrep invocation 2017-12-07 14:21:37 +01:00
speedmann
9a1f769828 Avoid usage of sed -E grep -q and printf -v 2017-12-07 14:18:54 +01:00
JAA
b91c0a0616 Don't use grep -B 2017-12-07 13:53:40 +01:00
JAA
4a9f607d31 Cleanup 2017-12-07 13:53:27 +01:00
speedmann
a00169451f Change bash to sh to fit project requirements 2017-12-07 13:10:59 +01:00
speedmann
ecba959dd9 Fix missed whitespaces 2017-12-07 13:07:05 +01:00
speedmann
a8202d4b37 Fix CI issues 2017-12-07 12:05:03 +01:00
speedmann
657334fb67 Add support for inwx.de API 2017-12-07 11:47:01 +01:00
Aarup
78712245f7 Add UnoEuro to README 2017-12-06 12:13:40 +01:00
Aarup
70702e41e9 Use _head_n 2017-12-06 11:55:29 +01:00
Aarup
0ca3141088 Added support for UnoEuro api 2017-12-06 11:50:54 +01:00
neil
ac0970abba Merge pull request #1131 from Neilpang/dev
Dev
2017-12-03 21:36:06 +08:00
neilpang
9eeebb147f fix osx build 2017-12-03 20:57:25 +08:00
neilpang
dcf8457f4d fix format 2017-12-03 13:16:37 +08:00
neilpang
534a5ad688 Merge branch 'fixci' into dev 2017-12-03 13:11:53 +08:00
neilpang
529cbc0379 run ci in docker 2017-12-03 12:51:51 +08:00
neil
b6aff65997 Merge pull request #1128 from Neilpang/dev
fix https://github.com/Neilpang/acme.sh/issues/1127
2017-12-02 19:56:39 +08:00
neilpang
b615cce92d fix https://github.com/Neilpang/acme.sh/issues/1127 2017-12-02 19:54:33 +08:00
neil
aea631d9d2 Merge pull request #1126 from Neilpang/dev
Dev
2017-12-02 11:16:18 +08:00
neil
bf942a4cb3 Merge pull request #1125 from Neilpang/freedns
fix https://github.com/Neilpang/acme.sh/issues/1109
2017-12-02 11:15:31 +08:00
neilpang
ceafe389af fix https://github.com/Neilpang/acme.sh/issues/1109 2017-11-26 20:57:02 +08:00
neilpang
f62457a24e fix 2017-11-13 20:54:29 +08:00
Daniel Lo Nigro
bab4f691c5 Fix lint warning 2017-11-12 18:38:30 -08:00
David Kerr
c7becddb78 Merge branch 'master' of https://github.com/Neilpang/acme.sh into ssh-deploy 2017-11-11 12:52:53 -05:00
neil
cc3660e259 Merge pull request #1107 from Neilpang/dev
fix https://github.com/Neilpang/acme.sh/issues/1106
2017-11-10 23:06:05 +08:00
neilpang
6e93ff8bca fix https://github.com/Neilpang/acme.sh/issues/1106 2017-11-10 23:01:29 +08:00
Daniel Lo Nigro
212d0f24d8 [cloudns] Add support for sub user IDs 2017-10-31 22:36:17 -07:00
neil
114003406d Merge pull request #1093 from Neilpang/dev
add dev guide
2017-11-01 10:15:36 +08:00
neilpang
4c99c0127b add dev guide 2017-11-01 10:14:44 +08:00
David Kerr
c809b33161 Merge branch 'master' of https://github.com/Neilpang/acme.sh into ssh-deploy 2017-10-29 21:03:05 -04:00
neil
3f1c7da15e Merge pull request #1079 from Neilpang/dev
Dev
2017-10-20 22:30:26 +08:00
neil
a46695581e Merge pull request #1077 from max2711/master
small Docker output enhancement
2017-10-20 22:13:51 +08:00
max2711
7902d10a3a remove unused crontab jobs 2017-10-20 14:22:20 +02:00
neil
8aff2bd74c Merge pull request #1075 from Neilpang/dev
fix https://github.com/Neilpang/acme.sh/issues/1074
2017-10-18 20:30:40 +08:00
neilpang
352dd907ac fix https://github.com/Neilpang/acme.sh/issues/1074 2017-10-18 20:27:09 +08:00
neil
43f195160e Merge pull request #1072 from Neilpang/dev
Dev
2017-10-12 21:54:13 +08:00
neilpang
872bfe4757 fix for PR https://github.com/Neilpang/acme.sh/pull/1069 2017-10-11 20:34:56 +08:00
neil
70bd493a25 Merge pull request #1061 from sahsanu/patch-1
Update ClouDNS.net API doc
2017-10-10 22:02:36 +08:00
neil
bd065838fa Merge pull request #1063 from Neilpang/dev
fix https://github.com/Neilpang/acme.sh/issues/1062
2017-10-08 19:48:19 +08:00
neilpang
5f6e3da766 fix https://github.com/Neilpang/acme.sh/issues/1062
change back to use openssl for tls mode.
2017-10-08 19:45:50 +08:00
sahsanu
ee56b9cd4e Update ClouDNS.net API doc
Update ClouDNS.net API doc to show that CLOUDNS_AUTH_ID and CLOUDNS_AUTH_PASSWORD will be saved in ~/.acme.sh/account.conf
2017-10-07 21:31:24 +02:00
neil
1a27172f20 Merge pull request #1059 from Neilpang/dev
Dev
2017-10-06 09:56:29 +08:00
neil
4ef1159666 Merge pull request #1055 from hiskang/deploy/strongswan
Deploy/strongswan
2017-10-04 08:59:05 +08:00
hiska
c924e7c537 remove "return 0" 2017-10-04 06:44:02 +09:00
neil
814bd7cb0d Merge pull request #1056 from hebbet/patch-1
unify headlines
2017-10-03 22:11:05 +08:00
neil
5f2d8c0155 Merge pull request #1052 from sahsanu/patch-1
Update dns_cloudns.sh to be able to save ID and PASSWORD
2017-10-03 22:09:48 +08:00
hebbet
372f691fd6 unify headlines
unify headlines in deploy readme
2017-10-02 15:04:02 +02:00
hiska
5f05a452fc Merge branch 'dev' into deploy/strongswan 2017-10-02 08:39:55 +09:00
hiska
afe3283c53 Update README.md 2017-10-02 08:34:32 +09:00
hiska
641a2895a6 Create strongswan.sh 2017-10-02 08:32:36 +09:00
sahsanu
c73c33f94c Update dns_cloudns.sh 2017-10-01 10:31:38 +02:00
sahsanu
6c7da215e7 Update dns_cloudns.sh 2017-10-01 10:06:38 +02:00
sahsanu
754a4a7c8b Update dns_cloudns.sh
Added code to save CLOUDNS_AUTH_ID and CLOUDNS_AUTH_PASSWORD on account.conf file so the id and password for cloudns can be reused.
2017-09-30 20:12:53 +02:00
neil
0427e8bbb4 Merge pull request #993 from fritteli/deploy-fritzbox
Deploy fritzbox
2017-09-29 21:00:07 +08:00
neil
c47f6ed30a Merge pull request #1048 from Neilpang/dev
Dev
2017-09-27 09:07:26 +08:00
neil
3bdc317fc8 Merge pull request #1046 from techdad/patch-1
Remove stray single-quote
2017-09-27 09:04:40 +08:00
neil
20cce349e4 Merge pull request #1044 from 2globalnomads/patch-5
#1042
2017-09-27 08:56:41 +08:00
Daniel
5261162fdf Remove stray single-quote
Get rid of a single stray erroneous single-quote that is breaking socat when using standalone mode.
2017-09-26 19:43:06 +04:00
Santeri Kannisto
acf117584b #1042
Apparently UAPI does not return any error code, just JSON output that has a string "status: 0" whenever the command fails.
2017-09-26 07:04:30 +04:00
neil
7b4bbed553 Merge pull request #1038 from Neilpang/dev
add debug info
2017-09-23 22:13:14 +08:00
neilpang
270ce87582 add debug info 2017-09-23 22:12:17 +08:00
Manuel Friedli
2fc0225bc9 Make command line example consistent with env variable example. 2017-09-12 11:35:21 +02:00
Manuel Friedli
3536cd336d Merge branch 'dev' into deploy-fritzbox 2017-09-12 11:32:54 +02:00
neil
86dd290c1d Merge pull request #1020 from Neilpang/dev
minor
2017-09-11 21:43:57 +08:00
neilpang
95949b6519 minor 2017-09-11 21:40:56 +08:00
neil
6499a7298d Merge pull request #1019 from Neilpang/dev
Dev
2017-09-11 21:30:02 +08:00
neilpang
042e09d29f Merge branch 'dev' of https://github.com/Neilpang/acme.sh into dev 2017-09-11 21:28:57 +08:00
neilpang
36309e6dbc minor, fix debug info 2017-09-11 21:28:37 +08:00
neil
e1ac201de1 Merge pull request #1014 from 2globalnomads/patch-4
1 cert per 1 domain for cpanel_uapi
2017-09-11 20:44:28 +08:00
neil
f0c4e44d2f Merge pull request #1015 from baloo/patch-1
Use stable gandi API url
2017-09-11 20:43:23 +08:00
neil
1dc3036822 Merge pull request #1017 from Neilpang/dev
Dev
2017-09-10 16:47:42 +08:00
neilpang
a6b399286e add socat 2017-09-09 14:15:11 +08:00
Arthur Gautier
856811bd2e Use stable gandi API url
The gandi api has changed its url for a more stable
one. Although https://dns.beta.gandi.net will continue to 
work for the foreseable future, this commits updates the
url to new official one.
2017-09-06 17:04:40 +00:00
neilpang
53273a15bf use socat for tls mode 2017-09-06 21:18:02 +08:00
neilpang
3eeb090578 fix tls mode back to use openssl 2017-09-06 20:50:31 +08:00
Santeri Kannisto
a9726fde19 1 cert per domain
for cpanel_uapi
2017-09-05 17:42:17 +04:00
Santeri Kannisto
f81d4033fa One cert per domain
Deploy works only for the first domain
2017-09-05 17:37:48 +04:00
neil
5e864ea3b5 Merge pull request #1013 from Neilpang/dev
Dev
2017-09-05 20:49:07 +08:00
neilpang
8148bfeacf fix https://github.com/Neilpang/acme.sh/issues/998 2017-09-05 20:32:14 +08:00
Manuel Friedli
1e30718df6 Try and work around shellcheck error SC2039: In POSIX sh, printf -%s-- is undefined. 2017-09-04 14:48:27 +02:00
Manuel Friedli
72e1eb88d9 Don't use individual redirects, but do it all in one block. 2017-09-04 14:40:28 +02:00
Manuel Friedli
8ee5ede834 Fix more formatting errors 2017-09-04 14:30:40 +02:00
Manuel Friedli
bd8b1a2501 Don't use wget directly, but instead use _get and _post. 2017-09-04 14:27:22 +02:00
Manuel Friedli
a098167bdb Fix more formatting errors 2017-09-04 14:07:10 +02:00
neil
7790208126 Merge pull request #1010 from 2globalnomads/patch-3
cpanel_uapi doc
2017-09-03 17:38:51 +08:00
Santeri
e52304edb4 cpanel_uapi
tried to make it a bit less confusing
2017-09-03 13:35:20 +04:00
neil
afdd02a80d Merge pull request #1006 from Neilpang/dev
Dev
2017-09-03 08:47:27 +08:00
neilpang
c73fdd4022 minor 2017-09-03 08:45:58 +08:00
neilpang
4356eefbb1 fix https://github.com/Neilpang/acme.sh/issues/1005#event-1232471561 2017-09-03 08:42:44 +08:00
neilpang
6104680caa fix https://github.com/Neilpang/acme.sh/issues/999 2017-09-02 20:46:04 +08:00
neil
4373fdf48c Merge pull request #1003 from Neilpang/dev
fix for behind proxy
2017-09-02 19:10:08 +08:00
neilpang
f9cdfd3e5b fix for behind proxy 2017-09-02 18:58:07 +08:00
neil
b6c2fc5a69 Merge pull request #1001 from Neilpang/socat
Socat
2017-09-02 17:56:15 +08:00
neilpang
cc6610edc2 add socat 2017-09-02 17:32:40 +08:00
neilpang
7b8ddfdd96 use socat 2017-09-02 08:59:30 +08:00
neilpang
443a5ca0c2 socat tls mode 2017-09-01 23:44:52 +08:00
neilpang
3794b5cb58 fix changes for :https://community.letsencrypt.org/t/acme-sh-standalone-fails-multiple-validation-requests-staging-multi-va/41249/8
use socat instead of nc.
2017-09-01 23:01:37 +08:00
Manuel Friedli
6cb5377d73 Fix bugs and more/new formatting errors. 2017-08-31 17:25:08 +02:00
Manuel Friedli
a3a92ff1df Fix formatting errors. 2017-08-31 17:12:11 +02:00
neil
2068efdb38 Merge pull request #995 from Neilpang/dev
Dev
2017-08-30 22:22:50 +08:00
neil
258ca1b434 Merge pull request #991 from fritteli/fritteli-typos
Fritteli typos
2017-08-30 21:57:30 +08:00
Manuel Friedli
103fa959cb Typo 2017-08-30 00:47:31 +02:00
Manuel Friedli
b6d48b7a14 Update README.md for the deploy hooks. 2017-08-30 00:45:03 +02:00
Manuel Friedli
412e4e6cf9 Add acknowledgement note 2017-08-30 00:24:31 +02:00
Manuel Friedli
e6f81173a3 Delete auto-backup file 2017-08-29 23:58:20 +02:00
Manuel Friedli
d50281453d Add --no-check-certificate option to wget, or else the initial deployment won't work because there isn't a valid certificate installed on the router yet. 2017-08-29 23:57:24 +02:00
Manuel Friedli
4bb488258d - Bugfixes
- Make sure the login actually worked
- Less output
2017-08-29 23:53:41 +02:00
Manuel Friedli
f6da19ba83 add deploy script for the AVM FRITZ!Box 2017-08-29 23:14:21 +02:00
fritteli
88bb7b780d Typos 2017-08-29 22:35:11 +02:00
neil
3805e5d37e Merge pull request #988 from Neilpang/dev
Dev
2017-08-25 20:56:23 +08:00
neilpang
a2d6daaef4 fix cpanel_uapi.sh 2017-08-25 20:54:10 +08:00
neilpang
48e9006cd1 fix cpanel uapi 2017-08-25 20:51:31 +08:00
neil
a25a4b5d11 Merge pull request #986 from Neilpang/dev
Dev
2017-08-22 20:28:35 +08:00
neilpang
309bec474f add warning for dns manual mode 2017-08-22 20:27:13 +08:00
neil
d36440a06d Merge pull request #940 from 2globalnomads/patch-1
cpanel_uapi.sh
2017-08-22 09:17:07 +08:00
neil
2a2f772412 Merge pull request #975 from Neilpang/dev
Dev
2017-08-17 22:06:10 +08:00
neil
6a524bff9d Merge pull request #973 from mvanini/master
Support for busybox in time2str()
2017-08-17 22:04:49 +08:00
neil
5def1169db Merge pull request #974 from Neilpang/dev
Dev
2017-08-17 21:52:33 +08:00
Michele
a07395fb56 Added support for busybox in time2str()
awk fallback if none of preceding method works
2017-08-17 12:50:28 +02:00
neil
e25a375f43 Merge pull request #969 from abelbeck/dns_duckdns
Update DuckDNS support, fix failure on first call, no longer save the…
2017-08-14 21:36:43 +08:00
Lonnie Abelbeck
96801e3478 Update DuckDNS support, fix failure on first call, no longer save the domain/username as a global, and other tweaks 2017-08-11 16:46:29 -05:00
neil
90100aa169 Merge pull request #967 from Neilpang/dev
support fcrontab, fix https://github.com/Neilpang/acme.sh/issues/966
2017-08-10 21:38:12 +08:00
neilpang
415f375ce6 support fcrontab, fix https://github.com/Neilpang/acme.sh/issues/966 2017-08-10 21:31:28 +08:00
David Kerr
94e9844179 Merge remote-tracking branch 'upstream/master' into ssh-deploy 2017-08-06 11:13:06 -04:00
neil
50d238b60f Merge pull request #963 from Neilpang/dev
format
2017-08-04 21:58:55 +08:00
neilpang
5c3b41bd93 format 2017-08-04 21:57:45 +08:00
neil
3e0971c159 Merge pull request #961 from Neilpang/dev
Dev
2017-08-03 23:40:05 +08:00
neil
57740fbd18 Merge pull request #960 from jfro/dev
Fix Linode DNS API to work on BSD
2017-08-03 22:38:17 +08:00
neil
16bc8f7040 Merge pull request #949 from candlerb/candlerb/unifi
Candlerb/unifi
2017-08-03 21:52:28 +08:00
Jeremy Knope
c145f24621 Remove extra space 2017-08-03 09:47:45 -04:00
Jeremy Knope
cd3a4573f2 Fix shell check errors 2017-07-31 08:37:30 -04:00
Brian Candler
8eab77f3c6 Add deployment script for unifi controller 2017-07-30 12:21:20 +01:00
neil
4af339424a Merge pull request #953 from angel333/master
Add DNS API script for Hurricane Electric DNS service
2017-07-30 10:45:40 +08:00
Ondrej Simek
4dd69a8b1a Exit codes, exit codes... Exit codes everywhere... 2017-07-29 14:40:56 +02:00
Ondrej Simek
baa1160594 Make Shellcheck happier about exit codes 2017-07-29 14:31:27 +02:00
Ondrej Simek
f438ff4bab Fix an improbable corner case. 2017-07-29 14:29:13 +02:00
Ondrej Simek
a25b2af66c Get rid of _find_num 2017-07-29 14:25:07 +02:00
Ondrej Simek
31b67ab92e Few non-critical fixes. 2017-07-29 13:52:28 +02:00
neil
5303b36913 Merge pull request #958 from Neilpang/dev
Dev
2017-07-29 15:25:16 +08:00
neilpang
a5c56c547d minor, fix dns param 2017-07-29 15:23:50 +08:00
Ondrej Simek
ccf9a9976c Fix the previous rushed commit. 2017-07-28 18:33:25 +02:00
Jeremy Knope
ab1efd923b back to sed 2017-07-28 10:26:56 -04:00
Ondrej Simek
d6780f9e49 Retain an exit code 2017-07-28 15:29:35 +02:00
Ondrej Simek
8534e3b2f7 Make shellcheck happier 2017-07-28 13:58:47 +02:00
Jeremy Knope
8e6cf669ad Try awk instead for \n replacements 2017-07-27 14:15:19 -04:00
Ondrej Simek
577380e98e Few fixes for shellcheck 2017-07-27 18:44:55 +02:00
Ondrej Simek
235b5b0c15 Small cosmetic fixes. 2017-07-27 18:06:19 +02:00
Ondrej Simek
aefed1d1b9 Get rid of shell arrays. 2017-07-27 18:04:53 +02:00
Jeremy Knope
d39649f30d Revert non-linode scripts since they're untested 2017-07-27 08:52:46 -04:00
Ondrej Simek
1546b7e5a9 Missing quotes 2017-07-26 20:21:36 +02:00
Ondrej Simek
ff74778dea Fix few issues from Travis 2017-07-26 20:15:34 +02:00
Jeremy Knope
29b21b828b Fix DNS API scripts on *BSD
\n isn't available in all regex/sed
2017-07-26 09:44:11 -04:00
neil
a6a0495392 Merge pull request #952 from candlerb/candlerb/isecc
Clarify keylength parameter to _isEccKey() and _initpath()
2017-07-25 19:05:51 +08:00
Brian Candler
3281043e27 Clarify keylength parameter to _isEccKey() and _initpath()
Closes #950
2017-07-25 09:39:19 +01:00
Ondrej Simek
f7299403f7 Incorporate Neilpang's comments 2017-07-23 07:31:55 +02:00
Ondrej Simek
a0d251a336 Merge remote-tracking branch 'upstream/dev' 2017-07-23 05:15:27 +02:00
Ondrej Simek
8ca45d3d03 Add HE to README 2017-07-23 05:13:33 +02:00
Ondrej Simek
d988542afc Sync with upstream 2017-07-23 05:09:48 +02:00
Ondrej Simek
4285d81ca9 Get rid of curl. 2017-07-23 05:00:02 +02:00
Santeri
4286b2917e renamed function 2017-07-19 12:22:00 +04:00
Santeri
d09b5cb80e Rename cpanel_uapi.sh to cpanel_deploy.sh 2017-07-19 07:39:21 +04:00
Santeri
90fd18bf42 Renamed script to cpanel_uapi.sh
As per Neil's request.
2017-07-18 15:48:17 +04:00
neil
cae6c8e5f5 Merge pull request #943 from Neilpang/dev
Dev
2017-07-14 20:38:11 +08:00
neil
473340c53b Merge pull request #936 from non7top/yandex
Add pdd.yandex.ru dns api support
2017-07-14 20:28:29 +08:00
Vladimir Berezhnoy
ae302ee600 reformat docs 2017-07-14 03:51:08 +03:00
Vladimir Berezhnoy
27934ac4ca Merge branch 'yandex' of github.com:non7top/acme.sh into yandex 2017-07-14 03:27:11 +03:00
Vladimir Berezhnoy
283ef9adb7 minor fixes 2017-07-14 03:26:36 +03:00
Vladimir Berezhnoy
377fe5ecde add documentation 2017-07-14 03:26:36 +03:00
Vladimir Berezhnoy
c848d3ee22 fix formatting 2017-07-14 03:26:36 +03:00
Vladimir Berezhnoy
eb6be88fac rework root domain detection 2017-07-14 03:26:36 +03:00
Vladimir Berezhnoy
fceb728501 fix egrep and exit 2017-07-14 03:26:36 +03:00
Vladimir Berezhnoy
a0df46258d remove python 2017-07-14 03:26:36 +03:00
Vladimir Berezhnoy
57d1db58db shfmt fixes 2017-07-14 03:26:36 +03:00
Vladimir Berezhnoy
d61b687853 remove awk 2017-07-14 03:26:36 +03:00
Vladimir Berezhnoy
42ab7a5d72 add newline and checks 2017-07-14 03:26:36 +03:00
Vladimir Berezhnoy
18cb11dcbf fix formatting 2017-07-14 03:26:36 +03:00
Vladimir Berezhnoy
e9d5407792 fix syntax 2017-07-14 03:26:36 +03:00
Vladimir Berezhnoy
a09b2c0074 fix syntax 2017-07-14 03:26:36 +03:00
Vladimir Berezhnoy
a460ac021f add pdd.yandex.ru dns api 2017-07-14 03:26:36 +03:00
Vladimir Berezhnoy
bdee66fe29 minor fixes 2017-07-13 18:37:13 +03:00
Vladimir Berezhnoy
84a251c8c7 add documentation 2017-07-13 17:05:57 +03:00
neil
cea763bb11 Merge pull request #942 from Neilpang/dev
output log
2017-07-13 20:56:53 +08:00
neilpang
accbda9d2f output log 2017-07-13 20:52:44 +08:00
Ondrej Simek
7d64e141e4 Add dns_he - DNS API script for Hurricane Electric DNS service
... Although not yet fully Posix compatible.
2017-07-12 20:24:54 +02:00
Vladimir Berezhnoy
6a9b4db448 fix formatting 2017-07-12 04:07:18 +03:00
Vladimir Berezhnoy
e6a95ecd08 rework root domain detection 2017-07-12 03:51:48 +03:00
Vladimir Berezhnoy
10cb7585a7 fix egrep and exit 2017-07-11 02:19:39 +03:00
Santeri
a577c7215f One more change to pass the check shellcheck test
Now it is tested and works also when run as a root.
2017-07-10 16:43:42 +04:00
neil
e5244cf3c0 Merge pull request #941 from Neilpang/dev
do not retry for a invalid cert in cronjob.
2017-07-10 19:58:22 +08:00
neilpang
c4d0aec536 do not retry for a invalid cert in cronjob.
fix https://github.com/Neilpang/acme.sh/issues/939
2017-07-10 19:51:55 +08:00
Santeri
796647158e Removed double quotes from _opt
Broke GoDaddy cpanel causing error (thanks Hedgehog)
2017-07-10 15:36:16 +04:00
Vladimir Berezhnoy
266e9d0619 remove python 2017-07-09 20:00:02 +03:00
Vladimir Berezhnoy
9ec54ef89b shfmt fixes 2017-07-09 13:21:55 +03:00
Vladimir Berezhnoy
256cb90f3c remove awk 2017-07-09 13:15:01 +03:00
Vladimir Berezhnoy
8f3a3b293d add newline and checks 2017-07-09 13:00:42 +03:00
neil
975a7359a2 Merge pull request #937 from Neilpang/dev
Dev
2017-07-09 09:48:37 +08:00
neil
ac7361a55e Merge pull request #935 from abelbeck/dns_dyn
Add 'dns_dyn' DNS challenge validation script for Dyn Managed DNS API, Issue #594
2017-07-09 09:20:34 +08:00
Vladimir Berezhnoy
bd41f50ba5 fix formatting 2017-07-08 22:02:34 +03:00
Vladimir Berezhnoy
a2038ab07e fix syntax 2017-07-08 21:57:27 +03:00
Vladimir Berezhnoy
6445a7674b fix syntax 2017-07-08 21:52:47 +03:00
Vladimir Berezhnoy
3bf2e89a1a add pdd.yandex.ru dns api 2017-07-08 21:35:22 +03:00
Lonnie Abelbeck
e6a13bf386 Merge branch 'dns_dyn' of github.com:abelbeck/acme.sh into dns_dyn 2017-07-08 07:10:09 -05:00
Lonnie Abelbeck
42b2adc03e Add 'dns_dyn' DNS challenge validation script for Dyn Managed DNS API
dns_dyn.sh, remove empty line at end

dns_dyn.sh, remove trailing spaces at end of line

Replace 'head -n' with the '_head_n' function

Update main README.md DNS API list
2017-07-08 07:06:51 -05:00
Lonnie Abelbeck
f2b9af01e8 Merge remote-tracking branch 'upstream/dev' into dns_dyn 2017-07-08 06:48:25 -05:00
Lonnie Abelbeck
9bd2d92755 Update main README.md DNS API list 2017-07-08 06:43:21 -05:00
Lonnie Abelbeck
babe884b7c Replace 'head -n' with the '_head_n' function 2017-07-08 06:39:18 -05:00
neilpang
200287254b add deactivate-account 2017-07-08 17:25:01 +08:00
neilpang
0b797f5964 fix new shellcheck error 2017-07-08 14:12:31 +08:00
neilpang
13a8c309f5 fix new shellcheck errors 2017-07-08 09:20:12 +08:00
Lonnie Abelbeck
528d2f29d3 dns_dyn.sh, remove trailing spaces at end of line 2017-07-07 10:33:24 -05:00
Lonnie Abelbeck
0aba5dc8de dns_dyn.sh, remove empty line at end 2017-07-07 10:22:20 -05:00
Lonnie Abelbeck
72fcf5ab85 Add 'dns_dyn' DNS challenge validation script for Dyn Managed DNS API 2017-07-07 09:51:43 -05:00
neil
dd9df068b0 Merge pull request #928 from Neilpang/dev
minor, fix format
2017-07-04 09:10:00 +08:00
neil
81772fb703 minor, fix format 2017-07-04 09:08:54 +08:00
neil
6304566603 Merge pull request #927 from Neilpang/dev
Dev
2017-07-04 08:29:38 +08:00
neilpang
5f8b60a0e5 fix https://github.com/Neilpang/acme.sh/issues/926
don't trigger validation for dns manually mode
2017-07-04 08:24:30 +08:00
raidenii
4964e075df Merge remote-tracking branch 'upstream/master' 2017-07-03 11:40:32 -04:00
neil
e2accaf70e Merge pull request #925 from raidenii/master
Fix for Name.com API
2017-07-03 20:55:36 +08:00
RaidenII
7b32bbfc26 Fix for SC2086. 2017-07-03 08:22:16 -04:00
RaidenII
6963f3880d Fixes the get_root function so that when domain doesn't exist it will correctly return error. 2017-07-03 03:28:28 -07:00
2globalnomads
6c3430b6e5 Wrote missing cpanel.sh
This script I wrote works for me on GoDaddy, but I don't have any other hosting services or cpanel version to test it. Hope it's better than nothing for you. Thanks for your great script!
Cheers,
Santeri
2017-07-02 23:24:14 +04:00
neil
c53f36a777 Merge pull request #920 from Neilpang/dev
Dev
2017-07-02 21:52:30 +08:00
neil
bb4d378733 Merge pull request #921 from raidenii/master
Fix README.md for DNS API.
2017-07-02 21:49:17 +08:00
RaidenII
333090a967 Fix README.md for DNS API. 2017-07-02 06:38:25 -07:00
neil
c8f5646d53 Merge pull request #919 from raidenii/master
Updated README.md for Name.com API application.
2017-07-02 21:34:19 +08:00
RaidenII
3002f6dfd5 Updated README.md for Name.com API application. 2017-07-02 06:02:44 -07:00
neil
3f8a50e2ae Merge pull request #909 from raidenii/master
DuckDNS.org and Name.com DNS API support
2017-07-02 20:13:12 +08:00
RaidenII
1a504118e5 Updated DNS API support list. 2017-07-02 04:55:06 -07:00
RaidenII
2e602ef6b0 Added ret value verification. 2017-07-02 04:45:07 -07:00
neil
d55c3faaeb Merge pull request #918 from Neilpang/dev
Dev
2017-07-02 19:20:59 +08:00
neilpang
6b185d20c0 fix format 2017-07-02 18:40:11 +08:00
neilpang
1bbc33a0cf minor fix CA_DIR 2017-07-02 18:24:55 +08:00
neilpang
a71eba07a1 minor, fix resource name 2017-07-02 18:05:55 +08:00
neilpang
422dd1fa4f Implement deactivate account: --deactivate-account 2017-07-02 17:02:54 +08:00
neilpang
c4b2e5829e add always-force-new-domain-key. fix https://github.com/Neilpang/acme.sh/issues/914 2017-07-02 15:25:35 +08:00
neilpang
1be222f6ed minor 2017-07-02 13:38:44 +08:00
neil
5463f459e6 Merge pull request #917 from Neilpang/dev
Dev
2017-07-01 22:44:29 +08:00
neilpang
14d7bfdab2 fix deactivate for lower rate limit 2017-07-01 21:47:30 +08:00
neilpang
ea722da3de add debug info 2017-07-01 20:31:42 +08:00
RaidenII
9aed1e2d17 Argh. Double quotes. 2017-07-01 05:18:12 -07:00
RaidenII
63c6ed3fd0 Fixes to follow coding standards. 2017-07-01 05:14:52 -07:00
neil
744bfc1982 Merge pull request #915 from Neilpang/dev
fix alias
2017-07-01 12:31:42 +08:00
neilpang
d04434e3ec fix alias 2017-07-01 10:54:14 +08:00
RaidenII
dc3b7b5775 Merge remote-tracking branch 'upstream/master' 2017-06-30 09:39:13 -04:00
RaidenII
17fbfd14db Minor fixes. 2017-06-30 08:32:39 -04:00
RaidenII
d0f5aece5f Fix SC2170. 2017-06-29 15:43:58 -04:00
RaidenII
eeda3062e1 Fix against POSIX standard. 2017-06-29 15:40:29 -04:00
RaidenII
168d712dec Fixed URL of Name.com API and removed useless debug for retcode. 2017-06-29 09:43:11 -04:00
RaidenII
e64ad5176e Added Name.com API support.
Minor change to DuckDNS API support.
2017-06-28 16:15:57 -04:00
neil
0e1469f359 Merge pull request #907 from Neilpang/dev
fix https://github.com/Neilpang/acme.sh/issues/905
2017-06-28 19:47:40 +08:00
neilpang
7d2b6cfeaf fix https://github.com/Neilpang/acme.sh/issues/905 2017-06-28 19:46:51 +08:00
neil
8e7d029946 Merge pull request #906 from Neilpang/dev
fix https://github.com/Neilpang/acme.sh/issues/900
2017-06-28 19:21:45 +08:00
neilpang
9dd62ae0f8 fix https://github.com/Neilpang/acme.sh/issues/900 2017-06-28 19:21:03 +08:00
RaidenII
e7dff4756f Using HTTPS for DuckDNS API and added instruction. 2017-06-27 15:28:10 -04:00
RaidenII
fa98d72f3a Added preliminary support for DuckDNS TXT record API, a free Dynamic DNS provider 2017-06-27 09:21:39 -04:00
neil
ccf0492890 Merge pull request #904 from Neilpang/dev
Dev
2017-06-27 19:57:50 +08:00
neilpang
eb0ef6bd3d fix https://github.com/Neilpang/acme.sh/issues/614#issuecomment-311160843 2017-06-27 19:56:43 +08:00
dkerr64
19aa2ccf4d Merge remote-tracking branch 'upstream/master' into ssh-deploy 2017-06-24 12:18:07 -04:00
neil
841b762796 minor 2017-06-23 18:11:11 +08:00
neil
63fb90806c Merge pull request #896 from Neilpang/dev
support --server
2017-06-20 21:59:08 +08:00
neilpang
88ada80686 step to 2.7.3 2017-06-20 21:51:18 +08:00
neilpang
7d5ddf5e6a Merge branch 'server' of https://github.com/Neilpang/acme.sh into server 2017-06-19 20:36:33 +08:00
neilpang
8f01919f62 minor 2017-06-19 20:34:49 +08:00
neilpang
98394f99b5 fix server host 2017-06-19 20:34:49 +08:00
neilpang
cae50e16a7 fix https://github.com/Neilpang/acme.sh/issues/882#issuecomment-309383956 2017-06-19 20:34:48 +08:00
neilpang
4a2ac7bd2e fix renew for stage cert 2017-06-19 20:34:48 +08:00
neilpang
a3bdaa85f2 minor 2017-06-19 20:34:47 +08:00
neilpang
40ef86f475 fix for deactivate function 2017-06-19 20:34:47 +08:00
neilpang
4cee14f3c5 fix format 2017-06-19 20:34:47 +08:00
neilpang
48d9a8c180 support --server 2017-06-19 20:34:46 +08:00
neilpang
1d384e3192 minor 2017-06-19 20:24:31 +08:00
neilpang
87f3dc4558 fix server host 2017-06-19 20:19:30 +08:00
neilpang
8afec596aa fix https://github.com/Neilpang/acme.sh/issues/882#issuecomment-309383956 2017-06-19 20:05:43 +08:00
neilpang
ce59fc6c10 fix renew for stage cert 2017-06-17 17:15:37 +08:00
neilpang
cbb74c984f minor 2017-06-17 16:30:04 +08:00
neilpang
287623df58 fix for deactivate function 2017-06-17 16:20:32 +08:00
neilpang
f8c1d97a25 fix format 2017-06-17 15:59:27 +08:00
neilpang
2a188905da support --server 2017-06-17 15:49:45 +08:00
dkerr64
6093a4f9f8 Merge remote-tracking branch 'upstream/master' into ssh-deploy 2017-05-19 21:25:39 -04:00
David Kerr
21f728f0ea Merge remote-tracking branch 'upstream/master' into ssh-deploy 2017-05-03 11:15:46 -04:00
David Kerr
3a439063a6 Merge remote-tracking branch 'upstream/master' into ssh-deploy 2017-04-22 11:45:03 -04:00
David Kerr
9964e6eba3 Merge remote-tracking branch 'upstream/master' into ssh-deploy 2017-04-17 15:28:36 -04:00
David Kerr
fd1598017a Merge remote-tracking branch 'upstream/master' into ssh-deploy 2017-04-05 16:47:56 -04:00
David Kerr
89f66ebf6d Merge remote-tracking branch 'upstream/master' into ssh-deploy 2017-03-24 10:55:42 -04:00
David Kerr
688973fa44 Merge remote-tracking branch 'upstream/master' into ssh-deploy 2017-03-21 16:30:46 -04:00
David Kerr
070a141601 Merge remote-tracking branch 'upstream/master' into ssh-deploy 2017-03-15 18:37:46 -04:00
David Kerr
158abf5c6c Remove line from README.md that I mistakenly added during
merge with master.
2017-03-07 12:09:07 -05:00
David Kerr
b30c1daf72 Merge remote-tracking branch 'upstream/master' into ssh-deploy 2017-03-07 12:04:35 -05:00
David Kerr
0649206796 remove _ACME prefix from all exported variables. 2017-03-07 11:57:03 -05:00
David Kerr
e0b00ee11a Merge remote-tracking branch 'upstream/master' into ssh-deploy 2017-02-20 15:27:10 -05:00
David Kerr
fa9afb0860 Merge remote-tracking branch 'upstream/master' into ssh-deploy 2017-02-18 23:45:36 -05:00
David Kerr
712b895170 Merge remote-tracking branch 'upstream/master' into ssh-deploy 2017-02-18 23:38:59 -05:00
David Kerr
710ce7c2e9 Merge remote-tracking branch 'upstream/master' into ssh-deploy 2017-02-17 14:28:50 -05:00
David Kerr
68a35155e4 Improve documentation in readme 2017-02-13 20:32:12 -05:00
David Kerr
d04ccb7a3f fix spelling error in readme 2017-02-12 18:20:43 -05:00
David Kerr
76c1ed6628 Additional documentation for the unifi example. 2017-02-12 18:08:17 -05:00
David Kerr
6f4abe95cb update markdown examples. 2017-02-12 11:24:00 -05:00
David Kerr
e35e313240 Fix error in Unifi example 2017-02-12 11:20:16 -05:00
David Kerr
3a77a6eded cleanup documentation and suppress some remote messages. 2017-02-12 11:17:23 -05:00
David Kerr
0a7a1b9bfb Merge remote-tracking branch 'upstream/master' into ssh-deploy 2017-02-12 10:45:51 -05:00
David Kerr
18a90734d9 Alternate backup cleanup after 180 days method. 2017-02-11 17:55:05 -05:00
David Kerr
a4b2cebef6 Make backup of certs on remote server optional. Defaults to yes. 2017-02-11 16:42:44 -05:00
David Kerr
68d708e56d Reduce and simplify number of exported variables. Also allow any cert file to
append to previous file.
2017-02-11 16:11:27 -05:00
David Kerr
e925ab0999 Merge remote-tracking branch 'upstream/master' into ssh-deploy 2017-02-11 14:37:02 -05:00
David Kerr
e3feac3fd8 Documentation updates 2017-02-08 21:13:00 -05:00
David Kerr
1a5989350f Some documentation in README 2017-02-08 21:02:00 -05:00
David Kerr
3365df7778 Make certificate domain name part of the backup directory name. 2017-02-08 10:15:39 -05:00
David Kerr
3be5a68e12 Rename sshdeploy.sh to ssh.sh 2017-02-07 13:05:22 -05:00
David Kerr
f158caa2eb Updates from code review 2017-02-06 21:49:20 -05:00
David Kerr
e02c94eb00 Merge remote-tracking branch 'upstream/master' into ssh-deploy 2017-02-06 21:31:55 -05:00
David Kerr
9507b121ac More selective pruning of certificate backup directories. 2017-02-05 15:34:03 -05:00
David Kerr
3812b275e9 Moving on to the next batch of travis errors. 2017-02-05 15:26:55 -05:00
David Kerr
6c1561f415 Grasping at straws now !! 2017-02-05 15:20:06 -05:00
David Kerr
9ab6353d73 Trying again. 2017-02-05 15:16:05 -05:00
David Kerr
ff60dc4d24 More Travis issues !!! 2017-02-05 15:12:23 -05:00
David Kerr
62e7d904b4 Travis errors 2017-02-05 15:02:59 -05:00
David Kerr
5d3de4b670 Additional info messages for backup management 2017-02-05 14:39:25 -05:00
David Kerr
7d75ad4c56 Backup old certificates before overwriting. Add userid export parameter.
And generate error if nothing to do at remote server.
2017-02-05 14:35:05 -05:00
David Kerr
989651c23b Initial version 2017-02-04 23:17:24 -05:00
44 changed files with 5457 additions and 953 deletions

View File

@@ -1,10 +1,14 @@
language: shell
sudo: required
dist: trusty
os:
- linux
- osx
services:
- docker
env:
global:
- SHFMT_URL=https://github.com/mvdan/sh/releases/download/v0.4.0/shfmt_v0.4.0_linux_amd64
@@ -18,20 +22,10 @@ addons:
install:
- if [ "$TRAVIS_OS_NAME" = 'osx' ]; then
brew update && brew install openssl;
brew info openssl;
ln -s /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/;
ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/;
ln -s /usr/local/Cellar/openssl/1.0.2j/bin/openssl /usr/local/openssl;
_old_path="$PATH";
echo "PATH=$PATH";
export PATH="";
export ACME_OPENSSL_BIN="/usr/local/openssl";
openssl version 2>&1 || true;
$ACME_OPENSSL_BIN version 2>&1 || true;
export PATH="$_old_path";
brew update && brew install socat;
export PATH="/usr/local/opt/openssl@1.1/bin:$PATH" ;
fi
script:
- echo "NGROK_TOKEN=$(echo "$NGROK_TOKEN" | wc -c)"
- command -V openssl && openssl version
@@ -40,10 +34,10 @@ script:
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then ~/shfmt -l -w -i 2 . ; fi
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then git diff --exit-code && echo "shfmt OK" ; fi
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then shellcheck -V ; fi
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then shellcheck **/*.sh && echo "shellcheck OK" ; fi
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then shellcheck -e SC2181 **/*.sh && echo "shellcheck OK" ; fi
- cd ..
- git clone https://github.com/Neilpang/acmetest.git && cp -r acme.sh acmetest/ && cd acmetest
- if [ "$TRAVIS_OS_NAME" = "linux" -a "$NGROK_TOKEN" ]; then sudo TEST_LOCAL="$TEST_LOCAL" NGROK_TOKEN="$NGROK_TOKEN" ./letest.sh ; fi
- if [ "$TRAVIS_OS_NAME" = "linux" -a "$NGROK_TOKEN" ]; then sudo TEST_LOCAL="$TEST_LOCAL" NGROK_TOKEN="$NGROK_TOKEN" ./rundocker.sh testplat ubuntu:latest ; fi
- if [ "$TRAVIS_OS_NAME" = "osx" -a "$NGROK_TOKEN" ]; then sudo TEST_LOCAL="$TEST_LOCAL" NGROK_TOKEN="$NGROK_TOKEN" ACME_OPENSSL_BIN="$ACME_OPENSSL_BIN" ./letest.sh ; fi

View File

@@ -1,10 +1,10 @@
FROM alpine
FROM alpine:3.6
RUN apk update -f \
&& apk --no-cache add -f \
openssl \
curl \
netcat-openbsd \
socat \
&& rm -rf /var/cache/apk/*
ENV LE_CONFIG_HOME /acme.sh
@@ -16,7 +16,7 @@ ADD ./ /install_acme.sh/
RUN cd /install_acme.sh && ([ -f /install_acme.sh/acme.sh ] && /install_acme.sh/acme.sh --install || curl https://get.acme.sh | sh) && rm -rf /install_acme.sh/
RUN ln -s /root/.acme.sh/acme.sh /usr/local/bin/acme.sh
RUN ln -s /root/.acme.sh/acme.sh /usr/local/bin/acme.sh && crontab -l | grep acme.sh | sed 's#> /dev/null##' | crontab -
RUN for verb in help \
version \
@@ -44,15 +44,17 @@ RUN for verb in help \
create-domain-key \
createCSR \
deactivate \
deactivate-account \
; do \
printf -- "%b" "#!/usr/bin/env sh\n/root/.acme.sh/acme.sh --${verb} --config-home /acme.sh \"\$@\"" >/usr/local/bin/--${verb} && chmod +x /usr/local/bin/--${verb} \
; done
RUN printf "%b" '#!'"/usr/bin/env sh\n \
if [ \"\$1\" = \"daemon\" ]; then \n \
crond -f\n \
trap \"echo stop && killall crond && exit 0\" SIGTERM SIGINT \n \
crond && while true; do sleep 1; done;\n \
else \n \
/root/.acme.sh/acme.sh --config-home /acme.sh \"\$@\"\n \
exec -- \"\$@\"\n \
fi" >/entry.sh && chmod +x /entry.sh
VOLUME /acme.sh

179
README.md
View File

@@ -3,6 +3,8 @@
[![Join the chat at https://gitter.im/acme-sh/Lobby](https://badges.gitter.im/acme-sh/Lobby.svg)](https://gitter.im/acme-sh/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
- An ACME protocol client written purely in Shell (Unix shell) language.
- Full ACME protocol implementation.
- Support ACME v1 and ACME v2
- Support ACME v2 wildcard certs
- Simple, powerful and very easy to use. You only need 3 minutes to learn it.
- Bash, dash and sh compatible.
- Simplest shell script for Let's Encrypt free certificate client.
@@ -23,7 +25,7 @@ Twitter: [@neilpangxa](https://twitter.com/neilpangxa)
# [中文说明](https://github.com/Neilpang/acme.sh/wiki/%E8%AF%B4%E6%98%8E)
# Who are using **acme.sh**
# Who:
- [FreeBSD.org](https://blog.crashed.org/letsencrypt-in-freebsd-org/)
- [ruby-china.org](https://ruby-china.org/topics/31983)
- [Proxmox](https://pve.proxmox.com/wiki/HTTPS_Certificate_Configuration_(Version_4.x_and_newer))
@@ -72,8 +74,9 @@ https://github.com/Neilpang/acmetest
- Webroot mode
- Standalone mode
- Apache mode
- Nginx mode ( Beta )
- Nginx mode
- DNS mode
- [DNS alias mode](https://github.com/Neilpang/acme.sh/wiki/DNS-alias-mode)
- [Stateless mode](https://github.com/Neilpang/acme.sh/wiki/Stateless-Mode)
@@ -127,7 +130,7 @@ Ok, you are ready to issue certs now.
Show help message:
```
```sh
root@v1:~# acme.sh -h
```
@@ -164,16 +167,16 @@ You must have at least one domain there.
You must point and bind all the domains to the same webroot dir: `/home/wwwroot/example.com`.
Generated/issued certs will be placed in `~/.acme.sh/example.com/`
The certs will be placed in `~/.acme.sh/example.com/`
The issued cert will be renewed automatically every **60** days.
The certs will be renewed automatically every **60** days.
More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert
# 3. Install the issued cert to Apache/Nginx etc.
# 3. Install the cert to Apache/Nginx etc.
After you issue a cert, you probably want to install/copy the cert to your Apache/Nginx or other servers.
After the cert is generated, you probably want to install/copy the cert to your Apache/Nginx or other servers.
You **MUST** use this command to copy the certs to the target files, **DO NOT** use the certs files in **~/.acme.sh/** folder, they are for internal use only, the folder structure may change in the future.
**Apache** example:
@@ -195,13 +198,15 @@ acme.sh --install-cert -d example.com \
Only the domain is required, all the other parameters are optional.
The ownership and permission info of existing files are preserved. You may want to precreate the files to have defined ownership and permission.
The ownership and permission info of existing files are preserved. You can pre-create the files to define the ownership and permission.
Install/copy the issued cert/key to the production Apache or Nginx path.
Install/copy the cert/key to the production Apache or Nginx path.
The cert will be renewed every **60** days by default (which is configurable). Once the cert is renewed, the Apache/Nginx service will be reloaded automatically by the command: `service apache2 force-reload` or `service nginx force-reload`.
**Please take care: The reloadcmd is very important. The cert can be automatically renewed, but, without a correct 'reloadcmd' the cert may not be flushed to your server(like nginx or apache), then your website will not be able to show renewed cert in 60 days.**
# 4. Use Standalone server to issue cert
**(requires you to be root/sudoer or have permission to listen on port 80 (TCP))**
@@ -236,14 +241,18 @@ More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert
If you are running a web server, Apache or Nginx, it is recommended to use the `Webroot mode`.
Particularly, if you are running an Apache server, you should use Apache mode instead. This mode doesn't write any files to your web root folder.
Particularly, if you are running an Apache server, you can use Apache mode instead. This mode doesn't write any files to your web root folder.
Just set string "apache" as the second argument and it will force use of apache plugin automatically.
```
```sh
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.
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.**
More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert
# 7. Use Nginx mode
@@ -260,44 +269,17 @@ It will configure nginx server automatically to verify the domain and then resto
So, the config is not changed.
```
```sh
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.
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.**
More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert
# 8. Use DNS mode:
Support the `dns-01` challenge.
```bash
acme.sh --issue --dns -d example.com -d www.example.com -d cp.example.com
```
You should get an output like below:
```
Add the following txt record:
Domain:_acme-challenge.example.com
Txt value:9ihDbjYfTExAYeDs4DBUeuTo18KBzwvTEjUnSwd32-c
Add the following txt record:
Domain:_acme-challenge.www.example.com
Txt value:9ihDbjxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Please add those txt records to the domains. Waiting for the dns to take effect.
```
Then just rerun with `renew` argument:
```bash
acme.sh --renew -d example.com
```
Ok, it's finished.
# 9. Automatic DNS API integration
# 8. Automatic DNS API integration
If your DNS provider supports API access, we can use that API to automatically issue the certs.
@@ -331,22 +313,68 @@ You don't have to do anything manually!
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
And:
1. lexicon DNS API: https://github.com/Neilpang/acme.sh/wiki/How-to-use-lexicon-dns-api
(DigitalOcean, DNSimple, DNSMadeEasy, DNSPark, EasyDNS, Namesilo, NS1, PointHQ, Rage4 and Vultr etc.)
**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)
# 9. Use DNS manual mode:
If your dns provider doesn't support any api access, you can add the txt record by your hand.
```bash
acme.sh --issue --dns -d example.com -d www.example.com -d cp.example.com
```
You should get an output like below:
```sh
Add the following txt record:
Domain:_acme-challenge.example.com
Txt value:9ihDbjYfTExAYeDs4DBUeuTo18KBzwvTEjUnSwd32-c
Add the following txt record:
Domain:_acme-challenge.www.example.com
Txt value:9ihDbjxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Please add those txt records to the domains. Waiting for the dns to take effect.
```
Then just rerun with `renew` argument:
```bash
acme.sh --renew -d example.com
```
Ok, it's done.
**Take care, this is dns manual mode, it can not be renewed automatically. you will have to add a new txt record to your domain by your hand when you renew your cert.**
**Please use dns api mode instead.**
# 10. Issue ECC certificates
@@ -354,7 +382,7 @@ For more details: [How to use DNS API](dnsapi)
And we support them too!
Just set the `length` parameter with a prefix `ec-`.
Just set the `keylength` parameter with a prefix `ec-`.
For example:
@@ -370,7 +398,7 @@ acme.sh --issue -w /home/wwwroot/example.com -d example.com --keylength ec-256
acme.sh --issue -w /home/wwwroot/example.com -d example.com -d www.example.com --keylength ec-256
```
Please look at the last parameter above.
Please look at the `keylength` parameter above.
Valid values are:
@@ -379,36 +407,60 @@ Valid values are:
3. **ec-521 (secp521r1, "ECDSA P-521", which is not supported by Let's Encrypt yet.)**
# 11. How to renew the issued certs
# 11. Issue Wildcard certificates
It's simple, just give a wildcard domain as the `-d` parameter.
```sh
acme.sh --issue -d example.com -d *.example.com --dns dns_cf
```
# 12. How to renew the certs
No, you don't need to renew the certs manually. All the certs will be renewed automatically every **60** days.
However, you can also force to renew any cert:
However, you can also force to renew a cert:
```
```sh
acme.sh --renew -d example.com --force
```
or, for ECC cert:
```
```sh
acme.sh --renew -d example.com --force --ecc
```
# 12. How to upgrade `acme.sh`
# 13. How to stop cert renewal
To stop renewal of a cert, you can execute the following to remove the cert from the renewal list:
```sh
acme.sh --remove -d example.com [--ecc]
```
The cert/key file is not removed from the disk.
You can remove the respective directory (e.g. `~/.acme.sh/example.com`) by yourself.
# 14. How to upgrade `acme.sh`
acme.sh is in constant development, so it's strongly recommended to use the latest code.
You can update acme.sh to the latest code:
```
```sh
acme.sh --upgrade
```
You can also enable auto upgrade:
```
```sh
acme.sh --upgrade --auto-upgrade
```
@@ -416,31 +468,30 @@ Then **acme.sh** will be kept up to date automatically.
Disable auto upgrade:
```
```sh
acme.sh --upgrade --auto-upgrade 0
```
# 13. Issue a cert from an existing CSR
# 15. Issue a cert from an existing CSR
https://github.com/Neilpang/acme.sh/wiki/Issue-a-cert-from-existing-CSR
# 14. Under the Hood
# 16. Under the Hood
Speak ACME language using shell, directly to "Let's Encrypt".
TODO:
# 15. Acknowledgments
# 17. Acknowledgments
1. Acme-tiny: https://github.com/diafygi/acme-tiny
2. ACME protocol: https://github.com/ietf-wg-acme/acme
3. Certbot: https://github.com/certbot/certbot
# 16. License & Others
# 18. License & Others
License is GPLv3
@@ -449,7 +500,7 @@ Please Star and Fork me.
[Issues](https://github.com/Neilpang/acme.sh/issues) and [pull requests](https://github.com/Neilpang/acme.sh/pulls) are welcome.
# 17. Donate
# 19. Donate
Your donation makes **acme.sh** better:
1. PayPal/Alipay(支付宝)/Wechat(微信): [https://donate.acme.sh/](https://donate.acme.sh/)

1310
acme.sh

File diff suppressed because it is too large Load Diff

View File

@@ -4,7 +4,9 @@ Before you can deploy your cert, you must [issue the cert first](https://github.
Here are the scripts to deploy the certs/key to the server/services.
## 1. Deploy the certs to your cpanel host.
## 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.)
@@ -18,7 +20,7 @@ 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.
## 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.
@@ -27,11 +29,150 @@ Currently supports Kong-v0.10.x.
acme.sh --deploy -d ftp.example.com --deploy-hook kong
```
## 3. Deploy the cert to remote server through SSH access.
## 3. Deploy the cert to remote server through SSH access
(TODO)
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...
## 4. Deploy the cert to local vsftpd server.
```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
@@ -53,7 +194,7 @@ 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.
## 5. Deploy the cert to local exim4 server
```sh
acme.sh --deploy -d ftp.example.com --deploy-hook exim4
@@ -80,3 +221,37 @@ acme.sh --deploy -d ftp.example.com --deploy-hook exim4
```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
```

View File

@@ -1,29 +0,0 @@
#!/usr/bin/env sh
#Here is the script to deploy the cert to your cpanel account by the cpanel APIs.
#returns 0 means success, otherwise error.
#export DEPLOY_CPANEL_USER=myusername
#export DEPLOY_CPANEL_PASSWORD=PASSWORD
######## Public functions #####################
#domain keyfile certfile cafile fullchain
cpanel_deploy() {
_cdomain="$1"
_ckey="$2"
_ccert="$3"
_cca="$4"
_cfullchain="$5"
_debug _cdomain "$_cdomain"
_debug _ckey "$_ckey"
_debug _ccert "$_ccert"
_debug _cca "$_cca"
_debug _cfullchain "$_cfullchain"
_err "Not implemented yet"
return 1
}

64
deploy/cpanel_uapi.sh Normal file
View File

@@ -0,0 +1,64 @@
#!/usr/bin/env sh
# Here is the script to deploy the cert to your cpanel using the cpanel API.
# Uses command line uapi. --user option is needed only if run as root.
# Returns 0 when success.
# Written by Santeri Kannisto <santeri.kannisto@2globalnomads.info>
# Public domain, 2017
#export DEPLOY_CPANEL_USER=myusername
######## Public functions #####################
#domain keyfile certfile cafile fullchain
cpanel_uapi_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 ! _exists uapi; then
_err "The command uapi is not found."
return 1
fi
if ! _exists php; then
_err "The command php is not found."
return 1
fi
# read cert and key files and urlencode both
_certstr=$(cat "$_ccert")
_keystr=$(cat "$_ckey")
_cert=$(php -r "echo urlencode(\"$_certstr\");")
_key=$(php -r "echo urlencode(\"$_keystr\");")
_debug _cert "$_cert"
_debug _key "$_key"
if [ "$(id -u)" = 0 ]; then
if [ -z "$DEPLOY_CPANEL_USER" ]; then
_err "It seems that you are root, please define the target user name: export DEPLOY_CPANEL_USER=username"
return 1
fi
_savedomainconf DEPLOY_CPANEL_USER "$DEPLOY_CPANEL_USER"
_response=$(uapi --user="$DEPLOY_CPANEL_USER" SSL install_ssl domain="$_cdomain" cert="$_cert" key="$_key")
else
_response=$(uapi SSL install_ssl domain="$_cdomain" cert="$_cert" key="$_key")
fi
error_response="status: 0"
if test "${_response#*$error_response}" != "$_response"; then
_err "Error in deploying certificate:"
_err "$_response"
return 1
fi
_debug response "$_response"
_info "Certificate successfully deployed"
return 0
}

108
deploy/fritzbox.sh Normal file
View File

@@ -0,0 +1,108 @@
#!/usr/bin/env sh
#Here is a script to deploy cert to an AVM FRITZ!Box router.
#returns 0 means success, otherwise error.
#DEPLOY_FRITZBOX_USERNAME="username"
#DEPLOY_FRITZBOX_PASSWORD="password"
#DEPLOY_FRITZBOX_URL="https://fritz.box"
# Kudos to wikrie at Github for his FRITZ!Box update script:
# https://gist.github.com/wikrie/f1d5747a714e0a34d0582981f7cb4cfb
######## Public functions #####################
#domain keyfile certfile cafile fullchain
fritzbox_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 ! _exists iconv; then
_err "iconv not found"
return 1
fi
_fritzbox_username="${DEPLOY_FRITZBOX_USERNAME}"
_fritzbox_password="${DEPLOY_FRITZBOX_PASSWORD}"
_fritzbox_url="${DEPLOY_FRITZBOX_URL}"
_debug _fritzbox_url "$_fritzbox_url"
_debug _fritzbox_username "$_fritzbox_username"
_secure_debug _fritzbox_password "$_fritzbox_password"
if [ -z "$_fritzbox_username" ]; then
_err "FRITZ!Box username is not found, please define DEPLOY_FRITZBOX_USERNAME."
return 1
fi
if [ -z "$_fritzbox_password" ]; then
_err "FRITZ!Box password is not found, please define DEPLOY_FRITZBOX_PASSWORD."
return 1
fi
if [ -z "$_fritzbox_url" ]; then
_err "FRITZ!Box url is not found, please define DEPLOY_FRITZBOX_URL."
return 1
fi
_saveaccountconf DEPLOY_FRITZBOX_USERNAME "${_fritzbox_username}"
_saveaccountconf DEPLOY_FRITZBOX_PASSWORD "${_fritzbox_password}"
_saveaccountconf DEPLOY_FRITZBOX_URL "${_fritzbox_url}"
# Do not check for a valid SSL certificate, because initially the cert is not valid, so it could not install the LE generated certificate
export HTTPS_INSECURE=1
_info "Log in to the FRITZ!Box"
_fritzbox_challenge="$(_get "${_fritzbox_url}/login_sid.lua" | sed -e 's/^.*<Challenge>//' -e 's/<\/Challenge>.*$//')"
_fritzbox_hash="$(printf "%s-%s" "${_fritzbox_challenge}" "${_fritzbox_password}" | iconv -f ASCII -t UTF16LE | md5sum | awk '{print $1}')"
_fritzbox_sid="$(_get "${_fritzbox_url}/login_sid.lua?sid=0000000000000000&username=${_fritzbox_username}&response=${_fritzbox_challenge}-${_fritzbox_hash}" | sed -e 's/^.*<SID>//' -e 's/<\/SID>.*$//')"
if [ -z "${_fritzbox_sid}" ] || [ "${_fritzbox_sid}" = "0000000000000000" ]; then
_err "Logging in to the FRITZ!Box failed. Please check username, password and URL."
return 1
fi
_info "Generate form POST request"
_post_request="$(_mktemp)"
_post_boundary="---------------------------$(date +%Y%m%d%H%M%S)"
# _CERTPASSWORD_ is unset because Let's Encrypt certificates don't have a password. But if they ever do, here's the place to use it!
_CERTPASSWORD_=
{
printf -- "--"
printf -- "%s\r\n" "${_post_boundary}"
printf "Content-Disposition: form-data; name=\"sid\"\r\n\r\n%s\r\n" "${_fritzbox_sid}"
printf -- "--"
printf -- "%s\r\n" "${_post_boundary}"
printf "Content-Disposition: form-data; name=\"BoxCertPassword\"\r\n\r\n%s\r\n" "${_CERTPASSWORD_}"
printf -- "--"
printf -- "%s\r\n" "${_post_boundary}"
printf "Content-Disposition: form-data; name=\"BoxCertImportFile\"; filename=\"BoxCert.pem\"\r\n"
printf "Content-Type: application/octet-stream\r\n\r\n"
cat "${_ckey}" "${_cfullchain}"
printf "\r\n"
printf -- "--"
printf -- "%s--" "${_post_boundary}"
} >>"${_post_request}"
_info "Upload certificate to the FRITZ!Box"
export _H1="Content-type: multipart/form-data boundary=${_post_boundary}"
_post "$(cat "${_post_request}")" "${_fritzbox_url}/cgi-bin/firmwarecfg" | grep SSL
retval=$?
if [ $retval = 0 ]; then
_info "Upload successful"
else
_err "Upload failed"
fi
rm "${_post_request}"
return $retval
}

205
deploy/ssh.sh Normal file
View File

@@ -0,0 +1,205 @@
#!/usr/bin/env sh
# Script to deploy certificates to remote server by SSH
# 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@SERVER from the host running acme.sh before
# using this script.
#
# The following variables exported from environment will be used.
# If not set then values previously saved in domain.conf file are used.
#
# Only a username is required. All others are optional.
#
# The following examples are for QNAP NAS running QTS 4.2
# export DEPLOY_SSH_CMD="" # defaults to ssh
# export DEPLOY_SSH_USER="admin" # required
# export DEPLOY_SSH_SERVER="qnap" # defaults to domain name
# 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_FULLCHAIN=""
# export DEPLOY_SSH_REMOTE_CMD="/etc/init.d/stunnel.sh restart"
# export DEPLOY_SSH_BACKUP="" # yes or no, default to yes
#
######## Public functions #####################
#domain keyfile certfile cafile fullchain
ssh_deploy() {
_cdomain="$1"
_ckey="$2"
_ccert="$3"
_cca="$4"
_cfullchain="$5"
_cmdstr=""
_homedir='~'
_backupprefix="$_homedir/.acme_ssh_deploy/$_cdomain-backup"
_backupdir="$_backupprefix-$(_utc_date | tr ' ' '-')"
if [ -f "$DOMAIN_CONF" ]; then
# shellcheck disable=SC1090
. "$DOMAIN_CONF"
fi
_debug _cdomain "$_cdomain"
_debug _ckey "$_ckey"
_debug _ccert "$_ccert"
_debug _cca "$_cca"
_debug _cfullchain "$_cfullchain"
# USER is required to login by SSH to remote host.
if [ -z "$DEPLOY_SSH_USER" ]; then
if [ -z "$Le_Deploy_ssh_user" ]; then
_err "DEPLOY_SSH_USER not defined."
return 1
fi
else
Le_Deploy_ssh_user="$DEPLOY_SSH_USER"
_savedomainconf Le_Deploy_ssh_user "$Le_Deploy_ssh_user"
fi
# SERVER is optional. If not provided then use _cdomain
if [ -n "$DEPLOY_SSH_SERVER" ]; then
Le_Deploy_ssh_server="$DEPLOY_SSH_SERVER"
_savedomainconf Le_Deploy_ssh_server "$Le_Deploy_ssh_server"
elif [ -z "$Le_Deploy_ssh_server" ]; then
Le_Deploy_ssh_server="$_cdomain"
fi
# CMD is optional. If not provided then use ssh
if [ -n "$DEPLOY_SSH_CMD" ]; then
Le_Deploy_ssh_cmd="$DEPLOY_SSH_CMD"
_savedomainconf Le_Deploy_ssh_cmd "$Le_Deploy_ssh_cmd"
elif [ -z "$Le_Deploy_ssh_cmd" ]; then
Le_Deploy_ssh_cmd="ssh"
fi
# BACKUP is optional. If not provided then default to yes
if [ "$DEPLOY_SSH_BACKUP" = "no" ]; then
Le_Deploy_ssh_backup="no"
elif [ -z "$Le_Deploy_ssh_backup" ]; then
Le_Deploy_ssh_backup="yes"
fi
_savedomainconf Le_Deploy_ssh_backup "$Le_Deploy_ssh_backup"
_info "Deploy certificates to remote server $Le_Deploy_ssh_user@$Le_Deploy_ssh_server"
# KEYFILE is optional.
# If provided then private key will be copied to provided filename.
if [ -n "$DEPLOY_SSH_KEYFILE" ]; then
Le_Deploy_ssh_keyfile="$DEPLOY_SSH_KEYFILE"
_savedomainconf Le_Deploy_ssh_keyfile "$Le_Deploy_ssh_keyfile"
fi
if [ -n "$Le_Deploy_ssh_keyfile" ]; then
if [ "$Le_Deploy_ssh_backup" = "yes" ]; then
# backup file we are about to overwrite.
_cmdstr="$_cmdstr cp $Le_Deploy_ssh_keyfile $_backupdir >/dev/null;"
fi
# copy new certificate into file.
_cmdstr="$_cmdstr echo \"$(cat "$_ckey")\" > $Le_Deploy_ssh_keyfile;"
_info "will copy private key to remote file $Le_Deploy_ssh_keyfile"
fi
# CERTFILE is optional.
# If provided then private key will be copied or appended to provided filename.
if [ -n "$DEPLOY_SSH_CERTFILE" ]; then
Le_Deploy_ssh_certfile="$DEPLOY_SSH_CERTFILE"
_savedomainconf Le_Deploy_ssh_certfile "$Le_Deploy_ssh_certfile"
fi
if [ -n "$Le_Deploy_ssh_certfile" ]; then
_pipe=">"
if [ "$Le_Deploy_ssh_certfile" = "$Le_Deploy_ssh_keyfile" ]; then
# if filename is same as previous file then append.
_pipe=">>"
elif [ "$Le_Deploy_ssh_backup" = "yes" ]; then
# backup file we are about to overwrite.
_cmdstr="$_cmdstr cp $Le_Deploy_ssh_certfile $_backupdir >/dev/null;"
fi
# copy new certificate into file.
_cmdstr="$_cmdstr echo \"$(cat "$_ccert")\" $_pipe $Le_Deploy_ssh_certfile;"
_info "will copy certificate to remote file $Le_Deploy_ssh_certfile"
fi
# CAFILE is optional.
# If provided then CA intermediate certificate will be copied or appended to provided filename.
if [ -n "$DEPLOY_SSH_CAFILE" ]; then
Le_Deploy_ssh_cafile="$DEPLOY_SSH_CAFILE"
_savedomainconf Le_Deploy_ssh_cafile "$Le_Deploy_ssh_cafile"
fi
if [ -n "$Le_Deploy_ssh_cafile" ]; then
_pipe=">"
if [ "$Le_Deploy_ssh_cafile" = "$Le_Deploy_ssh_keyfile" ] \
|| [ "$Le_Deploy_ssh_cafile" = "$Le_Deploy_ssh_certfile" ]; then
# if filename is same as previous file then append.
_pipe=">>"
elif [ "$Le_Deploy_ssh_backup" = "yes" ]; then
# backup file we are about to overwrite.
_cmdstr="$_cmdstr cp $Le_Deploy_ssh_cafile $_backupdir >/dev/null;"
fi
# copy new certificate into file.
_cmdstr="$_cmdstr echo \"$(cat "$_cca")\" $_pipe $Le_Deploy_ssh_cafile;"
_info "will copy CA file to remote file $Le_Deploy_ssh_cafile"
fi
# FULLCHAIN is optional.
# If provided then fullchain certificate will be copied or appended to provided filename.
if [ -n "$DEPLOY_SSH_FULLCHAIN" ]; then
Le_Deploy_ssh_fullchain="$DEPLOY_SSH_FULLCHAIN"
_savedomainconf Le_Deploy_ssh_fullchain "$Le_Deploy_ssh_fullchain"
fi
if [ -n "$Le_Deploy_ssh_fullchain" ]; then
_pipe=">"
if [ "$Le_Deploy_ssh_fullchain" = "$Le_Deploy_ssh_keyfile" ] \
|| [ "$Le_Deploy_ssh_fullchain" = "$Le_Deploy_ssh_certfile" ] \
|| [ "$Le_Deploy_ssh_fullchain" = "$Le_Deploy_ssh_cafile" ]; then
# if filename is same as previous file then append.
_pipe=">>"
elif [ "$Le_Deploy_ssh_backup" = "yes" ]; then
# backup file we are about to overwrite.
_cmdstr="$_cmdstr cp $Le_Deploy_ssh_fullchain $_backupdir >/dev/null;"
fi
# copy new certificate into file.
_cmdstr="$_cmdstr echo \"$(cat "$_cfullchain")\" $_pipe $Le_Deploy_ssh_fullchain;"
_info "will copy fullchain to remote file $Le_Deploy_ssh_fullchain"
fi
# REMOTE_CMD is optional.
# If provided then this command will be executed on remote host.
if [ -n "$DEPLOY_SSH_REMOTE_CMD" ]; then
Le_Deploy_ssh_remote_cmd="$DEPLOY_SSH_REMOTE_CMD"
_savedomainconf Le_Deploy_ssh_remote_cmd "$Le_Deploy_ssh_remote_cmd"
fi
if [ -n "$Le_Deploy_ssh_remote_cmd" ]; then
_cmdstr="$_cmdstr $Le_Deploy_ssh_remote_cmd;"
_info "Will execute remote command $Le_Deploy_ssh_remote_cmd"
fi
if [ -z "$_cmdstr" ]; then
_err "No remote commands to excute. Failed to deploy certificates to remote server"
return 1
elif [ "$Le_Deploy_ssh_backup" = "yes" ]; then
# run cleanup on the backup directory, erase all older
# than 180 days (15552000 seconds).
_cmdstr="{ now=\"\$(date -u +%s)\"; for fn in $_backupprefix*; \
do if [ -d \"\$fn\" ] && [ \"\$(expr \$now - \$(date -ur \$fn +%s) )\" -ge \"15552000\" ]; \
then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; done; }; $_cmdstr"
# Alternate version of above... _cmdstr="find $_backupprefix* -type d -mtime +180 2>/dev/null | xargs rm -rf; $_cmdstr"
# Create our backup directory for overwritten cert files.
_cmdstr="mkdir -p $_backupdir; $_cmdstr"
_info "Backup of old certificate files will be placed in remote directory $_backupdir"
_info "Backup directories erased after 180 days."
fi
_debug "Remote commands to execute: $_cmdstr"
_info "Submitting sequence of commands to remote server by ssh"
# quotations in bash cmd below intended. Squash travis spellcheck error
# shellcheck disable=SC2029
$Le_Deploy_ssh_cmd -T "$Le_Deploy_ssh_user@$Le_Deploy_ssh_server" sh -c "'$_cmdstr'"
_ret="$?"
if [ "$_ret" != "0" ]; then
_err "Error code $_ret returned from $Le_Deploy_ssh_cmd"
fi
return $_ret
}

55
deploy/strongswan.sh Normal file
View File

@@ -0,0 +1,55 @@
#!/usr/bin/env sh
#Here is a sample custom api script.
#This file name is "myapi.sh"
#So, here must be a method myapi_deploy()
#Which will be called by acme.sh to deploy the cert
#returns 0 means success, otherwise error.
######## Public functions #####################
#domain keyfile certfile cafile fullchain
strongswan_deploy() {
_cdomain="$1"
_ckey="$2"
_ccert="$3"
_cca="$4"
_cfullchain="$5"
_info "Using strongswan"
if [ -x /usr/sbin/ipsec ]; then
_ipsec=/usr/sbin/ipsec
elif [ -x /usr/sbin/strongswan ]; then
_ipsec=/usr/sbin/strongswan
elif [ -x /usr/local/sbin/ipsec ]; then
_ipsec=/usr/local/sbin/ipsec
else
_err "no strongswan or ipsec command is detected"
return 1
fi
_info _ipsec "$_ipsec"
_confdir=$($_ipsec --confdir)
if [ $? -ne 0 ] || [ -z "$_confdir" ]; then
_err "no strongswan --confdir is detected"
return 1
fi
_info _confdir "$_confdir"
_debug _cdomain "$_cdomain"
_debug _ckey "$_ckey"
_debug _ccert "$_ccert"
_debug _cca "$_cca"
_debug _cfullchain "$_cfullchain"
cat "$_ckey" >"${_confdir}/ipsec.d/private/$(basename "$_ckey")"
cat "$_ccert" >"${_confdir}/ipsec.d/certs/$(basename "$_ccert")"
cat "$_cca" >"${_confdir}/ipsec.d/cacerts/$(basename "$_cca")"
cat "$_cfullchain" >"${_confdir}/ipsec.d/cacerts/$(basename "$_cfullchain")"
$_ipsec reload
}

100
deploy/unifi.sh Normal file
View File

@@ -0,0 +1,100 @@
#!/usr/bin/env sh
#Here is a script to deploy cert to unifi server.
#returns 0 means success, otherwise error.
#DEPLOY_UNIFI_KEYSTORE="/usr/lib/unifi/data/keystore"
#DEPLOY_UNIFI_KEYPASS="aircontrolenterprise"
#DEPLOY_UNIFI_RELOAD="service unifi restart"
######## Public functions #####################
#domain keyfile certfile cafile fullchain
unifi_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 ! _exists keytool; then
_err "keytool not found"
return 1
fi
DEFAULT_UNIFI_KEYSTORE="/usr/lib/unifi/data/keystore"
_unifi_keystore="${DEPLOY_UNIFI_KEYSTORE:-$DEFAULT_UNIFI_KEYSTORE}"
DEFAULT_UNIFI_KEYPASS="aircontrolenterprise"
_unifi_keypass="${DEPLOY_UNIFI_KEYPASS:-$DEFAULT_UNIFI_KEYPASS}"
DEFAULT_UNIFI_RELOAD="service unifi restart"
_reload="${DEPLOY_UNIFI_RELOAD:-$DEFAULT_UNIFI_RELOAD}"
_debug _unifi_keystore "$_unifi_keystore"
if [ ! -f "$_unifi_keystore" ]; then
if [ -z "$DEPLOY_UNIFI_KEYSTORE" ]; then
_err "unifi keystore is not found, please define DEPLOY_UNIFI_KEYSTORE"
return 1
else
_err "It seems that the specified unifi keystore is not valid, please check."
return 1
fi
fi
if [ ! -w "$_unifi_keystore" ]; then
_err "The file $_unifi_keystore is not writable, please change the permission."
return 1
fi
_info "Generate import pkcs12"
_import_pkcs12="$(_mktemp)"
_toPkcs "$_import_pkcs12" "$_ckey" "$_ccert" "$_cca" "$_unifi_keypass" unifi root
if [ "$?" != "0" ]; then
_err "Oops, error creating import pkcs12, please report bug to us."
return 1
fi
_info "Modify unifi keystore: $_unifi_keystore"
if keytool -importkeystore \
-deststorepass "$_unifi_keypass" -destkeypass "$_unifi_keypass" -destkeystore "$_unifi_keystore" \
-srckeystore "$_import_pkcs12" -srcstoretype PKCS12 -srcstorepass "$_unifi_keypass" \
-alias unifi -noprompt; then
_info "Import keystore success!"
rm "$_import_pkcs12"
else
_err "Import unifi keystore error, please report bug to us."
rm "$_import_pkcs12"
return 1
fi
_info "Run reload: $_reload"
if eval "$_reload"; then
_info "Reload success!"
if [ "$DEPLOY_UNIFI_KEYSTORE" ]; then
_savedomainconf DEPLOY_UNIFI_KEYSTORE "$DEPLOY_UNIFI_KEYSTORE"
else
_cleardomainconf DEPLOY_UNIFI_KEYSTORE
fi
if [ "$DEPLOY_UNIFI_KEYPASS" ]; then
_savedomainconf DEPLOY_UNIFI_KEYPASS "$DEPLOY_UNIFI_KEYPASS"
else
_cleardomainconf DEPLOY_UNIFI_KEYPASS
fi
if [ "$DEPLOY_UNIFI_RELOAD" ]; then
_savedomainconf DEPLOY_UNIFI_RELOAD "$DEPLOY_UNIFI_RELOAD"
else
_cleardomainconf DEPLOY_UNIFI_RELOAD
fi
return 0
else
_err "Reload error"
return 1
fi
return 0
}

56
deploy/vault_cli.sh Normal file
View File

@@ -0,0 +1,56 @@
#!/usr/bin/env sh
# Here is a script to deploy cert to hashicorp vault
# (https://www.vaultproject.io/)
#
# it requires the vault binary to be available in PATH, and the following
# environment variables:
#
# VAULT_PREFIX - this contains the prefix path in vault
# VAULT_ADDR - vault requires this to find your vault server
#
# additionally, you need to ensure that VAULT_TOKEN is avialable or
# `vault auth` has applied the appropriate authorization for the vault binary
# to access the vault server
#returns 0 means success, otherwise error.
######## Public functions #####################
#domain keyfile certfile cafile fullchain
vault_cli_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"
# validate required env vars
if [ -z "$VAULT_PREFIX" ]; then
_err "VAULT_PREFIX needs to be defined (contains prefix path in vault)"
return 1
fi
if [ -z "$VAULT_ADDR" ]; then
_err "VAULT_ADDR needs to be defined (contains vault connection address)"
return 1
fi
VAULT_CMD=$(which vault)
if [ ! $? ]; then
_err "cannot find vault binary!"
return 1
fi
$VAULT_CMD write "${VAULT_PREFIX}/${_cdomain}/cert.pem" value=@"$_ccert" || return 1
$VAULT_CMD write "${VAULT_PREFIX}/${_cdomain}/cert.key" value=@"$_ckey" || return 1
$VAULT_CMD write "${VAULT_PREFIX}/${_cdomain}/fullchain.pem" value=@"$_cfullchain" || return 1
}

View File

@@ -354,7 +354,7 @@ acme.sh --issue --dns dns_gandi_livedns -d example.com -d www.example.com
First, generate a TSIG key for updating the zone.
```
keymgr tsig generate acme_key algorithm hmac-sha512 > /etc/knot/acme.key
keymgr tsig generate -t acme_key hmac-sha512 > /etc/knot/acme.key
```
Include this key in your knot configuration file.
@@ -409,10 +409,13 @@ acme.sh --issue --dns dns_dgon -d example.com -d www.example.com
## 21. Use ClouDNS.net API
You need to set the HTTP API user ID and password credentials. See: https://www.cloudns.net/wiki/article/42/
You need to set the HTTP API user ID and password credentials. See: https://www.cloudns.net/wiki/article/42/. For security reasons, it's recommended to use a sub user ID that only has access to the necessary zones, as a regular API user has access to your entire account.
```
export CLOUDNS_AUTH_ID=XXXXX
# Use this for a sub auth ID
export CLOUDNS_SUB_AUTH_ID=XXXXX
# Use this for a regular auth ID
#export CLOUDNS_AUTH_ID=XXXXX
export CLOUDNS_AUTH_PASSWORD="YYYYYYYYY"
```
@@ -420,6 +423,7 @@ Ok, let's issue a cert now:
```
acme.sh --issue --dns dns_cloudns -d example.com -d www.example.com
```
The `CLOUDNS_AUTH_ID` and `CLOUDNS_AUTH_PASSWORD` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
## 22. Use Infoblox API
@@ -505,6 +509,282 @@ Ok, let's issue a cert now:
acme.sh --issue --dns dns_nsone -d example.com -d www.example.com
```
## 27. Use DuckDNS.org API
```
export DuckDNS_Token="aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
```
Please note that since DuckDNS uses StartSSL as their cert provider, thus
--insecure may need to be used when issuing certs:
```
acme.sh --insecure --issue --dns dns_duckdns -d mydomain.duckdns.org
```
For issues, please report to https://github.com/raidenii/acme.sh/issues.
## 28. Use Name.com API
You'll need to fill out the form at https://www.name.com/reseller/apply to apply
for API username and token.
```
export Namecom_Username="testuser"
export Namecom_Token="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
```
And now you can issue certs with:
```
acme.sh --issue --dns dns_namecom -d example.com -d www.example.com
```
For issues, please report to https://github.com/raidenii/acme.sh/issues.
## 29. Use Dyn Managed DNS API to automatically issue cert
First, login to your Dyn Managed DNS account: https://portal.dynect.net/login/
It is recommended to add a new user specific for API access.
The minimum "Zones & Records Permissions" required are:
```
RecordAdd
RecordUpdate
RecordDelete
RecordGet
ZoneGet
ZoneAddNode
ZoneRemoveNode
ZonePublish
```
Pass the API user credentials to the environment:
```
export DYN_Customer="customer"
export DYN_Username="apiuser"
export DYN_Password="secret"
```
Ok, let's issue a cert now:
```
acme.sh --issue --dns dns_dyn -d example.com -d www.example.com
```
The `DYN_Customer`, `DYN_Username` and `DYN_Password` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
## 30. Use pdd.yandex.ru API
```
export PDD_Token="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
```
Follow these instructions to get the token for your domain https://tech.yandex.com/domain/doc/concepts/access-docpage/
```
acme.sh --issue --dns dns_yandex -d mydomain.example.org
```
For issues, please report to https://github.com/non7top/acme.sh/issues.
## 31. Use Hurricane Electric
Hurricane Electric (https://dns.he.net/) doesn't have an API so just set your login credentials like so:
```
export HE_Username="yourusername"
export HE_Password="password"
```
Then you can issue your certificate:
```
acme.sh --issue --dns dns_he -d example.com -d www.example.com
```
The `HE_Username` and `HE_Password` settings will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
Please report any issues to https://github.com/angel333/acme.sh or to <me@ondrejsimek.com>.
## 32. Use UnoEuro API to automatically issue cert
First you need to login to your UnoEuro account to get your API key.
```
export UNO_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"
export UNO_User="UExxxxxx"
```
Ok, let's issue a cert now:
```
acme.sh --issue --dns dns_unoeuro -d example.com -d www.example.com
```
The `UNO_Key` and `UNO_User` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
## 33. Use INWX
[INWX](https://www.inwx.de/) offers an [xmlrpc api](https://www.inwx.de/de/help/apidoc) with your standard login credentials, set them like so:
```
export INWX_User="yourusername"
export INWX_Password="password"
```
Then you can issue your certificates with:
```
acme.sh --issue --dns dns_inwx -d example.com -d www.example.com
```
The `INWX_User` and `INWX_Password` settings will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
## 34. User Servercow API v1
Create a new user from the servercow control center. Don't forget to activate **DNS API** for this user.
```
export SERVERCOW_API_Username=username
export SERVERCOW_API_Password=password
```
Now you cann issue a cert:
```
acme.sh --issue --dns dns_servercow -d example.com -d www.example.com
```
Both, `SERVERCOW_API_Username` and `SERVERCOW_API_Password` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
## 35. Use Namesilo.com API
You'll need to generate an API key at https://www.namesilo.com/account_api.php
Optionally you may restrict the access to an IP range there.
```
export Namesilo_Key="xxxxxxxxxxxxxxxxxxxxxxxx"
```
And now you can issue certs with:
```
acme.sh --issue --dns dns_namesilo --dnssleep 900 -d example.com -d www.example.com
```
## 36. Use autoDNS (InternetX)
[InternetX](https://www.internetx.com/) offers an [xml api](https://help.internetx.com/display/API/AutoDNS+XML-API) with your standard login credentials, set them like so:
```
export AUTODNS_USER="yourusername"
export AUTODNS_PASSWORD="password"
export AUTODNS_CONTEXT="context"
```
Then you can issue your certificates with:
```
acme.sh --issue --dns dns_autodns -d example.com -d www.example.com
```
The `AUTODNS_USER`, `AUTODNS_PASSWORD` and `AUTODNS_CONTEXT` settings will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
## 37. Use Azure DNS
You have to create a service principal first. See:[How to use Azure DNS](../../../wiki/How-to-use-Azure-DNS)
```
export AZUREDNS_SUBSCRIPTIONID="12345678-9abc-def0-1234-567890abcdef"
export AZUREDNS_TENANTID="11111111-2222-3333-4444-555555555555"
export AZUREDNS_APPID="3b5033b5-7a66-43a5-b3b9-a36b9e7c25ed"
export AZUREDNS_CLIENTSECRET="1b0224ef-34d4-5af9-110f-77f527d561bd"
```
Then you can issue your certificates with:
```
acme.sh --issue --dns dns_azure -d example.com -d www.example.com
```
`AZUREDNS_SUBSCRIPTIONID`, `AZUREDNS_TENANTID`,`AZUREDNS_APPID` and `AZUREDNS_CLIENTSECRET` settings will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
## 38. Use selectel.com(selectel.ru) domain API to automatically issue cert
First you need to login to your account to get your API key from: https://my.selectel.ru/profile/apikeys.
```sh
export SL_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"
```
Ok, let's issue a cert now:
```
acme.sh --issue --dns dns_selectel -d example.com -d www.example.com
```
The `SL_Key` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
## 39. Use zonomi.com domain API to automatically issue cert
First you need to login to your account to find your API key from: http://zonomi.com/app/dns/dyndns.jsp
Your will find your api key in the example urls:
```sh
https://zonomi.com/app/dns/dyndns.jsp?host=example.com&api_key=1063364558943540954358668888888888
```
```sh
export ZM_Key="1063364558943540954358668888888888"
```
Ok, let's issue a cert now:
```
acme.sh --issue --dns dns_zonomi -d example.com -d www.example.com
```
The `ZM_Key` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
## 40. Use DreamHost DNS API
DNS API keys may be created at https://panel.dreamhost.com/?tree=home.api.
Ensure the created key has add and remove privelages.
```
export DH_API_Key="<api key>"
acme.sh --issue --dns dns_dreamhost -d example.com -d www.example.com
```
The 'DH_API_KEY' will be saved in `~/.acme.sh/account.conf` and will
be reused when needed.
## 41. Use DirectAdmin API
The DirectAdmin interface has it's own Let's encrypt functionality, but this
script can be used to generate certificates for names which are not hosted on
DirectAdmin
User must provide login data and URL to the DirectAdmin incl. port.
You can create an user which only has access to
- CMD_API_DNS_CONTROL
- CMD_API_SHOW_DOMAINS
By using the Login Keys function.
See also https://www.directadmin.com/api.php and https://www.directadmin.com/features.php?id=1298
```
export DA_Api="https://remoteUser:remotePassword@da.domain.tld:8443"
export DA_Api_Insecure=1
```
Set `DA_Api_Insecure` to 1 for insecure and 0 for secure -> difference is whether ssl cert is checked for validity (0) or whether it is just accepted (1)
Ok, let's issue a cert now:
```
acme.sh --issue --dns dns_da -d example.com -d www.example.com
```
The `DA_Api` and `DA_Api_Insecure` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
# Use custom API
If your API is not supported yet, you can write your own DNS API.
@@ -521,6 +801,7 @@ acme.sh --issue --dns dns_myapi -d example.com -d www.example.com
For more details, please check our sample script: [dns_myapi.sh](dns_myapi.sh)
See: https://github.com/Neilpang/acme.sh/wiki/DNS-API-Dev-Guide
# Use lexicon DNS API

View File

@@ -10,6 +10,8 @@ dns_ali_add() {
fulldomain=$1
txtvalue=$2
Ali_Key="${Ali_Key:-$(_readaccountconf_mutable Ali_Key)}"
Ali_Secret="${Ali_Secret:-$(_readaccountconf_mutable Ali_Secret)}"
if [ -z "$Ali_Key" ] || [ -z "$Ali_Secret" ]; then
Ali_Key=""
Ali_Secret=""
@@ -18,8 +20,8 @@ dns_ali_add() {
fi
#save the api key and secret to the account conf file.
_saveaccountconf Ali_Key "$Ali_Key"
_saveaccountconf Ali_Secret "$Ali_Secret"
_saveaccountconf_mutable Ali_Key "$Ali_Key"
_saveaccountconf_mutable Ali_Secret "$Ali_Secret"
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
@@ -32,6 +34,15 @@ dns_ali_add() {
dns_ali_rm() {
fulldomain=$1
txtvalue=$2
Ali_Key="${Ali_Key:-$(_readaccountconf_mutable Ali_Key)}"
Ali_Secret="${Ali_Secret:-$(_readaccountconf_mutable Ali_Secret)}"
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
return 1
fi
_clean
}
@@ -76,16 +87,14 @@ _ali_rest() {
return 1
fi
_debug2 response "$response"
if [ -z "$2" ]; then
message="$(printf "%s" "$response" | _egrep_o "\"Message\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \")"
if [ -n "$message" ]; then
message="$(echo "$response" | _egrep_o "\"Message\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \")"
if [ "$message" ]; then
_err "$message"
return 1
fi
fi
_debug2 response "$response"
return 0
}
_ali_urlencode() {
@@ -112,12 +121,14 @@ _ali_nonce() {
}
_check_exist_query() {
_qdomain="$1"
_qsubdomain="$2"
query=''
query=$query'AccessKeyId='$Ali_Key
query=$query'&Action=DescribeDomainRecords'
query=$query'&DomainName='$1
query=$query'&DomainName='$_qdomain
query=$query'&Format=json'
query=$query'&RRKeyWord=_acme-challenge'
query=$query'&RRKeyWord='$_qsubdomain
query=$query'&SignatureMethod=HMAC-SHA1'
query=$query"&SignatureNonce=$(_ali_nonce)"
query=$query'&SignatureVersion=1.0'
@@ -169,17 +180,21 @@ _describe_records_query() {
}
_clean() {
_check_exist_query "$_domain"
_check_exist_query "$_domain" "$_sub_domain"
if ! _ali_rest "Check exist records" "ignore"; then
return 1
fi
records="$(echo "$response" -n | _egrep_o "\"RecordId\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \")"
printf "%s" "$records" \
| while read -r record_id; do
_delete_record_query "$record_id"
_ali_rest "Delete record $record_id" "ignore"
done
record_id="$(echo "$response" | tr '{' "\n" | grep "$_sub_domain" | grep "$txtvalue" | tr "," "\n" | grep RecordId | cut -d '"' -f 4)"
_debug2 record_id "$record_id"
if [ -z "$record_id" ]; then
_debug "record not found, skip"
else
_delete_record_query "$record_id"
_ali_rest "Delete record $record_id" "ignore"
fi
}
_timestamp() {

264
dnsapi/dns_autodns.sh Normal file
View File

@@ -0,0 +1,264 @@
#!/usr/bin/env sh
# -*- mode: sh; tab-width: 2; indent-tabs-mode: s; coding: utf-8 -*-
# This is the InternetX autoDNS xml api wrapper for acme.sh
# Author: auerswald@gmail.com
# Created: 2018-01-14
#
# export AUTODNS_USER="username"
# export AUTODNS_PASSWORD="password"
# export AUTODNS_CONTEXT="context"
#
# Usage:
# acme.sh --issue --dns dns_autodns -d example.com
AUTODNS_API="https://gateway.autodns.com"
# Arguments:
# txtdomain
# txt
dns_autodns_add() {
fulldomain="$1"
txtvalue="$2"
AUTODNS_USER="${AUTODNS_USER:-$(_readaccountconf_mutable AUTODNS_USER)}"
AUTODNS_PASSWORD="${AUTODNS_PASSWORD:-$(_readaccountconf_mutable AUTODNS_PASSWORD)}"
AUTODNS_CONTEXT="${AUTODNS_CONTEXT:-$(_readaccountconf_mutable AUTODNS_CONTEXT)}"
if [ -z "$AUTODNS_USER" ] || [ -z "$AUTODNS_CONTEXT" ] || [ -z "$AUTODNS_PASSWORD" ]; then
_err "You don't specify autodns user, password and context."
return 1
fi
_saveaccountconf_mutable AUTODNS_USER "$AUTODNS_USER"
_saveaccountconf_mutable AUTODNS_PASSWORD "$AUTODNS_PASSWORD"
_saveaccountconf_mutable AUTODNS_CONTEXT "$AUTODNS_CONTEXT"
_debug "First detect the root zone"
if ! _get_autodns_zone "$fulldomain"; then
_err "invalid domain"
return 1
fi
_debug _sub_domain "$_sub_domain"
_debug _zone "$_zone"
_debug _system_ns "$_system_ns"
_info "Adding TXT record"
autodns_response="$(_autodns_zone_update "$_zone" "$_sub_domain" "$txtvalue" "$_system_ns")"
if [ "$?" -eq "0" ]; then
_info "Added, OK"
return 0
fi
return 1
}
# Arguments:
# txtdomain
# txt
dns_autodns_rm() {
fulldomain="$1"
txtvalue="$2"
AUTODNS_USER="${AUTODNS_USER:-$(_readaccountconf_mutable AUTODNS_USER)}"
AUTODNS_PASSWORD="${AUTODNS_PASSWORD:-$(_readaccountconf_mutable AUTODNS_PASSWORD)}"
AUTODNS_CONTEXT="${AUTODNS_CONTEXT:-$(_readaccountconf_mutable AUTODNS_CONTEXT)}"
if [ -z "$AUTODNS_USER" ] || [ -z "$AUTODNS_CONTEXT" ] || [ -z "$AUTODNS_PASSWORD" ]; then
_err "You don't specify autodns user, password and context."
return 1
fi
_debug "First detect the root zone"
if ! _get_autodns_zone "$fulldomain"; then
_err "zone not found"
return 1
fi
_debug _sub_domain "$_sub_domain"
_debug _zone "$_zone"
_debug _system_ns "$_system_ns"
_info "Delete TXT record"
autodns_response="$(_autodns_zone_cleanup "$_zone" "$_sub_domain" "$txtvalue" "$_system_ns")"
if [ "$?" -eq "0" ]; then
_info "Deleted, OK"
return 0
fi
return 1
}
#################### Private functions below ##################################
# Arguments:
# fulldomain
# Returns:
# _sub_domain=_acme-challenge.www
# _zone=domain.com
# _system_ns
_get_autodns_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
autodns_response="$(_autodns_zone_inquire "$h")"
if [ "$?" -ne "0" ]; then
_err "invalid domain"
return 1
fi
if _contains "$autodns_response" "<summary>1</summary>" >/dev/null; then
_zone="$(echo "$autodns_response" | _egrep_o '<name>[^<]*</name>' | cut -d '>' -f 2 | cut -d '<' -f 1)"
_system_ns="$(echo "$autodns_response" | _egrep_o '<system_ns>[^<]*</system_ns>' | cut -d '>' -f 2 | cut -d '<' -f 1)"
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
return 0
fi
p=$i
i=$(_math "$i" + 1)
done
return 1
}
_build_request_auth_xml() {
printf "<auth>
<user>%s</user>
<password>%s</password>
<context>%s</context>
</auth>" "$AUTODNS_USER" "$AUTODNS_PASSWORD" "$AUTODNS_CONTEXT"
}
# Arguments:
# zone
_build_zone_inquire_xml() {
printf "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<request>
%s
<task>
<code>0205</code>
<view>
<children>1</children>
<limit>1</limit>
</view>
<where>
<key>name</key>
<operator>eq</operator>
<value>%s</value>
</where>
</task>
</request>" "$(_build_request_auth_xml)" "$1"
}
# Arguments:
# zone
# subdomain
# txtvalue
# system_ns
_build_zone_update_xml() {
printf "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<request>
%s
<task>
<code>0202001</code>
<default>
<rr_add>
<name>%s</name>
<ttl>600</ttl>
<type>TXT</type>
<value>%s</value>
</rr_add>
</default>
<zone>
<name>%s</name>
<system_ns>%s</system_ns>
</zone>
</task>
</request>" "$(_build_request_auth_xml)" "$2" "$3" "$1" "$4"
}
# Arguments:
# zone
_autodns_zone_inquire() {
request_data="$(_build_zone_inquire_xml "$1")"
autodns_response="$(_autodns_api_call "$request_data")"
ret="$?"
printf "%s" "$autodns_response"
return "$ret"
}
# Arguments:
# zone
# subdomain
# txtvalue
# system_ns
_autodns_zone_update() {
request_data="$(_build_zone_update_xml "$1" "$2" "$3" "$4")"
autodns_response="$(_autodns_api_call "$request_data")"
ret="$?"
printf "%s" "$autodns_response"
return "$ret"
}
# Arguments:
# zone
# subdomain
# txtvalue
# system_ns
_autodns_zone_cleanup() {
request_data="$(_build_zone_update_xml "$1" "$2" "$3" "$4")"
# replace 'rr_add>' with 'rr_rem>' in request_data
request_data="$(printf -- "%s" "$request_data" | sed 's/rr_add>/rr_rem>/g')"
autodns_response="$(_autodns_api_call "$request_data")"
ret="$?"
printf "%s" "$autodns_response"
return "$ret"
}
# Arguments:
# request_data
_autodns_api_call() {
request_data="$1"
_debug request_data "$request_data"
autodns_response="$(_post "$request_data" "$AUTODNS_API")"
ret="$?"
_debug autodns_response "$autodns_response"
if [ "$ret" -ne "0" ]; then
_err "error"
return 1
fi
if _contains "$autodns_response" "<type>success</type>" >/dev/null; then
_info "success"
printf "%s" "$autodns_response"
return 0
fi
return 1
}

View File

@@ -19,17 +19,25 @@ dns_aws_add() {
fulldomain=$1
txtvalue=$2
AWS_ACCESS_KEY_ID="${AWS_ACCESS_KEY_ID:-$(_readaccountconf_mutable AWS_ACCESS_KEY_ID)}"
AWS_SECRET_ACCESS_KEY="${AWS_SECRET_ACCESS_KEY:-$(_readaccountconf_mutable AWS_SECRET_ACCESS_KEY)}"
if [ -z "$AWS_ACCESS_KEY_ID" ] || [ -z "$AWS_SECRET_ACCESS_KEY" ]; then
_use_container_role || _use_instance_role
fi
if [ -z "$AWS_ACCESS_KEY_ID" ] || [ -z "$AWS_SECRET_ACCESS_KEY" ]; then
AWS_ACCESS_KEY_ID=""
AWS_SECRET_ACCESS_KEY=""
_err "You don't specify aws route53 api key id and and api key secret yet."
_err "Please create you key and try again. see $(__green $AWS_WIKI)"
_err "Please create your key and try again. see $(__green $AWS_WIKI)"
return 1
fi
if [ -z "$AWS_SESSION_TOKEN" ]; then
_saveaccountconf AWS_ACCESS_KEY_ID "$AWS_ACCESS_KEY_ID"
_saveaccountconf AWS_SECRET_ACCESS_KEY "$AWS_SECRET_ACCESS_KEY"
#save for future use, unless using a role which will be fetched as needed
if [ -z "$_using_role" ]; then
_saveaccountconf_mutable AWS_ACCESS_KEY_ID "$AWS_ACCESS_KEY_ID"
_saveaccountconf_mutable AWS_SECRET_ACCESS_KEY "$AWS_SECRET_ACCESS_KEY"
fi
_debug "First detect the root zone"
@@ -41,7 +49,26 @@ dns_aws_add() {
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
_aws_tmpl_xml="<ChangeResourceRecordSetsRequest xmlns=\"https://route53.amazonaws.com/doc/2013-04-01/\"><ChangeBatch><Changes><Change><Action>UPSERT</Action><ResourceRecordSet><Name>$fulldomain</Name><Type>TXT</Type><TTL>300</TTL><ResourceRecords><ResourceRecord><Value>\"$txtvalue\"</Value></ResourceRecord></ResourceRecords></ResourceRecordSet></Change></Changes></ChangeBatch></ChangeResourceRecordSetsRequest>"
_info "Geting existing records for $fulldomain"
if ! aws_rest GET "2013-04-01$_domain_id/rrset" "name=$fulldomain&type=TXT"; then
return 1
fi
if _contains "$response" "<Name>$fulldomain.</Name>"; then
_resource_record="$(echo "$response" | sed 's/<ResourceRecordSet>/"/g' | tr '"' "\n" | grep "<Name>$fulldomain.</Name>" | _egrep_o "<ResourceRecords.*</ResourceRecords>" | sed "s/<ResourceRecords>//" | sed "s#</ResourceRecords>##")"
_debug "_resource_record" "$_resource_record"
else
_debug "single new add"
fi
if [ "$_resource_record" ] && _contains "$response" "$txtvalue"; then
_info "The txt record already exists, skip"
return 0
fi
_debug "Adding records"
_aws_tmpl_xml="<ChangeResourceRecordSetsRequest xmlns=\"https://route53.amazonaws.com/doc/2013-04-01/\"><ChangeBatch><Changes><Change><Action>UPSERT</Action><ResourceRecordSet><Name>$fulldomain</Name><Type>TXT</Type><TTL>300</TTL><ResourceRecords>$_resource_record<ResourceRecord><Value>\"$txtvalue\"</Value></ResourceRecord></ResourceRecords></ResourceRecordSet></Change></Changes></ChangeBatch></ChangeResourceRecordSetsRequest>"
if aws_rest POST "2013-04-01$_domain_id/rrset/" "" "$_aws_tmpl_xml" && _contains "$response" "ChangeResourceRecordSetsResponse"; then
_info "txt record updated success."
@@ -56,6 +83,13 @@ dns_aws_rm() {
fulldomain=$1
txtvalue=$2
AWS_ACCESS_KEY_ID="${AWS_ACCESS_KEY_ID:-$(_readaccountconf_mutable AWS_ACCESS_KEY_ID)}"
AWS_SECRET_ACCESS_KEY="${AWS_SECRET_ACCESS_KEY:-$(_readaccountconf_mutable AWS_SECRET_ACCESS_KEY)}"
if [ -z "$AWS_ACCESS_KEY_ID" ] || [ -z "$AWS_SECRET_ACCESS_KEY" ]; then
_use_container_role || _use_instance_role
fi
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"
@@ -65,7 +99,20 @@ dns_aws_rm() {
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
_aws_tmpl_xml="<ChangeResourceRecordSetsRequest xmlns=\"https://route53.amazonaws.com/doc/2013-04-01/\"><ChangeBatch><Changes><Change><Action>DELETE</Action><ResourceRecordSet><ResourceRecords><ResourceRecord><Value>\"$txtvalue\"</Value></ResourceRecord></ResourceRecords><Name>$fulldomain.</Name><Type>TXT</Type><TTL>300</TTL></ResourceRecordSet></Change></Changes></ChangeBatch></ChangeResourceRecordSetsRequest>"
_info "Geting existing records for $fulldomain"
if ! aws_rest GET "2013-04-01$_domain_id/rrset" "name=$fulldomain&type=TXT"; then
return 1
fi
if _contains "$response" "<Name>$fulldomain.</Name>"; then
_resource_record="$(echo "$response" | sed 's/<ResourceRecordSet>/"/g' | tr '"' "\n" | grep "<Name>$fulldomain.</Name>" | _egrep_o "<ResourceRecords.*</ResourceRecords>" | sed "s/<ResourceRecords>//" | sed "s#</ResourceRecords>##")"
_debug "_resource_record" "$_resource_record"
else
_debug "no records exists, skip"
return 0
fi
_aws_tmpl_xml="<ChangeResourceRecordSetsRequest xmlns=\"https://route53.amazonaws.com/doc/2013-04-01/\"><ChangeBatch><Changes><Change><Action>DELETE</Action><ResourceRecordSet><ResourceRecords>$_resource_record</ResourceRecords><Name>$fulldomain.</Name><Type>TXT</Type><TTL>300</TTL></ResourceRecordSet></Change></Changes></ChangeBatch></ChangeResourceRecordSetsRequest>"
if aws_rest POST "2013-04-01$_domain_id/rrset/" "" "$_aws_tmpl_xml" && _contains "$response" "ChangeResourceRecordSetsResponse"; then
_info "txt record deleted success."
@@ -84,9 +131,9 @@ _get_root() {
p=1
if aws_rest GET "2013-04-01/hostedzone"; then
_debug "response" "$response"
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
_debug2 "Checking domain: $h"
if [ -z "$h" ]; then
if _contains "$response" "<IsTruncated>true</IsTruncated>" && _contains "$response" "<NextMarker>"; then
_debug "IsTruncated"
@@ -102,23 +149,23 @@ _get_root() {
fi
fi
#not valid
_err "Invalid domain"
return 1
fi
if _contains "$response" "<Name>$h.</Name>"; then
hostedzone="$(echo "$response" | sed 's/<HostedZone>/#&/g' | tr '#' '\n' | _egrep_o "<HostedZone><Id>[^<]*<.Id><Name>$h.<.Name>.*<PrivateZone>false<.PrivateZone>.*<.HostedZone>")"
_debug hostedzone "$hostedzone"
if [ -z "$hostedzone" ]; then
_err "Error, can not get hostedzone."
if [ "$hostedzone" ]; then
_domain_id=$(printf "%s\n" "$hostedzone" | _egrep_o "<Id>.*<.Id>" | head -n 1 | _egrep_o ">.*<" | tr -d "<>")
if [ "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_domain=$h
return 0
fi
_err "Can not find domain id: $h"
return 1
fi
_domain_id=$(printf "%s\n" "$hostedzone" | _egrep_o "<Id>.*<.Id>" | head -n 1 | _egrep_o ">.*<" | tr -d "<>")
if [ "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_domain=$h
return 0
fi
return 1
fi
p=$i
i=$(_math "$i" + 1)
@@ -127,6 +174,55 @@ _get_root() {
return 1
}
_use_container_role() {
# automatically set if running inside ECS
if [ -z "$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI" ]; then
_debug "No ECS environment variable detected"
return 1
fi
_use_metadata "169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"
}
_use_instance_role() {
_url="http://169.254.169.254/latest/meta-data/iam/security-credentials/"
_debug "_url" "$_url"
if ! _get "$_url" true 1 | _head_n 1 | grep -Fq 200; then
_debug "Unable to fetch IAM role from instance metadata"
return 1
fi
_aws_role=$(_get "$_url" "" 1)
_debug "_aws_role" "$_aws_role"
_use_metadata "$_url$_aws_role"
}
_use_metadata() {
_aws_creds="$(
_get "$1" "" 1 \
| _normalizeJson \
| tr '{,}' '\n' \
| while read -r _line; do
_key="$(echo "${_line%%:*}" | tr -d '"')"
_value="${_line#*:}"
_debug3 "_key" "$_key"
_secure_debug3 "_value" "$_value"
case "$_key" in
AccessKeyId) echo "AWS_ACCESS_KEY_ID=$_value" ;;
SecretAccessKey) echo "AWS_SECRET_ACCESS_KEY=$_value" ;;
Token) echo "AWS_SESSION_TOKEN=$_value" ;;
esac
done \
| paste -sd' ' -
)"
_secure_debug "_aws_creds" "$_aws_creds"
if [ -z "$_aws_creds" ]; then
return 1
fi
eval "$_aws_creds"
_using_role=true
}
#method uri qstr data
aws_rest() {
mtd="$1"
@@ -208,7 +304,7 @@ aws_rest() {
kServiceH="$(printf "$Service%s" | _hmac "$Hash" "$kRegionH" hex)"
_debug2 kServiceH "$kServiceH"
kSigningH="$(printf "aws4_request%s" | _hmac "$Hash" "$kServiceH" hex)"
kSigningH="$(printf "%s" "aws4_request" | _hmac "$Hash" "$kServiceH" hex)"
_debug2 kSigningH "$kSigningH"
signature="$(printf "$StringToSign%s" | _hmac "$Hash" "$kSigningH" hex)"
@@ -232,6 +328,7 @@ aws_rest() {
fi
_ret="$?"
_debug2 response "$response"
if [ "$_ret" = "0" ]; then
if _contains "$response" "<ErrorResponse"; then
_err "Response error:$response"

339
dnsapi/dns_azure.sh Normal file
View File

@@ -0,0 +1,339 @@
#!/usr/bin/env sh
WIKI="https://github.com/Neilpang/acme.sh/wiki/How-to-use-Azure-DNS"
######## Public functions #####################
# Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
# Used to add txt record
#
# Ref: https://docs.microsoft.com/en-us/rest/api/dns/recordsets/createorupdate
#
dns_azure_add() {
fulldomain=$1
txtvalue=$2
AZUREDNS_SUBSCRIPTIONID="${AZUREDNS_SUBSCRIPTIONID:-$(_readaccountconf_mutable AZUREDNS_SUBSCRIPTIONID)}"
AZUREDNS_TENANTID="${AZUREDNS_TENANTID:-$(_readaccountconf_mutable AZUREDNS_TENANTID)}"
AZUREDNS_APPID="${AZUREDNS_APPID:-$(_readaccountconf_mutable AZUREDNS_APPID)}"
AZUREDNS_CLIENTSECRET="${AZUREDNS_CLIENTSECRET:-$(_readaccountconf_mutable AZUREDNS_CLIENTSECRET)}"
if [ -z "$AZUREDNS_SUBSCRIPTIONID" ]; then
AZUREDNS_SUBSCRIPTIONID=""
AZUREDNS_TENANTID=""
AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET=""
_err "You didn't specify the Azure Subscription ID "
return 1
fi
if [ -z "$AZUREDNS_TENANTID" ]; then
AZUREDNS_SUBSCRIPTIONID=""
AZUREDNS_TENANTID=""
AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET=""
_err "You didn't specify the Azure Tenant ID "
return 1
fi
if [ -z "$AZUREDNS_APPID" ]; then
AZUREDNS_SUBSCRIPTIONID=""
AZUREDNS_TENANTID=""
AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET=""
_err "You didn't specify the Azure App ID"
return 1
fi
if [ -z "$AZUREDNS_CLIENTSECRET" ]; then
AZUREDNS_SUBSCRIPTIONID=""
AZUREDNS_TENANTID=""
AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET=""
_err "You didn't specify the Azure Client Secret"
return 1
fi
#save account details to account conf file.
_saveaccountconf_mutable AZUREDNS_SUBSCRIPTIONID "$AZUREDNS_SUBSCRIPTIONID"
_saveaccountconf_mutable AZUREDNS_TENANTID "$AZUREDNS_TENANTID"
_saveaccountconf_mutable AZUREDNS_APPID "$AZUREDNS_APPID"
_saveaccountconf_mutable AZUREDNS_CLIENTSECRET "$AZUREDNS_CLIENTSECRET"
accesstoken=$(_azure_getaccess_token "$AZUREDNS_TENANTID" "$AZUREDNS_APPID" "$AZUREDNS_CLIENTSECRET")
if ! _get_root "$fulldomain" "$AZUREDNS_SUBSCRIPTIONID" "$accesstoken"; then
_err "invalid domain"
return 1
fi
_debug _domain_id "$_domain_id"
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
acmeRecordURI="https://management.azure.com$(printf '%s' "$_domain_id" | sed 's/\\//g')/TXT/$_sub_domain?api-version=2017-09-01"
_debug "$acmeRecordURI"
# Get existing TXT record
_azure_rest GET "$acmeRecordURI" "" "$accesstoken"
values="{\"value\":[\"$txtvalue\"]}"
timestamp="$(_time)"
if [ "$_code" = "200" ]; then
vlist="$(echo "$response" | _egrep_o "\"value\"\s*:\s*\[\s*\"[^\"]*\"\s*]" | cut -d : -f 2 | tr -d "[]\"")"
_debug "existing TXT found"
_debug "$vlist"
existingts="$(echo "$response" | _egrep_o "\"acmetscheck\"\s*:\s*\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d "\"")"
if [ -z "$existingts" ]; then
# the record was not created by acme.sh. Copy the exisiting entires
existingts=$timestamp
fi
_diff="$(_math "$timestamp - $existingts")"
_debug "existing txt age: $_diff"
# only use recently added records and discard if older than 2 hours because they are probably orphaned
if [ "$_diff" -lt 7200 ]; then
_debug "existing txt value: $vlist"
for v in $vlist; do
values="$values ,{\"value\":[\"$v\"]}"
done
fi
fi
# Add the txtvalue TXT Record
body="{\"properties\":{\"metadata\":{\"acmetscheck\":\"$timestamp\"},\"TTL\":10, \"TXTRecords\":[$values]}}"
_azure_rest PUT "$acmeRecordURI" "$body" "$accesstoken"
if [ "$_code" = "200" ] || [ "$_code" = '201' ]; then
_info "validation value added"
else
_err "error adding validation value ($_code)"
return 1
fi
}
# Usage: fulldomain txtvalue
# Used to remove the txt record after validation
#
# Ref: https://docs.microsoft.com/en-us/rest/api/dns/recordsets/delete
#
dns_azure_rm() {
fulldomain=$1
txtvalue=$2
AZUREDNS_SUBSCRIPTIONID="${AZUREDNS_SUBSCRIPTIONID:-$(_readaccountconf_mutable AZUREDNS_SUBSCRIPTIONID)}"
AZUREDNS_TENANTID="${AZUREDNS_TENANTID:-$(_readaccountconf_mutable AZUREDNS_TENANTID)}"
AZUREDNS_APPID="${AZUREDNS_APPID:-$(_readaccountconf_mutable AZUREDNS_APPID)}"
AZUREDNS_CLIENTSECRET="${AZUREDNS_CLIENTSECRET:-$(_readaccountconf_mutable AZUREDNS_CLIENTSECRET)}"
if [ -z "$AZUREDNS_SUBSCRIPTIONID" ]; then
AZUREDNS_SUBSCRIPTIONID=""
AZUREDNS_TENANTID=""
AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET=""
_err "You didn't specify the Azure Subscription ID "
return 1
fi
if [ -z "$AZUREDNS_TENANTID" ]; then
AZUREDNS_SUBSCRIPTIONID=""
AZUREDNS_TENANTID=""
AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET=""
_err "You didn't specify the Azure Tenant ID "
return 1
fi
if [ -z "$AZUREDNS_APPID" ]; then
AZUREDNS_SUBSCRIPTIONID=""
AZUREDNS_TENANTID=""
AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET=""
_err "You didn't specify the Azure App ID"
return 1
fi
if [ -z "$AZUREDNS_CLIENTSECRET" ]; then
AZUREDNS_SUBSCRIPTIONID=""
AZUREDNS_TENANTID=""
AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET=""
_err "You didn't specify the Azure Client Secret"
return 1
fi
accesstoken=$(_azure_getaccess_token "$AZUREDNS_TENANTID" "$AZUREDNS_APPID" "$AZUREDNS_CLIENTSECRET")
if ! _get_root "$fulldomain" "$AZUREDNS_SUBSCRIPTIONID" "$accesstoken"; then
_err "invalid domain"
return 1
fi
_debug _domain_id "$_domain_id"
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
acmeRecordURI="https://management.azure.com$(printf '%s' "$_domain_id" | sed 's/\\//g')/TXT/$_sub_domain?api-version=2017-09-01"
_debug "$acmeRecordURI"
# Get existing TXT record
_azure_rest GET "$acmeRecordURI" "" "$accesstoken"
timestamp="$(_time)"
if [ "$_code" = "200" ]; then
vlist="$(echo "$response" | _egrep_o "\"value\"\s*:\s*\[\s*\"[^\"]*\"\s*]" | cut -d : -f 2 | tr -d "[]\"" | grep -v "$txtvalue")"
values=""
comma=""
for v in $vlist; do
values="$values$comma{\"value\":[\"$v\"]}"
comma=","
done
if [ -z "$values" ]; then
# No values left remove record
_debug "removing validation record completely $acmeRecordURI"
_azure_rest DELETE "$acmeRecordURI" "" "$accesstoken"
if [ "$_code" = "200" ] || [ "$_code" = '204' ]; then
_info "validation record removed"
else
_err "error removing validation record ($_code)"
return 1
fi
else
# Remove only txtvalue from the TXT Record
body="{\"properties\":{\"metadata\":{\"acmetscheck\":\"$timestamp\"},\"TTL\":10, \"TXTRecords\":[$values]}}"
_azure_rest PUT "$acmeRecordURI" "$body" "$accesstoken"
if [ "$_code" = "200" ] || [ "$_code" = '201' ]; then
_info "validation value removed"
else
_err "error removing validation value ($_code)"
return 1
fi
fi
fi
}
################### Private functions below ##################################
_azure_rest() {
m=$1
ep="$2"
data="$3"
accesstoken="$4"
MAX_REQUEST_RETRY_TIMES=5
_request_retry_times=0
while [ "${_request_retry_times}" -lt "$MAX_REQUEST_RETRY_TIMES" ]; do
_debug3 _request_retry_times "$_request_retry_times"
export _H1="authorization: Bearer $accesstoken"
export _H2="accept: application/json"
export _H3="Content-Type: application/json"
# clear headers from previous request to avoid getting wrong http code on timeouts
:>"$HTTP_HEADER"
_debug "$ep"
if [ "$m" != "GET" ]; then
_secure_debug2 "data $data"
response="$(_post "$data" "$ep" "" "$m")"
else
response="$(_get "$ep")"
fi
_secure_debug2 "response $response"
_code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\r\n")"
_debug "http response code $_code"
if [ "$_code" = "401" ]; then
# we have an invalid access token set to expired
_saveaccountconf_mutable AZUREDNS_TOKENVALIDTO "0"
_err "access denied make sure your Azure settings are correct. See $WIKI"
return 1
fi
# See https://docs.microsoft.com/en-us/azure/architecture/best-practices/retry-service-specific#general-rest-and-retry-guidelines for retryable HTTP codes
if [ "$?" != "0" ] || [ -z "$_code" ] || [ "$_code" = "408" ] || [ "$_code" = "500" ] || [ "$_code" = "503" ] || [ "$_code" = "504" ]; then
_request_retry_times="$(_math "$_request_retry_times" + 1)"
_info "REST call error $_code retrying $ep in $_request_retry_times s"
_sleep "$_request_retry_times"
continue
fi
break
done
if [ "$_request_retry_times" = "$MAX_REQUEST_RETRY_TIMES" ]; then
_err "Error Azure REST called was retried $MAX_REQUEST_RETRY_TIMES times."
_err "Calling $ep failed."
return 1
fi
response="$(echo "$response" | _normalizeJson)"
return 0
}
## Ref: https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-protocols-oauth-service-to-service#request-an-access-token
_azure_getaccess_token() {
tenantID=$1
clientID=$2
clientSecret=$3
accesstoken="${AZUREDNS_BEARERTOKEN:-$(_readaccountconf_mutable AZUREDNS_BEARERTOKEN)}"
expires_on="${AZUREDNS_TOKENVALIDTO:-$(_readaccountconf_mutable AZUREDNS_TOKENVALIDTO)}"
# can we reuse the bearer token?
if [ -n "$accesstoken" ] && [ -n "$expires_on" ]; then
if [ "$(_time)" -lt "$expires_on" ]; then
# brearer token is still valid - reuse it
_debug "reusing bearer token"
printf "%s" "$accesstoken"
return 0
else
_debug "bearer token expired"
fi
fi
_debug "getting new bearer token"
export _H1="accept: application/json"
export _H2="Content-Type: application/x-www-form-urlencoded"
body="resource=$(printf "%s" 'https://management.core.windows.net/' | _url_encode)&client_id=$(printf "%s" "$clientID" | _url_encode)&client_secret=$(printf "%s" "$clientSecret" | _url_encode)&grant_type=client_credentials"
_secure_debug2 "data $body"
response="$(_post "$body" "https://login.microsoftonline.com/$tenantID/oauth2/token" "" "POST")"
_secure_debug2 "response $response"
response="$(echo "$response" | _normalizeJson)"
accesstoken=$(echo "$response" | _egrep_o "\"access_token\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \")
expires_on=$(echo "$response" | _egrep_o "\"expires_on\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \")
if [ -z "$accesstoken" ]; then
_err "no acccess token received. Check your Azure settings see $WIKI"
return 1
fi
if [ "$?" != "0" ]; then
_err "error $response"
return 1
fi
_saveaccountconf_mutable AZUREDNS_BEARERTOKEN "$accesstoken"
_saveaccountconf_mutable AZUREDNS_TOKENVALIDTO "$expires_on"
printf "%s" "$accesstoken"
return 0
}
_get_root() {
domain=$1
subscriptionId=$2
accesstoken=$3
i=2
p=1
## Ref: https://docs.microsoft.com/en-us/rest/api/dns/zones/list
## returns up to 100 zones in one response therefore handling more results is not not implemented
## (ZoneListResult with continuation token for the next page of results)
## Per https://docs.microsoft.com/en-us/azure/azure-subscription-service-limits#dns-limits you are limited to 100 Zone/subscriptions anyways
##
_azure_rest GET "https://management.azure.com/subscriptions/$subscriptionId/providers/Microsoft.Network/dnszones?api-version=2017-09-01" "" "$accesstoken"
# Find matching domain name is Json response
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
_debug2 "Checking domain: $h"
if [ -z "$h" ]; then
#not valid
_err "Invalid domain"
return 1
fi
if _contains "$response" "\"name\":\"$h\"" >/dev/null; then
_domain_id=$(echo "$response" | _egrep_o "\{\"id\":\"[^\"]*$h\"" | head -n 1 | cut -d : -f 2 | tr -d \")
if [ "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_domain=$h
return 0
fi
return 1
fi
p=$i
i=$(_math "$i" + 1)
done
return 1
}

View File

@@ -51,33 +51,36 @@ dns_cf_add() {
return 1
fi
count=$(printf "%s\n" "$response" | _egrep_o "\"count\":[^,]*" | cut -d : -f 2)
_debug count "$count"
if [ "$count" = "0" ]; then
_info "Adding record"
if _cf_rest POST "zones/$_domain_id/dns_records" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":120}"; then
if printf -- "%s" "$response" | grep "$fulldomain" >/dev/null; then
_info "Added, OK"
return 0
else
_err "Add txt record error."
return 1
fi
fi
_err "Add txt record error."
else
_info "Updating record"
record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | head -n 1)
_debug "record_id" "$record_id"
_cf_rest PUT "zones/$_domain_id/dns_records/$record_id" "{\"id\":\"$record_id\",\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"zone_id\":\"$_domain_id\",\"zone_name\":\"$_domain\"}"
if [ "$?" = "0" ]; then
_info "Updated, OK"
# For wildcard cert, the main root domain and the wildcard domain have the same txt subdomain name, so
# we can not use updating anymore.
# count=$(printf "%s\n" "$response" | _egrep_o "\"count\":[^,]*" | cut -d : -f 2)
# _debug count "$count"
# if [ "$count" = "0" ]; then
_info "Adding record"
if _cf_rest POST "zones/$_domain_id/dns_records" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":120}"; then
if printf -- "%s" "$response" | grep "$fulldomain" >/dev/null; then
_info "Added, OK"
return 0
else
_err "Add txt record error."
return 1
fi
_err "Update error"
return 1
fi
_err "Add txt record error."
return 1
# else
# _info "Updating record"
# record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | head -n 1)
# _debug "record_id" "$record_id"
#
# _cf_rest PUT "zones/$_domain_id/dns_records/$record_id" "{\"id\":\"$record_id\",\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"zone_id\":\"$_domain_id\",\"zone_name\":\"$_domain\"}"
# if [ "$?" = "0" ]; then
# _info "Updated, OK"
# return 0
# fi
# _err "Update error"
# return 1
# fi
}

View File

@@ -4,6 +4,7 @@
# Repository: https://github.com/ClouDNS/acme.sh/
#CLOUDNS_AUTH_ID=XXXXX
#CLOUDNS_SUB_AUTH_ID=XXXXX
#CLOUDNS_AUTH_PASSWORD="YYYYYYYYY"
CLOUDNS_API="https://api.cloudns.net"
@@ -25,30 +26,18 @@ dns_cloudns_add() {
host="$(echo "$1" | sed "s/\.$zone\$//")"
record=$2
record_id=$(_dns_cloudns_get_record_id "$zone" "$host")
_debug zone "$zone"
_debug host "$host"
_debug record "$record"
_debug record_id "$record_id"
if [ -z "$record_id" ]; then
_info "Adding the TXT record for $1"
_dns_cloudns_http_api_call "dns/add-record.json" "domain-name=$zone&record-type=TXT&host=$host&record=$record&ttl=60"
if ! _contains "$response" "\"status\":\"Success\""; then
_err "Record cannot be added."
return 1
fi
_info "Added."
else
_info "Updating the TXT record for $1"
_dns_cloudns_http_api_call "dns/mod-record.json" "domain-name=$zone&record-id=$record_id&record-type=TXT&host=$host&record=$record&ttl=60"
if ! _contains "$response" "\"status\":\"Success\""; then
_err "The TXT record for $1 cannot be updated."
return 1
fi
_info "Updated."
_info "Adding the TXT record for $1"
_dns_cloudns_http_api_call "dns/add-record.json" "domain-name=$zone&record-type=TXT&host=$host&record=$record&ttl=60"
if ! _contains "$response" "\"status\":\"Success\""; then
_err "Record cannot be added."
return 1
fi
_info "Added."
return 0
}
@@ -71,22 +60,32 @@ dns_cloudns_rm() {
host="$(echo "$1" | sed "s/\.$zone\$//")"
record=$2
record_id=$(_dns_cloudns_get_record_id "$zone" "$host")
_debug zone "$zone"
_debug host "$host"
_debug record "$record"
_debug record_id "$record_id"
if [ ! -z "$record_id" ]; then
_info "Deleting the TXT record for $1"
_dns_cloudns_http_api_call "dns/delete-record.json" "domain-name=$zone&record-id=$record_id"
if ! _contains "$response" "\"status\":\"Success\""; then
_err "The TXT record for $1 cannot be deleted."
return 1
fi
_info "Deleted."
_dns_cloudns_http_api_call "dns/records.json" "domain-name=$zone&host=$host&type=TXT"
if ! _contains "$response" "\"id\":"; then
return 1
fi
for i in $(echo "$response" | tr '{' "\n" | grep "$record"); do
record_id=$(echo "$i" | tr ',' "\n" | grep -E '^"id"' | sed -re 's/^\"id\"\:\"([0-9]+)\"$/\1/g')
if [ ! -z "$record_id" ]; then
_debug zone "$zone"
_debug host "$host"
_debug record "$record"
_debug record_id "$record_id"
_info "Deleting the TXT record for $1"
_dns_cloudns_http_api_call "dns/delete-record.json" "domain-name=$zone&record-id=$record_id"
if ! _contains "$response" "\"status\":\"Success\""; then
_err "The TXT record for $1 cannot be deleted."
else
_info "Deleted."
fi
fi
done
return 0
}
@@ -96,8 +95,20 @@ _dns_cloudns_init_check() {
return 0
fi
if [ -z "$CLOUDNS_AUTH_ID" ]; then
_err "CLOUDNS_AUTH_ID is not configured"
CLOUDNS_AUTH_ID="${CLOUDNS_AUTH_ID:-$(_readaccountconf_mutable CLOUDNS_AUTH_ID)}"
CLOUDNS_SUB_AUTH_ID="${CLOUDNS_SUB_AUTH_ID:-$(_readaccountconf_mutable CLOUDNS_SUB_AUTH_ID)}"
CLOUDNS_AUTH_PASSWORD="${CLOUDNS_AUTH_PASSWORD:-$(_readaccountconf_mutable CLOUDNS_AUTH_PASSWORD)}"
if [ -z "$CLOUDNS_AUTH_ID$CLOUDNS_SUB_AUTH_ID" ] || [ -z "$CLOUDNS_AUTH_PASSWORD" ]; then
CLOUDNS_AUTH_ID=""
CLOUDNS_SUB_AUTH_ID=""
CLOUDNS_AUTH_PASSWORD=""
_err "You don't specify cloudns api id and password yet."
_err "Please create you id and password and try again."
return 1
fi
if [ -z "$CLOUDNS_AUTH_ID" ] && [ -z "$CLOUDNS_SUB_AUTH_ID" ]; then
_err "CLOUDNS_AUTH_ID or CLOUDNS_SUB_AUTH_ID is not configured"
return 1
fi
@@ -113,6 +124,11 @@ _dns_cloudns_init_check() {
return 1
fi
# save the api id and password to the account conf file.
_saveaccountconf_mutable CLOUDNS_AUTH_ID "$CLOUDNS_AUTH_ID"
_saveaccountconf_mutable CLOUDNS_SUB_AUTH_ID "$CLOUDNS_SUB_AUTH_ID"
_saveaccountconf_mutable CLOUDNS_AUTH_PASSWORD "$CLOUDNS_AUTH_PASSWORD"
CLOUDNS_INIT_CHECK_COMPLETED=1
return 0
@@ -141,30 +157,28 @@ _dns_cloudns_get_zone_name() {
return 1
}
_dns_cloudns_get_record_id() {
_dns_cloudns_http_api_call "dns/records.json" "domain-name=$1&host=$2&type=TXT"
if _contains "$response" "\"id\":"; then
echo "$response" | cut -d '"' -f 2
return 0
fi
return 1
}
_dns_cloudns_http_api_call() {
method=$1
_debug CLOUDNS_AUTH_ID "$CLOUDNS_AUTH_ID"
_debug CLOUDNS_SUB_AUTH_ID "$CLOUDNS_SUB_AUTH_ID"
_debug CLOUDNS_AUTH_PASSWORD "$CLOUDNS_AUTH_PASSWORD"
if [ -z "$2" ]; then
data="auth-id=$CLOUDNS_AUTH_ID&auth-password=$CLOUDNS_AUTH_PASSWORD"
if [ ! -z "$CLOUDNS_SUB_AUTH_ID" ]; then
auth_user="sub-auth-id=$CLOUDNS_SUB_AUTH_ID"
else
data="auth-id=$CLOUDNS_AUTH_ID&auth-password=$CLOUDNS_AUTH_PASSWORD&$2"
auth_user="auth-id=$CLOUDNS_AUTH_ID"
fi
if [ -z "$2" ]; then
data="$auth_user&auth-password=$CLOUDNS_AUTH_PASSWORD"
else
data="$auth_user&auth-password=$CLOUDNS_AUTH_PASSWORD&$2"
fi
response="$(_get "$CLOUDNS_API/$method?$data")"
_debug2 response "$response"
_debug response "$response"
return 0
}

View File

@@ -36,33 +36,18 @@ dns_cx_add() {
return 1
fi
existing_records "$_domain" "$_sub_domain"
_debug count "$count"
if [ "$?" != "0" ]; then
_err "Error get existing records."
return 1
fi
if [ "$count" = "0" ]; then
add_record "$_domain" "$_sub_domain" "$txtvalue"
else
update_record "$_domain" "$_sub_domain" "$txtvalue"
fi
if [ "$?" = "0" ]; then
return 0
fi
return 1
add_record "$_domain" "$_sub_domain" "$txtvalue"
}
#fulldomain
#fulldomain txtvalue
dns_cx_rm() {
fulldomain=$1
txtvalue=$2
REST_API="$CX_Api"
if _get_root "$fulldomain"; then
record_id=""
existing_records "$_domain" "$_sub_domain"
if ! [ "$record_id" = "" ]; then
existing_records "$_domain" "$_sub_domain" "$txtvalue"
if [ "$record_id" ]; then
_rest DELETE "record/$record_id/$_domain_id" "{}"
_info "Deleted record ${fulldomain}"
fi
@@ -77,7 +62,6 @@ existing_records() {
_debug "Getting txt records"
root=$1
sub=$2
count=0
if ! _rest GET "record/$_domain_id?:domain_id?host_id=0&offset=0&row_num=100"; then
return 1
fi
@@ -89,7 +73,6 @@ existing_records() {
fi
if printf "%s" "$response" | grep '"type":"TXT"' >/dev/null; then
count=1
record_id=$(printf "%s\n" "$seg" | _egrep_o '"record_id":"[^"]*"' | cut -d : -f 2 | tr -d \" | _head_n 1)
_debug record_id "$record_id"
return 0
@@ -114,23 +97,6 @@ add_record() {
return 0
}
#update the txt record
#Usage: root sub txtvalue
update_record() {
root=$1
sub=$2
txtvalue=$3
fulldomain="$sub.$root"
_info "Updating record"
if _rest PUT "record/$record_id" "{\"domain_id\": $_domain_id, \"host\":\"$_sub_domain\", \"value\":\"$txtvalue\", \"type\":\"TXT\",\"ttl\":600, \"line_id\":1}"; then
return 0
fi
return 1
}
#################### Private functions below ##################################
#_acme-challenge.www.domain.com
#returns

184
dnsapi/dns_da.sh Executable file
View File

@@ -0,0 +1,184 @@
#!/usr/bin/env sh
# -*- mode: sh; tab-width: 2; indent-tabs-mode: s; coding: utf-8 -*-
# vim: et ts=2 sw=2
#
# DirectAdmin 1.41.0 API
# The DirectAdmin interface has it's own Let's encrypt functionality, but this
# script can be used to generate certificates for names which are not hosted on
# DirectAdmin
#
# User must provide login data and URL to DirectAdmin incl. port.
# You can create login key, by using the Login Keys function
# ( https://da.example.com:8443/CMD_LOGIN_KEYS ), which only has access to
# - CMD_API_DNS_CONTROL
# - CMD_API_SHOW_DOMAINS
#
# See also https://www.directadmin.com/api.php and
# https://www.directadmin.com/features.php?id=1298
#
# Report bugs to https://github.com/TigerP/acme.sh/issues
#
# Values to export:
# export DA_Api="https://remoteUser:remotePassword@da.example.com:8443"
# export DA_Api_Insecure=1
#
# Set DA_Api_Insecure to 1 for insecure and 0 for secure -> difference is
# whether ssl cert is checked for validity (0) or whether it is just accepted
# (1)
#
######## Public functions #####################
# Usage: dns_myapi_add _acme-challenge.www.example.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
# Used to add txt record
dns_da_add() {
fulldomain="${1}"
txtvalue="${2}"
_debug "Calling: dns_da_add() '${fulldomain}' '${txtvalue}'"
_DA_credentials && _DA_getDomainInfo && _DA_addTxt
}
# Usage: dns_da_rm _acme-challenge.www.example.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
# Used to remove the txt record after validation
dns_da_rm() {
fulldomain="${1}"
txtvalue="${2}"
_debug "Calling: dns_da_rm() '${fulldomain}' '${txtvalue}'"
_DA_credentials && _DA_getDomainInfo && _DA_rmTxt
}
#################### Private functions below ##################################
# Usage: _DA_credentials
# It will check if the needed settings are available
_DA_credentials() {
DA_Api="${DA_Api:-$(_readaccountconf_mutable DA_Api)}"
DA_Api_Insecure="${DA_Api_Insecure:-$(_readaccountconf_mutable DA_Api_Insecure)}"
if [ -z "${DA_Api}" ] || [ -z "${DA_Api_Insecure}" ]; then
DA_Api=""
DA_Api_Insecure=""
_err "You haven't specified the DirectAdmin Login data, URL and whether you want check the DirectAdmin SSL cert. Please try again."
return 1
else
_saveaccountconf_mutable DA_Api "${DA_Api}"
_saveaccountconf_mutable DA_Api_Insecure "${DA_Api_Insecure}"
# Set whether curl should use secure or insecure mode
export HTTPS_INSECURE="${DA_Api_Insecure}"
fi
}
# Usage: _get_root _acme-challenge.www.example.com
# Split the full domain to a domain and subdomain
#returns
# _sub_domain=_acme-challenge.www
# _domain=example.com
_get_root() {
domain=$1
i=2
p=1
# Get a list of all the domains
# response will contain "list[]=example.com&list[]=example.org"
_da_api CMD_API_SHOW_DOMAINS "" "${domain}"
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
_debug h "$h"
if [ -z "$h" ]; then
# not valid
_debug "The given domain $h is not valid"
return 1
fi
if _contains "$response" "$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
_debug "Stop on 100"
return 1
}
# Usage: _da_api CMD_API_* data example.com
# Use the DirectAdmin API and check the result
# returns
# response="error=0&text=Result text&details="
_da_api() {
cmd=$1
data=$2
domain=$3
_debug "$domain; $data"
response="$(_post "$data" "$DA_Api/$cmd" "" "POST")"
if [ "$?" != "0" ]; then
_err "error $cmd"
return 1
fi
_debug response "$response"
case "${cmd}" in
CMD_API_DNS_CONTROL)
# Parse the result in general
# error=0&text=Records Deleted&details=
# error=1&text=Cannot View Dns Record&details=No domain provided
err_field="$(_getfield "$response" 1 '&')"
txt_field="$(_getfield "$response" 2 '&')"
details_field="$(_getfield "$response" 3 '&')"
error="$(_getfield "$err_field" 2 '=')"
text="$(_getfield "$txt_field" 2 '=')"
details="$(_getfield "$details_field" 2 '=')"
_debug "error: ${error}, text: ${text}, details: ${details}"
if [ "$error" != "0" ]; then
_err "error $response"
return 1
fi
;;
CMD_API_SHOW_DOMAINS) ;;
esac
return 0
}
# Usage: _DA_getDomainInfo
# Get the root zone if possible
_DA_getDomainInfo() {
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"
return 1
else
_debug "The root domain: $_domain"
_debug "The sub domain: $_sub_domain"
fi
return 0
}
# Usage: _DA_addTxt
# Use the API to add a record
_DA_addTxt() {
curData="domain=${_domain}&action=add&type=TXT&name=${_sub_domain}&value=\"${txtvalue}\""
_debug "Calling _DA_addTxt: '${curData}' '${DA_Api}/CMD_API_DNS_CONTROL'"
_da_api CMD_API_DNS_CONTROL "${curData}" "${_domain}"
_debug "Result of _DA_addTxt: '$response'"
if _contains "${response}" 'error=0'; then
_debug "Add TXT succeeded"
return 0
fi
_debug "Add TXT failed"
return 1
}
# Usage: _DA_rmTxt
# Use the API to remove a record
_DA_rmTxt() {
curData="domain=${_domain}&action=select&txtrecs0=name=${_sub_domain}&amp;value=\"${txtvalue}\""
_debug "Calling _DA_rmTxt: '${curData}' '${DA_Api}/CMD_API_DNS_CONTROL'"
if _da_api CMD_API_DNS_CONTROL "${curData}" "${_domain}"; then
_debug "Result of _DA_rmTxt: '$response'"
else
_err "Result of _DA_rmTxt: '$response'"
fi
if _contains "${response}" 'error=0'; then
_debug "RM TXT succeeded"
return 0
fi
_debug "RM TXT failed"
return 1
}

View File

@@ -15,6 +15,8 @@ dns_dp_add() {
fulldomain=$1
txtvalue=$2
DP_Id="${DP_Id:-$(_readaccountconf_mutable DP_Id)}"
DP_Key="${DP_Key:-$(_readaccountconf_mutable DP_Key)}"
if [ -z "$DP_Id" ] || [ -z "$DP_Key" ]; then
DP_Id=""
DP_Key=""
@@ -24,8 +26,8 @@ dns_dp_add() {
fi
#save the api key and email to the account conf file.
_saveaccountconf DP_Id "$DP_Id"
_saveaccountconf DP_Key "$DP_Key"
_saveaccountconf_mutable DP_Id "$DP_Id"
_saveaccountconf_mutable DP_Key "$DP_Key"
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
@@ -33,24 +35,18 @@ dns_dp_add() {
return 1
fi
existing_records "$_domain" "$_sub_domain"
_debug count "$count"
if [ "$?" != "0" ]; then
_err "Error get existing records."
return 1
fi
add_record "$_domain" "$_sub_domain" "$txtvalue"
if [ "$count" = "0" ]; then
add_record "$_domain" "$_sub_domain" "$txtvalue"
else
update_record "$_domain" "$_sub_domain" "$txtvalue"
fi
}
#fulldomain txtvalue
dns_dp_rm() {
fulldomain=$1
txtvalue=$2
DP_Id="${DP_Id:-$(_readaccountconf_mutable DP_Id)}"
DP_Key="${DP_Key:-$(_readaccountconf_mutable DP_Key)}"
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"
@@ -83,37 +79,6 @@ dns_dp_rm() {
}
#usage: root sub
#return if the sub record already exists.
#echos the existing records count.
# '0' means doesn't exist
existing_records() {
_debug "Getting txt records"
root=$1
sub=$2
if ! _rest POST "Record.List" "login_token=$DP_Id,$DP_Key&domain_id=$_domain_id&sub_domain=$_sub_domain"; then
return 1
fi
if _contains "$response" 'No records'; then
count=0
return 0
fi
if _contains "$response" "Action completed successful"; then
count=$(printf "%s" "$response" | grep -c '<type>TXT</type>' | tr -d ' ')
record_id=$(printf "%s" "$response" | grep '^<id>' | tail -1 | cut -d '>' -f 2 | cut -d '<' -f 1)
_debug record_id "$record_id"
return 0
else
_err "get existing records error."
return 1
fi
count=0
}
#add the txt record.
#usage: root sub txtvalue
add_record() {
@@ -128,34 +93,7 @@ add_record() {
return 1
fi
if _contains "$response" "Action completed successful"; then
return 0
fi
return 1 #error
}
#update the txt record
#Usage: root sub txtvalue
update_record() {
root=$1
sub=$2
txtvalue=$3
fulldomain="$sub.$root"
_info "Updating record"
if ! _rest POST "Record.Modify" "login_token=$DP_Id,$DP_Key&format=json&domain_id=$_domain_id&sub_domain=$_sub_domain&record_type=TXT&value=$txtvalue&record_line=默认&record_id=$record_id"; then
return 1
fi
if _contains "$response" "Action completed successful"; then
return 0
fi
return 1 #error
_contains "$response" "Action completed successful" || _contains "$response" "Domain record already exists"
}
#################### Private functions below ##################################

97
dnsapi/dns_dreamhost.sh Normal file
View File

@@ -0,0 +1,97 @@
#!/usr/bin/env sh
#Author: RhinoLance
#Report Bugs here: https://github.com/RhinoLance/acme.sh
#
#define the api endpoint
DH_API_ENDPOINT="https://api.dreamhost.com/"
querystring=""
######## Public functions #####################
#Usage: dns_myapi_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_dreamhost_add() {
fulldomain=$1
txtvalue=$2
if ! validate "$fulldomain" "$txtvalue"; then
return 1
fi
querystring="key=$DH_API_KEY&cmd=dns-add_record&record=$fulldomain&type=TXT&value=$txtvalue"
if ! submit "$querystring"; then
return 1
fi
return 0
}
#Usage: fulldomain txtvalue
#Remove the txt record after validation.
dns_dreamhost_rm() {
fulldomain=$1
txtvalue=$2
if ! validate "$fulldomain" "$txtvalue"; then
return 1
fi
querystring="key=$DH_API_KEY&cmd=dns-remove_record&record=$fulldomain&type=TXT&value=$txtvalue"
if ! submit "$querystring"; then
return 1
fi
return 0
}
#################### Private functions below ##################################
#send the command to the api endpoint.
submit() {
querystring=$1
url="$DH_API_ENDPOINT?$querystring"
_debug url "$url"
if ! response="$(_get "$url")"; then
_err "Error <$1>"
return 1
fi
if [ -z "$2" ]; then
message="$(echo "$response" | _egrep_o "\"Message\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \")"
if [ -n "$message" ]; then
_err "$message"
return 1
fi
fi
_debug response "$response"
return 0
}
#check that we have a valid API Key
validate() {
fulldomain=$1
txtvalue=$2
_info "Using dreamhost"
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
#retrieve the API key from the environment variable if it exists, otherwise look for a saved key.
DH_API_KEY="${DH_API_KEY:-$(_readaccountconf_mutable DH_API_KEY)}"
if [ -z "$DH_API_KEY" ]; then
DH_API_KEY=""
_err "You didn't specify the DreamHost api key yet (export DH_API_KEY=\"<api key>\")"
_err "Please login to your control panel, create a key and try again."
return 1
fi
#save the api key to the account conf file.
_saveaccountconf_mutable DH_API_KEY "$DH_API_KEY"
}

128
dnsapi/dns_duckdns.sh Executable file
View File

@@ -0,0 +1,128 @@
#!/usr/bin/env sh
#Created by RaidenII, to use DuckDNS's API to add/remove text records
#06/27/2017
# Pass credentials before "acme.sh --issue --dns dns_duckdns ..."
# --
# export DuckDNS_Token="aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
# --
#
# Due to the fact that DuckDNS uses StartSSL as cert provider, --insecure may need to be used with acme.sh
DuckDNS_API="https://www.duckdns.org/update"
######## Public functions #####################
#Usage: dns_duckdns_add _acme-challenge.domain.duckdns.org "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_duckdns_add() {
fulldomain=$1
txtvalue=$2
DuckDNS_Token="${DuckDNS_Token:-$(_readaccountconf_mutable DuckDNS_Token)}"
if [ -z "$DuckDNS_Token" ]; then
_err "You must export variable: DuckDNS_Token"
_err "The token for your DuckDNS account is necessary."
_err "You can look it up in your DuckDNS account."
return 1
fi
# Now save the credentials.
_saveaccountconf_mutable DuckDNS_Token "$DuckDNS_Token"
# Unfortunately, DuckDNS 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 DuckDNS
if ! _duckdns_get_domain; then
return 1
fi
# Now add the TXT record to DuckDNS
_info "Trying to add TXT record"
if _duckdns_rest GET "domains=$_duckdns_domain&token=$DuckDNS_Token&txt=$txtvalue"; then
if [ "$response" = "OK" ]; then
_info "TXT record has been successfully added to your DuckDNS 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_duckdns_rm() {
fulldomain=$1
txtvalue=$2
DuckDNS_Token="${DuckDNS_Token:-$(_readaccountconf_mutable DuckDNS_Token)}"
if [ -z "$DuckDNS_Token" ]; then
_err "You must export variable: DuckDNS_Token"
_err "The token for your DuckDNS account is necessary."
_err "You can look it up in your DuckDNS account."
return 1
fi
if ! _duckdns_get_domain; then
return 1
fi
# Now remove the TXT record from DuckDNS
_info "Trying to remove TXT record"
if _duckdns_rest GET "domains=$_duckdns_domain&token=$DuckDNS_Token&txt=&clear=true"; then
if [ "$response" = "OK" ]; then
_info "TXT record has been successfully removed from your DuckDNS 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.duckdns.org
#returns
# _duckdns_domain=domain
_duckdns_get_domain() {
# We'll extract the domain/username from full domain
_duckdns_domain="$(printf "%s" "$fulldomain" | _lower_case | _egrep_o '[.][^.][^.]*[.]duckdns.org' | cut -d . -f 2)"
if [ -z "$_duckdns_domain" ]; then
_err "Error extracting the domain."
return 1
fi
return 0
}
#Usage: method URI
_duckdns_rest() {
method=$1
param="$2"
_debug param "$param"
url="$DuckDNS_API?$param"
_debug url "$url"
# DuckDNS uses GET to update domain info
if [ "$method" = "GET" ]; then
response="$(_get "$url")"
else
_err "Unsupported method"
return 1
fi
_debug2 response "$response"
return 0
}

339
dnsapi/dns_dyn.sh Normal file
View File

@@ -0,0 +1,339 @@
#!/usr/bin/env sh
#
# Dyn.com Domain API
#
# Author: Gerd Naschenweng
# https://github.com/magicdude4eva
#
# Dyn Managed DNS API
# https://help.dyn.com/dns-api-knowledge-base/
#
# It is recommended to add a "Dyn Managed DNS" user specific for API access.
# The "Zones & Records Permissions" required by this script are:
# --
# RecordAdd
# RecordUpdate
# RecordDelete
# RecordGet
# ZoneGet
# ZoneAddNode
# ZoneRemoveNode
# ZonePublish
# --
#
# Pass credentials before "acme.sh --issue --dns dns_dyn ..."
# --
# export DYN_Customer="customer"
# export DYN_Username="apiuser"
# export DYN_Password="secret"
# --
DYN_API="https://api.dynect.net/REST"
#REST_API
######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "Challenge-code"
dns_dyn_add() {
fulldomain="$1"
txtvalue="$2"
DYN_Customer="${DYN_Customer:-$(_readaccountconf_mutable DYN_Customer)}"
DYN_Username="${DYN_Username:-$(_readaccountconf_mutable DYN_Username)}"
DYN_Password="${DYN_Password:-$(_readaccountconf_mutable DYN_Password)}"
if [ -z "$DYN_Customer" ] || [ -z "$DYN_Username" ] || [ -z "$DYN_Password" ]; then
DYN_Customer=""
DYN_Username=""
DYN_Password=""
_err "You must export variables: DYN_Customer, DYN_Username and DYN_Password"
return 1
fi
#save the config variables to the account conf file.
_saveaccountconf_mutable DYN_Customer "$DYN_Customer"
_saveaccountconf_mutable DYN_Username "$DYN_Username"
_saveaccountconf_mutable DYN_Password "$DYN_Password"
if ! _dyn_get_authtoken; then
return 1
fi
if [ -z "$_dyn_authtoken" ]; then
_dyn_end_session
return 1
fi
if ! _dyn_get_zone; then
_dyn_end_session
return 1
fi
if ! _dyn_add_record; then
_dyn_end_session
return 1
fi
if ! _dyn_publish_zone; then
_dyn_end_session
return 1
fi
_dyn_end_session
return 0
}
#Usage: fulldomain txtvalue
#Remove the txt record after validation.
dns_dyn_rm() {
fulldomain="$1"
txtvalue="$2"
DYN_Customer="${DYN_Customer:-$(_readaccountconf_mutable DYN_Customer)}"
DYN_Username="${DYN_Username:-$(_readaccountconf_mutable DYN_Username)}"
DYN_Password="${DYN_Password:-$(_readaccountconf_mutable DYN_Password)}"
if [ -z "$DYN_Customer" ] || [ -z "$DYN_Username" ] || [ -z "$DYN_Password" ]; then
DYN_Customer=""
DYN_Username=""
DYN_Password=""
_err "You must export variables: DYN_Customer, DYN_Username and DYN_Password"
return 1
fi
if ! _dyn_get_authtoken; then
return 1
fi
if [ -z "$_dyn_authtoken" ]; then
_dyn_end_session
return 1
fi
if ! _dyn_get_zone; then
_dyn_end_session
return 1
fi
if ! _dyn_get_record_id; then
_dyn_end_session
return 1
fi
if [ -z "$_dyn_record_id" ]; then
_dyn_end_session
return 1
fi
if ! _dyn_rm_record; then
_dyn_end_session
return 1
fi
if ! _dyn_publish_zone; then
_dyn_end_session
return 1
fi
_dyn_end_session
return 0
}
#################### Private functions below ##################################
#get Auth-Token
_dyn_get_authtoken() {
_info "Start Dyn API Session"
data="{\"customer_name\":\"$DYN_Customer\", \"user_name\":\"$DYN_Username\", \"password\":\"$DYN_Password\"}"
dyn_url="$DYN_API/Session/"
method="POST"
_debug data "$data"
_debug dyn_url "$dyn_url"
export _H1="Content-Type: application/json"
response="$(_post "$data" "$dyn_url" "" "$method")"
sessionstatus="$(printf "%s\n" "$response" | _egrep_o '"status" *: *"[^"]*' | _head_n 1 | sed 's#^"status" *: *"##')"
_debug response "$response"
_debug sessionstatus "$sessionstatus"
if [ "$sessionstatus" = "success" ]; then
_dyn_authtoken="$(printf "%s\n" "$response" | _egrep_o '"token" *: *"[^"]*' | _head_n 1 | sed 's#^"token" *: *"##')"
_info "Token received"
_debug _dyn_authtoken "$_dyn_authtoken"
return 0
fi
_dyn_authtoken=""
_err "get token failed"
return 1
}
#fulldomain=_acme-challenge.www.domain.com
#returns
# _dyn_zone=domain.com
_dyn_get_zone() {
i=2
while true; do
domain="$(printf "%s" "$fulldomain" | cut -d . -f "$i-100")"
if [ -z "$domain" ]; then
break
fi
dyn_url="$DYN_API/Zone/$domain/"
export _H1="Auth-Token: $_dyn_authtoken"
export _H2="Content-Type: application/json"
response="$(_get "$dyn_url" "" "")"
sessionstatus="$(printf "%s\n" "$response" | _egrep_o '"status" *: *"[^"]*' | _head_n 1 | sed 's#^"status" *: *"##')"
_debug dyn_url "$dyn_url"
_debug response "$response"
_debug sessionstatus "$sessionstatus"
if [ "$sessionstatus" = "success" ]; then
_dyn_zone="$domain"
return 0
fi
i=$(_math "$i" + 1)
done
_dyn_zone=""
_err "get zone failed"
return 1
}
#add TXT record
_dyn_add_record() {
_info "Adding TXT record"
data="{\"rdata\":{\"txtdata\":\"$txtvalue\"},\"ttl\":\"300\"}"
dyn_url="$DYN_API/TXTRecord/$_dyn_zone/$fulldomain/"
method="POST"
export _H1="Auth-Token: $_dyn_authtoken"
export _H2="Content-Type: application/json"
response="$(_post "$data" "$dyn_url" "" "$method")"
sessionstatus="$(printf "%s\n" "$response" | _egrep_o '"status" *: *"[^"]*' | _head_n 1 | sed 's#^"status" *: *"##')"
_debug response "$response"
_debug sessionstatus "$sessionstatus"
if [ "$sessionstatus" = "success" ]; then
_info "TXT Record successfully added"
return 0
fi
_err "add TXT record failed"
return 1
}
#publish the zone
_dyn_publish_zone() {
_info "Publishing zone"
data="{\"publish\":\"true\"}"
dyn_url="$DYN_API/Zone/$_dyn_zone/"
method="PUT"
export _H1="Auth-Token: $_dyn_authtoken"
export _H2="Content-Type: application/json"
response="$(_post "$data" "$dyn_url" "" "$method")"
sessionstatus="$(printf "%s\n" "$response" | _egrep_o '"status" *: *"[^"]*' | _head_n 1 | sed 's#^"status" *: *"##')"
_debug response "$response"
_debug sessionstatus "$sessionstatus"
if [ "$sessionstatus" = "success" ]; then
_info "Zone published"
return 0
fi
_err "publish zone failed"
return 1
}
#get record_id of TXT record so we can delete the record
_dyn_get_record_id() {
_info "Getting record_id of TXT record"
dyn_url="$DYN_API/TXTRecord/$_dyn_zone/$fulldomain/"
export _H1="Auth-Token: $_dyn_authtoken"
export _H2="Content-Type: application/json"
response="$(_get "$dyn_url" "" "")"
sessionstatus="$(printf "%s\n" "$response" | _egrep_o '"status" *: *"[^"]*' | _head_n 1 | sed 's#^"status" *: *"##')"
_debug response "$response"
_debug sessionstatus "$sessionstatus"
if [ "$sessionstatus" = "success" ]; then
_dyn_record_id="$(printf "%s\n" "$response" | _egrep_o "\"data\" *: *\[\"/REST/TXTRecord/$_dyn_zone/$fulldomain/[^\"]*" | _head_n 1 | sed "s#^\"data\" *: *\[\"/REST/TXTRecord/$_dyn_zone/$fulldomain/##")"
_debug _dyn_record_id "$_dyn_record_id"
return 0
fi
_dyn_record_id=""
_err "getting record_id failed"
return 1
}
#delete TXT record
_dyn_rm_record() {
_info "Deleting TXT record"
dyn_url="$DYN_API/TXTRecord/$_dyn_zone/$fulldomain/$_dyn_record_id/"
method="DELETE"
_debug dyn_url "$dyn_url"
export _H1="Auth-Token: $_dyn_authtoken"
export _H2="Content-Type: application/json"
response="$(_post "" "$dyn_url" "" "$method")"
sessionstatus="$(printf "%s\n" "$response" | _egrep_o '"status" *: *"[^"]*' | _head_n 1 | sed 's#^"status" *: *"##')"
_debug response "$response"
_debug sessionstatus "$sessionstatus"
if [ "$sessionstatus" = "success" ]; then
_info "TXT record successfully deleted"
return 0
fi
_err "delete TXT record failed"
return 1
}
#logout
_dyn_end_session() {
_info "End Dyn API Session"
dyn_url="$DYN_API/Session/"
method="DELETE"
_debug dyn_url "$dyn_url"
export _H1="Auth-Token: $_dyn_authtoken"
export _H2="Content-Type: application/json"
response="$(_post "" "$dyn_url" "" "$method")"
_debug response "$response"
_dyn_authtoken=""
return 0
}

View File

@@ -53,6 +53,9 @@ dns_freedns_add() {
i="$(_math "$i" - 1)"
sub_domain="$(echo "$fulldomain" | cut -d. -f -"$i")"
_debug "top_domain: $top_domain"
_debug "sub_domain: $sub_domain"
# Sometimes FreeDNS does not return the subdomain page but rather
# returns a page regarding becoming a premium member. This usually
# happens after a period of inactivity. Immediately trying again
@@ -71,18 +74,9 @@ dns_freedns_add() {
return 1
fi
# Now convert the tables in the HTML to CSV. This litte gem from
# http://stackoverflow.com/questions/1403087/how-can-i-convert-an-html-table-to-csv
subdomain_csv="$(echo "$htmlpage" \
| grep -i -e '</\?TABLE\|</\?TD\|</\?TR\|</\?TH' \
| sed 's/^[\ \t]*//g' \
| tr -d '\n' \
| sed 's/<\/TR[^>]*>/\n/Ig' \
| sed 's/<\/\?\(TABLE\|TR\)[^>]*>//Ig' \
| sed 's/^<T[DH][^>]*>\|<\/\?T[DH][^>]*>$//Ig' \
| sed 's/<\/T[DH][^>]*><T[DH][^>]*>/,/Ig' \
| grep 'edit.php?' \
| grep "$top_domain")"
subdomain_csv="$(echo "$htmlpage" | tr -d "\n\r" | _egrep_o '<form .*</form>' | sed 's/<tr>/@<tr>/g' | tr '@' '\n' | grep edit.php | grep "$top_domain")"
_debug3 "subdomain_csv: $subdomain_csv"
# The above beauty ends with striping out rows that do not have an
# href to edit.php and do not have the top domain we are looking for.
# So all we should be left with is CSV of table of subdomains we are
@@ -90,55 +84,27 @@ dns_freedns_add() {
# Now we have to read through this table and extract the data we need
lines="$(echo "$subdomain_csv" | wc -l)"
nl='
'
i=0
found=0
DNSdomainid=""
while [ "$i" -lt "$lines" ]; do
i="$(_math "$i" + 1)"
line="$(echo "$subdomain_csv" | cut -d "$nl" -f "$i")"
tmp="$(echo "$line" | cut -d ',' -f 1)"
if [ $found = 0 ] && _startswith "$tmp" "<td>$top_domain"; then
line="$(echo "$subdomain_csv" | sed -n "${i}p")"
_debug2 "line: $line"
if [ $found = 0 ] && _contains "$line" "<td>$top_domain</td>"; then
# this line will contain DNSdomainid for the top_domain
DNSdomainid="$(echo "$line" | cut -d ',' -f 2 | sed 's/^.*domain_id=//;s/>.*//')"
DNSdomainid="$(echo "$line" | _egrep_o "edit_domain_id *= *.*>" | cut -d = -f 2 | cut -d '>' -f 1)"
_debug2 "DNSdomainid: $DNSdomainid"
found=1
else
# lines contain DNS records for all subdomains
DNSname="$(echo "$line" | cut -d ',' -f 2 | sed 's/^[^>]*>//;s/<\/a>.*//')"
DNStype="$(echo "$line" | cut -d ',' -f 3)"
if [ "$DNSname" = "$fulldomain" ] && [ "$DNStype" = "TXT" ]; then
DNSdataid="$(echo "$line" | cut -d ',' -f 2 | sed 's/^.*data_id=//;s/>.*//')"
# Now get current value for the TXT record. This method may
# not produce accurate results as the value field is truncated
# on this webpage. To get full value we would need to load
# another page. However we don't really need this so long as
# there is only one TXT record for the acme challenge subdomain.
DNSvalue="$(echo "$line" | cut -d ',' -f 4 | sed 's/^[^&quot;]*&quot;//;s/&quot;.*//;s/<\/td>.*//')"
if [ $found != 0 ]; then
break
# we are breaking out of the loop at the first match of DNS name
# and DNS type (if we are past finding the domainid). This assumes
# that there is only ever one TXT record for the LetsEncrypt/acme
# challenge subdomain. This seems to be a reasonable assumption
# as the acme client deletes the TXT record on successful validation.
fi
else
DNSname=""
DNStype=""
fi
break
fi
done
_debug "DNSname: $DNSname DNStype: $DNStype DNSdomainid: $DNSdomainid DNSdataid: $DNSdataid"
_debug "DNSvalue: $DNSvalue"
if [ -z "$DNSdomainid" ]; then
# If domain ID is empty then something went wrong (top level
# domain not found at FreeDNS).
if [ "$attempts" = "0" ]; then
# exhausted maximum retry attempts
_debug "$htmlpage"
_debug "$subdomain_csv"
_err "Domain $top_domain not found at FreeDNS"
return 1
fi
@@ -150,34 +116,10 @@ dns_freedns_add() {
_info "Retry loading subdomain page ($attempts attempts remaining)"
done
if [ -z "$DNSdataid" ]; then
# If data ID is empty then specific subdomain does not exist yet, need
# to create it this should always be the case as the acme client
# deletes the entry after domain is validated.
_freedns_add_txt_record "$FREEDNS_COOKIE" "$DNSdomainid" "$sub_domain" "$txtvalue"
return $?
else
if [ "$txtvalue" = "$DNSvalue" ]; then
# if value in TXT record matches value requested then DNS record
# does not need to be updated. But...
# Testing value match fails. Website is truncating the value field.
# So for now we will always go down the else path. Though in theory
# should never come here anyway as the acme client deletes
# the TXT record on successful validation, so we should not even
# have found a TXT record !!
_info "No update necessary for $fulldomain at FreeDNS"
return 0
else
# Delete the old TXT record (with the wrong value)
_freedns_delete_txt_record "$FREEDNS_COOKIE" "$DNSdataid"
if [ "$?" = "0" ]; then
# And add in new TXT record with the value provided
_freedns_add_txt_record "$FREEDNS_COOKIE" "$DNSdomainid" "$sub_domain" "$txtvalue"
fi
return $?
fi
fi
return 0
# Add in new TXT record with the value provided
_debug "Adding TXT record for $fulldomain, $txtvalue"
_freedns_add_txt_record "$FREEDNS_COOKIE" "$DNSdomainid" "$sub_domain" "$txtvalue"
return $?
}
#Usage: fulldomain txtvalue
@@ -210,18 +152,9 @@ dns_freedns_rm() {
return 1
fi
# Now convert the tables in the HTML to CSV. This litte gem from
# http://stackoverflow.com/questions/1403087/how-can-i-convert-an-html-table-to-csv
subdomain_csv="$(echo "$htmlpage" \
| grep -i -e '</\?TABLE\|</\?TD\|</\?TR\|</\?TH' \
| sed 's/^[\ \t]*//g' \
| tr -d '\n' \
| sed 's/<\/TR[^>]*>/\n/Ig' \
| sed 's/<\/\?\(TABLE\|TR\)[^>]*>//Ig' \
| sed 's/^<T[DH][^>]*>\|<\/\?T[DH][^>]*>$//Ig' \
| sed 's/<\/T[DH][^>]*><T[DH][^>]*>/,/Ig' \
| grep 'edit.php?' \
| grep "$fulldomain")"
subdomain_csv="$(echo "$htmlpage" | tr -d "\n\r" | _egrep_o '<form .*</form>' | sed 's/<tr>/@<tr>/g' | tr '@' '\n' | grep edit.php | grep "$fulldomain")"
_debug3 "subdomain_csv: $subdomain_csv"
# The above beauty ends with striping out rows that do not have an
# href to edit.php and do not have the domain name we are looking for.
# So all we should be left with is CSV of table of subdomains we are
@@ -229,35 +162,53 @@ dns_freedns_rm() {
# Now we have to read through this table and extract the data we need
lines="$(echo "$subdomain_csv" | wc -l)"
nl='
'
i=0
found=0
DNSdataid=""
while [ "$i" -lt "$lines" ]; do
i="$(_math "$i" + 1)"
line="$(echo "$subdomain_csv" | cut -d "$nl" -f "$i")"
DNSname="$(echo "$line" | cut -d ',' -f 2 | sed 's/^[^>]*>//;s/<\/a>.*//')"
DNStype="$(echo "$line" | cut -d ',' -f 3)"
if [ "$DNSname" = "$fulldomain" ] && [ "$DNStype" = "TXT" ]; then
DNSdataid="$(echo "$line" | cut -d ',' -f 2 | sed 's/^.*data_id=//;s/>.*//')"
DNSvalue="$(echo "$line" | cut -d ',' -f 4 | sed 's/^[^&quot;]*&quot;//;s/&quot;.*//;s/<\/td>.*//')"
_debug "DNSvalue: $DNSvalue"
# if [ "$DNSvalue" = "$txtvalue" ]; then
# Testing value match fails. Website is truncating the value
# field. So for now we will assume that there is only one TXT
# field for the sub domain and just delete it. Currently this
# is a safe assumption.
_freedns_delete_txt_record "$FREEDNS_COOKIE" "$DNSdataid"
return $?
# fi
line="$(echo "$subdomain_csv" | sed -n "${i}p")"
_debug3 "line: $line"
DNSname="$(echo "$line" | _egrep_o 'edit.php.*</a>' | cut -d '>' -f 2 | cut -d '<' -f 1)"
_debug2 "DNSname: $DNSname"
if [ "$DNSname" = "$fulldomain" ]; then
DNStype="$(echo "$line" | sed 's/<td/@<td/g' | tr '@' '\n' | sed -n '4p' | cut -d '>' -f 2 | cut -d '<' -f 1)"
_debug2 "DNStype: $DNStype"
if [ "$DNStype" = "TXT" ]; then
DNSdataid="$(echo "$line" | _egrep_o 'data_id=.*' | cut -d = -f 2 | cut -d '>' -f 1)"
_debug2 "DNSdataid: $DNSdataid"
DNSvalue="$(echo "$line" | sed 's/<td/@<td/g' | tr '@' '\n' | sed -n '5p' | cut -d '>' -f 2 | cut -d '<' -f 1)"
if _startswith "$DNSvalue" "&quot;"; then
# remove the quotation from the start
DNSvalue="$(echo "$DNSvalue" | cut -c 7-)"
fi
if _endswith "$DNSvalue" "..."; then
# value was truncated, remove the dot dot dot from the end
DNSvalue="$(echo "$DNSvalue" | sed 's/...$//')"
elif _endswith "$DNSvalue" "&quot;"; then
# else remove the closing quotation from the end
DNSvalue="$(echo "$DNSvalue" | sed 's/......$//')"
fi
_debug2 "DNSvalue: $DNSvalue"
if [ -n "$DNSdataid" ] && _startswith "$txtvalue" "$DNSvalue"; then
# Found a match. But note... Website is truncating the
# value field so we are only testing that part that is not
# truncated. This should be accurate enough.
_debug "Deleting TXT record for $fulldomain, $txtvalue"
_freedns_delete_txt_record "$FREEDNS_COOKIE" "$DNSdataid"
return $?
fi
fi
fi
done
done
# If we get this far we did not find a match (after two attempts)
# Not necessarily an error, but log anyway.
_debug2 "$subdomain_csv"
_info "Cannot delete TXT record for $fulldomain/$txtvalue. Does not exist at FreeDNS"
_debug3 "$subdomain_csv"
_info "Cannot delete TXT record for $fulldomain, $txtvalue. Does not exist at FreeDNS"
return 0
}
@@ -285,7 +236,7 @@ _freedns_login() {
# if cookies is not empty then logon successful
if [ -z "$cookies" ]; then
_debug "$htmlpage"
_debug3 "htmlpage: $htmlpage"
_err "FreeDNS login failed for user $username. Check $HTTP_HEADER file"
return 1
fi
@@ -314,7 +265,7 @@ _freedns_retrieve_subdomain_page() {
return 1
fi
_debug2 "$htmlpage"
_debug3 "htmlpage: $htmlpage"
printf "%s" "$htmlpage"
return 0
@@ -336,17 +287,17 @@ _freedns_add_txt_record() {
_err "FreeDNS failed to add TXT record for $subdomain bad RC from _post"
return 1
elif ! grep "200 OK" "$HTTP_HEADER" >/dev/null; then
_debug "$htmlpage"
_debug3 "htmlpage: $htmlpage"
_err "FreeDNS failed to add TXT record for $subdomain. Check $HTTP_HEADER file"
return 1
elif _contains "$htmlpage" "security code was incorrect"; then
_debug "$htmlpage"
_debug3 "htmlpage: $htmlpage"
_err "FreeDNS failed to add TXT record for $subdomain as FreeDNS requested security code"
_err "Note that you cannot use automatic DNS validation for FreeDNS public domains"
return 1
fi
_debug2 "$htmlpage"
_debug3 "htmlpage: $htmlpage"
_info "Added acme challenge TXT record for $fulldomain at FreeDNS"
return 0
}
@@ -365,7 +316,7 @@ _freedns_delete_txt_record() {
_err "FreeDNS failed to delete TXT record for $data_id bad RC from _get"
return 1
elif ! _contains "$htmlheader" "200 OK"; then
_debug "$htmlheader"
_debug2 "htmlheader: $htmlheader"
_err "FreeDNS failed to delete TXT record $data_id"
return 1
fi

View File

@@ -11,7 +11,7 @@
#
######## Public functions #####################
GANDI_LIVEDNS_API="https://dns.beta.gandi.net/api/v5"
GANDI_LIVEDNS_API="https://dns.api.gandi.net/api/v5"
#Usage: dns_gandi_livedns_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_gandi_livedns_add() {

View File

@@ -15,6 +15,8 @@ dns_gd_add() {
fulldomain=$1
txtvalue=$2
GD_Key="${GD_Key:-$(_readaccountconf_mutable GD_Key)}"
GD_Secret="${GD_Secret:-$(_readaccountconf_mutable GD_Secret)}"
if [ -z "$GD_Key" ] || [ -z "$GD_Secret" ]; then
GD_Key=""
GD_Secret=""
@@ -24,8 +26,8 @@ dns_gd_add() {
fi
#save the api key and email to the account conf file.
_saveaccountconf GD_Key "$GD_Key"
_saveaccountconf GD_Secret "$GD_Secret"
_saveaccountconf_mutable GD_Key "$GD_Key"
_saveaccountconf_mutable GD_Secret "$GD_Secret"
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
@@ -36,8 +38,27 @@ dns_gd_add() {
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
_debug "Getting existing records"
if ! _gd_rest GET "domains/$_domain/records/TXT/$_sub_domain"; then
return 1
fi
if _contains "$response" "$txtvalue"; then
_info "The record is existing, skip"
return 0
fi
_add_data="{\"data\":\"$txtvalue\"}"
for t in $(echo "$response" | tr '{' "\n" | grep "\"name\":\"$_sub_domain\"" | tr ',' "\n" | grep '"data"' | cut -d : -f 2); do
_debug2 t "$t"
if [ "$t" ]; then
_add_data="$_add_data,{\"data\":$t}"
fi
done
_debug2 _add_data "$_add_data"
_info "Adding record"
if _gd_rest PUT "domains/$_domain/records/TXT/$_sub_domain" "[{\"data\":\"$txtvalue\"}]"; then
if _gd_rest PUT "domains/$_domain/records/TXT/$_sub_domain" "[$_add_data]"; then
if [ "$response" = "{}" ]; then
_info "Added, sleeping 10 seconds"
_sleep 10
@@ -56,7 +77,47 @@ dns_gd_add() {
#fulldomain
dns_gd_rm() {
fulldomain=$1
txtvalue=$2
GD_Key="${GD_Key:-$(_readaccountconf_mutable GD_Key)}"
GD_Secret="${GD_Secret:-$(_readaccountconf_mutable GD_Secret)}"
_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 "Getting existing records"
if ! _gd_rest GET "domains/$_domain/records/TXT/$_sub_domain"; then
return 1
fi
if ! _contains "$response" "$txtvalue"; then
_info "The record is not existing, skip"
return 0
fi
_add_data=""
for t in $(echo "$response" | tr '{' "\n" | grep "\"name\":\"$_sub_domain\"" | tr ',' "\n" | grep '"data"' | cut -d : -f 2); do
_debug2 t "$t"
if [ "$t" ] && [ "$t" != "\"$txtvalue\"" ]; then
if [ "$_add_data" ]; then
_add_data="$_add_data,{\"data\":$t}"
else
_add_data="{\"data\":$t}"
fi
fi
done
if [ -z "$_add_data" ]; then
_add_data="{\"data\":\"\"}"
fi
_debug2 _add_data "$_add_data"
_gd_rest PUT "domains/$_domain/records/TXT/$_sub_domain" "[$_add_data]"
}
#################### Private functions below ##################################

158
dnsapi/dns_he.sh Executable file
View File

@@ -0,0 +1,158 @@
#!/usr/bin/env sh
########################################################################
# Hurricane Electric hook script for acme.sh
#
# Environment variables:
#
# - $HE_Username (your dns.he.net username)
# - $HE_Password (your dns.he.net password)
#
# Author: Ondrej Simek <me@ondrejsimek.com>
# Git repo: https://github.com/angel333/acme.sh
#-- dns_he_add() - Add TXT record --------------------------------------
# Usage: dns_he_add _acme-challenge.subdomain.domain.com "XyZ123..."
dns_he_add() {
_full_domain=$1
_txt_value=$2
_info "Using DNS-01 Hurricane Electric hook"
HE_Username="${HE_Username:-$(_readaccountconf_mutable HE_Username)}"
HE_Password="${HE_Password:-$(_readaccountconf_mutable HE_Password)}"
if [ -z "$HE_Username" ] || [ -z "$HE_Password" ]; then
HE_Username=
HE_Password=
_err "No auth details provided. Please set user credentials using the \$HE_Username and \$HE_Password envoronment variables."
return 1
fi
_saveaccountconf_mutable HE_Username "$HE_Username"
_saveaccountconf_mutable HE_Password "$HE_Password"
# Fills in the $_zone_id
_find_zone "$_full_domain" || return 1
_debug "Zone id \"$_zone_id\" will be used."
body="email=${HE_Username}&pass=${HE_Password}"
body="$body&account="
body="$body&menu=edit_zone"
body="$body&Type=TXT"
body="$body&hosted_dns_zoneid=$_zone_id"
body="$body&hosted_dns_recordid="
body="$body&hosted_dns_editzone=1"
body="$body&Priority="
body="$body&Name=$_full_domain"
body="$body&Content=$_txt_value"
body="$body&TTL=300"
body="$body&hosted_dns_editrecord=Submit"
response="$(_post "$body" "https://dns.he.net/")"
exit_code="$?"
if [ "$exit_code" -eq 0 ]; then
_info "TXT record added successfully."
else
_err "Couldn't add the TXT record."
fi
_debug2 response "$response"
return "$exit_code"
}
#-- dns_he_rm() - Remove TXT record ------------------------------------
# Usage: dns_he_rm _acme-challenge.subdomain.domain.com "XyZ123..."
dns_he_rm() {
_full_domain=$1
_txt_value=$2
_info "Cleaning up after DNS-01 Hurricane Electric hook"
HE_Username="${HE_Username:-$(_readaccountconf_mutable HE_Username)}"
HE_Password="${HE_Password:-$(_readaccountconf_mutable HE_Password)}"
# fills in the $_zone_id
_find_zone "$_full_domain" || return 1
_debug "Zone id \"$_zone_id\" will be used."
# Find the record id to clean
body="email=${HE_Username}&pass=${HE_Password}"
body="$body&hosted_dns_zoneid=$_zone_id"
body="$body&menu=edit_zone"
body="$body&hosted_dns_editzone="
response="$(_post "$body" "https://dns.he.net/")"
_debug2 "response" "$response"
if ! _contains "$response" "$_txt_value"; then
_debug "The txt record is not found, just skip"
return 0
fi
_record_id="$(echo "$response" | tr -d "#" | sed "s/<tr/#<tr/g" | tr -d "\n" | tr "#" "\n" | grep "$_full_domain" | grep '"dns_tr"' | grep "$_txt_value" | cut -d '"' -f 4)"
_debug2 _record_id "$_record_id"
if [ -z "$_record_id" ]; then
_err "Can not find record id"
return 1
fi
# Remove the record
body="email=${HE_Username}&pass=${HE_Password}"
body="$body&menu=edit_zone"
body="$body&hosted_dns_zoneid=$_zone_id"
body="$body&hosted_dns_recordid=$_record_id"
body="$body&hosted_dns_editzone=1"
body="$body&hosted_dns_delrecord=1"
body="$body&hosted_dns_delconfirm=delete"
_post "$body" "https://dns.he.net/" \
| grep '<div id="dns_status" onClick="hideThis(this);">Successfully removed record.</div>' \
>/dev/null
exit_code="$?"
if [ "$exit_code" -eq 0 ]; then
_info "Record removed successfully."
else
_err "Could not clean (remove) up the record. Please go to HE administration interface and clean it by hand."
return "$exit_code"
fi
}
########################## PRIVATE FUNCTIONS ###########################
_find_zone() {
_domain="$1"
body="email=${HE_Username}&pass=${HE_Password}"
response="$(_post "$body" "https://dns.he.net/")"
_debug2 response "$response"
_table="$(echo "$response" | tr -d "#" | sed "s/<table/#<table/g" | tr -d "\n" | tr "#" "\n" | grep 'id="domains_table"')"
_debug2 _table "$_table"
_matches="$(echo "$_table" | sed "s/<tr/#<tr/g" | tr "#" "\n" | grep 'alt="edit"' | tr -d " " | sed "s/<td/#<td/g" | tr "#" "\n" | grep 'hosted_dns_zoneid')"
_debug2 _matches "$_matches"
# Zone names and zone IDs are in same order
_zone_ids=$(echo "$_matches" | _egrep_o "hosted_dns_zoneid=[0-9]*&" | cut -d = -f 2 | tr -d '&')
_zone_names=$(echo "$_matches" | _egrep_o "name=.*onclick" | cut -d '"' -f 2)
_debug2 "These are the zones on this HE account:"
_debug2 "$_zone_names"
_debug2 "And these are their respective IDs:"
_debug2 "$_zone_ids"
if [ -z "$_zone_names" ] || [ -z "$_zone_ids" ]; then
_err "Can not get zone names."
return 1
fi
# Walk through all possible zone names
_strip_counter=1
while true; do
_attempted_zone=$(echo "$_domain" | cut -d . -f ${_strip_counter}-)
# All possible zone names have been tried
if [ -z "$_attempted_zone" ]; then
_err "No zone for domain \"$_domain\" found."
return 1
fi
_debug "Looking for zone \"${_attempted_zone}\""
line_num="$(echo "$_zone_names" | grep -n "$_attempted_zone" | cut -d : -f 1)"
if [ "$line_num" ]; then
_zone_id=$(echo "$_zone_ids" | sed -n "${line_num}p")
_debug "Found relevant zone \"$_attempted_zone\" with id \"$_zone_id\" - will be used for domain \"$_domain\"."
return 0
fi
_debug "Zone \"$_attempted_zone\" doesn't exist, let's try a less specific zone."
_strip_counter=$(_math "$_strip_counter" + 1)
done
}
# vim: et:ts=2:sw=2:

View File

@@ -41,10 +41,10 @@ dns_infoblox_add() {
export _H2="Authorization: Basic $Infoblox_CredsEncoded"
## Add the challenge record to the Infoblox grid member
result=$(_post "" "$baseurlnObject" "" "POST")
result="$(_post "" "$baseurlnObject" "" "POST")"
## Let's see if we get something intelligible back from the unit
if echo "$result" | egrep "record:txt/.*:.*/$Infoblox_View"; then
if [ "$(echo "$result" | _egrep_o "record:txt/.*:.*/$Infoblox_View")" ]; then
_info "Successfully created the txt record"
return 0
else
@@ -66,7 +66,7 @@ dns_infoblox_rm() {
_debug txtvalue "$txtvalue"
## Base64 encode the credentials
Infoblox_CredsEncoded=$(printf "%b" "$Infoblox_Creds" | _base64)
Infoblox_CredsEncoded="$(printf "%b" "$Infoblox_Creds" | _base64)"
## Construct the HTTP Authorization header
export _H1="Accept-Language:en-US"
@@ -74,17 +74,17 @@ dns_infoblox_rm() {
## Does the record exist? Let's check.
baseurlnObject="https://$Infoblox_Server/wapi/v2.2.2/record:txt?name=$fulldomain&text=$txtvalue&view=$Infoblox_View&_return_type=xml-pretty"
result=$(_get "$baseurlnObject")
result="$(_get "$baseurlnObject")"
## Let's see if we get something intelligible back from the grid
if echo "$result" | egrep "record:txt/.*:.*/$Infoblox_View"; then
if [ "$(echo "$result" | _egrep_o "record:txt/.*:.*/$Infoblox_View")" ]; then
## Extract the object reference
objRef=$(printf "%b" "$result" | _egrep_o "record:txt/.*:.*/$Infoblox_View")
objRef="$(printf "%b" "$result" | _egrep_o "record:txt/.*:.*/$Infoblox_View")"
objRmUrl="https://$Infoblox_Server/wapi/v2.2.2/$objRef"
## Delete them! All the stale records!
rmResult=$(_post "" "$objRmUrl" "" "DELETE")
rmResult="$(_post "" "$objRmUrl" "" "DELETE")"
## Let's see if that worked
if echo "$rmResult" | egrep "record:txt/.*:.*/$Infoblox_View"; then
if [ "$(echo "$rmResult" | _egrep_o "record:txt/.*:.*/$Infoblox_View")" ]; then
_info "Successfully deleted $objRef"
return 0
else

311
dnsapi/dns_inwx.sh Executable file
View File

@@ -0,0 +1,311 @@
#!/usr/bin/env sh
#
#INWX_User="username"
#
#INWX_Password="password"
INWX_Api="https://api.domrobot.com/xmlrpc/"
######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_inwx_add() {
fulldomain=$1
txtvalue=$2
INWX_User="${INWX_User:-$(_readaccountconf_mutable INWX_User)}"
INWX_Password="${INWX_Password:-$(_readaccountconf_mutable INWX_Password)}"
if [ -z "$INWX_User" ] || [ -z "$INWX_Password" ]; then
INWX_User=""
INWX_Password=""
_err "You don't specify inwx user and password yet."
_err "Please create you key and try again."
return 1
fi
#save the api key and email to the account conf file.
_saveaccountconf_mutable INWX_User "$INWX_User"
_saveaccountconf_mutable INWX_Password "$INWX_Password"
_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"
_inwx_add_record "$_domain" "$_sub_domain" "$txtvalue"
}
#fulldomain txtvalue
dns_inwx_rm() {
fulldomain=$1
txtvalue=$2
INWX_User="${INWX_User:-$(_readaccountconf_mutable INWX_User)}"
INWX_Password="${INWX_Password:-$(_readaccountconf_mutable INWX_Password)}"
if [ -z "$INWX_User" ] || [ -z "$INWX_Password" ]; then
INWX_User=""
INWX_Password=""
_err "You don't specify inwx user and password yet."
_err "Please create you key and try again."
return 1
fi
#save the api key and email to the account conf file.
_saveaccountconf_mutable INWX_User "$INWX_User"
_saveaccountconf_mutable INWX_Password "$INWX_Password"
_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 "Getting txt records"
xml_content=$(printf '<?xml version="1.0" encoding="UTF-8"?>
<methodCall>
<methodName>nameserver.info</methodName>
<params>
<param>
<value>
<struct>
<member>
<name>domain</name>
<value>
<string>%s</string>
</value>
</member>
<member>
<name>type</name>
<value>
<string>TXT</string>
</value>
</member>
<member>
<name>name</name>
<value>
<string>%s</string>
</value>
</member>
</struct>
</value>
</param>
</params>
</methodCall>' "$_domain" "$_sub_domain")
response="$(_post "$xml_content" "$INWX_Api" "" "POST")"
if ! _contains "$response" "Command completed successfully"; then
_err "Error could not get txt records"
return 1
fi
if ! printf "%s" "$response" | grep "count" >/dev/null; then
_info "Do not need to delete record"
else
_record_id=$(printf '%s' "$response" | _egrep_o '.*(<member><name>record){1}(.*)([0-9]+){1}' | _egrep_o '<name>id<\/name><value><int>[0-9]+' | _egrep_o '[0-9]+')
_info "Deleting record"
_inwx_delete_record "$_record_id"
fi
}
#################### Private functions below ##################################
_inwx_login() {
xml_content=$(printf '<?xml version="1.0" encoding="UTF-8"?>
<methodCall>
<methodName>account.login</methodName>
<params>
<param>
<value>
<struct>
<member>
<name>user</name>
<value>
<string>%s</string>
</value>
</member>
<member>
<name>pass</name>
<value>
<string>%s</string>
</value>
</member>
</struct>
</value>
</param>
</params>
</methodCall>' $INWX_User $INWX_Password)
response="$(_post "$xml_content" "$INWX_Api" "" "POST")"
printf "Cookie: %s" "$(grep "domrobot=" "$HTTP_HEADER" | grep "^Set-Cookie:" | _tail_n 1 | _egrep_o 'domrobot=[^;]*;' | tr -d ';')"
}
_get_root() {
domain=$1
_debug "get root"
domain=$1
i=2
p=1
_H1=$(_inwx_login)
export _H1
xml_content='<?xml version="1.0" encoding="UTF-8"?>
<methodCall>
<methodName>nameserver.list</methodName>
</methodCall>'
response="$(_post "$xml_content" "$INWX_Api" "" "POST")"
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 _contains "$response" "$h"; 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
}
_inwx_delete_record() {
record_id=$1
xml_content=$(printf '<?xml version="1.0" encoding="UTF-8"?>
<methodCall>
<methodName>nameserver.deleteRecord</methodName>
<params>
<param>
<value>
<struct>
<member>
<name>id</name>
<value>
<int>%s</int>
</value>
</member>
</struct>
</value>
</param>
</params>
</methodCall>' "$record_id")
response="$(_post "$xml_content" "$INWX_Api" "" "POST")"
if ! printf "%s" "$response" | grep "Command completed successfully" >/dev/null; then
_err "Error"
return 1
fi
return 0
}
_inwx_update_record() {
record_id=$1
txtval=$2
xml_content=$(printf '<?xml version="1.0" encoding="UTF-8"?>
<methodCall>
<methodName>nameserver.updateRecord</methodName>
<params>
<param>
<value>
<struct>
<member>
<name>content</name>
<value>
<string>%s</string>
</value>
</member>
<member>
<name>id</name>
<value>
<int>%s</int>
</value>
</member>
</struct>
</value>
</param>
</params>
</methodCall>' "$txtval" "$record_id")
response="$(_post "$xml_content" "$INWX_Api" "" "POST")"
if ! printf "%s" "$response" | grep "Command completed successfully" >/dev/null; then
_err "Error"
return 1
fi
return 0
}
_inwx_add_record() {
domain=$1
sub_domain=$2
txtval=$3
xml_content=$(printf '<?xml version="1.0" encoding="UTF-8"?>
<methodCall>
<methodName>nameserver.createRecord</methodName>
<params>
<param>
<value>
<struct>
<member>
<name>domain</name>
<value>
<string>%s</string>
</value>
</member>
<member>
<name>type</name>
<value>
<string>TXT</string>
</value>
</member>
<member>
<name>content</name>
<value>
<string>%s</string>
</value>
</member>
<member>
<name>name</name>
<value>
<string>%s</string>
</value>
</member>
</struct>
</value>
</param>
</params>
</methodCall>' "$domain" "$txtval" "$sub_domain")
response="$(_post "$xml_content" "$INWX_Api" "" "POST")"
if ! printf "%s" "$response" | grep "Command completed successfully" >/dev/null; then
_err "Error"
return 1
fi
return 0
}

View File

@@ -2,7 +2,6 @@
# ISPConfig 3.1 API
# User must provide login data and URL to the ISPConfig installation incl. port. The remote user in ISPConfig must have access to:
# - DNS zone Functions
# - DNS txt Functions
# Report bugs to https://github.com/sjau/acme.sh

View File

@@ -68,7 +68,7 @@ dns_linode_rm() {
_parameters="&DomainID=$_domain_id"
if _rest GET "domain.resource.list" "$_parameters" && [ -n "$response" ]; then
response="$(echo "$response" | tr -d "\n" | sed 's/{/\n&/g')"
response="$(echo "$response" | tr -d "\n" | tr '{' "|" | sed 's/|/&{/g' | tr "|" "\n")"
resource="$(echo "$response" | _egrep_o "{.*\"NAME\":\s*\"$_sub_domain\".*}")"
if [ "$resource" ]; then
@@ -128,7 +128,7 @@ _get_root() {
p=1
if _rest GET "domain.list"; then
response="$(echo "$response" | tr -d "\n" | sed 's/{/\n&/g')"
response="$(echo "$response" | tr -d "\n" | tr '{' "|" | sed 's/|/&{/g' | tr "|" "\n")"
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
_debug h "$h"

View File

@@ -8,7 +8,6 @@
#LUA_Email="user@luadns.net"
LUA_Api="https://api.luadns.com/v1"
LUA_auth=$(printf "%s" "$LUA_Email:$LUA_Key" | _base64)
######## Public functions #####################
@@ -17,6 +16,10 @@ dns_lua_add() {
fulldomain=$1
txtvalue=$2
LUA_Key="${LUA_Key:-$(_readaccountconf_mutable LUA_Key)}"
LUA_Email="${LUA_Email:-$(_readaccountconf_mutable LUA_Email)}"
LUA_auth=$(printf "%s" "$LUA_Email:$LUA_Key" | _base64)
if [ -z "$LUA_Key" ] || [ -z "$LUA_Email" ]; then
LUA_Key=""
LUA_Email=""
@@ -26,8 +29,8 @@ dns_lua_add() {
fi
#save the api key and email to the account conf file.
_saveaccountconf LUA_Key "$LUA_Key"
_saveaccountconf LUA_Email "$LUA_Email"
_saveaccountconf_mutable LUA_Key "$LUA_Key"
_saveaccountconf_mutable LUA_Email "$LUA_Email"
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
@@ -38,50 +41,27 @@ dns_lua_add() {
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
_debug "Getting txt records"
_LUA_rest GET "zones/${_domain_id}/records"
if ! _contains "$response" "\"id\":"; then
_err "Error"
return 1
fi
count=$(printf "%s\n" "$response" | _egrep_o "\"name\":\"$fulldomain.\",\"type\":\"TXT\"" | wc -l | tr -d " ")
_debug count "$count"
if [ "$count" = "0" ]; then
_info "Adding record"
if _LUA_rest POST "zones/$_domain_id/records" "{\"type\":\"TXT\",\"name\":\"$fulldomain.\",\"content\":\"$txtvalue\",\"ttl\":120}"; then
if _contains "$response" "$fulldomain"; then
_info "Added"
#todo: check if the record takes effect
return 0
else
_err "Add txt record error."
return 1
fi
fi
_err "Add txt record error."
else
_info "Updating record"
record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[^,]*,\"name\":\"$fulldomain.\",\"type\":\"TXT\"" | _head_n 1 | cut -d: -f2 | cut -d, -f1)
_debug "record_id" "$record_id"
_LUA_rest PUT "zones/$_domain_id/records/$record_id" "{\"id\":$record_id,\"type\":\"TXT\",\"name\":\"$fulldomain.\",\"content\":\"$txtvalue\",\"zone_id\":$_domain_id,\"ttl\":120}"
if [ "$?" = "0" ] && _contains "$response" "updated_at"; then
_info "Updated!"
_info "Adding record"
if _LUA_rest POST "zones/$_domain_id/records" "{\"type\":\"TXT\",\"name\":\"$fulldomain.\",\"content\":\"$txtvalue\",\"ttl\":120}"; then
if _contains "$response" "$fulldomain"; then
_info "Added"
#todo: check if the record takes effect
return 0
else
_err "Add txt record error."
return 1
fi
_err "Update error"
return 1
fi
}
#fulldomain
dns_lua_rm() {
fulldomain=$1
txtvalue=$2
LUA_Key="${LUA_Key:-$(_readaccountconf_mutable LUA_Key)}"
LUA_Email="${LUA_Email:-$(_readaccountconf_mutable LUA_Email)}"
LUA_auth=$(printf "%s" "$LUA_Email:$LUA_Key" | _base64)
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"

View File

@@ -43,34 +43,16 @@ dns_me_add() {
return 1
fi
count=$(printf "%s\n" "$response" | _egrep_o "\"totalRecords\":[^,]*" | cut -d : -f 2)
_debug count "$count"
if [ "$count" = "0" ]; then
_info "Adding record"
if _me_rest POST "$_domain_id/records/" "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"value\":\"$txtvalue\",\"gtdLocation\":\"DEFAULT\",\"ttl\":120}"; then
if printf -- "%s" "$response" | grep \"id\": >/dev/null; then
_info "Added"
#todo: check if the record takes effect
return 0
else
_err "Add txt record error."
return 1
fi
fi
_err "Add txt record error."
else
_info "Updating record"
record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[^,]*" | cut -d : -f 2 | head -n 1)
_debug "record_id" "$record_id"
_me_rest PUT "$_domain_id/records/$record_id/" "{\"id\":\"$record_id\",\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"value\":\"$txtvalue\",\"gtdLocation\":\"DEFAULT\",\"ttl\":120}"
if [ "$?" = "0" ]; then
_info "Updated"
_info "Adding record"
if _me_rest POST "$_domain_id/records/" "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"value\":\"$txtvalue\",\"gtdLocation\":\"DEFAULT\",\"ttl\":120}"; then
if printf -- "%s" "$response" | grep \"id\": >/dev/null; then
_info "Added"
#todo: check if the record takes effect
return 0
else
_err "Add txt record error."
return 1
fi
_err "Update error"
return 1
fi
}
@@ -96,7 +78,7 @@ dns_me_rm() {
if [ "$count" = "0" ]; then
_info "Don't need to remove."
else
record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[^,]*" | cut -d : -f 2 | head -n 1)
record_id=$(printf "%s\n" "$response" | _egrep_o ",\"value\":\"..$txtvalue..\",\"id\":[^,]*" | cut -d : -f 3 | head -n 1)
_debug "record_id" "$record_id"
if [ -z "$record_id" ]; then
_err "Can not get record id to remove."
@@ -152,7 +134,7 @@ _me_rest() {
data="$3"
_debug "$ep"
cdate=$(date -u +"%a, %d %b %Y %T %Z")
cdate=$(LANG=C date -u +"%a, %d %b %Y %T %Z")
hmac=$(printf "%s" "$cdate" | _hmac sha1 "$(printf "%s" "$ME_Secret" | _hex_dump | tr -d " ")" hex)
export _H1="x-dnsme-apiKey: $ME_Key"

166
dnsapi/dns_namecom.sh Executable file
View File

@@ -0,0 +1,166 @@
#!/usr/bin/env sh
#Author: RaidenII
#Created 06/28/2017
#Updated 03/01/2018, rewrote to support name.com API v4
#Utilize name.com API to finish dns-01 verifications.
######## Public functions #####################
Namecom_API="https://api.name.com/v4"
#Usage: dns_namecom_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_namecom_add() {
fulldomain=$1
txtvalue=$2
# First we need name.com credentials.
if [ -z "$Namecom_Username" ]; then
Namecom_Username=""
_err "Username for name.com is missing."
_err "Please specify that in your environment variable."
return 1
fi
if [ -z "$Namecom_Token" ]; then
Namecom_Token=""
_err "API token for name.com is missing."
_err "Please specify that in your environment variable."
return 1
fi
# Save them in configuration.
_saveaccountconf Namecom_Username "$Namecom_Username"
_saveaccountconf Namecom_Token "$Namecom_Token"
# Login in using API
if ! _namecom_login; then
return 1
fi
# Find domain in domain list.
if ! _namecom_get_root "$fulldomain"; then
_err "Unable to find domain specified."
return 1
fi
# 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\"")
if [ "$_retvalue" ]; then
_info "Successfully added TXT record, ready for validation."
return 0
else
_err "Unable to add the DNS record."
return 1
fi
fi
}
#Usage: fulldomain txtvalue
#Remove the txt record after validation.
dns_namecom_rm() {
fulldomain=$1
txtvalue=$2
if ! _namecom_login; then
return 1
fi
# Find domain in domain list.
if ! _namecom_get_root "$fulldomain"; then
_err "Unable to find domain specified."
return 1
fi
# 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]+)
_debug record_id "$_record_id"
if [ "$_record_id" ]; then
_info "Successfully retrieved the record id for ACME challenge."
else
_err "Unable to retrieve the record id."
return 1
fi
fi
# Remove the DNS record using record id.
if _namecom_rest DELETE "domains/$_domain/records/$_record_id"; then
_info "Successfully removed the TXT record."
return 0
else
_err "Unable to delete record id."
return 1
fi
}
#################### Private functions below ##################################
_namecom_rest() {
method=$1
param=$2
data=$3
export _H1="Authorization: Basic $_namecom_auth"
export _H2="Content-Type: application/json"
if [ "$method" != "GET" ]; then
response="$(_post "$data" "$Namecom_API/$param" "" "$method")"
else
response="$(_get "$Namecom_API/$param")"
fi
if [ "$?" != "0" ]; then
_err "error $param"
return 1
fi
_debug2 response "$response"
return 0
}
_namecom_login() {
# Auth string
# Name.com API v4 uses http basic auth to authenticate
# need to convert the token for http auth
_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\"")
if [ "$retcode" ]; then
_info "Successfully logged in."
else
_err "Logging in failed."
return 1
fi
fi
}
_namecom_get_root() {
domain=$1
i=2
p=1
if ! _namecom_rest GET "domains"; then
return 1
fi
# Need to exclude the last field (tld)
numfields=$(echo "$domain" | _egrep_o "\." | wc -l)
while [ $i -le "$numfields" ]; do
host=$(printf "%s" "$domain" | cut -d . -f $i-100)
_debug host "$host"
if [ -z "$host" ]; then
return 1
fi
if _contains "$response" "$host"; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_domain="$host"
return 0
fi
p=$i
i=$(_math "$i" + 1)
done
return 1
}

137
dnsapi/dns_namesilo.sh Executable file
View File

@@ -0,0 +1,137 @@
#!/usr/bin/env sh
#Author: meowthink
#Created 01/14/2017
#Utilize namesilo.com API to finish dns-01 verifications.
Namesilo_API="https://www.namesilo.com/api"
######## Public functions #####################
#Usage: dns_myapi_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_namesilo_add() {
fulldomain=$1
txtvalue=$2
if [ -z "$Namesilo_Key" ]; then
Namesilo_Key=""
_err "API token for namesilo.com is missing."
_err "Please specify that in your environment variable."
return 1
fi
#save the api key and email to the account conf file.
_saveaccountconf Namesilo_Key "$Namesilo_Key"
if ! _get_root "$fulldomain"; then
_err "Unable to find domain specified."
return 1
fi
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
_debug txtvalue "$txtvalue"
if _namesilo_rest GET "dnsAddRecord?version=1&type=xml&key=$Namesilo_Key&domain=$_domain&rrtype=TXT&rrhost=$_sub_domain&rrvalue=$txtvalue"; then
retcode=$(printf "%s\n" "$response" | _egrep_o "<code>300")
if [ "$retcode" ]; then
_info "Successfully added TXT record, ready for validation."
return 0
else
_err "Unable to add the DNS record."
return 1
fi
fi
}
#Usage: fulldomain txtvalue
#Remove the txt record after validation.
dns_namesilo_rm() {
fulldomain=$1
txtvalue=$2
if ! _get_root "$fulldomain"; then
_err "Unable to find domain specified."
return 1
fi
# Get the record id.
if _namesilo_rest GET "dnsListRecords?version=1&type=xml&key=$Namesilo_Key&domain=$_domain"; then
retcode=$(printf "%s\n" "$response" | _egrep_o "<code>300")
if [ "$retcode" ]; then
_record_id=$(printf "%s\n" "$response" | _egrep_o "<record_id>([^<]*)</record_id><type>TXT</type><host>$fulldomain</host>" | _egrep_o "<record_id>([^<]*)</record_id>" | sed -r "s/<record_id>([^<]*)<\/record_id>/\1/" | tail -n 1)
_debug record_id "$_record_id"
_info "Successfully retrieved the record id for ACME challenge."
else
_err "Unable to retrieve the record id."
return 1
fi
fi
# Remove the DNS record using record id.
if _namesilo_rest GET "dnsDeleteRecord?version=1&type=xml&key=$Namesilo_Key&domain=$_domain&rrid=$_record_id"; then
retcode=$(printf "%s\n" "$response" | _egrep_o "<code>300")
if [ "$retcode" ]; then
_info "Successfully removed the TXT record."
return 0
else
_err "Unable to remove the DNS record."
return 1
fi
fi
}
#################### 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
if ! _namesilo_rest GET "listDomains?version=1&type=xml&key=$Namesilo_Key"; then
return 1
fi
# Need to exclude the last field (tld)
numfields=$(echo "$domain" | _egrep_o "\." | wc -l)
while [ $i -le "$numfields" ]; do
host=$(printf "%s" "$domain" | cut -d . -f $i-100)
_debug host "$host"
if [ -z "$host" ]; then
return 1
fi
if _contains "$response" "$host"; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_domain="$host"
return 0
fi
p=$i
i=$(_math "$i" + 1)
done
return 1
}
_namesilo_rest() {
method=$1
param=$2
data=$3
if [ "$method" != "GET" ]; then
response="$(_post "$data" "$Namesilo_API/$param" "" "$method")"
else
response="$(_get "$Namesilo_API/$param")"
fi
if [ "$?" != "0" ]; then
_err "error $param"
return 1
fi
_debug2 response "$response"
return 0
}

View File

@@ -59,10 +59,10 @@ dns_nsone_add() {
_err "Add txt record error."
else
_info "Updating record"
record_id=$(printf "%s\n" "$response" | _egrep_o "\"domain\":\"$fulldomain.\",[^{]*\"type\":\"TXT\",\"id\":\"[^,]*\"" | _head_n 1 | cut -d: -f7 | cut -d, -f1)
_debug "record_id" "$record_id"
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\"]}],\"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\"}"
if [ "$?" = "0" ] && _contains "$response" "$fulldomain"; then
_info "Updated!"
#todo: check if the record takes effect

View File

@@ -78,12 +78,9 @@ _ovh_get_api() {
esac
}
######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_ovh_add() {
fulldomain=$1
txtvalue=$2
_initAuth() {
OVH_AK="${OVH_AK:-$(_readaccountconf_mutable OVH_AK)}"
OVH_AS="${OVH_AS:-$(_readaccountconf_mutable OVH_AS)}"
if [ -z "$OVH_AK" ] || [ -z "$OVH_AS" ]; then
OVH_AK=""
@@ -93,21 +90,26 @@ dns_ovh_add() {
return 1
fi
#save the api key and email to the account conf file.
_saveaccountconf OVH_AK "$OVH_AK"
_saveaccountconf OVH_AS "$OVH_AS"
if [ "$OVH_AK" != "$(_readaccountconf OVH_AK)" ]; then
_info "It seems that your ovh key is changed, let's clear consumer key first."
_clearaccountconf OVH_CK
fi
_saveaccountconf_mutable OVH_AK "$OVH_AK"
_saveaccountconf_mutable OVH_AS "$OVH_AS"
OVH_END_POINT="${OVH_END_POINT:-$(_readaccountconf_mutable OVH_END_POINT)}"
if [ -z "$OVH_END_POINT" ]; then
OVH_END_POINT="ovh-eu"
fi
_info "Using OVH endpoint: $OVH_END_POINT"
if [ "$OVH_END_POINT" != "ovh-eu" ]; then
_saveaccountconf OVH_END_POINT "$OVH_END_POINT"
_saveaccountconf_mutable OVH_END_POINT "$OVH_END_POINT"
fi
OVH_API="$(_ovh_get_api $OVH_END_POINT)"
_debug OVH_API "$OVH_API"
OVH_CK="${OVH_CK:-$(_readaccountconf_mutable OVH_CK)}"
if [ -z "$OVH_CK" ]; then
_info "OVH consumer key is empty, Let's get one:"
if ! _ovh_authentication; then
@@ -119,14 +121,26 @@ dns_ovh_add() {
_info "Checking authentication"
response="$(_ovh_rest GET "domain")"
if _contains "$response" "INVALID_CREDENTIAL"; then
if ! _ovh_rest GET "domain" || _contains "$response" "INVALID_CREDENTIAL"; then
_err "The consumer key is invalid: $OVH_CK"
_err "Please retry to create a new one."
_clearaccountconf OVH_CK
return 1
fi
_info "Consumer key is ok."
return 0
}
######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_ovh_add() {
fulldomain=$1
txtvalue=$2
if ! _initAuth; then
return 1
fi
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
@@ -137,49 +151,58 @@ dns_ovh_add() {
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
_debug "Getting txt records"
_ovh_rest GET "domain/zone/$_domain/record?fieldType=TXT&subDomain=$_sub_domain"
if _contains "$response" '\[\]' || _contains "$response" "This service does not exist"; then
_info "Adding record"
if _ovh_rest POST "domain/zone/$_domain/record" "{\"fieldType\":\"TXT\",\"subDomain\":\"$_sub_domain\",\"target\":\"$txtvalue\",\"ttl\":60}"; then
if _contains "$response" "$txtvalue"; then
_ovh_rest POST "domain/zone/$_domain/refresh"
_debug "Refresh:$response"
_info "Added, sleeping 10 seconds"
sleep 10
return 0
fi
_info "Adding record"
if _ovh_rest POST "domain/zone/$_domain/record" "{\"fieldType\":\"TXT\",\"subDomain\":\"$_sub_domain\",\"target\":\"$txtvalue\",\"ttl\":60}"; then
if _contains "$response" "$txtvalue"; then
_ovh_rest POST "domain/zone/$_domain/refresh"
_debug "Refresh:$response"
_info "Added, sleep 10 seconds."
_sleep 10
return 0
fi
_err "Add txt record error."
else
_info "Updating record"
record_id=$(printf "%s" "$response" | tr -d "[]" | cut -d , -f 1)
if [ -z "$record_id" ]; then
_err "Can not get record id."
return 1
fi
_debug "record_id" "$record_id"
if _ovh_rest PUT "domain/zone/$_domain/record/$record_id" "{\"target\":\"$txtvalue\",\"subDomain\":\"$_sub_domain\",\"ttl\":60}"; then
if _contains "$response" "null"; then
_ovh_rest POST "domain/zone/$_domain/refresh"
_debug "Refresh:$response"
_info "Updated, sleeping 10 seconds"
sleep 10
return 0
fi
fi
_err "Update error"
return 1
fi
_err "Add txt record error."
return 1
}
#fulldomain
dns_ovh_rm() {
fulldomain=$1
txtvalue=$2
if ! _initAuth; 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 "Getting txt records"
if ! _ovh_rest GET "domain/zone/$_domain/record?fieldType=TXT&subDomain=$_sub_domain"; then
return 1
fi
for rid in $(echo "$response" | tr '][,' ' '); do
_debug rid "$rid"
if ! _ovh_rest GET "domain/zone/$_domain/record/$rid"; then
return 1
fi
if _contains "$response" "\"target\":\"$txtvalue\""; then
_debug "Found txt id:$rid"
if ! _ovh_rest DELETE "domain/zone/$_domain/record/$rid"; then
return 1
fi
return 0
fi
done
return 1
}
#################### Private functions below ##################################
@@ -191,7 +214,7 @@ _ovh_authentication() {
_H3=""
_H4=""
_ovhdata='{"accessRules": [{"method": "GET","path": "/auth/time"},{"method": "GET","path": "/domain"},{"method": "GET","path": "/domain/zone/*"},{"method": "GET","path": "/domain/zone/*/record"},{"method": "POST","path": "/domain/zone/*/record"},{"method": "POST","path": "/domain/zone/*/refresh"},{"method": "PUT","path": "/domain/zone/*/record/*"}],"redirection":"'$ovh_success'"}'
_ovhdata='{"accessRules": [{"method": "GET","path": "/auth/time"},{"method": "GET","path": "/domain"},{"method": "GET","path": "/domain/zone/*"},{"method": "GET","path": "/domain/zone/*/record"},{"method": "POST","path": "/domain/zone/*/record"},{"method": "POST","path": "/domain/zone/*/refresh"},{"method": "PUT","path": "/domain/zone/*/record/*"},{"method": "DELETE","path": "/domain/zone/*/record/*"}],"redirection":"'$ovh_success'"}'
response="$(_post "$_ovhdata" "$OVH_API/auth/credential")"
_debug3 response "$response"
@@ -279,15 +302,15 @@ _ovh_rest() {
export _H3="X-Ovh-Timestamp: $_ovh_t"
export _H4="X-Ovh-Consumer: $OVH_CK"
export _H5="Content-Type: application/json;charset=utf-8"
if [ "$data" ] || [ "$m" = "POST" ] || [ "$m" = "PUT" ]; then
if [ "$data" ] || [ "$m" = "POST" ] || [ "$m" = "PUT" ] || [ "$m" = "DELETE" ]; then
_debug data "$data"
response="$(_post "$data" "$_ovh_url" "" "$m")"
else
response="$(_get "$_ovh_url")"
fi
if [ "$?" != "0" ]; then
_err "error $ep"
if [ "$?" != "0" ] || _contains "$response" "INVALID_CREDENTIAL"; then
_err "error $response"
return 1
fi
_debug2 response "$response"

161
dnsapi/dns_selectel.sh Normal file
View File

@@ -0,0 +1,161 @@
#!/usr/bin/env sh
#
#SL_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"
#
SL_Api="https://api.selectel.ru/domains/v1"
######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_selectel_add() {
fulldomain=$1
txtvalue=$2
SL_Key="${SL_Key:-$(_readaccountconf_mutable SL_Key)}"
if [ -z "$SL_Key" ]; then
SL_Key=""
_err "You don't specify selectel.ru api key yet."
_err "Please create you key and try again."
return 1
fi
#save the api key to the account conf file.
_saveaccountconf_mutable SL_Key "$SL_Key"
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"
return 1
fi
_debug _domain_id "$_domain_id"
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
_info "Adding record"
if _sl_rest POST "/$_domain_id/records/" "{\"type\": \"TXT\", \"ttl\": 60, \"name\": \"$fulldomain\", \"content\": \"$txtvalue\"}"; then
if _contains "$response" "$txtvalue" || _contains "$response" "record_already_exists"; then
_info "Added, OK"
return 0
fi
fi
_err "Add txt record error."
return 1
}
#fulldomain txtvalue
dns_selectel_rm() {
fulldomain=$1
txtvalue=$2
SL_Key="${SL_Key:-$(_readaccountconf_mutable SL_Key)}"
if [ -z "$SL_Key" ]; then
SL_Key=""
_err "You don't specify slectel api key yet."
_err "Please create you key and try again."
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"
_sl_rest GET "/${_domain_id}/records/"
if ! _contains "$response" "$txtvalue"; then
_err "Txt record not found"
return 1
fi
_record_seg="$(echo "$response" | _egrep_o "\"content\" *: *\"$txtvalue\"[^}]*}")"
_debug2 "_record_seg" "$_record_seg"
if [ -z "$_record_seg" ]; then
_err "can not find _record_seg"
return 1
fi
_record_id="$(echo "$_record_seg" | tr "," "\n" | tr "}" "\n" | tr -d " " | grep "\"id\"" | cut -d : -f 2)"
_debug2 "_record_id" "$_record_id"
if [ -z "$_record_id" ]; then
_err "can not find _record_id"
return 1
fi
if ! _sl_rest DELETE "/$_domain_id/records/$_record_id"; then
_err "Delete record error."
return 1
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() {
domain=$1
if ! _sl_rest GET "/"; then
return 1
fi
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 _contains "$response" "\"name\": \"$h\","; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_domain=$h
_debug "Getting domain id for $h"
if ! _sl_rest GET "/$h"; then
return 1
fi
_domain_id="$(echo "$response" | tr "," "\n" | tr "}" "\n" | tr -d " " | grep "\"id\":" | cut -d : -f 2)"
return 0
fi
p=$i
i=$(_math "$i" + 1)
done
return 1
}
_sl_rest() {
m=$1
ep="$2"
data="$3"
_debug "$ep"
export _H1="X-Token: $SL_Key"
export _H2="Content-Type: application/json"
if [ "$m" != "GET" ]; then
_debug data "$data"
response="$(_post "$data" "$SL_Api/$ep" "" "$m")"
else
response="$(_get "$SL_Api/$ep")"
fi
if [ "$?" != "0" ]; then
_err "error $ep"
return 1
fi
_debug2 response "$response"
return 0
}

170
dnsapi/dns_servercow.sh Executable file
View File

@@ -0,0 +1,170 @@
#!/usr/bin/env sh
##########
# Custom servercow.de DNS API v1 for use with [acme.sh](https://github.com/Neilpang/acme.sh)
#
# Usage:
# export SERVERCOW_API_Username=username
# export SERVERCOW_API_Password=password
# acme.sh --issue -d example.com --dns dns_servercow
#
# Issues:
# Any issues / questions / suggestions can be posted here:
# https://github.com/jhartlep/servercow-dns-api/issues
#
# Author: Jens Hartlep
##########
SERVERCOW_API="https://api.servercow.de/dns/v1/domains"
# Usage dns_servercow_add _acme-challenge.www.domain.com "abcdefghijklmnopqrstuvwxyz"
dns_servercow_add() {
fulldomain=$1
txtvalue=$2
_info "Using servercow"
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
SERVERCOW_API_Username="${SERVERCOW_API_Username:-$(_readaccountconf_mutable SERVERCOW_API_Username)}"
SERVERCOW_API_Password="${SERVERCOW_API_Password:-$(_readaccountconf_mutable SERVERCOW_API_Password)}"
if [ -z "$SERVERCOW_API_Username" ] || [ -z "$SERVERCOW_API_Password" ]; then
SERVERCOW_API_Username=""
SERVERCOW_API_Password=""
_err "You don't specify servercow api username and password yet."
_err "Please create your username and password and try again."
return 1
fi
# save the credentials to the account conf file
_saveaccountconf_mutable SERVERCOW_API_Username "$SERVERCOW_API_Username"
_saveaccountconf_mutable SERVERCOW_API_Password "$SERVERCOW_API_Password"
_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"
if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":20}"; then
if printf -- "%s" "$response" | grep "ok" >/dev/null; 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_servercow_rm() {
fulldomain=$1
txtvalue=$2
_info "Using servercow"
_debug fulldomain "$fulldomain"
_debug txtvalue "$fulldomain"
SERVERCOW_API_Username="${SERVERCOW_API_Username:-$(_readaccountconf_mutable SERVERCOW_API_Username)}"
SERVERCOW_API_Password="${SERVERCOW_API_Password:-$(_readaccountconf_mutable SERVERCOW_API_Password)}"
if [ -z "$SERVERCOW_API_Username" ] || [ -z "$SERVERCOW_API_Password" ]; then
SERVERCOW_API_Username=""
SERVERCOW_API_Password=""
_err "You don't specify servercow api username and password yet."
_err "Please create your username and password and try again."
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"
if _servercow_api DELETE "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\"}"; then
if printf -- "%s" "$response" | grep "ok" >/dev/null; then
_info "Deleted, OK"
_contains "$response" '"message":"ok"'
else
_err "delete txt record error."
return 1
fi
fi
}
#################### Private functions below ##################################
# _acme-challenge.www.domain.com
# returns
# _sub_domain=_acme-challenge.www
# _domain=domain.com
_get_root() {
fulldomain=$1
i=2
p=1
while true; do
_domain=$(printf "%s" "$fulldomain" | cut -d . -f $i-100)
_debug _domain "$_domain"
if [ -z "$_domain" ]; then
# not valid
return 1
fi
if ! _servercow_api GET "$_domain"; then
return 1
fi
if ! _contains "$response" '"error":"no such domain in user context"' >/dev/null; then
_sub_domain=$(printf "%s" "$fulldomain" | cut -d . -f 1-$p)
if [ -z "$_sub_domain" ]; then
# not valid
return 1
fi
return 0
fi
p=$i
i=$(_math "$i" + 1)
done
return 1
}
_servercow_api() {
method=$1
domain=$2
data="$3"
export _H1="Content-Type: application/json"
export _H2="X-Auth-Username: $SERVERCOW_API_Username"
export _H3="X-Auth-Password: $SERVERCOW_API_Password"
if [ "$method" != "GET" ]; then
_debug data "$data"
response="$(_post "$data" "$SERVERCOW_API/$domain" "" "$method")"
else
response="$(_get "$SERVERCOW_API/$domain")"
fi
if [ "$?" != "0" ]; then
_err "error $domain"
return 1
fi
_debug2 response "$response"
return 0
}

202
dnsapi/dns_unoeuro.sh Normal file
View File

@@ -0,0 +1,202 @@
#!/usr/bin/env sh
#
#UNO_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"
#
#UNO_User="UExxxxxx"
Uno_Api="https://api.unoeuro.com/1"
######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_unoeuro_add() {
fulldomain=$1
txtvalue=$2
UNO_Key="${UNO_Key:-$(_readaccountconf_mutable UNO_Key)}"
UNO_User="${UNO_User:-$(_readaccountconf_mutable UNO_User)}"
if [ -z "$UNO_Key" ] || [ -z "$UNO_User" ]; then
UNO_Key=""
UNO_User=""
_err "You haven't specified a UnoEuro api key and account yet."
_err "Please create your key and try again."
return 1
fi
if ! _contains "$UNO_User" "UE"; then
_err "It seems that the UNO_User=$UNO_User is not a valid username."
_err "Please check and retry."
return 1
fi
#save the api key and email to the account conf file.
_saveaccountconf_mutable UNO_Key "$UNO_Key"
_saveaccountconf_mutable UNO_User "$UNO_User"
_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"
_uno_rest GET "my/products/$h/dns/records"
if ! _contains "$response" "\"status\": 200" >/dev/null; then
_err "Error"
return 1
fi
if ! _contains "$response" "$_sub_domain" >/dev/null; then
_info "Adding record"
if _uno_rest POST "my/products/$h/dns/records" "{\"name\":\"$fulldomain\",\"type\":\"TXT\",\"data\":\"$txtvalue\",\"ttl\":120}"; then
if _contains "$response" "\"status\": 200" >/dev/null; then
_info "Added, OK"
return 0
else
_err "Add txt record error."
return 1
fi
fi
_err "Add txt record error."
else
_info "Updating record"
record_line_number=$(echo "$response" | grep -n "$_sub_domain" | cut -d : -f 1)
record_line_number=$(_math "$record_line_number" - 1)
record_id=$(echo "$response" | _head_n "$record_line_number" | _tail_n 1 1 | _egrep_o "[0-9]{1,}")
_debug "record_id" "$record_id"
_uno_rest PUT "my/products/$h/dns/records/$record_id" "{\"name\":\"$fulldomain\",\"type\":\"TXT\",\"data\":\"$txtvalue\",\"ttl\":120}"
if _contains "$response" "\"status\": 200" >/dev/null; then
_info "Updated, OK"
return 0
fi
_err "Update error"
return 1
fi
}
#fulldomain txtvalue
dns_unoeuro_rm() {
fulldomain=$1
txtvalue=$2
UNO_Key="${UNO_Key:-$(_readaccountconf_mutable UNO_Key)}"
UNO_User="${UNO_User:-$(_readaccountconf_mutable UNO_User)}"
if [ -z "$UNO_Key" ] || [ -z "$UNO_User" ]; then
UNO_Key=""
UNO_User=""
_err "You haven't specified a UnoEuro api key and account yet."
_err "Please create your key and try again."
return 1
fi
if ! _contains "$UNO_User" "UE"; then
_err "It seems that the UNO_User=$UNO_User is not a valid username."
_err "Please check and retry."
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"
_uno_rest GET "my/products/$h/dns/records"
if ! _contains "$response" "\"status\": 200"; then
_err "Error"
return 1
fi
if ! _contains "$response" "$_sub_domain"; then
_info "Don't need to remove."
else
record_line_number=$(echo "$response" | grep -n "$_sub_domain" | cut -d : -f 1)
record_line_number=$(_math "$record_line_number" - 1)
record_id=$(echo "$response" | _head_n "$record_line_number" | _tail_n 1 1 | _egrep_o "[0-9]{1,}")
_debug "record_id" "$record_id"
if [ -z "$record_id" ]; then
_err "Can not get record id to remove."
return 1
fi
if ! _uno_rest DELETE "my/products/$h/dns/records/$record_id"; then
_err "Delete record error."
return 1
fi
_contains "$response" "\"status\": 200"
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"
if [ -z "$h" ]; then
#not valid
return 1
fi
if ! _uno_rest GET "my/products/$h/dns/records"; then
return 1
fi
if _contains "$response" "\"status\": 200"; then
_domain_id=$h
if [ "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_domain=$h
return 0
fi
return 1
fi
p=$i
i=$(_math "$i" + 1)
done
return 1
}
_uno_rest() {
m=$1
ep="$2"
data="$3"
_debug "$ep"
export _H1="Content-Type: application/json"
if [ "$m" != "GET" ]; then
_debug data "$data"
response="$(_post "$data" "$Uno_Api/$UNO_User/$UNO_Key/$ep" "" "$m")"
else
response="$(_get "$Uno_Api/$UNO_User/$UNO_Key/$ep")"
fi
if [ "$?" != "0" ]; then
_err "error $ep"
return 1
fi
_debug2 response "$response"
return 0
}

106
dnsapi/dns_yandex.sh Executable file
View File

@@ -0,0 +1,106 @@
#!/usr/bin/env sh
# Author: non7top@gmail.com
# 07 Jul 2017
# report bugs at https://github.com/non7top/acme.sh
# Values to export:
# export PDD_Token="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
######## Public functions #####################
#Usage: dns_myapi_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_yandex_add() {
fulldomain="${1}"
txtvalue="${2}"
_debug "Calling: dns_yandex_add() '${fulldomain}' '${txtvalue}'"
_PDD_credentials || return 1
export _H1="PddToken: $PDD_Token"
_PDD_get_domain "$fulldomain"
_debug "Found suitable domain in pdd: $curDomain"
curData="domain=${curDomain}&type=TXT&subdomain=${curSubdomain}&ttl=360&content=${txtvalue}"
curUri="https://pddimp.yandex.ru/api2/admin/dns/add"
curResult="$(_post "${curData}" "${curUri}")"
_debug "Result: $curResult"
}
#Usage: dns_myapi_rm _acme-challenge.www.domain.com
dns_yandex_rm() {
fulldomain="${1}"
_debug "Calling: dns_yandex_rm() '${fulldomain}'"
_PDD_credentials || return 1
export _H1="PddToken: $PDD_Token"
record_id=$(pdd_get_record_id "${fulldomain}")
_debug "Result: $record_id"
_PDD_get_domain "$fulldomain"
_debug "Found suitable domain in pdd: $curDomain"
curUri="https://pddimp.yandex.ru/api2/admin/dns/del"
curData="domain=${curDomain}&record_id=${record_id}"
curResult="$(_post "${curData}" "${curUri}")"
_debug "Result: $curResult"
}
#################### Private functions below ##################################
_PDD_get_domain() {
fulldomain="${1}"
__page=1
__last=0
while [ $__last -eq 0 ]; do
uri1="https://pddimp.yandex.ru/api2/admin/domain/domains?page=${__page}&on_page=20"
res1=$(_get "$uri1" | _normalizeJson)
#_debug "$res1"
__found=$(echo "$res1" | sed -n -e 's#.* "found": \([^,]*\),.*#\1#p')
_debug "found: $__found results on page"
if [ "$__found" -lt 20 ]; then
_debug "last page: $__page"
__last=1
fi
__all_domains="$__all_domains $(echo "$res1" | tr "," "\n" | grep '"name"' | cut -d: -f2 | sed -e 's@"@@g')"
__page=$(_math $__page + 1)
done
k=2
while [ $k -lt 10 ]; do
__t=$(echo "$fulldomain" | cut -d . -f $k-100)
_debug "finding zone for domain $__t"
for d in $__all_domains; do
if [ "$d" = "$__t" ]; then
p=$(_math $k - 1)
curSubdomain="$(echo "$fulldomain" | cut -d . -f "1-$p")"
curDomain="$__t"
return 0
fi
done
k=$(_math $k + 1)
done
_err "No suitable domain found in your account"
return 1
}
_PDD_credentials() {
if [ -z "${PDD_Token}" ]; then
PDD_Token=""
_err "You need to export PDD_Token=xxxxxxxxxxxxxxxxx"
_err "You can get it at https://pddimp.yandex.ru/api2/admin/get_token"
return 1
else
_saveaccountconf PDD_Token "${PDD_Token}"
fi
}
pdd_get_record_id() {
fulldomain="${1}"
_PDD_get_domain "$fulldomain"
_debug "Found suitable domain in pdd: $curDomain"
curUri="https://pddimp.yandex.ru/api2/admin/dns/list?domain=${curDomain}"
curResult="$(_get "${curUri}" | _normalizeJson)"
_debug "Result: $curResult"
echo "$curResult" | _egrep_o "{[^{]*\"content\":[^{]*\"subdomain\":\"${curSubdomain}\"" | sed -n -e 's#.* "record_id": \(.*\),[^,]*#\1#p'
}

85
dnsapi/dns_zonomi.sh Normal file
View File

@@ -0,0 +1,85 @@
#!/usr/bin/env sh
#
#ZM_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"
#
#https://zonomi.com dns api
ZM_Api="https://zonomi.com/app/dns/dyndns.jsp"
######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_zonomi_add() {
fulldomain=$1
txtvalue=$2
ZM_Key="${ZM_Key:-$(_readaccountconf_mutable ZM_Key)}"
if [ -z "$ZM_Key" ]; then
ZM_Key=""
_err "You don't specify zonomi api key yet."
_err "Please create your key and try again."
return 1
fi
#save the api key to the account conf file.
_saveaccountconf_mutable ZM_Key "$ZM_Key"
_info "Get existing txt records for $fulldomain"
if ! _zm_request "action=QUERY&name=$fulldomain"; then
_err "error"
return 1
fi
if _contains "$response" "<record"; then
_debug "get and update records"
_qstr="action[1]=SET&type[1]=TXT&name[1]=$fulldomain&value[1]=$txtvalue"
_qindex=2
for t in $(echo "$response" | tr -d "\r\n" | _egrep_o '<action.*</action>' | tr "<" "\n" | grep record | grep 'type="TXT"' | cut -d '"' -f 6); do
_debug2 t "$t"
_qstr="$_qstr&action[$_qindex]=SET&type[$_qindex]=TXT&name[$_qindex]=$fulldomain&value[$_qindex]=$t"
_qindex="$(_math "$_qindex" + 1)"
done
_zm_request "$_qstr"
else
_debug "Just add record"
_zm_request "action=SET&type=TXT&name=$fulldomain&value=$txtvalue"
fi
}
#fulldomain txtvalue
dns_zonomi_rm() {
fulldomain=$1
txtvalue=$2
ZM_Key="${ZM_Key:-$(_readaccountconf_mutable ZM_Key)}"
if [ -z "$ZM_Key" ]; then
ZM_Key=""
_err "You don't specify zonomi api key yet."
_err "Please create your key and try again."
return 1
fi
_zm_request "action=DELETE&type=TXT&name=$fulldomain"
}
#################### Private functions below ##################################
#qstr
_zm_request() {
qstr="$1"
_debug2 "qstr" "$qstr"
_zm_url="$ZM_Api?api_key=$ZM_Key&$qstr"
_debug2 "_zm_url" "$_zm_url"
response="$(_get "$_zm_url")"
if [ "$?" != "0" ]; then
return 1
fi
_debug2 response "$response"
_contains "$response" "<is_ok>OK:"
}