mirror of
https://github.com/acmesh-official/acme.sh.git
synced 2026-01-04 12:22:19 +08:00
Compare commits
165 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2a2d556551 | ||
|
|
0f762d98a4 | ||
|
|
36752cb6a8 | ||
|
|
90b65c6618 | ||
|
|
7250a300df | ||
|
|
34bb00450d | ||
|
|
63dadd8983 | ||
|
|
67c990e8cf | ||
|
|
0292e20c86 | ||
|
|
9088c8741a | ||
|
|
faedea2120 | ||
|
|
e1a0f5706d | ||
|
|
a78a4e6716 | ||
|
|
6bbf927f57 | ||
|
|
4c32bc8e22 | ||
|
|
df671a77f6 | ||
|
|
dca9def42c | ||
|
|
edee7ea284 | ||
|
|
658d09ed84 | ||
|
|
c41de8f270 | ||
|
|
9d2ee2127d | ||
|
|
e49ece8793 | ||
|
|
188274277a | ||
|
|
c0cb3945f1 | ||
|
|
e07795e8f0 | ||
|
|
bda454fe9c | ||
|
|
856e77053e | ||
|
|
2ce145f359 | ||
|
|
7e7291ace9 | ||
|
|
61c853a3c1 | ||
|
|
4346139d65 | ||
|
|
1476f83ba7 | ||
|
|
c959d64099 | ||
|
|
e67d26caeb | ||
|
|
86c3fa0df0 | ||
|
|
75ae57e194 | ||
|
|
d42feae0af | ||
|
|
45971b8083 | ||
|
|
8e9bbd1bb3 | ||
|
|
ec10a3eab4 | ||
|
|
49deb4af24 | ||
|
|
10f171b6e4 | ||
|
|
735db1a12b | ||
|
|
b2f4cc2dc5 | ||
|
|
d43b587d17 | ||
|
|
6b07a955f2 | ||
|
|
e23c02575d | ||
|
|
b1bf634136 | ||
|
|
459faf4dfb | ||
|
|
8cdceb83b2 | ||
|
|
6aa1ec0802 | ||
|
|
0727f7054b | ||
|
|
37cc611e3f | ||
|
|
c39e6c4423 | ||
|
|
1566656af3 | ||
|
|
737eba57bd | ||
|
|
d32cedd7dc | ||
|
|
2b6aa26703 | ||
|
|
95f1336060 | ||
|
|
f46ee93597 | ||
|
|
56d799f449 | ||
|
|
6251652c93 | ||
|
|
6a2c9a0dc1 | ||
|
|
4dd709b543 | ||
|
|
aa9f5b8c4a | ||
|
|
f485f3fdb5 | ||
|
|
c6a0ec64cb | ||
|
|
e0b179e5f3 | ||
|
|
dac7a3d272 | ||
|
|
beed123fb0 | ||
|
|
267e582827 | ||
|
|
69c02cae76 | ||
|
|
4f386663e7 | ||
|
|
eaae0547f2 | ||
|
|
b203f2abaa | ||
|
|
5490a2f3ba | ||
|
|
ba44235471 | ||
|
|
be556f9e36 | ||
|
|
5e5ba11601 | ||
|
|
e384df30fa | ||
|
|
4635dacf7f | ||
|
|
18e4d270d9 | ||
|
|
3bcb91f6ae | ||
|
|
5e574a355d | ||
|
|
640c7c5fa3 | ||
|
|
eb6395a62c | ||
|
|
2b2845aa07 | ||
|
|
54d8c66f3e | ||
|
|
95bbf1b190 | ||
|
|
ee2dab51f3 | ||
|
|
f63409eed9 | ||
|
|
ad8940ad73 | ||
|
|
b8bfb5a56c | ||
|
|
3f58823430 | ||
|
|
e488220bfc | ||
|
|
e6e0771496 | ||
|
|
fe77d43fa0 | ||
|
|
737a7a2db2 | ||
|
|
6ae8d10132 | ||
|
|
7d249b6d3b | ||
|
|
a532b82771 | ||
|
|
e8756482aa | ||
|
|
35d6da785b | ||
|
|
dbdcbd4b9e | ||
|
|
a2b6f49c5c | ||
|
|
a31ed4a723 | ||
|
|
b2fc84c98e | ||
|
|
927369b06d | ||
|
|
401fd37e35 | ||
|
|
759cdf10c5 | ||
|
|
6e7ce1eec1 | ||
|
|
2a65955e88 | ||
|
|
5b0d6a1375 | ||
|
|
0510da0853 | ||
|
|
365d22d076 | ||
|
|
1760169ef9 | ||
|
|
32ea224933 | ||
|
|
38a067e203 | ||
|
|
ab6f1b6df7 | ||
|
|
b36802edff | ||
|
|
1d2af0f291 | ||
|
|
40e8c5e2b0 | ||
|
|
e11d0d37ee | ||
|
|
ea4266538a | ||
|
|
aa7bf9169f | ||
|
|
a95e83ab6e | ||
|
|
86daaf4bf2 | ||
|
|
d5b4f02932 | ||
|
|
15deec6c53 | ||
|
|
17b1875151 | ||
|
|
bfda8f0b8a | ||
|
|
7bb0ff986b | ||
|
|
f3cfef4021 | ||
|
|
3184c3c21b | ||
|
|
9264737985 | ||
|
|
c9b353a689 | ||
|
|
fda6502f33 | ||
|
|
0fdac82b93 | ||
|
|
6b3d6d5211 | ||
|
|
cb89ee39f5 | ||
|
|
be827be742 | ||
|
|
83b49b23e4 | ||
|
|
8339b88180 | ||
|
|
608547c62c | ||
|
|
bd00db4292 | ||
|
|
68debc474a | ||
|
|
6a7f993a9a | ||
|
|
d2d023cca7 | ||
|
|
7f9b8d68ac | ||
|
|
4bb8e3a121 | ||
|
|
eacc00f786 | ||
|
|
93fd6170a3 | ||
|
|
6f4c5fcc87 | ||
|
|
a7ca010d4e | ||
|
|
a836842a7e | ||
|
|
f8c11a324a | ||
|
|
052c9be111 | ||
|
|
854e520528 | ||
|
|
05737b85eb | ||
|
|
c8a2308739 | ||
|
|
ed46a078f9 | ||
|
|
4f7c2bf8c3 | ||
|
|
0e341726d2 | ||
|
|
a4f9746d3a | ||
|
|
556c546b2e |
17
.github/workflows/DNS.yml
vendored
17
.github/workflows/DNS.yml
vendored
@@ -37,7 +37,7 @@ jobs:
|
|||||||
- name: "Read this: https://github.com/acmesh-official/acme.sh/wiki/DNS-API-Test"
|
- name: "Read this: https://github.com/acmesh-official/acme.sh/wiki/DNS-API-Test"
|
||||||
run: |
|
run: |
|
||||||
echo "Read this: https://github.com/acmesh-official/acme.sh/wiki/DNS-API-Test"
|
echo "Read this: https://github.com/acmesh-official/acme.sh/wiki/DNS-API-Test"
|
||||||
if [ "${{github.actor}}" != "Neilpang" ]; then
|
if [ "${{github.repository_owner}}" != "acmesh-official" ]; then
|
||||||
false
|
false
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -49,6 +49,7 @@ jobs:
|
|||||||
TEST_DNS : ${{ secrets.TEST_DNS }}
|
TEST_DNS : ${{ secrets.TEST_DNS }}
|
||||||
TestingDomain: ${{ secrets.TestingDomain }}
|
TestingDomain: ${{ secrets.TestingDomain }}
|
||||||
TEST_DNS_NO_WILDCARD: ${{ secrets.TEST_DNS_NO_WILDCARD }}
|
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 }}
|
TEST_DNS_SLEEP: ${{ secrets.TEST_DNS_SLEEP }}
|
||||||
CASE: le_test_dnsapi
|
CASE: le_test_dnsapi
|
||||||
TEST_LOCAL: 1
|
TEST_LOCAL: 1
|
||||||
@@ -87,6 +88,7 @@ jobs:
|
|||||||
TEST_DNS : ${{ secrets.TEST_DNS }}
|
TEST_DNS : ${{ secrets.TEST_DNS }}
|
||||||
TestingDomain: ${{ secrets.TestingDomain }}
|
TestingDomain: ${{ secrets.TestingDomain }}
|
||||||
TEST_DNS_NO_WILDCARD: ${{ secrets.TEST_DNS_NO_WILDCARD }}
|
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 }}
|
TEST_DNS_SLEEP: ${{ secrets.TEST_DNS_SLEEP }}
|
||||||
CASE: le_test_dnsapi
|
CASE: le_test_dnsapi
|
||||||
TEST_LOCAL: 1
|
TEST_LOCAL: 1
|
||||||
@@ -124,6 +126,7 @@ jobs:
|
|||||||
TEST_DNS : ${{ secrets.TEST_DNS }}
|
TEST_DNS : ${{ secrets.TEST_DNS }}
|
||||||
TestingDomain: ${{ secrets.TestingDomain }}
|
TestingDomain: ${{ secrets.TestingDomain }}
|
||||||
TEST_DNS_NO_WILDCARD: ${{ secrets.TEST_DNS_NO_WILDCARD }}
|
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 }}
|
TEST_DNS_SLEEP: ${{ secrets.TEST_DNS_SLEEP }}
|
||||||
CASE: le_test_dnsapi
|
CASE: le_test_dnsapi
|
||||||
TEST_LOCAL: 1
|
TEST_LOCAL: 1
|
||||||
@@ -170,12 +173,13 @@ jobs:
|
|||||||
./letest.sh
|
./letest.sh
|
||||||
|
|
||||||
FreeBSD:
|
FreeBSD:
|
||||||
runs-on: macos-latest
|
runs-on: macos-10.15
|
||||||
needs: Windows
|
needs: Windows
|
||||||
env:
|
env:
|
||||||
TEST_DNS : ${{ secrets.TEST_DNS }}
|
TEST_DNS : ${{ secrets.TEST_DNS }}
|
||||||
TestingDomain: ${{ secrets.TestingDomain }}
|
TestingDomain: ${{ secrets.TestingDomain }}
|
||||||
TEST_DNS_NO_WILDCARD: ${{ secrets.TEST_DNS_NO_WILDCARD }}
|
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 }}
|
TEST_DNS_SLEEP: ${{ secrets.TEST_DNS_SLEEP }}
|
||||||
CASE: le_test_dnsapi
|
CASE: le_test_dnsapi
|
||||||
TEST_LOCAL: 1
|
TEST_LOCAL: 1
|
||||||
@@ -186,7 +190,7 @@ jobs:
|
|||||||
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||||
- uses: vmactions/freebsd-vm@v0.1.4
|
- uses: vmactions/freebsd-vm@v0.1.4
|
||||||
with:
|
with:
|
||||||
envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG ${{ 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 ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}'
|
||||||
prepare: pkg install -y socat curl
|
prepare: pkg install -y socat curl
|
||||||
usesh: true
|
usesh: true
|
||||||
run: |
|
run: |
|
||||||
@@ -209,12 +213,13 @@ jobs:
|
|||||||
./letest.sh
|
./letest.sh
|
||||||
|
|
||||||
Solaris:
|
Solaris:
|
||||||
runs-on: macos-latest
|
runs-on: macos-10.15
|
||||||
needs: FreeBSD
|
needs: FreeBSD
|
||||||
env:
|
env:
|
||||||
TEST_DNS : ${{ secrets.TEST_DNS }}
|
TEST_DNS : ${{ secrets.TEST_DNS }}
|
||||||
TestingDomain: ${{ secrets.TestingDomain }}
|
TestingDomain: ${{ secrets.TestingDomain }}
|
||||||
TEST_DNS_NO_WILDCARD: ${{ secrets.TEST_DNS_NO_WILDCARD }}
|
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 }}
|
TEST_DNS_SLEEP: ${{ secrets.TEST_DNS_SLEEP }}
|
||||||
CASE: le_test_dnsapi
|
CASE: le_test_dnsapi
|
||||||
TEST_LOCAL: 1
|
TEST_LOCAL: 1
|
||||||
@@ -223,9 +228,9 @@ jobs:
|
|||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Clone acmetest
|
- name: Clone acmetest
|
||||||
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||||
- uses: vmactions/solaris-vm@v0.0.3
|
- uses: vmactions/solaris-vm@v0.0.5
|
||||||
with:
|
with:
|
||||||
envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG ${{ 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 ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}'
|
||||||
prepare: pkgutil -y -i socat
|
prepare: pkgutil -y -i socat
|
||||||
run: |
|
run: |
|
||||||
pkg set-mediator -v -I default@1.1 openssl
|
pkg set-mediator -v -I default@1.1 openssl
|
||||||
|
|||||||
11
.github/workflows/FreeBSD.yml
vendored
11
.github/workflows/FreeBSD.yml
vendored
@@ -24,20 +24,23 @@ jobs:
|
|||||||
CA_ECDSA: ""
|
CA_ECDSA: ""
|
||||||
CA: ""
|
CA: ""
|
||||||
CA_EMAIL: ""
|
CA_EMAIL: ""
|
||||||
|
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1
|
||||||
- TEST_ACME_Server: "ZeroSSL.com"
|
- TEST_ACME_Server: "ZeroSSL.com"
|
||||||
CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA"
|
CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA"
|
||||||
CA: "ZeroSSL RSA Domain Secure Site CA"
|
CA: "ZeroSSL RSA Domain Secure Site CA"
|
||||||
CA_EMAIL: "githubtest@acme.sh"
|
CA_EMAIL: "githubtest@acme.sh"
|
||||||
runs-on: macos-latest
|
TEST_PREFERRED_CHAIN: ""
|
||||||
|
runs-on: macos-10.15
|
||||||
env:
|
env:
|
||||||
TEST_LOCAL: 1
|
TEST_LOCAL: 1
|
||||||
TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }}
|
TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }}
|
||||||
CA_ECDSA: ${{ matrix.CA_ECDSA }}
|
CA_ECDSA: ${{ matrix.CA_ECDSA }}
|
||||||
CA: ${{ matrix.CA }}
|
CA: ${{ matrix.CA }}
|
||||||
CA_EMAIL: ${{ matrix.CA_EMAIL }}
|
CA_EMAIL: ${{ matrix.CA_EMAIL }}
|
||||||
|
TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: vmactions/cf-tunnel@v0.0.2
|
- uses: vmactions/cf-tunnel@v0.0.3
|
||||||
id: tunnel
|
id: tunnel
|
||||||
with:
|
with:
|
||||||
protocol: http
|
protocol: http
|
||||||
@@ -46,9 +49,9 @@ 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 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||||
- uses: vmactions/freebsd-vm@v0.1.4
|
- uses: vmactions/freebsd-vm@v0.1.5
|
||||||
with:
|
with:
|
||||||
envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL'
|
envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN'
|
||||||
nat: |
|
nat: |
|
||||||
"8080": "80"
|
"8080": "80"
|
||||||
prepare: pkg install -y socat curl
|
prepare: pkg install -y socat curl
|
||||||
|
|||||||
3
.github/workflows/Linux.yml
vendored
3
.github/workflows/Linux.yml
vendored
@@ -20,10 +20,11 @@ jobs:
|
|||||||
Linux:
|
Linux:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: ["ubuntu:latest", "debian:latest", "almalinux:latest", "fedora:latest", "centos:latest", "opensuse/leap:latest", "alpine:latest", "oraclelinux:8", "kalilinux/kali", "archlinux:latest", "mageia", "gentoo/stage3-amd64"]
|
os: ["ubuntu:latest", "debian:latest", "almalinux:latest", "fedora:latest", "centos:7", "opensuse/leap:latest", "alpine:latest", "oraclelinux:8", "kalilinux/kali", "archlinux:latest", "mageia", "gentoo/stage3"]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
env:
|
env:
|
||||||
TEST_LOCAL: 1
|
TEST_LOCAL: 1
|
||||||
|
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Clone acmetest
|
- name: Clone acmetest
|
||||||
|
|||||||
3
.github/workflows/MacOS.yml
vendored
3
.github/workflows/MacOS.yml
vendored
@@ -24,10 +24,12 @@ jobs:
|
|||||||
CA_ECDSA: ""
|
CA_ECDSA: ""
|
||||||
CA: ""
|
CA: ""
|
||||||
CA_EMAIL: ""
|
CA_EMAIL: ""
|
||||||
|
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1
|
||||||
- TEST_ACME_Server: "ZeroSSL.com"
|
- TEST_ACME_Server: "ZeroSSL.com"
|
||||||
CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA"
|
CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA"
|
||||||
CA: "ZeroSSL RSA Domain Secure Site CA"
|
CA: "ZeroSSL RSA Domain Secure Site CA"
|
||||||
CA_EMAIL: "githubtest@acme.sh"
|
CA_EMAIL: "githubtest@acme.sh"
|
||||||
|
TEST_PREFERRED_CHAIN: ""
|
||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
env:
|
env:
|
||||||
TEST_LOCAL: 1
|
TEST_LOCAL: 1
|
||||||
@@ -35,6 +37,7 @@ jobs:
|
|||||||
CA_ECDSA: ${{ matrix.CA_ECDSA }}
|
CA_ECDSA: ${{ matrix.CA_ECDSA }}
|
||||||
CA: ${{ matrix.CA }}
|
CA: ${{ matrix.CA }}
|
||||||
CA_EMAIL: ${{ matrix.CA_EMAIL }}
|
CA_EMAIL: ${{ matrix.CA_EMAIL }}
|
||||||
|
TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Install tools
|
- name: Install tools
|
||||||
|
|||||||
23
.github/workflows/PebbleStrict.yml
vendored
23
.github/workflows/PebbleStrict.yml
vendored
@@ -37,3 +37,26 @@ jobs:
|
|||||||
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||||
- name: Run acmetest
|
- name: Run acmetest
|
||||||
run: cd ../acmetest && ./letest.sh
|
run: cd ../acmetest && ./letest.sh
|
||||||
|
|
||||||
|
PebbleStrict_IPCert:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
TestingDomain: 10.30.50.1
|
||||||
|
ACME_DIRECTORY: https://localhost:14000/dir
|
||||||
|
HTTPS_INSECURE: 1
|
||||||
|
Le_HTTPPort: 5002
|
||||||
|
Le_TLSPort: 5001
|
||||||
|
TEST_LOCAL: 1
|
||||||
|
TEST_CA: "Pebble Intermediate CA"
|
||||||
|
TEST_IPCERT: 1
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Install tools
|
||||||
|
run: sudo apt-get install -y socat
|
||||||
|
- name: Run Pebble
|
||||||
|
run: cd .. && curl https://raw.githubusercontent.com/letsencrypt/pebble/master/docker-compose.yml >docker-compose.yml && docker-compose up -d
|
||||||
|
- name: Clone acmetest
|
||||||
|
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||||
|
- name: Run acmetest
|
||||||
|
run: cd ../acmetest && ./letest.sh
|
||||||
11
.github/workflows/Solaris.yml
vendored
11
.github/workflows/Solaris.yml
vendored
@@ -24,20 +24,23 @@ jobs:
|
|||||||
CA_ECDSA: ""
|
CA_ECDSA: ""
|
||||||
CA: ""
|
CA: ""
|
||||||
CA_EMAIL: ""
|
CA_EMAIL: ""
|
||||||
|
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1
|
||||||
- TEST_ACME_Server: "ZeroSSL.com"
|
- TEST_ACME_Server: "ZeroSSL.com"
|
||||||
CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA"
|
CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA"
|
||||||
CA: "ZeroSSL RSA Domain Secure Site CA"
|
CA: "ZeroSSL RSA Domain Secure Site CA"
|
||||||
CA_EMAIL: "githubtest@acme.sh"
|
CA_EMAIL: "githubtest@acme.sh"
|
||||||
runs-on: macos-latest
|
TEST_PREFERRED_CHAIN: ""
|
||||||
|
runs-on: macos-10.15
|
||||||
env:
|
env:
|
||||||
TEST_LOCAL: 1
|
TEST_LOCAL: 1
|
||||||
TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }}
|
TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }}
|
||||||
CA_ECDSA: ${{ matrix.CA_ECDSA }}
|
CA_ECDSA: ${{ matrix.CA_ECDSA }}
|
||||||
CA: ${{ matrix.CA }}
|
CA: ${{ matrix.CA }}
|
||||||
CA_EMAIL: ${{ matrix.CA_EMAIL }}
|
CA_EMAIL: ${{ matrix.CA_EMAIL }}
|
||||||
|
TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: vmactions/cf-tunnel@v0.0.2
|
- uses: vmactions/cf-tunnel@v0.0.3
|
||||||
id: tunnel
|
id: tunnel
|
||||||
with:
|
with:
|
||||||
protocol: http
|
protocol: http
|
||||||
@@ -46,9 +49,9 @@ 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 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||||
- uses: vmactions/solaris-vm@v0.0.3
|
- uses: vmactions/solaris-vm@v0.0.5
|
||||||
with:
|
with:
|
||||||
envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL'
|
envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN'
|
||||||
nat: |
|
nat: |
|
||||||
"8080": "80"
|
"8080": "80"
|
||||||
prepare: pkgutil -y -i socat curl
|
prepare: pkgutil -y -i socat curl
|
||||||
|
|||||||
32
.github/workflows/Ubuntu.yml
vendored
32
.github/workflows/Ubuntu.yml
vendored
@@ -24,10 +24,26 @@ jobs:
|
|||||||
CA_ECDSA: ""
|
CA_ECDSA: ""
|
||||||
CA: ""
|
CA: ""
|
||||||
CA_EMAIL: ""
|
CA_EMAIL: ""
|
||||||
|
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1
|
||||||
- TEST_ACME_Server: "ZeroSSL.com"
|
- TEST_ACME_Server: "ZeroSSL.com"
|
||||||
CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA"
|
CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA"
|
||||||
CA: "ZeroSSL RSA Domain Secure Site CA"
|
CA: "ZeroSSL RSA Domain Secure Site CA"
|
||||||
CA_EMAIL: "githubtest@acme.sh"
|
CA_EMAIL: "githubtest@acme.sh"
|
||||||
|
TEST_PREFERRED_CHAIN: ""
|
||||||
|
- TEST_ACME_Server: "https://localhost:9000/acme/acme/directory"
|
||||||
|
CA_ECDSA: "Smallstep Intermediate CA"
|
||||||
|
CA: "Smallstep Intermediate CA"
|
||||||
|
CA_EMAIL: ""
|
||||||
|
TEST_PREFERRED_CHAIN: ""
|
||||||
|
NO_REVOKE: 1
|
||||||
|
- TEST_ACME_Server: "https://localhost:9000/acme/acme/directory"
|
||||||
|
CA_ECDSA: "Smallstep Intermediate CA"
|
||||||
|
CA: "Smallstep Intermediate CA"
|
||||||
|
CA_EMAIL: ""
|
||||||
|
TEST_PREFERRED_CHAIN: ""
|
||||||
|
NO_REVOKE: 1
|
||||||
|
TEST_IPCERT: 1
|
||||||
|
TestingDomain: "172.17.0.1"
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
env:
|
env:
|
||||||
@@ -37,10 +53,26 @@ jobs:
|
|||||||
CA: ${{ matrix.CA }}
|
CA: ${{ matrix.CA }}
|
||||||
CA_EMAIL: ${{ matrix.CA_EMAIL }}
|
CA_EMAIL: ${{ matrix.CA_EMAIL }}
|
||||||
NO_ECC_384: ${{ matrix.NO_ECC_384 }}
|
NO_ECC_384: ${{ matrix.NO_ECC_384 }}
|
||||||
|
TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }}
|
||||||
|
NO_REVOKE: ${{ matrix.NO_REVOKE }}
|
||||||
|
TEST_IPCERT: ${{ matrix.TEST_IPCERT }}
|
||||||
|
TestingDomain: ${{ matrix.TestingDomain }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Install tools
|
- name: Install tools
|
||||||
run: sudo apt-get install -y socat
|
run: sudo apt-get install -y socat
|
||||||
|
- name: Start StepCA
|
||||||
|
if: ${{ matrix.TEST_ACME_Server=='https://localhost:9000/acme/acme/directory' }}
|
||||||
|
run: |
|
||||||
|
docker run --rm -d \
|
||||||
|
-p 9000:9000 \
|
||||||
|
-e "DOCKER_STEPCA_INIT_NAME=Smallstep" \
|
||||||
|
-e "DOCKER_STEPCA_INIT_DNS_NAMES=localhost,$(hostname -f)" \
|
||||||
|
--name stepca \
|
||||||
|
smallstep/step-ca \
|
||||||
|
&& sleep 5 && docker exec stepca step ca provisioner add acme --type ACME \
|
||||||
|
&& docker exec stepca kill -1 1 \
|
||||||
|
&& docker exec stepca cat /home/step/certs/root_ca.crt | sudo bash -c "cat - >>/etc/ssl/certs/ca-certificates.crt"
|
||||||
- name: Clone acmetest
|
- name: Clone acmetest
|
||||||
run: |
|
run: |
|
||||||
cd .. \
|
cd .. \
|
||||||
|
|||||||
5
.github/workflows/Windows.yml
vendored
5
.github/workflows/Windows.yml
vendored
@@ -24,10 +24,12 @@ jobs:
|
|||||||
CA_ECDSA: ""
|
CA_ECDSA: ""
|
||||||
CA: ""
|
CA: ""
|
||||||
CA_EMAIL: ""
|
CA_EMAIL: ""
|
||||||
|
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1
|
||||||
- TEST_ACME_Server: "ZeroSSL.com"
|
- TEST_ACME_Server: "ZeroSSL.com"
|
||||||
CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA"
|
CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA"
|
||||||
CA: "ZeroSSL RSA Domain Secure Site CA"
|
CA: "ZeroSSL RSA Domain Secure Site CA"
|
||||||
CA_EMAIL: "githubtest@acme.sh"
|
CA_EMAIL: "githubtest@acme.sh"
|
||||||
|
TEST_PREFERRED_CHAIN: ""
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
env:
|
env:
|
||||||
TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }}
|
TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }}
|
||||||
@@ -37,6 +39,7 @@ jobs:
|
|||||||
TEST_LOCAL: 1
|
TEST_LOCAL: 1
|
||||||
#The 80 port is used by Windows server, we have to use a custom port, tunnel will also use this port.
|
#The 80 port is used by Windows server, we have to use a custom port, tunnel will also use this port.
|
||||||
Le_HTTPPort: 8888
|
Le_HTTPPort: 8888
|
||||||
|
TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }}
|
||||||
steps:
|
steps:
|
||||||
- name: Set git to use LF
|
- name: Set git to use LF
|
||||||
run: |
|
run: |
|
||||||
@@ -49,7 +52,7 @@ jobs:
|
|||||||
shell: cmd
|
shell: cmd
|
||||||
- name: Install cygwin additional packages
|
- name: Install cygwin additional packages
|
||||||
run: |
|
run: |
|
||||||
C:\tools\cygwin\cygwinsetup.exe -qgnNdO -R C:/tools/cygwin -s http://mirrors.kernel.org/sourceware/cygwin/ -P socat,curl,cron,unzip,git
|
C:\tools\cygwin\cygwinsetup.exe -qgnNdO -R C:/tools/cygwin -s http://mirrors.kernel.org/sourceware/cygwin/ -P socat,curl,cron,unzip,git,xxd
|
||||||
shell: cmd
|
shell: cmd
|
||||||
- name: Set ENV
|
- name: Set ENV
|
||||||
shell: cmd
|
shell: cmd
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM alpine:3.12
|
FROM alpine:3.15
|
||||||
|
|
||||||
RUN apk --no-cache add -f \
|
RUN apk --no-cache add -f \
|
||||||
openssl \
|
openssl \
|
||||||
@@ -11,7 +11,8 @@ RUN apk --no-cache add -f \
|
|||||||
tzdata \
|
tzdata \
|
||||||
oath-toolkit-oathtool \
|
oath-toolkit-oathtool \
|
||||||
tar \
|
tar \
|
||||||
libidn
|
libidn \
|
||||||
|
jq
|
||||||
|
|
||||||
ENV LE_CONFIG_HOME /acme.sh
|
ENV LE_CONFIG_HOME /acme.sh
|
||||||
|
|
||||||
@@ -40,6 +41,7 @@ RUN for verb in help \
|
|||||||
revoke \
|
revoke \
|
||||||
remove \
|
remove \
|
||||||
list \
|
list \
|
||||||
|
info \
|
||||||
showcsr \
|
showcsr \
|
||||||
install-cronjob \
|
install-cronjob \
|
||||||
uninstall-cronjob \
|
uninstall-cronjob \
|
||||||
@@ -55,6 +57,7 @@ RUN for verb in help \
|
|||||||
deactivate-account \
|
deactivate-account \
|
||||||
set-notify \
|
set-notify \
|
||||||
set-default-ca \
|
set-default-ca \
|
||||||
|
set-default-chain \
|
||||||
; do \
|
; do \
|
||||||
printf -- "%b" "#!/usr/bin/env sh\n/root/.acme.sh/acme.sh --${verb} --config-home /acme.sh \"\$@\"" >/usr/local/bin/--${verb} && chmod +x /usr/local/bin/--${verb} \
|
printf -- "%b" "#!/usr/bin/env sh\n/root/.acme.sh/acme.sh --${verb} --config-home /acme.sh \"\$@\"" >/usr/local/bin/--${verb} && chmod +x /usr/local/bin/--${verb} \
|
||||||
; done
|
; done
|
||||||
|
|||||||
271
acme.sh
271
acme.sh
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
VER=3.0.1
|
VER=3.0.2
|
||||||
|
|
||||||
PROJECT_NAME="acme.sh"
|
PROJECT_NAME="acme.sh"
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ CA_BUYPASS="https://api.buypass.com/acme/directory"
|
|||||||
CA_BUYPASS_TEST="https://api.test4.buypass.no/acme/directory"
|
CA_BUYPASS_TEST="https://api.test4.buypass.no/acme/directory"
|
||||||
|
|
||||||
CA_ZEROSSL="https://acme.zerossl.com/v2/DV90"
|
CA_ZEROSSL="https://acme.zerossl.com/v2/DV90"
|
||||||
_ZERO_EAB_ENDPOINT="http://api.zerossl.com/acme/eab-credentials-email"
|
_ZERO_EAB_ENDPOINT="https://api.zerossl.com/acme/eab-credentials-email"
|
||||||
|
|
||||||
CA_SSLCOM_RSA="https://acme.ssl.com/sslcom-dv-rsa"
|
CA_SSLCOM_RSA="https://acme.ssl.com/sslcom-dv-rsa"
|
||||||
CA_SSLCOM_ECC="https://acme.ssl.com/sslcom-dv-ecc"
|
CA_SSLCOM_ECC="https://acme.ssl.com/sslcom-dv-ecc"
|
||||||
@@ -59,6 +59,9 @@ VTYPE_HTTP="http-01"
|
|||||||
VTYPE_DNS="dns-01"
|
VTYPE_DNS="dns-01"
|
||||||
VTYPE_ALPN="tls-alpn-01"
|
VTYPE_ALPN="tls-alpn-01"
|
||||||
|
|
||||||
|
ID_TYPE_DNS="dns"
|
||||||
|
ID_TYPE_IP="ip"
|
||||||
|
|
||||||
LOCAL_ANY_ADDRESS="0.0.0.0"
|
LOCAL_ANY_ADDRESS="0.0.0.0"
|
||||||
|
|
||||||
DEFAULT_RENEW=60
|
DEFAULT_RENEW=60
|
||||||
@@ -77,8 +80,8 @@ NGINX="nginx:"
|
|||||||
NGINX_START="#ACME_NGINX_START"
|
NGINX_START="#ACME_NGINX_START"
|
||||||
NGINX_END="#ACME_NGINX_END"
|
NGINX_END="#ACME_NGINX_END"
|
||||||
|
|
||||||
BEGIN_CSR="-----BEGIN CERTIFICATE REQUEST-----"
|
BEGIN_CSR="-----BEGIN [NEW ]\{0,4\}CERTIFICATE REQUEST-----"
|
||||||
END_CSR="-----END CERTIFICATE REQUEST-----"
|
END_CSR="-----END [NEW ]\{0,4\}CERTIFICATE REQUEST-----"
|
||||||
|
|
||||||
BEGIN_CERT="-----BEGIN CERTIFICATE-----"
|
BEGIN_CERT="-----BEGIN CERTIFICATE-----"
|
||||||
END_CERT="-----END CERTIFICATE-----"
|
END_CERT="-----END CERTIFICATE-----"
|
||||||
@@ -141,6 +144,8 @@ NOTIFY_MODE_CERT=1
|
|||||||
|
|
||||||
NOTIFY_MODE_DEFAULT=$NOTIFY_MODE_BULK
|
NOTIFY_MODE_DEFAULT=$NOTIFY_MODE_BULK
|
||||||
|
|
||||||
|
_BASE64_ENCODED_CFGS="Le_PreHook Le_PostHook Le_RenewHook Le_Preferred_Chain Le_ReloadCmd"
|
||||||
|
|
||||||
_DEBUG_WIKI="https://github.com/acmesh-official/acme.sh/wiki/How-to-debug-acme.sh"
|
_DEBUG_WIKI="https://github.com/acmesh-official/acme.sh/wiki/How-to-debug-acme.sh"
|
||||||
|
|
||||||
_PREPARE_LINK="https://github.com/acmesh-official/acme.sh/wiki/Install-preparations"
|
_PREPARE_LINK="https://github.com/acmesh-official/acme.sh/wiki/Install-preparations"
|
||||||
@@ -426,19 +431,27 @@ _secure_debug3() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_upper_case() {
|
_upper_case() {
|
||||||
|
if _is_solaris; then
|
||||||
|
tr '[:lower:]' '[:upper:]'
|
||||||
|
else
|
||||||
# shellcheck disable=SC2018,SC2019
|
# shellcheck disable=SC2018,SC2019
|
||||||
tr 'a-z' 'A-Z'
|
tr 'a-z' 'A-Z'
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
_lower_case() {
|
_lower_case() {
|
||||||
|
if _is_solaris; then
|
||||||
|
tr '[:upper:]' '[:lower:]'
|
||||||
|
else
|
||||||
# shellcheck disable=SC2018,SC2019
|
# shellcheck disable=SC2018,SC2019
|
||||||
tr 'A-Z' 'a-z'
|
tr 'A-Z' 'a-z'
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
_startswith() {
|
_startswith() {
|
||||||
_str="$1"
|
_str="$1"
|
||||||
_sub="$2"
|
_sub="$2"
|
||||||
echo "$_str" | grep "^$_sub" >/dev/null 2>&1
|
echo "$_str" | grep -- "^$_sub" >/dev/null 2>&1
|
||||||
}
|
}
|
||||||
|
|
||||||
_endswith() {
|
_endswith() {
|
||||||
@@ -1040,9 +1053,9 @@ _sign() {
|
|||||||
|
|
||||||
_sign_openssl="${ACME_OPENSSL_BIN:-openssl} dgst -sign $keyfile "
|
_sign_openssl="${ACME_OPENSSL_BIN:-openssl} dgst -sign $keyfile "
|
||||||
|
|
||||||
if grep "BEGIN RSA PRIVATE KEY" "$keyfile" >/dev/null 2>&1 || grep "BEGIN PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then
|
if _isRSA "$keyfile" >/dev/null 2>&1; then
|
||||||
$_sign_openssl -$alg | _base64
|
$_sign_openssl -$alg | _base64
|
||||||
elif grep "BEGIN EC PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then
|
elif _isEcc "$keyfile" >/dev/null 2>&1; then
|
||||||
if ! _signedECText="$($_sign_openssl -sha$__ECC_KEY_LEN | ${ACME_OPENSSL_BIN:-openssl} asn1parse -inform DER)"; then
|
if ! _signedECText="$($_sign_openssl -sha$__ECC_KEY_LEN | ${ACME_OPENSSL_BIN:-openssl} asn1parse -inform DER)"; then
|
||||||
_err "Sign failed: $_sign_openssl"
|
_err "Sign failed: $_sign_openssl"
|
||||||
_err "Key file: $keyfile"
|
_err "Key file: $keyfile"
|
||||||
@@ -1222,19 +1235,28 @@ _createcsr() {
|
|||||||
|
|
||||||
if [ "$acmeValidationv1" ]; then
|
if [ "$acmeValidationv1" ]; then
|
||||||
domainlist="$(_idn "$domainlist")"
|
domainlist="$(_idn "$domainlist")"
|
||||||
printf -- "\nsubjectAltName=DNS:$domainlist" >>"$csrconf"
|
_debug2 domainlist "$domainlist"
|
||||||
|
alt=""
|
||||||
|
for dl in $(echo "$domainlist" | tr "," ' '); do
|
||||||
|
if [ "$alt" ]; then
|
||||||
|
alt="$alt,$(_getIdType "$dl" | _upper_case):$dl"
|
||||||
|
else
|
||||||
|
alt="$(_getIdType "$dl" | _upper_case):$dl"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
printf -- "\nsubjectAltName=$alt" >>"$csrconf"
|
||||||
elif [ -z "$domainlist" ] || [ "$domainlist" = "$NO_VALUE" ]; then
|
elif [ -z "$domainlist" ] || [ "$domainlist" = "$NO_VALUE" ]; then
|
||||||
#single domain
|
#single domain
|
||||||
_info "Single domain" "$domain"
|
_info "Single domain" "$domain"
|
||||||
printf -- "\nsubjectAltName=DNS:$(_idn "$domain")" >>"$csrconf"
|
printf -- "\nsubjectAltName=$(_getIdType "$domain" | _upper_case):$(_idn "$domain")" >>"$csrconf"
|
||||||
else
|
else
|
||||||
domainlist="$(_idn "$domainlist")"
|
domainlist="$(_idn "$domainlist")"
|
||||||
_debug2 domainlist "$domainlist"
|
_debug2 domainlist "$domainlist"
|
||||||
if _contains "$domainlist" ","; then
|
alt="$(_getIdType "$domain" | _upper_case):$(_idn "$domain")"
|
||||||
alt="DNS:$(_idn "$domain"),DNS:$(echo "$domainlist" | sed "s/,,/,/g" | sed "s/,/,DNS:/g")"
|
for dl in $(echo "'$domainlist'" | sed "s/,/' '/g"); do
|
||||||
else
|
dl=$(echo "$dl" | tr -d "'")
|
||||||
alt="DNS:$(_idn "$domain"),DNS:$domainlist"
|
alt="$alt,$(_getIdType "$dl" | _upper_case):$dl"
|
||||||
fi
|
done
|
||||||
#multi
|
#multi
|
||||||
_info "Multi domain" "$alt"
|
_info "Multi domain" "$alt"
|
||||||
printf -- "\nsubjectAltName=$alt" >>"$csrconf"
|
printf -- "\nsubjectAltName=$alt" >>"$csrconf"
|
||||||
@@ -1251,10 +1273,18 @@ _createcsr() {
|
|||||||
_csr_cn="$(_idn "$domain")"
|
_csr_cn="$(_idn "$domain")"
|
||||||
_debug2 _csr_cn "$_csr_cn"
|
_debug2 _csr_cn "$_csr_cn"
|
||||||
if _contains "$(uname -a)" "MINGW"; then
|
if _contains "$(uname -a)" "MINGW"; then
|
||||||
|
if _isIP "$_csr_cn"; then
|
||||||
|
${ACME_OPENSSL_BIN:-openssl} req -new -sha256 -key "$csrkey" -subj "//O=$PROJECT_NAME" -config "$csrconf" -out "$csr"
|
||||||
|
else
|
||||||
${ACME_OPENSSL_BIN:-openssl} req -new -sha256 -key "$csrkey" -subj "//CN=$_csr_cn" -config "$csrconf" -out "$csr"
|
${ACME_OPENSSL_BIN:-openssl} req -new -sha256 -key "$csrkey" -subj "//CN=$_csr_cn" -config "$csrconf" -out "$csr"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if _isIP "$_csr_cn"; then
|
||||||
|
${ACME_OPENSSL_BIN:-openssl} req -new -sha256 -key "$csrkey" -subj "/O=$PROJECT_NAME" -config "$csrconf" -out "$csr"
|
||||||
else
|
else
|
||||||
${ACME_OPENSSL_BIN:-openssl} req -new -sha256 -key "$csrkey" -subj "/CN=$_csr_cn" -config "$csrconf" -out "$csr"
|
${ACME_OPENSSL_BIN:-openssl} req -new -sha256 -key "$csrkey" -subj "/CN=$_csr_cn" -config "$csrconf" -out "$csr"
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
#_signcsr key csr conf cert
|
#_signcsr key csr conf cert
|
||||||
@@ -1602,6 +1632,24 @@ _stat() {
|
|||||||
return 1 #error, 'stat' not found
|
return 1 #error, 'stat' not found
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#keyfile
|
||||||
|
_isRSA() {
|
||||||
|
keyfile=$1
|
||||||
|
if grep "BEGIN RSA PRIVATE KEY" "$keyfile" >/dev/null 2>&1 || ${ACME_OPENSSL_BIN:-openssl} rsa -in "$keyfile" -noout -text | grep "^publicExponent:" >/dev/null 2>&1; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
#keyfile
|
||||||
|
_isEcc() {
|
||||||
|
keyfile=$1
|
||||||
|
if grep "BEGIN EC PRIVATE KEY" "$keyfile" >/dev/null 2>&1 || ${ACME_OPENSSL_BIN:-openssl} ec -in "$keyfile" -noout -text 2>/dev/null | grep "^NIST CURVE:" >/dev/null 2>&1; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
#keyfile
|
#keyfile
|
||||||
_calcjwk() {
|
_calcjwk() {
|
||||||
keyfile="$1"
|
keyfile="$1"
|
||||||
@@ -1615,7 +1663,7 @@ _calcjwk() {
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if grep "BEGIN RSA PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then
|
if _isRSA "$keyfile"; then
|
||||||
_debug "RSA key"
|
_debug "RSA key"
|
||||||
pub_exp=$(${ACME_OPENSSL_BIN:-openssl} rsa -in "$keyfile" -noout -text | grep "^publicExponent:" | cut -d '(' -f 2 | cut -d 'x' -f 2 | cut -d ')' -f 1)
|
pub_exp=$(${ACME_OPENSSL_BIN:-openssl} rsa -in "$keyfile" -noout -text | grep "^publicExponent:" | cut -d '(' -f 2 | cut -d 'x' -f 2 | cut -d ')' -f 1)
|
||||||
if [ "${#pub_exp}" = "5" ]; then
|
if [ "${#pub_exp}" = "5" ]; then
|
||||||
@@ -1637,7 +1685,7 @@ _calcjwk() {
|
|||||||
JWK_HEADER='{"alg": "RS256", "jwk": '$jwk'}'
|
JWK_HEADER='{"alg": "RS256", "jwk": '$jwk'}'
|
||||||
JWK_HEADERPLACE_PART1='{"nonce": "'
|
JWK_HEADERPLACE_PART1='{"nonce": "'
|
||||||
JWK_HEADERPLACE_PART2='", "alg": "RS256"'
|
JWK_HEADERPLACE_PART2='", "alg": "RS256"'
|
||||||
elif grep "BEGIN EC PRIVATE KEY" "$keyfile" >/dev/null 2>&1; then
|
elif _isEcc "$keyfile"; then
|
||||||
_debug "EC key"
|
_debug "EC key"
|
||||||
crv="$(${ACME_OPENSSL_BIN:-openssl} ec -in "$keyfile" -noout -text 2>/dev/null | grep "^NIST CURVE:" | cut -d ":" -f 2 | tr -d " \r\n")"
|
crv="$(${ACME_OPENSSL_BIN:-openssl} ec -in "$keyfile" -noout -text 2>/dev/null | grep "^NIST CURVE:" | cut -d ":" -f 2 | tr -d " \r\n")"
|
||||||
_debug3 crv "$crv"
|
_debug3 crv "$crv"
|
||||||
@@ -1810,8 +1858,6 @@ _inithttp() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_HTTP_MAX_RETRY=8
|
|
||||||
|
|
||||||
# body url [needbase64] [POST|PUT|DELETE] [ContentType]
|
# body url [needbase64] [POST|PUT|DELETE] [ContentType]
|
||||||
_post() {
|
_post() {
|
||||||
body="$1"
|
body="$1"
|
||||||
@@ -1819,33 +1865,6 @@ _post() {
|
|||||||
needbase64="$3"
|
needbase64="$3"
|
||||||
httpmethod="$4"
|
httpmethod="$4"
|
||||||
_postContentType="$5"
|
_postContentType="$5"
|
||||||
_sleep_retry_sec=1
|
|
||||||
_http_retry_times=0
|
|
||||||
_hcode=0
|
|
||||||
while [ "${_http_retry_times}" -le "$_HTTP_MAX_RETRY" ]; do
|
|
||||||
[ "$_http_retry_times" = "$_HTTP_MAX_RETRY" ]
|
|
||||||
_lastHCode="$?"
|
|
||||||
_debug "Retrying post"
|
|
||||||
_post_impl "$body" "$_post_url" "$needbase64" "$httpmethod" "$_postContentType" "$_lastHCode"
|
|
||||||
_hcode="$?"
|
|
||||||
_debug _hcode "$_hcode"
|
|
||||||
if [ "$_hcode" = "0" ]; then
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
_http_retry_times=$(_math $_http_retry_times + 1)
|
|
||||||
_sleep $_sleep_retry_sec
|
|
||||||
done
|
|
||||||
return $_hcode
|
|
||||||
}
|
|
||||||
|
|
||||||
# body url [needbase64] [POST|PUT|DELETE] [ContentType] [displayError]
|
|
||||||
_post_impl() {
|
|
||||||
body="$1"
|
|
||||||
_post_url="$2"
|
|
||||||
needbase64="$3"
|
|
||||||
httpmethod="$4"
|
|
||||||
_postContentType="$5"
|
|
||||||
displayError="$6"
|
|
||||||
|
|
||||||
if [ -z "$httpmethod" ]; then
|
if [ -z "$httpmethod" ]; then
|
||||||
httpmethod="POST"
|
httpmethod="POST"
|
||||||
@@ -1897,9 +1916,7 @@ _post_impl() {
|
|||||||
fi
|
fi
|
||||||
_ret="$?"
|
_ret="$?"
|
||||||
if [ "$_ret" != "0" ]; then
|
if [ "$_ret" != "0" ]; then
|
||||||
if [ -z "$displayError" ] || [ "$displayError" = "0" ]; then
|
|
||||||
_err "Please refer to https://curl.haxx.se/libcurl/c/libcurl-errors.html for error code: $_ret"
|
_err "Please refer to https://curl.haxx.se/libcurl/c/libcurl-errors.html for error code: $_ret"
|
||||||
fi
|
|
||||||
if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
|
if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
|
||||||
_err "Here is the curl dump log:"
|
_err "Here is the curl dump log:"
|
||||||
_err "$(cat "$_CURL_DUMP")"
|
_err "$(cat "$_CURL_DUMP")"
|
||||||
@@ -1955,10 +1972,8 @@ _post_impl() {
|
|||||||
_debug "wget returns 8, the server returns a 'Bad request' response, lets process the response later."
|
_debug "wget returns 8, the server returns a 'Bad request' response, lets process the response later."
|
||||||
fi
|
fi
|
||||||
if [ "$_ret" != "0" ]; then
|
if [ "$_ret" != "0" ]; then
|
||||||
if [ -z "$displayError" ] || [ "$displayError" = "0" ]; then
|
|
||||||
_err "Please refer to https://www.gnu.org/software/wget/manual/html_node/Exit-Status.html for error code: $_ret"
|
_err "Please refer to https://www.gnu.org/software/wget/manual/html_node/Exit-Status.html for error code: $_ret"
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
_sed_i "s/^ *//g" "$HTTP_HEADER"
|
_sed_i "s/^ *//g" "$HTTP_HEADER"
|
||||||
else
|
else
|
||||||
_ret="$?"
|
_ret="$?"
|
||||||
@@ -1971,38 +1986,13 @@ _post_impl() {
|
|||||||
|
|
||||||
# url getheader timeout
|
# url getheader timeout
|
||||||
_get() {
|
_get() {
|
||||||
url="$1"
|
|
||||||
onlyheader="$2"
|
|
||||||
t="$3"
|
|
||||||
_sleep_retry_sec=1
|
|
||||||
_http_retry_times=0
|
|
||||||
_hcode=0
|
|
||||||
while [ "${_http_retry_times}" -le "$_HTTP_MAX_RETRY" ]; do
|
|
||||||
[ "$_http_retry_times" = "$_HTTP_MAX_RETRY" ]
|
|
||||||
_lastHCode="$?"
|
|
||||||
_debug "Retrying GET"
|
|
||||||
_get_impl "$url" "$onlyheader" "$t" "$_lastHCode"
|
|
||||||
_hcode="$?"
|
|
||||||
_debug _hcode "$_hcode"
|
|
||||||
if [ "$_hcode" = "0" ]; then
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
_http_retry_times=$(_math $_http_retry_times + 1)
|
|
||||||
_sleep $_sleep_retry_sec
|
|
||||||
done
|
|
||||||
return $_hcode
|
|
||||||
}
|
|
||||||
|
|
||||||
# url getheader timeout displayError
|
|
||||||
_get_impl() {
|
|
||||||
_debug GET
|
_debug GET
|
||||||
url="$1"
|
url="$1"
|
||||||
onlyheader="$2"
|
onlyheader="$2"
|
||||||
t="$3"
|
t="$3"
|
||||||
displayError="$4"
|
|
||||||
_debug url "$url"
|
_debug url "$url"
|
||||||
_debug "timeout=$t"
|
_debug "timeout=$t"
|
||||||
_debug "displayError" "$displayError"
|
|
||||||
_inithttp
|
_inithttp
|
||||||
|
|
||||||
if [ "$_ACME_CURL" ] && [ "${ACME_USE_WGET:-0}" = "0" ]; then
|
if [ "$_ACME_CURL" ] && [ "${ACME_USE_WGET:-0}" = "0" ]; then
|
||||||
@@ -2021,9 +2011,7 @@ _get_impl() {
|
|||||||
fi
|
fi
|
||||||
ret=$?
|
ret=$?
|
||||||
if [ "$ret" != "0" ]; then
|
if [ "$ret" != "0" ]; then
|
||||||
if [ -z "$displayError" ] || [ "$displayError" = "0" ]; then
|
|
||||||
_err "Please refer to https://curl.haxx.se/libcurl/c/libcurl-errors.html for error code: $ret"
|
_err "Please refer to https://curl.haxx.se/libcurl/c/libcurl-errors.html for error code: $ret"
|
||||||
fi
|
|
||||||
if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
|
if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
|
||||||
_err "Here is the curl dump log:"
|
_err "Here is the curl dump log:"
|
||||||
_err "$(cat "$_CURL_DUMP")"
|
_err "$(cat "$_CURL_DUMP")"
|
||||||
@@ -2049,10 +2037,8 @@ _get_impl() {
|
|||||||
_debug "wget returns 8, the server returns a 'Bad request' response, lets process the response later."
|
_debug "wget returns 8, the server returns a 'Bad request' response, lets process the response later."
|
||||||
fi
|
fi
|
||||||
if [ "$ret" != "0" ]; then
|
if [ "$ret" != "0" ]; then
|
||||||
if [ -z "$displayError" ] || [ "$displayError" = "0" ]; then
|
|
||||||
_err "Please refer to https://www.gnu.org/software/wget/manual/html_node/Exit-Status.html for error code: $ret"
|
_err "Please refer to https://www.gnu.org/software/wget/manual/html_node/Exit-Status.html for error code: $ret"
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
else
|
else
|
||||||
ret=$?
|
ret=$?
|
||||||
_err "Neither curl nor wget is found, can not do GET."
|
_err "Neither curl nor wget is found, can not do GET."
|
||||||
@@ -3168,7 +3154,7 @@ _checkConf() {
|
|||||||
for included in $(cat "$2" | tr "\t" " " | grep "^ *include *.*;" | sed "s/include //" | tr -d " ;"); do
|
for included in $(cat "$2" | tr "\t" " " | grep "^ *include *.*;" | sed "s/include //" | tr -d " ;"); do
|
||||||
_debug "check included $included"
|
_debug "check included $included"
|
||||||
if ! _startswith "$included" "/" && _exists dirname; then
|
if ! _startswith "$included" "/" && _exists dirname; then
|
||||||
_relpath="$(dirname "$_c_file")"
|
_relpath="$(dirname "$2")"
|
||||||
_debug "_relpath" "$_relpath"
|
_debug "_relpath" "$_relpath"
|
||||||
included="$_relpath/$included"
|
included="$_relpath/$included"
|
||||||
fi
|
fi
|
||||||
@@ -4174,6 +4160,41 @@ _match_issuer() {
|
|||||||
_contains "$_rootissuer" "$_missuer"
|
_contains "$_rootissuer" "$_missuer"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ip
|
||||||
|
_isIPv4() {
|
||||||
|
for seg in $(echo "$1" | tr '.' ' '); do
|
||||||
|
_debug2 seg "$seg"
|
||||||
|
if [ "$(echo "$seg" | tr -d [0-9])" ]; then
|
||||||
|
#not all number
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
if [ $seg -ge 0 ] && [ $seg -lt 256 ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
done
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
#ip6
|
||||||
|
_isIPv6() {
|
||||||
|
_contains "$1" ":"
|
||||||
|
}
|
||||||
|
|
||||||
|
#ip
|
||||||
|
_isIP() {
|
||||||
|
_isIPv4 "$1" || _isIPv6 "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
#identifier
|
||||||
|
_getIdType() {
|
||||||
|
if _isIP "$1"; then
|
||||||
|
echo "$ID_TYPE_IP"
|
||||||
|
else
|
||||||
|
echo "$ID_TYPE_DNS"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
#webroot, domain domainlist keylength
|
#webroot, domain domainlist keylength
|
||||||
issue() {
|
issue() {
|
||||||
if [ -z "$2" ]; then
|
if [ -z "$2" ]; then
|
||||||
@@ -4222,12 +4243,6 @@ issue() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_debug "Using ACME_DIRECTORY: $ACME_DIRECTORY"
|
|
||||||
|
|
||||||
if ! _initAPI; then
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -f "$DOMAIN_CONF" ]; then
|
if [ -f "$DOMAIN_CONF" ]; then
|
||||||
Le_NextRenewTime=$(_readdomainconf Le_NextRenewTime)
|
Le_NextRenewTime=$(_readdomainconf Le_NextRenewTime)
|
||||||
_debug Le_NextRenewTime "$Le_NextRenewTime"
|
_debug Le_NextRenewTime "$Le_NextRenewTime"
|
||||||
@@ -4247,6 +4262,11 @@ issue() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
_debug "Using ACME_DIRECTORY: $ACME_DIRECTORY"
|
||||||
|
if ! _initAPI; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
_savedomainconf "Le_Domain" "$_main_domain"
|
_savedomainconf "Le_Domain" "$_main_domain"
|
||||||
_savedomainconf "Le_Alt" "$_alt_domains"
|
_savedomainconf "Le_Alt" "$_alt_domains"
|
||||||
_savedomainconf "Le_Webroot" "$_web_roots"
|
_savedomainconf "Le_Webroot" "$_web_roots"
|
||||||
@@ -4331,7 +4351,7 @@ issue() {
|
|||||||
dvsep=','
|
dvsep=','
|
||||||
if [ -z "$vlist" ]; then
|
if [ -z "$vlist" ]; then
|
||||||
#make new order request
|
#make new order request
|
||||||
_identifiers="{\"type\":\"dns\",\"value\":\"$(_idn "$_main_domain")\"}"
|
_identifiers="{\"type\":\"$(_getIdType "$_main_domain")\",\"value\":\"$(_idn "$_main_domain")\"}"
|
||||||
_w_index=1
|
_w_index=1
|
||||||
while true; do
|
while true; do
|
||||||
d="$(echo "$_alt_domains," | cut -d , -f "$_w_index")"
|
d="$(echo "$_alt_domains," | cut -d , -f "$_w_index")"
|
||||||
@@ -4340,7 +4360,7 @@ issue() {
|
|||||||
if [ -z "$d" ]; then
|
if [ -z "$d" ]; then
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
_identifiers="$_identifiers,{\"type\":\"dns\",\"value\":\"$(_idn "$d")\"}"
|
_identifiers="$_identifiers,{\"type\":\"$(_getIdType "$d")\",\"value\":\"$(_idn "$d")\"}"
|
||||||
done
|
done
|
||||||
_debug2 _identifiers "$_identifiers"
|
_debug2 _identifiers "$_identifiers"
|
||||||
if ! _send_signed_request "$ACME_NEW_ORDER" "{\"identifiers\": [$_identifiers]}"; then
|
if ! _send_signed_request "$ACME_NEW_ORDER" "{\"identifiers\": [$_identifiers]}"; then
|
||||||
@@ -5101,7 +5121,7 @@ renew() {
|
|||||||
_isEcc="$2"
|
_isEcc="$2"
|
||||||
|
|
||||||
_initpath "$Le_Domain" "$_isEcc"
|
_initpath "$Le_Domain" "$_isEcc"
|
||||||
|
_set_level=${NOTIFY_LEVEL:-$NOTIFY_LEVEL_DEFAULT}
|
||||||
_info "$(__green "Renew: '$Le_Domain'")"
|
_info "$(__green "Renew: '$Le_Domain'")"
|
||||||
if [ ! -f "$DOMAIN_CONF" ]; then
|
if [ ! -f "$DOMAIN_CONF" ]; then
|
||||||
_info "'$Le_Domain' is not an issued domain, skip."
|
_info "'$Le_Domain' is not an issued domain, skip."
|
||||||
@@ -5131,12 +5151,16 @@ renew() {
|
|||||||
CA_CONF=""
|
CA_CONF=""
|
||||||
_debug3 "initpath again."
|
_debug3 "initpath again."
|
||||||
_initpath "$Le_Domain" "$_isEcc"
|
_initpath "$Le_Domain" "$_isEcc"
|
||||||
_initAPI
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "$FORCE" ] && [ "$Le_NextRenewTime" ] && [ "$(_time)" -lt "$Le_NextRenewTime" ]; then
|
if [ -z "$FORCE" ] && [ "$Le_NextRenewTime" ] && [ "$(_time)" -lt "$Le_NextRenewTime" ]; then
|
||||||
_info "Skip, Next renewal time is: $(__green "$Le_NextRenewTimeStr")"
|
_info "Skip, Next renewal time is: $(__green "$Le_NextRenewTimeStr")"
|
||||||
_info "Add '$(__red '--force')' to force to renew."
|
_info "Add '$(__red '--force')' to force to renew."
|
||||||
|
if [ -z "$_ACME_IN_RENEWALL" ]; then
|
||||||
|
if [ $_set_level -ge $NOTIFY_LEVEL_SKIP ]; then
|
||||||
|
_send_notify "Renew $Le_Domain skipped" "Good, the cert is skipped." "$NOTIFY_HOOK" "$RENEW_SKIP"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
return "$RENEW_SKIP"
|
return "$RENEW_SKIP"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -5163,6 +5187,17 @@ renew() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
_ACME_IS_RENEW=""
|
_ACME_IS_RENEW=""
|
||||||
|
if [ -z "$_ACME_IN_RENEWALL" ]; then
|
||||||
|
if [ "$res" = "0" ]; then
|
||||||
|
if [ $_set_level -ge $NOTIFY_LEVEL_RENEW ]; then
|
||||||
|
_send_notify "Renew $d success" "Good, the cert is renewed." "$NOTIFY_HOOK" 0
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if [ $_set_level -ge $NOTIFY_LEVEL_ERROR ]; then
|
||||||
|
_send_notify "Renew $d error" "There is an error." "$NOTIFY_HOOK" 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
return "$res"
|
return "$res"
|
||||||
}
|
}
|
||||||
@@ -5180,6 +5215,7 @@ renewAll() {
|
|||||||
_notify_code=$RENEW_SKIP
|
_notify_code=$RENEW_SKIP
|
||||||
_set_level=${NOTIFY_LEVEL:-$NOTIFY_LEVEL_DEFAULT}
|
_set_level=${NOTIFY_LEVEL:-$NOTIFY_LEVEL_DEFAULT}
|
||||||
_debug "_set_level" "$_set_level"
|
_debug "_set_level" "$_set_level"
|
||||||
|
export _ACME_IN_RENEWALL=1
|
||||||
for di in "${CERT_HOME}"/*.*/; do
|
for di in "${CERT_HOME}"/*.*/; do
|
||||||
_debug di "$di"
|
_debug di "$di"
|
||||||
if ! [ -d "$di" ]; then
|
if ! [ -d "$di" ]; then
|
||||||
@@ -5202,13 +5238,13 @@ renewAll() {
|
|||||||
_error_level="$NOTIFY_LEVEL_RENEW"
|
_error_level="$NOTIFY_LEVEL_RENEW"
|
||||||
_notify_code=0
|
_notify_code=0
|
||||||
fi
|
fi
|
||||||
if [ "$_ACME_IN_CRON" ]; then
|
|
||||||
if [ $_set_level -ge $NOTIFY_LEVEL_RENEW ]; then
|
if [ $_set_level -ge $NOTIFY_LEVEL_RENEW ]; then
|
||||||
if [ "$NOTIFY_MODE" = "$NOTIFY_MODE_CERT" ]; then
|
if [ "$NOTIFY_MODE" = "$NOTIFY_MODE_CERT" ]; then
|
||||||
_send_notify "Renew $d success" "Good, the cert is renewed." "$NOTIFY_HOOK" 0
|
_send_notify "Renew $d success" "Good, the cert is renewed." "$NOTIFY_HOOK" 0
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
_success_msg="${_success_msg} $d
|
_success_msg="${_success_msg} $d
|
||||||
"
|
"
|
||||||
elif [ "$rc" = "$RENEW_SKIP" ]; then
|
elif [ "$rc" = "$RENEW_SKIP" ]; then
|
||||||
@@ -5216,13 +5252,13 @@ renewAll() {
|
|||||||
_error_level="$NOTIFY_LEVEL_SKIP"
|
_error_level="$NOTIFY_LEVEL_SKIP"
|
||||||
_notify_code=$RENEW_SKIP
|
_notify_code=$RENEW_SKIP
|
||||||
fi
|
fi
|
||||||
if [ "$_ACME_IN_CRON" ]; then
|
|
||||||
if [ $_set_level -ge $NOTIFY_LEVEL_SKIP ]; then
|
if [ $_set_level -ge $NOTIFY_LEVEL_SKIP ]; then
|
||||||
if [ "$NOTIFY_MODE" = "$NOTIFY_MODE_CERT" ]; then
|
if [ "$NOTIFY_MODE" = "$NOTIFY_MODE_CERT" ]; then
|
||||||
_send_notify "Renew $d skipped" "Good, the cert is skipped." "$NOTIFY_HOOK" "$RENEW_SKIP"
|
_send_notify "Renew $d skipped" "Good, the cert is skipped." "$NOTIFY_HOOK" "$RENEW_SKIP"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
_info "Skipped $d"
|
_info "Skipped $d"
|
||||||
_skipped_msg="${_skipped_msg} $d
|
_skipped_msg="${_skipped_msg} $d
|
||||||
"
|
"
|
||||||
@@ -5231,13 +5267,13 @@ renewAll() {
|
|||||||
_error_level="$NOTIFY_LEVEL_ERROR"
|
_error_level="$NOTIFY_LEVEL_ERROR"
|
||||||
_notify_code=1
|
_notify_code=1
|
||||||
fi
|
fi
|
||||||
if [ "$_ACME_IN_CRON" ]; then
|
|
||||||
if [ $_set_level -ge $NOTIFY_LEVEL_ERROR ]; then
|
if [ $_set_level -ge $NOTIFY_LEVEL_ERROR ]; then
|
||||||
if [ "$NOTIFY_MODE" = "$NOTIFY_MODE_CERT" ]; then
|
if [ "$NOTIFY_MODE" = "$NOTIFY_MODE_CERT" ]; then
|
||||||
_send_notify "Renew $d error" "There is an error." "$NOTIFY_HOOK" 1
|
_send_notify "Renew $d error" "There is an error." "$NOTIFY_HOOK" 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
_error_msg="${_error_msg} $d
|
_error_msg="${_error_msg} $d
|
||||||
"
|
"
|
||||||
if [ "$_stopRenewOnError" ]; then
|
if [ "$_stopRenewOnError" ]; then
|
||||||
@@ -5252,7 +5288,7 @@ renewAll() {
|
|||||||
done
|
done
|
||||||
_debug _error_level "$_error_level"
|
_debug _error_level "$_error_level"
|
||||||
_debug _set_level "$_set_level"
|
_debug _set_level "$_set_level"
|
||||||
if [ "$_ACME_IN_CRON" ] && [ $_error_level -le $_set_level ]; then
|
if [ $_error_level -le $_set_level ]; then
|
||||||
if [ -z "$NOTIFY_MODE" ] || [ "$NOTIFY_MODE" = "$NOTIFY_MODE_BULK" ]; then
|
if [ -z "$NOTIFY_MODE" ] || [ "$NOTIFY_MODE" = "$NOTIFY_MODE_BULK" ]; then
|
||||||
_msg_subject="Renew"
|
_msg_subject="Renew"
|
||||||
if [ "$_error_msg" ]; then
|
if [ "$_error_msg" ]; then
|
||||||
@@ -5675,10 +5711,18 @@ installcronjob() {
|
|||||||
_CRONTAB="crontab"
|
_CRONTAB="crontab"
|
||||||
if [ -f "$LE_WORKING_DIR/$PROJECT_ENTRY" ]; then
|
if [ -f "$LE_WORKING_DIR/$PROJECT_ENTRY" ]; then
|
||||||
lesh="\"$LE_WORKING_DIR\"/$PROJECT_ENTRY"
|
lesh="\"$LE_WORKING_DIR\"/$PROJECT_ENTRY"
|
||||||
|
else
|
||||||
|
_debug "_SCRIPT_" "$_SCRIPT_"
|
||||||
|
_script="$(_readlink "$_SCRIPT_")"
|
||||||
|
_debug _script "$_script"
|
||||||
|
if [ -f "$_script" ]; then
|
||||||
|
_info "Using the current script from: $_script"
|
||||||
|
lesh="$_script"
|
||||||
else
|
else
|
||||||
_err "Can not install cronjob, $PROJECT_ENTRY not found."
|
_err "Can not install cronjob, $PROJECT_ENTRY not found."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
if [ "$_c_home" ]; then
|
if [ "$_c_home" ]; then
|
||||||
_c_entry="--config-home \"$_c_home\" "
|
_c_entry="--config-home \"$_c_home\" "
|
||||||
fi
|
fi
|
||||||
@@ -5904,7 +5948,7 @@ _deactivate() {
|
|||||||
_initAPI
|
_initAPI
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_identifiers="{\"type\":\"dns\",\"value\":\"$_d_domain\"}"
|
_identifiers="{\"type\":\"$(_getIdType "$_d_domain")\",\"value\":\"$_d_domain\"}"
|
||||||
if ! _send_signed_request "$ACME_NEW_ORDER" "{\"identifiers\": [$_identifiers]}"; then
|
if ! _send_signed_request "$ACME_NEW_ORDER" "{\"identifiers\": [$_identifiers]}"; then
|
||||||
_err "Can not get domain new order."
|
_err "Can not get domain new order."
|
||||||
return 1
|
return 1
|
||||||
@@ -5940,7 +5984,7 @@ _deactivate() {
|
|||||||
thumbprint="$(__calc_account_thumbprint)"
|
thumbprint="$(__calc_account_thumbprint)"
|
||||||
fi
|
fi
|
||||||
_debug "Trigger validation."
|
_debug "Trigger validation."
|
||||||
vtype="$VTYPE_DNS"
|
vtype="$(_getIdType "$_d_domain")"
|
||||||
entry="$(echo "$response" | _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*')"
|
entry="$(echo "$response" | _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*')"
|
||||||
_debug entry "$entry"
|
_debug entry "$entry"
|
||||||
if [ -z "$entry" ]; then
|
if [ -z "$entry" ]; then
|
||||||
@@ -6532,6 +6576,7 @@ Commands:
|
|||||||
--revoke Revoke a cert.
|
--revoke Revoke a cert.
|
||||||
--remove Remove the cert from list of certs known to $PROJECT_NAME.
|
--remove Remove the cert from list of certs known to $PROJECT_NAME.
|
||||||
--list List all the certs.
|
--list List all the certs.
|
||||||
|
--info Show the $PROJECT_NAME configs, or the configs for a domain with [-d domain] parameter.
|
||||||
--to-pkcs12 Export the certificate and key to a pfx file.
|
--to-pkcs12 Export the certificate and key to a pfx file.
|
||||||
--to-pkcs8 Convert to pkcs8 format.
|
--to-pkcs8 Convert to pkcs8 format.
|
||||||
--sign-csr Issue a cert from an existing csr.
|
--sign-csr Issue a cert from an existing csr.
|
||||||
@@ -6849,6 +6894,28 @@ setdefaultchain() {
|
|||||||
_savecaconf "DEFAULT_PREFERRED_CHAIN" "$_preferred_chain"
|
_savecaconf "DEFAULT_PREFERRED_CHAIN" "$_preferred_chain"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#domain ecc
|
||||||
|
info() {
|
||||||
|
_domain="$1"
|
||||||
|
_ecc="$2"
|
||||||
|
_initpath
|
||||||
|
if [ -z "$_domain" ]; then
|
||||||
|
_debug "Show global configs"
|
||||||
|
echo "LE_WORKING_DIR=$LE_WORKING_DIR"
|
||||||
|
echo "LE_CONFIG_HOME=$LE_CONFIG_HOME"
|
||||||
|
cat "$ACCOUNT_CONF_PATH"
|
||||||
|
else
|
||||||
|
_debug "Show domain configs"
|
||||||
|
(
|
||||||
|
_initpath "$_domain" "$_ecc"
|
||||||
|
echo "DOMAIN_CONF=$DOMAIN_CONF"
|
||||||
|
for seg in $(cat $DOMAIN_CONF | cut -d = -f 1); do
|
||||||
|
echo "$seg=$(_readdomainconf "$seg")"
|
||||||
|
done
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
_process() {
|
_process() {
|
||||||
_CMD=""
|
_CMD=""
|
||||||
_domain=""
|
_domain=""
|
||||||
@@ -6958,6 +7025,9 @@ _process() {
|
|||||||
--list)
|
--list)
|
||||||
_CMD="list"
|
_CMD="list"
|
||||||
;;
|
;;
|
||||||
|
--info)
|
||||||
|
_CMD="info"
|
||||||
|
;;
|
||||||
--install-cronjob | --installcronjob)
|
--install-cronjob | --installcronjob)
|
||||||
_CMD="installcronjob"
|
_CMD="installcronjob"
|
||||||
;;
|
;;
|
||||||
@@ -7509,6 +7579,9 @@ _process() {
|
|||||||
list)
|
list)
|
||||||
list "$_listraw" "$_domain"
|
list "$_listraw" "$_domain"
|
||||||
;;
|
;;
|
||||||
|
info)
|
||||||
|
info "$_domain" "$_ecc"
|
||||||
|
;;
|
||||||
installcronjob) installcronjob "$_confighome" ;;
|
installcronjob) installcronjob "$_confighome" ;;
|
||||||
uninstallcronjob) uninstallcronjob ;;
|
uninstallcronjob) uninstallcronjob ;;
|
||||||
cron) cron ;;
|
cron) cron ;;
|
||||||
|
|||||||
@@ -36,43 +36,51 @@ fritzbox_deploy() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_fritzbox_username="${DEPLOY_FRITZBOX_USERNAME}"
|
# Clear traces of incorrectly stored values
|
||||||
_fritzbox_password="${DEPLOY_FRITZBOX_PASSWORD}"
|
_clearaccountconf DEPLOY_FRITZBOX_USERNAME
|
||||||
_fritzbox_url="${DEPLOY_FRITZBOX_URL}"
|
_clearaccountconf DEPLOY_FRITZBOX_PASSWORD
|
||||||
|
_clearaccountconf DEPLOY_FRITZBOX_URL
|
||||||
|
|
||||||
_debug _fritzbox_url "$_fritzbox_url"
|
# Read config from saved values or env
|
||||||
_debug _fritzbox_username "$_fritzbox_username"
|
_getdeployconf DEPLOY_FRITZBOX_USERNAME
|
||||||
_secure_debug _fritzbox_password "$_fritzbox_password"
|
_getdeployconf DEPLOY_FRITZBOX_PASSWORD
|
||||||
if [ -z "$_fritzbox_username" ]; then
|
_getdeployconf DEPLOY_FRITZBOX_URL
|
||||||
|
|
||||||
|
_debug DEPLOY_FRITZBOX_URL "$DEPLOY_FRITZBOX_URL"
|
||||||
|
_debug DEPLOY_FRITZBOX_USERNAME "$DEPLOY_FRITZBOX_USERNAME"
|
||||||
|
_secure_debug DEPLOY_FRITZBOX_PASSWORD "$DEPLOY_FRITZBOX_PASSWORD"
|
||||||
|
|
||||||
|
if [ -z "$DEPLOY_FRITZBOX_USERNAME" ]; then
|
||||||
_err "FRITZ!Box username is not found, please define DEPLOY_FRITZBOX_USERNAME."
|
_err "FRITZ!Box username is not found, please define DEPLOY_FRITZBOX_USERNAME."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
if [ -z "$_fritzbox_password" ]; then
|
if [ -z "$DEPLOY_FRITZBOX_PASSWORD" ]; then
|
||||||
_err "FRITZ!Box password is not found, please define DEPLOY_FRITZBOX_PASSWORD."
|
_err "FRITZ!Box password is not found, please define DEPLOY_FRITZBOX_PASSWORD."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
if [ -z "$_fritzbox_url" ]; then
|
if [ -z "$DEPLOY_FRITZBOX_URL" ]; then
|
||||||
_err "FRITZ!Box url is not found, please define DEPLOY_FRITZBOX_URL."
|
_err "FRITZ!Box url is not found, please define DEPLOY_FRITZBOX_URL."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_saveaccountconf DEPLOY_FRITZBOX_USERNAME "${_fritzbox_username}"
|
# Save current values
|
||||||
_saveaccountconf DEPLOY_FRITZBOX_PASSWORD "${_fritzbox_password}"
|
_savedeployconf DEPLOY_FRITZBOX_USERNAME "$DEPLOY_FRITZBOX_USERNAME"
|
||||||
_saveaccountconf DEPLOY_FRITZBOX_URL "${_fritzbox_url}"
|
_savedeployconf DEPLOY_FRITZBOX_PASSWORD "$DEPLOY_FRITZBOX_PASSWORD"
|
||||||
|
_savedeployconf DEPLOY_FRITZBOX_URL "$DEPLOY_FRITZBOX_URL"
|
||||||
|
|
||||||
# Do not check for a valid SSL certificate, because initially the cert is not valid, so it could not install the LE generated certificate
|
# Do not check for a valid SSL certificate, because initially the cert is not valid, so it could not install the LE generated certificate
|
||||||
export HTTPS_INSECURE=1
|
export HTTPS_INSECURE=1
|
||||||
|
|
||||||
_info "Log in to the FRITZ!Box"
|
_info "Log in to the FRITZ!Box"
|
||||||
_fritzbox_challenge="$(_get "${_fritzbox_url}/login_sid.lua" | sed -e 's/^.*<Challenge>//' -e 's/<\/Challenge>.*$//')"
|
_fritzbox_challenge="$(_get "${DEPLOY_FRITZBOX_URL}/login_sid.lua" | sed -e 's/^.*<Challenge>//' -e 's/<\/Challenge>.*$//')"
|
||||||
if _exists iconv; then
|
if _exists iconv; then
|
||||||
_fritzbox_hash="$(printf "%s-%s" "${_fritzbox_challenge}" "${_fritzbox_password}" | iconv -f ASCII -t UTF16LE | _digest md5 hex)"
|
_fritzbox_hash="$(printf "%s-%s" "${_fritzbox_challenge}" "${DEPLOY_FRITZBOX_PASSWORD}" | iconv -f ASCII -t UTF16LE | _digest md5 hex)"
|
||||||
elif _exists uconv; then
|
elif _exists uconv; then
|
||||||
_fritzbox_hash="$(printf "%s-%s" "${_fritzbox_challenge}" "${_fritzbox_password}" | uconv -f ASCII -t UTF16LE | _digest md5 hex)"
|
_fritzbox_hash="$(printf "%s-%s" "${_fritzbox_challenge}" "${DEPLOY_FRITZBOX_PASSWORD}" | uconv -f ASCII -t UTF16LE | _digest md5 hex)"
|
||||||
else
|
else
|
||||||
_fritzbox_hash="$(printf "%s-%s" "${_fritzbox_challenge}" "${_fritzbox_password}" | perl -p -e 'use Encode qw/encode/; print encode("UTF-16LE","$_"); $_="";' | _digest md5 hex)"
|
_fritzbox_hash="$(printf "%s-%s" "${_fritzbox_challenge}" "${DEPLOY_FRITZBOX_PASSWORD}" | perl -p -e 'use Encode qw/encode/; print encode("UTF-16LE","$_"); $_="";' | _digest md5 hex)"
|
||||||
fi
|
fi
|
||||||
_fritzbox_sid="$(_get "${_fritzbox_url}/login_sid.lua?sid=0000000000000000&username=${_fritzbox_username}&response=${_fritzbox_challenge}-${_fritzbox_hash}" | sed -e 's/^.*<SID>//' -e 's/<\/SID>.*$//')"
|
_fritzbox_sid="$(_get "${DEPLOY_FRITZBOX_URL}/login_sid.lua?sid=0000000000000000&username=${DEPLOY_FRITZBOX_USERNAME}&response=${_fritzbox_challenge}-${_fritzbox_hash}" | sed -e 's/^.*<SID>//' -e 's/<\/SID>.*$//')"
|
||||||
|
|
||||||
if [ -z "${_fritzbox_sid}" ] || [ "${_fritzbox_sid}" = "0000000000000000" ]; then
|
if [ -z "${_fritzbox_sid}" ] || [ "${_fritzbox_sid}" = "0000000000000000" ]; then
|
||||||
_err "Logging in to the FRITZ!Box failed. Please check username, password and URL."
|
_err "Logging in to the FRITZ!Box failed. Please check username, password and URL."
|
||||||
@@ -104,7 +112,7 @@ fritzbox_deploy() {
|
|||||||
_info "Upload certificate to the FRITZ!Box"
|
_info "Upload certificate to the FRITZ!Box"
|
||||||
|
|
||||||
export _H1="Content-type: multipart/form-data boundary=${_post_boundary}"
|
export _H1="Content-type: multipart/form-data boundary=${_post_boundary}"
|
||||||
_post "$(cat "${_post_request}")" "${_fritzbox_url}/cgi-bin/firmwarecfg" | grep SSL
|
_post "$(cat "${_post_request}")" "${DEPLOY_FRITZBOX_URL}/cgi-bin/firmwarecfg" | grep SSL
|
||||||
|
|
||||||
retval=$?
|
retval=$?
|
||||||
if [ $retval = 0 ]; then
|
if [ $retval = 0 ]; then
|
||||||
|
|||||||
156
deploy/openmediavault.sh
Normal file
156
deploy/openmediavault.sh
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
# This deploy hook is tested on OpenMediaVault 5.x. It supports both local and remote deployment.
|
||||||
|
# The way it works is that if a cert with the matching domain name is not found, it will firstly create a dummy cert to get its uuid, and then replace it with your cert.
|
||||||
|
#
|
||||||
|
# DEPLOY_OMV_WEBUI_ADMIN - This is OMV web gui admin account. Default value is admin. It's required as the user parameter (-u) for the omv-rpc command.
|
||||||
|
# DEPLOY_OMV_HOST and DEPLOY_OMV_SSH_USER are optional. They are used for remote deployment through ssh (support public key authentication only). Per design, OMV web gui admin doesn't have ssh permission, so another account is needed for ssh.
|
||||||
|
#
|
||||||
|
# returns 0 means success, otherwise error.
|
||||||
|
|
||||||
|
######## Public functions #####################
|
||||||
|
|
||||||
|
#domain keyfile certfile cafile fullchain
|
||||||
|
openmediavault_deploy() {
|
||||||
|
_cdomain="$1"
|
||||||
|
_ckey="$2"
|
||||||
|
_ccert="$3"
|
||||||
|
_cca="$4"
|
||||||
|
_cfullchain="$5"
|
||||||
|
|
||||||
|
_debug _cdomain "$_cdomain"
|
||||||
|
_debug _ckey "$_ckey"
|
||||||
|
_debug _ccert "$_ccert"
|
||||||
|
_debug _cca "$_cca"
|
||||||
|
_debug _cfullchain "$_cfullchain"
|
||||||
|
|
||||||
|
_getdeployconf DEPLOY_OMV_WEBUI_ADMIN
|
||||||
|
|
||||||
|
if [ -z "$DEPLOY_OMV_WEBUI_ADMIN" ]; then
|
||||||
|
DEPLOY_OMV_WEBUI_ADMIN="admin"
|
||||||
|
fi
|
||||||
|
|
||||||
|
_savedeployconf DEPLOY_OMV_WEBUI_ADMIN "$DEPLOY_OMV_WEBUI_ADMIN"
|
||||||
|
|
||||||
|
_getdeployconf DEPLOY_OMV_HOST
|
||||||
|
_getdeployconf DEPLOY_OMV_SSH_USER
|
||||||
|
|
||||||
|
if [ -n "$DEPLOY_OMV_HOST" ] && [ -n "$DEPLOY_OMV_SSH_USER" ]; then
|
||||||
|
_info "[OMV deploy-hook] Deploy certificate remotely through ssh."
|
||||||
|
_savedeployconf DEPLOY_OMV_HOST "$DEPLOY_OMV_HOST"
|
||||||
|
_savedeployconf DEPLOY_OMV_SSH_USER "$DEPLOY_OMV_SSH_USER"
|
||||||
|
else
|
||||||
|
_info "[OMV deploy-hook] Deploy certificate locally."
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$DEPLOY_OMV_HOST" ] && [ -n "$DEPLOY_OMV_SSH_USER" ]; then
|
||||||
|
|
||||||
|
_command="omv-rpc -u $DEPLOY_OMV_WEBUI_ADMIN 'CertificateMgmt' 'getList' '{\"start\": 0, \"limit\": -1}' | jq -r '.data[] | select(.name==\"/CN='$_cdomain'\") | .uuid'"
|
||||||
|
# shellcheck disable=SC2029
|
||||||
|
_uuid=$(ssh "$DEPLOY_OMV_SSH_USER@$DEPLOY_OMV_HOST" "$_command")
|
||||||
|
_debug _command "$_command"
|
||||||
|
|
||||||
|
if [ -z "$_uuid" ]; then
|
||||||
|
_info "[OMV deploy-hook] Domain $_cdomain has no certificate in openmediavault, creating it!"
|
||||||
|
_command="omv-rpc -u $DEPLOY_OMV_WEBUI_ADMIN 'CertificateMgmt' 'create' '{\"cn\": \"test.example.com\", \"size\": 4096, \"days\": 3650, \"c\": \"\", \"st\": \"\", \"l\": \"\", \"o\": \"\", \"ou\": \"\", \"email\": \"\"}' | jq -r '.uuid'"
|
||||||
|
# shellcheck disable=SC2029
|
||||||
|
_uuid=$(ssh "$DEPLOY_OMV_SSH_USER@$DEPLOY_OMV_HOST" "$_command")
|
||||||
|
_debug _command "$_command"
|
||||||
|
|
||||||
|
if [ -z "$_uuid" ]; then
|
||||||
|
_err "[OMV deploy-hook] An error occured while creating the certificate"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
_info "[OMV deploy-hook] Domain $_cdomain has uuid: $_uuid"
|
||||||
|
_fullchain=$(jq <"$_cfullchain" -aRs .)
|
||||||
|
_key=$(jq <"$_ckey" -aRs .)
|
||||||
|
|
||||||
|
_debug _fullchain "$_fullchain"
|
||||||
|
_debug _key "$_key"
|
||||||
|
|
||||||
|
_info "[OMV deploy-hook] Updating key and certificate in openmediavault"
|
||||||
|
_command="omv-rpc -u $DEPLOY_OMV_WEBUI_ADMIN 'CertificateMgmt' 'set' '{\"uuid\":\"$_uuid\", \"certificate\":$_fullchain, \"privatekey\":$_key, \"comment\":\"acme.sh deployed $(date)\"}'"
|
||||||
|
# shellcheck disable=SC2029
|
||||||
|
_result=$(ssh "$DEPLOY_OMV_SSH_USER@$DEPLOY_OMV_HOST" "$_command")
|
||||||
|
|
||||||
|
_debug _command "$_command"
|
||||||
|
_debug _result "$_result"
|
||||||
|
|
||||||
|
_command="omv-rpc -u $DEPLOY_OMV_WEBUI_ADMIN 'WebGui' 'setSettings' \$(omv-rpc -u $DEPLOY_OMV_WEBUI_ADMIN 'WebGui' 'getSettings' | jq -c '.sslcertificateref=\"$_uuid\"')"
|
||||||
|
# shellcheck disable=SC2029
|
||||||
|
_result=$(ssh "$DEPLOY_OMV_SSH_USER@$DEPLOY_OMV_HOST" "$_command")
|
||||||
|
|
||||||
|
_debug _command "$_command"
|
||||||
|
_debug _result "$_result"
|
||||||
|
|
||||||
|
_info "[OMV deploy-hook] Asking openmediavault to apply changes... (this could take some time, hang in there)"
|
||||||
|
_command="omv-rpc -u $DEPLOY_OMV_WEBUI_ADMIN 'Config' 'applyChanges' '{\"modules\":[], \"force\": false}'"
|
||||||
|
# shellcheck disable=SC2029
|
||||||
|
_result=$(ssh "$DEPLOY_OMV_SSH_USER@$DEPLOY_OMV_HOST" "$_command")
|
||||||
|
|
||||||
|
_debug _command "$_command"
|
||||||
|
_debug _result "$_result"
|
||||||
|
|
||||||
|
_info "[OMV deploy-hook] Asking nginx to reload"
|
||||||
|
_command="nginx -s reload"
|
||||||
|
# shellcheck disable=SC2029
|
||||||
|
_result=$(ssh "$DEPLOY_OMV_SSH_USER@$DEPLOY_OMV_HOST" "$_command")
|
||||||
|
|
||||||
|
_debug _command "$_command"
|
||||||
|
_debug _result "$_result"
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
_uuid=$(omv-rpc -u $DEPLOY_OMV_WEBUI_ADMIN 'CertificateMgmt' 'getList' '{"start": 0, "limit": -1}' | jq -r '.data[] | select(.name=="/CN='$_cdomain'") | .uuid')
|
||||||
|
if [ -z "$_uuid" ]; then
|
||||||
|
_info "[OMV deploy-hook] Domain $_cdomain has no certificate in openmediavault, creating it!"
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
_uuid=$(omv-rpc -u $DEPLOY_OMV_WEBUI_ADMIN 'CertificateMgmt' 'create' '{"cn": "test.example.com", "size": 4096, "days": 3650, "c": "", "st": "", "l": "", "o": "", "ou": "", "email": ""}' | jq -r '.uuid')
|
||||||
|
|
||||||
|
if [ -z "$_uuid" ]; then
|
||||||
|
_err "[OMB deploy-hook] An error occured while creating the certificate"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
_info "[OMV deploy-hook] Domain $_cdomain has uuid: $_uuid"
|
||||||
|
_fullchain=$(jq <"$_cfullchain" -aRs .)
|
||||||
|
_key=$(jq <"$_ckey" -aRs .)
|
||||||
|
|
||||||
|
_debug _fullchain "$_fullchain"
|
||||||
|
_debug _key "$_key"
|
||||||
|
|
||||||
|
_info "[OMV deploy-hook] Updating key and certificate in openmediavault"
|
||||||
|
_command="omv-rpc -u $DEPLOY_OMV_WEBUI_ADMIN 'CertificateMgmt' 'set' '{\"uuid\":\"$_uuid\", \"certificate\":$_fullchain, \"privatekey\":$_key, \"comment\":\"acme.sh deployed $(date)\"}'"
|
||||||
|
_result=$(eval "$_command")
|
||||||
|
|
||||||
|
_debug _command "$_command"
|
||||||
|
_debug _result "$_result"
|
||||||
|
|
||||||
|
_command="omv-rpc -u $DEPLOY_OMV_WEBUI_ADMIN 'WebGui' 'setSettings' \$(omv-rpc -u $DEPLOY_OMV_WEBUI_ADMIN 'WebGui' 'getSettings' | jq -c '.sslcertificateref=\"$_uuid\"')"
|
||||||
|
_result=$(eval "$_command")
|
||||||
|
|
||||||
|
_debug _command "$_command"
|
||||||
|
_debug _result "$_result"
|
||||||
|
|
||||||
|
_info "[OMV deploy-hook] Asking openmediavault to apply changes... (this could take some time, hang in there)"
|
||||||
|
_command="omv-rpc -u $DEPLOY_OMV_WEBUI_ADMIN 'Config' 'applyChanges' '{\"modules\":[], \"force\": false}'"
|
||||||
|
_result=$(eval "$_command")
|
||||||
|
|
||||||
|
_debug _command "$_command"
|
||||||
|
_debug _result "$_result"
|
||||||
|
|
||||||
|
_info "[OMV deploy-hook] Asking nginx to reload"
|
||||||
|
_command="nginx -s reload"
|
||||||
|
_result=$(eval "$_command")
|
||||||
|
|
||||||
|
_debug _command "$_command"
|
||||||
|
_debug _result "$_result"
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
@@ -66,21 +66,31 @@ routeros_deploy() {
|
|||||||
_debug _cca "$_cca"
|
_debug _cca "$_cca"
|
||||||
_debug _cfullchain "$_cfullchain"
|
_debug _cfullchain "$_cfullchain"
|
||||||
|
|
||||||
|
_getdeployconf ROUTER_OS_HOST
|
||||||
|
|
||||||
if [ -z "$ROUTER_OS_HOST" ]; then
|
if [ -z "$ROUTER_OS_HOST" ]; then
|
||||||
_debug "Using _cdomain as ROUTER_OS_HOST, please set if not correct."
|
_debug "Using _cdomain as ROUTER_OS_HOST, please set if not correct."
|
||||||
ROUTER_OS_HOST="$_cdomain"
|
ROUTER_OS_HOST="$_cdomain"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
_getdeployconf ROUTER_OS_USERNAME
|
||||||
|
|
||||||
if [ -z "$ROUTER_OS_USERNAME" ]; then
|
if [ -z "$ROUTER_OS_USERNAME" ]; then
|
||||||
_err "Need to set the env variable ROUTER_OS_USERNAME"
|
_err "Need to set the env variable ROUTER_OS_USERNAME"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
_getdeployconf ROUTER_OS_ADDITIONAL_SERVICES
|
||||||
|
|
||||||
if [ -z "$ROUTER_OS_ADDITIONAL_SERVICES" ]; then
|
if [ -z "$ROUTER_OS_ADDITIONAL_SERVICES" ]; then
|
||||||
_debug "Not enabling additional services"
|
_debug "Not enabling additional services"
|
||||||
ROUTER_OS_ADDITIONAL_SERVICES=""
|
ROUTER_OS_ADDITIONAL_SERVICES=""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
_savedeployconf ROUTER_OS_HOST "$ROUTER_OS_HOST"
|
||||||
|
_savedeployconf ROUTER_OS_USERNAME "$ROUTER_OS_USERNAME"
|
||||||
|
_savedeployconf ROUTER_OS_ADDITIONAL_SERVICES "$ROUTER_OS_ADDITIONAL_SERVICES"
|
||||||
|
|
||||||
_info "Trying to push key '$_ckey' to router"
|
_info "Trying to push key '$_ckey' to router"
|
||||||
scp "$_ckey" "$ROUTER_OS_USERNAME@$ROUTER_OS_HOST:$_cdomain.key"
|
scp "$_ckey" "$ROUTER_OS_USERNAME@$ROUTER_OS_HOST:$_cdomain.key"
|
||||||
_info "Trying to push cert '$_cfullchain' to router"
|
_info "Trying to push cert '$_cfullchain' to router"
|
||||||
|
|||||||
@@ -2,8 +2,7 @@
|
|||||||
|
|
||||||
# Here is a script to deploy cert to Synology DSM
|
# Here is a script to deploy cert to Synology DSM
|
||||||
#
|
#
|
||||||
# it requires the jq and curl are in the $PATH and the following
|
# It requires following environment variables:
|
||||||
# environment variables must be set:
|
|
||||||
#
|
#
|
||||||
# SYNO_Username - Synology Username to login (must be an administrator)
|
# SYNO_Username - Synology Username to login (must be an administrator)
|
||||||
# SYNO_Password - Synology Password to login
|
# SYNO_Password - Synology Password to login
|
||||||
@@ -16,6 +15,12 @@
|
|||||||
# SYNO_Hostname - defaults to localhost
|
# SYNO_Hostname - defaults to localhost
|
||||||
# SYNO_Port - defaults to 5000
|
# SYNO_Port - defaults to 5000
|
||||||
# SYNO_DID - device ID to skip OTP - defaults to empty
|
# SYNO_DID - device ID to skip OTP - defaults to empty
|
||||||
|
# SYNO_TOTP_SECRET - TOTP secret to generate OTP - defaults to empty
|
||||||
|
#
|
||||||
|
# Dependencies:
|
||||||
|
# -------------
|
||||||
|
# - jq and curl
|
||||||
|
# - oathtool (When using 2 Factor Authentication and SYNO_TOTP_SECRET is set)
|
||||||
#
|
#
|
||||||
#returns 0 means success, otherwise error.
|
#returns 0 means success, otherwise error.
|
||||||
|
|
||||||
@@ -36,6 +41,7 @@ synology_dsm_deploy() {
|
|||||||
_getdeployconf SYNO_Password
|
_getdeployconf SYNO_Password
|
||||||
_getdeployconf SYNO_Create
|
_getdeployconf SYNO_Create
|
||||||
_getdeployconf SYNO_DID
|
_getdeployconf SYNO_DID
|
||||||
|
_getdeployconf SYNO_TOTP_SECRET
|
||||||
if [ -z "${SYNO_Username:-}" ] || [ -z "${SYNO_Password:-}" ]; then
|
if [ -z "${SYNO_Username:-}" ] || [ -z "${SYNO_Password:-}" ]; then
|
||||||
_err "SYNO_Username & SYNO_Password must be set"
|
_err "SYNO_Username & SYNO_Password must be set"
|
||||||
return 1
|
return 1
|
||||||
@@ -86,13 +92,18 @@ synology_dsm_deploy() {
|
|||||||
encoded_username="$(printf "%s" "$SYNO_Username" | _url_encode)"
|
encoded_username="$(printf "%s" "$SYNO_Username" | _url_encode)"
|
||||||
encoded_password="$(printf "%s" "$SYNO_Password" | _url_encode)"
|
encoded_password="$(printf "%s" "$SYNO_Password" | _url_encode)"
|
||||||
|
|
||||||
|
otp_code=""
|
||||||
|
if [ -n "$SYNO_TOTP_SECRET" ]; then
|
||||||
|
otp_code="$(oathtool --base32 --totp "${SYNO_TOTP_SECRET}" 2>/dev/null)"
|
||||||
|
fi
|
||||||
|
|
||||||
if [ -n "$SYNO_DID" ]; then
|
if [ -n "$SYNO_DID" ]; then
|
||||||
_H1="Cookie: did=$SYNO_DID"
|
_H1="Cookie: did=$SYNO_DID"
|
||||||
export _H1
|
export _H1
|
||||||
_debug3 H1 "${_H1}"
|
_debug3 H1 "${_H1}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
response=$(_post "method=login&account=$encoded_username&passwd=$encoded_password&api=SYNO.API.Auth&version=$api_version&enable_syno_token=yes" "$_base_url/webapi/auth.cgi?enable_syno_token=yes")
|
response=$(_post "method=login&account=$encoded_username&passwd=$encoded_password&api=SYNO.API.Auth&version=$api_version&enable_syno_token=yes&otp_code=$otp_code" "$_base_url/webapi/auth.cgi?enable_syno_token=yes")
|
||||||
token=$(echo "$response" | grep "synotoken" | sed -n 's/.*"synotoken" *: *"\([^"]*\).*/\1/p')
|
token=$(echo "$response" | grep "synotoken" | sed -n 's/.*"synotoken" *: *"\([^"]*\).*/\1/p')
|
||||||
_debug3 response "$response"
|
_debug3 response "$response"
|
||||||
_debug token "$token"
|
_debug token "$token"
|
||||||
@@ -100,6 +111,7 @@ synology_dsm_deploy() {
|
|||||||
if [ -z "$token" ]; then
|
if [ -z "$token" ]; then
|
||||||
_err "Unable to authenticate to $SYNO_Hostname:$SYNO_Port using $SYNO_Scheme."
|
_err "Unable to authenticate to $SYNO_Hostname:$SYNO_Port using $SYNO_Scheme."
|
||||||
_err "Check your username and password."
|
_err "Check your username and password."
|
||||||
|
_err "If two-factor authentication is enabled for the user, set SYNO_TOTP_SECRET."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
sid=$(echo "$response" | grep "sid" | sed -n 's/.*"sid" *: *"\([^"]*\).*/\1/p')
|
sid=$(echo "$response" | grep "sid" | sed -n 's/.*"sid" *: *"\([^"]*\).*/\1/p')
|
||||||
@@ -112,6 +124,7 @@ synology_dsm_deploy() {
|
|||||||
_savedeployconf SYNO_Username "$SYNO_Username"
|
_savedeployconf SYNO_Username "$SYNO_Username"
|
||||||
_savedeployconf SYNO_Password "$SYNO_Password"
|
_savedeployconf SYNO_Password "$SYNO_Password"
|
||||||
_savedeployconf SYNO_DID "$SYNO_DID"
|
_savedeployconf SYNO_DID "$SYNO_DID"
|
||||||
|
_savedeployconf SYNO_TOTP_SECRET "$SYNO_TOTP_SECRET"
|
||||||
|
|
||||||
_info "Getting certificates in Synology DSM"
|
_info "Getting certificates in Synology DSM"
|
||||||
response=$(_post "api=SYNO.Core.Certificate.CRT&method=list&version=1&_sid=$sid" "$_base_url/webapi/entry.cgi")
|
response=$(_post "api=SYNO.Core.Certificate.CRT&method=list&version=1&_sid=$sid" "$_base_url/webapi/entry.cgi")
|
||||||
|
|||||||
180
deploy/truenas.sh
Normal file
180
deploy/truenas.sh
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
# Here is a scipt to deploy the cert to your TrueNAS using the REST API.
|
||||||
|
# https://www.truenas.com/docs/hub/additional-topics/api/rest_api.html
|
||||||
|
#
|
||||||
|
# Written by Frank Plass github@f-plass.de
|
||||||
|
# https://github.com/danb35/deploy-freenas/blob/master/deploy_freenas.py
|
||||||
|
# Thanks to danb35 for your template!
|
||||||
|
#
|
||||||
|
# Following environment variables must be set:
|
||||||
|
#
|
||||||
|
# export DEPLOY_TRUENAS_APIKEY="<API_KEY_GENERATED_IN_THE_WEB_UI"
|
||||||
|
#
|
||||||
|
# The following environmental variables may be set if you don't like their
|
||||||
|
# default values:
|
||||||
|
#
|
||||||
|
# DEPLOY_TRUENAS_HOSTNAME - defaults to localhost
|
||||||
|
# DEPLOY_TRUENAS_SCHEME - defaults to http, set alternatively to https
|
||||||
|
#
|
||||||
|
#returns 0 means success, otherwise error.
|
||||||
|
|
||||||
|
######## Public functions #####################
|
||||||
|
|
||||||
|
#domain keyfile certfile cafile fullchain
|
||||||
|
truenas_deploy() {
|
||||||
|
_cdomain="$1"
|
||||||
|
_ckey="$2"
|
||||||
|
_ccert="$3"
|
||||||
|
_cca="$4"
|
||||||
|
_cfullchain="$5"
|
||||||
|
|
||||||
|
_debug _cdomain "$_cdomain"
|
||||||
|
_debug _ckey "$_ckey"
|
||||||
|
_debug _ccert "$_ccert"
|
||||||
|
_debug _cca "$_cca"
|
||||||
|
_debug _cfullchain "$_cfullchain"
|
||||||
|
|
||||||
|
_getdeployconf DEPLOY_TRUENAS_APIKEY
|
||||||
|
|
||||||
|
if [ -z "$DEPLOY_TRUENAS_APIKEY" ]; then
|
||||||
|
_err "TrueNAS Api Key is not found, please define DEPLOY_TRUENAS_APIKEY."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_secure_debug2 DEPLOY_TRUENAS_APIKEY "$DEPLOY_TRUENAS_APIKEY"
|
||||||
|
|
||||||
|
# Optional hostname, scheme for TrueNAS
|
||||||
|
_getdeployconf DEPLOY_TRUENAS_HOSTNAME
|
||||||
|
_getdeployconf DEPLOY_TRUENAS_SCHEME
|
||||||
|
|
||||||
|
# default values for hostname and scheme
|
||||||
|
[ -n "${DEPLOY_TRUENAS_HOSTNAME}" ] || DEPLOY_TRUENAS_HOSTNAME="localhost"
|
||||||
|
[ -n "${DEPLOY_TRUENAS_SCHEME}" ] || DEPLOY_TRUENAS_SCHEME="http"
|
||||||
|
|
||||||
|
_debug2 DEPLOY_TRUENAS_HOSTNAME "$DEPLOY_TRUENAS_HOSTNAME"
|
||||||
|
_debug2 DEPLOY_TRUENAS_SCHEME "$DEPLOY_TRUENAS_SCHEME"
|
||||||
|
|
||||||
|
_api_url="$DEPLOY_TRUENAS_SCHEME://$DEPLOY_TRUENAS_HOSTNAME/api/v2.0"
|
||||||
|
_debug _api_url "$_api_url"
|
||||||
|
|
||||||
|
_H1="Authorization: Bearer $DEPLOY_TRUENAS_APIKEY"
|
||||||
|
_secure_debug3 _H1 "$_H1"
|
||||||
|
|
||||||
|
_info "Testing Connection TrueNAS"
|
||||||
|
_response=$(_get "$_api_url/system/state")
|
||||||
|
_info "TrueNAS System State: $_response."
|
||||||
|
|
||||||
|
if [ -z "$_response" ]; then
|
||||||
|
_err "Unable to authenticate to $_api_url."
|
||||||
|
_err 'Check your Connection and set DEPLOY_TRUENAS_HOSTNAME="192.168.178.x".'
|
||||||
|
_err 'or'
|
||||||
|
_err 'set DEPLOY_TRUENAS_HOSTNAME="<truenas_dnsname>".'
|
||||||
|
_err 'Check your Connection and set DEPLOY_TRUENAS_SCHEME="https".'
|
||||||
|
_err "Check your Api Key."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_savedeployconf DEPLOY_TRUENAS_APIKEY "$DEPLOY_TRUENAS_APIKEY"
|
||||||
|
_savedeployconf DEPLOY_TRUENAS_HOSTNAME "$DEPLOY_TRUENAS_HOSTNAME"
|
||||||
|
_savedeployconf DEPLOY_TRUENAS_SCHEME "$DEPLOY_TRUENAS_SCHEME"
|
||||||
|
|
||||||
|
_info "Getting active certificate from TrueNAS"
|
||||||
|
_response=$(_get "$_api_url/system/general")
|
||||||
|
_active_cert_id=$(echo "$_response" | grep -B2 '"name":' | grep 'id' | tr -d -- '"id: ,')
|
||||||
|
_active_cert_name=$(echo "$_response" | grep '"name":' | sed -n 's/.*: "\(.\{1,\}\)",$/\1/p')
|
||||||
|
_param_httpsredirect=$(echo "$_response" | grep '"ui_httpsredirect":' | sed -n 's/.*": \(.\{1,\}\),$/\1/p')
|
||||||
|
_debug Active_UI_Certificate_ID "$_active_cert_id"
|
||||||
|
_debug Active_UI_Certificate_Name "$_active_cert_name"
|
||||||
|
_debug Active_UI_http_redirect "$_param_httpsredirect"
|
||||||
|
|
||||||
|
if [ "$DEPLOY_TRUENAS_SCHEME" = "http" ] && [ "$_param_httpsredirect" = "true" ]; then
|
||||||
|
_info "http Redirect active"
|
||||||
|
_info "Setting DEPLOY_TRUENAS_SCHEME to 'https'"
|
||||||
|
DEPLOY_TRUENAS_SCHEME="https"
|
||||||
|
_api_url="$DEPLOY_TRUENAS_SCHEME://$DEPLOY_TRUENAS_HOSTNAME/api/v2.0"
|
||||||
|
_savedeployconf DEPLOY_TRUENAS_SCHEME "$DEPLOY_TRUENAS_SCHEME"
|
||||||
|
fi
|
||||||
|
|
||||||
|
_info "Upload new certifikate to TrueNAS"
|
||||||
|
_certname="Letsencrypt_$(_utc_date | tr ' ' '_' | tr -d -- ':')"
|
||||||
|
_debug3 _certname "$_certname"
|
||||||
|
|
||||||
|
_certData="{\"create_type\": \"CERTIFICATE_CREATE_IMPORTED\", \"name\": \"${_certname}\", \"certificate\": \"$(_json_encode <"$_cfullchain")\", \"privatekey\": \"$(_json_encode <"$_ckey")\"}"
|
||||||
|
_add_cert_result="$(_post "$_certData" "$_api_url/certificate" "" "POST" "application/json")"
|
||||||
|
|
||||||
|
_debug3 _add_cert_result "$_add_cert_result"
|
||||||
|
|
||||||
|
_info "Getting Certificate list to get new Cert ID"
|
||||||
|
_cert_list=$(_get "$_api_url/system/general/ui_certificate_choices")
|
||||||
|
_cert_id=$(echo "$_cert_list" | grep "$_certname" | sed -n 's/.*"\([0-9]\{1,\}\)".*$/\1/p')
|
||||||
|
|
||||||
|
_debug3 _cert_id "$_cert_id"
|
||||||
|
|
||||||
|
_info "Activate Certificate ID: $_cert_id"
|
||||||
|
_activateData="{\"ui_certificate\": \"${_cert_id}\"}"
|
||||||
|
_activate_result="$(_post "$_activateData" "$_api_url/system/general" "" "PUT" "application/json")"
|
||||||
|
|
||||||
|
_debug3 _activate_result "$_activate_result"
|
||||||
|
|
||||||
|
_info "Check if WebDAV certificate is the same as the WEB UI"
|
||||||
|
_webdav_list=$(_get "$_api_url/webdav")
|
||||||
|
_webdav_cert_id=$(echo "$_webdav_list" | grep '"certssl":' | tr -d -- '"certsl: ,')
|
||||||
|
|
||||||
|
if [ "$_webdav_cert_id" = "$_active_cert_id" ]; then
|
||||||
|
_info "Update the WebDAV Certificate"
|
||||||
|
_debug _webdav_cert_id "$_webdav_cert_id"
|
||||||
|
_webdav_data="{\"certssl\": \"${_cert_id}\"}"
|
||||||
|
_activate_webdav_cert="$(_post "$_webdav_data" "$_api_url/webdav" "" "PUT" "application/json")"
|
||||||
|
_webdav_new_cert_id=$(echo "$_activate_webdav_cert" | _json_decode | sed -n 's/.*: \([0-9]\{1,\}\) }$/\1/p')
|
||||||
|
if [ "$_webdav_new_cert_id" -eq "$_cert_id" ]; then
|
||||||
|
_info "WebDAV Certificate update successfully"
|
||||||
|
else
|
||||||
|
_err "Unable to set WebDAV certificate"
|
||||||
|
_debug3 _activate_webdav_cert "$_activate_webdav_cert"
|
||||||
|
_debug3 _webdav_new_cert_id "$_webdav_new_cert_id"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_debug3 _webdav_new_cert_id "$_webdav_new_cert_id"
|
||||||
|
else
|
||||||
|
_info "WebDAV certificate not set or not the same as Web UI"
|
||||||
|
fi
|
||||||
|
|
||||||
|
_info "Check if FTP certificate is the same as the WEB UI"
|
||||||
|
_ftp_list=$(_get "$_api_url/ftp")
|
||||||
|
_ftp_cert_id=$(echo "$_ftp_list" | grep '"ssltls_certificate":' | tr -d -- '"certislfa:_ ,')
|
||||||
|
|
||||||
|
if [ "$_ftp_cert_id" = "$_active_cert_id" ]; then
|
||||||
|
_info "Update the FTP Certificate"
|
||||||
|
_debug _ftp_cert_id "$_ftp_cert_id"
|
||||||
|
_ftp_data="{\"ssltls_certificate\": \"${_cert_id}\"}"
|
||||||
|
_activate_ftp_cert="$(_post "$_ftp_data" "$_api_url/ftp" "" "PUT" "application/json")"
|
||||||
|
_ftp_new_cert_id=$(echo "$_activate_ftp_cert" | _json_decode | sed -n 's/.*: \([0-9]\{1,\}\) }$/\1/p')
|
||||||
|
if [ "$_ftp_new_cert_id" -eq "$_cert_id" ]; then
|
||||||
|
_info "FTP Certificate update successfully"
|
||||||
|
else
|
||||||
|
_err "Unable to set FTP certificate"
|
||||||
|
_debug3 _activate_ftp_cert "$_activate_ftp_cert"
|
||||||
|
_debug3 _ftp_new_cert_id "$_ftp_new_cert_id"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_debug3 _activate_ftp_cert "$_activate_ftp_cert"
|
||||||
|
else
|
||||||
|
_info "FTP certificate not set or not the same as Web UI"
|
||||||
|
fi
|
||||||
|
|
||||||
|
_info "Delete old Certificate"
|
||||||
|
_delete_result="$(_post "" "$_api_url/certificate/id/$_active_cert_id" "" "DELETE" "application/json")"
|
||||||
|
|
||||||
|
_debug3 _delete_result "$_delete_result"
|
||||||
|
|
||||||
|
_info "Reload WebUI from TrueNAS"
|
||||||
|
_restart_UI=$(_get "$_api_url/system/general/ui_restart")
|
||||||
|
_debug2 _restart_UI "$_restart_UI"
|
||||||
|
|
||||||
|
if [ -n "$_add_cert_result" ] && [ -n "$_activate_result" ]; then
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
_err "Certupdate was not succesfull, please use --debug"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
@@ -56,12 +56,23 @@ vault_deploy() {
|
|||||||
export _H1="X-Vault-Token: $VAULT_TOKEN"
|
export _H1="X-Vault-Token: $VAULT_TOKEN"
|
||||||
|
|
||||||
if [ -n "$FABIO" ]; then
|
if [ -n "$FABIO" ]; then
|
||||||
|
if [ -n "$VAULT_KV_V2" ]; then
|
||||||
|
_post "{ \"data\": {\"cert\": \"$_cfullchain\", \"key\": \"$_ckey\"} }" "$URL"
|
||||||
|
else
|
||||||
_post "{\"cert\": \"$_cfullchain\", \"key\": \"$_ckey\"}" "$URL"
|
_post "{\"cert\": \"$_cfullchain\", \"key\": \"$_ckey\"}" "$URL"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if [ -n "$VAULT_KV_V2" ]; then
|
||||||
|
_post "{\"data\": {\"value\": \"$_ccert\"}}" "$URL/cert.pem"
|
||||||
|
_post "{\"data\": {\"value\": \"$_ckey\"}}" "$URL/cert.key"
|
||||||
|
_post "{\"data\": {\"value\": \"$_cca\"}}" "$URL/chain.pem"
|
||||||
|
_post "{\"data\": {\"value\": \"$_cfullchain\"}}" "$URL/fullchain.pem"
|
||||||
else
|
else
|
||||||
_post "{\"value\": \"$_ccert\"}" "$URL/cert.pem"
|
_post "{\"value\": \"$_ccert\"}" "$URL/cert.pem"
|
||||||
_post "{\"value\": \"$_ckey\"}" "$URL/cert.key"
|
_post "{\"value\": \"$_ckey\"}" "$URL/cert.key"
|
||||||
_post "{\"value\": \"$_cca\"}" "$URL/chain.pem"
|
_post "{\"value\": \"$_cca\"}" "$URL/chain.pem"
|
||||||
_post "{\"value\": \"$_cfullchain\"}" "$URL/fullchain.pem"
|
_post "{\"value\": \"$_cfullchain\"}" "$URL/fullchain.pem"
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
63
dnsapi/dns_acmedns.sh
Normal file → Executable file
63
dnsapi/dns_acmedns.sh
Normal file → Executable file
@@ -1,31 +1,70 @@
|
|||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
#
|
#
|
||||||
#Author: Wolfgang Ebner
|
#Author: Wolfgang Ebner
|
||||||
#Report Bugs here: https://github.com/webner/acme.sh
|
#Author: Sven Neubuaer
|
||||||
|
#Report Bugs here: https://github.com/dampfklon/acme.sh
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# export ACMEDNS_BASE_URL="https://auth.acme-dns.io"
|
||||||
|
#
|
||||||
|
# You can optionally define an already existing account:
|
||||||
|
#
|
||||||
|
# export ACMEDNS_USERNAME="<username>"
|
||||||
|
# export ACMEDNS_PASSWORD="<password>"
|
||||||
|
# export ACMEDNS_SUBDOMAIN="<subdomain>"
|
||||||
#
|
#
|
||||||
######## Public functions #####################
|
######## Public functions #####################
|
||||||
|
|
||||||
#Usage: dns_acmedns_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
#Usage: dns_acmedns_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||||
|
# Used to add txt record
|
||||||
dns_acmedns_add() {
|
dns_acmedns_add() {
|
||||||
fulldomain=$1
|
fulldomain=$1
|
||||||
txtvalue=$2
|
txtvalue=$2
|
||||||
_info "Using acme-dns"
|
_info "Using acme-dns"
|
||||||
_debug fulldomain "$fulldomain"
|
_debug "fulldomain $fulldomain"
|
||||||
_debug txtvalue "$txtvalue"
|
_debug "txtvalue $txtvalue"
|
||||||
|
|
||||||
ACMEDNS_UPDATE_URL="${ACMEDNS_UPDATE_URL:-$(_readaccountconf_mutable ACMEDNS_UPDATE_URL)}"
|
#for compatiblity from account conf
|
||||||
ACMEDNS_USERNAME="${ACMEDNS_USERNAME:-$(_readaccountconf_mutable ACMEDNS_USERNAME)}"
|
ACMEDNS_USERNAME="${ACMEDNS_USERNAME:-$(_readaccountconf_mutable ACMEDNS_USERNAME)}"
|
||||||
|
_clearaccountconf_mutable ACMEDNS_USERNAME
|
||||||
ACMEDNS_PASSWORD="${ACMEDNS_PASSWORD:-$(_readaccountconf_mutable ACMEDNS_PASSWORD)}"
|
ACMEDNS_PASSWORD="${ACMEDNS_PASSWORD:-$(_readaccountconf_mutable ACMEDNS_PASSWORD)}"
|
||||||
|
_clearaccountconf_mutable ACMEDNS_PASSWORD
|
||||||
ACMEDNS_SUBDOMAIN="${ACMEDNS_SUBDOMAIN:-$(_readaccountconf_mutable ACMEDNS_SUBDOMAIN)}"
|
ACMEDNS_SUBDOMAIN="${ACMEDNS_SUBDOMAIN:-$(_readaccountconf_mutable ACMEDNS_SUBDOMAIN)}"
|
||||||
|
_clearaccountconf_mutable ACMEDNS_SUBDOMAIN
|
||||||
|
|
||||||
if [ "$ACMEDNS_UPDATE_URL" = "" ]; then
|
ACMEDNS_BASE_URL="${ACMEDNS_BASE_URL:-$(_readdomainconf ACMEDNS_BASE_URL)}"
|
||||||
ACMEDNS_UPDATE_URL="https://auth.acme-dns.io/update"
|
ACMEDNS_USERNAME="${ACMEDNS_USERNAME:-$(_readdomainconf ACMEDNS_USERNAME)}"
|
||||||
|
ACMEDNS_PASSWORD="${ACMEDNS_PASSWORD:-$(_readdomainconf ACMEDNS_PASSWORD)}"
|
||||||
|
ACMEDNS_SUBDOMAIN="${ACMEDNS_SUBDOMAIN:-$(_readdomainconf ACMEDNS_SUBDOMAIN)}"
|
||||||
|
|
||||||
|
if [ "$ACMEDNS_BASE_URL" = "" ]; then
|
||||||
|
ACMEDNS_BASE_URL="https://auth.acme-dns.io"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_saveaccountconf_mutable ACMEDNS_UPDATE_URL "$ACMEDNS_UPDATE_URL"
|
ACMEDNS_UPDATE_URL="$ACMEDNS_BASE_URL/update"
|
||||||
_saveaccountconf_mutable ACMEDNS_USERNAME "$ACMEDNS_USERNAME"
|
ACMEDNS_REGISTER_URL="$ACMEDNS_BASE_URL/register"
|
||||||
_saveaccountconf_mutable ACMEDNS_PASSWORD "$ACMEDNS_PASSWORD"
|
|
||||||
_saveaccountconf_mutable ACMEDNS_SUBDOMAIN "$ACMEDNS_SUBDOMAIN"
|
if [ -z "$ACMEDNS_USERNAME" ] || [ -z "$ACMEDNS_PASSWORD" ]; then
|
||||||
|
response="$(_post "" "$ACMEDNS_REGISTER_URL" "" "POST")"
|
||||||
|
_debug response "$response"
|
||||||
|
ACMEDNS_USERNAME=$(echo "$response" | sed -n 's/^{.*\"username\":[ ]*\"\([^\"]*\)\".*}/\1/p')
|
||||||
|
_debug "received username: $ACMEDNS_USERNAME"
|
||||||
|
ACMEDNS_PASSWORD=$(echo "$response" | sed -n 's/^{.*\"password\":[ ]*\"\([^\"]*\)\".*}/\1/p')
|
||||||
|
_debug "received password: $ACMEDNS_PASSWORD"
|
||||||
|
ACMEDNS_SUBDOMAIN=$(echo "$response" | sed -n 's/^{.*\"subdomain\":[ ]*\"\([^\"]*\)\".*}/\1/p')
|
||||||
|
_debug "received subdomain: $ACMEDNS_SUBDOMAIN"
|
||||||
|
ACMEDNS_FULLDOMAIN=$(echo "$response" | sed -n 's/^{.*\"fulldomain\":[ ]*\"\([^\"]*\)\".*}/\1/p')
|
||||||
|
_info "##########################################################"
|
||||||
|
_info "# Create $fulldomain CNAME $ACMEDNS_FULLDOMAIN DNS entry #"
|
||||||
|
_info "##########################################################"
|
||||||
|
_info "Press enter to continue... "
|
||||||
|
read -r _
|
||||||
|
fi
|
||||||
|
|
||||||
|
_savedomainconf ACMEDNS_BASE_URL "$ACMEDNS_BASE_URL"
|
||||||
|
_savedomainconf ACMEDNS_USERNAME "$ACMEDNS_USERNAME"
|
||||||
|
_savedomainconf ACMEDNS_PASSWORD "$ACMEDNS_PASSWORD"
|
||||||
|
_savedomainconf ACMEDNS_SUBDOMAIN "$ACMEDNS_SUBDOMAIN"
|
||||||
|
|
||||||
export _H1="X-Api-User: $ACMEDNS_USERNAME"
|
export _H1="X-Api-User: $ACMEDNS_USERNAME"
|
||||||
export _H2="X-Api-Key: $ACMEDNS_PASSWORD"
|
export _H2="X-Api-Key: $ACMEDNS_PASSWORD"
|
||||||
@@ -48,8 +87,8 @@ dns_acmedns_rm() {
|
|||||||
fulldomain=$1
|
fulldomain=$1
|
||||||
txtvalue=$2
|
txtvalue=$2
|
||||||
_info "Using acme-dns"
|
_info "Using acme-dns"
|
||||||
_debug fulldomain "$fulldomain"
|
_debug "fulldomain $fulldomain"
|
||||||
_debug txtvalue "$txtvalue"
|
_debug "txtvalue $txtvalue"
|
||||||
}
|
}
|
||||||
|
|
||||||
#################### Private functions below ##################################
|
#################### Private functions below ##################################
|
||||||
|
|||||||
@@ -9,15 +9,12 @@ WIKI="https://github.com/acmesh-official/acme.sh/wiki/How-to-use-Azure-DNS"
|
|||||||
#
|
#
|
||||||
# Ref: https://docs.microsoft.com/en-us/rest/api/dns/recordsets/createorupdate
|
# Ref: https://docs.microsoft.com/en-us/rest/api/dns/recordsets/createorupdate
|
||||||
#
|
#
|
||||||
|
|
||||||
dns_azure_add() {
|
dns_azure_add() {
|
||||||
fulldomain=$1
|
fulldomain=$1
|
||||||
txtvalue=$2
|
txtvalue=$2
|
||||||
|
|
||||||
AZUREDNS_SUBSCRIPTIONID="${AZUREDNS_SUBSCRIPTIONID:-$(_readaccountconf_mutable AZUREDNS_SUBSCRIPTIONID)}"
|
AZUREDNS_SUBSCRIPTIONID="${AZUREDNS_SUBSCRIPTIONID:-$(_readaccountconf_mutable AZUREDNS_SUBSCRIPTIONID)}"
|
||||||
AZUREDNS_TENANTID="${AZUREDNS_TENANTID:-$(_readaccountconf_mutable AZUREDNS_TENANTID)}"
|
|
||||||
AZUREDNS_APPID="${AZUREDNS_APPID:-$(_readaccountconf_mutable AZUREDNS_APPID)}"
|
|
||||||
AZUREDNS_CLIENTSECRET="${AZUREDNS_CLIENTSECRET:-$(_readaccountconf_mutable AZUREDNS_CLIENTSECRET)}"
|
|
||||||
|
|
||||||
if [ -z "$AZUREDNS_SUBSCRIPTIONID" ]; then
|
if [ -z "$AZUREDNS_SUBSCRIPTIONID" ]; then
|
||||||
AZUREDNS_SUBSCRIPTIONID=""
|
AZUREDNS_SUBSCRIPTIONID=""
|
||||||
AZUREDNS_TENANTID=""
|
AZUREDNS_TENANTID=""
|
||||||
@@ -26,6 +23,22 @@ dns_azure_add() {
|
|||||||
_err "You didn't specify the Azure Subscription ID"
|
_err "You didn't specify the Azure Subscription ID"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
#save subscription id to account conf file.
|
||||||
|
_saveaccountconf_mutable AZUREDNS_SUBSCRIPTIONID "$AZUREDNS_SUBSCRIPTIONID"
|
||||||
|
|
||||||
|
AZUREDNS_MANAGEDIDENTITY="${AZUREDNS_MANAGEDIDENTITY:-$(_readaccountconf_mutable AZUREDNS_MANAGEDIDENTITY)}"
|
||||||
|
if [ "$AZUREDNS_MANAGEDIDENTITY" = true ]; then
|
||||||
|
_info "Using Azure managed identity"
|
||||||
|
#save managed identity as preferred authentication method, clear service principal credentials from conf file.
|
||||||
|
_saveaccountconf_mutable AZUREDNS_MANAGEDIDENTITY "$AZUREDNS_MANAGEDIDENTITY"
|
||||||
|
_saveaccountconf_mutable AZUREDNS_TENANTID ""
|
||||||
|
_saveaccountconf_mutable AZUREDNS_APPID ""
|
||||||
|
_saveaccountconf_mutable AZUREDNS_CLIENTSECRET ""
|
||||||
|
else
|
||||||
|
_info "You didn't ask to use Azure managed identity, checking service principal credentials"
|
||||||
|
AZUREDNS_TENANTID="${AZUREDNS_TENANTID:-$(_readaccountconf_mutable AZUREDNS_TENANTID)}"
|
||||||
|
AZUREDNS_APPID="${AZUREDNS_APPID:-$(_readaccountconf_mutable AZUREDNS_APPID)}"
|
||||||
|
AZUREDNS_CLIENTSECRET="${AZUREDNS_CLIENTSECRET:-$(_readaccountconf_mutable AZUREDNS_CLIENTSECRET)}"
|
||||||
|
|
||||||
if [ -z "$AZUREDNS_TENANTID" ]; then
|
if [ -z "$AZUREDNS_TENANTID" ]; then
|
||||||
AZUREDNS_SUBSCRIPTIONID=""
|
AZUREDNS_SUBSCRIPTIONID=""
|
||||||
@@ -53,13 +66,15 @@ dns_azure_add() {
|
|||||||
_err "You didn't specify the Azure Client Secret"
|
_err "You didn't specify the Azure Client Secret"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
#save account details to account conf file.
|
|
||||||
_saveaccountconf_mutable AZUREDNS_SUBSCRIPTIONID "$AZUREDNS_SUBSCRIPTIONID"
|
#save account details to account conf file, don't opt in for azure manages identity check.
|
||||||
|
_saveaccountconf_mutable AZUREDNS_MANAGEDIDENTITY "false"
|
||||||
_saveaccountconf_mutable AZUREDNS_TENANTID "$AZUREDNS_TENANTID"
|
_saveaccountconf_mutable AZUREDNS_TENANTID "$AZUREDNS_TENANTID"
|
||||||
_saveaccountconf_mutable AZUREDNS_APPID "$AZUREDNS_APPID"
|
_saveaccountconf_mutable AZUREDNS_APPID "$AZUREDNS_APPID"
|
||||||
_saveaccountconf_mutable AZUREDNS_CLIENTSECRET "$AZUREDNS_CLIENTSECRET"
|
_saveaccountconf_mutable AZUREDNS_CLIENTSECRET "$AZUREDNS_CLIENTSECRET"
|
||||||
|
fi
|
||||||
|
|
||||||
accesstoken=$(_azure_getaccess_token "$AZUREDNS_TENANTID" "$AZUREDNS_APPID" "$AZUREDNS_CLIENTSECRET")
|
accesstoken=$(_azure_getaccess_token "$AZUREDNS_MANAGEDIDENTITY" "$AZUREDNS_TENANTID" "$AZUREDNS_APPID" "$AZUREDNS_CLIENTSECRET")
|
||||||
|
|
||||||
if ! _get_root "$fulldomain" "$AZUREDNS_SUBSCRIPTIONID" "$accesstoken"; then
|
if ! _get_root "$fulldomain" "$AZUREDNS_SUBSCRIPTIONID" "$accesstoken"; then
|
||||||
_err "invalid domain"
|
_err "invalid domain"
|
||||||
@@ -116,10 +131,6 @@ dns_azure_rm() {
|
|||||||
txtvalue=$2
|
txtvalue=$2
|
||||||
|
|
||||||
AZUREDNS_SUBSCRIPTIONID="${AZUREDNS_SUBSCRIPTIONID:-$(_readaccountconf_mutable AZUREDNS_SUBSCRIPTIONID)}"
|
AZUREDNS_SUBSCRIPTIONID="${AZUREDNS_SUBSCRIPTIONID:-$(_readaccountconf_mutable AZUREDNS_SUBSCRIPTIONID)}"
|
||||||
AZUREDNS_TENANTID="${AZUREDNS_TENANTID:-$(_readaccountconf_mutable AZUREDNS_TENANTID)}"
|
|
||||||
AZUREDNS_APPID="${AZUREDNS_APPID:-$(_readaccountconf_mutable AZUREDNS_APPID)}"
|
|
||||||
AZUREDNS_CLIENTSECRET="${AZUREDNS_CLIENTSECRET:-$(_readaccountconf_mutable AZUREDNS_CLIENTSECRET)}"
|
|
||||||
|
|
||||||
if [ -z "$AZUREDNS_SUBSCRIPTIONID" ]; then
|
if [ -z "$AZUREDNS_SUBSCRIPTIONID" ]; then
|
||||||
AZUREDNS_SUBSCRIPTIONID=""
|
AZUREDNS_SUBSCRIPTIONID=""
|
||||||
AZUREDNS_TENANTID=""
|
AZUREDNS_TENANTID=""
|
||||||
@@ -129,6 +140,15 @@ dns_azure_rm() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
AZUREDNS_MANAGEDIDENTITY="${AZUREDNS_MANAGEDIDENTITY:-$(_readaccountconf_mutable AZUREDNS_MANAGEDIDENTITY)}"
|
||||||
|
if [ "$AZUREDNS_MANAGEDIDENTITY" = true ]; then
|
||||||
|
_info "Using Azure managed identity"
|
||||||
|
else
|
||||||
|
_info "You didn't ask to use Azure managed identity, checking service principal credentials"
|
||||||
|
AZUREDNS_TENANTID="${AZUREDNS_TENANTID:-$(_readaccountconf_mutable AZUREDNS_TENANTID)}"
|
||||||
|
AZUREDNS_APPID="${AZUREDNS_APPID:-$(_readaccountconf_mutable AZUREDNS_APPID)}"
|
||||||
|
AZUREDNS_CLIENTSECRET="${AZUREDNS_CLIENTSECRET:-$(_readaccountconf_mutable AZUREDNS_CLIENTSECRET)}"
|
||||||
|
|
||||||
if [ -z "$AZUREDNS_TENANTID" ]; then
|
if [ -z "$AZUREDNS_TENANTID" ]; then
|
||||||
AZUREDNS_SUBSCRIPTIONID=""
|
AZUREDNS_SUBSCRIPTIONID=""
|
||||||
AZUREDNS_TENANTID=""
|
AZUREDNS_TENANTID=""
|
||||||
@@ -155,8 +175,9 @@ dns_azure_rm() {
|
|||||||
_err "You didn't specify the Azure Client Secret"
|
_err "You didn't specify the Azure Client Secret"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
accesstoken=$(_azure_getaccess_token "$AZUREDNS_TENANTID" "$AZUREDNS_APPID" "$AZUREDNS_CLIENTSECRET")
|
accesstoken=$(_azure_getaccess_token "$AZUREDNS_MANAGEDIDENTITY" "$AZUREDNS_TENANTID" "$AZUREDNS_APPID" "$AZUREDNS_CLIENTSECRET")
|
||||||
|
|
||||||
if ! _get_root "$fulldomain" "$AZUREDNS_SUBSCRIPTIONID" "$accesstoken"; then
|
if ! _get_root "$fulldomain" "$AZUREDNS_SUBSCRIPTIONID" "$accesstoken"; then
|
||||||
_err "invalid domain"
|
_err "invalid domain"
|
||||||
@@ -258,9 +279,10 @@ _azure_rest() {
|
|||||||
|
|
||||||
## Ref: https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-protocols-oauth-service-to-service#request-an-access-token
|
## Ref: https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-protocols-oauth-service-to-service#request-an-access-token
|
||||||
_azure_getaccess_token() {
|
_azure_getaccess_token() {
|
||||||
tenantID=$1
|
managedIdentity=$1
|
||||||
clientID=$2
|
tenantID=$2
|
||||||
clientSecret=$3
|
clientID=$3
|
||||||
|
clientSecret=$4
|
||||||
|
|
||||||
accesstoken="${AZUREDNS_BEARERTOKEN:-$(_readaccountconf_mutable AZUREDNS_BEARERTOKEN)}"
|
accesstoken="${AZUREDNS_BEARERTOKEN:-$(_readaccountconf_mutable AZUREDNS_BEARERTOKEN)}"
|
||||||
expires_on="${AZUREDNS_TOKENVALIDTO:-$(_readaccountconf_mutable AZUREDNS_TOKENVALIDTO)}"
|
expires_on="${AZUREDNS_TOKENVALIDTO:-$(_readaccountconf_mutable AZUREDNS_TOKENVALIDTO)}"
|
||||||
@@ -278,9 +300,16 @@ _azure_getaccess_token() {
|
|||||||
fi
|
fi
|
||||||
_debug "getting new bearer token"
|
_debug "getting new bearer token"
|
||||||
|
|
||||||
|
if [ "$managedIdentity" = true ]; then
|
||||||
|
# https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/how-to-use-vm-token#get-a-token-using-http
|
||||||
|
export _H1="Metadata: true"
|
||||||
|
response="$(_get http://169.254.169.254/metadata/identity/oauth2/token\?api-version=2018-02-01\&resource=https://management.azure.com/)"
|
||||||
|
response="$(echo "$response" | _normalizeJson)"
|
||||||
|
accesstoken=$(echo "$response" | _egrep_o "\"access_token\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \")
|
||||||
|
expires_on=$(echo "$response" | _egrep_o "\"expires_on\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \")
|
||||||
|
else
|
||||||
export _H1="accept: application/json"
|
export _H1="accept: application/json"
|
||||||
export _H2="Content-Type: application/x-www-form-urlencoded"
|
export _H2="Content-Type: application/x-www-form-urlencoded"
|
||||||
|
|
||||||
body="resource=$(printf "%s" 'https://management.core.windows.net/' | _url_encode)&client_id=$(printf "%s" "$clientID" | _url_encode)&client_secret=$(printf "%s" "$clientSecret" | _url_encode)&grant_type=client_credentials"
|
body="resource=$(printf "%s" 'https://management.core.windows.net/' | _url_encode)&client_id=$(printf "%s" "$clientID" | _url_encode)&client_secret=$(printf "%s" "$clientSecret" | _url_encode)&grant_type=client_credentials"
|
||||||
_secure_debug2 "data $body"
|
_secure_debug2 "data $body"
|
||||||
response="$(_post "$body" "https://login.microsoftonline.com/$tenantID/oauth2/token" "" "POST")"
|
response="$(_post "$body" "https://login.microsoftonline.com/$tenantID/oauth2/token" "" "POST")"
|
||||||
@@ -289,6 +318,7 @@ _azure_getaccess_token() {
|
|||||||
response="$(echo "$response" | _normalizeJson)"
|
response="$(echo "$response" | _normalizeJson)"
|
||||||
accesstoken=$(echo "$response" | _egrep_o "\"access_token\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \")
|
accesstoken=$(echo "$response" | _egrep_o "\"access_token\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \")
|
||||||
expires_on=$(echo "$response" | _egrep_o "\"expires_on\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \")
|
expires_on=$(echo "$response" | _egrep_o "\"expires_on\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \")
|
||||||
|
fi
|
||||||
|
|
||||||
if [ -z "$accesstoken" ]; then
|
if [ -z "$accesstoken" ]; then
|
||||||
_err "no acccess token received. Check your Azure settings see $WIKI"
|
_err "no acccess token received. Check your Azure settings see $WIKI"
|
||||||
|
|||||||
@@ -2,11 +2,14 @@
|
|||||||
|
|
||||||
# Author: Boyan Peychev <boyan at cloudns dot net>
|
# Author: Boyan Peychev <boyan at cloudns dot net>
|
||||||
# Repository: https://github.com/ClouDNS/acme.sh/
|
# Repository: https://github.com/ClouDNS/acme.sh/
|
||||||
|
# Editor: I Komang Suryadana
|
||||||
|
|
||||||
#CLOUDNS_AUTH_ID=XXXXX
|
#CLOUDNS_AUTH_ID=XXXXX
|
||||||
#CLOUDNS_SUB_AUTH_ID=XXXXX
|
#CLOUDNS_SUB_AUTH_ID=XXXXX
|
||||||
#CLOUDNS_AUTH_PASSWORD="YYYYYYYYY"
|
#CLOUDNS_AUTH_PASSWORD="YYYYYYYYY"
|
||||||
CLOUDNS_API="https://api.cloudns.net"
|
CLOUDNS_API="https://api.cloudns.net"
|
||||||
|
DOMAIN_TYPE=
|
||||||
|
DOMAIN_MASTER=
|
||||||
|
|
||||||
######## Public functions #####################
|
######## Public functions #####################
|
||||||
|
|
||||||
@@ -61,6 +64,15 @@ dns_cloudns_rm() {
|
|||||||
host="$(echo "$1" | sed "s/\.$zone\$//")"
|
host="$(echo "$1" | sed "s/\.$zone\$//")"
|
||||||
record=$2
|
record=$2
|
||||||
|
|
||||||
|
_dns_cloudns_get_zone_info "$zone"
|
||||||
|
|
||||||
|
_debug "Type" "$DOMAIN_TYPE"
|
||||||
|
_debug "Cloud Master" "$DOMAIN_MASTER"
|
||||||
|
if _contains "$DOMAIN_TYPE" "cloud"; then
|
||||||
|
zone=$DOMAIN_MASTER
|
||||||
|
fi
|
||||||
|
_debug "ZONE" "$zone"
|
||||||
|
|
||||||
_dns_cloudns_http_api_call "dns/records.json" "domain-name=$zone&host=$host&type=TXT"
|
_dns_cloudns_http_api_call "dns/records.json" "domain-name=$zone&host=$host&type=TXT"
|
||||||
if ! _contains "$response" "\"id\":"; then
|
if ! _contains "$response" "\"id\":"; then
|
||||||
return 1
|
return 1
|
||||||
@@ -134,6 +146,18 @@ _dns_cloudns_init_check() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_dns_cloudns_get_zone_info() {
|
||||||
|
zone=$1
|
||||||
|
_dns_cloudns_http_api_call "dns/get-zone-info.json" "domain-name=$zone"
|
||||||
|
if ! _contains "$response" "\"status\":\"Failed\""; then
|
||||||
|
DOMAIN_TYPE=$(echo "$response" | _egrep_o '"type":"[^"]*"' | cut -d : -f 2 | tr -d '"')
|
||||||
|
if _contains "$DOMAIN_TYPE" "cloud"; then
|
||||||
|
DOMAIN_MASTER=$(echo "$response" | _egrep_o '"cloud-master":"[^"]*"' | cut -d : -f 2 | tr -d '"')
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
_dns_cloudns_get_zone_name() {
|
_dns_cloudns_get_zone_name() {
|
||||||
i=2
|
i=2
|
||||||
while true; do
|
while true; do
|
||||||
|
|||||||
159
dnsapi/dns_cpanel.sh
Executable file
159
dnsapi/dns_cpanel.sh
Executable file
@@ -0,0 +1,159 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
#
|
||||||
|
#Author: Bjarne Saltbaek
|
||||||
|
#Report Bugs here: https://github.com/acmesh-official/acme.sh/issues/3732
|
||||||
|
#
|
||||||
|
#
|
||||||
|
######## Public functions #####################
|
||||||
|
#
|
||||||
|
# Export CPANEL username,api token and hostname in the following variables
|
||||||
|
#
|
||||||
|
# cPanel_Username=username
|
||||||
|
# cPanel_Apitoken=apitoken
|
||||||
|
# cPanel_Hostname=hostname
|
||||||
|
#
|
||||||
|
# Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||||
|
# Used to add txt record
|
||||||
|
dns_cpanel_add() {
|
||||||
|
fulldomain=$1
|
||||||
|
txtvalue=$2
|
||||||
|
|
||||||
|
_info "Adding TXT record to cPanel based system"
|
||||||
|
_debug fulldomain "$fulldomain"
|
||||||
|
_debug txtvalue "$txtvalue"
|
||||||
|
_debug cPanel_Username "$cPanel_Username"
|
||||||
|
_debug cPanel_Apitoken "$cPanel_Apitoken"
|
||||||
|
_debug cPanel_Hostname "$cPanel_Hostname"
|
||||||
|
|
||||||
|
if ! _cpanel_login; then
|
||||||
|
_err "cPanel Login failed for user $cPanel_Username. Check $HTTP_HEADER file"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_debug "First detect the root zone"
|
||||||
|
if ! _get_root "$fulldomain"; then
|
||||||
|
_err "No matching root domain for $fulldomain found"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
# adding entry
|
||||||
|
_info "Adding the entry"
|
||||||
|
stripped_fulldomain=$(echo "$fulldomain" | sed "s/.$_domain//")
|
||||||
|
_debug "Adding $stripped_fulldomain to $_domain zone"
|
||||||
|
_myget "json-api/cpanel?cpanel_jsonapi_apiversion=2&cpanel_jsonapi_module=ZoneEdit&cpanel_jsonapi_func=add_zone_record&domain=$_domain&name=$stripped_fulldomain&type=TXT&txtdata=$txtvalue&ttl=1"
|
||||||
|
if _successful_update; then return 0; fi
|
||||||
|
_err "Couldn't create entry!"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Usage: fulldomain txtvalue
|
||||||
|
# Used to remove the txt record after validation
|
||||||
|
dns_cpanel_rm() {
|
||||||
|
fulldomain=$1
|
||||||
|
txtvalue=$2
|
||||||
|
|
||||||
|
_info "Using cPanel based system"
|
||||||
|
_debug fulldomain "$fulldomain"
|
||||||
|
_debug txtvalue "$txtvalue"
|
||||||
|
|
||||||
|
if ! _cpanel_login; then
|
||||||
|
_err "cPanel Login failed for user $cPanel_Username. Check $HTTP_HEADER file"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! _get_root; then
|
||||||
|
_err "No matching root domain for $fulldomain found"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_findentry "$fulldomain" "$txtvalue"
|
||||||
|
if [ -z "$_id" ]; then
|
||||||
|
_info "Entry doesn't exist, nothing to delete"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
_debug "Deleting record..."
|
||||||
|
_myget "json-api/cpanel?cpanel_jsonapi_apiversion=2&cpanel_jsonapi_module=ZoneEdit&cpanel_jsonapi_func=remove_zone_record&domain=$_domain&line=$_id"
|
||||||
|
# removing entry
|
||||||
|
_debug "_result is: $_result"
|
||||||
|
|
||||||
|
if _successful_update; then return 0; fi
|
||||||
|
_err "Couldn't delete entry!"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
#################### Private functions below ##################################
|
||||||
|
|
||||||
|
_checkcredentials() {
|
||||||
|
cPanel_Username="${cPanel_Username:-$(_readaccountconf_mutable cPanel_Username)}"
|
||||||
|
cPanel_Apitoken="${cPanel_Apitoken:-$(_readaccountconf_mutable cPanel_Apitoken)}"
|
||||||
|
cPanel_Hostname="${cPanel_Hostname:-$(_readaccountconf_mutable cPanel_Hostname)}"
|
||||||
|
|
||||||
|
if [ -z "$cPanel_Username" ] || [ -z "$cPanel_Apitoken" ] || [ -z "$cPanel_Hostname" ]; then
|
||||||
|
cPanel_Username=""
|
||||||
|
cPanel_Apitoken=""
|
||||||
|
cPanel_Hostname=""
|
||||||
|
_err "You haven't specified cPanel username, apitoken and hostname yet."
|
||||||
|
_err "Please add credentials and try again."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
#save the credentials to the account conf file.
|
||||||
|
_saveaccountconf_mutable cPanel_Username "$cPanel_Username"
|
||||||
|
_saveaccountconf_mutable cPanel_Apitoken "$cPanel_Apitoken"
|
||||||
|
_saveaccountconf_mutable cPanel_Hostname "$cPanel_Hostname"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
_cpanel_login() {
|
||||||
|
if ! _checkcredentials; then return 1; fi
|
||||||
|
|
||||||
|
if ! _myget "json-api/cpanel?cpanel_jsonapi_apiversion=2&cpanel_jsonapi_module=CustInfo&cpanel_jsonapi_func=displaycontactinfo"; then
|
||||||
|
_err "cPanel login failed for user $cPanel_Username."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
_myget() {
|
||||||
|
#Adds auth header to request
|
||||||
|
export _H1="Authorization: cpanel $cPanel_Username:$cPanel_Apitoken"
|
||||||
|
_result=$(_get "$cPanel_Hostname/$1")
|
||||||
|
}
|
||||||
|
|
||||||
|
_get_root() {
|
||||||
|
_myget 'json-api/cpanel?cpanel_jsonapi_apiversion=2&cpanel_jsonapi_module=ZoneEdit&cpanel_jsonapi_func=fetchzones'
|
||||||
|
_domains=$(echo "$_result" | sed 's/.*\(zones.*\[\).*/\1/' | cut -d':' -f2 | sed 's/"//g' | sed 's/{//g')
|
||||||
|
_debug "_result is: $_result"
|
||||||
|
_debug "_domains is: $_domains"
|
||||||
|
if [ -z "$_domains" ]; then
|
||||||
|
_err "Primary domain list not found!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
for _domain in $_domains; do
|
||||||
|
_debug "Checking if $fulldomain ends with $_domain"
|
||||||
|
if (_endswith "$fulldomain" "$_domain"); then
|
||||||
|
_debug "Root domain: $_domain"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
_successful_update() {
|
||||||
|
if (echo "$_result" | grep -q 'newserial'); then return 0; fi
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
_findentry() {
|
||||||
|
_debug "In _findentry"
|
||||||
|
#returns id of dns entry, if it exists
|
||||||
|
_myget "json-api/cpanel?cpanel_jsonapi_apiversion=2&cpanel_jsonapi_module=ZoneEdit&cpanel_jsonapi_func=fetchzone_records&domain=$_domain"
|
||||||
|
_id=$(echo "$_result" | sed "s/.*\(line.*$fulldomain.*$txtvalue\).*/\1/" | cut -d ':' -f 2 | cut -d ',' -f 1)
|
||||||
|
_debug "_result is: $_result"
|
||||||
|
_debug "fulldomain. is $fulldomain."
|
||||||
|
_debug "txtvalue is $txtvalue"
|
||||||
|
_debug "_id is: $_id"
|
||||||
|
if [ -n "$_id" ]; then
|
||||||
|
_debug "Entry found with _id=$_id"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
}
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
# --
|
# --
|
||||||
#
|
#
|
||||||
|
|
||||||
DDNSS_DNS_API="https://ip4.ddnss.de/upd.php"
|
DDNSS_DNS_API="https://ddnss.de/upd.php"
|
||||||
|
|
||||||
######## Public functions #####################
|
######## Public functions #####################
|
||||||
|
|
||||||
@@ -77,7 +77,7 @@ dns_ddnss_rm() {
|
|||||||
|
|
||||||
# Now remove the TXT record from DDNS DNS
|
# Now remove the TXT record from DDNS DNS
|
||||||
_info "Trying to remove TXT record"
|
_info "Trying to remove TXT record"
|
||||||
if _ddnss_rest GET "key=$DDNSS_Token&host=$_ddnss_domain&txtm=1&txt=."; then
|
if _ddnss_rest GET "key=$DDNSS_Token&host=$_ddnss_domain&txtm=2"; then
|
||||||
if [ "$response" = "Updated 1 hostname." ]; then
|
if [ "$response" = "Updated 1 hostname." ]; then
|
||||||
_info "TXT record has been successfully removed from your DDNSS domain."
|
_info "TXT record has been successfully removed from your DDNSS domain."
|
||||||
return 0
|
return 0
|
||||||
|
|||||||
87
dnsapi/dns_dnshome.sh
Executable file
87
dnsapi/dns_dnshome.sh
Executable file
@@ -0,0 +1,87 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
# dnsHome.de API for acme.sh
|
||||||
|
#
|
||||||
|
# This Script adds the necessary TXT record to a Subdomain
|
||||||
|
#
|
||||||
|
# Author dnsHome.de (https://github.com/dnsHome-de)
|
||||||
|
#
|
||||||
|
# Report Bugs to https://github.com/acmesh-official/acme.sh/issues/3819
|
||||||
|
#
|
||||||
|
# export DNSHOME_Subdomain=""
|
||||||
|
# export DNSHOME_SubdomainPassword=""
|
||||||
|
|
||||||
|
# Usage: add subdomain.ddnsdomain.tld "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||||
|
# Used to add txt record
|
||||||
|
dns_dnshome_add() {
|
||||||
|
txtvalue=$2
|
||||||
|
|
||||||
|
DNSHOME_Subdomain="${DNSHOME_Subdomain:-$(_readdomainconf DNSHOME_Subdomain)}"
|
||||||
|
DNSHOME_SubdomainPassword="${DNSHOME_SubdomainPassword:-$(_readdomainconf DNSHOME_SubdomainPassword)}"
|
||||||
|
|
||||||
|
if [ -z "$DNSHOME_Subdomain" ] || [ -z "$DNSHOME_SubdomainPassword" ]; then
|
||||||
|
DNSHOME_Subdomain=""
|
||||||
|
DNSHOME_SubdomainPassword=""
|
||||||
|
_err "Please specify/export your dnsHome.de Subdomain and Password"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
#save the credentials to the account conf file.
|
||||||
|
_savedomainconf DNSHOME_Subdomain "$DNSHOME_Subdomain"
|
||||||
|
_savedomainconf DNSHOME_SubdomainPassword "$DNSHOME_SubdomainPassword"
|
||||||
|
|
||||||
|
DNSHOME_Api="https://$DNSHOME_Subdomain:$DNSHOME_SubdomainPassword@www.dnshome.de/dyndns.php"
|
||||||
|
|
||||||
|
_DNSHOME_rest POST "acme=add&txt=$txtvalue"
|
||||||
|
if ! echo "$response" | grep 'successfully' >/dev/null; then
|
||||||
|
_err "Error"
|
||||||
|
_err "$response"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Usage: txtvalue
|
||||||
|
# Used to remove the txt record after validation
|
||||||
|
dns_dnshome_rm() {
|
||||||
|
txtvalue=$2
|
||||||
|
|
||||||
|
DNSHOME_Subdomain="${DNSHOME_Subdomain:-$(_readdomainconf DNSHOME_Subdomain)}"
|
||||||
|
DNSHOME_SubdomainPassword="${DNSHOME_SubdomainPassword:-$(_readdomainconf DNSHOME_SubdomainPassword)}"
|
||||||
|
|
||||||
|
DNSHOME_Api="https://$DNSHOME_Subdomain:$DNSHOME_SubdomainPassword@www.dnshome.de/dyndns.php"
|
||||||
|
|
||||||
|
if [ -z "$DNSHOME_Subdomain" ] || [ -z "$DNSHOME_SubdomainPassword" ]; then
|
||||||
|
DNSHOME_Subdomain=""
|
||||||
|
DNSHOME_SubdomainPassword=""
|
||||||
|
_err "Please specify/export your dnsHome.de Subdomain and Password"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_DNSHOME_rest POST "acme=rm&txt=$txtvalue"
|
||||||
|
if ! echo "$response" | grep 'successfully' >/dev/null; then
|
||||||
|
_err "Error"
|
||||||
|
_err "$response"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
#################### Private functions below ##################################
|
||||||
|
_DNSHOME_rest() {
|
||||||
|
method=$1
|
||||||
|
data="$2"
|
||||||
|
_debug "$data"
|
||||||
|
|
||||||
|
_debug data "$data"
|
||||||
|
response="$(_post "$data" "$DNSHOME_Api" "" "$method")"
|
||||||
|
|
||||||
|
if [ "$?" != "0" ]; then
|
||||||
|
_err "error $data"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_debug2 response "$response"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
@@ -163,5 +163,8 @@ _dns_gcloud_get_rrdatas() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
ttl=$(echo "$rrdatas" | cut -f1)
|
ttl=$(echo "$rrdatas" | cut -f1)
|
||||||
rrdatas=$(echo "$rrdatas" | cut -f2 | sed 's/","/"\n"/g')
|
# starting with version 353.0.0 gcloud seems to
|
||||||
|
# separate records with a semicolon instead of commas
|
||||||
|
# see also https://cloud.google.com/sdk/docs/release-notes#35300_2021-08-17
|
||||||
|
rrdatas=$(echo "$rrdatas" | cut -f2 | sed 's/"[,;]"/"\n"/g')
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ dns_huaweicloud_add() {
|
|||||||
_err "dns_api(dns_huaweicloud): Error getting token."
|
_err "dns_api(dns_huaweicloud): Error getting token."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
_debug "Access token is: ${token}"
|
_secure_debug "Access token is:" "${token}"
|
||||||
|
|
||||||
unset zoneid
|
unset zoneid
|
||||||
zoneid="$(_get_zoneid "${token}" "${fulldomain}")"
|
zoneid="$(_get_zoneid "${token}" "${fulldomain}")"
|
||||||
@@ -43,7 +43,7 @@ dns_huaweicloud_add() {
|
|||||||
_err "dns_api(dns_huaweicloud): Error getting zone id."
|
_err "dns_api(dns_huaweicloud): Error getting zone id."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
_debug "Zone ID is: ${zoneid}"
|
_debug "Zone ID is:" "${zoneid}"
|
||||||
|
|
||||||
_debug "Adding Record"
|
_debug "Adding Record"
|
||||||
_add_record "${token}" "${fulldomain}" "${txtvalue}"
|
_add_record "${token}" "${fulldomain}" "${txtvalue}"
|
||||||
@@ -86,7 +86,7 @@ dns_huaweicloud_rm() {
|
|||||||
_err "dns_api(dns_huaweicloud): Error getting token."
|
_err "dns_api(dns_huaweicloud): Error getting token."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
_debug "Access token is: ${token}"
|
_secure_debug "Access token is:" "${token}"
|
||||||
|
|
||||||
unset zoneid
|
unset zoneid
|
||||||
zoneid="$(_get_zoneid "${token}" "${fulldomain}")"
|
zoneid="$(_get_zoneid "${token}" "${fulldomain}")"
|
||||||
@@ -94,7 +94,7 @@ dns_huaweicloud_rm() {
|
|||||||
_err "dns_api(dns_huaweicloud): Error getting zone id."
|
_err "dns_api(dns_huaweicloud): Error getting zone id."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
_debug "Zone ID is: ${zoneid}"
|
_debug "Zone ID is:" "${zoneid}"
|
||||||
|
|
||||||
# Remove all records
|
# Remove all records
|
||||||
# Therotically HuaweiCloud does not allow more than one record set
|
# Therotically HuaweiCloud does not allow more than one record set
|
||||||
@@ -129,14 +129,28 @@ _get_zoneid() {
|
|||||||
fi
|
fi
|
||||||
_debug "$h"
|
_debug "$h"
|
||||||
response=$(_get "${dns_api}/v2/zones?name=${h}")
|
response=$(_get "${dns_api}/v2/zones?name=${h}")
|
||||||
|
_debug2 "$response"
|
||||||
if _contains "${response}" "id"; then
|
if _contains "${response}" '"id"'; then
|
||||||
|
zoneidlist=$(echo "${response}" | _egrep_o "\"id\": *\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | tr -d " ")
|
||||||
|
zonenamelist=$(echo "${response}" | _egrep_o "\"name\": *\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | tr -d " ")
|
||||||
|
_debug2 "Return Zone ID(s):" "${zoneidlist}"
|
||||||
|
_debug2 "Return Zone Name(s):" "${zonenamelist}"
|
||||||
|
zoneidnum=0
|
||||||
|
zoneidcount=$(echo "${zoneidlist}" | grep -c '^')
|
||||||
|
_debug "Retund Zone ID(s) Count:" "${zoneidcount}"
|
||||||
|
while [ "${zoneidnum}" -lt "${zoneidcount}" ]; do
|
||||||
|
zoneidnum=$(_math "$zoneidnum" + 1)
|
||||||
|
_zoneid=$(echo "${zoneidlist}" | sed -n "${zoneidnum}p")
|
||||||
|
zonename=$(echo "${zonenamelist}" | sed -n "${zoneidnum}p")
|
||||||
|
_debug "Check Zone Name" "${zonename}"
|
||||||
|
if [ "${zonename}" = "${h}." ]; then
|
||||||
_debug "Get Zone ID Success."
|
_debug "Get Zone ID Success."
|
||||||
_zoneid=$(echo "${response}" | _egrep_o "\"id\": *\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | tr -d " ")
|
_debug "ZoneID:" "${_zoneid}"
|
||||||
printf "%s" "${_zoneid}"
|
printf "%s" "${_zoneid}"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
i=$(_math "$i" + 1)
|
i=$(_math "$i" + 1)
|
||||||
done
|
done
|
||||||
return 1
|
return 1
|
||||||
@@ -149,7 +163,7 @@ _get_recordset_id() {
|
|||||||
export _H1="X-Auth-Token: ${_token}"
|
export _H1="X-Auth-Token: ${_token}"
|
||||||
|
|
||||||
response=$(_get "${dns_api}/v2/zones/${_zoneid}/recordsets?name=${_domain}")
|
response=$(_get "${dns_api}/v2/zones/${_zoneid}/recordsets?name=${_domain}")
|
||||||
if _contains "${response}" "id"; then
|
if _contains "${response}" '"id"'; then
|
||||||
_id="$(echo "${response}" | _egrep_o "\"id\": *\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | tr -d " ")"
|
_id="$(echo "${response}" | _egrep_o "\"id\": *\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | tr -d " ")"
|
||||||
printf "%s" "${_id}"
|
printf "%s" "${_id}"
|
||||||
return 0
|
return 0
|
||||||
@@ -197,7 +211,7 @@ _add_record() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
_record_id="$(_get_recordset_id "${_token}" "${_domain}" "${zoneid}")"
|
_record_id="$(_get_recordset_id "${_token}" "${_domain}" "${zoneid}")"
|
||||||
_debug "Record Set ID is: ${_record_id}"
|
_debug "Record Set ID is:" "${_record_id}"
|
||||||
|
|
||||||
# Remove all records
|
# Remove all records
|
||||||
while [ "${_record_id}" != "0" ]; do
|
while [ "${_record_id}" != "0" ]; do
|
||||||
@@ -269,7 +283,7 @@ _get_token() {
|
|||||||
_post "${body}" "${iam_api}/v3/auth/tokens" >/dev/null
|
_post "${body}" "${iam_api}/v3/auth/tokens" >/dev/null
|
||||||
_code=$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")
|
_code=$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")
|
||||||
_token=$(grep "^X-Subject-Token" "$HTTP_HEADER" | cut -d " " -f 2-)
|
_token=$(grep "^X-Subject-Token" "$HTTP_HEADER" | cut -d " " -f 2-)
|
||||||
_debug2 "${_code}"
|
_secure_debug "${_code}"
|
||||||
printf "%s" "${_token}"
|
printf "%s" "${_token}"
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ dns_ispconfig_rm() {
|
|||||||
#################### Private functions below ##################################
|
#################### Private functions below ##################################
|
||||||
|
|
||||||
_ISPC_credentials() {
|
_ISPC_credentials() {
|
||||||
if [ -z "${ISPC_User}" ] || [ -z "$ISPC_Password" ] || [ -z "${ISPC_Api}" ] || [ -z "${ISPC_Api_Insecure}" ]; then
|
if [ -z "${ISPC_User}" ] || [ -z "$ISPC_Password" ] || [ -z "${ISPC_Api}" ] || [ -n "${ISPC_Api_Insecure}" ]; then
|
||||||
ISPC_User=""
|
ISPC_User=""
|
||||||
ISPC_Password=""
|
ISPC_Password=""
|
||||||
ISPC_Api=""
|
ISPC_Api=""
|
||||||
|
|||||||
@@ -19,8 +19,9 @@ dns_knot_add() {
|
|||||||
|
|
||||||
_info "Adding ${fulldomain}. 60 TXT \"${txtvalue}\""
|
_info "Adding ${fulldomain}. 60 TXT \"${txtvalue}\""
|
||||||
|
|
||||||
knsupdate -y "${KNOT_KEY}" <<EOF
|
knsupdate <<EOF
|
||||||
server ${KNOT_SERVER}
|
server ${KNOT_SERVER}
|
||||||
|
key ${KNOT_KEY}
|
||||||
zone ${_domain}.
|
zone ${_domain}.
|
||||||
update add ${fulldomain}. 60 TXT "${txtvalue}"
|
update add ${fulldomain}. 60 TXT "${txtvalue}"
|
||||||
send
|
send
|
||||||
@@ -49,8 +50,9 @@ dns_knot_rm() {
|
|||||||
|
|
||||||
_info "Removing ${fulldomain}. TXT"
|
_info "Removing ${fulldomain}. TXT"
|
||||||
|
|
||||||
knsupdate -y "${KNOT_KEY}" <<EOF
|
knsupdate <<EOF
|
||||||
server ${KNOT_SERVER}
|
server ${KNOT_SERVER}
|
||||||
|
key ${KNOT_KEY}
|
||||||
zone ${_domain}.
|
zone ${_domain}.
|
||||||
update del ${fulldomain}. TXT
|
update del ${fulldomain}. TXT
|
||||||
send
|
send
|
||||||
|
|||||||
261
dnsapi/dns_mythic_beasts.sh
Executable file
261
dnsapi/dns_mythic_beasts.sh
Executable file
@@ -0,0 +1,261 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
# Mythic Beasts is a long-standing UK service provider using standards-based OAuth2 authentication
|
||||||
|
# To test: ./acme.sh --dns dns_mythic_beasts --test --debug 1 --output-insecure --issue --domain domain.com
|
||||||
|
# Cannot retest once cert is issued
|
||||||
|
# OAuth2 tokens only valid for 300 seconds so we do not store
|
||||||
|
# NOTE: This will remove all TXT records matching the fulldomain, not just the added ones (_acme-challenge.www.domain.com)
|
||||||
|
|
||||||
|
# Test OAuth2 credentials
|
||||||
|
#MB_AK="aaaaaaaaaaaaaaaa"
|
||||||
|
#MB_AS="bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
|
||||||
|
|
||||||
|
# URLs
|
||||||
|
MB_API='https://api.mythic-beasts.com/dns/v2/zones'
|
||||||
|
MB_AUTH='https://auth.mythic-beasts.com/login'
|
||||||
|
|
||||||
|
######## Public functions #####################
|
||||||
|
|
||||||
|
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||||
|
dns_mythic_beasts_add() {
|
||||||
|
fulldomain=$1
|
||||||
|
txtvalue=$2
|
||||||
|
|
||||||
|
_info "MYTHIC BEASTS Adding record $fulldomain = $txtvalue"
|
||||||
|
if ! _initAuth; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! _get_root "$fulldomain"; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# method path body_data
|
||||||
|
if _mb_rest POST "$_domain/records/$_sub_domain/TXT" "$txtvalue"; then
|
||||||
|
|
||||||
|
if _contains "$response" "1 records added"; then
|
||||||
|
_info "Added, verifying..."
|
||||||
|
# Max 120 seconds to publish
|
||||||
|
for i in $(seq 1 6); do
|
||||||
|
# Retry on error
|
||||||
|
if ! _mb_rest GET "$_domain/records/$_sub_domain/TXT?verify"; then
|
||||||
|
_sleep 20
|
||||||
|
else
|
||||||
|
_info "Record published!"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
else
|
||||||
|
_err "\n$response"
|
||||||
|
fi
|
||||||
|
|
||||||
|
fi
|
||||||
|
_err "Add txt record error."
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
#Usage: rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||||
|
dns_mythic_beasts_rm() {
|
||||||
|
fulldomain=$1
|
||||||
|
txtvalue=$2
|
||||||
|
|
||||||
|
_info "MYTHIC BEASTS Removing record $fulldomain = $txtvalue"
|
||||||
|
if ! _initAuth; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! _get_root "$fulldomain"; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# method path body_data
|
||||||
|
if _mb_rest DELETE "$_domain/records/$_sub_domain/TXT" "$txtvalue"; then
|
||||||
|
_info "Record removed"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
_err "Remove txt record error."
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
#################### Private functions below ##################################
|
||||||
|
|
||||||
|
#Possible formats:
|
||||||
|
# _acme-challenge.www.example.com
|
||||||
|
# _acme-challenge.example.com
|
||||||
|
# _acme-challenge.example.co.uk
|
||||||
|
# _acme-challenge.www.example.co.uk
|
||||||
|
# _acme-challenge.sub1.sub2.www.example.co.uk
|
||||||
|
# sub1.sub2.example.co.uk
|
||||||
|
# example.com
|
||||||
|
# example.co.uk
|
||||||
|
#returns
|
||||||
|
# _sub_domain=_acme-challenge.www
|
||||||
|
# _domain=domain.com
|
||||||
|
_get_root() {
|
||||||
|
domain=$1
|
||||||
|
i=1
|
||||||
|
p=1
|
||||||
|
|
||||||
|
_debug "Detect the root zone"
|
||||||
|
while true; do
|
||||||
|
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
||||||
|
if [ -z "$h" ]; then
|
||||||
|
_err "Domain exhausted"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Use the status errors to find the domain, continue on 403 Access denied
|
||||||
|
# method path body_data
|
||||||
|
_mb_rest GET "$h/records"
|
||||||
|
ret="$?"
|
||||||
|
if [ "$ret" -eq 0 ]; then
|
||||||
|
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
|
||||||
|
_domain="$h"
|
||||||
|
_debug _sub_domain "$_sub_domain"
|
||||||
|
_debug _domain "$_domain"
|
||||||
|
return 0
|
||||||
|
elif [ "$ret" -eq 1 ]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
p=$i
|
||||||
|
i=$(_math "$i" + 1)
|
||||||
|
|
||||||
|
if [ "$i" -gt 50 ]; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
_err "Domain too long"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
_initAuth() {
|
||||||
|
MB_AK="${MB_AK:-$(_readaccountconf_mutable MB_AK)}"
|
||||||
|
MB_AS="${MB_AS:-$(_readaccountconf_mutable MB_AS)}"
|
||||||
|
|
||||||
|
if [ -z "$MB_AK" ] || [ -z "$MB_AS" ]; then
|
||||||
|
MB_AK=""
|
||||||
|
MB_AS=""
|
||||||
|
_err "Please specify an OAuth2 Key & Secret"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_saveaccountconf_mutable MB_AK "$MB_AK"
|
||||||
|
_saveaccountconf_mutable MB_AS "$MB_AS"
|
||||||
|
|
||||||
|
if ! _oauth2; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_info "Checking authentication"
|
||||||
|
_secure_debug access_token "$MB_TK"
|
||||||
|
_sleep 1
|
||||||
|
|
||||||
|
# GET a list of zones
|
||||||
|
# method path body_data
|
||||||
|
if ! _mb_rest GET ""; then
|
||||||
|
_err "The token is invalid"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_info "Token OK"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Github appears to use an outbound proxy for requests which means subsequent requests may not have the same
|
||||||
|
# source IP. The standard Mythic Beasts OAuth2 tokens are tied to an IP, meaning github test requests fail
|
||||||
|
# authentication. This is a work around using an undocumented MB API to obtain a token not tied to an
|
||||||
|
# IP just for the github tests.
|
||||||
|
_oauth2() {
|
||||||
|
if [ "$GITHUB_ACTIONS" = "true" ]; then
|
||||||
|
_oauth2_github
|
||||||
|
else
|
||||||
|
_oauth2_std
|
||||||
|
fi
|
||||||
|
return $?
|
||||||
|
}
|
||||||
|
|
||||||
|
_oauth2_std() {
|
||||||
|
# HTTP Basic Authentication
|
||||||
|
_H1="Authorization: Basic $(echo "$MB_AK:$MB_AS" | _base64)"
|
||||||
|
_H2="Accepts: application/json"
|
||||||
|
export _H1 _H2
|
||||||
|
body="grant_type=client_credentials"
|
||||||
|
|
||||||
|
_info "Getting OAuth2 token..."
|
||||||
|
# body url [needbase64] [POST|PUT|DELETE] [ContentType]
|
||||||
|
response="$(_post "$body" "$MB_AUTH" "" "POST" "application/x-www-form-urlencoded")"
|
||||||
|
if _contains "$response" "\"token_type\":\"bearer\""; then
|
||||||
|
MB_TK="$(echo "$response" | _egrep_o "access_token\":\"[^\"]*\"" | cut -d : -f 2 | tr -d '"')"
|
||||||
|
if [ -z "$MB_TK" ]; then
|
||||||
|
_err "Unable to get access_token"
|
||||||
|
_err "\n$response"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
_err "OAuth2 token_type not Bearer"
|
||||||
|
_err "\n$response"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_debug2 response "$response"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
_oauth2_github() {
|
||||||
|
_H1="Accepts: application/json"
|
||||||
|
export _H1
|
||||||
|
body="{\"login\":{\"handle\":\"$MB_AK\",\"pass\":\"$MB_AS\",\"floating\":1}}"
|
||||||
|
|
||||||
|
_info "Getting Floating token..."
|
||||||
|
# body url [needbase64] [POST|PUT|DELETE] [ContentType]
|
||||||
|
response="$(_post "$body" "$MB_AUTH" "" "POST" "application/json")"
|
||||||
|
MB_TK="$(echo "$response" | _egrep_o "\"token\":\"[^\"]*\"" | cut -d : -f 2 | tr -d '"')"
|
||||||
|
if [ -z "$MB_TK" ]; then
|
||||||
|
_err "Unable to get token"
|
||||||
|
_err "\n$response"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_debug2 response "$response"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# method path body_data
|
||||||
|
_mb_rest() {
|
||||||
|
# URL encoded body for single API operations
|
||||||
|
m="$1"
|
||||||
|
ep="$2"
|
||||||
|
data="$3"
|
||||||
|
|
||||||
|
if [ -z "$ep" ]; then
|
||||||
|
_mb_url="$MB_API"
|
||||||
|
else
|
||||||
|
_mb_url="$MB_API/$ep"
|
||||||
|
fi
|
||||||
|
|
||||||
|
_H1="Authorization: Bearer $MB_TK"
|
||||||
|
_H2="Accepts: application/json"
|
||||||
|
export _H1 _H2
|
||||||
|
if [ "$data" ] || [ "$m" = "POST" ] || [ "$m" = "PUT" ] || [ "$m" = "DELETE" ]; then
|
||||||
|
# body url [needbase64] [POST|PUT|DELETE] [ContentType]
|
||||||
|
response="$(_post "data=$data" "$_mb_url" "" "$m" "application/x-www-form-urlencoded")"
|
||||||
|
else
|
||||||
|
response="$(_get "$_mb_url")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$?" != "0" ]; then
|
||||||
|
_err "Request error"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
header="$(cat "$HTTP_HEADER")"
|
||||||
|
status="$(echo "$header" | _egrep_o "^HTTP[^ ]* .*$" | cut -d " " -f 2-100 | tr -d "\f\n")"
|
||||||
|
code="$(echo "$status" | _egrep_o "^[0-9]*")"
|
||||||
|
if [ "$code" -ge 400 ] || _contains "$response" "\"error\"" || _contains "$response" "invalid_client"; then
|
||||||
|
_err "error $status"
|
||||||
|
_err "\n$response"
|
||||||
|
_debug "\n$header"
|
||||||
|
return 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
_debug2 response "$response"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
@@ -150,7 +150,7 @@ _get_root() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
_debug h "$h"
|
_debug h "$h"
|
||||||
id=$(echo "$_domain_response" | _egrep_o "\"[^\"]*\":{\"enabled\":\"1\",\"type\":{\"master\":{\"value\":\"master\",\"selected\":1},\"slave\":{\"value\":\"slave\",\"selected\":0}},\"masterip\":\"[^\"]*\"(,\"allownotifyslave\":{\"\":{[^}]*}},|,)\"domainname\":\"${h}\"" | cut -d ':' -f 1 | cut -d '"' -f 2)
|
id=$(echo "$_domain_response" | _egrep_o "\"[^\"]*\":{\"enabled\":\"1\",\"type\":{\"master\":{\"value\":\"master\",\"selected\":1},\"slave\":{\"value\":\"slave\",\"selected\":0}},\"masterip\":{\"\":{[^}]*}}(,\"allownotifyslave\":{\"\":{[^}]*}},|,)\"domainname\":\"${h}\"" | cut -d ':' -f 1 | cut -d '"' -f 2)
|
||||||
|
|
||||||
if [ -n "$id" ]; then
|
if [ -n "$id" ]; then
|
||||||
_debug id "$id"
|
_debug id "$id"
|
||||||
|
|||||||
@@ -92,9 +92,10 @@ _get_root() {
|
|||||||
domains_list=$(echo "${response}" | grep dname | sed -r "s/.*dname=\"([^\"]+)\".*/\\1/g")
|
domains_list=$(echo "${response}" | grep dname | sed -r "s/.*dname=\"([^\"]+)\".*/\\1/g")
|
||||||
|
|
||||||
for ITEM in ${domains_list}; do
|
for ITEM in ${domains_list}; do
|
||||||
|
IDN_ITEM="$(_idn "${ITEM}")"
|
||||||
case "${domain}" in
|
case "${domain}" in
|
||||||
*${ITEM}*)
|
*${IDN_ITEM}*)
|
||||||
_domain=${ITEM}
|
_domain=${IDN_ITEM}
|
||||||
_debug _domain "${_domain}"
|
_debug _domain "${_domain}"
|
||||||
return 0
|
return 0
|
||||||
;;
|
;;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
#
|
# API-integration for Simply.com (https://www.simply.com)
|
||||||
|
|
||||||
#SIMPLY_AccountName="accountname"
|
#SIMPLY_AccountName="accountname"
|
||||||
#
|
|
||||||
#SIMPLY_ApiKey="apikey"
|
#SIMPLY_ApiKey="apikey"
|
||||||
#
|
#
|
||||||
#SIMPLY_Api="https://api.simply.com/1/[ACCOUNTNAME]/[APIKEY]"
|
#SIMPLY_Api="https://api.simply.com/1/[ACCOUNTNAME]/[APIKEY]"
|
||||||
@@ -51,7 +51,7 @@ dns_simply_rm() {
|
|||||||
|
|
||||||
_simply_save_config
|
_simply_save_config
|
||||||
|
|
||||||
_debug "First detect the root zone"
|
_debug "Find the DNS zone"
|
||||||
|
|
||||||
if ! _get_root "$fulldomain"; then
|
if ! _get_root "$fulldomain"; then
|
||||||
_err "invalid domain"
|
_err "invalid domain"
|
||||||
@@ -77,8 +77,8 @@ dns_simply_rm() {
|
|||||||
for record in $records; do
|
for record in $records; do
|
||||||
_debug record "$record"
|
_debug record "$record"
|
||||||
|
|
||||||
record_data=$(echo "$record" | cut -d "," -f 3 | sed 's/"//g' | grep "data" | cut -d ":" -f 2)
|
record_data=$(echo "$record" | sed -n "s/.*\"data\":\"\([^\"]*\)\".*/\1/p")
|
||||||
record_type=$(echo "$record" | cut -d "," -f 4 | sed 's/"//g' | grep "type" | cut -d ":" -f 2)
|
record_type=$(echo "$record" | sed -n "s/.*\"type\":\"\([^\"]*\)\".*/\1/p")
|
||||||
|
|
||||||
_debug2 record_data "$record_data"
|
_debug2 record_data "$record_data"
|
||||||
_debug2 record_type "$record_type"
|
_debug2 record_type "$record_type"
|
||||||
@@ -151,7 +151,7 @@ _simply_save_config() {
|
|||||||
_simply_get_all_records() {
|
_simply_get_all_records() {
|
||||||
domain=$1
|
domain=$1
|
||||||
|
|
||||||
if ! _simply_rest GET "my/products/$domain/dns/records"; then
|
if ! _simply_rest GET "my/products/$domain/dns/records/"; then
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -169,7 +169,7 @@ _get_root() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! _simply_rest GET "my/products/$h/dns"; then
|
if ! _simply_rest GET "my/products/$h/dns/"; then
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -193,7 +193,7 @@ _simply_add_record() {
|
|||||||
|
|
||||||
data="{\"name\": \"$sub_domain\", \"type\":\"TXT\", \"data\": \"$txtval\", \"priority\":0, \"ttl\": 3600}"
|
data="{\"name\": \"$sub_domain\", \"type\":\"TXT\", \"data\": \"$txtval\", \"priority\":0, \"ttl\": 3600}"
|
||||||
|
|
||||||
if ! _simply_rest POST "my/products/$domain/dns/records" "$data"; then
|
if ! _simply_rest POST "my/products/$domain/dns/records/" "$data"; then
|
||||||
_err "Adding record not successfull!"
|
_err "Adding record not successfull!"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
@@ -214,7 +214,7 @@ _simply_delete_record() {
|
|||||||
|
|
||||||
_debug record_id "Delete record with id $record_id"
|
_debug record_id "Delete record with id $record_id"
|
||||||
|
|
||||||
if ! _simply_rest DELETE "my/products/$domain/dns/records/$record_id"; then
|
if ! _simply_rest DELETE "my/products/$domain/dns/records/$record_id/"; then
|
||||||
_err "Deleting record not successfull!"
|
_err "Deleting record not successfull!"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
@@ -250,6 +250,8 @@ _simply_rest() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
response="$(echo "$response" | _normalizeJson)"
|
||||||
|
|
||||||
_debug2 response "$response"
|
_debug2 response "$response"
|
||||||
|
|
||||||
if _contains "$response" "Invalid account authorization"; then
|
if _contains "$response" "Invalid account authorization"; then
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ dns_world4you_add() {
|
|||||||
export _H1="Cookie: W4YSESSID=$sessid"
|
export _H1="Cookie: W4YSESSID=$sessid"
|
||||||
form=$(_get "$WORLD4YOU_API/$paketnr/dns")
|
form=$(_get "$WORLD4YOU_API/$paketnr/dns")
|
||||||
formiddp=$(echo "$form" | grep 'AddDnsRecordForm\[uniqueFormIdDP\]' | sed 's/^.*name="AddDnsRecordForm\[uniqueFormIdDP\]" value="\([^"]*\)".*$/\1/')
|
formiddp=$(echo "$form" | grep 'AddDnsRecordForm\[uniqueFormIdDP\]' | sed 's/^.*name="AddDnsRecordForm\[uniqueFormIdDP\]" value="\([^"]*\)".*$/\1/')
|
||||||
formidttl=$(echo "$form" | grep 'AddDnsRecordForm\[uniqueFormIdTTL\]' | sed 's/^.*name="AddDnsRecordForm\[uniqueFormIdTTL\]" value="\([^"]*\)".*$/\1/')
|
|
||||||
form_token=$(echo "$form" | grep 'AddDnsRecordForm\[_token\]' | sed 's/^.*name="AddDnsRecordForm\[_token\]" value="\([^"]*\)".*$/\1/')
|
form_token=$(echo "$form" | grep 'AddDnsRecordForm\[_token\]' | sed 's/^.*name="AddDnsRecordForm\[_token\]" value="\([^"]*\)".*$/\1/')
|
||||||
if [ -z "$formiddp" ]; then
|
if [ -z "$formiddp" ]; then
|
||||||
_err "Unable to parse form"
|
_err "Unable to parse form"
|
||||||
@@ -45,9 +44,7 @@ dns_world4you_add() {
|
|||||||
|
|
||||||
_resethttp
|
_resethttp
|
||||||
export ACME_HTTP_NO_REDIRECTS=1
|
export ACME_HTTP_NO_REDIRECTS=1
|
||||||
body="AddDnsRecordForm[name]=$RECORD&AddDnsRecordForm[dnsType][type]=TXT&\
|
body="AddDnsRecordForm[name]=$RECORD&AddDnsRecordForm[dnsType][type]=TXT&AddDnsRecordForm[value]=$value&AddDnsRecordForm[uniqueFormIdDP]=$formiddp&AddDnsRecordForm[_token]=$form_token"
|
||||||
AddDnsRecordForm[value]=$value&AddDnsRecordForm[aktivPaket]=$paketnr&AddDnsRecordForm[uniqueFormIdDP]=$formiddp&\
|
|
||||||
AddDnsRecordForm[uniqueFormIdTTL]=$formidttl&AddDnsRecordForm[_token]=$form_token"
|
|
||||||
_info "Adding record..."
|
_info "Adding record..."
|
||||||
ret=$(_post "$body" "$WORLD4YOU_API/$paketnr/dns" '' POST 'application/x-www-form-urlencoded')
|
ret=$(_post "$body" "$WORLD4YOU_API/$paketnr/dns" '' POST 'application/x-www-form-urlencoded')
|
||||||
_resethttp
|
_resethttp
|
||||||
@@ -101,7 +98,6 @@ dns_world4you_rm() {
|
|||||||
|
|
||||||
form=$(_get "$WORLD4YOU_API/$paketnr/dns")
|
form=$(_get "$WORLD4YOU_API/$paketnr/dns")
|
||||||
formiddp=$(echo "$form" | grep 'DeleteDnsRecordForm\[uniqueFormIdDP\]' | sed 's/^.*name="DeleteDnsRecordForm\[uniqueFormIdDP\]" value="\([^"]*\)".*$/\1/')
|
formiddp=$(echo "$form" | grep 'DeleteDnsRecordForm\[uniqueFormIdDP\]' | sed 's/^.*name="DeleteDnsRecordForm\[uniqueFormIdDP\]" value="\([^"]*\)".*$/\1/')
|
||||||
formidttl=$(echo "$form" | grep 'DeleteDnsRecordForm\[uniqueFormIdTTL\]' | sed 's/^.*name="DeleteDnsRecordForm\[uniqueFormIdTTL\]" value="\([^"]*\)".*$/\1/')
|
|
||||||
form_token=$(echo "$form" | grep 'DeleteDnsRecordForm\[_token\]' | sed 's/^.*name="DeleteDnsRecordForm\[_token\]" value="\([^"]*\)".*$/\1/')
|
form_token=$(echo "$form" | grep 'DeleteDnsRecordForm\[_token\]' | sed 's/^.*name="DeleteDnsRecordForm\[_token\]" value="\([^"]*\)".*$/\1/')
|
||||||
if [ -z "$formiddp" ]; then
|
if [ -z "$formiddp" ]; then
|
||||||
_err "Unable to parse form"
|
_err "Unable to parse form"
|
||||||
@@ -113,11 +109,9 @@ dns_world4you_rm() {
|
|||||||
|
|
||||||
_resethttp
|
_resethttp
|
||||||
export ACME_HTTP_NO_REDIRECTS=1
|
export ACME_HTTP_NO_REDIRECTS=1
|
||||||
body="DeleteDnsRecordForm[recordId]=$recordid&DeleteDnsRecordForm[aktivPaket]=$paketnr&\
|
body="DeleteDnsRecordForm[recordId]=$recordid&DeleteDnsRecordForm[uniqueFormIdDP]=$formiddp&DeleteDnsRecordForm[_token]=$form_token"
|
||||||
DeleteDnsRecordForm[uniqueFormIdDP]=$formiddp&DeleteDnsRecordForm[uniqueFormIdTTL]=$formidttl&\
|
|
||||||
DeleteDnsRecordForm[_token]=$form_token"
|
|
||||||
_info "Removing record..."
|
_info "Removing record..."
|
||||||
ret=$(_post "$body" "$WORLD4YOU_API/$paketnr/deleteRecord" '' POST 'application/x-www-form-urlencoded')
|
ret=$(_post "$body" "$WORLD4YOU_API/$paketnr/dns/record/delete" '' POST 'application/x-www-form-urlencoded')
|
||||||
_resethttp
|
_resethttp
|
||||||
|
|
||||||
if _contains "$(_head_n 3 <"$HTTP_HEADER")" '302'; then
|
if _contains "$(_head_n 3 <"$HTTP_HEADER")" '302'; then
|
||||||
@@ -190,7 +184,7 @@ _get_paketnr() {
|
|||||||
fqdn="$1"
|
fqdn="$1"
|
||||||
form="$2"
|
form="$2"
|
||||||
|
|
||||||
domains=$(echo "$form" | grep '^ *[A-Za-z0-9_\.-]*\.[A-Za-z0-9_-]*$' | sed 's/^\s*\(\S*\)$/\1/')
|
domains=$(echo "$form" | grep '^ *[A-Za-z0-9_\.-]*\.[A-Za-z0-9_-]*$' | sed 's/^ *\(.*\)$/\1/')
|
||||||
domain=''
|
domain=''
|
||||||
for domain in $domains; do
|
for domain in $domains; do
|
||||||
if _contains "$fqdn" "$domain\$"; then
|
if _contains "$fqdn" "$domain\$"; then
|
||||||
|
|||||||
51
notify/bark.sh
Normal file
51
notify/bark.sh
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
#Support iOS Bark Notification
|
||||||
|
|
||||||
|
#BARK_API_URL="https://api.day.app/xxxx"
|
||||||
|
#BARK_SOUND="yyyy"
|
||||||
|
#BARK_GROUP="zzzz"
|
||||||
|
|
||||||
|
# subject content statusCode
|
||||||
|
bark_send() {
|
||||||
|
_subject="$1"
|
||||||
|
_content="$2"
|
||||||
|
_statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped
|
||||||
|
_debug "_subject" "$_subject"
|
||||||
|
_debug "_content" "$_content"
|
||||||
|
_debug "_statusCode" "$_statusCode"
|
||||||
|
|
||||||
|
BARK_API_URL="${BARK_API_URL:-$(_readaccountconf_mutable BARK_API_URL)}"
|
||||||
|
if [ -z "$BARK_API_URL" ]; then
|
||||||
|
BARK_API_URL=""
|
||||||
|
_err "You didn't specify a Bark API URL BARK_API_URL yet."
|
||||||
|
_err "You can download Bark from App Store and get yours."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_saveaccountconf_mutable BARK_API_URL "$BARK_API_URL"
|
||||||
|
|
||||||
|
BARK_SOUND="${BARK_SOUND:-$(_readaccountconf_mutable BARK_SOUND)}"
|
||||||
|
_saveaccountconf_mutable BARK_SOUND "$BARK_SOUND"
|
||||||
|
|
||||||
|
BARK_GROUP="${BARK_GROUP:-$(_readaccountconf_mutable BARK_GROUP)}"
|
||||||
|
if [ -z "$BARK_GROUP" ]; then
|
||||||
|
BARK_GROUP="ACME"
|
||||||
|
_info "The BARK_GROUP is not set, so use the default ACME as group name."
|
||||||
|
else
|
||||||
|
_saveaccountconf_mutable BARK_GROUP "$BARK_GROUP"
|
||||||
|
fi
|
||||||
|
|
||||||
|
_content=$(echo "$_content" | _url_encode)
|
||||||
|
_subject=$(echo "$_subject" | _url_encode)
|
||||||
|
|
||||||
|
response="$(_get "$BARK_API_URL/$_subject/$_content?sound=$BARK_SOUND&group=$BARK_GROUP")"
|
||||||
|
|
||||||
|
if [ "$?" = "0" ] && _contains "$response" "success"; then
|
||||||
|
_info "Bark API fired success."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
_err "Bark API fired error."
|
||||||
|
_err "$response"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
48
notify/feishu.sh
Normal file
48
notify/feishu.sh
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
#Support feishu webhooks api
|
||||||
|
|
||||||
|
#required
|
||||||
|
#FEISHU_WEBHOOK="xxxx"
|
||||||
|
|
||||||
|
#optional
|
||||||
|
#FEISHU_KEYWORD="yyyy"
|
||||||
|
|
||||||
|
# subject content statusCode
|
||||||
|
feishu_send() {
|
||||||
|
_subject="$1"
|
||||||
|
_content="$2"
|
||||||
|
_statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped
|
||||||
|
_debug "_subject" "$_subject"
|
||||||
|
_debug "_content" "$_content"
|
||||||
|
_debug "_statusCode" "$_statusCode"
|
||||||
|
|
||||||
|
FEISHU_WEBHOOK="${FEISHU_WEBHOOK:-$(_readaccountconf_mutable FEISHU_WEBHOOK)}"
|
||||||
|
if [ -z "$FEISHU_WEBHOOK" ]; then
|
||||||
|
FEISHU_WEBHOOK=""
|
||||||
|
_err "You didn't specify a feishu webhooks FEISHU_WEBHOOK yet."
|
||||||
|
_err "You can get yours from https://www.feishu.cn"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_saveaccountconf_mutable FEISHU_WEBHOOK "$FEISHU_WEBHOOK"
|
||||||
|
|
||||||
|
FEISHU_KEYWORD="${FEISHU_KEYWORD:-$(_readaccountconf_mutable FEISHU_KEYWORD)}"
|
||||||
|
if [ "$FEISHU_KEYWORD" ]; then
|
||||||
|
_saveaccountconf_mutable FEISHU_KEYWORD "$FEISHU_KEYWORD"
|
||||||
|
fi
|
||||||
|
|
||||||
|
_content=$(echo "$_content" | _json_encode)
|
||||||
|
_subject=$(echo "$_subject" | _json_encode)
|
||||||
|
_data="{\"msg_type\": \"text\", \"content\": {\"text\": \"[$FEISHU_KEYWORD]\n$_subject\n$_content\"}}"
|
||||||
|
|
||||||
|
response="$(_post "$_data" "$FEISHU_WEBHOOK" "" "POST" "application/json")"
|
||||||
|
|
||||||
|
if [ "$?" = "0" ] && _contains "$response" "StatusCode\":0"; then
|
||||||
|
_info "feishu webhooks event fired success."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
_err "feishu webhooks event fired error."
|
||||||
|
_err "$response"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
62
notify/gotify.sh
Normal file
62
notify/gotify.sh
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
#Support Gotify
|
||||||
|
|
||||||
|
#GOTIFY_URL="https://gotify.example.com"
|
||||||
|
#GOTIFY_TOKEN="123456789ABCDEF"
|
||||||
|
|
||||||
|
#optional
|
||||||
|
#GOTIFY_PRIORITY=0
|
||||||
|
|
||||||
|
# subject content statusCode
|
||||||
|
gotify_send() {
|
||||||
|
_subject="$1"
|
||||||
|
_content="$2"
|
||||||
|
_statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped
|
||||||
|
_debug "_subject" "$_subject"
|
||||||
|
_debug "_content" "$_content"
|
||||||
|
_debug "_statusCode" "$_statusCode"
|
||||||
|
|
||||||
|
GOTIFY_URL="${GOTIFY_URL:-$(_readaccountconf_mutable GOTIFY_URL)}"
|
||||||
|
if [ -z "$GOTIFY_URL" ]; then
|
||||||
|
GOTIFY_URL=""
|
||||||
|
_err "You didn't specify the gotify server url GOTIFY_URL."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_saveaccountconf_mutable GOTIFY_URL "$GOTIFY_URL"
|
||||||
|
|
||||||
|
GOTIFY_TOKEN="${GOTIFY_TOKEN:-$(_readaccountconf_mutable GOTIFY_TOKEN)}"
|
||||||
|
if [ -z "$GOTIFY_TOKEN" ]; then
|
||||||
|
GOTIFY_TOKEN=""
|
||||||
|
_err "You didn't specify the gotify token GOTIFY_TOKEN."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_saveaccountconf_mutable GOTIFY_TOKEN "$GOTIFY_TOKEN"
|
||||||
|
|
||||||
|
GOTIFY_PRIORITY="${GOTIFY_PRIORITY:-$(_readaccountconf_mutable GOTIFY_PRIORITY)}"
|
||||||
|
if [ -z "$GOTIFY_PRIORITY" ]; then
|
||||||
|
GOTIFY_PRIORITY=0
|
||||||
|
else
|
||||||
|
_saveaccountconf_mutable GOTIFY_PRIORITY "$GOTIFY_PRIORITY"
|
||||||
|
fi
|
||||||
|
|
||||||
|
export _H1="X-Gotify-Key: ${GOTIFY_TOKEN}"
|
||||||
|
export _H2="Content-Type: application/json"
|
||||||
|
|
||||||
|
_content=$(echo "$_content" | _json_encode)
|
||||||
|
_subject=$(echo "$_subject" | _json_encode)
|
||||||
|
|
||||||
|
_data="{\"title\": \"${_subject}\", \"message\": \"${_content}\", \"priority\": ${GOTIFY_PRIORITY}}"
|
||||||
|
|
||||||
|
response="$(_post "${_data}" "${GOTIFY_URL}/message" "" "POST" "application/json")"
|
||||||
|
|
||||||
|
if [ "$?" != "0" ]; then
|
||||||
|
_err "Failed to send message"
|
||||||
|
_err "$response"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_debug2 response "$response"
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
@@ -62,7 +62,7 @@ mail_send() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
contenttype="text/plain; charset=utf-8"
|
contenttype="text/plain; charset=utf-8"
|
||||||
subject="=?UTF-8?B?$(echo "$_subject" | _base64)?="
|
subject="=?UTF-8?B?$(printf -- "%b" "$_subject" | _base64)?="
|
||||||
result=$({ _mail_body | eval "$(_mail_cmnd)"; } 2>&1)
|
result=$({ _mail_body | eval "$(_mail_cmnd)"; } 2>&1)
|
||||||
|
|
||||||
# shellcheck disable=SC2181
|
# shellcheck disable=SC2181
|
||||||
@@ -131,6 +131,7 @@ _mail_body() {
|
|||||||
echo "To: $MAIL_TO"
|
echo "To: $MAIL_TO"
|
||||||
echo "Subject: $subject"
|
echo "Subject: $subject"
|
||||||
echo "Content-Type: $contenttype"
|
echo "Content-Type: $contenttype"
|
||||||
|
echo "MIME-Version: 1.0"
|
||||||
echo
|
echo
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|||||||
Reference in New Issue
Block a user