515 Commits
2.8.5 ... u

Author SHA1 Message Date
neil
5be69ee40b Update LetsEncrypt.yml 2020-08-28 09:32:38 +08:00
neil
386e67fb75 fix badge 2020-08-27 22:35:05 +08:00
neil
4b3e188017 remove travis 2020-08-27 22:17:10 +08:00
neil
e90a9e4643 add token 2020-08-27 21:49:19 +08:00
neil
c41786535d fix name 2020-08-27 21:46:29 +08:00
neil
021881ea98 add ubuntu test in github actions 2020-08-27 21:45:26 +08:00
neil
fdb96e91f1 match issuer ignoring case 2020-08-27 21:41:18 +08:00
neilpang
8d0e485120 add set-default-ca 2020-08-27 18:07:26 +08:00
neil
0c15655574 Merge pull request #3125 from lcts/usage-cleanup
Update individual 'Usage: ...'-messages to match showhelp()
2020-08-22 00:55:44 +08:00
neilpang
328b6d1cc6 add docker hub badge 2020-08-21 18:19:26 +08:00
Christopher Engelhard
b67d663a38 fix wrong options listed in --ecc help entry 2020-08-21 12:19:26 +02:00
Christopher Engelhard
dd6c5c9eea add documentation for --password option 2020-08-21 12:15:45 +02:00
Christopher Engelhard
2e87e64bd1 update individual Usage: messages to match showHelp 2020-08-21 12:12:30 +02:00
neil
a9403013df Merge pull request #3069 from PedroLamas/pedrolamas/multi-arch-build
Fixes #3068 - Adds docker multi-arch support
2020-08-21 18:05:52 +08:00
Pedro Lamas
05477c1a03 Fixes Dockerfile 2020-08-21 11:03:53 +01:00
Pedro Lamas
fcb6198a82 More updated following PR comments 2020-08-21 10:55:07 +01:00
Pedro Lamas
410d0bc125 Updates following PR comments 2020-08-21 10:40:13 +01:00
Pedro Lamas
abc62b9348 more 2020-08-21 10:34:43 +01:00
Pedro Lamas
6fbf33c8f4 More changes 2020-08-21 10:17:54 +01:00
neil
0ceb750dc7 Merge pull request #3119 from lcts/usage-cleanup
Update showhelp() message & add some hyphenated option forms for clarity & consistency
2020-08-21 16:26:02 +08:00
Christopher Engelhard
a48c22d14f add missing blank lines after links to wiki 2020-08-21 09:58:58 +02:00
Christopher Engelhard
1521199e44 add hidden alias --to-pkcs for --to-pkcs12 2020-08-21 09:56:57 +02:00
Christopher Engelhard
2910be82a4 revert change of --no-color option 2020-08-21 09:54:47 +02:00
Christopher Engelhard
07fdb087dc fix typo 2020-08-21 09:53:04 +02:00
Christopher Engelhard
58150f5dcd change --pkcs to --pkcs12 2020-08-21 09:53:04 +02:00
Christopher Engelhard
e7a6ff39f9 fix wrong indentation 2020-08-21 09:53:04 +02:00
Christopher Engelhard
b086afb272 fix some more issues in showhelp() 2020-08-21 09:53:04 +02:00
Christopher Engelhard
7decf76883 group commands logically, rearrange option forms in _process()
Commands have been reordered in showhelp() to a more consistent grouping,
help > version > install > certs > csr > account > cron > other

All option alternatives in _process() case statement have been reordered toshow the canonical variants first, legacy variants after.
2020-08-21 09:53:04 +02:00
Christopher Engelhard
d81369d63a add hyphenated options, fix wrong -ccr in usage() 2020-08-21 09:53:04 +02:00
Christopher Engelhard
c0fbe8237b reformat usage message for consistency & clarity 2020-08-21 09:53:04 +02:00
neil
58923b2846 Merge pull request #3099 from Alexilmarranen/dev
Issue2547 wrong url construction for multiple dns services
2020-08-20 22:10:34 +08:00
neil
d9f9477a52 move badge
move badge
2020-08-20 21:44:37 +08:00
neil
966c744992 minor, just move badge position 2020-08-20 21:41:36 +08:00
neil
7e5107d90f Merge pull request #3121 from acmesh-official/peb
Add pebble strict to CI
2020-08-20 21:33:32 +08:00
neil
c1668c9bdb add pebble badge 2020-08-20 21:26:42 +08:00
neil
7ddc2ccf1a add TEST_CA 2020-08-20 21:06:21 +08:00
neil
3cd85fb395 install socat 2020-08-20 20:54:27 +08:00
neil
b805ea9bf6 fix dir 2020-08-20 20:52:42 +08:00
neil
edd76f595a fix dir 2020-08-20 20:37:23 +08:00
neil
c131b63852 typo 2020-08-20 20:32:22 +08:00
neil
a70f377388 add pebble 2020-08-20 20:18:53 +08:00
neil
15ce3ec41a Merge pull request #3117 from acmesh-official/fix-preferred-chain-for-renewal
fix preferred chain for renewal
2020-08-20 09:14:48 +08:00
neil
b7b01999d9 fix preferred chain for renewal
fix https://github.com/acmesh-official/acme.sh/issues/3116
2020-08-20 09:13:44 +08:00
Alexilmarranen
956114fc42 Issue2336 Add subdomain (3 and more) support
Fix for issue in https://github.com/acmesh-official/acme.sh/issues/2336#issuecomment-670522738
2020-08-19 00:50:18 +03:00
neil
bb3a986859 Merge branch 'dev' of https://github.com/acmesh-official/acme.sh into dev 2020-08-18 23:28:25 +08:00
neil
50fefc3bb0 minor 2020-08-18 23:28:06 +08:00
neil
19555a98ed Merge pull request #3112 from olibu/dev
Dev: Fix issue #2833
2020-08-18 22:30:30 +08:00
neil
9021f006f0 update shfmt 2020-08-18 22:22:03 +08:00
Oliver Burgmaier
2d5f14388e Revert "Removed content for clean pull request"
This reverts commit ab47bf6451.
2020-08-18 14:52:23 +02:00
Oliver Burgmaier
ab47bf6451 Removed content for clean pull request 2020-08-18 14:01:02 +02:00
Oliver Burgmaier
d8bd45c2bd Fix issue #2833 with backslash in JSON
Backslash will be removed form JSON responses for each request
and for the initial configuration request
2020-08-18 13:53:48 +02:00
neil
72235a5f72 add shellcheck badge 2020-08-17 23:13:00 +08:00
neil
b6508cccec Merge pull request #3108 from acmesh-official/ga
support Github Actions
2020-08-17 22:59:46 +08:00
neil
d9e7cf659e Update ci.yml 2020-08-17 22:52:59 +08:00
neil
cf500cd817 fix 2020-08-17 22:50:19 +08:00
neil
f1338aca84 fix 2020-08-17 22:49:09 +08:00
neil
284de4ac5d add actions 2020-08-17 22:46:52 +08:00
neil
19c4345162 fix shfmt 2020-08-17 22:18:20 +08:00
neil
d5d38b3331 support multiple intermediate CA matching for --preferred-chain 2020-08-17 22:06:02 +08:00
neil
bd04638d27 minor 2020-08-16 17:36:24 +08:00
neil
0b531e9fbc fix format 2020-08-16 16:59:08 +08:00
neil
e3ebd582ec support "--preferred-chain" to select chain
https://github.com/acmesh-official/acme.sh/wiki/Preferred-Chain
2020-08-16 16:57:06 +08:00
neil
95ef046d0a fix https://github.com/acmesh-official/acme.sh/issues/3103 2020-08-15 12:32:15 +08:00
neil
b3a801df11 fix test endpoint 2020-08-15 10:33:24 +08:00
neil
a6d22e3b22 1. save the CA url anyway.
2. clear some code.
2020-08-13 23:12:30 +08:00
neil
0415c050a5 remove gitads 2020-08-13 23:04:19 +08:00
neil
014396cf11 Merge pull request #3082 from kappernet/dev
initial kapper.net DNS API support
2020-08-13 17:34:50 +08:00
kapper.net support account
70488f9c56 Merge branch 'dev' of https://github.com/kappernet/acme.sh into dev 2020-08-13 00:24:11 +02:00
kapper.net support account
0052ab7148 more mutable + style-update
more mutable config-read-calls
more details for TXT records info + errors;
typo fixed (create instead of delete)
2020-08-13 00:23:57 +02:00
Harald Kapper
f725040dd5 Merge pull request #6 from acmesh-official/dev
sync upstream
2020-08-12 23:55:25 +02:00
kapper.net support account
f131863642 now with "_saveaccountconf_mutable"
_saveaccountconf_mutable instead of _saveaccountconf now used.

Co-Authored-By: kapper.net support account <33451837+kappernet@users.noreply.github.com>
2020-08-12 23:48:11 +02:00
neil
836a293f16 Merge pull request #3100 from acmesh-official/eab
Suppor EAB and Zerossl.com
2020-08-12 22:31:03 +08:00
neil
1177cc3f29 fix format 2020-08-12 22:09:37 +08:00
neil
269847d19d Add CA name to the --list command output. 2020-08-12 21:45:20 +08:00
neil
df22f68088 Add info for set-default-ca 2020-08-12 21:25:35 +08:00
neil
d83d8552b8 Add "--server" wiki 2020-08-12 21:17:15 +08:00
neil
365aa69afd fix format 2020-08-12 20:48:53 +08:00
neil
578c338d40 Display ZeroSSL usage 2020-08-12 20:48:53 +08:00
neil
389518e1b8 1. move email to ca conf
2. get EAB credentials from Zerossl by email automatically
2020-08-12 20:48:53 +08:00
neil
d42ff227f1 fix format 2020-08-12 20:48:53 +08:00
neil
737e9e48ca 1. Support short names for --server parameter, The valid values are: letsencrypt, letsencrypt_test, buypass, buypass_test and zerossl
2. Support Zerossl.com acme protocol.
3. Add "--set-default-ca  --server xxxx" command to set the default CA to use.
2020-08-12 20:48:52 +08:00
neil
f96d91cb6c eab 2020-08-12 20:48:52 +08:00
neil
85503655ab Display ZeroSSL usage 2020-08-12 20:47:17 +08:00
neil
8d811760a9 1. move email to ca conf
2. get EAB credentials from Zerossl by email automatically
2020-08-12 20:43:44 +08:00
Alexilmarranen
4e0de22375 Issue2547 wrong url construction for multiple dns services
Fix for problem in https://github.com/acmesh-official/acme.sh/issues/2547#issuecomment-672830796
2020-08-12 15:17:54 +03:00
neil
7cfbf100eb Merge pull request #3098 from andybotting/dev
Rename openstack to dns_openstack
2020-08-12 10:10:52 +08:00
Andy Botting
edbe026b49 Rename openstack to dns_openstack
Although the DNS API dev guide at https://github.com/acmesh-official/acme.sh/wiki/DNS-API-Dev-Guide
says `The script file name must be myapi.sh`, it should really
be names dns_myapi.sh for consistency.
2020-08-12 11:24:45 +10:00
neil
1e967eceef fix format 2020-08-11 23:45:12 +08:00
neil
7d20db93d3 1. Support short names for --server parameter, The valid values are: letsencrypt, letsencrypt_test, buypass, buypass_test and zerossl
2. Support Zerossl.com acme protocol.
3. Add "--set-default-ca  --server xxxx" command to set the default CA to use.
2020-08-11 23:28:52 +08:00
Harald Kapper
fb05a42d2e Merge pull request #3 from acmesh-official/dev
sync upstream
2020-08-09 04:31:07 +02:00
neil
e932be0fb3 eab 2020-08-09 09:53:22 +08:00
neil
70b49980cb fix format 2020-08-09 09:40:22 +08:00
neil
a2d872a9f0 Merge pull request #3087 from draevin/dev-netlify
Add Netlify API support
2020-08-05 09:21:10 +08:00
Draevin Luke
e8bcde31b7 Add Netlify API support 2020-08-04 16:33:24 -07:00
neil
40cda9220a fix https://github.com/acmesh-official/acme.sh/issues/3077 2020-08-03 21:22:32 +08:00
kapper.net support account
a494683bc8 Merge branch 'dev' of https://github.com/kappernet/acme.sh into dev 2020-08-02 15:59:59 +02:00
kapper.net support account
2ba6a85eca fix multiple txt-records delete + API update
new API version
fix to delete specific TXT records for wildcard-certs with LE

Co-Authored-By: Harald Kapper <hknet@users.noreply.github.com>
2020-08-02 15:59:46 +02:00
kapper.net support account
0e58158a59 Merge pull request #2 from acmesh-official/dev
sync upstream
2020-08-02 13:56:52 +02:00
neil
af740592c9 Merge pull request #3073 from vi9076/dev
Fix failed test in acmetest. Item alpine:latest - test 12
2020-08-02 14:41:40 +08:00
neil
c9452c9f31 Merge pull request #2574 from rewqazxv/master
Fix sudo issue
2020-08-02 14:31:45 +08:00
kapper.net support account
494a1603e4 Update dns_kappernet.sh
add issue-link in sourcecode

Co-Authored-By: Harald Kapper <hknet@users.noreply.github.com>
2020-08-02 01:41:26 +02:00
kapper.net support account
5207e111e1 initial kapper.net DNS API support
hopefully this time we get it right ;)

Co-Authored-By: Harald Kapper <hknet@users.noreply.github.com>
2020-08-02 00:19:28 +02:00
neil
06995fb080 Merge pull request #3075 from jpmens/patch-2
Remove unecessary word from README.md
2020-07-28 09:34:48 +08:00
neil
1f5cafc2d1 Update README.md 2020-07-28 09:32:15 +08:00
JP Mens
f190de39a6 Remove unecessary word from README.md 2020-07-27 14:34:35 +02:00
neil
272ab746a6 Merge pull request #3071 from pdxgf1208/dev
Update dns_dynv6.sh
2020-07-27 15:57:07 +08:00
neil
fce0bf6e59 Merge pull request #3070 from phedoreanu/replace_response_equals_with_contains
replace response equals with contains
2020-07-27 15:54:05 +08:00
neil
5957786b2c Merge pull request #3072 from tresni/synology_dsm
Support for DS218+
2020-07-27 15:52:37 +08:00
Vinton Huang
4f3f4e23e4 Fix failed test in acmetest. Item alpine:latest - test 12: le_test_standandalone_deactivate_v2
- Message of failed test [1]: /root/.acme.sh/acme.sh --deactivate -d testdocker.acme.sh [FAIL]
- Reason of failure: left brace was not escaped. According to the standard [2], if special chars appear first in an ERE, it will produce undefined results.
- egrep from busybox (and thus alpine) take it as an error, but egrep from GNU grep (included in most distros) and *BSD are more tolerant, just ignore it.
- Fix: consider the right brace at the right-hand side of the ERE, the result string will not contain right brace. So the left-hand side should not contain left brace, too.
[1] 446939706e/logs/alpine-latest.out (L119)
[2] 9.4.3 ERE Special Characters, The Open Group Base Specifications. https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html
2020-07-27 03:55:07 +08:00
Brian Hartvigsen
5f5096e1d4 Addressing issues found in DS218+ DSM
DS218+ appears to have a slighly different DSM that sends back headers in lowercase.

