mirror of
https://github.com/acmesh-official/acme.sh.git
synced 2026-08-23 16:03:30 +08:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ef7b2d3c2e | ||
|
|
b481ffb81b | ||
|
|
b1a8eb1c95 | ||
|
|
e0c0297ba3 | ||
|
|
1cbd223386 | ||
|
|
5180911929 | ||
|
|
5ff7f0a4e7 |
20
.github/workflows/vtag.yml
vendored
20
.github/workflows/vtag.yml
vendored
@@ -23,10 +23,22 @@ jobs:
|
|||||||
- name: Create the v-prefixed tag
|
- name: Create the v-prefixed tag
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ github.token }}
|
GH_TOKEN: ${{ github.token }}
|
||||||
|
REPO: ${{ github.repository }}
|
||||||
|
TAG: ${{ github.ref_name }}
|
||||||
run: |
|
run: |
|
||||||
if gh api "repos/${{ github.repository }}/git/ref/tags/v${{ github.ref_name }}" >/dev/null 2>&1; then
|
if gh api "repos/$REPO/git/ref/tags/v$TAG" >/dev/null 2>&1; then
|
||||||
echo "Tag v${{ github.ref_name }} already exists, nothing to do."
|
echo "Tag v$TAG already exists, nothing to do."
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
gh api "repos/${{ github.repository }}/git/refs" -f ref="refs/tags/v${{ github.ref_name }}" -f sha="${{ github.sha }}"
|
# Mirror the object the pushed tag actually points at: the commit
|
||||||
echo "Created tag v${{ github.ref_name }} -> ${{ github.sha }}"
|
# for a lightweight tag, the tag object itself for an annotated or
|
||||||
|
# signed one. Pointing the mirror at the commit would strip the
|
||||||
|
# signature, so "git verify-tag v3.1.3" would fail while
|
||||||
|
# "git verify-tag 3.1.3" succeeds.
|
||||||
|
sha="$(gh api "repos/$REPO/git/ref/tags/$TAG" --jq .object.sha)"
|
||||||
|
if [ -z "$sha" ] || [ "$sha" = "null" ]; then
|
||||||
|
echo "Could not resolve refs/tags/$TAG"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
gh api "repos/$REPO/git/refs" -f ref="refs/tags/v$TAG" -f sha="$sha"
|
||||||
|
echo "Created tag v$TAG -> $sha"
|
||||||
|
|||||||
25
README.md
25
README.md
@@ -227,6 +227,31 @@ Cron entry example:
|
|||||||
acme.sh -h
|
acme.sh -h
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### 🔏 Verify a Release
|
||||||
|
|
||||||
|
Release tags from `3.1.5` on are signed with the maintainer's SSH key. The
|
||||||
|
signing happens on the maintainer's machine, so the private key is never
|
||||||
|
available to CI. The public half is [`allowed_signers`](allowed_signers) in
|
||||||
|
this repository. From a clone:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git config gpg.ssh.allowedSignersFile allowed_signers
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git verify-tag 3.1.5
|
||||||
|
```
|
||||||
|
|
||||||
|
The signature covers the tag object, which pins the commit and therefore the
|
||||||
|
whole tree, so a good signature verifies every file at that release and no
|
||||||
|
separate tarball checksum is needed. Build a tarball from the verified tag:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git archive --format=tar.gz --prefix=acme.sh-3.1.5/ 3.1.5 > acme.sh-3.1.5.tar.gz
|
||||||
|
```
|
||||||
|
|
||||||
|
> ⚠️ Tags up to `3.1.4` predate the signing key and are unsigned.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 2️⃣ Issue a Certificate
|
### 2️⃣ Issue a Certificate
|
||||||
|
|||||||
49
acme.sh
49
acme.sh
@@ -7072,6 +7072,30 @@ _uninstall_win_taskscheduler() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#binpath
|
||||||
|
#Reads a crontab listing from stdin, prints it without the acme.sh cron
|
||||||
|
#entries that call binpath.
|
||||||
|
_filter_cron_bin() {
|
||||||
|
_fcb_bin="$1"
|
||||||
|
if [ -z "$_fcb_bin" ]; then
|
||||||
|
cat
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
#a case pattern with a quoted variable matches binpath literally, which
|
||||||
|
#grep cannot do portably: Solaris /usr/bin/grep has no -F, and as a regex
|
||||||
|
#the dot of ~/.acme.sh would stand for any character
|
||||||
|
while IFS= read -r _fcb_line || [ -n "$_fcb_line" ]; do
|
||||||
|
case "$_fcb_line" in
|
||||||
|
*"$_fcb_bin --cron"*)
|
||||||
|
_debug3 "Dropping cron entry" "$_fcb_line"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "$_fcb_line"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
#confighome
|
#confighome
|
||||||
installcronjob() {
|
installcronjob() {
|
||||||
_c_home="$1"
|
_c_home="$1"
|
||||||
@@ -7141,7 +7165,26 @@ installcronjob() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
if ! echo "$_cron_entries" | grep "$PROJECT_ENTRY --cron"; then
|
#An entry that calls LE_WORKING_DIR/PROJECT_ENTRY is dead once that copy is
|
||||||
|
#gone: ACME_PACKAGED installs never write it, and the package manager
|
||||||
|
#removes it when it takes over. The entry below would then keep the install
|
||||||
|
#from adding a working one and cron would fail silently every day, so drop
|
||||||
|
#the stale entries first.
|
||||||
|
_cron_stale=""
|
||||||
|
if [ ! -f "$LE_WORKING_DIR/$PROJECT_ENTRY" ] && [ "$_cron_entries" ]; then
|
||||||
|
_cron_kept="$(echo "$_cron_entries" | _filter_cron_bin "\"$LE_WORKING_DIR\"/$PROJECT_ENTRY")"
|
||||||
|
if [ "$_cron_kept" != "$_cron_entries" ]; then
|
||||||
|
_info "Removing the cron job that calls the missing $LE_WORKING_DIR/$PROJECT_ENTRY"
|
||||||
|
_cron_entries="$_cron_kept"
|
||||||
|
_cron_stale=1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
#>/dev/null: grep would print the matching crontab line to the console
|
||||||
|
_cron_add=""
|
||||||
|
if ! echo "$_cron_entries" | grep "$PROJECT_ENTRY --cron" >/dev/null; then
|
||||||
|
_cron_add=1
|
||||||
|
fi
|
||||||
|
if [ "$_cron_add" ] || [ "$_cron_stale" ]; then
|
||||||
if _exists uname && uname -a | grep SunOS >/dev/null; then
|
if _exists uname && uname -a | grep SunOS >/dev/null; then
|
||||||
_CRONTAB_STDIN="$_CRONTAB --"
|
_CRONTAB_STDIN="$_CRONTAB --"
|
||||||
else
|
else
|
||||||
@@ -7151,7 +7194,9 @@ installcronjob() {
|
|||||||
if [ "$_cron_entries" ]; then
|
if [ "$_cron_entries" ]; then
|
||||||
echo "$_cron_entries"
|
echo "$_cron_entries"
|
||||||
fi
|
fi
|
||||||
echo "$_cron_entry"
|
if [ "$_cron_add" ]; then
|
||||||
|
echo "$_cron_entry"
|
||||||
|
fi
|
||||||
} | $_CRONTAB_STDIN
|
} | $_CRONTAB_STDIN
|
||||||
fi
|
fi
|
||||||
if [ "$?" != "0" ]; then
|
if [ "$?" != "0" ]; then
|
||||||
|
|||||||
20
allowed_signers
Normal file
20
allowed_signers
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# acme.sh release signing key.
|
||||||
|
#
|
||||||
|
# Release tags are signed with this key. Its private half is held by the
|
||||||
|
# maintainer and is never available to CI, so a compromise of the build
|
||||||
|
# pipeline cannot produce a tag that verifies against this file.
|
||||||
|
#
|
||||||
|
# Fingerprint: SHA256:M60qVafm/NUywQHXAkoQcj2v6KgkfrdSXv6mPejUUeE
|
||||||
|
#
|
||||||
|
# To verify a release tag, from a clone of this repository:
|
||||||
|
#
|
||||||
|
# git config gpg.ssh.allowedSignersFile allowed_signers
|
||||||
|
# git verify-tag 3.1.5
|
||||||
|
#
|
||||||
|
# A good signature covers the tag object, which pins the commit, which pins
|
||||||
|
# the whole tree -- so verifying the tag verifies every file at that
|
||||||
|
# release. Build a tarball from the verified tag with:
|
||||||
|
#
|
||||||
|
# git archive --format=tar.gz --prefix=acme.sh-3.1.5/ 3.1.5 > acme.sh-3.1.5.tar.gz
|
||||||
|
#
|
||||||
|
github@neilpang.com namespaces="git" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBTjI0HBJn3uhfT2DsNcFybfAZi3ADbIacMpz1BItKdB
|
||||||
@@ -1,24 +1,29 @@
|
|||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
# Deploy hook for UniFi OS Server (self-hosted).
|
# Deploy hook for UniFi OS, via the certificate REST API.
|
||||||
#
|
#
|
||||||
# Supports:
|
# Works against any UniFi OS whose management UI exposes
|
||||||
# - UniFi OS Server on macOS
|
# /api/userCertificates. Confirmed on:
|
||||||
# - UniFi OS Server on Linux
|
# - UniFi OS Server (the separately-installed, self-hosted application)
|
||||||
# - UniFi OS Server on Windows should also work (runs under WSL2), but
|
# on macOS and on Linux. Windows should also work (it runs under
|
||||||
# has not been tested.
|
# WSL2), but has not been tested.
|
||||||
|
# Tested on: Ubuntu 26.04 (remote) and macOS 26.6 (local).
|
||||||
|
# - UniFi OS hardware: UDM Pro on UniFi OS 5.1.26, UCG Fiber on
|
||||||
|
# UniFi OS 5.0.16 (user reports, see issues 7184 and 6916).
|
||||||
|
# No lower version bound is claimed -- if the UI has a certificate
|
||||||
|
# manager, this hook should work.
|
||||||
#
|
#
|
||||||
# Tested on: Ubuntu 26.04 (remote) and macOS 26.6 (local).
|
# `unifios` vs `unifi`: the split is the access method, not the product
|
||||||
|
# line. `unifi` writes files / a Java keystore and needs local or SSH
|
||||||
|
# access on the device; this hook drives the same REST API the web UI
|
||||||
|
# uses and works remotely. Use `unifi` where acme.sh runs on the device
|
||||||
|
# itself, this hook where it does not.
|
||||||
#
|
#
|
||||||
# This is a different product from the Cloud Key / UDM hardware and
|
# The API is served on the management port, which differs per install:
|
||||||
# self-hosted Unifi Controller covered by the `unifi` deploy hook above
|
# UniFi OS Server listens on 11443 (hence the default below), while
|
||||||
# (that hook already covers Cloud Key running UnifiOS v2.0.0+/Gen2/2+) --
|
# UniFi OS hardware serves it on 443 -- set DEPLOY_UNIFIOS_HOST to
|
||||||
# this hook targets the separately-installed, self-hosted "UniFi OS Server"
|
# "https://<host>" there.
|
||||||
# application instead, which stores certificates in its own Postgres
|
|
||||||
# database via a REST API rather than a Java keystore, so the `unifi`
|
|
||||||
# hook's approach does not apply here.
|
|
||||||
#
|
#
|
||||||
# UniFi OS Server exposes a REST API on its management port (default
|
# Endpoints used, all as the web UI itself calls them:
|
||||||
# 11443) that its own web UI uses for certificate management:
|
|
||||||
# POST /api/auth/login - session login (cookie + JWT)
|
# POST /api/auth/login - session login (cookie + JWT)
|
||||||
# GET /api/userCertificates - list uploaded certificates
|
# GET /api/userCertificates - list uploaded certificates
|
||||||
# POST /api/userCertificates - upload a new certificate
|
# POST /api/userCertificates - upload a new certificate
|
||||||
@@ -41,8 +46,9 @@
|
|||||||
# Uses core acme.sh helpers throughout (_post/_get, _json_encode,
|
# Uses core acme.sh helpers throughout (_post/_get, _json_encode,
|
||||||
# _durl_replace_base64, _dbase64, _egrep_o) rather than raw curl -k or
|
# _durl_replace_base64, _dbase64, _egrep_o) rather than raw curl -k or
|
||||||
# python3, so the wget fallback, --debug tracing, and CA_BUNDLE are all
|
# python3, so the wget fallback, --debug tracing, and CA_BUNDLE are all
|
||||||
# honored the same as every other hook. The management API's cert is
|
# honored the same as every other hook. The management API's cert may be
|
||||||
# self-signed (it's a management-only port, not meant for public exposure),
|
# self-signed -- it always is on a fresh install, and there is no reliable
|
||||||
|
# way to tell in advance whether an earlier run has already replaced it --
|
||||||
# so this hook sets HTTPS_INSECURE=1 itself, scoped to its own subshell (see
|
# so this hook sets HTTPS_INSECURE=1 itself, scoped to its own subshell (see
|
||||||
# acme.sh's per-hook sourcing in _deploy) -- it does not weaken TLS
|
# acme.sh's per-hook sourcing in _deploy) -- it does not weaken TLS
|
||||||
# verification for the rest of the acme.sh run, e.g. the connection to the
|
# verification for the rest of the acme.sh run, e.g. the connection to the
|
||||||
@@ -63,9 +69,11 @@
|
|||||||
#
|
#
|
||||||
# Settings:
|
# Settings:
|
||||||
# DEPLOY_UNIFIOS_HOST - base URL of the management API
|
# DEPLOY_UNIFIOS_HOST - base URL of the management API
|
||||||
# (default: "https://localhost:11443")
|
# (default: "https://localhost:11443", i.e. a UniFi OS Server on the
|
||||||
# DEPLOY_UNIFIOS_USERNAME - UniFi OS Server admin username (required)
|
# same machine as acme.sh; set it to "https://<host>" for UniFi OS
|
||||||
# DEPLOY_UNIFIOS_PASSWORD - UniFi OS Server admin password (required)
|
# hardware or any remote target)
|
||||||
|
# DEPLOY_UNIFIOS_USERNAME - UniFi OS admin username (required)
|
||||||
|
# DEPLOY_UNIFIOS_PASSWORD - UniFi OS admin password (required)
|
||||||
#
|
#
|
||||||
# Example:
|
# Example:
|
||||||
# export DEPLOY_UNIFIOS_USERNAME="acmeuser"
|
# export DEPLOY_UNIFIOS_USERNAME="acmeuser"
|
||||||
|
|||||||
@@ -75,6 +75,11 @@ dns_easydns_rm() {
|
|||||||
EASYDNS_Token="${EASYDNS_Token:-$(_readaccountconf_mutable EASYDNS_Token)}"
|
EASYDNS_Token="${EASYDNS_Token:-$(_readaccountconf_mutable EASYDNS_Token)}"
|
||||||
EASYDNS_Key="${EASYDNS_Key:-$(_readaccountconf_mutable EASYDNS_Key)}"
|
EASYDNS_Key="${EASYDNS_Key:-$(_readaccountconf_mutable EASYDNS_Key)}"
|
||||||
|
|
||||||
|
if [ -z "$EASYDNS_Token" ] || [ -z "$EASYDNS_Key" ]; then
|
||||||
|
_err "You didn't specify an easydns.net token or api key. Signup at https://cp.easydns.com/manage/security/api/signup.php"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
_debug "First detect the root zone"
|
_debug "First detect the root zone"
|
||||||
if ! _get_root "$fulldomain"; then
|
if ! _get_root "$fulldomain"; then
|
||||||
_err "invalid domain"
|
_err "invalid domain"
|
||||||
@@ -91,24 +96,21 @@ dns_easydns_rm() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
count=$(printf "%s\n" "$response" | _egrep_o "\"count\":[^,]*" | cut -d : -f 2)
|
record_id=$(printf "%s\n" "$response" | tr '{' '\n' | grep "\"rdata\":\"$txtvalue\"" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \")
|
||||||
_debug count "$count"
|
_debug "record_id" "$record_id"
|
||||||
if [ "$count" = "0" ]; then
|
|
||||||
|
if [ -z "$record_id" ]; then
|
||||||
_info "Don't need to remove."
|
_info "Don't need to remove."
|
||||||
else
|
return 0
|
||||||
record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | head -n 1)
|
|
||||||
_debug "record_id" "$record_id"
|
|
||||||
if [ -z "$record_id" ]; then
|
|
||||||
_err "Can not get record id to remove."
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
if ! _EASYDNS_rest DELETE "zones/records/$_domain/$record_id"; then
|
|
||||||
_err "Delete record error."
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
_contains "$response" "\"status\":200"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if ! _EASYDNS_rest DELETE "zones/records/$_domain/$record_id"; then
|
||||||
|
_err "Delete record error."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_contains "$response" "\"status\":200"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#################### Private functions below ##################################
|
#################### Private functions below ##################################
|
||||||
|
|||||||
121
dnsapi/dns_myloc.sh
Executable file
121
dnsapi/dns_myloc.sh
Executable file
@@ -0,0 +1,121 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
dns_myloc_info='myloc.de
|
||||||
|
Site: myloc.de
|
||||||
|
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_myloc
|
||||||
|
Issues: github.com/acmesh-official/acme.sh/issues/5193
|
||||||
|
Options:
|
||||||
|
MYLOC_token API token
|
||||||
|
'
|
||||||
|
|
||||||
|
# updater for the (experimental) API of myloc.de / webtropia.com
|
||||||
|
# usage: acme.sh --issue -d example.com --dns dns_myloc --dnssleep 60
|
||||||
|
# API documentation at https://apidoc.myloc.de/
|
||||||
|
# As the API does not support quering available zones yet, the zone for a given
|
||||||
|
# fulldomain is searched recursively by removing prefixes one-by-one.
|
||||||
|
|
||||||
|
_myloc_api="https://zkm.myloc.de/api"
|
||||||
|
|
||||||
|
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||||
|
dns_myloc_add() {
|
||||||
|
_myloc_fulldomain=$1
|
||||||
|
_myloc_txtvalue=$2
|
||||||
|
|
||||||
|
_myloc_token="${MYLOC_token:-$(_readaccountconf_mutable MYLOC_token)}"
|
||||||
|
if [ -z "$_myloc_token" ]; then
|
||||||
|
_err "You didn't specify MYLOC_token"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
export _H1="Content-Type: application/json"
|
||||||
|
export _H2="Authorization: Bearer $_myloc_token"
|
||||||
|
|
||||||
|
_myloc_zone="$(_myloc_get_zone "$_myloc_fulldomain")"
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# save token if the previous request was successful
|
||||||
|
_saveaccountconf_mutable MYLOC_token "$_myloc_token"
|
||||||
|
|
||||||
|
_info "Adding record"
|
||||||
|
_myloc_record="{\"type\":\"TXT\",\"name\":\"${_myloc_fulldomain}\",\"content\":\"\\\"${_myloc_txtvalue}\\\"\",\"ttl\":60}"
|
||||||
|
_debug "add record request $_myloc_record to ${_myloc_api}/dns/zone/${_myloc_zone}"
|
||||||
|
_myloc_response="$(_post "$_myloc_record" "${_myloc_api}/dns/zone/${_myloc_zone}" "" "PUT")"
|
||||||
|
_myloc_status=$?
|
||||||
|
_code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\r\n")"
|
||||||
|
_debug "add record response $_code $_myloc_response"
|
||||||
|
if [ $_myloc_status -ne 0 ]; then
|
||||||
|
_err "Add txt record curl error."
|
||||||
|
return 1
|
||||||
|
elif [ "$_code" = "204" ] && [ -z "$_myloc_response" ]; then
|
||||||
|
_info "Add txt record success"
|
||||||
|
return 0
|
||||||
|
elif _contains "$_myloc_response" "error" || _contains "$_myloc_response" "unexpected"; then
|
||||||
|
_err "Add txt record api error."
|
||||||
|
return 1
|
||||||
|
else
|
||||||
|
_err "Add txt record unknown response."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#_myloc_fulldomain _myloc_txtvalue
|
||||||
|
dns_myloc_rm() {
|
||||||
|
_myloc_fulldomain=$1
|
||||||
|
_myloc_txtvalue=$2
|
||||||
|
|
||||||
|
_myloc_token="${MYLOC_token:-$(_readaccountconf_mutable MYLOC_token)}"
|
||||||
|
if [ -z "$_myloc_token" ]; then
|
||||||
|
_err "You didn't specify MYLOC_token"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
export _H1="Content-Type: application/json"
|
||||||
|
export _H2="Authorization: Bearer $_myloc_token"
|
||||||
|
|
||||||
|
_myloc_zone="$(_myloc_get_zone "$_myloc_fulldomain")"
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# save token if the previous request was successful
|
||||||
|
_saveaccountconf_mutable MYLOC_token "$_myloc_token"
|
||||||
|
|
||||||
|
_info "Deleting record for $_myloc_fulldomain"
|
||||||
|
_myloc_record="{\"type\":\"TXT\",\"name\":\"${_myloc_fulldomain}\",\"content\":\"\\\"${_myloc_txtvalue}\\\"\"}"
|
||||||
|
_debug "delete record $_myloc_record"
|
||||||
|
_myloc_response="$(_post "$_myloc_record" "${_myloc_api}/dns/zone/${_myloc_zone}" "" "DELETE")"
|
||||||
|
_myloc_status=$?
|
||||||
|
_code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\r\n")"
|
||||||
|
_debug "delete response $_code $_myloc_response"
|
||||||
|
if [ $_myloc_status -ne 0 ] || [ "$_code" != "204" ]; then
|
||||||
|
_err "Failed to delete record"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Usage: _myloc_get_zone "_acme-challenge.sub1.mydomain.com"
|
||||||
|
# Subdomains are walked until a zone is found or TLD is reached
|
||||||
|
_myloc_get_zone() {
|
||||||
|
_myloc_zone=$1
|
||||||
|
|
||||||
|
while [ "${_myloc_zone#*.}" != "$_myloc_zone" ]; do
|
||||||
|
_debug "Get zone trying $_myloc_zone"
|
||||||
|
_myloc_response="$(_get "${_myloc_api}/dns/zone/${_myloc_zone}")"
|
||||||
|
_myloc_status=$?
|
||||||
|
_debug "Get zone response $_myloc_response"
|
||||||
|
_code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\r\n")"
|
||||||
|
if [ $_myloc_status -eq 0 ] && [ "$_code" = "200" ]; then
|
||||||
|
_debug "Get zone success for $_myloc_zone"
|
||||||
|
echo "${_myloc_zone}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
_myloc_zone="${_myloc_zone#*.}"
|
||||||
|
done
|
||||||
|
|
||||||
|
_err "Get zone failed for all candidates"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user