mirror of
https://github.com/acmesh-official/acme.sh.git
synced 2026-08-13 12:33:30 +02:00
Merge pull request #7008 from acmesh-official/dev
Some checks failed
DNS / CheckToken (push) Has been cancelled
DNS / Fail (push) Has been cancelled
DNS / Docker (push) Has been cancelled
DNS / MacOS (push) Has been cancelled
DNS / Windows (push) Has been cancelled
DNS / FreeBSD (push) Has been cancelled
DNS / OpenBSD (push) Has been cancelled
DNS / NetBSD (push) Has been cancelled
DNS / DragonFlyBSD (push) Has been cancelled
DNS / MidnightBSD (push) Has been cancelled
DNS / Solaris (push) Has been cancelled
DNS / Omnios (push) Has been cancelled
DNS / OpenIndiana (push) Has been cancelled
DNS / Tribblix (push) Has been cancelled
DNS / Haiku (push) Has been cancelled
DragonFlyBSD / DragonFlyBSD (, , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
FreeBSD / FreeBSD (, , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
FreeBSD / FreeBSD (1, , , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
Haiku / Haiku (, , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
Haiku / Haiku (1, , , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
Linux / Linux (almalinux:latest) (push) Has been cancelled
Linux / Linux (alpine:latest) (push) Has been cancelled
Linux / Linux (archlinux:latest) (push) Has been cancelled
Linux / Linux (debian:latest) (push) Has been cancelled
Linux / Linux (fedora:latest) (push) Has been cancelled
Linux / Linux (gentoo/stage3) (push) Has been cancelled
Linux / Linux (kalilinux/kali) (push) Has been cancelled
Linux / Linux (opensuse/leap:latest) (push) Has been cancelled
Linux / Linux (oraclelinux:8) (push) Has been cancelled
Linux / Linux (ubuntu:latest) (push) Has been cancelled
MacOS / MacOS (, , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
MidnightBSD / MidnightBSD (, , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
NetBSD / NetBSD (, , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
Omnios / Omnios (, , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
Omnios / Omnios (1, , , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
OpenBSD / OpenBSD (, , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
OpenBSD / OpenBSD (1, , , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
OpenIndiana / OpenIndiana (, , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
OpenIndiana / OpenIndiana (1, , , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
PebbleStrict / PebbleStrict (push) Has been cancelled
PebbleStrict / PebbleStrict_IPCert (push) Has been cancelled
Solaris / Solaris (, , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
Solaris / Solaris (1, , , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
Tribblix / Tribblix (, , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
Tribblix / Tribblix (1, , , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
Ubuntu / Ubuntu (, , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
Ubuntu / Ubuntu (1, , , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
Ubuntu / Ubuntu (Smallstep Intermediate CA, Smallstep Intermediate CA, , 1, https://localhost:9000/acme/acme/directory, ) (push) Has been cancelled
Ubuntu / Ubuntu (Smallstep Intermediate CA, Smallstep Intermediate CA, , 1, https://localhost:9000/acme/acme/directory, 1, , 172.17.0.1) (push) Has been cancelled
Ubuntu / Ubuntu (ZeroSSL RSA DV SSL CA 2, ZeroSSL ECC DV SSL CA 2, githubtest@acme.sh, ZeroSSL.com, ) (push) Has been cancelled
Windows / Windows (, , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
Build DockerHub / CheckToken (push) Has been cancelled
Build DockerHub / build (push) Has been cancelled
Shellcheck / ShellCheck (push) Has been cancelled
Shellcheck / shfmt (push) Has been cancelled
Some checks failed
DNS / CheckToken (push) Has been cancelled
DNS / Fail (push) Has been cancelled
DNS / Docker (push) Has been cancelled
DNS / MacOS (push) Has been cancelled
DNS / Windows (push) Has been cancelled
DNS / FreeBSD (push) Has been cancelled
DNS / OpenBSD (push) Has been cancelled
DNS / NetBSD (push) Has been cancelled
DNS / DragonFlyBSD (push) Has been cancelled
DNS / MidnightBSD (push) Has been cancelled
DNS / Solaris (push) Has been cancelled
DNS / Omnios (push) Has been cancelled
DNS / OpenIndiana (push) Has been cancelled
DNS / Tribblix (push) Has been cancelled
DNS / Haiku (push) Has been cancelled
DragonFlyBSD / DragonFlyBSD (, , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
FreeBSD / FreeBSD (, , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
FreeBSD / FreeBSD (1, , , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
Haiku / Haiku (, , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
Haiku / Haiku (1, , , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
Linux / Linux (almalinux:latest) (push) Has been cancelled
Linux / Linux (alpine:latest) (push) Has been cancelled
Linux / Linux (archlinux:latest) (push) Has been cancelled
Linux / Linux (debian:latest) (push) Has been cancelled
Linux / Linux (fedora:latest) (push) Has been cancelled
Linux / Linux (gentoo/stage3) (push) Has been cancelled
Linux / Linux (kalilinux/kali) (push) Has been cancelled
Linux / Linux (opensuse/leap:latest) (push) Has been cancelled
Linux / Linux (oraclelinux:8) (push) Has been cancelled
Linux / Linux (ubuntu:latest) (push) Has been cancelled
MacOS / MacOS (, , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
MidnightBSD / MidnightBSD (, , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
NetBSD / NetBSD (, , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
Omnios / Omnios (, , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
Omnios / Omnios (1, , , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
OpenBSD / OpenBSD (, , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
OpenBSD / OpenBSD (1, , , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
OpenIndiana / OpenIndiana (, , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
OpenIndiana / OpenIndiana (1, , , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
PebbleStrict / PebbleStrict (push) Has been cancelled
PebbleStrict / PebbleStrict_IPCert (push) Has been cancelled
Solaris / Solaris (, , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
Solaris / Solaris (1, , , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
Tribblix / Tribblix (, , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
Tribblix / Tribblix (1, , , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
Ubuntu / Ubuntu (, , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
Ubuntu / Ubuntu (1, , , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
Ubuntu / Ubuntu (Smallstep Intermediate CA, Smallstep Intermediate CA, , 1, https://localhost:9000/acme/acme/directory, ) (push) Has been cancelled
Ubuntu / Ubuntu (Smallstep Intermediate CA, Smallstep Intermediate CA, , 1, https://localhost:9000/acme/acme/directory, 1, , 172.17.0.1) (push) Has been cancelled
Ubuntu / Ubuntu (ZeroSSL RSA DV SSL CA 2, ZeroSSL ECC DV SSL CA 2, githubtest@acme.sh, ZeroSSL.com, ) (push) Has been cancelled
Windows / Windows (, , , LetsEncrypt.org_test, (STAGING)) (push) Has been cancelled
Build DockerHub / CheckToken (push) Has been cancelled
Build DockerHub / build (push) Has been cancelled
Shellcheck / ShellCheck (push) Has been cancelled
Shellcheck / shfmt (push) Has been cancelled
sync
This commit is contained in:
commit
3c848adbb7
9 changed files with 541 additions and 295 deletions
58
.github/workflows/DNS.yml
vendored
58
.github/workflows/DNS.yml
vendored
|
|
@ -661,9 +661,65 @@ jobs:
|
|||
|
||||
|
||||
|
||||
Haiku:
|
||||
Tribblix:
|
||||
runs-on: ubuntu-latest
|
||||
needs: OpenIndiana
|
||||
env:
|
||||
TEST_DNS : ${{ secrets.TEST_DNS }}
|
||||
TestingDomain: ${{ secrets.TestingDomain }}
|
||||
TEST_DNS_NO_WILDCARD: ${{ secrets.TEST_DNS_NO_WILDCARD }}
|
||||
TEST_DNS_NO_SUBDOMAIN: ${{ secrets.TEST_DNS_NO_SUBDOMAIN }}
|
||||
TEST_DNS_SLEEP: ${{ secrets.TEST_DNS_SLEEP }}
|
||||
CASE: le_test_dnsapi
|
||||
TEST_LOCAL: 1
|
||||
DEBUG: ${{ secrets.DEBUG }}
|
||||
http_proxy: ${{ secrets.http_proxy }}
|
||||
https_proxy: ${{ secrets.https_proxy }}
|
||||
HTTPS_INSECURE: 1 # always set to 1 to ignore https error, since Tribblix doesn't accept the expired ISRG X1 root
|
||||
TokenName1: ${{ secrets.TokenName1}}
|
||||
TokenName2: ${{ secrets.TokenName2}}
|
||||
TokenName3: ${{ secrets.TokenName3}}
|
||||
TokenName4: ${{ secrets.TokenName4}}
|
||||
TokenName5: ${{ secrets.TokenName5}}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Clone acmetest
|
||||
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||
- uses: vmactions/tribblix-vm@v1
|
||||
with:
|
||||
debug-on-error: ${{ vars.DEBUG_ON_ERROR }}
|
||||
envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_NO_SUBDOMAIN TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG http_proxy https_proxy HTTPS_INSECURE TokenName1 TokenName2 TokenName3 TokenName4 TokenName5 ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}'
|
||||
sync: nfs
|
||||
prepare: zap install socat
|
||||
run: |
|
||||
if [ "${{ secrets.TokenName1}}" ] ; then
|
||||
export ${{ secrets.TokenName1}}="${{ secrets.TokenValue1}}"
|
||||
fi
|
||||
if [ "${{ secrets.TokenName2}}" ] ; then
|
||||
export ${{ secrets.TokenName2}}="${{ secrets.TokenValue2}}"
|
||||
fi
|
||||
if [ "${{ secrets.TokenName3}}" ] ; then
|
||||
export ${{ secrets.TokenName3}}="${{ secrets.TokenValue3}}"
|
||||
fi
|
||||
if [ "${{ secrets.TokenName4}}" ] ; then
|
||||
export ${{ secrets.TokenName4}}="${{ secrets.TokenValue4}}"
|
||||
fi
|
||||
if [ "${{ secrets.TokenName5}}" ] ; then
|
||||
export ${{ secrets.TokenName5}}="${{ secrets.TokenValue5}}"
|
||||
fi
|
||||
cd ../acmetest
|
||||
./letest.sh
|
||||
- name: DebugOnError
|
||||
if: ${{ failure() }}
|
||||
run: |
|
||||
echo "See how to debug in VM:"
|
||||
echo "https://github.com/acmesh-official/acme.sh/wiki/debug-in-VM"
|
||||
|
||||
|
||||
|
||||
Haiku:
|
||||
runs-on: ubuntu-latest
|
||||
needs: Tribblix
|
||||
env:
|
||||
TEST_DNS : ${{ secrets.TEST_DNS }}
|
||||
TestingDomain: ${{ secrets.TestingDomain }}
|
||||
|
|
|
|||
79
.github/workflows/Tribblix.yml
vendored
Normal file
79
.github/workflows/Tribblix.yml
vendored
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
name: Tribblix
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- '*'
|
||||
paths:
|
||||
- '*.sh'
|
||||
- '.github/workflows/Tribblix.yml'
|
||||
|
||||
pull_request:
|
||||
branches:
|
||||
- dev
|
||||
paths:
|
||||
- '*.sh'
|
||||
- '.github/workflows/Tribblix.yml'
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
|
||||
|
||||
jobs:
|
||||
Tribblix:
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- TEST_ACME_Server: "LetsEncrypt.org_test"
|
||||
CA_ECDSA: ""
|
||||
CA: ""
|
||||
CA_EMAIL: ""
|
||||
TEST_PREFERRED_CHAIN: (STAGING)
|
||||
- TEST_ACME_Server: "LetsEncrypt.org_test"
|
||||
CA_ECDSA: ""
|
||||
CA: ""
|
||||
CA_EMAIL: ""
|
||||
TEST_PREFERRED_CHAIN: (STAGING)
|
||||
ACME_USE_WGET: 1
|
||||
#- TEST_ACME_Server: "ZeroSSL.com"
|
||||
# CA_ECDSA: "ZeroSSL ECC DV SSL CA 2"
|
||||
# CA: "ZeroSSL RSA DV SSL CA 2"
|
||||
# CA_EMAIL: "githubtest@acme.sh"
|
||||
# TEST_PREFERRED_CHAIN: ""
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
TEST_LOCAL: 1
|
||||
TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }}
|
||||
CA_ECDSA: ${{ matrix.CA_ECDSA }}
|
||||
CA: ${{ matrix.CA }}
|
||||
CA_EMAIL: ${{ matrix.CA_EMAIL }}
|
||||
TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }}
|
||||
ACME_USE_WGET: ${{ matrix.ACME_USE_WGET }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: anyvm-org/cf-tunnel@v0
|
||||
id: tunnel
|
||||
with:
|
||||
protocol: http
|
||||
port: 8080
|
||||
- name: Set envs
|
||||
run: echo "TestingDomain=${{steps.tunnel.outputs.server}}" >> $GITHUB_ENV
|
||||
- name: Clone acmetest
|
||||
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||
- uses: vmactions/tribblix-vm@v1
|
||||
with:
|
||||
debug-on-error: ${{ vars.DEBUG_ON_ERROR }}
|
||||
envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN ACME_USE_WGET'
|
||||
nat: |
|
||||
"8080": "80"
|
||||
prepare: zap install socat curl wget
|
||||
sync: nfs
|
||||
run: |
|
||||
cd ../acmetest \
|
||||
&& ./letest.sh
|
||||
- name: DebugOnError
|
||||
if: ${{ failure() }}
|
||||
run: |
|
||||
echo "See how to debug in VM:"
|
||||
echo "https://github.com/acmesh-official/acme.sh/wiki/debug-in-VM"
|
||||
14
.github/workflows/dockerhub.yml
vendored
14
.github/workflows/dockerhub.yml
vendored
|
|
@ -41,6 +41,9 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
needs: CheckToken
|
||||
if: "contains(needs.CheckToken.outputs.hasToken, 'true')"
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
steps:
|
||||
- name: checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
|
@ -58,6 +61,9 @@ jobs:
|
|||
- name: login to docker hub
|
||||
run: |
|
||||
echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin
|
||||
- name: login to ghcr
|
||||
run: |
|
||||
echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin
|
||||
- name: build and push the image
|
||||
run: |
|
||||
if [[ $GITHUB_REF == refs/tags/* ]]; then
|
||||
|
|
@ -73,6 +79,8 @@ jobs:
|
|||
fi
|
||||
fi
|
||||
|
||||
echo "DOCKER_IMAGE_TAG=${DOCKER_IMAGE_TAG}" >>"$GITHUB_ENV"
|
||||
|
||||
DOCKER_LABELS=()
|
||||
while read -r label; do
|
||||
DOCKER_LABELS+=(--label "${label}")
|
||||
|
|
@ -84,3 +92,9 @@ jobs:
|
|||
--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 .
|
||||
- name: mirror the image to ghcr (best-effort)
|
||||
run: |
|
||||
docker buildx imagetools create \
|
||||
--tag ghcr.io/${{ github.repository }}:${DOCKER_IMAGE_TAG} \
|
||||
${DOCKER_IMAGE}:${DOCKER_IMAGE_TAG} \
|
||||
|| echo "::warning::GHCR mirror failed; Docker Hub publish unaffected"
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
<a href="https://github.com/acmesh-official/acme.sh/actions/workflows/MidnightBSD.yml"><img src="https://github.com/acmesh-official/acme.sh/actions/workflows/MidnightBSD.yml/badge.svg" alt="MidnightBSD"></a>
|
||||
<a href="https://github.com/acmesh-official/acme.sh/actions/workflows/Omnios.yml"><img src="https://github.com/acmesh-official/acme.sh/actions/workflows/Omnios.yml/badge.svg" alt="Omnios"></a>
|
||||
<a href="https://github.com/acmesh-official/acme.sh/actions/workflows/OpenIndiana.yml"><img src="https://github.com/acmesh-official/acme.sh/actions/workflows/OpenIndiana.yml/badge.svg" alt="OpenIndiana"></a>
|
||||
<a href="https://github.com/acmesh-official/acme.sh/actions/workflows/Tribblix.yml"><img src="https://github.com/acmesh-official/acme.sh/actions/workflows/Tribblix.yml/badge.svg" alt="Tribblix"></a>
|
||||
<a href="https://github.com/acmesh-official/acme.sh/actions/workflows/Haiku.yml"><img src="https://github.com/acmesh-official/acme.sh/actions/workflows/Haiku.yml/badge.svg" alt="Haiku"></a>
|
||||
</p>
|
||||
|
||||
|
|
@ -112,6 +113,7 @@
|
|||
|23|-----| OpenWRT: Tested and working. See [wiki page](https://github.com/acmesh-official/acme.sh/wiki/How-to-run-on-OpenWRT)
|
||||
|24|[](https://github.com/acmesh-official/letest#here-are-the-latest-status)| Proxmox: See Proxmox VE Wiki. Version [4.x, 5.0, 5.1](https://pve.proxmox.com/wiki/HTTPS_Certificate_Configuration_(Version_4.x,_5.0_and_5.1)#Let.27s_Encrypt_using_acme.sh), version [5.2 and up](https://pve.proxmox.com/wiki/Certificate_Management)
|
||||
|25|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Haiku.yml)|Haiku OS
|
||||
|26|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Tribblix.yml)|Tribblix
|
||||
|
||||
|
||||
> 🧪 Check our [testing project](https://github.com/acmesh-official/acmetest)
|
||||
|
|
|
|||
6
acme.sh
6
acme.sh
|
|
@ -4895,7 +4895,7 @@ issue() {
|
|||
# (Let's Encrypt) may also reject with a malformed error if the prior cert
|
||||
# was issued by a different issuer / different CA. Retry without "replaces"
|
||||
# whenever the failure mentions ARI or the replaces field.
|
||||
if [ "$_replaces_certID" ] && { _contains "$response" "alreadyReplaced" || _contains "$response" "'replaces'" || _contains "$response" "ARI"; }; then
|
||||
if [ "$_replaces_certID" ] && { _contains "$response" "alreadyReplaced" || _contains "$response" "urn:ietf:params:acme:error:malformed" || _contains "$response" "'replaces'" || _contains "$response" "ARI"; }; then
|
||||
_info "ARI 'replaces' rejected by CA, retrying newOrder without 'replaces'."
|
||||
if ! _send_signed_request "$ACME_NEW_ORDER" "$_newOrderObj}"; then
|
||||
_err "Error creating new order."
|
||||
|
|
@ -5785,7 +5785,7 @@ renew() {
|
|||
_debug "_renewServer" "$_renewServer"
|
||||
|
||||
_initpath "$Le_Domain" "$_isEcc"
|
||||
|
||||
_info "Renew: $Le_Domain"
|
||||
_set_level=${NOTIFY_LEVEL:-$NOTIFY_LEVEL_DEFAULT}
|
||||
_info "$(__green "Renewing: '$Le_Domain'")"
|
||||
if [ ! -f "$DOMAIN_CONF" ]; then
|
||||
|
|
@ -6865,7 +6865,7 @@ deactivate() {
|
|||
#cert
|
||||
_getAKI() {
|
||||
_cert="$1"
|
||||
${ACME_OPENSSL_BIN:-openssl} x509 -in "$_cert" -text -noout | grep "X509v3 Authority Key Identifier" -A 1 | _tail_n 1 | tr -d ': ' | sed "s/keyid//"
|
||||
${ACME_OPENSSL_BIN:-openssl} x509 -in "$_cert" -text -noout | grep -A 1 "X509v3 Authority Key Identifier" | _tail_n 1 | tr -d ': ' | sed "s/keyid//"
|
||||
}
|
||||
|
||||
#cert
|
||||
|
|
|
|||
|
|
@ -1,256 +0,0 @@
|
|||
#!/usr/bin/env sh
|
||||
# shellcheck disable=SC2034
|
||||
dns_hetzner_info='Hetzner.com
|
||||
Site: Hetzner.com
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_hetzner
|
||||
Options:
|
||||
HETZNER_Token API Token
|
||||
Issues: github.com/acmesh-official/acme.sh/issues/2943
|
||||
'
|
||||
|
||||
HETZNER_Api="https://dns.hetzner.com/api/v1"
|
||||
|
||||
######## Public functions #####################
|
||||
|
||||
# Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
# Used to add txt record
|
||||
# Ref: https://dns.hetzner.com/api-docs/
|
||||
dns_hetzner_add() {
|
||||
full_domain=$1
|
||||
txt_value=$2
|
||||
|
||||
HETZNER_Token="${HETZNER_Token:-$(_readaccountconf_mutable HETZNER_Token)}"
|
||||
|
||||
if [ -z "$HETZNER_Token" ]; then
|
||||
HETZNER_Token=""
|
||||
_err "You didn't specify a Hetzner api token."
|
||||
_err "You can get yours from here https://dns.hetzner.com/settings/api-token."
|
||||
return 1
|
||||
fi
|
||||
|
||||
#save the api key and email to the account conf file.
|
||||
_saveaccountconf_mutable HETZNER_Token "$HETZNER_Token"
|
||||
|
||||
_debug "First detect the root zone"
|
||||
|
||||
if ! _get_root "$full_domain"; then
|
||||
_err "Invalid domain"
|
||||
return 1
|
||||
fi
|
||||
_debug _domain_id "$_domain_id"
|
||||
_debug _sub_domain "$_sub_domain"
|
||||
_debug _domain "$_domain"
|
||||
|
||||
_debug "Getting TXT records"
|
||||
if ! _find_record "$_sub_domain" "$txt_value"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ -z "$_record_id" ]; then
|
||||
_info "Adding record"
|
||||
if _hetzner_rest POST "records" "{\"zone_id\":\"${HETZNER_Zone_ID}\",\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"value\":\"$txt_value\",\"ttl\":120}"; then
|
||||
if _contains "$response" "$txt_value"; then
|
||||
_info "Record added, OK"
|
||||
_sleep 2
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
_err "Add txt record error${_response_error}"
|
||||
return 1
|
||||
else
|
||||
_info "Found record id: $_record_id."
|
||||
_info "Record found, do nothing."
|
||||
return 0
|
||||
# we could modify a record, if the names for txt records for *.example.com and example.com would be not the same
|
||||
#if _hetzner_rest PUT "records/${_record_id}" "{\"zone_id\":\"${HETZNER_Zone_ID}\",\"type\":\"TXT\",\"name\":\"$full_domain\",\"value\":\"$txt_value\",\"ttl\":120}"; then
|
||||
# if _contains "$response" "$txt_value"; then
|
||||
# _info "Modified, OK"
|
||||
# return 0
|
||||
# fi
|
||||
#fi
|
||||
#_err "Add txt record error (modify)."
|
||||
#return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Usage: full_domain txt_value
|
||||
# Used to remove the txt record after validation
|
||||
dns_hetzner_rm() {
|
||||
full_domain=$1
|
||||
txt_value=$2
|
||||
|
||||
HETZNER_Token="${HETZNER_Token:-$(_readaccountconf_mutable HETZNER_Token)}"
|
||||
|
||||
_debug "First detect the root zone"
|
||||
if ! _get_root "$full_domain"; then
|
||||
_err "Invalid domain"
|
||||
return 1
|
||||
fi
|
||||
_debug _domain_id "$_domain_id"
|
||||
_debug _sub_domain "$_sub_domain"
|
||||
_debug _domain "$_domain"
|
||||
|
||||
_debug "Getting TXT records"
|
||||
if ! _find_record "$_sub_domain" "$txt_value"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ -z "$_record_id" ]; then
|
||||
_info "Remove not needed. Record not found."
|
||||
else
|
||||
if ! _hetzner_rest DELETE "records/$_record_id"; then
|
||||
_err "Delete record error${_response_error}"
|
||||
return 1
|
||||
fi
|
||||
_sleep 2
|
||||
_info "Record deleted"
|
||||
fi
|
||||
}
|
||||
|
||||
#################### Private functions below ##################################
|
||||
#returns
|
||||
# _record_id=a8d58f22d6931bf830eaa0ec6464bf81 if found; or 1 if error
|
||||
_find_record() {
|
||||
unset _record_id
|
||||
_record_name=$1
|
||||
_record_value=$2
|
||||
|
||||
if [ -z "$_record_value" ]; then
|
||||
_record_value='[^"]*'
|
||||
fi
|
||||
|
||||
_debug "Getting all records"
|
||||
_hetzner_rest GET "records?zone_id=${_domain_id}"
|
||||
|
||||
if _response_has_error; then
|
||||
_err "Error${_response_error}"
|
||||
return 1
|
||||
else
|
||||
_record_id=$(
|
||||
echo "$response" |
|
||||
grep -o "{[^\{\}]*\"name\":\"$_record_name\"[^\}]*}" |
|
||||
grep "\"value\":\"$_record_value\"" |
|
||||
while read -r record; do
|
||||
# test for type and
|
||||
if [ -n "$(echo "$record" | _egrep_o '"type":"TXT"')" ]; then
|
||||
echo "$record" | _egrep_o '"id":"[^"]*"' | cut -d : -f 2 | tr -d \"
|
||||
break
|
||||
fi
|
||||
done
|
||||
)
|
||||
fi
|
||||
}
|
||||
|
||||
#_acme-challenge.www.domain.com
|
||||
#returns
|
||||
# _sub_domain=_acme-challenge.www
|
||||
# _domain=domain.com
|
||||
# _domain_id=sdjkglgdfewsdfg
|
||||
_get_root() {
|
||||
domain=$1
|
||||
i=1
|
||||
p=1
|
||||
|
||||
domain_without_acme=$(echo "$domain" | cut -d . -f 2-)
|
||||
domain_param_name=$(echo "HETZNER_Zone_ID_for_${domain_without_acme}" | sed 's/[\.\-]/_/g')
|
||||
|
||||
_debug "Reading zone_id for '$domain_without_acme' from config..."
|
||||
HETZNER_Zone_ID=$(_readdomainconf "$domain_param_name")
|
||||
if [ "$HETZNER_Zone_ID" ]; then
|
||||
_debug "Found, using: $HETZNER_Zone_ID"
|
||||
if ! _hetzner_rest GET "zones/${HETZNER_Zone_ID}"; then
|
||||
_debug "Zone with id '$HETZNER_Zone_ID' does not exist."
|
||||
_cleardomainconf "$domain_param_name"
|
||||
unset HETZNER_Zone_ID
|
||||
else
|
||||
if _contains "$response" "\"id\":\"$HETZNER_Zone_ID\""; then
|
||||
_domain=$(printf "%s\n" "$response" | _egrep_o '"name":"[^"]*"' | cut -d : -f 2 | tr -d \" | head -n 1)
|
||||
if [ "$_domain" ]; then
|
||||
_cut_length=$((${#domain} - ${#_domain} - 1))
|
||||
_sub_domain=$(printf "%s" "$domain" | cut -c "1-$_cut_length")
|
||||
_domain_id="$HETZNER_Zone_ID"
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
_debug "Trying to get zone id by domain name for '$domain_without_acme'."
|
||||
while true; do
|
||||
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
|
||||
if [ -z "$h" ]; then
|
||||
#not valid
|
||||
return 1
|
||||
fi
|
||||
_debug h "$h"
|
||||
|
||||
_hetzner_rest GET "zones?name=$h"
|
||||
|
||||
if _contains "$response" "\"name\":\"$h\"" || _contains "$response" '"total_entries":1'; then
|
||||
_domain_id=$(echo "$response" | _egrep_o "\[.\"id\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \")
|
||||
if [ "$_domain_id" ]; then
|
||||
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
|
||||
_domain=$h
|
||||
HETZNER_Zone_ID=$_domain_id
|
||||
_savedomainconf "$domain_param_name" "$HETZNER_Zone_ID"
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
p=$i
|
||||
i=$(_math "$i" + 1)
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
#returns
|
||||
# _response_error
|
||||
_response_has_error() {
|
||||
unset _response_error
|
||||
|
||||
err_part="$(echo "$response" | _egrep_o '"error":\{[^\}]*\}')"
|
||||
|
||||
if [ -n "$err_part" ]; then
|
||||
err_code=$(echo "$err_part" | _egrep_o '"code":[0-9]+' | cut -d : -f 2)
|
||||
err_message=$(echo "$err_part" | _egrep_o '"message":"[^"]+"' | cut -d : -f 2 | tr -d \")
|
||||
|
||||
if [ -n "$err_code" ] && [ -n "$err_message" ]; then
|
||||
_response_error=" - message: ${err_message}, code: ${err_code}"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
#returns
|
||||
# response
|
||||
_hetzner_rest() {
|
||||
m=$1
|
||||
ep="$2"
|
||||
data="$3"
|
||||
_debug "$ep"
|
||||
|
||||
key_trimmed=$(echo "$HETZNER_Token" | tr -d \")
|
||||
|
||||
export _H1="Content-TType: application/json"
|
||||
export _H2="Auth-API-Token: $key_trimmed"
|
||||
|
||||
if [ "$m" != "GET" ]; then
|
||||
_debug data "$data"
|
||||
response="$(_post "$data" "$HETZNER_Api/$ep" "" "$m")"
|
||||
else
|
||||
response="$(_get "$HETZNER_Api/$ep")"
|
||||
fi
|
||||
|
||||
if [ "$?" != "0" ] || _response_has_error; then
|
||||
_debug "Error$_response_error"
|
||||
return 1
|
||||
fi
|
||||
_debug2 response "$response"
|
||||
return 0
|
||||
}
|
||||
91
dnsapi/dns_ipprojects.sh
Normal file
91
dnsapi/dns_ipprojects.sh
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
#!/usr/bin/env sh
|
||||
# shellcheck disable=SC2034
|
||||
dns_ipprojects_info='IP-Projects DNS
|
||||
Site: ip-projects.de/
|
||||
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_ipprojects
|
||||
Options:
|
||||
IPP_Apikey API Key
|
||||
Issues: github.com/acmesh-official/acme.sh/issues/6958
|
||||
Author: Markus Ebner
|
||||
'
|
||||
|
||||
IPP_Apikey="${IPP_Apikey:-$(_readaccountconf_mutable IPP_Apikey)}"
|
||||
IPP_API="https://api.ip-projects.de/v1/dns/acme"
|
||||
|
||||
######## Public functions ########
|
||||
|
||||
dns_ipprojects_add() {
|
||||
fulldomain="$1"
|
||||
txtvalue="$2"
|
||||
|
||||
_info "Using IP-Projects DNS API to add record"
|
||||
_debug fulldomain "$fulldomain"
|
||||
_debug txtvalue "$txtvalue"
|
||||
|
||||
if ! _IPP_load_credentials; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
_IPP_api_request "add" "$fulldomain" "$txtvalue"
|
||||
}
|
||||
|
||||
dns_ipprojects_rm() {
|
||||
fulldomain="$1"
|
||||
txtvalue="$2"
|
||||
|
||||
_info "Using IP-Projects DNS API to remove record"
|
||||
_debug fulldomain "$fulldomain"
|
||||
_debug txtvalue "$txtvalue"
|
||||
|
||||
if ! _IPP_load_credentials; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
_IPP_api_request "remove" "$fulldomain" "$txtvalue"
|
||||
}
|
||||
|
||||
######## Private helpers ########
|
||||
|
||||
_IPP_load_credentials() {
|
||||
IPP_Apikey="${IPP_Apikey:-$(_readaccountconf_mutable IPP_Apikey)}"
|
||||
|
||||
if [ -z "$IPP_Apikey" ]; then
|
||||
_err "You must export IPP_Apikey"
|
||||
_err "e.g.: export IPP_Apikey=\"your_api_key\""
|
||||
return 1
|
||||
fi
|
||||
|
||||
_saveaccountconf_mutable IPP_Apikey "$IPP_Apikey"
|
||||
return 0
|
||||
}
|
||||
|
||||
_IPP_api_request() {
|
||||
action="$1"
|
||||
domain="$2"
|
||||
value="$3"
|
||||
|
||||
url="$IPP_API/$action"
|
||||
|
||||
data="{\"domain\":\"$domain\",\"key\":\"$domain\",\"value\":\"$value\"}"
|
||||
_debug url "$url"
|
||||
_debug data "$data"
|
||||
export _H1="X-API-Key: $IPP_Apikey"
|
||||
|
||||
response="$(_post "$data" "$url" "" "POST" "application/json")"
|
||||
ret="$?"
|
||||
_ipprojects_last_http_code=$(grep "^HTTP" "${HTTP_HEADER}" | _tail_n 1 | cut -d " " -f 2 | tr -d '\r\n')
|
||||
|
||||
_debug response "$response"
|
||||
|
||||
if [ "$ret" != "0" ]; then
|
||||
_err "HTTP request failed"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ "$_ipprojects_last_http_code" != "200" ]; then
|
||||
_err "API returned an error [code: ${_ipprojects_last_http_code}]"
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
238
dnsapi/dns_poweradmin.sh
Normal file
238
dnsapi/dns_poweradmin.sh
Normal file
|
|
@ -0,0 +1,238 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
# shellcheck disable=SC2034
|
||||
|
||||
# Credits to the authors of dnsapi/dns_pdns.sh as this reuses much of that code.
|
||||
|
||||
dns_poweradmin_info='Poweradmin API
|
||||
Site: https://www.poweradmin.org/
|
||||
Docs: https://github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_poweradmin
|
||||
Options:
|
||||
POWERADMIN_URL API URL (with scheme). E.g. "https://poweradmin.example.com" or "http://192.168.0.10:8080"
|
||||
POWERADMIN_API_KEY API Token "pwa_xxxx"
|
||||
POWERADMIN_API_VERSION Optionally override Poweradmin API version.
|
||||
Issues: https://github.com/acmesh-official/acme.sh/issues/6912
|
||||
Author: Jakob Næss <https://github.com/InvisibleDuck>
|
||||
'
|
||||
|
||||
######## Public functions ####################
|
||||
|
||||
# Usage: dns_poweradmin_add _acme-challenge.www.domain.com "123456789ABCDEF"
|
||||
# fulldomain
|
||||
# txtvalue
|
||||
dns_poweradmin_add() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
|
||||
POWERADMIN_URL="${POWERADMIN_URL:-$(_readaccountconf_mutable POWERADMIN_URL)}"
|
||||
POWERADMIN_API_KEY="${POWERADMIN_API_KEY:-$(_readaccountconf_mutable POWERADMIN_API_KEY)}"
|
||||
POWERADMIN_API_VERSION="${POWERADMIN_API_VERSION:-$(_readaccountconf_mutable POWERADMIN_API_VERSION)}"
|
||||
POWERADMIN_API_VERSION="${POWERADMIN_API_VERSION:-2}"
|
||||
|
||||
if [ -z "$POWERADMIN_URL" ]; then
|
||||
POWERADMIN_URL=""
|
||||
_err "You didn't specify Poweradmin URL."
|
||||
_err "Please set POWERADMIN_URL and try again."
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ -z "$POWERADMIN_API_KEY" ]; then
|
||||
POWERADMIN_API_KEY=""
|
||||
_err "You didn't specify Poweradmin token."
|
||||
_err "Please set POWERADMIN_API_KEY and try again."
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Save the api addr, key, and version to the account conf file.
|
||||
_saveaccountconf_mutable POWERADMIN_URL "$POWERADMIN_URL"
|
||||
_saveaccountconf_mutable POWERADMIN_API_KEY "$POWERADMIN_API_KEY"
|
||||
_saveaccountconf_mutable POWERADMIN_API_VERSION "$POWERADMIN_API_VERSION"
|
||||
|
||||
_debug "Detect root zone"
|
||||
if ! _get_root "$fulldomain"; then
|
||||
_err "invalid domain"
|
||||
return 1
|
||||
fi
|
||||
|
||||
_debug _domain "$_domain"
|
||||
_debug _zone_id "$_zone_id"
|
||||
|
||||
if ! _set_record "$fulldomain" "$txtvalue"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Usage: dns_poweradmin_rm _acme-challenge.www.domain.com "123456789ABCDEF"
|
||||
# fulldomain
|
||||
# txtvalue
|
||||
dns_poweradmin_rm() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
|
||||
POWERADMIN_URL="${POWERADMIN_URL:-$(_readaccountconf_mutable POWERADMIN_URL)}"
|
||||
POWERADMIN_API_KEY="${POWERADMIN_API_KEY:-$(_readaccountconf_mutable POWERADMIN_API_KEY)}"
|
||||
POWERADMIN_API_VERSION="${POWERADMIN_API_VERSION:-$(_readaccountconf_mutable POWERADMIN_API_VERSION)}"
|
||||
POWERADMIN_API_VERSION="${POWERADMIN_API_VERSION:-2}"
|
||||
|
||||
_debug "Detect root zone"
|
||||
if ! _get_root "$fulldomain"; then
|
||||
_err "invalid domain"
|
||||
return 1
|
||||
fi
|
||||
|
||||
_debug _domain "$_domain"
|
||||
_debug _zone_id "$_zone_id"
|
||||
|
||||
if ! _rm_record "$fulldomain" "$txtvalue"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
######## Private functions below #####################
|
||||
|
||||
_set_record() {
|
||||
_info "Adding TXT record"
|
||||
full=$1
|
||||
new_challenge=$2
|
||||
|
||||
data='{"name":"'$full'","type":"TXT","content":"'$new_challenge'","ttl":60}'
|
||||
|
||||
if ! _poweradmin_rest "POST" "/api/v${POWERADMIN_API_VERSION}/zones/$_zone_id/records" "$data" "application/json"; then
|
||||
_err "Failed to add TXT record"
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
_rm_record() {
|
||||
_info "Remove TXT record"
|
||||
full=$1
|
||||
txtvalue=$2
|
||||
|
||||
if ! _poweradmin_rest "GET" "/api/v${POWERADMIN_API_VERSION}/zones/$_zone_id/records"; then
|
||||
_err "Failed to retrieve records"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# The API returns: {"success":true,"data":[{"id":..., "name":"...", "type":"TXT", "content":"...", ...}]}
|
||||
_txt_record_obj=$(
|
||||
printf '%s\n' "$response" |
|
||||
sed 's/^.*"data":\[//; s/\],"message":.*$//' |
|
||||
awk '{ gsub(/},{/, "}\n{"); print }' |
|
||||
grep -F "\"name\":\"$full\"" |
|
||||
grep -F "\"type\":\"TXT\"" |
|
||||
grep -F "\"content\":\"$txtvalue\"" |
|
||||
_head_n 1
|
||||
)
|
||||
|
||||
if [ -z "$_txt_record_obj" ]; then
|
||||
_info "TXT record not found for $full with content $txtvalue"
|
||||
return 0
|
||||
fi
|
||||
|
||||
record_id=$(printf '%s\n' "$_txt_record_obj" | sed -n 's/.*"id":\([0-9][0-9]*\).*/\1/p' | _head_n 1)
|
||||
record_type=$(printf '%s\n' "$_txt_record_obj" | sed -n 's/.*"type":"\([^"]*\)".*/\1/p' | _head_n 1)
|
||||
record_name=$(printf '%s\n' "$_txt_record_obj" | sed -n 's/.*"name":"\([^"]*\)".*/\1/p' | _head_n 1)
|
||||
record_content=$(printf '%s\n' "$_txt_record_obj" | sed -n 's/.*"content":"\([^"]*\)".*/\1/p' | _head_n 1)
|
||||
|
||||
_debug2 "_txt_record_obj=$_txt_record_obj"
|
||||
_debug2 "record id: $record_id"
|
||||
_debug2 "record type: $record_type"
|
||||
_debug2 "record name: $record_name"
|
||||
_debug2 "record content: $record_content"
|
||||
|
||||
if [ "$record_type" != "TXT" ]; then
|
||||
_err "Refusing to delete non-TXT record id=$record_id type=$record_type name=$full"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! _poweradmin_rest "DELETE" "/api/v${POWERADMIN_API_VERSION}/zones/$_zone_id/records/$record_id"; then
|
||||
_err "Failed to delete TXT record"
|
||||
return 1
|
||||
fi
|
||||
|
||||
_info "Record deleted successfully"
|
||||
return 0
|
||||
}
|
||||
|
||||
# _acme-challenge.www.domain.com
|
||||
# returns
|
||||
# _domain=domain.com
|
||||
# _zone_id=220
|
||||
_get_root() {
|
||||
domain=$1
|
||||
i=1
|
||||
|
||||
if ! _poweradmin_rest "GET" "/api/v${POWERADMIN_API_VERSION}/zones"; then
|
||||
_err "Failed to retrieve zones"
|
||||
return 1
|
||||
fi
|
||||
|
||||
_zones_response="$response"
|
||||
|
||||
while true; do
|
||||
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
|
||||
|
||||
if [ -z "$h" ]; then
|
||||
_debug "Root domain not found for $domain"
|
||||
return 1
|
||||
fi
|
||||
|
||||
zone_obj=$(
|
||||
printf '%s' "$_zones_response" |
|
||||
sed 's/},{/}\n{/g' |
|
||||
grep -F "\"name\":\"$h\"" |
|
||||
_head_n 1
|
||||
)
|
||||
|
||||
if [ -n "$zone_obj" ]; then
|
||||
_zone_id=$(printf '%s' "$zone_obj" | _egrep_o '"id":[0-9][0-9]*' | _head_n 1 | cut -d: -f2)
|
||||
_domain="$h"
|
||||
_debug "Found zone: $_domain with id: $_zone_id"
|
||||
return 0
|
||||
fi
|
||||
|
||||
i=$(_math "$i" + 1)
|
||||
done
|
||||
}
|
||||
|
||||
_poweradmin_rest() {
|
||||
method=$1
|
||||
ep=$2
|
||||
data=$3
|
||||
ct=$4
|
||||
|
||||
export _H1="X-API-Key: $POWERADMIN_API_KEY"
|
||||
|
||||
if [ "$method" = "GET" ]; then
|
||||
response="$(_get "$POWERADMIN_URL$ep")"
|
||||
else
|
||||
_debug "API call: $method $ep"
|
||||
_debug "Content-Type: $ct"
|
||||
_debug "Payload: $data"
|
||||
response="$(_post "$data" "$POWERADMIN_URL$ep" "" "$method" "$ct")"
|
||||
fi
|
||||
|
||||
# Clear _H1 variable
|
||||
unset -v _H1
|
||||
|
||||
if [ "$?" != "0" ]; then
|
||||
_err "API error on $method $ep"
|
||||
_debug "Response: $response"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if printf '%s' "$response" | grep -q '"success"[[:space:]]*:[[:space:]]*false'; then
|
||||
_err "API reported failure on $method $ep"
|
||||
_debug "Response: $response"
|
||||
return 1
|
||||
fi
|
||||
|
||||
_debug2 "API Response: $response"
|
||||
return 0
|
||||
}
|
||||
|
|
@ -8,11 +8,7 @@ Options:
|
|||
SIMPLY_ApiKey API Key
|
||||
'
|
||||
|
||||
#SIMPLY_Api="https://api.simply.com/2/"
|
||||
SIMPLY_Api_Default="https://api.simply.com/2"
|
||||
|
||||
#This is used for determining success of REST call
|
||||
SIMPLY_SUCCESS_CODE='"status":200'
|
||||
SIMPLY_Api="https://api.simply.com/2"
|
||||
|
||||
######## Public functions #####################
|
||||
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
|
|
@ -72,7 +68,16 @@ dns_simply_rm() {
|
|||
return 1
|
||||
fi
|
||||
|
||||
records=$(echo "$response" | tr '{' "\n" | grep 'record_id\|type\|data\|\name' | sed 's/\"record_id/;\"record_id/' | tr "\n" ' ' | tr -d ' ' | tr ';' ' ')
|
||||
case "$_simply_http_code" in
|
||||
2*) ;;
|
||||
*)
|
||||
_err "Failed to fetch DNS records (HTTP $_simply_http_code)"
|
||||
_err "$response"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
records=$(echo "$response" | tr '{' "\n" | grep -E 'record_id|type|data|name' | sed 's/\"record_id/;\"record_id/' | tr "\n" ' ' | tr -d ' ' | tr ';' ' ')
|
||||
|
||||
nr_of_deleted_records=0
|
||||
_info "Fetching txt record"
|
||||
|
|
@ -95,7 +100,7 @@ dns_simply_rm() {
|
|||
|
||||
if [ "$record_id" -gt 0 ]; then
|
||||
|
||||
if ! _simply_delete_record "$_domain" "$_sub_domain" "$record_id"; then
|
||||
if ! _simply_delete_record "$_domain" "$record_id"; then
|
||||
_err "Record with id $record_id could not be deleted"
|
||||
return 1
|
||||
fi
|
||||
|
|
@ -122,14 +127,9 @@ dns_simply_rm() {
|
|||
#################### Private functions below ##################################
|
||||
|
||||
_simply_load_config() {
|
||||
SIMPLY_Api="${SIMPLY_Api:-$(_readaccountconf_mutable SIMPLY_Api)}"
|
||||
SIMPLY_AccountName="${SIMPLY_AccountName:-$(_readaccountconf_mutable SIMPLY_AccountName)}"
|
||||
SIMPLY_ApiKey="${SIMPLY_ApiKey:-$(_readaccountconf_mutable SIMPLY_ApiKey)}"
|
||||
|
||||
if [ -z "$SIMPLY_Api" ]; then
|
||||
SIMPLY_Api="$SIMPLY_Api_Default"
|
||||
fi
|
||||
|
||||
if [ -z "$SIMPLY_AccountName" ] || [ -z "$SIMPLY_ApiKey" ]; then
|
||||
SIMPLY_AccountName=""
|
||||
SIMPLY_ApiKey=""
|
||||
|
|
@ -144,9 +144,6 @@ _simply_load_config() {
|
|||
}
|
||||
|
||||
_simply_save_config() {
|
||||
if [ "$SIMPLY_Api" != "$SIMPLY_Api_Default" ]; then
|
||||
_saveaccountconf_mutable SIMPLY_Api "$SIMPLY_Api"
|
||||
fi
|
||||
_saveaccountconf_mutable SIMPLY_AccountName "$SIMPLY_AccountName"
|
||||
_saveaccountconf_mutable SIMPLY_ApiKey "$SIMPLY_ApiKey"
|
||||
}
|
||||
|
|
@ -163,26 +160,39 @@ _simply_get_all_records() {
|
|||
|
||||
_get_root() {
|
||||
domain=$1
|
||||
|
||||
if ! _simply_rest GET "my/products/"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
case "$_simply_http_code" in
|
||||
2*) ;;
|
||||
*)
|
||||
_err "Failed to fetch product list (HTTP $_simply_http_code)"
|
||||
_err "$response"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
i=2
|
||||
p=1
|
||||
while true; do
|
||||
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
|
||||
if [ -z "$h" ]; then
|
||||
#not valid
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! _simply_rest GET "my/products/$h/dns/"; then
|
||||
return 1
|
||||
fi
|
||||
_domain=$(printf "%s" "$response" | tr '}' '\n' |
|
||||
grep -F -e "\"object\":\"$h\"" -e "\"name\":\"$h\"" -e "\"name_idn\":\"$h\"" |
|
||||
sed -n 's/.*"object":"\([^"]*\)".*/\1/p' |
|
||||
_head_n 1)
|
||||
|
||||
if ! _contains "$response" "$SIMPLY_SUCCESS_CODE"; then
|
||||
_debug "$h not found"
|
||||
else
|
||||
if [ -n "$_domain" ]; then
|
||||
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
|
||||
_domain="$h"
|
||||
return 0
|
||||
fi
|
||||
|
||||
_debug "No Simply.com product found for $h"
|
||||
p="$i"
|
||||
i=$(_math "$i" + 1)
|
||||
done
|
||||
|
|
@ -194,39 +204,44 @@ _simply_add_record() {
|
|||
sub_domain=$2
|
||||
txtval=$3
|
||||
|
||||
data="{\"name\": \"$sub_domain\", \"type\":\"TXT\", \"data\": \"$txtval\", \"priority\":0, \"ttl\": 3600}"
|
||||
data="{\"name\": \"$sub_domain\", \"type\":\"TXT\", \"data\": \"$txtval\", \"priority\":0, \"ttl\": 120}"
|
||||
|
||||
if ! _simply_rest POST "my/products/$domain/dns/records/" "$data"; then
|
||||
_err "Adding record not successfull!"
|
||||
_err "Adding record not successful!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! _contains "$response" "$SIMPLY_SUCCESS_CODE"; then
|
||||
_err "Call to API not sucessfull, see below message for more details"
|
||||
case "$_simply_http_code" in
|
||||
2*) ;;
|
||||
*)
|
||||
_err "Call to API not successful (HTTP $_simply_http_code), see below message for more details"
|
||||
_err "$response"
|
||||
return 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
_simply_delete_record() {
|
||||
domain=$1
|
||||
sub_domain=$2
|
||||
record_id=$3
|
||||
record_id=$2
|
||||
|
||||
_debug record_id "Delete record with id $record_id"
|
||||
|
||||
if ! _simply_rest DELETE "my/products/$domain/dns/records/$record_id/"; then
|
||||
_err "Deleting record not successfull!"
|
||||
_err "Deleting record not successful!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! _contains "$response" "$SIMPLY_SUCCESS_CODE"; then
|
||||
_err "Call to API not sucessfull, see below message for more details"
|
||||
case "$_simply_http_code" in
|
||||
2*) ;;
|
||||
*)
|
||||
_err "Call to API not successful (HTTP $_simply_http_code), see below message for more details"
|
||||
_err "$response"
|
||||
return 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
return 0
|
||||
}
|
||||
|
|
@ -248,17 +263,24 @@ _simply_rest() {
|
|||
|
||||
export _H2="Content-Type: application/json"
|
||||
|
||||
: >"$HTTP_HEADER"
|
||||
|
||||
if [ "$m" != "GET" ]; then
|
||||
response="$(_post "$data" "$SIMPLY_Api/$ep" "" "$m")"
|
||||
else
|
||||
response="$(_get "$SIMPLY_Api/$ep")"
|
||||
fi
|
||||
|
||||
if [ "$?" != "0" ]; then
|
||||
_ret="$?"
|
||||
unset _H1 _H2
|
||||
|
||||
if [ "$_ret" != "0" ]; then
|
||||
_err "error $ep"
|
||||
return 1
|
||||
fi
|
||||
|
||||
_simply_http_code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d' ' -f2 | tr -d '\r\n')"
|
||||
|
||||
response="$(echo "$response" | _normalizeJson)"
|
||||
|
||||
_debug2 response "$response"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue