Merge branch 'acmesh-official:master' into master

This commit is contained in:
baerengraben 2025-01-17 17:34:27 +01:00 committed by GitHub
commit 89b7e8f5da
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
191 changed files with 5963 additions and 2617 deletions

View File

@ -1,5 +1,6 @@
name: DNS name: DNS
on: on:
workflow_dispatch:
push: push:
paths: paths:
- 'dnsapi/*.sh' - 'dnsapi/*.sh'
@ -65,7 +66,7 @@ jobs:
TokenName4: ${{ secrets.TokenName4}} TokenName4: ${{ secrets.TokenName4}}
TokenName5: ${{ secrets.TokenName5}} TokenName5: ${{ secrets.TokenName5}}
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Clone acmetest - name: Clone acmetest
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
- name: Set env file - name: Set env file
@ -113,7 +114,7 @@ jobs:
TokenName4: ${{ secrets.TokenName4}} TokenName4: ${{ secrets.TokenName4}}
TokenName5: ${{ secrets.TokenName5}} TokenName5: ${{ secrets.TokenName5}}
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Install tools - name: Install tools
run: brew install socat run: brew install socat
- name: Clone acmetest - name: Clone acmetest
@ -164,7 +165,7 @@ jobs:
- name: Set git to use LF - name: Set git to use LF
run: | run: |
git config --global core.autocrlf false git config --global core.autocrlf false
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Install cygwin base packages with chocolatey - name: Install cygwin base packages with chocolatey
run: | run: |
choco config get cacheLocation choco config get cacheLocation
@ -204,7 +205,7 @@ jobs:
FreeBSD: FreeBSD:
runs-on: macos-12 runs-on: ubuntu-latest
needs: Windows needs: Windows
env: env:
TEST_DNS : ${{ secrets.TEST_DNS }} TEST_DNS : ${{ secrets.TEST_DNS }}
@ -223,10 +224,10 @@ jobs:
TokenName4: ${{ secrets.TokenName4}} TokenName4: ${{ secrets.TokenName4}}
TokenName5: ${{ secrets.TokenName5}} TokenName5: ${{ secrets.TokenName5}}
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Clone acmetest - name: Clone acmetest
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
- uses: vmactions/freebsd-vm@v0 - uses: vmactions/freebsd-vm@v1
with: 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}}' 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 install -y socat curl prepare: pkg install -y socat curl
@ -255,7 +256,7 @@ jobs:
OpenBSD: OpenBSD:
runs-on: macos-12 runs-on: ubuntu-latest
needs: FreeBSD needs: FreeBSD
env: env:
TEST_DNS : ${{ secrets.TEST_DNS }} TEST_DNS : ${{ secrets.TEST_DNS }}
@ -274,13 +275,13 @@ jobs:
TokenName4: ${{ secrets.TokenName4}} TokenName4: ${{ secrets.TokenName4}}
TokenName5: ${{ secrets.TokenName5}} TokenName5: ${{ secrets.TokenName5}}
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Clone acmetest - name: Clone acmetest
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
- uses: vmactions/openbsd-vm@v0 - uses: vmactions/openbsd-vm@v1
with: 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}}' 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 usesh: true
copyback: false copyback: false
run: | run: |
@ -306,7 +307,7 @@ jobs:
NetBSD: NetBSD:
runs-on: macos-12 runs-on: ubuntu-latest
needs: OpenBSD needs: OpenBSD
env: env:
TEST_DNS : ${{ secrets.TEST_DNS }} TEST_DNS : ${{ secrets.TEST_DNS }}
@ -325,14 +326,14 @@ jobs:
TokenName4: ${{ secrets.TokenName4}} TokenName4: ${{ secrets.TokenName4}}
TokenName5: ${{ secrets.TokenName5}} TokenName5: ${{ secrets.TokenName5}}
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Clone acmetest - name: Clone acmetest
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
- uses: vmactions/netbsd-vm@v0 - uses: vmactions/netbsd-vm@v1
with: 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}}' 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: | prepare: |
pkg_add curl socat /usr/sbin/pkg_add curl socat
usesh: true usesh: true
copyback: false copyback: false
run: | run: |
@ -358,7 +359,7 @@ jobs:
DragonFlyBSD: DragonFlyBSD:
runs-on: macos-12 runs-on: ubuntu-latest
needs: NetBSD needs: NetBSD
env: env:
TEST_DNS : ${{ secrets.TEST_DNS }} TEST_DNS : ${{ secrets.TEST_DNS }}
@ -377,10 +378,10 @@ jobs:
TokenName4: ${{ secrets.TokenName4}} TokenName4: ${{ secrets.TokenName4}}
TokenName5: ${{ secrets.TokenName5}} TokenName5: ${{ secrets.TokenName5}}
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Clone acmetest - name: Clone acmetest
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
- uses: vmactions/dragonflybsd-vm@v0 - uses: vmactions/dragonflybsd-vm@v1
with: 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}}' 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: | prepare: |
@ -413,7 +414,7 @@ jobs:
Solaris: Solaris:
runs-on: macos-12 runs-on: ubuntu-latest
needs: DragonFlyBSD needs: DragonFlyBSD
env: env:
TEST_DNS : ${{ secrets.TEST_DNS }} TEST_DNS : ${{ secrets.TEST_DNS }}
@ -433,10 +434,10 @@ jobs:
TokenName4: ${{ secrets.TokenName4}} TokenName4: ${{ secrets.TokenName4}}
TokenName5: ${{ secrets.TokenName5}} TokenName5: ${{ secrets.TokenName5}}
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Clone acmetest - name: Clone acmetest
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
- uses: vmactions/solaris-vm@v0 - uses: vmactions/solaris-vm@v1
with: with:
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}}' 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}}'
copyback: false copyback: false
@ -463,3 +464,52 @@ jobs:
./letest.sh ./letest.sh
Omnios:
runs-on: ubuntu-latest
needs: Solaris
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 Omnios 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@v4
- name: Clone acmetest
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
- uses: vmactions/omnios-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 HTTPS_INSECURE TokenName1 TokenName2 TokenName3 TokenName4 TokenName5 ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}'
copyback: false
prepare: pkg 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

View File

@ -20,7 +20,6 @@ concurrency:
jobs: jobs:
DragonFlyBSD: DragonFlyBSD:
strategy: strategy:
@ -30,13 +29,13 @@ jobs:
CA_ECDSA: "" CA_ECDSA: ""
CA: "" CA: ""
CA_EMAIL: "" CA_EMAIL: ""
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1 TEST_PREFERRED_CHAIN: (STAGING)
#- TEST_ACME_Server: "ZeroSSL.com" #- TEST_ACME_Server: "ZeroSSL.com"
# CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" # CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA"
# CA: "ZeroSSL RSA Domain Secure Site CA" # CA: "ZeroSSL RSA Domain Secure Site CA"
# CA_EMAIL: "githubtest@acme.sh" # CA_EMAIL: "githubtest@acme.sh"
# TEST_PREFERRED_CHAIN: "" # TEST_PREFERRED_CHAIN: ""
runs-on: macos-12 runs-on: ubuntu-latest
env: env:
TEST_LOCAL: 1 TEST_LOCAL: 1
TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }} TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }}
@ -44,8 +43,9 @@ jobs:
CA: ${{ matrix.CA }} CA: ${{ matrix.CA }}
CA_EMAIL: ${{ matrix.CA_EMAIL }} CA_EMAIL: ${{ matrix.CA_EMAIL }}
TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }} TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }}
ACME_USE_WGET: ${{ matrix.ACME_USE_WGET }}
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: vmactions/cf-tunnel@v0 - uses: vmactions/cf-tunnel@v0
id: tunnel id: tunnel
with: with:
@ -55,15 +55,15 @@ jobs:
run: echo "TestingDomain=${{steps.tunnel.outputs.server}}" >> $GITHUB_ENV run: echo "TestingDomain=${{steps.tunnel.outputs.server}}" >> $GITHUB_ENV
- name: Clone acmetest - name: Clone acmetest
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
- uses: vmactions/dragonflybsd-vm@v0 - uses: vmactions/dragonflybsd-vm@v1
with: with:
envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN' envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN ACME_USE_WGET'
copyback: "false"
nat: | nat: |
"8080": "80" "8080": "80"
prepare: | prepare: |
pkg install -y curl socat libnghttp2 pkg install -y curl socat libnghttp2
usesh: true usesh: true
copyback: false
run: | run: |
cd ../acmetest \ cd ../acmetest \
&& ./letest.sh && ./letest.sh

View File

@ -29,19 +29,19 @@ jobs:
CA_ECDSA: "" CA_ECDSA: ""
CA: "" CA: ""
CA_EMAIL: "" CA_EMAIL: ""
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1 TEST_PREFERRED_CHAIN: (STAGING)
- TEST_ACME_Server: "LetsEncrypt.org_test" - TEST_ACME_Server: "LetsEncrypt.org_test"
CA_ECDSA: "" CA_ECDSA: ""
CA: "" CA: ""
CA_EMAIL: "" CA_EMAIL: ""
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1 TEST_PREFERRED_CHAIN: (STAGING)
ACME_USE_WGET: 1 ACME_USE_WGET: 1
#- TEST_ACME_Server: "ZeroSSL.com" #- TEST_ACME_Server: "ZeroSSL.com"
# CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" # CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA"
# CA: "ZeroSSL RSA Domain Secure Site CA" # CA: "ZeroSSL RSA Domain Secure Site CA"
# CA_EMAIL: "githubtest@acme.sh" # CA_EMAIL: "githubtest@acme.sh"
# TEST_PREFERRED_CHAIN: "" # TEST_PREFERRED_CHAIN: ""
runs-on: macos-12 runs-on: ubuntu-latest
env: env:
TEST_LOCAL: 1 TEST_LOCAL: 1
TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }} TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }}
@ -51,7 +51,7 @@ jobs:
TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }} TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }}
ACME_USE_WGET: ${{ matrix.ACME_USE_WGET }} ACME_USE_WGET: ${{ matrix.ACME_USE_WGET }}
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: vmactions/cf-tunnel@v0 - uses: vmactions/cf-tunnel@v0
id: tunnel id: tunnel
with: with:
@ -61,7 +61,7 @@ jobs:
run: echo "TestingDomain=${{steps.tunnel.outputs.server}}" >> $GITHUB_ENV run: echo "TestingDomain=${{steps.tunnel.outputs.server}}" >> $GITHUB_ENV
- name: Clone acmetest - name: Clone acmetest
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
- uses: vmactions/freebsd-vm@v0 - uses: vmactions/freebsd-vm@v1
with: with:
envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN ACME_USE_WGET' envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN ACME_USE_WGET'
nat: | nat: |

View File

@ -26,14 +26,14 @@ jobs:
Linux: Linux:
strategy: strategy:
matrix: matrix:
os: ["ubuntu:latest", "debian:latest", "almalinux:latest", "fedora:latest", "centos:7", "opensuse/leap:latest", "alpine:latest", "oraclelinux:8", "kalilinux/kali", "archlinux:latest", "mageia", "gentoo/stage3"] os: ["ubuntu:latest", "debian:latest", "almalinux:latest", "fedora:latest", "opensuse/leap:latest", "alpine:latest", "oraclelinux:8", "kalilinux/kali", "archlinux:latest", "mageia", "gentoo/stage3"]
runs-on: ubuntu-latest runs-on: ubuntu-latest
env: env:
TEST_LOCAL: 1 TEST_LOCAL: 1
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1 TEST_PREFERRED_CHAIN: (STAGING)
TEST_ACME_Server: "LetsEncrypt.org_test" TEST_ACME_Server: "LetsEncrypt.org_test"
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Clone acmetest - name: Clone acmetest
run: | run: |
cd .. \ cd .. \

View File

@ -29,7 +29,7 @@ jobs:
CA_ECDSA: "" CA_ECDSA: ""
CA: "" CA: ""
CA_EMAIL: "" CA_EMAIL: ""
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1 TEST_PREFERRED_CHAIN: (STAGING)
#- TEST_ACME_Server: "ZeroSSL.com" #- TEST_ACME_Server: "ZeroSSL.com"
# CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" # CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA"
# CA: "ZeroSSL RSA Domain Secure Site CA" # CA: "ZeroSSL RSA Domain Secure Site CA"
@ -44,7 +44,7 @@ jobs:
CA_EMAIL: ${{ matrix.CA_EMAIL }} CA_EMAIL: ${{ matrix.CA_EMAIL }}
TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }} TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }}
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Install tools - name: Install tools
run: brew install socat run: brew install socat
- name: Clone acmetest - name: Clone acmetest

View File

@ -20,7 +20,6 @@ concurrency:
jobs: jobs:
NetBSD: NetBSD:
strategy: strategy:
@ -30,13 +29,13 @@ jobs:
CA_ECDSA: "" CA_ECDSA: ""
CA: "" CA: ""
CA_EMAIL: "" CA_EMAIL: ""
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1 TEST_PREFERRED_CHAIN: (STAGING)
#- TEST_ACME_Server: "ZeroSSL.com" #- TEST_ACME_Server: "ZeroSSL.com"
# CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" # CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA"
# CA: "ZeroSSL RSA Domain Secure Site CA" # CA: "ZeroSSL RSA Domain Secure Site CA"
# CA_EMAIL: "githubtest@acme.sh" # CA_EMAIL: "githubtest@acme.sh"
# TEST_PREFERRED_CHAIN: "" # TEST_PREFERRED_CHAIN: ""
runs-on: macos-12 runs-on: ubuntu-latest
env: env:
TEST_LOCAL: 1 TEST_LOCAL: 1
TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }} TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }}
@ -44,8 +43,9 @@ jobs:
CA: ${{ matrix.CA }} CA: ${{ matrix.CA }}
CA_EMAIL: ${{ matrix.CA_EMAIL }} CA_EMAIL: ${{ matrix.CA_EMAIL }}
TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }} TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }}
ACME_USE_WGET: ${{ matrix.ACME_USE_WGET }}
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: vmactions/cf-tunnel@v0 - uses: vmactions/cf-tunnel@v0
id: tunnel id: tunnel
with: with:
@ -55,13 +55,13 @@ jobs:
run: echo "TestingDomain=${{steps.tunnel.outputs.server}}" >> $GITHUB_ENV run: echo "TestingDomain=${{steps.tunnel.outputs.server}}" >> $GITHUB_ENV
- name: Clone acmetest - name: Clone acmetest
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
- uses: vmactions/netbsd-vm@v0 - uses: vmactions/netbsd-vm@v1
with: with:
envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN' envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN ACME_USE_WGET'
nat: | nat: |
"8080": "80" "8080": "80"
prepare: | prepare: |
pkg_add curl socat /usr/sbin/pkg_add curl socat
usesh: true usesh: true
copyback: false copyback: false
run: | run: |

75
.github/workflows/Omnios.yml vendored Normal file
View File

@ -0,0 +1,75 @@
name: Omnios
on:
push:
branches:
- '*'
paths:
- '*.sh'
- '.github/workflows/Omnios.yml'
pull_request:
branches:
- dev
paths:
- '*.sh'
- '.github/workflows/Omnios.yml'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
Omnios:
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 Domain Secure Site CA"
# CA: "ZeroSSL RSA Domain Secure Site CA"
# 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@v4
- uses: vmactions/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/omnios-vm@v1
with:
envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN ACME_USE_WGET'
nat: |
"8080": "80"
prepare: pkg install socat wget
copyback: false
run: |
cd ../acmetest \
&& ./letest.sh

View File

@ -29,19 +29,19 @@ jobs:
CA_ECDSA: "" CA_ECDSA: ""
CA: "" CA: ""
CA_EMAIL: "" CA_EMAIL: ""
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1 TEST_PREFERRED_CHAIN: (STAGING)
- TEST_ACME_Server: "LetsEncrypt.org_test" - TEST_ACME_Server: "LetsEncrypt.org_test"
CA_ECDSA: "" CA_ECDSA: ""
CA: "" CA: ""
CA_EMAIL: "" CA_EMAIL: ""
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1 TEST_PREFERRED_CHAIN: (STAGING)
ACME_USE_WGET: 1 ACME_USE_WGET: 1
#- TEST_ACME_Server: "ZeroSSL.com" #- TEST_ACME_Server: "ZeroSSL.com"
# CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" # CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA"
# CA: "ZeroSSL RSA Domain Secure Site CA" # CA: "ZeroSSL RSA Domain Secure Site CA"
# CA_EMAIL: "githubtest@acme.sh" # CA_EMAIL: "githubtest@acme.sh"
# TEST_PREFERRED_CHAIN: "" # TEST_PREFERRED_CHAIN: ""
runs-on: macos-12 runs-on: ubuntu-latest
env: env:
TEST_LOCAL: 1 TEST_LOCAL: 1
TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }} TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }}
@ -51,7 +51,7 @@ jobs:
TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }} TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }}
ACME_USE_WGET: ${{ matrix.ACME_USE_WGET }} ACME_USE_WGET: ${{ matrix.ACME_USE_WGET }}
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: vmactions/cf-tunnel@v0 - uses: vmactions/cf-tunnel@v0
id: tunnel id: tunnel
with: with:
@ -61,7 +61,7 @@ jobs:
run: echo "TestingDomain=${{steps.tunnel.outputs.server}}" >> $GITHUB_ENV run: echo "TestingDomain=${{steps.tunnel.outputs.server}}" >> $GITHUB_ENV
- name: Clone acmetest - name: Clone acmetest
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
- uses: vmactions/openbsd-vm@v0 - uses: vmactions/openbsd-vm@v1
with: with:
envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN ACME_USE_WGET' envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN ACME_USE_WGET'
nat: | nat: |

View File

@ -33,11 +33,11 @@ jobs:
TEST_CA: "Pebble Intermediate CA" TEST_CA: "Pebble Intermediate CA"
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Install tools - name: Install tools
run: sudo apt-get install -y socat run: sudo apt-get install -y socat
- name: Run Pebble - name: Run Pebble
run: cd .. && curl https://raw.githubusercontent.com/letsencrypt/pebble/master/docker-compose.yml >docker-compose.yml && docker-compose up -d run: cd .. && curl https://raw.githubusercontent.com/letsencrypt/pebble/master/docker-compose.yml >docker-compose.yml && docker compose up -d
- name: Set up Pebble - name: Set up Pebble
run: curl --request POST --data '{"ip":"10.30.50.1"}' http://localhost:8055/set-default-ipv4 run: curl --request POST --data '{"ip":"10.30.50.1"}' http://localhost:8055/set-default-ipv4
- name: Clone acmetest - name: Clone acmetest
@ -58,7 +58,7 @@ jobs:
TEST_IPCERT: 1 TEST_IPCERT: 1
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Install tools - name: Install tools
run: sudo apt-get install -y socat run: sudo apt-get install -y socat
- name: Run Pebble - name: Run Pebble

View File

@ -14,12 +14,12 @@ on:
- '*.sh' - '*.sh'
- '.github/workflows/Solaris.yml' - '.github/workflows/Solaris.yml'
concurrency: concurrency:
group: ${{ github.workflow }}-${{ github.ref }} group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true cancel-in-progress: true
jobs: jobs:
Solaris: Solaris:
strategy: strategy:
@ -29,19 +29,19 @@ jobs:
CA_ECDSA: "" CA_ECDSA: ""
CA: "" CA: ""
CA_EMAIL: "" CA_EMAIL: ""
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1 TEST_PREFERRED_CHAIN: (STAGING)
- TEST_ACME_Server: "LetsEncrypt.org_test" - TEST_ACME_Server: "LetsEncrypt.org_test"
CA_ECDSA: "" CA_ECDSA: ""
CA: "" CA: ""
CA_EMAIL: "" CA_EMAIL: ""
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1 TEST_PREFERRED_CHAIN: (STAGING)
ACME_USE_WGET: 1 ACME_USE_WGET: 1
#- TEST_ACME_Server: "ZeroSSL.com" #- TEST_ACME_Server: "ZeroSSL.com"
# CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" # CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA"
# CA: "ZeroSSL RSA Domain Secure Site CA" # CA: "ZeroSSL RSA Domain Secure Site CA"
# CA_EMAIL: "githubtest@acme.sh" # CA_EMAIL: "githubtest@acme.sh"
# TEST_PREFERRED_CHAIN: "" # TEST_PREFERRED_CHAIN: ""
runs-on: macos-12 runs-on: ubuntu-latest
env: env:
TEST_LOCAL: 1 TEST_LOCAL: 1
TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }} TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }}
@ -51,7 +51,7 @@ jobs:
TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }} TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }}
ACME_USE_WGET: ${{ matrix.ACME_USE_WGET }} ACME_USE_WGET: ${{ matrix.ACME_USE_WGET }}
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: vmactions/cf-tunnel@v0 - uses: vmactions/cf-tunnel@v0
id: tunnel id: tunnel
with: with:
@ -61,14 +61,15 @@ jobs:
run: echo "TestingDomain=${{steps.tunnel.outputs.server}}" >> $GITHUB_ENV run: echo "TestingDomain=${{steps.tunnel.outputs.server}}" >> $GITHUB_ENV
- name: Clone acmetest - name: Clone acmetest
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
- uses: vmactions/solaris-vm@v0 - uses: vmactions/solaris-vm@v1
with: with:
envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN ACME_USE_WGET' envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN ACME_USE_WGET'
copyback: "false"
nat: | nat: |
"8080": "80" "8080": "80"
prepare: pkgutil -y -i socat curl wget prepare: pkgutil -y -i socat curl wget
copyback: false
run: | run: |
cd ../acmetest \ cd ../acmetest \
&& ./letest.sh && ./letest.sh

View File

@ -29,12 +29,12 @@ jobs:
CA_ECDSA: "" CA_ECDSA: ""
CA: "" CA: ""
CA_EMAIL: "" CA_EMAIL: ""
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1 TEST_PREFERRED_CHAIN: (STAGING)
- TEST_ACME_Server: "LetsEncrypt.org_test" - TEST_ACME_Server: "LetsEncrypt.org_test"
CA_ECDSA: "" CA_ECDSA: ""
CA: "" CA: ""
CA_EMAIL: "" CA_EMAIL: ""
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1 TEST_PREFERRED_CHAIN: (STAGING)
ACME_USE_WGET: 1 ACME_USE_WGET: 1
- TEST_ACME_Server: "ZeroSSL.com" - TEST_ACME_Server: "ZeroSSL.com"
CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA"
@ -70,7 +70,7 @@ jobs:
TestingDomain: ${{ matrix.TestingDomain }} TestingDomain: ${{ matrix.TestingDomain }}
ACME_USE_WGET: ${{ matrix.ACME_USE_WGET }} ACME_USE_WGET: ${{ matrix.ACME_USE_WGET }}
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Install tools - name: Install tools
run: sudo apt-get install -y socat wget run: sudo apt-get install -y socat wget
- name: Start StepCA - name: Start StepCA

View File

@ -29,7 +29,7 @@ jobs:
CA_ECDSA: "" CA_ECDSA: ""
CA: "" CA: ""
CA_EMAIL: "" CA_EMAIL: ""
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1 TEST_PREFERRED_CHAIN: (STAGING)
#- TEST_ACME_Server: "ZeroSSL.com" #- TEST_ACME_Server: "ZeroSSL.com"
# CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" # CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA"
# CA: "ZeroSSL RSA Domain Secure Site CA" # CA: "ZeroSSL RSA Domain Secure Site CA"
@ -49,7 +49,7 @@ jobs:
- name: Set git to use LF - name: Set git to use LF
run: | run: |
git config --global core.autocrlf false git config --global core.autocrlf false
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Install cygwin base packages with chocolatey - name: Install cygwin base packages with chocolatey
run: | run: |
choco config get cacheLocation choco config get cacheLocation

View File