Reported by @BartSiwek in #2727
2020-07-25 21:56:18 -06:00
12bbf7608ae1
4b35aef728 Update dns_dynv6.sh
Add support for domains like '*.v6.rocks'
2020-07-25 21:48:11 +08:00
Adrian Fedoreanu
6a0ed51f5e replace response equals with contains 2020-07-24 16:28:34 +02:00
Pedro Lamas
67360e93b8 Correctly labels Docker images per branch 2020-07-24 09:25:58 +01:00
Pedro Lamas
f18f4c69f2 Adds Docker multi-arch build support 2020-07-23 14:57:16 +01:00
neil
41435578d2 Merge pull request #3055 from andybotting/openstack-dns
Add OpenStack Designate DNS API support
2020-07-16 13:45:01 +08:00
neil
7f33ae3bee Merge pull request #3059 from andybotting/dev
Fix CI test failure for deploy/openstack.sh
2020-07-16 13:44:40 +08:00
neil
645135bf56 Merge pull request #3051 from szepeviktor/patch-2
Upgrade Travis image
2020-07-16 13:44:02 +08:00
Viktor Szépe
eb9005ad74 Fix SC2236 2020-07-16 06:18:46 +02:00
Viktor Szépe
14089f8c6a Fix SC2236 2020-07-16 06:18:12 +02:00
Viktor Szépe
49094120d9 Fix SC2236 2020-07-16 06:17:11 +02:00
Viktor Szépe
fe4111a9f5 Fix SC2236 2020-07-16 06:14:50 +02:00
Viktor Szépe
61613bee98 Fix SC2230 2020-07-16 06:13:15 +02:00
Andy Botting
3ce967d8e5 Fix CI test failure for deploy/openstack.sh 2020-07-16 13:53:21 +10:00
Andy Botting
aad9afad59 Add OpenStack Designate DNS API support
This provider relies on the the python-openstackclient and
python-designateclient tools be installed and working, with
either password or application credentials loaded in your env.
2020-07-16 13:25:59 +10:00
neil
8cbbd022fc Merge pull request #3057 from andybotting/openstack-deploy
Add OpenStack Barbican deploy support
2020-07-16 09:24:12 +08:00
Andy Botting
9b23cd6d19 Add OpenStack Barbican deploy support
This provider relies on the the python-openstackclient and
python-designateclient tools be installed and working, with
either password or application credentials loaded in your env.
2020-07-16 09:59:40 +10:00
Viktor Szépe
d94f241d3c Upgrade Travis image 2020-07-15 20:45:11 +02:00
neil
bb7c11adf1 Merge pull request #3049 from acmesh-official/dev
sync
2020-07-15 21:32:07 +08:00
neil
5c295254bf fix format 2020-07-15 21:31:14 +08:00
neil
236e8cc95c add gitads 2020-07-15 21:30:17 +08:00
neil
421973e0d9 Merge pull request #3046 from acmesh-official/dev
sync
2020-07-14 21:56:08 +08:00
neil
e2a5af1cf7 fix format 2020-07-14 21:49:50 +08:00
neil
f31debc09c fix format 2020-07-13 21:03:57 +08:00
neil
6654d7a919 fix format 2020-07-13 20:56:58 +08:00
neil
44743b5f6f Merge pull request #3043 from robertoetcheverryr/dev
Added check for Authentication failure in dns_dynu module
2020-07-13 14:54:16 +08:00
robertoetcheverryr
f80276584f Added check for Authentication failure in dns_dynu module 2020-07-12 23:43:03 -03:00
neil
cda41debfc Merge pull request #3042 from andrewheberle/patch-2
Use base64 for docker reload command
2020-07-13 09:40:14 +08:00
neil
2c50d01c26 Merge pull request #3039 from vi9076/master
Update "Tested OS" section of README.md
2020-07-13 09:35:51 +08:00
andrewheberle
01ebb6576d Use base64 for reload
Ensure that reload command is encoded with base64 so special characters in command do not wreck config on renewals
2020-07-13 09:31:47 +08:00
Vinton Huang
aaca0b6f76 Update "Tested OS" section of README.md
- Update openSUSE build badge file name (opensuse-leap.svg -> opensuse-leap-latest.svg)
- Update link target of build badge (letest -> acmetest), for item 1-12, 15, 16, 18, 19, 21
- Update Proxmox document link for 5.2 and later
2020-07-11 19:50:16 +08:00
neil
84e1f3649f Merge pull request #3035 from acmesh-official/dev
sync
2020-07-08 23:12:19 +08:00
neil
0ab2cfaf8b Merge pull request #3029 from licaon-kter/patch-2
Fix typo candindates
2020-07-08 22:25:20 +08:00
neil
0545d6f083 Merge pull request #3031 from peterkelm/patch-1
Reflect recent Variomedia API changes
2020-07-08 22:24:14 +08:00
neil
d804228956 fix https://github.com/acmesh-official/acme.sh/issues/3032 2020-07-08 22:22:06 +08:00
neil
f7d70df2ba Merge pull request #3033 from grindsa/ecc_sign
Prepending for ecc signature
2020-07-08 22:10:31 +08:00
neil
4daef52991 Merge pull request #3034 from acmesh-official/dev
sync
2020-07-08 21:30:43 +08:00
grindsa
a329547682 prepending for ecc signature
leftpadding "0" if _ec_s and _ec_r are to short
2020-07-08 11:59:20 +02:00
peterkelm
f02af8d481 Reflect recent Variomedia API changes
Spaces were recently removed from the JSON "response" returned by Variomedia's API.
2020-07-07 22:56:51 +02:00
neil
dd6c067832 fix format 2020-07-07 20:52:00 +08:00
Licaon_Kter
dbc435506c Fix typo candindates 2020-07-07 12:06:37 +00:00
neil
f00e289014 fix format 2020-07-07 20:02:48 +08:00
neil
1dffaba266 fix format 2020-07-07 19:58:02 +08:00
neil
958a2f4274 Merge pull request #3017 from metaquanta/master
dns_duckdns.sh - correctly extract domain
2020-07-05 21:52:26 +08:00
Matthew
21718a69d3 Update dns_duckdns.sh
Don't depend on eregex in sed
2020-07-03 07:48:38 -04:00
neil
c650ae0e19 Merge pull request #3015 from TonyGravagno/dev
Trivial text changes
2020-07-03 16:59:47 +08:00
neil
9ed435d04a Merge pull request #3023 from tomsommer/patch-1
unoeuro.com is now simply.com
2020-07-03 16:42:20 +08:00
neil
fed6a0c24e Merge pull request #3024 from snvad/fix2963-dns_regru
Fix bug in dns_regru.sh (#2963)
2020-07-03 16:41:33 +08:00
snv
44b9a8e7ed fix new line at end of file 2020-07-02 13:18:37 +04:00
snv
c16757b03a add some debug output and fix data in GET request 2020-07-02 12:59:24 +04:00
snv
5d0dde5c15 main changes 2020-07-02 12:23:46 +04:00
Tom Sommer
f60356e8c7 Username not required to contain "UE" 2020-07-02 09:48:05 +02:00
Tom Sommer
cdf8f78962 unoeuro.com is now simply.com
Maintaining the naming of the API (for backwards compatibility), but renaming hostname.
2020-07-02 09:47:05 +02:00
Matthew
4539d236df dns_duckdns.sh - correctly extract domain
$fulldomain could be just 'domain.duckdns.org' if provided with --domain-alias or '_acme-challenge.domain.duckdns.org' otherwise. In the latter case, '_acme-challenge' is thrown away. Correctly extract 'domain' in both cases.
2020-06-30 07:19:41 -04:00
Matthew
8718ac0c4b duckdns doesn't permit subdomains or underscores 2020-06-30 02:22:08 -04:00
Tony Gravagno
94787d537a Issue #2849 Trivial variable name fix from apacheMajer to apacheMajor 2020-06-29 11:51:55 -07:00
Tony Gravagno
bb8cff967e Merge branch 'dev' of https://github.com/TonyGravagno/acme.sh into dev 2020-06-29 11:31:18 -07:00
Tony Gravagno
eca57beec1 Issue #2850 : grammar corrections for "exists" and "exist". 2020-06-29 11:29:10 -07:00
neil
58b4eb04f9 Merge pull request #3002 from msamoylych/dev
dns_hexonet: Fix removing DNS records
2020-06-25 23:15:15 +08:00
msamoylych
a9d46297c4 Update dns_hexonet.sh
Fix removing DNS records
2020-06-24 12:26:11 +03:00
msamoylych
e9edecf34a Update dns_hexonet.sh
Remove useless &
2020-06-24 12:25:23 +03:00
neil
71a5f0e84e Merge pull request #3000 from acmesh-official/dev
sync
2020-06-24 13:38:03 +08:00
neil
fb22ee94d9 Merge pull request #2917 from mdbraber/lexicon_output_fix
Lexicon output fix
2020-06-10 22:45:39 +08:00
Maarten den Braber
f03904ebce change to --output QUIET 2020-06-09 09:57:36 +02:00
neil
60e04b9065 Merge pull request #2961 from DerVerruckteFuchs/master
Fix broken grep so that One984HOSTING_COOKIE actually gets set, and isn't left empty.
2020-05-26 21:39:47 +08:00
DerVerruckteFuchs
025da92450 Handle case insensitivity for HTTP/1.1 headers. 2020-05-26 02:00:05 -04:00
neil
5de4aa091b Merge pull request #2962 from grindsa/retry-after-fix
retry-timer fix
2020-05-26 09:34:46 +08:00
grindsa
1fe8235a85 Update acme.sh 2020-05-25 20:28:05 +02:00
DerVerruckteFuchs
0ab14399ae Fix broken grep so that One984HOSTING_COOKIE actually gets set, and isn't left empty. 2020-05-25 12:04:26 -04:00
neil
15dded712c fix retry
https://github.com/acmesh-official/acme.sh/issues/2939#issuecomment-632481658
2020-05-24 18:04:47 +08:00
neil
8837f7e6e8 Merge pull request #2929 from PMExtra/dev
Support multiple servers for SSH deployment
2020-05-24 18:02:56 +08:00
neil
e8defd821a update readme 2020-05-23 20:37:06 +08:00
neil
5d6effeff5 Merge pull request #2955 from dandv/patch-2
Fix sloppy English
2020-05-23 20:31:59 +08:00
Dan Dascalescu
427c278012 Fix sloppy English 2020-05-22 10:28:29 -07:00
PM Extra
a78a09f594 Support multiple servers for SSH deployment. 2020-05-22 18:15:38 +08:00
neil
59fd48cfe2 support Retry-After header
https://github.com/acmesh-official/acme.sh/issues/2939
2020-05-21 22:32:19 +08:00
neil
cc78ab4855 Merge pull request #2923 from mdbraber/add-provider-transip
Add TransIP provider
2020-05-21 22:27:50 +08:00
Maarten den Braber
063562261e Fix string truncation for POSIX 2020-05-19 23:09:16 +02:00
Maarten den Braber
70619dd0b7 Remove debugging 2020-05-19 20:07:14 +02:00
Maarten den Braber
63031fb278 bugfixes 2020-05-19 20:04:23 +02:00
neil
7f924a56b3 Merge pull request #2950 from acmesh-official/revoke
fix https://github.com/acmesh-official/acme.sh/issues/2880
2020-05-19 23:32:41 +08:00
neil
114f2a1465 fix https://github.com/acmesh-official/acme.sh/issues/2880 2020-05-19 23:26:58 +08:00
Maarten den Braber
5d2777634a Fix forgotten then 2020-05-19 16:43:39 +02:00
Maarten den Braber
2d5b4a0003 Change if-statement for private keys to more portable version 2020-05-19 16:39:49 +02:00
Maarten den Braber
adfa1704e2 Update nonce calculation to use acme.sh methods instead of openssl
command
2020-05-19 16:38:23 +02:00
neil
ab3fd6be8f Merge pull request #2942 from gassan/dns-hetzner
Added dnsapi/dns_hetzner.sh
2020-05-19 22:18:19 +08:00
neil
47702d075e Merge pull request #2945 from ianw/rax-lookup
dns_rackspace: search for domain
2020-05-19 22:12:45 +08:00
neil
341f000b9c Merge pull request #2947 from kref/patch-1
fix octal escapes for printf %b format
2020-05-19 13:45:42 +08:00
kref
0deea53931 fix octal escapes for printf %b format
Stop it from misinterpreting a following digit as part of the escape sequence
2020-05-19 13:27:00 +08:00
Ian Wienand
8b3d792bec dns_rackspace: search for domain
The current call uses the /domains end-point which lists all domains.
This only returns 100 domains at a time, so for long domain lists you
may not match and find the required ID.

Switch to using the search interface that only returns values matching
the requested domain.  This will avoid missing results.

Reported by @jjamfd.

Closes: #2944
2020-05-18 15:29:31 +10:00
Gassan Gousseinov
b82c48b66f shfmt 2020-05-17 23:09:22 +02:00
Gassan Gousseinov
fa91516dce added dnsapi/dns_hetzner.sh 2020-05-17 21:40:54 +02:00
Maarten den Braber
4954b44d8e Remove default key file (leave it to the user to explicitly specify) 2020-05-16 16:18:05 +02:00
neil
d132e51ac7 Merge pull request #2922 from QDaniel/QDaniel-patch-INWX
INWX fix Domain Limit #1491
2020-05-16 21:43:31 +08:00
neil
243b6ae985 Merge pull request #2931 from dvaerum/dev
Bug fix: DNS TXT entries will now be removed for dns_gdnsdk.sh
2020-05-16 21:39:06 +08:00
neil
8780ba3626 Merge pull request #2935 from tresni/synology_dsm
Update Synology DSM deploy hook
2020-05-16 21:02:32 +08:00
Brian Hartvigsen
694194be2f Shellcheck fix
SYNO_Certificate gets set by _getdeployconf, so this may be an empty string but that's fine
2020-05-16 02:25:53 -06:00
Brian Hartvigsen
c7f61f8b80 Allow rotating the default certificate which has no description
This means, by default, we will rotate the default certificate that comes with the DSM
2020-05-16 02:02:23 -06:00
Brian Hartvigsen
3a7c7fe4e8 Fix shellcheck issues 2020-05-16 00:19:18 -06:00
Brian Hartvigsen
668967a719 If SYNO_Create is not set here, print the nice message 2020-05-16 00:05:35 -06:00
Brian Hartvigsen
d15c14ab93 Fix support for wget
I'm actually not entirely sure why/how this worked with curl but not wget, but it did.  The short answer is that using a GET does not result in the HTTP_HEADER file being written, instead you must pass in the http_headers param ($2) which will return the HTTP headers as a string.  Luckily, the Token is in both the body and the header.  We need it and the id (and smid if 2fa) cookie to proceed.  So now we parrse the response for that instead of the HTTP_HEADER file.

Interesting side note: wget is fine if the URL contains a \r or \n, but curl will barf on it.  So we need to make sure those are stripped from the token as it will be passed in the URL later.
2020-05-15 23:53:00 -06:00
Brian Hartvigsen
52b81608a1 need to _url_encode anything sent in GET requests
Fixes issue raised by @tatablack
2020-05-15 23:48:50 -06:00
Dennis Vestergaard Værum
048f754d83 Bug fix: DNS TXT entries will now be removed for dns_gdnsdk.sh 2020-05-14 23:04:08 +02:00
Maarten den Braber
d5ef3a3f8c Formatting issues 2020-05-13 17:07:19 +02:00
Maarten den Braber
e768e285ce Remove extra newline 2020-05-13 16:49:42 +02:00
Maarten den Braber
a102d775b2 Formatting issues 2020-05-13 16:49:07 +02:00
Maarten den Braber
65e82b03ad Fix CI errors 2020-05-13 16:11:53 +02:00
Maarten den Braber
80a636bd14 Fix extra space 2020-05-13 16:08:34 +02:00
Maarten den Braber
a4c57ee363 Add TransIP provider 2020-05-13 15:35:51 +02:00
QDaniel
94bf54e7e0 INWX fix Domain Limit #1491 2020-05-13 12:14:27 +02:00
neil
b18ce5ade0 Merge pull request #2872 from honzahommer/feat/notify-teams
Add Microsoft Teams notify
2020-05-10 22:50:15 +08:00
Honza Hommer
99793bb2c4 chore: remove shellcheck disable 2020-05-09 12:26:16 +02:00
neil
093936e594 Merge pull request #2914 from philband/philband-patch-1
Add support for Njalla DNS API
2020-05-08 22:40:31 +08:00
Maarten den Braber
036a37e351 Nullify output from lexicon_cmd to prevent getting wrong return codes 2020-05-07 23:19:02 +02:00
Philipp Bandow
d904df57ca Bugfix error message in rest function 2020-05-07 15:45:47 +02:00
Philipp Bandow
d507979ec1 Make CI happy: Remove extraneous new line 2020-05-07 15:41:09 +02:00
Philipp Bandow
9bbcfead67 Bugfix shell format error 2020-05-07 15:37:59 +02:00
Philipp Bandow
81036894c0 Add new DNS Provider: Njalla 2020-05-07 15:28:00 +02:00
neil
9044adecb5 start 2.8.7 2020-05-04 08:43:47 +08:00
neil
9190fdd42c Merge pull request #2903 from acmesh-official/dev
sync
2020-05-04 08:41:37 +08:00
neil
eab35605e4 remove sudo 2020-05-03 11:01:02 +08:00
neil
28b65a7e7b Merge pull request #2898 from ThiloGa/dyndnsfree
adding support for dyndnsfree.de
2020-05-03 10:50:29 +08:00
neil
5d1d2308b4 Merge pull request #2900 from felixbuenemann/patch-2
Fix HAProxy Deploy Hook OCSP Update
2020-05-03 10:45:56 +08:00
Felix Bünemann
cf5952f508 fix haproxy deploy hook ocsp update
fixes ocsp reponse update failing with `Responder Error: unauthorized (6)`
by removing `-no_nonce` switch from `openssl oscp` command .
2020-05-02 22:14:21 +02:00
ThiloGa
3b0d7bc4ad typo fixing 2020-05-02 08:29:44 +02:00
ThiloGa
22f8ab110e typo fixing 2020-05-02 08:26:26 +02:00
neil
8f2d085d28 Merge pull request #2899 from acmesh-official/dev
sync
2020-05-01 23:55:21 +08:00
neil
c3d7f5b28b build on docker hub 2020-05-01 23:44:56 +08:00
ThiloGa
45e6000619 adding support for dyndnsfree.de 2020-05-01 06:25:19 +02:00
neil
7cd00a6760 Merge pull request #2886 from Ritbit/Fix_openprovider.sh_#2104
#2104 Fix openprovider.sh
2020-04-29 21:19:02 +08:00
neil
cecc53fed3 Merge pull request #2892 from acmesh-official/dev
sync
2020-04-29 10:46:04 +08:00
neil
58c2c70146 fix https://github.com/acmesh-official/acme.sh/issues/2888 2020-04-29 10:42:17 +08:00
neil
ad9f488df6 fix https://github.com/acmesh-official/acme.sh/issues/2888 2020-04-29 10:38:21 +08:00
neil
b19799bc72 fix https://github.com/acmesh-official/acme.sh/issues/2888 2020-04-29 10:19:35 +08:00
neil
1209b9b86e fix https://github.com/acmesh-official/acme.sh/issues/2888 2020-04-29 10:15:13 +08:00
neil
da957a3caf fix https://github.com/acmesh-official/acme.sh/issues/2888 2020-04-29 10:12:29 +08:00
Bas van Ritbergen
1bfd0f0149 Update dns_openprovider.sh
fixed shebang shell to be as suggested
2020-04-27 15:41:50 +02:00
Bas van Ritbergen
3ff48b8559 Update dns_openprovider.sh
#2104  Fix wildcard handling & custom NS config for OpenProvider DNS
2020-04-27 15:34:20 +02:00
neil
6ba1eda96f fix https://github.com/acmesh-official/acme.sh/issues/2883#issuecomment-619215961 2020-04-25 22:44:00 +08:00
neil
dddfe07867 Merge pull request #2879 from blablup/OPNsense_dns
Allow old and new API response for OPNsense Plugin
2020-04-24 22:16:03 +08:00
neil
054f67eeb8 Merge pull request #2877 from vktg/loopia300ttl
DNS Loopia min 300 TTL
2020-04-24 22:13:27 +08:00
neil
65c59c8c30 Merge pull request #2882 from acmesh-official/dev
sync
2020-04-24 22:10:38 +08:00
Honza Hommer
24925a1739 feat: add default colors 2020-04-22 21:13:52 +02:00
Jesai Langenbach
c49b40ee95 Allow old and new API response
CLOSES #2480
2020-04-21 11:43:08 +02:00
Viktor G
c06db30a65 DNS Loopia min 300 TTL 2020-04-20 21:05:40 +03:00
neil
0ed6fef49b Merge pull request #2876 from wurzelpanzer/easydns-updates
easyDNS API out of beta
2020-04-20 21:45:48 +08:00
wurzelpanzer
9bad11ec79 easyDNS API out of beta
Added new links to API docs and API access signup
2020-04-20 08:49:08 +02:00
Honza Hommer
74cdcde449 fix: remove :xdigit: 2020-04-19 23:59:35 +02:00
neil
1613461504 Merge pull request #2869 from wwebers/fix_opnsense
Fix for latest "os-bind" plugin
2020-04-19 20:39:25 +08:00
neil
0043f3558c Merge pull request #2870 from softcat/fix/inwx-api
Fix for INWX DNS API (multiple domains and 2FA enabled failing)
2020-04-19 20:36:47 +08:00
Honza Hommer
a9c4b8dd1a feat: Microsoft Teams notify 2020-04-19 01:03:04 +02:00
Nils Sandmann
5d00edc896 Fix multiple domains with 2FA, reuse session cookie 2020-04-18 18:54:43 +02:00
Nils Sandmann
3bad815982 Better error handling on login, return correct return code 2020-04-18 18:52:08 +02:00
Wolfram Webers
08cc7587ab - Adding fix for latest "os-bind" plugin 2020-04-18 18:11:24 +02:00
neil
458c0db3a8 Merge pull request #2868 from acmesh-official/reason
fix format
2020-04-18 22:35:27 +08:00
neil
a995333081 fix format 2020-04-18 22:34:32 +08:00
neil
8eb608a839 Merge pull request #2866 from acmesh-official/reason
support revoke reason.
2020-04-18 20:16:24 +08:00
neil
1041c9f9fc support revoke reason.
https://github.com/acmesh-official/acme.sh/issues/2856
2020-04-18 20:03:48 +08:00
neil
1564742b76 add comments 2020-04-18 19:38:38 +08:00
neil
b887fd153d Merge pull request #2843 from der-berni/patch-1
Update to work with new one.com procedure
2020-04-18 19:22:47 +08:00
neil
d083674fb1 Merge pull request #2779 from honzahommer/notify/mail.sh
Add msmtp command to notify/mail.sh
2020-04-18 19:00:42 +08:00
neil
ed7a945261 add comment message. 2020-04-18 18:59:33 +08:00
neil
ef5ffa939f Merge pull request #2864 from siwyd/fix-updating-empty-email
Fix: allow removal of email address as contact
2020-04-18 18:55:03 +08:00
neil
d842ccb287 fix format error 2020-04-18 18:51:08 +08:00
neil
233893f122 Merge pull request #2863 from mod242/master
Filter out blank lines
2020-04-18 18:50:22 +08:00
Simon Wydooghe
2febdfc363 Fix: allow removal of email address as contact
It seems the current code doesn't allow for removing the email address
from the contact field. This fixes that. This only removes the email
address if an explicit empty email address is specified on the command
line or in the account.conf file. If it is left unspecified on the
command line it still just uses whatever was configured in the
account.conf.
2020-04-17 15:53:15 +02:00
mod242
2c971a2598 Filter out blank lines
Response from the provider has changed so that there are blank lines at the end, which leads to the result can not be parsed correctly
2020-04-16 20:03:34 +02:00
neil
b4c3c20e5e Merge pull request #2797 from EAliakbar/arvandns
Adding Arvan Dns Api
2020-04-12 14:09:54 +08:00
neil
b6fbb012ad Merge pull request #2749 from dkerr64/ssh-deploy
Updates to ssh_deploy hook
2020-04-12 13:58:44 +08:00
neil
7f4db5a731 Merge pull request #2855 from maidmeow4/master
Fix a typo in dns_he.sh on line 27
2020-04-12 13:47:24 +08:00
喵喵喵喵四
4dfdfa0b7d Fix typo on line 27 2020-04-12 12:28:07 +08:00
neil
dbf659c575 Merge pull request #2854 from acmesh-official/dev
sync
2020-04-12 12:11:11 +08:00
neil
cd8e04471c Merge branch 'dev' of https://github.com/acmesh-official/acme.sh into dev 2020-04-12 11:48:43 +08:00
neil
93de1e4903 un-escape json chars
fix https://github.com/acmesh-official/acme.sh/issues/2833
2020-04-12 11:48:24 +08:00
neil
2df43c9e2b Merge pull request #2847 from woutd/fix-constellix-api-domain-search
Constellix made changes to their API.
2020-04-12 10:49:35 +08:00
neil
5ace44493a fix comments 2020-04-12 10:47:41 +08:00
neil
a57ba3d81c update comments 2020-04-12 10:38:31 +08:00
neil
6298112531 Merge pull request #2852 from phedoreanu/dns_1984hosting
add dns_1984hosting.sh
2020-04-12 10:15:52 +08:00
neil
25afca55f6 Merge pull request #2853 from scottw/master
show response when unable to retrieve DNS records for a zone
2020-04-12 09:41:00 +08:00
Scott Wiersdorf
52a16c917f show response when unable to retrieve DNS records for a zone 2020-04-11 11:24:30 -06:00
Adrian Fedoreanu
eef9a60037 add dns_1984hosting dns api 2020-04-10 23:34:00 +02:00
Wout
e158b5ccf6 Constellix made changes to their API. They added more search capabilities, but the changes are not backwards compatible. We need to use the exact parameter instead of name now. 2020-04-09 19:15:32 +02:00
neil
f03d7efb5e Merge pull request #2845 from woutd/fix-constellix-domain-id
Fixes getting the correct domain id using Contellix API.
2020-04-09 20:21:50 +08:00
der-berni
da7b1fb014 cleanup according to styleguide / ShellCheck 2020-04-09 12:17:08 +02:00
Wout
62378d063e Fixes getting the correct domain id using Contellix API. 2020-04-07 22:34:05 +02:00
der-berni
5fac282ee0 Update to work with new one.com procedure
Since some Months, its no longer possible to add TXT Records with the Name "_acme-challenge" to the base domain.
To override the fallback value, you must use a CNAME and proxy it.
For example.
CNAME _acme-challenge.yourdomain.com => proxy_acme-challenge.yourdomain.com
The TXT Records have to be created on proxy_acme-challenge.yourdomain.com

Since the default CNAME TTL is 3600 seconds, it is recommended to leave the CNAME record.
But if you would like to use the build-in SSL (for your web-site etc.) from one.com, you have to delete the record.

A new variable "ONECOM_KeepCnameProxy" you can set in the account.conf is used to keep the CNAME record.
By default the CNAME record will be removed.

For ex.: SAVED_ONECOM_KeepCnameProxy='1'
to keep the CNAME Record and speedup the process.
2020-04-07 19:25:39 +02:00
neil
6eff873a07 Merge pull request #2783 from Blfrg/dns_me
dns_me id parse using only sed
2020-04-06 10:32:09 +08:00
neil
1fb306c9d3 Merge pull request #2841 from aattww/master
Add support for Joker.com
2020-04-06 10:29:55 +08:00
aattww
c064b3896a Change command check to fully pass shellcheck 2020-04-06 01:13:59 +03:00
aattww
8400d1e60e Add bugs report link 2020-04-05 22:07:20 +03:00
aattww
5530e74382 Initial release 2020-04-05 21:57:37 +03:00
neil
47a38a8977 Merge pull request #2839 from acmesh-official/dev
sync
2020-04-05 13:47:08 +08:00
neil
47883a94a6 support auto-comment 2020-04-05 13:46:02 +08:00
neil
ca19bbd366 Merge pull request #2831 from olibu/dev
Dev
2020-04-04 11:36:48 +08:00
Oliver Burgmaier
7595808d26 fix #2828 mailto compliant to RFC6068
This fix removes the space between "mailto:" and the email address to
make the contact attribute compliant to RFC6068.
2020-04-01 20:35:07 +02:00
Oliver Burgmaier
37d22a144a fix #2830 Autorization segment typo fixed
This fixes the parsing of the authorization segment in the response of
an order. Without this fix the start of the array is not found
correctly and therefore the finalize URL is part of the authorization
segment. Changing the regex to *\[[^\[]*\] fix this. Seems to be a typo
which has not been recognized so far. This can be only recognized if
the response is in a single line.
2020-04-01 20:31:06 +02:00
Oliver Burgmaier
dc697a6862 fix #2830 Autorization segment typo fixed
This fixes the parsing of the authorization segment in the response of
an order. Without this fix the start of the array is not found
correctly and therefore the finalize URL is part of the authorization
segment. Changing the regex to *\[[^\[]*\] fix this. Seems to be a typo
which has not been recognized so far. This can be only recognized if
the response is in a single line.
2020-04-01 20:24:40 +02:00
neil
5398bac533 Merge pull request #2823 from acmesh-official/dev
sync
2020-03-31 21:36:26 +08:00
neil
9984a168cb Merge pull request #2822 from xiaohuilam/patch-1
Try incrementing cert issuing waiting counter.
2020-03-31 21:15:30 +08:00
neil
286f3713b0 Merge pull request #2816 from netpok/patch-2
Fix invalid domain error on dns_cf update
2020-03-31 21:08:59 +08:00
Xiaohui Lam
ff9be30f86 resolved #2818 2020-03-31 03:10:12 +08:00
netpok
34cebe8c0c Fix invalid domain error on dns_cf update
When dns_cf used with Zone ID it fails on removal of the entry.

This pull request adds the missing CF_Zone_ID loading.
2020-03-29 23:45:52 +02:00
Ehsan Aliakbar
200cd5972a fix shellcheck errors in Arvan Dns Api 2020-03-28 21:50:58 +04:30
neil
808d1af578 Merge pull request #2777 from ThiloGa/dev
add support for namemaster.de
2020-03-28 19:06:25 +08:00
neil
d0995665a3 Merge pull request #2808 from ucando/dev
enable qiniu deploy hook to deploy more than one domain
2020-03-28 16:46:13 +08:00
ucando
6132af8ecb enable qiniu to deploy more than one domain 2020-03-26 14:59:23 +08:00
neil
2e9c4914a8 Merge pull request #2807 from acmesh-official/dev
sync
2020-03-26 09:10:18 +08:00
neil
bf0d513e5b Merge pull request #2798 from oliverblaha/dev
add support for upgrade from tag
2020-03-25 19:50:05 +08:00
neil
2be435ff32 Merge pull request #2802 from luoch/patch-1
update dns_dp.sh
2020-03-25 14:49:03 +08:00
罗诚
20ba820253 Update dns_dp.sh
https://dnsapi.cn has change the default language to cn other then en. So the api call need to add `lang=en` to url params for getting the english messages.
And, They also change the susccess message from "Action completed successful" to "Operation successful". Simply use "successful" as keyword will be fine.
2020-03-25 14:39:52 +08:00
neil
44fd332965 Merge pull request #2799 from PaloAltoNetworks/fix-panos-data-format
fix(deploy/panos): data format improvements
2020-03-25 11:11:57 +08:00
Brian Torres-Gil
0453d656d6 fix(deploy/panos): data format improvements
It was discovered in testing that PAN-OS < 9.0 has slightly different
requirements for the multipart/form-data format and requires the `type`
parameter to be passed in the URL. These corrections should work for all
PAN-OS versions.
2020-03-24 20:01:51 -07:00
Oliver Blaha
cb7e38577d add support for upgrade from tag 2020-03-24 14:44:35 +01:00
Ehsan Aliakbar
4fa59ea04e Adding Arvan Dns Api 2020-03-24 17:56:50 +04:30
ThiloGa
bc2ed602e7 deleted txt entry routine by request of namemaster.de, entry is deleted automatically 2020-03-21 21:18:25 +01:00
ThiloGa
a1c4d159dd further shellcheck fixes 2020-03-21 19:48:17 +01:00
ThiloGa
598f29b78e doing shellcheck staff 2020-03-21 19:41:46 +01:00
ThiloGa
f61f2d6e5e adaptations to the new api functions
_get_root fully functional due to the extended api
2020-03-21 19:28:16 +01:00
dkerr64
f38df4df11 Make remote backup directory path user configurable. 2020-03-14 21:51:21 -04:00
neil
1e34ccbe2e Merge pull request #2782 from lippertmarkus/feature-deployhook-synology-otp
Add OTP support to Synology DSM deployhook
2020-03-14 16:05:05 +08:00
Honza Hommer
2a8746f6b0 Feat: add msmtp command 2020-03-11 22:32:37 +01:00
dkerr64
554e083f3d For MULTI_CALL default to undefined, deleting entry in config file if set to "no" 2020-03-11 10:58:36 -04:00
Jeremiah
5d881a8b0f use more compatible regex flag 2020-03-09 11:34:50 -06:00
neil
3d81641139 fix format 2020-03-09 19:04:32 +08:00
Jeremiah
c25b4ba099 dns_me id parse using only sed 2020-03-08 15:39:18 -06:00
Markus Lippert
fd64c20807 store device ID 2020-03-08 20:22:31 +01:00
Markus Lippert
80f1034dd6 add OTP support 2020-03-08 19:49:46 +01:00
Honza Hommer
15b841da06 Feat: simplify conditions for bin and command 2020-03-08 04:47:55 +01:00
neil
902c08e9c9 Merge branch 'dev' of https://github.com/acmesh-official/acme.sh into dev 2020-03-08 10:17:41 +08:00
neil
ea652c023e fix https://github.com/acmesh-official/acme.sh/issues/2778 2020-03-08 10:17:21 +08:00
ThiloGa
3c79bb77db fixing travis-ci warnings SC2086: Double quote to prevent globbing and word splitting. 2020-03-07 21:21:39 +01:00
ThiloGa
d8dbb85946 small fixes 2020-03-07 21:11:08 +01:00
ThiloGa
20702d26ec fixing https://github.com/koalaman/shellcheck/wiki/SC2181 problems 2020-03-07 21:05:42 +01:00
ThiloGa
7d7e9501fa fixing https://github.com/koalaman/shellcheck/wiki/SC2181 problems 2020-03-07 20:37:29 +01:00
ThiloGa
efef76d9cf fixed typo 2020-03-07 19:34:57 +01:00
ThiloGa
e1e1ee31f0 Dont use $? directly anymore 2020-03-07 16:00:52 +01:00
ThiloGa
142ca58d38 removed some unused Vars 2020-03-07 15:45:41 +01:00
ThiloGa
3b01bf7bda removed the probably last blank line 2020-03-07 15:33:21 +01:00
ThiloGa
30416f54d1 Fixes for Travis CI
-removing some blanks etc.
2020-03-07 15:18:25 +01:00
ThiloGa
f21ef0d2e9 add support for namemaster.de 2020-03-07 14:55:09 +01:00
neil
39ced21a6f Merge pull request #2198 from pipedrive/Add-AWS_API-slowrate
Add aws api slowrate
2020-03-07 19:59:20 +08:00
neil
0f24417cb3 Merge pull request #2769 from ianw/update-account-json
Update account.json on account update
2020-03-07 19:50:17 +08:00
neil
f84a87f2a2 remove DEFAULT_DNS_SLEEP.
fix https://github.com/acmesh-official/acme.sh/issues/2773
2020-03-07 18:26:22 +08:00
David Kerr
dada57e5c4 Merge branch 'ssh-deploy' of https://github.com/dkerr64/acme.sh into ssh-deploy 2020-03-05 16:22:59 -05:00
neil
d437d6fde9 Merge pull request #2770 from acmesh-official/dev
add clearlinux
2020-03-04 09:53:51 +08:00
neil
69b11575e3 add clearlinux
fix https://github.com/acmesh-official/acme.sh/issues/2768
2020-03-04 09:51:16 +08:00
Ian Wienand
72e1a1b2e9 Update account.json on account update
When running --updateaccount, the ca/<ca>/account.json file isn't
updated with the new response showing the updated account details.
This can be a bit confusing if you add an email to the account but
then you're not sure if it actually applied looking at this file.

Write out the new response on successful account updates.
2020-03-04 12:28:21 +11:00
dkerr64
8ba573d196 Change variable name to MULTI_CALL so default can be "no" 2020-03-03 13:40:33 -05:00
David Kerr
4593231049 Merge branch 'ssh-deploy' of https://github.com/dkerr64/acme.sh into ssh-deploy
# Conflicts:
#	deploy/ssh.sh
2020-02-28 08:37:25 -05:00
neil
de9eac760b Merge pull request #2754 from acmesh-official/dev
sync
2020-02-25 21:46:42 +08:00
neil
12ad8d52ae Merge pull request #2753 from nobbs/fix_docker_deploy
Fix error on docker deploy command with spaces.
2020-02-25 21:34:07 +08:00
alex
22f9a3b467 Fix error on docker deploy command with spaces.
This adds quotes to the last eval in _getdeployconf which is reponsible
for loading and exporting saved environment variables back into the
acme.sh process. This caused some errors if used with the docker
deploy-hook and the example nginx "service nginx force-reload" command
as it contains spaces.
2020-02-25 12:37:46 +01:00
Stephane Moser
b64f0ba83f Update usage of AWS_DNS_SLOWRATE 2020-02-24 23:14:40 +00:00
dkerr64
f73a494407 Remove spaces on blank line to fix travis error 2020-02-22 22:09:28 -05:00
dkerr64
46ee74ed16 Remove variable from info/error printout that could potentially expose login credentials. 2020-02-22 22:05:06 -05:00
dkerr64
806b746fc0 Fix bug where backup and batch_mode yes/no values could not be changed.
Once set to "no" then they could never be set back to "yes"
2020-02-22 21:23:59 -05:00
dkerr64
cc820e97c6 Add support for DEPLOY_SSH_BATCH_MODE with default of yes.
Before this update all remote commands were bunched together and
sent to the remote host in a single SSH command.  This could result
in a very long sequence of commands that might be rejected by a
remote host (example is VMware ESXi that uses busybox sh).
With this update you can set DEPLOY_SSH_BATCH_MODE="no" and
each remote command is sent as a separate SSH call so now we
do not have big long sequence of commands.  Defaults to same
behaviour as before this update.
2020-02-22 21:10:42 -05:00
dkerr64
283b04df73 Move cleanup of backup directory to first step in the function. 2020-02-22 20:43:28 -05:00
dkerr64
6420d1239f Move call to remote system into separate function 2020-02-22 20:31:52 -05:00
dkerr64
04771e5a4a Move call to remote system into separate function 2020-02-22 20:16:36 -05:00
dkerr64
3d9608faa0 Move -T parameter into default ssh command variable 2020-02-22 20:09:24 -05:00
David Kerr
b7b4ae4262 Merge branch 'dev' of https://github.com/acmesh-official/acme.sh into ssh-deploy 2020-02-22 20:01:41 -05:00
neil
b73b078705 Merge pull request #2719 from qwqVictor/dev
Add support for CQHTTP QQ bot API
2020-02-22 17:44:15 +08:00
neil
887fa8649b Merge pull request #2670 from sreyemnayr/fix-pfsense-linode
Fix pfsense linode
2020-02-22 13:41:19 +08:00
neil
f6172d7273 Merge pull request #2690 from nstepa/dns_yandex
Fix dns records removing after usage.
2020-02-22 13:39:04 +08:00
neil
c70681712d Merge pull request #2746 from acmesh-official/dev
sync
2020-02-22 13:34:01 +08:00
neil
80ca6de531 Merge pull request #2728 from artooro/master
add support for using a Zone ID
2020-02-22 13:28:37 +08:00
neil
c6c395cd0f Merge pull request #2737 from xpac1985/patch-3
Make socat debug output show version + features instead of help text
2020-02-22 12:10:22 +08:00
neil
4831064623 Merge pull request #2744 from xpac1985/patch-2
haproxy deploy script now compatible with OpenSSL v1.1+
2020-02-21 23:20:34 +08:00
neil
d4660a23c0 Merge pull request #2742 from adrian5/patch-3
Fix phrasing in README
2020-02-21 22:34:18 +08:00
xpac1985
e184a1b9e6 haproxy deploy script now compatible with OpenSSL v1.1+
haproxy deploy script now compatible with OpenSSL v1.1+

The OpenSSL OCSP request for haproxy deployment breaks from OpenSSL v1.1.0 on.
The format of the `-header` option has been changed and does now contain a `=` instead of a whitespace.
Other projects have hit the same issue:
https://github.com/nghttp2/nghttp2/issues/742

This commit determines the OpenSSL/LibreSSL version and then adjusts the request accordingly.
Also removed the duplicate command line and added some more debug output.
2020-02-20 23:28:55 +01:00
adrian5
f8662c9bc2 Fix phrasing in README 2020-02-20 18:43:08 +01:00
xpac1985
463df9e4ba Make socat debug output show version + features instead of help text 2020-02-18 16:26:15 +01:00
neil
c768581829 Merge pull request #2735 from acmesh-official/dev
sync
2020-02-15 21:56:03 +08:00
neil
754f7a7891 Merge pull request #2614 from PaloAltoNetworks/deploy-panos
Adding abillity to deploy cert to Palo Alto Networks Firewall via API.
2020-02-15 20:46:59 +08:00
Paul Nguyen
21450a08c2 Fixed 6 character requirement. 2020-02-13 18:01:27 -08:00
Paul Nguyen
c355b25bb1 Fixed line formatting 2020-02-12 15:00:23 -08:00
Paul Nguyen
1fe3d80838 Updated to use saveconf function and base64encode. 2020-02-12 14:57:31 -08:00
Paul Nguyen
930e16b64a fix gitdiff 2020-02-11 22:50:05 -08:00
Paul Nguyen
2077a70d03 Fixing gitdiff 2020-02-11 22:44:51 -08:00
Paul Nguyen
cbdb8bd9b9 Fixing gitdiff 2020-02-11 22:34:55 -08:00
Paul Nguyen
5dcb417676 ShellCheck fixes 2020-02-11 22:26:48 -08:00
Paul Nguyen
71bc993e3d Fixed Shellchecks 2020-02-11 22:23:10 -08:00
Paul Nguyen
c2812896f8 Update deployer 2020-02-11 18:15:10 -08:00
Arthur Wiebe
d43227ede4 fix shellcheck issues 2020-02-11 13:07:10 -05:00
neil
8554ae38ed Merge pull request #2369 from tresni/synology_dsm
Initial support for Synology DSM deployhook
2020-02-11 20:12:47 +08:00
neil
da656caf1e Merge pull request #2726 from Blfrg/dns_me
fix #2031 dns_me id parse
2020-02-11 19:09:38 +08:00
neil
51fc853228 Merge pull request #1341 from phlegx/all-inkl-kasserver-dns-script
All inkl kasserver dns script
2020-02-11 19:08:31 +08:00
neil
7a30cb9de7 Merge branch 'dev' into all-inkl-kasserver-dns-script 2020-02-11 19:07:20 +08:00
Brian Hartvigsen
1b475cf9f3 Remove -q from greps 2020-02-10 21:02:27 -07:00
Arthur Wiebe
719b690451 add support for using a Zone ID 2020-02-10 10:22:55 -05:00
neil
3cdc523dec Merge pull request #2628 from woutd/master
Add DNS API support for Constellix
2020-02-10 22:27:05 +08:00
Blfrg
eb49127b9e improve id parse
Locate only the outer most "id" property
2020-02-09 14:50:29 -06:00
Brian Hartvigsen
d07172a528 Replace disabled linter with variable substituion 2020-02-09 12:06:13 -08:00
Brian Hartvigsen
79637097ba Use _utc_date 2020-02-09 11:50:50 -08:00
Brian Hartvigsen
1259341095 Use deployconf properly 2020-02-09 03:10:11 -08:00
Brian Hartvigsen
5d3bc95ac5 Fix some debug output 2020-02-09 02:50:29 -08:00
Brian Hartvigsen
de25232a73 Allow creating new certificates when certificate is not found 2020-02-09 02:26:55 -08:00
Brian Hartvigsen
95769de464 Fix shfmt/shellcheck issues 2020-02-09 02:01:26 -08:00
Brian Hartvigsen
52a168b961 Stop using jq/curl directly
This is a lot more fragile then the previous code due to treating JSON as just a string
2020-02-09 01:49:20 -08:00
Brian Hartvigsen
b3b00b6700 Using domainconf instead of account 2020-02-09 01:49:20 -08:00
Brian Hartvigsen
8e8cda132c Remove boilerplate from what I used for template 2020-02-09 01:49:20 -08:00
Brian Hartvigsen
6459ccb185 Cleanup shfmt warnings 2020-02-09 01:49:20 -08:00
Brian Hartvigsen
548f83c3ad Cleanup shellcheck errors 2020-02-09 01:49:19 -08:00
Brian Hartvigsen
555e0de9e4 Initial support for Synology DSM
This allows you to update a key on a Synology DSM using the existing API.
Handles restarting the necessary services the certificate is attached to and all other internal stuff (copying the certificate around, etc.)

This is way less error prone than most articles I've found on how to update a Synology DSM certificate.
2020-02-09 01:49:19 -08:00
Wout
cc4bce283f Merge branch 'master' of git://github.com/acmesh-official/acme.sh 2020-02-09 10:13:17 +01:00
Blfrg
8189a34d14 fix dns_me id parse
The API seems to have changed and the ID is no longer in the same location.
2020-02-08 16:43:23 -06:00
Victor Huang
5d88ad554f Improved token processing method and misc bugfixes
Replace '_err' to '_debug' in the final error report.
Removed redundancy code.
2020-02-08 23:24:45 +08:00
Wout
2cc50a2b65 Cosmetic fixes. 2020-02-08 12:27:19 +01:00
Victor Huang
33670a5bd0 CQHTTP: Change shebang to "/usr/bin/env sh" 2020-02-06 11:26:56 +08:00
Victor Huang
64f8a222cb Add support for CQHTTP QQ bot API 2020-02-06 11:12:14 +08:00
Paul Nguyen
d9a9695fe0 Deploy certificates to Palo Alto Network Firewalls 2020-02-05 14:29:01 -08:00
neil
8e6c4e1aca Merge pull request #2481 from blablup/OPNsense_dns
Add OPNsense Bind API Support
2020-01-31 16:37:31 +08:00
neil
490fbfc13e Merge pull request #2701 from xpac1985/patch-1
Updated/fixed some entries in --help output
2020-01-31 16:32:13 +08:00
neil
4b45973361 Merge pull request #2470 from StefanAbl/master
DNS Api for dynv6
2020-01-31 16:30:51 +08:00
neil
4c27e08e3d Merge pull request #2692 from helbgd/patch-7
fix for ddnss.de updates
2020-01-31 16:29:16 +08:00
neil
94eb80597b Merge pull request #2712 from acmesh-official/dev
update repo name
2020-01-30 12:44:47 +08:00
neilpang
d610eb15d8 update repo name 2020-01-30 12:44:02 +08:00
neil
4f53cd1704 Merge pull request #2711 from acmesh-official/dev
update repo name
2020-01-30 12:08:21 +08:00
neilpang
d795fac37a update repo name 2020-01-30 12:06:39 +08:00
neil
ce6b71a58b Merge pull request #2710 from acmesh-official/dev
start v2.8.6, change the repo name
2020-01-30 10:51:51 +08:00
neilpang
09f74a9af8 start v2.8.6, change the repo name 2020-01-30 10:50:39 +08:00
neil
552a49a680 Merge pull request #2707 from Neilpang/2695
fix 2695
2020-01-27 23:56:33 +08:00
neilpang
97741398fb minor 2020-01-27 23:40:51 +08:00
neilpang
f8b225e70e fix format 2020-01-27 23:30:36 +08:00
neil
57b4eda014 Merge pull request #2706 from Neilpang/dev
sync
2020-01-27 23:09:30 +08:00
neilpang
fc3a181779 move the error message 2020-01-27 23:07:10 +08:00
neilpang
9541ea6a9f fix bug https://github.com/Neilpang/acme.sh/issues/2695
If a domain was already verified by http-01 method,  when we try to issue a cert for them same domain with dns-01 method, we just get only one challenge object of type http-01 with "valid" status, from the authz-v3 url. So, we report error that we are not able the validate the domain, because of that we don't find dns-01 challenge.
This behavior is not the same as before. I believe it was changed by the letsencrypt CA.
2020-01-27 23:07:10 +08:00
neilpang
f716f6060e minor check update hash for branch name 2020-01-27 23:02:09 +08:00
neilpang
dc0cca8c83 move the error message 2020-01-27 22:22:25 +08:00
neilpang
4f303de00c fix bug https://github.com/Neilpang/acme.sh/issues/2695
If a domain was already verified by http-01 method,  when we try to issue a cert for them same domain with dns-01 method, we just get only one challenge object of type http-01 with "valid" status, from the authz-v3 url. So, we report error that we are not able the validate the domain, because of that we don't find dns-01 challenge.
This behavior is not the same as before. I believe it was changed by the letsencrypt CA.
2020-01-27 22:12:21 +08:00
neilpang
05aa26e619 minor, remove space key 2020-01-27 21:22:42 +08:00
Phlegx Systems OG
1c4b831922 Merge pull request #7 from Marco4223/Fix-issues-and-reslolve-zone-and-record-name
Update dns_kas.sh
2020-01-24 09:01:04 +01:00
Marco4223
6613ae57b0 Update dns_kas.sh
sleep 10 to _sleep 10
2020-01-23 19:20:44 +01:00
xpac1985
b6552aff75 Added maximum account key length to --help output 2020-01-22 21:21:38 +01:00
xpac1985
3c98fae4f2 Updated/fixed some entries in --help output 2020-01-22 20:00:04 +01:00
neil
2028e4c8ad Merge pull request #2700 from radek-sprta/clouddns
Support for CloudDNS API
2020-01-22 22:20:30 +08:00
Radek SPRTA
5c7feba77b Format with shfmt 2020-01-22 05:33:46 +01:00
Radek SPRTA
23f2677052 Do not print HTTP responses to stdout 2020-01-22 02:53:50 +01:00
Radek SPRTA
6b67511748 Disable check 2020-01-22 02:03:11 +01:00
Radek SPRTA
36e0feea43 Clean up comments 2020-01-22 01:59:40 +01:00
Radek SPRTA
69392f67e8 Correctly handle .co.uk type domains 2020-01-22 01:33:15 +01:00
Radek SPRTA
e7d130cc11 Add support for CloudDNS API 2020-01-21 06:36:31 +01:00
StefanAbl
6e3ba3ca45 travis 2020-01-18 13:53:26 +01:00
StefanAbl
0f54cf83f4 fixed dynv6 dns validation 2020-01-18 13:48:29 +01:00
Phlegx Systems OG
fb209cdfde Merge pull request #6 from Marco4223/Fix-issues-and-reslolve-zone-and-record-name
delete spaces in empty lines
2020-01-15 19:47:26 +01:00
Marco4223
431c53efcf Update dns_kas.sh
Removing spaces in empty lines
2020-01-15 17:48:30 +01:00
rewqazxv
79ad0ff56b Simplify code 2020-01-15 22:11:34 +08:00
Phlegx Systems OG
96180e7555 Merge pull request #5 from Marco4223/Fix-issues-and-reslolve-zone-and-record-name
Update dns_kas.sh
2020-01-15 14:01:04 +01:00
Marco4223
024619676b Update dns_kas.sh
fixing 4 Travis style
2020-01-15 13:56:01 +01:00
helbgd
b1ce6ffcc7 www is incorrect as well
use ip4 and not www, if you use www it deletes the ip4 address of the host and updates only the ip6 address
2020-01-14 15:27:35 +01:00
helbgd
f01936ca4f Server Name not correct
the servername of the server that has the upd.php file was not correct
2020-01-14 15:19:37 +01:00
Phlegx Systems OG
58cfc0d0cf Merge pull request #4 from Marco4223/Fix-issues-and-reslolve-zone-and-record-name
Update dns_kas.sh
2020-01-14 10:10:39 +01:00
Nick Stepa
4eff3b6a24 Change error to info in case record already exists. 2020-01-12 15:16:48 +01:00
Nick Stepa
e5f69f0815 Fix indentation. 2020-01-12 14:07:49 +01:00
Nick Stepa
ef7b51beb7 Remove local keyword. 2020-01-12 13:54:18 +01:00
Nick Stepa
8494ac8f3d Fix dns records removing after usage. 2020-01-12 13:29:09 +01:00
Ryan Meyers
38a8721a91 Escape opening brackets 2020-01-04 10:52:52 -06:00
Ryan Meyers
8aedf26a87 Replace \s with hard space 2020-01-04 10:51:32 -06:00
Marco4223
8dd1df71cc Update dns_kas.sh
tested and works now
2020-01-02 17:10:36 +01:00
Marco4223
2214507db0 Revert "Update dns_kas.sh"
This reverts commit 99c47dd50a.
2019-12-29 10:59:28 +01:00
Marco4223
a138425417 Update dns_kas.sh
sorry for this commit.  ;)
Fix NewBeMistakes
2019-12-28 23:42:46 +01:00
Marco4223
99c47dd50a Update dns_kas.sh
only bash needed
2019-12-28 22:42:51 +01:00
Marco4223
594b83e7a6 Update dns_kas.sh
remove "rev" command
fix "Error removing txt for domain:_acme-challenge.foo"
2019-12-28 11:58:21 +01:00
Martin Kammerlander
239d53426a Merge remote-tracking branch 'upstream/dev' into all-inkl-kasserver-dns-script 2019-12-12 16:36:41 +01:00
Martin Kammerlander
3ccac629bc Change the loop for sh. 2019-12-12 16:23:42 +01:00
Wout
e8e6feeb0f Use different e-mail. 2019-12-11 17:15:35 +01:00
Wout
c22705a593 Add DNS API support for Constellix. 2019-12-11 17:13:11 +01:00
Martin Kammerlander
953a9b1768 Remove obsolete blank. 2019-11-29 22:51:23 +01:00
Martin Kammerlander
c641b61b26 Fix a few snytax issues 2019-11-29 22:46:44 +01:00
Martin Kammerlander
d87e507865 Merge remote-tracking branch 'upstream/dev' into all-inkl-kasserver-dns-script 2019-11-29 22:27:11 +01:00
Martin Kammerlander
ec1f9841b2 Replace grep -A. 2019-11-29 22:22:26 +01:00
Stephane Moser
37978b4fe5 Merge branch 'dev' into Add-AWS_API-slowrate 2019-11-22 10:20:25 +00:00
Martin Kammerlander
e22c5ea800 Merge with Neilpang dev repo. 2019-11-10 17:39:56 +01:00
Phlegx Systems OG
16bfb1727f Merge pull request #3 from dojo90/all-inkl-kasserver-dns-script
support to delete multiple entries
2019-11-10 17:15:01 +01:00
Jesai Langenbach
9cb328966c typo 2019-11-08 08:58:51 +01:00
Jesai Langenbach
0c76890572 whitespace fix 2019-11-08 08:52:10 +01:00
Jesai Langenbach
18fc42e63b typos and integrate suggestions from stilez 2019-11-07 22:06:32 +01:00
Jesai Langenbach
fc8d9df516 fix newline 2019-11-07 14:33:38 +01:00
Jesai Langenbach
afdf8a78c0 fix space 2019-11-07 14:18:09 +01:00
Jesai Langenbach
0b3ae1f972 Add suggestions 2019-11-07 14:10:30 +01:00
rewqazxv
6a5ee72722 format code style 2019-11-06 20:27:12 +08:00
rewqazxv
c6ec8bc0d9 fix sudo issue 2019-11-06 18:57:05 +08:00
Jesai Langenbach
b85c1a8861 Fix additional line 2019-10-25 08:22:15 +02:00
Jesai Langenbach
430956d304 Fix whitespaces 2019-10-25 08:13:35 +02:00
Jesai Langenbach
c0449a3ed2 Only save Attributes if it is set 2019-10-25 08:04:20 +02:00
Jesai Langenbach
bfa6e52470 another whitespace 2019-09-12 20:50:20 +02:00
Jesai Langenbach
ec654d2355 More space removing 2019-09-12 17:24:00 +02:00
Jesai Langenbach
dfb4883c93 Some fixes 2019-09-12 17:17:32 +02:00
Jesai Langenbach
4bf1f579f5 Add OPNsense Bind API Support 2019-09-12 16:28:57 +02:00
Dominic Jonas
1ef7fd3659 support to delete multiple entries 2019-06-05 11:38:41 +02:00
Stephane Moser
aeed287122 Add Double quote to slowrateslepp 2019-04-02 10:27:22 +01:00
Stephane Moser
ea6a3c0963 Use AWS_DNS_SLOWRATE env variable instead of arg 2019-03-29 14:39:32 +00:00
Stephane Moser
8902a5c5cd Revert "Add --dnsslowrate arg"
This reverts commit 16db9a7337.
2019-03-29 14:33:15 +00:00
Stephane Moser
3021c5cfad Use dnsslowrate arg 2019-03-29 14:12:50 +00:00
Stephane Moser
16db9a7337 Add --dnsslowrate arg 2019-03-29 14:12:34 +00:00
Martin Kammerlander
68f66ca101 Add default delay for the calls to KAS api since they are very restrictive with that. 2018-08-02 16:20:48 +02:00
Martin Kammerlander
c34aadfbf7 Merge with latest dev branch. 2018-06-08 10:35:17 +02:00
Martin Kammerlander
cb4a2cf029 remove debug output 2018-03-16 16:47:47 +01:00
Martin Kammerlander
26b5180bf7 Rename full_domain and txt_value variables. 2018-03-16 15:49:40 +01:00
Martin Kammerlander
11bfb1e5fd Fix return values of some functions. 2018-03-16 15:02:47 +01:00
Martin Kammerlander
e431df06ab Only create entry. Remove update. 2018-03-16 14:54:08 +01:00
Martin Kammerlander
cbf0ceacd5 Update dnsapi Readme. 2018-03-16 14:51:16 +01:00
Martin Kammerlander
8c634d8323 Merge branch 'dev' into all-inkl-kasserver-dns-script 2018-03-16 14:49:02 +01:00
Martin Kammerlander
32d7bd5ab1 Add own github repository URL. 2018-03-09 16:33:35 +01:00
Martin Kammerlander
861df49670 Add All-inkl kasserver script. 2018-03-09 16:29:47 +01:00
86 changed files with 6070 additions and 1641 deletions

View File

@@ -2,7 +2,7 @@
我很忙, 每天可能只有 几秒钟 时间看你的 issue, 如果不按照我的要求写 issue, 你可能不会得到任何回复, 石沉大海.
请确保已经更新到最新的代码, 然后贴上来 `--debug 2` 的调试输出. 没有调试信息. 我做不了什么.
如何调试 https://github.com/Neilpang/acme.sh/wiki/How-to-debug-acme.sh
如何调试 https://github.com/acmesh-official/acme.sh/wiki/How-to-debug-acme.sh
If it is a bug report:
- make sure you are able to repro it on the latest released version.
@@ -10,7 +10,7 @@ You can install the latest version by: `acme.sh --upgrade`
- Search the existing issues.
- Refer to the [WIKI](https://wiki.acme.sh).
- Debug info [Debug](https://github.com/Neilpang/acme.sh/wiki/How-to-debug-acme.sh).
- Debug info [Debug](https://github.com/acmesh-official/acme.sh/wiki/How-to-debug-acme.sh).
-->

View File

@@ -3,7 +3,7 @@
Please send to `dev` branch instead.
Any PR to `master` branch will NOT be merged.
2. For dns api support, read this guide first: https://github.com/Neilpang/acme.sh/wiki/DNS-API-Dev-Guide
2. For dns api support, read this guide first: https://github.com/acmesh-official/acme.sh/wiki/DNS-API-Dev-Guide
You will NOT get any review without passing this guide. You also need to fix the CI errors.
-->

40
.github/auto-comment.yml vendored Normal file
View File

@@ -0,0 +1,40 @@
# Comment to a new issue.
issuesOpened: >
If this is a bug report, please upgrade to the latest code and try again:
如果有 bug, 请先更新到最新版试试:
```
acme.sh --upgrade
```
please also provide the log with `--debug 2`.
同时请提供调试输出 `--debug 2`
see: https://github.com/acmesh-official/acme.sh/wiki/How-to-debug-acme.sh
Without `--debug 2` log, your issue will NEVER get replied.
没有调试输出, 你的 issue 不会得到任何解答.
pullRequestOpened: >
First, NEVER send a PR to `master` branch, it will NEVER be accepted. Please send to the `dev` branch instead.
If this is a PR to support new DNS API or new notification API, please read this guide first:
https://github.com/acmesh-official/acme.sh/wiki/DNS-API-Dev-Guide
Please check the guide items one by one.
Then add your usage here:
https://github.com/acmesh-official/acme.sh/wiki/dnsapi
Or some other wiki pages:
https://github.com/acmesh-official/acme.sh/wiki/deployhooks
https://github.com/acmesh-official/acme.sh/wiki/notify

32
.github/workflows/LetsEncrypt.yml vendored Normal file
View File

@@ -0,0 +1,32 @@
name: LetsEncrypt
on: [push, pull_request]
jobs:
Ubuntu:
runs-on: ubuntu-latest
env:
NGROK_TOKEN : ${{ secrets.NGROK_TOKEN }}
TEST_LOCAL: 1
steps:
- uses: actions/checkout@v2
- name: Install tools
run: sudo apt-get install -y socat
- name: Clone acmetest
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
- name: Run acmetest
run: cd ../acmetest && sudo TEST_LOCAL="$TEST_LOCAL" NGROK_TOKEN="$NGROK_TOKEN" ./letest.sh
MacOS:
needs: Ubuntu
runs-on: macos-latest
env:
NGROK_TOKEN : ${{ secrets.NGROK_TOKEN }}
TEST_LOCAL: 1
steps:
- uses: actions/checkout@v2
- name: Install tools
run: brew update && brew install socat;
- name: Clone acmetest
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
- name: Run acmetest
run: cd ../acmetest && sudo TEST_LOCAL="$TEST_LOCAL" NGROK_TOKEN="$NGROK_TOKEN" ./letest.sh

27
.github/workflows/PebbleStrict.yml vendored Normal file
View File

@@ -0,0 +1,27 @@
name: PebbleStrict
on: [push, pull_request]
jobs:
PebbleStrict:
runs-on: ubuntu-latest
env:
TestingDomain: example.com
TestingAltDomains: www.example.com
ACME_DIRECTORY: https://localhost:14000/dir
HTTPS_INSECURE: 1
Le_HTTPPort: 5002
TEST_LOCAL: 1
TEST_CA: "Pebble Intermediate CA"
steps:
- uses: actions/checkout@v2
- name: Install tools
run: sudo apt-get install -y socat
- name: Run Pebble
run: cd .. && curl https://raw.githubusercontent.com/letsencrypt/pebble/master/docker-compose.yml >docker-compose.yml && docker-compose up -d
- name: Set up Pebble
run: curl --request POST --data '{"ip":"10.30.50.1"}' http://localhost:8055/set-default-ipv4
- name: Clone acmetest
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
- name: Run acmetest
run: cd ../acmetest && ./letest.sh

46
.github/workflows/dockerhub.yml vendored Normal file
View File

@@ -0,0 +1,46 @@
name: Build DockerHub
on:
push:
branches:
- '*'
tags:
- '*'
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: checkout code
uses: actions/checkout@v2
- name: install buildx
id: buildx
uses: crazy-max/ghaction-docker-buildx@v3
with:
buildx-version: latest
qemu-version: latest
- name: login to docker hub
run: |
echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin
- name: build and push the image
run: |
DOCKER_IMAGE=neilpang/acme.sh
if [[ $GITHUB_REF == refs/tags/* ]]; then
DOCKER_IMAGE_TAG=${GITHUB_REF#refs/tags/}
fi
if [[ $GITHUB_REF == refs/heads/* ]]; then
DOCKER_IMAGE_TAG=${GITHUB_REF#refs/heads/}
if [[ $DOCKER_IMAGE_TAG == master ]]; then
DOCKER_IMAGE_TAG=latest
AUTO_UPGRADE=1
fi
fi
docker buildx build \
--tag ${DOCKER_IMAGE}:${DOCKER_IMAGE_TAG} \
--output "type=image,push=true" \
--build-arg AUTO_UPGRADE=${AUTO_UPGRADE} \
--platform linux/arm64/v8,linux/amd64,linux/arm/v6,linux/arm/v7,linux/386 .

16
.github/workflows/shellcheck.yml vendored Normal file
View File

@@ -0,0 +1,16 @@
name: Shellcheck
on: [push, pull_request]
jobs:
formatCheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install Shellcheck
run: sudo apt-get install -y shellcheck
- name: DoShellcheck
run: shellcheck -V && shellcheck -e SC2181 **/*.sh && echo "shellcheck OK"
- name: Install shfmt
run: curl -sSL https://github.com/mvdan/sh/releases/download/v3.1.2/shfmt_v3.1.2_linux_amd64 -o ~/shfmt && chmod +x ~/shfmt
- name: shfmt
run: ~/shfmt -l -w -i 2 . ; git diff --exit-code && echo "shfmt OK"

View File

@@ -1,38 +0,0 @@
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
install:
- if [ "$TRAVIS_OS_NAME" = 'osx' ]; then
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
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then curl -sSL $SHFMT_URL -o ~/shfmt && chmod +x ~/shfmt && ~/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 -e SC2181 **/*.sh && echo "shellcheck OK" ; fi
- cd ..
- git clone --depth 1 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" ./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
matrix:
fast_finish: true

View File

@@ -1,4 +1,4 @@
FROM alpine:3.10
FROM alpine:3.12
RUN apk update -f \
&& apk --no-cache add -f \
@@ -15,7 +15,9 @@ RUN apk update -f \
ENV LE_CONFIG_HOME /acme.sh
ENV AUTO_UPGRADE 1
ARG AUTO_UPGRADE=1
ENV AUTO_UPGRADE $AUTO_UPGRADE
#Install
ADD ./ /install_acme.sh/
@@ -52,6 +54,7 @@ RUN for verb in help \
deactivate \
deactivate-account \
set-notify \
set-default-ca \
; 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

119
README.md
View File

@@ -1,13 +1,24 @@
# An ACME Shell script: acme.sh [![Build Status](https://travis-ci.org/Neilpang/acme.sh.svg?branch=master)](https://travis-ci.org/Neilpang/acme.sh)
# An ACME Shell script: acme.sh
![shellcheck](https://github.com/acmesh-official/acme.sh/workflows/LetsEncrypt/badge.svg)
![shellcheck](https://github.com/acmesh-official/acme.sh/workflows/Shellcheck/badge.svg)
![shellcheck](https://github.com/acmesh-official/acme.sh/workflows/PebbleStrict/badge.svg)
![shellcheck](https://github.com/acmesh-official/acme.sh/workflows/Build%20DockerHub/badge.svg)
<a href="https://opencollective.com/acmesh" alt="Financial Contributors on Open Collective"><img src="https://opencollective.com/acmesh/all/badge.svg?label=financial+contributors" /></a>
[![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)
[![Docker stars](https://img.shields.io/docker/stars/neilpang/acme.sh.svg)](https://hub.docker.com/r/neilpang/acme.sh "Click to view the image on Docker Hub")
[![Docker pulls](https://img.shields.io/docker/pulls/neilpang/acme.sh.svg)](https://hub.docker.com/r/neilpang/acme.sh "Click to view the image on Docker Hub")
<a href="https://opencollective.com/acmesh" alt="Financial Contributors on Open Collective"><img src="https://opencollective.com/acmesh/all/badge.svg?label=financial+contributors" /></a> [![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.
- Purely written in Shell with no dependencies on python or the official Let's Encrypt client.
- Just one script to issue, renew and install your certificates automatically.
- DOES NOT require `root/sudoer` access.
@@ -17,19 +28,19 @@
It's probably the `easiest & smartest` shell script to automatically issue & renew the free certificates from Let's Encrypt.
Wiki: https://github.com/Neilpang/acme.sh/wiki
Wiki: https://github.com/acmesh-official/acme.sh/wiki
For Docker Fans: [acme.sh :two_hearts: Docker ](https://github.com/Neilpang/acme.sh/wiki/Run-acme.sh-in-docker)
For Docker Fans: [acme.sh :two_hearts: Docker ](https://github.com/acmesh-official/acme.sh/wiki/Run-acme.sh-in-docker)
Twitter: [@neilpangxa](https://twitter.com/neilpangxa)
# [中文说明](https://github.com/Neilpang/acme.sh/wiki/%E8%AF%B4%E6%98%8E)
# [中文说明](https://github.com/acmesh-official/acme.sh/wiki/%E8%AF%B4%E6%98%8E)
# 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))
- [Proxmox](https://pve.proxmox.com/wiki/Certificate_Management)
- [pfsense](https://github.com/pfsense/FreeBSD-ports/pull/89)
- [webfaction](https://community.webfaction.com/questions/19988/using-letsencrypt)
- [Loadbalancer.org](https://www.loadbalancer.org/blog/loadbalancer-org-with-lets-encrypt-quick-and-dirty)
@@ -40,41 +51,43 @@ Twitter: [@neilpangxa](https://twitter.com/neilpangxa)
- [opnsense.org](https://github.com/opnsense/plugins/tree/master/security/acme-client/src/opnsense/scripts/OPNsense/AcmeClient)
- [CentOS Web Panel](http://centos-webpanel.com/)
- [lnmp.org](https://lnmp.org/)
- [more...](https://github.com/Neilpang/acme.sh/wiki/Blogs-and-tutorials)
- [more...](https://github.com/acmesh-official/acme.sh/wiki/Blogs-and-tutorials)
# Tested OS
| NO | Status| Platform|
|----|-------|---------|
|1|[![](https://neilpang.github.io/acmetest/status/ubuntu-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)| Ubuntu
|2|[![](https://neilpang.github.io/acmetest/status/debian-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)| Debian
|3|[![](https://neilpang.github.io/acmetest/status/centos-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|CentOS
|4|[![](https://neilpang.github.io/acmetest/status/windows-cygwin.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Windows (cygwin with curl, openssl and crontab included)
|5|[![](https://neilpang.github.io/acmetest/status/freebsd.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|FreeBSD
|6|[![](https://neilpang.github.io/acmetest/status/pfsense.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|pfsense
|7|[![](https://neilpang.github.io/acmetest/status/opensuse-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|openSUSE
|8|[![](https://neilpang.github.io/acmetest/status/alpine-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Alpine Linux (with curl)
|9|[![](https://neilpang.github.io/acmetest/status/base-archlinux.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Archlinux
|10|[![](https://neilpang.github.io/acmetest/status/fedora-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|fedora
|11|[![](https://neilpang.github.io/acmetest/status/kalilinux-kali-linux-docker.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Kali Linux
|12|[![](https://neilpang.github.io/acmetest/status/oraclelinux-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Oracle Linux
|13|[![](https://neilpang.github.io/acmetest/status/proxmox.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)| Proxmox https://pve.proxmox.com/wiki/HTTPSCertificateConfiguration#Let.27s_Encrypt_using_acme.sh
|14|-----| Cloud Linux https://github.com/Neilpang/le/issues/111
|15|[![](https://neilpang.github.io/acmetest/status/openbsd.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|OpenBSD
|16|[![](https://neilpang.github.io/acmetest/status/mageia.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Mageia
|17|-----| OpenWRT: Tested and working. See [wiki page](https://github.com/Neilpang/acme.sh/wiki/How-to-run-on-OpenWRT)
|18|[![](https://neilpang.github.io/acmetest/status/solaris.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|SunOS/Solaris
|19|[![](https://neilpang.github.io/acmetest/status/gentoo-stage3-amd64.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Gentoo Linux
|20|[![Build Status](https://travis-ci.org/Neilpang/acme.sh.svg?branch=master)](https://travis-ci.org/Neilpang/acme.sh)|Mac OSX
|1|[![](https://acmesh-official.github.io/acmetest/status/ubuntu-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)| Ubuntu
|2|[![](https://acmesh-official.github.io/acmetest/status/debian-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)| Debian
|3|[![](https://acmesh-official.github.io/acmetest/status/centos-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|CentOS
|4|[![](https://acmesh-official.github.io/acmetest/status/windows-cygwin.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Windows (cygwin with curl, openssl and crontab included)
|5|[![](https://acmesh-official.github.io/acmetest/status/freebsd.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|FreeBSD
|6|[![](https://acmesh-official.github.io/acmetest/status/pfsense.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|pfsense
|7|[![](https://acmesh-official.github.io/acmetest/status/opensuse-leap-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|openSUSE
|8|[![](https://acmesh-official.github.io/acmetest/status/alpine-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Alpine Linux (with curl)
|9|[![](https://acmesh-official.github.io/acmetest/status/archlinux-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Archlinux
|10|[![](https://acmesh-official.github.io/acmetest/status/fedora-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|fedora
|11|[![](https://acmesh-official.github.io/acmetest/status/kalilinux-kali.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Kali Linux
|12|[![](https://acmesh-official.github.io/acmetest/status/oraclelinux-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Oracle Linux
|13|[![](https://acmesh-official.github.io/acmetest/status/proxmox.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)| Proxmox: See Proxmox VE Wiki. Version [4.x, 5.0, 5.1](https://pve.proxmox.com/wiki/HTTPS_Certificate_Configuration_(Version_4.x,_5.0_and_5.1)#Let.27s_Encrypt_using_acme.sh), version [5.2 and up](https://pve.proxmox.com/wiki/Certificate_Management)
|14|-----| Cloud Linux https://github.com/acmesh-official/acme.sh/issues/111
|15|[![](https://acmesh-official.github.io/acmetest/status/openbsd.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|OpenBSD
|16|[![](https://acmesh-official.github.io/acmetest/status/mageia.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Mageia
|17|-----| OpenWRT: Tested and working. See [wiki page](https://github.com/acmesh-official/acme.sh/wiki/How-to-run-on-OpenWRT)
|18|[![](https://acmesh-official.github.io/acmetest/status/solaris.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|SunOS/Solaris
|19|[![](https://acmesh-official.github.io/acmetest/status/gentoo-stage3-amd64.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Gentoo Linux
|20|[![Build Status](https://github.com/acmesh-official/acme.sh/workflows/LetsEncrypt/badge.svg)](https://github.com/acmesh-official/acme.sh/actions?query=workflow%3ALetsEncrypt)|Mac OSX
|21|[![](https://acmesh-official.github.io/acmetest/status/clearlinux-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|ClearLinux
For all build statuses, check our [weekly build project](https://github.com/Neilpang/acmetest):
For all build statuses, check our [weekly build project](https://github.com/acmesh-official/acmetest):
https://github.com/Neilpang/acmetest
https://github.com/acmesh-official/acmetest
# Supported CA
- Letsencrypt.org CA(default)
- [BuyPass.com CA](https://github.com/Neilpang/acme.sh/wiki/BuyPass.com-CA)
- [ZeroSSL.com CA](https://github.com/acmesh-official/acme.sh/wiki/ZeroSSL.com-CA)
- [BuyPass.com CA](https://github.com/acmesh-official/acme.sh/wiki/BuyPass.com-CA)
- [Pebble strict Mode](https://github.com/letsencrypt/pebble)
# Supported modes
@@ -85,15 +98,15 @@ https://github.com/Neilpang/acmetest
- Apache mode
- 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)
- [DNS alias mode](https://github.com/acmesh-official/acme.sh/wiki/DNS-alias-mode)
- [Stateless mode](https://github.com/acmesh-official/acme.sh/wiki/Stateless-Mode)
# 1. How to install
### 1. Install online
Check this project: https://github.com/Neilpang/get.acme.sh
Check this project: https://github.com/acmesh-official/get.acme.sh
```bash
curl https://get.acme.sh | sh
@@ -111,14 +124,14 @@ wget -O - https://get.acme.sh | sh
Clone this project and launch installation:
```bash
git clone https://github.com/Neilpang/acme.sh.git
git clone https://github.com/acmesh-official/acme.sh.git
cd ./acme.sh
./acme.sh --install
```
You `don't have to be root` then, although `it is recommended`.
Advanced Installation: https://github.com/Neilpang/acme.sh/wiki/How-to-install
Advanced Installation: https://github.com/acmesh-official/acme.sh/wiki/How-to-install
The installer will perform 3 actions:
@@ -180,7 +193,7 @@ The certs will be placed in `~/.acme.sh/example.com/`
The certs will be renewed automatically every **60** days.
More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert
More examples: https://github.com/acmesh-official/acme.sh/wiki/How-to-issue-a-cert
# 3. Install the cert to Apache/Nginx etc.
@@ -226,7 +239,7 @@ Port `80` (TCP) **MUST** be free to listen on, otherwise you will be prompted to
acme.sh --issue --standalone -d example.com -d www.example.com -d cp.example.com
```
More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert
More examples: https://github.com/acmesh-official/acme.sh/wiki/How-to-issue-a-cert
# 5. Use Standalone ssl server to issue cert
@@ -238,14 +251,14 @@ Port `443` (TCP) **MUST** be free to listen on, otherwise you will be prompted t
acme.sh --issue --alpn -d example.com -d www.example.com -d cp.example.com
```
More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert
More examples: https://github.com/acmesh-official/acme.sh/wiki/How-to-issue-a-cert
# 6. Use Apache mode
**(requires you to be root/sudoer, since it is required to interact with Apache server)**
If you are running a web server, Apache or Nginx, it is recommended to use the `Webroot mode`.
If you are running a web server, it is recommended to use the `Webroot mode`.
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.
@@ -257,15 +270,15 @@ 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.**
We don't want to mess with your apache server, don't worry.**
More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert
More examples: https://github.com/acmesh-official/acme.sh/wiki/How-to-issue-a-cert
# 7. Use Nginx mode
**(requires you to be root/sudoer, since it is required to interact with Nginx server)**
If you are running a web server, Apache or Nginx, it is recommended to use the `Webroot mode`.
If you are running a web server, it is recommended to use the `Webroot mode`.
Particularly, if you are running an nginx server, you can use nginx mode instead. This mode doesn't write any files to your web root folder.
@@ -281,9 +294,9 @@ 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.**
We don't want to mess with your nginx server, don't worry.**
More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert
More examples: https://github.com/acmesh-official/acme.sh/wiki/How-to-issue-a-cert
# 8. Automatic DNS API integration
@@ -293,13 +306,13 @@ You don't have to do anything manually!
### Currently acme.sh supports most of the dns providers:
https://github.com/Neilpang/acme.sh/wiki/dnsapi
https://github.com/acmesh-official/acme.sh/wiki/dnsapi
# 9. Use DNS manual mode:
See: https://github.com/Neilpang/acme.sh/wiki/dns-manual-mode first.
See: https://github.com/acmesh-official/acme.sh/wiki/dns-manual-mode first.
If your dns provider doesn't support any api access, you can add the txt record by your hand.
If your dns provider doesn't support any api access, you can add the txt record by hand.
```bash
acme.sh --issue --dns -d example.com -d www.example.com -d cp.example.com
@@ -430,12 +443,12 @@ acme.sh --upgrade --auto-upgrade 0
# 15. Issue a cert from an existing CSR
https://github.com/Neilpang/acme.sh/wiki/Issue-a-cert-from-existing-CSR
https://github.com/acmesh-official/acme.sh/wiki/Issue-a-cert-from-existing-CSR
# 16. Send notifications in cronjob
https://github.com/Neilpang/acme.sh/wiki/notify
https://github.com/acmesh-official/acme.sh/wiki/notify
# 17. Under the Hood
@@ -456,7 +469,7 @@ TODO:
### Code Contributors
This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].
<a href="https://github.com/Neilpang/acme.sh/graphs/contributors"><img src="https://opencollective.com/acmesh/contributors.svg?width=890&button=false" /></a>
<a href="https://github.com/acmesh-official/acme.sh/graphs/contributors"><img src="https://opencollective.com/acmesh/contributors.svg?width=890&button=false" /></a>
### Financial Contributors
@@ -487,7 +500,7 @@ License is GPLv3
Please Star and Fork me.
[Issues](https://github.com/Neilpang/acme.sh/issues) and [pull requests](https://github.com/Neilpang/acme.sh/pulls) are welcome.
[Issues](https://github.com/acmesh-official/acme.sh/issues) and [pull requests](https://github.com/acmesh-official/acme.sh/pulls) are welcome.
# 20. Donate
@@ -495,4 +508,4 @@ Your donation makes **acme.sh** better:
1. PayPal/Alipay(支付宝)/Wechat(微信): [https://donate.acme.sh/](https://donate.acme.sh/)
[Donate List](https://github.com/Neilpang/acme.sh/wiki/Donate-list)
[Donate List](https://github.com/acmesh-official/acme.sh/wiki/Donate-list)

2463
acme.sh

File diff suppressed because it is too large Load Diff

View File

@@ -2,5 +2,5 @@
deploy hook usage:
https://github.com/Neilpang/acme.sh/wiki/deployhooks
https://github.com/acmesh-official/acme.sh/wiki/deployhooks

View File

@@ -8,7 +8,7 @@
#DEPLOY_DOCKER_CONTAINER_FULLCHAIN_FILE="/path/to/fullchain.pem"
#DEPLOY_DOCKER_CONTAINER_RELOAD_CMD="service nginx force-reload"
_DEPLOY_DOCKER_WIKI="https://github.com/Neilpang/acme.sh/wiki/deploy-to-docker-containers"
_DEPLOY_DOCKER_WIKI="https://github.com/acmesh-official/acme.sh/wiki/deploy-to-docker-containers"
_DOCKER_HOST_DEFAULT="/var/run/docker.sock"
@@ -91,7 +91,7 @@ docker_deploy() {
_getdeployconf DEPLOY_DOCKER_CONTAINER_RELOAD_CMD
_debug2 DEPLOY_DOCKER_CONTAINER_RELOAD_CMD "$DEPLOY_DOCKER_CONTAINER_RELOAD_CMD"
if [ "$DEPLOY_DOCKER_CONTAINER_RELOAD_CMD" ]; then
_savedeployconf DEPLOY_DOCKER_CONTAINER_RELOAD_CMD "$DEPLOY_DOCKER_CONTAINER_RELOAD_CMD"
_savedeployconf DEPLOY_DOCKER_CONTAINER_RELOAD_CMD "$DEPLOY_DOCKER_CONTAINER_RELOAD_CMD" "base64"
fi
_cid="$(_get_id "$DEPLOY_DOCKER_CONTAINER_LABEL")"

View File

@@ -69,8 +69,8 @@ exim4_deploy() {
cp "$_exim4_conf" "$_backup_conf"
_info "Modify exim4 conf: $_exim4_conf"
if _setopt "$_exim4_conf" "tls_certificate" "=" "$_real_fullchain" \
&& _setopt "$_exim4_conf" "tls_privatekey" "=" "$_real_key"; then
if _setopt "$_exim4_conf" "tls_certificate" "=" "$_real_fullchain" &&
_setopt "$_exim4_conf" "tls_privatekey" "=" "$_real_key"; then
_info "Set config success!"
else
_err "Config exim4 server error, please report bug to us."

View File

@@ -208,33 +208,36 @@ haproxy_deploy() {
_issuerdn=$(openssl x509 -in "${_issuer}" -issuer -noout | cut -d'/' -f2,3,4,5,6,7,8,9,10)
_debug _issuerdn "${_issuerdn}"
_info "Requesting OCSP response"
# Request the OCSP response from the issuer and store it
# If the issuer is a CA cert then our command line has "-CAfile" added
if [ "${_subjectdn}" = "${_issuerdn}" ]; then
# If the issuer is a CA cert then our command line has "-CAfile" added
openssl ocsp \
-issuer "${_issuer}" \
-cert "${_pem}" \
-url "${_ocsp_url}" \
-header Host "${_ocsp_host}" \
-respout "${_ocsp}" \
-verify_other "${_issuer}" \
-no_nonce \
-CAfile "${_issuer}" \
| grep -q "${_pem}: good"
_ret=$?
_cafile_argument="-CAfile \"${_issuer}\""
else
# Issuer is not a root CA so no "-CAfile" option
openssl ocsp \
-issuer "${_issuer}" \
-cert "${_pem}" \
-url "${_ocsp_url}" \
-header Host "${_ocsp_host}" \
-respout "${_ocsp}" \
-verify_other "${_issuer}" \
-no_nonce \
| grep -q "${_pem}: good"
_ret=$?
_cafile_argument=""
fi
_debug _cafile_argument "${_cafile_argument}"
# if OpenSSL/LibreSSL is v1.1 or above, the format for the -header option has changed
_openssl_version=$(openssl version | cut -d' ' -f2)
_debug _openssl_version "${_openssl_version}"
_openssl_major=$(echo "${_openssl_version}" | cut -d '.' -f1)
_openssl_minor=$(echo "${_openssl_version}" | cut -d '.' -f2)
if [ "${_openssl_major}" -eq "1" ] && [ "${_openssl_minor}" -ge "1" ] || [ "${_openssl_major}" -ge "2" ]; then
_header_sep="="
else
_header_sep=" "
fi
# Request the OCSP response from the issuer and store it
_openssl_ocsp_cmd="openssl ocsp \
-issuer \"${_issuer}\" \
-cert \"${_pem}\" \
-url \"${_ocsp_url}\" \
-header Host${_header_sep}\"${_ocsp_host}\" \
-respout \"${_ocsp}\" \
-verify_other \"${_issuer}\" \
${_cafile_argument} \
| grep -q \"${_pem}: good\""
_debug _openssl_ocsp_cmd "${_openssl_ocsp_cmd}"
eval "${_openssl_ocsp_cmd}"
_ret=$?
else
# Non fatal: No issuer file was present so no OCSP stapling file created
_err "OCSP stapling in use but no .issuer file was present"

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env sh
# If certificate already exist it will update only cert and key not touching other parameter
# If certificate doesn't exist it will only upload cert and key and not set other parameter
# If certificate already exists it will update only cert and key, not touching other parameters
# If certificate doesn't exist it will only upload cert and key, and not set other parameters
# Note that we deploy full chain
# Written by Geoffroi Genot <ggenot@voxbone.com>

262
deploy/openstack.sh Normal file
View File

@@ -0,0 +1,262 @@
#!/usr/bin/env sh
# OpenStack Barbican deploy hook
#
# This requires you to have OpenStackClient and python-barbicanclient
# installed.
#
# You will require Keystone V3 credentials loaded into your environment, which
# could be either password or v3applicationcredential type.
#
# Author: Andy Botting <andy@andybotting.com>
openstack_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 openstack; then
_err "OpenStack client not found"
return 1
fi
_openstack_credentials || return $?
_info "Generate import pkcs12"
_import_pkcs12="$(_mktemp)"
if ! _openstack_to_pkcs "$_import_pkcs12" "$_ckey" "$_ccert" "$_cca"; then
_err "Error creating pkcs12 certificate"
return 1
fi
_debug _import_pkcs12 "$_import_pkcs12"
_base64_pkcs12=$(_base64 "multiline" <"$_import_pkcs12")
secretHrefs=$(_openstack_get_secrets)
_debug secretHrefs "$secretHrefs"
_openstack_store_secret || return $?
if [ -n "$secretHrefs" ]; then
_info "Cleaning up existing secret"
_openstack_delete_secrets || return $?
fi
_info "Certificate successfully deployed"
return 0
}
_openstack_store_secret() {
if ! openstack secret store --name "$_cdomain." -t 'application/octet-stream' -e base64 --payload "$_base64_pkcs12"; then
_err "Failed to create OpenStack secret"
return 1
fi
return
}
_openstack_delete_secrets() {
echo "$secretHrefs" | while read -r secretHref; do
_info "Deleting old secret $secretHref"
if ! openstack secret delete "$secretHref"; then
_err "Failed to delete OpenStack secret"
return 1
fi
done
return
}
_openstack_get_secrets() {
if ! secretHrefs=$(openstack secret list -f value --name "$_cdomain." | cut -d' ' -f1); then
_err "Failed to list secrets"
return 1
fi
echo "$secretHrefs"
}
_openstack_to_pkcs() {
# The existing _toPkcs command can't allow an empty password, due to sh
# -z test, so copied here and forcing the empty password.
_cpfx="$1"
_ckey="$2"
_ccert="$3"
_cca="$4"
${ACME_OPENSSL_BIN:-openssl} pkcs12 -export -out "$_cpfx" -inkey "$_ckey" -in "$_ccert" -certfile "$_cca" -password "pass:"
}
_openstack_credentials() {
_debug "Check OpenStack credentials"
# If we have OS_AUTH_URL already set in the environment, then assume we want
# to use those, otherwise use stored credentials
if [ -n "$OS_AUTH_URL" ]; then
_debug "OS_AUTH_URL env var found, using environment"
else
_debug "OS_AUTH_URL not found, loading stored credentials"
OS_AUTH_URL="${OS_AUTH_URL:-$(_readaccountconf_mutable OS_AUTH_URL)}"
OS_IDENTITY_API_VERSION="${OS_IDENTITY_API_VERSION:-$(_readaccountconf_mutable OS_IDENTITY_API_VERSION)}"
OS_AUTH_TYPE="${OS_AUTH_TYPE:-$(_readaccountconf_mutable OS_AUTH_TYPE)}"
OS_APPLICATION_CREDENTIAL_ID="${OS_APPLICATION_CREDENTIAL_ID:-$(_readaccountconf_mutable OS_APPLICATION_CREDENTIAL_ID)}"
OS_APPLICATION_CREDENTIAL_SECRET="${OS_APPLICATION_CREDENTIAL_SECRET:-$(_readaccountconf_mutable OS_APPLICATION_CREDENTIAL_SECRET)}"
OS_USERNAME="${OS_USERNAME:-$(_readaccountconf_mutable OS_USERNAME)}"
OS_PASSWORD="${OS_PASSWORD:-$(_readaccountconf_mutable OS_PASSWORD)}"
OS_PROJECT_NAME="${OS_PROJECT_NAME:-$(_readaccountconf_mutable OS_PROJECT_NAME)}"
OS_PROJECT_ID="${OS_PROJECT_ID:-$(_readaccountconf_mutable OS_PROJECT_ID)}"
OS_USER_DOMAIN_NAME="${OS_USER_DOMAIN_NAME:-$(_readaccountconf_mutable OS_USER_DOMAIN_NAME)}"
OS_USER_DOMAIN_ID="${OS_USER_DOMAIN_ID:-$(_readaccountconf_mutable OS_USER_DOMAIN_ID)}"
OS_PROJECT_DOMAIN_NAME="${OS_PROJECT_DOMAIN_NAME:-$(_readaccountconf_mutable OS_PROJECT_DOMAIN_NAME)}"
OS_PROJECT_DOMAIN_ID="${OS_PROJECT_DOMAIN_ID:-$(_readaccountconf_mutable OS_PROJECT_DOMAIN_ID)}"
fi
# Check each var and either save or clear it depending on whether its set.
# The helps us clear out old vars in the case where a user may want
# to switch between password and app creds
_debug "OS_AUTH_URL" "$OS_AUTH_URL"
if [ -n "$OS_AUTH_URL" ]; then
export OS_AUTH_URL
_saveaccountconf_mutable OS_AUTH_URL "$OS_AUTH_URL"
else
unset OS_AUTH_URL
_clearaccountconf SAVED_OS_AUTH_URL
fi
_debug "OS_IDENTITY_API_VERSION" "$OS_IDENTITY_API_VERSION"
if [ -n "$OS_IDENTITY_API_VERSION" ]; then
export OS_IDENTITY_API_VERSION
_saveaccountconf_mutable OS_IDENTITY_API_VERSION "$OS_IDENTITY_API_VERSION"
else
unset OS_IDENTITY_API_VERSION
_clearaccountconf SAVED_OS_IDENTITY_API_VERSION
fi
_debug "OS_AUTH_TYPE" "$OS_AUTH_TYPE"
if [ -n "$OS_AUTH_TYPE" ]; then
export OS_AUTH_TYPE
_saveaccountconf_mutable OS_AUTH_TYPE "$OS_AUTH_TYPE"
else
unset OS_AUTH_TYPE
_clearaccountconf SAVED_OS_AUTH_TYPE
fi
_debug "OS_APPLICATION_CREDENTIAL_ID" "$OS_APPLICATION_CREDENTIAL_ID"
if [ -n "$OS_APPLICATION_CREDENTIAL_ID" ]; then
export OS_APPLICATION_CREDENTIAL_ID
_saveaccountconf_mutable OS_APPLICATION_CREDENTIAL_ID "$OS_APPLICATION_CREDENTIAL_ID"
else
unset OS_APPLICATION_CREDENTIAL_ID
_clearaccountconf SAVED_OS_APPLICATION_CREDENTIAL_ID
fi
_secure_debug "OS_APPLICATION_CREDENTIAL_SECRET" "$OS_APPLICATION_CREDENTIAL_SECRET"
if [ -n "$OS_APPLICATION_CREDENTIAL_SECRET" ]; then
export OS_APPLICATION_CREDENTIAL_SECRET
_saveaccountconf_mutable OS_APPLICATION_CREDENTIAL_SECRET "$OS_APPLICATION_CREDENTIAL_SECRET"
else
unset OS_APPLICATION_CREDENTIAL_SECRET
_clearaccountconf SAVED_OS_APPLICATION_CREDENTIAL_SECRET
fi
_debug "OS_USERNAME" "$OS_USERNAME"
if [ -n "$OS_USERNAME" ]; then
export OS_USERNAME
_saveaccountconf_mutable OS_USERNAME "$OS_USERNAME"
else
unset OS_USERNAME
_clearaccountconf SAVED_OS_USERNAME
fi
_secure_debug "OS_PASSWORD" "$OS_PASSWORD"
if [ -n "$OS_PASSWORD" ]; then
export OS_PASSWORD
_saveaccountconf_mutable OS_PASSWORD "$OS_PASSWORD"
else
unset OS_PASSWORD
_clearaccountconf SAVED_OS_PASSWORD
fi
_debug "OS_PROJECT_NAME" "$OS_PROJECT_NAME"
if [ -n "$OS_PROJECT_NAME" ]; then
export OS_PROJECT_NAME
_saveaccountconf_mutable OS_PROJECT_NAME "$OS_PROJECT_NAME"
else
unset OS_PROJECT_NAME
_clearaccountconf SAVED_OS_PROJECT_NAME
fi
_debug "OS_PROJECT_ID" "$OS_PROJECT_ID"
if [ -n "$OS_PROJECT_ID" ]; then
export OS_PROJECT_ID
_saveaccountconf_mutable OS_PROJECT_ID "$OS_PROJECT_ID"
else
unset OS_PROJECT_ID
_clearaccountconf SAVED_OS_PROJECT_ID
fi
_debug "OS_USER_DOMAIN_NAME" "$OS_USER_DOMAIN_NAME"
if [ -n "$OS_USER_DOMAIN_NAME" ]; then
export OS_USER_DOMAIN_NAME
_saveaccountconf_mutable OS_USER_DOMAIN_NAME "$OS_USER_DOMAIN_NAME"
else
unset OS_USER_DOMAIN_NAME
_clearaccountconf SAVED_OS_USER_DOMAIN_NAME
fi
_debug "OS_USER_DOMAIN_ID" "$OS_USER_DOMAIN_ID"
if [ -n "$OS_USER_DOMAIN_ID" ]; then
export OS_USER_DOMAIN_ID
_saveaccountconf_mutable OS_USER_DOMAIN_ID "$OS_USER_DOMAIN_ID"
else
unset OS_USER_DOMAIN_ID
_clearaccountconf SAVED_OS_USER_DOMAIN_ID
fi
_debug "OS_PROJECT_DOMAIN_NAME" "$OS_PROJECT_DOMAIN_NAME"
if [ -n "$OS_PROJECT_DOMAIN_NAME" ]; then
export OS_PROJECT_DOMAIN_NAME
_saveaccountconf_mutable OS_PROJECT_DOMAIN_NAME "$OS_PROJECT_DOMAIN_NAME"
else
unset OS_PROJECT_DOMAIN_NAME
_clearaccountconf SAVED_OS_PROJECT_DOMAIN_NAME
fi
_debug "OS_PROJECT_DOMAIN_ID" "$OS_PROJECT_DOMAIN_ID"
if [ -n "$OS_PROJECT_DOMAIN_ID" ]; then
export OS_PROJECT_DOMAIN_ID
_saveaccountconf_mutable OS_PROJECT_DOMAIN_ID "$OS_PROJECT_DOMAIN_ID"
else
unset OS_PROJECT_DOMAIN_ID
_clearaccountconf SAVED_OS_PROJECT_DOMAIN_ID
fi
if [ "$OS_AUTH_TYPE" = "v3applicationcredential" ]; then
# Application Credential auth
if [ -z "$OS_APPLICATION_CREDENTIAL_ID" ] || [ -z "$OS_APPLICATION_CREDENTIAL_SECRET" ]; then
_err "When using OpenStack application credentials, OS_APPLICATION_CREDENTIAL_ID"
_err "and OS_APPLICATION_CREDENTIAL_SECRET must be set."
_err "Please check your credentials and try again."
return 1
fi
else
# Password auth
if [ -z "$OS_USERNAME" ] || [ -z "$OS_PASSWORD" ]; then
_err "OpenStack username or password not found."
_err "Please check your credentials and try again."
return 1
fi
if [ -z "$OS_PROJECT_NAME" ] && [ -z "$OS_PROJECT_ID" ]; then
_err "When using password authentication, OS_PROJECT_NAME or"
_err "OS_PROJECT_ID must be set."
_err "Please check your credentials and try again."
return 1
fi
fi
return 0
}

139
deploy/panos.sh Normal file
View File

@@ -0,0 +1,139 @@
#!/usr/bin/env sh
# Script to deploy certificates to Palo Alto Networks PANOS via API
# Note PANOS API KEY and IP address needs to be set prior to running.
# The following variables exported from environment will be used.
# If not set then values previously saved in domain.conf file are used.
#
# Firewall admin with superuser and IP address is required.
#
# export PANOS_USER="" # required
# export PANOS_PASS="" # required
# export PANOS_HOST="" # required
# This function is to parse the XML
parse_response() {
type=$2
if [ "$type" = 'keygen' ]; then
status=$(echo "$1" | sed 's/^.*\(['\'']\)\([a-z]*\)'\''.*/\2/g')
if [ "$status" = "success" ]; then
panos_key=$(echo "$1" | sed 's/^.*\(<key>\)\(.*\)<\/key>.*/\2/g')
_panos_key=$panos_key
else
message="PAN-OS Key could not be set."
fi
else
status=$(echo "$1" | sed 's/^.*"\([a-z]*\)".*/\1/g')
message=$(echo "$1" | sed 's/^.*<result>\(.*\)<\/result.*/\1/g')
fi
return 0
}
deployer() {
content=""
type=$1 # Types are keygen, cert, key, commit
_debug "**** Deploying $type *****"
panos_url="https://$_panos_host/api/"
if [ "$type" = 'keygen' ]; then
_H1="Content-Type: application/x-www-form-urlencoded"
content="type=keygen&user=$_panos_user&password=$_panos_pass"
# content="$content${nl}--$delim${nl}Content-Disposition: form-data; type=\"keygen\"; user=\"$_panos_user\"; password=\"$_panos_pass\"${nl}Content-Type: application/octet-stream${nl}${nl}"
fi
if [ "$type" = 'cert' ] || [ "$type" = 'key' ]; then
#Generate DEIM
delim="-----MultipartDelimiter$(date "+%s%N")"
nl="\015\012"
#Set Header
export _H1="Content-Type: multipart/form-data; boundary=$delim"
if [ "$type" = 'cert' ]; then
panos_url="${panos_url}?type=import"
content="--$delim${nl}Content-Disposition: form-data; name=\"category\"\r\n\r\ncertificate"
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"certificate-name\"\r\n\r\n$_cdomain"
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"key\"\r\n\r\n$_panos_key"
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"format\"\r\n\r\npem"
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"file\"; filename=\"$(basename "$_cfullchain")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_cfullchain")"
fi
if [ "$type" = 'key' ]; then
panos_url="${panos_url}?type=import"
content="--$delim${nl}Content-Disposition: form-data; name=\"category\"\r\n\r\nprivate-key"
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"certificate-name\"\r\n\r\n$_cdomain"
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"key\"\r\n\r\n$_panos_key"
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"format\"\r\n\r\npem"
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"passphrase\"\r\n\r\n123456"
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"file\"; filename=\"$(basename "$_ckey")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ckey")"
fi
#Close multipart
content="$content${nl}--$delim--${nl}${nl}"
#Convert CRLF
content=$(printf %b "$content")
fi
if [ "$type" = 'commit' ]; then
export _H1="Content-Type: application/x-www-form-urlencoded"
cmd=$(printf "%s" "<commit><partial><$_panos_user></$_panos_user></partial></commit>" | _url_encode)
content="type=commit&key=$_panos_key&cmd=$cmd"
fi
response=$(_post "$content" "$panos_url" "" "POST")
parse_response "$response" "$type"
# Saving response to variables
response_status=$status
#DEBUG
_debug response_status "$response_status"
if [ "$response_status" = "success" ]; then
_debug "Successfully deployed $type"
return 0
else
_err "Deploy of type $type failed. Try deploying with --debug to troubleshoot."
_debug "$message"
return 1
fi
}
# This is the main function that will call the other functions to deploy everything.
panos_deploy() {
_cdomain="$1"
_ckey="$2"
_cfullchain="$5"
# PANOS ENV VAR check
if [ -z "$PANOS_USER" ] || [ -z "$PANOS_PASS" ] || [ -z "$PANOS_HOST" ]; then
_debug "No ENV variables found lets check for saved variables"
_getdeployconf PANOS_USER
_getdeployconf PANOS_PASS
_getdeployconf PANOS_HOST
_panos_user=$PANOS_USER
_panos_pass=$PANOS_PASS
_panos_host=$PANOS_HOST
if [ -z "$_panos_user" ] && [ -z "$_panos_pass" ] && [ -z "$_panos_host" ]; then
_err "No host, user and pass found.. If this is the first time deploying please set PANOS_HOST, PANOS_USER and PANOS_PASS in environment variables. Delete them after you have succesfully deployed certs."
return 1
else
_debug "Using saved env variables."
fi
else
_debug "Detected ENV variables to be saved to the deploy conf."
# Encrypt and save user
_savedeployconf PANOS_USER "$PANOS_USER" 1
_savedeployconf PANOS_PASS "$PANOS_PASS" 1
_savedeployconf PANOS_HOST "$PANOS_HOST" 1
_panos_user="$PANOS_USER"
_panos_pass="$PANOS_PASS"
_panos_host="$PANOS_HOST"
fi
_debug "Let's use username and pass to generate token."
if [ -z "$_panos_user" ] || [ -z "$_panos_pass" ] || [ -z "$_panos_host" ]; then
_err "Please pass username and password and host as env variables PANOS_USER, PANOS_PASS and PANOS_HOST"
return 1
else
_debug "Getting PANOS KEY"
deployer keygen
if [ -z "$_panos_key" ]; then
_err "Missing apikey."
return 1
else
deployer cert
deployer key
deployer commit
fi
fi
}

View File

@@ -6,6 +6,8 @@
# export QINIU_AK="QINIUACCESSKEY"
# export QINIU_SK="QINIUSECRETKEY"
# export QINIU_CDN_DOMAIN="cdn.example.com"
# If you have more than one domain, just
# export QINIU_CDN_DOMAIN="cdn1.example.com cdn2.example.com"
QINIU_API_BASE="https://api.qiniu.com"
@@ -67,21 +69,23 @@ qiniu_deploy() {
_debug certId "$_certId"
## update domain ssl config
update_path="/domain/$QINIU_CDN_DOMAIN/httpsconf"
update_body="{\"certid\":$_certId,\"forceHttps\":false}"
update_access_token="$(_make_access_token "$update_path")"
_debug update_access_token "$update_access_token"
export _H1="Authorization: QBox $update_access_token"
update_response=$(_post "$update_body" "$QINIU_API_BASE$update_path" 0 "PUT" "application/json" | _dbase64 "multiline")
for domain in $QINIU_CDN_DOMAIN; do
update_path="/domain/$domain/httpsconf"
update_access_token="$(_make_access_token "$update_path")"
_debug update_access_token "$update_access_token"
export _H1="Authorization: QBox $update_access_token"
update_response=$(_post "$update_body" "$QINIU_API_BASE$update_path" 0 "PUT" "application/json" | _dbase64 "multiline")
if _contains "$update_response" "error"; then
_err "Error in updating domain httpsconf:"
_err "$update_response"
return 1
fi
if _contains "$update_response" "error"; then
_err "Error in updating domain $domain httpsconf:"
_err "$update_response"
return 1
fi
_debug update_response "$update_response"
_info "Certificate successfully deployed"
_debug update_response "$update_response"
_info "Domain $domain certificate has been deployed successfully"
done
return 0
}

View File

@@ -12,7 +12,7 @@
# 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_CMD="" # defaults to "ssh -T"
# export DEPLOY_SSH_USER="admin" # required
# export DEPLOY_SSH_SERVER="qnap" # defaults to domain name
# export DEPLOY_SSH_KEYFILE="/etc/stunnel/stunnel.pem"
@@ -20,7 +20,9 @@
# 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
# export DEPLOY_SSH_BACKUP="" # yes or no, default to yes or previously saved value
# export DEPLOY_SSH_BACKUP_PATH=".acme_ssh_deploy" # path on remote system. Defaults to .acme_ssh_deploy
# export DEPLOY_SSH_MULTI_CALL="" # yes or no, default to no or previously saved value
#
######## Public functions #####################
@@ -31,10 +33,7 @@ ssh_deploy() {
_ccert="$3"
_cca="$4"
_cfullchain="$5"
_cmdstr=""
_homedir='~'
_backupprefix="$_homedir/.acme_ssh_deploy/$_cdomain-backup"
_backupdir="$_backupprefix-$(_utc_date | tr ' ' '-')"
_deploy_ssh_servers=""
if [ -f "$DOMAIN_CONF" ]; then
# shellcheck disable=SC1090
@@ -71,18 +70,74 @@ ssh_deploy() {
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"
Le_Deploy_ssh_cmd="ssh -T"
fi
# BACKUP is optional. If not provided then default to yes
# BACKUP is optional. If not provided then default to previously saved value or yes.
if [ "$DEPLOY_SSH_BACKUP" = "no" ]; then
Le_Deploy_ssh_backup="no"
elif [ -z "$Le_Deploy_ssh_backup" ]; then
elif [ -z "$Le_Deploy_ssh_backup" ] || [ "$DEPLOY_SSH_BACKUP" = "yes" ]; then
Le_Deploy_ssh_backup="yes"
fi
_savedomainconf Le_Deploy_ssh_backup "$Le_Deploy_ssh_backup"
# BACKUP_PATH is optional. If not provided then default to previously saved value or .acme_ssh_deploy
if [ -n "$DEPLOY_SSH_BACKUP_PATH" ]; then
Le_Deploy_ssh_backup_path="$DEPLOY_SSH_BACKUP_PATH"
elif [ -z "$Le_Deploy_ssh_backup_path" ]; then
Le_Deploy_ssh_backup_path=".acme_ssh_deploy"
fi
_savedomainconf Le_Deploy_ssh_backup_path "$Le_Deploy_ssh_backup_path"
# MULTI_CALL is optional. If not provided then default to previously saved
# value (which may be undefined... equivalent to "no").
if [ "$DEPLOY_SSH_MULTI_CALL" = "yes" ]; then
Le_Deploy_ssh_multi_call="yes"
_savedomainconf Le_Deploy_ssh_multi_call "$Le_Deploy_ssh_multi_call"
elif [ "$DEPLOY_SSH_MULTI_CALL" = "no" ]; then
Le_Deploy_ssh_multi_call=""
_cleardomainconf Le_Deploy_ssh_multi_call
fi
_deploy_ssh_servers=$Le_Deploy_ssh_server
for Le_Deploy_ssh_server in $_deploy_ssh_servers; do
_ssh_deploy
done
}
_ssh_deploy() {
_err_code=0
_cmdstr=""
_backupprefix=""
_backupdir=""
_info "Deploy certificates to remote server $Le_Deploy_ssh_user@$Le_Deploy_ssh_server"
if [ "$Le_Deploy_ssh_multi_call" = "yes" ]; then
_info "Using MULTI_CALL mode... Required commands sent in multiple calls to remote host"
else
_info "Required commands batched and sent in single call to remote host"
fi
if [ "$Le_Deploy_ssh_backup" = "yes" ]; then
_backupprefix="$Le_Deploy_ssh_backup_path/$_cdomain-backup"
_backupdir="$_backupprefix-$(_utc_date | tr ' ' '-')"
# 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."
if [ "$Le_Deploy_ssh_multi_call" = "yes" ]; then
if ! _ssh_remote_cmd "$_cmdstr"; then
return $_err_code
fi
_cmdstr=""
fi
fi
# KEYFILE is optional.
# If provided then private key will be copied to provided filename.
@@ -98,6 +153,12 @@ ssh_deploy() {
# 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"
if [ "$Le_Deploy_ssh_multi_call" = "yes" ]; then
if ! _ssh_remote_cmd "$_cmdstr"; then
return $_err_code
fi
_cmdstr=""
fi
fi
# CERTFILE is optional.
@@ -118,6 +179,12 @@ ssh_deploy() {
# 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"
if [ "$Le_Deploy_ssh_multi_call" = "yes" ]; then
if ! _ssh_remote_cmd "$_cmdstr"; then
return $_err_code
fi
_cmdstr=""
fi
fi
# CAFILE is optional.
@@ -128,8 +195,8 @@ ssh_deploy() {
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 [ "$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
@@ -139,6 +206,12 @@ ssh_deploy() {
# 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"
if [ "$Le_Deploy_ssh_multi_call" = "yes" ]; then
if ! _ssh_remote_cmd "$_cmdstr"; then
return $_err_code
fi
_cmdstr=""
fi
fi
# FULLCHAIN is optional.
@@ -149,9 +222,9 @@ ssh_deploy() {
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 [ "$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
@@ -161,6 +234,12 @@ ssh_deploy() {
# 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"
if [ "$Le_Deploy_ssh_multi_call" = "yes" ]; then
if ! _ssh_remote_cmd "$_cmdstr"; then
return $_err_code
fi
_cmdstr=""
fi
fi
# REMOTE_CMD is optional.
@@ -172,34 +251,36 @@ ssh_deploy() {
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"
if [ "$Le_Deploy_ssh_multi_call" = "yes" ]; then
if ! _ssh_remote_cmd "$_cmdstr"; then
return $_err_code
fi
_cmdstr=""
fi
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."
# if commands not all sent in multiple calls then all commands sent in a single SSH call now...
if [ -n "$_cmdstr" ]; then
if ! _ssh_remote_cmd "$_cmdstr"; then
return $_err_code
fi
fi
return 0
}
_secure_debug "Remote commands to execute: " "$_cmdstr"
#cmd
_ssh_remote_cmd() {
_cmd="$1"
_secure_debug "Remote commands to execute: $_cmd"
_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="$?"
$Le_Deploy_ssh_cmd "$Le_Deploy_ssh_user@$Le_Deploy_ssh_server" sh -c "'$_cmd'"
_err_code="$?"
if [ "$_ret" != "0" ]; then
_err "Error code $_ret returned from $Le_Deploy_ssh_cmd"
if [ "$_err_code" != "0" ]; then
_err "Error code $_err_code returned from ssh"
fi
return $_ret
return $_err_code
}

152
deploy/synology_dsm.sh Normal file
View File

@@ -0,0 +1,152 @@
#!/usr/bin/env sh
# Here is a script to deploy cert to Synology DSM
#
# it requires the jq and curl are in the $PATH and the following
# environment variables must be set:
#
# SYNO_Username - Synology Username to login (must be an administrator)
# SYNO_Password - Synology Password to login
# SYNO_Certificate - Certificate description to target for replacement
#
# The following environmental variables may be set if you don't like their
# default values:
#
# SYNO_Scheme - defaults to http
# SYNO_Hostname - defaults to localhost
# SYNO_Port - defaults to 5000
# SYNO_DID - device ID to skip OTP - defaults to empty
#
#returns 0 means success, otherwise error.
######## Public functions #####################
_syno_get_cookie_data() {
grep -i "\W$1=" | grep -i "^Set-Cookie:" | _tail_n 1 | _egrep_o "$1=[^;]*;" | tr -d ';'
}
#domain keyfile certfile cafile fullchain
synology_dsm_deploy() {
_cdomain="$1"
_ckey="$2"
_ccert="$3"
_cca="$4"
_debug _cdomain "$_cdomain"
# Get Username and Password, but don't save until we successfully authenticate
_getdeployconf SYNO_Username
_getdeployconf SYNO_Password
_getdeployconf SYNO_Create
_getdeployconf SYNO_DID
if [ -z "${SYNO_Username:-}" ] || [ -z "${SYNO_Password:-}" ]; then
_err "SYNO_Username & SYNO_Password must be set"
return 1
fi
_debug2 SYNO_Username "$SYNO_Username"
_secure_debug2 SYNO_Password "$SYNO_Password"
# Optional scheme, hostname, and port for Synology DSM
_getdeployconf SYNO_Scheme
_getdeployconf SYNO_Hostname
_getdeployconf SYNO_Port
# default vaules for scheme, hostname, and port
# defaulting to localhost and http because it's localhost...
[ -n "${SYNO_Scheme}" ] || SYNO_Scheme="http"
[ -n "${SYNO_Hostname}" ] || SYNO_Hostname="localhost"
[ -n "${SYNO_Port}" ] || SYNO_Port="5000"
_savedeployconf SYNO_Scheme "$SYNO_Scheme"
_savedeployconf SYNO_Hostname "$SYNO_Hostname"
_savedeployconf SYNO_Port "$SYNO_Port"
_debug2 SYNO_Scheme "$SYNO_Scheme"
_debug2 SYNO_Hostname "$SYNO_Hostname"
_debug2 SYNO_Port "$SYNO_Port"
# Get the certificate description, but don't save it until we verfiy it's real
_getdeployconf SYNO_Certificate
_debug SYNO_Certificate "${SYNO_Certificate:-}"
_base_url="$SYNO_Scheme://$SYNO_Hostname:$SYNO_Port"
_debug _base_url "$_base_url"
# Login, get the token from JSON and session id from cookie
_info "Logging into $SYNO_Hostname:$SYNO_Port"
encoded_username="$(printf "%s" "$SYNO_Username" | _url_encode)"
encoded_password="$(printf "%s" "$SYNO_Password" | _url_encode)"
encoded_did="$(printf "%s" "$SYNO_DID" | _url_encode)"
response=$(_get "$_base_url/webman/login.cgi?username=$encoded_username&passwd=$encoded_password&enable_syno_token=yes&device_id=$encoded_did" 1)
token=$(echo "$response" | grep -i "X-SYNO-TOKEN:" | sed -n 's/^X-SYNO-TOKEN: \(.*\)$/\1/pI' | tr -d "\r\n")
_debug3 response "$response"
_debug token "$token"
if [ -z "$token" ]; then
_err "Unable to authenticate to $SYNO_Hostname:$SYNO_Port using $SYNO_Scheme."
_err "Check your username and password."
return 1
fi
_H1="Cookie: $(echo "$response" | _syno_get_cookie_data "id"); $(echo "$response" | _syno_get_cookie_data "smid")"
_H2="X-SYNO-TOKEN: $token"
export _H1
export _H2
_debug2 H1 "${_H1}"
_debug2 H2 "${_H2}"
# Now that we know the username and password are good, save them
_savedeployconf SYNO_Username "$SYNO_Username"
_savedeployconf SYNO_Password "$SYNO_Password"
_savedeployconf SYNO_DID "$SYNO_DID"
_info "Getting certificates in Synology DSM"
response=$(_post "api=SYNO.Core.Certificate.CRT&method=list&version=1" "$_base_url/webapi/entry.cgi")
_debug3 response "$response"
id=$(echo "$response" | sed -n "s/.*\"desc\":\"$SYNO_Certificate\",\"id\":\"\([^\"]*\).*/\1/p")
_debug2 id "$id"
if [ -z "$id" ] && [ -z "${SYNO_Create:-}" ]; then
_err "Unable to find certificate: $SYNO_Certificate and \$SYNO_Create is not set"
return 1
fi
# we've verified this certificate description is a thing, so save it
_savedeployconf SYNO_Certificate "$SYNO_Certificate"
default=false
if echo "$response" | sed -n "s/.*\"desc\":\"$SYNO_Certificate\",\([^{]*\).*/\1/p" | grep -- 'is_default":true' >/dev/null; then
default=true
fi
_debug2 default "$default"
_info "Generate form POST request"
nl="\0015\0012"
delim="--------------------------$(_utc_date | tr -d -- '-: ')"
content="--$delim${nl}Content-Disposition: form-data; name=\"key\"; filename=\"$(basename "$_ckey")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ckey")\0012"
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"cert\"; filename=\"$(basename "$_ccert")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ccert")\0012"
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"inter_cert\"; filename=\"$(basename "$_cca")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_cca")\0012"
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"id\"${nl}${nl}$id"
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"desc\"${nl}${nl}${SYNO_Certificate}"
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"as_default\"${nl}${nl}${default}"
content="$content${nl}--$delim--${nl}"
content="$(printf "%b_" "$content")"
content="${content%_}" # protect trailing \n
_info "Upload certificate to the Synology DSM"
response=$(_post "$content" "$_base_url/webapi/entry.cgi?api=SYNO.Core.Certificate&method=import&version=1&SynoToken=$token" "" "POST" "multipart/form-data; boundary=${delim}")
_debug3 response "$response"
if ! echo "$response" | grep '"error":' >/dev/null; then
if echo "$response" | grep '"restart_httpd":true' >/dev/null; then
_info "http services were restarted"
else
_info "http services were NOT restarted"
fi
return 0
else
_err "Unable to update certificate, error code $response"
return 1
fi
}

View File

@@ -43,7 +43,7 @@ vault_cli_deploy() {
return 1
fi
VAULT_CMD=$(which vault)
VAULT_CMD=$(command -v vault)
if [ ! $? ]; then
_err "cannot find vault binary!"
return 1

View File

@@ -65,9 +65,9 @@ vsftpd_deploy() {
cp "$_vsftpd_conf" "$_backup_conf"
_info "Modify vsftpd conf: $_vsftpd_conf"
if _setopt "$_vsftpd_conf" "rsa_cert_file" "=" "$_real_fullchain" \
&& _setopt "$_vsftpd_conf" "rsa_private_key_file" "=" "$_real_key" \
&& _setopt "$_vsftpd_conf" "ssl_enable" "=" "YES"; then
if _setopt "$_vsftpd_conf" "rsa_cert_file" "=" "$_real_fullchain" &&
_setopt "$_vsftpd_conf" "rsa_private_key_file" "=" "$_real_key" &&
_setopt "$_vsftpd_conf" "ssl_enable" "=" "YES"; then
_info "Set config success!"
else
_err "Config vsftpd server error, please report bug to us."

View File

@@ -2,5 +2,5 @@
DNS api usage:
https://github.com/Neilpang/acme.sh/wiki/dnsapi
https://github.com/acmesh-official/acme.sh/wiki/dnsapi

254
dnsapi/dns_1984hosting.sh Executable file
View File

@@ -0,0 +1,254 @@
#!/usr/bin/env sh
#This file name is "dns_1984hosting.sh"
#So, here must be a method dns_1984hosting_add()
#Which will be called by acme.sh to add the txt record to your api system.
#returns 0 means success, otherwise error.
#Author: Adrian Fedoreanu
#Report Bugs here: https://github.com/acmesh-official/acme.sh
# or here... https://github.com/acmesh-official/acme.sh/issues/2851
#
######## Public functions #####################
# Export 1984HOSTING username and password in following variables
#
# One984HOSTING_Username=username
# One984HOSTING_Password=password
#
# sessionid cookie is saved in ~/.acme.sh/account.conf
# username/password need to be set only when changed.
#Usage: dns_1984hosting_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_1984hosting_add() {
fulldomain=$1
txtvalue=$2
_info "Add TXT record using 1984Hosting"
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
if ! _1984hosting_login; then
_err "1984Hosting login failed for user $One984HOSTING_Username. Check $HTTP_HEADER file"
return 1
fi
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain" "$fulldomain"
return 1
fi
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
_1984hosting_add_txt_record "$_domain" "$_sub_domain" "$txtvalue"
return $?
}
#Usage: fulldomain txtvalue
#Remove the txt record after validation.
dns_1984hosting_rm() {
fulldomain=$1
txtvalue=$2
_info "Delete TXT record using 1984Hosting"
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
if ! _1984hosting_login; then
_err "1984Hosting login failed for user $One984HOSTING_Username. Check $HTTP_HEADER file"
return 1
fi
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain" "$fulldomain"
return 1
fi
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
_1984hosting_delete_txt_record "$_domain" "$_sub_domain"
return $?
}
#################### Private functions below ##################################
# usage _1984hosting_add_txt_record domain subdomain value
# returns 0 success
_1984hosting_add_txt_record() {
_debug "Add TXT record $1 with value '$3'"
domain="$1"
subdomain="$2"
value="$(printf '%s' "$3" | _url_encode)"
url="https://management.1984hosting.com/domains/entry/"
postdata="entry=new"
postdata="$postdata&type=TXT"
postdata="$postdata&ttl=3600"
postdata="$postdata&zone=$domain"
postdata="$postdata&host=$subdomain"
postdata="$postdata&rdata=%22$value%22"
_debug2 postdata "$postdata"
_authpost "$postdata" "$url"
response="$(echo "$_response" | _normalizeJson)"
_debug2 response "$response"
if _contains "$response" '"haserrors": true'; then
_err "1984Hosting failed to add TXT record for $subdomain bad RC from _post"
return 1
elif _contains "$response" "<html>"; then
_err "1984Hosting failed to add TXT record for $subdomain. Check $HTTP_HEADER file"
return 1
elif _contains "$response" '"auth": false'; then
_err "1984Hosting failed to add TXT record for $subdomain. Invalid or expired cookie"
return 1
fi
_info "Added acme challenge TXT record for $fulldomain at 1984Hosting"
return 0
}
# usage _1984hosting_delete_txt_record entry_id
# returns 0 success
_1984hosting_delete_txt_record() {
_debug "Delete $fulldomain TXT record"
domain="$1"
subdomain="$2"
url="https://management.1984hosting.com/domains"
_htmlget "$url" "$domain"
_debug2 _response "$_response"
zone_id="$(echo "$_response" | _egrep_o 'zone\/[0-9]+')"
_debug2 zone_id "$zone_id"
if [ -z "$zone_id" ]; then
_err "Error getting zone_id for $1"
return 1
fi
_htmlget "$url/$zone_id" "$subdomain"
_debug2 _response "$_response"
entry_id="$(echo "$_response" | _egrep_o 'entry_[0-9]+' | sed 's/entry_//')"
_debug2 entry_id "$entry_id"
if [ -z "$entry_id" ]; then
_err "Error getting TXT entry_id for $1"
return 1
fi
_authpost "entry=$entry_id" "$url/delentry/"
response="$(echo "$_response" | _normalizeJson)"
_debug2 response "$response"
if ! _contains "$response" '"ok": true'; then
_err "1984Hosting failed to delete TXT record for $entry_id bad RC from _post"
return 1
fi
_info "Deleted acme challenge TXT record for $fulldomain at 1984Hosting"
return 0
}
# usage: _1984hosting_login username password
# returns 0 success
_1984hosting_login() {
if ! _check_credentials; then return 1; fi
if _check_cookie; then
_debug "Already logged in"
return 0
fi
_debug "Login to 1984Hosting as user $One984HOSTING_Username"
username=$(printf '%s' "$One984HOSTING_Username" | _url_encode)
password=$(printf '%s' "$One984HOSTING_Password" | _url_encode)
url="https://management.1984hosting.com/accounts/checkuserauth/"
response="$(_post "username=$username&password=$password&otpkey=" "$url")"
response="$(echo "$response" | _normalizeJson)"
_debug2 response "$response"
if _contains "$response" '"loggedin": true'; then
One984HOSTING_COOKIE="$(grep -i '^set-cookie:' "$HTTP_HEADER" | _tail_n 1 | _egrep_o 'sessionid=[^;]*;' | tr -d ';')"
export One984HOSTING_COOKIE
_saveaccountconf_mutable One984HOSTING_COOKIE "$One984HOSTING_COOKIE"
return 0
fi
return 1
}
_check_credentials() {
if [ -z "$One984HOSTING_Username" ] || [ -z "$One984HOSTING_Password" ]; then
One984HOSTING_Username=""
One984HOSTING_Password=""
_err "You haven't specified 1984Hosting username or password yet."
_err "Please export as One984HOSTING_Username / One984HOSTING_Password and try again."
return 1
fi
return 0
}
_check_cookie() {
One984HOSTING_COOKIE="${One984HOSTING_COOKIE:-$(_readaccountconf_mutable One984HOSTING_COOKIE)}"
if [ -z "$One984HOSTING_COOKIE" ]; then
_debug "No cached cookie found"
return 1
fi
_authget "https://management.1984hosting.com/accounts/loginstatus/"
response="$(echo "$_response" | _normalizeJson)"
if _contains "$response" '"ok": true'; then
_debug "Cached cookie still valid"
return 0
fi
_debug "Cached cookie no longer valid"
One984HOSTING_COOKIE=""
_saveaccountconf_mutable One984HOSTING_COOKIE "$One984HOSTING_COOKIE"
return 1
}
#_acme-challenge.www.domain.com
#returns
# _sub_domain=_acme-challenge.www
# _domain=domain.com
_get_root() {
domain="$1"
i=2
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
if [ -z "$h" ]; then
#not valid
return 1
fi
_authget "https://management.1984hosting.com/domains/soacheck/?zone=$h&nameserver=ns0.1984.is."
if _contains "$_response" "serial"; 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
}
# add extra headers to request
_authget() {
export _H1="Cookie: $One984HOSTING_COOKIE"
_response=$(_get "$1")
}
# truncate huge HTML response
# echo: Argument list too long
_htmlget() {
export _H1="Cookie: $One984HOSTING_COOKIE"
_response=$(_get "$1" | grep "$2" | _head_n 1)
}
# add extra headers to request
_authpost() {
export _H1="Cookie: $One984HOSTING_COOKIE"
_response=$(_post "$1" "$2")
}

View File

@@ -181,6 +181,7 @@ _describe_records_query() {
_clean() {
_check_exist_query "$_domain" "$_sub_domain"
# do not correct grammar here
if ! _ali_rest "Check exist records" "ignore"; then
return 1
fi

163
dnsapi/dns_arvan.sh Normal file
View File

@@ -0,0 +1,163 @@
#!/usr/bin/env sh
#Arvan_Token="xxxx"
ARVAN_API_URL="https://napi.arvancloud.com/cdn/4.0/domains"
#Author: Ehsan Aliakbar
#Report Bugs here: https://github.com/Neilpang/acme.sh
#
######## Public functions #####################
#Usage: dns_arvan_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_arvan_add() {
fulldomain=$1
txtvalue=$2
_info "Using Arvan"
Arvan_Token="${Arvan_Token:-$(_readaccountconf_mutable Arvan_Token)}"
if [ -z "$Arvan_Token" ]; then
_err "You didn't specify \"Arvan_Token\" token yet."
_err "You can get yours from here https://npanel.arvancloud.com/profile/api-keys"
return 1
fi
#save the api token to the account conf file.
_saveaccountconf_mutable Arvan_Token "$Arvan_Token"
_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 _arvan_rest POST "$_domain/dns-records" "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"value\":{\"text\":\"$txtvalue\"},\"ttl\":120}"; then
if _contains "$response" "$txtvalue"; then
_info "Added, OK"
return 0
elif _contains "$response" "Record Data is Duplicated"; then
_info "Already exists, 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_arvan_rm() {
fulldomain=$1
txtvalue=$2
_info "Using Arvan"
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
Arvan_Token="${Arvan_Token:-$(_readaccountconf_mutable Arvan_Token)}"
_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"
shorted_txtvalue=$(printf "%s" "$txtvalue" | cut -d "-" -d "_" -f1)
_arvan_rest GET "${_domain}/dns-records?search=$shorted_txtvalue"
if ! printf "%s" "$response" | grep \"current_page\":1 >/dev/null; then
_err "Error on Arvan Api"
_err "Please create a github issue with debbug log"
return 1
fi
count=$(printf "%s\n" "$response" | _egrep_o "\"total\":[^,]*" | cut -d : -f 2)
_debug count "$count"
if [ "$count" = "0" ]; then
_info "Don't need to remove."
else
record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | head -n 1)
_debug "record_id" "$record_id"
if [ -z "$record_id" ]; then
_err "Can not get record id to remove."
return 1
fi
if ! _arvan_rest "DELETE" "${_domain}/dns-records/$record_id"; then
_err "Delete record error."
return 1
fi
_debug "$response"
_contains "$response" 'dns record deleted'
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=1
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 ! _arvan_rest GET "?search=$h"; then
return 1
fi
if _contains "$response" "\"domain\":\"$h\"" || _contains "$response" '"total":1'; then
_domain_id=$(echo "$response" | _egrep_o "\[.\"id\":\"[^\"]*\"" | _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
}
_arvan_rest() {
mtd="$1"
ep="$2"
data="$3"
token_trimmed=$(echo "$Arvan_Token" | tr -d '"')
export _H1="Authorization: $token_trimmed"
if [ "$mtd" = "DELETE" ]; then
#DELETE Request shouldn't have Content-Type
_debug data "$data"
response="$(_post "$data" "$ARVAN_API_URL/$ep" "" "$mtd")"
elif [ "$mtd" = "POST" ]; then
export _H2="Content-Type: application/json"
_debug data "$data"
response="$(_post "$data" "$ARVAN_API_URL/$ep" "" "$mtd")"
else
response="$(_get "$ARVAN_API_URL/$ep$data")"
fi
}

View File

@@ -12,7 +12,7 @@
AWS_HOST="route53.amazonaws.com"
AWS_URL="https://$AWS_HOST"
AWS_WIKI="https://github.com/Neilpang/acme.sh/wiki/How-to-use-Amazon-Route53-API"
AWS_WIKI="https://github.com/acmesh-official/acme.sh/wiki/How-to-use-Amazon-Route53-API"
######## Public functions #####################
@@ -23,6 +23,7 @@ dns_aws_add() {
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)}"
AWS_DNS_SLOWRATE="${AWS_DNS_SLOWRATE:-$(_readaccountconf_mutable AWS_DNS_SLOWRATE)}"
if [ -z "$AWS_ACCESS_KEY_ID" ] || [ -z "$AWS_SECRET_ACCESS_KEY" ]; then
_use_container_role || _use_instance_role
@@ -40,6 +41,7 @@ dns_aws_add() {
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"
_saveaccountconf_mutable AWS_DNS_SLOWRATE "$AWS_DNS_SLOWRATE"
fi
_debug "First detect the root zone"
@@ -77,7 +79,13 @@ dns_aws_add() {
if aws_rest POST "2013-04-01$_domain_id/rrset/" "" "$_aws_tmpl_xml" && _contains "$response" "ChangeResourceRecordSetsResponse"; then
_info "TXT record updated successfully."
_sleep 1
if [ -n "$AWS_DNS_SLOWRATE" ]; then
_info "Slow rate activated: sleeping for $AWS_DNS_SLOWRATE seconds"
_sleep "$AWS_DNS_SLOWRATE"
else
_sleep 1
fi
return 0
fi
_sleep 1
@@ -91,6 +99,7 @@ dns_aws_rm() {
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)}"
AWS_DNS_SLOWRATE="${AWS_DNS_SLOWRATE:-$(_readaccountconf_mutable AWS_DNS_SLOWRATE)}"
if [ -z "$AWS_ACCESS_KEY_ID" ] || [ -z "$AWS_SECRET_ACCESS_KEY" ]; then
_use_container_role || _use_instance_role
@@ -125,7 +134,13 @@ dns_aws_rm() {
if aws_rest POST "2013-04-01$_domain_id/rrset/" "" "$_aws_tmpl_xml" && _contains "$response" "ChangeResourceRecordSetsResponse"; then
_info "TXT record deleted successfully."
_sleep 1
if [ -n "$AWS_DNS_SLOWRATE" ]; then
_info "Slow rate activated: sleeping for $AWS_DNS_SLOWRATE seconds"
_sleep "$AWS_DNS_SLOWRATE"
else
_sleep 1
fi
return 0
fi
_sleep 1
@@ -207,21 +222,21 @@ _use_instance_role() {
_use_metadata() {
_aws_creds="$(
_get "$1" "" 1 \
| _normalizeJson \
| tr '{,}' '\n' \
| while read -r _line; do
_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" ;;
AccessKeyId) echo "AWS_ACCESS_KEY_ID=$_value" ;;
SecretAccessKey) echo "AWS_SECRET_ACCESS_KEY=$_value" ;;
Token) echo "AWS_SESSION_TOKEN=$_value" ;;
esac
done \
| paste -sd' ' -
done |
paste -sd' ' -
)"
_secure_debug "_aws_creds" "$_aws_creds"

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env sh
WIKI="https://github.com/Neilpang/acme.sh/wiki/How-to-use-Azure-DNS"
WIKI="https://github.com/acmesh-official/acme.sh/wiki/How-to-use-Azure-DNS"
######## Public functions #####################
@@ -172,7 +172,7 @@ dns_azure_rm() {
_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")"
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
@@ -220,7 +220,7 @@ _azure_rest() {
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"
: >"$HTTP_HEADER"
_debug "$ep"
if [ "$m" != "GET" ]; then
_secure_debug2 "data $data"

View File

@@ -7,6 +7,7 @@
#CF_Token="xxxx"
#CF_Account_ID="xxxx"
#CF_Zone_ID="xxxx"
CF_Api="https://api.cloudflare.com/client/v4"
@@ -19,12 +20,14 @@ dns_cf_add() {
CF_Token="${CF_Token:-$(_readaccountconf_mutable CF_Token)}"
CF_Account_ID="${CF_Account_ID:-$(_readaccountconf_mutable CF_Account_ID)}"
CF_Zone_ID="${CF_Zone_ID:-$(_readaccountconf_mutable CF_Zone_ID)}"
CF_Key="${CF_Key:-$(_readaccountconf_mutable CF_Key)}"
CF_Email="${CF_Email:-$(_readaccountconf_mutable CF_Email)}"
if [ "$CF_Token" ]; then
_saveaccountconf_mutable CF_Token "$CF_Token"
_saveaccountconf_mutable CF_Account_ID "$CF_Account_ID"
_saveaccountconf_mutable CF_Zone_ID "$CF_Zone_ID"
else
if [ -z "$CF_Key" ] || [ -z "$CF_Email" ]; then
CF_Key=""
@@ -56,7 +59,7 @@ dns_cf_add() {
_debug "Getting txt records"
_cf_rest GET "zones/${_domain_id}/dns_records?type=TXT&name=$fulldomain"
if ! printf "%s" "$response" | grep \"success\":true >/dev/null; then
if ! echo "$response" | tr -d " " | grep \"success\":true >/dev/null; then
_err "Error"
return 1
fi
@@ -91,6 +94,7 @@ dns_cf_rm() {
CF_Token="${CF_Token:-$(_readaccountconf_mutable CF_Token)}"
CF_Account_ID="${CF_Account_ID:-$(_readaccountconf_mutable CF_Account_ID)}"
CF_Zone_ID="${CF_Zone_ID:-$(_readaccountconf_mutable CF_Zone_ID)}"
CF_Key="${CF_Key:-$(_readaccountconf_mutable CF_Key)}"
CF_Email="${CF_Email:-$(_readaccountconf_mutable CF_Email)}"
@@ -106,17 +110,17 @@ dns_cf_rm() {
_debug "Getting txt records"
_cf_rest GET "zones/${_domain_id}/dns_records?type=TXT&name=$fulldomain&content=$txtvalue"
if ! printf "%s" "$response" | grep \"success\":true >/dev/null; then
_err "Error"
if ! echo "$response" | tr -d " " | grep \"success\":true >/dev/null; then
_err "Error: $response"
return 1
fi
count=$(printf "%s\n" "$response" | _egrep_o "\"count\":[^,]*" | cut -d : -f 2)
count=$(echo "$response" | _egrep_o "\"count\": *[^,]*" | cut -d : -f 2 | tr -d " ")
_debug count "$count"
if [ "$count" = "0" ]; then
_info "Don't need to remove."
else
record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | head -n 1)
record_id=$(echo "$response" | _egrep_o "\"id\": *\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | _head_n 1 | tr -d " ")
_debug "record_id" "$record_id"
if [ -z "$record_id" ]; then
_err "Can not get record id to remove."
@@ -126,7 +130,7 @@ dns_cf_rm() {
_err "Delete record error."
return 1
fi
_contains "$response" '"success":true'
echo "$response" | tr -d " " | grep \"success\":true >/dev/null
fi
}
@@ -141,6 +145,28 @@ _get_root() {
domain=$1
i=1
p=1
# Use Zone ID directly if provided
if [ "$CF_Zone_ID" ]; then
if ! _cf_rest GET "zones/$CF_Zone_ID"; then
return 1
else
if echo "$response" | tr -d " " | grep \"success\":true >/dev/null; then
_domain=$(echo "$response" | _egrep_o "\"name\": *\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | _head_n 1 | tr -d " ")
if [ "$_domain" ]; then
_cutlength=$((${#domain} - ${#_domain} - 1))
_sub_domain=$(printf "%s" "$domain" | cut -c "1-$_cutlength")
_domain_id=$CF_Zone_ID
return 0
else
return 1
fi
else
return 1
fi
fi
fi
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
_debug h "$h"
@@ -160,7 +186,7 @@ _get_root() {
fi
if _contains "$response" "\"name\":\"$h\"" || _contains "$response" '"total_count":1'; then
_domain_id=$(echo "$response" | _egrep_o "\[.\"id\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \")
_domain_id=$(echo "$response" | _egrep_o "\[.\"id\": *\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \" | tr -d " ")
if [ "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_domain=$h

197
dnsapi/dns_clouddns.sh Executable file
View File

@@ -0,0 +1,197 @@
#!/usr/bin/env sh
# Author: Radek Sprta <sprta@vshosting.cz>
#CLOUDDNS_EMAIL=XXXXX
#CLOUDDNS_PASSWORD="YYYYYYYYY"
#CLOUDDNS_CLIENT_ID=XXXXX
CLOUDDNS_API='https://admin.vshosting.cloud/clouddns'
CLOUDDNS_LOGIN_API='https://admin.vshosting.cloud/api/public/auth/login'
######## Public functions #####################
# Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_clouddns_add() {
fulldomain=$1
txtvalue=$2
_debug "fulldomain" "$fulldomain"
CLOUDDNS_CLIENT_ID="${CLOUDDNS_CLIENT_ID:-$(_readaccountconf_mutable CLOUDDNS_CLIENT_ID)}"
CLOUDDNS_EMAIL="${CLOUDDNS_EMAIL:-$(_readaccountconf_mutable CLOUDDNS_EMAIL)}"
CLOUDDNS_PASSWORD="${CLOUDDNS_PASSWORD:-$(_readaccountconf_mutable CLOUDDNS_PASSWORD)}"
if [ -z "$CLOUDDNS_PASSWORD" ] || [ -z "$CLOUDDNS_EMAIL" ] || [ -z "$CLOUDDNS_CLIENT_ID" ]; then
CLOUDDNS_CLIENT_ID=""
CLOUDDNS_EMAIL=""
CLOUDDNS_PASSWORD=""
_err "You didn't specify a CloudDNS password, email and client ID yet."
return 1
fi
if ! _contains "$CLOUDDNS_EMAIL" "@"; then
_err "It seems that the CLOUDDNS_EMAIL=$CLOUDDNS_EMAIL is not a valid email address."
_err "Please check and retry."
return 1
fi
# Save CloudDNS client id, email and password to config file
_saveaccountconf_mutable CLOUDDNS_CLIENT_ID "$CLOUDDNS_CLIENT_ID"
_saveaccountconf_mutable CLOUDDNS_EMAIL "$CLOUDDNS_EMAIL"
_saveaccountconf_mutable CLOUDDNS_PASSWORD "$CLOUDDNS_PASSWORD"
_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"
# Add TXT record
data="{\"type\":\"TXT\",\"name\":\"$fulldomain.\",\"value\":\"$txtvalue\",\"domainId\":\"$_domain_id\"}"
if _clouddns_api POST "record-txt" "$data"; then
if _contains "$response" "$txtvalue"; then
_info "Added, OK"
elif _contains "$response" '"code":4136'; then
_info "Already exists, OK"
else
_err "Add TXT record error."
return 1
fi
fi
_debug "Publishing record changes"
_clouddns_api PUT "domain/$_domain_id/publish" "{\"soaTtl\":300}"
}
# Usage: rm _acme-challenge.www.domain.com
dns_clouddns_rm() {
fulldomain=$1
_debug "fulldomain" "$fulldomain"
CLOUDDNS_CLIENT_ID="${CLOUDDNS_CLIENT_ID:-$(_readaccountconf_mutable CLOUDDNS_CLIENT_ID)}"
CLOUDDNS_EMAIL="${CLOUDDNS_EMAIL:-$(_readaccountconf_mutable CLOUDDNS_EMAIL)}"
CLOUDDNS_PASSWORD="${CLOUDDNS_PASSWORD:-$(_readaccountconf_mutable CLOUDDNS_PASSWORD)}"
_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"
# Get record ID
_clouddns_api GET "domain/$_domain_id"
if _contains "$response" "lastDomainRecordList"; then
re="\"lastDomainRecordList\".*\"id\":\"([^\"}]*)\"[^}]*\"name\":\"$fulldomain.\","
_last_domains=$(echo "$response" | _egrep_o "$re")
re2="\"id\":\"([^\"}]*)\"[^}]*\"name\":\"$fulldomain.\","
_record_id=$(echo "$_last_domains" | _egrep_o "$re2" | _head_n 1 | cut -d : -f 2 | cut -d , -f 1 | tr -d "\"")
_debug _record_id "$_record_id"
else
_err "Could not retrieve record ID"
return 1
fi
_info "Removing record"
if _clouddns_api DELETE "record/$_record_id"; then
if _contains "$response" "\"error\":"; then
_err "Could not remove record"
return 1
fi
fi
_debug "Publishing record changes"
_clouddns_api PUT "domain/$_domain_id/publish" "{\"soaTtl\":300}"
}
#################### Private functions below ##################################
# Usage: _get_root _acme-challenge.www.domain.com
# Returns:
# _sub_domain=_acme-challenge.www
# _domain=domain.com
# _domain_id=sdjkglgdfewsdfg
_get_root() {
domain=$1
# Get domain root
data="{\"search\": [{\"name\": \"clientId\", \"operator\": \"eq\", \"value\": \"$CLOUDDNS_CLIENT_ID\"}]}"
_clouddns_api "POST" "domain/search" "$data"
domain_slice="$domain"
while [ -z "$domain_root" ]; do
if _contains "$response" "\"domainName\":\"$domain_slice\.\""; then
domain_root="$domain_slice"
_debug domain_root "$domain_root"
fi
domain_slice="$(echo "$domain_slice" | cut -d . -f 2-)"
done
# Get domain id
data="{\"search\": [{\"name\": \"clientId\", \"operator\": \"eq\", \"value\": \"$CLOUDDNS_CLIENT_ID\"}, \
{\"name\": \"domainName\", \"operator\": \"eq\", \"value\": \"$domain_root.\"}]}"
_clouddns_api "POST" "domain/search" "$data"
if _contains "$response" "\"id\":\""; then
re='domainType\":\"[^\"]*\",\"id\":\"([^\"]*)\",' # Match domain id
_domain_id=$(echo "$response" | _egrep_o "$re" | _head_n 1 | cut -d : -f 3 | tr -d "\",")
if [ "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | sed "s/.$domain_root//")
_domain="$domain_root"
return 0
fi
_err 'Domain name not found on your CloudDNS account'
return 1
fi
return 1
}
# Usage: _clouddns_api GET domain/search '{"data": "value"}'
# Returns:
# response='{"message": "api response"}'
_clouddns_api() {
method=$1
endpoint="$2"
data="$3"
_debug endpoint "$endpoint"
if [ -z "$CLOUDDNS_TOKEN" ]; then
_clouddns_login
fi
_debug CLOUDDNS_TOKEN "$CLOUDDNS_TOKEN"
export _H1="Content-Type: application/json"
export _H2="Authorization: Bearer $CLOUDDNS_TOKEN"
if [ "$method" != "GET" ]; then
_debug data "$data"
response="$(_post "$data" "$CLOUDDNS_API/$endpoint" "" "$method" | tr -d '\t\r\n ')"
else
response="$(_get "$CLOUDDNS_API/$endpoint" | tr -d '\t\r\n ')"
fi
# shellcheck disable=SC2181
if [ "$?" != "0" ]; then
_err "Error $endpoint"
return 1
fi
_debug2 response "$response"
return 0
}
# Returns:
# CLOUDDNS_TOKEN=dslfje2rj23l
_clouddns_login() {
login_data="{\"email\": \"$CLOUDDNS_EMAIL\", \"password\": \"$CLOUDDNS_PASSWORD\"}"
response="$(_post "$login_data" "$CLOUDDNS_LOGIN_API" "" "POST" "Content-Type: application/json")"
if _contains "$response" "\"accessToken\":\""; then
CLOUDDNS_TOKEN=$(echo "$response" | _egrep_o "\"accessToken\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \")
export CLOUDDNS_TOKEN
else
echo 'Could not get CloudDNS access token; check your credentials'
return 1
fi
return 0
}

View File

@@ -69,7 +69,7 @@ dns_cloudns_rm() {
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
if [ -n "$record_id" ]; then
_debug zone "$zone"
_debug host "$host"
_debug record "$record"
@@ -91,7 +91,7 @@ dns_cloudns_rm() {
#################### Private functions below ##################################
_dns_cloudns_init_check() {
if [ ! -z "$CLOUDNS_INIT_CHECK_COMPLETED" ]; then
if [ -n "$CLOUDNS_INIT_CHECK_COMPLETED" ]; then
return 0
fi
@@ -164,7 +164,7 @@ _dns_cloudns_http_api_call() {
_debug CLOUDNS_SUB_AUTH_ID "$CLOUDNS_SUB_AUTH_ID"
_debug CLOUDNS_AUTH_PASSWORD "$CLOUDNS_AUTH_PASSWORD"
if [ ! -z "$CLOUDNS_SUB_AUTH_ID" ]; then
if [ -n "$CLOUDNS_SUB_AUTH_ID" ]; then
auth_user="sub-auth-id=$CLOUDNS_SUB_AUTH_ID"
else
auth_user="auth-id=$CLOUDNS_AUTH_ID"

View File

@@ -115,9 +115,9 @@ dns_conoha_rm() {
return 1
fi
record_id=$(printf "%s" "$response" | _egrep_o '{[^}]*}' \
| grep '"type":"TXT"' | grep "\"data\":\"$txtvalue\"" | _egrep_o "\"id\":\"[^\"]*\"" \
| _head_n 1 | cut -d : -f 2 | tr -d \")
record_id=$(printf "%s" "$response" | _egrep_o '{[^}]*}' |
grep '"type":"TXT"' | grep "\"data\":\"$txtvalue\"" | _egrep_o "\"id\":\"[^\"]*\"" |
_head_n 1 | cut -d : -f 2 | tr -d \")
if [ -z "$record_id" ]; then
_err "Can not get record id to remove."
return 1

141
dnsapi/dns_constellix.sh Normal file
View File

@@ -0,0 +1,141 @@
#!/usr/bin/env sh
# Author: Wout Decre <wout@canodus.be>
CONSTELLIX_Api="https://api.dns.constellix.com/v1"
#CONSTELLIX_Key="XXX"
#CONSTELLIX_Secret="XXX"
######## Public functions #####################
# Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
# Used to add txt record
dns_constellix_add() {
fulldomain=$1
txtvalue=$2
CONSTELLIX_Key="${CONSTELLIX_Key:-$(_readaccountconf_mutable CONSTELLIX_Key)}"
CONSTELLIX_Secret="${CONSTELLIX_Secret:-$(_readaccountconf_mutable CONSTELLIX_Secret)}"
if [ -z "$CONSTELLIX_Key" ] || [ -z "$CONSTELLIX_Secret" ]; then
_err "You did not specify the Contellix API key and secret yet."
return 1
fi
_saveaccountconf_mutable CONSTELLIX_Key "$CONSTELLIX_Key"
_saveaccountconf_mutable CONSTELLIX_Secret "$CONSTELLIX_Secret"
if ! _get_root "$fulldomain"; then
_err "Invalid domain"
return 1
fi
_info "Adding TXT record"
if _constellix_rest POST "domains/${_domain_id}/records" "[{\"type\":\"txt\",\"add\":true,\"set\":{\"name\":\"${_sub_domain}\",\"ttl\":120,\"roundRobin\":[{\"value\":\"${txtvalue}\"}]}}]"; then
if printf -- "%s" "$response" | grep "{\"success\":\"1 record(s) added, 0 record(s) updated, 0 record(s) deleted\"}" >/dev/null; then
_info "Added"
return 0
else
_err "Error adding TXT record"
return 1
fi
fi
}
# Usage: fulldomain txtvalue
# Used to remove the txt record after validation
dns_constellix_rm() {
fulldomain=$1
txtvalue=$2
CONSTELLIX_Key="${CONSTELLIX_Key:-$(_readaccountconf_mutable CONSTELLIX_Key)}"
CONSTELLIX_Secret="${CONSTELLIX_Secret:-$(_readaccountconf_mutable CONSTELLIX_Secret)}"
if [ -z "$CONSTELLIX_Key" ] || [ -z "$CONSTELLIX_Secret" ]; then
_err "You did not specify the Contellix API key and secret yet."
return 1
fi
if ! _get_root "$fulldomain"; then
_err "Invalid domain"
return 1
fi
_info "Removing TXT record"
if _constellix_rest POST "domains/${_domain_id}/records" "[{\"type\":\"txt\",\"delete\":true,\"filter\":{\"field\":\"name\",\"op\":\"eq\",\"value\":\"${_sub_domain}\"}}]"; then
if printf -- "%s" "$response" | grep "{\"success\":\"0 record(s) added, 0 record(s) updated, 1 record(s) deleted\"}" >/dev/null; then
_info "Removed"
return 0
else
_err "Error removing TXT record"
return 1
fi
fi
}
#################### Private functions below ##################################
_get_root() {
domain=$1
i=2
p=1
_debug "Detecting root zone"
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
if [ -z "$h" ]; then
return 1
fi
if ! _constellix_rest GET "domains/search?exact=$h"; then
return 1
fi
if _contains "$response" "\"name\":\"$h\""; then
_domain_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[0-9]+" | cut -d ':' -f 2)
if [ "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d '.' -f 1-$p)
_domain="$h"
_debug _domain_id "$_domain_id"
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
return 0
fi
return 1
fi
p=$i
i=$(_math "$i" + 1)
done
return 1
}
_constellix_rest() {
m=$1
ep="$2"
data="$3"
_debug "$ep"
rdate=$(date +"%s")"000"
hmac=$(printf "%s" "$rdate" | _hmac sha1 "$(printf "%s" "$CONSTELLIX_Secret" | _hex_dump | tr -d ' ')" | _base64)
export _H1="x-cnsdns-apiKey: $CONSTELLIX_Key"
export _H2="x-cnsdns-requestDate: $rdate"
export _H3="x-cnsdns-hmac: $hmac"
export _H4="Accept: application/json"
export _H5="Content-Type: application/json"
if [ "$m" != "GET" ]; then
_debug data "$data"
response="$(_post "$data" "$CONSTELLIX_Api/$ep" "" "$m")"
else
response="$(_get "$CONSTELLIX_Api/$ep")"
fi
if [ "$?" != "0" ]; then
_err "Error $ep"
return 1
fi
_debug response "$response"
return 0
}

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env sh
########
# Custom cyon.ch DNS API for use with [acme.sh](https://github.com/Neilpang/acme.sh)
# Custom cyon.ch DNS API for use with [acme.sh](https://github.com/acmesh-official/acme.sh)
#
# Usage: acme.sh --issue --dns dns_cyon -d www.domain.com
#
@@ -18,23 +18,23 @@
########
dns_cyon_add() {
_cyon_load_credentials \
&& _cyon_load_parameters "$@" \
&& _cyon_print_header "add" \
&& _cyon_login \
&& _cyon_change_domain_env \
&& _cyon_add_txt \
&& _cyon_logout
_cyon_load_credentials &&
_cyon_load_parameters "$@" &&
_cyon_print_header "add" &&
_cyon_login &&
_cyon_change_domain_env &&
_cyon_add_txt &&
_cyon_logout
}
dns_cyon_rm() {
_cyon_load_credentials \
&& _cyon_load_parameters "$@" \
&& _cyon_print_header "delete" \
&& _cyon_login \
&& _cyon_change_domain_env \
&& _cyon_delete_txt \
&& _cyon_logout
_cyon_load_credentials &&
_cyon_load_parameters "$@" &&
_cyon_print_header "delete" &&
_cyon_login &&
_cyon_change_domain_env &&
_cyon_delete_txt &&
_cyon_logout
}
#########################
@@ -66,7 +66,7 @@ _cyon_load_credentials() {
_debug "Save credentials to account.conf"
_saveaccountconf CY_Username "${CY_Username}"
_saveaccountconf CY_Password_B64 "$CY_Password_B64"
if [ ! -z "${CY_OTP_Secret}" ]; then
if [ -n "${CY_OTP_Secret}" ]; then
_saveaccountconf CY_OTP_Secret "$CY_OTP_Secret"
else
_clearaccountconf CY_OTP_Secret
@@ -164,7 +164,7 @@ _cyon_login() {
# todo: instead of just checking if the env variable is defined, check if we actually need to do a 2FA auth request.
# 2FA authentication with OTP?
if [ ! -z "${CY_OTP_Secret}" ]; then
if [ -n "${CY_OTP_Secret}" ]; then
_info " - Authorising with OTP code..."
if ! _exists oathtool; then

View File

@@ -115,23 +115,23 @@ _da_api() {
_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) ;;
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
}

View File

@@ -12,7 +12,7 @@
# --
#
DDNSS_DNS_API="https://ddnss.de/upd.php"
DDNSS_DNS_API="https://ip4.ddnss.de/upd.php"
######## Public functions #####################
@@ -119,7 +119,7 @@ _ddnss_rest() {
# DDNSS uses GET to update domain info
if [ "$method" = "GET" ]; then
response="$(_get "$url" | sed 's/<[a-zA-Z\/][^>]*>//g' | _tail_n 1)"
response="$(_get "$url" | sed 's/<[a-zA-Z\/][^>]*>//g' | tr -s "\n" | _tail_n 1)"
else
_err "Unsupported method"
return 1

65
dnsapi/dns_df.sh Normal file
View File

@@ -0,0 +1,65 @@
#!/usr/bin/env sh
########################################################################
# https://dyndnsfree.de hook script for acme.sh
#
# Environment variables:
#
# - $DF_user (your dyndnsfree.de username)
# - $DF_password (your dyndnsfree.de password)
#
# Author: Thilo Gass <thilo.gass@gmail.com>
# Git repo: https://github.com/ThiloGa/acme.sh
#-- dns_df_add() - Add TXT record --------------------------------------
# Usage: dns_df_add _acme-challenge.subdomain.domain.com "XyZ123..."
dyndnsfree_api="https://dynup.de/acme.php"
dns_df_add() {
fulldomain=$1
txt_value=$2
_info "Using DNS-01 dyndnsfree.de hook"
DF_user="${DF_user:-$(_readaccountconf_mutable DF_user)}"
DF_password="${DF_password:-$(_readaccountconf_mutable DF_password)}"
if [ -z "$DF_user" ] || [ -z "$DF_password" ]; then
DF_user=""
DF_password=""
_err "No auth details provided. Please set user credentials using the \$DF_user and \$DF_password environment variables."
return 1
fi
#save the api user and password to the account conf file.
_debug "Save user and password"
_saveaccountconf_mutable DF_user "$DF_user"
_saveaccountconf_mutable DF_password "$DF_password"
domain="$(printf "%s" "$fulldomain" | cut -d"." -f2-)"
get="$dyndnsfree_api?username=$DF_user&password=$DF_password&hostname=$domain&add_hostname=$fulldomain&txt=$txt_value"
if ! erg="$(_get "$get")"; then
_err "error Adding $fulldomain TXT: $txt_value"
return 1
fi
if _contains "$erg" "success"; then
_info "Success, TXT Added, OK"
else
_err "error Adding $fulldomain TXT: $txt_value erg: $erg"
return 1
fi
_debug "ok Auto $fulldomain TXT: $txt_value erg: $erg"
return 0
}
dns_df_rm() {
fulldomain=$1
txtvalue=$2
_info "TXT enrty in $fulldomain is deleted automatically"
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
}

View File

@@ -22,7 +22,7 @@ dns_dgon_add() {
txtvalue=$2
DO_API_KEY="${DO_API_KEY:-$(_readaccountconf_mutable DO_API_KEY)}"
# Check if API Key Exist
# Check if API Key Exists
if [ -z "$DO_API_KEY" ]; then
DO_API_KEY=""
_err "You did not specify DigitalOcean API key."
@@ -77,7 +77,7 @@ dns_dgon_rm() {
txtvalue=$2
DO_API_KEY="${DO_API_KEY:-$(_readaccountconf_mutable DO_API_KEY)}"
# Check if API Key Exist
# Check if API Key Exists
if [ -z "$DO_API_KEY" ]; then
DO_API_KEY=""
_err "You did not specify DigitalOcean API key."
@@ -122,12 +122,12 @@ dns_dgon_rm() {
## check for what we are looking for: "type":"A","name":"$_sub_domain"
record="$(echo "$domain_list" | _egrep_o "\"id\"\s*\:\s*\"*[0-9]+\"*[^}]*\"name\"\s*\:\s*\"$_sub_domain\"[^}]*\"data\"\s*\:\s*\"$txtvalue\"")"
if [ ! -z "$record" ]; then
if [ -n "$record" ]; then
## we found records
rec_ids="$(echo "$record" | _egrep_o "id\"\s*\:\s*\"*[0-9]+" | _egrep_o "[0-9]+")"
_debug rec_ids "$rec_ids"
if [ ! -z "$rec_ids" ]; then
if [ -n "$rec_ids" ]; then
echo "$rec_ids" | while IFS= read -r rec_id; do
## delete the record
## delete URL for removing the one we dont want
@@ -218,7 +218,7 @@ _get_base_domain() {
## we got part of a domain back - grep it out
found="$(echo "$domain_list" | _egrep_o "\"name\"\s*\:\s*\"$_domain\"")"
## check if it exists
if [ ! -z "$found" ]; then
if [ -n "$found" ]; then
## exists - exit loop returning the parts
sub_point=$(_math $i - 1)
_sub_domain=$(printf "%s" "$fulldomain" | cut -d . -f 1-"$sub_point")

View File

@@ -67,14 +67,14 @@ _dns_do_list_rrs() {
_err "getRRList origin ${_domain} failed"
return 1
fi
_rr_list="$(echo "${response}" \
| tr -d "\n\r\t" \
| sed -e 's/<item xsi:type="ns2:Map">/\n/g' \
| grep ">$(_regexcape "$fulldomain")</value>" \
| sed -e 's/<\/item>/\n/g' \
| grep '>id</key><value' \
| _egrep_o '>[0-9]{1,16}<' \
| tr -d '><')"
_rr_list="$(echo "${response}" |
tr -d "\n\r\t" |
sed -e 's/<item xsi:type="ns2:Map">/\n/g' |
grep ">$(_regexcape "$fulldomain")</value>" |
sed -e 's/<\/item>/\n/g' |
grep '>id</key><value' |
_egrep_o '>[0-9]{1,16}<' |
tr -d '><')"
[ "${_rr_list}" ]
}
@@ -120,10 +120,10 @@ _get_root() {
i=1
_dns_do_soap getDomainList
_all_domains="$(echo "${response}" \
| tr -d "\n\r\t " \
| _egrep_o 'domain</key><value[^>]+>[^<]+' \
| sed -e 's/^domain<\/key><value[^>]*>//g')"
_all_domains="$(echo "${response}" |
tr -d "\n\r\t " |
_egrep_o 'domain</key><value[^>]+>[^<]+' |
sed -e 's/^domain<\/key><value[^>]*>//g')"
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)

View File

@@ -53,7 +53,7 @@ dns_dp_rm() {
return 1
fi
if ! _rest POST "Record.List" "login_token=$DP_Id,$DP_Key&format=json&domain_id=$_domain_id&sub_domain=$_sub_domain"; then
if ! _rest POST "Record.List" "login_token=$DP_Id,$DP_Key&format=json&lang=en&domain_id=$_domain_id&sub_domain=$_sub_domain"; then
_err "Record.Lis error."
return 1
fi
@@ -70,12 +70,12 @@ dns_dp_rm() {
return 1
fi
if ! _rest POST "Record.Remove" "login_token=$DP_Id,$DP_Key&format=json&domain_id=$_domain_id&record_id=$record_id"; then
if ! _rest POST "Record.Remove" "login_token=$DP_Id,$DP_Key&format=json&lang=en&domain_id=$_domain_id&record_id=$record_id"; then
_err "Record.Remove error."
return 1
fi
_contains "$response" "Action completed successful"
_contains "$response" "successful"
}
@@ -89,11 +89,11 @@ add_record() {
_info "Adding record"
if ! _rest POST "Record.Create" "login_token=$DP_Id,$DP_Key&format=json&domain_id=$_domain_id&sub_domain=$_sub_domain&record_type=TXT&value=$txtvalue&record_line=默认"; then
if ! _rest POST "Record.Create" "login_token=$DP_Id,$DP_Key&format=json&lang=en&domain_id=$_domain_id&sub_domain=$_sub_domain&record_type=TXT&value=$txtvalue&record_line=默认"; then
return 1
fi
_contains "$response" "Action completed successful" || _contains "$response" "Domain record already exists"
_contains "$response" "successful" || _contains "$response" "Domain record already exists"
}
#################### Private functions below ##################################
@@ -113,11 +113,11 @@ _get_root() {
return 1
fi
if ! _rest POST "Domain.Info" "login_token=$DP_Id,$DP_Key&format=json&domain=$h"; then
if ! _rest POST "Domain.Info" "login_token=$DP_Id,$DP_Key&format=json&lang=en&domain=$h"; then
return 1
fi
if _contains "$response" "Action completed successful"; then
if _contains "$response" "successful"; then
_domain_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \")
_debug _domain_id "$_domain_id"
if [ "$_domain_id" ]; then

View File

@@ -91,13 +91,12 @@ dns_duckdns_rm() {
#################### Private functions below ##################################
#fulldomain=_acme-challenge.domain.duckdns.org
#returns
# _duckdns_domain=domain
# fulldomain may be 'domain.duckdns.org' (if using --domain-alias) or '_acme-challenge.domain.duckdns.org'
# either way, return 'domain'. (duckdns does not allow further subdomains and restricts domains to [a-z0-9-].)
_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)"
_duckdns_domain="$(printf "%s" "$fulldomain" | _lower_case | _egrep_o '^(_acme-challenge\.)?[a-z0-9-]*\.duckdns\.org' | sed 's/^\(_acme-challenge\.\)\?\([a-z0-9-]*\)\.duckdns\.org/\2/')"
if [ -z "$_duckdns_domain" ]; then
_err "Error extracting the domain."

View File

@@ -216,6 +216,10 @@ _dynu_authentication() {
_err "Authentication failed."
return 1
fi
if _contains "$response" "Authentication Exception"; then
_err "Authentication failed."
return 1
fi
if _contains "$response" "access_token"; then
Dynu_Token=$(printf "%s" "$response" | tr -d "{}" | cut -d , -f 1 | cut -d : -f 2 | cut -d '"' -f 2)
fi

121
dnsapi/dns_dynv6.sh Normal file
View File

@@ -0,0 +1,121 @@
#!/usr/bin/env sh
#Author StefanAbl
#Usage specify a private keyfile to use with dynv6 'export KEY="path/to/keyfile"'
#if no keyfile is specified, you will be asked if you want to create one in /home/$USER/.ssh/dynv6 and /home/$USER/.ssh/dynv6.pub
######## Public functions #####################
# Please Read this guide first: https://github.com/Neilpang/acme.sh/wiki/DNS-API-Dev-Guide
#Usage: dns_myapi_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_dynv6_add() {
fulldomain=$1
txtvalue=$2
_info "Using dynv6 api"
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
_get_keyfile
_info "using keyfile $dynv6_keyfile"
_get_domain "$fulldomain"
_your_hosts="$(ssh -i "$dynv6_keyfile" api@dynv6.com hosts)"
if ! _contains "$_your_hosts" "$_host"; then
_debug "The host is $_host and the record $_record"
_debug "Dynv6 returned $_your_hosts"
_err "The host $_host does not exist on your dynv6 account"
return 1
fi
_debug "found host on your account"
returnval="$(ssh -i "$dynv6_keyfile" api@dynv6.com hosts \""$_host"\" records set \""$_record"\" txt data \""$txtvalue"\")"
_debug "Dynv6 returend this after record was added: $returnval"
if _contains "$returnval" "created"; then
return 0
elif _contains "$returnval" "updated"; then
return 0
else
_err "Something went wrong! it does not seem like the record was added succesfully"
return 1
fi
return 1
}
#Usage: fulldomain txtvalue
#Remove the txt record after validation.
dns_dynv6_rm() {
fulldomain=$1
txtvalue=$2
_info "Using dynv6 api"
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
_get_keyfile
_info "using keyfile $dynv6_keyfile"
_get_domain "$fulldomain"
_your_hosts="$(ssh -i "$dynv6_keyfile" api@dynv6.com hosts)"
if ! _contains "$_your_hosts" "$_host"; then
_debug "The host is $_host and the record $_record"
_debug "Dynv6 returned $_your_hosts"
_err "The host $_host does not exist on your dynv6 account"
return 1
fi
_debug "found host on your account"
_info "$(ssh -i "$dynv6_keyfile" api@dynv6.com hosts "\"$_host\"" records del "\"$_record\"" txt)"
return 0
}
#################### Private functions below ##################################
#Usage: No Input required
#returns
#dynv6_keyfile the path to the new keyfile that has been generated
_generate_new_key() {
dynv6_keyfile="$(eval echo ~"$USER")/.ssh/dynv6"
_info "Path to key file used: $dynv6_keyfile"
if [ ! -f "$dynv6_keyfile" ] && [ ! -f "$dynv6_keyfile.pub" ]; then
_debug "generating key in $dynv6_keyfile and $dynv6_keyfile.pub"
ssh-keygen -f "$dynv6_keyfile" -t ssh-ed25519 -N ''
else
_err "There is already a file in $dynv6_keyfile or $dynv6_keyfile.pub"
return 1
fi
}
#Usage: _acme-challenge.www.example.dynv6.net
#returns
#_host= example.dynv6.net
#_record=_acme-challenge.www
#aborts if not a valid domain
_get_domain() {
_full_domain="$1"
_debug "getting domain for $_full_domain"
if ! _contains "$_full_domain" 'dynv6.net' && ! _contains "$_full_domain" 'dns.army' && ! _contains "$_full_domain" 'dns.navy' && ! _contains "$_full_domain" 'v6.rocks'; then
_err "The hosts does not seem to be a dynv6 host"
return 1
fi
_record="${_full_domain%.*}"
_record="${_record%.*}"
_record="${_record%.*}"
_debug "The record we are ging to use is $_record"
_host="$_full_domain"
while [ "$(echo "$_host" | grep -o '\.' | wc -l)" != "2" ]; do
_host="${_host#*.}"
done
_debug "And the host is $_host"
return 0
}
# Usage: No input required
#returns
#dynv6_keyfile path to the key that will be used
_get_keyfile() {
_debug "get keyfile method called"
dynv6_keyfile="${dynv6_keyfile:-$(_readaccountconf_mutable dynv6_keyfile)}"
_debug Your key is "$dynv6_keyfile"
if [ -z "$dynv6_keyfile" ]; then
if [ -z "$KEY" ]; then
_err "You did not specify a key to use with dynv6"
_info "Creating new dynv6 api key to add to dynv6.com"
_generate_new_key
_info "Please add this key to dynv6.com $(cat "$dynv6_keyfile.pub")"
_info "Hit Enter to contiue"
read -r _
#save the credentials to the account conf file.
else
dynv6_keyfile="$KEY"
fi
_saveaccountconf_mutable dynv6_keyfile "$dynv6_keyfile"
fi
}

View File

@@ -3,12 +3,11 @@
#######################################################
#
# easyDNS REST API for acme.sh by Neilpang based on dns_cf.sh
#
# Please note: # API is currently beta and subject to constant change
# http://sandbox.rest.easydns.net:3000/
#
# API Documentation: https://sandbox.rest.easydns.net:3001/
#
# Author: wurzelpanzer [wurzelpanzer@maximolider.net]
# Report Bugs here: https://github.com/Neilpang/acme.sh/issues/2647
# Report Bugs here: https://github.com/acmesh-official/acme.sh/issues/2647
#
#################### Public functions #################
@@ -25,7 +24,7 @@ dns_easydns_add() {
EASYDNS_Key="${EASYDNS_Key:-$(_readaccountconf_mutable EASYDNS_Key)}"
if [ -z "$EASYDNS_Token" ] || [ -z "$EASYDNS_Key" ]; then
_err "You didn't specify an easydns.net token or api key. Please sign up at http://docs.sandbox.rest.easydns.net/beta_signup.php"
_err "You didn't specify an easydns.net token or api key. Signup at https://cp.easydns.com/manage/security/api/signup.php"
return 1
else
_saveaccountconf_mutable EASYDNS_Token "$EASYDNS_Token"

View File

@@ -7,7 +7,7 @@
#
#Author: David Kerr
#Report Bugs here: https://github.com/dkerr64/acme.sh
#or here... https://github.com/Neilpang/acme.sh/issues/2305
#or here... https://github.com/acmesh-official/acme.sh/issues/2305
#
######## Public functions #####################
@@ -303,10 +303,10 @@ _freedns_domain_id() {
return 1
fi
domain_id="$(echo "$htmlpage" | tr -d " \t\r\n\v\f" | sed 's/<tr>/@<tr>/g' | tr '@' '\n' \
| grep "<td>$search_domain</td>\|<td>$search_domain(.*)</td>" \
| sed -n 's/.*\(edit\.php?edit_domain_id=[0-9a-zA-Z]*\).*/\1/p' \
| cut -d = -f 2)"
domain_id="$(echo "$htmlpage" | tr -d " \t\r\n\v\f" | sed 's/<tr>/@<tr>/g' | tr '@' '\n' |
grep "<td>$search_domain</td>\|<td>$search_domain(.*)</td>" |
sed -n 's/.*\(edit\.php?edit_domain_id=[0-9a-zA-Z]*\).*/\1/p' |
cut -d = -f 2)"
# The above beauty extracts domain ID from the html page...
# strip out all blank space and new lines. Then insert newlines
# before each table row <tr>
@@ -349,11 +349,11 @@ _freedns_data_id() {
return 1
fi
data_id="$(echo "$htmlpage" | tr -d " \t\r\n\v\f" | sed 's/<tr>/@<tr>/g' | tr '@' '\n' \
| grep "<td[a-zA-Z=#]*>$record_type</td>" \
| grep "<ahref.*>$search_domain</a>" \
| sed -n 's/.*\(edit\.php?data_id=[0-9a-zA-Z]*\).*/\1/p' \
| cut -d = -f 2)"
data_id="$(echo "$htmlpage" | tr -d " \t\r\n\v\f" | sed 's/<tr>/@<tr>/g' | tr '@' '\n' |
grep "<td[a-zA-Z=#]*>$record_type</td>" |
grep "<ahref.*>$search_domain</a>" |
sed -n 's/.*\(edit\.php?data_id=[0-9a-zA-Z]*\).*/\1/p' |
cut -d = -f 2)"
# The above beauty extracts data ID from the html page...
# strip out all blank space and new lines. Then insert newlines
# before each table row <tr>

View File

@@ -69,9 +69,9 @@ dns_gandi_livedns_rm() {
_gandi_livedns_rest PUT \
"domains/$_domain/records/$_sub_domain/TXT" \
"{\"rrset_ttl\": 300, \"rrset_values\": $_new_rrset_values}" \
&& _contains "$response" '{"message": "DNS Record Created"}' \
&& _info "Removing record $(__green "success")"
"{\"rrset_ttl\": 300, \"rrset_values\": $_new_rrset_values}" &&
_contains "$response" '{"message": "DNS Record Created"}' &&
_info "Removing record $(__green "success")"
}
#################### Private functions below ##################################
@@ -125,9 +125,9 @@ _dns_gandi_append_record() {
fi
_debug new_rrset_values "$_rrset_values"
_gandi_livedns_rest PUT "domains/$_domain/records/$sub_domain/TXT" \
"{\"rrset_ttl\": 300, \"rrset_values\": $_rrset_values}" \
&& _contains "$response" '{"message": "DNS Record Created"}' \
&& _info "Adding record $(__green "success")"
"{\"rrset_ttl\": 300, \"rrset_values\": $_rrset_values}" &&
_contains "$response" '{"message": "DNS Record Created"}' &&
_info "Adding record $(__green "success")"
}
_dns_gandi_existing_rrset_values() {
@@ -145,8 +145,8 @@ _dns_gandi_existing_rrset_values() {
return 1
fi
_debug "Already has TXT record."
_rrset_values=$(echo "$response" | _egrep_o 'rrset_values.*\[.*\]' \
| _egrep_o '\[".*\"]')
_rrset_values=$(echo "$response" | _egrep_o 'rrset_values.*\[.*\]' |
_egrep_o '\[".*\"]')
return 0
}

View File

@@ -78,8 +78,8 @@ _dns_gcloud_execute_tr() {
for i in $(seq 1 120); do
if gcloud dns record-sets changes list \
--zone="$managedZone" \
--filter='status != done' \
| grep -q '^.*'; then
--filter='status != done' |
grep -q '^.*'; then
_info "_dns_gcloud_execute_tr: waiting for transaction to be comitted ($i/120)..."
sleep 5
else
@@ -137,11 +137,11 @@ _dns_gcloud_find_zone() {
# List domains and find the zone with the deepest sub-domain (in case of some levels of delegation)
if ! match=$(gcloud dns managed-zones list \
--format="value(name, dnsName)" \
--filter="$filter" \
| while read -r dnsName name; do
--filter="$filter" |
while read -r dnsName name; do
printf "%s\t%s\t%s\n" "$(echo "$name" | awk -F"." '{print NF-1}')" "$dnsName" "$name"
done \
| sort -n -r | _head_n 1 | cut -f2,3 | grep '^.*'); then
done |
sort -n -r | _head_n 1 | cut -f2,3 | grep '^.*'); then
_err "_dns_gcloud_find_zone: Can't find a matching managed zone! Perhaps wrong project or gcloud credentials?"
return 1
fi

View File

@@ -91,7 +91,7 @@ dns_gd_rm() {
fi
if ! _contains "$response" "$txtvalue"; then
_info "The record is not existing, skip"
_info "The record does not exist, skip"
return 0
fi

View File

@@ -157,9 +157,18 @@ _successful_update() {
}
_findentry() {
#args $1: fulldomain, $2: txtvalue
#returns id of dns entry, if it exists
_myget "action=dns_primary_changeDNSsetup&user_domain=$_domain"
_id=$(echo "$_result" | _egrep_o "<td>$1</td>\s*<td>$2</td>[^?]*[^&]*&id=[^&]*" | sed 's/^.*=//')
_debug3 "_result: $_result"
_tmp_result=$(echo "$_result" | tr -d '\n\r' | _egrep_o "<td>$1</td>\s*<td>$2</td>[^?]*[^&]*&id=[^&]*")
_debug _tmp_result "$_tmp_result"
if [ -z "${_tmp_result:-}" ]; then
_debug "The variable is _tmp_result is not supposed to be empty, there may be something wrong with the script"
fi
_id=$(echo "$_tmp_result" | sed 's/^.*=//')
if [ -n "$_id" ]; then
_debug "Entry found with _id=$_id"
return 0

View File

@@ -24,7 +24,7 @@ dns_he_add() {
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."
_err "No auth details provided. Please set user credentials using the \$HE_Username and \$HE_Password environment variables."
return 1
fi
_saveaccountconf_mutable HE_Username "$HE_Username"
@@ -101,8 +101,8 @@ dns_he_rm() {
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>' \
_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

252
dnsapi/dns_hetzner.sh Normal file
View File

@@ -0,0 +1,252 @@
#!/usr/bin/env sh
#
#HETZNER_Token="sdfsdfsdfljlbjkljlkjsdfoiwje"
#
HETZNER_Api="https://dns.hetzner.com/api/v1"
######## Public functions #####################
# Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
# Used to add txt record
# Ref: https://dns.hetzner.com/api-docs/
dns_hetzner_add() {
full_domain=$1
txt_value=$2
HETZNER_Token="${HETZNER_Token:-$(_readaccountconf_mutable HETZNER_Token)}"
if [ -z "$HETZNER_Token" ]; then
HETZNER_Token=""
_err "You didn't specify a Hetzner api token."
_err "You can get yours from here https://dns.hetzner.com/settings/api-token."
return 1
fi
#save the api key and email to the account conf file.
_saveaccountconf_mutable HETZNER_Token "$HETZNER_Token"
_debug "First detect the root zone"
if ! _get_root "$full_domain"; then
_err "Invalid domain"
return 1
fi
_debug _domain_id "$_domain_id"
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
_debug "Getting TXT records"
if ! _find_record "$_sub_domain" "$txt_value"; then
return 1
fi
if [ -z "$_record_id" ]; then
_info "Adding record"
if _hetzner_rest POST "records" "{\"zone_id\":\"${HETZNER_Zone_ID}\",\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"value\":\"$txt_value\",\"ttl\":120}"; then
if _contains "$response" "$txt_value"; then
_info "Record added, OK"
_sleep 2
return 0
fi
fi
_err "Add txt record error${_response_error}"
return 1
else
_info "Found record id: $_record_id."
_info "Record found, do nothing."
return 0
# we could modify a record, if the names for txt records for *.example.com and example.com would be not the same
#if _hetzner_rest PUT "records/${_record_id}" "{\"zone_id\":\"${HETZNER_Zone_ID}\",\"type\":\"TXT\",\"name\":\"$full_domain\",\"value\":\"$txt_value\",\"ttl\":120}"; then
# if _contains "$response" "$txt_value"; then
# _info "Modified, OK"
# return 0
# fi
#fi
#_err "Add txt record error (modify)."
#return 1
fi
}
# Usage: full_domain txt_value
# Used to remove the txt record after validation
dns_hetzner_rm() {
full_domain=$1
txt_value=$2
HETZNER_Token="${HETZNER_Token:-$(_readaccountconf_mutable HETZNER_Token)}"
_debug "First detect the root zone"
if ! _get_root "$full_domain"; then
_err "Invalid domain"
return 1
fi
_debug _domain_id "$_domain_id"
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
_debug "Getting TXT records"
if ! _find_record "$_sub_domain" "$txt_value"; then
return 1
fi
if [ -z "$_record_id" ]; then
_info "Remove not needed. Record not found."
else
if ! _hetzner_rest DELETE "records/$_record_id"; then
_err "Delete record error${_response_error}"
return 1
fi
_sleep 2
_info "Record deleted"
fi
}
#################### Private functions below ##################################
#returns
# _record_id=a8d58f22d6931bf830eaa0ec6464bf81 if found; or 1 if error
_find_record() {
unset _record_id
_record_name=$1
_record_value=$2
if [ -z "$_record_value" ]; then
_record_value='[^"]*'
fi
_debug "Getting all records"
_hetzner_rest GET "records?zone_id=${_domain_id}"
if _response_has_error; then
_err "Error${_response_error}"
return 1
else
_record_id=$(
echo "$response" |
grep -o "{[^\{\}]*\"name\":\"$_record_name\"[^\}]*}" |
grep "\"value\":\"$_record_value\"" |
while read -r record; do
# test for type and
if [ -n "$(echo "$record" | _egrep_o '"type":"TXT"')" ]; then
echo "$record" | _egrep_o '"id":"[^"]*"' | cut -d : -f 2 | tr -d \"
break
fi
done
)
fi
}
#_acme-challenge.www.domain.com
#returns
# _sub_domain=_acme-challenge.www
# _domain=domain.com
# _domain_id=sdjkglgdfewsdfg
_get_root() {
domain=$1
i=1
p=1
domain_without_acme=$(echo "$domain" | cut -d . -f 2-)
domain_param_name=$(echo "HETZNER_Zone_ID_for_${domain_without_acme}" | sed 's/[\.\-]/_/g')
_debug "Reading zone_id for '$domain_without_acme' from config..."
HETZNER_Zone_ID=$(_readdomainconf "$domain_param_name")
if [ "$HETZNER_Zone_ID" ]; then
_debug "Found, using: $HETZNER_Zone_ID"
if ! _hetzner_rest GET "zones/${HETZNER_Zone_ID}"; then
_debug "Zone with id '$HETZNER_Zone_ID' does not exist."
_cleardomainconf "$domain_param_name"
unset HETZNER_Zone_ID
else
if _contains "$response" "\"id\":\"$HETZNER_Zone_ID\""; then
_domain=$(printf "%s\n" "$response" | _egrep_o '"name":"[^"]*"' | cut -d : -f 2 | tr -d \" | head -n 1)
if [ "$_domain" ]; then
_cut_length=$((${#domain} - ${#_domain} - 1))
_sub_domain=$(printf "%s" "$domain" | cut -c "1-$_cut_length")
_domain_id="$HETZNER_Zone_ID"
return 0
else
return 1
fi
else
return 1
fi
fi
fi
_debug "Trying to get zone id by domain name for '$domain_without_acme'."
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
if [ -z "$h" ]; then
#not valid
return 1
fi
_debug h "$h"
_hetzner_rest GET "zones?name=$h"
if _contains "$response" "\"name\":\"$h\"" || _contains "$response" '"total_entries":1'; then
_domain_id=$(echo "$response" | _egrep_o "\[.\"id\":\"[^\"]*\"" | _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
HETZNER_Zone_ID=$_domain_id
_savedomainconf "$domain_param_name" "$HETZNER_Zone_ID"
return 0
fi
return 1
fi
p=$i
i=$(_math "$i" + 1)
done
return 1
}
#returns
# _response_error
_response_has_error() {
unset _response_error
err_part="$(echo "$response" | _egrep_o '"error":{[^}]*}')"
if [ -n "$err_part" ]; then
err_code=$(echo "$err_part" | _egrep_o '"code":[0-9]+' | cut -d : -f 2)
err_message=$(echo "$err_part" | _egrep_o '"message":"[^"]+"' | cut -d : -f 2 | tr -d \")
if [ -n "$err_code" ] && [ -n "$err_message" ]; then
_response_error=" - message: ${err_message}, code: ${err_code}"
return 0
fi
fi
return 1
}
#returns
# response
_hetzner_rest() {
m=$1
ep="$2"
data="$3"
_debug "$ep"
key_trimmed=$(echo "$HETZNER_Token" | tr -d \")
export _H1="Content-TType: application/json"
export _H2="Auth-API-Token: $key_trimmed"
if [ "$m" != "GET" ]; then
_debug data "$data"
response="$(_post "$data" "$HETZNER_Api/$ep" "" "$m")"
else
response="$(_get "$HETZNER_Api/$ep")"
fi
if [ "$?" != "0" ] || _response_has_error; then
_debug "Error$_response_error"
return 1
fi
_debug2 response "$response"
return 0
}

View File

@@ -42,7 +42,7 @@ dns_hexonet_add() {
_debug _domain "$_domain"
_debug "Getting txt records"
_hexonet_rest "&command=QueryDNSZoneRRList&dnszone=${h}.&RRTYPE=TXT"
_hexonet_rest "command=QueryDNSZoneRRList&dnszone=${h}.&RRTYPE=TXT"
if ! _contains "$response" "CODE=200"; then
_err "Error"
@@ -88,7 +88,7 @@ dns_hexonet_rm() {
_debug _domain "$_domain"
_debug "Getting txt records"
_hexonet_rest "&command=QueryDNSZoneRRList&dnszone=${h}.&RRTYPE=TXT&RR=${txtvalue}"
_hexonet_rest "command=QueryDNSZoneRRList&dnszone=${h}.&RRTYPE=TXT&RR=${_sub_domain}%20IN%20TXT%20\"${txtvalue}\""
if ! _contains "$response" "CODE=200"; then
_err "Error"
@@ -100,7 +100,7 @@ dns_hexonet_rm() {
if [ "$count" = "0" ]; then
_info "Don't need to remove."
else
if ! _hexonet_rest "&command=UpdateDNSZone&dnszone=${_domain}.&delrr0='${_sub_domain}%20IN%20TXT%20\"${txtvalue}\""; then
if ! _hexonet_rest "command=UpdateDNSZone&dnszone=${_domain}.&delrr0=${_sub_domain}%20IN%20TXT%20\"${txtvalue}\""; then
_err "Delete record error."
return 1
fi
@@ -126,7 +126,7 @@ _get_root() {
return 1
fi
if ! _hexonet_rest "&command=QueryDNSZoneRRList&dnszone=${h}."; then
if ! _hexonet_rest "command=QueryDNSZoneRRList&dnszone=${h}."; then
return 1
fi

View File

@@ -34,6 +34,10 @@ dns_inwx_add() {
_saveaccountconf_mutable INWX_Password "$INWX_Password"
_saveaccountconf_mutable INWX_Shared_Secret "$INWX_Shared_Secret"
if ! _inwx_login; then
return 1
fi
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"
@@ -55,6 +59,7 @@ dns_inwx_rm() {
INWX_User="${INWX_User:-$(_readaccountconf_mutable INWX_User)}"
INWX_Password="${INWX_Password:-$(_readaccountconf_mutable INWX_Password)}"
INWX_Shared_Secret="${INWX_Shared_Secret:-$(_readaccountconf_mutable INWX_Shared_Secret)}"
if [ -z "$INWX_User" ] || [ -z "$INWX_Password" ]; then
INWX_User=""
INWX_Password=""
@@ -63,9 +68,9 @@ dns_inwx_rm() {
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"
if ! _inwx_login; then
return 1
fi
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
@@ -126,8 +131,42 @@ dns_inwx_rm() {
#################### Private functions below ##################################
_inwx_check_cookie() {
INWX_Cookie="${INWX_Cookie:-$(_readaccountconf_mutable INWX_Cookie)}"
if [ -z "$INWX_Cookie" ]; then
_debug "No cached cookie found"
return 1
fi
_H1="$INWX_Cookie"
export _H1
xml_content=$(printf '<?xml version="1.0" encoding="UTF-8"?>
<methodCall>
<methodName>account.info</methodName>
</methodCall>')
response="$(_post "$xml_content" "$INWX_Api" "" "POST")"
if _contains "$response" "<member><name>code</name><value><int>1000</int></value></member>"; then
_debug "Cached cookie still valid"
return 0
fi
_debug "Cached cookie no longer valid"
_H1=""
export _H1
INWX_Cookie=""
_saveaccountconf_mutable INWX_Cookie "$INWX_Cookie"
return 1
}
_inwx_login() {
if _inwx_check_cookie; then
_debug "Already logged in"
return 0
fi
xml_content=$(printf '<?xml version="1.0" encoding="UTF-8"?>
<methodCall>
<methodName>account.login</methodName>
@@ -151,17 +190,25 @@ _inwx_login() {
</value>
</param>
</params>
</methodCall>' $INWX_User $INWX_Password)
</methodCall>' "$INWX_User" "$INWX_Password")
response="$(_post "$xml_content" "$INWX_Api" "" "POST")"
_H1=$(printf "Cookie: %s" "$(grep "domrobot=" "$HTTP_HEADER" | grep "^Set-Cookie:" | _tail_n 1 | _egrep_o 'domrobot=[^;]*;' | tr -d ';')")
INWX_Cookie=$(printf "Cookie: %s" "$(grep "domrobot=" "$HTTP_HEADER" | grep "^Set-Cookie:" | _tail_n 1 | _egrep_o 'domrobot=[^;]*;' | tr -d ';')")
_H1=$INWX_Cookie
export _H1
export INWX_Cookie
_saveaccountconf_mutable INWX_Cookie "$INWX_Cookie"
if ! _contains "$response" "<member><name>code</name><value><int>1000</int></value></member>"; then
_err "INWX API: Authentication error (username/password correct?)"
return 1
fi
#https://github.com/inwx/php-client/blob/master/INWX/Domrobot.php#L71
if _contains "$response" "<member><name>code</name><value><int>1000</int></value></member>" \
&& _contains "$response" "<member><name>tfa</name><value><string>GOOGLE-AUTH</string></value></member>"; then
if _contains "$response" "<member><name>tfa</name><value><string>GOOGLE-AUTH</string></value></member>"; then
if [ -z "$INWX_Shared_Secret" ]; then
_err "Mobile TAN detected."
_err "INWX API: Mobile TAN detected."
_err "Please define a shared secret."
return 1
fi
@@ -194,6 +241,11 @@ _inwx_login() {
</methodCall>' "$tan")
response="$(_post "$xml_content" "$INWX_Api" "" "POST")"
if ! _contains "$response" "<member><name>code</name><value><int>1000</int></value></member>"; then
_err "INWX API: Mobile TAN not correct."
return 1
fi
fi
}
@@ -206,11 +258,23 @@ _get_root() {
i=2
p=1
_inwx_login
xml_content='<?xml version="1.0" encoding="UTF-8"?>
<methodCall>
<methodName>nameserver.list</methodName>
<params>
<param>
<value>
<struct>
<member>
<name>pagelimit</name>
<value>
<int>9999</int>
</value>
</member>
</struct>
</value>
</param>
</params>
</methodCall>'
response="$(_post "$xml_content" "$INWX_Api" "" "POST")"

View File

@@ -95,29 +95,29 @@ _ISPC_getZoneInfo() {
server_id=$(echo "${curResult}" | _egrep_o "server_id.*" | cut -d ':' -f 2 | cut -d '"' -f 2)
_debug "Server ID: '${server_id}'"
case "${server_id}" in
'' | *[!0-9]*)
_err "Server ID is not numeric."
return 1
;;
*) _info "Retrieved Server ID" ;;
'' | *[!0-9]*)
_err "Server ID is not numeric."
return 1
;;
*) _info "Retrieved Server ID" ;;
esac
zone=$(echo "${curResult}" | _egrep_o "\"id.*" | cut -d ':' -f 2 | cut -d '"' -f 2)
_debug "Zone: '${zone}'"
case "${zone}" in
'' | *[!0-9]*)
_err "Zone ID is not numeric."
return 1
;;
*) _info "Retrieved Zone ID" ;;
'' | *[!0-9]*)
_err "Zone ID is not numeric."
return 1
;;
*) _info "Retrieved Zone ID" ;;
esac
client_id=$(echo "${curResult}" | _egrep_o "sys_userid.*" | cut -d ':' -f 2 | cut -d '"' -f 2)
_debug "Client ID: '${client_id}'"
case "${client_id}" in
'' | *[!0-9]*)
_err "Client ID is not numeric."
return 1
;;
*) _info "Retrieved Client ID." ;;
'' | *[!0-9]*)
_err "Client ID is not numeric."
return 1
;;
*) _info "Retrieved Client ID." ;;
esac
zoneFound=""
zoneEnd=""
@@ -135,11 +135,11 @@ _ISPC_addTxt() {
record_id=$(echo "${curResult}" | _egrep_o "\"response.*" | cut -d ':' -f 2 | cut -d '"' -f 2)
_debug "Record ID: '${record_id}'"
case "${record_id}" in
'' | *[!0-9]*)
_err "Couldn't add ACME Challenge TXT record to zone."
return 1
;;
*) _info "Added ACME Challenge TXT record to zone." ;;
'' | *[!0-9]*)
_err "Couldn't add ACME Challenge TXT record to zone."
return 1
;;
*) _info "Added ACME Challenge TXT record to zone." ;;
esac
}
@@ -153,24 +153,24 @@ _ISPC_rmTxt() {
record_id=$(echo "${curResult}" | _egrep_o "\"id.*" | cut -d ':' -f 2 | cut -d '"' -f 2)
_debug "Record ID: '${record_id}'"
case "${record_id}" in
'' | *[!0-9]*)
_err "Record ID is not numeric."
'' | *[!0-9]*)
_err "Record ID is not numeric."
return 1
;;
*)
unset IFS
_info "Retrieved Record ID."
curData="{\"session_id\":\"${sessionID}\",\"primary_id\":\"${record_id}\",\"update_serial\":true}"
curResult="$(_post "${curData}" "${ISPC_Api}?dns_txt_delete")"
_debug "Calling _ISPC_rmTxt: '${curData}' '${ISPC_Api}?dns_txt_delete'"
_debug "Result of _ISPC_rmTxt: '$curResult'"
if _contains "${curResult}" '"code":"ok"'; then
_info "Removed ACME Challenge TXT record from zone."
else
_err "Couldn't remove ACME Challenge TXT record from zone."
return 1
;;
*)
unset IFS
_info "Retrieved Record ID."
curData="{\"session_id\":\"${sessionID}\",\"primary_id\":\"${record_id}\",\"update_serial\":true}"
curResult="$(_post "${curData}" "${ISPC_Api}?dns_txt_delete")"
_debug "Calling _ISPC_rmTxt: '${curData}' '${ISPC_Api}?dns_txt_delete'"
_debug "Result of _ISPC_rmTxt: '$curResult'"
if _contains "${curResult}" '"code":"ok"'; then
_info "Removed ACME Challenge TXT record from zone."
else
_err "Couldn't remove ACME Challenge TXT record from zone."
return 1
fi
;;
fi
;;
esac
fi
}

129
dnsapi/dns_joker.sh Normal file
View File

@@ -0,0 +1,129 @@
#!/usr/bin/env sh
# Joker.com API for acme.sh
#
# This script adds the necessary TXT record to a domain in Joker.com.
#
# You must activate Dynamic DNS in Joker.com DNS configuration first.
# Username and password below refer to Dynamic DNS authentication,
# not your Joker.com login credentials.
# See: https://joker.com/faq/content/11/427/en/what-is-dynamic-dns-dyndns.html
#
# NOTE: This script does not support wildcard certificates, because
# Joker.com API does not support adding two TXT records with the same
# subdomain. Adding the second record will overwrite the first one.
# See: https://joker.com/faq/content/6/496/en/let_s-encrypt-support.html
# "... this request will replace all TXT records for the specified
# label by the provided content"
#
# Author: aattww (https://github.com/aattww/)
#
# Report bugs to https://github.com/acmesh-official/acme.sh/issues/2840
#
# JOKER_USERNAME="xxxx"
# JOKER_PASSWORD="xxxx"
JOKER_API="https://svc.joker.com/nic/replace"
######## Public functions #####################
#Usage: dns_joker_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_joker_add() {
fulldomain=$1
txtvalue=$2
JOKER_USERNAME="${JOKER_USERNAME:-$(_readaccountconf_mutable JOKER_USERNAME)}"
JOKER_PASSWORD="${JOKER_PASSWORD:-$(_readaccountconf_mutable JOKER_PASSWORD)}"
if [ -z "$JOKER_USERNAME" ] || [ -z "$JOKER_PASSWORD" ]; then
_err "No Joker.com username and password specified."
return 1
fi
_saveaccountconf_mutable JOKER_USERNAME "$JOKER_USERNAME"
_saveaccountconf_mutable JOKER_PASSWORD "$JOKER_PASSWORD"
if ! _get_root "$fulldomain"; then
_err "Invalid domain"
return 1
fi
_info "Adding TXT record"
if _joker_rest "username=$JOKER_USERNAME&password=$JOKER_PASSWORD&zone=$_domain&label=$_sub_domain&type=TXT&value=$txtvalue"; then
if _startswith "$response" "OK"; then
_info "Added, OK"
return 0
fi
fi
_err "Error adding TXT record."
return 1
}
#fulldomain txtvalue
dns_joker_rm() {
fulldomain=$1
txtvalue=$2
JOKER_USERNAME="${JOKER_USERNAME:-$(_readaccountconf_mutable JOKER_USERNAME)}"
JOKER_PASSWORD="${JOKER_PASSWORD:-$(_readaccountconf_mutable JOKER_PASSWORD)}"
if ! _get_root "$fulldomain"; then
_err "Invalid domain"
return 1
fi
_info "Removing TXT record"
# TXT record is removed by setting its value to empty.
if _joker_rest "username=$JOKER_USERNAME&password=$JOKER_PASSWORD&zone=$_domain&label=$_sub_domain&type=TXT&value="; then
if _startswith "$response" "OK"; then
_info "Removed, OK"
return 0
fi
fi
_err "Error removing TXT record."
return 1
}
#################### Private functions below ##################################
#_acme-challenge.www.domain.com
#returns
# _sub_domain=_acme-challenge.www
# _domain=domain.com
_get_root() {
fulldomain=$1
i=1
while true; do
h=$(printf "%s" "$fulldomain" | cut -d . -f $i-100)
_debug h "$h"
if [ -z "$h" ]; then
return 1
fi
# Try to remove a test record. With correct root domain, username and password this will return "OK: ..." regardless
# of record in question existing or not.
if _joker_rest "username=$JOKER_USERNAME&password=$JOKER_PASSWORD&zone=$h&label=jokerTXTUpdateTest&type=TXT&value="; then
if _startswith "$response" "OK"; then
_sub_domain="$(echo "$fulldomain" | sed "s/\\.$h\$//")"
_domain=$h
return 0
fi
fi
i=$(_math "$i" + 1)
done
_debug "Root domain not found"
return 1
}
_joker_rest() {
data="$1"
_debug data "$data"
if ! response="$(_post "$data" "$JOKER_API" "" "POST")"; then
_err "Error POSTing"
return 1
fi
_debug response "$response"
return 0
}

150
dnsapi/dns_kappernet.sh Normal file
View File

@@ -0,0 +1,150 @@
#!/usr/bin/env sh
# kapper.net domain api
# for further questions please contact: support@kapper.net
# please report issues here: https://github.com/acmesh-official/acme.sh/issues/2977
#KAPPERNETDNS_Key="yourKAPPERNETapikey"
#KAPPERNETDNS_Secret="yourKAPPERNETapisecret"
KAPPERNETDNS_Api="https://dnspanel.kapper.net/API/1.2?APIKey=$KAPPERNETDNS_Key&APISecret=$KAPPERNETDNS_Secret"
###############################################################################
# called with
# fullhostname: something.example.com
# txtvalue: someacmegenerated string
dns_kappernet_add() {
fullhostname=$1
txtvalue=$2
KAPPERNETDNS_Key="${KAPPERNETDNS_Key:-$(_readaccountconf_mutable KAPPERNETDNS_Key)}"
KAPPERNETDNS_Secret="${KAPPERNETDNS_Secret:-$(_readaccountconf_mutable KAPPERNETDNS_Secret)}"
if [ -z "$KAPPERNETDNS_Key" ] || [ -z "$KAPPERNETDNS_Secret" ]; then
KAPPERNETDNS_Key=""
KAPPERNETDNS_Secret=""
_err "Please specify your kapper.net api key and secret."
_err "If you have not received yours - send your mail to"
_err "support@kapper.net to get your key and secret."
return 1
fi
#store the api key and email to the account conf file.
_saveaccountconf_mutable KAPPERNETDNS_Key "$KAPPERNETDNS_Key"
_saveaccountconf_mutable KAPPERNETDNS_Secret "$KAPPERNETDNS_Secret"
_debug "Checking Domain ..."
if ! _get_root "$fullhostname"; then
_err "invalid domain"
return 1
fi
_debug _sub_domain "SUBDOMAIN: $_sub_domain"
_debug _domain "DOMAIN: $_domain"
_info "Trying to add TXT DNS Record"
data="%7B%22name%22%3A%22$fullhostname%22%2C%22type%22%3A%22TXT%22%2C%22content%22%3A%22$txtvalue%22%2C%22ttl%22%3A%223600%22%2C%22prio%22%3A%22%22%7D"
if _kappernet_api GET "action=new&subject=$_domain&data=$data"; then
if _contains "$response" "{\"OK\":true"; then
_info "Waiting 120 seconds for DNS to spread the new record"
_sleep 120
return 0
else
_err "Error creating a TXT DNS Record: $fullhostname TXT $txtvalue"
_err "Error Message: $response"
return 1
fi
fi
_err "Failed creating TXT Record"
}
###############################################################################
# called with
# fullhostname: something.example.com
dns_kappernet_rm() {
fullhostname=$1
txtvalue=$2
KAPPERNETDNS_Key="${KAPPERNETDNS_Key:-$(_readaccountconf_mutable KAPPERNETDNS_Key)}"
KAPPERNETDNS_Secret="${KAPPERNETDNS_Secret:-$(_readaccountconf_mutable KAPPERNETDNS_Secret)}"
if [ -z "$KAPPERNETDNS_Key" ] || [ -z "$KAPPERNETDNS_Secret" ]; then
KAPPERNETDNS_Key=""
KAPPERNETDNS_Secret=""
_err "Please specify your kapper.net api key and secret."
_err "If you have not received yours - send your mail to"
_err "support@kapper.net to get your key and secret."
return 1
fi
#store the api key and email to the account conf file.
_saveaccountconf_mutable KAPPERNETDNS_Key "$KAPPERNETDNS_Key"
_saveaccountconf_mutable KAPPERNETDNS_Secret "$KAPPERNETDNS_Secret"
_info "Trying to remove the TXT Record: $fullhostname containing $txtvalue"
data="%7B%22name%22%3A%22$fullhostname%22%2C%22type%22%3A%22TXT%22%2C%22content%22%3A%22$txtvalue%22%2C%22ttl%22%3A%223600%22%2C%22prio%22%3A%22%22%7D"
if _kappernet_api GET "action=del&subject=$fullhostname&data=$data"; then
if _contains "$response" "{\"OK\":true"; then
return 0
else
_err "Error deleting DNS Record: $fullhostname containing $txtvalue"
_err "Problem: $response"
return 1
fi
fi
_err "Problem deleting TXT DNS record"
}
#################### Private functions below ##################################
# called with hostname
# e.g._acme-challenge.www.domain.com returns
# _sub_domain=_acme-challenge.www
# _domain=domain.com
_get_root() {
domain=$1
i=2
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
if [ -z "$h" ]; then
#not valid
return 1
fi
if ! _kappernet_api GET "action=list&subject=$h"; then
return 1
fi
if _contains "$response" '"OK":false'; then
_debug "$h not found"
else
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_domain="$h"
return 0
fi
p="$i"
i=$(_math "$i" + 1)
done
return 1
}
################################################################################
# calls the kapper.net DNS Panel API
# with
# method
# param
_kappernet_api() {
method=$1
param="$2"
_debug param "PARAMETER=$param"
url="$KAPPERNETDNS_Api&$param"
_debug url "URL=$url"
if [ "$method" = "GET" ]; then
response="$(_get "$url")"
else
_err "Unsupported method"
return 1
fi
_debug2 response "$response"
return 0
}

168
dnsapi/dns_kas.sh Executable file
View File

@@ -0,0 +1,168 @@
#!/usr/bin/env sh
########################################################################
# All-inkl Kasserver hook script for acme.sh
#
# Environment variables:
#
# - $KAS_Login (Kasserver API login name)
# - $KAS_Authtype (Kasserver API auth type. Default: sha1)
# - $KAS_Authdata (Kasserver API auth data.)
#
# Author: Martin Kammerlander, Phlegx Systems OG <martin.kammerlander@phlegx.com>
# Updated by: Marc-Oliver Lange <git@die-lang.es>
# Credits: Inspired by dns_he.sh. Thanks a lot man!
# Git repo: https://github.com/phlegx/acme.sh
# TODO: Better Error handling
########################################################################
KAS_Api="https://kasapi.kasserver.com/dokumentation/formular.php"
######## Public functions #####################
dns_kas_add() {
_fulldomain=$1
_txtvalue=$2
_info "Using DNS-01 All-inkl/Kasserver hook"
_info "Adding $_fulldomain DNS TXT entry on All-inkl/Kasserver"
_info "Check and Save Props"
_check_and_save
_info "Checking Zone and Record_Name"
_get_zone_and_record_name "$_fulldomain"
_info "Getting Record ID"
_get_record_id
_info "Creating TXT DNS record"
params="?kas_login=$KAS_Login"
params="$params&kas_auth_type=$KAS_Authtype"
params="$params&kas_auth_data=$KAS_Authdata"
params="$params&var1=record_name"
params="$params&wert1=$_record_name"
params="$params&var2=record_type"
params="$params&wert2=TXT"
params="$params&var3=record_data"
params="$params&wert3=$_txtvalue"
params="$params&var4=record_aux"
params="$params&wert4=0"
params="$params&kas_action=add_dns_settings"
params="$params&var5=zone_host"
params="$params&wert5=$_zone"
_debug2 "Wait for 10 seconds by default before calling KAS API."
_sleep 10
response="$(_get "$KAS_Api$params")"
_debug2 "response" "$response"
if ! _contains "$response" "TRUE"; then
_err "An unkown error occurred, please check manually."
return 1
fi
return 0
}
dns_kas_rm() {
_fulldomain=$1
_txtvalue=$2
_info "Using DNS-01 All-inkl/Kasserver hook"
_info "Cleaning up after All-inkl/Kasserver hook"
_info "Removing $_fulldomain DNS TXT entry on All-inkl/Kasserver"
_info "Check and Save Props"
_check_and_save
_info "Checking Zone and Record_Name"
_get_zone_and_record_name "$_fulldomain"
_info "Getting Record ID"
_get_record_id
# If there is a record_id, delete the entry
if [ -n "$_record_id" ]; then
params="?kas_login=$KAS_Login"
params="$params&kas_auth_type=$KAS_Authtype"
params="$params&kas_auth_data=$KAS_Authdata"
params="$params&kas_action=delete_dns_settings"
for i in $_record_id; do
params2="$params&var1=record_id"
params2="$params2&wert1=$i"
_debug2 "Wait for 10 seconds by default before calling KAS API."
_sleep 10
response="$(_get "$KAS_Api$params2")"
_debug2 "response" "$response"
if ! _contains "$response" "TRUE"; then
_err "Either the txt record is not found or another error occurred, please check manually."
return 1
fi
done
else # Cannot delete or unkown error
_err "No record_id found that can be deleted. Please check manually."
return 1
fi
return 0
}
########################## PRIVATE FUNCTIONS ###########################
# Checks for the ENV variables and saves them
_check_and_save() {
KAS_Login="${KAS_Login:-$(_readaccountconf_mutable KAS_Login)}"
KAS_Authtype="${KAS_Authtype:-$(_readaccountconf_mutable KAS_Authtype)}"
KAS_Authdata="${KAS_Authdata:-$(_readaccountconf_mutable KAS_Authdata)}"
if [ -z "$KAS_Login" ] || [ -z "$KAS_Authtype" ] || [ -z "$KAS_Authdata" ]; then
KAS_Login=
KAS_Authtype=
KAS_Authdata=
_err "No auth details provided. Please set user credentials using the \$KAS_Login, \$KAS_Authtype, and \$KAS_Authdata environment variables."
return 1
fi
_saveaccountconf_mutable KAS_Login "$KAS_Login"
_saveaccountconf_mutable KAS_Authtype "$KAS_Authtype"
_saveaccountconf_mutable KAS_Authdata "$KAS_Authdata"
return 0
}
# Gets back the base domain/zone and record name.
# See: https://github.com/Neilpang/acme.sh/wiki/DNS-API-Dev-Guide
_get_zone_and_record_name() {
params="?kas_login=$KAS_Login"
params="?kas_login=$KAS_Login"
params="$params&kas_auth_type=$KAS_Authtype"
params="$params&kas_auth_data=$KAS_Authdata"
params="$params&kas_action=get_domains"
_debug2 "Wait for 10 seconds by default before calling KAS API."
_sleep 10
response="$(_get "$KAS_Api$params")"
_debug2 "response" "$response"
_zonen="$(echo "$response" | tr -d "\n\r" | tr -d " " | tr '[]' '<>' | sed "s/=>Array/\n=> Array/g" | tr ' ' '\n' | grep "domain_name" | tr '<' '\n' | grep "domain_name" | sed "s/domain_name>=>//g")"
_domain="$1"
_temp_domain="$(echo "$1" | sed 's/\.$//')"
_rootzone="$_domain"
for i in $_zonen; do
l1=${#_rootzone}
l2=${#i}
if _endswith "$_domain" "$i" && [ "$l1" -ge "$l2" ]; then
_rootzone="$i"
fi
done
_zone="${_rootzone}."
_temp_record_name="$(echo "$_temp_domain" | sed "s/$_rootzone//g")"
_record_name="$(echo "$_temp_record_name" | sed 's/\.$//')"
_debug2 "Zone:" "$_zone"
_debug2 "Domain:" "$_domain"
_debug2 "Record_Name:" "$_record_name"
return 0
}
# Retrieve the DNS record ID
_get_record_id() {
params="?kas_login=$KAS_Login"
params="$params&kas_auth_type=$KAS_Authtype"
params="$params&kas_auth_data=$KAS_Authdata"
params="$params&kas_action=get_dns_settings"
params="$params&var1=zone_host"
params="$params&wert1=$_zone"
_debug2 "Wait for 10 seconds by default before calling KAS API."
_sleep 10
response="$(_get "$KAS_Api$params")"
_debug2 "response" "$response"
_record_id="$(echo "$response" | tr -d "\n\r" | tr -d " " | tr '[]' '<>' | sed "s/=>Array/\n=> Array/g" | tr ' ' '\n' | grep "=>$_record_name<" | grep '>TXT<' | tr '<' '\n' | grep record_id | sed "s/record_id>=>//g")"
_debug2 _record_id "$_record_id"
return 0
}

View File

@@ -37,7 +37,7 @@ dns_kinghost_add() {
_debug "Getting txt records"
_kinghost_rest GET "dns" "name=$fulldomain&content=$txtvalue"
#This API call returns "status":"ok" if dns record does not exists
#This API call returns "status":"ok" if dns record does not exist
#We are creating a new txt record here, so we expect the "ok" status
if ! echo "$response" | grep '"status":"ok"' >/dev/null; then
_err "Error"

View File

@@ -5,7 +5,7 @@
# https://github.com/AnalogJ/lexicon
lexicon_cmd="lexicon"
wiki="https://github.com/Neilpang/acme.sh/wiki/How-to-use-lexicon-dns-api"
wiki="https://github.com/acmesh-official/acme.sh/wiki/How-to-use-lexicon-dns-api"
_lexicon_init() {
if ! _exists "$lexicon_cmd"; then
@@ -92,7 +92,7 @@ dns_lexicon_add() {
_savedomainconf LEXICON_OPTS "$LEXICON_OPTS"
# shellcheck disable=SC2086
$lexicon_cmd "$PROVIDER" $LEXICON_OPTS create "${domain}" TXT --name="_acme-challenge.${domain}." --content="${txtvalue}"
$lexicon_cmd "$PROVIDER" $LEXICON_OPTS create "${domain}" TXT --name="_acme-challenge.${domain}." --content="${txtvalue}" --output QUIET
}
@@ -108,6 +108,6 @@ dns_lexicon_rm() {
domain=$(printf "%s" "$fulldomain" | cut -d . -f 2-999)
# shellcheck disable=SC2086
$lexicon_cmd "$PROVIDER" $LEXICON_OPTS delete "${domain}" TXT --name="_acme-challenge.${domain}." --content="${txtvalue}"
$lexicon_cmd "$PROVIDER" $LEXICON_OPTS delete "${domain}" TXT --name="_acme-challenge.${domain}." --content="${txtvalue}" --output QUIET
}

View File

@@ -36,7 +36,7 @@ dns_linode_v4_add() {
}"
if _rest POST "/$_domain_id/records" "$_payload" && [ -n "$response" ]; then
_resource_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":\s*[0-9]+" | cut -d : -f 2 | tr -d " " | _head_n 1)
_resource_id=$(printf "%s\n" "$response" | _egrep_o "\"id\": *[0-9]+" | cut -d : -f 2 | tr -d " " | _head_n 1)
_debug _resource_id "$_resource_id"
if [ -z "$_resource_id" ]; then
@@ -74,9 +74,9 @@ dns_linode_v4_rm() {
if _rest GET "/$_domain_id/records" && [ -n "$response" ]; then
response="$(echo "$response" | tr -d "\n" | tr '{' "|" | sed 's/|/&{/g' | tr "|" "\n")"
resource="$(echo "$response" | _egrep_o "{.*\"name\":\s*\"$_sub_domain\".*}")"
resource="$(echo "$response" | _egrep_o "\{.*\"name\": *\"$_sub_domain\".*}")"
if [ "$resource" ]; then
_resource_id=$(printf "%s\n" "$resource" | _egrep_o "\"id\":\s*[0-9]+" | _head_n 1 | cut -d : -f 2 | tr -d \ )
_resource_id=$(printf "%s\n" "$resource" | _egrep_o "\"id\": *[0-9]+" | _head_n 1 | cut -d : -f 2 | tr -d \ )
if [ "$_resource_id" ]; then
_debug _resource_id "$_resource_id"
@@ -139,9 +139,9 @@ _get_root() {
return 1
fi
hostedzone="$(echo "$response" | _egrep_o "{.*\"domain\":\s*\"$h\".*}")"
hostedzone="$(echo "$response" | _egrep_o "\{.*\"domain\": *\"$h\".*}")"
if [ "$hostedzone" ]; then
_domain_id=$(printf "%s\n" "$hostedzone" | _egrep_o "\"id\":\s*[0-9]+" | _head_n 1 | cut -d : -f 2 | tr -d \ )
_domain_id=$(printf "%s\n" "$hostedzone" | _egrep_o "\"id\": *[0-9]+" | _head_n 1 | cut -d : -f 2 | tr -d \ )
if [ "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_domain=$h

View File

@@ -217,7 +217,7 @@ _loopia_add_record() {
</member>
<member>
<name>ttl</name>
<value><int>60</int></value>
<value><int>300</int></value>
</member>
<member>
<name>rdata</name>

View File

@@ -114,7 +114,7 @@ _get_root() {
fi
if _contains "$response" "\"name\":\"$h\""; then
_domain_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[^,]*" | head -n 1 | cut -d : -f 2 | tr -d '}')
_domain_id=$(printf "%s\n" "$response" | sed 's/^{//; s/}$//; s/{.*}//' | sed -r 's/^.*"id":([0-9]+).*$/\1/')
if [ "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_domain="$h"

View File

@@ -10,7 +10,7 @@
# used to communicate with the MailinaBox Custom DNS API
# Report Bugs here:
# https://github.com/billgertz/MIAB_dns_api (for dns_miab.sh)
# https://github.com/Neilpang/acme.sh (for acme.sh)
# https://github.com/acmesh-official/acme.sh (for acme.sh)
#
######## Public functions #####################

View File

@@ -7,11 +7,11 @@
#returns 0 means success, otherwise error.
#
#Author: Neilpang
#Report Bugs here: https://github.com/Neilpang/acme.sh
#Report Bugs here: https://github.com/acmesh-official/acme.sh
#
######## Public functions #####################
# Please Read this guide first: https://github.com/Neilpang/acme.sh/wiki/DNS-API-Dev-Guide
# Please Read this guide first: https://github.com/acmesh-official/acme.sh/wiki/DNS-API-Dev-Guide
#Usage: dns_myapi_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_myapi_add() {

162
dnsapi/dns_netlify.sh Normal file
View File

@@ -0,0 +1,162 @@
#!/usr/bin/env sh
#NETLIFY_ACCESS_TOKEN="xxxx"
NETLIFY_HOST="api.netlify.com/api/v1/"
NETLIFY_URL="https://$NETLIFY_HOST"
######## Public functions #####################
#Usage: dns_myapi_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_netlify_add() {
fulldomain=$1
txtvalue=$2
NETLIFY_ACCESS_TOKEN="${NETLIFY_ACCESS_TOKEN:-$(_readaccountconf_mutable NETLIFY_ACCESS_TOKEN)}"
if [ -z "$NETLIFY_ACCESS_TOKEN" ]; then
NETLIFY_ACCESS_TOKEN=""
_err "Please specify your Netlify Access Token and try again."
return 1
fi
_info "Using Netlify"
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
_saveaccountconf_mutable NETLIFY_ACCESS_TOKEN "$NETLIFY_ACCESS_TOKEN"
if ! _get_root "$fulldomain" "$accesstoken"; then
_err "invalid domain"
return 1
fi
_debug _domain_id "$_domain_id"
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
dnsRecordURI="dns_zones/$_domain_id/dns_records"
body="{\"type\":\"TXT\", \"hostname\":\"$_sub_domain\", \"value\":\"$txtvalue\", \"ttl\":\"10\"}"
_netlify_rest POST "$dnsRecordURI" "$body" "$NETLIFY_ACCESS_TOKEN"
_code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")"
if [ "$_code" = "200" ] || [ "$_code" = '201' ]; then
_info "validation value added"
return 0
else
_err "error adding validation value ($_code)"
return 1
fi
_err "Not fully implemented!"
return 1
}
#Usage: dns_myapi_rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
#Remove the txt record after validation.
dns_netlify_rm() {
_info "Using Netlify"
txtdomain="$1"
txt="$2"
_debug txtdomain "$txtdomain"
_debug txt "$txt"
_saveaccountconf_mutable NETLIFY_ACCESS_TOKEN "$NETLIFY_ACCESS_TOKEN"
if ! _get_root "$txtdomain" "$accesstoken"; then
_err "invalid domain"
return 1
fi
_debug _domain_id "$_domain_id"
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
dnsRecordURI="dns_zones/$_domain_id/dns_records"
_netlify_rest GET "$dnsRecordURI" "" "$NETLIFY_ACCESS_TOKEN"
_record_id=$(echo "$response" | _egrep_o "\"type\":\"TXT\",[^\}]*\"value\":\"$txt\"" | head -n 1 | _egrep_o "\"id\":\"[^\"\}]*\"" | cut -d : -f 2 | tr -d \")
_debug _record_id "$_record_id"
if [ "$_record_id" ]; then
_netlify_rest DELETE "$dnsRecordURI/$_record_id" "" "$NETLIFY_ACCESS_TOKEN"
_code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")"
if [ "$_code" = "200" ] || [ "$_code" = '204' ]; then
_info "validation value removed"
return 0
else
_err "error removing validation value ($_code)"
return 1
fi
return 0
fi
return 1
}
#################### Private functions below ##################################
_get_root() {
domain=$1
accesstoken=$2
i=1
p=1
_netlify_rest GET "dns_zones" "" "$accesstoken"
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 "\"[^\"]*\",\"name\":\"$h" | cut -d , -f 1 | tr -d \")
if [ "$_domain_id" ]; then
if [ "$i" = 1 ]; then
#create the record at the domain apex (@) if only the domain name was provided as --domain-alias
_sub_domain="@"
else
_sub_domain=$(echo "$domain" | cut -d . -f 1-$p)
fi
_domain=$h
return 0
fi
return 1
fi
p=$i
i=$(_math "$i" + 1)
done
return 1
}
_netlify_rest() {
m=$1
ep="$2"
data="$3"
_debug "$ep"
token_trimmed=$(echo "$NETLIFY_ACCESS_TOKEN" | tr -d '"')
export _H1="Content-Type: application/json"
export _H2="Authorization: Bearer $token_trimmed"
: >"$HTTP_HEADER"
if [ "$m" != "GET" ]; then
_debug data "$data"
response="$(_post "$data" "$NETLIFY_URL$ep" "" "$m")"
else
response="$(_get "$NETLIFY_URL$ep")"
fi
if [ "$?" != "0" ]; then
_err "error $ep"
return 1
fi
_debug2 response "$response"
return 0
}

View File

@@ -166,7 +166,7 @@ _get_root() {
if _contains "$_all_domains" "^$h$"; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_domain=$h
_service=$(printf "%s" "$response" | grep "idn-name=\"$_domain\"" | sed -r "s/.*service=\"(.*)\".*$/\1/")
_service=$(printf "%s" "$response" | grep -m 1 "idn-name=\"$_domain\"" | sed -r "s/.*service=\"(.*)\".*$/\1/")
return 0
fi
p="$i"

168
dnsapi/dns_njalla.sh Normal file
View File

@@ -0,0 +1,168 @@
#!/usr/bin/env sh
#
#NJALLA_Token="sdfsdfsdfljlbjkljlkjsdfoiwje"
NJALLA_Api="https://njal.la/api/1/"
######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_njalla_add() {
fulldomain=$1
txtvalue=$2
NJALLA_Token="${NJALLA_Token:-$(_readaccountconf_mutable NJALLA_Token)}"
if [ "$NJALLA_Token" ]; then
_saveaccountconf_mutable NJALLA_Token "$NJALLA_Token"
else
NJALLA_Token=""
_err "You didn't specify a Njalla api token yet."
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"
# 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 _njalla_rest "{\"method\":\"add-record\",\"params\":{\"domain\":\"$_domain\",\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"content\":\"$txtvalue\",\"ttl\":120}}"; then
if _contains "$response" "$txtvalue"; then
_info "Added, OK"
return 0
else
_err "Add txt record error."
return 1
fi
fi
_err "Add txt record error."
return 1
}
#fulldomain txtvalue
dns_njalla_rm() {
fulldomain=$1
txtvalue=$2
NJALLA_Token="${NJALLA_Token:-$(_readaccountconf_mutable NJALLA_Token)}"
if [ "$NJALLA_Token" ]; then
_saveaccountconf_mutable NJALLA_Token "$NJALLA_Token"
else
NJALLA_Token=""
_err "You didn't specify a Njalla api token yet."
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 records for domain"
if ! _njalla_rest "{\"method\":\"list-records\",\"params\":{\"domain\":\"${_domain}\"}}"; then
return 1
fi
if ! echo "$response" | tr -d " " | grep "\"id\":" >/dev/null; then
_err "Error: $response"
return 1
fi
records=$(echo "$response" | _egrep_o "\"records\":\s?\[(.*)\]\}" | _egrep_o "\[.*\]" | _egrep_o "\{[^\{\}]*\"id\":[^\{\}]*\}")
count=$(echo "$records" | wc -l)
_debug count "$count"
if [ "$count" = "0" ]; then
_info "Don't need to remove."
else
echo "$records" | while read -r record; do
record_name=$(echo "$record" | _egrep_o "\"name\":\s?\"[^\"]*\"" | cut -d : -f 2 | tr -d " " | tr -d \")
record_content=$(echo "$record" | _egrep_o "\"content\":\s?\"[^\"]*\"" | cut -d : -f 2 | tr -d " " | tr -d \")
record_id=$(echo "$record" | _egrep_o "\"id\":\s?[0-9]+" | cut -d : -f 2 | tr -d " " | tr -d \")
if [ "$_sub_domain" = "$record_name" ]; then
if [ "$txtvalue" = "$record_content" ]; then
_debug "record_id" "$record_id"
if ! _njalla_rest "{\"method\":\"remove-record\",\"params\":{\"domain\":\"${_domain}\",\"id\":${record_id}}}"; then
_err "Delete record error."
return 1
fi
echo "$response" | tr -d " " | grep "\"result\"" >/dev/null
fi
fi
done
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=1
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 ! _njalla_rest "{\"method\":\"get-domain\",\"params\":{\"domain\":\"${h}\"}}"; then
return 1
fi
if _contains "$response" "\"$h\""; then
_domain_returned=$(echo "$response" | _egrep_o "\{\"name\": *\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \" | tr -d " ")
if [ "$_domain_returned" ]; 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
}
_njalla_rest() {
data="$1"
token_trimmed=$(echo "$NJALLA_Token" | tr -d '"')
export _H1="Content-Type: application/json"
export _H2="Accept: application/json"
export _H3="Authorization: Njalla $token_trimmed"
_debug data "$data"
response="$(_post "$data" "$NJALLA_Api" "" "POST")"
if [ "$?" != "0" ]; then
_err "error $data"
return 1
fi
_debug2 response "$response"
return 0
}

88
dnsapi/dns_nm.sh Normal file
View File

@@ -0,0 +1,88 @@
#!/usr/bin/env sh
########################################################################
# https://namemaster.de hook script for acme.sh
#
# Environment variables:
#
# - $NM_user (your namemaster.de API username)
# - $NM_sha256 (your namemaster.de API password_as_sha256hash)
#
# Author: Thilo Gass <thilo.gass@gmail.com>
# Git repo: https://github.com/ThiloGa/acme.sh
#-- dns_nm_add() - Add TXT record --------------------------------------
# Usage: dns_nm_add _acme-challenge.subdomain.domain.com "XyZ123..."
namemaster_api="https://namemaster.de/api/api.php"
dns_nm_add() {
fulldomain=$1
txt_value=$2
_info "Using DNS-01 namemaster hook"
NM_user="${NM_user:-$(_readaccountconf_mutable NM_user)}"
NM_sha256="${NM_sha256:-$(_readaccountconf_mutable NM_sha256)}"
if [ -z "$NM_user" ] || [ -z "$NM_sha256" ]; then
NM_user=""
NM_sha256=""
_err "No auth details provided. Please set user credentials using the \$NM_user and \$NM_sha256 environment variables."
return 1
fi
#save the api user and sha256 password to the account conf file.
_debug "Save user and hash"
_saveaccountconf_mutable NM_user "$NM_user"
_saveaccountconf_mutable NM_sha256 "$NM_sha256"
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain" "$fulldomain"
return 1
fi
_info "die Zone lautet:" "$zone"
get="$namemaster_api?User=$NM_user&Password=$NM_sha256&Antwort=csv&Typ=ACME&zone=$zone&hostname=$fulldomain&TXT=$txt_value&Action=Auto&Lifetime=3600"
if ! erg="$(_get "$get")"; then
_err "error Adding $fulldomain TXT: $txt_value"
return 1
fi
if _contains "$erg" "Success"; then
_info "Success, TXT Added, OK"
else
_err "error Adding $fulldomain TXT: $txt_value erg: $erg"
return 1
fi
_debug "ok Auto $fulldomain TXT: $txt_value erg: $erg"
return 0
}
dns_nm_rm() {
fulldomain=$1
txtvalue=$2
_info "TXT enrty in $fulldomain is deleted automatically"
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
}
_get_root() {
domain=$1
get="$namemaster_api?User=$NM_user&Password=$NM_sha256&Typ=acme&hostname=$domain&Action=getzone&antwort=csv"
if ! zone="$(_get "$get")"; then
_err "error getting Zone"
return 1
else
if _contains "$zone" "hostname not found"; then
return 1
fi
fi
}

View File

@@ -5,7 +5,10 @@
# Author: github: @diseq
# Created: 2019-02-17
# Fixed by: @der-berni
# Modified: 2019-05-31
# Modified: 2020-04-07
#
# Use ONECOM_KeepCnameProxy to keep the CNAME DNS record
# export ONECOM_KeepCnameProxy="1"
#
# export ONECOM_User="username"
# export ONECOM_Password="password"
@@ -30,32 +33,45 @@ dns_one_add() {
return 1
fi
mysubdomain=$_sub_domain
mydomain=$_domain
_debug mysubdomain "$mysubdomain"
_debug mydomain "$mydomain"
subdomain="${_sub_domain}"
maindomain=${_domain}
# get entries
response="$(_get "https://www.one.com/admin/api/domains/$mydomain/dns/custom_records")"
_debug response "$response"
useProxy=0
if [ "${_sub_domain}" = "_acme-challenge" ]; then
subdomain="proxy${_sub_domain}"
useProxy=1
fi
# Update the IP address for domain entry
postdata="{\"type\":\"dns_custom_records\",\"attributes\":{\"priority\":0,\"ttl\":600,\"type\":\"TXT\",\"prefix\":\"$mysubdomain\",\"content\":\"$txtvalue\"}}"
_debug postdata "$postdata"
response="$(_post "$postdata" "https://www.one.com/admin/api/domains/$mydomain/dns/custom_records" "" "POST" "application/json")"
response="$(echo "$response" | _normalizeJson)"
_debug response "$response"
_debug subdomain "$subdomain"
_debug maindomain "$maindomain"
id=$(echo "$response" | sed -n "s/{\"result\":{\"data\":{\"type\":\"dns_custom_records\",\"id\":\"\([^\"]*\)\",\"attributes\":{\"prefix\":\"$mysubdomain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"priority\":0,\"ttl\":600}}},\"metadata\":null}/\1/p")
if [ $useProxy -eq 1 ]; then
#Check if the CNAME exists
_dns_one_getrecord "CNAME" "$_sub_domain" "$subdomain.$maindomain"
if [ -z "$id" ]; then
_info "$(__red "Add CNAME Proxy record: '$(__green "\"$_sub_domain\" => \"$subdomain.$maindomain\"")'")"
_dns_one_addrecord "CNAME" "$_sub_domain" "$subdomain.$maindomain"
if [ -z "$id" ]; then
_err "Add txt record error."
return 1
else
_info "Added, OK ($id)"
_info "Not valid yet, let's wait 1 hour to take effect."
_sleep 3600
fi
fi
#Check if the TXT exists
_dns_one_getrecord "TXT" "$subdomain" "$txtvalue"
if [ -n "$id" ]; then
_info "$(__green "Txt record with the same value found. Skip adding.")"
return 0
fi
_dns_one_addrecord "TXT" "$subdomain" "$txtvalue"
if [ -z "$id" ]; then
_err "Add TXT record error."
return 1
else
_info "$(__green "Added, OK ($id)")"
return 0
fi
}
dns_one_rm() {
@@ -73,36 +89,45 @@ dns_one_rm() {
return 1
fi
mysubdomain=$_sub_domain
mydomain=$_domain
_debug mysubdomain "$mysubdomain"
_debug mydomain "$mydomain"
subdomain="${_sub_domain}"
maindomain=${_domain}
# get entries
response="$(_get "https://www.one.com/admin/api/domains/$mydomain/dns/custom_records")"
response="$(echo "$response" | _normalizeJson)"
_debug response "$response"
useProxy=0
if [ "${_sub_domain}" = "_acme-challenge" ]; then
subdomain="proxy${_sub_domain}"
useProxy=1
fi
id=$(printf -- "%s" "$response" | sed -n "s/.*{\"type\":\"dns_custom_records\",\"id\":\"\([^\"]*\)\",\"attributes\":{\"prefix\":\"$mysubdomain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"priority\":0,\"ttl\":600}.*/\1/p")
_debug subdomain "$subdomain"
_debug maindomain "$maindomain"
if [ $useProxy -eq 1 ]; then
if [ "$ONECOM_KeepCnameProxy" = "1" ]; then
_info "$(__red "Keeping CNAME Proxy record: '$(__green "\"$_sub_domain\" => \"$subdomain.$maindomain\"")'")"
else
#Check if the CNAME exists
_dns_one_getrecord "CNAME" "$_sub_domain" "$subdomain.$maindomain"
if [ -n "$id" ]; then
_info "$(__red "Removing CNAME Proxy record: '$(__green "\"$_sub_domain\" => \"$subdomain.$maindomain\"")'")"
_dns_one_delrecord "$id"
fi
fi
fi
#Check if the TXT exists
_dns_one_getrecord "TXT" "$subdomain" "$txtvalue"
if [ -z "$id" ]; then
_err "Txt record not found."
return 1
fi
# delete entry
response="$(_post "$postdata" "https://www.one.com/admin/api/domains/$mydomain/dns/custom_records/$id" "" "DELETE" "application/json")"
response="$(echo "$response" | _normalizeJson)"
_debug response "$response"
if [ "$response" = '{"result":null,"metadata":null}' ]; then
_info "Removed, OK"
if _dns_one_delrecord "$id"; then
_info "$(__green Removed, OK)"
return 0
else
_err "Removing txt record error."
return 1
fi
}
#_acme-challenge.www.domain.com
@@ -138,6 +163,8 @@ _get_root() {
_dns_one_login() {
# get credentials
ONECOM_KeepCnameProxy="${ONECOM_KeepCnameProxy:-$(_readaccountconf_mutable ONECOM_KeepCnameProxy)}"
ONECOM_KeepCnameProxy="${ONECOM_KeepCnameProxy:-0}"
ONECOM_User="${ONECOM_User:-$(_readaccountconf_mutable ONECOM_User)}"
ONECOM_Password="${ONECOM_Password:-$(_readaccountconf_mutable ONECOM_Password)}"
if [ -z "$ONECOM_User" ] || [ -z "$ONECOM_Password" ]; then
@@ -149,6 +176,7 @@ _dns_one_login() {
fi
#save the api key and email to the account conf file.
_saveaccountconf_mutable ONECOM_KeepCnameProxy "$ONECOM_KeepCnameProxy"
_saveaccountconf_mutable ONECOM_User "$ONECOM_User"
_saveaccountconf_mutable ONECOM_Password "$ONECOM_Password"
@@ -177,3 +205,75 @@ _dns_one_login() {
return 0
}
_dns_one_getrecord() {
type="$1"
name="$2"
value="$3"
if [ -z "$type" ]; then
type="TXT"
fi
if [ -z "$name" ]; then
_err "Record name is empty."
return 1
fi
response="$(_get "https://www.one.com/admin/api/domains/$maindomain/dns/custom_records")"
response="$(echo "$response" | _normalizeJson)"
_debug response "$response"
if [ -z "${value}" ]; then
id=$(printf -- "%s" "$response" | sed -n "s/.*{\"type\":\"dns_custom_records\",\"id\":\"\([^\"]*\)\",\"attributes\":{\"prefix\":\"${name}\",\"type\":\"${type}\",\"content\":\"[^\"]*\",\"priority\":0,\"ttl\":600}.*/\1/p")
response=$(printf -- "%s" "$response" | sed -n "s/.*{\"type\":\"dns_custom_records\",\"id\":\"[^\"]*\",\"attributes\":{\"prefix\":\"${name}\",\"type\":\"${type}\",\"content\":\"\([^\"]*\)\",\"priority\":0,\"ttl\":600}.*/\1/p")
else
id=$(printf -- "%s" "$response" | sed -n "s/.*{\"type\":\"dns_custom_records\",\"id\":\"\([^\"]*\)\",\"attributes\":{\"prefix\":\"${name}\",\"type\":\"${type}\",\"content\":\"${value}\",\"priority\":0,\"ttl\":600}.*/\1/p")
fi
if [ -z "$id" ]; then
return 1
fi
return 0
}
_dns_one_addrecord() {
type="$1"
name="$2"
value="$3"
if [ -z "$type" ]; then
type="TXT"
fi
if [ -z "$name" ]; then
_err "Record name is empty."
return 1
fi
postdata="{\"type\":\"dns_custom_records\",\"attributes\":{\"priority\":0,\"ttl\":600,\"type\":\"${type}\",\"prefix\":\"${name}\",\"content\":\"${value}\"}}"
_debug postdata "$postdata"
response="$(_post "$postdata" "https://www.one.com/admin/api/domains/$maindomain/dns/custom_records" "" "POST" "application/json")"
response="$(echo "$response" | _normalizeJson)"
_debug response "$response"
id=$(echo "$response" | sed -n "s/{\"result\":{\"data\":{\"type\":\"dns_custom_records\",\"id\":\"\([^\"]*\)\",\"attributes\":{\"prefix\":\"$subdomain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"priority\":0,\"ttl\":600}}},\"metadata\":null}/\1/p")
if [ -z "$id" ]; then
return 1
else
return 0
fi
}
_dns_one_delrecord() {
id="$1"
if [ -z "$id" ]; then
return 1
fi
response="$(_post "" "https://www.one.com/admin/api/domains/$maindomain/dns/custom_records/$id" "" "DELETE" "application/json")"
response="$(echo "$response" | _normalizeJson)"
_debug response "$response"
if [ "$response" = '{"result":null,"metadata":null}' ]; then
return 0
else
return 1
fi
}

View File

@@ -3,7 +3,7 @@
# This is the OpenProvider API wrapper for acme.sh
#
# Author: Sylvia van Os
# Report Bugs here: https://github.com/Neilpang/acme.sh/issues/2104
# Report Bugs here: https://github.com/acmesh-official/acme.sh/issues/2104
#
# export OPENPROVIDER_USER="username"
# export OPENPROVIDER_PASSWORDHASH="hashed_password"
@@ -59,16 +59,17 @@ dns_openprovider_add() {
break
fi
items="$(echo "$items" | sed "s|${item}||")"
tmpitem="$(echo "$item" | sed 's/\*/\\*/g')"
items="$(echo "$items" | sed "s|${tmpitem}||")"
results_retrieved="$(_math "$results_retrieved" + 1)"
new_item="$(echo "$item" | sed -n 's/.*<item>.*\(<name>\(.*\)\.'"$_domain_name"'\.'"$_domain_extension"'<\/name>.*\(<type>.*<\/type>\).*\(<value>.*<\/value>\).*\(<prio>.*<\/prio>\).*\(<ttl>.*<\/ttl>\)\).*<\/item>.*/<item><name>\2<\/name>\3\4\5\6<\/item>/p')"
if [ -z "$new_item" ]; then
# Base record
# Domain apex
new_item="$(echo "$item" | sed -n 's/.*<item>.*\(<name>\(.*\)'"$_domain_name"'\.'"$_domain_extension"'<\/name>.*\(<type>.*<\/type>\).*\(<value>.*<\/value>\).*\(<prio>.*<\/prio>\).*\(<ttl>.*<\/ttl>\)\).*<\/item>.*/<item><name>\2<\/name>\3\4\5\6<\/item>/p')"
fi
if [ -z "$(echo "$new_item" | _egrep_o ".*<type>(A|AAAA|CNAME|MX|SPF|SRV|TXT|TLSA|SSHFP|CAA)<\/type>.*")" ]; then
if [ -z "$(echo "$new_item" | _egrep_o ".*<type>(A|AAAA|CNAME|MX|SPF|SRV|TXT|TLSA|SSHFP|CAA|NS)<\/type>.*")" ]; then
_debug "not an allowed record type, skipping" "$new_item"
continue
fi
@@ -86,7 +87,7 @@ dns_openprovider_add() {
_debug "Creating acme record"
acme_record="$(echo "$fulldomain" | sed -e "s/.$_domain_name.$_domain_extension$//")"
_openprovider_request "$(printf '<modifyZoneDnsRequest><domain><name>%s</name><extension>%s</extension></domain><type>master</type><records><array>%s<item><name>%s</name><type>TXT</type><value>%s</value><ttl>86400</ttl></item></array></records></modifyZoneDnsRequest>' "$_domain_name" "$_domain_extension" "$existing_items" "$acme_record" "$txtvalue")"
_openprovider_request "$(printf '<modifyZoneDnsRequest><domain><name>%s</name><extension>%s</extension></domain><type>master</type><records><array>%s<item><name>%s</name><type>TXT</type><value>%s</value><ttl>600</ttl></item></array></records></modifyZoneDnsRequest>' "$_domain_name" "$_domain_extension" "$existing_items" "$acme_record" "$txtvalue")"
return 0
}
@@ -136,7 +137,8 @@ dns_openprovider_rm() {
break
fi
items="$(echo "$items" | sed "s|${item}||")"
tmpitem="$(echo "$item" | sed 's/\*/\\*/g')"
items="$(echo "$items" | sed "s|${tmpitem}||")"
results_retrieved="$(_math "$results_retrieved" + 1)"
if ! echo "$item" | grep -v "$fulldomain"; then
@@ -147,11 +149,11 @@ dns_openprovider_rm() {
new_item="$(echo "$item" | sed -n 's/.*<item>.*\(<name>\(.*\)\.'"$_domain_name"'\.'"$_domain_extension"'<\/name>.*\(<type>.*<\/type>\).*\(<value>.*<\/value>\).*\(<prio>.*<\/prio>\).*\(<ttl>.*<\/ttl>\)\).*<\/item>.*/<item><name>\2<\/name>\3\4\5\6<\/item>/p')"
if [ -z "$new_item" ]; then
# Base record
# domain apex
new_item="$(echo "$item" | sed -n 's/.*<item>.*\(<name>\(.*\)'"$_domain_name"'\.'"$_domain_extension"'<\/name>.*\(<type>.*<\/type>\).*\(<value>.*<\/value>\).*\(<prio>.*<\/prio>\).*\(<ttl>.*<\/ttl>\)\).*<\/item>.*/<item><name>\2<\/name>\3\4\5\6<\/item>/p')"
fi
if [ -z "$(echo "$new_item" | _egrep_o ".*<type>(A|AAAA|CNAME|MX|SPF|SRV|TXT|TLSA|SSHFP|CAA)<\/type>.*")" ]; then
if [ -z "$(echo "$new_item" | _egrep_o ".*<type>(A|AAAA|CNAME|MX|SPF|SRV|TXT|TLSA|SSHFP|CAA|NS)<\/type>.*")" ]; then
_debug "not an allowed record type, skipping" "$new_item"
continue
fi
@@ -205,7 +207,8 @@ _get_root() {
break
fi
items="$(echo "$items" | sed "s|${item}||")"
tmpitem="$(echo "$item" | sed 's/\*/\\*/g')"
items="$(echo "$items" | sed "s|${tmpitem}||")"
results_retrieved="$(_math "$results_retrieved" + 1)"

348
dnsapi/dns_openstack.sh Executable file
View File

@@ -0,0 +1,348 @@
#!/usr/bin/env sh
# OpenStack Designate API plugin
#
# This requires you to have OpenStackClient and python-desginateclient
# installed.
#
# You will require Keystone V3 credentials loaded into your environment, which
# could be either password or v3applicationcredential type.
#
# Author: Andy Botting <andy@andybotting.com>
######## Public functions #####################
# Usage: dns_openstack_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_openstack_add() {
fulldomain=$1
txtvalue=$2
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
_dns_openstack_credentials || return $?
_dns_openstack_check_setup || return $?
_dns_openstack_find_zone || return $?
_dns_openstack_get_recordset || return $?
_debug _recordset_id "$_recordset_id"
if [ -n "$_recordset_id" ]; then
_dns_openstack_get_records || return $?
_debug _records "$_records"
fi
_dns_openstack_create_recordset || return $?
}
# Usage: dns_openstack_rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
# Remove the txt record after validation.
dns_openstack_rm() {
fulldomain=$1
txtvalue=$2
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
_dns_openstack_credentials || return $?
_dns_openstack_check_setup || return $?
_dns_openstack_find_zone || return $?
_dns_openstack_get_recordset || return $?
_debug _recordset_id "$_recordset_id"
if [ -n "$_recordset_id" ]; then
_dns_openstack_get_records || return $?
_debug _records "$_records"
fi
_dns_openstack_delete_recordset || return $?
}
#################### Private functions below ##################################
_dns_openstack_create_recordset() {
if [ -z "$_recordset_id" ]; then
_info "Creating a new recordset"
if ! _recordset_id=$(openstack recordset create -c id -f value --type TXT --record "$txtvalue" "$_zone_id" "$fulldomain."); then
_err "No recordset ID found after create"
return 1
fi
else
_info "Updating existing recordset"
# Build new list of --record <rec> args for update
_record_args="--record $txtvalue"
for _rec in $_records; do
_record_args="$_record_args --record $_rec"
done
# shellcheck disable=SC2086
if ! _recordset_id=$(openstack recordset set -c id -f value $_record_args "$_zone_id" "$fulldomain."); then
_err "Recordset update failed"
return 1
fi
fi
_max_retries=60
_sleep_sec=5
_retry_times=0
while [ "$_retry_times" -lt "$_max_retries" ]; do
_retry_times=$(_math "$_retry_times" + 1)
_debug3 _retry_times "$_retry_times"
_record_status=$(openstack recordset show -c status -f value "$_zone_id" "$_recordset_id")
_info "Recordset status is $_record_status"
if [ "$_record_status" = "ACTIVE" ]; then
return 0
elif [ "$_record_status" = "ERROR" ]; then
return 1
else
_sleep $_sleep_sec
fi
done
_err "Recordset failed to become ACTIVE"
return 1
}
_dns_openstack_delete_recordset() {
if [ "$_records" = "$txtvalue" ]; then
_info "Only one record found, deleting recordset"
if ! openstack recordset delete "$_zone_id" "$fulldomain." >/dev/null; then
_err "Failed to delete recordset"
return 1
fi
else
_info "Found existing records, updating recordset"
# Build new list of --record <rec> args for update
_record_args=""
for _rec in $_records; do
if [ "$_rec" = "$txtvalue" ]; then
continue
fi
_record_args="$_record_args --record $_rec"
done
# shellcheck disable=SC2086
if ! openstack recordset set -c id -f value $_record_args "$_zone_id" "$fulldomain." >/dev/null; then
_err "Recordset update failed"
return 1
fi
fi
}
_dns_openstack_get_root() {
# Take the full fqdn and strip away pieces until we get an exact zone name
# match. For example, _acme-challenge.something.domain.com might need to go
# into something.domain.com or domain.com
_zone_name=$1
_zone_list=$2
while [ "$_zone_name" != "" ]; do
_zone_name="$(echo "$_zone_name" | sed 's/[^.]*\.*//')"
echo "$_zone_list" | while read -r id name; do
if _startswith "$_zone_name." "$name"; then
echo "$id"
fi
done
done | _head_n 1
}
_dns_openstack_find_zone() {
if ! _zone_list="$(openstack zone list -c id -c name -f value)"; then
_err "Can't list zones. Check your OpenStack credentials"
return 1
fi
_debug _zone_list "$_zone_list"
if ! _zone_id="$(_dns_openstack_get_root "$fulldomain" "$_zone_list")"; then
_err "Can't find a matching zone. Check your OpenStack credentials"
return 1
fi
_debug _zone_id "$_zone_id"
}
_dns_openstack_get_records() {
if ! _records=$(openstack recordset show -c records -f value "$_zone_id" "$fulldomain."); then
_err "Failed to get records"
return 1
fi
return 0
}
_dns_openstack_get_recordset() {
if ! _recordset_id=$(openstack recordset list -c id -f value --name "$fulldomain." "$_zone_id"); then
_err "Failed to get recordset"
return 1
fi
return 0
}
_dns_openstack_check_setup() {
if ! _exists openstack; then
_err "OpenStack client not found"
return 1
fi
}
_dns_openstack_credentials() {
_debug "Check OpenStack credentials"
# If we have OS_AUTH_URL already set in the environment, then assume we want
# to use those, otherwise use stored credentials
if [ -n "$OS_AUTH_URL" ]; then
_debug "OS_AUTH_URL env var found, using environment"
else
_debug "OS_AUTH_URL not found, loading stored credentials"
OS_AUTH_URL="${OS_AUTH_URL:-$(_readaccountconf_mutable OS_AUTH_URL)}"
OS_IDENTITY_API_VERSION="${OS_IDENTITY_API_VERSION:-$(_readaccountconf_mutable OS_IDENTITY_API_VERSION)}"
OS_AUTH_TYPE="${OS_AUTH_TYPE:-$(_readaccountconf_mutable OS_AUTH_TYPE)}"
OS_APPLICATION_CREDENTIAL_ID="${OS_APPLICATION_CREDENTIAL_ID:-$(_readaccountconf_mutable OS_APPLICATION_CREDENTIAL_ID)}"
OS_APPLICATION_CREDENTIAL_SECRET="${OS_APPLICATION_CREDENTIAL_SECRET:-$(_readaccountconf_mutable OS_APPLICATION_CREDENTIAL_SECRET)}"
OS_USERNAME="${OS_USERNAME:-$(_readaccountconf_mutable OS_USERNAME)}"
OS_PASSWORD="${OS_PASSWORD:-$(_readaccountconf_mutable OS_PASSWORD)}"
OS_PROJECT_NAME="${OS_PROJECT_NAME:-$(_readaccountconf_mutable OS_PROJECT_NAME)}"
OS_PROJECT_ID="${OS_PROJECT_ID:-$(_readaccountconf_mutable OS_PROJECT_ID)}"
OS_USER_DOMAIN_NAME="${OS_USER_DOMAIN_NAME:-$(_readaccountconf_mutable OS_USER_DOMAIN_NAME)}"
OS_USER_DOMAIN_ID="${OS_USER_DOMAIN_ID:-$(_readaccountconf_mutable OS_USER_DOMAIN_ID)}"
OS_PROJECT_DOMAIN_NAME="${OS_PROJECT_DOMAIN_NAME:-$(_readaccountconf_mutable OS_PROJECT_DOMAIN_NAME)}"
OS_PROJECT_DOMAIN_ID="${OS_PROJECT_DOMAIN_ID:-$(_readaccountconf_mutable OS_PROJECT_DOMAIN_ID)}"
fi
# Check each var and either save or clear it depending on whether its set.
# The helps us clear out old vars in the case where a user may want
# to switch between password and app creds
_debug "OS_AUTH_URL" "$OS_AUTH_URL"
if [ -n "$OS_AUTH_URL" ]; then
export OS_AUTH_URL
_saveaccountconf_mutable OS_AUTH_URL "$OS_AUTH_URL"
else
unset OS_AUTH_URL
_clearaccountconf SAVED_OS_AUTH_URL
fi
_debug "OS_IDENTITY_API_VERSION" "$OS_IDENTITY_API_VERSION"
if [ -n "$OS_IDENTITY_API_VERSION" ]; then
export OS_IDENTITY_API_VERSION
_saveaccountconf_mutable OS_IDENTITY_API_VERSION "$OS_IDENTITY_API_VERSION"
else
unset OS_IDENTITY_API_VERSION
_clearaccountconf SAVED_OS_IDENTITY_API_VERSION
fi
_debug "OS_AUTH_TYPE" "$OS_AUTH_TYPE"
if [ -n "$OS_AUTH_TYPE" ]; then
export OS_AUTH_TYPE
_saveaccountconf_mutable OS_AUTH_TYPE "$OS_AUTH_TYPE"
else
unset OS_AUTH_TYPE
_clearaccountconf SAVED_OS_AUTH_TYPE
fi
_debug "OS_APPLICATION_CREDENTIAL_ID" "$OS_APPLICATION_CREDENTIAL_ID"
if [ -n "$OS_APPLICATION_CREDENTIAL_ID" ]; then
export OS_APPLICATION_CREDENTIAL_ID
_saveaccountconf_mutable OS_APPLICATION_CREDENTIAL_ID "$OS_APPLICATION_CREDENTIAL_ID"
else
unset OS_APPLICATION_CREDENTIAL_ID
_clearaccountconf SAVED_OS_APPLICATION_CREDENTIAL_ID
fi
_secure_debug "OS_APPLICATION_CREDENTIAL_SECRET" "$OS_APPLICATION_CREDENTIAL_SECRET"
if [ -n "$OS_APPLICATION_CREDENTIAL_SECRET" ]; then
export OS_APPLICATION_CREDENTIAL_SECRET
_saveaccountconf_mutable OS_APPLICATION_CREDENTIAL_SECRET "$OS_APPLICATION_CREDENTIAL_SECRET"
else
unset OS_APPLICATION_CREDENTIAL_SECRET
_clearaccountconf SAVED_OS_APPLICATION_CREDENTIAL_SECRET
fi
_debug "OS_USERNAME" "$OS_USERNAME"
if [ -n "$OS_USERNAME" ]; then
export OS_USERNAME
_saveaccountconf_mutable OS_USERNAME "$OS_USERNAME"
else
unset OS_USERNAME
_clearaccountconf SAVED_OS_USERNAME
fi
_secure_debug "OS_PASSWORD" "$OS_PASSWORD"
if [ -n "$OS_PASSWORD" ]; then
export OS_PASSWORD
_saveaccountconf_mutable OS_PASSWORD "$OS_PASSWORD"
else
unset OS_PASSWORD
_clearaccountconf SAVED_OS_PASSWORD
fi
_debug "OS_PROJECT_NAME" "$OS_PROJECT_NAME"
if [ -n "$OS_PROJECT_NAME" ]; then
export OS_PROJECT_NAME
_saveaccountconf_mutable OS_PROJECT_NAME "$OS_PROJECT_NAME"
else
unset OS_PROJECT_NAME
_clearaccountconf SAVED_OS_PROJECT_NAME
fi
_debug "OS_PROJECT_ID" "$OS_PROJECT_ID"
if [ -n "$OS_PROJECT_ID" ]; then
export OS_PROJECT_ID
_saveaccountconf_mutable OS_PROJECT_ID "$OS_PROJECT_ID"
else
unset OS_PROJECT_ID
_clearaccountconf SAVED_OS_PROJECT_ID
fi
_debug "OS_USER_DOMAIN_NAME" "$OS_USER_DOMAIN_NAME"
if [ -n "$OS_USER_DOMAIN_NAME" ]; then
export OS_USER_DOMAIN_NAME
_saveaccountconf_mutable OS_USER_DOMAIN_NAME "$OS_USER_DOMAIN_NAME"
else
unset OS_USER_DOMAIN_NAME
_clearaccountconf SAVED_OS_USER_DOMAIN_NAME
fi
_debug "OS_USER_DOMAIN_ID" "$OS_USER_DOMAIN_ID"
if [ -n "$OS_USER_DOMAIN_ID" ]; then
export OS_USER_DOMAIN_ID
_saveaccountconf_mutable OS_USER_DOMAIN_ID "$OS_USER_DOMAIN_ID"
else
unset OS_USER_DOMAIN_ID
_clearaccountconf SAVED_OS_USER_DOMAIN_ID
fi
_debug "OS_PROJECT_DOMAIN_NAME" "$OS_PROJECT_DOMAIN_NAME"
if [ -n "$OS_PROJECT_DOMAIN_NAME" ]; then
export OS_PROJECT_DOMAIN_NAME
_saveaccountconf_mutable OS_PROJECT_DOMAIN_NAME "$OS_PROJECT_DOMAIN_NAME"
else
unset OS_PROJECT_DOMAIN_NAME
_clearaccountconf SAVED_OS_PROJECT_DOMAIN_NAME
fi
_debug "OS_PROJECT_DOMAIN_ID" "$OS_PROJECT_DOMAIN_ID"
if [ -n "$OS_PROJECT_DOMAIN_ID" ]; then
export OS_PROJECT_DOMAIN_ID
_saveaccountconf_mutable OS_PROJECT_DOMAIN_ID "$OS_PROJECT_DOMAIN_ID"
else
unset OS_PROJECT_DOMAIN_ID
_clearaccountconf SAVED_OS_PROJECT_DOMAIN_ID
fi
if [ "$OS_AUTH_TYPE" = "v3applicationcredential" ]; then
# Application Credential auth
if [ -z "$OS_APPLICATION_CREDENTIAL_ID" ] || [ -z "$OS_APPLICATION_CREDENTIAL_SECRET" ]; then
_err "When using OpenStack application credentials, OS_APPLICATION_CREDENTIAL_ID"
_err "and OS_APPLICATION_CREDENTIAL_SECRET must be set."
_err "Please check your credentials and try again."
return 1
fi
else
# Password auth
if [ -z "$OS_USERNAME" ] || [ -z "$OS_PASSWORD" ]; then
_err "OpenStack username or password not found."
_err "Please check your credentials and try again."
return 1
fi
if [ -z "$OS_PROJECT_NAME" ] && [ -z "$OS_PROJECT_ID" ]; then
_err "When using password authentication, OS_PROJECT_NAME or"
_err "OS_PROJECT_ID must be set."
_err "Please check your credentials and try again."
return 1
fi
fi
return 0
}

273
dnsapi/dns_opnsense.sh Executable file
View File

@@ -0,0 +1,273 @@
#!/usr/bin/env sh
#OPNsense Bind API
#https://docs.opnsense.org/development/api.html
#
#OPNs_Host="opnsense.example.com"
#OPNs_Port="443"
# optional, defaults to 443 if unset
#OPNs_Key="qocfU9RSbt8vTIBcnW8bPqCrpfAHMDvj5OzadE7Str+rbjyCyk7u6yMrSCHtBXabgDDXx/dY0POUp7ZA"
#OPNs_Token="pZEQ+3ce8dDlfBBdg3N8EpqpF5I1MhFqdxX06le6Gl8YzyQvYCfCzNaFX9O9+IOSyAs7X71fwdRiZ+Lv"
#OPNs_Api_Insecure=0
# optional, defaults to 0 if unset
# Set 1 for insecure and 0 for secure -> difference is whether ssl cert is checked for validity (0) or whether it is just accepted (1)
######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "123456789ABCDEF0000000000000000000000000000000000000"
#fulldomain
#txtvalue
OPNs_DefaultPort=443
OPNs_DefaultApi_Insecure=0
dns_opnsense_add() {
fulldomain=$1
txtvalue=$2
_opns_check_auth || return 1
if ! set_record "$fulldomain" "$txtvalue"; then
return 1
fi
return 0
}
#fulldomain
dns_opnsense_rm() {
fulldomain=$1
txtvalue=$2
_opns_check_auth || return 1
if ! rm_record "$fulldomain" "$txtvalue"; then
return 1
fi
return 0
}
set_record() {
fulldomain=$1
new_challenge=$2
_info "Adding record $fulldomain with challenge: $new_challenge"
_debug "Detect root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"
return 1
fi
_debug _domain "$_domain"
_debug _host "$_host"
_debug _domainid "$_domainid"
_return_str=""
_record_string=""
_build_record_string "$_domainid" "$_host" "$new_challenge"
_uuid=""
if _existingchallenge "$_domain" "$_host" "$new_challenge"; then
# Update
if _opns_rest "POST" "/record/setRecord/${_uuid}" "$_record_string"; then
_return_str="$response"
else
return 1
fi
else
#create
if _opns_rest "POST" "/record/addRecord" "$_record_string"; then
_return_str="$response"
else
return 1
fi
fi
if echo "$_return_str" | _egrep_o "\"result\":\"saved\"" >/dev/null; then
_opns_rest "POST" "/service/reconfigure" "{}"
_debug "Record created"
else
_err "Error creating record $_record_string"
return 1
fi
return 0
}
rm_record() {
fulldomain=$1
new_challenge="$2"
_info "Remove record $fulldomain with challenge: $new_challenge"
_debug "Detect root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"
return 1
fi
_debug _domain "$_domain"
_debug _host "$_host"
_debug _domainid "$_domainid"
_uuid=""
if _existingchallenge "$_domain" "$_host" "$new_challenge"; then
# Delete
if _opns_rest "POST" "/record/delRecord/${_uuid}" "\{\}"; then
if echo "$_return_str" | _egrep_o "\"result\":\"deleted\"" >/dev/null; then
_opns_rest "POST" "/service/reconfigure" "{}"
_debug "Record deleted"
else
_err "Error deleting record $_host from domain $fulldomain"
return 1
fi
else
_err "Error deleting record $_host from domain $fulldomain"
return 1
fi
else
_info "Record not found, nothing to remove"
fi
return 0
}
#################### Private functions below ##################################
#_acme-challenge.www.domain.com
#returns
# _domainid=domid
#_domain=domain.com
_get_root() {
domain=$1
i=2
p=1
if _opns_rest "GET" "/domain/get"; then
_domain_response="$response"
else
return 1
fi
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
if [ -z "$h" ]; then
#not valid
return 1
fi
_debug h "$h"
id=$(echo "$_domain_response" | _egrep_o "\"[^\"]*\":{\"enabled\":\"1\",\"type\":{\"master\":{\"value\":\"master\",\"selected\":1},\"slave\":{\"value\":\"slave\",\"selected\":0}},\"masterip\":\"[^\"]*\"(,\"allownotifyslave\":{\"\":{[^}]*}},|,)\"domainname\":\"${h}\"" | cut -d ':' -f 1 | cut -d '"' -f 2)
if [ -n "$id" ]; then
_debug id "$id"
_host=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_domain="${h}"
_domainid="${id}"
return 0
fi
p=$i
i=$(_math $i + 1)
done
_debug "$domain not found"
return 1
}
_opns_rest() {
method=$1
ep=$2
data=$3
#Percent encode user and token
key=$(echo "$OPNs_Key" | tr -d "\n\r" | _url_encode)
token=$(echo "$OPNs_Token" | tr -d "\n\r" | _url_encode)
opnsense_url="https://${key}:${token}@${OPNs_Host}:${OPNs_Port:-$OPNs_DefaultPort}/api/bind${ep}"
export _H1="Content-Type: application/json"
_debug2 "Try to call api: https://${OPNs_Host}:${OPNs_Port:-$OPNs_DefaultPort}/api/bind${ep}"
if [ ! "$method" = "GET" ]; then
_debug data "$data"
export _H1="Content-Type: application/json"
response="$(_post "$data" "$opnsense_url" "" "$method")"
else
export _H1=""
response="$(_get "$opnsense_url")"
fi
if [ "$?" != "0" ]; then
_err "error $ep"
return 1
fi
_debug2 response "$response"
return 0
}
_build_record_string() {
_record_string="{\"record\":{\"enabled\":\"1\",\"domain\":\"$1\",\"name\":\"$2\",\"type\":\"TXT\",\"value\":\"$3\"}}"
}
_existingchallenge() {
if _opns_rest "GET" "/record/searchRecord"; then
_record_response="$response"
else
return 1
fi
_uuid=""
_uuid=$(echo "$_record_response" | _egrep_o "\"uuid\":\"[^\"]*\",\"enabled\":\"[01]\",\"domain\":\"$1\",\"name\":\"$2\",\"type\":\"TXT\",\"value\":\"$3\"" | cut -d ':' -f 2 | cut -d '"' -f 2)
if [ -n "$_uuid" ]; then
_debug uuid "$_uuid"
return 0
fi
_debug "${2}.$1{1} record not found"
return 1
}
_opns_check_auth() {
OPNs_Host="${OPNs_Host:-$(_readaccountconf_mutable OPNs_Host)}"
OPNs_Port="${OPNs_Port:-$(_readaccountconf_mutable OPNs_Port)}"
OPNs_Key="${OPNs_Key:-$(_readaccountconf_mutable OPNs_Key)}"
OPNs_Token="${OPNs_Token:-$(_readaccountconf_mutable OPNs_Token)}"
OPNs_Api_Insecure="${OPNs_Api_Insecure:-$(_readaccountconf_mutable OPNs_Api_Insecure)}"
if [ -z "$OPNs_Host" ]; then
_err "You don't specify OPNsense address."
return 1
else
_saveaccountconf_mutable OPNs_Host "$OPNs_Host"
fi
if ! printf '%s' "$OPNs_Port" | grep '^[0-9]*$' >/dev/null; then
_err 'OPNs_Port specified but not numeric value'
return 1
elif [ -z "$OPNs_Port" ]; then
_info "OPNSense port not specified. Defaulting to using port $OPNs_DefaultPort"
else
_saveaccountconf_mutable OPNs_Port "$OPNs_Port"
fi
if ! printf '%s' "$OPNs_Api_Insecure" | grep '^[01]$' >/dev/null; then
_err 'OPNs_Api_Insecure specified but not 0/1 value'
return 1
elif [ -n "$OPNs_Api_Insecure" ]; then
_saveaccountconf_mutable OPNs_Api_Insecure "$OPNs_Api_Insecure"
fi
export HTTPS_INSECURE="${OPNs_Api_Insecure:-$OPNs_DefaultApi_Insecure}"
if [ -z "$OPNs_Key" ]; then
_err "you have not specified your OPNsense api key id."
_err "Please set OPNs_Key and try again."
return 1
else
_saveaccountconf_mutable OPNs_Key "$OPNs_Key"
fi
if [ -z "$OPNs_Token" ]; then
_err "you have not specified your OPNsense token."
_err "Please create OPNs_Token and try again."
return 1
else
_saveaccountconf_mutable OPNs_Token "$OPNs_Token"
fi
if ! _opns_rest "GET" "/general/get"; then
_err "Call to OPNsense API interface failed. Unable to access OPNsense API."
return 1
fi
return 0
}

View File

@@ -32,49 +32,49 @@ SYS_CA='https://ca.api.soyoustart.com/1.0'
#'runabove-ca'
RAV_CA='https://api.runabove.com/1.0'
wiki="https://github.com/Neilpang/acme.sh/wiki/How-to-use-OVH-domain-api"
wiki="https://github.com/acmesh-official/acme.sh/wiki/How-to-use-OVH-domain-api"
ovh_success="https://github.com/Neilpang/acme.sh/wiki/OVH-Success"
ovh_success="https://github.com/acmesh-official/acme.sh/wiki/OVH-Success"
_ovh_get_api() {
_ogaep="$1"
case "${_ogaep}" in
ovh-eu | ovheu)
printf "%s" $OVH_EU
return
;;
ovh-ca | ovhca)
printf "%s" $OVH_CA
return
;;
kimsufi-eu | kimsufieu)
printf "%s" $KSF_EU
return
;;
kimsufi-ca | kimsufica)
printf "%s" $KSF_CA
return
;;
soyoustart-eu | soyoustarteu)
printf "%s" $SYS_EU
return
;;
soyoustart-ca | soyoustartca)
printf "%s" $SYS_CA
return
;;
runabove-ca | runaboveca)
printf "%s" $RAV_CA
return
;;
ovh-eu | ovheu)
printf "%s" $OVH_EU
return
;;
ovh-ca | ovhca)
printf "%s" $OVH_CA
return
;;
kimsufi-eu | kimsufieu)
printf "%s" $KSF_EU
return
;;
kimsufi-ca | kimsufica)
printf "%s" $KSF_CA
return
;;
soyoustart-eu | soyoustarteu)
printf "%s" $SYS_EU
return
;;
soyoustart-ca | soyoustartca)
printf "%s" $SYS_CA
return
;;
runabove-ca | runaboveca)
printf "%s" $RAV_CA
return
;;
*)
*)
_err "Unknown parameter : $1"
return 1
;;
_err "Unknown parameter : $1"
return 1
;;
esac
}

View File

@@ -2,7 +2,7 @@
## Name: dns_pleskxml.sh
## Created by Stilez.
## Also uses some code from PR#1832 by @romanlum (https://github.com/Neilpang/acme.sh/pull/1832/files)
## Also uses some code from PR#1832 by @romanlum (https://github.com/acmesh-official/acme.sh/pull/1832/files)
## This DNS-01 method uses the Plesk XML API described at:
## https://docs.plesk.com/en-US/12.5/api-rpc/about-xml-api.28709
@@ -136,11 +136,12 @@ dns_pleskxml_rm() {
# Reduce output to one line per DNS record, filtered for TXT records with a record ID only (which they should all have)
# Also strip out spaces between tags, redundant <data> and </data> group tags and any <self-closing/> tags
reclist="$(_api_response_split "$pleskxml_prettyprint_result" 'result' '<status>ok</status>' \
| sed 's# \{1,\}<\([a-zA-Z]\)#<\1#g;s#</\{0,1\}data>##g;s#<[a-z][^/<>]*/>##g' \
| grep "<site-id>${root_domain_id}</site-id>" \
| grep '<id>[0-9]\{1,\}</id>' \
| grep '<type>TXT</type>'
reclist="$(
_api_response_split "$pleskxml_prettyprint_result" 'result' '<status>ok</status>' |
sed 's# \{1,\}<\([a-zA-Z]\)#<\1#g;s#</\{0,1\}data>##g;s#<[a-z][^/<>]*/>##g' |
grep "<site-id>${root_domain_id}</site-id>" |
grep '<id>[0-9]\{1,\}</id>' |
grep '<type>TXT</type>'
)"
if [ -z "$reclist" ]; then
@@ -151,10 +152,11 @@ dns_pleskxml_rm() {
_debug "Got list of DNS TXT records for root domain '$root_domain_name':"
_debug "$reclist"
recid="$(_value "$reclist" \
| grep "<host>${fulldomain}.</host>" \
| grep "<value>${txtvalue}</value>" \
| sed 's/^.*<id>\([0-9]\{1,\}\)<\/id>.*$/\1/'
recid="$(
_value "$reclist" |
grep "<host>${fulldomain}.</host>" |
grep "<value>${txtvalue}</value>" |
sed 's/^.*<id>\([0-9]\{1,\}\)<\/id>.*$/\1/'
)"
if ! _value "$recid" | grep '^[0-9]\{1,\}$' >/dev/null; then
@@ -220,11 +222,11 @@ _countdots() {
# Last line could change to <sed -n '/.../p'> instead, with suitable escaping of ['"/$],
# if future Plesk XML API changes ever require extended regex
_api_response_split() {
printf '%s' "$1" \
| sed 's/^ +//;s/ +$//' \
| tr -d '\n\r' \
| sed "s/<\/\{0,1\}$2>/${NEWLINE}/g" \
| grep "$3"
printf '%s' "$1" |
sed 's/^ +//;s/ +$//' |
tr -d '\n\r' |
sed "s/<\/\{0,1\}$2>/${NEWLINE}/g" |
grep "$3"
}
#################### Private functions below (DNS functions) ##################################
@@ -261,14 +263,15 @@ _call_api() {
elif [ "$statuslines_count_okay" -ne "$statuslines_count_total" ]; then
# We have some status lines that aren't "ok". Any available details are in API response fields "status" "errcode" and "errtext"
# Workaround for basic regex:
# Workaround for basic regex:
# - filter output to keep only lines like this: "SPACES<TAG>text</TAG>SPACES" (shouldn't be necessary with prettyprint but guarantees subsequent code is ok)
# - then edit the 3 "useful" error tokens individually and remove closing tags on all lines
# - then filter again to remove all lines not edited (which will be the lines not starting A-Z)
errtext="$(_value "$pleskxml_prettyprint_result" \
| grep '^ *<[a-z]\{1,\}>[^<]*<\/[a-z]\{1,\}> *$' \
| sed 's/^ *<status>/Status: /;s/^ *<errcode>/Error code: /;s/^ *<errtext>/Error text: /;s/<\/.*$//' \
| grep '^[A-Z]'
errtext="$(
_value "$pleskxml_prettyprint_result" |
grep '^ *<[a-z]\{1,\}>[^<]*<\/[a-z]\{1,\}> *$' |
sed 's/^ *<status>/Status: /;s/^ *<errcode>/Error code: /;s/^ *<errtext>/Error text: /;s/<\/.*$//' |
grep '^[A-Z]'
)"
fi

View File

@@ -9,7 +9,7 @@ RACKSPACE_Endpoint="https://dns.api.rackspacecloud.com/v1.0"
# 20190213 - The name & id fields swapped in the API response; fix sed
# 20190101 - Duplicating file for new pull request to dev branch
# Original - tcocca:rackspace_dnsapi https://github.com/Neilpang/acme.sh/pull/1297
# Original - tcocca:rackspace_dnsapi https://github.com/acmesh-official/acme.sh/pull/1297
######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
@@ -73,7 +73,7 @@ _get_root_zone() {
#not valid
return 1
fi
if ! _rackspace_rest GET "$RACKSPACE_Tenant/domains"; then
if ! _rackspace_rest GET "$RACKSPACE_Tenant/domains/search?name=$h"; then
return 1
fi
_debug2 response "$response"

View File

@@ -5,7 +5,6 @@
#
# REGRU_API_Password="test"
#
_domain=$_domain
REGRU_API_URL="https://api.reg.ru/api/regru2"
@@ -27,10 +26,20 @@ dns_regru_add() {
_saveaccountconf_mutable REGRU_API_Username "$REGRU_API_Username"
_saveaccountconf_mutable REGRU_API_Password "$REGRU_API_Password"
_info "Adding TXT record to ${fulldomain}"
response="$(_get "$REGRU_API_URL/zone/add_txt?input_data={%22username%22:%22${REGRU_API_Username}%22,%22password%22:%22${REGRU_API_Password}%22,%22domains%22:[{%22dname%22:%22${_domain}%22}],%22subdomain%22:%22_acme-challenge%22,%22text%22:%22${txtvalue}%22,%22output_content_type%22:%22plain%22}&input_format=json")"
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"
return 1
fi
_debug _domain "$_domain"
if _contains "${response}" 'success'; then
_subdomain=$(echo "$fulldomain" | sed -r "s/.$_domain//")
_debug _subdomain "$_subdomain"
_info "Adding TXT record to ${fulldomain}"
_regru_rest POST "zone/add_txt" "input_data={%22username%22:%22${REGRU_API_Username}%22,%22password%22:%22${REGRU_API_Password}%22,%22domains%22:[{%22dname%22:%22${_domain}%22}],%22subdomain%22:%22${_subdomain}%22,%22text%22:%22${txtvalue}%22,%22output_content_type%22:%22plain%22}&input_format=json"
if ! _contains "${response}" 'error'; then
return 0
fi
_err "Could not create resource record, check logs"
@@ -51,13 +60,67 @@ dns_regru_rm() {
return 1
fi
_info "Deleting resource record $fulldomain"
response="$(_get "$REGRU_API_URL/zone/remove_record?input_data={%22username%22:%22${REGRU_API_Username}%22,%22password%22:%22${REGRU_API_Password}%22,%22domains%22:[{%22dname%22:%22${_domain}%22}],%22subdomain%22:%22_acme-challenge%22,%22content%22:%22${txtvalue}%22,%22record_type%22:%22TXT%22,%22output_content_type%22:%22plain%22}&input_format=json")"
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"
return 1
fi
_debug _domain "$_domain"
if _contains "${response}" 'success'; then
_subdomain=$(echo "$fulldomain" | sed -r "s/.$_domain//")
_debug _subdomain "$_subdomain"
_info "Deleting resource record $fulldomain"
_regru_rest POST "zone/remove_record" "input_data={%22username%22:%22${REGRU_API_Username}%22,%22password%22:%22${REGRU_API_Password}%22,%22domains%22:[{%22dname%22:%22${_domain}%22}],%22subdomain%22:%22${_subdomain}%22,%22content%22:%22${txtvalue}%22,%22record_type%22:%22TXT%22,%22output_content_type%22:%22plain%22}&input_format=json"
if ! _contains "${response}" 'error'; then
return 0
fi
_err "Could not delete resource record, check logs"
_err "${response}"
return 1
}
#################### Private functions below ##################################
#_acme-challenge.www.domain.com
#returns
# _domain=domain.com
_get_root() {
domain=$1
_regru_rest POST "service/get_list" "username=${REGRU_API_Username}&password=${REGRU_API_Password}&output_format=xml&servtype=domain"
domains_list=$(echo "${response}" | grep dname | sed -r "s/.*dname=\"([^\"]+)\".*/\\1/g")
for ITEM in ${domains_list}; do
case "${domain}" in
*${ITEM}*)
_domain=${ITEM}
_debug _domain "${_domain}"
return 0
;;
esac
done
return 1
}
#returns
# response
_regru_rest() {
m=$1
ep="$2"
data="$3"
_debug "$ep"
export _H1="Content-Type: application/x-www-form-urlencoded"
if [ "$m" != "GET" ]; then
_debug data "$data"
response="$(_post "$data" "$REGRU_API_URL/$ep" "" "$m")"
else
response="$(_get "$REGRU_API_URL/$ep?$data")"
fi
_debug response "${response}"
return 0
}

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env sh
##########
# Custom servercow.de DNS API v1 for use with [acme.sh](https://github.com/Neilpang/acme.sh)
# Custom servercow.de DNS API v1 for use with [acme.sh](https://github.com/acmesh-official/acme.sh)
#
# Usage:
# export SERVERCOW_API_Username=username

162
dnsapi/dns_transip.sh Normal file
View File

@@ -0,0 +1,162 @@
#!/usr/bin/env sh
TRANSIP_Api_Url="https://api.transip.nl/v6"
TRANSIP_Token_Read_Only="false"
TRANSIP_Token_Global_Key="false"
TRANSIP_Token_Expiration="30 minutes"
# You can't reuse a label token, so we leave this empty normally
TRANSIP_Token_Label=""
######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_transip_add() {
fulldomain="$1"
_debug fulldomain="$fulldomain"
txtvalue="$2"
_debug txtvalue="$txtvalue"
_transip_setup "$fulldomain" || return 1
_info "Creating TXT record."
if ! _transip_rest POST "domains/$_domain/dns" "{\"dnsEntry\":{\"name\":\"$_sub_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"expire\":300}}"; then
_err "Could not add TXT record."
return 1
fi
return 0
}
dns_transip_rm() {
fulldomain=$1
_debug fulldomain="$fulldomain"
txtvalue=$2
_debug txtvalue="$txtvalue"
_transip_setup "$fulldomain" || return 1
_info "Removing TXT record."
if ! _transip_rest DELETE "domains/$_domain/dns" "{\"dnsEntry\":{\"name\":\"$_sub_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"expire\":300}}"; then
_err "Could not remove TXT record $_sub_domain for $domain"
return 1
fi
return 0
}
#################### Private functions below ##################################
#_acme-challenge.www.domain.com
#returns
# _sub_domain=_acme-challenge.www
# _domain=domain.com
_get_root() {
domain="$1"
i=2
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
if [ -z "$h" ]; then
#not valid
return 1
fi
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_domain="$h"
if _transip_rest GET "domains/$h/dns" && _contains "$response" "dnsEntries"; then
return 0
fi
p=$i
i=$(_math "$i" + 1)
done
_err "Unable to parse this domain"
return 1
}
_transip_rest() {
m="$1"
ep="$2"
data="$3"
_debug ep "$ep"
export _H1="Accept: application/json"
export _H2="Authorization: Bearer $_token"
export _H4="Content-Type: application/json"
if [ "$m" != "GET" ]; then
_debug data "$data"
response="$(_post "$data" "$TRANSIP_Api_Url/$ep" "" "$m")"
retcode=$?
else
response="$(_get "$TRANSIP_Api_Url/$ep")"
retcode=$?
fi
if [ "$retcode" != "0" ]; then
_err "error $ep"
return 1
fi
_debug2 response "$response"
return 0
}
_transip_get_token() {
nonce=$(echo "TRANSIP$(_time)" | _digest sha1 hex | cut -c 1-32)
_debug nonce "$nonce"
data="{\"login\":\"${TRANSIP_Username}\",\"nonce\":\"${nonce}\",\"read_only\":\"${TRANSIP_Token_Read_Only}\",\"expiration_time\":\"${TRANSIP_Token_Expiration}\",\"label\":\"${TRANSIP_Token_Label}\",\"global_key\":\"${TRANSIP_Token_Global_Key}\"}"
_debug data "$data"
#_signature=$(printf "%s" "$data" | openssl dgst -sha512 -sign "$TRANSIP_Key_File" | _base64)
_signature=$(printf "%s" "$data" | _sign "$TRANSIP_Key_File" "sha512")
_debug2 _signature "$_signature"
export _H1="Signature: $_signature"
export _H2="Content-Type: application/json"
response="$(_post "$data" "$TRANSIP_Api_Url/auth" "" "POST")"
retcode=$?
_debug2 response "$response"
if [ "$retcode" != "0" ]; then
_err "Authentication failed."
return 1
fi
if _contains "$response" "token"; then
_token="$(echo "$response" | _normalizeJson | sed -n 's/^{"token":"\(.*\)"}/\1/p')"
_debug _token "$_token"
return 0
fi
return 1
}
_transip_setup() {
fulldomain=$1
# retrieve the transip creds
TRANSIP_Username="${TRANSIP_Username:-$(_readaccountconf_mutable TRANSIP_Username)}"
TRANSIP_Key_File="${TRANSIP_Key_File:-$(_readaccountconf_mutable TRANSIP_Key_File)}"
# check their vals for null
if [ -z "$TRANSIP_Username" ] || [ -z "$TRANSIP_Key_File" ]; then
TRANSIP_Username=""
TRANSIP_Key_File=""
_err "You didn't specify a TransIP username and api key file location"
_err "Please set those values and try again."
return 1
fi
# save the username and api key to the account conf file.
_saveaccountconf_mutable TRANSIP_Username "$TRANSIP_Username"
_saveaccountconf_mutable TRANSIP_Key_File "$TRANSIP_Key_File"
if [ -f "$TRANSIP_Key_File" ]; then
if ! grep "BEGIN PRIVATE KEY" "$TRANSIP_Key_File" >/dev/null 2>&1; then
_err "Key file doesn't seem to be a valid key: ${TRANSIP_Key_File}"
return 1
fi
else
_err "Can't read private key file: ${TRANSIP_Key_File}"
return 1
fi
if [ -z "$_token" ]; then
if ! _transip_get_token; then
_err "Can not get token."
return 1
fi
fi
_get_root "$fulldomain" || return 1
return 0
}

View File

@@ -5,7 +5,7 @@
#
#UNO_User="UExxxxxx"
Uno_Api="https://api.unoeuro.com/1"
Uno_Api="https://api.simply.com/1"
######## Public functions #####################
@@ -24,12 +24,6 @@ dns_unoeuro_add() {
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"

View File

@@ -107,7 +107,7 @@ _get_root() {
fi
if _startswith "$response" "\{\"data\":"; then
if _contains "$response" "\"id\": \"$h\""; then
if _contains "$response" "\"id\":\"$h\""; then
_sub_domain="$(echo "$fulldomain" | sed "s/\\.$h\$//")"
_domain=$h
return 0

View File

@@ -6,6 +6,9 @@
# Values to export:
# export PDD_Token="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
# Sometimes cloudflare / google doesn't pick new dns records fast enough.
# You can add --dnssleep XX to params as workaround.
######## Public functions #####################
#Usage: dns_myapi_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
@@ -13,97 +16,106 @@ 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" || return 1
_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"
_PDD_credentials || return 1
_PDD_get_domain || return 1
_debug "Found suitable domain: $domain"
_PDD_get_record_ids || return 1
_debug "Record_ids: $record_ids"
if [ -n "$record_ids" ]; then
_info "All existing $subdomain records from $domain will be removed at the very end."
fi
data="domain=${domain}&type=TXT&subdomain=${subdomain}&ttl=300&content=${txtvalue}"
uri="https://pddimp.yandex.ru/api2/admin/dns/add"
result="$(_post "${data}" "${uri}" | _normalizeJson)"
_debug "Result: $result"
if ! _contains "$result" '"success":"ok"'; then
if _contains "$result" '"success":"error"' && _contains "$result" '"error":"record_exists"'; then
_info "Record already exists."
else
_err "Can't add $subdomain to $domain."
return 1
fi
fi
}
#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"
_PDD_get_domain "$fulldomain" || return 1
_debug "Found suitable domain in pdd: $curDomain"
_debug "Found suitable domain: $domain"
record_id=$(pdd_get_record_id "${fulldomain}")
_debug "Result: $record_id"
_PDD_get_record_ids "${domain}" "${subdomain}" || return 1
_debug "Record_ids: $record_ids"
for rec_i in $record_id; do
curUri="https://pddimp.yandex.ru/api2/admin/dns/del"
curData="domain=${curDomain}&record_id=${rec_i}"
curResult="$(_post "${curData}" "${curUri}")"
_debug "Result: $curResult"
for record_id in $record_ids; do
data="domain=${domain}&record_id=${record_id}"
uri="https://pddimp.yandex.ru/api2/admin/dns/del"
result="$(_post "${data}" "${uri}" | _normalizeJson)"
_debug "Result: $result"
if ! _contains "$result" '"success":"ok"'; then
_info "Can't remove $subdomain from $domain."
fi
done
}
#################### 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)"
_debug2 "res1" "$res1"
__found="$(echo "$res1" | sed -n -e 's#.* "found": \([^,]*\),.*#\1#p')"
_debug "found: $__found results on page"
if [ "0$__found" -lt 20 ]; then
_debug "last page: $__page"
__last=1
subdomain_start=1
while true; do
domain_start=$(_math $subdomain_start + 1)
domain=$(echo "$fulldomain" | cut -d . -f "$domain_start"-)
subdomain=$(echo "$fulldomain" | cut -d . -f -"$subdomain_start")
_debug "Checking domain $domain"
if [ -z "$domain" ]; then
return 1
fi
__all_domains="$__all_domains $(echo "$res1" | tr "," "\n" | grep '"name"' | cut -d: -f2 | sed -e 's@"@@g')"
uri="https://pddimp.yandex.ru/api2/admin/dns/list?domain=$domain"
result="$(_get "${uri}" | _normalizeJson)"
_debug "Result: $result"
__page=$(_math $__page + 1)
if _contains "$result" '"success":"ok"'; then
return 0
fi
subdomain_start=$(_math $subdomain_start + 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"
_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
export _H1="PddToken: $PDD_Token"
}
pdd_get_record_id() {
fulldomain="${1}"
_PDD_get_record_ids() {
_debug "Check existing records for $subdomain"
_PDD_get_domain "$fulldomain"
_debug "Found suitable domain in pdd: $curDomain"
uri="https://pddimp.yandex.ru/api2/admin/dns/list?domain=${domain}"
result="$(_get "${uri}" | _normalizeJson)"
_debug "Result: $result"
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'
if ! _contains "$result" '"success":"ok"'; then
return 1
fi
record_ids=$(echo "$result" | _egrep_o "{[^{]*\"subdomain\":\"${subdomain}\"[^}]*}" | sed -n -e 's#.*"record_id": \([0-9]*\).*#\1#p')
}

64
notify/cqhttp.sh Normal file
View File

@@ -0,0 +1,64 @@
#!/usr/bin/env sh
#Support for CQHTTP api. Push notification on CoolQ
#CQHTTP_TOKEN="" Recommended to be not empty, QQ application token
#CQHTTP_USER="" Required, QQ receiver ID
#CQHTTP_APIROOT="" Required, CQHTTP Server URL (without slash suffix)
#CQHTTP_CUSTOM_MSGHEAD="" Optional, custom message header
CQHTTP_APIPATH="/send_private_msg"
cqhttp_send() {
_subject="$1"
_content="$2"
_statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped
_debug "_statusCode" "$_statusCode"
CQHTTP_TOKEN="${CQHTTP_TOKEN:-$(_readaccountconf_mutable CQHTTP_TOKEN)}"
if [ -z "$CQHTTP_TOKEN" ]; then
CQHTTP_TOKEN=""
_info "You didn't specify a CQHTTP application token yet, which is unsafe. Assuming it to be empty."
else
_saveaccountconf_mutable CQHTTP_TOKEN "$CQHTTP_TOKEN"
fi
CQHTTP_USER="${CQHTTP_USER:-$(_readaccountconf_mutable CQHTTP_USER)}"
if [ -z "$CQHTTP_USER" ]; then
CQHTTP_USER=""
_err "You didn't specify a QQ user yet."
return 1
fi
_saveaccountconf_mutable CQHTTP_USER "$CQHTTP_USER"
CQHTTP_APIROOT="${CQHTTP_APIROOT:-$(_readaccountconf_mutable CQHTTP_APIROOT)}"
if [ -z "$CQHTTP_APIROOT" ]; then
CQHTTP_APIROOT=""
_err "You didn't specify the API root yet."
return 1
fi
_saveaccountconf_mutable CQHTTP_APIROOT "$CQHTTP_APIROOT"
CQHTTP_CUSTOM_MSGHEAD="${CQHTTP_CUSTOM_MSGHEAD:-$(_readaccountconf_mutable CQHTTP_CUSTOM_MSGHEAD)}"
if [ -z "$CQHTTP_CUSTOM_MSGHEAD" ]; then
CQHTTP_CUSTOM_MSGHEAD="A message from acme.sh:"
else
_saveaccountconf_mutable CQHTTP_CUSTOM_MSGHEAD "$CQHTTP_CUSTOM_MSGHEAD"
fi
_access_token="$(printf "%s" "$CQHTTP_TOKEN" | _url_encode)"
_user_id="$(printf "%s" "$CQHTTP_USER" | _url_encode)"
_message="$(printf "$CQHTTP_CUSTOM_MSGHEAD %s\\n%s" "$_subject" "$_content" | _url_encode)"
_finalUrl="$CQHTTP_APIROOT$CQHTTP_APIPATH?access_token=$_access_token&user_id=$_user_id&message=$_message"
response="$(_get "$_finalUrl")"
if [ "$?" = "0" ] && _contains "$response" "\"retcode\":0,\"status\":\"ok\""; then
_info "QQ send success."
return 0
fi
_err "QQ send error."
_debug "URL" "$_finalUrl"
_debug "Response" "$response"
return 1
}

View File

@@ -6,6 +6,7 @@
#MAIL_FROM="yyyy@gmail.com"
#MAIL_TO="yyyy@gmail.com"
#MAIL_NOVALIDATE=""
#MAIL_MSMTP_ACCOUNT=""
mail_send() {
_subject="$1"
@@ -76,18 +77,17 @@ mail_send() {
}
_mail_bin() {
if [ -n "$MAIL_BIN" ]; then
_MAIL_BIN="$MAIL_BIN"
elif _exists "sendmail"; then
_MAIL_BIN="sendmail"
elif _exists "ssmtp"; then
_MAIL_BIN="ssmtp"
elif _exists "mutt"; then
_MAIL_BIN="mutt"
elif _exists "mail"; then
_MAIL_BIN="mail"
else
_err "Please install sendmail, ssmtp, mutt or mail first."
_MAIL_BIN=""
for b in "$MAIL_BIN" sendmail ssmtp mutt mail msmtp; do
if _exists "$b"; then
_MAIL_BIN="$b"
break
fi
done
if [ -z "$_MAIL_BIN" ]; then
_err "Please install sendmail, ssmtp, mutt, mail or msmtp first."
return 1
fi
@@ -95,39 +95,44 @@ _mail_bin() {
}
_mail_cmnd() {
_MAIL_ARGS=""
case $(basename "$_MAIL_BIN") in
sendmail)
if [ -n "$MAIL_FROM" ]; then
echo "'$_MAIL_BIN' -f '$MAIL_FROM' '$MAIL_TO'"
else
echo "'$_MAIL_BIN' '$MAIL_TO'"
fi
;;
ssmtp)
echo "'$_MAIL_BIN' '$MAIL_TO'"
;;
mutt | mail)
echo "'$_MAIL_BIN' -s '$_subject' '$MAIL_TO'"
;;
*)
_err "Command $MAIL_BIN is not supported, use sendmail, ssmtp, mutt or mail."
return 1
;;
sendmail)
if [ -n "$MAIL_FROM" ]; then
_MAIL_ARGS="-f '$MAIL_FROM'"
fi
;;
mutt | mail)
_MAIL_ARGS="-s '$_subject'"
;;
msmtp)
if [ -n "$MAIL_FROM" ]; then
_MAIL_ARGS="-f '$MAIL_FROM'"
fi
if [ -n "$MAIL_MSMTP_ACCOUNT" ]; then
_MAIL_ARGS="$_MAIL_ARGS -a '$MAIL_MSMTP_ACCOUNT'"
fi
;;
*) ;;
esac
echo "'$_MAIL_BIN' $_MAIL_ARGS '$MAIL_TO'"
}
_mail_body() {
case $(basename "$_MAIL_BIN") in
sendmail | ssmtp)
if [ -n "$MAIL_FROM" ]; then
echo "From: $MAIL_FROM"
fi
sendmail | ssmtp | msmtp)
if [ -n "$MAIL_FROM" ]; then
echo "From: $MAIL_FROM"
fi
echo "To: $MAIL_TO"
echo "Subject: $subject"
echo "Content-Type: $contenttype"
echo
;;
echo "To: $MAIL_TO"
echo "Subject: $subject"
echo "Content-Type: $contenttype"
echo
;;
esac
echo "$_content"

86
notify/teams.sh Normal file
View File

@@ -0,0 +1,86 @@
#!/usr/bin/env sh
#Support Microsoft Teams webhooks
#TEAMS_WEBHOOK_URL=""
#TEAMS_THEME_COLOR=""
#TEAMS_SUCCESS_COLOR=""
#TEAMS_ERROR_COLOR=""
#TEAMS_SKIP_COLOR=""
teams_send() {
_subject="$1"
_content="$2"
_statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped
_debug "_statusCode" "$_statusCode"
_color_success="2cbe4e" # green
_color_danger="cb2431" # red
_color_muted="586069" # gray
TEAMS_WEBHOOK_URL="${TEAMS_WEBHOOK_URL:-$(_readaccountconf_mutable TEAMS_WEBHOOK_URL)}"
if [ -z "$TEAMS_WEBHOOK_URL" ]; then
TEAMS_WEBHOOK_URL=""
_err "You didn't specify a Microsoft Teams webhook url TEAMS_WEBHOOK_URL yet."
return 1
fi
_saveaccountconf_mutable TEAMS_WEBHOOK_URL "$TEAMS_WEBHOOK_URL"
TEAMS_THEME_COLOR="${TEAMS_THEME_COLOR:-$(_readaccountconf_mutable TEAMS_THEME_COLOR)}"
if [ -n "$TEAMS_THEME_COLOR" ]; then
_saveaccountconf_mutable TEAMS_THEME_COLOR "$TEAMS_THEME_COLOR"
fi
TEAMS_SUCCESS_COLOR="${TEAMS_SUCCESS_COLOR:-$(_readaccountconf_mutable TEAMS_SUCCESS_COLOR)}"
if [ -n "$TEAMS_SUCCESS_COLOR" ]; then
_saveaccountconf_mutable TEAMS_SUCCESS_COLOR "$TEAMS_SUCCESS_COLOR"
fi
TEAMS_ERROR_COLOR="${TEAMS_ERROR_COLOR:-$(_readaccountconf_mutable TEAMS_ERROR_COLOR)}"
if [ -n "$TEAMS_ERROR_COLOR" ]; then
_saveaccountconf_mutable TEAMS_ERROR_COLOR "$TEAMS_ERROR_COLOR"
fi
TEAMS_SKIP_COLOR="${TEAMS_SKIP_COLOR:-$(_readaccountconf_mutable TEAMS_SKIP_COLOR)}"
if [ -n "$TEAMS_SKIP_COLOR" ]; then
_saveaccountconf_mutable TEAMS_SKIP_COLOR "$TEAMS_SKIP_COLOR"
fi
export _H1="Content-Type: application/json"
_subject=$(echo "$_subject" | _json_encode)
_content=$(echo "$_content" | _json_encode)
case "$_statusCode" in
0)
_color="${TEAMS_SUCCESS_COLOR:-$_color_success}"
;;
1)
_color="${TEAMS_ERROR_COLOR:-$_color_danger}"
;;
2)
_color="${TEAMS_SKIP_COLOR:-$_color_muted}"
;;
esac
_color=$(echo "$_color" | tr -cd 'a-fA-F0-9')
if [ -z "$_color" ]; then
_color=$(echo "${TEAMS_THEME_COLOR:-$_color_muted}" | tr -cd 'a-fA-F0-9')
fi
_data="{\"title\": \"$_subject\","
if [ -n "$_color" ]; then
_data="$_data\"themeColor\": \"$_color\", "
fi
_data="$_data\"text\": \"$_content\"}"
if response=$(_post "$_data" "$TEAMS_WEBHOOK_URL"); then
if ! _contains "$response" error; then
_info "teams send success."
return 0
fi
fi
_err "teams send error."
_err "$response"
return 1
}

View File

@@ -71,13 +71,13 @@ _xmpp_bin() {
_xmpp_cmnd() {
case $(basename "$_XMPP_BIN") in
sendxmpp)
echo "'$_XMPP_BIN' '$XMPP_TO' $XMPP_BIN_ARGS"
;;
*)
_err "Command $XMPP_BIN is not supported, use sendxmpp."
return 1
;;
sendxmpp)
echo "'$_XMPP_BIN' '$XMPP_TO' $XMPP_BIN_ARGS"
;;
*)
_err "Command $XMPP_BIN is not supported, use sendxmpp."
return 1
;;
esac
}