Browse Source

Merge branch 'acmesh-official:master' into master

pull/4757/head
laraveluser 12 months ago
committed by GitHub
parent
commit
a6a1de50c8
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 89
      .github/workflows/DNS.yml
  2. 12
      .github/workflows/DragonFlyBSD.yml
  3. 6
      .github/workflows/FreeBSD.yml
  4. 2
      .github/workflows/Linux.yml
  5. 2
      .github/workflows/MacOS.yml
  6. 8
      .github/workflows/NetBSD.yml
  7. 75
      .github/workflows/Omnios.yml
  8. 6
      .github/workflows/OpenBSD.yml
  9. 4
      .github/workflows/PebbleStrict.yml
  10. 13
      .github/workflows/Solaris.yml
  11. 2
      .github/workflows/Ubuntu.yml
  12. 2
      .github/workflows/Windows.yml
  13. 2
      .github/workflows/dockerhub.yml
  14. 3
      .github/workflows/pr_dns.yml
  15. 2
      .github/workflows/pr_notify.yml
  16. 4
      .github/workflows/shellcheck.yml
  17. 35
      README.md
  18. 53
      acme.sh
  19. 2
      deploy/haproxy.sh
  20. 152
      deploy/panos.sh
  21. 8
      deploy/proxmoxve.sh
  22. 13
      deploy/synology_dsm.sh
  23. 4
      dnsapi/dns_1984hosting.sh
  24. 2
      dnsapi/dns_ali.sh
  25. 180
      dnsapi/dns_artfiles.sh
  26. 2
      dnsapi/dns_aws.sh
  27. 185
      dnsapi/dns_dnsexit.sh
  28. 21
      dnsapi/dns_gandi_livedns.sh
  29. 2
      dnsapi/dns_gcloud.sh
  30. 4
      dnsapi/dns_gcore.sh
  31. 2
      dnsapi/dns_inwx.sh
  32. 38
      dnsapi/dns_pleskxml.sh
  33. 211
      dnsapi/dns_tencent.sh
  34. 17
      dnsapi/dns_variomedia.sh
  35. 105
      dnsapi/dns_west_cn.sh
  36. 52
      notify/mattermost.sh

89
.github/workflows/DNS.yml

@ -65,7 +65,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 +113,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 +164,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 +204,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 +223,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 +255,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,10 +274,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/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
@ -306,7 +306,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,10 +325,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/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: |
@ -358,7 +358,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,14 +377,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/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: |
pkg install -y curl socat
pkg install -y curl socat libnghttp2
usesh: true usesh: true
copyback: false copyback: false
run: | run: |
@ -413,7 +413,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 +433,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 +463,54 @@ 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: |
pkg set-mediator -v -I default@1.1 openssl
export PATH=/usr/gnu/bin:$PATH
if [ "${{ secrets.TokenName1}}" ] ; then
export ${{ secrets.TokenName1}}="${{ secrets.TokenValue1}}"
fi
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

12
.github/workflows/DragonFlyBSD.yml

@ -20,7 +20,6 @@ concurrency:
jobs: jobs:
DragonFlyBSD: DragonFlyBSD:
strategy: strategy:
@ -36,7 +35,7 @@ jobs:
# 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'
copyback: "false"
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 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

6
.github/workflows/FreeBSD.yml

@ -41,7 +41,7 @@ jobs:
# 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: |

2
.github/workflows/Linux.yml

@ -33,7 +33,7 @@ jobs:
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1 TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1
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 .. \

2
.github/workflows/MacOS.yml

@ -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

8
.github/workflows/NetBSD.yml

@ -36,7 +36,7 @@ jobs:
# 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 }}
@ -45,7 +45,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
- 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'
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

@ -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) Pretend Pear X1
- TEST_ACME_Server: "LetsEncrypt.org_test"
CA_ECDSA: ""
CA: ""
CA_EMAIL: ""
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1
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

6
.github/workflows/OpenBSD.yml

@ -41,7 +41,7 @@ jobs:
# 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: |

4
.github/workflows/PebbleStrict.yml

@ -33,7 +33,7 @@ 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
@ -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

13
.github/workflows/Solaris.yml

@ -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:
@ -41,7 +41,7 @@ jobs:
# 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

2
.github/workflows/Ubuntu.yml

@ -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

2
.github/workflows/Windows.yml

@ -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

2
.github/workflows/dockerhub.yml

@ -41,7 +41,7 @@ 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: Set up Docker Buildx - name: Set up Docker Buildx

3
.github/workflows/pr_dns.yml

@ -22,9 +22,10 @@ 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).
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.
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, 都必须确保通过这个测试.
` `
}) })

2
.github/workflows/pr_notify.yml

@ -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 ✨
` `

4
.github/workflows/shellcheck.yml

@ -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

35
README.md