@ -15,6 +15,8 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }} group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true cancel-in-progress: true
env:
DOCKER_IMAGE: neilpang/acme.sh
jobs: jobs:
CheckToken: CheckToken:
@ -41,9 +43,14 @@ jobs:
if: "contains(needs.CheckToken.outputs.hasToken, 'true')" if: "contains(needs.CheckToken.outputs.hasToken, 'true')"
steps: steps:
- name: checkout code - name: checkout code
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@v2 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 - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2 uses: docker/setup-buildx-action@v2
- name: login to docker hub - name: login to docker hub
@ -51,8 +58,6 @@ jobs:
echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin
- name: build and push the image - name: build and push the image
run: | run: |
DOCKER_IMAGE=neilpang/acme.sh
if [[ $GITHUB_REF == refs/tags/* ]]; then if [[ $GITHUB_REF == refs/tags/* ]]; then
DOCKER_IMAGE_TAG=${GITHUB_REF#refs/tags/} DOCKER_IMAGE_TAG=${GITHUB_REF#refs/tags/}
fi fi
@ -66,8 +71,14 @@ jobs:
fi fi
fi fi
DOCKER_LABELS=()
while read -r label; do
DOCKER_LABELS+=(--label "${label}")
done <<<"${DOCKER_METADATA_OUTPUT_LABELS}"
docker buildx build \ docker buildx build \
--tag ${DOCKER_IMAGE}:${DOCKER_IMAGE_TAG} \ --tag ${DOCKER_IMAGE}:${DOCKER_IMAGE_TAG} \
"${DOCKER_LABELS[@]}" \
--output "type=image,push=true" \ --output "type=image,push=true" \
--build-arg AUTO_UPGRADE=${AUTO_UPGRADE} \ --build-arg AUTO_UPGRADE=${AUTO_UPGRADE} \
--platform linux/arm64/v8,linux/amd64,linux/arm/v6,linux/arm/v7,linux/386,linux/ppc64le,linux/s390x . --platform linux/arm64/v8,linux/amd64,linux/arm/v6,linux/arm/v7,linux/386,linux/ppc64le,linux/s390x .

View File

@ -4,8 +4,6 @@ on:
pull_request_target: pull_request_target:
types: types:
- opened - opened
branches:
- 'dev'
paths: paths:
- 'dnsapi/*.sh' - 'dnsapi/*.sh'
@ -22,9 +20,12 @@ jobs:
owner: context.repo.owner, owner: context.repo.owner,
repo: context.repo.repo, repo: context.repo.repo,
body: `**Welcome** body: `**Welcome**
Please make sure you're read our [DNS API Dev Guide](../wiki/DNS-API-Dev-Guide) and [DNS-API-Test](../wiki/DNS-API-Test). 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. 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 ✨ We look forward to reviewing your Pull request shortly ✨
注意: 必须通过了 [DNS-API-Test](../wiki/DNS-API-Test) 才会被 review. 无论是修改, 还是新加的 dns api, 都必须确保通过这个测试.
` `
}) })

View File

@ -1,4 +1,4 @@
name: Check dns api name: Check notify api
on: on:
pull_request_target: pull_request_target:
@ -22,7 +22,7 @@ jobs:
owner: context.repo.owner, owner: context.repo.owner,
repo: context.repo.repo, repo: context.repo.repo,
body: `**Welcome** body: `**Welcome**
Please make sure you're read our [Code-of-conduct](../wiki/Code-of-conduct) and add the usage here: [notify](../wiki/notify). Please make sure you've read our [Code-of-conduct](../wiki/Code-of-conduct) and add the usage here: [notify](../wiki/notify).
Then reply on this message, otherwise, your code will not be reviewed or merged. Then reply on this message, otherwise, your code will not be reviewed or merged.
We look forward to reviewing your Pull request shortly ✨ We look forward to reviewing your Pull request shortly ✨
` `

View File

@ -22,7 +22,7 @@ jobs:
ShellCheck: ShellCheck:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Install Shellcheck - name: Install Shellcheck
run: sudo apt-get install -y shellcheck run: sudo apt-get install -y shellcheck
- name: DoShellcheck - name: DoShellcheck
@ -31,7 +31,7 @@ jobs:
shfmt: shfmt:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Install shfmt - name: Install shfmt
run: curl -sSL https://github.com/mvdan/sh/releases/download/v3.1.2/shfmt_v3.1.2_linux_amd64 -o ~/shfmt && chmod +x ~/shfmt run: curl -sSL https://github.com/mvdan/sh/releases/download/v3.1.2/shfmt_v3.1.2_linux_amd64 -o ~/shfmt && chmod +x ~/shfmt
- name: shfmt - name: shfmt

View File

@ -8,7 +8,7 @@
[![Windows](https://github.com/acmesh-official/acme.sh/actions/workflows/Windows.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Windows.yml) [![Windows](https://github.com/acmesh-official/acme.sh/actions/workflows/Windows.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Windows.yml)
[![Solaris](https://github.com/acmesh-official/acme.sh/actions/workflows/Solaris.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Solaris.yml) [![Solaris](https://github.com/acmesh-official/acme.sh/actions/workflows/Solaris.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Solaris.yml)
[![DragonFlyBSD](https://github.com/acmesh-official/acme.sh/actions/workflows/DragonFlyBSD.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/DragonFlyBSD.yml) [![DragonFlyBSD](https://github.com/acmesh-official/acme.sh/actions/workflows/DragonFlyBSD.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/DragonFlyBSD.yml)
[![Omnios](https://github.com/acmesh-official/acme.sh/actions/workflows/Omnios.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Omnios.yml)
![Shellcheck](https://github.com/acmesh-official/acme.sh/workflows/Shellcheck/badge.svg) ![Shellcheck](https://github.com/acmesh-official/acme.sh/workflows/Shellcheck/badge.svg)
![PebbleStrict](https://github.com/acmesh-official/acme.sh/workflows/PebbleStrict/badge.svg) ![PebbleStrict](https://github.com/acmesh-official/acme.sh/workflows/PebbleStrict/badge.svg)
@ -73,20 +73,21 @@ Twitter: [@neilpangxa](https://twitter.com/neilpangxa)
|7|[![OpenBSD](https://github.com/acmesh-official/acme.sh/actions/workflows/OpenBSD.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/OpenBSD.yml)|OpenBSD |7|[![OpenBSD](https://github.com/acmesh-official/acme.sh/actions/workflows/OpenBSD.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/OpenBSD.yml)|OpenBSD
|8|[![NetBSD](https://github.com/acmesh-official/acme.sh/actions/workflows/NetBSD.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/NetBSD.yml)|NetBSD |8|[![NetBSD](https://github.com/acmesh-official/acme.sh/actions/workflows/NetBSD.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/NetBSD.yml)|NetBSD
|9|[![DragonFlyBSD](https://github.com/acmesh-official/acme.sh/actions/workflows/DragonFlyBSD.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/DragonFlyBSD.yml)|DragonFlyBSD |9|[![DragonFlyBSD](https://github.com/acmesh-official/acme.sh/actions/workflows/DragonFlyBSD.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/DragonFlyBSD.yml)|DragonFlyBSD
|10|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)| Debian |10|[![Omnios](https://github.com/acmesh-official/acme.sh/actions/workflows/Omnios.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Omnios.yml)|Omnios
|11|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|CentOS |11|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)| Debian
|12|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|openSUSE |12|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|CentOS
|13|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Alpine Linux (with curl) |13|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|openSUSE
|14|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Archlinux |14|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Alpine Linux (with curl)
|15|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|fedora |15|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Archlinux
|16|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Kali Linux |16|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|fedora
|17|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Oracle Linux |17|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Kali Linux
|18|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Mageia |18|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Oracle Linux
|19|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Gentoo Linux |19|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Mageia
|10|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|ClearLinux |10|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Gentoo Linux
|11|-----| Cloud Linux https://github.com/acmesh-official/acme.sh/issues/111 |11|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|ClearLinux
|22|-----| OpenWRT: Tested and working. See [wiki page](https://github.com/acmesh-official/acme.sh/wiki/How-to-run-on-OpenWRT) |22|-----| Cloud Linux https://github.com/acmesh-official/acme.sh/issues/111
|23|[![](https://acmesh-official.github.io/acmetest/status/proxmox.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)| Proxmox: See Proxmox VE Wiki. Version [4.x, 5.0, 5.1](https://pve.proxmox.com/wiki/HTTPS_Certificate_Configuration_(Version_4.x,_5.0_and_5.1)#Let.27s_Encrypt_using_acme.sh), version [5.2 and up](https://pve.proxmox.com/wiki/Certificate_Management) |23|-----| OpenWRT: Tested and working. See [wiki page](https://github.com/acmesh-official/acme.sh/wiki/How-to-run-on-OpenWRT)
|24|[![](https://acmesh-official.github.io/acmetest/status/proxmox.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)| Proxmox: See Proxmox VE Wiki. Version [4.x, 5.0, 5.1](https://pve.proxmox.com/wiki/HTTPS_Certificate_Configuration_(Version_4.x,_5.0_and_5.1)#Let.27s_Encrypt_using_acme.sh), version [5.2 and up](https://pve.proxmox.com/wiki/Certificate_Management)
Check our [testing project](https://github.com/acmesh-official/acmetest): Check our [testing project](https://github.com/acmesh-official/acmetest):

850
acme.sh

File diff suppressed because it is too large Load Diff

88
deploy/ali_cdn.sh Normal file
View File

@ -0,0 +1,88 @@
#!/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 multiple CDN domains using the same certificate, just
# export DEPLOY_ALI_CDN_DOMAIN="cdn1.example.com cdn2.example.com"
#
# For DCDN, see ali_dcdn deploy hook
Ali_CDN_API="https://cdn.aliyuncs.com/"
ali_cdn_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_CDN_DOMAIN
if [ "$DEPLOY_ALI_CDN_DOMAIN" ]; then
_savedeployconf DEPLOY_ALI_CDN_DOMAIN "$DEPLOY_ALI_CDN_DOMAIN"
else
DEPLOY_ALI_CDN_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_CDN_DOMAIN; do
_set_cdn_domain_ssl_certificate_query "$domain" "$_cert" "$_key"
if _ali_rest "Set CDN domain SSL certificate for $domain" "" POST; then
_info "Domain $domain certificate has been deployed successfully"
fi
done
return 0
}
# domain pub pri
_set_cdn_domain_ssl_certificate_query() {
endpoint=$Ali_CDN_API
query=''
query=$query'AccessKeyId='$Ali_Key
query=$query'&Action=SetCdnDomainSSLCertificate'
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-05-10'
}

88
deploy/ali_dcdn.sh Normal file
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'
}

View File

@ -109,6 +109,5 @@ exim4_deploy() {
fi fi
return 1 return 1
fi fi
return 0
} }

View File

@ -36,6 +36,19 @@
# Note: This functionality requires HAProxy was compiled against # Note: This functionality requires HAProxy was compiled against
# a version of OpenSSL that supports this. # a version of OpenSSL that supports this.
# #
# export DEPLOY_HAPROXY_HOT_UPDATE="yes"
# export DEPLOY_HAPROXY_STATS_SOCKET="UNIX:/run/haproxy/admin.sock"
#
# OPTIONAL: Deploy the certificate over the HAProxy stats socket without
# needing to reload HAProxy. Default is "no".
#
# Require the socat binary. DEPLOY_HAPROXY_STATS_SOCKET variable uses the socat
# address format.
#
# export DEPLOY_HAPROXY_MASTER_CLI="UNIX:/run/haproxy-master.sock"
#
# OPTIONAL: To use the master CLI with DEPLOY_HAPROXY_HOT_UPDATE="yes" instead
# of a stats socket, use this variable.
######## Public functions ##################### ######## Public functions #####################
@ -46,6 +59,7 @@ haproxy_deploy() {
_ccert="$3" _ccert="$3"
_cca="$4" _cca="$4"
_cfullchain="$5" _cfullchain="$5"
_cmdpfx=""
# Some defaults # Some defaults
DEPLOY_HAPROXY_PEM_PATH_DEFAULT="/etc/haproxy" DEPLOY_HAPROXY_PEM_PATH_DEFAULT="/etc/haproxy"
@ -53,6 +67,8 @@ haproxy_deploy() {
DEPLOY_HAPROXY_BUNDLE_DEFAULT="no" DEPLOY_HAPROXY_BUNDLE_DEFAULT="no"
DEPLOY_HAPROXY_ISSUER_DEFAULT="no" DEPLOY_HAPROXY_ISSUER_DEFAULT="no"
DEPLOY_HAPROXY_RELOAD_DEFAULT="true" DEPLOY_HAPROXY_RELOAD_DEFAULT="true"
DEPLOY_HAPROXY_HOT_UPDATE_DEFAULT="no"
DEPLOY_HAPROXY_STATS_SOCKET_DEFAULT="UNIX:/run/haproxy/admin.sock"
_debug _cdomain "${_cdomain}" _debug _cdomain "${_cdomain}"
_debug _ckey "${_ckey}" _debug _ckey "${_ckey}"
@ -86,6 +102,11 @@ haproxy_deploy() {
_savedomainconf Le_Deploy_haproxy_pem_name "${Le_Deploy_haproxy_pem_name}" _savedomainconf Le_Deploy_haproxy_pem_name "${Le_Deploy_haproxy_pem_name}"
elif [ -z "${Le_Deploy_haproxy_pem_name}" ]; then elif [ -z "${Le_Deploy_haproxy_pem_name}" ]; then
Le_Deploy_haproxy_pem_name="${DEPLOY_HAPROXY_PEM_NAME_DEFAULT}" Le_Deploy_haproxy_pem_name="${DEPLOY_HAPROXY_PEM_NAME_DEFAULT}"
# We better not have '*' as the first character
if [ "${Le_Deploy_haproxy_pem_name%%"${Le_Deploy_haproxy_pem_name#?}"}" = '*' ]; then
# removes the first characters and add a _ instead
Le_Deploy_haproxy_pem_name="_${Le_Deploy_haproxy_pem_name#?}"
fi
fi fi
# BUNDLE is optional. If not provided then assume "${DEPLOY_HAPROXY_BUNDLE_DEFAULT}" # BUNDLE is optional. If not provided then assume "${DEPLOY_HAPROXY_BUNDLE_DEFAULT}"
@ -118,6 +139,36 @@ haproxy_deploy() {
Le_Deploy_haproxy_reload="${DEPLOY_HAPROXY_RELOAD_DEFAULT}" Le_Deploy_haproxy_reload="${DEPLOY_HAPROXY_RELOAD_DEFAULT}"
fi fi
# HOT_UPDATE is optional. If not provided then assume "${DEPLOY_HAPROXY_HOT_UPDATE_DEFAULT}"
_getdeployconf DEPLOY_HAPROXY_HOT_UPDATE
_debug2 DEPLOY_HAPROXY_HOT_UPDATE "${DEPLOY_HAPROXY_HOT_UPDATE}"
if [ -n "${DEPLOY_HAPROXY_HOT_UPDATE}" ]; then
Le_Deploy_haproxy_hot_update="${DEPLOY_HAPROXY_HOT_UPDATE}"
_savedomainconf Le_Deploy_haproxy_hot_update "${Le_Deploy_haproxy_hot_update}"
elif [ -z "${Le_Deploy_haproxy_hot_update}" ]; then
Le_Deploy_haproxy_hot_update="${DEPLOY_HAPROXY_HOT_UPDATE_DEFAULT}"
fi
# STATS_SOCKET is optional. If not provided then assume "${DEPLOY_HAPROXY_STATS_SOCKET_DEFAULT}"
_getdeployconf DEPLOY_HAPROXY_STATS_SOCKET
_debug2 DEPLOY_HAPROXY_STATS_SOCKET "${DEPLOY_HAPROXY_STATS_SOCKET}"
if [ -n "${DEPLOY_HAPROXY_STATS_SOCKET}" ]; then
Le_Deploy_haproxy_stats_socket="${DEPLOY_HAPROXY_STATS_SOCKET}"
_savedomainconf Le_Deploy_haproxy_stats_socket "${Le_Deploy_haproxy_stats_socket}"
elif [ -z "${Le_Deploy_haproxy_stats_socket}" ]; then
Le_Deploy_haproxy_stats_socket="${DEPLOY_HAPROXY_STATS_SOCKET_DEFAULT}"
fi
# MASTER_CLI is optional. No defaults are used. When the master CLI is used,
# all commands are sent with a prefix.
_getdeployconf DEPLOY_HAPROXY_MASTER_CLI
_debug2 DEPLOY_HAPROXY_MASTER_CLI "${DEPLOY_HAPROXY_MASTER_CLI}"
if [ -n "${DEPLOY_HAPROXY_MASTER_CLI}" ]; then
Le_Deploy_haproxy_stats_socket="${DEPLOY_HAPROXY_MASTER_CLI}"
_savedomainconf Le_Deploy_haproxy_stats_socket "${Le_Deploy_haproxy_stats_socket}"
_cmdpfx="@1 " # command prefix used for master CLI only.
fi
# Set the suffix depending if we are creating a bundle or not # Set the suffix depending if we are creating a bundle or not
if [ "${Le_Deploy_haproxy_bundle}" = "yes" ]; then if [ "${Le_Deploy_haproxy_bundle}" = "yes" ]; then
_info "Bundle creation requested" _info "Bundle creation requested"
@ -142,12 +193,13 @@ haproxy_deploy() {
_issuer="${_pem}.issuer" _issuer="${_pem}.issuer"
_ocsp="${_pem}.ocsp" _ocsp="${_pem}.ocsp"
_reload="${Le_Deploy_haproxy_reload}" _reload="${Le_Deploy_haproxy_reload}"
_statssock="${Le_Deploy_haproxy_stats_socket}"
_info "Deploying PEM file" _info "Deploying PEM file"
# Create a temporary PEM file # Create a temporary PEM file
_temppem="$(_mktemp)" _temppem="$(_mktemp)"
_debug _temppem "${_temppem}" _debug _temppem "${_temppem}"
cat "${_ckey}" "${_ccert}" "${_cca}" >"${_temppem}" cat "${_ccert}" "${_cca}" "${_ckey}" | grep . >"${_temppem}"
_ret="$?" _ret="$?"
# Check that we could create the temporary file # Check that we could create the temporary file
@ -265,15 +317,86 @@ haproxy_deploy() {
fi fi
fi fi
# Reload HAProxy if [ "${Le_Deploy_haproxy_hot_update}" = "yes" ]; then
_debug _reload "${_reload}" # set the socket name for messages
eval "${_reload}" if [ -n "${_cmdpfx}" ]; then
_ret=$? _socketname="master CLI"
if [ "${_ret}" != "0" ]; then else
_err "Error code ${_ret} during reload" _socketname="stats socket"
return ${_ret} fi
# Update certificate over HAProxy stats socket or master CLI.
if _exists socat; then
# look for the certificate on the stats socket, to chose between updating or creating one
_socat_cert_cmd="echo '${_cmdpfx}show ssl cert' | socat '${_statssock}' - | grep -q '^${_pem}$'"
_debug _socat_cert_cmd "${_socat_cert_cmd}"
eval "${_socat_cert_cmd}"
_ret=$?
if [ "${_ret}" != "0" ]; then
_newcert="1"
_info "Creating new certificate '${_pem}' over HAProxy ${_socketname}."
# certificate wasn't found, it's a new one. We should check if the crt-list exists and creates/inserts the certificate.
_socat_crtlist_show_cmd="echo '${_cmdpfx}show ssl crt-list' | socat '${_statssock}' - | grep -q '^${Le_Deploy_haproxy_pem_path}$'"
_debug _socat_crtlist_show_cmd "${_socat_crtlist_show_cmd}"
eval "${_socat_crtlist_show_cmd}"
_ret=$?
if [ "${_ret}" != "0" ]; then
_err "Couldn't find '${Le_Deploy_haproxy_pem_path}' in haproxy 'show ssl crt-list'"
return "${_ret}"
fi
# create a new certificate
_socat_new_cmd="echo '${_cmdpfx}new ssl cert ${_pem}' | socat '${_statssock}' - | grep -q 'New empty'"
_debug _socat_new_cmd "${_socat_new_cmd}"
eval "${_socat_new_cmd}"
_ret=$?
if [ "${_ret}" != "0" ]; then
_err "Couldn't create '${_pem}' in haproxy"
return "${_ret}"
fi
else
_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}"
eval "${_socat_cert_set_cmd}"
_ret=$?
if [ "${_ret}" != "0" ]; then
_err "Can't update '${_pem}' in haproxy"
return "${_ret}"
fi
_socat_cert_commit_cmd="echo '${_cmdpfx}commit ssl cert ${_pem}' | socat '${_statssock}' - | grep -q '^Success!$'"
_debug _socat_cert_commit_cmd "${_socat_cert_commit_cmd}"
eval "${_socat_cert_commit_cmd}"
_ret=$?
if [ "${_ret}" != "0" ]; then
_err "Can't commit '${_pem}' in haproxy"
return ${_ret}
fi
if [ "${_newcert}" = "1" ]; then
# if this is a new certificate, it needs to be inserted into the crt-list`
_socat_cert_add_cmd="echo '${_cmdpfx}add ssl crt-list ${Le_Deploy_haproxy_pem_path} ${_pem}' | socat '${_statssock}' - | grep -q 'Success!'"
_debug _socat_cert_add_cmd "${_socat_cert_add_cmd}"
eval "${_socat_cert_add_cmd}"
_ret=$?
if [ "${_ret}" != "0" ]; then
_err "Can't update '${_pem}' in haproxy"
return "${_ret}"
fi
fi
else
_err "'socat' is not available, couldn't update over ${_socketname}"
fi
else else
_info "Reload successful" # Reload HAProxy
_debug _reload "${_reload}"
eval "${_reload}"
_ret=$?
if [ "${_ret}" != "0" ]; then
_err "Error code ${_ret} during reload"
return ${_ret}
else
_info "Reload successful"
fi
fi fi
return 0 return 0

View File

@ -12,6 +12,9 @@
# export PANOS_USER="" #User *MUST* have Commit and Import Permissions in XML API for Admin Role # export PANOS_USER="" #User *MUST* have Commit and Import Permissions in XML API for Admin Role
# export PANOS_PASS="" # export PANOS_PASS=""
# #
# OPTIONAL
# export PANOS_TEMPLATE="" #Template Name of panorama managed devices
#
# The script will automatically generate a new API key if # The script will automatically generate a new API key if
# no key is found, or if a saved key has expired or is invalid. # no key is found, or if a saved key has expired or is invalid.
@ -78,6 +81,9 @@ deployer() {
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"key\"\r\n\r\n$_panos_key" content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"key\"\r\n\r\n$_panos_key"
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"format\"\r\n\r\npem" content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"format\"\r\n\r\npem"
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"file\"; filename=\"$(basename "$_cfullchain")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_cfullchain")" content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"file\"; filename=\"$(basename "$_cfullchain")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_cfullchain")"
if [ "$_panos_template" ]; then
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"target-tpl\"\r\n\r\n$_panos_template"
fi
fi fi
if [ "$type" = 'key' ]; then if [ "$type" = 'key' ]; then
panos_url="${panos_url}?type=import" panos_url="${panos_url}?type=import"
@ -87,6 +93,9 @@ deployer() {
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"format\"\r\n\r\npem" content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"format\"\r\n\r\npem"
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"passphrase\"\r\n\r\n123456" content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"passphrase\"\r\n\r\n123456"
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"file\"; filename=\"$(basename "$_cdomain.key")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ckey")" content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"file\"; filename=\"$(basename "$_cdomain.key")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ckey")"
if [ "$_panos_template" ]; then
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"target-tpl\"\r\n\r\n$_panos_template"
fi
fi fi
#Close multipart #Close multipart
content="$content${nl}--$delim--${nl}${nl}" content="$content${nl}--$delim--${nl}${nl}"
@ -173,10 +182,20 @@ panos_deploy() {
unset _panos_key unset _panos_key
fi fi
# PANOS_TEMPLATE
if [ "$PANOS_TEMPLATE" ]; then
_debug "Detected ENV variable PANOS_TEMPLATE. Saving to file."
_savedeployconf PANOS_TEMPLATE "$PANOS_TEMPLATE" 1
else
_debug "Attempting to load variable PANOS_TEMPLATE from file."
_getdeployconf PANOS_TEMPLATE
fi
#Store variables #Store variables
_panos_host=$PANOS_HOST _panos_host=$PANOS_HOST
_panos_user=$PANOS_USER _panos_user=$PANOS_USER
_panos_pass=$PANOS_PASS _panos_pass=$PANOS_PASS
_panos_template=$PANOS_TEMPLATE
#Test API Key if found. If the key is invalid, the variable _panos_key will be unset. #Test API Key if found. If the key is invalid, the variable _panos_key will be unset.
if [ "$_panos_host" ] && [ "$_panos_key" ]; then if [ "$_panos_host" ] && [ "$_panos_key" ]; then

View File

@ -99,11 +99,11 @@ proxmoxve_deploy() {
_proxmoxve_api_token_key="$DEPLOY_PROXMOXVE_API_TOKEN_KEY" _proxmoxve_api_token_key="$DEPLOY_PROXMOXVE_API_TOKEN_KEY"
_savedeployconf DEPLOY_PROXMOXVE_API_TOKEN_KEY "$DEPLOY_PROXMOXVE_API_TOKEN_KEY" _savedeployconf DEPLOY_PROXMOXVE_API_TOKEN_KEY "$DEPLOY_PROXMOXVE_API_TOKEN_KEY"
fi fi
_debug2 DEPLOY_PROXMOXVE_API_TOKEN_KEY _proxmoxve_api_token_key _debug2 DEPLOY_PROXMOXVE_API_TOKEN_KEY "$_proxmoxve_api_token_key"
# PVE API Token header value. Used in "Authorization: PVEAPIToken". # PVE API Token header value. Used in "Authorization: PVEAPIToken".
_proxmoxve_header_api_token="${_proxmoxve_user}@${_proxmoxve_user_realm}!${_proxmoxve_api_token_name}=${_proxmoxve_api_token_key}" _proxmoxve_header_api_token="${_proxmoxve_user}@${_proxmoxve_user_realm}!${_proxmoxve_api_token_name}=${_proxmoxve_api_token_key}"
_debug2 "Auth Header" _proxmoxve_header_api_token _debug2 "Auth Header" "$_proxmoxve_header_api_token"
# Ugly. I hate putting heredocs inside functions because heredocs don't # Ugly. I hate putting heredocs inside functions because heredocs don't
# account for whitespace correctly but it _does_ work and is several times # account for whitespace correctly but it _does_ work and is several times
@ -124,8 +124,8 @@ HEREDOC
) )
_debug2 Payload "$_json_payload" _debug2 Payload "$_json_payload"
# Push certificates to server. _info "Push certificates to server"
export _HTTPS_INSECURE=1 export HTTPS_INSECURE=1
export _H1="Authorization: PVEAPIToken=${_proxmoxve_header_api_token}" export _H1="Authorization: PVEAPIToken=${_proxmoxve_header_api_token}"
_post "$_json_payload" "$_target_url" "" POST "application/json" _post "$_json_payload" "$_target_url" "" POST "application/json"

View File

@ -137,7 +137,8 @@ routeros_deploy() {
return $_err_code return $_err_code
fi fi
DEPLOY_SCRIPT_CMD="/system script add name=\"LE Cert Deploy - $_cdomain\" owner=$ROUTER_OS_USERNAME \ DEPLOY_SCRIPT_CMD=":do {/system script remove \"LECertDeploy-$_cdomain\" } on-error={ }; \
/system script add name=\"LECertDeploy-$_cdomain\" owner=$ROUTER_OS_USERNAME \
comment=\"generated by routeros deploy script in acme.sh\" \ comment=\"generated by routeros deploy script in acme.sh\" \
source=\"/certificate remove [ find name=$_cdomain.cer_0 ];\ source=\"/certificate remove [ find name=$_cdomain.cer_0 ];\
\n/certificate remove [ find name=$_cdomain.cer_1 ];\ \n/certificate remove [ find name=$_cdomain.cer_1 ];\
@ -146,8 +147,8 @@ source=\"/certificate remove [ find name=$_cdomain.cer_0 ];\
\n/certificate import file-name=$_cdomain.cer passphrase=\\\"\\\";\ \n/certificate import file-name=$_cdomain.cer passphrase=\\\"\\\";\
\n/certificate import file-name=$_cdomain.key passphrase=\\\"\\\";\ \n/certificate import file-name=$_cdomain.key passphrase=\\\"\\\";\
\ndelay 1;\ \ndelay 1;\
\n/file remove $_cdomain.cer;\ \n:do {/file remove $_cdomain.cer; } on-error={ }\
\n/file remove $_cdomain.key;\ \n:do {/file remove $_cdomain.key; } on-error={ }\
\ndelay 2;\ \ndelay 2;\
\n/ip service set www-ssl certificate=$_cdomain.cer_0;\ \n/ip service set www-ssl certificate=$_cdomain.cer_0;\
\n$ROUTER_OS_ADDITIONAL_SERVICES;\ \n$ROUTER_OS_ADDITIONAL_SERVICES;\
@ -158,11 +159,11 @@ source=\"/certificate remove [ find name=$_cdomain.cer_0 ];\
return $_err_code return $_err_code
fi fi
if ! _ssh_remote_cmd "/system script run \"LE Cert Deploy - $_cdomain\""; then if ! _ssh_remote_cmd "/system script run \"LECertDeploy-$_cdomain\""; then
return $_err_code return $_err_code
fi fi
if ! _ssh_remote_cmd "/system script remove \"LE Cert Deploy - $_cdomain\""; then if ! _ssh_remote_cmd "/system script remove \"LECertDeploy-$_cdomain\""; then
return $_err_code return $_err_code
fi fi

172
deploy/ruckus.sh Executable file
View File

@ -0,0 +1,172 @@
#!/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
_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/;.*//'
}
_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
}

