Compare commits

...
479 Commits
Author SHA1 Message Date
neil 6887805402 Merge pull request #4067 from acmesh-official/dev
sync
2022-05-04 18:36:45 +08:00
neil 7f9074adbf fix format 2022-05-03 21:35:26 +08:00
neil 64847afc3f save the default key length 2022-05-03 21:19:29 +08:00
neil 641f6977a9 Merge pull request #4065 from acmesh-official/dev
sync
2022-05-03 18:38:45 +08:00
neil 84c2b0c3d7 Merge pull request #4063 from nicolaspn/OVH_DNS_refresh_after_delete_txt_record
Ovh dns refresh after delete txt record
2022-05-02 23:34:14 +08:00
nicolaspn 24ce7c1991 Add call dns OVH API for refresh domain after delete TXT record 2022-05-02 16:16:56 +02:00
neil 8be3465f94 Merge pull request #4061 from acmesh-official/dev
Dev
2022-04-30 22:47:57 +08:00
neil 8ba7d02fdb Merge pull request #4059 from NerLOR/master
dns_world4you: fix _parse_paket_nr
2022-04-29 14:48:31 +08:00
neil ef8a199a5a Merge pull request #4057 from mrakopes/master
issue 3007 - fix base64 decoding logic for single- and multi-line encoded string
2022-04-29 09:25:39 +08:00
Lorenz Stechauner db83643c1e dns_world4you: fix _parse_paket_nr
Signed-off-by: Lorenz Stechauner <lorenz.stechauner@necronda.net>
2022-04-28 20:49:55 +02:00
mrakopes 9b6f775276 fix base64 decoding logic for single- ane multi-line encoded string 2022-04-28 13:25:22 +02:00
neilpang 69040dd668 fix format 2022-04-28 18:09:26 +08:00
neilpang 14b5914233 fix renew bug 2022-04-28 18:06:07 +08:00
neil a0eabd2298 Merge pull request #4049 from Aarup/dev
Removed GratisDNS api
2022-04-25 16:10:39 +08:00
Jakob Aarup Skov 9b27298d54 Removed GratisDNS api 2022-04-25 09:43:38 +02:00
neil 3075b4515a Merge pull request #4045 from axelhahn/4044-use-challenge-alias-false
handle challenge-alias "false"
2022-04-21 16:35:29 +08:00
neil 39bc417706 Update acme.sh 2022-04-21 07:02:53 +08:00
neil e11e32cd52 Merge pull request #4035 from ccope-netgate/master
LoopiaAPI error handling isn't compatible with FreeBSD
2022-04-21 06:58:44 +08:00
Hahn Axel (hahn) 019a7bd66b handle challenge-alias "false" 2022-04-20 16:03:36 +02:00
neil 4d89ce5d50 read csr with empty subject
https://github.com/acmesh-official/acme.sh/issues/4024
2022-04-20 09:14:53 +08:00
Sing Yu Chan c31027b284 use sleep infinity instead sleep 1 2022-04-20 09:04:13 +08:00
neil f17ec7a4f5 Merge pull request #4037 from ahwayakchih/master
Update dns_mydevil.sh
2022-04-20 09:01:29 +08:00
neil deec6aab1a Merge pull request #4039 from DerVerruckteFuchs/1984-update-URL
1984 update url
2022-04-20 09:00:14 +08:00
Bruce Lam 3e8d9a1987 added: ipv6 identifier support 2022-04-20 08:23:22 +08:00
DerVerruckteFuchs 5e465a298f Update 1984 Hosting's URL 2022-04-15 23:04:10 -04:00
Marcin Konicki 515c9e7811 Fix DNS handling for MyDevil.net
MyDevil updated their tool to require y|n confirmation when deleting record.
2022-04-15 10:38:45 +02:00
Christopher Cope 03c8309703 Fix dns_loopia on FreeBSD 2022-04-13 15:41:44 -04:00
neilpang 2c28d6b10c fix for renew server 2022-04-13 20:20:28 +08:00
neil df79443ed8 Merge pull request #3997 from tumarov/fornex_com_support
fornex.com API support
2022-04-12 11:01:53 +08:00
neil 2b891f7f1d Update dns_fornex.sh 2022-04-12 10:11:05 +08:00
neil e4ed0b1884 Merge pull request #4029 from quthla/patch-1
Store Mailcow deploy parameters
2022-04-12 10:06:35 +08:00
neil c8c1c09189 Merge pull request #4032 from acmesh-official/dev
sync
2022-04-12 10:05:22 +08:00
quthla 08ae8cc3cb Fix 2022-04-11 11:39:21 +02:00
quthla 201673ca8a Store Mailcow deploy parameters 2022-04-11 00:29:55 +02:00
Bruce Lam 29e23ac9ce Due to down of cloudxns.net, remove dns_cx.sh 2022-04-10 19:57:25 +08:00
neilpang 00483e8cdd exclude zerossl tests in the CI
It's not stable
2022-04-10 19:42:49 +08:00
neil 83da01a2e1 Merge pull request #4027 from acmesh-official/dev
sync
2022-04-10 14:49:09 +08:00
neil 7cd6ff054b add 2022-04-10 14:48:10 +08:00
neilpang 6be2bb2289 Update acme.sh
revert only when there is no `--server` specified.
2022-04-08 22:28:21 +08:00
neilpang 439defca42 switch from staging api to production api
https://github.com/acmesh-official/acme.sh/issues/2401
2022-04-08 22:15:26 +08:00
neil 8a85bb2989 Merge pull request #4017 from exogee-technology/dev
Fix / Netlify API should only match exact domain matches.
2022-04-08 21:03:54 +08:00
neil 5e7519183d Merge pull request #4020 from sjau/dns_ispconfig_typo
dns_ispconfig: add missing brackets
2022-04-07 17:29:25 +08:00
hyper_ch 40e7eca1ee dns_ispconfig: adding missing brackets 2022-04-07 11:07:06 +02:00
Kevin Brown 481f02de88 Also check for the closing quote so that only exact domain matches are found. 2022-04-06 14:29:25 +10:00
neilpang 6a90856f0e don't renew cert if valid-to is set to an absolute date
don't renew cert if valid-to is set to an absolute date
2022-04-05 17:05:33 +08:00
neil dcbbee8adb Merge pull request #4012 from acmesh-official/dev
Support "NotBefore" and NotAfter
2022-04-03 22:01:00 +08:00
neilpang 225adcc836 fix renewal for validto
fix renewal for validto
2022-04-03 21:58:41 +08:00
neilpang 0f607413d0 fix for solaris time format 2022-04-03 20:05:30 +08:00
neilpang 922553032b typo 2022-04-02 09:35:17 +08:00
neilpang b49999721c Update acme.sh 2022-04-01 21:58:29 +08:00
neilpang de4c4eedd8 Support NotBefore and NotAfter
Add `--valid-from` and `--valid-to`:
https://github.com/acmesh-official/acme.sh/wiki/Validity
2022-04-01 21:22:42 +08:00
neilpang bcc984fc09 minor 2022-03-31 09:46:42 +08:00
neilpang d53262fab6 fix update account
fix https://github.com/acmesh-official/acme.sh/issues/4009
2022-03-31 09:35:32 +08:00
neilpang 532e44bcea normalize domains
fix https://github.com/acmesh-official/acme.sh/issues/4005
2022-03-30 23:37:38 +08:00
neilpang 3fb67629c1 Update README.md 2022-03-30 23:06:07 +08:00
neil 6145465823 Merge pull request #4006 from acmesh-official/dev
sync
2022-03-30 23:03:44 +08:00
neilpang fb5091a388 support Google ACME server
see: https://github.com/acmesh-official/acme.sh/wiki/Server
2022-03-30 22:47:12 +08:00
neilpang 0d05f9ba80 Update acme.sh
fix https://github.com/acmesh-official/acme.sh/issues/4001
2022-03-27 12:08:24 +08:00
neil a300df0020 Update dns_fornex.sh 2022-03-25 15:48:17 +08:00
neil a50158cbeb Merge pull request #3982 from waldner/master
Geoscaling: read credentials when removing records too
2022-03-24 15:15:58 +08:00
Timur Umarov 7278fd25e5 Added fornex.com api 2022-03-23 17:46:38 +03:00
neil 6fb8c0ec4c Merge pull request #3989 from abiessmann/deploy_routeros_handle_remote_errors
deploy/routeros: handle errors
2022-03-20 13:30:58 +08:00
neil 07cedc55e2 Merge pull request #3978 from nikolajbrinch/dev
Fixes Simply.com to use REST API version 2 with Basic Auth
2022-03-20 13:19:13 +08:00
neil ae3cc81f03 Merge pull request #2924 from ianepperson/master
Add Discord notification
2022-03-20 12:43:43 +08:00
neil 97a45e3b02 Update discord.sh 2022-03-20 12:43:23 +08:00
neil 451b290b79 Update discord.sh 2022-03-20 12:42:35 +08:00
neil 499ea07934 Merge pull request #3993 from imgrant/deploy-truenas-s3-feature
feat: Configure TrueNAS S3 certificate
2022-03-20 12:34:58 +08:00
Ian Grant afa06267a2 style: Neaten up some of the info & error messages, fix some typos 2022-03-19 20:39:48 +00:00
Ian Grant d4a6d9c076 fix: Adjust the sed extraction of certificate ID from JSON response
Prior to this, an error in the regex didn't match. Resolves #3992 (TrueNAS deploy hook fails to set certificate for FTP or WebDAV)
2022-03-19 20:38:47 +00:00
Ian Grant c3f6112443 feat: Configure certificate for TrueNAS S3 service (MinIO) 2022-03-19 20:36:11 +00:00
Andreas Bießmann 3411b736dd deploy/routeros: add error handling for scp
In order to stop processing on failure to copy certificate
to remote side, fail on error of scp command.

Signed-off-by: Andreas Bießmann <andreas@biessmann.org>
2022-03-18 09:10:12 +01:00
Andreas Bießmann c603b9c40b deploy/routeros: add error handling for ssh
In order to detect errorneous scripts on remote side, catch return code
and handle it respectively.

Signed-off-by: Andreas Bießmann <andreas@biessmann.org>
Reviewed-by: Ross Shen @sjtuross
2022-03-18 09:07:59 +01:00
neil 1e2c5d038f Merge pull request #3986 from abiessmann/fix_depoly_routeros
deploy/routeros.sh: fix routeros script
2022-03-17 21:25:59 +08:00
Andreas Bießmann 9d6d96adf3 deploy/routeros.sh: fix routeros script
Commit c46ceb06b4 introduced an error in
routeros script.

Fix it!

Signed-off-by: Andreas Bießmann <andreas@biessmann.org>
2022-03-17 12:24:42 +01:00
waldner 8d574ecb34 Geoscaling: get creds for removal too 2022-03-15 18:56:54 +01:00
neil 9ebb2ac2e4 Merge pull request #3980 from acmesh-official/dev
sync
2022-03-14 23:02:08 +08:00
neil 7b935eec5d Merge pull request #3979 from dislazy/dev
fix(notify):remove nofity,move weixin_work.sh to notify
2022-03-11 13:56:53 +08:00
bosong b209f66654 fix(notify):remove nofity,move weixin_work.sh to notify 2022-03-11 13:41:12 +08:00
neil b98b4951b4 Merge pull request #3669 from youuy/master
Add Weixin Work notify hook
2022-03-11 12:21:55 +08:00
Nikolaj Brinch Jørgensen 227d62a5dc Fixes Simply.com to use REST API version 2 with Basic Auth 2022-03-10 11:13:38 +01:00
neil 7fae5553a8 Merge pull request #3977 from gabbe/Encode_password
Accept some special characters in password and some error handling
2022-03-10 09:10:17 +08:00
Gabriel Thörnblad 6ead019873 Accept some special characters in password and added a little bit better error handling 2022-03-09 17:12:09 +01:00
neil e58b00d9a2 Merge pull request #3964 from gabbe/Loopia_API_is_updated
Update dns_loopia.sh
2022-03-07 21:52:03 +08:00
Gabriel Thörnblad b75e90f8c9 Double quote variables (shellcheck suggestions) 2022-03-07 10:28:09 +01:00
Gabriel Thörnblad e82f3439c3 Trigger CI 2022-03-07 10:13:45 +01:00
neil 0bc8e3bee5 Merge pull request #3965 from waldner/master
geoscaling DNS API
2022-03-07 09:08:01 +08:00
waldner 13f80acb2d geoscaling DNS API 2022-03-05 19:34:36 +01:00
neil 8fe813acff Merge pull request #3932 from peterlh/master
Added curanet dns support
2022-03-05 18:58:14 +08:00
Gabriel Thörnblad 0ed4fc6a12 Update dns_loopia.sh
Loopia API is now less tolerant so we need another <value> tag surrounding the <struct>
2022-03-04 13:38:05 +01:00
neil e88442cb46 Merge pull request #3947 from abiessmann/deploy_routeros_fixes
deploy/routeros.sh fixes
2022-02-22 21:52:36 +08:00
neil 930609e875 Merge pull request #3948 from richard-9000/richard-9000-patch-1
dns_opnsense.sh - Fixed the domain parse regex
2022-02-22 21:41:22 +08:00
richard-9000 8752d08ce9 dns_opnsense.sh - Fixed the domain parse regex
Extended the regex to skip the new transferkey and hmac sections of opnsense bind.
2022-02-19 10:52:24 -08:00
Andreas Bießmann c46ceb06b4 deploy/routeros.sh: change DEPLOY_SCRIPT_CMD
This set the owner of script to ssh user, have the comment line in script
as real comment and removes policy since this is set from current user,
at least for RouterOS 7.x.

Signed-off-by: Andreas Bießmann <andreas@biessmann.org>
2022-02-19 14:13:01 +01:00
Andreas Bießmann 92e4ecce3b deploy/routeros.sh: remove all certificates
As the script is applying the fullchain which includes three certificates,
delete all of them before applying updated certificate.

Signed-off-by: Andreas Bießmann <andreas@biessmann.org>
2022-02-19 14:13:01 +01:00
Andreas Bießmann 8a2f673903 deploy/routeros.sh: make ssh/scp configurable
In order to modify ssh/scp commands make them configurable via
environment variables.

Signed-off-by: Andreas Bießmann <andreas@biessmann.org>
2022-02-19 14:12:59 +01:00
peter 9a677534a7 added more debug info when rm recordid is empty 2022-02-13 14:00:14 +01:00
peter af08d67fad rem. ; 2022-02-12 23:41:26 +01:00
peter a2901d61ea check for return values 2022-02-12 23:39:33 +01:00
peter aaae83efec check for return values 2022-02-12 20:18:08 +01:00
neil 7369298638 Merge pull request #3921 from andischerer/master
Added united-domains Reselling DNS API
2022-02-11 21:24:40 +08:00
neil a761bd20fa Merge pull request #3934 from mac-zhou/dev
Add environment variables ROUTER_OS_PORT
2022-02-11 21:13:27 +08:00
neilpang 01ace11293 Update dns_ispconfig.sh
fix https://github.com/acmesh-official/acme.sh/issues/3895#issuecomment-1035409954
2022-02-11 21:11:04 +08:00
Mac_Zhou 205e95a246 Add environment variables ROUTER_OS_PORT 2022-02-10 11:29:09 +08:00
neil 2c2a43e1ec Update dns_cf.sh
if CF_Zone_ID is used,  save it to domain conf instead.
2022-02-09 18:08:55 +08:00
peter 0c9a6da623 more specific delete of records 2022-02-08 17:18:48 +01:00
Andreas Scherer 888d91d14a FIX dns_udr api: loop variable 2022-02-08 15:57:19 +01:00
peter 2c0cc87b4c final commit 2022-02-08 13:49:04 +01:00
peter ee0fadf247 shfmt 2022-02-08 13:34:42 +01:00
peter 9fb89d7fd2 shfmt 2022-02-08 13:33:43 +01:00
peter af5c36e4ad shfmt' 2022-02-08 13:32:15 +01:00
peter a5f943e227 removed unused variable 2022-02-08 13:24:31 +01:00
peter f8532ba812 removed unused variable 2022-02-08 13:21:02 +01:00
peter fac4e151cc description 2022-02-08 13:19:22 +01:00
Andreas Scherer f3a0a25380 FIX dns_udr api: ttl, xargs, cleanup 2022-02-08 08:05:48 +01:00
neil 5a237795ea Merge pull request #3928 from johnelliott/missing-oathtool-dep-error
Add err log for missing oathtool in Synology
2022-02-08 14:26:06 +08:00
John Elliott 3a99a77104 Update return statement 2022-02-07 21:55:12 -08:00
John Elliott 5ce8050e46 Update missing oathtool check 2022-02-07 11:58:14 -08:00
John Elliott 5ae3a020bd Add err log for missing oathtool in Synology
Alerts the user that the oathtool is missing and the TOTP can't be
generated.
2022-02-07 11:53:24 -08:00
neilpang af193291fa Update acme.sh
fix https://github.com/acmesh-official/acme.sh/issues/3127#issuecomment-1030742187
2022-02-06 16:17:04 +08:00
neil b39df5cef0 Merge pull request #3906 from NerLOR/master
Adapt dns_world4you to new world4you website behaviour
2022-02-06 09:52:45 +08:00
peter dc61c9e277 description 2022-02-05 22:21:18 +01:00
peter 10a15e1188 nothing 2022-02-05 21:12:36 +01:00
peterlh a2bb6a4f1f changed gettoken to use _post
changed gettoken to use _post instead of curl+jq
2022-02-05 21:07:04 +01:00
peterlh 38a19fa574 created dns_curanet.sh 2022-02-05 20:54:30 +01:00
neilpang 9ec4b59afb start v3.0.3
start v3.0.3
2022-02-05 21:28:07 +08:00
Lorenz Stechauner 20877146df Merge branch 'acmesh-official:master' into master 2022-02-04 20:36:31 +01:00
neil 2a2d556551 Merge pull request #3927 from acmesh-official/dev
sync
2022-02-04 13:53:40 +08:00
neilpang 0f762d98a4 Update Linux.yml
use centos:7
2022-02-04 13:52:23 +08:00
neilpang 36752cb6a8 Update acme.sh
fix zerossl endpoint
2022-02-04 13:49:58 +08:00
Andreas Scherer a7f2d89e3f Added united-domains Reselling DNS API 2022-02-01 14:46:20 +01:00
neil 90b65c6618 fix https://github.com/acmesh-official/acme.sh/issues/3898
https://github.com/acmesh-official/acme.sh/issues/3898
2022-01-27 18:00:44 +08:00
Lorenz Stechauner 190ec0c14c Adapt dns_world4you to new world4you website behaviour 2022-01-24 16:47:47 +01:00
michal 7250a300df add managed identity support for azure dns 2022-01-22 13:22:44 +08:00
neil 34bb00450d Merge pull request #3896 from sjtuross/omv
add remote deploy hook for openmediavault 5
2022-01-21 20:39:07 +08:00
neil 63dadd8983 Merge pull request #3901 from tutugreen/tutugreen-patch-2
Fix dns_huaweicloud subshell return
2022-01-21 20:35:47 +08:00
Ross Shen 67c990e8cf omv deploy hook: add usage comments 2022-01-20 17:46:47 +08:00
Ross Shen 0292e20c86 omv deploy hook: support both local and remote deployment 2022-01-20 17:27:11 +08:00
Yuan Ming 9088c8741a Fix dns_huaweicloud subshell return
Replace pipe read with line count loop, fix useless return in subshell.
2022-01-20 14:01:33 +08:00
neilpang faedea2120 Update dns_ddnss.sh 2022-01-19 22:22:53 +08:00
Vitaly Kireev e1a0f5706d DNS REGRU utf-list to idn (punycode)
service/get_list returns domains in utf. But if utf, then error Error parsing certificate request: x509: SAN dNSName is malformed

early using my patch by IDN_ITEM="$(echo "${ITEM}" | idn)"

Now replacing by IDN_ITEM="$(_idn "${ITEM}")"
2022-01-19 21:59:48 +08:00
Ross Shen a78a4e6716 omv deploy hook: shellcheck disable=SC2029 2022-01-19 21:42:17 +08:00
Ross Shen 6bbf927f57 omv deploy hook: separate DEPLOY_OMV_WEBUI_ADMIN and DEPLOY_OMV_SSH_USER 2022-01-19 21:13:02 +08:00
neilpang 4c32bc8e22 Merge branch 'dev' 2022-01-19 20:55:24 +08:00
Ross Shen df671a77f6 routeros deploy hook: store the env vars within the domainconf
related to #2344 and #2413
2022-01-19 20:46:29 +08:00
Ross Shen dca9def42c add remote deploy hook for openmediavault 5
based on #3757
2022-01-19 12:36:54 +08:00
Ross Shen edee7ea284 routeros deploy hook: store the env vars within the domainconf
related to #2344 and #2413
2022-01-16 20:46:09 +08:00
neil 658d09ed84 Merge pull request #3396 from F-Plass/master
deploy scipt for TrueNAS Server using REST API
2022-01-16 08:17:49 +08:00
neil c41de8f270 Merge pull request #3891 from tutugreen/dev
dns_huaweicloud.sh minor bug fixes
2022-01-15 19:38:22 +08:00
Yuan Ming 9d2ee2127d dns_huaweicloud debug info adjust
_secure_debug for sensitive token.
2022-01-15 19:23:30 +08:00
Yuan Ming e49ece8793 dns_huaweicloud.sh minor bug fixes
1. Match zone name in response in case multiple items return.
2. Use string '"id"' (single quotation marks added) to check if zone/record exist in _get_zoneid() & _get_recordset_id(). Fix domain can't contain string "id".

(Sensitive _debug Access Token Commented out, For CICD Run)
2022-01-14 22:10:26 +08:00
neil 188274277a fix https://github.com/acmesh-official/acme.sh/issues/3883 2022-01-11 17:16:51 +08:00
neil c0cb3945f1 Merge pull request #3884 from acmesh-official/dev
sync
2022-01-11 17:09:59 +08:00
neil e07795e8f0 fix https://github.com/acmesh-official/acme.sh/issues/3883 2022-01-11 16:56:19 +08:00
I Komang Suryadana bda454fe9c Remove cloud domain record with cloud master zone. (#3507) 2022-01-11 15:25:10 +08:00
neil 856e77053e Merge branch '3870' into dev 2022-01-10 16:29:44 +08:00
Felix Matouschek 2ce145f359 Refactoring amcedns api (second try) (#3231) 2022-01-09 11:11:00 +08:00
Sergey Pashinin 7e7291ace9 Support Vault KV v2 (#3502) 2022-01-09 11:01:38 +08:00
Victor R. Santos 61c853a3c1 Add Gotify notification (#3759) 2022-01-09 10:39:28 +08:00
Bodenhaltung 4346139d65 Add dnsHome.de API (#3823)
Add dnsHome.de API
2022-01-09 10:32:22 +08:00
neil 1476f83ba7 Merge pull request #3879 from acmesh-official/dev
sync
2022-01-08 21:22:18 +08:00
neil c959d64099 Merge pull request #3807 from dacrystal/topic/synology_dsm-otp_code
Add SYNO_TOTP_SECRET for user with two-factor authentication enabled
2022-01-08 20:03:13 +08:00
neil e67d26caeb fix https://github.com/acmesh-official/acme.sh/issues/3845#issuecomment-999367478 2022-01-08 19:58:49 +08:00
neil 86c3fa0df0 remove retry for get and post 2022-01-08 19:51:04 +08:00
neil 75ae57e194 report false 2022-01-08 19:19:51 +08:00
neil d42feae0af fix ecdsa name for stepca 2022-01-07 23:44:19 +08:00
neil 45971b8083 add ip cert test for stepCA 2022-01-07 23:43:08 +08:00
neil 8e9bbd1bb3 fix CI 2022-01-07 23:35:18 +08:00
neil ec10a3eab4 fix CI 2022-01-07 23:14:46 +08:00
neil 49deb4af24 fix CI 2022-01-07 23:09:56 +08:00
neil 10f171b6e4 fix ci 2022-01-07 23:05:49 +08:00
neil 735db1a12b fix ci 2022-01-07 23:00:34 +08:00
neil b2f4cc2dc5 add Step-ca to CI
https://github.com/acmesh-official/acme.sh/issues/3871
2022-01-07 22:58:42 +08:00
neil d43b587d17 fix https://github.com/acmesh-official/acme.sh/issues/3870 2022-01-07 22:06:18 +08:00
neil 6b07a955f2 Merge pull request #3877 from jvandborg/master
Cannot wait for PR #3673 to be completed
2022-01-07 19:09:44 +08:00
Jacob Vandborg e23c02575d Removed DNS sleep
Users should use command line parameter --dnssleep instead
2022-01-07 08:10:31 +01:00
neil b1bf634136 Merge pull request #3876 from fraenki/fix_fritz
deploy/fritzbox: allow hook to be used with multiple fritzboxes
2022-01-07 09:48:54 +08:00
jvandborg 459faf4dfb Format to comply with style guide 2022-01-06 22:03:39 +01:00
Jacob Vandborg 8cdceb83b2 Cannot wait for PR #3673 to be completed
PR #3673 Fix simply.com API seems abandoned by maintainer and I need this fixed asap

Changes implemented
* Normalize JSON and fix not handling return code correctly
* Add some information to comments
* Fix trailing slash on URIs
* Add 60 second sleep for zone to be written
* Fix parsing record_data and record_type
2022-01-06 19:21:05 +01:00
Frank Wall 6aa1ec0802 deploy/fritzbox: allow hook to be used with multiple fritzboxes
Previously the deploy hook config was stored in the account config.
This seems odd and adds unnecessary limitations to the hook.
Now we're using the correct _*deployconf() functions to read and
write the deploy hook config.
2022-01-06 16:20:43 +01:00
Joel Pearson 0727f7054b Allow optional "NEW" in CSR header and footer
When generating a CSR in Windows it seems to create a CSR header that looks like "-----BEGIN NEW CERTIFICATE REQUEST-----", but the addition of "NEW" breaks the parsing of the CSR. Making "NEW " optional fixes the problem.

Apparently certbot is tolerant of both forms, see: https://community.letsencrypt.org/t/error-parsing-certificate-request-resolved/40039/6 for more information.
2022-01-06 17:41:42 +08:00
neilpang 37cc611e3f fix gentoo image 2022-01-06 17:41:42 +08:00
neilpang c39e6c4423 add --info command to show the global configs or domain configs.
https://github.com/acmesh-official/acme.sh/issues/2444
2022-01-06 17:41:42 +08:00
neilpang 1566656af3 fix https://github.com/acmesh-official/acme.sh/issues/3869 2022-01-06 17:41:42 +08:00
neilpang 737eba57bd send notifications for renew command
https://github.com/acmesh-official/acme.sh/issues/3869#issuecomment-1003546762
2022-01-06 17:41:41 +08:00
Viktor G d32cedd7dc DNS-ISPConfig ISPC_Api_Insecure argument check fix 2022-01-06 17:41:41 +08:00
racitup 2b6aa26703 fix: Neilpang review 2022-01-06 17:41:41 +08:00
racitup 95f1336060 fix: token request body quoting 2022-01-06 17:41:41 +08:00
racitup f46ee93597 fix: github switch 2022-01-06 17:41:41 +08:00
racitup 56d799f449 fix: debugging 2022-01-06 17:41:41 +08:00
racitup 6251652c93 fix: correct return value 2022-01-06 17:41:41 +08:00
racitup 6a2c9a0dc1 fix: floating token for github 2022-01-06 17:41:41 +08:00
racitup 4dd709b543 feat: Mythic Beasts DNS API script 2022-01-06 17:41:41 +08:00
wacki4 aa9f5b8c4a Update dns_opnsense.sh
Correction when having many zones.
2022-01-06 17:41:41 +08:00
wacki4 f485f3fdb5 Update dns_opnsense.sh
Update for opnsense regards to error in #3735
2022-01-06 17:41:41 +08:00
neilpang c6a0ec64cb upgrade solaris vm 2022-01-06 17:41:41 +08:00
Christian Burmeister e0b179e5f3 Update Dockerfile - alpine:3.12 -> alpine:3.15
The support for the base image alpine:3.12 will expire in 4 months (https://endoflife.date/alpine), so it would make sense to upgrade to the current version alpine:3.15. 
I was able to create the acme.sh image with the new alpine:3.15 version without errors and also create and deploy a certificate, but further testing would be useful.
2022-01-06 17:41:41 +08:00
Jens Meißner dac7a3d272 [dns_knot] Use key command instead of command line argument to transmit dns key data. 2022-01-06 17:41:41 +08:00
neilpang beed123fb0 fix tunnel version 2022-01-06 17:41:41 +08:00
neilpang 267e582827 add TEST_DNS_NO_SUBDOMAIN 2022-01-06 17:41:40 +08:00
neilpang 69c02cae76 pass TEST_DNS_NO_SUBDOMAIN 2022-01-06 17:41:40 +08:00
neilpang 4f386663e7 fix for OpenBSD7
https://github.com/acmesh-official/acme.sh/issues/3833
2022-01-06 17:41:40 +08:00
neilpang eaae0547f2 upgrade Solaris 2022-01-06 17:41:40 +08:00
F-Plass b203f2abaa Merge branch 'acmesh-official:master' into master 2021-12-03 17:18:44 +01:00
neil 5490a2f3ba Merge pull request #3837 from acmesh-official/dev
sync
2021-11-30 22:49:43 +08:00
neil ba44235471 Update DNS.yml 2021-11-30 13:10:39 +08:00
neil be556f9e36 Merge pull request #3818 from hguandl/master
Add iOS Bark notify hook
2021-11-21 09:54:55 +08:00
Hao Guan 5e5ba11601 Add iOS Bark notify hook. 2021-11-21 02:39:46 +08:00
neil e384df30fa Merge pull request #3813 from acmesh-official/dev
fix https://github.com/acmesh-official/acme.sh/issues/3806
2021-11-19 13:35:18 +08:00
Nasser Alansari 4635dacf7f Add SYNO_TOTP_SECRET for user with two-factor authentication 2021-11-13 13:01:38 +03:00
neilpang 18e4d270d9 fix https://github.com/acmesh-official/acme.sh/issues/3806 2021-11-13 15:23:32 +08:00
F-Plass 3bcb91f6ae Update truenas.sh
solved the problem of UI-Restart after 12.0-U3
2021-11-11 23:03:00 +01:00
neil 5e574a355d Merge pull request #3800 from acmesh-official/dev
sync
2021-11-10 09:22:45 +08:00
neil 640c7c5fa3 Merge pull request #3798 from Scre13/patch_mail_sh
removed -- at beginning of subject
2021-11-09 11:49:25 +08:00
neil eb6395a62c Update mail.sh 2021-11-09 11:48:58 +08:00
Scre13 2b2845aa07 removed -- at beginning of subject 2021-11-09 04:28:30 +01:00
neil 54d8c66f3e Merge pull request #3797 from Scre13/patch_lf_mime_version
Removed newline at the end of subject, added MIME-Version header
2021-11-09 09:32:03 +08:00
neil 95bbf1b190 Update mail.sh 2021-11-09 09:30:36 +08:00
Scre13 ee2dab51f3 removed newline at the end of subject, added MIME-Version header 2021-11-08 22:13:14 +01:00
neil f63409eed9 fix https://github.com/acmesh-official/acme.sh/issues/1559 2021-11-06 12:27:50 +08:00
neil ad8940ad73 Merge pull request #3796 from acmesh-official/ip
Ip
2021-11-06 12:00:13 +08:00
neil b8bfb5a56c fix format 2021-11-06 11:28:11 +08:00
neil 3f58823430 fix ip cert 2021-11-06 11:26:06 +08:00
neil e488220bfc fix for solaris 2021-11-06 11:16:41 +08:00
neil e6e0771496 fix for ip cert alpn mode 2021-11-06 11:16:40 +08:00
neil fe77d43fa0 fix _deactivate for ip cert 2021-11-06 11:16:40 +08:00
neil 737a7a2db2 add test for ipcert 2021-11-06 11:16:12 +08:00
neil 6ae8d10132 support ip cert: rfc https://tools.ietf.org/html/rfc8738 2021-11-06 11:15:10 +08:00
neil 7d249b6d3b start 3.0.2 2021-11-06 09:52:21 +08:00
neil a532b82771 Merge pull request #3793 from jearton/feature/feishu-notify
Add feishu notification
2021-11-04 09:43:59 +08:00
neil e8756482aa Update feishu.sh 2021-11-04 09:42:30 +08:00
jearton 35d6da785b add support for feishu notification 2021-11-04 00:41:58 +08:00
neilpang dbdcbd4b9e add set-default-chain 2021-11-02 20:37:14 +08:00
neil a2b6f49c5c Merge pull request #2998 from masbicudo/dev
Notify user about a possible problem when using synology_dsm.sh with user that enabled 2fa
2021-11-01 13:42:57 +08:00
Miguel Angelo a31ed4a723 Notify user about a possible problem when using synology_dsm.sh with 2fa enabled user account 2021-11-01 01:40:14 -03:00
neil b2fc84c98e Merge pull request #3787 from acmesh-official/dev
sync
2021-10-31 17:31:35 +08:00
neil 927369b06d Merge pull request #3772 from retoo/bugfix/dns-gcloud-fix-format-change
dns_gcloud: allowrecord-sets list output to be separated by 'semicolon'
2021-10-21 22:33:31 +08:00
Reto Schuettel 401fd37e35 dns_gcloud: allowrecord-sets list output to be separated by 'semicolon'
gcloud dns record-sets list used to separate records by comma, with
version 353.0.0 the tool uses semicolons instead.
2021-10-20 18:18:02 +02:00
neil 759cdf10c5 Merge pull request #3745 from NerLOR/master
Fix Word4You dns plugin to work with current api
2021-10-20 23:39:29 +08:00
Lorenz Stechauner 6e7ce1eec1 dns_world4you: fix for freeBSD sed
Signed-off-by: Lorenz Stechauner <lorenz.stechauner@necronda.net>
2021-10-20 14:29:06 +02:00
Lorenz Stechauner 2a65955e88 Merge branch 'acmesh-official:master' into master 2021-10-18 11:20:15 +02:00
neil 5b0d6a1375 Merge pull request #3756 from acmesh-official/dev
sync
2021-10-13 09:04:06 +08:00
neil 0510da0853 fix test chain root name. 2021-10-13 00:28:14 +08:00
neil 365d22d076 add TEST_PREFERRED_CHAIN 2021-10-13 00:03:12 +08:00
neil 1760169ef9 fix Windows test 2021-10-12 23:43:20 +08:00
neil 32ea224933 update versions 2021-10-12 21:31:06 +08:00
neilpang 38a067e203 fix https://github.com/acmesh-official/acme.sh/issues/3752 2021-10-12 20:55:11 +08:00
neil ab6f1b6df7 Merge pull request #3746 from tuffnatty/patch-1
Don't use global variable as local in recursion context
2021-10-09 21:29:36 +08:00
neil b36802edff Merge pull request #3728 from arnebjarne/dns_cpanel
Support for cPanel DNS
2021-10-09 10:29:27 +08:00
Bjarne Saltbaek 1d2af0f291 force a re-test. 2021-10-08 20:10:46 +02:00
Phil Krylov 40e8c5e2b0 Don't use global variable as local in recursion context
```nginx
include conf.d/*;
include sites-enabled/*;
```
In this situation, after the first recursive `_checkConf` invocation 4 lines below, `$_c_file` does not contain what you expect anymore, and the second lookup checks for `conf.d/sites-enabled/*` which is obviously wrong.
2021-10-08 18:24:21 +02:00
Bjarne Saltbaek e11d0d37ee force a re-test. Le servere fails during test 2021-10-07 20:51:18 +02:00
Bjarne Saltbaek ea4266538a force a re-test 2021-10-07 20:21:51 +02:00
Lorenz Stechauner aa7bf9169f Fix Word4You dns plugin to work with current api
the value for uniqueFormIdTTL is not available or needed anymore.
values for 'aktivPaket' are not needed by the api.

changed endpoint for deletion from `/deleteRecord` to `/dns/record/delete`
2021-10-06 14:06:44 +02:00
Bjarne Saltbaek a95e83ab6e Added txtvalue to dns lookup 2021-10-03 18:45:21 +02:00
Bjarne Saltbaek 86daaf4bf2 Added remove entry debug 2021-10-03 18:37:51 +02:00
Bjarne Saltbaek d5b4f02932 Added proper id lookup with whitespace removed 2021-10-03 18:13:05 +02:00
Bjarne Saltbaek 15deec6c53 Added proper id lookup with missing bracket 2021-10-03 18:11:28 +02:00
Bjarne Saltbaek 17b1875151 Added proper id lookup 2021-10-03 18:08:21 +02:00
Bjarne Saltbaek bfda8f0b8a First jq rework - 12. redo 2021-10-03 17:53:59 +02:00
Bjarne Saltbaek 7bb0ff986b First jq rework - 11. redo 2021-10-03 17:50:57 +02:00
Bjarne Saltbaek f3cfef4021 First jq rework - 10. redo 2021-10-03 17:40:01 +02:00
Bjarne Saltbaek 3184c3c21b First jq rework - 9. redo 2021-10-03 17:10:38 +02:00
Bjarne Saltbaek 9264737985 First jq rework - 8. redo 2021-10-03 17:04:49 +02:00
Bjarne Saltbaek c9b353a689 First jq rework - 8. redo 2021-10-03 17:02:24 +02:00
Bjarne Saltbaek fda6502f33 First jq rework - 7. redo 2021-10-03 17:00:53 +02:00
Bjarne Saltbaek 0fdac82b93 First jq rework - 6. redo 2021-10-03 16:55:44 +02:00
Bjarne Saltbaek 6b3d6d5211 First jq rework - 5. redo 2021-10-03 16:51:02 +02:00
Bjarne Saltbaek cb89ee39f5 Merge branch 'acmesh-official:master' into dns_cpanel 2021-10-03 16:49:38 +02:00
Bjarne Saltbaek be827be742 First jq rework - 4. redo 2021-10-03 16:48:23 +02:00
neil 8fcecd59a0 Merge pull request #3734 from acmesh-official/dev
sync
2021-10-03 22:48:12 +08:00
Bjarne Saltbaek 83b49b23e4 Merge branch 'acmesh-official:master' into dns_cpanel 2021-10-03 16:37:55 +02:00
neil f5ee618986 Merge pull request #3599 from cirow/dev
Pushbullet Webhook notification
2021-10-03 22:34:21 +08:00
Bjarne Saltbaek 8339b88180 First jq rework - docker fails in Github - not my fault... 2021-10-03 16:34:12 +02:00
neil f2958818c8 Update pushbullet.sh 2021-10-03 22:33:41 +08:00
Bjarne Saltbaek 608547c62c First jq rework - 3. redo 2021-10-03 16:32:03 +02:00
neil 20f604948f Update pushbullet.sh 2021-10-03 22:31:56 +08:00
neil f72a4f966d Merge pull request #3664 from shadowlmd/fix-grep-dns-he
Fix grep options processing in dns_he module
2021-10-03 22:25:44 +08:00
Bjarne Saltbaek bd00db4292 First jq rework - redo 2021-10-03 16:25:21 +02:00
Bjarne Saltbaek 68debc474a First jq rework 2021-10-03 16:20:08 +02:00
Bjarne Saltbaek 6a7f993a9a Forced CI 2021-10-03 15:56:26 +02:00
neil ae25931b37 Merge pull request #3733 from acmesh-official/dev
sync
2021-10-03 21:30:46 +08:00
neil 84fe6654cc fix for https://github.com/acmesh-official/acme.sh/issues/3717 2021-10-03 20:59:55 +08:00
Bjarne Saltbaek d2d023cca7 added saving of cPanel_Hostname 2021-10-03 13:35:22 +02:00
neil 64908e0080 fix Windows path 2021-10-03 19:28:30 +08:00
neil d4e1899747 support "--set-default-chain", fix https://github.com/acmesh-official/acme.sh/issues/3717 2021-10-03 19:02:45 +08:00
Bjarne Saltbaek 7f9b8d68ac Added dns-cpanel.sh as support for cPanel controlled DNS systems 2021-10-02 19:30:07 +02:00
neil 5b1e849bde Merge pull request #3725 from acmesh-official/dev
sync
2021-10-01 23:02:30 +08:00
neil fba6de76b1 Merge pull request #3687 from gstrauss/use-getdeployconf
use _getdeployconf instead of sourcing DOMAIN_CONF
2021-10-01 12:41:12 +08:00
Glenn Strauss 8419b42e83 use ${ACME_OPENSSL_BIN:-openssl} instead of openssl
(requested by @Neilpang in #3687)
2021-09-30 19:00:39 -04:00
neil 5f38c15b1f Merge pull request #3709 from ToJIka4/add_veesp_api
Add Veesp DNS API
2021-09-25 15:52:04 +08:00
neil c3b72baa8e Merge pull request #3710 from tcocca/dev
Rackspace changed their API response, fixed the sed matching
2021-09-24 10:25:42 +08:00
Tom Cocca 16d0416f22 trigger GH Actions again 2021-09-23 08:50:20 -04:00
Tom Cocca b9aa4f4478 trigger a GH actions change 2021-09-23 08:20:50 -04:00
Tom Cocca 8d3ad3a8c1 Rackspace changed their API response, fixed the sed matching 2021-09-23 08:10:17 -04:00
Stephen Pliaskin 5a689ce897 Add Veesp DNS API 2021-09-22 23:17:50 +03:00
neil 35e22703af Merge pull request #3697 from DerVerruckteFuchs/1984-hosting-cookie-fix
1984 hosting cookie fix
2021-09-15 09:27:00 +08:00
DerVerruckteFuchs 41a2d0e06c reduce ttl 2021-09-13 11:44:39 -04:00
DerVerruckteFuchs 4d95e35c06 get response based on $txtvalue 2021-09-12 17:38:27 -04:00
DerVerruckteFuchs 4e553f34ba get TXT entry based on $txtvalue 2021-09-12 17:20:01 -04:00
DerVerruckteFuchs b910726c43 pick first entry if more than one TXT entry exists 2021-09-12 17:05:36 -04:00
DerVerruckteFuchs 64e3cab6ab add correct number of vars for _get_zone_id 2021-09-12 16:57:32 -04:00
DerVerruckteFuchs f3196396a2 fix email filtering 2021-09-12 16:49:53 -04:00
DerVerruckteFuchs 148336929d fix formatting 2021-09-12 16:27:40 -04:00
DerVerruckteFuchs 2f3ec3a77f filter out instances where email@domain.com exists 2021-09-12 16:25:21 -04:00
Christophe B Billheimer 8d7a487013 change $@ -> $_domain 2021-09-12 14:10:54 -04:00
Christophe B Billheimer 622464ff5e fix error message for _get_zone_id 2021-09-12 13:49:31 -04:00
Christophe B Billheimer b45a44e405 fix formatting 2021-09-12 13:33:55 -04:00
Christophe B Billheimer a196958bd6 add check when getting zone id 2021-09-12 13:13:55 -04:00
Christophe B Billheimer f101418658 change _url -> url 2021-09-12 13:03:54 -04:00
Christophe B Billheimer aa05a1e81d make sure _url gets set where it is needed 2021-09-12 13:00:03 -04:00
Christophe B Billheimer 384bc62f25 make _get_zone_id usage consistent 2021-09-12 12:54:42 -04:00
Christophe B Billheimer 46e62f1a9a fix typo 2021-09-12 12:50:03 -04:00
Christophe B Billheimer c5c2014081 add _get_zone_id to dns_1984hosting_rm to get the zone id 2021-09-12 12:48:27 -04:00
Christophe B Billheimer c668c603cc add Referer and X-CSRFToken HTTP headers 2021-09-12 12:45:06 -04:00
Christophe B Billheimer 8f3b7c179e put cookies into a format that the 1984 Hosting website expects 2021-09-12 12:37:56 -04:00
Christophe B Billheimer ea18c47011 move getting zone id code into its own function 2021-09-12 12:35:20 -04:00
Christophe B Billheimer ced7110a78 remove -o option from grep and use _egrep_o instead 2021-09-10 08:49:38 -04:00
Christophe B Billheimer 92f13eb8bf get both the CSRF token and session ID cookies, as they are both needed for login now 2021-09-10 08:02:13 -04:00
Christophe B Billheimer 1312ef7e50 simplify One984HOSTING_COOKIE grep 2021-09-10 07:25:18 -04:00
Christophe B Billheimer e992979113 Merge branch 'master' of github.com:DerVerruckteFuchs/acme.sh into 1984-hosting-cookie-fix 2021-09-08 22:49:24 -04:00
Christophe B Billheimer d317b49940 use head instead of tail so that the sessionid cookie gets set correctly 2021-09-08 22:48:43 -04:00
neil 6be53468c5 Merge pull request #3691 from nookery/patch-1
the type of 'snis' is array
2021-09-07 11:55:44 +08:00
neil 046094bdcb Merge pull request #3696 from TheTyrius/dev
[dns_netcup] Fix variable name
2021-09-07 09:34:12 +08:00
Philipp B 1064c270d9 Fix variable name
Wrong variable name was used in login() and logout(), preventing operation.
2021-09-06 17:01:31 +02:00
Nookery 2447fccf1e name="snis" => name="snis[]"
kong 2.5.x,snis参数是一个数组
2021-09-04 16:59:50 +08:00
Glenn Strauss c43c711f72 use _getdeployconf instead of sourcing DOMAIN_CONF
(requested by @Neilpang in #3394)

github: closes #3394
2021-09-01 16:37:10 -04:00
Michael Weber f354e6de69 lighttpd deploy hook
* verbatim copy from haproxy.sh, s/haproxy/lighttpd
* enable issuer
2021-09-01 16:33:24 -04:00
neil 12615c46f8 Merge pull request #3682 from acmesh-official/dev
sync
2021-08-29 22:18:31 +08:00
neil b335840f97 Merge pull request #3657 from Sp1l/extend_pre_hook
Make domain names available to pre hook
2021-08-22 11:01:02 +08:00
Leo 6d84f59e6b Add Weixin Work notify hook 2021-08-21 04:11:21 +08:00
neilpang c5efec678e remove clearlinux 2021-08-18 20:59:47 +08:00
Aleksei Faians 83cb89e4f7 treat variable contents as text, don't process switches 2021-08-17 08:58:04 +03:00
neilpang 6bdf689d0f fix https://github.com/acmesh-official/acme.sh/issues/3660 2021-08-15 08:52:55 +08:00
Bernard Spil e164362069 Make domain names available to pre hook
Export Le_Domains and Le_Alt so your pre-hook script can run additional checks.

Allows running checks on the domain names before the first call to the ACME API. Thereby not counting against the rate-limit when an issue is going to be problematic.

Supersedes:	#3288
2021-08-10 12:36:29 +02:00
neilpang 72e3f33f28 fix docker test 2021-08-08 08:49:15 +08:00
neilpang ccfd907914 fix https://github.com/acmesh-official/acme.sh/issues/3649 2021-08-07 21:06:05 +08:00
neilpang 5a44e63cad fix nginx mode
https://github.com/acmesh-official/acme.sh/issues/3648#issuecomment-894045613
2021-08-06 21:22:10 +08:00
neil d96cca3822 Merge pull request #3647 from acmesh-official/dev
sync
2021-08-05 20:14:00 +08:00
neilpang 06580bf0e4 fix https://github.com/acmesh-official/acme.sh/issues/1914#issuecomment-893188476 2021-08-05 20:12:42 +08:00
neil b21bd64764 Merge pull request #3646 from jonwltn/dev
Minor output formatting changes.
2021-08-05 16:54:53 +08:00
jonwltn 6b97dc6734 Minor output formatting changes. 2021-08-04 10:44:48 -07:00
neil 4e3f328a02 Merge pull request #3644 from acmesh-official/dev
sync
2021-08-04 21:43:40 +08:00
neil 8380ca2fdd Merge pull request #3641 from felixonmars/patch-1
Correct a typo in dns_aws.sh
2021-08-03 11:01:59 +08:00
Felix Yan ec678bc6d2 Correct a typo in dns_aws.sh 2021-08-03 01:36:59 +08:00
neilpang 2b5e2d4760 fix nginx mode 2021-08-01 15:44:14 +08:00
neilpang 89abad7980 fix https://github.com/acmesh-official/acme.sh/issues/3635 2021-08-01 13:11:52 +08:00
neil d84da5bdbf Merge pull request #3638 from acmesh-official/dev
fix https://github.com/acmesh-official/acme.sh/issues/3624#issuecomme…
2021-08-01 08:47:41 +08:00
neilpang 5cc1d9521c fix https://github.com/acmesh-official/acme.sh/issues/3624#issuecomment-887689325 2021-07-28 22:14:54 +08:00
neil a199fc6113 Merge pull request #3621 from acmesh-official/dev
sync
2021-07-24 23:42:34 +08:00
neil 655e34b166 minor, clean links for renewal 2021-07-24 16:23:43 +08:00
neil 5ea3a02d6a Merge pull request #3587 from xpac1985/patch-2
dns_infoblox.sh: Fix Infoblox_View handling + some cleanup
2021-07-24 16:00:55 +08:00
neil 15c68c9594 Merge pull request #3620 from acmesh-official/dev
sync
2021-07-24 15:48:36 +08:00
neil 08438608d1 fix format 2021-07-24 15:46:58 +08:00
neil 2da94e0fdf Merge pull request #3617 from Ivanovitchk/dev
dns_ovh: fix random add/remove txt records failures
2021-07-22 14:00:29 +08:00
Ivanovitch_k 63165764dc dns_ovh: fix random add/remove txt records failures
due to inconsistent curl api response json
2021-07-22 00:24:11 +02:00
neilpang 103810ce20 add info 2021-07-20 21:05:17 +08:00
neil f59356b96b Merge pull request #3612 from acmesh-official/retry
add retry logic for http requests
2021-07-20 20:59:41 +08:00
ciro 4a8511f680 fix wrong variable name 2021-07-17 13:50:45 -03:00
cirow cd6698c688 Merge branch 'acmesh-official:dev' into dev 2021-07-15 22:56:26 -03:00
ciro c7ca9d7e36 fix shfmt issues 2021-07-15 22:55:35 -03:00
neil d70b759cb9 format 2021-07-15 22:47:20 +08:00
neil ae3dda0f8f add retry for get() and post() 2021-07-15 22:21:32 +08:00
neil e229ba5945 Merge pull request #3601 from acmesh-official/3600
fix https://github.com/acmesh-official/acme.sh/issues/3600
2021-07-12 22:27:19 +08:00
neil dcc50093bb fix https://github.com/acmesh-official/acme.sh/issues/3600 2021-07-12 21:46:08 +08:00
neil 0831690f79 Merge pull request #3595 from stevenzhu25/patch-1
Feature Request: Add sender name for SendGrid notify hook
2021-07-12 09:11:29 +08:00
ciro 98ef51514f added pushbullet functionality 2021-07-11 20:29:44 -03:00
neilpang ac9993394c update 2021-07-11 21:58:47 +08:00
Steven Zhu 849c3fd9c9 Fix space inconsistency 2021-07-06 22:54:15 -04:00
Steven Zhu da58fcbfce Add sender name for SendGrid notify hook 2021-07-06 20:51:51 -04:00
neil fa3cd9736f Merge pull request #3593 from jonwltn/fix-dnspod
Fix the URL for checking DNSPod availability.
2021-07-05 09:27:41 +08:00
jonwltn a0c5d17539 Fix the URL for checking DNSPod availability. 2021-07-02 09:23:45 -07:00
xpac1985 224cd04673 Shell formatting, again 2021-07-01 22:59:43 +02:00
xpac1985 52243d0870 Clean up formatting (SHFMT) 2021-07-01 22:54:56 +02:00
xpac1985 d519873fa4 Fix Infoblox_View handling + some cleanup
URL is now constructed after possible fallback value for Infoblox_View is being set
Infoblox_View is URLencoded to deal with e.g. spaces
Some cleanup, clearer log messages etc.
2021-07-01 22:25:49 +02:00
neil a76dcd4ba1 Merge pull request #3581 from acmesh-official/dev
sync
2021-06-28 21:21:04 +08:00
neilpang 2d07185300 use letsencrypt server to renew certs if no server was saved. 2021-06-28 21:16:32 +08:00
neil 518e1df257 sync (#3580)
sync
2021-06-28 21:10:42 +08:00
neilpang e0def66959 fix for compatiblity 2021-06-27 11:29:51 +08:00
neil 772d970074 fix CI tests (#3574)
fix CI tests
2021-06-25 23:20:40 +08:00
neilpang ba7d85145a fix env 2021-06-25 23:01:47 +08:00
neilpang fb73dceab0 fix format 2021-06-25 22:46:55 +08:00
neilpang 13fd83e0ba fix revoke 2021-06-25 22:44:23 +08:00
neilpang 719ba75fcc fix test server 2021-06-25 22:29:40 +08:00
neilpang 13ab98440c fix initapi 2021-06-25 22:23:17 +08:00
neilpang 1752004301 fix deactivate 2021-06-25 22:16:16 +08:00
neilpang 536a5f7cff fix deactivate 2021-06-25 21:59:38 +08:00
neilpang a69aece23a Use TEST_ACME_Server 2021-06-25 21:28:20 +08:00
neilpang 77d3815baa use TEST_ACME_Server 2021-06-25 21:18:03 +08:00
neilpang e225e17386 remove unused file 2021-06-25 20:56:46 +08:00
neil 3290208749 Merge pull request #3573 from acmesh-official/dev
Dev
2021-06-25 20:13:06 +08:00
neil 3106187aac Merge pull request #3572 from funzoneq/pdns-fix-content-type
Pdns fix content type
2021-06-25 18:25:19 +08:00
Arnoud Vermeer eae490b5b1 [dns_pdns] Fix: missing content type in PATCH requests #3454 2021-06-25 10:12:23 +02:00
neilpang bcce77508a remove buypass test 2021-06-25 00:04:13 +08:00
neilpang e9bdf02cfc fix filter 2021-06-25 00:01:46 +08:00
neilpang 77f659c9b9 add NO_ECC_384 2021-06-24 23:57:21 +08:00
neilpang c66e157a14 fix path filter 2021-06-24 23:30:16 +08:00
neilpang 2c927277e2 fix error 2021-06-24 23:23:46 +08:00
neilpang 29fe1c86da fix initapi 2021-06-24 23:21:10 +08:00
neilpang 1ae9c48370 fix error 2021-06-24 22:05:43 +08:00
neilpang 078a8b40e9 add buypass test 2021-06-24 22:03:00 +08:00
neilpang 9daeae1695 remove unnecessary check 2021-06-24 20:45:15 +08:00
neilpang 014e016058 add retry for init api 2021-06-24 20:35:49 +08:00
neil f41f93af3a Merge pull request #3491 from bgarret/consul-deploy-hook
Consul deploy hooks
2021-06-24 20:25:01 +08:00
neil 51539521b1 Merge pull request #3551 from marcusgrando/dev
Added Azion DNS API
2021-06-24 20:19:52 +08:00
Marcus Grando 522dec34a5 Added Azion DNS API 2021-06-23 08:45:22 -03:00
neil ea6d76cce6 Merge pull request #3569 from Habetdin/dev
notify/telegram.sh: Fix special characters escaping
2021-06-23 13:27:07 +08:00
Habetdin 7c7d61f61e Fix special characters escaping
To escape characters '_', '*', '`', '[' outside of an entity, prepend the characters '\' before them.
2021-06-23 03:20:07 +03:00
Marcus Grando 184dde92a2 Added Azion DNS API 2021-06-22 14:06:05 -03:00
neil 7e43c794fd Merge pull request #3567 from acmesh-official/dev
support SSL.com
2021-06-22 20:40:43 +08:00
neilpang c7285967d6 fix for list short name 2021-06-22 20:39:00 +08:00
neilpang 41f4baadb9 minor 2021-06-22 07:59:02 +08:00
neilpang 20082ec9fb update status 2021-06-22 07:55:12 +08:00
neilpang 8dae8c52c0 split in to multiple files, so that it can pass more. 2021-06-22 07:48:37 +08:00
neil 068076c0d5 Merge pull request #3565 from acmesh-official/dev
Dev
2021-06-21 23:42:23 +08:00
neilpang c0ae44a41b fix format 2021-06-21 22:59:14 +08:00
neilpang 593e8e1f63 move ca key path 2021-06-21 22:47:22 +08:00
neilpang 707cf35f0a fix format 2021-06-21 22:29:14 +08:00
neilpang 30f11d0e16 typo 2021-06-21 21:41:56 +08:00
neilpang 53d6ab6c23 support SSL.com 2021-06-21 21:31:00 +08:00
neilpang 280e44304a fix for compatibility to sslcom 2021-06-21 20:11:15 +08:00
neilpang 79fac4466e minor 2021-06-20 16:58:20 +08:00
neil 0e9f09e582 Merge pull request #3539 from Djelibeybi/dev
Add DNS API plugin for Oracle Cloud Infrastructure DNS Service
2021-06-20 16:05:56 +08:00
Avi Miller 25d0fdf8ff fix: fix a format issue reported by shellfmt
Signed-off-by: Avi Miller <avi.miller@oracle.com>
2021-06-20 17:07:04 +10:00
Avi Miller 1d089d4541 fix: refactor the way the config is read from file and envvars
The plugin will use the following order of precedence:

environment value > file value > default value

See the wiki for details on environment variable names.

Signed-off-by: Avi Miller <avi.miller@oracle.com>
2021-06-20 17:00:53 +10:00
neilpang 1c78663378 exclude test for dns api changes 2021-06-20 12:26:12 +08:00
Avi Miller 7666022840 fix: revert _readini() function to be more generic
Also switched [::space::] with a literal space for better
cross-platform compatibility.

Signed-off-by: Avi Miller <avi.miller@oracle.com>
2021-06-20 13:12:14 +10:00
Avi Miller 946c8b498a feat: enable automatic configuration from an OCI configuration file
The individual parameters can still be overridden via the
corresponding OCI_CLI environment variable.

Signed-off-by: Avi Miller <avi.miller@oracle.com>
2021-06-20 09:10:24 +10:00
Marcus Grando 406ca66c8d Added Azion DNS API 2021-06-19 15:19:56 -03:00
Avi Miller ed971df93a fix: add missing else/return 1 to if block
Signed-off-by: Avi Miller <avi.miller@oracle.com>
2021-06-19 15:41:34 +10:00
neilpang 74c054b2a5 fix https://github.com/acmesh-official/acme.sh/issues/3563 2021-06-19 11:52:11 +08:00
Avi Miller 017a10189c fix: switch to using functions instead of calling OpenSSL directly
Also reduced the number of environment variables which simplifies
the documentation and requirements. The variable names now match
those used by the OCI CLI.

Signed-off-by: Avi Miller <avi.miller@oracle.com>
2021-06-18 12:00:42 +10:00
neil f1c361855e Merge pull request #2526 from PeterDaveHello/Refactor_Dockerfile
Refactor Dockerfile
2021-06-17 22:01:27 +08:00
neil 3d72df4666 Merge pull request #2529 from PeterDaveHello/UpdateREADME.md
Remove invalid "Contribute" link in README.md
2021-06-16 23:11:56 +08:00
Peter Dave Hello 6f732a9957 Use COPY instead of ADD in Dockerfile for folder
Ref:
https://docs.docker.com/develop/develop-images/#add-or-copy
2021-06-16 22:47:36 +08:00
Peter Dave Hello 447bf77dfe Simplify apk command in Dockerfile
With apk `--no-cache` parameter, there is no need to run `apk update`
and manually clean up the cache, apk will update automatically without
leaving local cache files to be cleaned up.
2021-06-16 22:47:33 +08:00
Peter Dave Hello 6621ef6a0b Remove invalid "Contribute" link in README.md 2021-06-16 19:44:31 +08:00
Marcus Grando e327c8758e Merge branch 'acmesh-official:dev' into dev 2021-06-15 17:49:17 -03:00
neil 8a08de5691 Merge pull request #3554 from acmesh-official/dev
add linux tests
2021-06-14 12:25:39 +08:00
neilpang 3d7375be8b update status 2021-06-14 12:00:42 +08:00
neilpang da754e9a71 fix 2021-06-14 11:52:45 +08:00
neilpang cc9ec806b2 add all Linux 2021-06-14 11:50:19 +08:00
neil 72cf037c0d Merge pull request #3553 from acmesh-official/dev
fix for solaris
2021-06-13 22:11:27 +08:00
neilpang 8ae08b29e4 fix for solaris 2021-06-13 21:37:26 +08:00
neil 4967fa020f Merge pull request #3552 from acmesh-official/dev
sync
2021-06-13 16:16:11 +08:00
neilpang 54f2640ef2 fix env 2021-06-13 15:52:38 +08:00
neilpang 56246592c7 set ca names in the env 2021-06-13 15:45:33 +08:00
neilpang 1ff5d71e12 fix windows 2021-06-13 15:30:51 +08:00
neilpang 67c42c5911 add zerossl 2021-06-13 15:00:30 +08:00
neilpang d0b514890a change default ca to zerossl 2021-06-13 14:29:26 +08:00
Marcus Grando c0285fbc15 Added Azion DNS API 2021-06-11 11:17:26 -03:00
neil a438c841e1 Merge pull request #3542 from DerVerruckteFuchs/_get_root()-fix
fix _get_root() so that it successfully gets the root domain
2021-06-09 17:50:54 +08:00
neil 19d7c2b336 fix bug 2021-06-06 22:53:39 +08:00
neil afb6c70909 Merge pull request #3541 from DerVerruckteFuchs/dns_1984hosting_add()-fix
fix dns_1984hosting_add() so checks for HTML responses actually find HTML responses
2021-06-06 22:48:40 +08:00
DerVerruckteFuchs d9af496b13 Merge branch 'dev' into _get_root()-fix 2021-06-05 23:20:01 -04:00
Christophe B Billheimer a55cf40b1b fix _get_root() so that it successfully gets the root domain 2021-06-05 23:06:28 -04:00
Christophe B Billheimer b19008d1b8 fix dns_1984hosting_add() so checks for HTML responses are actually find HTML responses 2021-06-05 22:38:45 -04:00
Avi Miller 6f88c81616 Add DNS API plugin for Oracle Cloud Infrastructure DNS Service
This plugin is has noticeably more required fields than most
other plugins due to the requirement that all requests to
the OCI REST API must be cryptographically signed by the client
using the draft standard proposed in draft-cavage-http-signatures-08[1].

The OCI specific implementation details of the draft standard are
documented in the Developer Guide[2].

NOTE: there is maximum allowed clock skew of five minutes between the
client and the API endpoint. Requests will be denied if the skew is
greater.

This PR also includes a minor tweak to the Solaris job in the DNS
workflow so that it uses the pre-installed GNU tools, curl and OpenSSL 1.1.1.
Without these changes, the signature generation function does not
work on Solaris.

[1]: https://datatracker.ietf.org/doc/html/draft-cavage-http-signatures-08
[2]: https://docs.oracle.com/en-us/iaas/Content/API/Concepts/signingrequests.htm#five

Signed-off-by: Avi Miller <avi.miller@oracle.com>
2021-06-05 21:55:40 +10:00
neil 43cb230f19 Merge pull request #3535 from sparunakian/dev
Fix typo (#3521)
2021-06-02 23:06:36 +08:00
neil fd6a59202d start 3.0.0 2021-06-02 23:06:12 +08:00
Stéphane Parunakian e353f66eaa Fix typo 2021-06-02 16:06:08 +02:00
Benoit Garret 07afc4953a Fix the shfmt check 2021-05-07 12:12:30 +02:00
Benoit Garret c127903127 Add Consul deploy hook 2021-05-05 10:01:09 +02:00
F-Plass 4bb8e3a121 Update truenas.sh
-error handling
2021-02-21 22:48:31 +01:00
F-Plass eacc00f786 Update truenas.sh
- check if curl exists
- check if wget exist, then errortext and exit scipt
- _get command "restartUI"  wirh info about curl error 52
2021-02-21 22:42:24 +01:00
F-Plass 93fd6170a3 Update truenas.sh 2021-02-13 12:38:57 +01:00
F-Plass 6f4c5fcc87 Update truenas.sh 2021-02-07 21:25:49 +01:00
F-Plass a7ca010d4e Update truenas.sh 2021-02-07 21:24:06 +01:00
F-Plass a836842a7e Update truenas.sh 2021-02-07 21:20:56 +01:00
F-Plass f8c11a324a Update truenas.sh 2021-02-07 19:19:04 +01:00
F-Plass 052c9be111 Update truenas.sh 2021-02-07 19:12:39 +01:00
F-Plass 854e520528 Update truenas.sh 2021-02-07 19:02:03 +01:00
F-Plass 05737b85eb Update truenas.sh 2021-02-07 18:47:04 +01:00
F-Plass c8a2308739 Update truenas.sh 2021-02-07 18:42:48 +01:00
F-Plass ed46a078f9 Update truenas.sh 2021-02-07 16:35:51 +01:00
F-Plass 4f7c2bf8c3 Update truenas.sh 2021-02-07 16:12:24 +01:00
F-Plass 0e341726d2 Edits after DoShellcheck 2021-02-06 23:20:52 +01:00
F-Plass a4f9746d3a Danksagung an danb35 2021-02-06 23:03:07 +01:00
F-Plass 556c546b2e Deploy Scipt for TrueNAs Server
acme .sh deploy Scipt for TrueNAS Server that uses the REST API from TrueNAS.

- Authentification with API Key
- If HTTP redirect is configured, automatik switch to HTTPS
- If WebDAV Certificate is the same as Web UI Certificate, Webdav Certificate get also an updated
- If FTP Certificate is the same as Web UI Certificate, FTP Certificate get also an updated
2021-02-06 22:48:25 +01:00
Ian Epperson 748cb28017 Add Discord notification 2020-05-13 10:39:11 -07:00
75 changed files with 4689 additions and 1099 deletions

No files matched your search

+1 -1
View File
@@ -3,7 +3,7 @@
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: acmesh
ko_fi: # Replace with a single Ko-fi username
ko_fi: neilpang
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
-40
View File
@@ -1,40 +0,0 @@
# 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
+22 -17
View File
@@ -37,7 +37,7 @@ jobs:
- name: "Read this: https://github.com/acmesh-official/acme.sh/wiki/DNS-API-Test"
run: |
echo "Read this: https://github.com/acmesh-official/acme.sh/wiki/DNS-API-Test"
if [ "${{github.actor}}" != "Neilpang" ]; then
if [ "${{github.repository_owner}}" != "acmesh-official" ]; then
false
fi
@@ -49,6 +49,7 @@ jobs:
TEST_DNS : ${{ secrets.TEST_DNS }}
TestingDomain: ${{ secrets.TestingDomain }}
TEST_DNS_NO_WILDCARD: ${{ secrets.TEST_DNS_NO_WILDCARD }}
TEST_DNS_NO_SUBDOMAIN: ${{ secrets.TEST_DNS_NO_SUBDOMAIN }}
TEST_DNS_SLEEP: ${{ secrets.TEST_DNS_SLEEP }}
CASE: le_test_dnsapi
TEST_LOCAL: 1
@@ -59,24 +60,24 @@ jobs:
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
- name: Set env file
run: |
cd ../acmetest
cd ../acmetest
if [ "${{ secrets.TokenName1}}" ] ; then
echo "${{ secrets.TokenName1}}=${{ secrets.TokenValue1}}" >> env.list
echo "${{ secrets.TokenName1}}=${{ secrets.TokenValue1}}" >> docker.env
fi
if [ "${{ secrets.TokenName2}}" ] ; then
echo "${{ secrets.TokenName2}}=${{ secrets.TokenValue2}}" >> env.list
echo "${{ secrets.TokenName2}}=${{ secrets.TokenValue2}}" >> docker.env
fi
if [ "${{ secrets.TokenName3}}" ] ; then
echo "${{ secrets.TokenName3}}=${{ secrets.TokenValue3}}" >> env.list
echo "${{ secrets.TokenName3}}=${{ secrets.TokenValue3}}" >> docker.env
fi
if [ "${{ secrets.TokenName4}}" ] ; then
echo "${{ secrets.TokenName4}}=${{ secrets.TokenValue4}}" >> env.list
echo "${{ secrets.TokenName4}}=${{ secrets.TokenValue4}}" >> docker.env
fi
if [ "${{ secrets.TokenName5}}" ] ; then
echo "${{ secrets.TokenName5}}=${{ secrets.TokenValue5}}" >> env.list
echo "${{ secrets.TokenName5}}=${{ secrets.TokenValue5}}" >> docker.env
fi
echo "TEST_DNS_NO_WILDCARD" >> env.list
echo "TEST_DNS_SLEEP" >> env.list
echo "TEST_DNS_NO_WILDCARD" >> docker.env
echo "TEST_DNS_SLEEP" >> docker.env
- name: Run acmetest
run: cd ../acmetest && ./rundocker.sh testall
@@ -87,6 +88,7 @@ jobs:
TEST_DNS : ${{ secrets.TEST_DNS }}
TestingDomain: ${{ secrets.TestingDomain }}
TEST_DNS_NO_WILDCARD: ${{ secrets.TEST_DNS_NO_WILDCARD }}
TEST_DNS_NO_SUBDOMAIN: ${{ secrets.TEST_DNS_NO_SUBDOMAIN }}
TEST_DNS_SLEEP: ${{ secrets.TEST_DNS_SLEEP }}
CASE: le_test_dnsapi
TEST_LOCAL: 1
@@ -124,6 +126,7 @@ jobs:
TEST_DNS : ${{ secrets.TEST_DNS }}
TestingDomain: ${{ secrets.TestingDomain }}
TEST_DNS_NO_WILDCARD: ${{ secrets.TEST_DNS_NO_WILDCARD }}
TEST_DNS_NO_SUBDOMAIN: ${{ secrets.TEST_DNS_NO_SUBDOMAIN }}
TEST_DNS_SLEEP: ${{ secrets.TEST_DNS_SLEEP }}
CASE: le_test_dnsapi
TEST_LOCAL: 1
@@ -170,12 +173,13 @@ jobs:
./letest.sh
FreeBSD:
runs-on: macos-latest
runs-on: macos-10.15
needs: Windows
env:
TEST_DNS : ${{ secrets.TEST_DNS }}
TestingDomain: ${{ secrets.TestingDomain }}
TEST_DNS_NO_WILDCARD: ${{ secrets.TEST_DNS_NO_WILDCARD }}
TEST_DNS_NO_SUBDOMAIN: ${{ secrets.TEST_DNS_NO_SUBDOMAIN }}
TEST_DNS_SLEEP: ${{ secrets.TEST_DNS_SLEEP }}
CASE: le_test_dnsapi
TEST_LOCAL: 1
@@ -186,7 +190,7 @@ jobs:
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
- uses: vmactions/freebsd-vm@v0.1.4
with:
envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}'
envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_NO_SUBDOMAIN TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}'
prepare: pkg install -y socat curl
usesh: true
run: |
@@ -209,12 +213,13 @@ jobs:
./letest.sh
Solaris:
runs-on: macos-latest
runs-on: macos-10.15
needs: FreeBSD
env:
TEST_DNS : ${{ secrets.TEST_DNS }}
TestingDomain: ${{ secrets.TestingDomain }}
TEST_DNS_NO_WILDCARD: ${{ secrets.TEST_DNS_NO_WILDCARD }}
TEST_DNS_NO_SUBDOMAIN: ${{ secrets.TEST_DNS_NO_SUBDOMAIN }}
TEST_DNS_SLEEP: ${{ secrets.TEST_DNS_SLEEP }}
CASE: le_test_dnsapi
TEST_LOCAL: 1
@@ -223,11 +228,13 @@ jobs:
- uses: actions/checkout@v2
- name: Clone acmetest
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
- uses: vmactions/solaris-vm@v0.0.3
- uses: vmactions/solaris-vm@v0.0.5
with:
envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}'
prepare: pkgutil -y -i socat curl
envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_NO_SUBDOMAIN TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}'
prepare: pkgutil -y -i socat
run: |
pkg set-mediator -v -I default@1.1 openssl
export PATH=/usr/gnu/bin:$PATH
if [ "${{ secrets.TokenName1}}" ] ; then
export ${{ secrets.TokenName1}}=${{ secrets.TokenValue1}}
fi
@@ -245,5 +252,3 @@ jobs:
fi
cd ../acmetest
./letest.sh
+63
View File
@@ -0,0 +1,63 @@
name: FreeBSD
on:
push:
branches:
- '*'
paths:
- '*.sh'
- '.github/workflows/FreeBSD.yml'
pull_request:
branches:
- dev
paths:
- '*.sh'
- '.github/workflows/FreeBSD.yml'
jobs:
FreeBSD:
strategy:
matrix:
include:
- TEST_ACME_Server: "LetsEncrypt.org_test"
CA_ECDSA: ""
CA: ""
CA_EMAIL: ""
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1
#- TEST_ACME_Server: "ZeroSSL.com"
# CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA"
# CA: "ZeroSSL RSA Domain Secure Site CA"
# CA_EMAIL: "githubtest@acme.sh"
# TEST_PREFERRED_CHAIN: ""
runs-on: macos-10.15
env:
TEST_LOCAL: 1
TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }}
CA_ECDSA: ${{ matrix.CA_ECDSA }}
CA: ${{ matrix.CA }}
CA_EMAIL: ${{ matrix.CA_EMAIL }}
TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }}
steps:
- uses: actions/checkout@v2
- uses: vmactions/cf-tunnel@v0.0.3
id: tunnel
with:
protocol: http
port: 8080
- name: Set envs
run: echo "TestingDomain=${{steps.tunnel.outputs.server}}" >> $GITHUB_ENV
- name: Clone acmetest
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
- uses: vmactions/freebsd-vm@v0.1.5
with:
envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN'
nat: |
"8080": "80"
prepare: pkg install -y socat curl
usesh: true
run: |
cd ../acmetest \
&& ./letest.sh
-127
View File
@@ -1,127 +0,0 @@
name: LetsEncrypt
on:
push:
branches:
- '*'
paths:
- '**.sh'
- '**.yml'
pull_request:
branches:
- dev
paths:
- '**.sh'
- '**.yml'
jobs:
Ubuntu:
runs-on: ubuntu-latest
env:
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 --preserve-env ./letest.sh
MacOS:
runs-on: macos-latest
env:
TEST_LOCAL: 1
steps:
- uses: actions/checkout@v2
- name: Install tools
run: 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 --preserve-env ./letest.sh
Windows:
runs-on: windows-latest
env:
TEST_LOCAL: 1
#The 80 port is used by Windows server, we have to use a custom port, tunnel will also use this port.
Le_HTTPPort: 8888
steps:
- name: Set git to use LF
run: |
git config --global core.autocrlf false
- uses: actions/checkout@v2
- name: Install cygwin base packages with chocolatey
run: |
choco config get cacheLocation
choco install --no-progress cygwin
shell: cmd
- name: Install cygwin additional packages
run: |
C:\tools\cygwin\cygwinsetup.exe -qgnNdO -R C:/tools/cygwin -s http://mirrors.kernel.org/sourceware/cygwin/ -P socat,curl,cron,unzip,git
shell: cmd
- name: Set ENV
shell: cmd
run: |
echo PATH=C:\tools\cygwin\bin;C:\tools\cygwin\usr\bin >> %GITHUB_ENV%
- name: Check ENV
shell: cmd
run: |
echo "PATH=%PATH%"
- name: Clone acmetest
shell: cmd
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
- name: Run acmetest
shell: cmd
run: cd ../acmetest && bash.exe -c ./letest.sh
FreeBSD:
runs-on: macos-latest
env:
TEST_LOCAL: 1
steps:
- uses: actions/checkout@v2
- uses: vmactions/cf-tunnel@v0.0.2
id: tunnel
with:
protocol: http
port: 8080
- name: Set envs
run: echo "TestingDomain=${{steps.tunnel.outputs.server}}" >> $GITHUB_ENV
- name: Clone acmetest
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
- uses: vmactions/freebsd-vm@v0.1.4
with:
envs: 'TEST_LOCAL TestingDomain'
nat: |
"8080": "80"
prepare: pkg install -y socat curl
usesh: true
run: |
cd ../acmetest && ./letest.sh
Solaris:
runs-on: macos-latest
env:
TEST_LOCAL: 1
steps:
- uses: actions/checkout@v2
- uses: vmactions/cf-tunnel@v0.0.2
id: tunnel
with:
protocol: http
port: 8080
- name: Set envs
run: echo "TestingDomain=${{steps.tunnel.outputs.server}}" >> $GITHUB_ENV
- name: Clone acmetest
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
- uses: vmactions/solaris-vm@v0.0.3
with:
envs: 'TEST_LOCAL TestingDomain'
nat: |
"8080": "80"
prepare: pkgutil -y -i socat curl
run: |
cd ../acmetest && ./letest.sh
+41
View File
@@ -0,0 +1,41 @@
name: Linux
on:
push:
branches:
- '*'
paths:
- '*.sh'
- '.github/workflows/Linux.yml'
pull_request:
branches:
- dev
paths:
- '*.sh'
- '.github/workflows/Linux.yml'
jobs:
Linux:
strategy:
matrix:
os: ["ubuntu:latest", "debian:latest", "almalinux:latest", "fedora:latest", "centos:7", "opensuse/leap:latest", "alpine:latest", "oraclelinux:8", "kalilinux/kali", "archlinux:latest", "mageia", "gentoo/stage3"]
runs-on: ubuntu-latest
env:
TEST_LOCAL: 1
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1
steps:
- uses: actions/checkout@v2
- 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 \
&& ./rundocker.sh testplat ${{ matrix.os }}
+55
View File
@@ -0,0 +1,55 @@
name: MacOS
on:
push:
branches:
- '*'
paths:
- '*.sh'
- '.github/workflows/MacOS.yml'
pull_request:
branches:
- dev
paths:
- '*.sh'
- '.github/workflows/MacOS.yml'
jobs:
MacOS:
strategy:
matrix:
include:
- TEST_ACME_Server: "LetsEncrypt.org_test"
CA_ECDSA: ""
CA: ""
CA_EMAIL: ""
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1
#- TEST_ACME_Server: "ZeroSSL.com"
# CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA"
# CA: "ZeroSSL RSA Domain Secure Site CA"
# CA_EMAIL: "githubtest@acme.sh"
# TEST_PREFERRED_CHAIN: ""
runs-on: macos-latest
env:
TEST_LOCAL: 1
TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }}
CA_ECDSA: ${{ matrix.CA_ECDSA }}
CA: ${{ matrix.CA }}
CA_EMAIL: ${{ matrix.CA_EMAIL }}
TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }}
steps:
- uses: actions/checkout@v2
- name: Install tools
run: 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 --preserve-env ./letest.sh
+28 -5
View File
@@ -4,14 +4,14 @@ on:
branches:
- '*'
paths:
- '**.sh'
- '**.yml'
- '*.sh'
- '.github/workflows/PebbleStrict.yml'
pull_request:
branches:
- dev
paths:
- '**.sh'
- '**.yml'
- '*.sh'
- '.github/workflows/PebbleStrict.yml'
jobs:
PebbleStrict:
@@ -19,7 +19,7 @@ jobs:
env:
TestingDomain: example.com
TestingAltDomains: www.example.com
ACME_DIRECTORY: https://localhost:14000/dir
TEST_ACME_Server: https://localhost:14000/dir
HTTPS_INSECURE: 1
Le_HTTPPort: 5002
TEST_LOCAL: 1
@@ -35,5 +35,28 @@ jobs:
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
PebbleStrict_IPCert:
runs-on: ubuntu-latest
env:
TestingDomain: 10.30.50.1
ACME_DIRECTORY: https://localhost:14000/dir
HTTPS_INSECURE: 1
Le_HTTPPort: 5002
Le_TLSPort: 5001
TEST_LOCAL: 1
TEST_CA: "Pebble Intermediate CA"
TEST_IPCERT: 1
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: 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
+61
View File
@@ -0,0 +1,61 @@
name: Solaris
on:
push:
branches:
- '*'
paths:
- '*.sh'
- '.github/workflows/Solaris.yml'
pull_request:
branches:
- dev
paths:
- '*.sh'
- '.github/workflows/Solaris.yml'
jobs:
Solaris:
strategy:
matrix:
include:
- TEST_ACME_Server: "LetsEncrypt.org_test"
CA_ECDSA: ""
CA: ""
CA_EMAIL: ""
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1
#- TEST_ACME_Server: "ZeroSSL.com"
# CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA"
# CA: "ZeroSSL RSA Domain Secure Site CA"
# CA_EMAIL: "githubtest@acme.sh"
# TEST_PREFERRED_CHAIN: ""
runs-on: macos-10.15
env:
TEST_LOCAL: 1
TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }}
CA_ECDSA: ${{ matrix.CA_ECDSA }}
CA: ${{ matrix.CA }}
CA_EMAIL: ${{ matrix.CA_EMAIL }}
TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }}
steps:
- uses: actions/checkout@v2
- uses: vmactions/cf-tunnel@v0.0.3
id: tunnel
with:
protocol: http
port: 8080
- name: Set envs
run: echo "TestingDomain=${{steps.tunnel.outputs.server}}" >> $GITHUB_ENV
- name: Clone acmetest
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
- uses: vmactions/solaris-vm@v0.0.5
with:
envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN'
nat: |
"8080": "80"
prepare: pkgutil -y -i socat curl
run: |
cd ../acmetest \
&& ./letest.sh
+86
View File
@@ -0,0 +1,86 @@
name: Ubuntu
on:
push:
branches:
- '*'
paths:
- '*.sh'
- '.github/workflows/Ubuntu.yml'
pull_request:
branches:
- dev
paths:
- '*.sh'
- '.github/workflows/Ubuntu.yml'
jobs:
Ubuntu:
strategy:
matrix:
include:
- TEST_ACME_Server: "LetsEncrypt.org_test"
CA_ECDSA: ""
CA: ""
CA_EMAIL: ""
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1
- TEST_ACME_Server: "ZeroSSL.com"
CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA"
CA: "ZeroSSL RSA Domain Secure Site CA"
CA_EMAIL: "githubtest@acme.sh"
TEST_PREFERRED_CHAIN: ""
- TEST_ACME_Server: "https://localhost:9000/acme/acme/directory"
CA_ECDSA: "Smallstep Intermediate CA"
CA: "Smallstep Intermediate CA"
CA_EMAIL: ""
TEST_PREFERRED_CHAIN: ""
NO_REVOKE: 1
- TEST_ACME_Server: "https://localhost:9000/acme/acme/directory"
CA_ECDSA: "Smallstep Intermediate CA"
CA: "Smallstep Intermediate CA"
CA_EMAIL: ""
TEST_PREFERRED_CHAIN: ""
NO_REVOKE: 1
TEST_IPCERT: 1
TestingDomain: "172.17.0.1"
runs-on: ubuntu-latest
env:
TEST_LOCAL: 1
TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }}
CA_ECDSA: ${{ matrix.CA_ECDSA }}
CA: ${{ matrix.CA }}
CA_EMAIL: ${{ matrix.CA_EMAIL }}
NO_ECC_384: ${{ matrix.NO_ECC_384 }}
TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }}
NO_REVOKE: ${{ matrix.NO_REVOKE }}
TEST_IPCERT: ${{ matrix.TEST_IPCERT }}
TestingDomain: ${{ matrix.TestingDomain }}
steps:
- uses: actions/checkout@v2
- name: Install tools
run: sudo apt-get install -y socat
- name: Start StepCA
if: ${{ matrix.TEST_ACME_Server=='https://localhost:9000/acme/acme/directory' }}
run: |
docker run --rm -d \
-p 9000:9000 \
-e "DOCKER_STEPCA_INIT_NAME=Smallstep" \
-e "DOCKER_STEPCA_INIT_DNS_NAMES=localhost,$(hostname -f)" \
--name stepca \
smallstep/step-ca \
&& sleep 5 && docker exec stepca step ca provisioner add acme --type ACME \
&& docker exec stepca kill -1 1 \
&& docker exec stepca cat /home/step/certs/root_ca.crt | sudo bash -c "cat - >>/etc/ssl/certs/ca-certificates.crt"
- 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 --preserve-env ./letest.sh
+73
View File
@@ -0,0 +1,73 @@
name: Windows
on:
push:
branches:
- '*'
paths:
- '*.sh'
- '.github/workflows/Windows.yml'
pull_request:
branches:
- dev
paths:
- '*.sh'
- '.github/workflows/Windows.yml'
jobs:
Windows:
strategy:
matrix:
include:
- TEST_ACME_Server: "LetsEncrypt.org_test"
CA_ECDSA: ""
CA: ""
CA_EMAIL: ""
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1
#- TEST_ACME_Server: "ZeroSSL.com"
# CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA"
# CA: "ZeroSSL RSA Domain Secure Site CA"
# CA_EMAIL: "githubtest@acme.sh"
# TEST_PREFERRED_CHAIN: ""
runs-on: windows-latest
env:
TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }}
CA_ECDSA: ${{ matrix.CA_ECDSA }}
CA: ${{ matrix.CA }}
CA_EMAIL: ${{ matrix.CA_EMAIL }}
TEST_LOCAL: 1
#The 80 port is used by Windows server, we have to use a custom port, tunnel will also use this port.
Le_HTTPPort: 8888
TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }}
steps:
- name: Set git to use LF
run: |
git config --global core.autocrlf false
- uses: actions/checkout@v2
- name: Install cygwin base packages with chocolatey
run: |
choco config get cacheLocation
choco install --no-progress cygwin
shell: cmd
- name: Install cygwin additional packages
run: |
C:\tools\cygwin\cygwinsetup.exe -qgnNdO -R C:/tools/cygwin -s http://mirrors.kernel.org/sourceware/cygwin/ -P socat,curl,cron,unzip,git,xxd
shell: cmd
- name: Set ENV
shell: cmd
run: |
echo PATH=C:\tools\cygwin\bin;C:\tools\cygwin\usr\bin;%PATH% >> %GITHUB_ENV%
- name: Check ENV
shell: cmd
run: |
echo "PATH=%PATH%"
- name: Clone acmetest
shell: cmd
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
- name: Run acmetest
shell: cmd
run: cd ../acmetest && bash.exe -c ./letest.sh
+5
View File
@@ -6,6 +6,11 @@ on:
- '*'
tags:
- '*'
paths:
- '**.sh'
- "Dockerfile"
- '.github/workflows/dockerhub.yml'
jobs:
CheckToken:
+2 -2
View File
@@ -5,13 +5,13 @@ on:
- '*'
paths:
- '**.sh'
- '**.yml'
- '.github/workflows/shellcheck.yml'
pull_request:
branches:
- dev
paths:
- '**.sh'
- '**.yml'
- '.github/workflows/shellcheck.yml'
jobs:
ShellCheck:
+8 -6
View File
@@ -1,7 +1,6 @@
FROM alpine:3.12
FROM alpine:3.15
RUN apk update -f \
&& apk --no-cache add -f \
RUN apk --no-cache add -f \
openssl \
openssh-client \
coreutils \
@@ -13,7 +12,7 @@ RUN apk update -f \
oath-toolkit-oathtool \
tar \
libidn \
&& rm -rf /var/cache/apk/*
jq
ENV LE_CONFIG_HOME /acme.sh
@@ -22,7 +21,7 @@ ARG AUTO_UPGRADE=1
ENV AUTO_UPGRADE $AUTO_UPGRADE
#Install
ADD ./ /install_acme.sh/
COPY ./ /install_acme.sh/
RUN cd /install_acme.sh && ([ -f /install_acme.sh/acme.sh ] && /install_acme.sh/acme.sh --install || curl https://get.acme.sh | sh) && rm -rf /install_acme.sh/
@@ -42,6 +41,7 @@ RUN for verb in help \
revoke \
remove \
list \
info \
showcsr \
install-cronjob \
uninstall-cronjob \
@@ -57,6 +57,7 @@ RUN for verb in help \
deactivate-account \
set-notify \
set-default-ca \
set-default-chain \
; 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
@@ -64,7 +65,8 @@ RUN for verb in help \
RUN printf "%b" '#!'"/usr/bin/env sh\n \
if [ \"\$1\" = \"daemon\" ]; then \n \
trap \"echo stop && killall crond && exit 0\" SIGTERM SIGINT \n \
crond && while true; do sleep 1; done;\n \
crond && sleep infinity &\n \
wait \n \
else \n \
exec -- \"\$@\"\n \
fi" >/entry.sh && chmod +x /entry.sh
+40 -32
View File
@@ -1,6 +1,11 @@
# An ACME Shell script: acme.sh
![LetsEncrypt](https://github.com/acmesh-official/acme.sh/workflows/LetsEncrypt/badge.svg)
[![FreeBSD](https://github.com/acmesh-official/acme.sh/actions/workflows/FreeBSD.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/FreeBSD.yml)
[![MacOS](https://github.com/acmesh-official/acme.sh/actions/workflows/MacOS.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/MacOS.yml)
[![Ubuntu](https://github.com/acmesh-official/acme.sh/actions/workflows/Ubuntu.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Ubuntu.yml)
[![Windows](https://github.com/acmesh-official/acme.sh/actions/workflows/Windows.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Windows.yml)
[![Solaris](https://github.com/acmesh-official/acme.sh/actions/workflows/Solaris.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Solaris.yml)
![Shellcheck](https://github.com/acmesh-official/acme.sh/workflows/Shellcheck/badge.svg)
![PebbleStrict](https://github.com/acmesh-official/acme.sh/workflows/PebbleStrict/badge.svg)
![DockerHub](https://github.com/acmesh-official/acme.sh/workflows/Build%20DockerHub/badge.svg)
@@ -15,18 +20,18 @@
- 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
- Support ECDSA certs
- Support SAN and wildcard certs
- Simple, powerful and very easy to use. You only need 3 minutes to learn it.
- Bash, dash and sh compatible.
- Purely written in Shell with no dependencies on python or the official Let's Encrypt client.
- Purely written in Shell with no dependencies on python.
- Just one script to issue, renew and install your certificates automatically.
- DOES NOT require `root/sudoer` access.
- Docker friendly
- IPv6 support
- Docker ready
- IPv6 ready
- Cron job notifications for renewal or error etc.
It's probably the `easiest & smartest` shell script to automatically issue & renew the free certificates from Let's Encrypt.
It's probably the `easiest & smartest` shell script to automatically issue & renew the free certificates.
Wiki: https://github.com/acmesh-official/acme.sh/wiki
@@ -57,37 +62,40 @@ Twitter: [@neilpangxa](https://twitter.com/neilpangxa)
| NO | Status| Platform|
|----|-------|---------|
|1|[![MacOS](https://github.com/acmesh-official/acme.sh/workflows/LetsEncrypt/badge.svg)](https://github.com/acmesh-official/acme.sh/actions?query=workflow%3ALetsEncrypt)|Mac OSX
|2|[![Windows](https://github.com/acmesh-official/acme.sh/workflows/LetsEncrypt/badge.svg)](https://github.com/acmesh-official/acme.sh/actions?query=workflow%3ALetsEncrypt)|Windows (cygwin with curl, openssl and crontab included)
|3|[![FreeBSD](https://github.com/acmesh-official/acme.sh/workflows/LetsEncrypt/badge.svg)](https://github.com/acmesh-official/acme.sh/actions?query=workflow%3ALetsEncrypt)|FreeBSD
|4|[![Solaris](https://github.com/acmesh-official/acme.sh/workflows/LetsEncrypt/badge.svg)](https://github.com/acmesh-official/acme.sh/actions?query=workflow%3ALetsEncrypt)|Solaris
|5|[![Ubuntu](https://github.com/acmesh-official/acme.sh/workflows/LetsEncrypt/badge.svg)](https://github.com/acmesh-official/acme.sh/actions?query=workflow%3ALetsEncrypt)| Ubuntu
|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/openbsd.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|OpenBSD
|8|[![](https://acmesh-official.github.io/acmetest/status/debian-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)| Debian
|9|[![](https://acmesh-official.github.io/acmetest/status/centos-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|CentOS
|10|[![](https://acmesh-official.github.io/acmetest/status/opensuse-leap-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|openSUSE
|11|[![](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)
|12|[![](https://acmesh-official.github.io/acmetest/status/archlinux-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Archlinux
|13|[![](https://acmesh-official.github.io/acmetest/status/fedora-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|fedora
|14|[![](https://acmesh-official.github.io/acmetest/status/kalilinux-kali.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Kali Linux
|15|[![](https://acmesh-official.github.io/acmetest/status/oraclelinux-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Oracle Linux
|16|[![](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)
|17|-----| Cloud Linux https://github.com/acmesh-official/acme.sh/issues/111
|18|[![](https://acmesh-official.github.io/acmetest/status/mageia.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Mageia
|19|-----| OpenWRT: Tested and working. See [wiki page](https://github.com/acmesh-official/acme.sh/wiki/How-to-run-on-OpenWRT)
|20|[![](https://acmesh-official.github.io/acmetest/status/gentoo-stage3-amd64.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|Gentoo Linux
|21|[![](https://acmesh-official.github.io/acmetest/status/clearlinux-latest.svg)](https://github.com/acmesh-official/acmetest#here-are-the-latest-status)|ClearLinux
|1|[![MacOS](https://github.com/acmesh-official/acme.sh/actions/workflows/MacOS.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/MacOS.yml)|Mac OSX
|2|[![Windows](https://github.com/acmesh-official/acme.sh/actions/workflows/Windows.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Windows.yml)|Windows (cygwin with curl, openssl and crontab included)
|3|[![FreeBSD](https://github.com/acmesh-official/acme.sh/actions/workflows/FreeBSD.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/FreeBSD.yml)|FreeBSD
|4|[![Solaris](https://github.com/acmesh-official/acme.sh/actions/workflows/Solaris.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Solaris.yml)|Solaris
|5|[![Ubuntu](https://github.com/acmesh-official/acme.sh/actions/workflows/Ubuntu.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Ubuntu.yml)| Ubuntu
|6|NA|pfsense
|7|NA|OpenBSD
|8|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)| Debian
|9|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|CentOS
|10|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|openSUSE
|11|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Alpine Linux (with curl)
|12|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Archlinux
|13|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|fedora
|14|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Kali Linux
|15|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Oracle Linux
|16|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Mageia
|17|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Gentoo Linux
|18|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|ClearLinux
|19|-----| Cloud Linux https://github.com/acmesh-official/acme.sh/issues/111
|20|-----| OpenWRT: Tested and working. See [wiki page](https://github.com/acmesh-official/acme.sh/wiki/How-to-run-on-OpenWRT)
|21|[![](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)
For all build statuses, check our [weekly build project](https://github.com/acmesh-official/acmetest):
Check our [testing project](https://github.com/acmesh-official/acmetest):
https://github.com/acmesh-official/acmetest
# Supported CA
- Letsencrypt.org CA(default)
- [ZeroSSL.com CA](https://github.com/acmesh-official/acme.sh/wiki/ZeroSSL.com-CA)
- [ZeroSSL.com CA](https://github.com/acmesh-official/acme.sh/wiki/ZeroSSL.com-CA)(default)
- Letsencrypt.org CA
- [BuyPass.com CA](https://github.com/acmesh-official/acme.sh/wiki/BuyPass.com-CA)
- [SSL.com CA](https://github.com/acmesh-official/acme.sh/wiki/SSL.com-CA)
- [Google.com Public CA](https://github.com/acmesh-official/acme.sh/wiki/Google-Public-CA)
- [Pebble strict Mode](https://github.com/letsencrypt/pebble)
- Any other [RFC8555](https://tools.ietf.org/html/rfc8555)-compliant CA
@@ -469,7 +477,7 @@ TODO:
### Code Contributors
This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].
This project exists thanks to all the people who contribute.
<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
+600 -188
View File
File diff suppressed because it is too large. Load diff
+98
View File
@@ -0,0 +1,98 @@
#!/usr/bin/env sh
# Here is a script to deploy cert to hashicorp consul using curl
# (https://www.consul.io/)
#
# it requires following environment variables:
#
# CONSUL_PREFIX - this contains the prefix path in consul
# CONSUL_HTTP_ADDR - consul requires this to find your consul server
#
# additionally, you need to ensure that CONSUL_HTTP_TOKEN is available
# to access the consul server
#returns 0 means success, otherwise error.
######## Public functions #####################
#domain keyfile certfile cafile fullchain
consul_deploy() {
_cdomain="$1"
_ckey="$2"
_ccert="$3"
_cca="$4"
_cfullchain="$5"
_debug _cdomain "$_cdomain"
_debug _ckey "$_ckey"
_debug _ccert "$_ccert"
_debug _cca "$_cca"
_debug _cfullchain "$_cfullchain"
# validate required env vars
_getdeployconf CONSUL_PREFIX
if [ -z "$CONSUL_PREFIX" ]; then
_err "CONSUL_PREFIX needs to be defined (contains prefix path in vault)"
return 1
fi
_savedeployconf CONSUL_PREFIX "$CONSUL_PREFIX"
_getdeployconf CONSUL_HTTP_ADDR
if [ -z "$CONSUL_HTTP_ADDR" ]; then
_err "CONSUL_HTTP_ADDR needs to be defined (contains consul connection address)"
return 1
fi
_savedeployconf CONSUL_HTTP_ADDR "$CONSUL_HTTP_ADDR"
CONSUL_CMD=$(command -v consul)
# force CLI, but the binary does not exist => error
if [ -n "$USE_CLI" ] && [ -z "$CONSUL_CMD" ]; then
_err "Cannot find the consul binary!"
return 1
fi
# use the CLI first
if [ -n "$USE_CLI" ] || [ -n "$CONSUL_CMD" ]; then
_info "Found consul binary, deploying with CLI"
consul_deploy_cli "$CONSUL_CMD" "$CONSUL_PREFIX"
else
_info "Did not find consul binary, deploying with API"
consul_deploy_api "$CONSUL_HTTP_ADDR" "$CONSUL_PREFIX" "$CONSUL_HTTP_TOKEN"
fi
}
consul_deploy_api() {
CONSUL_HTTP_ADDR="$1"
CONSUL_PREFIX="$2"
CONSUL_HTTP_TOKEN="$3"
URL="$CONSUL_HTTP_ADDR/v1/kv/$CONSUL_PREFIX"
export _H1="X-Consul-Token: $CONSUL_HTTP_TOKEN"
if [ -n "$FABIO" ]; then
_post "$(cat "$_cfullchain")" "$URL/${_cdomain}-cert.pem" '' "PUT" || return 1
_post "$(cat "$_ckey")" "$URL/${_cdomain}-key.pem" '' "PUT" || return 1
else
_post "$(cat "$_ccert")" "$URL/${_cdomain}/cert.pem" '' "PUT" || return 1
_post "$(cat "$_ckey")" "$URL/${_cdomain}/cert.key" '' "PUT" || return 1
_post "$(cat "$_cca")" "$URL/${_cdomain}/chain.pem" '' "PUT" || return 1
_post "$(cat "$_cfullchain")" "$URL/${_cdomain}/fullchain.pem" '' "PUT" || return 1
fi
}
consul_deploy_cli() {
CONSUL_CMD="$1"
CONSUL_PREFIX="$2"
if [ -n "$FABIO" ]; then
$CONSUL_CMD kv put "${CONSUL_PREFIX}/${_cdomain}-cert.pem" @"$_cfullchain" || return 1
$CONSUL_CMD kv put "${CONSUL_PREFIX}/${_cdomain}-key.pem" @"$_ckey" || return 1
else
$CONSUL_CMD kv put "${CONSUL_PREFIX}/${_cdomain}/cert.pem" value=@"$_ccert" || return 1
$CONSUL_CMD kv put "${CONSUL_PREFIX}/${_cdomain}/cert.key" value=@"$_ckey" || return 1
$CONSUL_CMD kv put "${CONSUL_PREFIX}/${_cdomain}/chain.pem" value=@"$_cca" || return 1
$CONSUL_CMD kv put "${CONSUL_PREFIX}/${_cdomain}/fullchain.pem" value=@"$_cfullchain" || return 1
fi
}
+26 -18
View File
@@ -36,43 +36,51 @@ fritzbox_deploy() {
fi
fi
_fritzbox_username="${DEPLOY_FRITZBOX_USERNAME}"
_fritzbox_password="${DEPLOY_FRITZBOX_PASSWORD}"
_fritzbox_url="${DEPLOY_FRITZBOX_URL}"
# Clear traces of incorrectly stored values
_clearaccountconf DEPLOY_FRITZBOX_USERNAME
_clearaccountconf DEPLOY_FRITZBOX_PASSWORD
_clearaccountconf DEPLOY_FRITZBOX_URL
_debug _fritzbox_url "$_fritzbox_url"
_debug _fritzbox_username "$_fritzbox_username"
_secure_debug _fritzbox_password "$_fritzbox_password"
if [ -z "$_fritzbox_username" ]; then
# Read config from saved values or env
_getdeployconf DEPLOY_FRITZBOX_USERNAME
_getdeployconf DEPLOY_FRITZBOX_PASSWORD
_getdeployconf DEPLOY_FRITZBOX_URL
_debug DEPLOY_FRITZBOX_URL "$DEPLOY_FRITZBOX_URL"
_debug DEPLOY_FRITZBOX_USERNAME "$DEPLOY_FRITZBOX_USERNAME"
_secure_debug DEPLOY_FRITZBOX_PASSWORD "$DEPLOY_FRITZBOX_PASSWORD"
if [ -z "$DEPLOY_FRITZBOX_USERNAME" ]; then
_err "FRITZ!Box username is not found, please define DEPLOY_FRITZBOX_USERNAME."
return 1
fi
if [ -z "$_fritzbox_password" ]; then
if [ -z "$DEPLOY_FRITZBOX_PASSWORD" ]; then
_err "FRITZ!Box password is not found, please define DEPLOY_FRITZBOX_PASSWORD."
return 1
fi
if [ -z "$_fritzbox_url" ]; then
if [ -z "$DEPLOY_FRITZBOX_URL" ]; then
_err "FRITZ!Box url is not found, please define DEPLOY_FRITZBOX_URL."
return 1
fi
_saveaccountconf DEPLOY_FRITZBOX_USERNAME "${_fritzbox_username}"
_saveaccountconf DEPLOY_FRITZBOX_PASSWORD "${_fritzbox_password}"
_saveaccountconf DEPLOY_FRITZBOX_URL "${_fritzbox_url}"
# Save current values
_savedeployconf DEPLOY_FRITZBOX_USERNAME "$DEPLOY_FRITZBOX_USERNAME"
_savedeployconf DEPLOY_FRITZBOX_PASSWORD "$DEPLOY_FRITZBOX_PASSWORD"
_savedeployconf DEPLOY_FRITZBOX_URL "$DEPLOY_FRITZBOX_URL"
# Do not check for a valid SSL certificate, because initially the cert is not valid, so it could not install the LE generated certificate
export HTTPS_INSECURE=1
_info "Log in to the FRITZ!Box"
_fritzbox_challenge="$(_get "${_fritzbox_url}/login_sid.lua" | sed -e 's/^.*<Challenge>//' -e 's/<\/Challenge>.*$//')"
_fritzbox_challenge="$(_get "${DEPLOY_FRITZBOX_URL}/login_sid.lua" | sed -e 's/^.*<Challenge>//' -e 's/<\/Challenge>.*$//')"
if _exists iconv; then
_fritzbox_hash="$(printf "%s-%s" "${_fritzbox_challenge}" "${_fritzbox_password}" | iconv -f ASCII -t UTF16LE | _digest md5 hex)"
_fritzbox_hash="$(printf "%s-%s" "${_fritzbox_challenge}" "${DEPLOY_FRITZBOX_PASSWORD}" | iconv -f ASCII -t UTF16LE | _digest md5 hex)"
elif _exists uconv; then
_fritzbox_hash="$(printf "%s-%s" "${_fritzbox_challenge}" "${_fritzbox_password}" | uconv -f ASCII -t UTF16LE | _digest md5 hex)"
_fritzbox_hash="$(printf "%s-%s" "${_fritzbox_challenge}" "${DEPLOY_FRITZBOX_PASSWORD}" | uconv -f ASCII -t UTF16LE | _digest md5 hex)"
else
_fritzbox_hash="$(printf "%s-%s" "${_fritzbox_challenge}" "${_fritzbox_password}" | perl -p -e 'use Encode qw/encode/; print encode("UTF-16LE","$_"); $_="";' | _digest md5 hex)"
_fritzbox_hash="$(printf "%s-%s" "${_fritzbox_challenge}" "${DEPLOY_FRITZBOX_PASSWORD}" | perl -p -e 'use Encode qw/encode/; print encode("UTF-16LE","$_"); $_="";' | _digest md5 hex)"
fi
_fritzbox_sid="$(_get "${_fritzbox_url}/login_sid.lua?sid=0000000000000000&username=${_fritzbox_username}&response=${_fritzbox_challenge}-${_fritzbox_hash}" | sed -e 's/^.*<SID>//' -e 's/<\/SID>.*$//')"
_fritzbox_sid="$(_get "${DEPLOY_FRITZBOX_URL}/login_sid.lua?sid=0000000000000000&username=${DEPLOY_FRITZBOX_USERNAME}&response=${_fritzbox_challenge}-${_fritzbox_hash}" | sed -e 's/^.*<SID>//' -e 's/<\/SID>.*$//')"
if [ -z "${_fritzbox_sid}" ] || [ "${_fritzbox_sid}" = "0000000000000000" ]; then
_err "Logging in to the FRITZ!Box failed. Please check username, password and URL."
@@ -104,7 +112,7 @@ fritzbox_deploy() {
_info "Upload certificate to the FRITZ!Box"
export _H1="Content-type: multipart/form-data boundary=${_post_boundary}"
_post "$(cat "${_post_request}")" "${_fritzbox_url}/cgi-bin/firmwarecfg" | grep SSL
_post "$(cat "${_post_request}")" "${DEPLOY_FRITZBOX_URL}/cgi-bin/firmwarecfg" | grep SSL
retval=$?
if [ $retval = 0 ]; then
+15 -10
View File
@@ -54,11 +54,6 @@ haproxy_deploy() {
DEPLOY_HAPROXY_ISSUER_DEFAULT="no"
DEPLOY_HAPROXY_RELOAD_DEFAULT="true"
if [ -f "${DOMAIN_CONF}" ]; then
# shellcheck disable=SC1090
. "${DOMAIN_CONF}"
fi
_debug _cdomain "${_cdomain}"
_debug _ckey "${_ckey}"
_debug _ccert "${_ccert}"
@@ -66,6 +61,8 @@ haproxy_deploy() {
_debug _cfullchain "${_cfullchain}"
# PEM_PATH is optional. If not provided then assume "${DEPLOY_HAPROXY_PEM_PATH_DEFAULT}"
_getdeployconf DEPLOY_HAPROXY_PEM_PATH
_debug2 DEPLOY_HAPROXY_PEM_PATH "${DEPLOY_HAPROXY_PEM_PATH}"
if [ -n "${DEPLOY_HAPROXY_PEM_PATH}" ]; then
Le_Deploy_haproxy_pem_path="${DEPLOY_HAPROXY_PEM_PATH}"
_savedomainconf Le_Deploy_haproxy_pem_path "${Le_Deploy_haproxy_pem_path}"
@@ -82,6 +79,8 @@ haproxy_deploy() {
fi
# PEM_NAME is optional. If not provided then assume "${DEPLOY_HAPROXY_PEM_NAME_DEFAULT}"
_getdeployconf DEPLOY_HAPROXY_PEM_NAME
_debug2 DEPLOY_HAPROXY_PEM_NAME "${DEPLOY_HAPROXY_PEM_NAME}"
if [ -n "${DEPLOY_HAPROXY_PEM_NAME}" ]; then
Le_Deploy_haproxy_pem_name="${DEPLOY_HAPROXY_PEM_NAME}"
_savedomainconf Le_Deploy_haproxy_pem_name "${Le_Deploy_haproxy_pem_name}"
@@ -90,6 +89,8 @@ haproxy_deploy() {
fi
# BUNDLE is optional. If not provided then assume "${DEPLOY_HAPROXY_BUNDLE_DEFAULT}"
_getdeployconf DEPLOY_HAPROXY_BUNDLE
_debug2 DEPLOY_HAPROXY_BUNDLE "${DEPLOY_HAPROXY_BUNDLE}"
if [ -n "${DEPLOY_HAPROXY_BUNDLE}" ]; then
Le_Deploy_haproxy_bundle="${DEPLOY_HAPROXY_BUNDLE}"
_savedomainconf Le_Deploy_haproxy_bundle "${Le_Deploy_haproxy_bundle}"
@@ -98,6 +99,8 @@ haproxy_deploy() {
fi
# ISSUER is optional. If not provided then assume "${DEPLOY_HAPROXY_ISSUER_DEFAULT}"
_getdeployconf DEPLOY_HAPROXY_ISSUER
_debug2 DEPLOY_HAPROXY_ISSUER "${DEPLOY_HAPROXY_ISSUER}"
if [ -n "${DEPLOY_HAPROXY_ISSUER}" ]; then
Le_Deploy_haproxy_issuer="${DEPLOY_HAPROXY_ISSUER}"
_savedomainconf Le_Deploy_haproxy_issuer "${Le_Deploy_haproxy_issuer}"
@@ -106,6 +109,8 @@ haproxy_deploy() {
fi
# RELOAD is optional. If not provided then assume "${DEPLOY_HAPROXY_RELOAD_DEFAULT}"
_getdeployconf DEPLOY_HAPROXY_RELOAD
_debug2 DEPLOY_HAPROXY_RELOAD "${DEPLOY_HAPROXY_RELOAD}"
if [ -n "${DEPLOY_HAPROXY_RELOAD}" ]; then
Le_Deploy_haproxy_reload="${DEPLOY_HAPROXY_RELOAD}"
_savedomainconf Le_Deploy_haproxy_reload "${Le_Deploy_haproxy_reload}"
@@ -190,7 +195,7 @@ haproxy_deploy() {
_info "Updating OCSP stapling info"
_debug _ocsp "${_ocsp}"
_info "Extracting OCSP URL"
_ocsp_url=$(openssl x509 -noout -ocsp_uri -in "${_pem}")
_ocsp_url=$(${ACME_OPENSSL_BIN:-openssl} x509 -noout -ocsp_uri -in "${_pem}")
_debug _ocsp_url "${_ocsp_url}"
# Only process OCSP if URL was present
@@ -203,9 +208,9 @@ haproxy_deploy() {
# Only process the certificate if we have a .issuer file
if [ -r "${_issuer}" ]; then
# Check if issuer cert is also a root CA cert
_subjectdn=$(openssl x509 -in "${_issuer}" -subject -noout | cut -d'/' -f2,3,4,5,6,7,8,9,10)
_subjectdn=$(${ACME_OPENSSL_BIN:-openssl} x509 -in "${_issuer}" -subject -noout | cut -d'/' -f2,3,4,5,6,7,8,9,10)
_debug _subjectdn "${_subjectdn}"
_issuerdn=$(openssl x509 -in "${_issuer}" -issuer -noout | cut -d'/' -f2,3,4,5,6,7,8,9,10)
_issuerdn=$(${ACME_OPENSSL_BIN:-openssl} x509 -in "${_issuer}" -issuer -noout | cut -d'/' -f2,3,4,5,6,7,8,9,10)
_debug _issuerdn "${_issuerdn}"
_info "Requesting OCSP response"
# If the issuer is a CA cert then our command line has "-CAfile" added
@@ -216,7 +221,7 @@ haproxy_deploy() {
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)
_openssl_version=$(${ACME_OPENSSL_BIN:-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)
@@ -226,7 +231,7 @@ haproxy_deploy() {
_header_sep=" "
fi
# Request the OCSP response from the issuer and store it
_openssl_ocsp_cmd="openssl ocsp \
_openssl_ocsp_cmd="${ACME_OPENSSL_BIN:-openssl} ocsp \
-issuer \"${_issuer}\" \
-cert \"${_pem}\" \
-url \"${_ocsp_url}\" \
+1 -1
View File
@@ -45,7 +45,7 @@ kong_deploy() {
#Generate data for request (Multipart/form-data with mixed content)
if [ -z "$ssl_uuid" ]; then
#set sni to domain
content="--$delim${nl}Content-Disposition: form-data; name=\"snis\"${nl}${nl}$_cdomain"
content="--$delim${nl}Content-Disposition: form-data; name=\"snis[]\"${nl}${nl}$_cdomain"
fi
#add key
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"key\"; filename=\"$(basename "$_ckey")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ckey")"
+280
View File
@@ -0,0 +1,280 @@
#!/usr/bin/env sh
# Script for acme.sh to deploy certificates to lighttpd
#
# The following variables can be exported:
#
# export DEPLOY_LIGHTTPD_PEM_NAME="${domain}.pem"
#
# Defines the name of the PEM file.
# Defaults to "<domain>.pem"
#
# export DEPLOY_LIGHTTPD_PEM_PATH="/etc/lighttpd"
#
# Defines location of PEM file for Lighttpd.
# Defaults to /etc/lighttpd
#
# export DEPLOY_LIGHTTPD_RELOAD="systemctl reload lighttpd"
#
# OPTIONAL: Reload command used post deploy
# This defaults to be a no-op (ie "true").
# It is strongly recommended to set this something that makes sense
# for your distro.
#
# export DEPLOY_LIGHTTPD_ISSUER="yes"
#
# OPTIONAL: Places CA file as "${DEPLOY_LIGHTTPD_PEM}.issuer"
# Note: Required for OCSP stapling to work
#
# export DEPLOY_LIGHTTPD_BUNDLE="no"
#
# OPTIONAL: Deploy this certificate as part of a multi-cert bundle
# This adds a suffix to the certificate based on the certificate type
# eg RSA certificates will have .rsa as a suffix to the file name
# Lighttpd will load all certificates and provide one or the other
# depending on client capabilities
# Note: This functionality requires Lighttpd was compiled against
# a version of OpenSSL that supports this.
#
######## Public functions #####################
#domain keyfile certfile cafile fullchain
lighttpd_deploy() {
_cdomain="$1"
_ckey="$2"
_ccert="$3"
_cca="$4"
_cfullchain="$5"
# Some defaults
DEPLOY_LIGHTTPD_PEM_PATH_DEFAULT="/etc/lighttpd"
DEPLOY_LIGHTTPD_PEM_NAME_DEFAULT="${_cdomain}.pem"
DEPLOY_LIGHTTPD_BUNDLE_DEFAULT="no"
DEPLOY_LIGHTTPD_ISSUER_DEFAULT="yes"
DEPLOY_LIGHTTPD_RELOAD_DEFAULT="true"
_debug _cdomain "${_cdomain}"
_debug _ckey "${_ckey}"
_debug _ccert "${_ccert}"
_debug _cca "${_cca}"
_debug _cfullchain "${_cfullchain}"
# PEM_PATH is optional. If not provided then assume "${DEPLOY_LIGHTTPD_PEM_PATH_DEFAULT}"
_getdeployconf DEPLOY_LIGHTTPD_PEM_PATH
_debug2 DEPLOY_LIGHTTPD_PEM_PATH "${DEPLOY_LIGHTTPD_PEM_PATH}"
if [ -n "${DEPLOY_LIGHTTPD_PEM_PATH}" ]; then
Le_Deploy_lighttpd_pem_path="${DEPLOY_LIGHTTPD_PEM_PATH}"
_savedomainconf Le_Deploy_lighttpd_pem_path "${Le_Deploy_lighttpd_pem_path}"
elif [ -z "${Le_Deploy_lighttpd_pem_path}" ]; then
Le_Deploy_lighttpd_pem_path="${DEPLOY_LIGHTTPD_PEM_PATH_DEFAULT}"
fi
# Ensure PEM_PATH exists
if [ -d "${Le_Deploy_lighttpd_pem_path}" ]; then
_debug "PEM_PATH ${Le_Deploy_lighttpd_pem_path} exists"
else
_err "PEM_PATH ${Le_Deploy_lighttpd_pem_path} does not exist"
return 1
fi
# PEM_NAME is optional. If not provided then assume "${DEPLOY_LIGHTTPD_PEM_NAME_DEFAULT}"
_getdeployconf DEPLOY_LIGHTTPD_PEM_NAME
_debug2 DEPLOY_LIGHTTPD_PEM_NAME "${DEPLOY_LIGHTTPD_PEM_NAME}"
if [ -n "${DEPLOY_LIGHTTPD_PEM_NAME}" ]; then
Le_Deploy_lighttpd_pem_name="${DEPLOY_LIGHTTPD_PEM_NAME}"
_savedomainconf Le_Deploy_lighttpd_pem_name "${Le_Deploy_lighttpd_pem_name}"
elif [ -z "${Le_Deploy_lighttpd_pem_name}" ]; then
Le_Deploy_lighttpd_pem_name="${DEPLOY_LIGHTTPD_PEM_NAME_DEFAULT}"
fi
# BUNDLE is optional. If not provided then assume "${DEPLOY_LIGHTTPD_BUNDLE_DEFAULT}"
_getdeployconf DEPLOY_LIGHTTPD_BUNDLE
_debug2 DEPLOY_LIGHTTPD_BUNDLE "${DEPLOY_LIGHTTPD_BUNDLE}"
if [ -n "${DEPLOY_LIGHTTPD_BUNDLE}" ]; then
Le_Deploy_lighttpd_bundle="${DEPLOY_LIGHTTPD_BUNDLE}"
_savedomainconf Le_Deploy_lighttpd_bundle "${Le_Deploy_lighttpd_bundle}"
elif [ -z "${Le_Deploy_lighttpd_bundle}" ]; then
Le_Deploy_lighttpd_bundle="${DEPLOY_LIGHTTPD_BUNDLE_DEFAULT}"
fi
# ISSUER is optional. If not provided then assume "${DEPLOY_LIGHTTPD_ISSUER_DEFAULT}"
_getdeployconf DEPLOY_LIGHTTPD_ISSUER
_debug2 DEPLOY_LIGHTTPD_ISSUER "${DEPLOY_LIGHTTPD_ISSUER}"
if [ -n "${DEPLOY_LIGHTTPD_ISSUER}" ]; then
Le_Deploy_lighttpd_issuer="${DEPLOY_LIGHTTPD_ISSUER}"
_savedomainconf Le_Deploy_lighttpd_issuer "${Le_Deploy_lighttpd_issuer}"
elif [ -z "${Le_Deploy_lighttpd_issuer}" ]; then
Le_Deploy_lighttpd_issuer="${DEPLOY_LIGHTTPD_ISSUER_DEFAULT}"
fi
# RELOAD is optional. If not provided then assume "${DEPLOY_LIGHTTPD_RELOAD_DEFAULT}"
_getdeployconf DEPLOY_LIGHTTPD_RELOAD
_debug2 DEPLOY_LIGHTTPD_RELOAD "${DEPLOY_LIGHTTPD_RELOAD}"
if [ -n "${DEPLOY_LIGHTTPD_RELOAD}" ]; then
Le_Deploy_lighttpd_reload="${DEPLOY_LIGHTTPD_RELOAD}"
_savedomainconf Le_Deploy_lighttpd_reload "${Le_Deploy_lighttpd_reload}"
elif [ -z "${Le_Deploy_lighttpd_reload}" ]; then
Le_Deploy_lighttpd_reload="${DEPLOY_LIGHTTPD_RELOAD_DEFAULT}"
fi
# Set the suffix depending if we are creating a bundle or not
if [ "${Le_Deploy_lighttpd_bundle}" = "yes" ]; then
_info "Bundle creation requested"
# Initialise $Le_Keylength if its not already set
if [ -z "${Le_Keylength}" ]; then
Le_Keylength=""
fi
if _isEccKey "${Le_Keylength}"; then
_info "ECC key type detected"
_suffix=".ecdsa"
else
_info "RSA key type detected"
_suffix=".rsa"
fi
else
_suffix=""
fi
_debug _suffix "${_suffix}"
# Set variables for later
_pem="${Le_Deploy_lighttpd_pem_path}/${Le_Deploy_lighttpd_pem_name}${_suffix}"
_issuer="${_pem}.issuer"
_ocsp="${_pem}.ocsp"
_reload="${Le_Deploy_lighttpd_reload}"
_info "Deploying PEM file"
# Create a temporary PEM file
_temppem="$(_mktemp)"
_debug _temppem "${_temppem}"
cat "${_ckey}" "${_ccert}" "${_cca}" >"${_temppem}"
_ret="$?"
# Check that we could create the temporary file
if [ "${_ret}" != "0" ]; then
_err "Error code ${_ret} returned during PEM file creation"
[ -f "${_temppem}" ] && rm -f "${_temppem}"
return ${_ret}
fi
# Move PEM file into place
_info "Moving new certificate into place"
_debug _pem "${_pem}"
cat "${_temppem}" >"${_pem}"
_ret=$?
# Clean up temp file
[ -f "${_temppem}" ] && rm -f "${_temppem}"
# Deal with any failure of moving PEM file into place
if [ "${_ret}" != "0" ]; then
_err "Error code ${_ret} returned while moving new certificate into place"
return ${_ret}
fi
# Update .issuer file if requested
if [ "${Le_Deploy_lighttpd_issuer}" = "yes" ]; then
_info "Updating .issuer file"
_debug _issuer "${_issuer}"
cat "${_cca}" >"${_issuer}"
_ret="$?"
if [ "${_ret}" != "0" ]; then
_err "Error code ${_ret} returned while copying issuer/CA certificate into place"
return ${_ret}
fi
else
[ -f "${_issuer}" ] && _err "Issuer file update not requested but .issuer file exists"
fi
# Update .ocsp file if certificate was requested with --ocsp/--ocsp-must-staple option
if [ -z "${Le_OCSP_Staple}" ]; then
Le_OCSP_Staple="0"
fi
if [ "${Le_OCSP_Staple}" = "1" ]; then
_info "Updating OCSP stapling info"
_debug _ocsp "${_ocsp}"
_info "Extracting OCSP URL"
_ocsp_url=$(${ACME_OPENSSL_BIN:-openssl} x509 -noout -ocsp_uri -in "${_pem}")
_debug _ocsp_url "${_ocsp_url}"
# Only process OCSP if URL was present
if [ "${_ocsp_url}" != "" ]; then
# Extract the hostname from the OCSP URL
_info "Extracting OCSP URL"
_ocsp_host=$(echo "${_ocsp_url}" | cut -d/ -f3)
_debug _ocsp_host "${_ocsp_host}"
# Only process the certificate if we have a .issuer file
if [ -r "${_issuer}" ]; then
# Check if issuer cert is also a root CA cert
_subjectdn=$(${ACME_OPENSSL_BIN:-openssl} x509 -in "${_issuer}" -subject -noout | cut -d'/' -f2,3,4,5,6,7,8,9,10)
_debug _subjectdn "${_subjectdn}"
_issuerdn=$(${ACME_OPENSSL_BIN:-openssl} x509 -in "${_issuer}" -issuer -noout | cut -d'/' -f2,3,4,5,6,7,8,9,10)
_debug _issuerdn "${_issuerdn}"
_info "Requesting OCSP response"
# If the issuer is a CA cert then our command line has "-CAfile" added
if [ "${_subjectdn}" = "${_issuerdn}" ]; then
_cafile_argument="-CAfile \"${_issuer}\""
else
_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=$(${ACME_OPENSSL_BIN:-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="${ACME_OPENSSL_BIN:-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"
fi
else
# Non fatal: No OCSP url was found int the certificate
_err "OCSP update requested but no OCSP URL was found in certificate"
fi
# Non fatal: Check return code of openssl command
if [ "${_ret}" != "0" ]; then
_err "Updating OCSP stapling failed with return code ${_ret}"
fi
else
# An OCSP file was already present but certificate did not have OCSP extension
if [ -f "${_ocsp}" ]; then
_err "OCSP was not requested but .ocsp file exists."
# Could remove the file at this step, although Lighttpd just ignores it in this case
# rm -f "${_ocsp}" || _err "Problem removing stale .ocsp file"
fi
fi
# Reload Lighttpd
_debug _reload "${_reload}"
eval "${_reload}"
_ret=$?
if [ "${_ret}" != "0" ]; then
_err "Error code ${_ret} during reload"
return ${_ret}
else
_info "Reload successful"
fi
return 0
}
+16 -12
View File
@@ -20,18 +20,23 @@ mailcow_deploy() {
_debug _cca "$_cca"
_debug _cfullchain "$_cfullchain"
_mailcow_path="${DEPLOY_MAILCOW_PATH}"
_getdeployconf DEPLOY_MAILCOW_PATH
_getdeployconf DEPLOY_MAILCOW_RELOAD
if [ -z "$_mailcow_path" ]; then
_debug DEPLOY_MAILCOW_PATH "$DEPLOY_MAILCOW_PATH"
_debug DEPLOY_MAILCOW_RELOAD "$DEPLOY_MAILCOW_RELOAD"
if [ -z "$DEPLOY_MAILCOW_PATH" ]; then
_err "Mailcow path is not found, please define DEPLOY_MAILCOW_PATH."
return 1
fi
#Tests if _ssl_path is the mailcow root directory.
if [ -f "${_mailcow_path}/generate_config.sh" ]; then
_ssl_path="${_mailcow_path}/data/assets/ssl/"
else
_ssl_path="${_mailcow_path}"
_savedeployconf DEPLOY_MAILCOW_PATH "$DEPLOY_MAILCOW_PATH"
[ -n "$DEPLOY_MAILCOW_RELOAD" ] && _savedeployconf DEPLOY_MAILCOW_RELOAD "$DEPLOY_MAILCOW_RELOAD"
_ssl_path="$DEPLOY_MAILCOW_PATH"
if [ -f "$DEPLOY_MAILCOW_PATH/generate_config.sh" ]; then
_ssl_path="$DEPLOY_MAILCOW_PATH/data/assets/ssl/"
fi
if [ ! -d "$_ssl_path" ]; then
@@ -40,16 +45,15 @@ mailcow_deploy() {
fi
# ECC or RSA
if [ -z "${Le_Keylength}" ]; then
Le_Keylength=""
fi
if _isEccKey "${Le_Keylength}"; then
length=$(_readdomainconf Le_Keylength)
if _isEccKey "$length"; then
_info "ECC key type detected"
_cert_name_prefix="ecdsa-"
else
_info "RSA key type detected"
_cert_name_prefix=""
fi
_info "Copying key and cert"
_real_key="$_ssl_path/${_cert_name_prefix}key.pem"
if ! cat "$_ckey" >"$_real_key"; then
@@ -63,7 +67,7 @@ mailcow_deploy() {
return 1
fi
DEFAULT_MAILCOW_RELOAD="docker restart $(docker ps -qaf name=postfix-mailcow); docker restart $(docker ps -qaf name=nginx-mailcow); docker restart $(docker ps -qaf name=dovecot-mailcow)"
DEFAULT_MAILCOW_RELOAD="docker restart \$(docker ps --quiet --filter name=nginx-mailcow --filter name=dovecot-mailcow)"
_reload="${DEPLOY_MAILCOW_RELOAD:-$DEFAULT_MAILCOW_RELOAD}"
_info "Run reload: $_reload"
+156
View File
@@ -0,0 +1,156 @@
#!/usr/bin/env sh
# This deploy hook is tested on OpenMediaVault 5.x. It supports both local and remote deployment.
# The way it works is that if a cert with the matching domain name is not found, it will firstly create a dummy cert to get its uuid, and then replace it with your cert.
#
# DEPLOY_OMV_WEBUI_ADMIN - This is OMV web gui admin account. Default value is admin. It's required as the user parameter (-u) for the omv-rpc command.
# DEPLOY_OMV_HOST and DEPLOY_OMV_SSH_USER are optional. They are used for remote deployment through ssh (support public key authentication only). Per design, OMV web gui admin doesn't have ssh permission, so another account is needed for ssh.
#
# returns 0 means success, otherwise error.
######## Public functions #####################
#domain keyfile certfile cafile fullchain
openmediavault_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"
_getdeployconf DEPLOY_OMV_WEBUI_ADMIN
if [ -z "$DEPLOY_OMV_WEBUI_ADMIN" ]; then
DEPLOY_OMV_WEBUI_ADMIN="admin"
fi
_savedeployconf DEPLOY_OMV_WEBUI_ADMIN "$DEPLOY_OMV_WEBUI_ADMIN"
_getdeployconf DEPLOY_OMV_HOST
_getdeployconf DEPLOY_OMV_SSH_USER
if [ -n "$DEPLOY_OMV_HOST" ] && [ -n "$DEPLOY_OMV_SSH_USER" ]; then
_info "[OMV deploy-hook] Deploy certificate remotely through ssh."
_savedeployconf DEPLOY_OMV_HOST "$DEPLOY_OMV_HOST"
_savedeployconf DEPLOY_OMV_SSH_USER "$DEPLOY_OMV_SSH_USER"
else
_info "[OMV deploy-hook] Deploy certificate locally."
fi
if [ -n "$DEPLOY_OMV_HOST" ] && [ -n "$DEPLOY_OMV_SSH_USER" ]; then
_command="omv-rpc -u $DEPLOY_OMV_WEBUI_ADMIN 'CertificateMgmt' 'getList' '{\"start\": 0, \"limit\": -1}' | jq -r '.data[] | select(.name==\"/CN='$_cdomain'\") | .uuid'"
# shellcheck disable=SC2029
_uuid=$(ssh "$DEPLOY_OMV_SSH_USER@$DEPLOY_OMV_HOST" "$_command")
_debug _command "$_command"
if [ -z "$_uuid" ]; then
_info "[OMV deploy-hook] Domain $_cdomain has no certificate in openmediavault, creating it!"
_command="omv-rpc -u $DEPLOY_OMV_WEBUI_ADMIN 'CertificateMgmt' 'create' '{\"cn\": \"test.example.com\", \"size\": 4096, \"days\": 3650, \"c\": \"\", \"st\": \"\", \"l\": \"\", \"o\": \"\", \"ou\": \"\", \"email\": \"\"}' | jq -r '.uuid'"
# shellcheck disable=SC2029
_uuid=$(ssh "$DEPLOY_OMV_SSH_USER@$DEPLOY_OMV_HOST" "$_command")
_debug _command "$_command"
if [ -z "$_uuid" ]; then
_err "[OMV deploy-hook] An error occured while creating the certificate"
return 1
fi
fi
_info "[OMV deploy-hook] Domain $_cdomain has uuid: $_uuid"
_fullchain=$(jq <"$_cfullchain" -aRs .)
_key=$(jq <"$_ckey" -aRs .)
_debug _fullchain "$_fullchain"
_debug _key "$_key"
_info "[OMV deploy-hook] Updating key and certificate in openmediavault"
_command="omv-rpc -u $DEPLOY_OMV_WEBUI_ADMIN 'CertificateMgmt' 'set' '{\"uuid\":\"$_uuid\", \"certificate\":$_fullchain, \"privatekey\":$_key, \"comment\":\"acme.sh deployed $(date)\"}'"
# shellcheck disable=SC2029
_result=$(ssh "$DEPLOY_OMV_SSH_USER@$DEPLOY_OMV_HOST" "$_command")
_debug _command "$_command"
_debug _result "$_result"
_command="omv-rpc -u $DEPLOY_OMV_WEBUI_ADMIN 'WebGui' 'setSettings' \$(omv-rpc -u $DEPLOY_OMV_WEBUI_ADMIN 'WebGui' 'getSettings' | jq -c '.sslcertificateref=\"$_uuid\"')"
# shellcheck disable=SC2029
_result=$(ssh "$DEPLOY_OMV_SSH_USER@$DEPLOY_OMV_HOST" "$_command")
_debug _command "$_command"
_debug _result "$_result"
_info "[OMV deploy-hook] Asking openmediavault to apply changes... (this could take some time, hang in there)"
_command="omv-rpc -u $DEPLOY_OMV_WEBUI_ADMIN 'Config' 'applyChanges' '{\"modules\":[], \"force\": false}'"
# shellcheck disable=SC2029
_result=$(ssh "$DEPLOY_OMV_SSH_USER@$DEPLOY_OMV_HOST" "$_command")
_debug _command "$_command"
_debug _result "$_result"
_info "[OMV deploy-hook] Asking nginx to reload"
_command="nginx -s reload"
# shellcheck disable=SC2029
_result=$(ssh "$DEPLOY_OMV_SSH_USER@$DEPLOY_OMV_HOST" "$_command")
_debug _command "$_command"
_debug _result "$_result"
else
# shellcheck disable=SC2086
_uuid=$(omv-rpc -u $DEPLOY_OMV_WEBUI_ADMIN 'CertificateMgmt' 'getList' '{"start": 0, "limit": -1}' | jq -r '.data[] | select(.name=="/CN='$_cdomain'") | .uuid')
if [ -z "$_uuid" ]; then
_info "[OMV deploy-hook] Domain $_cdomain has no certificate in openmediavault, creating it!"
# shellcheck disable=SC2086
_uuid=$(omv-rpc -u $DEPLOY_OMV_WEBUI_ADMIN 'CertificateMgmt' 'create' '{"cn": "test.example.com", "size": 4096, "days": 3650, "c": "", "st": "", "l": "", "o": "", "ou": "", "email": ""}' | jq -r '.uuid')
if [ -z "$_uuid" ]; then
_err "[OMB deploy-hook] An error occured while creating the certificate"
return 1
fi
fi
_info "[OMV deploy-hook] Domain $_cdomain has uuid: $_uuid"
_fullchain=$(jq <"$_cfullchain" -aRs .)
_key=$(jq <"$_ckey" -aRs .)
_debug _fullchain "$_fullchain"
_debug _key "$_key"
_info "[OMV deploy-hook] Updating key and certificate in openmediavault"
_command="omv-rpc -u $DEPLOY_OMV_WEBUI_ADMIN 'CertificateMgmt' 'set' '{\"uuid\":\"$_uuid\", \"certificate\":$_fullchain, \"privatekey\":$_key, \"comment\":\"acme.sh deployed $(date)\"}'"
_result=$(eval "$_command")
_debug _command "$_command"
_debug _result "$_result"
_command="omv-rpc -u $DEPLOY_OMV_WEBUI_ADMIN 'WebGui' 'setSettings' \$(omv-rpc -u $DEPLOY_OMV_WEBUI_ADMIN 'WebGui' 'getSettings' | jq -c '.sslcertificateref=\"$_uuid\"')"
_result=$(eval "$_command")
_debug _command "$_command"
_debug _result "$_result"
_info "[OMV deploy-hook] Asking openmediavault to apply changes... (this could take some time, hang in there)"
_command="omv-rpc -u $DEPLOY_OMV_WEBUI_ADMIN 'Config' 'applyChanges' '{\"modules\":[], \"force\": false}'"
_result=$(eval "$_command")
_debug _command "$_command"
_debug _result "$_result"
_info "[OMV deploy-hook] Asking nginx to reload"
_command="nginx -s reload"
_result=$(eval "$_command")
_debug _command "$_command"
_debug _result "$_result"
fi
return 0
}
+105 -13
View File
@@ -23,6 +23,7 @@
# ```sh
# export ROUTER_OS_USERNAME=certuser
# export ROUTER_OS_HOST=router.example.com
# export ROUTER_OS_PORT=22
#
# acme.sh --deploy -d ftp.example.com --deploy-hook routeros
# ```
@@ -48,6 +49,16 @@
# One optional thing to do as well is to create a script that updates
# all the required services and run that script in a single command.
#
# To adopt parameters to `scp` and/or `ssh` set the optional
# `ROUTER_OS_SSH_CMD` and `ROUTER_OS_SCP_CMD` variables accordingly,
# see ssh(1) and scp(1) for parameters to those commands.
#
# Example:
# ```ssh
# export ROUTER_OS_SSH_CMD="ssh -i /acme.sh/.ssh/router.example.com -o UserKnownHostsFile=/acme.sh/.ssh/known_hosts"
# export ROUTER_OS_SCP_CMD="scp -i /acme.sh/.ssh/router.example.com -o UserKnownHostsFile=/acme.sh/.ssh/known_hosts"
# ````
#
# returns 0 means success, otherwise error.
######## Public functions #####################
@@ -59,6 +70,7 @@ routeros_deploy() {
_ccert="$3"
_cca="$4"
_cfullchain="$5"
_err_code=0
_debug _cdomain "$_cdomain"
_debug _ckey "$_ckey"
@@ -66,29 +78,70 @@ routeros_deploy() {
_debug _cca "$_cca"
_debug _cfullchain "$_cfullchain"
_getdeployconf ROUTER_OS_HOST
if [ -z "$ROUTER_OS_HOST" ]; then
_debug "Using _cdomain as ROUTER_OS_HOST, please set if not correct."
ROUTER_OS_HOST="$_cdomain"
fi
_getdeployconf ROUTER_OS_USERNAME
if [ -z "$ROUTER_OS_USERNAME" ]; then
_err "Need to set the env variable ROUTER_OS_USERNAME"
return 1
fi
_getdeployconf ROUTER_OS_PORT
if [ -z "$ROUTER_OS_PORT" ]; then
_debug "Using default port 22 as ROUTER_OS_PORT, please set if not correct."
ROUTER_OS_PORT=22
fi
_getdeployconf ROUTER_OS_SSH_CMD
if [ -z "$ROUTER_OS_SSH_CMD" ]; then
_debug "Use default ssh setup."
ROUTER_OS_SSH_CMD="ssh -p $ROUTER_OS_PORT"
fi
_getdeployconf ROUTER_OS_SCP_CMD
if [ -z "$ROUTER_OS_SCP_CMD" ]; then
_debug "USe default scp setup."
ROUTER_OS_SCP_CMD="scp -P $ROUTER_OS_PORT"
fi
_getdeployconf ROUTER_OS_ADDITIONAL_SERVICES
if [ -z "$ROUTER_OS_ADDITIONAL_SERVICES" ]; then
_debug "Not enabling additional services"
ROUTER_OS_ADDITIONAL_SERVICES=""
fi
_info "Trying to push key '$_ckey' to router"
scp "$_ckey" "$ROUTER_OS_USERNAME@$ROUTER_OS_HOST:$_cdomain.key"
_info "Trying to push cert '$_cfullchain' to router"
scp "$_cfullchain" "$ROUTER_OS_USERNAME@$ROUTER_OS_HOST:$_cdomain.cer"
DEPLOY_SCRIPT_CMD="/system script add name=\"LE Cert Deploy - $_cdomain\" owner=admin policy=ftp,read,write,password,sensitive \
source=\"## generated by routeros deploy script in acme.sh;\
\n/certificate remove [ find name=$_cdomain.cer_0 ];\
_savedeployconf ROUTER_OS_HOST "$ROUTER_OS_HOST"
_savedeployconf ROUTER_OS_USERNAME "$ROUTER_OS_USERNAME"
_savedeployconf ROUTER_OS_PORT "$ROUTER_OS_PORT"
_savedeployconf ROUTER_OS_SSH_CMD "$ROUTER_OS_SSH_CMD"
_savedeployconf ROUTER_OS_SCP_CMD "$ROUTER_OS_SCP_CMD"
_savedeployconf ROUTER_OS_ADDITIONAL_SERVICES "$ROUTER_OS_ADDITIONAL_SERVICES"
# push key to routeros
if ! _scp_certificate "$_ckey" "$ROUTER_OS_USERNAME@$ROUTER_OS_HOST:$_cdomain.key"; then
return $_err_code
fi
# push certificate chain to routeros
if ! _scp_certificate "$_cfullchain" "$ROUTER_OS_USERNAME@$ROUTER_OS_HOST:$_cdomain.cer"; then
return $_err_code
fi
DEPLOY_SCRIPT_CMD="/system script add name=\"LE Cert Deploy - $_cdomain\" owner=$ROUTER_OS_USERNAME \
comment=\"generated by routeros deploy script in acme.sh\" \
source=\"/certificate remove [ find name=$_cdomain.cer_0 ];\
\n/certificate remove [ find name=$_cdomain.cer_1 ];\
\n/certificate remove [ find name=$_cdomain.cer_2 ];\
\ndelay 1;\
\n/certificate import file-name=$_cdomain.cer passphrase=\\\"\\\";\
\n/certificate import file-name=$_cdomain.key passphrase=\\\"\\\";\
@@ -100,12 +153,51 @@ source=\"## generated by routeros deploy script in acme.sh;\
\n$ROUTER_OS_ADDITIONAL_SERVICES;\
\n\"
"
# shellcheck disable=SC2029
ssh "$ROUTER_OS_USERNAME@$ROUTER_OS_HOST" "$DEPLOY_SCRIPT_CMD"
# shellcheck disable=SC2029
ssh "$ROUTER_OS_USERNAME@$ROUTER_OS_HOST" "/system script run \"LE Cert Deploy - $_cdomain\""
# shellcheck disable=SC2029
ssh "$ROUTER_OS_USERNAME@$ROUTER_OS_HOST" "/system script remove \"LE Cert Deploy - $_cdomain\""
if ! _ssh_remote_cmd "$DEPLOY_SCRIPT_CMD"; then
return $_err_code
fi
if ! _ssh_remote_cmd "/system script run \"LE Cert Deploy - $_cdomain\""; then
return $_err_code
fi
if ! _ssh_remote_cmd "/system script remove \"LE Cert Deploy - $_cdomain\""; then
return $_err_code
fi
return 0
}
# inspired by deploy/ssh.sh
_ssh_remote_cmd() {
_cmd="$1"
_secure_debug "Remote commands to execute: $_cmd"
_info "Submitting sequence of commands to routeros"
# quotations in bash cmd below intended. Squash travis spellcheck error
# shellcheck disable=SC2029
$ROUTER_OS_SSH_CMD "$ROUTER_OS_USERNAME@$ROUTER_OS_HOST" "$_cmd"
_err_code="$?"
if [ "$_err_code" != "0" ]; then
_err "Error code $_err_code returned from routeros"
fi
return $_err_code
}
_scp_certificate() {
_src="$1"
_dst="$2"
_secure_debug "scp '$_src' to '$_dst'"
_info "Push key '$_src' to routeros"
$ROUTER_OS_SCP_CMD "$_src" "$_dst"
_err_code="$?"
if [ "$_err_code" != "0" ]; then
_err "Error code $_err_code returned from scp"
fi
return $_err_code
}
+22 -5
View File
@@ -35,11 +35,6 @@ ssh_deploy() {
_cfullchain="$5"
_deploy_ssh_servers=""
if [ -f "$DOMAIN_CONF" ]; then
# shellcheck disable=SC1090
. "$DOMAIN_CONF"
fi
_debug _cdomain "$_cdomain"
_debug _ckey "$_ckey"
_debug _ccert "$_ccert"
@@ -47,6 +42,8 @@ ssh_deploy() {
_debug _cfullchain "$_cfullchain"
# USER is required to login by SSH to remote host.
_getdeployconf DEPLOY_SSH_USER
_debug2 DEPLOY_SSH_USER "$DEPLOY_SSH_USER"
if [ -z "$DEPLOY_SSH_USER" ]; then
if [ -z "$Le_Deploy_ssh_user" ]; then
_err "DEPLOY_SSH_USER not defined."
@@ -58,6 +55,8 @@ ssh_deploy() {
fi
# SERVER is optional. If not provided then use _cdomain
_getdeployconf DEPLOY_SSH_SERVER
_debug2 DEPLOY_SSH_SERVER "$DEPLOY_SSH_SERVER"
if [ -n "$DEPLOY_SSH_SERVER" ]; then
Le_Deploy_ssh_server="$DEPLOY_SSH_SERVER"
_savedomainconf Le_Deploy_ssh_server "$Le_Deploy_ssh_server"
@@ -66,6 +65,8 @@ ssh_deploy() {
fi
# CMD is optional. If not provided then use ssh
_getdeployconf DEPLOY_SSH_CMD
_debug2 DEPLOY_SSH_CMD "$DEPLOY_SSH_CMD"
if [ -n "$DEPLOY_SSH_CMD" ]; then
Le_Deploy_ssh_cmd="$DEPLOY_SSH_CMD"
_savedomainconf Le_Deploy_ssh_cmd "$Le_Deploy_ssh_cmd"
@@ -74,6 +75,8 @@ ssh_deploy() {
fi
# BACKUP is optional. If not provided then default to previously saved value or yes.
_getdeployconf DEPLOY_SSH_BACKUP
_debug2 DEPLOY_SSH_BACKUP "$DEPLOY_SSH_BACKUP"
if [ "$DEPLOY_SSH_BACKUP" = "no" ]; then
Le_Deploy_ssh_backup="no"
elif [ -z "$Le_Deploy_ssh_backup" ] || [ "$DEPLOY_SSH_BACKUP" = "yes" ]; then
@@ -82,6 +85,8 @@ ssh_deploy() {
_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
_getdeployconf DEPLOY_SSH_BACKUP_PATH
_debug2 DEPLOY_SSH_BACKUP_PATH "$DEPLOY_SSH_BACKUP_PATH"
if [ -n "$DEPLOY_SSH_BACKUP_PATH" ]; then
Le_Deploy_ssh_backup_path="$DEPLOY_SSH_BACKUP_PATH"
elif [ -z "$Le_Deploy_ssh_backup_path" ]; then
@@ -91,6 +96,8 @@ ssh_deploy() {
# MULTI_CALL is optional. If not provided then default to previously saved
# value (which may be undefined... equivalent to "no").
_getdeployconf DEPLOY_SSH_MULTI_CALL
_debug2 DEPLOY_SSH_MULTI_CALL "$DEPLOY_SSH_MULTI_CALL"
if [ "$DEPLOY_SSH_MULTI_CALL" = "yes" ]; then
Le_Deploy_ssh_multi_call="yes"
_savedomainconf Le_Deploy_ssh_multi_call "$Le_Deploy_ssh_multi_call"
@@ -141,6 +148,8 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d
# KEYFILE is optional.
# If provided then private key will be copied to provided filename.
_getdeployconf DEPLOY_SSH_KEYFILE
_debug2 DEPLOY_SSH_KEYFILE "$DEPLOY_SSH_KEYFILE"
if [ -n "$DEPLOY_SSH_KEYFILE" ]; then
Le_Deploy_ssh_keyfile="$DEPLOY_SSH_KEYFILE"
_savedomainconf Le_Deploy_ssh_keyfile "$Le_Deploy_ssh_keyfile"
@@ -163,6 +172,8 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d
# CERTFILE is optional.
# If provided then certificate will be copied or appended to provided filename.
_getdeployconf DEPLOY_SSH_CERTFILE
_debug2 DEPLOY_SSH_CERTFILE "$DEPLOY_SSH_CERTFILE"
if [ -n "$DEPLOY_SSH_CERTFILE" ]; then
Le_Deploy_ssh_certfile="$DEPLOY_SSH_CERTFILE"
_savedomainconf Le_Deploy_ssh_certfile "$Le_Deploy_ssh_certfile"
@@ -189,6 +200,8 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d
# CAFILE is optional.
# If provided then CA intermediate certificate will be copied or appended to provided filename.
_getdeployconf DEPLOY_SSH_CAFILE
_debug2 DEPLOY_SSH_CAFILE "$DEPLOY_SSH_CAFILE"
if [ -n "$DEPLOY_SSH_CAFILE" ]; then
Le_Deploy_ssh_cafile="$DEPLOY_SSH_CAFILE"
_savedomainconf Le_Deploy_ssh_cafile "$Le_Deploy_ssh_cafile"
@@ -216,6 +229,8 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d
# FULLCHAIN is optional.
# If provided then fullchain certificate will be copied or appended to provided filename.
_getdeployconf DEPLOY_SSH_FULLCHAIN
_debug2 DEPLOY_SSH_FULLCHAIN "$DEPLOY_SSH_FULLCHAIN"
if [ -n "$DEPLOY_SSH_FULLCHAIN" ]; then
Le_Deploy_ssh_fullchain="$DEPLOY_SSH_FULLCHAIN"
_savedomainconf Le_Deploy_ssh_fullchain "$Le_Deploy_ssh_fullchain"
@@ -244,6 +259,8 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d
# REMOTE_CMD is optional.
# If provided then this command will be executed on remote host.
_getdeployconf DEPLOY_SSH_REMOTE_CMD
_debug2 DEPLOY_SSH_REMOTE_CMD "$DEPLOY_SSH_REMOTE_CMD"
if [ -n "$DEPLOY_SSH_REMOTE_CMD" ]; then
Le_Deploy_ssh_remote_cmd="$DEPLOY_SSH_REMOTE_CMD"
_savedomainconf Le_Deploy_ssh_remote_cmd "$Le_Deploy_ssh_remote_cmd"
+21 -3
View File
@@ -2,8 +2,7 @@
# 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:
# It requires following environment variables:
#
# SYNO_Username - Synology Username to login (must be an administrator)
# SYNO_Password - Synology Password to login
@@ -16,6 +15,12 @@
# SYNO_Hostname - defaults to localhost
# SYNO_Port - defaults to 5000
# SYNO_DID - device ID to skip OTP - defaults to empty
# SYNO_TOTP_SECRET - TOTP secret to generate OTP - defaults to empty
#
# Dependencies:
# -------------
# - jq and curl
# - oathtool (When using 2 Factor Authentication and SYNO_TOTP_SECRET is set)
#
#returns 0 means success, otherwise error.
@@ -36,6 +41,7 @@ synology_dsm_deploy() {
_getdeployconf SYNO_Password
_getdeployconf SYNO_Create
_getdeployconf SYNO_DID
_getdeployconf SYNO_TOTP_SECRET
if [ -z "${SYNO_Username:-}" ] || [ -z "${SYNO_Password:-}" ]; then
_err "SYNO_Username & SYNO_Password must be set"
return 1
@@ -86,13 +92,23 @@ synology_dsm_deploy() {
encoded_username="$(printf "%s" "$SYNO_Username" | _url_encode)"
encoded_password="$(printf "%s" "$SYNO_Password" | _url_encode)"
otp_code=""
if [ -n "$SYNO_TOTP_SECRET" ]; then
if _exists oathtool; then
otp_code="$(oathtool --base32 --totp "${SYNO_TOTP_SECRET}" 2>/dev/null)"
else
_err "oathtool could not be found, install oathtool to use SYNO_TOTP_SECRET"
return 1
fi
fi
if [ -n "$SYNO_DID" ]; then
_H1="Cookie: did=$SYNO_DID"
export _H1
_debug3 H1 "${_H1}"
fi
response=$(_post "method=login&account=$encoded_username&passwd=$encoded_password&api=SYNO.API.Auth&version=$api_version&enable_syno_token=yes" "$_base_url/webapi/auth.cgi?enable_syno_token=yes")
response=$(_post "method=login&account=$encoded_username&passwd=$encoded_password&api=SYNO.API.Auth&version=$api_version&enable_syno_token=yes&otp_code=$otp_code" "$_base_url/webapi/auth.cgi?enable_syno_token=yes")
token=$(echo "$response" | grep "synotoken" | sed -n 's/.*"synotoken" *: *"\([^"]*\).*/\1/p')
_debug3 response "$response"
_debug token "$token"
@@ -100,6 +116,7 @@ synology_dsm_deploy() {
if [ -z "$token" ]; then
_err "Unable to authenticate to $SYNO_Hostname:$SYNO_Port using $SYNO_Scheme."
_err "Check your username and password."
_err "If two-factor authentication is enabled for the user, set SYNO_TOTP_SECRET."
return 1
fi
sid=$(echo "$response" | grep "sid" | sed -n 's/.*"sid" *: *"\([^"]*\).*/\1/p')
@@ -112,6 +129,7 @@ synology_dsm_deploy() {
_savedeployconf SYNO_Username "$SYNO_Username"
_savedeployconf SYNO_Password "$SYNO_Password"
_savedeployconf SYNO_DID "$SYNO_DID"
_savedeployconf SYNO_TOTP_SECRET "$SYNO_TOTP_SECRET"
_info "Getting certificates in Synology DSM"
response=$(_post "api=SYNO.Core.Certificate.CRT&method=list&version=1&_sid=$sid" "$_base_url/webapi/entry.cgi")
+202
View File
@@ -0,0 +1,202 @@
#!/usr/bin/env sh
# Here is a scipt to deploy the cert to your TrueNAS using the REST API.
# https://www.truenas.com/docs/hub/additional-topics/api/rest_api.html
#
# Written by Frank Plass github@f-plass.de
# https://github.com/danb35/deploy-freenas/blob/master/deploy_freenas.py
# Thanks to danb35 for your template!
#
# Following environment variables must be set:
#
# export DEPLOY_TRUENAS_APIKEY="<API_KEY_GENERATED_IN_THE_WEB_UI"
#
# The following environmental variables may be set if you don't like their
# default values:
#
# DEPLOY_TRUENAS_HOSTNAME - defaults to localhost
# DEPLOY_TRUENAS_SCHEME - defaults to http, set alternatively to https
#
#returns 0 means success, otherwise error.
######## Public functions #####################
#domain keyfile certfile cafile fullchain
truenas_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"
_getdeployconf DEPLOY_TRUENAS_APIKEY
if [ -z "$DEPLOY_TRUENAS_APIKEY" ]; then
_err "TrueNAS API key not found, please set the DEPLOY_TRUENAS_APIKEY environment variable."
return 1
fi
_secure_debug2 DEPLOY_TRUENAS_APIKEY "$DEPLOY_TRUENAS_APIKEY"
# Optional hostname, scheme for TrueNAS
_getdeployconf DEPLOY_TRUENAS_HOSTNAME
_getdeployconf DEPLOY_TRUENAS_SCHEME
# default values for hostname and scheme
[ -n "${DEPLOY_TRUENAS_HOSTNAME}" ] || DEPLOY_TRUENAS_HOSTNAME="localhost"
[ -n "${DEPLOY_TRUENAS_SCHEME}" ] || DEPLOY_TRUENAS_SCHEME="http"
_debug2 DEPLOY_TRUENAS_HOSTNAME "$DEPLOY_TRUENAS_HOSTNAME"
_debug2 DEPLOY_TRUENAS_SCHEME "$DEPLOY_TRUENAS_SCHEME"
_api_url="$DEPLOY_TRUENAS_SCHEME://$DEPLOY_TRUENAS_HOSTNAME/api/v2.0"
_debug _api_url "$_api_url"
_H1="Authorization: Bearer $DEPLOY_TRUENAS_APIKEY"
_secure_debug3 _H1 "$_H1"
_info "Testing Connection TrueNAS"
_response=$(_get "$_api_url/system/state")
_info "TrueNAS system state: $_response."
if [ -z "$_response" ]; then
_err "Unable to authenticate to $_api_url."
_err 'Check your connection settings are correct, e.g.'
_err 'DEPLOY_TRUENAS_HOSTNAME="192.168.x.y" or DEPLOY_TRUENAS_HOSTNAME="truenas.example.com".'
_err 'DEPLOY_TRUENAS_SCHEME="https" or DEPLOY_TRUENAS_SCHEME="http".'
_err "Verify your TrueNAS API key is valid and set correctly, e.g. DEPLOY_TRUENAS_APIKEY=xxxx...."
return 1
fi
_savedeployconf DEPLOY_TRUENAS_APIKEY "$DEPLOY_TRUENAS_APIKEY"
_savedeployconf DEPLOY_TRUENAS_HOSTNAME "$DEPLOY_TRUENAS_HOSTNAME"
_savedeployconf DEPLOY_TRUENAS_SCHEME "$DEPLOY_TRUENAS_SCHEME"
_info "Getting current active certificate from TrueNAS"
_response=$(_get "$_api_url/system/general")
_active_cert_id=$(echo "$_response" | grep -B2 '"name":' | grep 'id' | tr -d -- '"id: ,')
_active_cert_name=$(echo "$_response" | grep '"name":' | sed -n 's/.*: "\(.\{1,\}\)",$/\1/p')
_param_httpsredirect=$(echo "$_response" | grep '"ui_httpsredirect":' | sed -n 's/.*": \(.\{1,\}\),$/\1/p')
_debug Active_UI_Certificate_ID "$_active_cert_id"
_debug Active_UI_Certificate_Name "$_active_cert_name"
_debug Active_UI_http_redirect "$_param_httpsredirect"
if [ "$DEPLOY_TRUENAS_SCHEME" = "http" ] && [ "$_param_httpsredirect" = "true" ]; then
_info "HTTP->HTTPS redirection is enabled"
_info "Setting DEPLOY_TRUENAS_SCHEME to 'https'"
DEPLOY_TRUENAS_SCHEME="https"
_api_url="$DEPLOY_TRUENAS_SCHEME://$DEPLOY_TRUENAS_HOSTNAME/api/v2.0"
_savedeployconf DEPLOY_TRUENAS_SCHEME "$DEPLOY_TRUENAS_SCHEME"
fi
_info "Uploading new certificate to TrueNAS"
_certname="Letsencrypt_$(_utc_date | tr ' ' '_' | tr -d -- ':')"
_debug3 _certname "$_certname"
_certData="{\"create_type\": \"CERTIFICATE_CREATE_IMPORTED\", \"name\": \"${_certname}\", \"certificate\": \"$(_json_encode <"$_cfullchain")\", \"privatekey\": \"$(_json_encode <"$_ckey")\"}"
_add_cert_result="$(_post "$_certData" "$_api_url/certificate" "" "POST" "application/json")"
_debug3 _add_cert_result "$_add_cert_result"
_info "Fetching list of installed certificates"
_cert_list=$(_get "$_api_url/system/general/ui_certificate_choices")
_cert_id=$(echo "$_cert_list" | grep "$_certname" | sed -n 's/.*"\([0-9]\{1,\}\)".*$/\1/p')
_debug3 _cert_id "$_cert_id"
_info "Current activate certificate ID: $_cert_id"
_activateData="{\"ui_certificate\": \"${_cert_id}\"}"
_activate_result="$(_post "$_activateData" "$_api_url/system/general" "" "PUT" "application/json")"
_debug3 _activate_result "$_activate_result"
_info "Checking if WebDAV certificate is the same as the TrueNAS web UI"
_webdav_list=$(_get "$_api_url/webdav")
_webdav_cert_id=$(echo "$_webdav_list" | grep '"certssl":' | tr -d -- '"certsl: ,')
if [ "$_webdav_cert_id" = "$_active_cert_id" ]; then
_info "Updating the WebDAV certificate"
_debug _webdav_cert_id "$_webdav_cert_id"
_webdav_data="{\"certssl\": \"${_cert_id}\"}"
_activate_webdav_cert="$(_post "$_webdav_data" "$_api_url/webdav" "" "PUT" "application/json")"
_webdav_new_cert_id=$(echo "$_activate_webdav_cert" | _json_decode | grep '"certssl":' | sed -n 's/.*: \([0-9]\{1,\}\),\{0,1\}$/\1/p')
if [ "$_webdav_new_cert_id" -eq "$_cert_id" ]; then
_info "WebDAV certificate updated successfully"
else
_err "Unable to set WebDAV certificate"
_debug3 _activate_webdav_cert "$_activate_webdav_cert"
_debug3 _webdav_new_cert_id "$_webdav_new_cert_id"
return 1
fi
_debug3 _webdav_new_cert_id "$_webdav_new_cert_id"
else
_info "WebDAV certificate is not configured or is not the same as TrueNAS web UI"
fi
_info "Checking if FTP certificate is the same as the TrueNAS web UI"
_ftp_list=$(_get "$_api_url/ftp")
_ftp_cert_id=$(echo "$_ftp_list" | grep '"ssltls_certificate":' | tr -d -- '"certislfa:_ ,')
if [ "$_ftp_cert_id" = "$_active_cert_id" ]; then
_info "Updating the FTP certificate"
_debug _ftp_cert_id "$_ftp_cert_id"
_ftp_data="{\"ssltls_certificate\": \"${_cert_id}\"}"
_activate_ftp_cert="$(_post "$_ftp_data" "$_api_url/ftp" "" "PUT" "application/json")"
_ftp_new_cert_id=$(echo "$_activate_ftp_cert" | _json_decode | grep '"ssltls_certificate":' | sed -n 's/.*: \([0-9]\{1,\}\),\{0,1\}$/\1/p')
if [ "$_ftp_new_cert_id" -eq "$_cert_id" ]; then
_info "FTP certificate updated successfully"
else
_err "Unable to set FTP certificate"
_debug3 _activate_ftp_cert "$_activate_ftp_cert"
_debug3 _ftp_new_cert_id "$_ftp_new_cert_id"
return 1
fi
_debug3 _activate_ftp_cert "$_activate_ftp_cert"
else
_info "FTP certificate is not configured or is not the same as TrueNAS web UI"
fi
_info "Checking if S3 certificate is the same as the TrueNAS web UI"
_s3_list=$(_get "$_api_url/s3")
_s3_cert_id=$(echo "$_s3_list" | grep '"certificate":' | tr -d -- '"certifa:_ ,')
if [ "$_s3_cert_id" = "$_active_cert_id" ]; then
_info "Updating the S3 certificate"
_debug _s3_cert_id "$_s3_cert_id"
_s3_data="{\"certificate\": \"${_cert_id}\"}"
_activate_s3_cert="$(_post "$_s3_data" "$_api_url/s3" "" "PUT" "application/json")"
_s3_new_cert_id=$(echo "$_activate_s3_cert" | _json_decode | grep '"certificate":' | sed -n 's/.*: \([0-9]\{1,\}\),\{0,1\}$/\1/p')
if [ "$_s3_new_cert_id" -eq "$_cert_id" ]; then
_info "S3 certificate updated successfully"
else
_err "Unable to set S3 certificate"
_debug3 _activate_s3_cert "$_activate_s3_cert"
_debug3 _s3_new_cert_id "$_s3_new_cert_id"
return 1
fi
_debug3 _activate_s3_cert "$_activate_s3_cert"
else
_info "S3 certificate is not configured or is not the same as TrueNAS web UI"
fi
_info "Deleting old certificate"
_delete_result="$(_post "" "$_api_url/certificate/id/$_active_cert_id" "" "DELETE" "application/json")"
_debug3 _delete_result "$_delete_result"
_info "Reloading TrueNAS web UI"
_restart_UI=$(_get "$_api_url/system/general/ui_restart")
_debug2 _restart_UI "$_restart_UI"
if [ -n "$_add_cert_result" ] && [ -n "$_activate_result" ]; then
return 0
else
_err "Certificate update was not succesful, please try again with --debug"
return 1
fi
}
+16 -5
View File
@@ -56,12 +56,23 @@ vault_deploy() {
export _H1="X-Vault-Token: $VAULT_TOKEN"
if [ -n "$FABIO" ]; then
_post "{\"cert\": \"$_cfullchain\", \"key\": \"$_ckey\"}" "$URL"
if [ -n "$VAULT_KV_V2" ]; then
_post "{ \"data\": {\"cert\": \"$_cfullchain\", \"key\": \"$_ckey\"} }" "$URL"
else
_post "{\"cert\": \"$_cfullchain\", \"key\": \"$_ckey\"}" "$URL"
fi
else
_post "{\"value\": \"$_ccert\"}" "$URL/cert.pem"
_post "{\"value\": \"$_ckey\"}" "$URL/cert.key"
_post "{\"value\": \"$_cca\"}" "$URL/chain.pem"
_post "{\"value\": \"$_cfullchain\"}" "$URL/fullchain.pem"
if [ -n "$VAULT_KV_V2" ]; then
_post "{\"data\": {\"value\": \"$_ccert\"}}" "$URL/cert.pem"
_post "{\"data\": {\"value\": \"$_ckey\"}}" "$URL/cert.key"
_post "{\"data\": {\"value\": \"$_cca\"}}" "$URL/chain.pem"
_post "{\"data\": {\"value\": \"$_cfullchain\"}}" "$URL/fullchain.pem"
else
_post "{\"value\": \"$_ccert\"}" "$URL/cert.pem"
_post "{\"value\": \"$_ckey\"}" "$URL/cert.key"
_post "{\"value\": \"$_cca\"}" "$URL/chain.pem"
_post "{\"value\": \"$_cfullchain\"}" "$URL/fullchain.pem"
fi
fi
}
+57 -32
View File
@@ -42,11 +42,11 @@ dns_1984hosting_add() {
_debug "Add TXT record $fulldomain with value '$txtvalue'"
value="$(printf '%s' "$txtvalue" | _url_encode)"
url="https://management.1984hosting.com/domains/entry/"
url="https://1984.hosting/domains/entry/"
postdata="entry=new"
postdata="$postdata&type=TXT"
postdata="$postdata&ttl=3600"
postdata="$postdata&ttl=900"
postdata="$postdata&zone=$_domain"
postdata="$postdata&host=$_sub_domain"
postdata="$postdata&rdata=%22$value%22"
@@ -59,7 +59,7 @@ dns_1984hosting_add() {
if _contains "$response" '"haserrors": true'; then
_err "1984Hosting failed to add TXT record for $_sub_domain bad RC from _post"
return 1
elif _contains "$response" "<html>"; then
elif _contains "$response" "html>"; then
_err "1984Hosting failed to add TXT record for $_sub_domain. Check $HTTP_HEADER file"
return 1
elif _contains "$response" '"auth": false'; then
@@ -93,20 +93,15 @@ dns_1984hosting_rm() {
fi
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
_debug "Delete $fulldomain TXT record"
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"
url="https://1984.hosting/domains"
if ! _get_zone_id "$url" "$_domain"; then
_err "invalid zone" "$_domain"
return 1
fi
_htmlget "$url/$zone_id" "$_sub_domain"
_htmlget "$url/$_zone_id" "$txtvalue"
_debug2 _response "$_response"
entry_id="$(echo "$_response" | _egrep_o 'entry_[0-9]+' | sed 's/entry_//')"
_debug2 entry_id "$entry_id"
@@ -135,7 +130,7 @@ dns_1984hosting_rm() {
_1984hosting_login() {
if ! _check_credentials; then return 1; fi
if _check_cookie; then
if _check_cookies; then
_debug "Already logged in"
return 0
fi
@@ -143,16 +138,19 @@ _1984hosting_login() {
_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/"
url="https://1984.hosting/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"
One984HOSTING_SESSIONID_COOKIE="$(grep -i '^set-cookie:' "$HTTP_HEADER" | _egrep_o 'sessionid=[^;]*;' | tr -d ';')"
One984HOSTING_CSRFTOKEN_COOKIE="$(grep -i '^set-cookie:' "$HTTP_HEADER" | _egrep_o 'csrftoken=[^;]*;' | tr -d ';')"
export One984HOSTING_SESSIONID_COOKIE
export One984HOSTING_CSRFTOKEN_COOKIE
_saveaccountconf_mutable One984HOSTING_SESSIONID_COOKIE "$One984HOSTING_SESSIONID_COOKIE"
_saveaccountconf_mutable One984HOSTING_CSRFTOKEN_COOKIE "$One984HOSTING_CSRFTOKEN_COOKIE"
return 0
fi
return 1
@@ -169,21 +167,24 @@ _check_credentials() {
return 0
}
_check_cookie() {
One984HOSTING_COOKIE="${One984HOSTING_COOKIE:-$(_readaccountconf_mutable One984HOSTING_COOKIE)}"
if [ -z "$One984HOSTING_COOKIE" ]; then
_debug "No cached cookie found"
_check_cookies() {
One984HOSTING_SESSIONID_COOKIE="${One984HOSTING_SESSIONID_COOKIE:-$(_readaccountconf_mutable One984HOSTING_SESSIONID_COOKIE)}"
One984HOSTING_CSRFTOKEN_COOKIE="${One984HOSTING_CSRFTOKEN_COOKIE:-$(_readaccountconf_mutable One984HOSTING_CSRFTOKEN_COOKIE)}"
if [ -z "$One984HOSTING_SESSIONID_COOKIE" ] || [ -z "$One984HOSTING_CSRFTOKEN_COOKIE" ]; then
_debug "No cached cookie(s) found"
return 1
fi
_authget "https://management.1984hosting.com/accounts/loginstatus/"
_authget "https://1984.hosting/accounts/loginstatus/"
if _contains "$response" '"ok": true'; then
_debug "Cached cookie still valid"
_debug "Cached cookies still valid"
return 0
fi
_debug "Cached cookie no longer valid"
One984HOSTING_COOKIE=""
_saveaccountconf_mutable One984HOSTING_COOKIE "$One984HOSTING_COOKIE"
_debug "Cached cookies no longer valid"
One984HOSTING_SESSIONID_COOKIE=""
One984HOSTING_CSRFTOKEN_COOKIE=""
_saveaccountconf_mutable One984HOSTING_SESSIONID_COOKIE "$One984HOSTING_SESSIONID_COOKIE"
_saveaccountconf_mutable One984HOSTING_CSRFTOKEN_COOKIE "$One984HOSTING_CSRFTOKEN_COOKIE"
return 1
}
@@ -203,8 +204,8 @@ _get_root() {
return 1
fi
_authget "https://management.1984hosting.com/domains/soacheck/?zone=$h&nameserver=ns0.1984.is."
if _contains "$_response" "serial" && ! _contains "$_response" 'null}'; then
_authget "https://1984.hosting/domains/soacheck/?zone=$h&nameserver=ns0.1984.is."
if _contains "$_response" "serial" && ! _contains "$_response" "null"; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_domain="$h"
return 0
@@ -215,9 +216,25 @@ _get_root() {
return 1
}
#usage: _get_zone_id url domain.com
#returns zone id for domain.com
_get_zone_id() {
url=$1
domain=$2
_htmlget "$url" "$domain"
_debug2 _response "$_response"
_zone_id="$(echo "$_response" | _egrep_o 'zone\/[0-9]+' | _head_n 1)"
_debug2 _zone_id "$_zone_id"
if [ -z "$_zone_id" ]; then
_err "Error getting _zone_id for $2"
return 1
fi
return 0
}
# add extra headers to request
_authget() {
export _H1="Cookie: $One984HOSTING_COOKIE"
export _H1="Cookie: $One984HOSTING_CSRFTOKEN_COOKIE;$One984HOSTING_SESSIONID_COOKIE"
_response=$(_get "$1" | _normalizeJson)
_debug2 _response "$_response"
}
@@ -225,12 +242,20 @@ _authget() {
# truncate huge HTML response
# echo: Argument list too long
_htmlget() {
export _H1="Cookie: $One984HOSTING_COOKIE"
_response=$(_get "$1" | grep "$2" | _head_n 1)
export _H1="Cookie: $One984HOSTING_CSRFTOKEN_COOKIE;$One984HOSTING_SESSIONID_COOKIE"
_response=$(_get "$1" | grep "$2")
if _contains "$_response" "@$2"; then
_response=$(echo "$_response" | grep -v "[@]" | _head_n 1)
fi
}
# add extra headers to request
_authpost() {
export _H1="Cookie: $One984HOSTING_COOKIE"
url="https://1984.hosting/domains"
_get_zone_id "$url" "$_domain"
csrf_header="$(echo "$One984HOSTING_CSRFTOKEN_COOKIE" | _egrep_o "=[^=][0-9a-zA-Z]*" | tr -d "=")"
export _H1="Cookie: $One984HOSTING_CSRFTOKEN_COOKIE;$One984HOSTING_SESSIONID_COOKIE"
export _H2="Referer: https://1984.hosting/domains/$_zone_id"
export _H3="X-CSRFToken: $csrf_header"
_response=$(_post "$1" "$2")
}
Regular → Executable
+51 -12
View File
@@ -1,31 +1,70 @@
#!/usr/bin/env sh
#
#Author: Wolfgang Ebner
#Report Bugs here: https://github.com/webner/acme.sh
#Author: Sven Neubuaer
#Report Bugs here: https://github.com/dampfklon/acme.sh
#
# Usage:
# export ACMEDNS_BASE_URL="https://auth.acme-dns.io"
#
# You can optionally define an already existing account:
#
# export ACMEDNS_USERNAME="<username>"
# export ACMEDNS_PASSWORD="<password>"
# export ACMEDNS_SUBDOMAIN="<subdomain>"
#
######## Public functions #####################
#Usage: dns_acmedns_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
# Used to add txt record
dns_acmedns_add() {
fulldomain=$1
txtvalue=$2
_info "Using acme-dns"
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
_debug "fulldomain $fulldomain"
_debug "txtvalue $txtvalue"
ACMEDNS_UPDATE_URL="${ACMEDNS_UPDATE_URL:-$(_readaccountconf_mutable ACMEDNS_UPDATE_URL)}"
#for compatiblity from account conf
ACMEDNS_USERNAME="${ACMEDNS_USERNAME:-$(_readaccountconf_mutable ACMEDNS_USERNAME)}"
_clearaccountconf_mutable ACMEDNS_USERNAME
ACMEDNS_PASSWORD="${ACMEDNS_PASSWORD:-$(_readaccountconf_mutable ACMEDNS_PASSWORD)}"
_clearaccountconf_mutable ACMEDNS_PASSWORD
ACMEDNS_SUBDOMAIN="${ACMEDNS_SUBDOMAIN:-$(_readaccountconf_mutable ACMEDNS_SUBDOMAIN)}"
_clearaccountconf_mutable ACMEDNS_SUBDOMAIN
if [ "$ACMEDNS_UPDATE_URL" = "" ]; then
ACMEDNS_UPDATE_URL="https://auth.acme-dns.io/update"
ACMEDNS_BASE_URL="${ACMEDNS_BASE_URL:-$(_readdomainconf ACMEDNS_BASE_URL)}"
ACMEDNS_USERNAME="${ACMEDNS_USERNAME:-$(_readdomainconf ACMEDNS_USERNAME)}"
ACMEDNS_PASSWORD="${ACMEDNS_PASSWORD:-$(_readdomainconf ACMEDNS_PASSWORD)}"
ACMEDNS_SUBDOMAIN="${ACMEDNS_SUBDOMAIN:-$(_readdomainconf ACMEDNS_SUBDOMAIN)}"
if [ "$ACMEDNS_BASE_URL" = "" ]; then
ACMEDNS_BASE_URL="https://auth.acme-dns.io"
fi
_saveaccountconf_mutable ACMEDNS_UPDATE_URL "$ACMEDNS_UPDATE_URL"
_saveaccountconf_mutable ACMEDNS_USERNAME "$ACMEDNS_USERNAME"
_saveaccountconf_mutable ACMEDNS_PASSWORD "$ACMEDNS_PASSWORD"
_saveaccountconf_mutable ACMEDNS_SUBDOMAIN "$ACMEDNS_SUBDOMAIN"
ACMEDNS_UPDATE_URL="$ACMEDNS_BASE_URL/update"
ACMEDNS_REGISTER_URL="$ACMEDNS_BASE_URL/register"
if [ -z "$ACMEDNS_USERNAME" ] || [ -z "$ACMEDNS_PASSWORD" ]; then
response="$(_post "" "$ACMEDNS_REGISTER_URL" "" "POST")"
_debug response "$response"
ACMEDNS_USERNAME=$(echo "$response" | sed -n 's/^{.*\"username\":[ ]*\"\([^\"]*\)\".*}/\1/p')
_debug "received username: $ACMEDNS_USERNAME"
ACMEDNS_PASSWORD=$(echo "$response" | sed -n 's/^{.*\"password\":[ ]*\"\([^\"]*\)\".*}/\1/p')
_debug "received password: $ACMEDNS_PASSWORD"
ACMEDNS_SUBDOMAIN=$(echo "$response" | sed -n 's/^{.*\"subdomain\":[ ]*\"\([^\"]*\)\".*}/\1/p')
_debug "received subdomain: $ACMEDNS_SUBDOMAIN"
ACMEDNS_FULLDOMAIN=$(echo "$response" | sed -n 's/^{.*\"fulldomain\":[ ]*\"\([^\"]*\)\".*}/\1/p')
_info "##########################################################"
_info "# Create $fulldomain CNAME $ACMEDNS_FULLDOMAIN DNS entry #"
_info "##########################################################"
_info "Press enter to continue... "
read -r _
fi
_savedomainconf ACMEDNS_BASE_URL "$ACMEDNS_BASE_URL"
_savedomainconf ACMEDNS_USERNAME "$ACMEDNS_USERNAME"
_savedomainconf ACMEDNS_PASSWORD "$ACMEDNS_PASSWORD"
_savedomainconf ACMEDNS_SUBDOMAIN "$ACMEDNS_SUBDOMAIN"
export _H1="X-Api-User: $ACMEDNS_USERNAME"
export _H2="X-Api-Key: $ACMEDNS_PASSWORD"
@@ -48,8 +87,8 @@ dns_acmedns_rm() {
fulldomain=$1
txtvalue=$2
_info "Using acme-dns"
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
_debug "fulldomain $fulldomain"
_debug "txtvalue $txtvalue"
}
#################### Private functions below ##################################
+1 -1
View File
@@ -32,7 +32,7 @@ dns_aws_add() {
if [ -z "$AWS_ACCESS_KEY_ID" ] || [ -z "$AWS_SECRET_ACCESS_KEY" ]; then
AWS_ACCESS_KEY_ID=""
AWS_SECRET_ACCESS_KEY=""
_err "You haven't specifed the aws route53 api key id and and api key secret yet."
_err "You haven't specified the aws route53 api key id and and api key secret yet."
_err "Please create your key and try again. see $(__green $AWS_WIKI)"
return 1
fi
+204
View File
@@ -0,0 +1,204 @@
#!/usr/bin/env sh
#
#AZION_Email=""
#AZION_Password=""
#
AZION_Api="https://api.azionapi.net"
######## Public functions ########
# Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
# Used to add txt record
dns_azion_add() {
fulldomain=$1
txtvalue=$2
_debug "Detect the root zone"
if ! _get_root "$fulldomain"; then
_err "Domain not found"
return 1
fi
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
_debug _domain_id "$_domain_id"
_info "Add or update record"
_get_record "$_domain_id" "$_sub_domain"
if [ "$record_id" ]; then
_payload="{\"record_type\": \"TXT\", \"entry\": \"$_sub_domain\", \"answers_list\": [$answers_list, \"$txtvalue\"], \"ttl\": 20}"
if _azion_rest PUT "intelligent_dns/$_domain_id/records/$record_id" "$_payload"; then
if _contains "$response" "$txtvalue"; then
_info "Record updated."
return 0
fi
fi
else
_payload="{\"record_type\": \"TXT\", \"entry\": \"$_sub_domain\", \"answers_list\": [\"$txtvalue\"], \"ttl\": 20}"
if _azion_rest POST "intelligent_dns/$_domain_id/records" "$_payload"; then
if _contains "$response" "$txtvalue"; then
_info "Record added."
return 0
fi
fi
fi
_err "Failed to add or update record."
return 1
}
# Usage: fulldomain txtvalue
# Used to remove the txt record after validation
dns_azion_rm() {
fulldomain=$1
txtvalue=$2
_debug "Detect the root zone"
if ! _get_root "$fulldomain"; then
_err "Domain not found"
return 1
fi
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
_debug _domain_id "$_domain_id"
_info "Removing record"
_get_record "$_domain_id" "$_sub_domain"
if [ "$record_id" ]; then
if _azion_rest DELETE "intelligent_dns/$_domain_id/records/$record_id"; then
_info "Record removed."
return 0
else
_err "Failed to remove record."
return 1
fi
else
_info "Record not found or already removed."
return 0
fi
}
#################### Private functions below ##################################
# Usage: _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
if ! _azion_rest GET "intelligent_dns"; then
return 1
fi
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
_debug h "$h"
if [ -z "$h" ]; then
# not valid
return 1
fi
if _contains "$response" "\"domain\":\"$h\""; then
_domain_id=$(echo "$response" | tr '{' "\n" | grep "\"domain\":\"$h\"" | _egrep_o "\"id\":[0-9]*" | _head_n 1 | cut -d : -f 2 | tr -d \")
_debug _domain_id "$_domain_id"
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
}
_get_record() {
_domain_id=$1
_record=$2
if ! _azion_rest GET "intelligent_dns/$_domain_id/records"; then
return 1
fi
if _contains "$response" "\"entry\":\"$_record\""; then
_json_record=$(echo "$response" | tr '{' "\n" | grep "\"entry\":\"$_record\"")
if [ "$_json_record" ]; then
record_id=$(echo "$_json_record" | _egrep_o "\"record_id\":[0-9]*" | _head_n 1 | cut -d : -f 2 | tr -d \")
answers_list=$(echo "$_json_record" | _egrep_o "\"answers_list\":\[.*\]" | _head_n 1 | cut -d : -f 2 | tr -d \[\])
return 0
fi
return 1
fi
return 1
}
_get_token() {
AZION_Email="${AZION_Email:-$(_readaccountconf_mutable AZION_Email)}"
AZION_Password="${AZION_Password:-$(_readaccountconf_mutable AZION_Password)}"
if ! _contains "$AZION_Email" "@"; then
_err "It seems that the AZION_Email is not a valid email address. Revalidate your environments."
return 1
fi
if [ -z "$AZION_Email" ] || [ -z "$AZION_Password" ]; then
_err "You didn't specified a AZION_Email/AZION_Password to generate Azion token."
return 1
fi
_saveaccountconf_mutable AZION_Email "$AZION_Email"
_saveaccountconf_mutable AZION_Password "$AZION_Password"
_basic_auth=$(printf "%s:%s" "$AZION_Email" "$AZION_Password" | _base64)
_debug _basic_auth "$_basic_auth"
export _H1="Accept: application/json; version=3"
export _H2="Content-Type: application/json"
export _H3="Authorization: Basic $_basic_auth"
response="$(_post "" "$AZION_Api/tokens" "" "POST")"
if _contains "$response" "\"token\":\"" >/dev/null; then
_azion_token=$(echo "$response" | _egrep_o "\"token\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \")
export AZION_Token="$_azion_token"
else
_err "Failed to generate Azion token"
return 1
fi
}
_azion_rest() {
_method=$1
_uri="$2"
_data="$3"
if [ -z "$AZION_Token" ]; then
_get_token
fi
_debug2 token "$AZION_Token"
export _H1="Accept: application/json; version=3"
export _H2="Content-Type: application/json"
export _H3="Authorization: token $AZION_Token"
if [ "$_method" != "GET" ]; then
_debug _data "$_data"
response="$(_post "$_data" "$AZION_Api/$_uri" "" "$_method")"
else
response="$(_get "$AZION_Api/$_uri")"
fi
_debug2 response "$response"
if [ "$?" != "0" ]; then
_err "error $_method $_uri $_data"
return 1
fi
return 0
}
+111 -81
View File
@@ -9,57 +9,72 @@ WIKI="https://github.com/acmesh-official/acme.sh/wiki/How-to-use-Azure-DNS"
#
# Ref: https://docs.microsoft.com/en-us/rest/api/dns/recordsets/createorupdate
#
dns_azure_add() {
fulldomain=$1
txtvalue=$2
AZUREDNS_SUBSCRIPTIONID="${AZUREDNS_SUBSCRIPTIONID:-$(_readaccountconf_mutable AZUREDNS_SUBSCRIPTIONID)}"
AZUREDNS_TENANTID="${AZUREDNS_TENANTID:-$(_readaccountconf_mutable AZUREDNS_TENANTID)}"
AZUREDNS_APPID="${AZUREDNS_APPID:-$(_readaccountconf_mutable AZUREDNS_APPID)}"
AZUREDNS_CLIENTSECRET="${AZUREDNS_CLIENTSECRET:-$(_readaccountconf_mutable AZUREDNS_CLIENTSECRET)}"
if [ -z "$AZUREDNS_SUBSCRIPTIONID" ]; then
AZUREDNS_SUBSCRIPTIONID=""
AZUREDNS_TENANTID=""
AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET=""
_err "You didn't specify the Azure Subscription ID "
_err "You didn't specify the Azure Subscription ID"
return 1
fi
if [ -z "$AZUREDNS_TENANTID" ]; then
AZUREDNS_SUBSCRIPTIONID=""
AZUREDNS_TENANTID=""
AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET=""
_err "You didn't specify the Azure Tenant ID "
return 1
fi
if [ -z "$AZUREDNS_APPID" ]; then
AZUREDNS_SUBSCRIPTIONID=""
AZUREDNS_TENANTID=""
AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET=""
_err "You didn't specify the Azure App ID"
return 1
fi
if [ -z "$AZUREDNS_CLIENTSECRET" ]; then
AZUREDNS_SUBSCRIPTIONID=""
AZUREDNS_TENANTID=""
AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET=""
_err "You didn't specify the Azure Client Secret"
return 1
fi
#save account details to account conf file.
#save subscription id to account conf file.
_saveaccountconf_mutable AZUREDNS_SUBSCRIPTIONID "$AZUREDNS_SUBSCRIPTIONID"
_saveaccountconf_mutable AZUREDNS_TENANTID "$AZUREDNS_TENANTID"
_saveaccountconf_mutable AZUREDNS_APPID "$AZUREDNS_APPID"
_saveaccountconf_mutable AZUREDNS_CLIENTSECRET "$AZUREDNS_CLIENTSECRET"
accesstoken=$(_azure_getaccess_token "$AZUREDNS_TENANTID" "$AZUREDNS_APPID" "$AZUREDNS_CLIENTSECRET")
AZUREDNS_MANAGEDIDENTITY="${AZUREDNS_MANAGEDIDENTITY:-$(_readaccountconf_mutable AZUREDNS_MANAGEDIDENTITY)}"
if [ "$AZUREDNS_MANAGEDIDENTITY" = true ]; then
_info "Using Azure managed identity"
#save managed identity as preferred authentication method, clear service principal credentials from conf file.
_saveaccountconf_mutable AZUREDNS_MANAGEDIDENTITY "$AZUREDNS_MANAGEDIDENTITY"
_saveaccountconf_mutable AZUREDNS_TENANTID ""
_saveaccountconf_mutable AZUREDNS_APPID ""
_saveaccountconf_mutable AZUREDNS_CLIENTSECRET ""
else
_info "You didn't ask to use Azure managed identity, checking service principal credentials"
AZUREDNS_TENANTID="${AZUREDNS_TENANTID:-$(_readaccountconf_mutable AZUREDNS_TENANTID)}"
AZUREDNS_APPID="${AZUREDNS_APPID:-$(_readaccountconf_mutable AZUREDNS_APPID)}"
AZUREDNS_CLIENTSECRET="${AZUREDNS_CLIENTSECRET:-$(_readaccountconf_mutable AZUREDNS_CLIENTSECRET)}"
if [ -z "$AZUREDNS_TENANTID" ]; then
AZUREDNS_SUBSCRIPTIONID=""
AZUREDNS_TENANTID=""
AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET=""
_err "You didn't specify the Azure Tenant ID "
return 1
fi
if [ -z "$AZUREDNS_APPID" ]; then
AZUREDNS_SUBSCRIPTIONID=""
AZUREDNS_TENANTID=""
AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET=""
_err "You didn't specify the Azure App ID"
return 1
fi
if [ -z "$AZUREDNS_CLIENTSECRET" ]; then
AZUREDNS_SUBSCRIPTIONID=""
AZUREDNS_TENANTID=""
AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET=""
_err "You didn't specify the Azure Client Secret"
return 1
fi
#save account details to account conf file, don't opt in for azure manages identity check.
_saveaccountconf_mutable AZUREDNS_MANAGEDIDENTITY "false"
_saveaccountconf_mutable AZUREDNS_TENANTID "$AZUREDNS_TENANTID"
_saveaccountconf_mutable AZUREDNS_APPID "$AZUREDNS_APPID"
_saveaccountconf_mutable AZUREDNS_CLIENTSECRET "$AZUREDNS_CLIENTSECRET"
fi
accesstoken=$(_azure_getaccess_token "$AZUREDNS_MANAGEDIDENTITY" "$AZUREDNS_TENANTID" "$AZUREDNS_APPID" "$AZUREDNS_CLIENTSECRET")
if ! _get_root "$fulldomain" "$AZUREDNS_SUBSCRIPTIONID" "$accesstoken"; then
_err "invalid domain"
@@ -116,10 +131,6 @@ dns_azure_rm() {
txtvalue=$2
AZUREDNS_SUBSCRIPTIONID="${AZUREDNS_SUBSCRIPTIONID:-$(_readaccountconf_mutable AZUREDNS_SUBSCRIPTIONID)}"
AZUREDNS_TENANTID="${AZUREDNS_TENANTID:-$(_readaccountconf_mutable AZUREDNS_TENANTID)}"
AZUREDNS_APPID="${AZUREDNS_APPID:-$(_readaccountconf_mutable AZUREDNS_APPID)}"
AZUREDNS_CLIENTSECRET="${AZUREDNS_CLIENTSECRET:-$(_readaccountconf_mutable AZUREDNS_CLIENTSECRET)}"
if [ -z "$AZUREDNS_SUBSCRIPTIONID" ]; then
AZUREDNS_SUBSCRIPTIONID=""
AZUREDNS_TENANTID=""
@@ -129,34 +140,44 @@ dns_azure_rm() {
return 1
fi
if [ -z "$AZUREDNS_TENANTID" ]; then
AZUREDNS_SUBSCRIPTIONID=""
AZUREDNS_TENANTID=""
AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET=""
_err "You didn't specify the Azure Tenant ID "
return 1
AZUREDNS_MANAGEDIDENTITY="${AZUREDNS_MANAGEDIDENTITY:-$(_readaccountconf_mutable AZUREDNS_MANAGEDIDENTITY)}"
if [ "$AZUREDNS_MANAGEDIDENTITY" = true ]; then
_info "Using Azure managed identity"
else
_info "You didn't ask to use Azure managed identity, checking service principal credentials"
AZUREDNS_TENANTID="${AZUREDNS_TENANTID:-$(_readaccountconf_mutable AZUREDNS_TENANTID)}"
AZUREDNS_APPID="${AZUREDNS_APPID:-$(_readaccountconf_mutable AZUREDNS_APPID)}"
AZUREDNS_CLIENTSECRET="${AZUREDNS_CLIENTSECRET:-$(_readaccountconf_mutable AZUREDNS_CLIENTSECRET)}"
if [ -z "$AZUREDNS_TENANTID" ]; then
AZUREDNS_SUBSCRIPTIONID=""
AZUREDNS_TENANTID=""
AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET=""
_err "You didn't specify the Azure Tenant ID "
return 1
fi
if [ -z "$AZUREDNS_APPID" ]; then
AZUREDNS_SUBSCRIPTIONID=""
AZUREDNS_TENANTID=""
AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET=""
_err "You didn't specify the Azure App ID"
return 1
fi
if [ -z "$AZUREDNS_CLIENTSECRET" ]; then
AZUREDNS_SUBSCRIPTIONID=""
AZUREDNS_TENANTID=""
AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET=""
_err "You didn't specify the Azure Client Secret"
return 1
fi
fi
if [ -z "$AZUREDNS_APPID" ]; then
AZUREDNS_SUBSCRIPTIONID=""
AZUREDNS_TENANTID=""
AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET=""
_err "You didn't specify the Azure App ID"
return 1
fi
if [ -z "$AZUREDNS_CLIENTSECRET" ]; then
AZUREDNS_SUBSCRIPTIONID=""
AZUREDNS_TENANTID=""
AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET=""
_err "You didn't specify the Azure Client Secret"
return 1
fi
accesstoken=$(_azure_getaccess_token "$AZUREDNS_TENANTID" "$AZUREDNS_APPID" "$AZUREDNS_CLIENTSECRET")
accesstoken=$(_azure_getaccess_token "$AZUREDNS_MANAGEDIDENTITY" "$AZUREDNS_TENANTID" "$AZUREDNS_APPID" "$AZUREDNS_CLIENTSECRET")
if ! _get_root "$fulldomain" "$AZUREDNS_SUBSCRIPTIONID" "$accesstoken"; then
_err "invalid domain"
@@ -258,9 +279,10 @@ _azure_rest() {
## Ref: https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-protocols-oauth-service-to-service#request-an-access-token
_azure_getaccess_token() {
tenantID=$1
clientID=$2
clientSecret=$3
managedIdentity=$1
tenantID=$2
clientID=$3
clientSecret=$4
accesstoken="${AZUREDNS_BEARERTOKEN:-$(_readaccountconf_mutable AZUREDNS_BEARERTOKEN)}"
expires_on="${AZUREDNS_TOKENVALIDTO:-$(_readaccountconf_mutable AZUREDNS_TOKENVALIDTO)}"
@@ -278,17 +300,25 @@ _azure_getaccess_token() {
fi
_debug "getting new bearer token"
export _H1="accept: application/json"
export _H2="Content-Type: application/x-www-form-urlencoded"
body="resource=$(printf "%s" 'https://management.core.windows.net/' | _url_encode)&client_id=$(printf "%s" "$clientID" | _url_encode)&client_secret=$(printf "%s" "$clientSecret" | _url_encode)&grant_type=client_credentials"
_secure_debug2 "data $body"
response="$(_post "$body" "https://login.microsoftonline.com/$tenantID/oauth2/token" "" "POST")"
_ret="$?"
_secure_debug2 "response $response"
response="$(echo "$response" | _normalizeJson)"
accesstoken=$(echo "$response" | _egrep_o "\"access_token\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \")
expires_on=$(echo "$response" | _egrep_o "\"expires_on\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \")
if [ "$managedIdentity" = true ]; then
# https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/how-to-use-vm-token#get-a-token-using-http
export _H1="Metadata: true"
response="$(_get http://169.254.169.254/metadata/identity/oauth2/token\?api-version=2018-02-01\&resource=https://management.azure.com/)"
response="$(echo "$response" | _normalizeJson)"
accesstoken=$(echo "$response" | _egrep_o "\"access_token\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \")
expires_on=$(echo "$response" | _egrep_o "\"expires_on\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \")
else
export _H1="accept: application/json"
export _H2="Content-Type: application/x-www-form-urlencoded"
body="resource=$(printf "%s" 'https://management.core.windows.net/' | _url_encode)&client_id=$(printf "%s" "$clientID" | _url_encode)&client_secret=$(printf "%s" "$clientSecret" | _url_encode)&grant_type=client_credentials"
_secure_debug2 "data $body"
response="$(_post "$body" "https://login.microsoftonline.com/$tenantID/oauth2/token" "" "POST")"
_ret="$?"
_secure_debug2 "response $response"
response="$(echo "$response" | _normalizeJson)"
accesstoken=$(echo "$response" | _egrep_o "\"access_token\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \")
expires_on=$(echo "$response" | _egrep_o "\"expires_on\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \")
fi
if [ -z "$accesstoken" ]; then
_err "no acccess token received. Check your Azure settings see $WIKI"
+9 -3
View File
@@ -25,9 +25,15 @@ dns_cf_add() {
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"
if [ "$CF_Zone_ID" ]; then
_savedomainconf CF_Token "$CF_Token"
_savedomainconf CF_Account_ID "$CF_Account_ID"
_savedomainconf CF_Zone_ID "$CF_Zone_ID"
else
_saveaccountconf_mutable CF_Token "$CF_Token"
_saveaccountconf_mutable CF_Account_ID "$CF_Account_ID"
_saveaccountconf_mutable CF_Zone_ID "$CF_Zone_ID"
fi
else
if [ -z "$CF_Key" ] || [ -z "$CF_Email" ]; then
CF_Key=""
+24
View File
@@ -2,11 +2,14 @@
# Author: Boyan Peychev <boyan at cloudns dot net>
# Repository: https://github.com/ClouDNS/acme.sh/
# Editor: I Komang Suryadana
#CLOUDNS_AUTH_ID=XXXXX
#CLOUDNS_SUB_AUTH_ID=XXXXX
#CLOUDNS_AUTH_PASSWORD="YYYYYYYYY"
CLOUDNS_API="https://api.cloudns.net"
DOMAIN_TYPE=
DOMAIN_MASTER=
######## Public functions #####################
@@ -61,6 +64,15 @@ dns_cloudns_rm() {
host="$(echo "$1" | sed "s/\.$zone\$//")"
record=$2
_dns_cloudns_get_zone_info "$zone"
_debug "Type" "$DOMAIN_TYPE"
_debug "Cloud Master" "$DOMAIN_MASTER"
if _contains "$DOMAIN_TYPE" "cloud"; then
zone=$DOMAIN_MASTER
fi
_debug "ZONE" "$zone"
_dns_cloudns_http_api_call "dns/records.json" "domain-name=$zone&host=$host&type=TXT"
if ! _contains "$response" "\"id\":"; then
return 1
@@ -134,6 +146,18 @@ _dns_cloudns_init_check() {
return 0
}
_dns_cloudns_get_zone_info() {
zone=$1
_dns_cloudns_http_api_call "dns/get-zone-info.json" "domain-name=$zone"
if ! _contains "$response" "\"status\":\"Failed\""; then
DOMAIN_TYPE=$(echo "$response" | _egrep_o '"type":"[^"]*"' | cut -d : -f 2 | tr -d '"')
if _contains "$DOMAIN_TYPE" "cloud"; then
DOMAIN_MASTER=$(echo "$response" | _egrep_o '"cloud-master":"[^"]*"' | cut -d : -f 2 | tr -d '"')
fi
fi
return 0
}
_dns_cloudns_get_zone_name() {
i=2
while true; do
+159
View File
@@ -0,0 +1,159 @@
#!/usr/bin/env sh
#
#Author: Bjarne Saltbaek
#Report Bugs here: https://github.com/acmesh-official/acme.sh/issues/3732
#
#
######## Public functions #####################
#
# Export CPANEL username,api token and hostname in the following variables
#
# cPanel_Username=username
# cPanel_Apitoken=apitoken
# cPanel_Hostname=hostname
#
# Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
# Used to add txt record
dns_cpanel_add() {
fulldomain=$1
txtvalue=$2
_info "Adding TXT record to cPanel based system"
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
_debug cPanel_Username "$cPanel_Username"
_debug cPanel_Apitoken "$cPanel_Apitoken"
_debug cPanel_Hostname "$cPanel_Hostname"
if ! _cpanel_login; then
_err "cPanel Login failed for user $cPanel_Username. Check $HTTP_HEADER file"
return 1
fi
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "No matching root domain for $fulldomain found"
return 1
fi
# adding entry
_info "Adding the entry"
stripped_fulldomain=$(echo "$fulldomain" | sed "s/.$_domain//")
_debug "Adding $stripped_fulldomain to $_domain zone"
_myget "json-api/cpanel?cpanel_jsonapi_apiversion=2&cpanel_jsonapi_module=ZoneEdit&cpanel_jsonapi_func=add_zone_record&domain=$_domain&name=$stripped_fulldomain&type=TXT&txtdata=$txtvalue&ttl=1"
if _successful_update; then return 0; fi
_err "Couldn't create entry!"
return 1
}
# Usage: fulldomain txtvalue
# Used to remove the txt record after validation
dns_cpanel_rm() {
fulldomain=$1
txtvalue=$2
_info "Using cPanel based system"
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
if ! _cpanel_login; then
_err "cPanel Login failed for user $cPanel_Username. Check $HTTP_HEADER file"
return 1
fi
if ! _get_root; then
_err "No matching root domain for $fulldomain found"
return 1
fi
_findentry "$fulldomain" "$txtvalue"
if [ -z "$_id" ]; then
_info "Entry doesn't exist, nothing to delete"
return 0
fi
_debug "Deleting record..."
_myget "json-api/cpanel?cpanel_jsonapi_apiversion=2&cpanel_jsonapi_module=ZoneEdit&cpanel_jsonapi_func=remove_zone_record&domain=$_domain&line=$_id"
# removing entry
_debug "_result is: $_result"
if _successful_update; then return 0; fi
_err "Couldn't delete entry!"
return 1
}
#################### Private functions below ##################################
_checkcredentials() {
cPanel_Username="${cPanel_Username:-$(_readaccountconf_mutable cPanel_Username)}"
cPanel_Apitoken="${cPanel_Apitoken:-$(_readaccountconf_mutable cPanel_Apitoken)}"
cPanel_Hostname="${cPanel_Hostname:-$(_readaccountconf_mutable cPanel_Hostname)}"
if [ -z "$cPanel_Username" ] || [ -z "$cPanel_Apitoken" ] || [ -z "$cPanel_Hostname" ]; then
cPanel_Username=""
cPanel_Apitoken=""
cPanel_Hostname=""
_err "You haven't specified cPanel username, apitoken and hostname yet."
_err "Please add credentials and try again."
return 1
fi
#save the credentials to the account conf file.
_saveaccountconf_mutable cPanel_Username "$cPanel_Username"
_saveaccountconf_mutable cPanel_Apitoken "$cPanel_Apitoken"
_saveaccountconf_mutable cPanel_Hostname "$cPanel_Hostname"
return 0
}
_cpanel_login() {
if ! _checkcredentials; then return 1; fi
if ! _myget "json-api/cpanel?cpanel_jsonapi_apiversion=2&cpanel_jsonapi_module=CustInfo&cpanel_jsonapi_func=displaycontactinfo"; then
_err "cPanel login failed for user $cPanel_Username."
return 1
fi
return 0
}
_myget() {
#Adds auth header to request
export _H1="Authorization: cpanel $cPanel_Username:$cPanel_Apitoken"
_result=$(_get "$cPanel_Hostname/$1")
}
_get_root() {
_myget 'json-api/cpanel?cpanel_jsonapi_apiversion=2&cpanel_jsonapi_module=ZoneEdit&cpanel_jsonapi_func=fetchzones'
_domains=$(echo "$_result" | sed 's/.*\(zones.*\[\).*/\1/' | cut -d':' -f2 | sed 's/"//g' | sed 's/{//g')
_debug "_result is: $_result"
_debug "_domains is: $_domains"
if [ -z "$_domains" ]; then
_err "Primary domain list not found!"
return 1
fi
for _domain in $_domains; do
_debug "Checking if $fulldomain ends with $_domain"
if (_endswith "$fulldomain" "$_domain"); then
_debug "Root domain: $_domain"
return 0
fi
done
return 1
}
_successful_update() {
if (echo "$_result" | grep -q 'newserial'); then return 0; fi
return 1
}
_findentry() {
_debug "In _findentry"
#returns id of dns entry, if it exists
_myget "json-api/cpanel?cpanel_jsonapi_apiversion=2&cpanel_jsonapi_module=ZoneEdit&cpanel_jsonapi_func=fetchzone_records&domain=$_domain"
_id=$(echo "$_result" | sed "s/.*\(line.*$fulldomain.*$txtvalue\).*/\1/" | cut -d ':' -f 2 | cut -d ',' -f 1)
_debug "_result is: $_result"
_debug "fulldomain. is $fulldomain."
_debug "txtvalue is $txtvalue"
_debug "_id is: $_id"
if [ -n "$_id" ]; then
_debug "Entry found with _id=$_id"
return 0
fi
return 1
}
+159
View File
@@ -0,0 +1,159 @@
#!/usr/bin/env sh
#Script to use with curanet.dk, scannet.dk, wannafind.dk, dandomain.dk DNS management.
#Requires api credentials with scope: dns
#Author: Peter L. Hansen <peter@r12.dk>
#Version 1.0
CURANET_REST_URL="https://api.curanet.dk/dns/v1/Domains"
CURANET_AUTH_URL="https://apiauth.dk.team.blue/auth/realms/Curanet/protocol/openid-connect/token"
CURANET_ACCESS_TOKEN=""
######## Public functions #####################
#Usage: dns_curanet_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_curanet_add() {
fulldomain=$1
txtvalue=$2
_info "Using curanet"
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
CURANET_AUTHCLIENTID="${CURANET_AUTHCLIENTID:-$(_readaccountconf_mutable CURANET_AUTHCLIENTID)}"
CURANET_AUTHSECRET="${CURANET_AUTHSECRET:-$(_readaccountconf_mutable CURANET_AUTHSECRET)}"
if [ -z "$CURANET_AUTHCLIENTID" ] || [ -z "$CURANET_AUTHSECRET" ]; then
CURANET_AUTHCLIENTID=""
CURANET_AUTHSECRET=""
_err "You don't specify curanet api client and secret."
_err "Please create your auth info and try again."
return 1
fi
#save the credentials to the account conf file.
_saveaccountconf_mutable CURANET_AUTHCLIENTID "$CURANET_AUTHCLIENTID"
_saveaccountconf_mutable CURANET_AUTHSECRET "$CURANET_AUTHSECRET"
if ! _get_token; then
_err "Unable to get token"
return 1
fi
if ! _get_root "$fulldomain"; then
_err "Invalid domain"
return 1
fi
export _H1="Content-Type: application/json-patch+json"
export _H2="Accept: application/json"
export _H3="Authorization: Bearer $CURANET_ACCESS_TOKEN"
data="{\"name\": \"$fulldomain\",\"type\": \"TXT\",\"ttl\": 60,\"priority\": 0,\"data\": \"$txtvalue\"}"
response="$(_post "$data" "$CURANET_REST_URL/${_domain}/Records" "" "")"
if _contains "$response" "$txtvalue"; then
_debug "TXT record added OK"
else
_err "Unable to add TXT record"
return 1
fi
return 0
}
#Usage: fulldomain txtvalue
#Remove the txt record after validation.
dns_curanet_rm() {
fulldomain=$1
txtvalue=$2
_info "Using curanet"
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
CURANET_AUTHCLIENTID="${CURANET_AUTHCLIENTID:-$(_readaccountconf_mutable CURANET_AUTHCLIENTID)}"
CURANET_AUTHSECRET="${CURANET_AUTHSECRET:-$(_readaccountconf_mutable CURANET_AUTHSECRET)}"
if ! _get_token; then
_err "Unable to get token"
return 1
fi
if ! _get_root "$fulldomain"; then
_err "Invalid domain"
return 1
fi
_debug "Getting current record list to identify TXT to delete"
export _H1="Content-Type: application/json"
export _H2="Accept: application/json"
export _H3="Authorization: Bearer $CURANET_ACCESS_TOKEN"
response="$(_get "$CURANET_REST_URL/${_domain}/Records" "" "")"
if ! _contains "$response" "$txtvalue"; then
_err "Unable to delete record (does not contain $txtvalue )"
return 1
fi
recordid=$(echo "$response" | _egrep_o "{\"id\":[0-9]+,\"name\":\"$fulldomain\",\"type\":\"TXT\",\"ttl\":60,\"priority\":0,\"data\":\"..$txtvalue" | _egrep_o "id\":[0-9]+" | cut -c 5-)
if [ -z "$recordid" ]; then
_err "Unable to get recordid"
_debug "regex {\"id\":[0-9]+,\"name\":\"$fulldomain\",\"type\":\"TXT\",\"ttl\":60,\"priority\":0,\"data\":\"..$txtvalue"
_debug "response $response"
return 1
fi
_debug "Deleting recordID $recordid"
response="$(_post "" "$CURANET_REST_URL/${_domain}/Records/$recordid" "" "DELETE")"
return 0
}
#################### Private functions below ##################################
_get_token() {
response="$(_post "grant_type=client_credentials&client_id=$CURANET_AUTHCLIENTID&client_secret=$CURANET_AUTHSECRET&scope=dns" "$CURANET_AUTH_URL" "" "")"
if ! _contains "$response" "access_token"; then
_err "Unable get access token"
return 1
fi
CURANET_ACCESS_TOKEN=$(echo "$response" | _egrep_o "\"access_token\":\"[^\"]+" | cut -c 17-)
if [ -z "$CURANET_ACCESS_TOKEN" ]; then
_err "Unable to get token"
return 1
fi
return 0
}
#_acme-challenge.www.domain.com
#returns
# _domain=domain.com
# _domain_id=sdjkglgdfewsdfg
_get_root() {
domain=$1
i=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
export _H1="Content-Type: application/json"
export _H2="Accept: application/json"
export _H3="Authorization: Bearer $CURANET_ACCESS_TOKEN"
response="$(_get "$CURANET_REST_URL/$h/Records" "" "")"
if [ ! "$(echo "$response" | _egrep_o "Entity not found")" ]; then
_domain=$h
return 0
fi
i=$(_math "$i" + 1)
done
return 1
}
-185
View File
@@ -1,185 +0,0 @@
#!/usr/bin/env sh
# CloudXNS Domain api
#
#CX_Key="1234"
#
#CX_Secret="sADDsdasdgdsf"
CX_Api="https://www.cloudxns.net/api2"
#REST_API
######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_cx_add() {
fulldomain=$1
txtvalue=$2
CX_Key="${CX_Key:-$(_readaccountconf_mutable CX_Key)}"
CX_Secret="${CX_Secret:-$(_readaccountconf_mutable CX_Secret)}"
if [ -z "$CX_Key" ] || [ -z "$CX_Secret" ]; then
CX_Key=""
CX_Secret=""
_err "You don't specify cloudxns.net api key or secret yet."
_err "Please create you key and try again."
return 1
fi
REST_API="$CX_Api"
#save the api key and email to the account conf file.
_saveaccountconf_mutable CX_Key "$CX_Key"
_saveaccountconf_mutable CX_Secret "$CX_Secret"
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"
return 1
fi
add_record "$_domain" "$_sub_domain" "$txtvalue"
}
#fulldomain txtvalue
dns_cx_rm() {
fulldomain=$1
txtvalue=$2
CX_Key="${CX_Key:-$(_readaccountconf_mutable CX_Key)}"
CX_Secret="${CX_Secret:-$(_readaccountconf_mutable CX_Secret)}"
REST_API="$CX_Api"
if _get_root "$fulldomain"; then
record_id=""
existing_records "$_domain" "$_sub_domain" "$txtvalue"
if [ "$record_id" ]; then
_rest DELETE "record/$record_id/$_domain_id" "{}"
_info "Deleted record ${fulldomain}"
fi
fi
}
#usage: root sub
#return if the sub record already exists.
#echos the existing records count.
# '0' means doesn't exist
existing_records() {
_debug "Getting txt records"
root=$1
sub=$2
if ! _rest GET "record/$_domain_id?:domain_id?host_id=0&offset=0&row_num=100"; then
return 1
fi
seg=$(printf "%s\n" "$response" | _egrep_o '"record_id":[^{]*host":"'"$_sub_domain"'"[^}]*\}')
_debug seg "$seg"
if [ -z "$seg" ]; then
return 0
fi
if printf "%s" "$response" | grep '"type":"TXT"' >/dev/null; then
record_id=$(printf "%s\n" "$seg" | _egrep_o '"record_id":"[^"]*"' | cut -d : -f 2 | tr -d \" | _head_n 1)
_debug record_id "$record_id"
return 0
fi
}
#add the txt record.
#usage: root sub txtvalue
add_record() {
root=$1
sub=$2
txtvalue=$3
fulldomain="$sub.$root"
_info "Adding record"
if ! _rest POST "record" "{\"domain_id\": $_domain_id, \"host\":\"$_sub_domain\", \"value\":\"$txtvalue\", \"type\":\"TXT\",\"ttl\":600, \"line_id\":1}"; then
return 1
fi
return 0
}
#################### Private functions below ##################################
#_acme-challenge.www.domain.com
#returns
# _sub_domain=_acme-challenge.www
# _domain=domain.com
# _domain_id=sdjkglgdfewsdfg
_get_root() {
domain=$1
i=2
p=1
if ! _rest GET "domain"; then
return 1
fi
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
_debug h "$h"
if [ -z "$h" ]; then
#not valid
return 1
fi
if _contains "$response" "$h."; then
seg=$(printf "%s\n" "$response" | _egrep_o '"id":[^{]*"'"$h"'."[^}]*}')
_debug seg "$seg"
_domain_id=$(printf "%s\n" "$seg" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \")
_debug _domain_id "$_domain_id"
if [ "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_debug _sub_domain "$_sub_domain"
_domain="$h"
_debug _domain "$_domain"
return 0
fi
return 1
fi
p="$i"
i=$(_math "$i" + 1)
done
return 1
}
#Usage: method URI data
_rest() {
m=$1
ep="$2"
_debug ep "$ep"
url="$REST_API/$ep"
_debug url "$url"
cdate=$(date -u "+%Y-%m-%d %H:%M:%S UTC")
_debug cdate "$cdate"
data="$3"
_debug data "$data"
sec="$CX_Key$url$data$cdate$CX_Secret"
_debug sec "$sec"
hmac=$(printf "%s" "$sec" | _digest md5 hex)
_debug hmac "$hmac"
export _H1="API-KEY: $CX_Key"
export _H2="API-REQUEST-DATE: $cdate"
export _H3="API-HMAC: $hmac"
export _H4="Content-Type: application/json"
if [ "$data" ]; then
response="$(_post "$data" "$url" "" "$m")"
else
response="$(_get "$url")"
fi
if [ "$?" != "0" ]; then
_err "error $ep"
return 1
fi
_debug2 response "$response"
_contains "$response" '"code":1'
}
+2 -2
View File
@@ -12,7 +12,7 @@
# --
#
DDNSS_DNS_API="https://ip4.ddnss.de/upd.php"
DDNSS_DNS_API="https://ddnss.de/upd.php"
######## Public functions #####################
@@ -77,7 +77,7 @@ dns_ddnss_rm() {
# Now remove the TXT record from DDNS DNS
_info "Trying to remove TXT record"
if _ddnss_rest GET "key=$DDNSS_Token&host=$_ddnss_domain&txtm=1&txt=."; then
if _ddnss_rest GET "key=$DDNSS_Token&host=$_ddnss_domain&txtm=2"; then
if [ "$response" = "Updated 1 hostname." ]; then
_info "TXT record has been successfully removed from your DDNSS domain."
return 0
+87
View File
@@ -0,0 +1,87 @@
#!/usr/bin/env sh
# dnsHome.de API for acme.sh
#
# This Script adds the necessary TXT record to a Subdomain
#
# Author dnsHome.de (https://github.com/dnsHome-de)
#
# Report Bugs to https://github.com/acmesh-official/acme.sh/issues/3819
#
# export DNSHOME_Subdomain=""
# export DNSHOME_SubdomainPassword=""
# Usage: add subdomain.ddnsdomain.tld "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
# Used to add txt record
dns_dnshome_add() {
txtvalue=$2
DNSHOME_Subdomain="${DNSHOME_Subdomain:-$(_readdomainconf DNSHOME_Subdomain)}"
DNSHOME_SubdomainPassword="${DNSHOME_SubdomainPassword:-$(_readdomainconf DNSHOME_SubdomainPassword)}"
if [ -z "$DNSHOME_Subdomain" ] || [ -z "$DNSHOME_SubdomainPassword" ]; then
DNSHOME_Subdomain=""
DNSHOME_SubdomainPassword=""
_err "Please specify/export your dnsHome.de Subdomain and Password"
return 1
fi
#save the credentials to the account conf file.
_savedomainconf DNSHOME_Subdomain "$DNSHOME_Subdomain"
_savedomainconf DNSHOME_SubdomainPassword "$DNSHOME_SubdomainPassword"
DNSHOME_Api="https://$DNSHOME_Subdomain:$DNSHOME_SubdomainPassword@www.dnshome.de/dyndns.php"
_DNSHOME_rest POST "acme=add&txt=$txtvalue"
if ! echo "$response" | grep 'successfully' >/dev/null; then
_err "Error"
_err "$response"
return 1
fi
return 0
}
# Usage: txtvalue
# Used to remove the txt record after validation
dns_dnshome_rm() {
txtvalue=$2
DNSHOME_Subdomain="${DNSHOME_Subdomain:-$(_readdomainconf DNSHOME_Subdomain)}"
DNSHOME_SubdomainPassword="${DNSHOME_SubdomainPassword:-$(_readdomainconf DNSHOME_SubdomainPassword)}"
DNSHOME_Api="https://$DNSHOME_Subdomain:$DNSHOME_SubdomainPassword@www.dnshome.de/dyndns.php"
if [ -z "$DNSHOME_Subdomain" ] || [ -z "$DNSHOME_SubdomainPassword" ]; then
DNSHOME_Subdomain=""
DNSHOME_SubdomainPassword=""
_err "Please specify/export your dnsHome.de Subdomain and Password"
return 1
fi
_DNSHOME_rest POST "acme=rm&txt=$txtvalue"
if ! echo "$response" | grep 'successfully' >/dev/null; then
_err "Error"
_err "$response"
return 1
fi
return 0
}
#################### Private functions below ##################################
_DNSHOME_rest() {
method=$1
data="$2"
_debug "$data"
_debug data "$data"
response="$(_post "$data" "$DNSHOME_Api" "" "$method")"
if [ "$?" != "0" ]; then
_err "error $data"
return 1
fi
_debug2 response "$response"
return 0
}
+146
View File
@@ -0,0 +1,146 @@
#!/usr/bin/env sh
#Author: Timur Umarov <inbox@tumarov.com>
FORNEX_API_URL="https://fornex.com/api/dns/v0.1"
######## Public functions #####################
#Usage: dns_fornex_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_fornex_add() {
fulldomain=$1
txtvalue=$2
if ! _Fornex_API; then
return 1
fi
if ! _get_root "$fulldomain"; then
_err "Unable to determine root domain"
return 1
else
_debug _domain "$_domain"
fi
_info "Adding record"
if _rest POST "$_domain/entry_set/add/" "host=$fulldomain&type=TXT&value=$txtvalue&apikey=$FORNEX_API_KEY"; then
_debug _response "$response"
if _contains "$response" '"ok": true' || _contains "$response" 'Такая запись уже существует.'; then
_info "Added, OK"
return 0
fi
fi
_err "Add txt record error."
return 1
}
#Usage: dns_fornex_rm _acme-challenge.www.domain.com
dns_fornex_rm() {
fulldomain=$1
txtvalue=$2
if ! _Fornex_API; then
return 1
fi
if ! _get_root "$fulldomain"; then
_err "Unable to determine root domain"
return 1
else
_debug _domain "$_domain"
fi
_debug "Getting txt records"
_rest GET "$_domain/entry_set.json?apikey=$FORNEX_API_KEY"
if ! _contains "$response" "$txtvalue"; then
_err "Txt record not found"
return 1
fi
_record_id="$(echo "$response" | _egrep_o "{[^{]*\"value\"*:*\"$txtvalue\"[^}]*}" | sed -n -e 's#.*"id": \([0-9]*\).*#\1#p')"
_debug "_record_id" "$_record_id"
if [ -z "$_record_id" ]; then
_err "can not find _record_id"
return 1
fi
if ! _rest POST "$_domain/entry_set/$_record_id/delete/" "apikey=$FORNEX_API_KEY"; then
_err "Delete record error."
return 1
fi
return 0
}
#################### Private functions below ##################################
#_acme-challenge.www.domain.com
#returns
# _sub_domain=_acme-challenge.www
# _domain=domain.com
_get_root() {
domain=$1
i=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 ! _rest GET "domain_list.json?q=$h&apikey=$FORNEX_API_KEY"; then
return 1
fi
if _contains "$response" "\"$h\"" >/dev/null; then
_domain=$h
return 0
else
_debug "$h not found"
fi
i=$(_math "$i" + 1)
done
return 1
}
_Fornex_API() {
FORNEX_API_KEY="${FORNEX_API_KEY:-$(_readaccountconf_mutable FORNEX_API_KEY)}"
if [ -z "$FORNEX_API_KEY" ]; then
FORNEX_API_KEY=""
_err "You didn't specify the Fornex API key yet."
_err "Please create your key and try again."
return 1
fi
_saveaccountconf_mutable FORNEX_API_KEY "$FORNEX_API_KEY"
}
#method method action data
_rest() {
m=$1
ep="$2"
data="$3"
_debug "$ep"
export _H1="Accept: application/json"
if [ "$m" != "GET" ]; then
_debug data "$data"
response="$(_post "$data" "$FORNEX_API_URL/$ep" "" "$m")"
else
response="$(_get "$FORNEX_API_URL/$ep" | _normalizeJson)"
fi
_ret="$?"
if [ "$_ret" != "0" ]; then
_err "error $ep"
return 1
fi
_debug2 response "$response"
return 0
}
+4 -1
View File
@@ -163,5 +163,8 @@ _dns_gcloud_get_rrdatas() {
return 1
fi
ttl=$(echo "$rrdatas" | cut -f1)
rrdatas=$(echo "$rrdatas" | cut -f2 | sed 's/","/"\n"/g')
# starting with version 353.0.0 gcloud seems to
# separate records with a semicolon instead of commas
# see also https://cloud.google.com/sdk/docs/release-notes#35300_2021-08-17
rrdatas=$(echo "$rrdatas" | cut -f2 | sed 's/"[,;]"/"\n"/g')
}
-177
View File
@@ -1,177 +0,0 @@
#!/usr/bin/env sh
#Author: Herman Sletteng
#Report Bugs here: https://github.com/loial/acme.sh
#
#
# Note, gratisdns requires a login first, so the script needs to handle
# temporary cookies. Since acme.sh _get/_post currently don't directly support
# cookies, I've defined wrapper functions _myget/_mypost to set the headers
GDNSDK_API="https://admin.gratisdns.com"
######## Public functions #####################
#Usage: dns_gdnsdk_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_gdnsdk_add() {
fulldomain=$1
txtvalue=$2
_info "Using gratisdns.dk"
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
if ! _gratisdns_login; then
_err "Login failed!"
return 1
fi
#finding domain zone
if ! _get_domain; then
_err "No matching root domain for $fulldomain found"
return 1
fi
# adding entry
_info "Adding the entry"
_mypost "action=dns_primary_record_added_txt&user_domain=$_domain&name=$fulldomain&txtdata=$txtvalue&ttl=1"
if _successful_update; then return 0; fi
_err "Couldn't create entry!"
return 1
}
#Usage: fulldomain txtvalue
#Remove the txt record after validation.
dns_gdnsdk_rm() {
fulldomain=$1
txtvalue=$2
_info "Using gratisdns.dk"
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
if ! _gratisdns_login; then
_err "Login failed!"
return 1
fi
if ! _get_domain; then
_err "No matching root domain for $fulldomain found"
return 1
fi
_findentry "$fulldomain" "$txtvalue"
if [ -z "$_id" ]; then
_info "Entry doesn't exist, nothing to delete"
return 0
fi
_debug "Deleting record..."
_mypost "action=dns_primary_delete_txt&user_domain=$_domain&id=$_id"
# removing entry
if _successful_update; then return 0; fi
_err "Couldn't delete entry!"
return 1
}
#################### Private functions below ##################################
_checkcredentials() {
GDNSDK_Username="${GDNSDK_Username:-$(_readaccountconf_mutable GDNSDK_Username)}"
GDNSDK_Password="${GDNSDK_Password:-$(_readaccountconf_mutable GDNSDK_Password)}"
if [ -z "$GDNSDK_Username" ] || [ -z "$GDNSDK_Password" ]; then
GDNSDK_Username=""
GDNSDK_Password=""
_err "You haven't specified gratisdns.dk username and password yet."
_err "Please add credentials and try again."
return 1
fi
#save the credentials to the account conf file.
_saveaccountconf_mutable GDNSDK_Username "$GDNSDK_Username"
_saveaccountconf_mutable GDNSDK_Password "$GDNSDK_Password"
return 0
}
_checkcookie() {
GDNSDK_Cookie="${GDNSDK_Cookie:-$(_readaccountconf_mutable GDNSDK_Cookie)}"
if [ -z "$GDNSDK_Cookie" ]; then
_debug "No cached cookie found"
return 1
fi
_myget "action="
if (echo "$_result" | grep -q "logmeout"); then
_debug "Cached cookie still valid"
return 0
fi
_debug "Cached cookie no longer valid"
GDNSDK_Cookie=""
_saveaccountconf_mutable GDNSDK_Cookie "$GDNSDK_Cookie"
return 1
}
_gratisdns_login() {
if ! _checkcredentials; then return 1; fi
if _checkcookie; then
_debug "Already logged in"
return 0
fi
_debug "Logging into GratisDNS with user $GDNSDK_Username"
if ! _mypost "login=$GDNSDK_Username&password=$GDNSDK_Password&action=logmein"; then
_err "GratisDNS login failed for user $GDNSDK_Username bad RC from _post"
return 1
fi
GDNSDK_Cookie="$(grep -A 15 '302 Found' "$HTTP_HEADER" | _egrep_o 'Cookie: [^;]*' | _head_n 1 | cut -d ' ' -f2)"
if [ -z "$GDNSDK_Cookie" ]; then
_err "GratisDNS login failed for user $GDNSDK_Username. Check $HTTP_HEADER file"
return 1
fi
export GDNSDK_Cookie
_saveaccountconf_mutable GDNSDK_Cookie "$GDNSDK_Cookie"
return 0
}
_myget() {
#Adds cookie to request
export _H1="Cookie: $GDNSDK_Cookie"
_result=$(_get "$GDNSDK_API?$1")
}
_mypost() {
#Adds cookie to request
export _H1="Cookie: $GDNSDK_Cookie"
_result=$(_post "$1" "$GDNSDK_API")
}
_get_domain() {
_myget 'action=dns_primarydns'
_domains=$(echo "$_result" | _egrep_o ' domain="[[:alnum:]._-]+' | sed 's/^.*"//')
if [ -z "$_domains" ]; then
_err "Primary domain list not found!"
return 1
fi
for _domain in $_domains; do
if (_endswith "$fulldomain" "$_domain"); then
_debug "Root domain: $_domain"
return 0
fi
done
return 1
}
_successful_update() {
if (echo "$_result" | grep -q 'table-success'); then return 0; fi
return 1
}
_findentry() {
#args $1: fulldomain, $2: txtvalue
#returns id of dns entry, if it exists
_myget "action=dns_primary_changeDNSsetup&user_domain=$_domain"
_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
fi
return 1
}
+232
View File
@@ -0,0 +1,232 @@
#!/usr/bin/env sh
########################################################################
# Geoscaling hook script for acme.sh
#
# Environment variables:
#
# - $GEOSCALING_Username (your Geoscaling username - this is usually NOT an amail address)
# - $GEOSCALING_Password (your Geoscaling password)
#-- dns_geoscaling_add() - Add TXT record --------------------------------------
# Usage: dns_geoscaling_add _acme-challenge.subdomain.domain.com "XyZ123..."
dns_geoscaling_add() {
full_domain=$1
txt_value=$2
_info "Using DNS-01 Geoscaling DNS2 hook"
GEOSCALING_Username="${GEOSCALING_Username:-$(_readaccountconf_mutable GEOSCALING_Username)}"
GEOSCALING_Password="${GEOSCALING_Password:-$(_readaccountconf_mutable GEOSCALING_Password)}"
if [ -z "$GEOSCALING_Username" ] || [ -z "$GEOSCALING_Password" ]; then
GEOSCALING_Username=
GEOSCALING_Password=
_err "No auth details provided. Please set user credentials using the \$GEOSCALING_Username and \$GEOSCALING_Password environment variables."
return 1
fi
_saveaccountconf_mutable GEOSCALING_Username "${GEOSCALING_Username}"
_saveaccountconf_mutable GEOSCALING_Password "${GEOSCALING_Password}"
# Fills in the $zone_id and $zone_name
find_zone "${full_domain}" || return 1
_debug "Zone id '${zone_id}' will be used."
# We're logged in here
# we should add ${full_domain} minus the trailing ${zone_name}
prefix=$(echo "${full_domain}" | sed "s|\\.${zone_name}\$||")
body="id=${zone_id}&name=${prefix}&type=TXT&content=${txt_value}&ttl=300&prio=0"
do_post "$body" "https://www.geoscaling.com/dns2/ajax/add_record.php"
exit_code="$?"
if [ "${exit_code}" -eq 0 ]; then
_info "TXT record added successfully."
else
_err "Couldn't add the TXT record."
fi
do_logout
return "${exit_code}"
}
#-- dns_geoscaling_rm() - Remove TXT record ------------------------------------
# Usage: dns_geoscaling_rm _acme-challenge.subdomain.domain.com "XyZ123..."
dns_geoscaling_rm() {
full_domain=$1
txt_value=$2
_info "Cleaning up after DNS-01 Geoscaling DNS2 hook"
GEOSCALING_Username="${GEOSCALING_Username:-$(_readaccountconf_mutable GEOSCALING_Username)}"
GEOSCALING_Password="${GEOSCALING_Password:-$(_readaccountconf_mutable GEOSCALING_Password)}"
if [ -z "$GEOSCALING_Username" ] || [ -z "$GEOSCALING_Password" ]; then
GEOSCALING_Username=
GEOSCALING_Password=
_err "No auth details provided. Please set user credentials using the \$GEOSCALING_Username and \$GEOSCALING_Password environment variables."
return 1
fi
_saveaccountconf_mutable GEOSCALING_Username "${GEOSCALING_Username}"
_saveaccountconf_mutable GEOSCALING_Password "${GEOSCALING_Password}"
# fills in the $zone_id
find_zone "${full_domain}" || return 1
_debug "Zone id '${zone_id}' will be used."
# Here we're logged in
# Find the record id to clean
# get the domain
response=$(do_get "https://www.geoscaling.com/dns2/index.php?module=domain&id=${zone_id}")
_debug2 "response" "$response"
table="$(echo "${response}" | tr -d '\n' | sed 's|.*<div class="box"><div class="boxtitle">Basic Records</div><div class="boxtext"><table|<table|; s|</table>.*|</table>|')"
_debug2 table "${table}"
names=$(echo "${table}" | _egrep_o 'id="[0-9]+\.name">[^<]*</td>' | sed 's|</td>||; s|.*>||')
ids=$(echo "${table}" | _egrep_o 'id="[0-9]+\.name">[^<]*</td>' | sed 's|\.name">.*||; s|id="||')
types=$(echo "${table}" | _egrep_o 'id="[0-9]+\.type">[^<]*</td>' | sed 's|</td>||; s|.*>||')
values=$(echo "${table}" | _egrep_o 'id="[0-9]+\.content">[^<]*</td>' | sed 's|</td>||; s|.*>||')
_debug2 names "${names}"
_debug2 ids "${ids}"
_debug2 types "${types}"
_debug2 values "${values}"
# look for line whose name is ${full_domain}, whose type is TXT, and whose value is ${txt_value}
line_num="$(echo "${values}" | grep -F -n -- "${txt_value}" | _head_n 1 | cut -d ':' -f 1)"
_debug2 line_num "${line_num}"
found_id=
if [ -n "$line_num" ]; then
type=$(echo "${types}" | sed -n "${line_num}p")
name=$(echo "${names}" | sed -n "${line_num}p")
id=$(echo "${ids}" | sed -n "${line_num}p")
_debug2 type "$type"
_debug2 name "$name"
_debug2 id "$id"
_debug2 full_domain "$full_domain"
if [ "${type}" = "TXT" ] && [ "${name}" = "${full_domain}" ]; then
found_id=${id}
fi
fi
if [ "${found_id}" = "" ]; then
_err "Can not find record id."
return 0
fi
# Remove the record
body="id=${zone_id}&record_id=${found_id}"
response=$(do_post "$body" "https://www.geoscaling.com/dns2/ajax/delete_record.php")
exit_code="$?"
if [ "$exit_code" -eq 0 ]; then
_info "Record removed successfully."
else
_err "Could not clean (remove) up the record. Please go to Geoscaling administration interface and clean it by hand."
fi
do_logout
return "${exit_code}"
}
########################## PRIVATE FUNCTIONS ###########################
do_get() {
_url=$1
export _H1="Cookie: $geoscaling_phpsessid_cookie"
_get "${_url}"
}
do_post() {
_body=$1
_url=$2
export _H1="Cookie: $geoscaling_phpsessid_cookie"
_post "${_body}" "${_url}"
}
do_login() {
_info "Logging in..."
username_encoded="$(printf "%s" "${GEOSCALING_Username}" | _url_encode)"
password_encoded="$(printf "%s" "${GEOSCALING_Password}" | _url_encode)"
body="username=${username_encoded}&password=${password_encoded}"
response=$(_post "$body" "https://www.geoscaling.com/dns2/index.php?module=auth")
_debug2 response "${response}"
#retcode=$(grep '^HTTP[^ ]*' "${HTTP_HEADER}" | _head_n 1 | _egrep_o '[0-9]+$')
retcode=$(grep '^HTTP[^ ]*' "${HTTP_HEADER}" | _head_n 1 | cut -d ' ' -f 2)
if [ "$retcode" != "302" ]; then
_err "Geoscaling login failed for user ${GEOSCALING_Username}. Check ${HTTP_HEADER} file"
return 1
fi
geoscaling_phpsessid_cookie="$(grep -i '^set-cookie:' "${HTTP_HEADER}" | _egrep_o 'PHPSESSID=[^;]*;' | tr -d ';')"
return 0
}
do_logout() {
_info "Logging out."
response="$(do_get "https://www.geoscaling.com/dns2/index.php?module=auth")"
_debug2 response "$response"
return 0
}
find_zone() {
domain="$1"
# do login
do_login || return 1
# get zones
response="$(do_get "https://www.geoscaling.com/dns2/index.php?module=domains")"
table="$(echo "${response}" | tr -d '\n' | sed 's|.*<div class="box"><div class="boxtitle">Your domains</div><div class="boxtext"><table|<table|; s|</table>.*|</table>|')"
_debug2 table "${table}"
zone_names="$(echo "${table}" | _egrep_o '<b>[^<]*</b>' | sed 's|<b>||;s|</b>||')"
_debug2 _matches "${zone_names}"
# Zone names and zone IDs are in same order
zone_ids=$(echo "${table}" | _egrep_o '<a href=.index\.php\?module=domain&id=[0-9]+. onclick="javascript:show_loader\(\);">' | sed 's|.*id=||;s|. .*||')
_debug2 "These are the zones on this Geoscaling account:"
_debug2 "zone_names" "${zone_names}"
_debug2 "And these are their respective IDs:"
_debug2 "zone_ids" "${zone_ids}"
if [ -z "${zone_names}" ] || [ -z "${zone_ids}" ]; then
_err "Can not get zone names or IDs."
return 1
fi
# Walk through all possible zone names
strip_counter=1
while true; do
attempted_zone=$(echo "${domain}" | cut -d . -f ${strip_counter}-)
# All possible zone names have been tried
if [ -z "${attempted_zone}" ]; then
_err "No zone for domain '${domain}' found."
return 1
fi
_debug "Looking for zone '${attempted_zone}'"
line_num="$(echo "${zone_names}" | grep -n "^${attempted_zone}\$" | _head_n 1 | cut -d : -f 1)"
_debug2 line_num "${line_num}"
if [ "$line_num" ]; then
zone_id=$(echo "${zone_ids}" | sed -n "${line_num}p")
zone_name=$(echo "${zone_names}" | sed -n "${line_num}p")
if [ -z "${zone_id}" ]; then
_err "Can not find zone id."
return 1
fi
_debug "Found relevant zone '${attempted_zone}' with id '${zone_id}' - will be used for domain '${domain}'."
return 0
fi
_debug "Zone '${attempted_zone}' doesn't exist, let's try a less specific zone."
strip_counter=$(_math "${strip_counter}" + 1)
done
}
# vim: et:ts=2:sw=2:
+1 -1
View File
@@ -85,7 +85,7 @@ dns_he_rm() {
_debug "The txt record is not found, just skip"
return 0
fi
_record_id="$(echo "$response" | tr -d "#" | sed "s/<tr/#<tr/g" | tr -d "\n" | tr "#" "\n" | grep "$_full_domain" | grep '"dns_tr"' | grep "$_txt_value" | cut -d '"' -f 4)"
_record_id="$(echo "$response" | tr -d "#" | sed "s/<tr/#<tr/g" | tr -d "\n" | tr "#" "\n" | grep "$_full_domain" | grep '"dns_tr"' | grep -- "$_txt_value" | cut -d '"' -f 4)"
_debug2 _record_id "$_record_id"
if [ -z "$_record_id" ]; then
_err "Can not find record id"
+28 -14
View File
@@ -35,7 +35,7 @@ dns_huaweicloud_add() {
_err "dns_api(dns_huaweicloud): Error getting token."
return 1
fi
_debug "Access token is: ${token}"
_secure_debug "Access token is:" "${token}"
unset zoneid
zoneid="$(_get_zoneid "${token}" "${fulldomain}")"
@@ -43,7 +43,7 @@ dns_huaweicloud_add() {
_err "dns_api(dns_huaweicloud): Error getting zone id."
return 1
fi
_debug "Zone ID is: ${zoneid}"
_debug "Zone ID is:" "${zoneid}"
_debug "Adding Record"
_add_record "${token}" "${fulldomain}" "${txtvalue}"
@@ -86,7 +86,7 @@ dns_huaweicloud_rm() {
_err "dns_api(dns_huaweicloud): Error getting token."
return 1
fi
_debug "Access token is: ${token}"
_secure_debug "Access token is:" "${token}"
unset zoneid
zoneid="$(_get_zoneid "${token}" "${fulldomain}")"
@@ -94,7 +94,7 @@ dns_huaweicloud_rm() {
_err "dns_api(dns_huaweicloud): Error getting zone id."
return 1
fi
_debug "Zone ID is: ${zoneid}"
_debug "Zone ID is:" "${zoneid}"
# Remove all records
# Therotically HuaweiCloud does not allow more than one record set
@@ -129,14 +129,28 @@ _get_zoneid() {
fi
_debug "$h"
response=$(_get "${dns_api}/v2/zones?name=${h}")
if _contains "${response}" "id"; then
_debug "Get Zone ID Success."
_zoneid=$(echo "${response}" | _egrep_o "\"id\": *\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | tr -d " ")
printf "%s" "${_zoneid}"
return 0
_debug2 "$response"
if _contains "${response}" '"id"'; then
zoneidlist=$(echo "${response}" | _egrep_o "\"id\": *\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | tr -d " ")
zonenamelist=$(echo "${response}" | _egrep_o "\"name\": *\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | tr -d " ")
_debug2 "Return Zone ID(s):" "${zoneidlist}"
_debug2 "Return Zone Name(s):" "${zonenamelist}"
zoneidnum=0
zoneidcount=$(echo "${zoneidlist}" | grep -c '^')
_debug "Retund Zone ID(s) Count:" "${zoneidcount}"
while [ "${zoneidnum}" -lt "${zoneidcount}" ]; do
zoneidnum=$(_math "$zoneidnum" + 1)
_zoneid=$(echo "${zoneidlist}" | sed -n "${zoneidnum}p")
zonename=$(echo "${zonenamelist}" | sed -n "${zoneidnum}p")
_debug "Check Zone Name" "${zonename}"
if [ "${zonename}" = "${h}." ]; then
_debug "Get Zone ID Success."
_debug "ZoneID:" "${_zoneid}"
printf "%s" "${_zoneid}"
return 0
fi
done
fi
i=$(_math "$i" + 1)
done
return 1
@@ -149,7 +163,7 @@ _get_recordset_id() {
export _H1="X-Auth-Token: ${_token}"
response=$(_get "${dns_api}/v2/zones/${_zoneid}/recordsets?name=${_domain}")
if _contains "${response}" "id"; then
if _contains "${response}" '"id"'; then
_id="$(echo "${response}" | _egrep_o "\"id\": *\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | tr -d " ")"
printf "%s" "${_id}"
return 0
@@ -197,7 +211,7 @@ _add_record() {
fi
_record_id="$(_get_recordset_id "${_token}" "${_domain}" "${zoneid}")"
_debug "Record Set ID is: ${_record_id}"
_debug "Record Set ID is:" "${_record_id}"
# Remove all records
while [ "${_record_id}" != "0" ]; do
@@ -269,7 +283,7 @@ _get_token() {
_post "${body}" "${iam_api}/v3/auth/tokens" >/dev/null
_code=$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")
_token=$(grep "^X-Subject-Token" "$HTTP_HEADER" | cut -d " " -f 2-)
_debug2 "${_code}"
_secure_debug "${_code}"
printf "%s" "${_token}"
return 0
}
+17 -8
View File
@@ -9,7 +9,6 @@ dns_infoblox_add() {
## Nothing to see here, just some housekeeping
fulldomain=$1
txtvalue=$2
baseurlnObject="https://$Infoblox_Server/wapi/v2.2.2/record:txt?name=$fulldomain&text=$txtvalue&view=$Infoblox_View"
_info "Using Infoblox API"
_debug fulldomain "$fulldomain"
@@ -19,12 +18,13 @@ dns_infoblox_add() {
if [ -z "$Infoblox_Creds" ] || [ -z "$Infoblox_Server" ]; then
Infoblox_Creds=""
Infoblox_Server=""
_err "You didn't specify the credentials, server or infoblox view yet (Infoblox_Creds, Infoblox_Server and Infoblox_View)."
_err "Please set them via EXPORT ([username:password], [ip or hostname]) and try again."
_err "You didn't specify the Infoblox credentials or server (Infoblox_Creds; Infoblox_Server)."
_err "Please set them via EXPORT Infoblox_Creds=username:password or EXPORT Infoblox_server=ip/hostname and try again."
return 1
fi
if [ -z "$Infoblox_View" ]; then
_info "No Infoblox_View set, using fallback value 'default'"
Infoblox_View="default"
fi
@@ -33,6 +33,9 @@ dns_infoblox_add() {
_saveaccountconf Infoblox_Server "$Infoblox_Server"
_saveaccountconf Infoblox_View "$Infoblox_View"
## URLencode Infoblox View to deal with e.g. spaces
Infoblox_ViewEncoded=$(printf "%b" "$Infoblox_View" | _url_encode)
## Base64 encode the credentials
Infoblox_CredsEncoded=$(printf "%b" "$Infoblox_Creds" | _base64)
@@ -40,11 +43,14 @@ dns_infoblox_add() {
export _H1="Accept-Language:en-US"
export _H2="Authorization: Basic $Infoblox_CredsEncoded"
## Construct the request URL
baseurlnObject="https://$Infoblox_Server/wapi/v2.2.2/record:txt?name=$fulldomain&text=$txtvalue&view=${Infoblox_ViewEncoded}"
## Add the challenge record to the Infoblox grid member
result="$(_post "" "$baseurlnObject" "" "POST")"
## Let's see if we get something intelligible back from the unit
if [ "$(echo "$result" | _egrep_o "record:txt/.*:.*/$Infoblox_View")" ]; then
if [ "$(echo "$result" | _egrep_o "record:txt/.*:.*/${Infoblox_ViewEncoded}")" ]; then
_info "Successfully created the txt record"
return 0
else
@@ -65,6 +71,9 @@ dns_infoblox_rm() {
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
## URLencode Infoblox View to deal with e.g. spaces
Infoblox_ViewEncoded=$(printf "%b" "$Infoblox_View" | _url_encode)
## Base64 encode the credentials
Infoblox_CredsEncoded="$(printf "%b" "$Infoblox_Creds" | _base64)"
@@ -73,18 +82,18 @@ dns_infoblox_rm() {
export _H2="Authorization: Basic $Infoblox_CredsEncoded"
## Does the record exist? Let's check.
baseurlnObject="https://$Infoblox_Server/wapi/v2.2.2/record:txt?name=$fulldomain&text=$txtvalue&view=$Infoblox_View&_return_type=xml-pretty"
baseurlnObject="https://$Infoblox_Server/wapi/v2.2.2/record:txt?name=$fulldomain&text=$txtvalue&view=${Infoblox_ViewEncoded}&_return_type=xml-pretty"
result="$(_get "$baseurlnObject")"
## Let's see if we get something intelligible back from the grid
if [ "$(echo "$result" | _egrep_o "record:txt/.*:.*/$Infoblox_View")" ]; then
if [ "$(echo "$result" | _egrep_o "record:txt/.*:.*/${Infoblox_ViewEncoded}")" ]; then
## Extract the object reference
objRef="$(printf "%b" "$result" | _egrep_o "record:txt/.*:.*/$Infoblox_View")"
objRef="$(printf "%b" "$result" | _egrep_o "record:txt/.*:.*/${Infoblox_ViewEncoded}")"
objRmUrl="https://$Infoblox_Server/wapi/v2.2.2/$objRef"
## Delete them! All the stale records!
rmResult="$(_post "" "$objRmUrl" "" "DELETE")"
## Let's see if that worked
if [ "$(echo "$rmResult" | _egrep_o "record:txt/.*:.*/$Infoblox_View")" ]; then
if [ "$(echo "$rmResult" | _egrep_o "record:txt/.*:.*/${Infoblox_ViewEncoded}")" ]; then
_info "Successfully deleted $objRef"
return 0
else
+1 -1
View File
@@ -32,7 +32,7 @@ dns_ispconfig_rm() {
#################### Private functions below ##################################
_ISPC_credentials() {
if [ -z "${ISPC_User}" ] || [ -z "$ISPC_Password" ] || [ -z "${ISPC_Api}" ] || [ -z "${ISPC_Api_Insecure}" ]; then
if [ -z "${ISPC_User}" ] || [ -z "${ISPC_Password}" ] || [ -z "${ISPC_Api}" ] || [ -z "${ISPC_Api_Insecure}" ]; then
ISPC_User=""
ISPC_Password=""
ISPC_Api=""
+4 -2
View File
@@ -19,8 +19,9 @@ dns_knot_add() {
_info "Adding ${fulldomain}. 60 TXT \"${txtvalue}\""
knsupdate -y "${KNOT_KEY}" <<EOF
knsupdate <<EOF
server ${KNOT_SERVER}
key ${KNOT_KEY}
zone ${_domain}.
update add ${fulldomain}. 60 TXT "${txtvalue}"
send
@@ -49,8 +50,9 @@ dns_knot_rm() {
_info "Removing ${fulldomain}. TXT"
knsupdate -y "${KNOT_KEY}" <<EOF
knsupdate <<EOF
server ${KNOT_SERVER}
key ${KNOT_KEY}
zone ${_domain}.
update del ${fulldomain}. TXT
send
+54 -30
View File
@@ -32,8 +32,12 @@ dns_loopia_add() {
_info "Adding record"
_loopia_add_sub_domain "$_domain" "$_sub_domain"
_loopia_add_record "$_domain" "$_sub_domain" "$txtvalue"
if ! _loopia_add_sub_domain "$_domain" "$_sub_domain"; then
return 1
fi
if ! _loopia_add_record "$_domain" "$_sub_domain" "$txtvalue"; then
return 1
fi
}
@@ -70,12 +74,13 @@ dns_loopia_rm() {
<value><string>%s</string></value>
</param>
</params>
</methodCall>' "$LOOPIA_User" "$LOOPIA_Password" "$_domain" "$_sub_domain")
</methodCall>' "$LOOPIA_User" "$Encoded_Password" "$_domain" "$_sub_domain")
response="$(_post "$xml_content" "$LOOPIA_Api" "" "POST")"
if ! _contains "$response" "OK"; then
_err "Error could not get txt records"
err_response=$(echo "$response" | sed 's/.*<string>\(.*\)<\/string>.*/\1/')
_err "Error could not get txt records: $err_response"
return 1
fi
}
@@ -101,6 +106,12 @@ _loopia_load_config() {
return 1
fi
if _contains "$LOOPIA_Password" "'" || _contains "$LOOPIA_Password" '"'; then
_err "Password contains quoute or double quoute and this is not supported by dns_loopia.sh"
return 1
fi
Encoded_Password=$(_xml_encode "$LOOPIA_Password")
return 0
}
@@ -133,11 +144,12 @@ _loopia_get_records() {
<value><string>%s</string></value>
</param>
</params>
</methodCall>' $LOOPIA_User $LOOPIA_Password "$domain" "$sub_domain")
</methodCall>' "$LOOPIA_User" "$Encoded_Password" "$domain" "$sub_domain")
response="$(_post "$xml_content" "$LOOPIA_Api" "" "POST")"
if ! _contains "$response" "<array>"; then
_err "Error"
err_response=$(echo "$response" | sed 's/.*<string>\(.*\)<\/string>.*/\1/')
_err "Error: $err_response"
return 1
fi
return 0
@@ -162,7 +174,7 @@ _get_root() {
<value><string>%s</string></value>
</param>
</params>
</methodCall>' $LOOPIA_User $LOOPIA_Password)
</methodCall>' "$LOOPIA_User" "$Encoded_Password")
response="$(_post "$xml_content" "$LOOPIA_Api" "" "POST")"
while true; do
@@ -206,32 +218,35 @@ _loopia_add_record() {
<value><string>%s</string></value>
</param>
<param>
<struct>
<member>
<name>type</name>
<value><string>TXT</string></value>
</member>
<member>
<name>priority</name>
<value><int>0</int></value>
</member>
<member>
<name>ttl</name>
<value><int>300</int></value>
</member>
<member>
<name>rdata</name>
<value><string>%s</string></value>
</member>
</struct>
<value>
<struct>
<member>
<name>type</name>
<value><string>TXT</string></value>
</member>
<member>
<name>priority</name>
<value><int>0</int></value>
</member>
<member>
<name>ttl</name>
<value><int>300</int></value>
</member>
<member>
<name>rdata</name>
<value><string>%s</string></value>
</member>
</struct>
</value>
</param>
</params>
</methodCall>' $LOOPIA_User $LOOPIA_Password "$domain" "$sub_domain" "$txtval")
</methodCall>' "$LOOPIA_User" "$Encoded_Password" "$domain" "$sub_domain" "$txtval")
response="$(_post "$xml_content" "$LOOPIA_Api" "" "POST")"
if ! _contains "$response" "OK"; then
_err "Error"
err_response=$(echo "$response" | sed 's/.*<string>\(.*\)<\/string>.*/\1/')
_err "Error: $err_response"
return 1
fi
return 0
@@ -255,7 +270,7 @@ _sub_domain_exists() {
<value><string>%s</string></value>
</param>
</params>
</methodCall>' $LOOPIA_User $LOOPIA_Password "$domain")
</methodCall>' "$LOOPIA_User" "$Encoded_Password" "$domain")
response="$(_post "$xml_content" "$LOOPIA_Api" "" "POST")"
@@ -290,13 +305,22 @@ _loopia_add_sub_domain() {
<value><string>%s</string></value>
</param>
</params>
</methodCall>' $LOOPIA_User $LOOPIA_Password "$domain" "$sub_domain")
</methodCall>' "$LOOPIA_User" "$Encoded_Password" "$domain" "$sub_domain")
response="$(_post "$xml_content" "$LOOPIA_Api" "" "POST")"
if ! _contains "$response" "OK"; then
_err "Error"
err_response=$(echo "$response" | sed 's/.*<string>\(.*\)<\/string>.*/\1/')
_err "Error: $err_response"
return 1
fi
return 0
}
_xml_encode() {
encoded_string=$1
encoded_string=$(echo "$encoded_string" | sed 's/&/\&amp;/')
encoded_string=$(echo "$encoded_string" | sed 's/</\&lt;/')
encoded_string=$(echo "$encoded_string" | sed 's/>/\&gt;/')
printf "%s" "$encoded_string"
}
+3 -1
View File
@@ -74,7 +74,7 @@ dns_mydevil_rm() {
validRecords="^${num}${w}${fulldomain}${w}TXT${w}${any}${txtvalue}$"
for id in $(devil dns list "$domain" | tail -n+2 | grep "${validRecords}" | cut -w -s -f 1); do
_info "Removing record $id from domain $domain"
devil dns del "$domain" "$id" || _err "Could not remove DNS record."
echo "y" | devil dns del "$domain" "$id" || _err "Could not remove DNS record."
done
}
@@ -87,7 +87,9 @@ mydevil_get_domain() {
domain=""
for domain in $(devil dns list | cut -w -s -f 1 | tail -n+2); do
_debug "Checking domain: $domain"
if _endswith "$fulldomain" "$domain"; then
_debug "Fulldomain '$fulldomain' matches '$domain'"
printf -- "%s" "$domain"
return 0
fi
+261
View File
@@ -0,0 +1,261 @@
#!/usr/bin/env sh
# Mythic Beasts is a long-standing UK service provider using standards-based OAuth2 authentication
# To test: ./acme.sh --dns dns_mythic_beasts --test --debug 1 --output-insecure --issue --domain domain.com
# Cannot retest once cert is issued
# OAuth2 tokens only valid for 300 seconds so we do not store
# NOTE: This will remove all TXT records matching the fulldomain, not just the added ones (_acme-challenge.www.domain.com)
# Test OAuth2 credentials
#MB_AK="aaaaaaaaaaaaaaaa"
#MB_AS="bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
# URLs
MB_API='https://api.mythic-beasts.com/dns/v2/zones'
MB_AUTH='https://auth.mythic-beasts.com/login'
######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_mythic_beasts_add() {
fulldomain=$1
txtvalue=$2
_info "MYTHIC BEASTS Adding record $fulldomain = $txtvalue"
if ! _initAuth; then
return 1
fi
if ! _get_root "$fulldomain"; then
return 1
fi
# method path body_data
if _mb_rest POST "$_domain/records/$_sub_domain/TXT" "$txtvalue"; then
if _contains "$response" "1 records added"; then
_info "Added, verifying..."
# Max 120 seconds to publish
for i in $(seq 1 6); do
# Retry on error
if ! _mb_rest GET "$_domain/records/$_sub_domain/TXT?verify"; then
_sleep 20
else
_info "Record published!"
return 0
fi
done
else
_err "\n$response"
fi
fi
_err "Add txt record error."
return 1
}
#Usage: rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_mythic_beasts_rm() {
fulldomain=$1
txtvalue=$2
_info "MYTHIC BEASTS Removing record $fulldomain = $txtvalue"
if ! _initAuth; then
return 1
fi
if ! _get_root "$fulldomain"; then
return 1
fi
# method path body_data
if _mb_rest DELETE "$_domain/records/$_sub_domain/TXT" "$txtvalue"; then
_info "Record removed"
return 0
fi
_err "Remove txt record error."
return 1
}
#################### Private functions below ##################################
#Possible formats:
# _acme-challenge.www.example.com
# _acme-challenge.example.com
# _acme-challenge.example.co.uk
# _acme-challenge.www.example.co.uk
# _acme-challenge.sub1.sub2.www.example.co.uk
# sub1.sub2.example.co.uk
# example.com
# example.co.uk
#returns
# _sub_domain=_acme-challenge.www
# _domain=domain.com
_get_root() {
domain=$1
i=1
p=1
_debug "Detect the root zone"
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
if [ -z "$h" ]; then
_err "Domain exhausted"
return 1
fi
# Use the status errors to find the domain, continue on 403 Access denied
# method path body_data
_mb_rest GET "$h/records"
ret="$?"
if [ "$ret" -eq 0 ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_domain="$h"
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
return 0
elif [ "$ret" -eq 1 ]; then
return 1
fi
p=$i
i=$(_math "$i" + 1)
if [ "$i" -gt 50 ]; then
break
fi
done
_err "Domain too long"
return 1
}
_initAuth() {
MB_AK="${MB_AK:-$(_readaccountconf_mutable MB_AK)}"
MB_AS="${MB_AS:-$(_readaccountconf_mutable MB_AS)}"
if [ -z "$MB_AK" ] || [ -z "$MB_AS" ]; then
MB_AK=""
MB_AS=""
_err "Please specify an OAuth2 Key & Secret"
return 1
fi
_saveaccountconf_mutable MB_AK "$MB_AK"
_saveaccountconf_mutable MB_AS "$MB_AS"
if ! _oauth2; then
return 1
fi
_info "Checking authentication"
_secure_debug access_token "$MB_TK"
_sleep 1
# GET a list of zones
# method path body_data
if ! _mb_rest GET ""; then
_err "The token is invalid"
return 1
fi
_info "Token OK"
return 0
}
# Github appears to use an outbound proxy for requests which means subsequent requests may not have the same
# source IP. The standard Mythic Beasts OAuth2 tokens are tied to an IP, meaning github test requests fail
# authentication. This is a work around using an undocumented MB API to obtain a token not tied to an
# IP just for the github tests.
_oauth2() {
if [ "$GITHUB_ACTIONS" = "true" ]; then
_oauth2_github
else
_oauth2_std
fi
return $?
}
_oauth2_std() {
# HTTP Basic Authentication
_H1="Authorization: Basic $(echo "$MB_AK:$MB_AS" | _base64)"
_H2="Accepts: application/json"
export _H1 _H2
body="grant_type=client_credentials"
_info "Getting OAuth2 token..."
# body url [needbase64] [POST|PUT|DELETE] [ContentType]
response="$(_post "$body" "$MB_AUTH" "" "POST" "application/x-www-form-urlencoded")"
if _contains "$response" "\"token_type\":\"bearer\""; then
MB_TK="$(echo "$response" | _egrep_o "access_token\":\"[^\"]*\"" | cut -d : -f 2 | tr -d '"')"
if [ -z "$MB_TK" ]; then
_err "Unable to get access_token"
_err "\n$response"
return 1
fi
else
_err "OAuth2 token_type not Bearer"
_err "\n$response"
return 1
fi
_debug2 response "$response"
return 0
}
_oauth2_github() {
_H1="Accepts: application/json"
export _H1
body="{\"login\":{\"handle\":\"$MB_AK\",\"pass\":\"$MB_AS\",\"floating\":1}}"
_info "Getting Floating token..."
# body url [needbase64] [POST|PUT|DELETE] [ContentType]
response="$(_post "$body" "$MB_AUTH" "" "POST" "application/json")"
MB_TK="$(echo "$response" | _egrep_o "\"token\":\"[^\"]*\"" | cut -d : -f 2 | tr -d '"')"
if [ -z "$MB_TK" ]; then
_err "Unable to get token"
_err "\n$response"
return 1
fi
_debug2 response "$response"
return 0
}
# method path body_data
_mb_rest() {
# URL encoded body for single API operations
m="$1"
ep="$2"
data="$3"
if [ -z "$ep" ]; then
_mb_url="$MB_API"
else
_mb_url="$MB_API/$ep"
fi
_H1="Authorization: Bearer $MB_TK"
_H2="Accepts: application/json"
export _H1 _H2
if [ "$data" ] || [ "$m" = "POST" ] || [ "$m" = "PUT" ] || [ "$m" = "DELETE" ]; then
# body url [needbase64] [POST|PUT|DELETE] [ContentType]
response="$(_post "data=$data" "$_mb_url" "" "$m" "application/x-www-form-urlencoded")"
else
response="$(_get "$_mb_url")"
fi
if [ "$?" != "0" ]; then
_err "Request error"
return 1
fi
header="$(cat "$HTTP_HEADER")"
status="$(echo "$header" | _egrep_o "^HTTP[^ ]* .*$" | cut -d " " -f 2-100 | tr -d "\f\n")"
code="$(echo "$status" | _egrep_o "^[0-9]*")"
if [ "$code" -ge 400 ] || _contains "$response" "\"error\"" || _contains "$response" "invalid_client"; then
_err "error $status"
_err "\n$response"
_debug "\n$header"
return 2
fi
_debug2 response "$response"
return 0
}
+4 -4
View File
@@ -119,16 +119,16 @@ login() {
tmp=$(_post "{\"action\": \"login\", \"param\": {\"apikey\": \"$NC_Apikey\", \"apipassword\": \"$NC_Apipw\", \"customernumber\": \"$NC_CID\"}}" "$end" "" "POST")
sid=$(echo "$tmp" | tr '{}' '\n' | grep apisessionid | cut -d '"' -f 4)
_debug "$tmp"
if [ "$(_getfield "$msg" "4" | sed s/\"status\":\"//g | sed s/\"//g)" != "success" ]; then
_err "$msg"
if [ "$(_getfield "$tmp" "4" | sed s/\"status\":\"//g | sed s/\"//g)" != "success" ]; then
_err "$tmp"
return 1
fi
}
logout() {
tmp=$(_post "{\"action\": \"logout\", \"param\": {\"apikey\": \"$NC_Apikey\", \"apisessionid\": \"$sid\", \"customernumber\": \"$NC_CID\"}}" "$end" "" "POST")
_debug "$tmp"
if [ "$(_getfield "$msg" "4" | sed s/\"status\":\"//g | sed s/\"//g)" != "success" ]; then
_err "$msg"
if [ "$(_getfield "$tmp" "4" | sed s/\"status\":\"//g | sed s/\"//g)" != "success" ]; then
_err "$tmp"
return 1
fi
}
+1 -1
View File
@@ -114,7 +114,7 @@ _get_root() {
fi
if _contains "$response" "\"name\":\"$h\"" >/dev/null; then
_domain_id=$(echo "$response" | _egrep_o "\"[^\"]*\",\"name\":\"$h" | cut -d , -f 1 | tr -d \")
_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
+1 -1
View File
@@ -51,7 +51,7 @@ dns_nsd_rm() {
Nsd_ZoneFile="${Nsd_ZoneFile:-$(_readdomainconf Nsd_ZoneFile)}"
Nsd_Command="${Nsd_Command:-$(_readdomainconf Nsd_Command)}"
sed -i "/$fulldomain. $ttlvalue IN TXT \"$txtvalue\"/d" "$Nsd_ZoneFile"
_sed_i "/$fulldomain. $ttlvalue IN TXT \"$txtvalue\"/d" "$Nsd_ZoneFile"
_info "Removed TXT record for $fulldomain"
_debug "Running $Nsd_Command"
if eval "$Nsd_Command"; then
+324
View File
@@ -0,0 +1,324 @@
#!/usr/bin/env sh
#
# Acme.sh DNS API plugin for Oracle Cloud Infrastructure
# Copyright (c) 2021, Oracle and/or its affiliates
#
# The plugin will automatically use the default profile from an OCI SDK and CLI
# configuration file, if it exists.
#
# Alternatively, set the following environment variables:
# - OCI_CLI_TENANCY : OCID of tenancy that contains the target DNS zone
# - OCI_CLI_USER : OCID of user with permission to add/remove records from zones
# - OCI_CLI_REGION : Should point to the tenancy home region
#
# One of the following two variables is required:
# - OCI_CLI_KEY_FILE: Path to private API signing key file in PEM format; or
# - OCI_CLI_KEY : The private API signing key in PEM format
#
# NOTE: using an encrypted private key that needs a passphrase is not supported.
#
dns_oci_add() {
_fqdn="$1"
_rdata="$2"
if _get_oci_zone; then
_add_record_body="{\"items\":[{\"domain\":\"${_sub_domain}.${_domain}\",\"rdata\":\"$_rdata\",\"rtype\":\"TXT\",\"ttl\": 30,\"operation\":\"ADD\"}]}"
response=$(_signed_request "PATCH" "/20180115/zones/${_domain}/records" "$_add_record_body")
if [ "$response" ]; then
_info "Success: added TXT record for ${_sub_domain}.${_domain}."
else
_err "Error: failed to add TXT record for ${_sub_domain}.${_domain}."
_err "Check that the user has permission to add records to this zone."
return 1
fi
else
return 1
fi
}
dns_oci_rm() {
_fqdn="$1"
_rdata="$2"
if _get_oci_zone; then
_remove_record_body="{\"items\":[{\"domain\":\"${_sub_domain}.${_domain}\",\"rdata\":\"$_rdata\",\"rtype\":\"TXT\",\"operation\":\"REMOVE\"}]}"
response=$(_signed_request "PATCH" "/20180115/zones/${_domain}/records" "$_remove_record_body")
if [ "$response" ]; then
_info "Success: removed TXT record for ${_sub_domain}.${_domain}."
else
_err "Error: failed to remove TXT record for ${_sub_domain}.${_domain}."
_err "Check that the user has permission to remove records from this zone."
return 1
fi
else
return 1
fi
}
#################### Private functions below ##################################
_get_oci_zone() {
if ! _oci_config; then
return 1
fi
if ! _get_zone "$_fqdn"; then
_err "Error: DNS Zone not found for $_fqdn in $OCI_CLI_TENANCY"
return 1
fi
return 0
}
_oci_config() {
_DEFAULT_OCI_CLI_CONFIG_FILE="$HOME/.oci/config"
OCI_CLI_CONFIG_FILE="${OCI_CLI_CONFIG_FILE:-$(_readaccountconf_mutable OCI_CLI_CONFIG_FILE)}"
if [ -z "$OCI_CLI_CONFIG_FILE" ]; then
OCI_CLI_CONFIG_FILE="$_DEFAULT_OCI_CLI_CONFIG_FILE"
fi
if [ "$_DEFAULT_OCI_CLI_CONFIG_FILE" != "$OCI_CLI_CONFIG_FILE" ]; then
_saveaccountconf_mutable OCI_CLI_CONFIG_FILE "$OCI_CLI_CONFIG_FILE"
else
_clearaccountconf_mutable OCI_CLI_CONFIG_FILE
fi
_DEFAULT_OCI_CLI_PROFILE="DEFAULT"
OCI_CLI_PROFILE="${OCI_CLI_PROFILE:-$(_readaccountconf_mutable OCI_CLI_PROFILE)}"
if [ "$_DEFAULT_OCI_CLI_PROFILE" != "$OCI_CLI_PROFILE" ]; then
_saveaccountconf_mutable OCI_CLI_PROFILE "$OCI_CLI_PROFILE"
else
OCI_CLI_PROFILE="$_DEFAULT_OCI_CLI_PROFILE"
_clearaccountconf_mutable OCI_CLI_PROFILE
fi
OCI_CLI_TENANCY="${OCI_CLI_TENANCY:-$(_readaccountconf_mutable OCI_CLI_TENANCY)}"
if [ "$OCI_CLI_TENANCY" ]; then
_saveaccountconf_mutable OCI_CLI_TENANCY "$OCI_CLI_TENANCY"
elif [ -f "$OCI_CLI_CONFIG_FILE" ]; then
_debug "Reading OCI_CLI_TENANCY value from: $OCI_CLI_CONFIG_FILE"
OCI_CLI_TENANCY="${OCI_CLI_TENANCY:-$(_readini "$OCI_CLI_CONFIG_FILE" tenancy "$OCI_CLI_PROFILE")}"
fi
if [ -z "$OCI_CLI_TENANCY" ]; then
_err "Error: unable to read OCI_CLI_TENANCY from config file or environment variable."
return 1
fi
OCI_CLI_USER="${OCI_CLI_USER:-$(_readaccountconf_mutable OCI_CLI_USER)}"
if [ "$OCI_CLI_USER" ]; then
_saveaccountconf_mutable OCI_CLI_USER "$OCI_CLI_USER"
elif [ -f "$OCI_CLI_CONFIG_FILE" ]; then
_debug "Reading OCI_CLI_USER value from: $OCI_CLI_CONFIG_FILE"
OCI_CLI_USER="${OCI_CLI_USER:-$(_readini "$OCI_CLI_CONFIG_FILE" user "$OCI_CLI_PROFILE")}"
fi
if [ -z "$OCI_CLI_USER" ]; then
_err "Error: unable to read OCI_CLI_USER from config file or environment variable."
return 1
fi
OCI_CLI_REGION="${OCI_CLI_REGION:-$(_readaccountconf_mutable OCI_CLI_REGION)}"
if [ "$OCI_CLI_REGION" ]; then
_saveaccountconf_mutable OCI_CLI_REGION "$OCI_CLI_REGION"
elif [ -f "$OCI_CLI_CONFIG_FILE" ]; then
_debug "Reading OCI_CLI_REGION value from: $OCI_CLI_CONFIG_FILE"
OCI_CLI_REGION="${OCI_CLI_REGION:-$(_readini "$OCI_CLI_CONFIG_FILE" region "$OCI_CLI_PROFILE")}"
fi
if [ -z "$OCI_CLI_REGION" ]; then
_err "Error: unable to read OCI_CLI_REGION from config file or environment variable."
return 1
fi
OCI_CLI_KEY="${OCI_CLI_KEY:-$(_readaccountconf_mutable OCI_CLI_KEY)}"
if [ -z "$OCI_CLI_KEY" ]; then
_clearaccountconf_mutable OCI_CLI_KEY
OCI_CLI_KEY_FILE="${OCI_CLI_KEY_FILE:-$(_readini "$OCI_CLI_CONFIG_FILE" key_file "$OCI_CLI_PROFILE")}"
if [ "$OCI_CLI_KEY_FILE" ] && [ -f "$OCI_CLI_KEY_FILE" ]; then
_debug "Reading OCI_CLI_KEY value from: $OCI_CLI_KEY_FILE"
OCI_CLI_KEY=$(_base64 <"$OCI_CLI_KEY_FILE")
_saveaccountconf_mutable OCI_CLI_KEY "$OCI_CLI_KEY"
fi
else
_saveaccountconf_mutable OCI_CLI_KEY "$OCI_CLI_KEY"
fi
if [ -z "$OCI_CLI_KEY_FILE" ] && [ -z "$OCI_CLI_KEY" ]; then
_err "Error: unable to find key file path in OCI config file or OCI_CLI_KEY_FILE."
_err "Error: unable to load private API signing key from OCI_CLI_KEY."
return 1
fi
if [ "$(printf "%s\n" "$OCI_CLI_KEY" | wc -l)" -eq 1 ]; then
OCI_CLI_KEY=$(printf "%s" "$OCI_CLI_KEY" | _dbase64 multiline)
fi
return 0
}
# _get_zone(): retrieves the Zone name and OCID
#
# _sub_domain=_acme-challenge.www
# _domain=domain.com
# _domain_ociid=ocid1.dns-zone.oc1..
_get_zone() {
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
_domain_id=$(_signed_request "GET" "/20180115/zones/$h" "" "id")
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
p=$i
i=$(_math "$i" + 1)
done
return 1
}
#Usage: privatekey
#Output MD5 fingerprint
_fingerprint() {
pkey="$1"
if [ -z "$pkey" ]; then
_usage "Usage: _fingerprint privkey"
return 1
fi
printf "%s" "$pkey" | ${ACME_OPENSSL_BIN:-openssl} rsa -pubout -outform DER 2>/dev/null | ${ACME_OPENSSL_BIN:-openssl} md5 -c | cut -d = -f 2 | tr -d ' '
}
_signed_request() {
_sig_method="$1"
_sig_target="$2"
_sig_body="$3"
_return_field="$4"
_key_fingerprint=$(_fingerprint "$OCI_CLI_KEY")
_sig_host="dns.$OCI_CLI_REGION.oraclecloud.com"
_sig_keyId="$OCI_CLI_TENANCY/$OCI_CLI_USER/$_key_fingerprint"
_sig_alg="rsa-sha256"
_sig_version="1"
_sig_now="$(LC_ALL=C \date -u "+%a, %d %h %Y %H:%M:%S GMT")"
_request_method=$(printf %s "$_sig_method" | _lower_case)
_curl_method=$(printf %s "$_sig_method" | _upper_case)
_request_target="(request-target): $_request_method $_sig_target"
_date_header="date: $_sig_now"
_host_header="host: $_sig_host"
_string_to_sign="$_request_target\n$_date_header\n$_host_header"
_sig_headers="(request-target) date host"
if [ "$_sig_body" ]; then
_secure_debug3 _sig_body "$_sig_body"
_sig_body_sha256="x-content-sha256: $(printf %s "$_sig_body" | _digest sha256)"
_sig_body_type="content-type: application/json"
_sig_body_length="content-length: ${#_sig_body}"
_string_to_sign="$_string_to_sign\n$_sig_body_sha256\n$_sig_body_type\n$_sig_body_length"
_sig_headers="$_sig_headers x-content-sha256 content-type content-length"
fi
_tmp_file=$(_mktemp)
if [ -f "$_tmp_file" ]; then
printf '%s' "$OCI_CLI_KEY" >"$_tmp_file"
_signature=$(printf '%b' "$_string_to_sign" | _sign "$_tmp_file" sha256 | tr -d '\r\n')
rm -f "$_tmp_file"
fi
_signed_header="Authorization: Signature version=\"$_sig_version\",keyId=\"$_sig_keyId\",algorithm=\"$_sig_alg\",headers=\"$_sig_headers\",signature=\"$_signature\""
_secure_debug3 _signed_header "$_signed_header"
if [ "$_curl_method" = "GET" ]; then
export _H1="$_date_header"
export _H2="$_signed_header"
_response="$(_get "https://${_sig_host}${_sig_target}")"
elif [ "$_curl_method" = "PATCH" ]; then
export _H1="$_date_header"
export _H2="$_sig_body_sha256"
export _H3="$_sig_body_type"
export _H4="$_sig_body_length"
export _H5="$_signed_header"
_response="$(_post "$_sig_body" "https://${_sig_host}${_sig_target}" "" "PATCH")"
else
_err "Unable to process method: $_curl_method."
fi
_ret="$?"
if [ "$_return_field" ]; then
_response="$(echo "$_response" | sed 's/\\\"//g'))"
_return=$(echo "${_response}" | _egrep_o "\"$_return_field\"\\s*:\\s*\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d "\"")
else
_return="$_response"
fi
printf "%s" "$_return"
return $_ret
}
# file key [section]
_readini() {
_file="$1"
_key="$2"
_section="${3:-DEFAULT}"
_start_n=$(grep -n '\['"$_section"']' "$_file" | cut -d : -f 1)
_debug3 _start_n "$_start_n"
if [ -z "$_start_n" ]; then
_err "Can not find section: $_section"
return 1
fi
_start_nn=$(_math "$_start_n" + 1)
_debug3 "_start_nn" "$_start_nn"
_left="$(sed -n "${_start_nn},99999p" "$_file")"
_debug3 _left "$_left"
_end="$(echo "$_left" | grep -n "^\[" | _head_n 1)"
_debug3 "_end" "$_end"
if [ "$_end" ]; then
_end_n=$(echo "$_end" | cut -d : -f 1)
_debug3 "_end_n" "$_end_n"
_seg_n=$(echo "$_left" | sed -n "1,${_end_n}p")
else
_seg_n="$_left"
fi
_debug3 "_seg_n" "$_seg_n"
_lineini="$(echo "$_seg_n" | grep "^ *$_key *= *")"
_inivalue="$(printf "%b" "$(eval "echo $_lineini | sed \"s/^ *${_key} *= *//g\"")")"
_debug2 _inivalue "$_inivalue"
echo "$_inivalue"
}
+1 -2
View File
@@ -150,8 +150,7 @@ _get_root() {
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)
id=$(echo "$_domain_response" | _egrep_o "\"[^\"]*\":{\"enabled\":\"1\",\"type\":{\"master\":{\"value\":\"master\",\"selected\":1},\"slave\":{\"value\":\"slave\",\"selected\":0}},\"masterip\":{\"[^\"]*\":{[^}]*}},\"transferkeyalgo\":{[^{]*{[^{]*{[^{]*{[^{]*{[^{]*{[^{]*{[^{]*{[^}]*}},\"transferkey\":\"[^\"]*\"(,\"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)
+5 -1
View File
@@ -198,6 +198,8 @@ dns_ovh_rm() {
if ! _ovh_rest DELETE "domain/zone/$_domain/record/$rid"; then
return 1
fi
_ovh_rest POST "domain/zone/$_domain/refresh"
_debug "Refresh:$response"
return 0
fi
done
@@ -261,7 +263,9 @@ _get_root() {
return 1
fi
if ! _contains "$response" "This service does not exist" >/dev/null && ! _contains "$response" "NOT_GRANTED_CALL" >/dev/null; then
if ! _contains "$response" "This service does not exist" >/dev/null &&
! _contains "$response" "This call has not been granted" >/dev/null &&
! _contains "$response" "NOT_GRANTED_CALL" >/dev/null; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_domain="$h"
return 0
+5 -4
View File
@@ -103,7 +103,7 @@ set_record() {
_build_record_string "$oldchallenge"
done
if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root" "{\"rrsets\": [{\"changetype\": \"REPLACE\", \"name\": \"$full.\", \"type\": \"TXT\", \"ttl\": $PDNS_Ttl, \"records\": [$_record_string]}]}"; then
if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root" "{\"rrsets\": [{\"changetype\": \"REPLACE\", \"name\": \"$full.\", \"type\": \"TXT\", \"ttl\": $PDNS_Ttl, \"records\": [$_record_string]}]}" "application/json"; then
_err "Set txt record error."
return 1
fi
@@ -126,7 +126,7 @@ rm_record() {
if _contains "$_existing_challenges" "$txtvalue"; then
#Delete all challenges (PowerDNS API does not allow to delete content)
if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root" "{\"rrsets\": [{\"changetype\": \"DELETE\", \"name\": \"$full.\", \"type\": \"TXT\"}]}"; then
if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root" "{\"rrsets\": [{\"changetype\": \"DELETE\", \"name\": \"$full.\", \"type\": \"TXT\"}]}" "application/json"; then
_err "Delete txt record error."
return 1
fi
@@ -140,7 +140,7 @@ rm_record() {
fi
done
#Recreate the existing challenges
if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root" "{\"rrsets\": [{\"changetype\": \"REPLACE\", \"name\": \"$full.\", \"type\": \"TXT\", \"ttl\": $PDNS_Ttl, \"records\": [$_record_string]}]}"; then
if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root" "{\"rrsets\": [{\"changetype\": \"REPLACE\", \"name\": \"$full.\", \"type\": \"TXT\", \"ttl\": $PDNS_Ttl, \"records\": [$_record_string]}]}" "application/json"; then
_err "Set txt record error."
return 1
fi
@@ -203,12 +203,13 @@ _pdns_rest() {
method=$1
ep=$2
data=$3
ct=$4
export _H1="X-API-Key: $PDNS_Token"
if [ ! "$method" = "GET" ]; then
_debug data "$data"
response="$(_post "$data" "$PDNS_Url$ep" "" "$method")"
response="$(_post "$data" "$PDNS_Url$ep" "" "$method" "$ct")"
else
response="$(_get "$PDNS_Url$ep")"
fi
+3 -2
View File
@@ -7,6 +7,7 @@
RACKSPACE_Endpoint="https://dns.api.rackspacecloud.com/v1.0"
# 20210923 - RS changed the fields in the API response; fix sed
# 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/acmesh-official/acme.sh/pull/1297
@@ -79,8 +80,8 @@ _get_root_zone() {
_debug2 response "$response"
if _contains "$response" "\"name\":\"$h\"" >/dev/null; then
# Response looks like:
# {"ttl":300,"accountId":12345,"id":1111111,"name":"example.com","emailAddress": ...<and so on>
_domain_id=$(echo "$response" | sed -n "s/^.*\"id\":\([^,]*\),\"name\":\"$h\",.*/\1/p")
# {"id":"12345","accountId":"1111111","name": "example.com","ttl":3600,"emailAddress": ... <and so on>
_domain_id=$(echo "$response" | sed -n "s/^.*\"id\":\"\([^,]*\)\",\"accountId\":\"[0-9]*\",\"name\":\"$h\",.*/\1/p")
_debug2 domain_id "$_domain_id"
if [ -n "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
+3 -2
View File
@@ -92,9 +92,10 @@ _get_root() {
domains_list=$(echo "${response}" | grep dname | sed -r "s/.*dname=\"([^\"]+)\".*/\\1/g")
for ITEM in ${domains_list}; do
IDN_ITEM="$(_idn "${ITEM}")"
case "${domain}" in
*${ITEM}*)
_domain=${ITEM}
*${IDN_ITEM}*)
_domain=${IDN_ITEM}
_debug _domain "${_domain}"
return 0
;;
+23 -15
View File
@@ -1,15 +1,15 @@
#!/usr/bin/env sh
#
# API-integration for Simply.com (https://www.simply.com)
#SIMPLY_AccountName="accountname"
#
#SIMPLY_ApiKey="apikey"
#
#SIMPLY_Api="https://api.simply.com/1/[ACCOUNTNAME]/[APIKEY]"
SIMPLY_Api_Default="https://api.simply.com/1"
#SIMPLY_Api="https://api.simply.com/2/"
SIMPLY_Api_Default="https://api.simply.com/2"
#This is used for determining success of REST call
SIMPLY_SUCCESS_CODE='"status": 200'
SIMPLY_SUCCESS_CODE='"status":200'
######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
@@ -51,7 +51,7 @@ dns_simply_rm() {
_simply_save_config
_debug "First detect the root zone"
_debug "Find the DNS zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"
@@ -77,8 +77,8 @@ dns_simply_rm() {
for record in $records; do
_debug record "$record"
record_data=$(echo "$record" | cut -d "," -f 3 | sed 's/"//g' | grep "data" | cut -d ":" -f 2)
record_type=$(echo "$record" | cut -d "," -f 4 | sed 's/"//g' | grep "type" | cut -d ":" -f 2)
record_data=$(echo "$record" | sed -n "s/.*\"data\":\"\([^\"]*\)\".*/\1/p")
record_type=$(echo "$record" | sed -n "s/.*\"type\":\"\([^\"]*\)\".*/\1/p")
_debug2 record_data "$record_data"
_debug2 record_type "$record_type"
@@ -151,7 +151,7 @@ _simply_save_config() {
_simply_get_all_records() {
domain=$1
if ! _simply_rest GET "my/products/$domain/dns/records"; then
if ! _simply_rest GET "my/products/$domain/dns/records/"; then
return 1
fi
@@ -169,7 +169,7 @@ _get_root() {
return 1
fi
if ! _simply_rest GET "my/products/$h/dns"; then
if ! _simply_rest GET "my/products/$h/dns/"; then
return 1
fi
@@ -193,7 +193,7 @@ _simply_add_record() {
data="{\"name\": \"$sub_domain\", \"type\":\"TXT\", \"data\": \"$txtval\", \"priority\":0, \"ttl\": 3600}"
if ! _simply_rest POST "my/products/$domain/dns/records" "$data"; then
if ! _simply_rest POST "my/products/$domain/dns/records/" "$data"; then
_err "Adding record not successfull!"
return 1
fi
@@ -214,7 +214,7 @@ _simply_delete_record() {
_debug record_id "Delete record with id $record_id"
if ! _simply_rest DELETE "my/products/$domain/dns/records/$record_id"; then
if ! _simply_rest DELETE "my/products/$domain/dns/records/$record_id/"; then
_err "Deleting record not successfull!"
return 1
fi
@@ -237,12 +237,18 @@ _simply_rest() {
_debug2 ep "$ep"
_debug2 m "$m"
export _H1="Content-Type: application/json"
basicauth=$(printf "%s:%s" "$SIMPLY_AccountName" "$SIMPLY_ApiKey" | _base64)
if [ "$basicauth" ]; then
export _H1="Authorization: Basic $basicauth"
fi
export _H2="Content-Type: application/json"
if [ "$m" != "GET" ]; then
response="$(_post "$data" "$SIMPLY_Api/$SIMPLY_AccountName/$SIMPLY_ApiKey/$ep" "" "$m")"
response="$(_post "$data" "$SIMPLY_Api/$ep" "" "$m")"
else
response="$(_get "$SIMPLY_Api/$SIMPLY_AccountName/$SIMPLY_ApiKey/$ep")"
response="$(_get "$SIMPLY_Api/$ep")"
fi
if [ "$?" != "0" ]; then
@@ -250,6 +256,8 @@ _simply_rest() {
return 1
fi
response="$(echo "$response" | _normalizeJson)"
_debug2 response "$response"
if _contains "$response" "Invalid account authorization"; then
+160
View File
@@ -0,0 +1,160 @@
#!/usr/bin/env sh
# united-domains Reselling (https://www.ud-reselling.com/) DNS API
# Author: Andreas Scherer (https://github.com/andischerer)
# Created: 2021-02-01
#
# Set the environment variables as below:
#
# export UDR_USER="your_username_goes_here"
# export UDR_PASS="some_password_goes_here"
#
UDR_API="https://api.domainreselling.de/api/call.cgi"
UDR_TTL="30"
######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "some_long_string_of_characters_go_here_from_lets_encrypt"
dns_udr_add() {
fulldomain=$1
txtvalue=$2
UDR_USER="${UDR_USER:-$(_readaccountconf_mutable UDR_USER)}"
UDR_PASS="${UDR_PASS:-$(_readaccountconf_mutable UDR_PASS)}"
if [ -z "$UDR_USER" ] || [ -z "$UDR_PASS" ]; then
UDR_USER=""
UDR_PASS=""
_err "You didn't specify an UD-Reselling username and password yet"
return 1
fi
# save the username and password to the account conf file.
_saveaccountconf_mutable UDR_USER "$UDR_USER"
_saveaccountconf_mutable UDR_PASS "$UDR_PASS"
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"
return 1
fi
_debug _dnszone "${_dnszone}"
_debug "Getting txt records"
if ! _udr_rest "QueryDNSZoneRRList" "dnszone=${_dnszone}"; then
return 1
fi
rr="${fulldomain}. ${UDR_TTL} IN TXT ${txtvalue}"
_debug resource_record "${rr}"
if _contains "$response" "$rr" >/dev/null; then
_err "Error, it would appear that this record already exists. Please review existing TXT records for this domain."
return 1
fi
_info "Adding record"
if ! _udr_rest "UpdateDNSZone" "dnszone=${_dnszone}&addrr0=${rr}"; then
_err "Adding the record did not succeed, please verify/check."
return 1
fi
_info "Added, OK"
return 0
}
dns_udr_rm() {
fulldomain=$1
txtvalue=$2
UDR_USER="${UDR_USER:-$(_readaccountconf_mutable UDR_USER)}"
UDR_PASS="${UDR_PASS:-$(_readaccountconf_mutable UDR_PASS)}"
if [ -z "$UDR_USER" ] || [ -z "$UDR_PASS" ]; then
UDR_USER=""
UDR_PASS=""
_err "You didn't specify an UD-Reselling username and password yet"
return 1
fi
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"
return 1
fi
_debug _dnszone "${_dnszone}"
_debug "Getting txt records"
if ! _udr_rest "QueryDNSZoneRRList" "dnszone=${_dnszone}"; then
return 1
fi
rr="${fulldomain}. ${UDR_TTL} IN TXT ${txtvalue}"
_debug resource_record "${rr}"
if _contains "$response" "$rr" >/dev/null; then
if ! _udr_rest "UpdateDNSZone" "dnszone=${_dnszone}&delrr0=${rr}"; then
_err "Deleting the record did not succeed, please verify/check."
return 1
fi
_info "Removed, OK"
return 0
else
_info "Text record is not present, will not delete anything."
return 0
fi
}
#################### Private functions below ##################################
#_acme-challenge.www.domain.com
#returns
# _sub_domain=_acme-challenge.www
# _domain=domain.com
_get_root() {
domain=$1
i=1
if ! _udr_rest "QueryDNSZoneList" ""; then
return 1
fi
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
_debug h "$h"
if [ -z "$h" ]; then
#not valid
return 1
fi
if _contains "${response}" "${h}." >/dev/null; then
_dnszone=$(echo "$response" | _egrep_o "${h}")
if [ "$_dnszone" ]; then
return 0
fi
return 1
fi
i=$(_math "$i" + 1)
done
return 1
}
_udr_rest() {
if [ -n "$2" ]; then
data="command=$1&$2"
else
data="command=$1"
fi
_debug data "${data}"
response="$(_post "${data}" "${UDR_API}?s_login=${UDR_USER}&s_pw=${UDR_PASS}" "" "POST")"
_code=$(echo "$response" | _egrep_o "code = ([0-9]+)" | _head_n 1 | cut -d = -f 2 | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')
_description=$(echo "$response" | _egrep_o "description = .*" | _head_n 1 | cut -d = -f 2 | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')
_debug response_code "$_code"
_debug response_description "$_description"
if [ ! "$_code" = "200" ]; then
_err "DNS-API-Error: $_description"
return 1
fi
return 0
}
+158
View File
@@ -0,0 +1,158 @@
#!/usr/bin/env sh
# bug reports to stepan@plyask.in
#
# export VEESP_User="username"
# export VEESP_Password="password"
VEESP_Api="https://secure.veesp.com/api"
######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_veesp_add() {
fulldomain=$1
txtvalue=$2
VEESP_Password="${VEESP_Password:-$(_readaccountconf_mutable VEESP_Password)}"
VEESP_User="${VEESP_User:-$(_readaccountconf_mutable VEESP_User)}"
VEESP_auth=$(printf "%s" "$VEESP_User:$VEESP_Password" | _base64)
if [ -z "$VEESP_Password" ] || [ -z "$VEESP_User" ]; then
VEESP_Password=""
VEESP_User=""
_err "You don't specify veesp api key and email yet."
_err "Please create you key and try again."
return 1
fi
#save the api key and email to the account conf file.
_saveaccountconf_mutable VEESP_Password "$VEESP_Password"
_saveaccountconf_mutable VEESP_User "$VEESP_User"
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"
return 1
fi
_debug _domain_id "$_domain_id"
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
_info "Adding record"
if VEESP_rest POST "service/$_service_id/dns/$_domain_id/records" "{\"name\":\"$fulldomain\",\"ttl\":1,\"priority\":0,\"type\":\"TXT\",\"content\":\"$txtvalue\"}"; then
if _contains "$response" "\"success\":true"; then
_info "Added"
#todo: check if the record takes effect
return 0
else
_err "Add txt record error."
return 1
fi
fi
}
# Usage: fulldomain txtvalue
# Used to remove the txt record after validation
dns_veesp_rm() {
fulldomain=$1
txtvalue=$2
VEESP_Password="${VEESP_Password:-$(_readaccountconf_mutable VEESP_Password)}"
VEESP_User="${VEESP_User:-$(_readaccountconf_mutable VEESP_User)}"
VEESP_auth=$(printf "%s" "$VEESP_User:$VEESP_Password" | _base64)
_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"
VEESP_rest GET "service/$_service_id/dns/$_domain_id"
count=$(printf "%s\n" "$response" | _egrep_o "\"type\":\"TXT\",\"content\":\".\"$txtvalue.\"\"" | wc -l | 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\":[^}]*\"type\":\"TXT\",\"content\":\".\"$txtvalue.\"\"" | cut -d\" -f4)
_debug "record_id" "$record_id"
if [ -z "$record_id" ]; then
_err "Can not get record id to remove."
return 1
fi
if ! VEESP_rest DELETE "service/$_service_id/dns/$_domain_id/records/$record_id"; then
_err "Delete record error."
return 1
fi
_contains "$response" "\"success\":true"
fi
}
#################### Private functions below ##################################
#_acme-challenge.www.domain.com
#returns
# _sub_domain=_acme-challenge.www
# _domain=domain.com
# _domain_id=sdjkglgdfewsdfg
_get_root() {
domain=$1
i=2
p=1
if ! VEESP_rest GET "dns"; then
return 1
fi
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
_debug h "$h"
if [ -z "$h" ]; then
#not valid
return 1
fi
if _contains "$response" "\"name\":\"$h\""; then
_domain_id=$(printf "%s\n" "$response" | _egrep_o "\"domain_id\":[^,]*,\"name\":\"$h\"" | cut -d : -f 2 | cut -d , -f 1 | cut -d '"' -f 2)
_debug _domain_id "$_domain_id"
_service_id=$(printf "%s\n" "$response" | _egrep_o "\"name\":\"$h\",\"service_id\":[^}]*" | cut -d : -f 3 | cut -d '"' -f 2)
_debug _service_id "$_service_id"
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
}
VEESP_rest() {
m=$1
ep="$2"
data="$3"
_debug "$ep"
export _H1="Accept: application/json"
export _H2="Authorization: Basic $VEESP_auth"
if [ "$m" != "GET" ]; then
_debug data "$data"
export _H3="Content-Type: application/json"
response="$(_post "$data" "$VEESP_Api/$ep" "" "$m")"
else
response="$(_get "$VEESP_Api/$ep")"
fi
if [ "$?" != "0" ]; then
_err "error $ep"
return 1
fi
_debug2 response "$response"
return 0
}
+3 -3
View File
@@ -33,7 +33,7 @@ dns_vultr_add() {
_debug 'Getting txt records'
_vultr_rest GET "dns/records?domain=$_domain"
if printf "%s\n" "$response" | grep "\"type\":\"TXT\",\"name\":\"$fulldomain\"" >/dev/null; then
if printf "%s\n" "$response" | grep -- "\"type\":\"TXT\",\"name\":\"$fulldomain\"" >/dev/null; then
_err 'Error'
return 1
fi
@@ -73,12 +73,12 @@ dns_vultr_rm() {
_debug 'Getting txt records'
_vultr_rest GET "dns/records?domain=$_domain"
if printf "%s\n" "$response" | grep "\"type\":\"TXT\",\"name\":\"$fulldomain\"" >/dev/null; then
if printf "%s\n" "$response" | grep -- "\"type\":\"TXT\",\"name\":\"$fulldomain\"" >/dev/null; then
_err 'Error'
return 1
fi
_record_id="$(echo "$response" | tr '{}' '\n' | grep '"TXT"' | grep "$txtvalue" | tr ',' '\n' | grep -i 'RECORDID' | cut -d : -f 2)"
_record_id="$(echo "$response" | tr '{}' '\n' | grep '"TXT"' | grep -- "$txtvalue" | tr ',' '\n' | grep -i 'RECORDID' | cut -d : -f 2)"
_debug _record_id "$_record_id"
if [ "$_record_id" ]; then
_info "Successfully retrieved the record id for ACME challenge."
+17 -25
View File
@@ -24,7 +24,7 @@ dns_world4you_add() {
fi
export _H1="Cookie: W4YSESSID=$sessid"
form=$(_get "$WORLD4YOU_API/dashboard/paketuebersicht")
form=$(_get "$WORLD4YOU_API/")
_get_paketnr "$fqdn" "$form"
paketnr="$PAKETNR"
if [ -z "$paketnr" ]; then
@@ -36,7 +36,6 @@ dns_world4you_add() {
export _H1="Cookie: W4YSESSID=$sessid"
form=$(_get "$WORLD4YOU_API/$paketnr/dns")
formiddp=$(echo "$form" | grep 'AddDnsRecordForm\[uniqueFormIdDP\]' | sed 's/^.*name="AddDnsRecordForm\[uniqueFormIdDP\]" value="\([^"]*\)".*$/\1/')
formidttl=$(echo "$form" | grep 'AddDnsRecordForm\[uniqueFormIdTTL\]' | sed 's/^.*name="AddDnsRecordForm\[uniqueFormIdTTL\]" value="\([^"]*\)".*$/\1/')
form_token=$(echo "$form" | grep 'AddDnsRecordForm\[_token\]' | sed 's/^.*name="AddDnsRecordForm\[_token\]" value="\([^"]*\)".*$/\1/')
if [ -z "$formiddp" ]; then
_err "Unable to parse form"
@@ -45,9 +44,7 @@ dns_world4you_add() {
_resethttp
export ACME_HTTP_NO_REDIRECTS=1
body="AddDnsRecordForm[name]=$RECORD&AddDnsRecordForm[dnsType][type]=TXT&\
AddDnsRecordForm[value]=$value&AddDnsRecordForm[aktivPaket]=$paketnr&AddDnsRecordForm[uniqueFormIdDP]=$formiddp&\
AddDnsRecordForm[uniqueFormIdTTL]=$formidttl&AddDnsRecordForm[_token]=$form_token"
body="AddDnsRecordForm[name]=$RECORD&AddDnsRecordForm[dnsType][type]=TXT&AddDnsRecordForm[value]=$value&AddDnsRecordForm[uniqueFormIdDP]=$formiddp&AddDnsRecordForm[_token]=$form_token"
_info "Adding record..."
ret=$(_post "$body" "$WORLD4YOU_API/$paketnr/dns" '' POST 'application/x-www-form-urlencoded')
_resethttp
@@ -57,15 +54,14 @@ AddDnsRecordForm[uniqueFormIdTTL]=$formidttl&AddDnsRecordForm[_token]=$form_toke
if _contains "$res" "successfully"; then
return 0
else
msg=$(echo "$res" | tr '\n' '\t' | sed 's/.*<h3 class="mb-5">[^\t]*\t *\([^\t]*\)\t.*/\1/')
if _contains "$msg" '^<\!DOCTYPE html>'; then
msg='Unknown error'
fi
_err "Unable to add record: $msg"
if _contains "$msg" '^<\!DOCTYPE html>'; then
msg=$(echo "$res" | grep -A 15 'data-type="danger"' | grep "<h3[^>]*>[^<]" | sed 's/<[^>]*>\|^\s*//g')
if [ "$msg" = '' ]; then
_err "Unable to add record: Unknown error"
echo "$ret" >'error-01.html'
echo "$res" >'error-02.html'
_err "View error-01.html and error-02.html for debugging"
else
_err "Unable to add record: my.world4you.com: $msg"
fi
return 1
fi
@@ -90,7 +86,7 @@ dns_world4you_rm() {
fi
export _H1="Cookie: W4YSESSID=$sessid"
form=$(_get "$WORLD4YOU_API/dashboard/paketuebersicht")
form=$(_get "$WORLD4YOU_API/")
_get_paketnr "$fqdn" "$form"
paketnr="$PAKETNR"
if [ -z "$paketnr" ]; then
@@ -101,7 +97,6 @@ dns_world4you_rm() {
form=$(_get "$WORLD4YOU_API/$paketnr/dns")
formiddp=$(echo "$form" | grep 'DeleteDnsRecordForm\[uniqueFormIdDP\]' | sed 's/^.*name="DeleteDnsRecordForm\[uniqueFormIdDP\]" value="\([^"]*\)".*$/\1/')
formidttl=$(echo "$form" | grep 'DeleteDnsRecordForm\[uniqueFormIdTTL\]' | sed 's/^.*name="DeleteDnsRecordForm\[uniqueFormIdTTL\]" value="\([^"]*\)".*$/\1/')
form_token=$(echo "$form" | grep 'DeleteDnsRecordForm\[_token\]' | sed 's/^.*name="DeleteDnsRecordForm\[_token\]" value="\([^"]*\)".*$/\1/')
if [ -z "$formiddp" ]; then
_err "Unable to parse form"
@@ -113,11 +108,9 @@ dns_world4you_rm() {
_resethttp
export ACME_HTTP_NO_REDIRECTS=1
body="DeleteDnsRecordForm[recordId]=$recordid&DeleteDnsRecordForm[aktivPaket]=$paketnr&\
DeleteDnsRecordForm[uniqueFormIdDP]=$formiddp&DeleteDnsRecordForm[uniqueFormIdTTL]=$formidttl&\
DeleteDnsRecordForm[_token]=$form_token"
body="DeleteDnsRecordForm[recordId]=$recordid&DeleteDnsRecordForm[uniqueFormIdDP]=$formiddp&DeleteDnsRecordForm[_token]=$form_token"
_info "Removing record..."
ret=$(_post "$body" "$WORLD4YOU_API/$paketnr/deleteRecord" '' POST 'application/x-www-form-urlencoded')
ret=$(_post "$body" "$WORLD4YOU_API/$paketnr/dns/record/delete" '' POST 'application/x-www-form-urlencoded')
_resethttp
if _contains "$(_head_n 3 <"$HTTP_HEADER")" '302'; then
@@ -125,15 +118,14 @@ DeleteDnsRecordForm[_token]=$form_token"
if _contains "$res" "successfully"; then
return 0
else
msg=$(echo "$res" | tr '\n' '\t' | sed 's/.*<h3 class="mb-5">[^\t]*\t *\([^\t]*\)\t.*/\1/')
if _contains "$msg" '^<\!DOCTYPE html>'; then
msg='Unknown error'
fi
_err "Unable to remove record: $msg"
if _contains "$msg" '^<\!DOCTYPE html>'; then
msg=$(echo "$res" | grep -A 15 'data-type="danger"' | grep "<h3[^>]*>[^<]" | sed 's/<[^>]*>\|^\s*//g')
if [ "$msg" = '' ]; then
_err "Unable to remove record: Unknown error"
echo "$ret" >'error-01.html'
echo "$res" >'error-02.html'
_err "View error-01.html and error-02.html for debugging"
else
_err "Unable to remove record: my.world4you.com: $msg"
fi
return 1
fi
@@ -190,7 +182,7 @@ _get_paketnr() {
fqdn="$1"
form="$2"
domains=$(echo "$form" | grep '^ *[A-Za-z0-9_\.-]*\.[A-Za-z0-9_-]*$' | sed 's/^\s*\(\S*\)$/\1/')
domains=$(echo "$form" | grep 'header-paket-domain' | sed 's/<[^>]*>//g' | sed 's/^.*>\([^>]*\)$/\1/')
domain=''
for domain in $domains; do
if _contains "$fqdn" "$domain\$"; then
@@ -205,6 +197,6 @@ _get_paketnr() {
TLD="$domain"
_debug domain "$domain"
RECORD=$(echo "$fqdn" | cut -c"1-$((${#fqdn} - ${#TLD} - 1))")
PAKETNR=$(echo "$form" | grep "data-textfilter=\".* $domain " | _head_n 1 | sed 's/^.* \([0-9]*\) .*$/\1/')
PAKETNR=$(echo "$form" | grep "data-textfilter=\".* $domain " | _tail_n 1 | sed "s|.*$WORLD4YOU_API/\\([0-9]*\\)/.*|\\1|")
return 0
}
+51
View File
@@ -0,0 +1,51 @@
#!/usr/bin/env sh
#Support iOS Bark Notification
#BARK_API_URL="https://api.day.app/xxxx"
#BARK_SOUND="yyyy"
#BARK_GROUP="zzzz"
# subject content statusCode
bark_send() {
_subject="$1"
_content="$2"
_statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped
_debug "_subject" "$_subject"
_debug "_content" "$_content"
_debug "_statusCode" "$_statusCode"
BARK_API_URL="${BARK_API_URL:-$(_readaccountconf_mutable BARK_API_URL)}"
if [ -z "$BARK_API_URL" ]; then
BARK_API_URL=""
_err "You didn't specify a Bark API URL BARK_API_URL yet."
_err "You can download Bark from App Store and get yours."
return 1
fi
_saveaccountconf_mutable BARK_API_URL "$BARK_API_URL"
BARK_SOUND="${BARK_SOUND:-$(_readaccountconf_mutable BARK_SOUND)}"
_saveaccountconf_mutable BARK_SOUND "$BARK_SOUND"
BARK_GROUP="${BARK_GROUP:-$(_readaccountconf_mutable BARK_GROUP)}"
if [ -z "$BARK_GROUP" ]; then
BARK_GROUP="ACME"
_info "The BARK_GROUP is not set, so use the default ACME as group name."
else
_saveaccountconf_mutable BARK_GROUP "$BARK_GROUP"
fi
_content=$(echo "$_content" | _url_encode)
_subject=$(echo "$_subject" | _url_encode)
response="$(_get "$BARK_API_URL/$_subject/$_content?sound=$BARK_SOUND&group=$BARK_GROUP")"
if [ "$?" = "0" ] && _contains "$response" "success"; then
_info "Bark API fired success."
return 0
fi
_err "Bark API fired error."
_err "$response"
return 1
}
+57
View File
@@ -0,0 +1,57 @@
#!/usr/bin/env sh
#Support Discord webhooks
# Required:
#DISCORD_WEBHOOK_URL=""
# Optional:
#DISCORD_USERNAME=""
#DISCORD_AVATAR_URL=""
discord_send() {
_subject="$1"
_content="$2"
_statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped
_debug "_statusCode" "$_statusCode"
DISCORD_WEBHOOK_URL="${DISCORD_WEBHOOK_URL:-$(_readaccountconf_mutable DISCORD_WEBHOOK_URL)}"
if [ -z "$DISCORD_WEBHOOK_URL" ]; then
DISCORD_WEBHOOK_URL=""
_err "You didn't specify a Discord webhook url DISCORD_WEBHOOK_URL yet."
return 1
fi
_saveaccountconf_mutable DISCORD_WEBHOOK_URL "$DISCORD_WEBHOOK_URL"
DISCORD_USERNAME="${DISCORD_USERNAME:-$(_readaccountconf_mutable DISCORD_USERNAME)}"
if [ "$DISCORD_USERNAME" ]; then
_saveaccountconf_mutable DISCORD_USERNAME "$DISCORD_USERNAME"
fi
DISCORD_AVATAR_URL="${DISCORD_AVATAR_URL:-$(_readaccountconf_mutable DISCORD_AVATAR_URL)}"
if [ "$DISCORD_AVATAR_URL" ]; then
_saveaccountconf_mutable DISCORD_AVATAR_URL "$DISCORD_AVATAR_URL"
fi
export _H1="Content-Type: application/json"
_content="$(printf "**%s**\n%s" "$_subject" "$_content" | _json_encode)"
_data="{\"content\": \"$_content\" "
if [ "$DISCORD_USERNAME" ]; then
_data="$_data, \"username\": \"$DISCORD_USERNAME\" "
fi
if [ "$DISCORD_AVATAR_URL" ]; then
_data="$_data, \"avatar_url\": \"$DISCORD_AVATAR_URL\" "
fi
_data="$_data}"
if _post "$_data" "$DISCORD_WEBHOOK_URL?wait=true"; then
# shellcheck disable=SC2154
if [ "$response" ]; then
_info "discord send success."
return 0
fi
fi
_err "discord send error."
_err "$response"
return 1
}
+48
View File
@@ -0,0 +1,48 @@
#!/usr/bin/env sh
#Support feishu webhooks api
#required
#FEISHU_WEBHOOK="xxxx"
#optional
#FEISHU_KEYWORD="yyyy"
# subject content statusCode
feishu_send() {
_subject="$1"
_content="$2"
_statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped
_debug "_subject" "$_subject"
_debug "_content" "$_content"
_debug "_statusCode" "$_statusCode"
FEISHU_WEBHOOK="${FEISHU_WEBHOOK:-$(_readaccountconf_mutable FEISHU_WEBHOOK)}"
if [ -z "$FEISHU_WEBHOOK" ]; then
FEISHU_WEBHOOK=""
_err "You didn't specify a feishu webhooks FEISHU_WEBHOOK yet."
_err "You can get yours from https://www.feishu.cn"
return 1
fi
_saveaccountconf_mutable FEISHU_WEBHOOK "$FEISHU_WEBHOOK"
FEISHU_KEYWORD="${FEISHU_KEYWORD:-$(_readaccountconf_mutable FEISHU_KEYWORD)}"
if [ "$FEISHU_KEYWORD" ]; then
_saveaccountconf_mutable FEISHU_KEYWORD "$FEISHU_KEYWORD"
fi
_content=$(echo "$_content" | _json_encode)
_subject=$(echo "$_subject" | _json_encode)
_data="{\"msg_type\": \"text\", \"content\": {\"text\": \"[$FEISHU_KEYWORD]\n$_subject\n$_content\"}}"
response="$(_post "$_data" "$FEISHU_WEBHOOK" "" "POST" "application/json")"
if [ "$?" = "0" ] && _contains "$response" "StatusCode\":0"; then
_info "feishu webhooks event fired success."
return 0
fi
_err "feishu webhooks event fired error."
_err "$response"
return 1
}
+62
View File
@@ -0,0 +1,62 @@
#!/usr/bin/env sh
#Support Gotify
#GOTIFY_URL="https://gotify.example.com"
#GOTIFY_TOKEN="123456789ABCDEF"
#optional
#GOTIFY_PRIORITY=0
# subject content statusCode
gotify_send() {
_subject="$1"
_content="$2"
_statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped
_debug "_subject" "$_subject"
_debug "_content" "$_content"
_debug "_statusCode" "$_statusCode"
GOTIFY_URL="${GOTIFY_URL:-$(_readaccountconf_mutable GOTIFY_URL)}"
if [ -z "$GOTIFY_URL" ]; then
GOTIFY_URL=""
_err "You didn't specify the gotify server url GOTIFY_URL."
return 1
fi
_saveaccountconf_mutable GOTIFY_URL "$GOTIFY_URL"
GOTIFY_TOKEN="${GOTIFY_TOKEN:-$(_readaccountconf_mutable GOTIFY_TOKEN)}"
if [ -z "$GOTIFY_TOKEN" ]; then
GOTIFY_TOKEN=""
_err "You didn't specify the gotify token GOTIFY_TOKEN."
return 1
fi
_saveaccountconf_mutable GOTIFY_TOKEN "$GOTIFY_TOKEN"
GOTIFY_PRIORITY="${GOTIFY_PRIORITY:-$(_readaccountconf_mutable GOTIFY_PRIORITY)}"
if [ -z "$GOTIFY_PRIORITY" ]; then
GOTIFY_PRIORITY=0
else
_saveaccountconf_mutable GOTIFY_PRIORITY "$GOTIFY_PRIORITY"
fi
export _H1="X-Gotify-Key: ${GOTIFY_TOKEN}"
export _H2="Content-Type: application/json"
_content=$(echo "$_content" | _json_encode)
_subject=$(echo "$_subject" | _json_encode)
_data="{\"title\": \"${_subject}\", \"message\": \"${_content}\", \"priority\": ${GOTIFY_PRIORITY}}"
response="$(_post "${_data}" "${GOTIFY_URL}/message" "" "POST" "application/json")"
if [ "$?" != "0" ]; then
_err "Failed to send message"
_err "$response"
return 1
fi
_debug2 response "$response"
return 0
}
+2 -1
View File
@@ -62,7 +62,7 @@ mail_send() {
fi
contenttype="text/plain; charset=utf-8"
subject="=?UTF-8?B?$(echo "$_subject" | _base64)?="
subject="=?UTF-8?B?$(printf -- "%b" "$_subject" | _base64)?="
result=$({ _mail_body | eval "$(_mail_cmnd)"; } 2>&1)
# shellcheck disable=SC2181
@@ -131,6 +131,7 @@ _mail_body() {
echo "To: $MAIL_TO"
echo "Subject: $subject"
echo "Content-Type: $contenttype"
echo "MIME-Version: 1.0"
echo
;;
esac
+44
View File
@@ -0,0 +1,44 @@
#!/usr/bin/env sh
#Support for pushbullet.com's api. Push notification, notification sync and message platform for multiple platforms
#PUSHBULLET_TOKEN="" Required, pushbullet application token
#PUSHBULLET_DEVICE="" Optional, Specific device, ignore to send to all devices
PUSHBULLET_URI="https://api.pushbullet.com/v2/pushes"
pushbullet_send() {
_subject="$1"
_content="$2"
_statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped
_debug "_statusCode" "$_statusCode"
PUSHBULLET_TOKEN="${PUSHBULLET_TOKEN:-$(_readaccountconf_mutable PUSHBULLET_TOKEN)}"
if [ -z "$PUSHBULLET_TOKEN" ]; then
PUSHBULLET_TOKEN=""
_err "You didn't specify a Pushbullet application token yet."
return 1
fi
_saveaccountconf_mutable PUSHBULLET_TOKEN "$PUSHBULLET_TOKEN"
PUSHBULLET_DEVICE="${PUSHBULLET_DEVICE:-$(_readaccountconf_mutable PUSHBULLET_DEVICE)}"
if [ -z "$PUSHBULLET_DEVICE" ]; then
_clearaccountconf_mutable PUSHBULLET_DEVICE
else
_saveaccountconf_mutable PUSHBULLET_DEVICE "$PUSHBULLET_DEVICE"
fi
export _H1="Content-Type: application/json"
export _H2="Access-Token: ${PUSHBULLET_TOKEN}"
_content="$(printf "*%s*\n" "$_content" | _json_encode)"
_subject="$(printf "*%s*\n" "$_subject" | _json_encode)"
_data="{\"type\": \"note\",\"title\": \"${_subject}\",\"body\": \"${_content}\",\"device_iden\": \"${PUSHBULLET_DEVICE}\"}"
response="$(_post "$_data" "$PUSHBULLET_URI")"
if [ "$?" != "0" ] || _contains "$response" "\"error_code\""; then
_err "PUSHBULLET send error."
_err "$response"
return 1
fi
_info "PUSHBULLET send success."
return 0
}
+9 -1
View File
@@ -37,11 +37,19 @@ sendgrid_send() {
fi
_saveaccountconf_mutable SENDGRID_FROM "$SENDGRID_FROM"
SENDGRID_FROM_NAME="${SENDGRID_FROM_NAME:-$(_readaccountconf_mutable SENDGRID_FROM_NAME)}"
_saveaccountconf_mutable SENDGRID_FROM_NAME "$SENDGRID_FROM_NAME"
export _H1="Authorization: Bearer $SENDGRID_API_KEY"
export _H2="Content-Type: application/json"
_content="$(echo "$_content" | _json_encode)"
_data="{\"personalizations\": [{\"to\": [{\"email\": \"$SENDGRID_TO\"}]}],\"from\": {\"email\": \"$SENDGRID_FROM\"},\"subject\": \"$_subject\",\"content\": [{\"type\": \"text/plain\", \"value\": \"$_content\"}]}"
if [ -z "$SENDGRID_FROM_NAME" ]; then
_data="{\"personalizations\": [{\"to\": [{\"email\": \"$SENDGRID_TO\"}]}],\"from\": {\"email\": \"$SENDGRID_FROM\"},\"subject\": \"$_subject\",\"content\": [{\"type\": \"text/plain\", \"value\": \"$_content\"}]}"
else
_data="{\"personalizations\": [{\"to\": [{\"email\": \"$SENDGRID_TO\"}]}],\"from\": {\"email\": \"$SENDGRID_FROM\", \"name\": \"$SENDGRID_FROM_NAME\"},\"subject\": \"$_subject\",\"content\": [{\"type\": \"text/plain\", \"value\": \"$_content\"}]}"
fi
response="$(_post "$_data" "https://api.sendgrid.com/v3/mail/send")"
if [ "$?" = "0" ] && [ -z "$response" ]; then
+1 -1
View File
@@ -27,7 +27,7 @@ telegram_send() {
fi
_saveaccountconf_mutable TELEGRAM_BOT_CHATID "$TELEGRAM_BOT_CHATID"
_content="$(printf "%s" "$_content" | sed -e 's/*/\\\\*/')"
_content="$(printf "%s" "$_content" | sed -e 's/\([_*`\[]\)/\\\\\1/g')"
_content="$(printf "*%s*\n%s" "$_subject" "$_content" | _json_encode)"
_data="{\"text\": \"$_content\", "
_data="$_data\"chat_id\": \"$TELEGRAM_BOT_CHATID\", "
+49
View File
@@ -0,0 +1,49 @@
#!/usr/bin/env sh
#Support weixin work webhooks api
#WEIXIN_WORK_WEBHOOK="xxxx"
#optional
#WEIXIN_WORK_KEYWORD="yyyy"
#`WEIXIN_WORK_SIGNING_KEY`="SEC08ffdbd403cbc3fc8a65xxxxxxxxxxxxxxxxxxxx"
# subject content statusCode
weixin_work_send() {
_subject="$1"
_content="$2"
_statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped
_debug "_subject" "$_subject"
_debug "_content" "$_content"
_debug "_statusCode" "$_statusCode"
WEIXIN_WORK_WEBHOOK="${WEIXIN_WORK_WEBHOOK:-$(_readaccountconf_mutable WEIXIN_WORK_WEBHOOK)}"
if [ -z "$WEIXIN_WORK_WEBHOOK" ]; then
WEIXIN_WORK_WEBHOOK=""
_err "You didn't specify a weixin_work webhooks WEIXIN_WORK_WEBHOOK yet."
_err "You can get yours from https://work.weixin.qq.com/api/doc/90000/90136/91770"
return 1
fi
_saveaccountconf_mutable WEIXIN_WORK_WEBHOOK "$WEIXIN_WORK_WEBHOOK"
WEIXIN_WORK_KEYWORD="${WEIXIN_WORK_KEYWORD:-$(_readaccountconf_mutable WEIXIN_WORK_KEYWORD)}"
if [ "$WEIXIN_WORK_KEYWORD" ]; then
_saveaccountconf_mutable WEIXIN_WORK_KEYWORD "$WEIXIN_WORK_KEYWORD"
fi
_content=$(echo "$_content" | _json_encode)
_subject=$(echo "$_subject" | _json_encode)
_data="{\"msgtype\": \"text\", \"text\": {\"content\": \"[$WEIXIN_WORK_KEYWORD]\n$_subject\n$_content\"}}"
response="$(_post "$_data" "$WEIXIN_WORK_WEBHOOK" "" "POST" "application/json")"
if [ "$?" = "0" ] && _contains "$response" "errmsg\":\"ok"; then
_info "weixin_work webhooks event fired success."
return 0
fi
_err "weixin_work webhooks event fired error."
_err "$response"
return 1
}
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.