Compare commits

..
307 Commits
Author SHA1 Message Date
neil 676d76696b Merge pull request #6328 from acmesh-official/dev
sync
2025-04-23 20:46:32 +02:00
neil 1d18432f8d Merge pull request #6315 from alindt/fix-vault-curl
Fix error detection in vault deploy hook
2025-04-23 20:34:29 +02:00
neil 277f13ff9d Merge pull request #6317 from ruuuch/edgecenter-dns
Add Edgecenter DNS API
2025-04-23 20:33:24 +02:00
rka 2d365efe56 Add Edgecenter DNS API 2025-04-18 02:48:48 +03:00
Alin Trăistaru e81635f23d check curl vault http return code 2025-04-18 00:25:10 +02:00
neil 9b267bb572 Merge pull request #6299 from Gontier-Julien/dev
Bump Alpine version from 3.17 to 3.21
2025-04-12 15:20:05 +01:00
Gontier Julien 20c7bfaff2 Bump Alpine version from 3.17 to 3.21
Signed-off-by: Gontier Julien <52894530+Gontier-Julien@users.noreply.github.com>
2025-04-11 20:09:03 +02:00
neil 1d87d9b370 Merge pull request #6287 from acmesh-official/dev
sync
2025-03-29 21:18:22 +01:00
neil 40b6db6a27 persist-credentials: false 2025-03-29 21:14:56 +01:00
neil 9ba662a53e Merge pull request #6285 from ms264556/bugfix/deploy_ruckus_checkecc
Don't deploy ECC certs to legacy Ruckus
2025-03-29 21:08:25 +01:00
neil dc228c3dbb Merge pull request #6282 from magyarsz/dev
Fix error message variable when reload cmd returns with an error
2025-03-29 21:03:22 +01:00
magyarsz dd5dd422d1 Merge branch 'dev' into dev 2025-03-28 21:19:12 +01:00
neil 73fdf4b957 Merge pull request #6286 from acmesh-official/dev
sync
2025-03-28 20:51:39 +01:00
neil a1de13657e minor, just copy necessary files 2025-03-28 20:50:08 +01:00
ms264556 93c19356d0 Don't deploy ECC certs to legacy Ruckus 2025-03-27 14:03:08 +13:00
Szabolcs Magyar 8a27c902ff Fix error message variable when reload cmd returns with an error 2025-03-25 19:29:12 +01:00
neil be35b55444 Merge pull request #623 from kevinoid/fix-well-known-perms
Avoid permissions errors for chown .well-known
2025-03-23 21:20:23 +01:00
neil a16ccf40c2 Merge pull request #6198 from lindsayzhou/fix-dns-netzner-error-regexp
fix regex of matching hetzner dns api error responses
2025-03-23 21:07:24 +01:00
Sikro 5c7b1cd5f2 add environment variable for notify/telegram.sh
Since the server in mainland China cannot connect to Telegram, add the TELEGRAM_BOT_URLBASE environment variable
Please add the proxy address you set. If this variable is not added, it will be the default value (https://api.telegram.org)
2025-03-23 21:00:34 +01:00
neil fc5e593e2d Merge pull request #6277 from beedaddy/ntfy_token
support NTFY_TOKEN
2025-03-21 20:07:34 +01:00
Martin Brodbeck f1dc79f0b5 support NTFY_TOKEN 2025-03-20 10:13:12 +01:00
neil 34ea97dcea Merge pull request #4384 from fraenki/cert_home
update documentation for --cert-home parameter
2025-03-19 11:04:06 +01:00
neil f2931163aa Merge pull request #6268 from wlallemand/haproxy-fix-secure-debug
haproxy: don't leak private keys when doing --debug
2025-03-15 11:09:55 +01:00
William Lallemand 7e320d2748 haproxy: don't leak private keys when doing --debug
It was reported in issue #6267 that the private key was leaked when
using the DEPLOY_HAPROXY_HOT_UPDATE=yes feature.

Indeed, the debugging code which sends commands to HAProxy was using
_debug even when passing the private key.

This patch fixes the issue by using _secure_debug when doing that.
2025-03-11 12:04:59 +01:00
neil 45660902ed Merge pull request #6262 from copyliu/copyliu-routeros-dev
routeros: file-name should in quotes in newer (7.18) version
2025-03-09 19:45:30 +01:00
neil 72318cb687 Merge pull request #6263 from markkuleinio/dev
dns_he_ddns: Add empty dns_he_ddns_rm() to remove warnings
2025-03-09 19:41:59 +01:00
neil f277223a65 Merge pull request #6257 from metaforget/master
cqhttp notify-hook:Compatibility with QQ Headless Project Napcat
2025-03-09 19:40:46 +01:00
Markku Leiniö 262fa74f5e dns_he_ddns: Add empty dns_he_ddns_rm() to remove warnings 2025-03-05 19:45:01 +02:00
copyliu ebdd221c72 routeros: file-name should in quotes in newer (7.18) version 2025-03-05 11:33:41 +08:00
metaforget 2b8d162c9e Merge branch 'dev' into master 2025-03-03 13:51:08 +08:00
metaforget dc8cf0e02e cqhttp notify-hook:Compatibility with QQ Headless Project Napcat 2025-03-03 10:37:38 +08:00
neil a054f6a97b Merge pull request #6240 from Giova96/master
Add FreeMyIP DNS Api Support
2025-03-02 13:06:25 +01:00
neil 63d11c3eea Merge pull request #6245 from aafbsd/patch-1
Support FreeBSD's sed -i
2025-02-28 19:48:05 +01:00
Giovannimaria Gandossi dd2199c472 Adding support for FreeMyIP dns API 2025-02-24 17:03:22 +01:00
aafbsd 661c3bbdb0 Support FreeBSD's sed -i
FreeBSD's sed requires an extension for the backup file when -i is used. However, it may be zero-length to indicate that no backup is desired.
2025-02-24 12:33:42 +00:00
neil 5236e81068 version 3.1.1 2025-02-23 09:28:14 +01:00
neil c459b5eb9d Merge pull request #6243 from acmesh-official/dev
sync
2025-02-23 09:26:46 +01:00
neil 384f0fb89a Merge pull request #6242 from NerLOR/master
dns_world4you: Adapt to change in world4you.com
2025-02-23 09:25:10 +01:00
Lorenz Stechauner 1d628bcf9e dns_world4you: Adapt to change in world4you.com 2025-02-22 18:56:15 +01:00
neil b8644f49ec Merge pull request #6239 from scruel/patch-1
chore(synology): remove personal mail
2025-02-20 10:38:47 +01:00
Scruel Tao 091c1f7ef1 chore(synology): remove personal mail 2025-02-20 17:16:23 +08:00
neil c838c3fa73 Merge pull request #6234 from tomo2403/deployhook-docker
Allow deploying of PKCS to docker containers and other hooks
2025-02-19 21:31:09 +01:00
neil 8bb9106b42 Merge pull request #6226 from davidha/fix-saved-local-hostname
Fix bug saving SYNO_LOCAL_HOSTNAME
2025-02-19 21:29:24 +01:00
tomo a7e3b0d184 Merge branch 'dev' into deployhook-docker 2025-02-15 20:24:05 +01:00
tomo 449c542d5a fixed env warning while building 2025-02-15 17:16:07 +01:00
tomo 7f19f8cf0e implemented deploying pfx to docker container 2025-02-15 15:18:10 +01:00
tomo b2eb704394 allowed deploying of pfx cert 2025-02-15 15:16:52 +01:00
David Ha 899da0c6ea Update synology_dsm.sh
fix check logic
2025-02-09 23:43:55 +00:00
David Ha def41a7878 Fix bug saving SYNO_LOCAL_HOSTNAME
Exporting SYNO_LOCAL_HOSTNAME=1 only works on the first deploy invocation. Subsequent deploys using the saved config fails because it saves $SYNO_HOSTNAME instead of $SYNO_LOCAL_HOSTNAME.
2025-02-09 22:56:46 +00:00
neil 6dbe49089e minor 2025-01-25 21:00:34 +01:00
neil 5883e5159f Merge pull request #6202 from ARNik/dns_beget
Add Beget.com DNS API support
2025-01-18 19:46:24 +01:00
ARNik 26a5d48f63 dnsapi: Beget.com fix case-sensitive domain names 2025-01-16 21:57:41 +03:00
ARNik aa6feb4b62 dnsapi: Beget.com fix rm record 2025-01-16 20:55:56 +03:00
ARNik 2fef0ebea8 dnsapi: Beget.com subdomain preparation rework 2025-01-16 20:55:56 +03:00
ARNik 66dd51a09a dnsapi: check Beget.com API replies 2025-01-16 19:45:26 +03:00
ARNik 077868604d dnsapi: Add Beget.com DNS API 2025-01-15 09:40:31 +03:00
Lindsay Zhou 6c555cb666 fix regex of matching hetzner dns api error responses 2025-01-13 11:11:36 +08:00
neil 0ae80272fb Merge pull request #5237 from markkuleinio/add-he-ddns
Add dnsapi script for HE DDNS
2025-01-11 10:48:12 +01:00
neil 7bef7cf9e2 Merge pull request #6108 from Attackwave/Truenas-Deploy-Websocket
Truenas deploy websocket
2025-01-11 10:46:40 +01:00
neil 6fa24cad18 Merge pull request #6195 from 3VAbdAVE/dev
Fixed cloudkey gen 2 changes
2025-01-10 20:40:28 +01:00
neil 6313020ba9 Merge pull request #6194 from ghen2/hostname
Portability: use `uname -n` instead of `hostname`.
2025-01-10 20:39:45 +01:00
3VAbdAVE b2eead386d Merge remote-tracking branch 'upstream/dev' into dev 2025-01-10 09:19:29 -05:00
Geert Hendrickx b826123d98 Portability: use uname -n instead of hostname.
`hostname` is not available by default on some modern Linux distributions
(eg. Arch Linux), whereas `uname -n` is defined by POSIX, so guaranteed.
2025-01-10 12:39:30 +01:00
neil cf537070d8 Merge pull request #5128 from vlad-kms/master
Feature: Add new version API dns SELECTEL dns_selectel.sh (actual v2)
2025-01-09 22:44:16 +01:00
neil 7a00a1dced Merge pull request #6191 from HTDemony/master
Create script for deploy certificate on Proxmox Backup Server
2025-01-09 22:42:01 +01:00
Demony 80c37ebab2 Merge branch 'dev' into master 2025-01-08 21:37:21 +01:00
neil 5fb4136bcd Merge pull request #6190 from jpmens/patch-2
Correct typo in acme.sh
2025-01-08 19:23:22 +01:00
Yann DEMOULIN 6a249ca1dd Create script for deploy certificate on Proxmox Backup Server 2025-01-07 22:23:27 +01:00
Jan-Piet Mens 5610d4782f Correct typo in acme.sh 2025-01-07 13:13:27 +01:00
Markku Leiniö fef4574c3c Fix option description 2025-01-04 21:34:14 +02:00
neil 65239c7c25 Merge pull request #6184 from JazzMalar/master
Update dns_cyon plugin
2025-01-04 10:43:54 +01:00
Markus Schenk 1b123054b3 also updated the other validation functions 2025-01-03 13:08:18 +01:00
Markus Schenk b29d17f522 changed char class for compatibility with openbsd 2025-01-03 13:04:04 +01:00
Markus Schenk 04aefbf28d moved the env change check to its own function 2025-01-03 00:31:27 +01:00
Attackwave f8fcf02448 Merge branch 'acmesh-official:master' into Truenas-Deploy-Websocket 2025-01-02 19:44:24 +01:00
Markus Schenk 0e4fd5269b run tests 2025-01-02 00:49:20 +01:00
Markus Schenk 6328496bfb run tests 2025-01-02 00:41:59 +01:00
Markus Schenk 524b40b75f adhere to shell formatting 2025-01-02 00:36:28 +01:00
Markus Schenk 0241552c0d update dns_cyon for updated field names and add validation 2025-01-02 00:26:47 +01:00
neil fd3f6687ce Merge pull request #6099 from catap/openbsd
Fix syntax for OpenBSD sh
2025-01-01 15:14:25 +01:00
neil 93d63749e6 Merge pull request #6178 from peterv99/dev
Add mijn.host DNS API Support
2025-01-01 15:10:45 +01:00
neil 41bf5450d9 Merge pull request #6181 from M0NsTeRRR/master
fix: remove control characters
2025-01-01 11:24:21 +01:00
Ludovic Ortega d37553e7b8 fix: remove control characters
Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>
2024-12-31 18:04:39 +01:00
neil 101d7138c2 Merge pull request #6176 from stokito/dnsapi_struct_info_missing
dnsapi: Add structured info for lima-city and west.cn
2024-12-31 11:24:02 +01:00
Sergey Ponomarev 11de3aed51 dnsapi: structured info minor fixes
Extend dns_myapi.sh info with samples.
omglol: Split Address option by a dot to avoid incorrect parsing with a dot from omg.lol

Signed-off-by: Sergey Ponomarev <stokito@gmail.com>
2024-12-31 11:45:29 +02:00
3VAbdAVE 4bb41cf886 Fixed bad variable. 2024-12-29 12:52:09 -05:00
peterv99 1ae7dd9b11 Updated info block 2024-12-29 09:30:48 +01:00
Sergey Ponomarev a3250fac6d dnsapi: Add structured info for lima-city and west.cn
Signed-off-by: Sergey Ponomarev <stokito@gmail.com>
2024-12-28 22:31:24 +02:00
neil fabe6317ef Merge pull request #6174 from stokito/dns_api_fix
DNS API: fix structural info for new providers
2024-12-28 20:05:44 +01:00
3VAbdAVE 23a4af9a52 Merge branch 'acmesh-official:master' into master 2024-12-28 13:19:17 -05:00
peterv99 9526dbadad mijn.host API unreliable, upped retry times to 15 2024-12-28 17:26:52 +01:00
Sergey Ponomarev 6ad469c637 dnsapi: Fix structured info
Signed-off-by: Sergey Ponomarev <stokito@gmail.com>
2024-12-28 17:42:58 +02:00
peterv99 b30cdf0873 Merge branch 'dev' of github.com:peterv99/acme.sh into dev 2024-12-28 13:35:53 +01:00
peterv99 234bc93ddb Removed superfluous debug message 2024-12-28 12:42:50 +01:00
peterv99 42862852b8 Corrected sleep message 2024-12-28 12:41:26 +01:00
peterv99 7a6101c417 Corrected sleep time message 2024-12-28 10:22:28 +01:00
peterv99 588123ed11 Updated backoff algorithm 2024-12-27 23:56:13 +01:00
peterv99 ac9852f9df Added fix for specific API error that mijn.host sometimes throws. 2024-12-27 16:47:02 +01:00
peterv99 d093476da5 Refactored REST calls to add generic retries,
as mijn.host API times out at times.
2024-12-27 12:55:12 +01:00
peterv99 9ad794f2cc Name change, function name change to mijnhost 2024-12-27 08:56:16 +01:00
peterv99 b0f566a80d Name change to be in line with other API scripts
Added time-out to _get calls at 120s to fix API timeouts
2024-12-26 23:36:55 +01:00
Vladimir Alexeev d3f3a70350 keep content:
# dns_selectel_info='Selectel.com
# Domains: Selectel.ru
# Site: Selectel.com
# Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_selectel
# Options:
# Variables that must be defined before running
2024-12-26 08:45:03 +10:00
Vladimir Alexeev 3f262fe872 keep content:
# dns_selectel_info='Selectel.com
# Domains: Selectel.ru
# Site: Selectel.com
# Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_selectel
# Options:
# Variables that must be defined before running
2024-12-26 08:12:36 +10:00
peterv99 150c708726 Better debug messages for root domain detection 2024-12-25 14:11:52 +01:00
peterv99 7512dbffbb Fixed yet another error in dns_rm 2024-12-25 09:50:27 +01:00
peterv99 3cfa882fe1 Fixed error in dns_mijn_host_rm 2024-12-25 08:52:09 +01:00
peterv99 35f3b7088d Updated PUT request to hold only fqdn domain name values# 2024-12-25 00:00:19 +01:00
peterv99 07220a324d Removed all jq references 2024-12-24 23:21:50 +01:00
peterv99 c7cecd5b4f Removed "." from _sub_domain to create a valid domain. 2024-12-24 17:30:50 +01:00
peterv99 ab1a2045d9 Made string removal in root domain detection posix compliant 2024-12-24 17:10:30 +01:00
peterv99 5e9a067e87 Fixed root domain detection and processing. 2024-12-24 16:55:26 +01:00
Peter Vos 4cc460be64 Added dns challenge for mijn.host 2024-12-24 13:33:15 +01:00
Vladimir Alexeev 112bfccfd5 fix _get_root() make it start from 1. because we need to support --domain-alias (only version api actual v2) 2024-12-24 16:00:01 +10:00
Владимир Алексеев b29cb08956 Merge branch 'acmesh-official:master' into master 2024-12-23 14:51:57 +10:00
Vladimir Alexeev e42ad9be24 fix
don't use debug3, use debug2
  add # shellcheck disable=SC2034
2024-12-23 14:50:28 +10:00
neil 02da1700e0 fix format 2024-12-22 14:19:58 +01:00
neil a9f97e1fe2 fix format 2024-12-22 14:17:33 +01:00
neil d75077c6f9 fix format 2024-12-22 13:36:43 +01:00
neil b81939f02d Merge pull request #6168 from adn77/master
Fix keystore ownership in Unifi deployment - unifi.sh
2024-12-22 13:26:26 +01:00
Alex 0e1d90dd0c Properly guess system.properties location 2024-12-20 10:36:45 +01:00
Alex 03e9c612b9 Correct file ownership according to keystore directory 2024-12-20 10:34:51 +01:00
neil f981c782bb Merge pull request #6160 from acmesh-official/dev
sync
2024-12-10 21:00:22 +01:00
neil 3fbdb7a007 fix format 2024-12-10 20:58:02 +01:00
neil 2997a15ba8 Merge pull request #6136 from lukavia/dev
Add support for ZoneEdit.com
2024-12-09 09:22:54 +01:00
neil b4c02eca16 Merge pull request #6114 from NerLOR/master
dns_world4you: Adapt to change in world4you.com DeleteDnsRecordForm
2024-12-07 23:01:16 +01:00
neil 223dc87cef usage 2024-12-07 22:50:12 +01:00
neil 3ccdae0634 Merge pull request #4832 from kchiem/dev
deploy hook for Ruckus ZoneDirector / Unleashed
2024-12-07 22:24:04 +01:00
Anton Avramov 11af6f49c6 Add support for ZoneEdit.com 2024-12-05 22:12:04 -05:00
Kevin Locke 22dfedf6ae Avoid permissions errors for chown .well-known
When acme.sh is run as a non-root user different from the owner of the
webroot directory it is unable to change the owner of the files in
.well-known to that user, causing permissions errors.  Avoid this by
making the files world-readable.

These files should pose no disclosure risk since they are sent in
cleartext during the HTTP Identifier Validation Challenge[1] and may
already be exposed by directory enumeration, depending on server
settings.  AFAIK they should be safe to expose as world-readable in all
cases.

1.  https://ietf-wg-acme.github.io/acme/#rfc.section.7.2

Fixes Neilpang/acme.sh#32
Signed-off-by: Kevin Locke <kevin@kevinlocke.name>
2024-11-30 16:34:52 -07:00
Lorenz Stechauner 157d3f9dc9 dns_word4you: Fix for OpenBSD 2024-11-30 20:25:55 +01:00
3VAbdAVE f3b2ab5e60 Fix gen1 cloudkey's symlinked keystore 2024-11-30 10:32:24 -05:00
neil fca53a0c2c Merge pull request #6117 from qupfer/technitum
add dns_api for Technitum dns server
2024-11-28 12:22:52 +01:00
Henning Reich 6d302889fa small cleanup 2024-11-27 10:11:50 +01:00
Henning Reich a94ac63e74 add issue link 2024-11-27 09:20:57 +01:00
Henning Reich 19e73f8889 add account to rm function 2024-11-26 12:29:07 +01:00
Henning Reich aacc26179e remove comments 2024-11-26 12:17:11 +01:00
Henning Reich 36f060dcf6 add author 2024-11-26 11:42:05 +01:00
Henning Reich cb12c8dfd5 working example 2024-11-26 11:21:17 +01:00
Lorenz Stechauner 9cd1d1a9dc dns_world4you: Adapt to change in world4you.com DeleteDnsRecordForm 2024-11-26 09:20:18 +01:00
Attackwave ebaf4c9c01 Update truenas_ws.sh (Output new certificate name) 2024-11-25 21:23:59 +01:00
Attackwave 44240339d9 Update truenas_ws.sh (Interpreter changed from bash to sh) 2024-11-25 21:13:43 +01:00
Attackwave 9110375173 Update truenas_ws.sh (fixed shfmt) 2024-11-25 20:50:40 +01:00
qupfer c3557bbe3f 1 2024-11-25 20:26:23 +01:00
Henning Reich cd924099e4 add template 2024-11-25 17:46:59 +00:00
Attackwave f2a311bb81 Update truenas_ws.sh (added return instead exit) 2024-11-25 14:44:52 +01:00
Attackwave d7855e8fe5 Update truenas_ws.sh (shfmt and shellcheck) 2024-11-24 14:59:51 +01:00
Attackwave 1e52efa867 Merge branch 'acmesh-official:master' into Truenas-Deploy-Websocket 2024-11-24 14:39:58 +01:00
neil 5d6f1bd2d7 Merge pull request #6110 from acmesh-official/dev
sync
2024-11-23 11:00:10 +01:00
neil 48ccaa8b91 Merge pull request #6106 from CreatorHRS/dev
fix: new version of fornex dns based on api version 2.3.1
2024-11-23 10:51:21 +01:00
mikhailkhr 54ac0048c4 fix: missing quotes 2024-11-20 12:43:58 +03:00
mikhailkhr 276e089419 fix: new version of fornex dns based on api version 2.3.1 2024-11-20 12:38:06 +03:00
Kirill A. Korinsky 3b8608761b Fix syntax for OpenBSD sh 2024-11-17 20:58:06 +01:00
Attackwave 413a91646c Create truenas_ws.sh 2024-11-16 19:15:39 +01:00
kchiem 4299c6a802 Merge pull request #5 from ms264556/dev
Remove awk usage & refuse host redirects
2024-11-15 00:32:43 -08:00
ms264556 4232923641 Remove awk usage and refuse redirect to new host 2024-11-15 12:39:41 +13:00
neil 75b4bb306b Merge pull request #6096 from acmesh-official/dev
sync
2024-11-14 20:44:30 +01:00
neil 4e0686f73c fix for omnios-r151052 2024-11-14 20:35:15 +01:00
neil 709f1e76d3 fix for omnios-r151052 2024-11-14 20:17:03 +01:00
neil 0c2d7b9c06 fix for latest omnios-r151052 2024-11-14 20:03:32 +01:00
kchiem 412e14a41c Merge pull request #4 from ms264556/dev
fix acme.sh PR shfmt failure
2024-11-13 12:04:16 -08:00
neil 532b425dd9 Merge pull request #5276 from stbeldarborge/master
Add existing bearer token support to Azure DNS API
2024-11-13 20:21:39 +01:00
ms264556 2bb5fbdee5 Remove HTTPS_INSECURE 2024-11-14 07:21:19 +13:00
ms264556 38c41b72d6 fix acme.sh PR shfmt failure 2024-11-14 07:16:38 +13:00
neil 30e89c3cdc Merge pull request #6094 from sergiustheblack/feature/swanctl
StrongSwan deploy hook: swanctl support
2024-11-13 09:01:54 +01:00
kchiem b665014707 Merge pull request #3 from ms264556/dev
Fix info logging
2024-11-12 21:11:22 -08:00
ms264556 e98e7a232f Fix info logging 2024-11-13 17:27:36 +13:00
kchiem 5f7ad72d45 Merge pull request #2 from ms264556/dev
fix insecure password debug and _info typo
2024-11-12 18:19:03 -08:00
Sergey Parfenov 9c25365b12 Add swanctl support 2024-11-13 04:07:28 +03:00
ms264556 0cc74b7cfe fix insecure password debug and _info typo 2024-11-13 12:50:51 +13:00
neil 8a972ea213 Merge pull request #6089 from M0NsTeRRR/master
fix(truenas): broken script since 23.10 scale release
2024-11-12 22:32:36 +01:00
Ludovic Ortega 2229bcc98b fix: echo flag 2024-11-12 22:15:44 +01:00
Ludovic Ortega 1bfd4672e1 fix: remove double square brackets 2024-11-12 22:10:34 +01:00
neil 15e9e8575a Merge pull request #5172 from vmmello/issue_4956
Fixes issue 4956: 'Linode DNS Pagination Bug'
2024-11-12 21:32:13 +01:00
kchiem d7bafa6dfa Merge pull request #1 from ms264556/dev
Rewrite deploy/ruckus.sh to use _get() and _post()
2024-11-12 00:38:37 -08:00
neil 35632f2109 Merge pull request #6093 from acmesh-official/dev
sync
2024-11-11 22:43:23 +01:00
Ludovic Ortega 08807b498e fix: bad copy/paste
Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>
2024-11-10 13:30:18 +01:00
Ludovic Ortega e8a453c567 fix: lint
Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>
2024-11-10 13:21:09 +01:00
ms264556 717802611a remove dead code 2024-11-10 22:43:57 +13:00
ms264556 b6a77e0231 Ruckus - use _get() and _post() 2024-11-10 22:12:38 +13:00
Ludovic Ortega 21b966c8e6 fix: don't check for subversion that can lead to error
Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>
2024-11-10 02:56:40 +01:00
Ludovic Ortega 64a1e88982 feat: add support for docker apps
Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>
2024-11-10 02:41:38 +01:00
Ludovic Ortega 34c8b882c6 fix: helm chart seems available only on truenas scale
Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>
2024-11-10 00:34:26 +01:00
Ludovic Ortega fa420d70cc fix: verify truenas os version 2024-11-10 00:13:53 +01:00
Ludovic Ortega 2c67934191 fix(truenas): builtin service deprecation 2024-11-09 23:29:52 +01:00
neil 821adcf178 Merge pull request #6087 from stokito/dnsapi-info
Dns API: fix structural info
2024-11-09 19:24:18 +01:00
Sergey Ponomarev 8bf9482bc0 dnsapi ionos_cloud: Use structured info
Signed-off-by: Sergey Ponomarev <stokito@gmail.com>
2024-11-09 18:31:52 +02:00
Sergey Ponomarev fe8ad3548b dnsapi alviy: Use structured info
Signed-off-by: Sergey Ponomarev <stokito@gmail.com>
2024-11-09 18:22:01 +02:00
Sergey Ponomarev 4f17bc0d86 dnsapi timeweb: Use structured info
Signed-off-by: Sergey Ponomarev <stokito@gmail.com>
2024-11-09 18:20:58 +02:00
Sergey Ponomarev 1a43c81840 dnsapi omg.lol: fix info
Description "Based on the omg.lol API" is useless for users so removed.
The link to api moved to comment bellow.
Domains: omg.lol is unnecessary because the DNS provider name is anyway omg.lol.
Site: changed to point to the https://omg.lol site.
Issues: put a link to the support issue.

Remove the useless "Please Read this guide first" comment.
Fix typos.

Signed-off-by: Sergey Ponomarev <stokito@gmail.com>
2024-11-09 18:10:25 +02:00
Vinicius Mello d3cf3f7a5c fix pagination bug for domains with a big zone file
the same pagination bug that happens for accounts with a large number of
domains also happens for DNS zones with a large number of records. The
previous code assumes that all records are returned in a single page.

Changed the code to do an exact match search so that it returns only the few
required records and never paginates replies.
2024-11-08 00:59:21 -03:00
Vinicius Mello 4f96a2a667 remove unnecessary variable 'export' on variable _H4 2024-11-07 17:36:25 -03:00
Vinicius Mello 7b63ebfcaa fix random failures due to unnecessary headers on requests
was unintendedly replaying the save _H4 header on all requests, what was
causing random failures on responses from the API.
2024-11-07 12:33:56 -03:00
Vinicius Mello 724f3aa301 rename variable, undo accidental revert from dev 2024-11-06 16:20:55 -03:00
vmmello 1ff326c89c dns_linode_v4.sh: trigger action 2024-11-05 14:57:28 -03:00
vmmello 2663f500cf dns_linode_v4.sh: trigger action 2024-11-05 11:43:04 -03:00
vmmello 43ed998ed6 dns_linode_v4.sh: trigger action execution (dummy change) 2024-11-05 11:26:37 -03:00
vmmello a3032ab945 dns_linode_v4.sh: remove uneeeded extra space (shfmt error) 2024-11-05 11:10:55 -03:00
vmmello af9425ed8f Merge branch 'dev' into issue_4956 2024-11-05 11:07:20 -03:00
neil d058ac6174 Merge pull request #5328 from sahsanu/dev
Fix dns_pdns.sh to use saved account conf
2024-11-03 13:22:29 +01:00
neil a4e7806d21 fix https://github.com/acmesh-official/acme.sh/issues/5208 2024-11-03 13:09:52 +01:00
Vinicius Mello 03906cc055 trigger github action 2024-10-28 12:07:33 -03:00
Vinicius Mello 10833dcf39 trigger github action 2024-10-28 11:50:28 -03:00
neil a00323412b Merge pull request #5374 from ryoon/posix-shell-portability
Fix POSIX shell portability
2024-10-25 08:55:38 +02:00
Ryo ONODERA 838a20ea95 Fix POSIX shell portability
POSIX standard says test command has '=" as for checking identical.
'==' is bash dialect.
Replace '==' with '='.

See:
https://pubs.opengroup.org/onlinepubs/009604399/utilities/test.html
2024-10-24 22:52:28 +09:00
Владимир Алексеев e8ed8cbfcd Merge branch 'dev' into master 2024-10-22 05:25:27 +10:00
neil 5c78a5e4fe Merge pull request #5331 from lifeboy/revert-TXT-add-update
Revert txt add update
2024-10-16 17:29:14 +02:00
Roland Giesler 30ed4af38d Revert TXT add update
The change was needed for Power-Mailinabox and broke Mail-in-a-box, so a new API for Power-Mailinabox has been added
2024-10-16 11:49:29 +02:00
sahsanu 6a9304dd1c Change _saveaccountconf to _saveaccountconf_mutable 2024-10-16 09:03:18 +02:00
sahsanu 1782eeb785 Fix dns_pdns.sh to use saved account conf 2024-10-14 16:18:44 +02:00
sahsanu 1aabb7d6de Fix dns_pdns.sh to use saved account conf 2024-10-14 15:59:54 +02:00
neil d4b8f9700b Merge pull request #5326 from acmesh-official/dev
sync
2024-10-13 18:02:13 +02:00
neil 2ebecf1aa0 fix format 2024-10-13 17:59:25 +02:00
neil 7031df4948 fix format 2024-10-13 17:58:19 +02:00
neil e0381dd757 fix format 2024-10-13 17:55:22 +02:00
neil 9b2eae24d2 fix format 2024-10-13 17:49:29 +02:00
neil 7362e8de4d fix format 2024-10-13 17:41:22 +02:00
neil 87beb0a5f2 fix name 2024-10-13 17:26:14 +02:00
neil fc69cea4f7 Merge pull request #5323 from allddd/update_porkbun_url
Update Porkbun API URL
2024-10-12 20:46:07 +02:00
allddd ad4780a1ac update api url 2024-10-12 01:07:35 +02:00
Eldar Borge 72f487d2e3 Merge branch 'acmesh-official:master' into master 2024-10-11 09:11:00 +02:00
stbeldarborge 0c10bd7dd7 shfmt 2024-10-10 12:35:05 +02:00
stbeldarborge b0418cb394 trigger 2024-10-10 12:23:07 +02:00
stbeldarborge a30c81dadc bearetoken 2024-10-10 12:00:11 +02:00
stbeldarborge 40df6e87db newline 2024-10-10 11:54:42 +02:00
stbeldarborge 0dff1dce8f accoutn conf 2024-10-10 11:50:57 +02:00
stbeldarborge ffd3b3e6b5 revert 2024-10-10 11:36:37 +02:00
stbeldarborge 1305b0d8dd revert 2024-10-10 11:29:34 +02:00
stbeldarborge 5fc41a3ea2 read account conf 2024-10-10 11:24:24 +02:00
stbeldarborge fc87fc7cab debug 2024-10-10 11:18:03 +02:00
stbeldarborge 8887a0a6d3 new name 2024-10-10 11:09:25 +02:00
stbeldarborge ba7764aeaf saveaccountconf 2024-10-10 10:59:29 +02:00
stbeldarborge 28afe6f29f comment 2024-10-10 10:30:54 +02:00
neil 138ab6dbbd Merge pull request #5315 from fazelukario/patch-1
Fix markdown issue in telegram notify hook
2024-10-07 08:48:02 +02:00
fazelukario 26c2fc21c8 Moving to MarkdownV2 as the old Markdown is obsolete
- Implemented MarkdownV2 with escape of all necessary characters.
- Ref: https://core.telegram.org/bots/api#markdownv2-style
2024-10-07 05:16:11 +03:00
fazelukario fef74c3bca feat Cross-Platform Compatibility Guide 2024-10-07 03:46:35 +03:00
fazelukario c390f1bfee Escape markdown for subject 2024-10-07 03:34:49 +03:00
neil f6698d4a84 Merge pull request #5301 from as-kholin/dns_omglol
Adding omg.lol DNS API
2024-10-06 11:52:33 +02:00
Gary McGregor 4193196c8b Merge remote-tracking branch 'upstream/dev' into dns_omglol 2024-10-04 23:39:55 -05:00
neil da06dc3728 Merge pull request #5313 from abulgatz/patch-1
Updated MS links, added wiki link, updated error messages, updated API limit comment
2024-10-03 09:33:19 +02:00
Adam Bulgatz a0b8be5941 Updated MS links, added wiki link, updated error messages, updated API limit comment
Updated all Microsoft links from old `docs` subdomain to new `learn` subdomain, and fixed a couple that weren't working.

Added missing $wiki variable to print the wiki link in error messages.

Updated spelling and formatting in error messages

Updated a comment and added a TODO as Microsoft has increased the number of allowed Public DNS zones per subscription from 100 to 250, while the function in this script can only handle the old limit of 100.
2024-10-03 01:24:07 -05:00
Gary McGregor fe971680ea With variable name updates, correct missed update for the name for saved variables 2024-09-30 07:42:09 -05:00
Gary McGregor 254eb8f304 Updated variable names per @NeilPang 2024-09-30 06:47:26 -05:00
Gary McGregor c9d15901d1 Merge remote-tracking branch 'upstream/master' into dns_omglol 2024-09-30 06:46:30 -05:00
Gary McGregor 59b3f5fb19 Merge remote-tracking branch 'upstream/dev' into dns_omglol 2024-09-29 23:09:22 -05:00
Gary McGregor dbe9dd47ce Correcting over-correct on debugging levels 2024-09-29 23:08:39 -05:00
neil 8e35f8c3aa Merge pull request #5309 from jschauma/master
on OpenBSD, add libiconv
2024-09-29 21:34:28 +02:00
Gary McGregor 80970a0ac6 Merge remote-tracking branch 'upstream/dev' into dns_omglol 2024-09-29 13:35:23 -05:00
Gary McGregor 432f6ac4d7 Updated input parameters per feedback from @Neilpang. Also updated debugging statements to be consistently applied. 2024-09-29 13:34:34 -05:00
neil eaf11009d1 Merge pull request #5310 from acmesh-official/dev
sync
2024-09-29 12:46:32 +02:00
neil df93fb773f Merge pull request #5297 from PMExtra/feature/ali_dcdn
Add ali_dcdn deploy hook (Alibaba Cloud DCDN)
2024-09-29 12:23:31 +02:00
Gary McGregor f6887a4dac Merge remote-tracking branch 'upstream/dev' into dns_omglol 2024-09-28 22:50:47 -05:00
Jan Schaumann 1c58c4c409 on OpenBSD, add libiconv
acme.sh dnsapi/dns_edgedns.sh invokes iconv(1) which is not provided by
OpenBSD in the base system. Adding the libiconv package provides this tool.

This should also help address acmesh-official/acme.sh#4350, albeit indirectly:
it looks like that PR cannot be merged because the OpenBSD test fails despite
the PR not actually changing anything having to do with iconv. That is, I
suspect that the test for OpenBSD failed (or would have failed, had it been
run?) prior to that PR being issued.

(This was previously submitted as
https://github.com/acmesh-official/acmetest/pull/28 )
2024-09-28 14:18:22 -04:00
neil a972901438 Merge pull request #5305 from mpgirro/oci-image-source
Add OpenContainers Annotations as Labels to Docker Image
2024-09-27 08:45:10 +02:00
Maximilian Irro 25703296a6 Add OpenContainer Image Format Annotations as Labels to Docker Image 2024-09-26 21:50:06 +02:00
PM Extra 7ebe97b931 Merge pull request #1 from ShirasawaSama/patch-1
fix: fix ali_dcdn function naming typo
2024-09-25 14:30:10 +08:00
Shirasawa 76719d1bf5 fix: fix ali_dcdn function naming typo 2024-09-25 00:27:04 +08:00
Gary McGregor cb113437f6 Updating per comment re: Exit vs Return on initial validation 2024-09-24 07:23:39 -05:00
Gary McGregor e6b3e42d61 Adding omg.lol DNS API 2024-09-23 22:21:37 -05:00
neil c20b0169a9 upgrade version 2024-09-23 18:15:10 +02:00
PMExtra 89342bcb75 add ali_dcdn deploy hook 2024-09-23 15:11:52 +08:00
neil e036eea362 Merge pull request #5158 from henrikalves/dode
update dns_doapi
2024-09-21 17:29:26 +02:00
neil 2044d633e9 Merge pull request #5183 from WinSCaP/patch-1
Update dns_openprovider.sh for OpenProvider
2024-09-21 17:24:53 +02:00
neil 8cb684e6bd fix https://github.com/acmesh-official/acme.sh/issues/5067 2024-09-21 17:11:17 +02:00
neil 997bd3392f fix https://github.com/acmesh-official/acme.sh/issues/5293 2024-09-21 13:21:32 +02:00
neil ad44c87746 Merge pull request #5296 from nikolaypronchev/master
Fix Timeweb Cloud DNS API pagination
2024-09-21 13:03:21 +02:00
Nikolay Pronchev 45ea2f82ba explicitly reset *_return variables 2024-09-20 15:14:30 +00:00
Nikolay Pronchev df6aa99ec2 fix Timeweb Cloud DNS API pagination 2024-09-20 14:00:44 +00:00
stbeldarborge 1029dd3504 fix format 2024-09-20 15:44:50 +02:00
neil 114eb6288d Merge pull request #5294 from PMExtra/refactor/ali_api
refactor: Alibaba Cloud API
2024-09-20 09:33:44 +02:00
PMExtra 2ea37e6a0d refactor(ali): check the result of prepare_ali_credentials 2024-09-20 14:55:33 +08:00
PMExtra ea2330b49f refactor(ali): move the loading script into ali_cdn_deploy 2024-09-20 14:54:07 +08:00
PMExtra 610bb2b85c refactor(ali): set API endpoint for each action 2024-09-19 16:30:04 +08:00
PMExtra fca6e9b932 refactor: Alibaba Cloud API 2024-09-19 15:49:42 +08:00
stbeldarborge 8860915fb9 remove dns 2024-09-03 21:36:54 +02:00
stbeldarborge f0d486d1ff add bearer token to removal 2024-09-03 20:59:17 +02:00
stbeldarborge b27767e8f4 logic 2024-09-02 16:04:34 +02:00
stbeldarborge 0b2edd28df bearer check 2024-09-02 16:02:36 +02:00
stbeldarborge dd634382d7 debug 2024-09-02 15:57:48 +02:00
stbeldarborge c7fb155733 debug 2024-09-02 15:56:12 +02:00
stbeldarborge 1eaa2cc619 debug 2024-09-02 15:53:33 +02:00
stbeldarborge 92a47aaac5 logic 2024-09-02 15:41:55 +02:00
stbeldarborge fcffe8beb9 feat: add bearer token support 2024-09-02 15:40:45 +02:00
Markku Leiniö 833632eee3 Add shellcheck disable=SC2034 for the info variable 2024-08-04 19:15:11 +03:00
Markku Leiniö abc76299c0 Fix documentation link 2024-08-04 18:58:59 +03:00
Markku Leiniö c96fcf319a Remove dns_he_ddns_rm(), not used 2024-08-04 18:25:20 +03:00
Markku Leiniö 5214a7c3ec Add dnsapi script for HE DDNS 2024-08-04 18:19:21 +03:00
Владимир Алексеев 51151293d7 Remove date -d on macOS 2024-07-06 21:01:25 +10:00
WinSCaP 617f4acfd6 Update dns_openprovider.sh for OpenProvider
Removed the NS type, as settings nameservers via API is no longer supported.  The API implementation is not changed to the new REST API.
2024-06-22 11:37:10 +02:00
Vinicius Mello 2f8fb360aa fix CI reported problems for shellcheck and shfmt
fix minor problems reported by shellcheck and shfmt
2024-06-12 15:03:02 -03:00
Vinicius Mello 05ec3922f1 minor wording fix
minor fix for text coherence
2024-06-11 17:17:37 -03:00
Vinicius Mello 1c9423ef31 fix pagination bug querying Linode API v4
fixes issue #4956

previous code only worked for the first 10 domains on the account (as Linode
API returned a paginated response, with only 10 records).

This change makes an exact search query for each subdomain, completely removing any
need for walking through paginated responses. What makes it work for large
accounts with any number of domains.
2024-06-11 12:50:45 -03:00
Henrik Alves b821836dc4 update dns_doapi 2024-05-27 12:45:01 +02:00
Владимир Алексеев a42fef0905 Merge branch 'dev' into master 2024-05-20 07:05:06 +10:00
Владимир Алексеев 95b51cf9e6 Merge branch 'acmesh-official:master' into master 2024-05-05 09:42:54 +10:00
Vladimir Alexeev a375e924b4 translation of comments into English 2024-05-05 07:42:22 +10:00
Vladimir Alexeev d989617825 set default SL_Ver to v1 2024-05-04 20:42:38 +10:00
Vladimir Alexeev 177d9b7cb0 set default SL_Ver to v1 2024-05-04 20:38:42 +10:00
Vladimir Alexeev 7a1305c1bb fix del record for v1, delete one entry at a time 2024-05-04 19:12:42 +10:00
Vladimir Alexeev 8bb29f53d1 test DNS for v1 (legacy) 003 2024-04-30 16:15:45 +10:00
Vladimir Alexeev 2e3c1ef4ac test DNS for v1 (legacy) 003 2024-04-30 13:49:53 +10:00
Vladimir Alexeev ada7e12b5a test DNS for v1 (legacy) 003 2024-04-30 11:03:53 +10:00
Vladimir Alexeev b8949ba3dd test DNS for v1 (legacy) 002 2024-04-30 10:01:50 +10:00
Vladimir Alexeev 73fe47ba79 test DNS for v1 (legacy) 001 2024-04-30 09:57:49 +10:00
Vladimir Alexeev 577920de86 test DNS for v2 (actual) 001 2024-04-30 08:36:36 +10:00
Vladimir Alexeev 517baa3235 test DNS for v2 (actual) 2024-04-29 22:54:31 +10:00
Keith Chiem ed72b090af deploy hook for Ruckus ZoneDirector / Unleashed 2023-10-18 20:32:39 -07:00
Frank Wall 778ee02803 update documentation for --cert-home
Although the main use-case may be the --install command, this command
also proves to be useful for the --signcsr and --issue commands.
2022-11-07 23:43:37 +01:00
141 changed files with 3467 additions and 769 deletions

No files matched your search

+1 -1
View File
@@ -281,7 +281,7 @@ jobs:
- uses: vmactions/openbsd-vm@v1
with:
envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_NO_SUBDOMAIN TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG http_proxy https_proxy TokenName1 TokenName2 TokenName3 TokenName4 TokenName5 ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}'
prepare: pkg_add socat curl
prepare: pkg_add socat curl libiconv
usesh: true
copyback: false
run: |
+15 -2
View File
@@ -15,6 +15,8 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
DOCKER_IMAGE: neilpang/acme.sh
jobs:
CheckToken:
@@ -42,8 +44,15 @@ jobs:
steps:
- name: checkout code
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v5.5.1
with:
images: ${DOCKER_IMAGE}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: login to docker hub
@@ -51,8 +60,6 @@ jobs:
echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin
- name: build and push the image
run: |
DOCKER_IMAGE=neilpang/acme.sh
if [[ $GITHUB_REF == refs/tags/* ]]; then
DOCKER_IMAGE_TAG=${GITHUB_REF#refs/tags/}
fi
@@ -66,8 +73,14 @@ jobs:
fi
fi
DOCKER_LABELS=()
while read -r label; do
DOCKER_LABELS+=(--label "${label}")
done <<<"${DOCKER_METADATA_OUTPUT_LABELS}"
docker buildx build \
--tag ${DOCKER_IMAGE}:${DOCKER_IMAGE_TAG} \
"${DOCKER_LABELS[@]}" \
--output "type=image,push=true" \
--build-arg AUTO_UPGRADE=${AUTO_UPGRADE} \
--platform linux/arm64/v8,linux/amd64,linux/arm/v6,linux/arm/v7,linux/386,linux/ppc64le,linux/s390x .
+1
View File
@@ -23,6 +23,7 @@ jobs:
First thing: don't send PR to the master branch, please send to the dev branch instead.
Please make sure you've read our [DNS API Dev Guide](../wiki/DNS-API-Dev-Guide) and [DNS-API-Test](../wiki/DNS-API-Test).
Then reply on this message, otherwise, your code will not be reviewed or merged.
Please also make sure to add/update the usage here: https://github.com/acmesh-official/acme.sh/wiki/dnsapi2
We look forward to reviewing your Pull request shortly ✨
注意: 必须通过了 [DNS-API-Test](../wiki/DNS-API-Test) 才会被 review. 无论是修改, 还是新加的 dns api, 都必须确保通过这个测试.
`
+1 -1
View File
@@ -1,4 +1,4 @@
name: Check dns api
name: Check notify api
on:
pull_request_target:
+8 -4
View File
@@ -1,4 +1,4 @@
FROM alpine:3.17
FROM alpine:3.21
RUN apk --no-cache add -f \
openssl \
@@ -15,14 +15,18 @@ RUN apk --no-cache add -f \
jq \
cronie
ENV LE_CONFIG_HOME /acme.sh
ENV LE_CONFIG_HOME=/acme.sh
ARG AUTO_UPGRADE=1
ENV AUTO_UPGRADE $AUTO_UPGRADE
ENV AUTO_UPGRADE=$AUTO_UPGRADE
#Install
COPY ./ /install_acme.sh/
COPY ./acme.sh /install_acme.sh/acme.sh
COPY ./deploy /install_acme.sh/deploy
COPY ./dnsapi /install_acme.sh/dnsapi
COPY ./notify /install_acme.sh/notify
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/
+43 -12
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env sh
VER=3.0.9
VER=3.1.1
PROJECT_NAME="acme.sh"
@@ -672,8 +672,10 @@ _hex_dump() {
#0 1 2 3 4 5 6 7 8 9 - _ . ~
#30 31 32 33 34 35 36 37 38 39 2d 5f 2e 7e
#_url_encode [upper-hex] the encoded hex will be upper-case if the argument upper-hex is followed
#stdin stdout
_url_encode() {
_upper_hex=$1
_hex_str=$(_hex_dump)
_debug3 "_url_encode"
_debug3 "_hex_str" "$_hex_str"
@@ -883,6 +885,9 @@ _url_encode() {
;;
#other hex
*)
if [ "$_upper_hex" = "upper-hex" ]; then
_hex_code=$(printf "%s" "$_hex_code" | _upper_case)
fi
printf '%%%s' "$_hex_code"
;;
esac
@@ -916,6 +921,9 @@ _sed_i() {
if sed -h 2>&1 | grep "\-i\[SUFFIX]" >/dev/null 2>&1; then
_debug "Using sed -i"
sed -i "$options" "$filename"
elif sed -h 2>&1 | grep "\-i extension" >/dev/null 2>&1; then
_debug "Using FreeBSD sed -i"
sed -i "" "$options" "$filename"
else
_debug "No -i support in sed"
text="$(cat "$filename")"
@@ -1437,7 +1445,7 @@ _toPkcs() {
else
${ACME_OPENSSL_BIN:-openssl} pkcs12 -export -out "$_cpfx" -inkey "$_ckey" -in "$_ccert" -certfile "$_cca"
fi
if [ "$?" == "0" ]; then
if [ "$?" = "0" ]; then
_savedomainconf "Le_PFXPassword" "$pfxPassword"
fi
@@ -1623,6 +1631,11 @@ _time2str() {
return
fi
#Omnios
if date -u -r "$1" +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null; then
return
fi
#Solaris
if printf "%(%Y-%m-%dT%H:%M:%SZ)T\n" $1 2>/dev/null; then
return
@@ -1806,7 +1819,11 @@ _date2time() {
return
fi
#Omnios
if da="$(echo "$1" | tr -d "Z" | tr "T" ' ')" perl -MTime::Piece -e 'print Time::Piece->strptime($ENV{da}, "%Y-%m-%d %H:%M:%S")->epoch, "\n";' 2>/dev/null; then
if python3 -c "import datetime; print(int(datetime.datetime.strptime(\"$1\", \"%Y-%m-%d %H:%M:%S\").replace(tzinfo=datetime.timezone.utc).timestamp()))" 2>/dev/null; then
return
fi
#Omnios
if python3 -c "import datetime; print(int(datetime.datetime.strptime(\"$1\", \"%Y-%m-%dT%H:%M:%SZ\").replace(tzinfo=datetime.timezone.utc).timestamp()))" 2>/dev/null; then
return
fi
_err "Cannot parse _date2time $1"
@@ -2188,7 +2205,6 @@ _send_signed_request() {
_debug2 _headers "$_headers"
_CACHED_NONCE="$(echo "$_headers" | grep -i "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2)"
fi
_debug2 _CACHED_NONCE "$_CACHED_NONCE"
if [ "$?" != "0" ]; then
_err "Cannot connect to $nonceurl to get nonce."
return 1
@@ -4989,9 +5005,11 @@ $_authorizations_map"
_debug "Writing token: $token to $wellknown_path/$token"
mkdir -p "$wellknown_path"
if ! printf "%s" "$keyauthorization" >"$wellknown_path/$token"; then
# Ensure .well-known is visible to web server user/group
# https://github.com/Neilpang/acme.sh/pull/32
if ! (umask ugo+rx &&
mkdir -p "$wellknown_path" &&
printf "%s" "$keyauthorization" >"$wellknown_path/$token"); then
_err "$d: Cannot write token to file: $wellknown_path/$token"
_clearupwebbroot "$_currentRoot" "$removelevel" "$token"
_clearup
@@ -5111,6 +5129,19 @@ $_authorizations_map"
_on_issue_err "$_post_hook" "$vlist"
return 1
fi
_retryafter=$(echo "$responseHeaders" | grep -i "^Retry-After *: *[0-9]\+ *" | cut -d : -f 2 | tr -d ' ' | tr -d '\r')
_sleep_overload_retry_sec=$_retryafter
if [ "$_sleep_overload_retry_sec" ]; then
if [ $_sleep_overload_retry_sec -le 600 ]; then
_sleep $_sleep_overload_retry_sec
else
_info "The retryafter=$_retryafter value is too large (> 600), will not retry anymore."
_clearupwebbroot "$_currentRoot" "$removelevel" "$token"
_clearup
_on_issue_err "$_post_hook" "$vlist"
return 1
fi
fi
done
done
@@ -5792,7 +5823,7 @@ _deploy() {
return 1
fi
if ! $d_command "$_d" "$CERT_KEY_PATH" "$CERT_PATH" "$CA_CERT_PATH" "$CERT_FULLCHAIN_PATH"; then
if ! $d_command "$_d" "$CERT_KEY_PATH" "$CERT_PATH" "$CA_CERT_PATH" "$CERT_FULLCHAIN_PATH" "$CERT_PFX_PATH"; then
_err "Error deploying for domain: $_d"
return 1
fi
@@ -5955,7 +5986,7 @@ _installcert() {
); then
_info "$(__green "Reload successful")"
else
_err "Reload error for: $Le_Domain"
_err "Reload error for: $_main_domain"
fi
fi
@@ -6035,7 +6066,7 @@ installcronjob() {
_script="$(_readlink "$_SCRIPT_")"
_debug _script "$_script"
if [ -f "$_script" ]; then
_info "Usinging the current script from: $_script"
_info "Using the current script from: $_script"
lesh="$_script"
else
_err "Cannot install cronjob, $PROJECT_ENTRY not found."
@@ -6787,7 +6818,7 @@ _send_notify() {
_nsource="$NOTIFY_SOURCE"
if [ -z "$_nsource" ]; then
_nsource="$(hostname)"
_nsource="$(uname -n)"
fi
_nsubject="$_nsubject by $_nsource"
@@ -6989,7 +7020,7 @@ Parameters:
--accountconf <file> Specifies a customized account config file.
--home <directory> Specifies the home dir for $PROJECT_NAME.
--cert-home <directory> Specifies the home dir to save all the certs, only valid for '--install' command.
--cert-home <directory> Specifies the home dir to save all the certs.
--config-home <directory> Specifies the home dir to save all the configurations.
--useragent <string> Specifies the user agent string. it will be saved for future use too.
-m, --email <email> Specifies the account email, only valid for the '--install' and '--update-account' command.
+19 -88
View File
@@ -1,17 +1,23 @@
#!/usr/bin/env sh
# shellcheck disable=SC2034,SC2154
# Script to create certificate to Alibaba Cloud CDN
#
# Docs: https://github.com/acmesh-official/acme.sh/wiki/deployhooks#33-deploy-your-certificate-to-cdn-or-dcdn-of-alibaba-cloud-aliyun
#
# This deployment required following variables
# export Ali_Key="ALIACCESSKEY"
# export Ali_Secret="ALISECRETKEY"
# The credentials are shared with all the Alibaba Cloud deploy hooks and dnsapi
#
# To specify the CDN domain that is different from the certificate CN, usually used for multi-domain or wildcard certificates
# export DEPLOY_ALI_CDN_DOMAIN="cdn.example.com"
# If you have more than one domain, just
# If you have multiple CDN domains using the same certificate, just
# export DEPLOY_ALI_CDN_DOMAIN="cdn1.example.com cdn2.example.com"
#
# The credentials are shared with all domains, also shared with dns_ali api
# For DCDN, see ali_dcdn deploy hook
Ali_API="https://cdn.aliyuncs.com/"
Ali_CDN_API="https://cdn.aliyuncs.com/"
ali_cdn_deploy() {
_cdomain="$1"
@@ -26,18 +32,16 @@ ali_cdn_deploy() {
_debug _cca "$_cca"
_debug _cfullchain "$_cfullchain"
Ali_Key="${Ali_Key:-$(_readaccountconf_mutable Ali_Key)}"
Ali_Secret="${Ali_Secret:-$(_readaccountconf_mutable Ali_Secret)}"
if [ -z "$Ali_Key" ] || [ -z "$Ali_Secret" ]; then
Ali_Key=""
Ali_Secret=""
_err "You don't specify aliyun api key and secret yet."
# Load dnsapi/dns_ali.sh to reduce the duplicated codes
# https://github.com/acmesh-official/acme.sh/pull/5205#issuecomment-2357867276
dnsapi_ali="$(_findHook "$_cdomain" "$_SUB_FOLDER_DNSAPI" dns_ali)"
# shellcheck source=/dev/null
if ! . "$dnsapi_ali"; then
_err "Error loading file $dnsapi_ali. Please check your API file and try again."
return 1
fi
#save the api key and secret to the account conf file.
_saveaccountconf_mutable Ali_Key "$Ali_Key"
_saveaccountconf_mutable Ali_Secret "$Ali_Secret"
_prepare_ali_credentials || return 1
_getdeployconf DEPLOY_ALI_CDN_DOMAIN
if [ "$DEPLOY_ALI_CDN_DOMAIN" ]; then
@@ -47,8 +51,8 @@ ali_cdn_deploy() {
fi
# read cert and key files and urlencode both
_cert=$(_url_encode_upper <"$_cfullchain")
_key=$(_url_encode_upper <"$_ckey")
_cert=$(_url_encode upper-hex <"$_cfullchain")
_key=$(_url_encode upper-hex <"$_ckey")
_debug2 _cert "$_cert"
_debug2 _key "$_key"
@@ -64,82 +68,9 @@ ali_cdn_deploy() {
return 0
}
#################### Private functions below ##################################
# act ign mtd
_ali_rest() {
act="$1"
ign="$2"
mtd="$3"
signature=$(printf "%s" "$mtd&%2F&$(_ali_urlencode "$query")" | _hmac "sha1" "$(printf "%s" "$Ali_Secret&" | _hex_dump | tr -d " ")" | _base64)
signature=$(_ali_urlencode "$signature")
url="$Ali_API?$query&Signature=$signature"
if [ "$mtd" = "GET" ]; then
response="$(_get "$url")"
else
# post payload is not supported yet because of signature
response="$(_post "" "$url")"
fi
_ret="$?"
_debug2 response "$response"
if [ "$_ret" != "0" ]; then
_err "Error <$act>"
return 1
fi
if [ -z "$ign" ]; then
message="$(echo "$response" | _egrep_o "\"Message\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \")"
if [ "$message" ]; then
_err "$message"
return 1
fi
fi
}
_ali_urlencode() {
_str="$1"
_str_len=${#_str}
_u_i=1
while [ "$_u_i" -le "$_str_len" ]; do
_str_c="$(printf "%s" "$_str" | cut -c "$_u_i")"
case $_str_c in [a-zA-Z0-9.~_-])
printf "%s" "$_str_c"
;;
*)
printf "%%%02X" "'$_str_c"
;;
esac
_u_i="$(_math "$_u_i" + 1)"
done
}
_ali_nonce() {
#_head_n 1 </dev/urandom | _digest "sha256" hex | cut -c 1-31
#Not so good...
date +"%s%N" | sed 's/%N//g'
}
_timestamp() {
date -u +"%Y-%m-%dT%H%%3A%M%%3A%SZ"
}
# stdin stdout
_url_encode_upper() {
encoded=$(_url_encode)
for match in $(echo "$encoded" | _egrep_o '%..' | sort -u); do
upper=$(echo "$match" | _upper_case)
encoded=$(echo "$encoded" | sed "s/$match/$upper/g")
done
echo "$encoded"
}
# domain pub pri
_set_cdn_domain_ssl_certificate_query() {
endpoint=$Ali_CDN_API
query=''
query=$query'AccessKeyId='$Ali_Key
query=$query'&Action=SetCdnDomainSSLCertificate'
+88
View File
@@ -0,0 +1,88 @@
#!/usr/bin/env sh
# shellcheck disable=SC2034,SC2154
# Script to create certificate to Alibaba Cloud DCDN
#
# Docs: https://github.com/acmesh-official/acme.sh/wiki/deployhooks#33-deploy-your-certificate-to-cdn-or-dcdn-of-alibaba-cloud-aliyun
#
# This deployment required following variables
# export Ali_Key="ALIACCESSKEY"
# export Ali_Secret="ALISECRETKEY"
# The credentials are shared with all the Alibaba Cloud deploy hooks and dnsapi
#
# To specify the DCDN domain that is different from the certificate CN, usually used for multi-domain or wildcard certificates
# export DEPLOY_ALI_DCDN_DOMAIN="dcdn.example.com"
# If you have multiple CDN domains using the same certificate, just
# export DEPLOY_ALI_DCDN_DOMAIN="dcdn1.example.com dcdn2.example.com"
#
# For regular CDN, see ali_cdn deploy hook
Ali_DCDN_API="https://dcdn.aliyuncs.com/"
ali_dcdn_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"
# Load dnsapi/dns_ali.sh to reduce the duplicated codes
# https://github.com/acmesh-official/acme.sh/pull/5205#issuecomment-2357867276
dnsapi_ali="$(_findHook "$_cdomain" "$_SUB_FOLDER_DNSAPI" dns_ali)"
# shellcheck source=/dev/null
if ! . "$dnsapi_ali"; then
_err "Error loading file $dnsapi_ali. Please check your API file and try again."
return 1
fi
_prepare_ali_credentials || return 1
_getdeployconf DEPLOY_ALI_DCDN_DOMAIN
if [ "$DEPLOY_ALI_DCDN_DOMAIN" ]; then
_savedeployconf DEPLOY_ALI_DCDN_DOMAIN "$DEPLOY_ALI_DCDN_DOMAIN"
else
DEPLOY_ALI_DCDN_DOMAIN="$_cdomain"
fi
# read cert and key files and urlencode both
_cert=$(_url_encode upper-hex <"$_cfullchain")
_key=$(_url_encode upper-hex <"$_ckey")
_debug2 _cert "$_cert"
_debug2 _key "$_key"
## update domain ssl config
for domain in $DEPLOY_ALI_DCDN_DOMAIN; do
_set_dcdn_domain_ssl_certificate_query "$domain" "$_cert" "$_key"
if _ali_rest "Set DCDN domain SSL certificate for $domain" "" POST; then
_info "Domain $domain certificate has been deployed successfully"
fi
done
return 0
}
# domain pub pri
_set_dcdn_domain_ssl_certificate_query() {
endpoint=$Ali_DCDN_API
query=''
query=$query'AccessKeyId='$Ali_Key
query=$query'&Action=SetDcdnDomainSSLCertificate'
query=$query'&CertType=upload'
query=$query'&DomainName='$1
query=$query'&Format=json'
query=$query'&SSLPri='$3
query=$query'&SSLProtocol=on'
query=$query'&SSLPub='$2
query=$query'&SignatureMethod=HMAC-SHA1'
query=$query"&SignatureNonce=$(_ali_nonce)"
query=$query'&SignatureVersion=1.0'
query=$query'&Timestamp='$(_timestamp)
query=$query'&Version=2018-01-15'
}
+13
View File
@@ -18,6 +18,7 @@ docker_deploy() {
_ccert="$3"
_cca="$4"
_cfullchain="$5"
_cpfx="$6"
_debug _cdomain "$_cdomain"
_getdeployconf DEPLOY_DOCKER_CONTAINER_LABEL
_debug2 DEPLOY_DOCKER_CONTAINER_LABEL "$DEPLOY_DOCKER_CONTAINER_LABEL"
@@ -88,6 +89,12 @@ docker_deploy() {
_savedeployconf DEPLOY_DOCKER_CONTAINER_FULLCHAIN_FILE "$DEPLOY_DOCKER_CONTAINER_FULLCHAIN_FILE"
fi
_getdeployconf DEPLOY_DOCKER_CONTAINER_PFX_FILE
_debug2 DEPLOY_DOCKER_CONTAINER_PFX_FILE "$DEPLOY_DOCKER_CONTAINER_PFX_FILE"
if [ "$DEPLOY_DOCKER_CONTAINER_PFX_FILE" ]; then
_savedeployconf DEPLOY_DOCKER_CONTAINER_PFX_FILE "$DEPLOY_DOCKER_CONTAINER_PFX_FILE"
fi
_getdeployconf DEPLOY_DOCKER_CONTAINER_RELOAD_CMD
_debug2 DEPLOY_DOCKER_CONTAINER_RELOAD_CMD "$DEPLOY_DOCKER_CONTAINER_RELOAD_CMD"
if [ "$DEPLOY_DOCKER_CONTAINER_RELOAD_CMD" ]; then
@@ -125,6 +132,12 @@ docker_deploy() {
fi
fi
if [ "$DEPLOY_DOCKER_CONTAINER_PFX_FILE" ]; then
if ! _docker_cp "$_cid" "$_cpfx" "$DEPLOY_DOCKER_CONTAINER_PFX_FILE"; then
return 1
fi
fi
if [ "$DEPLOY_DOCKER_CONTAINER_RELOAD_CMD" ]; then
_info "Reloading: $DEPLOY_DOCKER_CONTAINER_RELOAD_CMD"
if ! _docker_exec "$_cid" "$DEPLOY_DOCKER_CONTAINER_RELOAD_CMD"; then
-1
View File
@@ -109,6 +109,5 @@ exim4_deploy() {
fi
return 1
fi
return 0
}
+1 -1
View File
@@ -357,7 +357,7 @@ haproxy_deploy() {
_info "Update existing certificate '${_pem}' over HAProxy ${_socketname}."
fi
_socat_cert_set_cmd="echo -e '${_cmdpfx}set ssl cert ${_pem} <<\n$(cat "${_pem}")\n' | socat '${_statssock}' - | grep -q 'Transaction created'"
_debug _socat_cert_set_cmd "${_socat_cert_set_cmd}"
_secure_debug _socat_cert_set_cmd "${_socat_cert_set_cmd}"
eval "${_socat_cert_set_cmd}"
_ret=$?
if [ "${_ret}" != "0" ]; then
+120
View File
@@ -0,0 +1,120 @@
#!/usr/bin/env sh
# Deploy certificates to a proxmox backup server using the API.
#
# Environment variables that can be set are:
# `DEPLOY_PROXMOXBS_SERVER`: The hostname of the proxmox backup server. Defaults to
# _cdomain.
# `DEPLOY_PROXMOXBS_SERVER_PORT`: The port number the management interface is on.
# Defaults to 8007.
# `DEPLOY_PROXMOXBS_USER`: The user we'll connect as. Defaults to root.
# `DEPLOY_PROXMOXBS_USER_REALM`: The authentication realm the user authenticates
# with. Defaults to pam.
# `DEPLOY_PROXMOXBS_API_TOKEN_NAME`: The name of the API token created for the
# user account. Defaults to acme.
# `DEPLOY_PROXMOXBS_API_TOKEN_KEY`: The API token. Required.
proxmoxbs_deploy() {
_cdomain="$1"
_ckey="$2"
_ccert="$3"
_cca="$4"
_cfullchain="$5"
_debug _cdomain "$_cdomain"
_debug2 _ckey "$_ckey"
_debug _ccert "$_ccert"
_debug _cca "$_cca"
_debug _cfullchain "$_cfullchain"
# "Sane" defaults.
_getdeployconf DEPLOY_PROXMOXBS_SERVER
if [ -z "$DEPLOY_PROXMOXBS_SERVER" ]; then
_target_hostname="$_cdomain"
else
_target_hostname="$DEPLOY_PROXMOXBS_SERVER"
_savedeployconf DEPLOY_PROXMOXBS_SERVER "$DEPLOY_PROXMOXBS_SERVER"
fi
_debug2 DEPLOY_PROXMOXBS_SERVER "$_target_hostname"
_getdeployconf DEPLOY_PROXMOXBS_SERVER_PORT
if [ -z "$DEPLOY_PROXMOXBS_SERVER_PORT" ]; then
_target_port="8007"
else
_target_port="$DEPLOY_PROXMOXBS_SERVER_PORT"
_savedeployconf DEPLOY_PROXMOXBS_SERVER_PORT "$DEPLOY_PROXMOXBS_SERVER_PORT"
fi
_debug2 DEPLOY_PROXMOXBS_SERVER_PORT "$_target_port"
# Complete URL.
_target_url="https://${_target_hostname}:${_target_port}/api2/json/nodes/localhost/certificates/custom"
_debug TARGET_URL "$_target_url"
# More "sane" defaults.
_getdeployconf DEPLOY_PROXMOXBS_USER
if [ -z "$DEPLOY_PROXMOXBS_USER" ]; then
_proxmoxbs_user="root"
else
_proxmoxbs_user="$DEPLOY_PROXMOXBS_USER"
_savedeployconf DEPLOY_PROXMOXBS_USER "$DEPLOY_PROXMOXBS_USER"
fi
_debug2 DEPLOY_PROXMOXBS_USER "$_proxmoxbs_user"
_getdeployconf DEPLOY_PROXMOXBS_USER_REALM
if [ -z "$DEPLOY_PROXMOXBS_USER_REALM" ]; then
_proxmoxbs_user_realm="pam"
else
_proxmoxbs_user_realm="$DEPLOY_PROXMOXBS_USER_REALM"
_savedeployconf DEPLOY_PROXMOXBS_USER_REALM "$DEPLOY_PROXMOXBS_USER_REALM"
fi
_debug2 DEPLOY_PROXMOXBS_USER_REALM "$_proxmoxbs_user_realm"
_getdeployconf DEPLOY_PROXMOXBS_API_TOKEN_NAME
if [ -z "$DEPLOY_PROXMOXBS_API_TOKEN_NAME" ]; then
_proxmoxbs_api_token_name="acme"
else
_proxmoxbs_api_token_name="$DEPLOY_PROXMOXBS_API_TOKEN_NAME"
_savedeployconf DEPLOY_PROXMOXBS_API_TOKEN_NAME "$DEPLOY_PROXMOXBS_API_TOKEN_NAME"
fi
_debug2 DEPLOY_PROXMOXBS_API_TOKEN_NAME "$_proxmoxbs_api_token_name"
# This is required.
_getdeployconf DEPLOY_PROXMOXBS_API_TOKEN_KEY
if [ -z "$DEPLOY_PROXMOXBS_API_TOKEN_KEY" ]; then
_err "API key not provided."
return 1
else
_proxmoxbs_api_token_key="$DEPLOY_PROXMOXBS_API_TOKEN_KEY"
_savedeployconf DEPLOY_PROXMOXBS_API_TOKEN_KEY "$DEPLOY_PROXMOXBS_API_TOKEN_KEY"
fi
_debug2 DEPLOY_PROXMOXBS_API_TOKEN_KEY "$_proxmoxbs_api_token_key"
# PBS API Token header value. Used in "Authorization: PBSAPIToken".
_proxmoxbs_header_api_token="${_proxmoxbs_user}@${_proxmoxbs_user_realm}!${_proxmoxbs_api_token_name}:${_proxmoxbs_api_token_key}"
_debug2 "Auth Header" "$_proxmoxbs_header_api_token"
# Ugly. I hate putting heredocs inside functions because heredocs don't
# account for whitespace correctly but it _does_ work and is several times
# cleaner than anything else I had here.
#
# This dumps the json payload to a variable that should be passable to the
# _psot function.
_json_payload=$(
cat <<HEREDOC
{
"certificates": "$(tr '\n' ':' <"$_cfullchain" | sed 's/:/\\n/g')",
"key": "$(tr '\n' ':' <"$_ckey" | sed 's/:/\\n/g')",
"node":"localhost",
"restart":true,
"force":true
}
HEREDOC
)
_debug2 Payload "$_json_payload"
_info "Push certificates to server"
export HTTPS_INSECURE=1
export _H1="Authorization: PBSAPIToken=${_proxmoxbs_header_api_token}"
_post "$_json_payload" "$_target_url" "" POST "application/json"
}
+2 -2
View File
@@ -144,8 +144,8 @@ 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=\\\"\\\";\
\n/certificate import file-name=\\\"$_cdomain.cer\\\" passphrase=\\\"\\\";\
\n/certificate import file-name=\\\"$_cdomain.key\\\" passphrase=\\\"\\\";\
\ndelay 1;\
\n:do {/file remove $_cdomain.cer; } on-error={ }\
\n:do {/file remove $_cdomain.key; } on-error={ }\
+200
View File
@@ -0,0 +1,200 @@
#!/usr/bin/env sh
# Here is a script to deploy cert to Ruckus ZoneDirector / Unleashed.
#
# Public domain, 2024, Tony Rielly <https://github.com/ms264556>
#
# ```sh
# acme.sh --deploy -d ruckus.example.com --deploy-hook ruckus
# ```
#
# Then you need to set the environment variables for the
# deploy script to work.
#
# ```sh
# export RUCKUS_HOST=myruckus.example.com
# export RUCKUS_USER=myruckususername
# export RUCKUS_PASS=myruckuspassword
#
# acme.sh --deploy -d myruckus.example.com --deploy-hook ruckus
# ```
#
# returns 0 means success, otherwise error.
######## Public functions #####################
#domain keyfile certfile cafile fullchain
ruckus_deploy() {
_cdomain="$1"
_ckey="$2"
_ccert="$3"
_cca="$4"
_cfullchain="$5"
_err_code=0
_debug _cdomain "$_cdomain"
_debug _ckey "$_ckey"
_debug _ccert "$_ccert"
_debug _cca "$_cca"
_debug _cfullchain "$_cfullchain"
_getdeployconf RUCKUS_HOST
_getdeployconf RUCKUS_USER
_getdeployconf RUCKUS_PASS
if [ -z "$RUCKUS_HOST" ]; then
_debug "Using _cdomain as RUCKUS_HOST, please set if not correct."
RUCKUS_HOST="$_cdomain"
fi
if [ -z "$RUCKUS_USER" ]; then
_err "Need to set the env variable RUCKUS_USER"
return 1
fi
if [ -z "$RUCKUS_PASS" ]; then
_err "Need to set the env variable RUCKUS_PASS"
return 1
fi
_savedeployconf RUCKUS_HOST "$RUCKUS_HOST"
_savedeployconf RUCKUS_USER "$RUCKUS_USER"
_savedeployconf RUCKUS_PASS "$RUCKUS_PASS"
_debug RUCKUS_HOST "$RUCKUS_HOST"
_debug RUCKUS_USER "$RUCKUS_USER"
_secure_debug RUCKUS_PASS "$RUCKUS_PASS"
export ACME_HTTP_NO_REDIRECTS=1
_info "Discovering the login URL"
_get "https://$RUCKUS_HOST" >/dev/null
_login_url="$(_response_header 'Location')"
if [ -n "$_login_url" ]; then
_login_path=$(echo "$_login_url" | sed 's|https\?://[^/]\+||')
if [ -z "$_login_path" ]; then
# redirect was to a different host
_err "Connection failed: redirected to a different host. Configure Unleashed with a Preferred Master or Management Interface."
return 1
fi
fi
if [ -z "${_login_url}" ]; then
_err "Connection failed: couldn't find login page."
return 1
fi
_base_url=$(dirname "$_login_url")
_login_page=$(basename "$_login_url")
if [ "$_login_page" = "index.html" ]; then
_err "Connection temporarily unavailable: Unleashed Rebuilding."
return 1
fi
if [ "$_login_page" = "wizard.jsp" ]; then
_err "Connection failed: Setup Wizard not complete."
return 1
fi
_info "Login"
_username_encoded="$(printf "%s" "$RUCKUS_USER" | _url_encode)"
_password_encoded="$(printf "%s" "$RUCKUS_PASS" | _url_encode)"
_login_query="$(printf "%s" "username=${_username_encoded}&password=${_password_encoded}&ok=Log+In")"
_post "$_login_query" "$_login_url" >/dev/null
_login_code="$(_response_code)"
if [ "$_login_code" = "200" ]; then
_err "Login failed: incorrect credentials."
return 1
fi
_info "Collect Session Cookie"
_H1="Cookie: $(_response_cookie)"
export _H1
_info "Collect CSRF Token"
_H2="X-CSRF-Token: $(_response_header 'HTTP_X_CSRF_TOKEN')"
export _H2
if _isRSA "$_ckey" >/dev/null 2>&1; then
_debug "Using RSA certificate."
else
_info "Verifying ECC certificate support."
_ul_version="$(_get_unleashed_version)"
if [ -z "$_ul_version" ]; then
_err "Your controller doesn't support ECC certificates. Please deploy an RSA certificate."
return 1
fi
_ul_version_major="$(echo "$_ul_version" | cut -d . -f 1)"
_ul_version_minor="$(echo "$_ul_version" | cut -d . -f 2)"
if [ "$_ul_version_major" -lt "200" ]; then
_err "ZoneDirector doesn't support ECC certificates. Please deploy an RSA certificate."
return 1
elif [ "$_ul_version_minor" -lt "13" ]; then
_err "Unleashed $_ul_version_major.$_ul_version_minor doesn't support ECC certificates. Please deploy an RSA certificate or upgrade to Unleashed 200.13+."
return 1
fi
_debug "ECC certificates OK for Unleashed $_ul_version_major.$_ul_version_minor."
fi
_info "Uploading certificate"
_post_upload "uploadcert" "$_cfullchain"
_info "Uploading private key"
_post_upload "uploadprivatekey" "$_ckey"
_info "Replacing certificate"
_replace_cert_ajax='<ajax-request action="docmd" comp="system" updater="rid.0.5" xcmd="replace-cert" checkAbility="6" timeout="-1"><xcmd cmd="replace-cert" cn="'$RUCKUS_HOST'"/></ajax-request>'
_post "$_replace_cert_ajax" "$_base_url/_cmdstat.jsp" >/dev/null
_info "Rebooting"
_cert_reboot_ajax='<ajax-request action="docmd" comp="worker" updater="rid.0.5" xcmd="cert-reboot" checkAbility="6"><xcmd cmd="cert-reboot" action="undefined"/></ajax-request>'
_post "$_cert_reboot_ajax" "$_base_url/_cmdstat.jsp" >/dev/null
return 0
}
_response_code() {
_egrep_o <"$HTTP_HEADER" "^HTTP[^ ]* .*$" | cut -d " " -f 2-100 | tr -d "\f\n" | _egrep_o "^[0-9]*"
}
_response_header() {
grep <"$HTTP_HEADER" -i "^$1:" | cut -d ':' -f 2- | tr -d "\r\n\t "
}
_response_cookie() {
_response_header 'Set-Cookie' | sed 's/;.*//'
}
_get_unleashed_version() {
_post '<ajax-request action="getstat" comp="system"><sysinfo/></ajax-request>' "$_base_url/_cmdstat.jsp" | _egrep_o "version-num=\"[^\"]*\"" | cut -d '"' -f 2
}
_post_upload() {
_post_action="$1"
_post_file="$2"
_post_boundary="----FormBoundary$(date "+%s%N")"
_post_data="$({
printf -- "--%s\r\n" "$_post_boundary"
printf -- "Content-Disposition: form-data; name=\"u\"; filename=\"%s\"\r\n" "$_post_action"
printf -- "Content-Type: application/octet-stream\r\n\r\n"
printf -- "%s\r\n" "$(cat "$_post_file")"
printf -- "--%s\r\n" "$_post_boundary"
printf -- "Content-Disposition: form-data; name=\"action\"\r\n\r\n"
printf -- "%s\r\n" "$_post_action"
printf -- "--%s\r\n" "$_post_boundary"
printf -- "Content-Disposition: form-data; name=\"callback\"\r\n\r\n"
printf -- "%s\r\n" "uploader_$_post_action"
printf -- "--%s--\r\n\r\n" "$_post_boundary"
})"
_post "$_post_data" "$_base_url/_upload.jsp?request_type=xhr" "" "" "multipart/form-data; boundary=$_post_boundary" >/dev/null
}
+77 -34
View File
@@ -10,46 +10,89 @@
#domain keyfile certfile cafile fullchain
strongswan_deploy() {
_cdomain="$1"
_ckey="$2"
_ccert="$3"
_cca="$4"
_cfullchain="$5"
_cdomain="${1}"
_ckey="${2}"
_ccert="${3}"
_cca="${4}"
_cfullchain="${5}"
_info "Using strongswan"
if [ -x /usr/sbin/ipsec ]; then
_ipsec=/usr/sbin/ipsec
elif [ -x /usr/sbin/strongswan ]; then
_ipsec=/usr/sbin/strongswan
elif [ -x /usr/local/sbin/ipsec ]; then
_ipsec=/usr/local/sbin/ipsec
else
if _exists ipsec; then
_ipsec=ipsec
elif _exists strongswan; then
_ipsec=strongswan
fi
if _exists swanctl; then
_swanctl=swanctl
fi
# For legacy stroke mode
if [ -n "${_ipsec}" ]; then
_info "${_ipsec} command detected"
_confdir=$(${_ipsec} --confdir)
if [ -z "${_confdir}" ]; then
_err "no strongswan --confdir is detected"
return 1
fi
_info _confdir "${_confdir}"
__deploy_cert "$@" "stroke" "${_confdir}"
${_ipsec} reload
fi
# For modern vici mode
if [ -n "${_swanctl}" ]; then
_info "${_swanctl} command detected"
for _dir in /usr/local/etc/swanctl /etc/swanctl /etc/strongswan/swanctl; do
if [ -d ${_dir} ]; then
_confdir=${_dir}
_info _confdir "${_confdir}"
break
fi
done
if [ -z "${_confdir}" ]; then
_err "no swanctl config dir is found"
return 1
fi
__deploy_cert "$@" "vici" "${_confdir}"
${_swanctl} --load-creds
fi
if [ -z "${_swanctl}" ] && [ -z "${_ipsec}" ]; then
_err "no strongswan or ipsec command is detected"
_err "no swanctl is detected"
return 1
fi
}
_info _ipsec "$_ipsec"
#################### Private functions below ##################################
_confdir=$($_ipsec --confdir)
if [ $? -ne 0 ] || [ -z "$_confdir" ]; then
_err "no strongswan --confdir is detected"
__deploy_cert() {
_cdomain="${1}"
_ckey="${2}"
_ccert="${3}"
_cca="${4}"
_cfullchain="${5}"
_swan_mode="${6}"
_confdir="${7}"
_debug _cdomain "${_cdomain}"
_debug _ckey "${_ckey}"
_debug _ccert "${_ccert}"
_debug _cca "${_cca}"
_debug _cfullchain "${_cfullchain}"
_debug _swan_mode "${_swan_mode}"
_debug _confdir "${_confdir}"
if [ "${_swan_mode}" = "vici" ]; then
_dir_private="private"
_dir_cert="x509"
_dir_ca="x509ca"
elif [ "${_swan_mode}" = "stroke" ]; then
_dir_private="ipsec.d/private"
_dir_cert="ipsec.d/certs"
_dir_ca="ipsec.d/cacerts"
else
_err "unknown StrongSwan mode ${_swan_mode}"
return 1
fi
_info _confdir "$_confdir"
_debug _cdomain "$_cdomain"
_debug _ckey "$_ckey"
_debug _ccert "$_ccert"
_debug _cca "$_cca"
_debug _cfullchain "$_cfullchain"
cat "$_ckey" >"${_confdir}/ipsec.d/private/$(basename "$_ckey")"
cat "$_ccert" >"${_confdir}/ipsec.d/certs/$(basename "$_ccert")"
cat "$_cca" >"${_confdir}/ipsec.d/cacerts/$(basename "$_cca")"
cat "$_cfullchain" >"${_confdir}/ipsec.d/cacerts/$(basename "$_cfullchain")"
$_ipsec reload
cat "${_ckey}" >"${_confdir}/${_dir_private}/$(basename "${_ckey}")"
cat "${_ccert}" >"${_confdir}/${_dir_cert}/$(basename "${_ccert}")"
cat "${_cca}" >"${_confdir}/${_dir_ca}/$(basename "${_cca}")"
if [ "${_swan_mode}" = "stroke" ]; then
cat "${_cfullchain}" >"${_confdir}/${_dir_ca}/$(basename "${_cfullchain}")"
fi
}
+4 -4
View File
@@ -186,8 +186,8 @@ synology_dsm_deploy() {
if [ -n "$SYNO_USE_TEMP_ADMIN" ]; then
_getdeployconf SYNO_LOCAL_HOSTNAME
_debug SYNO_LOCAL_HOSTNAME "${SYNO_LOCAL_HOSTNAME:-}"
if [ "$SYNO_LOCAL_HOSTNAME" != "1" ] && [ "$SYNO_LOCAL_HOSTNAME" == "$SYNO_HOSTNAME" ]; then
if [ "$SYNO_HOSTNAME" != "localhost" ] && [ "$SYNO_HOSTNAME" != "127.0.0.1" ]; then
if [ "$SYNO_HOSTNAME" != "localhost" ] && [ "$SYNO_HOSTNAME" != "127.0.0.1" ]; then
if [ "$SYNO_LOCAL_HOSTNAME" != "1" ]; then
_err "SYNO_USE_TEMP_ADMIN=1 only support local deployment, though if you are sure that the hostname $SYNO_HOSTNAME is targeting to your **current local machine**, execute 'export SYNO_LOCAL_HOSTNAME=1' then rerun."
return 1
fi
@@ -320,7 +320,7 @@ synology_dsm_deploy() {
_cleardeployconf SYNO_DEVICE_ID
_cleardeployconf SYNO_DEVICE_NAME
_savedeployconf SYNO_USE_TEMP_ADMIN "$SYNO_USE_TEMP_ADMIN"
_savedeployconf SYNO_LOCAL_HOSTNAME "$SYNO_HOSTNAME"
_savedeployconf SYNO_LOCAL_HOSTNAME "$SYNO_LOCAL_HOSTNAME"
else
_savedeployconf SYNO_USERNAME "$SYNO_USERNAME"
_savedeployconf SYNO_PASSWORD "$SYNO_PASSWORD"
@@ -411,7 +411,7 @@ _temp_admin_create() {
_username="$1"
_password="$2"
synouser --del "$_username" >/dev/null 2>/dev/null
synouser --add "$_username" "$_password" "" 0 "scruelt@hotmail.com" 0 >/dev/null
synouser --add "$_username" "$_password" "" 0 "" 0 >/dev/null
}
_temp_admin_cleanup() {
+112 -63
View File
@@ -9,7 +9,7 @@
#
# Following environment variables must be set:
#
# export DEPLOY_TRUENAS_APIKEY="<API_KEY_GENERATED_IN_THE_WEB_UI"
# 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:
@@ -64,6 +64,20 @@ truenas_deploy() {
_response=$(_get "$_api_url/system/state")
_info "TrueNAS system state: $_response."
_info "Getting TrueNAS version"
_response=$(_get "$_api_url/system/version")
if echo "$_response" | grep -q "SCALE"; then
_truenas_os=$(echo "$_response" | cut -d '-' -f 2)
_truenas_version=$(echo "$_response" | cut -d '-' -f 3 | tr -d '"' | cut -d '.' -f 1,2)
else
_truenas_os="unknown"
_truenas_version="unknown"
fi
_info "Detected TrueNAS system os: $_truenas_os"
_info "Detected TrueNAS system version: $_truenas_version"
if [ -z "$_response" ]; then
_err "Unable to authenticate to $_api_url."
_err 'Check your connection settings are correct, e.g.'
@@ -115,27 +129,106 @@ truenas_deploy() {
_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: ,')
_truenas_version_23_10="23.10"
_truenas_version_24_10="24.10"
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"
_check_version=$(printf "%s\n%s" "$_truenas_version_23_10" "$_truenas_version" | sort -V | head -n 1)
if [ "$_truenas_os" != "SCALE" ] || [ "$_check_version" != "$_truenas_version_23_10" ]; then
_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"
return 1
else
_info "WebDAV 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
fi
if [ "$_truenas_os" = "SCALE" ]; then
_check_version=$(printf "%s\n%s" "$_truenas_version_24_10" "$_truenas_version" | sort -V | head -n 1)
if [ "$_check_version" != "$_truenas_version_24_10" ]; then
_info "Checking if any chart release Apps is using the same certificate as TrueNAS web UI. Tool 'jq' is required"
if _exists jq; then
_info "Query all chart release"
_release_list=$(_get "$_api_url/chart/release")
_related_name_list=$(printf "%s" "$_release_list" | jq -r "[.[] | {name,certId: .config.ingress?.main.tls[]?.scaleCert} | select(.certId==$_active_cert_id) | .name ] | unique")
_release_length=$(printf "%s" "$_related_name_list" | jq -r "length")
_info "Found $_release_length related chart release in list: $_related_name_list"
for i in $(seq 0 $((_release_length - 1))); do
_release_name=$(echo "$_related_name_list" | jq -r ".[$i]")
_info "Updating certificate from $_active_cert_id to $_cert_id for chart release: $_release_name"
#Read the chart release configuration
_chart_config=$(printf "%s" "$_release_list" | jq -r ".[] | select(.name==\"$_release_name\")")
#Replace the old certificate id with the new one in path .config.ingress.main.tls[].scaleCert. Then update .config.ingress
_updated_chart_config=$(printf "%s" "$_chart_config" | jq "(.config.ingress?.main.tls[]? | select(.scaleCert==$_active_cert_id) | .scaleCert ) |= $_cert_id | .config.ingress ")
_update_chart_result="$(_post "{\"values\" : { \"ingress\" : $_updated_chart_config } }" "$_api_url/chart/release/id/$_release_name" "" "PUT" "application/json")"
_debug3 _update_chart_result "$_update_chart_result"
done
else
_info "Tool 'jq' does not exists, skip chart release checking"
fi
else
_info "Checking if any app is using the same certificate as TrueNAS web UI. Tool 'jq' is required"
if _exists jq; then
_info "Query all apps"
_app_list=$(_get "$_api_url/app")
_app_id_list=$(printf "%s" "$_app_list" | jq -r '.[].name')
_app_length=$(echo "$_app_id_list" | wc -l)
_info "Found $_app_length apps"
_info "Checking for each app if an update is needed"
for i in $(seq 1 "$_app_length"); do
_app_id=$(echo "$_app_id_list" | sed -n "${i}p")
_app_config="$(_post "\"$_app_id\"" "$_api_url/app/config" "" "POST" "application/json")"
# Check if the app use the same certificate TrueNAS web UI
_app_active_cert_config=$(echo "$_app_config" | tr -d '\000-\037' | _json_decode | jq -r ".ix_certificates[\"$_active_cert_id\"]")
if [ "$_app_active_cert_config" != "null" ]; then
_info "Updating certificate from $_active_cert_id to $_cert_id for app: $_app_id"
#Replace the old certificate id with the new one in path
_update_app_result="$(_post "{\"values\" : { \"network\": { \"certificate_id\": $_cert_id } } }" "$_api_url/app/id/$_app_id" "" "PUT" "application/json")"
_debug3 _update_app_result "$_update_app_result"
fi
done
else
_info "Tool 'jq' does not exists, skip app checking"
fi
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"
@@ -161,50 +254,6 @@ truenas_deploy() {
_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 "Checking if any chart release Apps is using the same certificate as TrueNAS web UI. Tool 'jq' is required"
if _exists jq; then
_info "Query all chart release"
_release_list=$(_get "$_api_url/chart/release")
_related_name_list=$(printf "%s" "$_release_list" | jq -r "[.[] | {name,certId: .config.ingress?.main.tls[]?.scaleCert} | select(.certId==$_active_cert_id) | .name ] | unique")
_release_length=$(printf "%s" "$_related_name_list" | jq -r "length")
_info "Found $_release_length related chart release in list: $_related_name_list"
for i in $(seq 0 $((_release_length - 1))); do
_release_name=$(echo "$_related_name_list" | jq -r ".[$i]")
_info "Updating certificate from $_active_cert_id to $_cert_id for chart release: $_release_name"
#Read the chart release configuration
_chart_config=$(printf "%s" "$_release_list" | jq -r ".[] | select(.name==\"$_release_name\")")
#Replace the old certificate id with the new one in path .config.ingress.main.tls[].scaleCert. Then update .config.ingress
_updated_chart_config=$(printf "%s" "$_chart_config" | jq "(.config.ingress?.main.tls[]? | select(.scaleCert==$_active_cert_id) | .scaleCert ) |= $_cert_id | .config.ingress ")
_update_chart_result="$(_post "{\"values\" : { \"ingress\" : $_updated_chart_config } }" "$_api_url/chart/release/id/$_release_name" "" "PUT" "application/json")"
_debug3 _update_chart_result "$_update_chart_result"
done
else
_info "Tool 'jq' does not exists, skip chart release checking"
fi
_info "Deleting old certificate"
_delete_result="$(_post "" "$_api_url/certificate/id/$_active_cert_id" "" "DELETE" "application/json")"
+294
View File
@@ -0,0 +1,294 @@
#!/usr/bin/env sh
# TrueNAS deploy script for SCALE/CORE using websocket
# It is recommend to use a wildcard certificate
#
# Websocket Documentation: https://www.truenas.com/docs/api/scale_websocket_api.html
#
# Tested with TrueNAS Scale - Electric Eel 24.10
# Changes certificate in the following services:
# - Web UI
# - FTP
# - iX Apps
#
# The following environment variables must be set:
# ------------------------------------------------
#
# # API KEY
# # Use the folowing URL to create a new API token: <TRUENAS_HOSTNAME OR IP>/ui/apikeys
# export DEPLOY_TRUENAS_APIKEY="<API_KEY_GENERATED_IN_THE_WEB_UI"
#
### Private functions
# Call websocket method
# Usage:
# _ws_response=$(_ws_call "math.dummycalc" "'{"x": 4, "y": 5}'")
# _info "$_ws_response"
#
# Output:
# {"z": 9}
#
# Arguments:
# $@ - midclt arguments for call
#
# Returns:
# JSON/JOBID
_ws_call() {
_debug "_ws_call arg1" "$1"
_debug "_ws_call arg2" "$2"
_debug "_ws_call arg3" "$3"
if [ $# -eq 3 ]; then
_ws_response=$(midclt -K "$DEPLOY_TRUENAS_APIKEY" call "$1" "$2" "$3")
fi
if [ $# -eq 2 ]; then
_ws_response=$(midclt -K "$DEPLOY_TRUENAS_APIKEY" call "$1" "$2")
fi
if [ $# -eq 1 ]; then
_ws_response=$(midclt -K "$DEPLOY_TRUENAS_APIKEY" call "$1")
fi
_debug "_ws_response" "$_ws_response"
printf "%s" "$_ws_response"
return 0
}
# Check argument is a number
# Usage:
#
# Output:
# n/a
#
# Arguments:
# $1 - Anything
#
# Returns:
# 0: true
# 1: false
_ws_check_jobid() {
case "$1" in
[0-9]*)
return 0
;;
esac
return 1
}
# Wait for job to finish and return result as JSON
# Usage:
# _ws_result=$(_ws_get_job_result "$_ws_jobid")
# _new_certid=$(printf "%s" "$_ws_result" | jq -r '."id"')
#
# Output:
# JSON result of the job
#
# Arguments:
# $1 - JobID
#
# Returns:
# n/a
_ws_get_job_result() {
while true; do
sleep 2
_ws_response=$(_ws_call "core.get_jobs" "[[\"id\", \"=\", $1]]")
if [ "$(printf "%s" "$_ws_response" | jq -r '.[]."state"')" != "RUNNING" ]; then
_ws_result="$(printf "%s" "$_ws_response" | jq '.[]."result"')"
_debug "_ws_result" "$_ws_result"
printf "%s" "$_ws_result"
_ws_error="$(printf "%s" "$_ws_response" | jq '.[]."error"')"
if [ "$_ws_error" != "null" ]; then
_err "Job $1 failed:"
_err "$_ws_error"
return 7
fi
break
fi
done
return 0
}
########################
### Public functions ###
########################
# truenas_ws_deploy
#
# Deploy new certificate to TrueNAS services
#
# Arguments
# 1: Domain
# 2: Key-File
# 3: Certificate-File
# 4: CA-File
# 5: FullChain-File
# Returns:
# 0: Success
# 1: Missing API Key
# 2: TrueNAS not ready
# 3: Not a JobID
# 4: FTP cert error
# 5: WebUI cert error
# 6: Job error
# 7: WS call error
# 10: No CORE or SCALE detected
#
truenas_ws_deploy() {
_domain="$1"
_file_key="$2"
_file_cert="$3"
_file_ca="$4"
_file_fullchain="$5"
_debug _domain "$_domain"
_debug _file_key "$_file_key"
_debug _file_cert "$_file_cert"
_debug _file_ca "$_file_ca"
_debug _file_fullchain "$_file_fullchain"
########## Environment check
_info "Checking environment variables..."
_getdeployconf DEPLOY_TRUENAS_APIKEY
# Check API Key
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"
_info "Environment variables: OK"
########## Health check
_info "Checking TrueNAS health..."
_ws_response=$(_ws_call "system.ready" | tr '[:lower:]' '[:upper:]')
_ws_ret=$?
if [ $_ws_ret -gt 0 ]; then
_err "Error calling system.ready:"
_err "$_ws_response"
return $_ws_ret
fi
if [ "$_ws_response" != "TRUE" ]; then
_err "TrueNAS is not ready."
_err "Please check environment variables DEPLOY_TRUENAS_APIKEY, DEPLOY_TRUENAS_HOSTNAME and DEPLOY_TRUENAS_PROTOCOL."
_err "Verify API key."
return 2
fi
_savedeployconf DEPLOY_TRUENAS_APIKEY "$DEPLOY_TRUENAS_APIKEY"
_info "TrueNAS health: OK"
########## System info
_info "Gather system info..."
_ws_response=$(_ws_call "system.info")
_truenas_system=$(printf "%s" "$_ws_response" | jq -r '."version"' | cut -d '-' -f 2 | tr '[:lower:]' '[:upper:]')
_truenas_version=$(printf "%s" "$_ws_response" | jq -r '."version"' | cut -d '-' -f 3)
_info "TrueNAS system: $_truenas_system"
_info "TrueNAS version: $_truenas_version"
if [ "$_truenas_system" != "SCALE" ] && [ "$_truenas_system" != "CORE" ]; then
_err "Cannot gather TrueNAS system. Nor CORE oder SCALE detected."
return 10
fi
########## Gather current certificate
_info "Gather current WebUI certificate..."
_ws_response="$(_ws_call "system.general.config")"
_ui_certificate_id=$(printf "%s" "$_ws_response" | jq -r '."ui_certificate"."id"')
_ui_certificate_name=$(printf "%s" "$_ws_response" | jq -r '."ui_certificate"."name"')
_info "Current WebUI certificate ID: $_ui_certificate_id"
_info "Current WebUI certificate name: $_ui_certificate_name"
########## Upload new certificate
_info "Upload new certificate..."
_certname="acme_$(_utc_date | tr -d '\-\:' | tr ' ' '_')"
_info "New WebUI certificate name: $_certname"
_debug _certname "$_certname"
_ws_jobid=$(_ws_call "certificate.create" "{\"name\": \"${_certname}\", \"create_type\": \"CERTIFICATE_CREATE_IMPORTED\", \"certificate\": \"$(_json_encode <"$_file_fullchain")\", \"privatekey\": \"$(_json_encode <"$_file_key")\", \"passphrase\": \"\"}")
_debug "_ws_jobid" "$_ws_jobid"
if ! _ws_check_jobid "$_ws_jobid"; then
_err "No JobID returned from websocket method."
return 3
fi
_ws_result=$(_ws_get_job_result "$_ws_jobid")
_ws_ret=$?
if [ $_ws_ret -gt 0 ]; then
return $_ws_ret
fi
_debug "_ws_result" "$_ws_result"
_new_certid=$(printf "%s" "$_ws_result" | jq -r '."id"')
_info "New certificate ID: $_new_certid"
########## FTP
_info "Replace FTP certificate..."
_ws_response=$(_ws_call "ftp.update" "{\"ssltls_certificate\": $_new_certid}")
_ftp_certid=$(printf "%s" "$_ws_response" | jq -r '."ssltls_certificate"')
if [ "$_ftp_certid" != "$_new_certid" ]; then
_err "Cannot set FTP certificate."
_debug "_ws_response" "$_ws_response"
return 4
fi
########## ix Apps (SCALE only)
if [ "$_truenas_system" = "SCALE" ]; then
_info "Replace app certificates..."
_ws_response=$(_ws_call "app.query")
for _app_name in $(printf "%s" "$_ws_response" | jq -r '.[]."name"'); do
_info "Checking app $_app_name..."
_ws_response=$(_ws_call "app.config" "$_app_name")
if [ "$(printf "%s" "$_ws_response" | jq -r '."network" | has("certificate_id")')" = "true" ]; then
_info "App has certificate option, setup new certificate..."
_info "App will be redeployed after updating the certificate."
_ws_jobid=$(_ws_call "app.update" "$_app_name" "{\"values\": {\"network\": {\"certificate_id\": $_new_certid}}}")
_debug "_ws_jobid" "$_ws_jobid"
if ! _ws_check_jobid "$_ws_jobid"; then
_err "No JobID returned from websocket method."
return 3
fi
_ws_result=$(_ws_get_job_result "$_ws_jobid")
_ws_ret=$?
if [ $_ws_ret -gt 0 ]; then
return $_ws_ret
fi
_debug "_ws_result" "$_ws_result"
_info "App certificate replaced."
else
_info "App has no certificate option, skipping..."
fi
done
fi
########## WebUI
_info "Replace WebUI certificate..."
_ws_response=$(_ws_call "system.general.update" "{\"ui_certificate\": $_new_certid}")
_changed_certid=$(printf "%s" "$_ws_response" | jq -r '."ui_certificate"."id"')
if [ "$_changed_certid" != "$_new_certid" ]; then
_err "WebUI certificate change error.."
return 5
else
_info "WebUI certificate replaced."
fi
_info "Restarting WebUI..."
_ws_response=$(_ws_call "system.general.ui_restart")
_info "Waiting for UI restart..."
sleep 6
########## Certificates
_info "Deleting old certificate..."
_ws_jobid=$(_ws_call "certificate.delete" "$_ui_certificate_id")
if ! _ws_check_jobid "$_ws_jobid"; then
_err "No JobID returned from websocket method."
return 3
fi
_ws_result=$(_ws_get_job_result "$_ws_jobid")
_ws_ret=$?
if [ $_ws_ret -gt 0 ]; then
return $_ws_ret
fi
_info "Have a nice day...bye!"
}
+65 -26
View File
@@ -30,7 +30,9 @@
# Keystore password (built into Unifi Controller, not a user-set password):
#DEPLOY_UNIFI_KEYPASS="aircontrolenterprise"
# Command to restart Unifi Controller:
#DEPLOY_UNIFI_RELOAD="service unifi restart"
# DEPLOY_UNIFI_RELOAD="systemctl restart unifi"
# System Properties file location for controller
#DEPLOY_UNIFI_SYSTEM_PROPERTIES="/usr/lib/unifi/data/system.properties"
#
# Settings for Unifi Cloud Key Gen1 (nginx admin pages):
# Directory where cloudkey.crt and cloudkey.key live:
@@ -43,7 +45,7 @@
# Directory where unifi-core.crt and unifi-core.key live:
#DEPLOY_UNIFI_CORE_CONFIG="/data/unifi-core/config/"
# Command to restart unifi-core:
#DEPLOY_UNIFI_RELOAD="systemctl restart unifi-core"
# DEPLOY_UNIFI_OS_RELOAD="systemctl restart unifi-core"
#
# At least one of DEPLOY_UNIFI_KEYSTORE, DEPLOY_UNIFI_CLOUDKEY_CERTDIR,
# or DEPLOY_UNIFI_CORE_CONFIG must exist to receive the deployed certs.
@@ -69,12 +71,16 @@ unifi_deploy() {
_getdeployconf DEPLOY_UNIFI_CLOUDKEY_CERTDIR
_getdeployconf DEPLOY_UNIFI_CORE_CONFIG
_getdeployconf DEPLOY_UNIFI_RELOAD
_getdeployconf DEPLOY_UNIFI_SYSTEM_PROPERTIES
_getdeployconf DEPLOY_UNIFI_OS_RELOAD
_debug2 DEPLOY_UNIFI_KEYSTORE "$DEPLOY_UNIFI_KEYSTORE"
_debug2 DEPLOY_UNIFI_KEYPASS "$DEPLOY_UNIFI_KEYPASS"
_debug2 DEPLOY_UNIFI_CLOUDKEY_CERTDIR "$DEPLOY_UNIFI_CLOUDKEY_CERTDIR"
_debug2 DEPLOY_UNIFI_CORE_CONFIG "$DEPLOY_UNIFI_CORE_CONFIG"
_debug2 DEPLOY_UNIFI_RELOAD "$DEPLOY_UNIFI_RELOAD"
_debug2 DEPLOY_UNIFI_OS_RELOAD "$DEPLOY_UNIFI_OS_RELOAD"
_debug2 DEPLOY_UNIFI_SYSTEM_PROPERTIES "$DEPLOY_UNIFI_SYSTEM_PROPERTIES"
# Space-separated list of environments detected and installed:
_services_updated=""
@@ -135,33 +141,53 @@ unifi_deploy() {
cp -f "$_import_pkcs12" "$_unifi_keystore"
fi
# correct file ownership according to the directory, the keystore is placed in
_unifi_keystore_dir=$(dirname "${_unifi_keystore}")
_unifi_keystore_dir_owner=$(find "${_unifi_keystore_dir}" -maxdepth 0 -printf '%u\n')
_unifi_keystore_owner=$(find "${_unifi_keystore}" -maxdepth 0 -printf '%u\n')
if ! [ "${_unifi_keystore_owner}" = "${_unifi_keystore_dir_owner}" ]; then
_debug "Changing keystore owner to ${_unifi_keystore_dir_owner}"
chown "$_unifi_keystore_dir_owner" "${_unifi_keystore}" >/dev/null 2>&1 # fail quietly if we're not running as root
fi
# Update unifi service for certificate cipher compatibility
_unifi_system_properties="${DEPLOY_UNIFI_SYSTEM_PROPERTIES:-/usr/lib/unifi/data/system.properties}"
if ${ACME_OPENSSL_BIN:-openssl} pkcs12 \
-in "$_import_pkcs12" \
-password pass:aircontrolenterprise \
-nokeys | ${ACME_OPENSSL_BIN:-openssl} x509 -text \
-noout | grep -i "signature" | grep -iq ecdsa >/dev/null 2>&1; then
cp -f /usr/lib/unifi/data/system.properties /usr/lib/unifi/data/system.properties_original
_info "Updating system configuration for cipher compatibility."
_info "Saved original system config to /usr/lib/unifi/data/system.properties_original"
sed -i '/unifi\.https\.ciphers/d' /usr/lib/unifi/data/system.properties
echo "unifi.https.ciphers=ECDHE-ECDSA-AES256-GCM-SHA384,ECDHE-RSA-AES128-GCM-SHA256" >>/usr/lib/unifi/data/system.properties
sed -i '/unifi\.https\.sslEnabledProtocols/d' /usr/lib/unifi/data/system.properties
echo "unifi.https.sslEnabledProtocols=TLSv1.3,TLSv1.2" >>/usr/lib/unifi/data/system.properties
_info "System configuration updated."
if [ -f "$(dirname "${DEPLOY_UNIFI_KEYSTORE}")/system.properties" ]; then
_unifi_system_properties="$(dirname "${DEPLOY_UNIFI_KEYSTORE}")/system.properties"
else
_unifi_system_properties="/usr/lib/unifi/data/system.properties"
fi
if [ -f "${_unifi_system_properties}" ]; then
cp -f "${_unifi_system_properties}" "${_unifi_system_properties}"_original
_info "Updating system configuration for cipher compatibility."
_info "Saved original system config to ${_unifi_system_properties}_original"
sed -i '/unifi\.https\.ciphers/d' "${_unifi_system_properties}"
echo "unifi.https.ciphers=ECDHE-ECDSA-AES256-GCM-SHA384,ECDHE-RSA-AES128-GCM-SHA256" >>"${_unifi_system_properties}"
sed -i '/unifi\.https\.sslEnabledProtocols/d' "${_unifi_system_properties}"
echo "unifi.https.sslEnabledProtocols=TLSv1.3,TLSv1.2" >>"${_unifi_system_properties}"
_info "System configuration updated."
fi
fi
rm "$_import_pkcs12"
# Restarting unifi-core will bring up unifi, doing it out of order results in
# a certificate error, and breaks wifiman.
# Restart if we aren't doing unifi-core, otherwise stop for later restart.
if systemctl -q is-active unifi; then
if [ ! -f "${DEPLOY_UNIFI_CORE_CONFIG:-/data/unifi-core/config}/unifi-core.key" ]; then
_reload_cmd="${_reload_cmd:+$_reload_cmd && }systemctl restart unifi"
else
_reload_cmd="${_reload_cmd:+$_reload_cmd && }systemctl stop unifi"
fi
# Restart if we aren't doing Unifi OS (e.g. unifi-core service), otherwise stop for later restart.
_unifi_reload="${DEPLOY_UNIFI_RELOAD:-systemctl restart unifi}"
if [ ! -f "${DEPLOY_UNIFI_CORE_CONFIG:-/data/unifi-core/config}/unifi-core.key" ]; then
_reload_cmd="${_reload_cmd:+$_reload_cmd && }$_unifi_reload"
else
_info "Stopping Unifi Controller for later restart."
_unifi_stop=$(echo "${_unifi_reload}" | sed -e 's/restart/stop/')
$_unifi_stop
_reload_cmd="${_reload_cmd:+$_reload_cmd && }$_unifi_reload"
_info "Unifi Controller stopped."
fi
_services_updated="${_services_updated} unifi"
_info "Install Unifi Controller certificate success!"
@@ -181,13 +207,24 @@ unifi_deploy() {
return 1
fi
# Cloud Key expects to load the keystore from /etc/ssl/private/unifi.keystore.jks.
# Normally /usr/lib/unifi/data/keystore is a symlink there (so the keystore was
# updated above), but if not, we don't know how to handle this installation:
if ! cmp -s "$_unifi_keystore" "${_cloudkey_certdir}/unifi.keystore.jks"; then
_err "Unsupported Cloud Key configuration: keystore not found at '${_cloudkey_certdir}/unifi.keystore.jks'"
return 1
# It appears that unifi won't start if this is a symlink, so we'll copy it instead.
# if ! cmp -s "$_unifi_keystore" "${_cloudkey_certdir}/unifi.keystore.jks"; then
# _err "Unsupported Cloud Key configuration: keystore not found at '${_cloudkey_certdir}/unifi.keystore.jks'"
# return 1
# fi
_info "Updating ${_cloudkey_certdir}/unifi.keystore.jks"
if [ -e "${_cloudkey_certdir}/unifi.keystore.jks" ]; then
if [ -L "${_cloudkey_certdir}/unifi.keystore.jks" ]; then
rm -f "${_cloudkey_certdir}/unifi.keystore.jks"
else
mv "${_cloudkey_certdir}/unifi.keystore.jks" "${_cloudkey_certdir}/unifi.keystore.jks_original"
fi
fi
cp "${_unifi_keystore}" "${_cloudkey_certdir}/unifi.keystore.jks"
cat "$_cfullchain" >"${_cloudkey_certdir}/cloudkey.crt"
cat "$_ckey" >"${_cloudkey_certdir}/cloudkey.key"
(cd "$_cloudkey_certdir" && tar -cf cert.tar cloudkey.crt cloudkey.key unifi.keystore.jks)
@@ -215,14 +252,14 @@ unifi_deploy() {
# Save the existing certs in case something goes wrong.
cp -f "${_unifi_core_config}"/unifi-core.crt "${_unifi_core_config}"/unifi-core_original.crt
cp -f "${_unifi_core_config}"/unifi-core.key "${_unifi_core_config}"/unifi-core_original.key
_info "Previous certificate and key saved to ${_unifi_core_config}/unifi-core_original.crt/key."
_info "Previous certificate and key saved to ${_unifi_core_config}/unifi-core_original.crt.key."
cat "$_cfullchain" >"${_unifi_core_config}/unifi-core.crt"
cat "$_ckey" >"${_unifi_core_config}/unifi-core.key"
if systemctl -q is-active unifi-core; then
_reload_cmd="${_reload_cmd:+$_reload_cmd && }systemctl restart unifi-core"
fi
_unifi_os_reload="${DEPLOY_UNIFI_OS_RELOAD:-systemctl restart unifi-core}"
_reload_cmd="${_reload_cmd:+$_reload_cmd && }$_unifi_os_reload"
_info "Install UnifiOS certificate success!"
_services_updated="${_services_updated} unifi-core"
elif [ "$DEPLOY_UNIFI_CORE_CONFIG" ]; then
@@ -261,6 +298,8 @@ unifi_deploy() {
_savedeployconf DEPLOY_UNIFI_CLOUDKEY_CERTDIR "$DEPLOY_UNIFI_CLOUDKEY_CERTDIR"
_savedeployconf DEPLOY_UNIFI_CORE_CONFIG "$DEPLOY_UNIFI_CORE_CONFIG"
_savedeployconf DEPLOY_UNIFI_RELOAD "$DEPLOY_UNIFI_RELOAD"
_savedeployconf DEPLOY_UNIFI_OS_RELOAD "$DEPLOY_UNIFI_OS_RELOAD"
_savedeployconf DEPLOY_UNIFI_SYSTEM_PROPERTIES "$DEPLOY_UNIFI_SYSTEM_PROPERTIES"
return 0
}
+84 -14
View File
@@ -80,10 +80,15 @@ vault_deploy() {
if [ -n "$VAULT_RENEW_TOKEN" ]; then
URL="$VAULT_ADDR/v1/auth/token/renew-self"
_info "Renew the Vault token to default TTL"
if ! _post "" "$URL" >/dev/null; then
_response=$(_post "" "$URL")
if [ "$?" != "0" ]; then
_err "Failed to renew the Vault token"
return 1
fi
if echo "$_response" | grep -q '"errors":\['; then
_err "Failed to renew the Vault token: $_response"
return 1
fi
fi
URL="$VAULT_ADDR/v1/$VAULT_PREFIX/$_cdomain"
@@ -91,29 +96,85 @@ vault_deploy() {
if [ -n "$VAULT_FABIO_MODE" ]; then
_info "Writing certificate and key to $URL in Fabio mode"
if [ -n "$VAULT_KV_V2" ]; then
_post "{ \"data\": {\"cert\": \"$_cfullchain\", \"key\": \"$_ckey\"} }" "$URL" >/dev/null || return 1
_response=$(_post "{ \"data\": {\"cert\": \"$_cfullchain\", \"key\": \"$_ckey\"} }" "$URL")
if [ "$?" != "0" ]; then return 1; fi
if echo "$_response" | grep -q '"errors":\['; then
_err "Vault error: $_response"
return 1
fi
else
_post "{\"cert\": \"$_cfullchain\", \"key\": \"$_ckey\"}" "$URL" >/dev/null || return 1
_response=$(_post "{\"cert\": \"$_cfullchain\", \"key\": \"$_ckey\"}" "$URL")
if [ "$?" != "0" ]; then return 1; fi
if echo "$_response" | grep -q '"errors":\['; then
_err "Vault error: $_response"
return 1
fi
fi
else
if [ -n "$VAULT_KV_V2" ]; then
_info "Writing certificate to $URL/cert.pem"
_post "{\"data\": {\"value\": \"$_ccert\"}}" "$URL/cert.pem" >/dev/null || return 1
_response=$(_post "{\"data\": {\"value\": \"$_ccert\"}}" "$URL/cert.pem")
if [ "$?" != "0" ]; then return 1; fi
if echo "$_response" | grep -q '"errors":\['; then
_err "Vault error writing cert.pem: $_response"
return 1
fi
_info "Writing key to $URL/cert.key"
_post "{\"data\": {\"value\": \"$_ckey\"}}" "$URL/cert.key" >/dev/null || return 1
_response=$(_post "{\"data\": {\"value\": \"$_ckey\"}}" "$URL/cert.key")
if [ "$?" != "0" ]; then return 1; fi
if echo "$_response" | grep -q '"errors":\['; then
_err "Vault error writing cert.key: $_response"
return 1
fi
_info "Writing CA certificate to $URL/ca.pem"
_post "{\"data\": {\"value\": \"$_cca\"}}" "$URL/ca.pem" >/dev/null || return 1
_response=$(_post "{\"data\": {\"value\": \"$_cca\"}}" "$URL/ca.pem")
if [ "$?" != "0" ]; then return 1; fi
if echo "$_response" | grep -q '"errors":\['; then
_err "Vault error writing ca.pem: $_response"
return 1
fi
_info "Writing full-chain certificate to $URL/fullchain.pem"
_post "{\"data\": {\"value\": \"$_cfullchain\"}}" "$URL/fullchain.pem" >/dev/null || return 1
_response=$(_post "{\"data\": {\"value\": \"$_cfullchain\"}}" "$URL/fullchain.pem")
if [ "$?" != "0" ]; then return 1; fi
if echo "$_response" | grep -q '"errors":\['; then
_err "Vault error writing fullchain.pem: $_response"
return 1
fi
else
_info "Writing certificate to $URL/cert.pem"
_post "{\"value\": \"$_ccert\"}" "$URL/cert.pem" >/dev/null || return 1
_response=$(_post "{\"value\": \"$_ccert\"}" "$URL/cert.pem")
if [ "$?" != "0" ]; then return 1; fi
if echo "$_response" | grep -q '"errors":\['; then
_err "Vault error writing cert.pem: $_response"
return 1
fi
_info "Writing key to $URL/cert.key"
_post "{\"value\": \"$_ckey\"}" "$URL/cert.key" >/dev/null || return 1
_response=$(_post "{\"value\": \"$_ckey\"}" "$URL/cert.key")
if [ "$?" != "0" ]; then return 1; fi
if echo "$_response" | grep -q '"errors":\['; then
_err "Vault error writing cert.key: $_response"
return 1
fi
_info "Writing CA certificate to $URL/ca.pem"
_post "{\"value\": \"$_cca\"}" "$URL/ca.pem" >/dev/null || return 1
_response=$(_post "{\"value\": \"$_cca\"}" "$URL/ca.pem")
if [ "$?" != "0" ]; then return 1; fi
if echo "$_response" | grep -q '"errors":\['; then
_err "Vault error writing ca.pem: $_response"
return 1
fi
_info "Writing full-chain certificate to $URL/fullchain.pem"
_post "{\"value\": \"$_cfullchain\"}" "$URL/fullchain.pem" >/dev/null || return 1
_response=$(_post "{\"value\": \"$_cfullchain\"}" "$URL/fullchain.pem")
if [ "$?" != "0" ]; then return 1; fi
if echo "$_response" | grep -q '"errors":\['; then
_err "Vault error writing fullchain.pem: $_response"
return 1
fi
fi
# To make it compatible with the wrong ca path `chain.pem` which was used in former versions
@@ -121,11 +182,20 @@ vault_deploy() {
_err "The CA certificate has moved from chain.pem to ca.pem, if you don't depend on chain.pem anymore, you can delete it to avoid this warning"
_info "Updating CA certificate to $URL/chain.pem for backward compatibility"
if [ -n "$VAULT_KV_V2" ]; then
_post "{\"data\": {\"value\": \"$_cca\"}}" "$URL/chain.pem" >/dev/null || return 1
_response=$(_post "{\"data\": {\"value\": \"$_cca\"}}" "$URL/chain.pem")
if [ "$?" != "0" ]; then return 1; fi
if echo "$_response" | grep -q '"errors":\['; then
_err "Vault error writing chain.pem: $_response"
return 1
fi
else
_post "{\"value\": \"$_cca\"}" "$URL/chain.pem" >/dev/null || return 1
_response=$(_post "{\"value\": \"$_cca\"}" "$URL/chain.pem")
if [ "$?" != "0" ]; then return 1; fi
if echo "$_response" | grep -q '"errors":\['; then
_err "Vault error writing chain.pem: $_response"
return 1
fi
fi
fi
fi
}
+1 -1
View File
@@ -106,5 +106,5 @@ vsftpd_deploy() {
fi
return 1
fi
return 0
}
+3 -3
View File
@@ -83,10 +83,10 @@ _get_root() {
return 1
fi
i=2
i=1
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
_debug "h" "$h"
if [ -z "$h" ]; then
#not valid
@@ -94,7 +94,7 @@ _get_root() {
fi
if _contains "$response" "\"$h\"" >/dev/null; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain=$h
return 0
fi
+2 -2
View File
@@ -95,7 +95,7 @@ _get_root() {
if _ad_rest GET "domain/"; then
response="$(echo "$response" | tr -d "\n" | sed 's/{/\n&/g')"
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
_debug h "$h"
if [ -z "$h" ]; then
#not valid
@@ -106,7 +106,7 @@ _get_root() {
if [ "$hostedzone" ]; then
_domain_id=$(printf "%s\n" "$hostedzone" | _egrep_o "\"id\":\s*[0-9]+" | _head_n 1 | cut -d : -f 2 | tr -d \ )
if [ "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain=$h
return 0
fi
+75 -64
View File
@@ -9,25 +9,19 @@ Options:
Ali_Secret API Secret
'
Ali_API="https://alidns.aliyuncs.com/"
# NOTICE:
# This file is referenced by Alibaba Cloud Services deploy hooks
# https://github.com/acmesh-official/acme.sh/pull/5205#issuecomment-2357867276
# Be careful when modifying this file, especially when making breaking changes for common functions
Ali_DNS_API="https://alidns.aliyuncs.com/"
#Usage: dns_ali_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_ali_add() {
fulldomain=$1
txtvalue=$2
Ali_Key="${Ali_Key:-$(_readaccountconf_mutable Ali_Key)}"
Ali_Secret="${Ali_Secret:-$(_readaccountconf_mutable Ali_Secret)}"
if [ -z "$Ali_Key" ] || [ -z "$Ali_Secret" ]; then
Ali_Key=""
Ali_Secret=""
_err "You don't specify aliyun api key and secret yet."
return 1
fi
#save the api key and secret to the account conf file.
_saveaccountconf_mutable Ali_Key "$Ali_Key"
_saveaccountconf_mutable Ali_Secret "$Ali_Secret"
_prepare_ali_credentials || return 1
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
@@ -52,14 +46,74 @@ dns_ali_rm() {
_clean
}
#################### Private functions below ##################################
#################### Alibaba Cloud common functions below ####################
_prepare_ali_credentials() {
Ali_Key="${Ali_Key:-$(_readaccountconf_mutable Ali_Key)}"
Ali_Secret="${Ali_Secret:-$(_readaccountconf_mutable Ali_Secret)}"
if [ -z "$Ali_Key" ] || [ -z "$Ali_Secret" ]; then
Ali_Key=""
Ali_Secret=""
_err "You don't specify aliyun api key and secret yet."
return 1
fi
#save the api key and secret to the account conf file.
_saveaccountconf_mutable Ali_Key "$Ali_Key"
_saveaccountconf_mutable Ali_Secret "$Ali_Secret"
}
# act ign mtd
_ali_rest() {
act="$1"
ign="$2"
mtd="${3:-GET}"
signature=$(printf "%s" "$mtd&%2F&$(printf "%s" "$query" | _url_encode upper-hex)" | _hmac "sha1" "$(printf "%s" "$Ali_Secret&" | _hex_dump | tr -d " ")" | _base64)
signature=$(printf "%s" "$signature" | _url_encode upper-hex)
url="$endpoint?Signature=$signature"
if [ "$mtd" = "GET" ]; then
url="$url&$query"
response="$(_get "$url")"
else
response="$(_post "$query" "$url" "" "$mtd" "application/x-www-form-urlencoded")"
fi
_ret="$?"
_debug2 response "$response"
if [ "$_ret" != "0" ]; then
_err "Error <$act>"
return 1
fi
if [ -z "$ign" ]; then
message="$(echo "$response" | _egrep_o "\"Message\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \")"
if [ "$message" ]; then
_err "$message"
return 1
fi
fi
}
_ali_nonce() {
#_head_n 1 </dev/urandom | _digest "sha256" hex | cut -c 1-31
#Not so good...
date +"%s%N" | sed 's/%N//g'
}
_timestamp() {
date -u +"%Y-%m-%dT%H%%3A%M%%3A%SZ"
}
#################### Private functions below ####################
_get_root() {
domain=$1
i=2
i=1
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
if [ -z "$h" ]; then
#not valid
return 1
@@ -71,7 +125,7 @@ _get_root() {
fi
if _contains "$response" "PageNumber"; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_debug _sub_domain "$_sub_domain"
_domain="$h"
_debug _domain "$_domain"
@@ -83,52 +137,10 @@ _get_root() {
return 1
}
_ali_rest() {
signature=$(printf "%s" "GET&%2F&$(_ali_urlencode "$query")" | _hmac "sha1" "$(printf "%s" "$Ali_Secret&" | _hex_dump | tr -d " ")" | _base64)
signature=$(_ali_urlencode "$signature")
url="$Ali_API?$query&Signature=$signature"
if ! response="$(_get "$url")"; then
_err "Error <$1>"
return 1
fi
_debug2 response "$response"
if [ -z "$2" ]; then
message="$(echo "$response" | _egrep_o "\"Message\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \")"
if [ "$message" ]; then
_err "$message"
return 1
fi
fi
}
_ali_urlencode() {
_str="$1"
_str_len=${#_str}
_u_i=1
while [ "$_u_i" -le "$_str_len" ]; do
_str_c="$(printf "%s" "$_str" | cut -c "$_u_i")"
case $_str_c in [a-zA-Z0-9.~_-])
printf "%s" "$_str_c"
;;
*)
printf "%%%02X" "'$_str_c"
;;
esac
_u_i="$(_math "$_u_i" + 1)"
done
}
_ali_nonce() {
#_head_n 1 </dev/urandom | _digest "sha256" hex | cut -c 1-31
#Not so good...
date +"%s%N" | sed 's/%N//g'
}
_check_exist_query() {
_qdomain="$1"
_qsubdomain="$2"
endpoint=$Ali_DNS_API
query=''
query=$query'AccessKeyId='$Ali_Key
query=$query'&Action=DescribeDomainRecords'
@@ -144,6 +156,7 @@ _check_exist_query() {
}
_add_record_query() {
endpoint=$Ali_DNS_API
query=''
query=$query'AccessKeyId='$Ali_Key
query=$query'&Action=AddDomainRecord'
@@ -160,6 +173,7 @@ _add_record_query() {
}
_delete_record_query() {
endpoint=$Ali_DNS_API
query=''
query=$query'AccessKeyId='$Ali_Key
query=$query'&Action=DeleteDomainRecord'
@@ -173,6 +187,7 @@ _delete_record_query() {
}
_describe_records_query() {
endpoint=$Ali_DNS_API
query=''
query=$query'AccessKeyId='$Ali_Key
query=$query'&Action=DescribeDomainRecords'
@@ -203,7 +218,3 @@ _clean() {
fi
}
_timestamp() {
date -u +"%Y-%m-%dT%H%%3A%M%%3A%SZ"
}
+8 -7
View File
@@ -1,11 +1,12 @@
#!/usr/bin/env sh
# Alviy domain api
#
# Get API key and secret from https://cloud.alviy.com/token
#
# Alviy_token="some-secret-key"
#
# Ex.: acme.sh --issue --staging --dns dns_alviy -d "*.s.example.com" -d "s.example.com"
# shellcheck disable=SC2034
dns_alviy_info='Alviy.com
Site: Alviy.com
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_alviy
Options:
Alviy_token API token. Get it from the https://cloud.alviy.com/token
Issues: github.com/acmesh-official/acme.sh/issues/5115
'
Alviy_Api="https://cloud.alviy.com/api/v1"
+2 -2
View File
@@ -131,7 +131,7 @@ _get_root() {
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
_debug h "$h"
if [ -z "$h" ]; then
#not valid
@@ -140,7 +140,7 @@ _get_root() {
_anx_rest GET "zone.json/${h}"
if _contains "$response" "\"name\":\"$h\""; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain=$h
return 0
fi
+2 -2
View File
@@ -107,7 +107,7 @@ _get_root() {
i=2
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
_debug h "$h"
if [ -z "$h" ]; then
#not valid
@@ -120,7 +120,7 @@ _get_root() {
if _contains "$response" "\"domain\":\"$h\""; then
_domain_id=$(echo "$response" | cut -d : -f 3 | cut -d , -f 1 | tr -d \")
if [ "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain=$h
return 0
fi
+2 -2
View File
@@ -117,7 +117,7 @@ _get_root() {
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
_debug h "$h"
if [ -z "$h" ]; then
#not valid
@@ -132,7 +132,7 @@ _get_root() {
_domain_id=$(echo "$response" | _normalizeJson | tr -d "{}" | tr "," "\n" | grep "\"id\": *\"" | cut -d : -f 2 | tr -d \" | _head_n 1 | tr -d " ")
_debug _domain_id "$_domain_id"
if [ "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain=$h
return 0
fi
+2 -2
View File
@@ -110,7 +110,7 @@ _get_autodns_zone() {
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
_debug h "$h"
if [ -z "$h" ]; then
@@ -128,7 +128,7 @@ _get_autodns_zone() {
if _contains "$autodns_response" "<summary>1</summary>" >/dev/null; then
_zone="$(echo "$autodns_response" | _egrep_o '<name>[^<]*</name>' | cut -d '>' -f 2 | cut -d '<' -f 1)"
_system_ns="$(echo "$autodns_response" | _egrep_o '<system_ns>[^<]*</system_ns>' | cut -d '>' -f 2 | cut -d '<' -f 1)"
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
return 0
fi
+2 -2
View File
@@ -158,7 +158,7 @@ _get_root() {
# iterate over names (a.b.c.d -> b.c.d -> c.d -> d)
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100 | sed 's/\./\\./g')
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100 | sed 's/\./\\./g')
_debug "Checking domain: $h"
if [ -z "$h" ]; then
_error "invalid domain"
@@ -174,7 +174,7 @@ _get_root() {
if [ "$hostedzone" ]; then
_domain_id=$(printf "%s\n" "$hostedzone" | _egrep_o "<Id>.*<.Id>" | head -n 1 | _egrep_o ">.*<" | tr -d "<>")
if [ "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain=$h
return 0
fi
+2 -2
View File
@@ -100,7 +100,7 @@ _get_root() {
fi
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
_debug h "$h"
if [ -z "$h" ]; then
# not valid
@@ -111,7 +111,7 @@ _get_root() {
_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)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain=$h
return 0
fi
+99 -67
View File
@@ -9,14 +9,17 @@ Options:
AZUREDNS_APPID App ID. App ID of the service principal
AZUREDNS_CLIENTSECRET Client Secret. Secret from creating the service principal
AZUREDNS_MANAGEDIDENTITY Use Managed Identity. Use Managed Identity assigned to a resource instead of a service principal. "true"/"false"
AZUREDNS_BEARERTOKEN Bearer Token. Used instead of service principal credentials or managed identity. Optional.
'
wiki=https://github.com/acmesh-official/acme.sh/wiki/How-to-use-Azure-DNS
######## Public functions #####################
# Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
# Used to add txt record
#
# Ref: https://docs.microsoft.com/en-us/rest/api/dns/recordsets/createorupdate
# Ref: https://learn.microsoft.com/en-us/rest/api/dns/record-sets/create-or-update?view=rest-dns-2018-05-01&tabs=HTTP
#
dns_azure_add() {
@@ -29,6 +32,7 @@ dns_azure_add() {
AZUREDNS_TENANTID=""
AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET=""
AZUREDNS_BEARERTOKEN=""
_err "You didn't specify the Azure Subscription ID"
return 1
fi
@@ -43,37 +47,45 @@ dns_azure_add() {
_saveaccountconf_mutable AZUREDNS_TENANTID ""
_saveaccountconf_mutable AZUREDNS_APPID ""
_saveaccountconf_mutable AZUREDNS_CLIENTSECRET ""
_saveaccountconf_mutable AZUREDNS_BEARERTOKEN ""
else
_info "You didn't ask to use Azure managed identity, checking service principal credentials"
_info "You didn't ask to use Azure managed identity, checking service principal credentials or provided bearer token"
AZUREDNS_TENANTID="${AZUREDNS_TENANTID:-$(_readaccountconf_mutable AZUREDNS_TENANTID)}"
AZUREDNS_APPID="${AZUREDNS_APPID:-$(_readaccountconf_mutable AZUREDNS_APPID)}"
AZUREDNS_CLIENTSECRET="${AZUREDNS_CLIENTSECRET:-$(_readaccountconf_mutable AZUREDNS_CLIENTSECRET)}"
AZUREDNS_BEARERTOKEN="${AZUREDNS_BEARERTOKEN:-$(_readaccountconf_mutable AZUREDNS_BEARERTOKEN)}"
if [ -z "$AZUREDNS_BEARERTOKEN" ]; then
if [ -z "$AZUREDNS_TENANTID" ]; then
AZUREDNS_SUBSCRIPTIONID=""
AZUREDNS_TENANTID=""
AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET=""
AZUREDNS_BEARERTOKEN=""
_err "You didn't specify the Azure Tenant 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=""
AZUREDNS_BEARERTOKEN=""
_err "You didn't specify the Azure App 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
if [ -z "$AZUREDNS_CLIENTSECRET" ]; then
AZUREDNS_SUBSCRIPTIONID=""
AZUREDNS_TENANTID=""
AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET=""
AZUREDNS_BEARERTOKEN=""
_err "You didn't specify the Azure Client Secret"
return 1
fi
else
_info "Using provided bearer token"
fi
#save account details to account conf file, don't opt in for azure manages identity check.
@@ -81,9 +93,14 @@ dns_azure_add() {
_saveaccountconf_mutable AZUREDNS_TENANTID "$AZUREDNS_TENANTID"
_saveaccountconf_mutable AZUREDNS_APPID "$AZUREDNS_APPID"
_saveaccountconf_mutable AZUREDNS_CLIENTSECRET "$AZUREDNS_CLIENTSECRET"
_saveaccountconf_mutable AZUREDNS_BEARERTOKEN "$AZUREDNS_BEARERTOKEN"
fi
accesstoken=$(_azure_getaccess_token "$AZUREDNS_MANAGEDIDENTITY" "$AZUREDNS_TENANTID" "$AZUREDNS_APPID" "$AZUREDNS_CLIENTSECRET")
if [ -z "$AZUREDNS_BEARERTOKEN" ]; then
accesstoken=$(_azure_getaccess_token "$AZUREDNS_MANAGEDIDENTITY" "$AZUREDNS_TENANTID" "$AZUREDNS_APPID" "$AZUREDNS_CLIENTSECRET")
else
accesstoken=$(echo "$AZUREDNS_BEARERTOKEN" | sed "s/Bearer //g")
fi
if ! _get_root "$fulldomain" "$AZUREDNS_SUBSCRIPTIONID" "$accesstoken"; then
_err "invalid domain"
@@ -133,7 +150,7 @@ dns_azure_add() {
# Usage: fulldomain txtvalue
# Used to remove the txt record after validation
#
# Ref: https://docs.microsoft.com/en-us/rest/api/dns/recordsets/delete
# Ref: https://learn.microsoft.com/en-us/rest/api/dns/record-sets/delete?view=rest-dns-2018-05-01&tabs=HTTP
#
dns_azure_rm() {
fulldomain=$1
@@ -145,6 +162,7 @@ dns_azure_rm() {
AZUREDNS_TENANTID=""
AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET=""
AZUREDNS_BEARERTOKEN=""
_err "You didn't specify the Azure Subscription ID "
return 1
fi
@@ -153,40 +171,51 @@ dns_azure_rm() {
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"
_info "You didn't ask to use Azure managed identity, checking service principal credentials or provided bearer token"
AZUREDNS_TENANTID="${AZUREDNS_TENANTID:-$(_readaccountconf_mutable AZUREDNS_TENANTID)}"
AZUREDNS_APPID="${AZUREDNS_APPID:-$(_readaccountconf_mutable AZUREDNS_APPID)}"
AZUREDNS_CLIENTSECRET="${AZUREDNS_CLIENTSECRET:-$(_readaccountconf_mutable AZUREDNS_CLIENTSECRET)}"
AZUREDNS_BEARERTOKEN="${AZUREDNS_BEARERTOKEN:-$(_readaccountconf_mutable AZUREDNS_BEARERTOKEN)}"
if [ -z "$AZUREDNS_BEARERTOKEN" ]; then
if [ -z "$AZUREDNS_TENANTID" ]; then
AZUREDNS_SUBSCRIPTIONID=""
AZUREDNS_TENANTID=""
AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET=""
AZUREDNS_BEARERTOKEN=""
_err "You didn't specify the Azure Tenant 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=""
AZUREDNS_BEARERTOKEN=""
_err "You didn't specify the Azure App 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
if [ -z "$AZUREDNS_CLIENTSECRET" ]; then
AZUREDNS_SUBSCRIPTIONID=""
AZUREDNS_TENANTID=""
AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET=""
AZUREDNS_BEARERTOKEN=""
_err "You didn't specify the Azure Client Secret"
return 1
fi
else
_info "Using provided bearer token"
fi
fi
accesstoken=$(_azure_getaccess_token "$AZUREDNS_MANAGEDIDENTITY" "$AZUREDNS_TENANTID" "$AZUREDNS_APPID" "$AZUREDNS_CLIENTSECRET")
if [ -z "$AZUREDNS_BEARERTOKEN" ]; then
accesstoken=$(_azure_getaccess_token "$AZUREDNS_MANAGEDIDENTITY" "$AZUREDNS_TENANTID" "$AZUREDNS_APPID" "$AZUREDNS_CLIENTSECRET")
else
accesstoken=$(echo "$AZUREDNS_BEARERTOKEN" | sed "s/Bearer //g")
fi
if ! _get_root "$fulldomain" "$AZUREDNS_SUBSCRIPTIONID" "$accesstoken"; then
_err "invalid domain"
@@ -265,10 +294,10 @@ _azure_rest() {
if [ "$_code" = "401" ]; then
# we have an invalid access token set to expired
_saveaccountconf_mutable AZUREDNS_TOKENVALIDTO "0"
_err "access denied make sure your Azure settings are correct. See $WIKI"
_err "Access denied. Invalid access token. Make sure your Azure settings are correct. See: $wiki"
return 1
fi
# See https://docs.microsoft.com/en-us/azure/architecture/best-practices/retry-service-specific#general-rest-and-retry-guidelines for retryable HTTP codes
# See https://learn.microsoft.com/en-us/azure/architecture/best-practices/retry-service-specific#general-rest-and-retry-guidelines for retryable HTTP codes
if [ "$_ret" != "0" ] || [ -z "$_code" ] || [ "$_code" = "408" ] || [ "$_code" = "500" ] || [ "$_code" = "503" ] || [ "$_code" = "504" ]; then
_request_retry_times="$(_math "$_request_retry_times" + 1)"
_info "REST call error $_code retrying $ep in $_request_retry_times s"
@@ -286,14 +315,14 @@ _azure_rest() {
return 0
}
## Ref: https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-protocols-oauth-service-to-service#request-an-access-token
## Ref: https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-client-creds-grant-flow#request-an-access-token
_azure_getaccess_token() {
managedIdentity=$1
tenantID=$2
clientID=$3
clientSecret=$4
accesstoken="${AZUREDNS_BEARERTOKEN:-$(_readaccountconf_mutable AZUREDNS_BEARERTOKEN)}"
accesstoken="${AZUREDNS_ACCESSTOKEN:-$(_readaccountconf_mutable AZUREDNS_ACCESSTOKEN)}"
expires_on="${AZUREDNS_TOKENVALIDTO:-$(_readaccountconf_mutable AZUREDNS_TOKENVALIDTO)}"
# can we reuse the bearer token?
@@ -310,7 +339,7 @@ _azure_getaccess_token() {
_debug "getting new bearer token"
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
# https://learn.microsoft.com/en-us/entra/identity/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)"
@@ -330,14 +359,14 @@ _azure_getaccess_token() {
fi
if [ -z "$accesstoken" ]; then
_err "no acccess token received. Check your Azure settings see $WIKI"
_err "No acccess token received. Check your Azure settings. See: $wiki"
return 1
fi
if [ "$_ret" != "0" ]; then
_err "error $response"
return 1
fi
_saveaccountconf_mutable AZUREDNS_BEARERTOKEN "$accesstoken"
_saveaccountconf_mutable AZUREDNS_ACCESSTOKEN "$accesstoken"
_saveaccountconf_mutable AZUREDNS_TOKENVALIDTO "$expires_on"
printf "%s" "$accesstoken"
return 0
@@ -350,15 +379,18 @@ _get_root() {
i=1
p=1
## Ref: https://docs.microsoft.com/en-us/rest/api/dns/zones/list
## returns up to 100 zones in one response therefore handling more results is not not implemented
## (ZoneListResult with continuation token for the next page of results)
## Per https://docs.microsoft.com/en-us/azure/azure-subscription-service-limits#dns-limits you are limited to 100 Zone/subscriptions anyways
## Ref: https://learn.microsoft.com/en-us/rest/api/dns/zones/list?view=rest-dns-2018-05-01&tabs=HTTP
## returns up to 100 zones in one response. Handling more results is not implemented
## (ZoneListResult with continuation token for the next page of results)
##
## TODO: handle more than 100 results, as per:
## https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/azure-subscription-service-limits#azure-dns-limits
## The new limit is 250 Public DNS zones per subscription, while the old limit was only 100
##
_azure_rest GET "https://management.azure.com/subscriptions/$subscriptionId/providers/Microsoft.Network/dnszones?\$top=500&api-version=2017-09-01" "" "$accesstoken"
# Find matching domain name in Json response
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
_debug2 "Checking domain: $h"
if [ -z "$h" ]; then
#not valid
@@ -373,7 +405,7 @@ _get_root() {
#create the record at the domain apex (@) if only the domain name was provided as --domain-alias
_sub_domain="@"
else
_sub_domain=$(echo "$domain" | cut -d . -f 1-$p)
_sub_domain=$(echo "$domain" | cut -d . -f 1-"$p")
fi
_domain=$h
return 0
+281
View File
@@ -0,0 +1,281 @@
#!/usr/bin/env sh
# shellcheck disable=SC2034
dns_beget_info='Beget.com
Site: Beget.com
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_beget
Options:
BEGET_User API user
BEGET_Password API password
Issues: github.com/acmesh-official/acme.sh/issues/6200
Author: ARNik arnik@arnik.ru
'
Beget_Api="https://api.beget.com/api"
#################### Public functions ####################
# Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
# Used to add txt record
dns_beget_add() {
fulldomain=$1
txtvalue=$2
_debug "dns_beget_add() $fulldomain $txtvalue"
fulldomain=$(echo "$fulldomain" | _lower_case)
Beget_Username="${Beget_Username:-$(_readaccountconf_mutable Beget_Username)}"
Beget_Password="${Beget_Password:-$(_readaccountconf_mutable Beget_Password)}"
if [ -z "$Beget_Username" ] || [ -z "$Beget_Password" ]; then
Beget_Username=""
Beget_Password=""
_err "You must export variables: Beget_Username, and Beget_Password"
return 1
fi
#save the credentials to the account conf file.
_saveaccountconf_mutable Beget_Username "$Beget_Username"
_saveaccountconf_mutable Beget_Password "$Beget_Password"
_info "Prepare subdomain."
if ! _prepare_subdomain "$fulldomain"; then
_err "Can't prepare subdomain."
return 1
fi
_info "Get domain records"
data="{\"fqdn\":\"$fulldomain\"}"
res=$(_api_call "$Beget_Api/dns/getData" "$data")
if ! _is_api_reply_ok "$res"; then
_err "Can't get domain records."
return 1
fi
_info "Add new TXT record"
data="{\"fqdn\":\"$fulldomain\",\"records\":{"
data=${data}$(_parce_records "$res" "A")
data=${data}$(_parce_records "$res" "AAAA")
data=${data}$(_parce_records "$res" "CAA")
data=${data}$(_parce_records "$res" "MX")
data=${data}$(_parce_records "$res" "SRV")
data=${data}$(_parce_records "$res" "TXT")
data=$(echo "$data" | sed 's/,$//')
data=${data}'}}'
str=$(_txt_to_dns_json "$txtvalue")
data=$(_add_record "$data" "TXT" "$str")
res=$(_api_call "$Beget_Api/dns/changeRecords" "$data")
if ! _is_api_reply_ok "$res"; then
_err "Can't change domain records."
return 1
fi
return 0
}
# Usage: fulldomain txtvalue
# Used to remove the txt record after validation
dns_beget_rm() {
fulldomain=$1
txtvalue=$2
_debug "dns_beget_rm() $fulldomain $txtvalue"
fulldomain=$(echo "$fulldomain" | _lower_case)
Beget_Username="${Beget_Username:-$(_readaccountconf_mutable Beget_Username)}"
Beget_Password="${Beget_Password:-$(_readaccountconf_mutable Beget_Password)}"
_info "Get current domain records"
data="{\"fqdn\":\"$fulldomain\"}"
res=$(_api_call "$Beget_Api/dns/getData" "$data")
if ! _is_api_reply_ok "$res"; then
_err "Can't get domain records."
return 1
fi
_info "Remove TXT record"
data="{\"fqdn\":\"$fulldomain\",\"records\":{"
data=${data}$(_parce_records "$res" "A")
data=${data}$(_parce_records "$res" "AAAA")
data=${data}$(_parce_records "$res" "CAA")
data=${data}$(_parce_records "$res" "MX")
data=${data}$(_parce_records "$res" "SRV")
data=${data}$(_parce_records "$res" "TXT")
data=$(echo "$data" | sed 's/,$//')
data=${data}'}}'
str=$(_txt_to_dns_json "$txtvalue")
data=$(_rm_record "$data" "$str")
res=$(_api_call "$Beget_Api/dns/changeRecords" "$data")
if ! _is_api_reply_ok "$res"; then
_err "Can't change domain records."
return 1
fi
return 0
}
#################### Private functions below ####################
# Create subdomain if needed
# Usage: _prepare_subdomain [fulldomain]
_prepare_subdomain() {
fulldomain=$1
_info "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"
if [ -z "$_sub_domain" ]; then
_debug "$fulldomain is a root domain."
return 0
fi
_info "Get subdomain list"
res=$(_api_call "$Beget_Api/domain/getSubdomainList")
if ! _is_api_reply_ok "$res"; then
_err "Can't get subdomain list."
return 1
fi
if _contains "$res" "\"fqdn\":\"$fulldomain\""; then
_debug "Subdomain $fulldomain already exist."
return 0
fi
_info "Subdomain $fulldomain does not exist. Let's create one."
data="{\"subdomain\":\"$_sub_domain\",\"domain_id\":$_domain_id}"
res=$(_api_call "$Beget_Api/domain/addSubdomainVirtual" "$data")
if ! _is_api_reply_ok "$res"; then
_err "Can't create subdomain."
return 1
fi
_debug "Cleanup subdomen records"
data="{\"fqdn\":\"$fulldomain\",\"records\":{}}"
res=$(_api_call "$Beget_Api/dns/changeRecords" "$data")
if ! _is_api_reply_ok "$res"; then
_debug "Can't cleanup $fulldomain records."
fi
data="{\"fqdn\":\"www.$fulldomain\",\"records\":{}}"
res=$(_api_call "$Beget_Api/dns/changeRecords" "$data")
if ! _is_api_reply_ok "$res"; then
_debug "Can't cleanup www.$fulldomain records."
fi
return 0
}
# Usage: _get_root _acme-challenge.www.domain.com
#returns
# _sub_domain=_acme-challenge.www
# _domain=domain.com
# _domain_id=32436365
_get_root() {
fulldomain=$1
i=1
p=1
_debug "Get domain list"
res=$(_api_call "$Beget_Api/domain/getList")
if ! _is_api_reply_ok "$res"; then
_err "Can't get domain list."
return 1
fi
while true; do
h=$(printf "%s" "$fulldomain" | cut -d . -f "$i"-100)
_debug h "$h"
if [ -z "$h" ]; then
return 1
fi
if _contains "$res" "$h"; then
_domain_id=$(echo "$res" | _egrep_o "\"id\":[0-9]*,\"fqdn\":\"$h\"" | cut -d , -f1 | cut -d : -f2)
if [ "$_domain_id" ]; then
if [ "$h" != "$fulldomain" ]; then
_sub_domain=$(echo "$fulldomain" | cut -d . -f 1-"$p")
else
_sub_domain=""
fi
_domain=$h
return 0
fi
return 1
fi
p="$i"
i=$(_math "$i" + 1)
done
return 1
}
# Parce DNS records from json string
# Usage: _parce_records [j_str] [record_name]
_parce_records() {
j_str=$1
record_name=$2
res="\"$record_name\":["
res=${res}$(echo "$j_str" | _egrep_o "\"$record_name\":\[.*" | cut -d '[' -f2 | cut -d ']' -f1)
res=${res}"],"
echo "$res"
}
# Usage: _add_record [data] [record_name] [record_data]
_add_record() {
data=$1
record_name=$2
record_data=$3
echo "$data" | sed "s/\"$record_name\":\[/\"$record_name\":\[$record_data,/" | sed "s/,\]/\]/"
}
# Usage: _rm_record [data] [record_data]
_rm_record() {
data=$1
record_data=$2
echo "$data" | sed "s/$record_data//g" | sed "s/,\+/,/g" |
sed "s/{,/{/g" | sed "s/,}/}/g" |
sed "s/\[,/\[/g" | sed "s/,\]/\]/g"
}
_txt_to_dns_json() {
echo "{\"ttl\":600,\"txtdata\":\"$1\"}"
}
# Usage: _api_call [api_url] [input_data]
_api_call() {
api_url="$1"
input_data="$2"
_debug "_api_call $api_url"
_debug "Request: $input_data"
# res=$(curl -s -L -D ./http.header \
# "$api_url" \
# --data-urlencode login=$Beget_Username \
# --data-urlencode passwd=$Beget_Password \
# --data-urlencode input_format=json \
# --data-urlencode output_format=json \
# --data-urlencode "input_data=$input_data")
url="$api_url?login=$Beget_Username&passwd=$Beget_Password&input_format=json&output_format=json"
if [ -n "$input_data" ]; then
url=${url}"&input_data="
url=${url}$(echo "$input_data" | _url_encode)
fi
res=$(_get "$url")
_debug "Reply: $res"
echo "$res"
}
# Usage: _is_api_reply_ok [api_reply]
_is_api_reply_ok() {
_contains "$1" '^{"status":"success","answer":{"status":"success","result":.*}}$'
}
+4 -4
View File
@@ -196,7 +196,7 @@ _get_base_domain() {
_debug2 domain_list "$domain_list"
i=1
while [ $i -gt 0 ]; do
while [ "$i" -gt 0 ]; do
## get next longest domain
_domain=$(printf "%s" "$fulldomain" | cut -d . -f "$i"-"$MAX_DOM")
## check we got something back from our cut (or are we at the end)
@@ -208,7 +208,7 @@ _get_base_domain() {
## check if it exists
if [ -n "$found" ]; then
## exists - exit loop returning the parts
sub_point=$(_math $i - 1)
sub_point=$(_math "$i" - 1)
_sub_domain=$(printf "%s" "$fulldomain" | cut -d . -f 1-"$sub_point")
_domain_id="$(echo "$found" | _egrep_o "Id\"\s*\:\s*\"*[0-9]+" | _egrep_o "[0-9]+")"
_debug _domain_id "$_domain_id"
@@ -218,11 +218,11 @@ _get_base_domain() {
return 0
fi
## increment cut point $i
i=$(_math $i + 1)
i=$(_math "$i" + 1)
done
if [ -z "$found" ]; then
page=$(_math $page + 1)
page=$(_math "$page" + 1)
nextpage="https://api.bunny.net/dnszone?page=$page"
## Find the next page if we don't have a match.
hasnextpage="$(echo "$domain_list" | _egrep_o "\"HasMoreItems\"\s*:\s*true")"
+2 -2
View File
@@ -186,7 +186,7 @@ _get_root() {
fi
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
_debug h "$h"
if [ -z "$h" ]; then
#not valid
@@ -206,7 +206,7 @@ _get_root() {
if _contains "$response" "\"name\":\"$h\"" || _contains "$response" '"total_count":1'; then
_domain_id=$(echo "$response" | _egrep_o "\[.\"id\": *\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \" | tr -d " ")
if [ "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain=$h
return 0
fi
+1 -1
View File
@@ -164,7 +164,7 @@ _dns_cloudns_get_zone_info() {
_dns_cloudns_get_zone_name() {
i=2
while true; do
zoneForCheck=$(printf "%s" "$1" | cut -d . -f $i-100)
zoneForCheck=$(printf "%s" "$1" | cut -d . -f "$i"-100)
if [ -z "$zoneForCheck" ]; then
return 1
+2 -2
View File
@@ -131,7 +131,7 @@ _cn_get_root() {
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
_debug h "$h"
_debug _H1 "${_H1}"
@@ -149,7 +149,7 @@ _cn_get_root() {
fi
if _contains "$_cn_zonelist" "\"name\":\"$h\"" >/dev/null; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain=$h
return 0
else
+2 -2
View File
@@ -237,7 +237,7 @@ _get_root() {
i=2
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100).
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100).
_debug h "$h"
if [ -z "$h" ]; then
#not valid
@@ -251,7 +251,7 @@ _get_root() {
if _contains "$response" "\"name\":\"$h\"" >/dev/null; then
_domain_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":\"[^\"]*\"" | head -n 1 | cut -d : -f 2 | tr -d \")
if [ "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain=$h
return 0
fi
+2 -2
View File
@@ -122,7 +122,7 @@ _get_root() {
p=1
_debug "Detecting root zone"
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
if [ -z "$h" ]; then
return 1
fi
@@ -134,7 +134,7 @@ _get_root() {
if _contains "$response" "\"name\":\"$h\""; then
_domain_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[0-9]*" | cut -d ':' -f 2)
if [ "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d '.' -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d '.' -f 1-"$p")
_domain="$h"
_debug _domain_id "$_domain_id"
+1 -1
View File
@@ -142,7 +142,7 @@ _get_root() {
i=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
_debug h "$h"
if [ -z "$h" ]; then
#not valid
+13 -6
View File
@@ -215,10 +215,8 @@ _cyon_change_domain_env() {
if ! _cyon_check_if_2fa_missed "${domain_env_response}"; then return 1; fi
domain_env_success="$(printf "%s" "${domain_env_response}" | _egrep_o '"authenticated":\w*' | cut -d : -f 2)"
# Bail if domain environment change fails.
if [ "${domain_env_success}" != "true" ]; then
if [ "$(printf "%s" "${domain_env_response}" | _cyon_get_environment_change_status)" != "true" ]; then
_err " $(printf "%s" "${domain_env_response}" | _cyon_get_response_message)"
_err ""
return 1
@@ -232,7 +230,7 @@ _cyon_add_txt() {
_info " - Adding DNS TXT entry..."
add_txt_url="https://my.cyon.ch/domain/dnseditor/add-record-async"
add_txt_data="zone=${fulldomain_idn}.&ttl=900&type=TXT&value=${txtvalue}"
add_txt_data="name=${fulldomain_idn}.&ttl=900&type=TXT&dnscontent=${txtvalue}"
add_txt_response="$(_post "$add_txt_data" "$add_txt_url")"
_debug add_txt_response "${add_txt_response}"
@@ -241,9 +239,10 @@ _cyon_add_txt() {
add_txt_message="$(printf "%s" "${add_txt_response}" | _cyon_get_response_message)"
add_txt_status="$(printf "%s" "${add_txt_response}" | _cyon_get_response_status)"
add_txt_validation="$(printf "%s" "${add_txt_response}" | _cyon_get_validation_status)"
# Bail if adding TXT entry fails.
if [ "${add_txt_status}" != "true" ]; then
if [ "${add_txt_status}" != "true" ] || [ "${add_txt_validation}" != "true" ]; then
_err " ${add_txt_message}"
_err ""
return 1
@@ -305,13 +304,21 @@ _cyon_get_response_message() {
}
_cyon_get_response_status() {
_egrep_o '"status":\w*' | cut -d : -f 2
_egrep_o '"status":[a-zA-z0-9]*' | cut -d : -f 2
}
_cyon_get_validation_status() {
_egrep_o '"valid":[a-zA-z0-9]*' | cut -d : -f 2
}
_cyon_get_response_success() {
_egrep_o '"onSuccess":"[^"]*"' | cut -d : -f 2 | tr -d '"'
}
_cyon_get_environment_change_status() {
_egrep_o '"authenticated":[a-zA-z0-9]*' | cut -d : -f 2
}
_cyon_check_if_2fa_missed() {
# Did we miss the 2FA?
if test "${1#*multi_factor_form}" != "${1}"; then
+2 -2
View File
@@ -61,7 +61,7 @@ _get_root() {
# response will contain "list[]=example.com&list[]=example.org"
_da_api CMD_API_SHOW_DOMAINS "" "${domain}"
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
_debug h "$h"
if [ -z "$h" ]; then
# not valid
@@ -69,7 +69,7 @@ _get_root() {
return 1
fi
if _contains "$response" "$h" >/dev/null; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain=$h
return 0
fi
+2 -2
View File
@@ -176,7 +176,7 @@ _get_root() {
i=2
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
_debug h "$h"
if [ -z "$h" ]; then
#not valid
@@ -188,7 +188,7 @@ _get_root() {
fi
if _contains "$response" "\"name\":\"$h\"" >/dev/null; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain=$h
return 0
fi
+3 -3
View File
@@ -203,7 +203,7 @@ _get_base_domain() {
_debug2 domain_list "$domain_list"
i=1
while [ $i -gt 0 ]; do
while [ "$i" -gt 0 ]; do
## get next longest domain
_domain=$(printf "%s" "$fulldomain" | cut -d . -f "$i"-"$MAX_DOM")
## check we got something back from our cut (or are we at the end)
@@ -215,14 +215,14 @@ _get_base_domain() {
## check if it exists
if [ -n "$found" ]; then
## exists - exit loop returning the parts
sub_point=$(_math $i - 1)
sub_point=$(_math "$i" - 1)
_sub_domain=$(printf "%s" "$fulldomain" | cut -d . -f 1-"$sub_point")
_debug _domain "$_domain"
_debug _sub_domain "$_sub_domain"
return 0
fi
## increment cut point $i
i=$(_math $i + 1)
i=$(_math "$i" + 1)
done
if [ -z "$found" ]; then
+1 -1
View File
@@ -84,7 +84,7 @@ _get_root() {
domain=$1
i=1
while true; do
_domain=$(printf "%s" "$domain" | cut -d . -f $i-100)
_domain=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
_debug h "$_domain"
if [ -z "$_domain" ]; then
return 1
+2 -2
View File
@@ -92,7 +92,7 @@ _get_root() {
i=2
previous=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
if [ -z "$h" ]; then
# not valid
return 1
@@ -105,7 +105,7 @@ _get_root() {
if _contains "$response" 'not found'; then
_debug "$h not found"
else
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$previous)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$previous")
_domain="$h"
_debug _domain "$_domain"
+1 -2
View File
@@ -2,7 +2,6 @@
# shellcheck disable=SC2034
dns_doapi_info='Domain-Offensive do.de
Official LetsEncrypt API for do.de / Domain-Offensive.
This is different from the dns_do adapter, because dns_do is only usable for enterprise customers.
This API is also available to private customers/individuals.
Site: do.de
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_doapi
@@ -11,7 +10,7 @@ Options:
Issues: github.com/acmesh-official/acme.sh/issues/2057
'
DO_API="https://www.do.de/api/letsencrypt"
DO_API="https://my.do.de/api/letsencrypt"
######## Public functions #####################
+2 -2
View File
@@ -93,7 +93,7 @@ _get_domainid() {
i=2
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
_debug "h" "$h"
if [ -z "$h" ]; then
#not valid
@@ -102,7 +102,7 @@ _get_domainid() {
if _contains "$response" "\"$h\"" >/dev/null; then
# We have found the domain name.
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain=$h
_domainid=$(printf "%s" "$response" | _egrep_o "[^{]*\"domain\":\"$_domain\"[^}]*" | _egrep_o "\"id\":[0-9]+" | cut -d : -f 2)
return 0
+2 -2
View File
@@ -109,7 +109,7 @@ _get_root() {
i=2
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
if [ -z "$h" ]; then
#not valid
return 1
@@ -123,7 +123,7 @@ _get_root() {
_domain_id=$(printf "%s\n" "$response" | _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)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_debug _sub_domain "$_sub_domain"
_domain="$h"
_debug _domain "$_domain"
+2 -2
View File
@@ -109,7 +109,7 @@ _get_root() {
i=2
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
if [ -z "$h" ]; then
#not valid
return 1
@@ -123,7 +123,7 @@ _get_root() {
_domain_id=$(printf "%s\n" "$response" | _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)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_debug _sub_domain "$_sub_domain"
_domain="$h"
_debug _domain "$_domain"
+2 -2
View File
@@ -110,7 +110,7 @@ _get_root() {
i=1
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
_debug h "$h"
if [ -z "$h" ]; then
#not valid
@@ -118,7 +118,7 @@ _get_root() {
fi
if _contains "$response" ">$h.</origin>"; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain=$h
return 0
fi
+2 -2
View File
@@ -126,7 +126,7 @@ _get_root() {
i=2
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
_debug h "$h"
if [ -z "$h" ]; then
#not valid
@@ -140,7 +140,7 @@ _get_root() {
if _contains "$response" "\"domainName\":\"$h\"" >/dev/null; then
dnsId=$(printf "%s" "$response" | tr -d "{}" | cut -d , -f 2 | cut -d : -f 2)
_domain_name=$h
_node=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_node=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
return 0
fi
p=$i
+1 -2
View File
@@ -43,9 +43,8 @@ dns_dynv6_add() {
_err "Something went wrong! it does not seem like the record was added successfully"
return 1
fi
return 1
fi
return 1
}
#Usage: fulldomain txtvalue
#Remove the txt record after validation.
+2 -2
View File
@@ -121,7 +121,7 @@ _get_root() {
i=1
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
_debug h "$h"
if [ -z "$h" ]; then
#not valid
@@ -133,7 +133,7 @@ _get_root() {
fi
if _contains "$response" "\"status\":200"; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain=$h
return 0
fi
+163
View File
@@ -0,0 +1,163 @@
#!/usr/bin/env sh
# shellcheck disable=SC2034
# EdgeCenter DNS API integration for acme.sh
# Author: Konstantin Ruchev <konstantin.ruchev@edgecenter.ru>
dns_edgecenter_info='edgecenter DNS API
Site: https://edgecenter.ru
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_edgecenter
Options:
EDGECENTER_API_KEY auth APIKey'
EDGECENTER_API="https://api.edgecenter.ru"
DOMAIN_TYPE=
DOMAIN_MASTER=
######## Public functions #####################
#Usage: dns_edgecenter_add _acme-challenge.www.domain.com "TXT_RECORD_VALUE"
dns_edgecenter_add() {
fulldomain="$1"
txtvalue="$2"
_info "Using EdgeCenter DNS API"
if ! _dns_edgecenter_init_check; then
return 1
fi
_debug "Detecting root zone for $fulldomain"
if ! _get_root "$fulldomain"; then
return 1
fi
subdomain="${fulldomain%."$_zone"}"
subdomain=${subdomain%.}
_debug "Zone: $_zone"
_debug "Subdomain: $subdomain"
_debug "TXT value: $txtvalue"
payload='{"resource_records": [ { "content": ["'"$txtvalue"'"] } ], "ttl": 60 }'
_dns_edgecenter_http_api_call "post" "dns/v2/zones/$_zone/$subdomain.$_zone/txt" "$payload"
if _contains "$response" '"error":"rrset is already exists"'; then
_debug "RRSet exists, merging values"
_dns_edgecenter_http_api_call "get" "dns/v2/zones/$_zone/$subdomain.$_zone/txt"
current="$response"
newlist=""
for v in $(echo "$current" | sed -n 's/.*"content":\["\([^"]*\)"\].*/\1/p'); do
newlist="$newlist {\"content\":[\"$v\"]},"
done
newlist="$newlist{\"content\":[\"$txtvalue\"]}"
putdata="{\"resource_records\":[${newlist}]}
"
_dns_edgecenter_http_api_call "put" "dns/v2/zones/$_zone/$subdomain.$_zone/txt" "$putdata"
_info "Updated existing RRSet with new TXT value."
return 0
fi
if _contains "$response" '"exception":'; then
_err "Record cannot be added."
return 1
fi
_info "TXT record added successfully."
return 0
}
#Usage: dns_edgecenter_rm _acme-challenge.www.domain.com "TXT_RECORD_VALUE"
dns_edgecenter_rm() {
fulldomain="$1"
txtvalue="$2"
_info "Removing TXT record for $fulldomain"
if ! _dns_edgecenter_init_check; then
return 1
fi
if ! _get_root "$fulldomain"; then
return 1
fi
subdomain="${fulldomain%."$_zone"}"
subdomain=${subdomain%.}
_dns_edgecenter_http_api_call "delete" "dns/v2/zones/$_zone/$subdomain.$_zone/txt"
if [ -z "$response" ]; then
_info "TXT record deleted successfully."
else
_info "TXT record may not have been deleted: $response"
fi
return 0
}
#################### Private functions below ##################################
_dns_edgecenter_init_check() {
EDGECENTER_API_KEY="${EDGECENTER_API_KEY:-$(_readaccountconf_mutable EDGECENTER_API_KEY)}"
if [ -z "$EDGECENTER_API_KEY" ]; then
_err "EDGECENTER_API_KEY was not exported."
return 1
fi
_saveaccountconf_mutable EDGECENTER_API_KEY "$EDGECENTER_API_KEY"
export _H1="Authorization: APIKey $EDGECENTER_API_KEY"
_dns_edgecenter_http_api_call "get" "dns/v2/clients/me/features"
if ! _contains "$response" '"id":'; then
_err "Invalid API key."
return 1
fi
return 0
}
_get_root() {
domain="$1"
i=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f "$i"-)
if [ -z "$h" ]; then
return 1
fi
_dns_edgecenter_http_api_call "get" "dns/v2/zones/$h"
if ! _contains "$response" 'zone is not found'; then
_zone="$h"
return 0
fi
i=$((i + 1))
done
return 1
}
_dns_edgecenter_http_api_call() {
mtd="$1"
endpoint="$2"
data="$3"
export _H1="Authorization: APIKey $EDGECENTER_API_KEY"
case "$mtd" in
get)
response="$(_get "$EDGECENTER_API/$endpoint")"
;;
post)
response="$(_post "$data" "$EDGECENTER_API/$endpoint")"
;;
delete)
response="$(_post "" "$EDGECENTER_API/$endpoint" "" "DELETE")"
;;
put)
response="$(_post "$data" "$EDGECENTER_API/$endpoint" "" "PUT")"
;;
*)
_err "Unknown HTTP method $mtd"
return 1
;;
esac
_debug "HTTP $mtd response: $response"
return 0
}
+2 -2
View File
@@ -151,7 +151,7 @@ _get_root() {
response="$_euserv_domain_orders"
while true; do
h=$(echo "$domain" | cut -d . -f $i-100)
h=$(echo "$domain" | cut -d . -f "$i"-100)
_debug h "$h"
if [ -z "$h" ]; then
#not valid
@@ -159,7 +159,7 @@ _get_root() {
fi
if _contains "$response" "$h"; then
_sub_domain=$(echo "$domain" | cut -d . -f 1-$p)
_sub_domain=$(echo "$domain" | cut -d . -f 1-"$p")
_domain="$h"
if ! _euserv_get_domain_id "$_domain"; then
_err "invalid domain"
+2 -2
View File
@@ -119,7 +119,7 @@ _get_root() {
i=2
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
_debug h "$h"
if [ -z "$h" ]; then
#not valid
@@ -130,7 +130,7 @@ _get_root() {
_domain_id=$(echo "$response" | tr '{' "\n" | grep "\"name\":\"$h\"" | _egrep_o "\"id\":[^,]+" | _head_n 1 | cut -d : -f 2 | tr -d \")
_domain_token=$(echo "$response" | tr '{' "\n" | grep "\"name\":\"$h\"" | _egrep_o "\"token\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \")
if [ "$_domain_token" ] && [ "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain=$h
return 0
fi
+13 -13
View File
@@ -9,7 +9,7 @@ Issues: github.com/acmesh-official/acme.sh/issues/3998
Author: Timur Umarov <inbox@tumarov.com>
'
FORNEX_API_URL="https://fornex.com/api/dns/v0.1"
FORNEX_API_URL="https://fornex.com/api"
######## Public functions #####################
@@ -30,12 +30,10 @@ dns_fornex_add() {
fi
_info "Adding record"
if _rest POST "$_domain/entry_set/add/" "host=$fulldomain&type=TXT&value=$txtvalue&apikey=$FORNEX_API_KEY"; then
if _rest POST "dns/domain/$_domain/entry_set/" "{\"host\" : \"${fulldomain}\" , \"type\" : \"TXT\" , \"value\" : \"${txtvalue}\" , \"ttl\" : null}"; then
_debug _response "$response"
if _contains "$response" '"ok": true' || _contains "$response" 'Такая запись уже существует.'; then
_info "Added, OK"
return 0
fi
_info "Added, OK"
return 0
fi
_err "Add txt record error."
return 1
@@ -58,21 +56,21 @@ dns_fornex_rm() {
fi
_debug "Getting txt records"
_rest GET "$_domain/entry_set.json?apikey=$FORNEX_API_KEY"
_rest GET "dns/domain/$_domain/entry_set?type=TXT&q=$fulldomain"
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')"
_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
if ! _rest DELETE "dns/domain/$_domain/entry_set/$_record_id/"; then
_err "Delete record error."
return 1
fi
@@ -90,18 +88,18 @@ _get_root() {
i=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
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
if ! _rest GET "dns/domain/"; then
return 1
fi
if _contains "$response" "\"$h\"" >/dev/null; then
if _contains "$response" "\"name\":\"$h\"" >/dev/null; then
_domain=$h
return 0
else
@@ -134,7 +132,9 @@ _rest() {
data="$3"
_debug "$ep"
export _H1="Accept: application/json"
export _H1="Authorization: Api-Key $FORNEX_API_KEY"
export _H2="Content-Type: application/json"
export _H3="Accept: application/json"
if [ "$m" != "GET" ]; then
_debug data "$data"
+105
View File
@@ -0,0 +1,105 @@
#!/usr/bin/env sh
# shellcheck disable=SC2034
dns_freemyip_info='FreeMyIP.com
Site: freemyip.com
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_freemyip
Options:
FREEMYIP_Token API Token
Issues: github.com/acmesh-official/acme.sh/issues/{XXXX}
Author: Recolic Keghart <root@recolic.net>, @Giova96
'
FREEMYIP_DNS_API="https://freemyip.com/update?"
################ Public functions ################
#Usage: dns_freemyip_add fulldomain txtvalue
dns_freemyip_add() {
fulldomain="$1"
txtvalue="$2"
_info "Add TXT record $txtvalue for $fulldomain using freemyip.com api"
FREEMYIP_Token="${FREEMYIP_Token:-$(_readaccountconf_mutable FREEMYIP_Token)}"
if [ -z "$FREEMYIP_Token" ]; then
FREEMYIP_Token=""
_err "You don't specify FREEMYIP_Token yet."
_err "Please specify your token and try again."
return 1
fi
#save the credentials to the account conf file.
_saveaccountconf_mutable FREEMYIP_Token "$FREEMYIP_Token"
if _is_root_domain_published "$fulldomain"; then
_err "freemyip API don't allow you to set multiple TXT record for the same subdomain!"
_err "You must apply certificate for only one domain at a time!"
_err "===="
_err "For example, aaa.yourdomain.freemyip.com and bbb.yourdomain.freemyip.com and yourdomain.freemyip.com ALWAYS share the same TXT record. They will overwrite each other if you apply multiple domain at the same time."
_debug "If you are testing this workflow in github pipeline or acmetest, please set TEST_DNS_NO_SUBDOMAIN=1 and TEST_DNS_NO_WILDCARD=1"
return 1
fi
# txtvalue must be url-encoded. But it's not necessary for acme txt value.
_freemyip_get_until_ok "${FREEMYIP_DNS_API}token=$FREEMYIP_Token&domain=$fulldomain&txt=$txtvalue" 2>&1
return $?
}
#Usage: dns_freemyip_rm fulldomain txtvalue
dns_freemyip_rm() {
fulldomain="$1"
txtvalue="$2"
_info "Delete TXT record $txtvalue for $fulldomain using freemyip.com api"
FREEMYIP_Token="${FREEMYIP_Token:-$(_readaccountconf_mutable FREEMYIP_Token)}"
if [ -z "$FREEMYIP_Token" ]; then
FREEMYIP_Token=""
_err "You don't specify FREEMYIP_Token yet."
_err "Please specify your token and try again."
return 1
fi
#save the credentials to the account conf file.
_saveaccountconf_mutable FREEMYIP_Token "$FREEMYIP_Token"
# Leave the TXT record as empty or "null" to delete the record.
_freemyip_get_until_ok "${FREEMYIP_DNS_API}token=$FREEMYIP_Token&domain=$fulldomain&txt=" 2>&1
return $?
}
################ Private functions below ################
_get_root() {
_fmi_d="$1"
echo "$_fmi_d" | rev | cut -d '.' -f 1-3 | rev
}
# There is random failure while calling freemyip API too fast. This function automatically retry until success.
_freemyip_get_until_ok() {
_fmi_url="$1"
for i in $(seq 1 8); do
_debug "HTTP GET freemyip.com API '$_fmi_url', retry $i/8..."
_get "$_fmi_url" | tee /dev/fd/2 | grep OK && return 0
_sleep 1 # DO NOT send the request too fast
done
_err "Failed to request freemyip API: $_fmi_url . Server does not say 'OK'"
return 1
}
# Verify in public dns if domain is already there.
_is_root_domain_published() {
_fmi_d="$1"
_webroot="$(_get_root "$_fmi_d")"
_info "Verifying '""$_fmi_d""' freemyip webroot (""$_webroot"") is not published yet"
for i in $(seq 1 3); do
_debug "'$_webroot' ns lookup, retry $i/3..."
if [ "$(_ns_lookup "$_fmi_d" TXT)" ]; then
_debug "'$_webroot' already has a TXT record published!"
return 0
fi
_sleep 10 # Give it some time to propagate the TXT record
done
return 1
}
+2 -2
View File
@@ -95,7 +95,7 @@ _get_root() {
i=2
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
_debug h "$h"
if [ -z "$h" ]; then
#not valid
@@ -112,7 +112,7 @@ _get_root() {
elif _contains "$response" '"code": 404'; then
_debug "$h not found"
else
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain="$h"
return 0
fi
+3 -3
View File
@@ -28,7 +28,7 @@ dns_gcore_add() {
fi
#save the api key to the account conf file.
_saveaccountconf_mutable GCORE_Key "$GCORE_Key"
_saveaccountconf_mutable GCORE_Key "$GCORE_Key" "base64"
_debug "First detect the zone name"
if ! _get_root "$fulldomain"; then
@@ -138,7 +138,7 @@ _get_root() {
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
_debug h "$h"
if [ -z "$h" ]; then
#not valid
@@ -152,7 +152,7 @@ _get_root() {
if _contains "$response" "\"name\":\"$h\""; then
_zone_name=$h
if [ "$_zone_name" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain=$h
return 0
fi
+2 -2
View File
@@ -148,7 +148,7 @@ _get_root() {
i=2
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
if [ -z "$h" ]; then
#not valid
return 1
@@ -161,7 +161,7 @@ _get_root() {
if _contains "$response" '"code":"NOT_FOUND"'; then
_debug "$h not found"
else
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain="$h"
return 0
fi
+1 -1
View File
@@ -202,7 +202,7 @@ find_zone() {
# Walk through all possible zone names
strip_counter=1
while true; do
attempted_zone=$(echo "${domain}" | cut -d . -f ${strip_counter}-)
attempted_zone=$(echo "${domain}" | cut -d . -f "${strip_counter}"-)
# All possible zone names have been tried
if [ -z "${attempted_zone}" ]; then
+1 -1
View File
@@ -132,7 +132,7 @@ _dns_googledomains_get_zone() {
i=2
while true; do
curr=$(printf "%s" "$domain" | cut -d . -f $i-100)
curr=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
_debug curr "$curr"
if [ -z "$curr" ]; then
+1 -1
View File
@@ -143,7 +143,7 @@ _find_zone() {
# Walk through all possible zone names
_strip_counter=1
while true; do
_attempted_zone=$(echo "$_domain" | cut -d . -f ${_strip_counter}-)
_attempted_zone=$(echo "$_domain" | cut -d . -f "${_strip_counter}"-)
# All possible zone names have been tried
if [ -z "$_attempted_zone" ]; then
+44
View File
@@ -0,0 +1,44 @@
#!/usr/bin/env sh
# shellcheck disable=SC2034
dns_he_ddns_info='Hurricane Electric HE.net DDNS
Site: dns.he.net
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_he_ddns
Options:
HE_DDNS_KEY The DDNS key
Author: Markku Leiniö
'
HE_DDNS_URL="https://dyn.dns.he.net/nic/update"
######## Public functions #####################
#Usage: dns_he_ddns_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_he_ddns_add() {
fulldomain=$1
txtvalue=$2
HE_DDNS_KEY="${HE_DDNS_KEY:-$(_readaccountconf_mutable HE_DDNS_KEY)}"
if [ -z "$HE_DDNS_KEY" ]; then
HE_DDNS_KEY=""
_err "You didn't specify a DDNS key for accessing the TXT record in HE API."
return 1
fi
#Save the DDNS key to the account conf file.
_saveaccountconf_mutable HE_DDNS_KEY "$HE_DDNS_KEY"
_info "Using Hurricane Electric DDNS API"
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
response="$(_post "hostname=$fulldomain&password=$HE_DDNS_KEY&txt=$txtvalue" "$HE_DDNS_URL")"
_info "Response: $response"
_contains "$response" "good" && return 0 || return 1
}
# dns_he_ddns_rm() is not doing anything because the API call always updates the
# contents of the existing record (that the API key gives access to).
dns_he_ddns_rm() {
fulldomain=$1
_debug "Delete TXT record called for '${fulldomain}', not doing anything."
return 0
}
Regular → Executable
+3 -3
View File
@@ -181,7 +181,7 @@ _get_root() {
_debug "Trying to get zone id by domain name for '$domain_without_acme'."
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
if [ -z "$h" ]; then
#not valid
return 1
@@ -193,7 +193,7 @@ _get_root() {
if _contains "$response" "\"name\":\"$h\"" || _contains "$response" '"total_entries":1'; then
_domain_id=$(echo "$response" | _egrep_o "\[.\"id\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \")
if [ "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain=$h
HETZNER_Zone_ID=$_domain_id
_savedomainconf "$domain_param_name" "$HETZNER_Zone_ID"
@@ -212,7 +212,7 @@ _get_root() {
_response_has_error() {
unset _response_error
err_part="$(echo "$response" | _egrep_o '"error":{[^}]*}')"
err_part="$(echo "$response" | _egrep_o '"error":\{[^\}]*\}')"
if [ -n "$err_part" ]; then
err_code=$(echo "$err_part" | _egrep_o '"code":[0-9]+' | cut -d : -f 2)
+2 -2
View File
@@ -123,7 +123,7 @@ _get_root() {
i=1
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
_debug h "$h"
if [ -z "$h" ]; then
#not valid
@@ -135,7 +135,7 @@ _get_root() {
fi
if _contains "$response" "CODE=200"; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain=$h
return 0
fi
+2 -2
View File
@@ -133,7 +133,7 @@ _get_root() {
fi
while true; do
h=$(printf "%s" "$domain" | cut -d . -f ${i}-100)
h=$(printf "%s" "$domain" | cut -d . -f "${i}"-100)
_debug h "$h"
if [ -z "$h" ]; then
#not valid
@@ -141,7 +141,7 @@ _get_root() {
fi
if _contains "$response" "\"$h\""; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-${p})
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"${p}")
_domain=${h}
return 0
fi
+2 -2
View File
@@ -293,7 +293,7 @@ _get_root() {
response="$(_post "$xml_content" "$INWX_Api" "" "POST")"
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
_debug h "$h"
if [ -z "$h" ]; then
#not valid
@@ -301,7 +301,7 @@ _get_root() {
fi
if _contains "$response" "$h"; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain="$h"
return 0
fi
+2 -2
View File
@@ -87,7 +87,7 @@ _get_root() {
_response="$(echo "$_response" | tr -d "\n")"
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
if [ -z "$h" ]; then
return 1
fi
@@ -96,7 +96,7 @@ _get_root() {
if [ "$_zone" ]; then
_zone_id=$(printf "%s\n" "$_zone" | _egrep_o "\"id\":\"[a-fA-F0-9\-]*\"" | _head_n 1 | cut -d : -f 2 | tr -d '\"')
if [ "$_zone_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain=$h
return 0
+8 -6
View File
@@ -1,12 +1,14 @@
#!/usr/bin/env sh
# shellcheck disable=SC2034
dns_ionos_cloud_info='IONOS Cloud DNS
Site: ionos.com
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_ionos_cloud
Options:
IONOS_TOKEN API Token.
Issues: github.com/acmesh-official/acme.sh/issues/5243
'
# Supports IONOS Cloud DNS API v1.15.4
#
# Usage:
# Export IONOS_TOKEN before calling acme.sh:
# $ export IONOS_TOKEN="..."
#
# $ acme.sh --issue --dns dns_ionos_cloud ...
IONOS_CLOUD_API="https://dns.de-fra.ionos.com"
IONOS_CLOUD_ROUTE_ZONES="/zones"
+2 -2
View File
@@ -135,7 +135,7 @@ _get_root() {
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
_debug2 "Checking domain: $h"
if ! jd_rest GET "domain"; then
_err "error get domain list"
@@ -153,7 +153,7 @@ _get_root() {
if [ "$hostedzone" ]; then
_domain_id="$(echo "$hostedzone" | tr ',' '\n' | grep "\"id\":" | cut -d : -f 2)"
if [ "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain=$h
return 0
fi
+1 -1
View File
@@ -80,7 +80,7 @@ _get_root() {
fulldomain=$1
i=1
while true; do
h=$(printf "%s" "$fulldomain" | cut -d . -f $i-100)
h=$(printf "%s" "$fulldomain" | cut -d . -f "$i"-100)
_debug h "$h"
if [ -z "$h" ]; then
return 1
+2 -2
View File
@@ -102,7 +102,7 @@ _get_root() {
i=2
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
if [ -z "$h" ]; then
#not valid
return 1
@@ -113,7 +113,7 @@ _get_root() {
if _contains "$response" '"OK":false'; then
_debug "$h not found"
else
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain="$h"
return 0
fi
+2 -2
View File
@@ -113,7 +113,7 @@ _get_root() {
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
if [ -z "$h" ]; then
#not valid
return 1
@@ -126,7 +126,7 @@ _get_root() {
if _contains "$response" '"domainid":'; then
_domain_id=$(printf "%s" "$response" | grep '"domainid":' | cut -d : -f 2 | cut -d , -f 1 | tr -d '\r' | tr -d '\n')
if [ "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain="$h"
return 0
fi
+11 -11
View File
@@ -1,13 +1,13 @@
#!/usr/bin/env sh
# Created by Laraveluser
#
# Pass credentials before "acme.sh --issue --dns dns_limacity ..."
# --
# export LIMACITY_APIKEY="<API-KEY>"
# --
#
# Pleas note: APIKEY must have following roles: dns.admin, domains.reader
# shellcheck disable=SC2034
dns_limacity_info='lima-city.de
Site: www.lima-city.de
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_limacity
Options:
LIMACITY_APIKEY API Key. Note: The API Key must have following roles: dns.admin, domains.reader
Issues: github.com/acmesh-official/acme.sh/issues/4758
Author: @Laraveluser
'
######## Public functions #####################
@@ -69,7 +69,7 @@ _lima_get_domain_id() {
if [ "$(echo "$domains" | _egrep_o "\{.*""domains""")" ]; then
response="$(echo "$domains" | tr -d "\n" | tr '{' "|" | sed 's/|/&{/g' | tr "|" "\n")"
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
_debug h "$h"
if [ -z "$h" ]; then
#not valid
@@ -80,7 +80,7 @@ _lima_get_domain_id() {
if [ "$hostedzone" ]; then
LIMACITY_DOMAINID=$(printf "%s\n" "$hostedzone" | _egrep_o "\"id\":\s*[0-9]+" | _head_n 1 | cut -d : -f 2 | tr -d \ )
if [ "$LIMACITY_DOMAINID" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain=$h
return 0
fi
+2 -2
View File
@@ -136,7 +136,7 @@ _get_root() {
if _rest GET "domain.list"; then
response="$(echo "$response" | tr -d "\n" | tr '{' "|" | sed 's/|/&{/g' | tr "|" "\n")"
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
_debug h "$h"
if [ -z "$h" ]; then
#not valid
@@ -147,7 +147,7 @@ _get_root() {
if [ "$hostedzone" ]; then
_domain_id=$(printf "%s\n" "$hostedzone" | _egrep_o "\"DOMAINID\":\s*[0-9]+" | _head_n 1 | cut -d : -f 2 | tr -d \ )
if [ "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain=$h
return 0
fi
+25 -17
View File
@@ -76,7 +76,7 @@ dns_linode_v4_rm() {
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
if _rest GET "/$_domain_id/records" && [ -n "$response" ]; then
if _H4="X-Filter: { \"type\": \"TXT\", \"name\": \"$_sub_domain\" }" _rest GET "/$_domain_id/records" && [ -n "$response" ]; then
response="$(echo "$response" | tr -d "\n" | tr '{' "|" | sed 's/|/&{/g' | tr "|" "\n")"
resource="$(echo "$response" | _egrep_o "\{.*\"name\": *\"$_sub_domain\".*}")"
@@ -131,34 +131,42 @@ _Linode_API() {
# _domain=domain.com
# _domain_id=12345
_get_root() {
domain=$1
full_host_str="$1"
i=2
p=1
while true; do
# loop through the received string (e.g. _acme-challenge.sub3.sub2.sub1.domain.tld),
# starting from the lowest subdomain, and check if it's a hosted domain
tst_hosted_domain=$(printf "%s" "$full_host_str" | cut -d . -f "$i"-100)
_debug tst_hosted_domain "$tst_hosted_domain"
if [ -z "$tst_hosted_domain" ]; then
#not valid
_err "Couldn't get domain from string '$full_host_str'."
return 1
fi
if _rest GET; then
response="$(echo "$response" | tr -d "\n" | tr '{' "|" | sed 's/|/&{/g' | tr "|" "\n")"
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
_debug h "$h"
if [ -z "$h" ]; then
#not valid
return 1
fi
hostedzone="$(echo "$response" | _egrep_o "\{.*\"domain\": *\"$h\".*}")"
_debug "Querying Linode APIv4 for hosted zone: $tst_hosted_domain"
if _H4="X-Filter: {\"domain\":\"$tst_hosted_domain\"}" _rest GET; then
_debug "Got response from API: $response"
response="$(echo "$response" | tr -d "\n" | tr '{' "|" | sed 's/|/&{/g' | tr "|" "\n")"
hostedzone="$(echo "$response" | _egrep_o "\{.*\"domain\": *\"$tst_hosted_domain\".*}")"
if [ "$hostedzone" ]; then
_domain_id=$(printf "%s\n" "$hostedzone" | _egrep_o "\"id\": *[0-9]+" | _head_n 1 | cut -d : -f 2 | tr -d \ )
_debug "Found domain hosted on Linode DNS. Zone: $tst_hosted_domain, id: $_domain_id"
if [ "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_domain=$h
_sub_domain=$(printf "%s" "$full_host_str" | cut -d . -f 1-"$p")
_domain=$tst_hosted_domain
return 0
fi
return 1
fi
p=$i
i=$(_math "$i" + 1)
done
fi
fi
done
return 1
}
+2 -2
View File
@@ -180,14 +180,14 @@ _get_root() {
response="$(_post "$xml_content" "$LOOPIA_Api" "" "POST")"
while true; do
h=$(echo "$domain" | cut -d . -f $i-100)
h=$(echo "$domain" | cut -d . -f "$i"-100)
if [ -z "$h" ]; then
#not valid
return 1
fi
if _contains "$response" "$h"; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain="$h"
return 0
fi
+2 -2
View File
@@ -110,7 +110,7 @@ _get_root() {
return 1
fi
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
_debug h "$h"
if [ -z "$h" ]; then
#not valid
@@ -121,7 +121,7 @@ _get_root() {
_domain_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[^,]*,\"name\":\"$h\"" | cut -d : -f 2 | cut -d , -f 1)
_debug _domain_id "$_domain_id"
if [ "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain="$h"
return 0
fi
+1 -1
View File
@@ -72,7 +72,7 @@ _reload_maradns() {
pidpath="$1"
kill -s HUP -- "$(cat "$pidpath")"
if [ $? -ne 0 ]; then
_err "Unable to reload MaraDNS, kill returned $?"
_err "Unable to reload MaraDNS, kill returned"
return 1
fi
}
+2 -2
View File
@@ -107,7 +107,7 @@ _get_root() {
i=2
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
if [ -z "$h" ]; then
#not valid
return 1
@@ -120,7 +120,7 @@ _get_root() {
if _contains "$response" "\"name\":\"$h\""; then
_domain_id=$(printf "%s\n" "$response" | sed 's/^{//; s/}$//; s/{.*}//' | sed -r 's/^.*"id":([0-9]+).*$/\1/')
if [ "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain="$h"
return 0
fi
+3 -4
View File
@@ -16,8 +16,7 @@ Author: Darven Dissek, William Gertz
#Usage: dns_miab_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_miab_add() {
fulldomain=$1
# Added "value=" and "&ttl=300" to accomodate the new TXT record format used by the MIAB/PMIAB API
txtvalue="value=$2&ttl=300"
txtvalue=$2
_info "Using miab challenge add"
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
@@ -113,7 +112,7 @@ _get_root() {
#cycle through the passed domain seperating out a test domain discarding
# the subdomain by marching thorugh the dots
while true; do
_test_domain=$(printf "%s" "$_passed_domain" | cut -d . -f ${_i}-100)
_test_domain=$(printf "%s" "$_passed_domain" | cut -d . -f "${_i}"-100)
_debug _test_domain "$_test_domain"
if [ -z "$_test_domain" ]; then
@@ -123,7 +122,7 @@ _get_root() {
#report found if the test domain is in the json response and
# report the subdomain
if _contains "$response" "\"$_test_domain\""; then
_sub_domain=$(printf "%s" "$_passed_domain" | cut -d . -f 1-${_p})
_sub_domain=$(printf "%s" "$_passed_domain" | cut -d . -f 1-"${_p}")
_domain=${_test_domain}
return 0
fi
+215
View File
@@ -0,0 +1,215 @@
#!/usr/bin/env sh
# shellcheck disable=SC2034
dns_mijnhost_info='mijn.host
Domains: mijn.host
Site: mijn.host
Docs: https://mijn.host/api/doc/
Issues: https://github.com/acmesh-official/acme.sh/issues/6177
Author: peterv99
Options:
MIJNHOST_API_KEY API Key
'
######## Public functions ###################### Constants for your mijn-host API
MIJNHOST_API="https://mijn.host/api/v2"
# Add TXT record for domain verification
dns_mijnhost_add() {
fulldomain=$1
txtvalue=$2
MIJNHOST_API_KEY="${MIJNHOST_API_KEY:-$(_readaccountconf_mutable MIJNHOST_API_KEY)}"
if [ -z "$MIJNHOST_API_KEY" ]; then
MIJNHOST_API_KEY=""
_err "You haven't specified your mijn-host API key yet."
_err "Please add MIJNHOST_API_KEY to the env."
return 1
fi
# Save the API key for future use
_saveaccountconf_mutable MIJNHOST_API_KEY "$MIJNHOST_API_KEY"
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "Invalid domain"
return 1
fi
_debug2 _sub_domain "$_sub_domain"
_debug2 _domain "$_domain"
_debug "Adding DNS record" "${fulldomain}."
# Construct the API URL
api_url="$MIJNHOST_API/domains/$_domain/dns"
# Getting previous records
_mijnhost_rest GET "$api_url" ""
if [ "$_code" != "200" ]; then
_err "Error getting current DNS enties ($_code)"
return 1
fi
records=$(echo "$response" | _egrep_o '"records":\[.*\]' | sed 's/"records"://')
_debug2 "Current records" "$records"
# Build the payload for the API
data="{\"type\":\"TXT\",\"name\":\"$fulldomain.\",\"value\":\"$txtvalue\",\"ttl\":300}"
_debug2 "Record to add" "$data"
# Updating the records
updated_records=$(echo "$records" | sed -E "s/\]( *$)/,$data\]/")
_debug2 "Updated records" "$updated_records"
# data
data="{\"records\": $updated_records}"
_mijnhost_rest PUT "$api_url" "$data"
if [ "$_code" = "200" ]; then
_info "DNS record succesfully added."
return 0
else
_err "Error adding DNS record ($_code)."
return 1
fi
}
# Remove TXT record after verification
dns_mijnhost_rm() {
fulldomain=$1
txtvalue=$2
MIJNHOST_API_KEY="${MIJNHOST_API_KEY:-$(_readaccountconf_mutable MIJNHOST_API_KEY)}"
if [ -z "$MIJNHOST_API_KEY" ]; then
MIJNHOST_API_KEY=""
_err "You haven't specified your mijn-host API key yet."
_err "Please add MIJNHOST_API_KEY to the env."
return 1
fi
_debug "Detecting root zone for" "${fulldomain}."
if ! _get_root "$fulldomain"; then
_err "Invalid domain"
return 1
fi
_debug "Removing DNS record for TXT value" "${txtvalue}."
# Construct the API URL
api_url="$MIJNHOST_API/domains/$_domain/dns"
# Get current records
_mijnhost_rest GET "$api_url" ""
if [ "$_code" != "200" ]; then
_err "Error getting current DNS enties ($_code)"
return 1
fi
_debug2 "Get current records response:" "$response"
records=$(echo "$response" | _egrep_o '"records":\[.*\]' | sed 's/"records"://')
_debug2 "Current records:" "$records"
updated_records=$(echo "$records" | sed -E "s/\{[^}]*\"value\":\"$txtvalue\"[^}]*\},?//g" | sed 's/,]/]/g')
_debug2 "Updated records:" "$updated_records"
# Build the new payload
data="{\"records\": $updated_records}"
# Use the _put method to update the records
_mijnhost_rest PUT "$api_url" "$data"
if [ "$_code" = "200" ]; then
_info "DNS record removed successfully."
return 0
else
_err "Error removing DNS record ($_code)."
return 1
fi
}
# Helper function to detect the root zone
_get_root() {
domain=$1
# Get current records
_debug "Getting current domains"
_mijnhost_rest GET "$MIJNHOST_API/domains" ""
if [ "$_code" != "200" ]; then
_err "error getting current domains ($_code)"
return 1
fi
# Extract root domains from response
rootDomains=$(echo "$response" | _egrep_o '"domain":"[^"]*"' | sed -E 's/"domain":"([^"]*)"/\1/')
_debug "Root domains:" "$rootDomains"
for rootDomain in $rootDomains; do
if _contains "$domain" "$rootDomain"; then
_domain="$rootDomain"
_sub_domain=$(echo "$domain" | sed "s/.$rootDomain//g")
_debug "Found root domain" "$_domain" "and subdomain" "$_sub_domain" "for" "$domain"
return 0
fi
done
return 1
}
# Helper function for rest calls
_mijnhost_rest() {
m=$1
ep="$2"
data="$3"
MAX_REQUEST_RETRY_TIMES=15
_request_retry_times=0
_retry_sleep=5 #Initial sleep time in seconds.
while [ "${_request_retry_times}" -lt "$MAX_REQUEST_RETRY_TIMES" ]; do
_debug2 _request_retry_times "$_request_retry_times"
export _H1="API-Key: $MIJNHOST_API_KEY"
export _H2="Content-Type: application/json"
# clear headers from previous request to avoid getting wrong http code on timeouts
: >"$HTTP_HEADER"
_debug "$ep"
if [ "$m" != "GET" ]; then
_debug2 "data $data"
response="$(_post "$data" "$ep" "" "$m")"
else
response="$(_get "$ep")"
fi
_ret="$?"
_debug2 "response $response"
_code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")"
_debug "http response code $_code"
if [ "$_code" = "401" ]; then
# we have an invalid API token, maybe it is expired?
_err "Access denied. Invalid API token."
return 1
fi
if [ "$_ret" != "0" ] || [ -z "$_code" ] || [ "$_code" = "400" ] || _contains "$response" "DNS records not managed by mijn.host"; then #Sometimes API errors out
_request_retry_times="$(_math "$_request_retry_times" + 1)"
_info "REST call error $_code retrying $ep in ${_retry_sleep}s"
_sleep "$_retry_sleep"
_retry_sleep="$(_math "$_retry_sleep" \* 2)"
continue
fi
break
done
if [ "$_request_retry_times" = "$MAX_REQUEST_RETRY_TIMES" ]; then
_err "Error mijn.host API call was retried $MAX_REQUEST_RETRY_TIMES times."
_err "Calling $ep failed."
return 1
fi
response="$(echo "$response" | _normalizeJson)"
return 0
}
+2 -2
View File
@@ -116,7 +116,7 @@ _get_root() {
return 1
fi
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
_debug h "$h"
if [ -z "$h" ]; then
#not valid
@@ -124,7 +124,7 @@ _get_root() {
fi
if _contains "$response" "\"name\":\"$h\""; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain="$h"
return 0
fi
+6 -4
View File
@@ -1,12 +1,14 @@
#!/usr/bin/env sh
# shellcheck disable=SC2034
dns_myapi_info='Custom API Example
A sample custom DNS API script.
Domains: example.com
A sample custom DNS API script description.
Domains: example.com example.net
Site: github.com/acmesh-official/acme.sh/wiki/DNS-API-Dev-Guide
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_duckdns
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_myapi
Options:
MYAPI_Token API Token. Get API Token from https://example.com/api/. Optional.
MYAPI_Token API Token. Get API Token from https://example.com/api/
MYAPI_Variable2 Option 2. Default "default value".
MYAPI_Variable2 Option 3. Optional.
Issues: github.com/acmesh-official/acme.sh
Author: Neil Pang <neilgit@neilpang.com>
'
+2 -2
View File
@@ -126,7 +126,7 @@ _get_root() {
fi
while true; do
_domain=$(printf "%s" "$fulldomain" | cut -d . -f $i-100)
_domain=$(printf "%s" "$fulldomain" | cut -d . -f "$i"-100)
if [ -z "$_domain" ]; then
# not valid
@@ -134,7 +134,7 @@ _get_root() {
fi
if [ "$_domain" = "$_root_domain" ]; then
_sub_domain=$(printf "%s" "$fulldomain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$fulldomain" | cut -d . -f 1-"$p")
return 0
fi
+2 -2
View File
@@ -107,7 +107,7 @@ _get_root() {
_debug "Detect the root zone"
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
if [ -z "$h" ]; then
_err "Domain exhausted"
return 1
@@ -118,7 +118,7 @@ _get_root() {
_mb_rest GET "$h/records"
ret="$?"
if [ "$ret" -eq 0 ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain="$h"
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
+6 -6
View File
@@ -109,7 +109,7 @@ _get_root_by_getList() {
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
_debug h "$h"
if [ -z "$h" ]; then
#not valid
@@ -123,7 +123,7 @@ _get_root_by_getList() {
if ! _contains "$response" "$h"; then
_debug "$h not found"
else
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain="$h"
return 0
fi
@@ -137,14 +137,14 @@ _get_root_by_getHosts() {
i=100
p=99
while [ $p -ne 0 ]; do
while [ "$p" -ne 0 ]; do
h=$(printf "%s" "$1" | cut -d . -f $i-100)
h=$(printf "%s" "$1" | cut -d . -f "$i"-100)
if [ -n "$h" ]; then
if _contains "$h" "\\."; then
_debug h "$h"
if _namecheap_set_tld_sld "$h"; then
_sub_domain=$(printf "%s" "$1" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$1" | cut -d . -f 1-"$p")
_domain="$h"
return 0
else
@@ -378,7 +378,7 @@ _namecheap_set_tld_sld() {
while true; do
_tld=$(printf "%s" "$domain" | cut -d . -f $i-100)
_tld=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
_debug tld "$_tld"
if [ -z "$_tld" ]; then
+3 -3
View File
@@ -159,15 +159,15 @@ _namecom_get_root() {
# Need to exclude the last field (tld)
numfields=$(echo "$domain" | _egrep_o "\." | wc -l)
while [ $i -le "$numfields" ]; do
host=$(printf "%s" "$domain" | cut -d . -f $i-100)
while [ "$i" -le "$numfields" ]; do
host=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
_debug host "$host"
if [ -z "$host" ]; then
return 1
fi
if _contains "$response" "$host"; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain="$host"
return 0
fi
+3 -3
View File
@@ -109,15 +109,15 @@ _get_root() {
# Need to exclude the last field (tld)
numfields=$(echo "$domain" | _egrep_o "\." | wc -l)
while [ $i -le "$numfields" ]; do
host=$(printf "%s" "$domain" | cut -d . -f $i-100)
while [ "$i" -le "$numfields" ]; do
host=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
_debug host "$host"
if [ -z "$host" ]; then
return 1
fi
if _contains "$response" ">$host</domain>"; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain="$host"
return 0
fi
+2 -2
View File
@@ -88,8 +88,8 @@ _get_root() {
i=2
p=1
while true; do
_domain=$(printf "%s" "$domain" | cut -d . -f $i-100)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_domain=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_debug _domain "$_domain"
if [ -z "$_domain" ]; then
#not valid
+2 -2
View File
@@ -126,7 +126,7 @@ _get_root() {
i=2
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
_debug h "$h"
if [ -z "$h" ]; then
#not valid
@@ -142,7 +142,7 @@ _get_root() {
if _contains "$response" "\"name\":\"$h\"" >/dev/null; then
_domain_id=$(echo "$response" | _egrep_o "\"id\":\s*[0-9]+" | _head_n 1 | cut -d: -f2 | cut -d, -f1)
if [ "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain=$h
return 0
fi
+3 -3
View File
@@ -19,7 +19,7 @@ client=""
dns_netcup_add() {
_debug NC_Apikey "$NC_Apikey"
login
_login
if [ "$NC_Apikey" = "" ] || [ "$NC_Apipw" = "" ] || [ "$NC_CID" = "" ]; then
_err "No Credentials given"
return 1
@@ -61,7 +61,7 @@ dns_netcup_add() {
}
dns_netcup_rm() {
login
_login
fulldomain=$1
txtvalue=$2
@@ -125,7 +125,7 @@ dns_netcup_rm() {
logout
}
login() {
_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"
+2 -5
View File
@@ -55,8 +55,6 @@ dns_netlify_add() {
return 1
fi
_err "Not fully implemented!"
return 1
}
#Usage: dns_myapi_rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
@@ -95,7 +93,6 @@ dns_netlify_rm() {
_err "error removing validation value ($_code)"
return 1
fi
return 0
fi
return 1
}
@@ -111,7 +108,7 @@ _get_root() {
_netlify_rest GET "dns_zones" "" "$accesstoken"
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
_debug2 "Checking domain: $h"
if [ -z "$h" ]; then
#not valid
@@ -126,7 +123,7 @@ _get_root() {
#create the record at the domain apex (@) if only the domain name was provided as --domain-alias
_sub_domain="@"
else
_sub_domain=$(echo "$domain" | cut -d . -f 1-$p)
_sub_domain=$(echo "$domain" | cut -d . -f 1-"$p")
fi
_domain=$h
return 0
+1 -1
View File
@@ -169,7 +169,7 @@ _get_root() {
fi
if _contains "$_all_domains" "^$h$"; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain=$h
_service=$(printf "%s" "$response" | grep -m 1 "idn-name=\"$_domain\"" | sed -r "s/.*service=\"(.*)\".*$/\1/")
return 0
+2 -2
View File
@@ -126,7 +126,7 @@ _get_root() {
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
_debug h "$h"
if [ -z "$h" ]; then
#not valid
@@ -140,7 +140,7 @@ _get_root() {
if _contains "$response" "\"$h\""; then
_domain_returned=$(echo "$response" | _egrep_o "\{\"name\": *\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \" | tr -d " ")
if [ "$_domain_returned" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain=$h
return 0
fi
+2 -2
View File
@@ -119,7 +119,7 @@ _get_root() {
return 1
fi
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
_debug h "$h"
if [ -z "$h" ]; then
#not valid
@@ -127,7 +127,7 @@ _get_root() {
fi
if _contains "$response" "\"zone\":\"$h\""; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain="$h"
return 0
fi
+2 -2
View File
@@ -154,7 +154,7 @@ _get_root() {
_debug response "${response}"
while true; do
h=$(printf "%s" "${domain}" | cut -d . -f $i-100)
h=$(printf "%s" "${domain}" | cut -d . -f "$i"-100)
_debug h "${h}"
if [ -z "${h}" ]; then
#not valid
@@ -165,7 +165,7 @@ _get_root() {
if [ "${hostedzone}" ]; then
_zone_id=$(printf "%s\n" "${hostedzone}" | _egrep_o "\"zone_id\": *[0-9]+" | _head_n 1 | cut -d : -f 2 | tr -d \ )
if [ "${_zone_id}" ]; then
_sub_domain=$(printf "%s" "${domain}" | cut -d . -f 1-${p})
_sub_domain=$(printf "%s" "${domain}" | cut -d . -f 1-"${p}")
_domain="${h}"
return 0
fi
Loaded 100 of 141 files, more files were not shown because too many files have changed in this diff. Show more
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.