View File

@ -10,46 +10,89 @@
#domain keyfile certfile cafile fullchain #domain keyfile certfile cafile fullchain
strongswan_deploy() { strongswan_deploy() {
_cdomain="$1" _cdomain="${1}"
_ckey="$2" _ckey="${2}"
_ccert="$3" _ccert="${3}"
_cca="$4" _cca="${4}"
_cfullchain="$5" _cfullchain="${5}"
_info "Using strongswan" _info "Using strongswan"
if _exists ipsec; then
if [ -x /usr/sbin/ipsec ]; then _ipsec=ipsec
_ipsec=/usr/sbin/ipsec elif _exists strongswan; then
elif [ -x /usr/sbin/strongswan ]; then _ipsec=strongswan
_ipsec=/usr/sbin/strongswan fi
elif [ -x /usr/local/sbin/ipsec ]; then if _exists swanctl; then
_ipsec=/usr/local/sbin/ipsec _swanctl=swanctl
else 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 strongswan or ipsec command is detected"
_err "no swanctl is detected"
return 1 return 1
fi fi
}
_info _ipsec "$_ipsec"
#################### Private functions below ##################################
_confdir=$($_ipsec --confdir)
if [ $? -ne 0 ] || [ -z "$_confdir" ]; then __deploy_cert() {
_err "no strongswan --confdir is detected" _cdomain="${1}"
return 1 _ckey="${2}"
fi _ccert="${3}"
_cca="${4}"
_info _confdir "$_confdir" _cfullchain="${5}"
_swan_mode="${6}"
_debug _cdomain "$_cdomain" _confdir="${7}"
_debug _ckey "$_ckey" _debug _cdomain "${_cdomain}"
_debug _ccert "$_ccert" _debug _ckey "${_ckey}"
_debug _cca "$_cca" _debug _ccert "${_ccert}"
_debug _cfullchain "$_cfullchain" _debug _cca "${_cca}"
_debug _cfullchain "${_cfullchain}"
cat "$_ckey" >"${_confdir}/ipsec.d/private/$(basename "$_ckey")" _debug _swan_mode "${_swan_mode}"
cat "$_ccert" >"${_confdir}/ipsec.d/certs/$(basename "$_ccert")" _debug _confdir "${_confdir}"
cat "$_cca" >"${_confdir}/ipsec.d/cacerts/$(basename "$_cca")" if [ "${_swan_mode}" = "vici" ]; then
cat "$_cfullchain" >"${_confdir}/ipsec.d/cacerts/$(basename "$_cfullchain")" _dir_private="private"
_dir_cert="x509"
$_ipsec reload _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
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
} }

View File

@ -8,20 +8,38 @@
# Updated: 2023-07-03 # Updated: 2023-07-03
# Issues: https://github.com/acmesh-official/acme.sh/issues/2727 # Issues: https://github.com/acmesh-official/acme.sh/issues/2727
################################################################################ ################################################################################
# Usage: # Usage (shown values are the examples):
# 1. export SYNO_Username="adminUser" # 1. Set required environment variables:
# 2. export SYNO_Password="adminPassword" # - use automatically created temp admin user to authenticate
# Optional exports (shown values are the defaults): # export SYNO_USE_TEMP_ADMIN=1
# - export SYNO_Certificate="" to replace a specific certificate via description # - or provide your own admin user credential to authenticate
# - export SYNO_Scheme="http" # 1. export SYNO_USERNAME="adminUser"
# - export SYNO_Hostname="localhost" # 2. export SYNO_PASSWORD="adminPassword"
# - export SYNO_Port="5000" # 2. Set optional environment variables
# - export SYNO_Device_Name="CertRenewal" - required for skipping 2FA-OTP # - common optional variables
# - export SYNO_Device_ID="" - required for skipping 2FA-OTP # - export SYNO_SCHEME="http" - defaults to "http"
# 3. acme.sh --deploy --deploy-hook synology_dsm -d example.com # - export SYNO_HOSTNAME="localhost" - defaults to "localhost"
# - export SYNO_PORT="5000" - defaults to "5000"
# - export SYNO_CREATE=1 - to allow creating the cert if it doesn't exist
# - export SYNO_CERTIFICATE="" - to replace a specific cert by its
# description
# - temp admin optional variables
# - export SYNO_LOCAL_HOSTNAME=1 - if set to 1, force to treat hostname is
# targeting current local machine (since
# this method only locally supported)
# - exsiting admin 2FA-OTP optional variables
# - export SYNO_OTP_CODE="XXXXXX" - if set, script won't require to
# interactive input the OTP code
# - export SYNO_DEVICE_NAME="CertRenewal" - if set, script won't require to
# interactive input the device name
# - export SYNO_DEVICE_ID="" - (deprecated, auth with OTP code instead)
# required for omitting 2FA-OTP
# 3. Run command:
# acme.sh --deploy --deploy-hook synology_dsm -d example.com
################################################################################ ################################################################################
# Dependencies: # Dependencies:
# - jq & curl # - curl
# - synouser & synogroup & synosetkeyvalue (Required for SYNO_USE_TEMP_ADMIN=1)
################################################################################ ################################################################################
# Return value: # Return value:
# 0 means success, otherwise error. # 0 means success, otherwise error.
@ -37,59 +55,89 @@ synology_dsm_deploy() {
_debug _cdomain "$_cdomain" _debug _cdomain "$_cdomain"
# Get username & password, but don't save until we authenticated successfully # Get username and password, but don't save until we authenticated successfully
_getdeployconf SYNO_Username _migratedeployconf SYNO_Username SYNO_USERNAME
_getdeployconf SYNO_Password _migratedeployconf SYNO_Password SYNO_PASSWORD
_getdeployconf SYNO_Create _migratedeployconf SYNO_Device_ID SYNO_DEVICE_ID
_getdeployconf SYNO_DID _migratedeployconf SYNO_Device_Name SYNO_DEVICE_NAME
_getdeployconf SYNO_TOTP_SECRET _getdeployconf SYNO_USERNAME
_getdeployconf SYNO_Device_Name _getdeployconf SYNO_PASSWORD
_getdeployconf SYNO_Device_ID _getdeployconf SYNO_DEVICE_ID
if [ -z "${SYNO_Username:-}" ] || [ -z "${SYNO_Password:-}" ]; then _getdeployconf SYNO_DEVICE_NAME
_err "SYNO_Username & SYNO_Password must be set"
# Prepare to use temp admin if SYNO_USE_TEMP_ADMIN is set
_getdeployconf SYNO_USE_TEMP_ADMIN
_check2cleardeployconfexp SYNO_USE_TEMP_ADMIN
_debug2 SYNO_USE_TEMP_ADMIN "$SYNO_USE_TEMP_ADMIN"
if [ -n "$SYNO_USE_TEMP_ADMIN" ]; then
if ! _exists synouser || ! _exists synogroup || ! _exists synosetkeyvalue; then
_err "Missing required tools to creat temp admin user, please set SYNO_USERNAME and SYNO_PASSWORD instead."
_err "Notice: temp admin user authorization method only supports local deployment on DSM."
return 1
fi
if synouser --help 2>&1 | grep -q 'Permission denied'; then
_err "For creating temp admin user, the deploy script must be run as root."
return 1
fi
[ -n "$SYNO_USERNAME" ] || _savedeployconf SYNO_USERNAME ""
[ -n "$SYNO_PASSWORD" ] || _savedeployconf SYNO_PASSWORD ""
_debug "Setting temp admin user credential..."
SYNO_USERNAME=sc-acmesh-tmp
SYNO_PASSWORD=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 16)
# Set 2FA-OTP settings to empty consider they won't be needed.
SYNO_DEVICE_ID=
SYNO_DEVICE_NAME=
SYNO_OTP_CODE=
else
_debug2 SYNO_USERNAME "$SYNO_USERNAME"
_secure_debug2 SYNO_PASSWORD "$SYNO_PASSWORD"
_debug2 SYNO_DEVICE_NAME "$SYNO_DEVICE_NAME"
_secure_debug2 SYNO_DEVICE_ID "$SYNO_DEVICE_ID"
fi
if [ -z "$SYNO_USERNAME" ] || [ -z "$SYNO_PASSWORD" ]; then
_err "You must set either SYNO_USE_TEMP_ADMIN, or set both SYNO_USERNAME and SYNO_PASSWORD."
return 1 return 1
fi fi
if [ -n "${SYNO_Device_Name:-}" ] && [ -z "${SYNO_Device_ID:-}" ]; then
_err "SYNO_Device_Name set, but SYNO_Device_ID is empty"
return 1
fi
_debug2 SYNO_Username "$SYNO_Username"
_secure_debug2 SYNO_Password "$SYNO_Password"
_debug2 SYNO_Create "$SYNO_Create"
_debug2 SYNO_Device_Name "$SYNO_Device_Name"
_secure_debug2 SYNO_Device_ID "$SYNO_Device_ID"
# Optional scheme, hostname & port for Synology DSM # Optional scheme, hostname and port for Synology DSM
_getdeployconf SYNO_Scheme _migratedeployconf SYNO_Scheme SYNO_SCHEME
_getdeployconf SYNO_Hostname _migratedeployconf SYNO_Hostname SYNO_HOSTNAME
_getdeployconf SYNO_Port _migratedeployconf SYNO_Port SYNO_PORT
_getdeployconf SYNO_SCHEME
_getdeployconf SYNO_HOSTNAME
_getdeployconf SYNO_PORT
# Default values for scheme, hostname & port # Default values for scheme, hostname and port
# Defaulting to localhost & http, because it's localhost… # Defaulting to localhost and http, because it's localhost…
[ -n "${SYNO_Scheme}" ] || SYNO_Scheme="http" [ -n "$SYNO_SCHEME" ] || SYNO_SCHEME=http
[ -n "${SYNO_Hostname}" ] || SYNO_Hostname="localhost" [ -n "$SYNO_HOSTNAME" ] || SYNO_HOSTNAME=localhost
[ -n "${SYNO_Port}" ] || SYNO_Port="5000" [ -n "$SYNO_PORT" ] || SYNO_PORT=5000
_savedeployconf SYNO_Scheme "$SYNO_Scheme" _savedeployconf SYNO_SCHEME "$SYNO_SCHEME"
_savedeployconf SYNO_Hostname "$SYNO_Hostname" _savedeployconf SYNO_HOSTNAME "$SYNO_HOSTNAME"
_savedeployconf SYNO_Port "$SYNO_Port" _savedeployconf SYNO_PORT "$SYNO_PORT"
_debug2 SYNO_Scheme "$SYNO_Scheme" _debug2 SYNO_SCHEME "$SYNO_SCHEME"
_debug2 SYNO_Hostname "$SYNO_Hostname" _debug2 SYNO_HOSTNAME "$SYNO_HOSTNAME"
_debug2 SYNO_Port "$SYNO_Port" _debug2 SYNO_PORT "$SYNO_PORT"
# Get the certificate description, but don't save it until we verify it's real # Get the certificate description, but don't save it until we verify it's real
_getdeployconf SYNO_Certificate _migratedeployconf SYNO_Certificate SYNO_CERTIFICATE "base64"
_debug SYNO_Certificate "${SYNO_Certificate:-}" _getdeployconf SYNO_CERTIFICATE
_check2cleardeployconfexp SYNO_CERTIFICATE
_debug SYNO_CERTIFICATE "${SYNO_CERTIFICATE:-}"
# shellcheck disable=SC1003 # We are not trying to escape a single quote # shellcheck disable=SC1003 # We are not trying to escape a single quote
if printf "%s" "$SYNO_Certificate" | grep '\\'; then if printf "%s" "$SYNO_CERTIFICATE" | grep '\\'; then
_err "Do not use a backslash (\) in your certificate description" _err "Do not use a backslash (\) in your certificate description"
return 1 return 1
fi fi
_base_url="$SYNO_Scheme://$SYNO_Hostname:$SYNO_Port" _debug "Getting API version..."
_base_url="$SYNO_SCHEME://$SYNO_HOSTNAME:$SYNO_PORT"
_debug _base_url "$_base_url" _debug _base_url "$_base_url"
_debug "Getting API version"
response=$(_get "$_base_url/webapi/query.cgi?api=SYNO.API.Info&version=1&method=query&query=SYNO.API.Auth") response=$(_get "$_base_url/webapi/query.cgi?api=SYNO.API.Info&version=1&method=query&query=SYNO.API.Auth")
api_path=$(echo "$response" | grep "SYNO.API.Auth" | sed -n 's/.*"path" *: *"\([^"]*\)".*/\1/p') api_path=$(echo "$response" | grep "SYNO.API.Auth" | sed -n 's/.*"path" *: *"\([^"]*\)".*/\1/p')
api_version=$(echo "$response" | grep "SYNO.API.Auth" | sed -n 's/.*"maxVersion" *: *\([0-9]*\).*/\1/p') api_version=$(echo "$response" | grep "SYNO.API.Auth" | sed -n 's/.*"maxVersion" *: *\([0-9]*\).*/\1/p')
@ -97,63 +145,167 @@ synology_dsm_deploy() {
_debug3 api_path "$api_path" _debug3 api_path "$api_path"
_debug3 api_version "$api_version" _debug3 api_version "$api_version"
# Login, get the session ID & SynoToken from JSON # Login, get the session ID and SynoToken from JSON
_info "Logging into $SYNO_Hostname:$SYNO_Port" _info "Logging into $SYNO_HOSTNAME:$SYNO_PORT..."
encoded_username="$(printf "%s" "$SYNO_Username" | _url_encode)" encoded_username="$(printf "%s" "$SYNO_USERNAME" | _url_encode)"
encoded_password="$(printf "%s" "$SYNO_Password" | _url_encode)" encoded_password="$(printf "%s" "$SYNO_PASSWORD" | _url_encode)"
# ## START ## - DEPRECATED, for backward compatibility
_getdeployconf SYNO_TOTP_SECRET
otp_code=""
# START - DEPRECATED, only kept for legacy compatibility reasons
if [ -n "$SYNO_TOTP_SECRET" ]; then if [ -n "$SYNO_TOTP_SECRET" ]; then
_info "WARNING: Usage of SYNO_TOTP_SECRET is deprecated!" _info "WARNING: Usage of SYNO_TOTP_SECRET is deprecated!"
_info " See synology_dsm.sh script or ACME.sh Wiki page for details:" _info " See synology_dsm.sh script or ACME.sh Wiki page for details:"
_info " https://github.com/acmesh-official/acme.sh/wiki/Synology-NAS-Guide" _info " https://github.com/acmesh-official/acme.sh/wiki/Synology-NAS-Guide"
DEPRECATED_otp_code="" if ! _exists oathtool; then
if _exists oathtool; then
DEPRECATED_otp_code="$(oathtool --base32 --totp "${SYNO_TOTP_SECRET}" 2>/dev/null)"
else
_err "oathtool could not be found, install oathtool to use SYNO_TOTP_SECRET" _err "oathtool could not be found, install oathtool to use SYNO_TOTP_SECRET"
return 1 return 1
fi fi
DEPRECATED_otp_code="$(oathtool --base32 --totp "$SYNO_TOTP_SECRET" 2>/dev/null)"
if [ -n "$SYNO_DID" ]; then if [ -z "$SYNO_DEVICE_ID" ]; then
_H1="Cookie: did=$SYNO_DID" _getdeployconf SYNO_DID
[ -n "$SYNO_DID" ] || SYNO_DEVICE_ID="$SYNO_DID"
fi
if [ -n "$SYNO_DEVICE_ID" ]; then
_H1="Cookie: did=$SYNO_DEVICE_ID"
export _H1 export _H1
_debug3 H1 "${_H1}" _debug3 H1 "${_H1}"
fi fi
response=$(_post "method=login&account=$encoded_username&passwd=$encoded_password&api=SYNO.API.Auth&version=$api_version&enable_syno_token=yes&otp_code=$DEPRECATED_otp_code&device_name=certrenewal&device_id=$SYNO_DID" "$_base_url/webapi/auth.cgi?enable_syno_token=yes") response=$(_post "method=login&account=$encoded_username&passwd=$encoded_password&api=SYNO.API.Auth&version=$api_version&enable_syno_token=yes&otp_code=$DEPRECATED_otp_code&device_name=certrenewal&device_id=$SYNO_DEVICE_ID" "$_base_url/webapi/$api_path?enable_syno_token=yes")
_debug3 response "$response" _debug3 response "$response"
# END - DEPRECATED, only kept for legacy compatibility reasons # ## END ## - DEPRECATED, for backward compatibility
# Get device ID if still empty first, otherwise log in right away # If SYNO_DEVICE_ID or SYNO_OTP_CODE is set, we treat current account enabled 2FA-OTP.
elif [ -z "${SYNO_Device_ID:-}" ]; then # Notice that if SYNO_USE_TEMP_ADMIN=1, both variables will be unset
printf "Enter OTP code for user '%s': " "$SYNO_Username" else
read -r otp_code if [ -n "$SYNO_DEVICE_ID" ] || [ -n "$SYNO_OTP_CODE" ]; then
if [ -z "${SYNO_Device_Name:-}" ]; then response='{"error":{"code":403}}'
# Assume the current account disabled 2FA-OTP, try to log in right away.
else
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
_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
fi
_debug "Creating temp admin user in Synology DSM..."
if synogroup --help | grep -q '\-\-memberadd '; then
_temp_admin_create "$SYNO_USERNAME" "$SYNO_PASSWORD"
synogroup --memberadd administrators "$SYNO_USERNAME" >/dev/null
elif synogroup --help | grep -q '\-\-member '; then
# For supporting DSM 6.x which only has `--member` parameter.
cur_admins=$(synogroup --get administrators | awk -F '[][]' '/Group Members/,0{if(NF>1)printf "%s ", $2}')
if [ -n "$cur_admins" ]; then
_temp_admin_create "$SYNO_USERNAME" "$SYNO_PASSWORD"
_secure_debug3 admin_users "$cur_admins$SYNO_USERNAME"
# shellcheck disable=SC2086
synogroup --member administrators $cur_admins $SYNO_USERNAME >/dev/null
else
_err "The tool synogroup may be broken, please set SYNO_USERNAME and SYNO_PASSWORD instead."
return 1
fi
else
_err "Unsupported synogroup tool detected, please set SYNO_USERNAME and SYNO_PASSWORD instead."
return 1
fi
# havig a workaround to temporary disable enforce 2FA-OTP, will restore
# it soon (after a single request), though if any accident occurs like
# unexpected interruption, this setting can be easily reverted manually.
otp_enforce_option=$(synogetkeyvalue /etc/synoinfo.conf otp_enforce_option)
if [ -n "$otp_enforce_option" ] && [ "${otp_enforce_option:-"none"}" != "none" ]; then
synosetkeyvalue /etc/synoinfo.conf otp_enforce_option none
_info "Enforcing 2FA-OTP has been disabled to complete temp admin authentication."
_info "Notice: it will be restored soon, if not, you can restore it manually via Control Panel."
_info "previous_otp_enforce_option" "$otp_enforce_option"
else
otp_enforce_option=""
fi
fi
response=$(_get "$_base_url/webapi/$api_path?api=SYNO.API.Auth&version=$api_version&method=login&format=sid&account=$encoded_username&passwd=$encoded_password&enable_syno_token=yes")
if [ -n "$SYNO_USE_TEMP_ADMIN" ] && [ -n "$otp_enforce_option" ]; then
synosetkeyvalue /etc/synoinfo.conf otp_enforce_option "$otp_enforce_option"
_info "Restored previous enforce 2FA-OTP option."
fi
_debug3 response "$response"
fi
fi
error_code=$(echo "$response" | grep '"error":' | grep -o '"code":[0-9]*' | grep -o '[0-9]*')
_debug2 error_code "$error_code"
# Account has 2FA-OTP enabled, since error 403 reported.
# https://global.download.synology.com/download/Document/Software/DeveloperGuide/Os/DSM/All/enu/DSM_Login_Web_API_Guide_enu.pdf
if [ "$error_code" == "403" ]; then
if [ -z "$SYNO_DEVICE_NAME" ]; then
printf "Enter device name or leave empty for default (CertRenewal): " printf "Enter device name or leave empty for default (CertRenewal): "
read -r SYNO_Device_Name read -r SYNO_DEVICE_NAME
[ -n "${SYNO_Device_Name}" ] || SYNO_Device_Name="CertRenewal" [ -n "$SYNO_DEVICE_NAME" ] || SYNO_DEVICE_NAME="CertRenewal"
fi fi
response=$(_get "$_base_url/webapi/$api_path?api=SYNO.API.Auth&version=$api_version&method=login&format=sid&account=$encoded_username&passwd=$encoded_password&otp_code=$otp_code&enable_syno_token=yes&enable_device_token=yes&device_name=$SYNO_Device_Name") if [ -n "$SYNO_DEVICE_ID" ]; then
_secure_debug3 response "$response" # Omit OTP code with SYNO_DEVICE_ID.
response=$(_get "$_base_url/webapi/$api_path?api=SYNO.API.Auth&version=$api_version&method=login&format=sid&account=$encoded_username&passwd=$encoded_password&enable_syno_token=yes&device_name=$SYNO_DEVICE_NAME&device_id=$SYNO_DEVICE_ID")
_secure_debug3 response "$response"
else
# Require the OTP code if still unset.
if [ -z "$SYNO_OTP_CODE" ]; then
printf "Enter OTP code for user '%s': " "$SYNO_USERNAME"
read -r SYNO_OTP_CODE
fi
_secure_debug SYNO_OTP_CODE "${SYNO_OTP_CODE:-}"
id_property='device_id' if [ -z "$SYNO_OTP_CODE" ]; then
[ "${api_version}" -gt '6' ] || id_property='did' response='{"error":{"code":404}}'
SYNO_Device_ID=$(echo "$response" | grep "$id_property" | sed -n 's/.*"'$id_property'" *: *"\([^"]*\).*/\1/p') else
_secure_debug2 SYNO_Device_ID "$SYNO_Device_ID" response=$(_get "$_base_url/webapi/$api_path?api=SYNO.API.Auth&version=$api_version&method=login&format=sid&account=$encoded_username&passwd=$encoded_password&enable_syno_token=yes&enable_device_token=yes&device_name=$SYNO_DEVICE_NAME&otp_code=$SYNO_OTP_CODE")
else _secure_debug3 response "$response"
response=$(_get "$_base_url/webapi/$api_path?api=SYNO.API.Auth&version=$api_version&method=login&format=sid&account=$encoded_username&passwd=$encoded_password&enable_syno_token=yes&device_name=$SYNO_Device_Name&device_id=$SYNO_Device_ID")
_debug3 response "$response" id_property='device_id'
[ "${api_version}" -gt '6' ] || id_property='did'
SYNO_DEVICE_ID=$(echo "$response" | grep "$id_property" | sed -n 's/.*"'$id_property'" *: *"\([^"]*\).*/\1/p')
_secure_debug2 SYNO_DEVICE_ID "$SYNO_DEVICE_ID"
fi
fi
error_code=$(echo "$response" | grep '"error":' | grep -o '"code":[0-9]*' | grep -o '[0-9]*')
_debug2 error_code "$error_code"
fi
if [ -n "$error_code" ]; then
if [ "$error_code" == "403" ] && [ -n "$SYNO_DEVICE_ID" ]; then
_cleardeployconf SYNO_DEVICE_ID
_err "Failed to authenticate with SYNO_DEVICE_ID (may expired or invalid), please try again in a new terminal window."
elif [ "$error_code" == "404" ]; then
_err "Failed to authenticate with provided 2FA-OTP code, please try again in a new terminal window."
elif [ "$error_code" == "406" ]; then
if [ -n "$SYNO_USE_TEMP_ADMIN" ]; then
_err "Failed with unexcepted error, please report this by providing full log with '--debug 3'."
else
_err "Enforce auth with 2FA-OTP enabled, please configure the user to enable 2FA-OTP to continue."
fi
elif [ "$error_code" == "400" ]; then
_err "Failed to authenticate, no such account or incorrect password."
elif [ "$error_code" == "401" ]; then
_err "Failed to authenticate with a non-existent account."
elif [ "$error_code" == "408" ] || [ "$error_code" == "409" ] || [ "$error_code" == "410" ]; then
_err "Failed to authenticate, the account password has expired or must be changed."
else
_err "Failed to authenticate with error: $error_code."
fi
_temp_admin_cleanup "$SYNO_USE_TEMP_ADMIN" "$SYNO_USERNAME"
return 1
fi fi
sid=$(echo "$response" | grep "sid" | sed -n 's/.*"sid" *: *"\([^"]*\).*/\1/p') sid=$(echo "$response" | grep "sid" | sed -n 's/.*"sid" *: *"\([^"]*\).*/\1/p')
token=$(echo "$response" | grep "synotoken" | sed -n 's/.*"synotoken" *: *"\([^"]*\).*/\1/p') token=$(echo "$response" | grep "synotoken" | sed -n 's/.*"synotoken" *: *"\([^"]*\).*/\1/p')
_debug "Session ID" "$sid" _debug "Session ID" "$sid"
_debug SynoToken "$token" _debug SynoToken "$token"
if [ -z "$SYNO_DID" ] && [ -z "$SYNO_Device_ID" ] || [ -z "$sid" ] || [ -z "$token" ]; then if [ -z "$sid" ] || [ -z "$token" ]; then
_err "Unable to authenticate to $_base_url - check your username & password." # Still can't get necessary info even got no errors, may Synology have API updated?
_err "If two-factor authentication is enabled for the user, set SYNO_Device_ID." _err "Unable to authenticate to $_base_url, you may report this by providing full log with '--debug 3'."
_temp_admin_cleanup "$SYNO_USE_TEMP_ADMIN" "$SYNO_USERNAME"
return 1 return 1
fi fi
@ -161,36 +313,62 @@ synology_dsm_deploy() {
export _H1 export _H1
_debug2 H1 "${_H1}" _debug2 H1 "${_H1}"
# Now that we know the username & password are good, save them # Now that we know the username and password are good, save them if not in temp admin mode.
_savedeployconf SYNO_Username "$SYNO_Username" if [ -n "$SYNO_USE_TEMP_ADMIN" ]; then
_savedeployconf SYNO_Password "$SYNO_Password" _cleardeployconf SYNO_USERNAME
_savedeployconf SYNO_Device_Name "$SYNO_Device_Name" _cleardeployconf SYNO_PASSWORD
_savedeployconf SYNO_Device_ID "$SYNO_Device_ID" _cleardeployconf SYNO_DEVICE_ID
_cleardeployconf SYNO_DEVICE_NAME
_savedeployconf SYNO_USE_TEMP_ADMIN "$SYNO_USE_TEMP_ADMIN"
_savedeployconf SYNO_LOCAL_HOSTNAME "$SYNO_HOSTNAME"
else
_savedeployconf SYNO_USERNAME "$SYNO_USERNAME"
_savedeployconf SYNO_PASSWORD "$SYNO_PASSWORD"
_savedeployconf SYNO_DEVICE_ID "$SYNO_DEVICE_ID"
_savedeployconf SYNO_DEVICE_NAME "$SYNO_DEVICE_NAME"
fi
_info "Getting certificates in Synology DSM" _info "Getting certificates in Synology DSM..."
response=$(_post "api=SYNO.Core.Certificate.CRT&method=list&version=1&_sid=$sid" "$_base_url/webapi/entry.cgi") response=$(_post "api=SYNO.Core.Certificate.CRT&method=list&version=1&_sid=$sid" "$_base_url/webapi/entry.cgi")
_debug3 response "$response" _debug3 response "$response"
escaped_certificate="$(printf "%s" "$SYNO_Certificate" | sed 's/\([].*^$[]\)/\\\1/g;s/"/\\\\"/g')" escaped_certificate="$(printf "%s" "$SYNO_CERTIFICATE" | sed 's/\([].*^$[]\)/\\\1/g;s/"/\\\\"/g')"
_debug escaped_certificate "$escaped_certificate" _debug escaped_certificate "$escaped_certificate"
id=$(echo "$response" | sed -n "s/.*\"desc\":\"$escaped_certificate\",\"id\":\"\([^\"]*\).*/\1/p") id=$(echo "$response" | sed -n "s/.*\"desc\":\"$escaped_certificate\",\"id\":\"\([^\"]*\).*/\1/p")
_debug2 id "$id" _debug2 id "$id"
if [ -z "$id" ] && [ -z "${SYNO_Create:-}" ]; then error_code=$(echo "$response" | grep '"error":' | grep -o '"code":[0-9]*' | grep -o '[0-9]*')
_err "Unable to find certificate: $SYNO_Certificate & \$SYNO_Create is not set" _debug2 error_code "$error_code"
if [ -n "$error_code" ]; then
if [ "$error_code" -eq 105 ]; then
_err "Current user is not administrator and does not have sufficient permission for deploying."
else
_err "Failed to fetch certificate info: $error_code, please try again or contact Synology to learn more."
fi
_temp_admin_cleanup "$SYNO_USE_TEMP_ADMIN" "$SYNO_USERNAME"
return 1
fi
_migratedeployconf SYNO_Create SYNO_CREATE
_getdeployconf SYNO_CREATE
_debug2 SYNO_CREATE "$SYNO_CREATE"
if [ -z "$id" ] && [ -z "$SYNO_CREATE" ]; then
_err "Unable to find certificate: $SYNO_CERTIFICATE and $SYNO_CREATE is not set."
_temp_admin_cleanup "$SYNO_USE_TEMP_ADMIN" "$SYNO_USERNAME"
return 1 return 1
fi fi
# We've verified this certificate description is a thing, so save it # We've verified this certificate description is a thing, so save it
_savedeployconf SYNO_Certificate "$SYNO_Certificate" "base64" _savedeployconf SYNO_CERTIFICATE "$SYNO_CERTIFICATE" "base64"
_info "Generate form POST request" _info "Generating form POST request..."
nl="\0015\0012" nl="\0015\0012"
delim="--------------------------$(_utc_date | tr -d -- '-: ')" delim="--------------------------$(_utc_date | tr -d -- '-: ')"
content="--$delim${nl}Content-Disposition: form-data; name=\"key\"; filename=\"$(basename "$_ckey")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ckey")\0012" content="--$delim${nl}Content-Disposition: form-data; name=\"key\"; filename=\"$(basename "$_ckey")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ckey")\0012"
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"cert\"; filename=\"$(basename "$_ccert")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ccert")\0012" content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"cert\"; filename=\"$(basename "$_ccert")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ccert")\0012"
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"inter_cert\"; filename=\"$(basename "$_cca")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_cca")\0012" content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"inter_cert\"; filename=\"$(basename "$_cca")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_cca")\0012"
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"id\"${nl}${nl}$id" content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"id\"${nl}${nl}$id"
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"desc\"${nl}${nl}${SYNO_Certificate}" content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"desc\"${nl}${nl}${SYNO_CERTIFICATE}"
if echo "$response" | sed -n "s/.*\"desc\":\"$escaped_certificate\",\([^{]*\).*/\1/p" | grep -- 'is_default":true' >/dev/null; then if echo "$response" | sed -n "s/.*\"desc\":\"$escaped_certificate\",\([^{]*\).*/\1/p" | grep -- 'is_default":true' >/dev/null; then
_debug2 default "This is the default certificate" _debug2 default "This is the default certificate"
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"as_default\"${nl}${nl}true" content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"as_default\"${nl}${nl}true"
@ -201,21 +379,22 @@ synology_dsm_deploy() {
content="$(printf "%b_" "$content")" content="$(printf "%b_" "$content")"
content="${content%_}" # protect trailing \n content="${content%_}" # protect trailing \n
_info "Upload certificate to the Synology DSM" _info "Upload certificate to the Synology DSM."
response=$(_post "$content" "$_base_url/webapi/entry.cgi?api=SYNO.Core.Certificate&method=import&version=1&SynoToken=$token&_sid=$sid" "" "POST" "multipart/form-data; boundary=${delim}") response=$(_post "$content" "$_base_url/webapi/entry.cgi?api=SYNO.Core.Certificate&method=import&version=1&SynoToken=$token&_sid=$sid" "" "POST" "multipart/form-data; boundary=${delim}")
_debug3 response "$response" _debug3 response "$response"
if ! echo "$response" | grep '"error":' >/dev/null; then if ! echo "$response" | grep '"error":' >/dev/null; then
if echo "$response" | grep '"restart_httpd":true' >/dev/null; then if echo "$response" | grep '"restart_httpd":true' >/dev/null; then
_info "Restarting HTTP services succeeded" _info "Restart HTTP services succeeded."
else else
_info "Restarting HTTP services failed" _info "Restart HTTP services failed."
fi fi
_temp_admin_cleanup "$SYNO_USE_TEMP_ADMIN" "$SYNO_USERNAME"
_logout _logout
return 0 return 0
else else
_err "Unable to update certificate, error code $response" _temp_admin_cleanup "$SYNO_USE_TEMP_ADMIN" "$SYNO_USERNAME"
_err "Unable to update certificate, got error response: $response."
_logout _logout
return 1 return 1
fi fi
@ -223,7 +402,44 @@ synology_dsm_deploy() {
#################### Private functions below ################################## #################### Private functions below ##################################
_logout() { _logout() {
# Logout to not occupy a permanent session, e.g. in DSM's "Connected Users" widget # Logout CERT user only to not occupy a permanent session, e.g. in DSM's "Connected Users" widget (based on previous variables)
response=$(_get "$_base_url/webapi/entry.cgi?api=SYNO.API.Auth&version=$api_version&method=logout") response=$(_get "$_base_url/webapi/$api_path?api=SYNO.API.Auth&version=$api_version&method=logout&_sid=$sid")
_debug3 response "$response" _debug3 response "$response"
} }
_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
}
_temp_admin_cleanup() {
_flag=$1
_username=$2
if [ -n "${_flag}" ]; then
_debug "Cleanuping temp admin info..."
synouser --del "$_username" >/dev/null
fi
}
#_cleardeployconf key
_cleardeployconf() {
_cleardomainconf "SAVED_$1"
}
# key
_check2cleardeployconfexp() {
_key="$1"
_clear_key="CLEAR_$_key"
# Clear saved settings if explicitly requested
if [ -n "$(eval echo \$"$_clear_key")" ]; then
_debug2 "$_key: value cleared from config, exported value will be ignored."
_cleardeployconf "$_key"
eval "$_key"=
export "$_key"=
eval SAVED_"$_key"=
export SAVED_"$_key"=
fi
}

View File

@ -9,7 +9,7 @@
# #
# Following environment variables must be set: # 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 # The following environmental variables may be set if you don't like their
# default values: # default values:
@ -64,6 +64,20 @@ truenas_deploy() {
_response=$(_get "$_api_url/system/state") _response=$(_get "$_api_url/system/state")
_info "TrueNAS system state: $_response." _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 if [ -z "$_response" ]; then
_err "Unable to authenticate to $_api_url." _err "Unable to authenticate to $_api_url."
_err 'Check your connection settings are correct, e.g.' _err 'Check your connection settings are correct, e.g.'
@ -115,27 +129,106 @@ truenas_deploy() {
_debug3 _activate_result "$_activate_result" _debug3 _activate_result "$_activate_result"
_info "Checking if WebDAV certificate is the same as the TrueNAS web UI" _truenas_version_23_10="23.10"
_webdav_list=$(_get "$_api_url/webdav") _truenas_version_24_10="24.10"
_webdav_cert_id=$(echo "$_webdav_list" | grep '"certssl":' | tr -d -- '"certsl: ,')
if [ "$_webdav_cert_id" = "$_active_cert_id" ]; then _check_version=$(printf "%s\n%s" "$_truenas_version_23_10" "$_truenas_version" | sort -V | head -n 1)
_info "Updating the WebDAV certificate" if [ "$_truenas_os" != "SCALE" ] || [ "$_check_version" != "$_truenas_version_23_10" ]; then
_debug _webdav_cert_id "$_webdav_cert_id" _info "Checking if WebDAV certificate is the same as the TrueNAS web UI"
_webdav_data="{\"certssl\": \"${_cert_id}\"}" _webdav_list=$(_get "$_api_url/webdav")
_activate_webdav_cert="$(_post "$_webdav_data" "$_api_url/webdav" "" "PUT" "application/json")" _webdav_cert_id=$(echo "$_webdav_list" | grep '"certssl":' | tr -d -- '"certsl: ,')
_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 if [ "$_webdav_cert_id" = "$_active_cert_id" ]; then
_info "WebDAV certificate updated successfully" _info "Updating the WebDAV certificate"
else _debug _webdav_cert_id "$_webdav_cert_id"
_err "Unable to set WebDAV certificate" _webdav_data="{\"certssl\": \"${_cert_id}\"}"
_debug3 _activate_webdav_cert "$_activate_webdav_cert" _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" _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" | _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 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 fi
_info "Checking if FTP certificate is the same as the TrueNAS web UI" _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" _info "FTP certificate is not configured or is not the same as TrueNAS web UI"
fi 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" _info "Deleting old certificate"
_delete_result="$(_post "" "$_api_url/certificate/id/$_active_cert_id" "" "DELETE" "application/json")" _delete_result="$(_post "" "$_api_url/certificate/id/$_active_cert_id" "" "DELETE" "application/json")"

View File

@ -5,6 +5,15 @@
# - self-hosted Unifi Controller # - self-hosted Unifi Controller
# - Unifi Cloud Key (Gen1/2/2+) # - Unifi Cloud Key (Gen1/2/2+)
# - Unifi Cloud Key running UnifiOS (v2.0.0+, Gen2/2+ only) # - Unifi Cloud Key running UnifiOS (v2.0.0+, Gen2/2+ only)
# - Unifi Dream Machine
# This has not been tested on other "all-in-one" devices such as
# UDM Pro or Unifi Express.
#
# OS Version v2.0.0+
# Network Application version 7.0.0+
# OS version ~3.1 removed java and keytool from the UnifiOS.
# Using PKCS12 format keystore appears to work fine.
#
# Please report bugs to https://github.com/acmesh-official/acme.sh/issues/3359 # Please report bugs to https://github.com/acmesh-official/acme.sh/issues/3359
#returns 0 means success, otherwise error. #returns 0 means success, otherwise error.
@ -74,14 +83,16 @@ unifi_deploy() {
_reload_cmd="" _reload_cmd=""
# Unifi Controller environment (self hosted or any Cloud Key) -- # Unifi Controller environment (self hosted or any Cloud Key) --
# auto-detect by file /usr/lib/unifi/data/keystore: # auto-detect by file /usr/lib/unifi/data/keystore
_unifi_keystore="${DEPLOY_UNIFI_KEYSTORE:-/usr/lib/unifi/data/keystore}" _unifi_keystore="${DEPLOY_UNIFI_KEYSTORE:-/usr/lib/unifi/data/keystore}"
if [ -f "$_unifi_keystore" ]; then if [ -f "$_unifi_keystore" ]; then
_info "Installing certificate for Unifi Controller (Java keystore)"
_debug _unifi_keystore "$_unifi_keystore" _debug _unifi_keystore "$_unifi_keystore"
if ! _exists keytool; then if ! _exists keytool; then
_err "keytool not found" _do_keytool=0
return 1 _info "Installing certificate for Unifi Controller (PKCS12 keystore)."
else
_do_keytool=1
_info "Installing certificate for Unifi Controller (Java keystore)"
fi fi
if [ ! -w "$_unifi_keystore" ]; then if [ ! -w "$_unifi_keystore" ]; then
_err "The file $_unifi_keystore is not writable, please change the permission." _err "The file $_unifi_keystore is not writable, please change the permission."
@ -92,6 +103,7 @@ unifi_deploy() {
_debug "Generate import pkcs12" _debug "Generate import pkcs12"
_import_pkcs12="$(_mktemp)" _import_pkcs12="$(_mktemp)"
_debug "_toPkcs $_import_pkcs12 $_ckey $_ccert $_cca $_unifi_keypass unifi root"
_toPkcs "$_import_pkcs12" "$_ckey" "$_ccert" "$_cca" "$_unifi_keypass" unifi root _toPkcs "$_import_pkcs12" "$_ckey" "$_ccert" "$_cca" "$_unifi_keypass" unifi root
# shellcheck disable=SC2181 # shellcheck disable=SC2181
if [ "$?" != "0" ]; then if [ "$?" != "0" ]; then
@ -99,22 +111,57 @@ unifi_deploy() {
return 1 return 1
fi fi
_debug "Import into keystore: $_unifi_keystore" # Save the existing keystore in case something goes wrong.
if keytool -importkeystore \ mv -f "${_unifi_keystore}" "${_unifi_keystore}"_original
-deststorepass "$_unifi_keypass" -destkeypass "$_unifi_keypass" -destkeystore "$_unifi_keystore" \ _info "Previous keystore saved to ${_unifi_keystore}_original."
-srckeystore "$_import_pkcs12" -srcstoretype PKCS12 -srcstorepass "$_unifi_keypass" \
-alias unifi -noprompt; then if [ "$_do_keytool" -eq 1 ]; then
_debug "Import keystore success!" _debug "Import into keystore: $_unifi_keystore"
rm "$_import_pkcs12" if keytool -importkeystore \
-deststorepass "$_unifi_keypass" -destkeypass "$_unifi_keypass" -destkeystore "$_unifi_keystore" \
-srckeystore "$_import_pkcs12" -srcstoretype PKCS12 -srcstorepass "$_unifi_keypass" \
-alias unifi -noprompt; then
_debug "Import keystore success!"
else
_err "Error importing into Unifi Java keystore."
_err "Please re-run with --debug and report a bug."
_info "Restoring original keystore."
mv -f "${_unifi_keystore}"_original "${_unifi_keystore}"
rm "$_import_pkcs12"
return 1
fi
else else
_err "Error importing into Unifi Java keystore." _debug "Copying new keystore to $_unifi_keystore"
_err "Please re-run with --debug and report a bug." cp -f "$_import_pkcs12" "$_unifi_keystore"
rm "$_import_pkcs12"
return 1
fi fi
# Update unifi service for certificate cipher compatibility
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."
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 systemctl -q is-active unifi; then
_reload_cmd="${_reload_cmd:+$_reload_cmd && }service unifi restart" 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
fi fi
_services_updated="${_services_updated} unifi" _services_updated="${_services_updated} unifi"
_info "Install Unifi Controller certificate success!" _info "Install Unifi Controller certificate success!"
@ -165,6 +212,11 @@ unifi_deploy() {
return 1 return 1
fi fi
# 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."
cat "$_cfullchain" >"${_unifi_core_config}/unifi-core.crt" cat "$_cfullchain" >"${_unifi_core_config}/unifi-core.crt"
cat "$_ckey" >"${_unifi_core_config}/unifi-core.key" cat "$_ckey" >"${_unifi_core_config}/unifi-core.key"

View File

@ -70,10 +70,10 @@ vault_deploy() {
# JSON does not allow multiline strings. # JSON does not allow multiline strings.
# So replacing new-lines with "\n" here # So replacing new-lines with "\n" here
_ckey=$(sed -z 's/\n/\\n/g' <"$2") _ckey=$(sed -e ':a' -e N -e '$ ! ba' -e 's/\n/\\n/g' <"$2")
_ccert=$(sed -z 's/\n/\\n/g' <"$3") _ccert=$(sed -e ':a' -e N -e '$ ! ba' -e 's/\n/\\n/g' <"$3")
_cca=$(sed -z 's/\n/\\n/g' <"$4") _cca=$(sed -e ':a' -e N -e '$ ! ba' -e 's/\n/\\n/g' <"$4")
_cfullchain=$(sed -z 's/\n/\\n/g' <"$5") _cfullchain=$(sed -e ':a' -e N -e '$ ! ba' -e 's/\n/\\n/g' <"$5")
export _H1="X-Vault-Token: $VAULT_TOKEN" export _H1="X-Vault-Token: $VAULT_TOKEN"

View File

@ -106,5 +106,5 @@ vsftpd_deploy() {
fi fi
return 1 return 1
fi fi
return 0
} }

View File

@ -1,22 +1,18 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# This file name is "dns_1984hosting.sh" # shellcheck disable=SC2034
# So, here must be a method dns_1984hosting_add() dns_1984hosting_info='1984.hosting
# Which will be called by acme.sh to add the txt record to your api system. Domains: 1984.is
# returns 0 means success, otherwise error. Site: 1984.hosting
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_1984hosting
# Author: Adrian Fedoreanu Options:
# Report Bugs here: https://github.com/acmesh-official/acme.sh One984HOSTING_Username Username
# or here... https://github.com/acmesh-official/acme.sh/issues/2851 One984HOSTING_Password Password
Issues: github.com/acmesh-official/acme.sh/issues/2851
Author: Adrian Fedoreanu
'
######## Public functions ##################### ######## Public functions #####################
# Export 1984HOSTING username and password in following variables
#
# One984HOSTING_Username=username
# One984HOSTING_Password=password
#
# username/password and csrftoken/sessionid cookies are saved in ~/.acme.sh/account.conf
# Usage: dns_1984hosting_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" # Usage: dns_1984hosting_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
# Add a text record. # Add a text record.
dns_1984hosting_add() { dns_1984hosting_add() {
@ -128,7 +124,7 @@ _1984hosting_login() {
_debug "Login to 1984Hosting as user $One984HOSTING_Username." _debug "Login to 1984Hosting as user $One984HOSTING_Username."
username=$(printf '%s' "$One984HOSTING_Username" | _url_encode) username=$(printf '%s' "$One984HOSTING_Username" | _url_encode)
password=$(printf '%s' "$One984HOSTING_Password" | _url_encode) password=$(printf '%s' "$One984HOSTING_Password" | _url_encode)
url="https://1984.hosting/accounts/checkuserauth/" url="https://1984.hosting/api/auth/"
_get "https://1984.hosting/accounts/login/" | grep "csrfmiddlewaretoken" _get "https://1984.hosting/accounts/login/" | grep "csrfmiddlewaretoken"
csrftoken="$(grep -i '^set-cookie:' "$HTTP_HEADER" | _egrep_o 'csrftoken=[^;]*;' | tr -d ';')" csrftoken="$(grep -i '^set-cookie:' "$HTTP_HEADER" | _egrep_o 'csrftoken=[^;]*;' | tr -d ';')"
@ -185,7 +181,7 @@ _check_cookies() {
return 1 return 1
fi fi
_authget "https://1984.hosting/accounts/loginstatus/" _authget "https://1984.hosting/api/auth/"
if _contains "$_response" '"ok": true'; then if _contains "$_response" '"ok": true'; then
_debug "Cached cookies still valid." _debug "Cached cookies still valid."
return 0 return 0
@ -215,8 +211,8 @@ _get_root() {
return 1 return 1
fi fi
_authget "https://1984.hosting/domains/soacheck/?zone=$h&nameserver=ns0.1984.is." _authget "https://1984.hosting/domains/zonestatus/$h/?cached=no"
if _contains "$_response" "serial" && ! _contains "$_response" "null"; then if _contains "$_response" '"ok": true'; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain="$h" _domain="$h"
return 0 return 0
@ -250,7 +246,6 @@ _authget() {
} }
# Truncate huge HTML response # Truncate huge HTML response
# Echo: Argument list too long
_htmlget() { _htmlget() {
export _H1="Cookie: $One984HOSTING_CSRFTOKEN_COOKIE; $One984HOSTING_SESSIONID_COOKIE" export _H1="Cookie: $One984HOSTING_CSRFTOKEN_COOKIE; $One984HOSTING_SESSIONID_COOKIE"
_response=$(_get "$1" | grep "$2") _response=$(_get "$1" | grep "$2")

View File

@ -1,18 +1,18 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# # shellcheck disable=SC2034
#Author: Wolfgang Ebner dns_acmedns_info='acme-dns Server API
#Author: Sven Neubuaer The acme-dns is a limited DNS server with RESTful API to handle ACME DNS challenges.
#Report Bugs here: https://github.com/dampfklon/acme.sh Site: github.com/joohoi/acme-dns
# Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_acmedns
# Usage: Options:
# export ACMEDNS_BASE_URL="https://auth.acme-dns.io" ACMEDNS_USERNAME Username. Optional.
# ACMEDNS_PASSWORD Password. Optional.
# You can optionally define an already existing account: ACMEDNS_SUBDOMAIN Subdomain. Optional.
# ACMEDNS_BASE_URL API endpoint. Default: "https://auth.acme-dns.io".
# export ACMEDNS_USERNAME="<username>" Issues: github.com/dampfklon/acme.sh
# export ACMEDNS_PASSWORD="<password>" Author: Wolfgang Ebner, Sven Neubuaer
# export ACMEDNS_SUBDOMAIN="<subdomain>" '
#
######## Public functions ##################### ######## Public functions #####################
#Usage: dns_acmedns_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" #Usage: dns_acmedns_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"

18
dnsapi/dns_acmeproxy.sh Normal file → Executable file
View File

@ -1,9 +1,17 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
## Acmeproxy DNS provider to be used with acmeproxy (https://github.com/mdbraber/acmeproxy) dns_acmeproxy_info='AcmeProxy Server API
## API integration by Maarten den Braber AcmeProxy can be used to as a single host in your network to request certificates through a DNS API.
## Clients can connect with the one AcmeProxy host so you do not need to store DNS API credentials on every single host.
## Report any bugs via https://github.com/mdbraber/acme.sh Site: github.com/mdbraber/acmeproxy
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_acmeproxy
Options:
ACMEPROXY_ENDPOINT API Endpoint
ACMEPROXY_USERNAME Username
ACMEPROXY_PASSWORD Password
Issues: github.com/acmesh-official/acme.sh/issues/2251
Author: Maarten den Braber
'
dns_acmeproxy_add() { dns_acmeproxy_add() {
fulldomain="${1}" fulldomain="${1}"

View File

@ -1,6 +1,13 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
#ACTIVE24_Token="sdfsdfsdfljlbjkljlkjsdfoiwje" dns_active24_info='Active24.com
Site: Active24.com
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_active24
Options:
ACTIVE24_Token API Token
Issues: github.com/acmesh-official/acme.sh/issues/2059
Author: Milan Pála
'
ACTIVE24_Api="https://api.active24.com" ACTIVE24_Api="https://api.active24.com"
@ -76,10 +83,10 @@ _get_root() {
return 1 return 1
fi fi
i=2 i=1
p=1 p=1
while true; do 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 "h" "$h"
if [ -z "$h" ]; then if [ -z "$h" ]; then
#not valid #not valid
@ -87,7 +94,7 @@ _get_root() {
fi fi
if _contains "$response" "\"$h\"" >/dev/null; then 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 _domain=$h
return 0 return 0
fi fi

View File

@ -1,12 +1,13 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
# dns_ad_info='AlwaysData.com
#AD_API_KEY="sdfsdfsdfljlbjkljlkjsdfoiwje" Site: AlwaysData.com
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_ad
#This is the Alwaysdata api wrapper for acme.sh Options:
# AD_API_KEY API Key
#Author: Paul Koppen Issues: github.com/acmesh-official/acme.sh/pull/503
#Report Bugs here: https://github.com/wpk-/acme.sh Author: Paul Koppen
'
AD_API_URL="https://$AD_API_KEY:@api.alwaysdata.com/v1" AD_API_URL="https://$AD_API_KEY:@api.alwaysdata.com/v1"
@ -94,7 +95,7 @@ _get_root() {
if _ad_rest GET "domain/"; then if _ad_rest GET "domain/"; then
response="$(echo "$response" | tr -d "\n" | sed 's/{/\n&/g')" response="$(echo "$response" | tr -d "\n" | sed 's/{/\n&/g')"
while true; do 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 h "$h"
if [ -z "$h" ]; then if [ -z "$h" ]; then
#not valid #not valid
@ -105,7 +106,7 @@ _get_root() {
if [ "$hostedzone" ]; then if [ "$hostedzone" ]; then
_domain_id=$(printf "%s\n" "$hostedzone" | _egrep_o "\"id\":\s*[0-9]+" | _head_n 1 | cut -d : -f 2 | tr -d \ ) _domain_id=$(printf "%s\n" "$hostedzone" | _egrep_o "\"id\":\s*[0-9]+" | _head_n 1 | cut -d : -f 2 | tr -d \ )
if [ "$_domain_id" ]; then 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 _domain=$h
return 0 return 0
fi fi

View File

@ -1,27 +1,27 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
dns_ali_info='AlibabaCloud.com
Domains: Aliyun.com
Site: AlibabaCloud.com
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_ali
Options:
Ali_Key API Key
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_Key="LTqIA87hOKdjevsf5" Ali_DNS_API="https://alidns.aliyuncs.com/"
#Ali_Secret="0p5EYueFNq501xnCPzKNbx6K51qPH2"
#Usage: dns_ali_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" #Usage: dns_ali_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_ali_add() { dns_ali_add() {
fulldomain=$1 fulldomain=$1
txtvalue=$2 txtvalue=$2
Ali_Key="${Ali_Key:-$(_readaccountconf_mutable Ali_Key)}" _prepare_ali_credentials || return 1
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"
_debug "First detect the root zone" _debug "First detect the root zone"
if ! _get_root "$fulldomain"; then if ! _get_root "$fulldomain"; then
@ -46,14 +46,74 @@ dns_ali_rm() {
_clean _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() { _get_root() {
domain=$1 domain=$1
i=2 i=1
p=1 p=1
while true; do 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 if [ -z "$h" ]; then
#not valid #not valid
return 1 return 1
@ -65,7 +125,7 @@ _get_root() {
fi fi
if _contains "$response" "PageNumber"; then 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" _debug _sub_domain "$_sub_domain"
_domain="$h" _domain="$h"
_debug _domain "$_domain" _debug _domain "$_domain"
@ -77,52 +137,10 @@ _get_root() {
return 1 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() { _check_exist_query() {
_qdomain="$1" _qdomain="$1"
_qsubdomain="$2" _qsubdomain="$2"
endpoint=$Ali_DNS_API
query='' query=''
query=$query'AccessKeyId='$Ali_Key query=$query'AccessKeyId='$Ali_Key
query=$query'&Action=DescribeDomainRecords' query=$query'&Action=DescribeDomainRecords'
@ -138,6 +156,7 @@ _check_exist_query() {
} }
_add_record_query() { _add_record_query() {
endpoint=$Ali_DNS_API
query='' query=''
query=$query'AccessKeyId='$Ali_Key query=$query'AccessKeyId='$Ali_Key
query=$query'&Action=AddDomainRecord' query=$query'&Action=AddDomainRecord'
@ -154,6 +173,7 @@ _add_record_query() {
} }
_delete_record_query() { _delete_record_query() {
endpoint=$Ali_DNS_API
query='' query=''
query=$query'AccessKeyId='$Ali_Key query=$query'AccessKeyId='$Ali_Key
query=$query'&Action=DeleteDomainRecord' query=$query'&Action=DeleteDomainRecord'
@ -167,6 +187,7 @@ _delete_record_query() {
} }
_describe_records_query() { _describe_records_query() {
endpoint=$Ali_DNS_API
query='' query=''
query=$query'AccessKeyId='$Ali_Key query=$query'AccessKeyId='$Ali_Key
query=$query'&Action=DescribeDomainRecords' query=$query'&Action=DescribeDomainRecords'
@ -197,7 +218,3 @@ _clean() {
fi fi
} }
_timestamp() {
date -u +"%Y-%m-%dT%H%%3A%M%%3A%SZ"
}

185
dnsapi/dns_alviy.sh Normal file
View File

@ -0,0 +1,185 @@
#!/usr/bin/env sh
# 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"
######## Public functions #####################
#Usage: dns_alviy_add _acme-challenge.www.domain.com "content"
dns_alviy_add() {
fulldomain=$1
txtvalue=$2
Alviy_token="${Alviy_token:-$(_readaccountconf_mutable Alviy_token)}"
if [ -z "$Alviy_token" ]; then
Alviy_token=""
_err "Please specify Alviy token."
return 1
fi
#save the api key and email to the account conf file.
_saveaccountconf_mutable Alviy_token "$Alviy_token"
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"
return 1
fi
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
_debug "Getting existing records"
if _alviy_txt_exists "$_domain" "$fulldomain" "$txtvalue"; then
_info "This record already exists, skipping"
return 0
fi
_add_data="{\"content\":\"$txtvalue\",\"type\":\"TXT\"}"
_debug2 _add_data "$_add_data"
_info "Adding record"
if _alviy_rest POST "zone/$_domain/domain/$fulldomain/" "$_add_data"; then
_debug "Checking updated records of '${fulldomain}'"
if ! _alviy_txt_exists "$_domain" "$fulldomain" "$txtvalue"; then
_err "TXT record '${txtvalue}' for '${fulldomain}', value wasn't set!"
return 1
fi
else
_err "Add txt record error, value '${txtvalue}' for '${fulldomain}' was not set."
return 1
fi
_sleep 10
_info "Added TXT record '${txtvalue}' for '${fulldomain}'."
return 0
}
#fulldomain
dns_alviy_rm() {
fulldomain=$1
txtvalue=$2
Alviy_token="${Alviy_token:-$(_readaccountconf_mutable Alviy_token)}"
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"
return 1
fi
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
if ! _alviy_txt_exists "$_domain" "$fulldomain" "$txtvalue"; then
_info "The record does not exist, skip"
return 0
fi
_add_data=""
uuid=$(echo "$response" | tr "{" "\n" | grep "$txtvalue" | tr "," "\n" | grep uuid | cut -d \" -f4)
# delete record
_debug "Delete TXT record for '${fulldomain}'"
if ! _alviy_rest DELETE "zone/$_domain/record/$uuid" "{\"confirm\":1}"; then
_err "Cannot delete empty TXT record for '$fulldomain'"
return 1
fi
_info "The record '$fulldomain'='$txtvalue' deleted"
}
#################### Private functions below ##################################
#_acme-challenge.www.domain.com
#returns
# _sub_domain=_acme-challenge.www
# _domain=domain.com
_get_root() {
domain=$1
i=3
a="init"
while [ -n "$a" ]; do
a=$(printf "%s" "$domain" | cut -d . -f $i-)
i=$((i + 1))
done
n=$((i - 3))
h=$(printf "%s" "$domain" | cut -d . -f $n-)
if [ -z "$h" ]; then
#not valid
_alviy_rest GET "zone/$domain/"
_debug "can't get host from $domain"
return 1
fi
if ! _alviy_rest GET "zone/$h/"; then
return 1
fi
if _contains "$response" '"code":"NOT_FOUND"'; then
_debug "$h not found"
else
s=$((n - 1))
_sub_domain=$(printf "%s" "$domain" | cut -d . -f -$s)
_domain="$h"
return 0
fi
return 1
}
_alviy_txt_exists() {
zone=$1
domain=$2
content_data=$3
_debug "Getting existing records"
if ! _alviy_rest GET "zone/$zone/domain/$domain/TXT/"; then
_info "The record does not exist"
return 1
fi
if ! _contains "$response" "$3"; then
_info "The record has other value"
return 1
fi
# GOOD code return - TRUE function
return 0
}
_alviy_rest() {
method=$1
path="$2"
content_data="$3"
_debug "$path"
export _H1="Authorization: Bearer $Alviy_token"
export _H2="Content-Type: application/json"
if [ "$content_data" ] || [ "$method" = "DELETE" ]; then
_debug "data ($method): " "$content_data"
response="$(_post "$content_data" "$Alviy_Api/$path" "" "$method")"
else
response="$(_get "$Alviy_Api/$path")"
fi
_code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")"
if [ "$_code" = "401" ]; then
_err "It seems that your api key or secret is not correct."
return 1
fi
if [ "$_code" != "200" ]; then
_err "API call error ($method): $path Response code $_code"
fi
if [ "$?" != "0" ]; then
_err "error on rest call ($method): $path. Response:"
_err "$response"
return 1
fi
_debug2 response "$response"
return 0
}

View File

@ -1,9 +1,12 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
# Anexia CloudDNS acme.sh hook dns_anx_info='Anexia.com CloudDNS
# Author: MA Site: Anexia.com
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_anx
#ANX_Token="xxxx" Options:
ANX_Token API Token
Issues: github.com/acmesh-official/acme.sh/issues/3238
'
ANX_API='https://engine.anexia-it.com/api/clouddns/v1' ANX_API='https://engine.anexia-it.com/api/clouddns/v1'
@ -127,18 +130,17 @@ _get_root() {
i=1 i=1
p=1 p=1
_anx_rest GET "zone.json"
while true; do 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 h "$h"
if [ -z "$h" ]; then if [ -z "$h" ]; then
#not valid #not valid
return 1 return 1
fi fi
_anx_rest GET "zone.json/${h}"
if _contains "$response" "\"name\":\"$h\""; then 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 _domain=$h
return 0 return 0
fi fi

View File

@ -1,17 +1,14 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
################################################################################ dns_artfiles_info='ArtFiles.de
# ACME.sh 3rd party DNS API plugin for ArtFiles.de Site: ArtFiles.de
################################################################################ Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_artfiles
# Author: Martin Arndt, https://troublezone.net/ Options:
# Released: 2022-02-27 AF_API_USERNAME API Username
# Issues: https://github.com/acmesh-official/acme.sh/issues/4718 AF_API_PASSWORD API Password
################################################################################ Issues: github.com/acmesh-official/acme.sh/issues/4718
# Usage: Author: Martin Arndt <https://troublezone.net/>
# 1. export AF_API_USERNAME='api12345678' '
# 2. export AF_API_PASSWORD='apiPassword'
# 3. acme.sh --issue -d example.com --dns dns_artfiles
################################################################################
########## API configuration ################################################### ########## API configuration ###################################################

View File

@ -1,11 +1,16 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
# Arvan_Token="Apikey xxxx" dns_arvan_info='ArvanCloud.ir
Site: ArvanCloud.ir
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_arvan
Options:
Arvan_Token API Token
Issues: github.com/acmesh-official/acme.sh/issues/2796
Author: Vahid Fardi
'
ARVAN_API_URL="https://napi.arvancloud.ir/cdn/4.0/domains" ARVAN_API_URL="https://napi.arvancloud.ir/cdn/4.0/domains"
# Author: Vahid Fardi
# Report Bugs here: https://github.com/Neilpang/acme.sh
#
######## Public functions ##################### ######## Public functions #####################
#Usage: dns_arvan_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" #Usage: dns_arvan_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
@ -102,7 +107,7 @@ _get_root() {
i=2 i=2
p=1 p=1
while true; do 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 h "$h"
if [ -z "$h" ]; then if [ -z "$h" ]; then
#not valid #not valid
@ -115,7 +120,7 @@ _get_root() {
if _contains "$response" "\"domain\":\"$h\""; then if _contains "$response" "\"domain\":\"$h\""; then
_domain_id=$(echo "$response" | cut -d : -f 3 | cut -d , -f 1 | tr -d \") _domain_id=$(echo "$response" | cut -d : -f 3 | cut -d , -f 1 | tr -d \")
if [ "$_domain_id" ]; then 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 _domain=$h
return 0 return 0
fi fi

View File

@ -1,9 +1,15 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
# dns_aurora_info='versio.nl AuroraDNS
#AURORA_Key="sdfsdfsdfljlbjkljlkjsdfoiwje" Domains: pcextreme.nl
# Site: versio.nl
#AURORA_Secret="sdfsdfsdfljlbjkljlkjsdfoiwje" Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_aurora
Options:
AURORA_Key API Key
AURORA_Secret API Secret
Issues: github.com/acmesh-official/acme.sh/issues/3459
Author: Jasper Zonneveld
'
AURORA_Api="https://api.auroradns.eu" AURORA_Api="https://api.auroradns.eu"
@ -111,7 +117,7 @@ _get_root() {
p=1 p=1
while true; do 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 h "$h"
if [ -z "$h" ]; then if [ -z "$h" ]; then
#not valid #not valid
@ -126,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 " ") _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" _debug _domain_id "$_domain_id"
if [ "$_domain_id" ]; then 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 _domain=$h
return 0 return 0
fi fi

View File

@ -1,16 +1,15 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# -*- mode: sh; tab-width: 2; indent-tabs-mode: s; coding: utf-8 -*- # shellcheck disable=SC2034
dns_autodns_info='InternetX autoDNS
# This is the InternetX autoDNS xml api wrapper for acme.sh InternetX autoDNS XML API
# Author: auerswald@gmail.com Site: InternetX.com/autodns/
# Created: 2018-01-14 Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_autodns
# Options:
# export AUTODNS_USER="username" AUTODNS_USER Username
# export AUTODNS_PASSWORD="password" AUTODNS_PASSWORD Password
# export AUTODNS_CONTEXT="context" AUTODNS_CONTEXT Context
# Author: <auerswald@gmail.com>
# Usage: '
# acme.sh --issue --dns dns_autodns -d example.com
AUTODNS_API="https://gateway.autodns.com" AUTODNS_API="https://gateway.autodns.com"
@ -111,7 +110,7 @@ _get_autodns_zone() {
p=1 p=1
while true; do 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 h "$h"
if [ -z "$h" ]; then if [ -z "$h" ]; then
@ -129,7 +128,7 @@ _get_autodns_zone() {
if _contains "$autodns_response" "<summary>1</summary>" >/dev/null; then 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)" _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)" _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 return 0
fi fi

View File

@ -1,13 +1,15 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
dns_aws_info='Amazon AWS Route53 domain API
Site: docs.aws.amazon.com/route53/
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_aws
Options:
AWS_ACCESS_KEY_ID API Key ID
AWS_SECRET_ACCESS_KEY API Secret
'
# # All `_sleep` commands are included to avoid Route53 throttling, see
#AWS_ACCESS_KEY_ID="sdfsdfsdfljlbjkljlkjsdfoiwje" # https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/DNSLimitations.html#limits-api-requests
#
#AWS_SECRET_ACCESS_KEY="xxxxxxx"
#This is the Amazon Route53 api wrapper for acme.sh
#All `_sleep` commands are included to avoid Route53 throttling, see
#https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/DNSLimitations.html#limits-api-requests
AWS_HOST="route53.amazonaws.com" AWS_HOST="route53.amazonaws.com"
AWS_URL="https://$AWS_HOST" AWS_URL="https://$AWS_HOST"
@ -145,7 +147,6 @@ dns_aws_rm() {
fi fi
_sleep 1 _sleep 1
return 1 return 1
} }
#################### Private functions below ################################## #################### Private functions below ##################################
@ -157,7 +158,7 @@ _get_root() {
# iterate over names (a.b.c.d -> b.c.d -> c.d -> d) # iterate over names (a.b.c.d -> b.c.d -> c.d -> d)
while true; do while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100) h=$(printf "%s" "$domain" | cut -d . -f "$i"-100 | sed 's/\./\\./g')
_debug "Checking domain: $h" _debug "Checking domain: $h"
if [ -z "$h" ]; then if [ -z "$h" ]; then
_error "invalid domain" _error "invalid domain"
@ -173,7 +174,7 @@ _get_root() {
if [ "$hostedzone" ]; then if [ "$hostedzone" ]; then
_domain_id=$(printf "%s\n" "$hostedzone" | _egrep_o "<Id>.*<.Id>" | head -n 1 | _egrep_o ">.*<" | tr -d "<>") _domain_id=$(printf "%s\n" "$hostedzone" | _egrep_o "<Id>.*<.Id>" | head -n 1 | _egrep_o ">.*<" | tr -d "<>")
if [ "$_domain_id" ]; then 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 _domain=$h
return 0 return 0
fi fi
@ -207,24 +208,40 @@ _use_container_role() {
} }
_use_instance_role() { _use_instance_role() {
_url="http://169.254.169.254/latest/meta-data/iam/security-credentials/" _instance_role_name_url="http://169.254.169.254/latest/meta-data/iam/security-credentials/"
_debug "_url" "$_url"
if ! _get "$_url" true 1 | _head_n 1 | grep -Fq 200; then if _get "$_instance_role_name_url" true 1 | _head_n 1 | grep -Fq 401; then
_debug "Using IMDSv2"
_token_url="http://169.254.169.254/latest/api/token"
export _H1="X-aws-ec2-metadata-token-ttl-seconds: 21600"
_token="$(_post "" "$_token_url" "" "PUT")"
_secure_debug3 "_token" "$_token"
if [ -z "$_token" ]; then
_debug "Unable to fetch IMDSv2 token from instance metadata"
return 1
fi
export _H1="X-aws-ec2-metadata-token: $_token"
fi
if ! _get "$_instance_role_name_url" true 1 | _head_n 1 | grep -Fq 200; then
_debug "Unable to fetch IAM role from instance metadata" _debug "Unable to fetch IAM role from instance metadata"
return 1 return 1
fi fi
_aws_role=$(_get "$_url" "" 1)
_debug "_aws_role" "$_aws_role" _instance_role_name=$(_get "$_instance_role_name_url" "" 1)
_use_metadata "$_url$_aws_role" _debug "_instance_role_name" "$_instance_role_name"
_use_metadata "$_instance_role_name_url$_instance_role_name" "$_token"
} }
_use_metadata() { _use_metadata() {
export _H1="X-aws-ec2-metadata-token: $2"
_aws_creds="$( _aws_creds="$(
_get "$1" "" 1 | _get "$1" "" 1 |
_normalizeJson | _normalizeJson |
tr '{,}' '\n' | tr '{,}' '\n' |
while read -r _line; do while read -r _line; do
_key="$(echo "${_line%%:*}" | tr -d '"')" _key="$(echo "${_line%%:*}" | tr -d '\"')"
_value="${_line#*:}" _value="${_line#*:}"
_debug3 "_key" "$_key" _debug3 "_key" "$_key"
_secure_debug3 "_value" "$_value" _secure_debug3 "_value" "$_value"

View File

@ -1,9 +1,13 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
# dns_azion_info='Azion.om
#AZION_Email="" Site: Azion.com
#AZION_Password="" Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_azion
# Options:
AZION_Email Email
AZION_Password Password
Issues: github.com/acmesh-official/acme.sh/issues/3555
'
AZION_Api="https://api.azionapi.net" AZION_Api="https://api.azionapi.net"
@ -96,7 +100,7 @@ _get_root() {
fi fi
while true; do 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 h "$h"
if [ -z "$h" ]; then if [ -z "$h" ]; then
# not valid # not valid
@ -107,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 \") _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" _debug _domain_id "$_domain_id"
if [ "$_domain_id" ]; then 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 _domain=$h
return 0 return 0
fi fi

View File

@ -1,13 +1,25 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
dns_azure_info='Azure
Site: Azure.microsoft.com
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_azure
Options:
AZUREDNS_SUBSCRIPTIONID Subscription ID
AZUREDNS_TENANTID Tenant ID
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 Optional Bearer Token. Used instead of service principal credentials or managed identity
'
WIKI="https://github.com/acmesh-official/acme.sh/wiki/How-to-use-Azure-DNS" wiki=https://github.com/acmesh-official/acme.sh/wiki/How-to-use-Azure-DNS
######## Public functions ##################### ######## Public functions #####################
# Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" # Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
# Used to add txt record # 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() { dns_azure_add() {
@ -20,6 +32,7 @@ dns_azure_add() {
AZUREDNS_TENANTID="" AZUREDNS_TENANTID=""
AZUREDNS_APPID="" AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET="" AZUREDNS_CLIENTSECRET=""
AZUREDNS_BEARERTOKEN=""
_err "You didn't specify the Azure Subscription ID" _err "You didn't specify the Azure Subscription ID"
return 1 return 1
fi fi
@ -34,37 +47,45 @@ dns_azure_add() {
_saveaccountconf_mutable AZUREDNS_TENANTID "" _saveaccountconf_mutable AZUREDNS_TENANTID ""
_saveaccountconf_mutable AZUREDNS_APPID "" _saveaccountconf_mutable AZUREDNS_APPID ""
_saveaccountconf_mutable AZUREDNS_CLIENTSECRET "" _saveaccountconf_mutable AZUREDNS_CLIENTSECRET ""
_saveaccountconf_mutable AZUREDNS_BEARERTOKEN ""
else 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_TENANTID="${AZUREDNS_TENANTID:-$(_readaccountconf_mutable AZUREDNS_TENANTID)}"
AZUREDNS_APPID="${AZUREDNS_APPID:-$(_readaccountconf_mutable AZUREDNS_APPID)}" AZUREDNS_APPID="${AZUREDNS_APPID:-$(_readaccountconf_mutable AZUREDNS_APPID)}"
AZUREDNS_CLIENTSECRET="${AZUREDNS_CLIENTSECRET:-$(_readaccountconf_mutable AZUREDNS_CLIENTSECRET)}" 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 if [ -z "$AZUREDNS_APPID" ]; then
AZUREDNS_SUBSCRIPTIONID="" AZUREDNS_SUBSCRIPTIONID=""
AZUREDNS_TENANTID="" AZUREDNS_TENANTID=""
AZUREDNS_APPID="" AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET="" AZUREDNS_CLIENTSECRET=""
_err "You didn't specify the Azure Tenant ID " AZUREDNS_BEARERTOKEN=""
return 1 _err "You didn't specify the Azure App ID"
fi return 1
fi
if [ -z "$AZUREDNS_APPID" ]; then if [ -z "$AZUREDNS_CLIENTSECRET" ]; then
AZUREDNS_SUBSCRIPTIONID="" AZUREDNS_SUBSCRIPTIONID=""
AZUREDNS_TENANTID="" AZUREDNS_TENANTID=""
AZUREDNS_APPID="" AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET="" AZUREDNS_CLIENTSECRET=""
_err "You didn't specify the Azure App ID" AZUREDNS_BEARERTOKEN=""
return 1 _err "You didn't specify the Azure Client Secret"
fi return 1
fi
if [ -z "$AZUREDNS_CLIENTSECRET" ]; then else
AZUREDNS_SUBSCRIPTIONID="" _info "Using provided bearer token"
AZUREDNS_TENANTID=""
AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET=""
_err "You didn't specify the Azure Client Secret"
return 1
fi fi
#save account details to account conf file, don't opt in for azure manages identity check. #save account details to account conf file, don't opt in for azure manages identity check.
@ -72,9 +93,14 @@ dns_azure_add() {
_saveaccountconf_mutable AZUREDNS_TENANTID "$AZUREDNS_TENANTID" _saveaccountconf_mutable AZUREDNS_TENANTID "$AZUREDNS_TENANTID"
_saveaccountconf_mutable AZUREDNS_APPID "$AZUREDNS_APPID" _saveaccountconf_mutable AZUREDNS_APPID "$AZUREDNS_APPID"
_saveaccountconf_mutable AZUREDNS_CLIENTSECRET "$AZUREDNS_CLIENTSECRET" _saveaccountconf_mutable AZUREDNS_CLIENTSECRET "$AZUREDNS_CLIENTSECRET"
_saveaccountconf_mutable AZUREDNS_BEARERTOKEN "$AZUREDNS_BEARERTOKEN"
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 if ! _get_root "$fulldomain" "$AZUREDNS_SUBSCRIPTIONID" "$accesstoken"; then
_err "invalid domain" _err "invalid domain"
@ -124,7 +150,7 @@ dns_azure_add() {
# Usage: fulldomain txtvalue # Usage: fulldomain txtvalue
# Used to remove the txt record after validation # 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() { dns_azure_rm() {
fulldomain=$1 fulldomain=$1
@ -136,6 +162,7 @@ dns_azure_rm() {
AZUREDNS_TENANTID="" AZUREDNS_TENANTID=""
AZUREDNS_APPID="" AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET="" AZUREDNS_CLIENTSECRET=""
AZUREDNS_BEARERTOKEN=""
_err "You didn't specify the Azure Subscription ID " _err "You didn't specify the Azure Subscription ID "
return 1 return 1
fi fi
@ -144,40 +171,51 @@ dns_azure_rm() {
if [ "$AZUREDNS_MANAGEDIDENTITY" = true ]; then if [ "$AZUREDNS_MANAGEDIDENTITY" = true ]; then
_info "Using Azure managed identity" _info "Using Azure managed identity"
else 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_TENANTID="${AZUREDNS_TENANTID:-$(_readaccountconf_mutable AZUREDNS_TENANTID)}"
AZUREDNS_APPID="${AZUREDNS_APPID:-$(_readaccountconf_mutable AZUREDNS_APPID)}" AZUREDNS_APPID="${AZUREDNS_APPID:-$(_readaccountconf_mutable AZUREDNS_APPID)}"
AZUREDNS_CLIENTSECRET="${AZUREDNS_CLIENTSECRET:-$(_readaccountconf_mutable AZUREDNS_CLIENTSECRET)}" 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 if [ -z "$AZUREDNS_APPID" ]; then
AZUREDNS_SUBSCRIPTIONID="" AZUREDNS_SUBSCRIPTIONID=""
AZUREDNS_TENANTID="" AZUREDNS_TENANTID=""
AZUREDNS_APPID="" AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET="" AZUREDNS_CLIENTSECRET=""
_err "You didn't specify the Azure Tenant ID " AZUREDNS_BEARERTOKEN=""
return 1 _err "You didn't specify the Azure App ID"
fi return 1
fi
if [ -z "$AZUREDNS_APPID" ]; then if [ -z "$AZUREDNS_CLIENTSECRET" ]; then
AZUREDNS_SUBSCRIPTIONID="" AZUREDNS_SUBSCRIPTIONID=""
AZUREDNS_TENANTID="" AZUREDNS_TENANTID=""
AZUREDNS_APPID="" AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET="" AZUREDNS_CLIENTSECRET=""
_err "You didn't specify the Azure App ID" AZUREDNS_BEARERTOKEN=""
return 1 _err "You didn't specify the Azure Client Secret"
fi return 1
fi
if [ -z "$AZUREDNS_CLIENTSECRET" ]; then else
AZUREDNS_SUBSCRIPTIONID="" _info "Using provided bearer token"
AZUREDNS_TENANTID=""
AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET=""
_err "You didn't specify the Azure Client Secret"
return 1
fi fi
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 if ! _get_root "$fulldomain" "$AZUREDNS_SUBSCRIPTIONID" "$accesstoken"; then
_err "invalid domain" _err "invalid domain"
@ -256,10 +294,10 @@ _azure_rest() {
if [ "$_code" = "401" ]; then if [ "$_code" = "401" ]; then
# we have an invalid access token set to expired # we have an invalid access token set to expired
_saveaccountconf_mutable AZUREDNS_TOKENVALIDTO "0" _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 return 1
fi 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 if [ "$_ret" != "0" ] || [ -z "$_code" ] || [ "$_code" = "408" ] || [ "$_code" = "500" ] || [ "$_code" = "503" ] || [ "$_code" = "504" ]; then
_request_retry_times="$(_math "$_request_retry_times" + 1)" _request_retry_times="$(_math "$_request_retry_times" + 1)"
_info "REST call error $_code retrying $ep in $_request_retry_times s" _info "REST call error $_code retrying $ep in $_request_retry_times s"
@ -277,14 +315,14 @@ _azure_rest() {
return 0 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() { _azure_getaccess_token() {
managedIdentity=$1 managedIdentity=$1
tenantID=$2 tenantID=$2
clientID=$3 clientID=$3
clientSecret=$4 clientSecret=$4
accesstoken="${AZUREDNS_BEARERTOKEN:-$(_readaccountconf_mutable AZUREDNS_BEARERTOKEN)}" accesstoken="${AZUREDNS_ACCESSTOKEN:-$(_readaccountconf_mutable AZUREDNS_ACCESSTOKEN)}"
expires_on="${AZUREDNS_TOKENVALIDTO:-$(_readaccountconf_mutable AZUREDNS_TOKENVALIDTO)}" expires_on="${AZUREDNS_TOKENVALIDTO:-$(_readaccountconf_mutable AZUREDNS_TOKENVALIDTO)}"
# can we reuse the bearer token? # can we reuse the bearer token?
@ -301,7 +339,7 @@ _azure_getaccess_token() {
_debug "getting new bearer token" _debug "getting new bearer token"
if [ "$managedIdentity" = true ]; then 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" 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="$(_get http://169.254.169.254/metadata/identity/oauth2/token\?api-version=2018-02-01\&resource=https://management.azure.com/)"
response="$(echo "$response" | _normalizeJson)" response="$(echo "$response" | _normalizeJson)"
@ -321,14 +359,14 @@ _azure_getaccess_token() {
fi fi
if [ -z "$accesstoken" ]; then 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 return 1
fi fi
if [ "$_ret" != "0" ]; then if [ "$_ret" != "0" ]; then
_err "error $response" _err "error $response"
return 1 return 1
fi fi
_saveaccountconf_mutable AZUREDNS_BEARERTOKEN "$accesstoken" _saveaccountconf_mutable AZUREDNS_ACCESSTOKEN "$accesstoken"
_saveaccountconf_mutable AZUREDNS_TOKENVALIDTO "$expires_on" _saveaccountconf_mutable AZUREDNS_TOKENVALIDTO "$expires_on"
printf "%s" "$accesstoken" printf "%s" "$accesstoken"
return 0 return 0
@ -341,15 +379,18 @@ _get_root() {
i=1 i=1
p=1 p=1
## Ref: https://docs.microsoft.com/en-us/rest/api/dns/zones/list ## 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 therefore handling more results is not not implemented ## returns up to 100 zones in one response. Handling more results is not implemented
## (ZoneListResult with continuation token for the next page of results) ## (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 ##
## 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" _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 # Find matching domain name in Json response
while true; do 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" _debug2 "Checking domain: $h"
if [ -z "$h" ]; then if [ -z "$h" ]; then
#not valid #not valid
@ -364,7 +405,7 @@ _get_root() {
#create the record at the domain apex (@) if only the domain name was provided as --domain-alias #create the record at the domain apex (@) if only the domain name was provided as --domain-alias
_sub_domain="@" _sub_domain="@"
else else
_sub_domain=$(echo "$domain" | cut -d . -f 1-$p) _sub_domain=$(echo "$domain" | cut -d . -f 1-"$p")
fi fi
_domain=$h _domain=$h
return 0 return 0

View File

@ -1,18 +1,17 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
dns_bookmyname_info='BookMyName.com
Site: BookMyName.com
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_bookmyname
Options:
BOOKMYNAME_USERNAME Username
BOOKMYNAME_PASSWORD Password
Issues: github.com/acmesh-official/acme.sh/issues/3209
Author: Neilpang
'
#Here is a sample custom api script.
#This file name is "dns_bookmyname.sh"
#So, here must be a method dns_bookmyname_add()
#Which will be called by acme.sh to add the txt record to your api system.
#returns 0 means success, otherwise error.
#
#Author: Neilpang
#Report Bugs here: https://github.com/acmesh-official/acme.sh
#
######## Public functions ##################### ######## Public functions #####################
# Please Read this guide first: https://github.com/acmesh-official/acme.sh/wiki/DNS-API-Dev-Guide
# BookMyName urls: # BookMyName urls:
# https://BOOKMYNAME_USERNAME:BOOKMYNAME_PASSWORD@www.bookmyname.com/dyndns/?hostname=_acme-challenge.domain.tld&type=txt&ttl=300&do=add&value="XXXXXXXX"' # https://BOOKMYNAME_USERNAME:BOOKMYNAME_PASSWORD@www.bookmyname.com/dyndns/?hostname=_acme-challenge.domain.tld&type=txt&ttl=300&do=add&value="XXXXXXXX"'
# https://BOOKMYNAME_USERNAME:BOOKMYNAME_PASSWORD@www.bookmyname.com/dyndns/?hostname=_acme-challenge.domain.tld&type=txt&ttl=300&do=remove&value="XXXXXXXX"' # https://BOOKMYNAME_USERNAME:BOOKMYNAME_PASSWORD@www.bookmyname.com/dyndns/?hostname=_acme-challenge.domain.tld&type=txt&ttl=300&do=remove&value="XXXXXXXX"'

View File

@ -1,16 +1,13 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
## Will be called by acme.sh to add the TXT record via the Bunny DNS API. dns_bunny_info='Bunny.net
## returns 0 means success, otherwise error. Site: Bunny.net/dns/
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_bunny
## Author: nosilver4u <nosilver4u at ewww.io> Options:
## GitHub: https://github.com/nosilver4u/acme.sh BUNNY_API_KEY API Key
Issues: github.com/acmesh-official/acme.sh/issues/4296
## Author: <nosilver4u@ewww.io>
## Environment Variables Required: '
##
## BUNNY_API_KEY="75310dc4-ca77-9ac3-9a19-f6355db573b49ce92ae1-2655-3ebd-61ac-3a3ae34834cc"
##
##################### Public functions ##################### ##################### Public functions #####################
@ -199,7 +196,7 @@ _get_base_domain() {
_debug2 domain_list "$domain_list" _debug2 domain_list "$domain_list"
i=1 i=1
while [ $i -gt 0 ]; do while [ "$i" -gt 0 ]; do
## get next longest domain ## get next longest domain
_domain=$(printf "%s" "$fulldomain" | cut -d . -f "$i"-"$MAX_DOM") _domain=$(printf "%s" "$fulldomain" | cut -d . -f "$i"-"$MAX_DOM")
## check we got something back from our cut (or are we at the end) ## check we got something back from our cut (or are we at the end)
@ -211,7 +208,7 @@ _get_base_domain() {
## check if it exists ## check if it exists
if [ -n "$found" ]; then if [ -n "$found" ]; then
## exists - exit loop returning the parts ## 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") _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]+")" _domain_id="$(echo "$found" | _egrep_o "Id\"\s*\:\s*\"*[0-9]+" | _egrep_o "[0-9]+")"
_debug _domain_id "$_domain_id" _debug _domain_id "$_domain_id"
@ -221,11 +218,11 @@ _get_base_domain() {
return 0 return 0
fi fi
## increment cut point $i ## increment cut point $i
i=$(_math $i + 1) i=$(_math "$i" + 1)
done done
if [ -z "$found" ]; then if [ -z "$found" ]; then
page=$(_math $page + 1) page=$(_math "$page" + 1)
nextpage="https://api.bunny.net/dnszone?page=$page" nextpage="https://api.bunny.net/dnszone?page=$page"
## Find the next page if we don't have a match. ## Find the next page if we don't have a match.
hasnextpage="$(echo "$domain_list" | _egrep_o "\"HasMoreItems\"\s*:\s*true")" hasnextpage="$(echo "$domain_list" | _egrep_o "\"HasMoreItems\"\s*:\s*true")"

View File

@ -1,13 +1,16 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
# dns_cf_info='CloudFlare
#CF_Key="sdfsdfsdfljlbjkljlkjsdfoiwje" Site: CloudFlare.com
# Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_cf
#CF_Email="xxxx@sss.com" Options:
CF_Key API Key
#CF_Token="xxxx" CF_Email Your account email
#CF_Account_ID="xxxx" OptionsAlt:
#CF_Zone_ID="xxxx" CF_Token API Token
CF_Account_ID Account ID
CF_Zone_ID Zone ID. Optional.
'
CF_Api="https://api.cloudflare.com/client/v4" CF_Api="https://api.cloudflare.com/client/v4"
@ -183,7 +186,7 @@ _get_root() {
fi fi
while true; do 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 h "$h"
if [ -z "$h" ]; then if [ -z "$h" ]; then
#not valid #not valid
@ -203,7 +206,7 @@ _get_root() {
if _contains "$response" "\"name\":\"$h\"" || _contains "$response" '"total_count":1'; then 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 " ") _domain_id=$(echo "$response" | _egrep_o "\[.\"id\": *\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \" | tr -d " ")
if [ "$_domain_id" ]; then 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 _domain=$h
return 0 return 0
fi fi

View File

@ -1,10 +1,15 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
# Author: Radek Sprta <sprta@vshosting.cz> dns_clouddns_info='vshosting.cz CloudDNS
Site: github.com/vshosting/clouddns
#CLOUDDNS_EMAIL=XXXXX Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_clouddns
#CLOUDDNS_PASSWORD="YYYYYYYYY" Options:
#CLOUDDNS_CLIENT_ID=XXXXX CLOUDDNS_EMAIL Email
CLOUDDNS_PASSWORD Password
CLOUDDNS_CLIENT_ID Client ID
Issues: github.com/acmesh-official/acme.sh/issues/2699
Author: Radek Sprta <sprta@vshosting.cz>
'
CLOUDDNS_API='https://admin.vshosting.cloud/clouddns' CLOUDDNS_API='https://admin.vshosting.cloud/clouddns'
CLOUDDNS_LOGIN_API='https://admin.vshosting.cloud/api/public/auth/login' CLOUDDNS_LOGIN_API='https://admin.vshosting.cloud/api/public/auth/login'

View File

@ -1,12 +1,15 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
dns_cloudns_info='ClouDNS.net
Site: ClouDNS.net
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_cloudns
Options:
CLOUDNS_AUTH_ID Regular auth ID
CLOUDNS_SUB_AUTH_ID Sub auth ID
CLOUDNS_AUTH_PASSWORD Auth Password
Author: Boyan Peychev <boyan@cloudns.net>
'
# Author: Boyan Peychev <boyan at cloudns dot net>
# Repository: https://github.com/ClouDNS/acme.sh/
# Editor: I Komang Suryadana
#CLOUDNS_AUTH_ID=XXXXX
#CLOUDNS_SUB_AUTH_ID=XXXXX
#CLOUDNS_AUTH_PASSWORD="YYYYYYYYY"
CLOUDNS_API="https://api.cloudns.net" CLOUDNS_API="https://api.cloudns.net"
DOMAIN_TYPE= DOMAIN_TYPE=
DOMAIN_MASTER= DOMAIN_MASTER=
@ -161,7 +164,7 @@ _dns_cloudns_get_zone_info() {
_dns_cloudns_get_zone_name() { _dns_cloudns_get_zone_name() {
i=2 i=2
while true; do 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 if [ -z "$zoneForCheck" ]; then
return 1 return 1

View File

@ -1,7 +1,14 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
# DNS API for acme.sh for Core-Networks (https://beta.api.core-networks.de/doc/). dns_cn_info='Core-Networks.de
# created by 5ll and francis Site: beta.api.Core-Networks.de/doc/
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_cn
Options:
CN_User User
CN_Password Password
Issues: github.com/acmesh-official/acme.sh/issues/2142
Author: 5ll, francis
'
CN_API="https://beta.api.core-networks.de" CN_API="https://beta.api.core-networks.de"
@ -124,7 +131,7 @@ _cn_get_root() {
p=1 p=1
while true; do 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 h "$h"
_debug _H1 "${_H1}" _debug _H1 "${_H1}"
@ -142,7 +149,7 @@ _cn_get_root() {
fi fi
if _contains "$_cn_zonelist" "\"name\":\"$h\"" >/dev/null; then 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 _domain=$h
return 0 return 0
else else

View File

@ -1,4 +1,15 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
dns_conoha_info='ConoHa.jp
Domains: ConoHa.io
Site: ConoHa.jp
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_conoha
Options:
CONOHA_Username Username
CONOHA_Password Password
CONOHA_TenantId TenantId
CONOHA_IdentityServiceApi Identity Service API. E.g. "https://identity.xxxx.conoha.io/v2.0"
'
CONOHA_DNS_EP_PREFIX_REGEXP="https://dns-service\." CONOHA_DNS_EP_PREFIX_REGEXP="https://dns-service\."
@ -226,7 +237,7 @@ _get_root() {
i=2 i=2
p=1 p=1
while true; do 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 h "$h"
if [ -z "$h" ]; then if [ -z "$h" ]; then
#not valid #not valid
@ -240,7 +251,7 @@ _get_root() {
if _contains "$response" "\"name\":\"$h\"" >/dev/null; then 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 \") _domain_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":\"[^\"]*\"" | head -n 1 | cut -d : -f 2 | tr -d \")
if [ "$_domain_id" ]; then 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 _domain=$h
return 0 return 0
fi fi

View File

@ -1,10 +1,16 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
# Author: Wout Decre <wout@canodus.be> dns_constellix_info='Constellix.com
Site: Constellix.com
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_constellix
Options:
CONSTELLIX_Key API Key
CONSTELLIX_Secret API Secret
Issues: github.com/acmesh-official/acme.sh/issues/2724
Author: Wout Decre <wout@canodus.be>
'
CONSTELLIX_Api="https://api.dns.constellix.com/v1" CONSTELLIX_Api="https://api.dns.constellix.com/v1"
#CONSTELLIX_Key="XXX"
#CONSTELLIX_Secret="XXX"
######## Public functions ##################### ######## Public functions #####################
@ -116,7 +122,7 @@ _get_root() {
p=1 p=1
_debug "Detecting root zone" _debug "Detecting root zone"
while true; do 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 if [ -z "$h" ]; then
return 1 return 1
fi fi
@ -128,7 +134,7 @@ _get_root() {
if _contains "$response" "\"name\":\"$h\""; then if _contains "$response" "\"name\":\"$h\""; then
_domain_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[0-9]*" | cut -d ':' -f 2) _domain_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[0-9]*" | cut -d ':' -f 2)
if [ "$_domain_id" ]; then 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" _domain="$h"
_debug _domain_id "$_domain_id" _debug _domain_id "$_domain_id"

View File

@ -1,18 +1,18 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# # shellcheck disable=SC2034
#Author: Bjarne Saltbaek dns_cpanel_info='cPanel Server API
#Report Bugs here: https://github.com/acmesh-official/acme.sh/issues/3732 Manage DNS via cPanel Dashboard.
# Site: cPanel.net
# Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_cpanel
Options:
cPanel_Username Username
cPanel_Apitoken API Token
cPanel_Hostname Server URL. E.g. "https://hostname:port"
Issues: github.com/acmesh-official/acme.sh/issues/3732
Author: Bjarne Saltbaek
'
######## Public functions ##################### ######## Public functions #####################
#
# Export CPANEL username,api token and hostname in the following variables
#
# cPanel_Username=username
# cPanel_Apitoken=apitoken
# cPanel_Hostname=hostname
#
# Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
# Used to add txt record # Used to add txt record
dns_cpanel_add() { dns_cpanel_add() {

View File

@ -1,9 +1,15 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
#Script to use with curanet.dk, scannet.dk, wannafind.dk, dandomain.dk DNS management. dns_curanet_info='Curanet.dk
#Requires api credentials with scope: dns Domains: scannet.dk wannafind.dk dandomain.dk
#Author: Peter L. Hansen <peter@r12.dk> Site: Curanet.dk
#Version 1.0 Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_curanet
Options:
CURANET_AUTHCLIENTID Auth ClientID. Requires scope dns
CURANET_AUTHSECRET Auth Secret
Issues: github.com/acmesh-official/acme.sh/issues/3933
Author: Peter L. Hansen <peter@r12.dk>
'
CURANET_REST_URL="https://api.curanet.dk/dns/v1/Domains" CURANET_REST_URL="https://api.curanet.dk/dns/v1/Domains"
CURANET_AUTH_URL="https://apiauth.dk.team.blue/auth/realms/Curanet/protocol/openid-connect/token" CURANET_AUTH_URL="https://apiauth.dk.team.blue/auth/realms/Curanet/protocol/openid-connect/token"
@ -136,7 +142,7 @@ _get_root() {
i=1 i=1
while true; do 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 h "$h"
if [ -z "$h" ]; then if [ -z "$h" ]; then
#not valid #not valid

View File

@ -1,21 +1,15 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
######## dns_cyon_info='cyon.ch
# Custom cyon.ch DNS API for use with [acme.sh](https://github.com/acmesh-official/acme.sh) Site: cyon.ch
# Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_cyon
# Usage: acme.sh --issue --dns dns_cyon -d www.domain.com Options:
# CY_Username Username
# Dependencies: CY_Password API Token
# ------------- CY_OTP_Secret OTP token. Only required if using 2FA
# - oathtool (When using 2 Factor Authentication) Issues: github.com/noplanman/cyon-api/issues
# Author: Armando Lüscher <armando@noplanman.ch>
# Issues: '
# -------
# Any issues / questions / suggestions can be posted here:
# https://github.com/noplanman/cyon-api/issues
#
# Author: Armando Lüscher <armando@noplanman.ch>
########
dns_cyon_add() { dns_cyon_add() {
_cyon_load_credentials && _cyon_load_credentials &&

View File

@ -1,31 +1,14 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# -*- mode: sh; tab-width: 2; indent-tabs-mode: s; coding: utf-8 -*- # shellcheck disable=SC2034
# vim: et ts=2 sw=2 dns_da_info='DirectAdmin Server API
# Site: DirectAdmin.com/api.php
# DirectAdmin 1.41.0 API Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_da
# The DirectAdmin interface has it's own Let's encrypt functionality, but this Options:
# script can be used to generate certificates for names which are not hosted on DA_Api API Server URL. E.g. "https://remoteUser:remotePassword@da.domain.tld:8443"
# DirectAdmin DA_Api_Insecure Insecure TLS. 0: check for cert validity, 1: always accept
# Issues: github.com/TigerP/acme.sh/issues
# User must provide login data and URL to DirectAdmin incl. port. '
# You can create login key, by using the Login Keys function
# ( https://da.example.com:8443/CMD_LOGIN_KEYS ), which only has access to
# - CMD_API_DNS_CONTROL
# - CMD_API_SHOW_DOMAINS
#
# See also https://www.directadmin.com/api.php and
# https://www.directadmin.com/features.php?id=1298
#
# Report bugs to https://github.com/TigerP/acme.sh/issues
#
# Values to export:
# export DA_Api="https://remoteUser:remotePassword@da.example.com:8443"
# export DA_Api_Insecure=1
#
# Set DA_Api_Insecure to 1 for insecure and 0 for secure -> difference is
# whether ssl cert is checked for validity (0) or whether it is just accepted
# (1)
#
######## Public functions ##################### ######## Public functions #####################
# Usage: dns_myapi_add _acme-challenge.www.example.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" # Usage: dns_myapi_add _acme-challenge.www.example.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
@ -78,7 +61,7 @@ _get_root() {
# response will contain "list[]=example.com&list[]=example.org" # response will contain "list[]=example.com&list[]=example.org"
_da_api CMD_API_SHOW_DOMAINS "" "${domain}" _da_api CMD_API_SHOW_DOMAINS "" "${domain}"
while true; do 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 h "$h"
if [ -z "$h" ]; then if [ -z "$h" ]; then
# not valid # not valid
@ -86,7 +69,7 @@ _get_root() {
return 1 return 1
fi fi
if _contains "$response" "$h" >/dev/null; then 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 _domain=$h
return 0 return 0
fi fi

View File

@ -1,16 +1,13 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
#Created by RaidenII, to use DuckDNS's API to add/remove text records dns_ddnss_info='DDNSS.de
#modified by helbgd @ 03/13/2018 to support ddnss.de Site: DDNSS.de
#modified by mod242 @ 04/24/2018 to support different ddnss domains Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_ddnss
#Please note: the Wildcard Feature must be turned on for the Host record Options:
#and the checkbox for TXT needs to be enabled DDNSS_Token API Token
Issues: github.com/acmesh-official/acme.sh/issues/2230
# Pass credentials before "acme.sh --issue --dns dns_ddnss ..." Author: RaidenII, helbgd, mod242
# -- '
# export DDNSS_Token="aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
# --
#
DDNSS_DNS_API="https://ddnss.de/upd.php" DDNSS_DNS_API="https://ddnss.de/upd.php"

View File

@ -1,11 +1,13 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# # shellcheck disable=SC2034
# deSEC.io Domain API dns_desec_info='deSEC.io
# Site: desec.readthedocs.io/en/latest/
# Author: Zheng Qian Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_desec
# Options:
# deSEC API doc DDNSS_Token API Token
# https://desec.readthedocs.io/en/latest/ Issues: github.com/acmesh-official/acme.sh/issues/2180
Author: Zheng Qian
'
REST_API="https://desec.io/api/v1/domains" REST_API="https://desec.io/api/v1/domains"
@ -174,7 +176,7 @@ _get_root() {
i=2 i=2
p=1 p=1
while true; do 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 h "$h"
if [ -z "$h" ]; then if [ -z "$h" ]; then
#not valid #not valid
@ -186,7 +188,7 @@ _get_root() {
fi fi
if _contains "$response" "\"name\":\"$h\"" >/dev/null; then 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 _domain=$h
return 0 return 0
fi fi

View File

@ -1,18 +1,15 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
######################################################################## dns_df_info='DynDnsFree.de
# https://dyndnsfree.de hook script for acme.sh Domains: dynup.de
# Site: DynDnsFree.de
# Environment variables: Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_df
# Options:
# - $DF_user (your dyndnsfree.de username) DF_user Username
# - $DF_password (your dyndnsfree.de password) DF_password Password
# Issues: github.com/acmesh-official/acme.sh/issues/2897
# Author: Thilo Gass <thilo.gass@gmail.com> Author: Thilo Gass <thilo.gass@gmail.com>
# Git repo: https://github.com/ThiloGa/acme.sh '
#-- dns_df_add() - Add TXT record --------------------------------------
# Usage: dns_df_add _acme-challenge.subdomain.domain.com "XyZ123..."
dyndnsfree_api="https://dynup.de/acme.php" dyndnsfree_api="https://dynup.de/acme.php"

View File

@ -1,16 +1,12 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
## Will be called by acme.sh to add the txt record to your api system. dns_dgon_info='DigitalOcean.com
## returns 0 means success, otherwise error. Site: DigitalOcean.com/help/api/
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_dgon
## Author: thewer <github at thewer.com> Options:
## GitHub: https://github.com/gitwer/acme.sh DO_API_KEY API Key
Author: <github@thewer.com>
## '
## Environment Variables Required:
##
## DO_API_KEY="75310dc4ca779ac39a19f6355db573b49ce92ae126553ebd61ac3a3ae34834cc"
##
##################### Public functions ##################### ##################### Public functions #####################
@ -207,7 +203,7 @@ _get_base_domain() {
_debug2 domain_list "$domain_list" _debug2 domain_list "$domain_list"
i=1 i=1
while [ $i -gt 0 ]; do while [ "$i" -gt 0 ]; do
## get next longest domain ## get next longest domain
_domain=$(printf "%s" "$fulldomain" | cut -d . -f "$i"-"$MAX_DOM") _domain=$(printf "%s" "$fulldomain" | cut -d . -f "$i"-"$MAX_DOM")
## check we got something back from our cut (or are we at the end) ## check we got something back from our cut (or are we at the end)
@ -219,14 +215,14 @@ _get_base_domain() {
## check if it exists ## check if it exists
if [ -n "$found" ]; then if [ -n "$found" ]; then
## exists - exit loop returning the parts ## 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") _sub_domain=$(printf "%s" "$fulldomain" | cut -d . -f 1-"$sub_point")
_debug _domain "$_domain" _debug _domain "$_domain"
_debug _sub_domain "$_sub_domain" _debug _sub_domain "$_sub_domain"
return 0 return 0
fi fi
## increment cut point $i ## increment cut point $i
i=$(_math $i + 1) i=$(_math "$i" + 1)
done done
if [ -z "$found" ]; then if [ -z "$found" ]; then

View File

@ -1,13 +1,16 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
dns_dnsexit_info='DNSExit.com
Site: DNSExit.com
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_dnsexit
Options:
DNSEXIT_API_KEY API Key
DNSEXIT_AUTH_USER Username
DNSEXIT_AUTH_PASS Password
Issues: github.com/acmesh-official/acme.sh/issues/4719
Author: Samuel Jimenez
'
#use dns-01 at DNSExit.com
#Author: Samuel Jimenez
#Report Bugs here: https://github.com/acmesh-official/acme.sh
#DNSEXIT_API_KEY=ABCDEFGHIJ0123456789abcdefghij
#DNSEXIT_AUTH_USER=login@email.address
#DNSEXIT_AUTH_PASS=aStrongPassword
DNSEXIT_API_URL="https://api.dnsexit.com/dns/" DNSEXIT_API_URL="https://api.dnsexit.com/dns/"
DNSEXIT_HOSTS_URL="https://update.dnsexit.com/ipupdate/hosts.jsp" DNSEXIT_HOSTS_URL="https://update.dnsexit.com/ipupdate/hosts.jsp"
@ -81,7 +84,7 @@ _get_root() {
domain=$1 domain=$1
i=1 i=1
while true; do while true; do
_domain=$(printf "%s" "$domain" | cut -d . -f $i-100) _domain=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
_debug h "$_domain" _debug h "$_domain"
if [ -z "$_domain" ]; then if [ -z "$_domain" ]; then
return 1 return 1

View File

@ -1,15 +1,14 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
# dnsHome.de API for acme.sh dns_dnshome_info='dnsHome.de
# Site: dnsHome.de
# This Script adds the necessary TXT record to a Subdomain Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_dnshome
# Options:
# Author dnsHome.de (https://github.com/dnsHome-de) DNSHOME_Subdomain Subdomain
# DNSHOME_SubdomainPassword Subdomain Password
# Report Bugs to https://github.com/acmesh-official/acme.sh/issues/3819 Issues: github.com/acmesh-official/acme.sh/issues/3819
# Author: dnsHome.de https://github.com/dnsHome-de
# export DNSHOME_Subdomain="" '
# export DNSHOME_SubdomainPassword=""
# Usage: add subdomain.ddnsdomain.tld "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" # Usage: add subdomain.ddnsdomain.tld "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
# Used to add txt record # Used to add txt record

View File

@ -1,12 +1,12 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
# DNSimple domain api dns_dnsimple_info='DNSimple.com
# https://github.com/pho3nixf1re/acme.sh/issues Site: DNSimple.com
# Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_dnsimple
# This is your oauth token which can be acquired on the account page. Please Options:
# note that this must be an _account_ token and not a _user_ token. DNSimple_OAUTH_TOKEN OAuth Token
# https://dnsimple.com/a/<your account id>/account/access_tokens Issues: github.com/pho3nixf1re/acme.sh/issues
# DNSimple_OAUTH_TOKEN="sdfsdfsdfljlbjkljlkjsdfoiwje" '
DNSimple_API="https://api.dnsimple.com/v2" DNSimple_API="https://api.dnsimple.com/v2"
@ -92,7 +92,7 @@ _get_root() {
i=2 i=2
previous=1 previous=1
while true; do 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 if [ -z "$h" ]; then
# not valid # not valid
return 1 return 1
@ -105,7 +105,7 @@ _get_root() {
if _contains "$response" 'not found'; then if _contains "$response" 'not found'; then
_debug "$h not found" _debug "$h not found"
else else
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$previous) _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$previous")
_domain="$h" _domain="$h"
_debug _domain "$_domain" _debug _domain "$_domain"

View File

@ -1,12 +1,15 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
dns_dnsservices_info='DNS.Services
Site: DNS.Services
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_dnsservices
Options:
DnsServices_Username Username
DnsServices_Password Password
Issues: github.com/acmesh-official/acme.sh/issues/4152
Author: Bjarke Bruun <bbruun@gmail.com>
'
#This file name is "dns_dnsservices.sh"
#Script for Danish DNS registra and DNS hosting provider https://dns.services
#Author: Bjarke Bruun <bbruun@gmail.com>
#Report Bugs here: https://github.com/acmesh-official/acme.sh/issues/4152
# Global variable to connect to the DNS.Services API
DNSServices_API=https://dns.services/api DNSServices_API=https://dns.services/api
######## Public functions ##################### ######## Public functions #####################

View File

@ -1,148 +0,0 @@
#!/usr/bin/env sh
# DNS API for Domain-Offensive / Resellerinterface / Domainrobot
# Report bugs at https://github.com/seidler2547/acme.sh/issues
# set these environment variables to match your customer ID and password:
# DO_PID="KD-1234567"
# DO_PW="cdfkjl3n2"
DO_URL="https://soap.resellerinterface.de/"
######## Public functions #####################
#Usage: dns_myapi_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_do_add() {
fulldomain=$1
txtvalue=$2
if _dns_do_authenticate; then
_info "Adding TXT record to ${_domain} as ${fulldomain}"
_dns_do_soap createRR origin "${_domain}" name "${fulldomain}" type TXT data "${txtvalue}" ttl 300
if _contains "${response}" '>success<'; then
return 0
fi
_err "Could not create resource record, check logs"
fi
return 1
}
#fulldomain
dns_do_rm() {
fulldomain=$1
if _dns_do_authenticate; then
if _dns_do_list_rrs; then
_dns_do_had_error=0
for _rrid in ${_rr_list}; do
_info "Deleting resource record $_rrid for $_domain"
_dns_do_soap deleteRR origin "${_domain}" rrid "${_rrid}"
if ! _contains "${response}" '>success<'; then
_dns_do_had_error=1
_err "Could not delete resource record for ${_domain}, id ${_rrid}"
fi
done
return $_dns_do_had_error
fi
fi
return 1
}
#################### Private functions below ##################################
_dns_do_authenticate() {
_info "Authenticating as ${DO_PID}"
_dns_do_soap authPartner partner "${DO_PID}" password "${DO_PW}"
if _contains "${response}" '>success<'; then
_get_root "$fulldomain"
_debug "_domain $_domain"
return 0
else
_err "Authentication failed, are DO_PID and DO_PW set correctly?"
fi
return 1
}
_dns_do_list_rrs() {
_dns_do_soap getRRList origin "${_domain}"
if ! _contains "${response}" 'SOAP-ENC:Array'; then
_err "getRRList origin ${_domain} failed"
return 1
fi
_rr_list="$(echo "${response}" |
tr -d "\n\r\t" |
sed -e 's/<item xsi:type="ns2:Map">/\n/g' |
grep ">$(_regexcape "$fulldomain")</value>" |
sed -e 's/<\/item>/\n/g' |
grep '>id</key><value' |
_egrep_o '>[0-9]{1,16}<' |
tr -d '><')"
[ "${_rr_list}" ]
}
_dns_do_soap() {
func="$1"
shift
# put the parameters to xml
body="<tns:${func} xmlns:tns=\"${DO_URL}\">"
while [ "$1" ]; do
_k="$1"
shift
_v="$1"
shift
body="$body<$_k>$_v</$_k>"
done
body="$body</tns:${func}>"
_debug2 "SOAP request ${body}"
# build SOAP XML
_xml='<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Body>'"$body"'</env:Body>
</env:Envelope>'
# set SOAP headers
export _H1="SOAPAction: ${DO_URL}#${func}"
if ! response="$(_post "${_xml}" "${DO_URL}")"; then
_err "Error <$1>"
return 1
fi
_debug2 "SOAP response $response"
# retrieve cookie header
_H2="$(_egrep_o 'Cookie: [^;]+' <"$HTTP_HEADER" | _head_n 1)"
export _H2
return 0
}
_get_root() {
domain=$1
i=1
_dns_do_soap getDomainList
_all_domains="$(echo "${response}" |
tr -d "\n\r\t " |
_egrep_o 'domain</key><value[^>]+>[^<]+' |
sed -e 's/^domain<\/key><value[^>]*>//g')"
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
if [ -z "$h" ]; then
return 1
fi
if _contains "${_all_domains}" "^$(_regexcape "$h")\$"; then
_domain="$h"
return 0
fi
i=$(_math $i + 1)
done
_debug "$domain not found"
return 1
}
_regexcape() {
echo "$1" | sed -e 's/\([]\.$*^[]\)/\\\1/g'
}

View File

@ -1,14 +1,16 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
dns_doapi_info='Domain-Offensive do.de
Official LetsEncrypt API for do.de / Domain-Offensive.
This API is also available to private customers/individuals.
Site: do.de
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_doapi
Options:
DO_LETOKEN LetsEncrypt Token
Issues: github.com/acmesh-official/acme.sh/issues/2057
'
# Official Let's Encrypt API for do.de / Domain-Offensive DO_API="https://my.do.de/api/letsencrypt"
#
# 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
#
# Provide the required LetsEncrypt token like this:
# DO_LETOKEN="FmD408PdqT1E269gUK57"
DO_API="https://www.do.de/api/letsencrypt"
######## Public functions ##################### ######## Public functions #####################

View File

@ -1,4 +1,13 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
dns_domeneshop_info='DomeneShop.no
Site: DomeneShop.no
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_domeneshop
Options:
DOMENESHOP_Token Token
DOMENESHOP_Secret Secret
Issues: github.com/acmesh-official/acme.sh/issues/2457
'
DOMENESHOP_Api_Endpoint="https://api.domeneshop.no/v0" DOMENESHOP_Api_Endpoint="https://api.domeneshop.no/v0"
@ -84,7 +93,7 @@ _get_domainid() {
i=2 i=2
p=1 p=1
while true; do 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 "h" "$h"
if [ -z "$h" ]; then if [ -z "$h" ]; then
#not valid #not valid
@ -93,7 +102,7 @@ _get_domainid() {
if _contains "$response" "\"$h\"" >/dev/null; then if _contains "$response" "\"$h\"" >/dev/null; then
# We have found the domain name. # 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 _domain=$h
_domainid=$(printf "%s" "$response" | _egrep_o "[^{]*\"domain\":\"$_domain\"[^}]*" | _egrep_o "\"id\":[0-9]+" | cut -d : -f 2) _domainid=$(printf "%s" "$response" | _egrep_o "[^{]*\"domain\":\"$_domain\"[^}]*" | _egrep_o "\"id\":[0-9]+" | cut -d : -f 2)
return 0 return 0

View File

@ -1,10 +1,12 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
# Dnspod.cn Domain api dns_dp_info='DNSPod.cn
# Site: DNSPod.cn
#DP_Id="1234" Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_dp
# Options:
#DP_Key="sADDsdasdgdsf" DP_Id Id
DP_Key Key
'
REST_API="https://dnsapi.cn" REST_API="https://dnsapi.cn"
@ -107,7 +109,7 @@ _get_root() {
i=2 i=2
p=1 p=1
while true; do 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 if [ -z "$h" ]; then
#not valid #not valid
return 1 return 1
@ -121,7 +123,7 @@ _get_root() {
_domain_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \") _domain_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \")
_debug _domain_id "$_domain_id" _debug _domain_id "$_domain_id"
if [ "$_domain_id" ]; then 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" _debug _sub_domain "$_sub_domain"
_domain="$h" _domain="$h"
_debug _domain "$_domain" _debug _domain "$_domain"

View File

@ -1,10 +1,12 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
# Dnspod.com Domain api dns_dpi_info='DNSPod.com
# Site: DNSPod.com
#DPI_Id="1234" Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_dpi
# Options:
#DPI_Key="sADDsdasdgdsf" DPI_Id Id
DPI_Key Key
'
REST_API="https://api.dnspod.com" REST_API="https://api.dnspod.com"
@ -107,7 +109,7 @@ _get_root() {
i=2 i=2
p=1 p=1
while true; do 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 if [ -z "$h" ]; then
#not valid #not valid
return 1 return 1
@ -121,7 +123,7 @@ _get_root() {
_domain_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \") _domain_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \")
_debug _domain_id "$_domain_id" _debug _domain_id "$_domain_id"
if [ "$_domain_id" ]; then 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" _debug _sub_domain "$_sub_domain"
_domain="$h" _domain="$h"
_debug _domain "$_domain" _debug _domain "$_domain"

View File

@ -1,10 +1,14 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
dns_dreamhost_info='DreamHost.com
Site: DreamHost.com
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_dreamhost
Options:
DH_API_KEY API Key
Issues: github.com/RhinoLance/acme.sh
Author: RhinoLance
'
#Author: RhinoLance
#Report Bugs here: https://github.com/RhinoLance/acme.sh
#
#define the api endpoint
DH_API_ENDPOINT="https://api.dreamhost.com/" DH_API_ENDPOINT="https://api.dreamhost.com/"
querystring="" querystring=""

View File

@ -1,14 +1,12 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
#Created by RaidenII, to use DuckDNS's API to add/remove text records dns_duckdns_info='DuckDNS.org
#06/27/2017 Site: www.DuckDNS.org
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_duckdns
# Pass credentials before "acme.sh --issue --dns dns_duckdns ..." Options:
# -- DuckDNS_Token API Token
# export DuckDNS_Token="aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee" Author: RaidenII
# -- '
#
# Due to the fact that DuckDNS uses StartSSL as cert provider, --insecure may need to be used with acme.sh
DuckDNS_API="https://www.duckdns.org/update" DuckDNS_API="https://www.duckdns.org/update"

View File

@ -1,7 +1,13 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
#DD_API_User="xxxxx" dns_durabledns_info='DurableDNS.com
#DD_API_Key="xxxxxx" Site: DurableDNS.com
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_durabledns
Options:
DD_API_User API User
DD_API_Key API Key
Issues: github.com/acmesh-official/acme.sh/issues/2281
'
_DD_BASE="https://durabledns.com/services/dns" _DD_BASE="https://durabledns.com/services/dns"
@ -104,7 +110,7 @@ _get_root() {
i=1 i=1
p=1 p=1
while true; do 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 h "$h"
if [ -z "$h" ]; then if [ -z "$h" ]; then
#not valid #not valid
@ -112,7 +118,7 @@ _get_root() {
fi fi
if _contains "$response" ">$h.</origin>"; then 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 _domain=$h
return 0 return 0
fi fi

View File

@ -1,10 +1,16 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# # shellcheck disable=SC2034
# Dyn.com Domain API dns_dyn_info='Dyn.com
# Domains: dynect.net
# Author: Gerd Naschenweng Site: Dyn.com
# https://github.com/magicdude4eva Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_dyn
# Options:
DYN_Customer Customer
DYN_Username API Username
DYN_Password Secret
Author: Gerd Naschenweng <https://github.com/magicdude4eva>
'
# Dyn Managed DNS API # Dyn Managed DNS API
# https://help.dyn.com/dns-api-knowledge-base/ # https://help.dyn.com/dns-api-knowledge-base/
# #
@ -20,13 +26,6 @@
# ZoneRemoveNode # ZoneRemoveNode
# ZonePublish # ZonePublish
# -- # --
#
# Pass credentials before "acme.sh --issue --dns dns_dyn ..."
# --
# export DYN_Customer="customer"
# export DYN_Username="apiuser"
# export DYN_Password="secret"
# --
DYN_API="https://api.dynect.net/REST" DYN_API="https://api.dynect.net/REST"

View File

@ -1,20 +1,21 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
dns_dynu_info='Dynu.com
Site: Dynu.com
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_dynu
Options:
Dynu_ClientId Client ID
Dynu_Secret Secret
Issues: github.com/shar0119/acme.sh
Author: Dynu Systems Inc
'
#Client ID
#Dynu_ClientId="0b71cae7-a099-4f6b-8ddf-94571cdb760d"
#
#Secret
#Dynu_Secret="aCUEY4BDCV45KI8CSIC3sp2LKQ9"
#
#Token #Token
Dynu_Token="" Dynu_Token=""
# #
#Endpoint #Endpoint
Dynu_EndPoint="https://api.dynu.com/v2" Dynu_EndPoint="https://api.dynu.com/v2"
#
#Author: Dynu Systems, Inc.
#Report Bugs here: https://github.com/shar0119/acme.sh
#
######## Public functions ##################### ######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" #Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
@ -125,7 +126,7 @@ _get_root() {
i=2 i=2
p=1 p=1
while true; do 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 h "$h"
if [ -z "$h" ]; then if [ -z "$h" ]; then
#not valid #not valid
@ -139,7 +140,7 @@ _get_root() {
if _contains "$response" "\"domainName\":\"$h\"" >/dev/null; then if _contains "$response" "\"domainName\":\"$h\"" >/dev/null; then
dnsId=$(printf "%s" "$response" | tr -d "{}" | cut -d , -f 2 | cut -d : -f 2) dnsId=$(printf "%s" "$response" | tr -d "{}" | cut -d , -f 2 | cut -d : -f 2)
_domain_name=$h _domain_name=$h
_node=$(printf "%s" "$domain" | cut -d . -f 1-$p) _node=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
return 0 return 0
fi fi
p=$i p=$i

View File

@ -1,16 +1,23 @@
#!/usr/bin/env sh #!/usr/bin/env sh
#Author StefanAbl # shellcheck disable=SC2034
#Usage specify a private keyfile to use with dynv6 'export KEY="path/to/keyfile"' dns_dynv6_info='DynV6.com
#or use the HTTP REST API by by specifying a token 'export DYNV6_TOKEN="value" Site: DynV6.com
#if no keyfile is specified, you will be asked if you want to create one in /home/$USER/.ssh/dynv6 and /home/$USER/.ssh/dynv6.pub Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_dynv6
Options:
DYNV6_TOKEN REST API token. Get from https://DynV6.com/keys
OptionsAlt:
KEY Path to SSH private key file. E.g. "/root/.ssh/dynv6"
Issues: github.com/acmesh-official/acme.sh/issues/2702
Author: StefanAbl
'
dynv6_api="https://dynv6.com/api/v2" dynv6_api="https://dynv6.com/api/v2"
######## Public functions ##################### ######## Public functions #####################
# Please Read this guide first: https://github.com/Neilpang/acme.sh/wiki/DNS-API-Dev-Guide # Please Read this guide first: https://github.com/Neilpang/acme.sh/wiki/DNS-API-Dev-Guide
#Usage: dns_dynv6_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" #Usage: dns_dynv6_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_dynv6_add() { dns_dynv6_add() {
fulldomain=$1 fulldomain="$(echo "$1" | _lower_case)"
txtvalue=$2 txtvalue="$2"
_info "Using dynv6 api" _info "Using dynv6 api"
_debug fulldomain "$fulldomain" _debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue" _debug txtvalue "$txtvalue"
@ -36,15 +43,14 @@ dns_dynv6_add() {
_err "Something went wrong! it does not seem like the record was added successfully" _err "Something went wrong! it does not seem like the record was added successfully"
return 1 return 1
fi fi
return 1
fi fi
return 1
} }
#Usage: fulldomain txtvalue #Usage: fulldomain txtvalue
#Remove the txt record after validation. #Remove the txt record after validation.
dns_dynv6_rm() { dns_dynv6_rm() {
fulldomain=$1 fulldomain="$(echo "$1" | _lower_case)"
txtvalue=$2 txtvalue="$2"
_info "Using dynv6 API" _info "Using dynv6 API"
_debug fulldomain "$fulldomain" _debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue" _debug txtvalue "$txtvalue"
@ -199,7 +205,7 @@ _get_zone_id() {
return 1 return 1
fi fi
zone_id="$(echo "$response" | tr '}' '\n' | grep "$selected" | tr ',' '\n' | grep id | tr -d '"')" zone_id="$(echo "$response" | tr '}' '\n' | grep "$selected" | tr ',' '\n' | grep '"id":' | tr -d '"')"
_zone_id="${zone_id#id:}" _zone_id="${zone_id#id:}"
_debug "zone id: $_zone_id" _debug "zone id: $_zone_id"
} }

View File

@ -1,14 +1,17 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
dns_easydns_info='easyDNS.net
Site: easyDNS.net
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_easydns
Options:
EASYDNS_Token API Token
EASYDNS_Key API Key
Issues: github.com/acmesh-official/acme.sh/issues/2647
Author: Neilpang, wurzelpanzer <wurzelpanzer@maximolider.net>
'
#######################################################
#
# easyDNS REST API for acme.sh by Neilpang based on dns_cf.sh
#
# API Documentation: https://sandbox.rest.easydns.net:3001/ # API Documentation: https://sandbox.rest.easydns.net:3001/
#
# Author: wurzelpanzer [wurzelpanzer@maximolider.net]
# Report Bugs here: https://github.com/acmesh-official/acme.sh/issues/2647
#
#################### Public functions ################# #################### Public functions #################
#EASYDNS_Key="xxxxxxxxxxxxxxxxxxxxxxxx" #EASYDNS_Key="xxxxxxxxxxxxxxxxxxxxxxxx"
@ -118,7 +121,7 @@ _get_root() {
i=1 i=1
p=1 p=1
while true; do 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 h "$h"
if [ -z "$h" ]; then if [ -z "$h" ]; then
#not valid #not valid
@ -130,7 +133,7 @@ _get_root() {
fi fi
if _contains "$response" "\"status\":200"; then 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 _domain=$h
return 0 return 0
fi fi

View File

@ -1,4 +1,15 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
dns_edgedns_info='Akamai.com Edge DNS
Site: techdocs.Akamai.com/edge-dns/reference/edge-dns-api
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_edgedns
Options: Specify individual credentials
AKAMAI_HOST Host
AKAMAI_ACCESS_TOKEN Access token
AKAMAI_CLIENT_TOKEN Client token
AKAMAI_CLIENT_SECRET Client secret
Issues: github.com/acmesh-official/acme.sh/issues/3157
'
# Akamai Edge DNS v2 API # Akamai Edge DNS v2 API
# User must provide Open Edgegrid API credentials to the EdgeDNS installation. The remote user in EdgeDNS must have CRUD access to # User must provide Open Edgegrid API credentials to the EdgeDNS installation. The remote user in EdgeDNS must have CRUD access to
@ -6,18 +17,10 @@
# Report bugs to https://control.akamai.com/apps/support-ui/#/contact-support # Report bugs to https://control.akamai.com/apps/support-ui/#/contact-support
# Values to export:
# --EITHER--
# *** TBD. NOT IMPLEMENTED YET *** # *** TBD. NOT IMPLEMENTED YET ***
# specify Edgegrid credentials file and section # Specify Edgegrid credentials file and section.
# AKAMAI_EDGERC=<full file path> # AKAMAI_EDGERC Edge RC. Full file path
# AKAMAI_EDGERC_SECTION="default" # AKAMAI_EDGERC_SECTION Edge RC Section. E.g. "default"
## --OR--
# specify indiviual credentials
# export AKAMAI_HOST = <host>
# export AKAMAI_ACCESS_TOKEN = <access token>
# export AKAMAI_CLIENT_TOKEN = <client token>
# export AKAMAI_CLIENT_SECRET = <client secret>
ACME_EDGEDNS_VERSION="0.1.0" ACME_EDGEDNS_VERSION="0.1.0"

View File

@ -1,18 +1,14 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
#This is the euserv.eu api wrapper for acme.sh dns_euserv_info='EUserv.com
# Domains: EUserv.eu
#Author: Michael Brueckner Site: EUserv.com
#Report Bugs: https://www.github.com/initit/acme.sh or mbr@initit.de Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_euserv
Options:
# EUSERV_Username Username
#EUSERV_Username="username" EUSERV_Password Password
# Author: Michael Brueckner
#EUSERV_Password="password" '
#
# Dependencies:
# -------------
# - none -
EUSERV_Api="https://api.euserv.net" EUSERV_Api="https://api.euserv.net"
@ -155,7 +151,7 @@ _get_root() {
response="$_euserv_domain_orders" response="$_euserv_domain_orders"
while true; do while true; do
h=$(echo "$domain" | cut -d . -f $i-100) h=$(echo "$domain" | cut -d . -f "$i"-100)
_debug h "$h" _debug h "$h"
if [ -z "$h" ]; then if [ -z "$h" ]; then
#not valid #not valid
@ -163,7 +159,7 @@ _get_root() {
fi fi
if _contains "$response" "$h"; then 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" _domain="$h"
if ! _euserv_get_domain_id "$_domain"; then if ! _euserv_get_domain_id "$_domain"; then
_err "invalid domain" _err "invalid domain"

View File

@ -1,4 +1,12 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
dns_exoscale_info='Exoscale.com
Site: Exoscale.com
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_exoscale
Options:
EXOSCALE_API_KEY API Key
EXOSCALE_SECRET_KEY API Secret key
'
EXOSCALE_API=https://api.exoscale.com/dns/v1 EXOSCALE_API=https://api.exoscale.com/dns/v1
@ -111,7 +119,7 @@ _get_root() {
i=2 i=2
p=1 p=1
while true; do 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 h "$h"
if [ -z "$h" ]; then if [ -z "$h" ]; then
#not valid #not valid
@ -122,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_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 \") _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 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 _domain=$h
return 0 return 0
fi fi

View File

@ -1,8 +1,15 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
dns_fornex_info='Fornex.com
Site: Fornex.com
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_fornex
Options:
FORNEX_API_KEY API Key
Issues: github.com/acmesh-official/acme.sh/issues/3998
Author: Timur Umarov <inbox@tumarov.com>
'
#Author: Timur Umarov <inbox@tumarov.com> FORNEX_API_URL="https://fornex.com/api"
FORNEX_API_URL="https://fornex.com/api/dns/v0.1"
######## Public functions ##################### ######## Public functions #####################
@ -23,12 +30,10 @@ dns_fornex_add() {
fi fi
_info "Adding record" _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" _debug _response "$response"
if _contains "$response" '"ok": true' || _contains "$response" 'Такая запись уже существует.'; then _info "Added, OK"
_info "Added, OK" return 0
return 0
fi
fi fi
_err "Add txt record error." _err "Add txt record error."
return 1 return 1
@ -51,21 +56,21 @@ dns_fornex_rm() {
fi fi
_debug "Getting txt records" _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 if ! _contains "$response" "$txtvalue"; then
_err "Txt record not found" _err "Txt record not found"
return 1 return 1
fi 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" _debug "_record_id" "$_record_id"
if [ -z "$_record_id" ]; then if [ -z "$_record_id" ]; then
_err "can not find _record_id" _err "can not find _record_id"
return 1 return 1
fi 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." _err "Delete record error."
return 1 return 1
fi fi
@ -83,18 +88,18 @@ _get_root() {
i=1 i=1
while true; do 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 h "$h"
if [ -z "$h" ]; then if [ -z "$h" ]; then
#not valid #not valid
return 1 return 1
fi fi
if ! _rest GET "domain_list.json?q=$h&apikey=$FORNEX_API_KEY"; then if ! _rest GET "dns/domain/"; then
return 1 return 1
fi fi
if _contains "$response" "\"$h\"" >/dev/null; then if _contains "$response" "\"name\":\"$h\"" >/dev/null; then
_domain=$h _domain=$h
return 0 return 0
else else
@ -127,7 +132,9 @@ _rest() {
data="$3" data="$3"
_debug "$ep" _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 if [ "$m" != "GET" ]; then
_debug data "$data" _debug data "$data"

View File

@ -1,14 +1,15 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
dns_freedns_info='FreeDNS
Site: FreeDNS.afraid.org
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_freedns
Options:
FREEDNS_User Username
FREEDNS_Password Password
Issues: github.com/acmesh-official/acme.sh/issues/2305
Author: David Kerr <https://github.com/dkerr64>
'
#This file name is "dns_freedns.sh"
#So, here must be a method dns_freedns_add()
#Which will be called by acme.sh to add the txt record to your api system.
#returns 0 means success, otherwise error.
#
#Author: David Kerr
#Report Bugs here: https://github.com/dkerr64/acme.sh
#or here... https://github.com/acmesh-official/acme.sh/issues/2305
#
######## Public functions ##################### ######## Public functions #####################
# Export FreeDNS userid and password in following variables... # Export FreeDNS userid and password in following variables...

View File

@ -1,19 +1,22 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
dns_gandi_livedns_info='Gandi.net LiveDNS
Site: Gandi.net/domain/dns
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_gandi_livedns
Options:
GANDI_LIVEDNS_KEY API Key
Issues: github.com/fcrozat/acme.sh
Author: Frédéric Crozat <fcrozat@suse.com>, Dominik Röttsches <drott@google.com>
'
# Gandi LiveDNS v5 API # Gandi LiveDNS v5 API
# https://api.gandi.net/docs/livedns/ # https://api.gandi.net/docs/livedns/
# https://api.gandi.net/docs/authentication/ for token + apikey (deprecated) authentication # https://api.gandi.net/docs/authentication/ for token + apikey (deprecated) authentication
# currently under beta # currently under beta
#
# Requires GANDI API KEY set in GANDI_LIVEDNS_KEY set as environment variable
#
#Author: Frédéric Crozat <fcrozat@suse.com>
# Dominik Röttsches <drott@google.com>
#Report Bugs here: https://github.com/fcrozat/acme.sh
#
######## Public functions ##################### ######## Public functions #####################
GANDI_LIVEDNS_API="https://dns.api.gandi.net/api/v5" GANDI_LIVEDNS_API="https://api.gandi.net/v5/livedns"
#Usage: dns_gandi_livedns_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" #Usage: dns_gandi_livedns_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_gandi_livedns_add() { dns_gandi_livedns_add() {
@ -78,7 +81,7 @@ dns_gandi_livedns_rm() {
_gandi_livedns_rest PUT \ _gandi_livedns_rest PUT \
"domains/$_domain/records/$_sub_domain/TXT" \ "domains/$_domain/records/$_sub_domain/TXT" \
"{\"rrset_ttl\": 300, \"rrset_values\": $_new_rrset_values}" && "{\"rrset_ttl\": 300, \"rrset_values\": $_new_rrset_values}" &&
_contains "$response" '{"message": "DNS Record Created"}' && _contains "$response" '{"message":"DNS Record Created"}' &&
_info "Removing record $(__green "success")" _info "Removing record $(__green "success")"
} }
@ -92,7 +95,7 @@ _get_root() {
i=2 i=2
p=1 p=1
while true; do 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 h "$h"
if [ -z "$h" ]; then if [ -z "$h" ]; then
#not valid #not valid
@ -109,7 +112,7 @@ _get_root() {
elif _contains "$response" '"code": 404'; then elif _contains "$response" '"code": 404'; then
_debug "$h not found" _debug "$h not found"
else else
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain="$h" _domain="$h"
return 0 return 0
fi fi
@ -134,7 +137,7 @@ _dns_gandi_append_record() {
_debug new_rrset_values "$_rrset_values" _debug new_rrset_values "$_rrset_values"
_gandi_livedns_rest PUT "domains/$_domain/records/$sub_domain/TXT" \ _gandi_livedns_rest PUT "domains/$_domain/records/$sub_domain/TXT" \
"{\"rrset_ttl\": 300, \"rrset_values\": $_rrset_values}" && "{\"rrset_ttl\": 300, \"rrset_values\": $_rrset_values}" &&
_contains "$response" '{"message": "DNS Record Created"}' && _contains "$response" '{"message":"DNS Record Created"}' &&
_info "Adding record $(__green "success")" _info "Adding record $(__green "success")"
} }
@ -144,11 +147,11 @@ _dns_gandi_existing_rrset_values() {
if ! _gandi_livedns_rest GET "domains/$domain/records/$sub_domain"; then if ! _gandi_livedns_rest GET "domains/$domain/records/$sub_domain"; then
return 1 return 1
fi fi
if ! _contains "$response" '"rrset_type": "TXT"'; then if ! _contains "$response" '"rrset_type":"TXT"'; then
_debug "Does not have a _acme-challenge TXT record yet." _debug "Does not have a _acme-challenge TXT record yet."
return 1 return 1
fi fi
if _contains "$response" '"rrset_values": \[\]'; then if _contains "$response" '"rrset_values":\[\]'; then
_debug "Empty rrset_values for TXT record, no previous TXT record." _debug "Empty rrset_values for TXT record, no previous TXT record."
return 1 return 1
fi fi
@ -169,7 +172,7 @@ _gandi_livedns_rest() {
if [ -n "$GANDI_LIVEDNS_TOKEN" ]; then if [ -n "$GANDI_LIVEDNS_TOKEN" ]; then
export _H2="Authorization: Bearer $GANDI_LIVEDNS_TOKEN" export _H2="Authorization: Bearer $GANDI_LIVEDNS_TOKEN"
else else
export _H2="X-Api-Key: $GANDI_LIVEDNS_KEY" export _H2="Authorization: Apikey $GANDI_LIVEDNS_KEY"
fi fi
if [ "$m" = "GET" ]; then if [ "$m" = "GET" ]; then

View File

@ -1,6 +1,12 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
# Author: Janos Lenart <janos@lenart.io> dns_gcloud_info='Google Cloud DNS
Site: Cloud.Google.com/dns
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_gcloud
Options:
CLOUDSDK_ACTIVE_CONFIG_NAME Active config name. E.g. "default"
Author: Janos Lenart <janos@lenart.io>
'
######## Public functions ##################### ######## Public functions #####################
@ -42,7 +48,7 @@ dns_gcloud_rm() {
echo "$rrdatas" | grep -F -v -- "\"$txtvalue\"" | _dns_gcloud_add_rrs || return $? echo "$rrdatas" | grep -F -v -- "\"$txtvalue\"" | _dns_gcloud_add_rrs || return $?
_dns_gcloud_execute_tr || return $? _dns_gcloud_execute_tr || return $?
_info "$fulldomain record added" _info "$fulldomain record removed"
} }
#################### Private functions below ################################## #################### Private functions below ##################################

View File

@ -1,11 +1,15 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
dns_gcore_info='Gcore.com
Site: Gcore.com
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_gcore
Options:
GCORE_Key API Key
Issues: github.com/acmesh-official/acme.sh/issues/4460
'
# GCORE_Api="https://api.gcore.com/dns/v2"
#GCORE_Key='773$7b7adaf2a2b32bfb1b83787b4ff32a67eb178e3ada1af733e47b1411f2461f7f4fa7ed7138e2772a46124377bad7384b3bb8d87748f87b3f23db4b8bbe41b2bb' GCORE_Doc="https://api.gcore.com/docs/dns"
#
GCORE_Api="https://api.gcorelabs.com/dns/v2"
GCORE_Doc="https://apidocs.gcore.com/dns"
######## Public functions ##################### ######## Public functions #####################
@ -24,7 +28,7 @@ dns_gcore_add() {
fi fi
#save the api key to the account conf file. #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" _debug "First detect the zone name"
if ! _get_root "$fulldomain"; then if ! _get_root "$fulldomain"; then
@ -134,7 +138,7 @@ _get_root() {
p=1 p=1
while true; do 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 h "$h"
if [ -z "$h" ]; then if [ -z "$h" ]; then
#not valid #not valid
@ -148,7 +152,7 @@ _get_root() {
if _contains "$response" "\"name\":\"$h\""; then if _contains "$response" "\"name\":\"$h\""; then
_zone_name=$h _zone_name=$h
if [ "$_zone_name" ]; then 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 _domain=$h
return 0 return 0
fi fi

View File

@ -1,12 +1,12 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
#Godaddy domain api dns_gd_info='GoDaddy.com
# Get API key and secret from https://developer.godaddy.com/ Site: GoDaddy.com
# Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_gd
# GD_Key="sdfsdfsdfljlbjkljlkjsdfoiwje" Options:
# GD_Secret="asdfsdfsfsdfsdfdfsdf" GD_Key API Key
# GD_Secret API Secret
# Ex.: acme.sh --issue --staging --dns dns_gd -d "*.s.example.com" -d "s.example.com" '
GD_Api="https://api.godaddy.com/v1" GD_Api="https://api.godaddy.com/v1"
@ -148,7 +148,7 @@ _get_root() {
i=2 i=2
p=1 p=1
while true; do 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 if [ -z "$h" ]; then
#not valid #not valid
return 1 return 1
@ -161,7 +161,7 @@ _get_root() {
if _contains "$response" '"code":"NOT_FOUND"'; then if _contains "$response" '"code":"NOT_FOUND"'; then
_debug "$h not found" _debug "$h not found"
else else
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_domain="$h" _domain="$h"
return 0 return 0
fi fi

View File

@ -1,12 +1,12 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
######################################################################## dns_geoscaling_info='GeoScaling.com
# Geoscaling hook script for acme.sh Site: GeoScaling.com
# Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_geoscaling
# Environment variables: Options:
# GEOSCALING_Username Username. This is usually NOT an email address
# - $GEOSCALING_Username (your Geoscaling username - this is usually NOT an amail address) GEOSCALING_Password Password
# - $GEOSCALING_Password (your Geoscaling password) '
#-- dns_geoscaling_add() - Add TXT record -------------------------------------- #-- dns_geoscaling_add() - Add TXT record --------------------------------------
# Usage: dns_geoscaling_add _acme-challenge.subdomain.domain.com "XyZ123..." # Usage: dns_geoscaling_add _acme-challenge.subdomain.domain.com "XyZ123..."
@ -202,7 +202,7 @@ find_zone() {
# Walk through all possible zone names # Walk through all possible zone names
strip_counter=1 strip_counter=1
while true; do 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 # All possible zone names have been tried
if [ -z "${attempted_zone}" ]; then if [ -z "${attempted_zone}" ]; then

View File

@ -1,10 +1,15 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
dns_googledomains_info='Google Domains
Site: Domains.Google.com
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_googledomains
Options:
GOOGLEDOMAINS_ACCESS_TOKEN API Access Token
GOOGLEDOMAINS_ZONE Zone
Issues: github.com/acmesh-official/acme.sh/issues/4545
Author: Alex Leigh <leigh@alexleigh.me>
'
# Author: Alex Leigh <leigh at alexleigh dot me>
# Created: 2023-03-02
#GOOGLEDOMAINS_ACCESS_TOKEN="xxxx"
#GOOGLEDOMAINS_ZONE="xxxx"
GOOGLEDOMAINS_API="https://acmedns.googleapis.com/v1/acmeChallengeSets" GOOGLEDOMAINS_API="https://acmedns.googleapis.com/v1/acmeChallengeSets"
######## Public functions ######## ######## Public functions ########
@ -127,7 +132,7 @@ _dns_googledomains_get_zone() {
i=2 i=2
while true; do while true; do
curr=$(printf "%s" "$domain" | cut -d . -f $i-100) curr=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
_debug curr "$curr" _debug curr "$curr"
if [ -z "$curr" ]; then if [ -z "$curr" ]; then

View File

@ -1,15 +1,14 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
######################################################################## dns_he_info='Hurricane Electric HE.net
# Hurricane Electric hook script for acme.sh Site: dns.he.net
# Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_he
# Environment variables: Options:
# HE_Username Username
# - $HE_Username (your dns.he.net username) HE_Password Password
# - $HE_Password (your dns.he.net password) Issues: github.com/angel333/acme.sh/issues/
# Author: Ondrej Simek <me@ondrejsimek.com>
# Author: Ondrej Simek <me@ondrejsimek.com> '
# Git repo: https://github.com/angel333/acme.sh
#-- dns_he_add() - Add TXT record -------------------------------------- #-- dns_he_add() - Add TXT record --------------------------------------
# Usage: dns_he_add _acme-challenge.subdomain.domain.com "XyZ123..." # Usage: dns_he_add _acme-challenge.subdomain.domain.com "XyZ123..."
@ -144,7 +143,7 @@ _find_zone() {
# Walk through all possible zone names # Walk through all possible zone names
_strip_counter=1 _strip_counter=1
while true; do 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 # All possible zone names have been tried
if [ -z "$_attempted_zone" ]; then if [ -z "$_attempted_zone" ]; then

View File

@ -1,8 +1,12 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
# dns_hetzner_info='Hetzner.com
#HETZNER_Token="sdfsdfsdfljlbjkljlkjsdfoiwje" 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" HETZNER_Api="https://dns.hetzner.com/api/v1"
@ -177,7 +181,7 @@ _get_root() {
_debug "Trying to get zone id by domain name for '$domain_without_acme'." _debug "Trying to get zone id by domain name for '$domain_without_acme'."
while true; do 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 if [ -z "$h" ]; then
#not valid #not valid
return 1 return 1
@ -189,7 +193,7 @@ _get_root() {
if _contains "$response" "\"name\":\"$h\"" || _contains "$response" '"total_entries":1'; then 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 \") _domain_id=$(echo "$response" | _egrep_o "\[.\"id\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \")
if [ "$_domain_id" ]; then 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 _domain=$h
HETZNER_Zone_ID=$_domain_id HETZNER_Zone_ID=$_domain_id
_savedomainconf "$domain_param_name" "$HETZNER_Zone_ID" _savedomainconf "$domain_param_name" "$HETZNER_Zone_ID"

View File

@ -1,9 +1,13 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
# dns_hexonet_info='Hexonet.com
# Hexonet_Login="username!roleId" Site: Hexonet.com
# Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_hexonet
# Hexonet_Password="rolePassword" Options:
Hexonet_Login Login. E.g. "username!roleId"
Hexonet_Password Role Password
Issues: github.com/acmesh-official/acme.sh/issues/2389
'
Hexonet_Api="https://coreapi.1api.net/api/call.cgi" Hexonet_Api="https://coreapi.1api.net/api/call.cgi"
@ -119,7 +123,7 @@ _get_root() {
i=1 i=1
p=1 p=1
while true; do 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 h "$h"
if [ -z "$h" ]; then if [ -z "$h" ]; then
#not valid #not valid
@ -131,7 +135,7 @@ _get_root() {
fi fi
if _contains "$response" "CODE=200"; then 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 _domain=$h
return 0 return 0
fi fi

View File

@ -1,10 +1,13 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
# hosting.de API dns_hostingde_info='Hosting.de
Site: Hosting.de
# Values to export: Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_hostingde
# export HOSTINGDE_ENDPOINT='https://secure.hosting.de' Options:
# export HOSTINGDE_APIKEY='xxxxx' HOSTINGDE_ENDPOINT Endpoint. E.g. "https://secure.hosting.de"
HOSTINGDE_APIKEY API Key
Issues: github.com/acmesh-official/acme.sh/issues/2058
'
######## Public functions ##################### ######## Public functions #####################

View File

@ -1,8 +1,14 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
# HUAWEICLOUD_Username dns_huaweicloud_info='HuaweiCloud.com
# HUAWEICLOUD_Password Site: HuaweiCloud.com
# HUAWEICLOUD_DomainName Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_huaweicloud
Options:
HUAWEICLOUD_Username Username
HUAWEICLOUD_Password Password
HUAWEICLOUD_DomainName DomainName
Issues: github.com/acmesh-official/acme.sh/issues/3265
'
iam_api="https://iam.myhuaweicloud.com" iam_api="https://iam.myhuaweicloud.com"
dns_api="https://dns.ap-southeast-1.myhuaweicloud.com" # Should work dns_api="https://dns.ap-southeast-1.myhuaweicloud.com" # Should work
@ -204,7 +210,7 @@ _get_recordset_id() {
_zoneid=$3 _zoneid=$3
export _H1="X-Auth-Token: ${_token}" export _H1="X-Auth-Token: ${_token}"
response=$(_get "${dns_api}/v2/zones/${_zoneid}/recordsets?name=${_domain}") response=$(_get "${dns_api}/v2/zones/${_zoneid}/recordsets?name=${_domain}&status=ACTIVE")
if _contains "${response}" '"id"'; then if _contains "${response}" '"id"'; then
_id="$(echo "${response}" | _egrep_o "\"id\": *\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | tr -d " ")" _id="$(echo "${response}" | _egrep_o "\"id\": *\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | tr -d " ")"
printf "%s" "${_id}" printf "%s" "${_id}"
@ -221,7 +227,7 @@ _add_record() {
# Get Existing Records # Get Existing Records
export _H1="X-Auth-Token: ${_token}" export _H1="X-Auth-Token: ${_token}"
response=$(_get "${dns_api}/v2/zones/${zoneid}/recordsets?name=${_domain}") response=$(_get "${dns_api}/v2/zones/${zoneid}/recordsets?name=${_domain}&status=ACTIVE")
_debug2 "${response}" _debug2 "${response}"
_exist_record=$(echo "${response}" | _egrep_o '"records":[^]]*' | sed 's/\"records\"\:\[//g') _exist_record=$(echo "${response}" | _egrep_o '"records":[^]]*' | sed 's/\"records\"\:\[//g')

View File

@ -1,8 +1,14 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
## Infoblox API integration by Jason Keller and Elijah Tenai dns_infoblox_info='Infoblox.com
## Site: Infoblox.com
## Report any bugs via https://github.com/jasonkeller/acme.sh Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_infoblox
Options:
Infoblox_Creds Credentials. E.g. "username:password"
Infoblox_Server Server hostname. IP or FQDN of infoblox appliance
Issues: github.com/jasonkeller/acme.sh
Author: Jason Keller, Elijah Tenai
'
dns_infoblox_add() { dns_infoblox_add() {

View File

@ -1,19 +1,20 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
dns_infomaniak_info='Infomaniak.com
Site: Infomaniak.com
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_infomaniak
Options:
INFOMANIAK_API_TOKEN API Token
Issues: github.com/acmesh-official/acme.sh/issues/3188
'
###############################################################################
# Infomaniak API integration
#
# To use this API you need visit the API dashboard of your account # To use this API you need visit the API dashboard of your account
# once logged into https://manager.infomaniak.com add /api/dashboard to the URL # once logged into https://manager.infomaniak.com add /api/dashboard to the URL
# #
# Please report bugs to
# https://github.com/acmesh-official/acme.sh/issues/3188
#
# Note: the URL looks like this: # Note: the URL looks like this:
# https://manager.infomaniak.com/v3/<account_id>/api/dashboard # https://manager.infomaniak.com/v3/<account_id>/api/dashboard
# Then generate a token with the scope Domain # Then generate a token with the scope Domain
# this is given as an environment variable INFOMANIAK_API_TOKEN # this is given as an environment variable INFOMANIAK_API_TOKEN
###############################################################################
# base variables # base variables

View File

@ -1,12 +1,14 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
#This is the Internet.BS api wrapper for acme.sh dns_internetbs_info='InternetBS.net
# Site: InternetBS.net
#Author: <alexey@nelexa.ru> Ne-Lexa Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_internetbs
#Report Bugs here: https://github.com/Ne-Lexa/acme.sh Options:
INTERNETBS_API_KEY API Key
#INTERNETBS_API_KEY="sdfsdfsdfljlbjkljlkjsdfoiwje" INTERNETBS_API_PASSWORD API Password
#INTERNETBS_API_PASSWORD="sdfsdfsdfljlbjkljlkjsdfoiwje" Issues: github.com/acmesh-official/acme.sh/issues/2261
Author: Ne-Lexa <alexey@nelexa.ru>
'
INTERNETBS_API_URL="https://api.internet.bs" INTERNETBS_API_URL="https://api.internet.bs"
@ -131,7 +133,7 @@ _get_root() {
fi fi
while true; do 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 h "$h"
if [ -z "$h" ]; then if [ -z "$h" ]; then
#not valid #not valid
@ -139,7 +141,7 @@ _get_root() {
fi fi
if _contains "$response" "\"$h\""; then 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} _domain=${h}
return 0 return 0
fi fi

View File

@ -1,10 +1,13 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
dns_inwx_info='INWX.de
Site: INWX.de
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_inwx
Options:
INWX_User Username
INWX_Password Password
'
#
#INWX_User="username"
#
#INWX_Password="password"
#
# Dependencies: # Dependencies:
# ------------- # -------------
# - oathtool (When using 2 Factor Authentication) # - oathtool (When using 2 Factor Authentication)
@ -160,6 +163,15 @@ _inwx_check_cookie() {
return 1 return 1
} }
_htmlEscape() {
_s="$1"
_s=$(echo "$_s" | sed "s/&/&amp;/g")
_s=$(echo "$_s" | sed "s/</\&lt;/g")
_s=$(echo "$_s" | sed "s/>/\&gt;/g")
_s=$(echo "$_s" | sed 's/"/\&quot;/g')
printf -- %s "$_s"
}
_inwx_login() { _inwx_login() {
if _inwx_check_cookie; then if _inwx_check_cookie; then
@ -167,6 +179,8 @@ _inwx_login() {
return 0 return 0
fi fi
XML_PASS=$(_htmlEscape "$INWX_Password")
xml_content=$(printf '<?xml version="1.0" encoding="UTF-8"?> xml_content=$(printf '<?xml version="1.0" encoding="UTF-8"?>
<methodCall> <methodCall>
<methodName>account.login</methodName> <methodName>account.login</methodName>
@ -190,7 +204,7 @@ _inwx_login() {
</value> </value>
</param> </param>
</params> </params>
</methodCall>' "$INWX_User" "$INWX_Password") </methodCall>' "$INWX_User" "$XML_PASS")
response="$(_post "$xml_content" "$INWX_Api" "" "POST")" response="$(_post "$xml_content" "$INWX_Api" "" "POST")"
@ -279,7 +293,7 @@ _get_root() {
response="$(_post "$xml_content" "$INWX_Api" "" "POST")" response="$(_post "$xml_content" "$INWX_Api" "" "POST")"
while true; do 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 h "$h"
if [ -z "$h" ]; then if [ -z "$h" ]; then
#not valid #not valid
@ -287,7 +301,7 @@ _get_root() {
fi fi
if _contains "$response" "$h"; then 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" _domain="$h"
return 0 return 0
fi fi

View File

@ -1,14 +1,13 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC2034
# Supports IONOS DNS API v1.0.1 dns_ionos_info='IONOS.de
# Site: IONOS.de
# Usage: Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_ionos
# Export IONOS_PREFIX and IONOS_SECRET before calling acme.sh: Options:
# IONOS_PREFIX Prefix
# $ export IONOS_PREFIX="..." IONOS_SECRET Secret
# $ export IONOS_SECRET="..." Issues: github.com/acmesh-official/acme.sh/issues/3379
# '
# $ acme.sh --issue --dns dns_ionos ...
IONOS_API="https://api.hosting.ionos.com/dns" IONOS_API="https://api.hosting.ionos.com/dns"
IONOS_ROUTE_ZONES="/v1/zones" IONOS_ROUTE_ZONES="/v1/zones"
@ -88,7 +87,7 @@ _get_root() {
_response="$(echo "$_response" | tr -d "\n")" _response="$(echo "$_response" | tr -d "\n")"
while true; do 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 if [ -z "$h" ]; then
return 1 return 1
fi fi
@ -97,7 +96,7 @@ _get_root() {
if [ "$_zone" ]; then 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 '\"') _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 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 _domain=$h
return 0 return 0

Some files were not shown because too many files have changed in this diff Show More