@ -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
|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
|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
|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)
|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
|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
|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
|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
|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
|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
|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
|11|-----| Cloud Linux https://github.com/acmesh-official/acme.sh/issues/111
|22|-----| OpenWRT: Tested and working. See [wiki page](https://github.com/acmesh-official/acme.sh/wiki/How-to-run-on-OpenWRT)
|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)
|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)| 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)|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)|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)|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)|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)|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)|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)|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)|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)|Gentoo Linux
|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|-----| Cloud Linux https://github.com/acmesh-official/acme.sh/issues/111
|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):
@ -506,10 +507,6 @@ Support this project with your organization. Your logo will show up here with a
<a href="https://opencollective.com/acmesh/organization/9/website"><img src="https://opencollective.com/acmesh/organization/9/avatar.svg"></a> <a href="https://opencollective.com/acmesh/organization/9/website"><img src="https://opencollective.com/acmesh/organization/9/avatar.svg"></a>
#### Sponsors
[![quantumca-acmesh-logo](https://user-images.githubusercontent.com/8305679/183255712-634ee1db-bb61-4c03-bca0-bacce99e078c.svg)](https://www.quantumca.com.cn/?__utm_source=acmesh-donation)
# 19. License & Others # 19. License & Others

53
acme.sh

@ -1,6 +1,6 @@
#!/usr/bin/env sh #!/usr/bin/env sh
VER=3.0.7
VER=3.0.8
PROJECT_NAME="acme.sh" PROJECT_NAME="acme.sh"
@ -102,12 +102,12 @@ ECC_SUFFIX="${ECC_SEP}ecc"
LOG_LEVEL_1=1 LOG_LEVEL_1=1
LOG_LEVEL_2=2 LOG_LEVEL_2=2
LOG_LEVEL_3=3 LOG_LEVEL_3=3
DEFAULT_LOG_LEVEL="$LOG_LEVEL_1"
DEFAULT_LOG_LEVEL="$LOG_LEVEL_2"
DEBUG_LEVEL_1=1 DEBUG_LEVEL_1=1
DEBUG_LEVEL_2=2 DEBUG_LEVEL_2=2
DEBUG_LEVEL_3=3 DEBUG_LEVEL_3=3
DEBUG_LEVEL_DEFAULT=$DEBUG_LEVEL_1
DEBUG_LEVEL_DEFAULT=$DEBUG_LEVEL_2
DEBUG_LEVEL_NONE=0 DEBUG_LEVEL_NONE=0
DOH_CLOUDFLARE=1 DOH_CLOUDFLARE=1
@ -931,7 +931,7 @@ fi
_egrep_o() { _egrep_o() {
if [ "$__USE_EGREP" ]; then if [ "$__USE_EGREP" ]; then
egrep -o "$1"
egrep -o -- "$1" 2>/dev/null
else else
sed -n 's/.*\('"$1"'\).*/\1/p' sed -n 's/.*\('"$1"'\).*/\1/p'
fi fi
@ -1561,7 +1561,7 @@ createDomainKey() {
createCSR() { createCSR() {
_info "Creating csr" _info "Creating csr"
if [ -z "$1" ]; then if [ -z "$1" ]; then
_usage "Usage: $PROJECT_ENTRY --create-csr --domain <domain.tld> [--domain <domain2.tld> ...]"
_usage "Usage: $PROJECT_ENTRY --create-csr --domain <domain.tld> [--domain <domain2.tld> ...] [--ecc]"
return return
fi fi
@ -1795,6 +1795,10 @@ _date2time() {
if date -u -j -f "%Y-%m-%d %H:%M:%S" "$(echo "$1" | tr -d "Z" | tr "T" ' ')" +"%s" 2>/dev/null; then if date -u -j -f "%Y-%m-%d %H:%M:%S" "$(echo "$1" | tr -d "Z" | tr "T" ' ')" +"%s" 2>/dev/null; then
return return
fi fi
#Omnios
if da="$(echo "$1" | tr -d "Z" | tr "T" ' ')" perl -MTime::Piece -e 'print Time::Piece->strptime($ENV{da}, "%Y-%m-%d %H:%M:%S")->epoch, "\n";' 2>/dev/null; then
return
fi
_err "Can not parse _date2time $1" _err "Can not parse _date2time $1"
return 1 return 1
} }
@ -2118,12 +2122,7 @@ _tail_n() {
} }
_tail_c() { _tail_c() {
if _is_solaris; then
#fix for solaris
tail -"$1"c
else
tail -c "$1"
fi
tail -c "$1" 2>/dev/null || tail -"$1"c
} }
# url payload needbase64 keyfile # url payload needbase64 keyfile
@ -3130,7 +3129,7 @@ _setNginx() {
_err "nginx command is not found." _err "nginx command is not found."
return 1 return 1
fi fi
NGINX_CONF="$(nginx -V 2>&1 | _egrep_o "--conf-path=[^ ]* " | tr -d " ")"
NGINX_CONF="$(nginx -V 2>&1 | _egrep_o "\-\-conf-path=[^ ]* " | tr -d " ")"
_debug NGINX_CONF "$NGINX_CONF" _debug NGINX_CONF "$NGINX_CONF"
NGINX_CONF="$(echo "$NGINX_CONF" | cut -d = -f 2)" NGINX_CONF="$(echo "$NGINX_CONF" | cut -d = -f 2)"
_debug NGINX_CONF "$NGINX_CONF" _debug NGINX_CONF "$NGINX_CONF"
@ -5015,9 +5014,9 @@ $_authorizations_map"
errordetail="$(echo "$error" | _egrep_o '"detail": *"[^"]*' | cut -d '"' -f 4)" errordetail="$(echo "$error" | _egrep_o '"detail": *"[^"]*' | cut -d '"' -f 4)"
_debug2 errordetail "$errordetail" _debug2 errordetail "$errordetail"
if [ "$errordetail" ]; then if [ "$errordetail" ]; then
_err "$d:Verify error:$errordetail"
_err "Invalid status, $d:Verify error detail:$errordetail"
else else
_err "$d:Verify error:$error"
_err "Invalid status, $d:Verify error:$error"
fi fi
if [ "$DEBUG" ]; then if [ "$DEBUG" ]; then
if [ "$vtype" = "$VTYPE_HTTP" ]; then if [ "$vtype" = "$VTYPE_HTTP" ]; then
@ -5044,7 +5043,7 @@ $_authorizations_map"
elif _contains "$status" "processing"; then elif _contains "$status" "processing"; then
_info "Processing, The CA is processing your order, please just wait. ($waittimes/$MAX_RETRY_TIMES)" _info "Processing, The CA is processing your order, please just wait. ($waittimes/$MAX_RETRY_TIMES)"
else else
_err "$d:Verify error:$response"
_err "Unknown status: $status, $d:Verify error:$response"
_clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
_clearup _clearup
_on_issue_err "$_post_hook" "$vlist" _on_issue_err "$_post_hook" "$vlist"
@ -5057,7 +5056,7 @@ $_authorizations_map"
_send_signed_request "$_authz_url" _send_signed_request "$_authz_url"
if [ "$?" != "0" ]; then if [ "$?" != "0" ]; then
_err "$d:Verify error:$response"
_err "Invalid code, $d:Verify error:$response"
_clearupwebbroot "$_currentRoot" "$removelevel" "$token" _clearupwebbroot "$_currentRoot" "$removelevel" "$token"
_clearup _clearup
_on_issue_err "$_post_hook" "$vlist" _on_issue_err "$_post_hook" "$vlist"
@ -5993,6 +5992,7 @@ installcronjob() {
fi fi
_t=$(_time) _t=$(_time)
random_minute=$(_math $_t % 60) random_minute=$(_math $_t % 60)
random_hour=$(_math $_t / 60 % 24)
if ! _exists "$_CRONTAB" && _exists "fcrontab"; then if ! _exists "$_CRONTAB" && _exists "fcrontab"; then
_CRONTAB="fcrontab" _CRONTAB="fcrontab"
@ -6017,16 +6017,14 @@ installcronjob() {
_info "Installing cron job" _info "Installing cron job"
if ! $_CRONTAB -l | grep "$PROJECT_ENTRY --cron"; then if ! $_CRONTAB -l | grep "$PROJECT_ENTRY --cron"; then
if _exists uname && uname -a | grep SunOS >/dev/null; then if _exists uname && uname -a | grep SunOS >/dev/null; then
$_CRONTAB -l | {
cat
echo "$random_minute 0 * * * $lesh --cron --home \"$LE_WORKING_DIR\" $_c_entry> /dev/null"
} | $_CRONTAB --
_CRONTAB_STDIN="$_CRONTAB --"
else else
_CRONTAB_STDIN="$_CRONTAB -"
fi
$_CRONTAB -l | { $_CRONTAB -l | {
cat cat
echo "$random_minute 0 * * * $lesh --cron --home \"$LE_WORKING_DIR\" $_c_entry> /dev/null"
} | $_CRONTAB -
fi
echo "$random_minute $random_hour * * * $lesh --cron --home \"$LE_WORKING_DIR\" $_c_entry> /dev/null"
} | $_CRONTAB_STDIN
fi fi
if [ "$?" != "0" ]; then if [ "$?" != "0" ]; then
_err "Install cron job failed. You need to manually renew your certs." _err "Install cron job failed. You need to manually renew your certs."
@ -6899,7 +6897,7 @@ Parameters:
-f, --force Force install, force cert renewal or override sudo restrictions. -f, --force Force install, force cert renewal or override sudo restrictions.
--staging, --test Use staging server, for testing. --staging, --test Use staging server, for testing.
--debug [0|1|2|3] Output debug info. Defaults to 1 if argument is omitted.
--debug [0|1|2|3] Output debug info. Defaults to $DEBUG_LEVEL_DEFAULT if argument is omitted.
--output-insecure Output all the sensitive messages. --output-insecure Output all the sensitive messages.
By default all the credentials/sensitive messages are hidden from the output/debug/log for security. By default all the credentials/sensitive messages are hidden from the output/debug/log for security.
-w, --webroot <directory> Specifies the web root folder for web root mode. -w, --webroot <directory> Specifies the web root folder for web root mode.
@ -6917,7 +6915,7 @@ Parameters:
-k, --keylength <bits> Specifies the domain key length: 2048, 3072, 4096, 8192 or ec-256, ec-384, ec-521. -k, --keylength <bits> Specifies the domain key length: 2048, 3072, 4096, 8192 or ec-256, ec-384, ec-521.
-ak, --accountkeylength <bits> Specifies the account key length: 2048, 3072, 4096 -ak, --accountkeylength <bits> Specifies the account key length: 2048, 3072, 4096
--log [file] Specifies the log file. Defaults to \"$DEFAULT_LOG_FILE\" if argument is omitted. --log [file] Specifies the log file. Defaults to \"$DEFAULT_LOG_FILE\" if argument is omitted.
--log-level <1|2> Specifies the log level, default is 1.
--log-level <1|2> Specifies the log level, default is $DEFAULT_LOG_LEVEL.
--syslog <0|3|6|7> Syslog level, 0: disable syslog, 3: error, 6: info, 7: debug. --syslog <0|3|6|7> Syslog level, 0: disable syslog, 3: error, 6: info, 7: debug.
--eab-kid <eab_key_id> Key Identifier for External Account Binding. --eab-kid <eab_key_id> Key Identifier for External Account Binding.
--eab-hmac-key <eab_hmac_key> HMAC key for External Account Binding. --eab-hmac-key <eab_hmac_key> HMAC key for External Account Binding.
@ -6925,7 +6923,7 @@ Parameters:
These parameters are to install the cert to nginx/apache or any other server after issue/renew a cert: These parameters are to install the cert to nginx/apache or any other server after issue/renew a cert:
--cert-file <file> Path to copy the cert file to after issue/renew..
--cert-file <file> Path to copy the cert file to after issue/renew.
--key-file <file> Path to copy the key file to after issue/renew. --key-file <file> Path to copy the key file to after issue/renew.
--ca-file <file> Path to copy the intermediate cert file to after issue/renew. --ca-file <file> Path to copy the intermediate cert file to after issue/renew.
--fullchain-file <file> Path to copy the fullchain cert file to after issue/renew. --fullchain-file <file> Path to copy the fullchain cert file to after issue/renew.
@ -6955,7 +6953,8 @@ Parameters:
--no-profile Only valid for '--install' command, which means: do not install aliases to user profile. --no-profile Only valid for '--install' command, which means: do not install aliases to user profile.
--no-color Do not output color text. --no-color Do not output color text.
--force-color Force output of color text. Useful for non-interactive use with the aha tool for HTML E-Mails. --force-color Force output of color text. Useful for non-interactive use with the aha tool for HTML E-Mails.
--ecc Specifies to use the ECC cert. Valid for '--install-cert', '--renew', '--revoke', '--to-pkcs12' and '--create-csr'
--ecc Specifies use of the ECC cert. Only valid for '--install-cert', '--renew', '--remove ', '--revoke',
'--deploy', '--to-pkcs8', '--to-pkcs12' and '--create-csr'.
--csr <file> Specifies the input csr. --csr <file> Specifies the input csr.
--pre-hook <command> Command to be run before obtaining any certificates. --pre-hook <command> Command to be run before obtaining any certificates.
--post-hook <command> Command to be run after attempting to obtain/renew certificates. Runs regardless of whether obtain/renew succeeded or failed. --post-hook <command> Command to be run after attempting to obtain/renew certificates. Runs regardless of whether obtain/renew succeeded or failed.

2
deploy/haproxy.sh

@ -147,7 +147,7 @@ haproxy_deploy() {
# 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}" >"${_temppem}"
_ret="$?" _ret="$?"
# Check that we could create the temporary file # Check that we could create the temporary file

152
deploy/panos.sh

@ -7,11 +7,15 @@
# #
# Firewall admin with superuser and IP address is required. # Firewall admin with superuser and IP address is required.
# #
# export PANOS_USER="" # required
# export PANOS_PASS="" # required
# export PANOS_HOST="" # required
# REQURED:
# export PANOS_HOST=""
# export PANOS_USER="" #User *MUST* have Commit and Import Permissions in XML API for Admin Role
# export PANOS_PASS=""
#
# The script will automatically generate a new API key if
# no key is found, or if a saved key has expired or is invalid.
# This function is to parse the XML
# This function is to parse the XML response from the firewall
parse_response() { parse_response() {
type=$2 type=$2
if [ "$type" = 'keygen' ]; then if [ "$type" = 'keygen' ]; then
@ -23,25 +27,46 @@ parse_response() {
message="PAN-OS Key could not be set." message="PAN-OS Key could not be set."
fi fi
else else
status=$(echo "$1" | sed 's/^.*"\([a-z]*\)".*/\1/g')
message=$(echo "$1" | sed 's/^.*<result>\(.*\)<\/result.*/\1/g')
status=$(echo "$1" | tr -d '\n' | sed 's/^.*"\([a-z]*\)".*/\1/g')
message=$(echo "$1" | tr -d '\n' | sed 's/.*\(<result>\|<msg>\|<line>\)\([^<]*\).*/\2/g')
_debug "Firewall message: $message"
if [ "$type" = 'keytest' ] && [ "$status" != "success" ]; then
_debug "**** API Key has EXPIRED or is INVALID ****"
unset _panos_key
fi
fi fi
return 0 return 0
} }
#This function is used to deploy to the firewall
deployer() { deployer() {
content="" content=""
type=$1 # Types are keygen, cert, key, commit
_debug "**** Deploying $type *****"
type=$1 # Types are keytest, keygen, cert, key, commit
panos_url="https://$_panos_host/api/" panos_url="https://$_panos_host/api/"
#Test API Key by performing a lookup
if [ "$type" = 'keytest' ]; then
_debug "**** Testing saved API Key ****"
_H1="Content-Type: application/x-www-form-urlencoded"
# Get Version Info to test key
content="type=version&key=$_panos_key"
## Exclude all scopes for the empty commit
#_exclude_scope="<policy-and-objects>exclude</policy-and-objects><device-and-network>exclude</device-and-network><shared-object>exclude</shared-object>"
#content="type=commit&action=partial&key=$_panos_key&cmd=<commit><partial>$_exclude_scope<admin><member>acmekeytest</member></admin></partial></commit>"
fi
# Generate API Key
if [ "$type" = 'keygen' ]; then if [ "$type" = 'keygen' ]; then
_debug "**** Generating new API Key ****"
_H1="Content-Type: application/x-www-form-urlencoded" _H1="Content-Type: application/x-www-form-urlencoded"
content="type=keygen&user=$_panos_user&password=$_panos_pass" content="type=keygen&user=$_panos_user&password=$_panos_pass"
# content="$content${nl}--$delim${nl}Content-Disposition: form-data; type=\"keygen\"; user=\"$_panos_user\"; password=\"$_panos_pass\"${nl}Content-Type: application/octet-stream${nl}${nl}" # content="$content${nl}--$delim${nl}Content-Disposition: form-data; type=\"keygen\"; user=\"$_panos_user\"; password=\"$_panos_pass\"${nl}Content-Type: application/octet-stream${nl}${nl}"
fi fi
# Deploy Cert or Key
if [ "$type" = 'cert' ] || [ "$type" = 'key' ]; then if [ "$type" = 'cert' ] || [ "$type" = 'key' ]; then
#Generate DEIM
_debug "**** Deploying $type ****"
#Generate DELIM
delim="-----MultipartDelimiter$(date "+%s%N")" delim="-----MultipartDelimiter$(date "+%s%N")"
nl="\015\012" nl="\015\012"
#Set Header #Set Header
@ -61,7 +86,7 @@ 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=\"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 "$_ckey")\"${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")"
fi fi
#Close multipart #Close multipart
content="$content${nl}--$delim--${nl}${nl}" content="$content${nl}--$delim--${nl}${nl}"
@ -69,16 +94,25 @@ deployer() {
content=$(printf %b "$content") content=$(printf %b "$content")
fi fi
# Commit changes
if [ "$type" = 'commit' ]; then if [ "$type" = 'commit' ]; then
_debug "**** Committing changes ****"
export _H1="Content-Type: application/x-www-form-urlencoded" export _H1="Content-Type: application/x-www-form-urlencoded"
cmd=$(printf "%s" "<commit><partial><$_panos_user></$_panos_user></partial></commit>" | _url_encode)
content="type=commit&key=$_panos_key&cmd=$cmd"
#Check for force commit - will commit ALL uncommited changes to the firewall. Use with caution!
if [ "$FORCE" ]; then
_debug "Force switch detected. Committing ALL changes to the firewall."
cmd=$(printf "%s" "<commit><partial><force><admin><member>$_panos_user</member></admin></force></partial></commit>" | _url_encode)
else
_exclude_scope="<policy-and-objects>exclude</policy-and-objects><device-and-network>exclude</device-and-network>"
cmd=$(printf "%s" "<commit><partial>$_exclude_scope<admin><member>$_panos_user</member></admin></partial></commit>" | _url_encode)
fi
content="type=commit&action=partial&key=$_panos_key&cmd=$cmd"
fi fi
response=$(_post "$content" "$panos_url" "" "POST") response=$(_post "$content" "$panos_url" "" "POST")
parse_response "$response" "$type" parse_response "$response" "$type"
# Saving response to variables # Saving response to variables
response_status=$status response_status=$status
#DEBUG
_debug response_status "$response_status" _debug response_status "$response_status"
if [ "$response_status" = "success" ]; then if [ "$response_status" = "success" ]; then
_debug "Successfully deployed $type" _debug "Successfully deployed $type"
@ -92,43 +126,85 @@ deployer() {
# This is the main function that will call the other functions to deploy everything. # This is the main function that will call the other functions to deploy everything.
panos_deploy() { panos_deploy() {
_cdomain="$1"
_cdomain=$(echo "$1" | sed 's/*/WILDCARD_/g') #Wildcard Safe Filename
_ckey="$2" _ckey="$2"
_cfullchain="$5" _cfullchain="$5"
# PANOS ENV VAR check
if [ -z "$PANOS_USER" ] || [ -z "$PANOS_PASS" ] || [ -z "$PANOS_HOST" ]; then
_debug "No ENV variables found lets check for saved variables"
_getdeployconf PANOS_USER
_getdeployconf PANOS_PASS
_getdeployconf PANOS_HOST
_panos_user=$PANOS_USER
_panos_pass=$PANOS_PASS
_panos_host=$PANOS_HOST
if [ -z "$_panos_user" ] && [ -z "$_panos_pass" ] && [ -z "$_panos_host" ]; then
_err "No host, user and pass found.. If this is the first time deploying please set PANOS_HOST, PANOS_USER and PANOS_PASS in environment variables. Delete them after you have succesfully deployed certs."
# VALID FILE CHECK
if [ ! -f "$_ckey" ] || [ ! -f "$_cfullchain" ]; then
_err "Unable to find a valid key and/or cert. If this is an ECDSA/ECC cert, use the --ecc flag when deploying."
return 1 return 1
else
_debug "Using saved env variables."
fi fi
# PANOS_HOST
if [ "$PANOS_HOST" ]; then
_debug "Detected ENV variable PANOS_HOST. Saving to file."
_savedeployconf PANOS_HOST "$PANOS_HOST" 1
else else
_debug "Detected ENV variables to be saved to the deploy conf."
# Encrypt and save user
_debug "Attempting to load variable PANOS_HOST from file."
_getdeployconf PANOS_HOST
fi
# PANOS USER
if [ "$PANOS_USER" ]; then
_debug "Detected ENV variable PANOS_USER. Saving to file."
_savedeployconf PANOS_USER "$PANOS_USER" 1 _savedeployconf PANOS_USER "$PANOS_USER" 1
else
_debug "Attempting to load variable PANOS_USER from file."
_getdeployconf PANOS_USER
fi
# PANOS_PASS
if [ "$PANOS_PASS" ]; then
_debug "Detected ENV variable PANOS_PASS. Saving to file."
_savedeployconf PANOS_PASS "$PANOS_PASS" 1 _savedeployconf PANOS_PASS "$PANOS_PASS" 1
_savedeployconf PANOS_HOST "$PANOS_HOST" 1
_panos_user="$PANOS_USER"
_panos_pass="$PANOS_PASS"
_panos_host="$PANOS_HOST"
else
_debug "Attempting to load variable PANOS_PASS from file."
_getdeployconf PANOS_PASS
fi
# PANOS_KEY
_getdeployconf PANOS_KEY
if [ "$PANOS_KEY" ]; then
_debug "Detected saved key."
_panos_key=$PANOS_KEY
else
_debug "No key detected"
unset _panos_key
fi
#Store variables
_panos_host=$PANOS_HOST
_panos_user=$PANOS_USER
_panos_pass=$PANOS_PASS
#Test API Key if found. If the key is invalid, the variable _panos_key will be unset.
if [ "$_panos_host" ] && [ "$_panos_key" ]; then
_debug "**** Testing API KEY ****"
deployer keytest
fi fi
_debug "Let's use username and pass to generate token."
if [ -z "$_panos_user" ] || [ -z "$_panos_pass" ] || [ -z "$_panos_host" ]; then
_err "Please pass username and password and host as env variables PANOS_USER, PANOS_PASS and PANOS_HOST"
# Check for valid variables
if [ -z "$_panos_host" ]; then
_err "No host found. If this is your first time deploying, please set PANOS_HOST in ENV variables. You can delete it after you have successfully deployed the certs."
return 1
elif [ -z "$_panos_user" ]; then
_err "No user found. If this is your first time deploying, please set PANOS_USER in ENV variables. You can delete it after you have successfully deployed the certs."
return 1
elif [ -z "$_panos_pass" ]; then
_err "No password found. If this is your first time deploying, please set PANOS_PASS in ENV variables. You can delete it after you have successfully deployed the certs."
return 1 return 1
else else
_debug "Getting PANOS KEY"
# Generate a new API key if no valid API key is found
if [ -z "$_panos_key" ]; then
_debug "**** Generating new PANOS API KEY ****"
deployer keygen deployer keygen
_savedeployconf PANOS_KEY "$_panos_key" 1
fi
# Confirm that a valid key was generated
if [ -z "$_panos_key" ]; then if [ -z "$_panos_key" ]; then
_err "Missing apikey."
_err "Unable to generate an API key. The user and pass may be invalid or not authorized to generate a new key. Please check the PANOS_USER and PANOS_PASS credentials and try again"
return 1 return 1
else else
deployer cert deployer cert

8
deploy/proxmoxve.sh

@ -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.
export _HTTPS_INSECURE=1
_info "Push certificates to server"
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"

13
deploy/synology_dsm.sh

@ -91,8 +91,10 @@ synology_dsm_deploy() {
_debug "Getting API version" _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_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')
_debug3 response "$response" _debug3 response "$response"
_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 & SynoToken from JSON
@ -133,12 +135,15 @@ synology_dsm_deploy() {
[ -n "${SYNO_Device_Name}" ] || SYNO_Device_Name="CertRenewal" [ -n "${SYNO_Device_Name}" ] || SYNO_Device_Name="CertRenewal"
fi fi
response=$(_get "$_base_url/webapi/entry.cgi?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")
_debug3 response "$response"
SYNO_Device_ID=$(echo "$response" | grep "device_id" | sed -n 's/.*"device_id" *: *"\([^"]*\).*/\1/p')
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")
_secure_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" _secure_debug2 SYNO_Device_ID "$SYNO_Device_ID"
else else
response=$(_get "$_base_url/webapi/entry.cgi?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")
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" _debug3 response "$response"
fi fi

4
dnsapi/dns_1984hosting.sh

@ -128,7 +128,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 +185,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

2
dnsapi/dns_ali.sh

@ -117,7 +117,7 @@ _ali_urlencode() {
_ali_nonce() { _ali_nonce() {
#_head_n 1 </dev/urandom | _digest "sha256" hex | cut -c 1-31 #_head_n 1 </dev/urandom | _digest "sha256" hex | cut -c 1-31
#Not so good... #Not so good...
date +"%s%N"
date +"%s%N" | sed 's/%N//g'
} }
_check_exist_query() { _check_exist_query() {

180
dnsapi/dns_artfiles.sh

@ -0,0 +1,180 @@
#!/usr/bin/env sh
################################################################################
# ACME.sh 3rd party DNS API plugin for ArtFiles.de
################################################################################
# Author: Martin Arndt, https://troublezone.net/
# Released: 2022-02-27
# Issues: https://github.com/acmesh-official/acme.sh/issues/4718
################################################################################
# Usage:
# 1. export AF_API_USERNAME='api12345678'
# 2. export AF_API_PASSWORD='apiPassword'
# 3. acme.sh --issue -d example.com --dns dns_artfiles
################################################################################
########## API configuration ###################################################
AF_API_SUCCESS='status":"OK'
AF_URL_DCP='https://dcp.c.artfiles.de/api/'
AF_URL_DNS=${AF_URL_DCP}'dns/{*}_dns.html?domain='
AF_URL_DOMAINS=${AF_URL_DCP}'domain/get_domains.html'
########## Public functions ####################################################
# Adds a new TXT record for given ACME challenge value & domain.
# Usage: dns_artfiles_add _acme-challenge.www.example.com "ACME challenge value"
dns_artfiles_add() {
domain="$1"
txtValue="$2"
_info 'Using ArtFiles.de DNS addition API…'
_debug 'Domain' "$domain"
_debug 'txtValue' "$txtValue"
_set_credentials
_saveaccountconf_mutable 'AF_API_USERNAME' "$AF_API_USERNAME"
_saveaccountconf_mutable 'AF_API_PASSWORD' "$AF_API_PASSWORD"
_set_headers
_get_zone "$domain"
_dns 'GET'
if ! _contains "$response" 'TXT'; then
_err 'Retrieving TXT records failed.'
return 1
fi
_clean_records
_dns 'SET' "$(printf -- '%s\n_acme-challenge "%s"' "$response" "$txtValue")"
if ! _contains "$response" "$AF_API_SUCCESS"; then
_err 'Adding ACME challenge value failed.'
return 1
fi
}
# Removes the existing TXT record for given ACME challenge value & domain.
# Usage: dns_artfiles_rm _acme-challenge.www.example.com "ACME challenge value"
dns_artfiles_rm() {
domain="$1"
txtValue="$2"
_info 'Using ArtFiles.de DNS removal API…'
_debug 'Domain' "$domain"
_debug 'txtValue' "$txtValue"
_set_credentials
_set_headers
_get_zone "$domain"
if ! _dns 'GET'; then
return 1
fi
if ! _contains "$response" "$txtValue"; then
_err 'Retrieved TXT records are missing given ACME challenge value.'
return 1
fi
_clean_records
response="$(printf -- '%s' "$response" | sed '/_acme-challenge "'"$txtValue"'"/d')"
_dns 'SET' "$response"
if ! _contains "$response" "$AF_API_SUCCESS"; then
_err 'Removing ACME challenge value failed.'
return 1
fi
}
########## Private functions ###################################################
# Cleans awful TXT records response of ArtFiles's API & pretty prints it.
# Usage: _clean_records
_clean_records() {
_info 'Cleaning TXT records…'
# Extract TXT part, strip trailing quote sign (ACME.sh API guidelines forbid
# usage of SED's GNU extensions, hence couldn't omit it via regex), strip '\'
# from '\"' & turn '\n' into real LF characters.
# Yup, awful API to use - but that's all we got to get this working, so… ;)
_debug2 'Raw ' "$response"
response="$(printf -- '%s' "$response" | sed 's/^.*TXT":"\([^}]*\).*$/\1/;s/,".*$//;s/.$//;s/\\"/"/g;s/\\n/\n/g')"
_debug2 'Clean' "$response"
}
# Executes an HTTP GET or POST request for getting or setting DNS records,
# containing given payload upon POST.
# Usage: _dns [GET | SET] [payload]
_dns() {
_info 'Executing HTTP request…'
action="$1"
payload="$(printf -- '%s' "$2" | _url_encode)"
url="$(printf -- '%s%s' "$AF_URL_DNS" "$domain" | sed 's/{\*}/'"$(printf -- '%s' "$action" | _lower_case)"'/')"
if [ "$action" = 'SET' ]; then
_debug2 'Payload' "$payload"
response="$(_post '' "$url&TXT=$payload" '' 'POST' 'application/x-www-form-urlencoded')"
else
response="$(_get "$url" '' 10)"
fi
if ! _contains "$response" "$AF_API_SUCCESS"; then
_err "DNS API error: $response"
return 1
fi
_debug 'Response' "$response"
return 0
}
# Gets the root domain zone for given domain.
# Usage: _get_zone _acme-challenge.www.example.com
_get_zone() {
fqdn="$1"
domains="$(_get "$AF_URL_DOMAINS" '' 10)"
_info 'Getting domain zone…'
_debug2 'FQDN' "$fqdn"
_debug2 'Domains' "$domains"
while _contains "$fqdn" "."; do
if _contains "$domains" "$fqdn"; then
domain="$fqdn"
_info "Found root domain zone: $domain"
break
else
fqdn="${fqdn#*.}"
_debug2 'FQDN' "$fqdn"
fi
done
if [ "$domain" = "$fqdn" ]; then
return 0
fi
_err 'Couldn'\''t find root domain zone.'
return 1
}
# Sets the credentials for accessing ArtFiles's API
# Usage: _set_credentials
_set_credentials() {
_info 'Setting credentials…'
AF_API_USERNAME="${AF_API_USERNAME:-$(_readaccountconf_mutable AF_API_USERNAME)}"
AF_API_PASSWORD="${AF_API_PASSWORD:-$(_readaccountconf_mutable AF_API_PASSWORD)}"
if [ -z "$AF_API_USERNAME" ] || [ -z "$AF_API_PASSWORD" ]; then
_err 'Missing ArtFiles.de username and/or password.'
_err 'Please ensure both are set via export command & try again.'
return 1
fi
}
# Adds the HTTP Authorization & Content-Type headers to a follow-up request.
# Usage: _set_headers
_set_headers() {
_info 'Setting headers…'
encoded="$(printf -- '%s:%s' "$AF_API_USERNAME" "$AF_API_PASSWORD" | _base64)"
export _H1="Authorization: Basic $encoded"
export _H2='Content-Type: application/json'
}

2
dnsapi/dns_aws.sh

@ -157,7 +157,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"

185
dnsapi/dns_dnsexit.sh

@ -0,0 +1,185 @@
#!/usr/bin/env sh
#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_HOSTS_URL="https://update.dnsexit.com/ipupdate/hosts.jsp"
######## Public functions #####################
#Usage: dns_dnsexit_add _acme-challenge.*.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_dnsexit_add() {
fulldomain=$1
txtvalue=$2
_info "Using DNSExit.com"
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
_debug 'Load account auth'
if ! get_account_info; then
return 1
fi
_debug 'First detect the root zone'
if ! _get_root "$fulldomain"; then
return 1
fi
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
if ! _dnsexit_rest "{\"domain\":\"$_domain\",\"add\":{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"content\":\"$txtvalue\",\"ttl\":0,\"overwrite\":false}}"; then
_err "$response"
return 1
fi
_debug2 _response "$response"
return 0
}
#Usage: fulldomain txtvalue
#Remove the txt record after validation.
dns_dnsexit_rm() {
fulldomain=$1
txtvalue=$2
_info "Using DNSExit.com"
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
_debug 'Load account auth'
if ! get_account_info; then
return 1
fi
_debug 'First detect the root zone'
if ! _get_root "$fulldomain"; then
_err "$response"
return 1
fi
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
if ! _dnsexit_rest "{\"domain\":\"$_domain\",\"delete\":{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"content\":\"$txtvalue\"}}"; then
_err "$response"
return 1
fi
_debug2 _response "$response"
return 0
}
#################### Private functions below ##################################
#_acme-challenge.www.domain.com
#returns
# _sub_domain=_acme-challenge.www
# _domain=domain.com
_get_root() {
domain=$1
i=1
while true; do
_domain=$(printf "%s" "$domain" | cut -d . -f $i-100)
_debug h "$_domain"
if [ -z "$_domain" ]; then
return 1
fi
_debug login "$DNSEXIT_AUTH_USER"
_debug password "$DNSEXIT_AUTH_PASS"
_debug domain "$_domain"
_dnsexit_http "login=$DNSEXIT_AUTH_USER&password=$DNSEXIT_AUTH_PASS&domain=$_domain"
if _contains "$response" "0=$_domain"; then
_sub_domain="$(echo "$fulldomain" | sed "s/\\.$_domain\$//")"
return 0
else
_debug "Go to next level of $_domain"
fi
i=$(_math "$i" + 1)
done
return 1
}
_dnsexit_rest() {
m=POST
ep=""
data="$1"
_debug _dnsexit_rest "$ep"
_debug data "$data"
api_key_trimmed=$(echo "$DNSEXIT_API_KEY" | tr -d '"')
export _H1="apikey: $api_key_trimmed"
export _H2='Content-Type: application/json'
if [ "$m" != "GET" ]; then
_debug data "$data"
response="$(_post "$data" "$DNSEXIT_API_URL/$ep" "" "$m")"
else
response="$(_get "$DNSEXIT_API_URL/$ep")"
fi
if [ "$?" != "0" ]; then
_err "Error $ep"
return 1
fi
_debug2 response "$response"
return 0
}
_dnsexit_http() {
m=GET
param="$1"
_debug param "$param"
_debug get "$DNSEXIT_HOSTS_URL?$param"
response="$(_get "$DNSEXIT_HOSTS_URL?$param")"
_debug response "$response"
if [ "$?" != "0" ]; then
_err "Error $param"
return 1
fi
_debug2 response "$response"
return 0
}
get_account_info() {
DNSEXIT_API_KEY="${DNSEXIT_API_KEY:-$(_readaccountconf_mutable DNSEXIT_API_KEY)}"
if test -z "$DNSEXIT_API_KEY"; then
DNSEXIT_API_KEY=''
_err 'DNSEXIT_API_KEY was not exported'
return 1
fi
_saveaccountconf_mutable DNSEXIT_API_KEY "$DNSEXIT_API_KEY"
DNSEXIT_AUTH_USER="${DNSEXIT_AUTH_USER:-$(_readaccountconf_mutable DNSEXIT_AUTH_USER)}"
if test -z "$DNSEXIT_AUTH_USER"; then
DNSEXIT_AUTH_USER=""
_err 'DNSEXIT_AUTH_USER was not exported'
return 1
fi
_saveaccountconf_mutable DNSEXIT_AUTH_USER "$DNSEXIT_AUTH_USER"
DNSEXIT_AUTH_PASS="${DNSEXIT_AUTH_PASS:-$(_readaccountconf_mutable DNSEXIT_AUTH_PASS)}"
if test -z "$DNSEXIT_AUTH_PASS"; then
DNSEXIT_AUTH_PASS=""
_err 'DNSEXIT_AUTH_PASS was not exported'
return 1
fi
_saveaccountconf_mutable DNSEXIT_AUTH_PASS "$DNSEXIT_AUTH_PASS"
return 0
}

21
dnsapi/dns_gandi_livedns.sh

@ -1,7 +1,8 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# Gandi LiveDNS v5 API # Gandi LiveDNS v5 API
# https://doc.livedns.gandi.net/
# https://api.gandi.net/docs/livedns/
# 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 # Requires GANDI API KEY set in GANDI_LIVEDNS_KEY set as environment variable
@ -19,13 +20,20 @@ dns_gandi_livedns_add() {
fulldomain=$1 fulldomain=$1
txtvalue=$2 txtvalue=$2
if [ -z "$GANDI_LIVEDNS_KEY" ]; then
_err "No API key specified for Gandi LiveDNS."
_err "Create your key and export it as GANDI_LIVEDNS_KEY"
if [ -z "$GANDI_LIVEDNS_KEY" ] && [ -z "$GANDI_LIVEDNS_TOKEN" ]; then
_err "No Token or API key (deprecated) specified for Gandi LiveDNS."
_err "Create your token or key and export it as GANDI_LIVEDNS_KEY or GANDI_LIVEDNS_TOKEN respectively"
return 1 return 1
fi fi
# Keep only one secret in configuration
if [ -n "$GANDI_LIVEDNS_TOKEN" ]; then
_saveaccountconf GANDI_LIVEDNS_TOKEN "$GANDI_LIVEDNS_TOKEN"
_clearaccountconf GANDI_LIVEDNS_KEY
elif [ -n "$GANDI_LIVEDNS_KEY" ]; then
_saveaccountconf GANDI_LIVEDNS_KEY "$GANDI_LIVEDNS_KEY" _saveaccountconf GANDI_LIVEDNS_KEY "$GANDI_LIVEDNS_KEY"
_clearaccountconf GANDI_LIVEDNS_TOKEN
fi
_debug "First detect the root zone" _debug "First detect the root zone"
if ! _get_root "$fulldomain"; then if ! _get_root "$fulldomain"; then
@ -157,7 +165,12 @@ _gandi_livedns_rest() {
_debug "$ep" _debug "$ep"
export _H1="Content-Type: application/json" export _H1="Content-Type: application/json"
if [ -n "$GANDI_LIVEDNS_TOKEN" ]; then
export _H2="Authorization: Bearer $GANDI_LIVEDNS_TOKEN"
else
export _H2="X-Api-Key: $GANDI_LIVEDNS_KEY" export _H2="X-Api-Key: $GANDI_LIVEDNS_KEY"
fi
if [ "$m" = "GET" ]; then if [ "$m" = "GET" ]; then
response="$(_get "$GANDI_LIVEDNS_API/$ep")" response="$(_get "$GANDI_LIVEDNS_API/$ep")"

2
dnsapi/dns_gcloud.sh

@ -42,7 +42,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 ##################################

4
dnsapi/dns_gcore.sh

@ -4,8 +4,8 @@
#GCORE_Key='773$7b7adaf2a2b32bfb1b83787b4ff32a67eb178e3ada1af733e47b1411f2461f7f4fa7ed7138e2772a46124377bad7384b3bb8d87748f87b3f23db4b8bbe41b2bb' #GCORE_Key='773$7b7adaf2a2b32bfb1b83787b4ff32a67eb178e3ada1af733e47b1411f2461f7f4fa7ed7138e2772a46124377bad7384b3bb8d87748f87b3f23db4b8bbe41b2bb'
# #
GCORE_Api="https://api.gcorelabs.com/dns/v2"
GCORE_Doc="https://apidocs.gcore.com/dns"
GCORE_Api="https://api.gcore.com/dns/v2"
GCORE_Doc="https://api.gcore.com/docs/dns"
######## Public functions ##################### ######## Public functions #####################

2
dnsapi/dns_inwx.sh

@ -194,7 +194,7 @@ _inwx_login() {
response="$(_post "$xml_content" "$INWX_Api" "" "POST")" response="$(_post "$xml_content" "$INWX_Api" "" "POST")"
INWX_Cookie=$(printf "Cookie: %s" "$(grep "domrobot=" "$HTTP_HEADER" | grep "^Set-Cookie:" | _tail_n 1 | _egrep_o 'domrobot=[^;]*;' | tr -d ';')")
INWX_Cookie=$(printf "Cookie: %s" "$(grep "domrobot=" "$HTTP_HEADER" | grep -i "^Set-Cookie:" | _tail_n 1 | _egrep_o 'domrobot=[^;]*;' | tr -d ';')")
_H1=$INWX_Cookie _H1=$INWX_Cookie
export _H1 export _H1
export INWX_Cookie export INWX_Cookie

38
dnsapi/dns_pleskxml.sh

@ -46,6 +46,10 @@ pleskxml_tplt_get_domains="<packet><webspace><get><filter/><dataset><gen_info/><
# Also used to test credentials and URI. # Also used to test credentials and URI.
# No params. # No params.
pleskxml_tplt_get_additional_domains="<packet><site><get><filter/><dataset><gen_info/></dataset></get></site></packet>"
# Get a list of additional domains that PLESK can manage, so we can check root domain + host for acme.sh
# No params.
pleskxml_tplt_get_dns_records="<packet><dns><get_rec><filter><site-id>%s</site-id></filter></get_rec></dns></packet>" pleskxml_tplt_get_dns_records="<packet><dns><get_rec><filter><site-id>%s</site-id></filter></get_rec></dns></packet>"
# Get all DNS records for a Plesk domain ID. # Get all DNS records for a Plesk domain ID.
# PARAM = Plesk domain id to query # PARAM = Plesk domain id to query
@ -375,16 +379,44 @@ _pleskxml_get_root_domain() {
return 1 return 1
fi fi
# Generate a crude list of domains known to this Plesk account.
# Generate a crude list of domains known to this Plesk account based on subscriptions.
# We convert <ascii-name> tags to <name> so it'll flag on a hit with either <name> or <ascii-name> fields, # We convert <ascii-name> tags to <name> so it'll flag on a hit with either <name> or <ascii-name> fields,
# for non-Western character sets. # for non-Western character sets.
# Output will be one line per known domain, containing 2 <name> tages and a single <id> tag # Output will be one line per known domain, containing 2 <name> tages and a single <id> tag
# We don't actually need to check for type, name, *and* id, but it guarantees only usable lines are returned. # We don't actually need to check for type, name, *and* id, but it guarantees only usable lines are returned.
output="$(_api_response_split "$pleskxml_prettyprint_result" 'result' '<status>ok</status>' | sed 's/<ascii-name>/<name>/g;s/<\/ascii-name>/<\/name>/g' | grep '<name>' | grep '<id>')" output="$(_api_response_split "$pleskxml_prettyprint_result" 'result' '<status>ok</status>' | sed 's/<ascii-name>/<name>/g;s/<\/ascii-name>/<\/name>/g' | grep '<name>' | grep '<id>')"
debug_output="$(printf "%s" "$output" | sed -n 's:.*<name>\(.*\)</name>.*:\1:p')"
_debug 'Domains managed by Plesk server are:'
_debug "$debug_output"
_debug "Querying Plesk server for list of additional managed domains..."
_call_api "$pleskxml_tplt_get_additional_domains"
if [ "$pleskxml_retcode" -ne 0 ]; then
return 1
fi
# Generate a crude list of additional domains known to this Plesk account based on sites.
# We convert <ascii-name> tags to <name> so it'll flag on a hit with either <name> or <ascii-name> fields,
# for non-Western character sets.
# Output will be one line per known domain, containing 2 <name> tages and a single <id> tag
# We don't actually need to check for type, name, *and* id, but it guarantees only usable lines are returned.
output_additional="$(_api_response_split "$pleskxml_prettyprint_result" 'result' '<status>ok</status>' | sed 's/<ascii-name>/<name>/g;s/<\/ascii-name>/<\/name>/g' | grep '<name>' | grep '<id>')"
debug_additional="$(printf "%s" "$output_additional" | sed -n 's:.*<name>\(.*\)</name>.*:\1:p')"
_debug 'Additional domains managed by Plesk server are:'
_debug "$debug_additional"
# Concate the two outputs together.
output="$(printf "%s" "$output $NEWLINE $output_additional")"
debug_output="$(printf "%s" "$output" | sed -n 's:.*<name>\(.*\)</name>.*:\1:p')"
_debug 'Domains managed by Plesk server are (ignore the hacked output):'
_debug "$output"
_debug 'Domains (including additional) managed by Plesk server are:'
_debug "$debug_output"
# loop and test if domain, or any parent domain, is managed by Plesk # loop and test if domain, or any parent domain, is managed by Plesk
# Loop until we don't have any '.' in the string we're testing as a candidate Plesk-managed domain # Loop until we don't have any '.' in the string we're testing as a candidate Plesk-managed domain

211
dnsapi/dns_tencent.sh

@ -0,0 +1,211 @@
#!/usr/bin/env sh
Tencent_API="https://dnspod.tencentcloudapi.com"
#Tencent_SecretId="AKIDz81d2cd22cdcdc2dcd1cc1d1A"
#Tencent_SecretKey="Gu5t9abcabcaabcbabcbbbcbcbbccbbcb"
#Usage: dns_tencent_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_tencent_add() {
fulldomain=$1
txtvalue=$2
Tencent_SecretId="${Tencent_SecretId:-$(_readaccountconf_mutable Tencent_SecretId)}"
Tencent_SecretKey="${Tencent_SecretKey:-$(_readaccountconf_mutable Tencent_SecretKey)}"
if [ -z "$Tencent_SecretId" ] || [ -z "$Tencent_SecretKey" ]; then
Tencent_SecretId=""
Tencent_SecretKey=""
_err "You don't specify tencent api SecretId and SecretKey yet."
return 1
fi
#save the api SecretId and SecretKey to the account conf file.
_saveaccountconf_mutable Tencent_SecretId "$Tencent_SecretId"
_saveaccountconf_mutable Tencent_SecretKey "$Tencent_SecretKey"
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
return 1
fi
_debug "Add record"
_add_record_query "$_domain" "$_sub_domain" "$txtvalue" && _tencent_rest "CreateRecord"
}
dns_tencent_rm() {
fulldomain=$1
txtvalue=$2
Tencent_SecretId="${Tencent_SecretId:-$(_readaccountconf_mutable Tencent_SecretId)}"
Tencent_SecretKey="${Tencent_SecretKey:-$(_readaccountconf_mutable Tencent_SecretKey)}"
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
return 1
fi
_debug "Get record list"
attempt=1
max_attempts=5
while [ -z "$record_id" ] && [ "$attempt" -le $max_attempts ]; do
_check_exist_query "$_domain" "$_sub_domain" "$txtvalue" && _tencent_rest "DescribeRecordFilterList"
record_id="$(echo "$response" | _egrep_o "\"RecordId\":\s*[0-9]+" | _egrep_o "[0-9]+")"
_debug2 record_id "$record_id"
if [ -z "$record_id" ]; then
_debug "Due to TencentCloud API synchronization delay, record not found, waiting 10 seconds and retrying"
_sleep 10
attempt=$(_math "$attempt + 1")
fi
done
record_id="$(echo "$response" | _egrep_o "\"RecordId\":\s*[0-9]+" | _egrep_o "[0-9]+")"
_debug2 record_id "$record_id"
if [ -z "$record_id" ]; then
_debug "record not found after $max_attempts attempts, skip"
else
_debug "Delete record"
_delete_record_query "$record_id" && _tencent_rest "DeleteRecord"
fi
}
#################### Private functions below ##################################
_get_root() {
domain=$1
i=1
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
if [ -z "$h" ]; then
#not valid
return 1
fi
_describe_records_query "$h" "@"
if ! _tencent_rest "DescribeRecordList" "ignore"; then
return 1
fi
if _contains "$response" "\"TotalCount\":"; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
_debug _sub_domain "$_sub_domain"
_domain="$h"
_debug _domain "$_domain"
return 0
fi
p="$i"
i=$(_math "$i" + 1)
done
return 1
}
_tencent_rest() {
action=$1
service="dnspod"
payload="${query}"
timestamp=$(date -u +%s)
token=$(tencent_signature_v3 $service "$action" "$payload" "$timestamp")
version="2021-03-23"
if ! response="$(tencent_api_request $service $version "$action" "$payload" "$timestamp")"; 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
}
_add_record_query() {
query="{\"Domain\":\"$1\",\"SubDomain\":\"$2\",\"RecordType\":\"TXT\",\"RecordLineId\":\"0\",\"RecordLine\":\"0\",\"Value\":\"$3\",\"TTL\":600}"
}
_describe_records_query() {
query="{\"Domain\":\"$1\",\"Limit\":3000}"
}
_delete_record_query() {
query="{\"Domain\":\"$_domain\",\"RecordId\":$1}"
}
_check_exist_query() {
_domain="$1"
_subdomain="$2"
_value="$3"
query="{\"Domain\":\"$_domain\",\"SubDomain\":\"$_subdomain\",\"RecordValue\":\"$_value\"}"
}
# shell client for tencent cloud api v3 | @author: rehiy
tencent_sha256() {
printf %b "$@" | _digest sha256 hex
}
tencent_hmac_sha256() {
k=$1
shift
hex_key=$(printf %b "$k" | _hex_dump | tr -d ' ')
printf %b "$@" | _hmac sha256 "$hex_key" hex
}
tencent_hmac_sha256_hexkey() {
k=$1
shift
printf %b "$@" | _hmac sha256 "$k" hex
}
tencent_signature_v3() {
service=$1
action=$(echo "$2" | _lower_case)
payload=${3:-'{}'}
timestamp=${4:-$(date +%s)}
domain="$service.tencentcloudapi.com"
secretId=${Tencent_SecretId:-'tencent-cloud-secret-id'}
secretKey=${Tencent_SecretKey:-'tencent-cloud-secret-key'}
algorithm='TC3-HMAC-SHA256'
date=$(date -u -d "@$timestamp" +%Y-%m-%d 2>/dev/null)
[ -z "$date" ] && date=$(date -u -r "$timestamp" +%Y-%m-%d)
canonicalUri='/'
canonicalQuery=''
canonicalHeaders="content-type:application/json\nhost:$domain\nx-tc-action:$action\n"
signedHeaders='content-type;host;x-tc-action'
canonicalRequest="POST\n$canonicalUri\n$canonicalQuery\n$canonicalHeaders\n$signedHeaders\n$(tencent_sha256 "$payload")"
credentialScope="$date/$service/tc3_request"
stringToSign="$algorithm\n$timestamp\n$credentialScope\n$(tencent_sha256 "$canonicalRequest")"
secretDate=$(tencent_hmac_sha256 "TC3$secretKey" "$date")
secretService=$(tencent_hmac_sha256_hexkey "$secretDate" "$service")
secretSigning=$(tencent_hmac_sha256_hexkey "$secretService" 'tc3_request')
signature=$(tencent_hmac_sha256_hexkey "$secretSigning" "$stringToSign")
echo "$algorithm Credential=$secretId/$credentialScope, SignedHeaders=$signedHeaders, Signature=$signature"
}
tencent_api_request() {
service=$1
version=$2
action=$3
payload=${4:-'{}'}
timestamp=${5:-$(date +%s)}
token=$(tencent_signature_v3 "$service" "$action" "$payload" "$timestamp")
_H1="Content-Type: application/json"
_H2="Authorization: $token"
_H3="X-TC-Version: $version"
_H4="X-TC-Timestamp: $timestamp"
_H5="X-TC-Action: $action"
_post "$payload" "$Tencent_API" "" "POST" "application/json"
}

17
dnsapi/dns_variomedia.sh

@ -69,7 +69,7 @@ dns_variomedia_rm() {
return 1 return 1
fi fi
_record_id="$(echo "$response" | cut -d '[' -f2 | cut -d']' -f1 | sed 's/},[ \t]*{/\},§\{/g' | tr § '\n' | grep "$_sub_domain" | grep "$txtvalue" | sed 's/^{//;s/}[,]?$//' | tr , '\n' | tr -d '\"' | grep ^id | cut -d : -f2 | tr -d ' ')"
_record_id="$(echo "$response" | sed -E 's/,"tags":\[[^]]*\]//g' | cut -d '[' -f2 | cut -d']' -f1 | sed 's/},[ \t]*{/\},§\{/g' | tr § '\n' | grep "$_sub_domain" | grep -- "$txtvalue" | sed 's/^{//;s/}[,]?$//' | tr , '\n' | tr -d '\"' | grep ^id | cut -d : -f2 | tr -d ' ')"
_debug _record_id "$_record_id" _debug _record_id "$_record_id"
if [ "$_record_id" ]; then if [ "$_record_id" ]; then
_info "Successfully retrieved the record id for ACME challenge." _info "Successfully retrieved the record id for ACME challenge."
@ -93,11 +93,11 @@ dns_variomedia_rm() {
# _sub_domain=_acme-challenge.www # _sub_domain=_acme-challenge.www
# _domain=domain.com # _domain=domain.com
_get_root() { _get_root() {
fulldomain=$1
domain=$1
i=1 i=1
p=1
while true; do while true; do
h=$(printf "%s" "$fulldomain" | cut -d . -f $i-100)
_debug h "$h"
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
if [ -z "$h" ]; then if [ -z "$h" ]; then
return 1 return 1
fi fi
@ -106,17 +106,14 @@ _get_root() {
return 1 return 1
fi fi
if _startswith "$response" "\{\"data\":"; then
if _contains "$response" "\"id\":\"$h\""; then if _contains "$response" "\"id\":\"$h\""; then
_sub_domain="$(echo "$fulldomain" | sed "s/\\.$h\$//")"
_domain=$h
_sub_domain=$(printf "%s" "$domain" | cut -d '.' -f 1-$p)
_domain="$h"
return 0 return 0
fi fi
fi
p=$i
i=$(_math "$i" + 1) i=$(_math "$i" + 1)
done done
_debug "root domain not found"
return 1 return 1
} }

105
dnsapi/dns_west_cn.sh

@ -0,0 +1,105 @@
#!/usr/bin/env sh
# West.cn Domain api
#WEST_Username="username"
#WEST_Key="sADDsdasdgdsf"
#Set key at https://www.west.cn/manager/API/APIconfig.asp
REST_API="https://api.west.cn/API/v2"
######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_west_cn_add() {
fulldomain=$1
txtvalue=$2
WEST_Username="${WEST_Username:-$(_readaccountconf_mutable WEST_Username)}"
WEST_Key="${WEST_Key:-$(_readaccountconf_mutable WEST_Key)}"
if [ -z "$WEST_Username" ] || [ -z "$WEST_Key" ]; then
WEST_Username=""
WEST_Key=""
_err "You don't specify west api key and username yet."
_err "Please set you key and try again."
return 1
fi
#save the api key and email to the account conf file.
_saveaccountconf_mutable WEST_Username "$WEST_Username"
_saveaccountconf_mutable WEST_Key "$WEST_Key"
add_record "$fulldomain" "$txtvalue"
}
#Usage: rm _acme-challenge.www.domain.com
dns_west_cn_rm() {
fulldomain=$1
txtvalue=$2
WEST_Username="${WEST_Username:-$(_readaccountconf_mutable WEST_Username)}"
WEST_Key="${WEST_Key:-$(_readaccountconf_mutable WEST_Key)}"
if ! _rest POST "domain/dns/" "act=dnsrec.list&username=$WEST_Username&apikey=$WEST_Key&domain=$fulldomain&hostname=$fulldomain&record_type=TXT"; then
_err "dnsrec.list error."
return 1
fi
if _contains "$response" 'no records'; then
_info "Don't need to remove."
return 0
fi
record_id=$(echo "$response" | tr "{" "\n" | grep -- "$txtvalue" | grep '^"record_id"' | cut -d : -f 2 | cut -d ',' -f 1)
_debug record_id "$record_id"
if [ -z "$record_id" ]; then
_err "Can not get record id."
return 1
fi
if ! _rest POST "domain/dns/" "act=dnsrec.remove&username=$WEST_Username&apikey=$WEST_Key&domain=$fulldomain&hostname=$fulldomain&record_id=$record_id"; then
_err "dnsrec.remove error."
return 1
fi
_contains "$response" "success"
}
#add the txt record.
#usage: add fulldomain txtvalue
add_record() {
fulldomain=$1
txtvalue=$2
_info "Adding record"
if ! _rest POST "domain/dns/" "act=dnsrec.add&username=$WEST_Username&apikey=$WEST_Key&domain=$fulldomain&hostname=$fulldomain&record_type=TXT&record_value=$txtvalue"; then
return 1
fi
_contains "$response" "success"
}
#Usage: method URI data
_rest() {
m="$1"
ep="$2"
data="$3"
_debug "$ep"
url="$REST_API/$ep"
_debug url "$url"
if [ "$m" = "GET" ]; then
response="$(_get "$url" | tr -d '\r')"
else
_debug2 data "$data"
response="$(_post "$data" "$url" | tr -d '\r')"
fi
if [ "$?" != "0" ]; then
_err "error $ep"
return 1
fi
_debug2 response "$response"
return 0
}

52
notify/mattermost.sh

@ -0,0 +1,52 @@
#!/usr/bin/env sh
# Support mattermost bots
#MATTERMOST_API_URL=""
#MATTERMOST_CHANNEL_ID=""
#MATTERMOST_BOT_TOKEN=""
mattermost_send() {
_subject="$1"
_content="$2"
_statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped
_debug "_statusCode" "$_statusCode"
MATTERMOST_API_URL="${MATTERMOST_API_URL:-$(_readaccountconf_mutable MATTERMOST_API_URL)}"
if [ -z "$MATTERMOST_API_URL" ]; then
_err "You didn't specify a Mattermost API URL MATTERMOST_API_URL yet."
return 1
fi
_saveaccountconf_mutable MATTERMOST_API_URL "$MATTERMOST_API_URL"
MATTERMOST_CHANNEL_ID="${MATTERMOST_CHANNEL_ID:-$(_readaccountconf_mutable MATTERMOST_CHANNEL_ID)}"
if [ -z "$MATTERMOST_CHANNEL_ID" ]; then
_err "You didn't specify a Mattermost channel id MATTERMOST_CHANNEL_ID yet."
return 1
fi
_saveaccountconf_mutable MATTERMOST_CHANNEL_ID "$MATTERMOST_CHANNEL_ID"
MATTERMOST_BOT_TOKEN="${MATTERMOST_BOT_TOKEN:-$(_readaccountconf_mutable MATTERMOST_BOT_TOKEN)}"
if [ -z "$MATTERMOST_BOT_TOKEN" ]; then
_err "You didn't specify a Mattermost bot API token MATTERMOST_BOT_TOKEN yet."
return 1
fi
_saveaccountconf_mutable MATTERMOST_BOT_TOKEN "$MATTERMOST_BOT_TOKEN"
_content="$(printf "*%s*\n%s" "$_subject" "$_content" | _json_encode)"
_data="{\"channel_id\": \"$MATTERMOST_CHANNEL_ID\", "
_data="$_data\"message\": \"$_content\"}"
export _H1="Authorization: Bearer $MATTERMOST_BOT_TOKEN"
response=""
if _post "$_data" "$MATTERMOST_API_URL" "" "POST" "application/json; charset=utf-8"; then
MATTERMOST_RESULT_OK=$(echo "$response" | _egrep_o 'create_at')
if [ "$?" = "0" ] && [ "$MATTERMOST_RESULT_OK" ]; then
_info "mattermost send success."
return 0
fi
fi
_err "mattermost send error."
_err "$response"
return 1
}
Loading…
Cancel
Save