Compare commits

...
237 Commits
46 changed files with 2233 additions and 372 deletions
+18 -13
View File
@@ -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
@@ -61,22 +62,22 @@ jobs:
run: | run: |
cd ../acmetest cd ../acmetest
if [ "${{ secrets.TokenName1}}" ] ; then if [ "${{ secrets.TokenName1}}" ] ; then
echo "${{ secrets.TokenName1}}=${{ secrets.TokenValue1}}" >> env.list echo "${{ secrets.TokenName1}}=${{ secrets.TokenValue1}}" >> docker.env
fi fi
if [ "${{ secrets.TokenName2}}" ] ; then if [ "${{ secrets.TokenName2}}" ] ; then
echo "${{ secrets.TokenName2}}=${{ secrets.TokenValue2}}" >> env.list echo "${{ secrets.TokenName2}}=${{ secrets.TokenValue2}}" >> docker.env
fi fi
if [ "${{ secrets.TokenName3}}" ] ; then if [ "${{ secrets.TokenName3}}" ] ; then
echo "${{ secrets.TokenName3}}=${{ secrets.TokenValue3}}" >> env.list echo "${{ secrets.TokenName3}}=${{ secrets.TokenValue3}}" >> docker.env
fi fi
if [ "${{ secrets.TokenName4}}" ] ; then if [ "${{ secrets.TokenName4}}" ] ; then
echo "${{ secrets.TokenName4}}=${{ secrets.TokenValue4}}" >> env.list echo "${{ secrets.TokenName4}}=${{ secrets.TokenValue4}}" >> docker.env
fi fi
if [ "${{ secrets.TokenName5}}" ] ; then if [ "${{ secrets.TokenName5}}" ] ; then
echo "${{ secrets.TokenName5}}=${{ secrets.TokenValue5}}" >> env.list echo "${{ secrets.TokenName5}}=${{ secrets.TokenValue5}}" >> docker.env
fi fi
echo "TEST_DNS_NO_WILDCARD" >> env.list echo "TEST_DNS_NO_WILDCARD" >> docker.env
echo "TEST_DNS_SLEEP" >> env.list echo "TEST_DNS_SLEEP" >> docker.env
- name: Run acmetest - name: Run acmetest
run: cd ../acmetest && ./rundocker.sh testall run: cd ../acmetest && ./rundocker.sh testall
@@ -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
+7 -4
View File
@@ -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
+2 -1
View File
@@ -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", "clearlinux:latest"] 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
View File
@@ -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
View File
@@ -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
+7 -4
View File
@@ -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
View File
@@ -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 -2
View File
@@ -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,12 +52,12 @@ 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
run: | run: |
echo PATH=C:\tools\cygwin\bin;C:\tools\cygwin\usr\bin >> %GITHUB_ENV% echo PATH=C:\tools\cygwin\bin;C:\tools\cygwin\usr\bin;%PATH% >> %GITHUB_ENV%
- name: Check ENV - name: Check ENV
shell: cmd shell: cmd
run: | run: |
+5 -2
View File
@@ -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
+232 -133
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env sh #!/usr/bin/env sh
VER=3.0.0 VER=3.0.2
PROJECT_NAME="acme.sh" PROJECT_NAME="acme.sh"
@@ -20,6 +20,8 @@ _SUB_FOLDER_DEPLOY="deploy"
_SUB_FOLDERS="$_SUB_FOLDER_DNSAPI $_SUB_FOLDER_DEPLOY $_SUB_FOLDER_NOTIFY" _SUB_FOLDERS="$_SUB_FOLDER_DNSAPI $_SUB_FOLDER_DEPLOY $_SUB_FOLDER_NOTIFY"
CA_LETSENCRYPT_V1="https://acme-v01.api.letsencrypt.org/directory"
CA_LETSENCRYPT_V2="https://acme-v02.api.letsencrypt.org/directory" CA_LETSENCRYPT_V2="https://acme-v02.api.letsencrypt.org/directory"
CA_LETSENCRYPT_V2_TEST="https://acme-staging-v02.api.letsencrypt.org/directory" CA_LETSENCRYPT_V2_TEST="https://acme-staging-v02.api.letsencrypt.org/directory"
@@ -27,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"
@@ -57,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
@@ -75,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-----"
@@ -139,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"
@@ -424,19 +431,27 @@ _secure_debug3() {
} }
_upper_case() { _upper_case() {
# shellcheck disable=SC2018,SC2019 if _is_solaris; then
tr 'a-z' 'A-Z' tr '[:lower:]' '[:upper:]'
else
# shellcheck disable=SC2018,SC2019
tr 'a-z' 'A-Z'
fi
} }
_lower_case() { _lower_case() {
# shellcheck disable=SC2018,SC2019 if _is_solaris; then
tr 'A-Z' 'a-z' tr '[:upper:]' '[:lower:]'
else
# shellcheck disable=SC2018,SC2019
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() {
@@ -1038,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"
@@ -1220,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"
@@ -1249,9 +1273,17 @@ _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
${ACME_OPENSSL_BIN:-openssl} req -new -sha256 -key "$csrkey" -subj "//CN=$_csr_cn" -config "$csrconf" -out "$csr" 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"
fi
else else
${ACME_OPENSSL_BIN:-openssl} req -new -sha256 -key "$csrkey" -subj "/CN=$_csr_cn" -config "$csrconf" -out "$csr" 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"
fi
fi fi
} }
@@ -1600,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"
@@ -1613,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
@@ -1635,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"
@@ -1808,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"
@@ -1817,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"
@@ -1895,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")"
@@ -1953,9 +1972,7 @@ _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
@@ -1969,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
@@ -2019,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")"
@@ -2047,9 +2037,7 @@ _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=$?
@@ -3166,9 +3154,9 @@ _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
if _checkConf "$1" "$included"; then if _checkConf "$1" "$included"; then
return 0 return 0
@@ -3380,6 +3368,8 @@ _on_before_issue() {
if [ "$_chk_pre_hook" ]; then if [ "$_chk_pre_hook" ]; then
_info "Run pre hook:'$_chk_pre_hook'" _info "Run pre hook:'$_chk_pre_hook'"
if ! ( if ! (
export Le_Domain="$_chk_main_domain"
export Le_Alt="$_chk_alt_domains"
cd "$DOMAIN_PATH" && eval "$_chk_pre_hook" cd "$DOMAIN_PATH" && eval "$_chk_pre_hook"
); then ); then
_err "Error when run pre hook." _err "Error when run pre hook."
@@ -4170,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
@@ -4207,7 +4232,7 @@ issue() {
if [ -z "$_ACME_IS_RENEW" ]; then if [ -z "$_ACME_IS_RENEW" ]; then
_initpath "$_main_domain" "$_key_length" _initpath "$_main_domain" "$_key_length"
mkdir -p "$DOMAIN_PATH" mkdir -p "$DOMAIN_PATH"
else elif ! _hasfield "$_web_roots" "$W_DNS"; then
Le_OrderFinalize="" Le_OrderFinalize=""
Le_LinkOrder="" Le_LinkOrder=""
Le_LinkCert="" Le_LinkCert=""
@@ -4218,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"
@@ -4243,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"
@@ -4327,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")"
@@ -4336,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
@@ -4930,7 +4954,9 @@ $_authorizations_map"
echo "$response" >"$CERT_PATH" echo "$response" >"$CERT_PATH"
_split_cert_chain "$CERT_PATH" "$CERT_FULLCHAIN_PATH" "$CA_CERT_PATH" _split_cert_chain "$CERT_PATH" "$CERT_FULLCHAIN_PATH" "$CA_CERT_PATH"
if [ -z "$_preferred_chain" ]; then
_preferred_chain=$(_readcaconf DEFAULT_PREFERRED_CHAIN)
fi
if [ "$_preferred_chain" ] && [ -f "$CERT_FULLCHAIN_PATH" ]; then if [ "$_preferred_chain" ] && [ -f "$CERT_FULLCHAIN_PATH" ]; then
if [ "$DEBUG" ]; then if [ "$DEBUG" ]; then
_debug "default chain issuers: " "$(_get_chain_issuers "$CERT_FULLCHAIN_PATH")" _debug "default chain issuers: " "$(_get_chain_issuers "$CERT_FULLCHAIN_PATH")"
@@ -4984,10 +5010,10 @@ $_authorizations_map"
_info "$(__green "Cert success.")" _info "$(__green "Cert success.")"
cat "$CERT_PATH" cat "$CERT_PATH"
_info "Your cert is in $(__green " $CERT_PATH ")" _info "Your cert is in: $(__green "$CERT_PATH")"
if [ -f "$CERT_KEY_PATH" ]; then if [ -f "$CERT_KEY_PATH" ]; then
_info "Your cert key is in $(__green " $CERT_KEY_PATH ")" _info "Your cert key is in: $(__green "$CERT_KEY_PATH")"
fi fi
if [ ! "$USER_PATH" ] || [ ! "$_ACME_IN_CRON" ]; then if [ ! "$USER_PATH" ] || [ ! "$_ACME_IN_CRON" ]; then
@@ -4996,8 +5022,8 @@ $_authorizations_map"
fi fi
fi fi
[ -f "$CA_CERT_PATH" ] && _info "The intermediate CA cert is in $(__green " $CA_CERT_PATH ")" [ -f "$CA_CERT_PATH" ] && _info "The intermediate CA cert is in: $(__green "$CA_CERT_PATH")"
[ -f "$CERT_FULLCHAIN_PATH" ] && _info "And the full chain certs is there: $(__green " $CERT_FULLCHAIN_PATH ")" [ -f "$CERT_FULLCHAIN_PATH" ] && _info "And the full chain certs is there: $(__green "$CERT_FULLCHAIN_PATH")"
Le_CertCreateTime=$(_time) Le_CertCreateTime=$(_time)
_savedomainconf "Le_CertCreateTime" "$Le_CertCreateTime" _savedomainconf "Le_CertCreateTime" "$Le_CertCreateTime"
@@ -5095,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."
@@ -5108,7 +5134,7 @@ renew() {
. "$DOMAIN_CONF" . "$DOMAIN_CONF"
_debug Le_API "$Le_API" _debug Le_API "$Le_API"
if [ -z "$Le_API" ]; then if [ -z "$Le_API" ] || [ "$CA_LETSENCRYPT_V1" = "$Le_API" ]; then
#if this is from an old version, Le_API is empty, #if this is from an old version, Le_API is empty,
#so, we force to use letsencrypt server #so, we force to use letsencrypt server
Le_API="$CA_LETSENCRYPT_V2" Le_API="$CA_LETSENCRYPT_V2"
@@ -5125,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
@@ -5157,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"
} }
@@ -5174,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
@@ -5196,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
@@ -5210,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
" "
@@ -5225,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
@@ -5246,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
@@ -5541,7 +5583,7 @@ _installcert() {
mkdir -p "$_backup_path" mkdir -p "$_backup_path"
if [ "$_real_cert" ]; then if [ "$_real_cert" ]; then
_info "Installing cert to:$_real_cert" _info "Installing cert to: $_real_cert"
if [ -f "$_real_cert" ] && [ ! "$_ACME_IS_RENEW" ]; then if [ -f "$_real_cert" ] && [ ! "$_ACME_IS_RENEW" ]; then
cp "$_real_cert" "$_backup_path/cert.bak" cp "$_real_cert" "$_backup_path/cert.bak"
fi fi
@@ -5549,7 +5591,7 @@ _installcert() {
fi fi
if [ "$_real_ca" ]; then if [ "$_real_ca" ]; then
_info "Installing CA to:$_real_ca" _info "Installing CA to: $_real_ca"
if [ "$_real_ca" = "$_real_cert" ]; then if [ "$_real_ca" = "$_real_cert" ]; then
echo "" >>"$_real_ca" echo "" >>"$_real_ca"
cat "$CA_CERT_PATH" >>"$_real_ca" || return 1 cat "$CA_CERT_PATH" >>"$_real_ca" || return 1
@@ -5562,7 +5604,7 @@ _installcert() {
fi fi
if [ "$_real_key" ]; then if [ "$_real_key" ]; then
_info "Installing key to:$_real_key" _info "Installing key to: $_real_key"
if [ -f "$_real_key" ] && [ ! "$_ACME_IS_RENEW" ]; then if [ -f "$_real_key" ] && [ ! "$_ACME_IS_RENEW" ]; then
cp "$_real_key" "$_backup_path/key.bak" cp "$_real_key" "$_backup_path/key.bak"
fi fi
@@ -5575,7 +5617,7 @@ _installcert() {
fi fi
if [ "$_real_fullchain" ]; then if [ "$_real_fullchain" ]; then
_info "Installing full chain to:$_real_fullchain" _info "Installing full chain to: $_real_fullchain"
if [ -f "$_real_fullchain" ] && [ ! "$_ACME_IS_RENEW" ]; then if [ -f "$_real_fullchain" ] && [ ! "$_ACME_IS_RENEW" ]; then
cp "$_real_fullchain" "$_backup_path/fullchain.bak" cp "$_real_fullchain" "$_backup_path/fullchain.bak"
fi fi
@@ -5670,8 +5712,16 @@ installcronjob() {
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 else
_err "Can not install cronjob, $PROJECT_ENTRY not found." _debug "_SCRIPT_" "$_SCRIPT_"
return 1 _script="$(_readlink "$_SCRIPT_")"
_debug _script "$_script"
if [ -f "$_script" ]; then
_info "Using the current script from: $_script"
lesh="$_script"
else
_err "Can not install cronjob, $PROJECT_ENTRY not found."
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\" "
@@ -5743,7 +5793,7 @@ uninstallcronjob() {
_info "Removing cron job" _info "Removing cron job"
cr="$($_CRONTAB -l | grep "$PROJECT_ENTRY --cron")" cr="$($_CRONTAB -l | grep "$PROJECT_ENTRY --cron")"
if [ "$cr" ]; then if [ "$cr" ]; then
if _exists uname && uname -a | grep solaris >/dev/null; then if _exists uname && uname -a | grep SunOS >/dev/null; then
$_CRONTAB -l | sed "/$PROJECT_ENTRY --cron/d" | $_CRONTAB -- $_CRONTAB -l | sed "/$PROJECT_ENTRY --cron/d" | $_CRONTAB --
else else
$_CRONTAB -l | sed "/$PROJECT_ENTRY --cron/d" | $_CRONTAB - $_CRONTAB -l | sed "/$PROJECT_ENTRY --cron/d" | $_CRONTAB -
@@ -5898,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
@@ -5934,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
@@ -6526,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.
@@ -6543,6 +6594,8 @@ Commands:
--deactivate Deactivate the domain authz, professional use. --deactivate Deactivate the domain authz, professional use.
--set-default-ca Used with '--server', Set the default CA to use. --set-default-ca Used with '--server', Set the default CA to use.
See: $_SERVER_WIKI See: $_SERVER_WIKI
--set-default-chain Set the default preferred chain for a CA.
See: $_PREFERRED_CHAIN_WIKI
Parameters: Parameters:
@@ -6829,6 +6882,40 @@ setdefaultca() {
_info "Changed default CA to: $(__green "$ACME_DIRECTORY")" _info "Changed default CA to: $(__green "$ACME_DIRECTORY")"
} }
#preferred-chain
setdefaultchain() {
_initpath
_preferred_chain="$1"
if [ -z "$_preferred_chain" ]; then
_err "Please give a '--preferred-chain value' value."
return 1
fi
mkdir -p "$CA_DIR"
_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=""
@@ -6938,6 +7025,9 @@ _process() {
--list) --list)
_CMD="list" _CMD="list"
;; ;;
--info)
_CMD="info"
;;
--install-cronjob | --installcronjob) --install-cronjob | --installcronjob)
_CMD="installcronjob" _CMD="installcronjob"
;; ;;
@@ -6980,6 +7070,9 @@ _process() {
--set-default-ca) --set-default-ca)
_CMD="setdefaultca" _CMD="setdefaultca"
;; ;;
--set-default-chain)
_CMD="setdefaultchain"
;;
-d | --domain) -d | --domain)
_dvalue="$2" _dvalue="$2"
@@ -7486,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 ;;
@@ -7510,6 +7606,9 @@ _process() {
setdefaultca) setdefaultca)
setdefaultca setdefaultca
;; ;;
setdefaultchain)
setdefaultchain "$_preferred_chain"
;;
*) *)
if [ "$_CMD" ]; then if [ "$_CMD" ]; then
_err "Invalid command: $_CMD" _err "Invalid command: $_CMD"
+26 -18
View File
@@ -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
+15 -10
View File
@@ -54,11 +54,6 @@ haproxy_deploy() {
DEPLOY_HAPROXY_ISSUER_DEFAULT="no" DEPLOY_HAPROXY_ISSUER_DEFAULT="no"
DEPLOY_HAPROXY_RELOAD_DEFAULT="true" DEPLOY_HAPROXY_RELOAD_DEFAULT="true"
if [ -f "${DOMAIN_CONF}" ]; then
# shellcheck disable=SC1090
. "${DOMAIN_CONF}"
fi
_debug _cdomain "${_cdomain}" _debug _cdomain "${_cdomain}"
_debug _ckey "${_ckey}" _debug _ckey "${_ckey}"
_debug _ccert "${_ccert}" _debug _ccert "${_ccert}"
@@ -66,6 +61,8 @@ haproxy_deploy() {
_debug _cfullchain "${_cfullchain}" _debug _cfullchain "${_cfullchain}"
# PEM_PATH is optional. If not provided then assume "${DEPLOY_HAPROXY_PEM_PATH_DEFAULT}" # PEM_PATH is optional. If not provided then assume "${DEPLOY_HAPROXY_PEM_PATH_DEFAULT}"
_getdeployconf DEPLOY_HAPROXY_PEM_PATH
_debug2 DEPLOY_HAPROXY_PEM_PATH "${DEPLOY_HAPROXY_PEM_PATH}"
if [ -n "${DEPLOY_HAPROXY_PEM_PATH}" ]; then if [ -n "${DEPLOY_HAPROXY_PEM_PATH}" ]; then
Le_Deploy_haproxy_pem_path="${DEPLOY_HAPROXY_PEM_PATH}" Le_Deploy_haproxy_pem_path="${DEPLOY_HAPROXY_PEM_PATH}"
_savedomainconf Le_Deploy_haproxy_pem_path "${Le_Deploy_haproxy_pem_path}" _savedomainconf Le_Deploy_haproxy_pem_path "${Le_Deploy_haproxy_pem_path}"
@@ -82,6 +79,8 @@ haproxy_deploy() {
fi fi
# PEM_NAME is optional. If not provided then assume "${DEPLOY_HAPROXY_PEM_NAME_DEFAULT}" # PEM_NAME is optional. If not provided then assume "${DEPLOY_HAPROXY_PEM_NAME_DEFAULT}"
_getdeployconf DEPLOY_HAPROXY_PEM_NAME
_debug2 DEPLOY_HAPROXY_PEM_NAME "${DEPLOY_HAPROXY_PEM_NAME}"
if [ -n "${DEPLOY_HAPROXY_PEM_NAME}" ]; then if [ -n "${DEPLOY_HAPROXY_PEM_NAME}" ]; then
Le_Deploy_haproxy_pem_name="${DEPLOY_HAPROXY_PEM_NAME}" Le_Deploy_haproxy_pem_name="${DEPLOY_HAPROXY_PEM_NAME}"
_savedomainconf Le_Deploy_haproxy_pem_name "${Le_Deploy_haproxy_pem_name}" _savedomainconf Le_Deploy_haproxy_pem_name "${Le_Deploy_haproxy_pem_name}"
@@ -90,6 +89,8 @@ haproxy_deploy() {
fi fi
# BUNDLE is optional. If not provided then assume "${DEPLOY_HAPROXY_BUNDLE_DEFAULT}" # BUNDLE is optional. If not provided then assume "${DEPLOY_HAPROXY_BUNDLE_DEFAULT}"
_getdeployconf DEPLOY_HAPROXY_BUNDLE
_debug2 DEPLOY_HAPROXY_BUNDLE "${DEPLOY_HAPROXY_BUNDLE}"
if [ -n "${DEPLOY_HAPROXY_BUNDLE}" ]; then if [ -n "${DEPLOY_HAPROXY_BUNDLE}" ]; then
Le_Deploy_haproxy_bundle="${DEPLOY_HAPROXY_BUNDLE}" Le_Deploy_haproxy_bundle="${DEPLOY_HAPROXY_BUNDLE}"
_savedomainconf Le_Deploy_haproxy_bundle "${Le_Deploy_haproxy_bundle}" _savedomainconf Le_Deploy_haproxy_bundle "${Le_Deploy_haproxy_bundle}"
@@ -98,6 +99,8 @@ haproxy_deploy() {
fi fi
# ISSUER is optional. If not provided then assume "${DEPLOY_HAPROXY_ISSUER_DEFAULT}" # ISSUER is optional. If not provided then assume "${DEPLOY_HAPROXY_ISSUER_DEFAULT}"
_getdeployconf DEPLOY_HAPROXY_ISSUER
_debug2 DEPLOY_HAPROXY_ISSUER "${DEPLOY_HAPROXY_ISSUER}"
if [ -n "${DEPLOY_HAPROXY_ISSUER}" ]; then if [ -n "${DEPLOY_HAPROXY_ISSUER}" ]; then
Le_Deploy_haproxy_issuer="${DEPLOY_HAPROXY_ISSUER}" Le_Deploy_haproxy_issuer="${DEPLOY_HAPROXY_ISSUER}"
_savedomainconf Le_Deploy_haproxy_issuer "${Le_Deploy_haproxy_issuer}" _savedomainconf Le_Deploy_haproxy_issuer "${Le_Deploy_haproxy_issuer}"
@@ -106,6 +109,8 @@ haproxy_deploy() {
fi fi
# RELOAD is optional. If not provided then assume "${DEPLOY_HAPROXY_RELOAD_DEFAULT}" # RELOAD is optional. If not provided then assume "${DEPLOY_HAPROXY_RELOAD_DEFAULT}"
_getdeployconf DEPLOY_HAPROXY_RELOAD
_debug2 DEPLOY_HAPROXY_RELOAD "${DEPLOY_HAPROXY_RELOAD}"
if [ -n "${DEPLOY_HAPROXY_RELOAD}" ]; then if [ -n "${DEPLOY_HAPROXY_RELOAD}" ]; then
Le_Deploy_haproxy_reload="${DEPLOY_HAPROXY_RELOAD}" Le_Deploy_haproxy_reload="${DEPLOY_HAPROXY_RELOAD}"
_savedomainconf Le_Deploy_haproxy_reload "${Le_Deploy_haproxy_reload}" _savedomainconf Le_Deploy_haproxy_reload "${Le_Deploy_haproxy_reload}"
@@ -190,7 +195,7 @@ haproxy_deploy() {
_info "Updating OCSP stapling info" _info "Updating OCSP stapling info"
_debug _ocsp "${_ocsp}" _debug _ocsp "${_ocsp}"
_info "Extracting OCSP URL" _info "Extracting OCSP URL"
_ocsp_url=$(openssl x509 -noout -ocsp_uri -in "${_pem}") _ocsp_url=$(${ACME_OPENSSL_BIN:-openssl} x509 -noout -ocsp_uri -in "${_pem}")
_debug _ocsp_url "${_ocsp_url}" _debug _ocsp_url "${_ocsp_url}"
# Only process OCSP if URL was present # Only process OCSP if URL was present
@@ -203,9 +208,9 @@ haproxy_deploy() {
# Only process the certificate if we have a .issuer file # Only process the certificate if we have a .issuer file
if [ -r "${_issuer}" ]; then if [ -r "${_issuer}" ]; then
# Check if issuer cert is also a root CA cert # Check if issuer cert is also a root CA cert
_subjectdn=$(openssl x509 -in "${_issuer}" -subject -noout | cut -d'/' -f2,3,4,5,6,7,8,9,10) _subjectdn=$(${ACME_OPENSSL_BIN:-openssl} x509 -in "${_issuer}" -subject -noout | cut -d'/' -f2,3,4,5,6,7,8,9,10)
_debug _subjectdn "${_subjectdn}" _debug _subjectdn "${_subjectdn}"
_issuerdn=$(openssl x509 -in "${_issuer}" -issuer -noout | cut -d'/' -f2,3,4,5,6,7,8,9,10) _issuerdn=$(${ACME_OPENSSL_BIN:-openssl} x509 -in "${_issuer}" -issuer -noout | cut -d'/' -f2,3,4,5,6,7,8,9,10)
_debug _issuerdn "${_issuerdn}" _debug _issuerdn "${_issuerdn}"
_info "Requesting OCSP response" _info "Requesting OCSP response"
# If the issuer is a CA cert then our command line has "-CAfile" added # If the issuer is a CA cert then our command line has "-CAfile" added
@@ -216,7 +221,7 @@ haproxy_deploy() {
fi fi
_debug _cafile_argument "${_cafile_argument}" _debug _cafile_argument "${_cafile_argument}"
# if OpenSSL/LibreSSL is v1.1 or above, the format for the -header option has changed # if OpenSSL/LibreSSL is v1.1 or above, the format for the -header option has changed
_openssl_version=$(openssl version | cut -d' ' -f2) _openssl_version=$(${ACME_OPENSSL_BIN:-openssl} version | cut -d' ' -f2)
_debug _openssl_version "${_openssl_version}" _debug _openssl_version "${_openssl_version}"
_openssl_major=$(echo "${_openssl_version}" | cut -d '.' -f1) _openssl_major=$(echo "${_openssl_version}" | cut -d '.' -f1)
_openssl_minor=$(echo "${_openssl_version}" | cut -d '.' -f2) _openssl_minor=$(echo "${_openssl_version}" | cut -d '.' -f2)
@@ -226,7 +231,7 @@ haproxy_deploy() {
_header_sep=" " _header_sep=" "
fi fi
# Request the OCSP response from the issuer and store it # Request the OCSP response from the issuer and store it
_openssl_ocsp_cmd="openssl ocsp \ _openssl_ocsp_cmd="${ACME_OPENSSL_BIN:-openssl} ocsp \
-issuer \"${_issuer}\" \ -issuer \"${_issuer}\" \
-cert \"${_pem}\" \ -cert \"${_pem}\" \
-url \"${_ocsp_url}\" \ -url \"${_ocsp_url}\" \
+1 -1
View File
@@ -45,7 +45,7 @@ kong_deploy() {
#Generate data for request (Multipart/form-data with mixed content) #Generate data for request (Multipart/form-data with mixed content)
if [ -z "$ssl_uuid" ]; then if [ -z "$ssl_uuid" ]; then
#set sni to domain #set sni to domain
content="--$delim${nl}Content-Disposition: form-data; name=\"snis\"${nl}${nl}$_cdomain" content="--$delim${nl}Content-Disposition: form-data; name=\"snis[]\"${nl}${nl}$_cdomain"
fi fi
#add key #add key
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"key\"; filename=\"$(basename "$_ckey")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ckey")" content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"key\"; filename=\"$(basename "$_ckey")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ckey")"
+280
View File
@@ -0,0 +1,280 @@
#!/usr/bin/env sh
# Script for acme.sh to deploy certificates to lighttpd
#
# The following variables can be exported:
#
# export DEPLOY_LIGHTTPD_PEM_NAME="${domain}.pem"
#
# Defines the name of the PEM file.
# Defaults to "<domain>.pem"
#
# export DEPLOY_LIGHTTPD_PEM_PATH="/etc/lighttpd"
#
# Defines location of PEM file for Lighttpd.
# Defaults to /etc/lighttpd
#
# export DEPLOY_LIGHTTPD_RELOAD="systemctl reload lighttpd"
#
# OPTIONAL: Reload command used post deploy
# This defaults to be a no-op (ie "true").
# It is strongly recommended to set this something that makes sense
# for your distro.
#
# export DEPLOY_LIGHTTPD_ISSUER="yes"
#
# OPTIONAL: Places CA file as "${DEPLOY_LIGHTTPD_PEM}.issuer"
# Note: Required for OCSP stapling to work
#
# export DEPLOY_LIGHTTPD_BUNDLE="no"
#
# OPTIONAL: Deploy this certificate as part of a multi-cert bundle
# This adds a suffix to the certificate based on the certificate type
# eg RSA certificates will have .rsa as a suffix to the file name
# Lighttpd will load all certificates and provide one or the other
# depending on client capabilities
# Note: This functionality requires Lighttpd was compiled against
# a version of OpenSSL that supports this.
#
######## Public functions #####################
#domain keyfile certfile cafile fullchain
lighttpd_deploy() {
_cdomain="$1"
_ckey="$2"
_ccert="$3"
_cca="$4"
_cfullchain="$5"
# Some defaults
DEPLOY_LIGHTTPD_PEM_PATH_DEFAULT="/etc/lighttpd"
DEPLOY_LIGHTTPD_PEM_NAME_DEFAULT="${_cdomain}.pem"
DEPLOY_LIGHTTPD_BUNDLE_DEFAULT="no"
DEPLOY_LIGHTTPD_ISSUER_DEFAULT="yes"
DEPLOY_LIGHTTPD_RELOAD_DEFAULT="true"
_debug _cdomain "${_cdomain}"
_debug _ckey "${_ckey}"
_debug _ccert "${_ccert}"
_debug _cca "${_cca}"
_debug _cfullchain "${_cfullchain}"
# PEM_PATH is optional. If not provided then assume "${DEPLOY_LIGHTTPD_PEM_PATH_DEFAULT}"
_getdeployconf DEPLOY_LIGHTTPD_PEM_PATH
_debug2 DEPLOY_LIGHTTPD_PEM_PATH "${DEPLOY_LIGHTTPD_PEM_PATH}"
if [ -n "${DEPLOY_LIGHTTPD_PEM_PATH}" ]; then
Le_Deploy_lighttpd_pem_path="${DEPLOY_LIGHTTPD_PEM_PATH}"
_savedomainconf Le_Deploy_lighttpd_pem_path "${Le_Deploy_lighttpd_pem_path}"
elif [ -z "${Le_Deploy_lighttpd_pem_path}" ]; then
Le_Deploy_lighttpd_pem_path="${DEPLOY_LIGHTTPD_PEM_PATH_DEFAULT}"
fi
# Ensure PEM_PATH exists
if [ -d "${Le_Deploy_lighttpd_pem_path}" ]; then
_debug "PEM_PATH ${Le_Deploy_lighttpd_pem_path} exists"
else
_err "PEM_PATH ${Le_Deploy_lighttpd_pem_path} does not exist"
return 1
fi
# PEM_NAME is optional. If not provided then assume "${DEPLOY_LIGHTTPD_PEM_NAME_DEFAULT}"
_getdeployconf DEPLOY_LIGHTTPD_PEM_NAME
_debug2 DEPLOY_LIGHTTPD_PEM_NAME "${DEPLOY_LIGHTTPD_PEM_NAME}"
if [ -n "${DEPLOY_LIGHTTPD_PEM_NAME}" ]; then
Le_Deploy_lighttpd_pem_name="${DEPLOY_LIGHTTPD_PEM_NAME}"
_savedomainconf Le_Deploy_lighttpd_pem_name "${Le_Deploy_lighttpd_pem_name}"
elif [ -z "${Le_Deploy_lighttpd_pem_name}" ]; then
Le_Deploy_lighttpd_pem_name="${DEPLOY_LIGHTTPD_PEM_NAME_DEFAULT}"
fi
# BUNDLE is optional. If not provided then assume "${DEPLOY_LIGHTTPD_BUNDLE_DEFAULT}"
_getdeployconf DEPLOY_LIGHTTPD_BUNDLE
_debug2 DEPLOY_LIGHTTPD_BUNDLE "${DEPLOY_LIGHTTPD_BUNDLE}"
if [ -n "${DEPLOY_LIGHTTPD_BUNDLE}" ]; then
Le_Deploy_lighttpd_bundle="${DEPLOY_LIGHTTPD_BUNDLE}"
_savedomainconf Le_Deploy_lighttpd_bundle "${Le_Deploy_lighttpd_bundle}"
elif [ -z "${Le_Deploy_lighttpd_bundle}" ]; then
Le_Deploy_lighttpd_bundle="${DEPLOY_LIGHTTPD_BUNDLE_DEFAULT}"
fi
# ISSUER is optional. If not provided then assume "${DEPLOY_LIGHTTPD_ISSUER_DEFAULT}"
_getdeployconf DEPLOY_LIGHTTPD_ISSUER
_debug2 DEPLOY_LIGHTTPD_ISSUER "${DEPLOY_LIGHTTPD_ISSUER}"
if [ -n "${DEPLOY_LIGHTTPD_ISSUER}" ]; then
Le_Deploy_lighttpd_issuer="${DEPLOY_LIGHTTPD_ISSUER}"
_savedomainconf Le_Deploy_lighttpd_issuer "${Le_Deploy_lighttpd_issuer}"
elif [ -z "${Le_Deploy_lighttpd_issuer}" ]; then
Le_Deploy_lighttpd_issuer="${DEPLOY_LIGHTTPD_ISSUER_DEFAULT}"
fi
# RELOAD is optional. If not provided then assume "${DEPLOY_LIGHTTPD_RELOAD_DEFAULT}"
_getdeployconf DEPLOY_LIGHTTPD_RELOAD
_debug2 DEPLOY_LIGHTTPD_RELOAD "${DEPLOY_LIGHTTPD_RELOAD}"
if [ -n "${DEPLOY_LIGHTTPD_RELOAD}" ]; then
Le_Deploy_lighttpd_reload="${DEPLOY_LIGHTTPD_RELOAD}"
_savedomainconf Le_Deploy_lighttpd_reload "${Le_Deploy_lighttpd_reload}"
elif [ -z "${Le_Deploy_lighttpd_reload}" ]; then
Le_Deploy_lighttpd_reload="${DEPLOY_LIGHTTPD_RELOAD_DEFAULT}"
fi
# Set the suffix depending if we are creating a bundle or not
if [ "${Le_Deploy_lighttpd_bundle}" = "yes" ]; then
_info "Bundle creation requested"
# Initialise $Le_Keylength if its not already set
if [ -z "${Le_Keylength}" ]; then
Le_Keylength=""
fi
if _isEccKey "${Le_Keylength}"; then
_info "ECC key type detected"
_suffix=".ecdsa"
else
_info "RSA key type detected"
_suffix=".rsa"
fi
else
_suffix=""
fi
_debug _suffix "${_suffix}"
# Set variables for later
_pem="${Le_Deploy_lighttpd_pem_path}/${Le_Deploy_lighttpd_pem_name}${_suffix}"
_issuer="${_pem}.issuer"
_ocsp="${_pem}.ocsp"
_reload="${Le_Deploy_lighttpd_reload}"
_info "Deploying PEM file"
# Create a temporary PEM file
_temppem="$(_mktemp)"
_debug _temppem "${_temppem}"
cat "${_ckey}" "${_ccert}" "${_cca}" >"${_temppem}"
_ret="$?"
# Check that we could create the temporary file
if [ "${_ret}" != "0" ]; then
_err "Error code ${_ret} returned during PEM file creation"
[ -f "${_temppem}" ] && rm -f "${_temppem}"
return ${_ret}
fi
# Move PEM file into place
_info "Moving new certificate into place"
_debug _pem "${_pem}"
cat "${_temppem}" >"${_pem}"
_ret=$?
# Clean up temp file
[ -f "${_temppem}" ] && rm -f "${_temppem}"
# Deal with any failure of moving PEM file into place
if [ "${_ret}" != "0" ]; then
_err "Error code ${_ret} returned while moving new certificate into place"
return ${_ret}
fi
# Update .issuer file if requested
if [ "${Le_Deploy_lighttpd_issuer}" = "yes" ]; then
_info "Updating .issuer file"
_debug _issuer "${_issuer}"
cat "${_cca}" >"${_issuer}"
_ret="$?"
if [ "${_ret}" != "0" ]; then
_err "Error code ${_ret} returned while copying issuer/CA certificate into place"
return ${_ret}
fi
else
[ -f "${_issuer}" ] && _err "Issuer file update not requested but .issuer file exists"
fi
# Update .ocsp file if certificate was requested with --ocsp/--ocsp-must-staple option
if [ -z "${Le_OCSP_Staple}" ]; then
Le_OCSP_Staple="0"
fi
if [ "${Le_OCSP_Staple}" = "1" ]; then
_info "Updating OCSP stapling info"
_debug _ocsp "${_ocsp}"
_info "Extracting OCSP URL"
_ocsp_url=$(${ACME_OPENSSL_BIN:-openssl} x509 -noout -ocsp_uri -in "${_pem}")
_debug _ocsp_url "${_ocsp_url}"
# Only process OCSP if URL was present
if [ "${_ocsp_url}" != "" ]; then
# Extract the hostname from the OCSP URL
_info "Extracting OCSP URL"
_ocsp_host=$(echo "${_ocsp_url}" | cut -d/ -f3)
_debug _ocsp_host "${_ocsp_host}"
# Only process the certificate if we have a .issuer file
if [ -r "${_issuer}" ]; then
# Check if issuer cert is also a root CA cert
_subjectdn=$(${ACME_OPENSSL_BIN:-openssl} x509 -in "${_issuer}" -subject -noout | cut -d'/' -f2,3,4,5,6,7,8,9,10)
_debug _subjectdn "${_subjectdn}"
_issuerdn=$(${ACME_OPENSSL_BIN:-openssl} x509 -in "${_issuer}" -issuer -noout | cut -d'/' -f2,3,4,5,6,7,8,9,10)
_debug _issuerdn "${_issuerdn}"
_info "Requesting OCSP response"
# If the issuer is a CA cert then our command line has "-CAfile" added
if [ "${_subjectdn}" = "${_issuerdn}" ]; then
_cafile_argument="-CAfile \"${_issuer}\""
else
_cafile_argument=""
fi
_debug _cafile_argument "${_cafile_argument}"
# if OpenSSL/LibreSSL is v1.1 or above, the format for the -header option has changed
_openssl_version=$(${ACME_OPENSSL_BIN:-openssl} version | cut -d' ' -f2)
_debug _openssl_version "${_openssl_version}"
_openssl_major=$(echo "${_openssl_version}" | cut -d '.' -f1)
_openssl_minor=$(echo "${_openssl_version}" | cut -d '.' -f2)
if [ "${_openssl_major}" -eq "1" ] && [ "${_openssl_minor}" -ge "1" ] || [ "${_openssl_major}" -ge "2" ]; then
_header_sep="="
else
_header_sep=" "
fi
# Request the OCSP response from the issuer and store it
_openssl_ocsp_cmd="${ACME_OPENSSL_BIN:-openssl} ocsp \
-issuer \"${_issuer}\" \
-cert \"${_pem}\" \
-url \"${_ocsp_url}\" \
-header Host${_header_sep}\"${_ocsp_host}\" \
-respout \"${_ocsp}\" \
-verify_other \"${_issuer}\" \
${_cafile_argument} \
| grep -q \"${_pem}: good\""
_debug _openssl_ocsp_cmd "${_openssl_ocsp_cmd}"
eval "${_openssl_ocsp_cmd}"
_ret=$?
else
# Non fatal: No issuer file was present so no OCSP stapling file created
_err "OCSP stapling in use but no .issuer file was present"
fi
else
# Non fatal: No OCSP url was found int the certificate
_err "OCSP update requested but no OCSP URL was found in certificate"
fi
# Non fatal: Check return code of openssl command
if [ "${_ret}" != "0" ]; then
_err "Updating OCSP stapling failed with return code ${_ret}"
fi
else
# An OCSP file was already present but certificate did not have OCSP extension
if [ -f "${_ocsp}" ]; then
_err "OCSP was not requested but .ocsp file exists."
# Could remove the file at this step, although Lighttpd just ignores it in this case
# rm -f "${_ocsp}" || _err "Problem removing stale .ocsp file"
fi
fi
# Reload Lighttpd
_debug _reload "${_reload}"
eval "${_reload}"
_ret=$?
if [ "${_ret}" != "0" ]; then
_err "Error code ${_ret} during reload"
return ${_ret}
else
_info "Reload successful"
fi
return 0
}
+156
View 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
}
+10
View File
@@ -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"
+22 -5
View File
@@ -35,11 +35,6 @@ ssh_deploy() {
_cfullchain="$5" _cfullchain="$5"
_deploy_ssh_servers="" _deploy_ssh_servers=""
if [ -f "$DOMAIN_CONF" ]; then
# shellcheck disable=SC1090
. "$DOMAIN_CONF"
fi
_debug _cdomain "$_cdomain" _debug _cdomain "$_cdomain"
_debug _ckey "$_ckey" _debug _ckey "$_ckey"
_debug _ccert "$_ccert" _debug _ccert "$_ccert"
@@ -47,6 +42,8 @@ ssh_deploy() {
_debug _cfullchain "$_cfullchain" _debug _cfullchain "$_cfullchain"
# USER is required to login by SSH to remote host. # USER is required to login by SSH to remote host.
_getdeployconf DEPLOY_SSH_USER
_debug2 DEPLOY_SSH_USER "$DEPLOY_SSH_USER"
if [ -z "$DEPLOY_SSH_USER" ]; then if [ -z "$DEPLOY_SSH_USER" ]; then
if [ -z "$Le_Deploy_ssh_user" ]; then if [ -z "$Le_Deploy_ssh_user" ]; then
_err "DEPLOY_SSH_USER not defined." _err "DEPLOY_SSH_USER not defined."
@@ -58,6 +55,8 @@ ssh_deploy() {
fi fi
# SERVER is optional. If not provided then use _cdomain # SERVER is optional. If not provided then use _cdomain
_getdeployconf DEPLOY_SSH_SERVER
_debug2 DEPLOY_SSH_SERVER "$DEPLOY_SSH_SERVER"
if [ -n "$DEPLOY_SSH_SERVER" ]; then if [ -n "$DEPLOY_SSH_SERVER" ]; then
Le_Deploy_ssh_server="$DEPLOY_SSH_SERVER" Le_Deploy_ssh_server="$DEPLOY_SSH_SERVER"
_savedomainconf Le_Deploy_ssh_server "$Le_Deploy_ssh_server" _savedomainconf Le_Deploy_ssh_server "$Le_Deploy_ssh_server"
@@ -66,6 +65,8 @@ ssh_deploy() {
fi fi
# CMD is optional. If not provided then use ssh # CMD is optional. If not provided then use ssh
_getdeployconf DEPLOY_SSH_CMD
_debug2 DEPLOY_SSH_CMD "$DEPLOY_SSH_CMD"
if [ -n "$DEPLOY_SSH_CMD" ]; then if [ -n "$DEPLOY_SSH_CMD" ]; then
Le_Deploy_ssh_cmd="$DEPLOY_SSH_CMD" Le_Deploy_ssh_cmd="$DEPLOY_SSH_CMD"
_savedomainconf Le_Deploy_ssh_cmd "$Le_Deploy_ssh_cmd" _savedomainconf Le_Deploy_ssh_cmd "$Le_Deploy_ssh_cmd"
@@ -74,6 +75,8 @@ ssh_deploy() {
fi fi
# BACKUP is optional. If not provided then default to previously saved value or yes. # BACKUP is optional. If not provided then default to previously saved value or yes.
_getdeployconf DEPLOY_SSH_BACKUP
_debug2 DEPLOY_SSH_BACKUP "$DEPLOY_SSH_BACKUP"
if [ "$DEPLOY_SSH_BACKUP" = "no" ]; then if [ "$DEPLOY_SSH_BACKUP" = "no" ]; then
Le_Deploy_ssh_backup="no" Le_Deploy_ssh_backup="no"
elif [ -z "$Le_Deploy_ssh_backup" ] || [ "$DEPLOY_SSH_BACKUP" = "yes" ]; then elif [ -z "$Le_Deploy_ssh_backup" ] || [ "$DEPLOY_SSH_BACKUP" = "yes" ]; then
@@ -82,6 +85,8 @@ ssh_deploy() {
_savedomainconf Le_Deploy_ssh_backup "$Le_Deploy_ssh_backup" _savedomainconf Le_Deploy_ssh_backup "$Le_Deploy_ssh_backup"
# BACKUP_PATH is optional. If not provided then default to previously saved value or .acme_ssh_deploy # BACKUP_PATH is optional. If not provided then default to previously saved value or .acme_ssh_deploy
_getdeployconf DEPLOY_SSH_BACKUP_PATH
_debug2 DEPLOY_SSH_BACKUP_PATH "$DEPLOY_SSH_BACKUP_PATH"
if [ -n "$DEPLOY_SSH_BACKUP_PATH" ]; then if [ -n "$DEPLOY_SSH_BACKUP_PATH" ]; then
Le_Deploy_ssh_backup_path="$DEPLOY_SSH_BACKUP_PATH" Le_Deploy_ssh_backup_path="$DEPLOY_SSH_BACKUP_PATH"
elif [ -z "$Le_Deploy_ssh_backup_path" ]; then elif [ -z "$Le_Deploy_ssh_backup_path" ]; then
@@ -91,6 +96,8 @@ ssh_deploy() {
# MULTI_CALL is optional. If not provided then default to previously saved # MULTI_CALL is optional. If not provided then default to previously saved
# value (which may be undefined... equivalent to "no"). # value (which may be undefined... equivalent to "no").
_getdeployconf DEPLOY_SSH_MULTI_CALL
_debug2 DEPLOY_SSH_MULTI_CALL "$DEPLOY_SSH_MULTI_CALL"
if [ "$DEPLOY_SSH_MULTI_CALL" = "yes" ]; then if [ "$DEPLOY_SSH_MULTI_CALL" = "yes" ]; then
Le_Deploy_ssh_multi_call="yes" Le_Deploy_ssh_multi_call="yes"
_savedomainconf Le_Deploy_ssh_multi_call "$Le_Deploy_ssh_multi_call" _savedomainconf Le_Deploy_ssh_multi_call "$Le_Deploy_ssh_multi_call"
@@ -141,6 +148,8 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d
# KEYFILE is optional. # KEYFILE is optional.
# If provided then private key will be copied to provided filename. # If provided then private key will be copied to provided filename.
_getdeployconf DEPLOY_SSH_KEYFILE
_debug2 DEPLOY_SSH_KEYFILE "$DEPLOY_SSH_KEYFILE"
if [ -n "$DEPLOY_SSH_KEYFILE" ]; then if [ -n "$DEPLOY_SSH_KEYFILE" ]; then
Le_Deploy_ssh_keyfile="$DEPLOY_SSH_KEYFILE" Le_Deploy_ssh_keyfile="$DEPLOY_SSH_KEYFILE"
_savedomainconf Le_Deploy_ssh_keyfile "$Le_Deploy_ssh_keyfile" _savedomainconf Le_Deploy_ssh_keyfile "$Le_Deploy_ssh_keyfile"
@@ -163,6 +172,8 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d
# CERTFILE is optional. # CERTFILE is optional.
# If provided then certificate will be copied or appended to provided filename. # If provided then certificate will be copied or appended to provided filename.
_getdeployconf DEPLOY_SSH_CERTFILE
_debug2 DEPLOY_SSH_CERTFILE "$DEPLOY_SSH_CERTFILE"
if [ -n "$DEPLOY_SSH_CERTFILE" ]; then if [ -n "$DEPLOY_SSH_CERTFILE" ]; then
Le_Deploy_ssh_certfile="$DEPLOY_SSH_CERTFILE" Le_Deploy_ssh_certfile="$DEPLOY_SSH_CERTFILE"
_savedomainconf Le_Deploy_ssh_certfile "$Le_Deploy_ssh_certfile" _savedomainconf Le_Deploy_ssh_certfile "$Le_Deploy_ssh_certfile"
@@ -189,6 +200,8 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d
# CAFILE is optional. # CAFILE is optional.
# If provided then CA intermediate certificate will be copied or appended to provided filename. # If provided then CA intermediate certificate will be copied or appended to provided filename.
_getdeployconf DEPLOY_SSH_CAFILE
_debug2 DEPLOY_SSH_CAFILE "$DEPLOY_SSH_CAFILE"
if [ -n "$DEPLOY_SSH_CAFILE" ]; then if [ -n "$DEPLOY_SSH_CAFILE" ]; then
Le_Deploy_ssh_cafile="$DEPLOY_SSH_CAFILE" Le_Deploy_ssh_cafile="$DEPLOY_SSH_CAFILE"
_savedomainconf Le_Deploy_ssh_cafile "$Le_Deploy_ssh_cafile" _savedomainconf Le_Deploy_ssh_cafile "$Le_Deploy_ssh_cafile"
@@ -216,6 +229,8 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d
# FULLCHAIN is optional. # FULLCHAIN is optional.
# If provided then fullchain certificate will be copied or appended to provided filename. # If provided then fullchain certificate will be copied or appended to provided filename.
_getdeployconf DEPLOY_SSH_FULLCHAIN
_debug2 DEPLOY_SSH_FULLCHAIN "$DEPLOY_SSH_FULLCHAIN"
if [ -n "$DEPLOY_SSH_FULLCHAIN" ]; then if [ -n "$DEPLOY_SSH_FULLCHAIN" ]; then
Le_Deploy_ssh_fullchain="$DEPLOY_SSH_FULLCHAIN" Le_Deploy_ssh_fullchain="$DEPLOY_SSH_FULLCHAIN"
_savedomainconf Le_Deploy_ssh_fullchain "$Le_Deploy_ssh_fullchain" _savedomainconf Le_Deploy_ssh_fullchain "$Le_Deploy_ssh_fullchain"
@@ -244,6 +259,8 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d
# REMOTE_CMD is optional. # REMOTE_CMD is optional.
# If provided then this command will be executed on remote host. # If provided then this command will be executed on remote host.
_getdeployconf DEPLOY_SSH_REMOTE_CMD
_debug2 DEPLOY_SSH_REMOTE_CMD "$DEPLOY_SSH_REMOTE_CMD"
if [ -n "$DEPLOY_SSH_REMOTE_CMD" ]; then if [ -n "$DEPLOY_SSH_REMOTE_CMD" ]; then
Le_Deploy_ssh_remote_cmd="$DEPLOY_SSH_REMOTE_CMD" Le_Deploy_ssh_remote_cmd="$DEPLOY_SSH_REMOTE_CMD"
_savedomainconf Le_Deploy_ssh_remote_cmd "$Le_Deploy_ssh_remote_cmd" _savedomainconf Le_Deploy_ssh_remote_cmd "$Le_Deploy_ssh_remote_cmd"
+16 -3
View File
@@ -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
View 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
}
+16 -5
View File
@@ -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
_post "{\"cert\": \"$_cfullchain\", \"key\": \"$_ckey\"}" "$URL" if [ -n "$VAULT_KV_V2" ]; then
_post "{ \"data\": {\"cert\": \"$_cfullchain\", \"key\": \"$_ckey\"} }" "$URL"
else
_post "{\"cert\": \"$_cfullchain\", \"key\": \"$_ckey\"}" "$URL"
fi
else else
_post "{\"value\": \"$_ccert\"}" "$URL/cert.pem" if [ -n "$VAULT_KV_V2" ]; then
_post "{\"value\": \"$_ckey\"}" "$URL/cert.key" _post "{\"data\": {\"value\": \"$_ccert\"}}" "$URL/cert.pem"
_post "{\"value\": \"$_cca\"}" "$URL/chain.pem" _post "{\"data\": {\"value\": \"$_ckey\"}}" "$URL/cert.key"
_post "{\"value\": \"$_cfullchain\"}" "$URL/fullchain.pem" _post "{\"data\": {\"value\": \"$_cca\"}}" "$URL/chain.pem"
_post "{\"data\": {\"value\": \"$_cfullchain\"}}" "$URL/fullchain.pem"
else
_post "{\"value\": \"$_ccert\"}" "$URL/cert.pem"
_post "{\"value\": \"$_ckey\"}" "$URL/cert.key"
_post "{\"value\": \"$_cca\"}" "$URL/chain.pem"
_post "{\"value\": \"$_cfullchain\"}" "$URL/fullchain.pem"
fi
fi fi
} }
+51 -26
View File
@@ -46,7 +46,7 @@ dns_1984hosting_add() {
postdata="entry=new" postdata="entry=new"
postdata="$postdata&type=TXT" postdata="$postdata&type=TXT"
postdata="$postdata&ttl=3600" postdata="$postdata&ttl=900"
postdata="$postdata&zone=$_domain" postdata="$postdata&zone=$_domain"
postdata="$postdata&host=$_sub_domain" postdata="$postdata&host=$_sub_domain"
postdata="$postdata&rdata=%22$value%22" postdata="$postdata&rdata=%22$value%22"
@@ -93,20 +93,15 @@ dns_1984hosting_rm() {
fi fi
_debug _sub_domain "$_sub_domain" _debug _sub_domain "$_sub_domain"
_debug _domain "$_domain" _debug _domain "$_domain"
_debug "Delete $fulldomain TXT record" _debug "Delete $fulldomain TXT record"
url="https://management.1984hosting.com/domains"
_htmlget "$url" "$_domain" url="https://management.1984hosting.com/domains"
_debug2 _response "$_response" if ! _get_zone_id "$url" "$_domain"; then
zone_id="$(echo "$_response" | _egrep_o 'zone\/[0-9]+')" _err "invalid zone" "$_domain"
_debug2 zone_id "$zone_id"
if [ -z "$zone_id" ]; then
_err "Error getting zone_id for $1"
return 1 return 1
fi fi
_htmlget "$url/$zone_id" "$_sub_domain" _htmlget "$url/$_zone_id" "$txtvalue"
_debug2 _response "$_response" _debug2 _response "$_response"
entry_id="$(echo "$_response" | _egrep_o 'entry_[0-9]+' | sed 's/entry_//')" entry_id="$(echo "$_response" | _egrep_o 'entry_[0-9]+' | sed 's/entry_//')"
_debug2 entry_id "$entry_id" _debug2 entry_id "$entry_id"
@@ -135,7 +130,7 @@ dns_1984hosting_rm() {
_1984hosting_login() { _1984hosting_login() {
if ! _check_credentials; then return 1; fi if ! _check_credentials; then return 1; fi
if _check_cookie; then if _check_cookies; then
_debug "Already logged in" _debug "Already logged in"
return 0 return 0
fi fi
@@ -150,9 +145,12 @@ _1984hosting_login() {
_debug2 response "$response" _debug2 response "$response"
if _contains "$response" '"loggedin": true'; then if _contains "$response" '"loggedin": true'; then
One984HOSTING_COOKIE="$(grep -i '^set-cookie:' "$HTTP_HEADER" | _tail_n 1 | _egrep_o 'sessionid=[^;]*;' | tr -d ';')" One984HOSTING_SESSIONID_COOKIE="$(grep -i '^set-cookie:' "$HTTP_HEADER" | _egrep_o 'sessionid=[^;]*;' | tr -d ';')"
export One984HOSTING_COOKIE One984HOSTING_CSRFTOKEN_COOKIE="$(grep -i '^set-cookie:' "$HTTP_HEADER" | _egrep_o 'csrftoken=[^;]*;' | tr -d ';')"
_saveaccountconf_mutable One984HOSTING_COOKIE "$One984HOSTING_COOKIE" export One984HOSTING_SESSIONID_COOKIE
export One984HOSTING_CSRFTOKEN_COOKIE
_saveaccountconf_mutable One984HOSTING_SESSIONID_COOKIE "$One984HOSTING_SESSIONID_COOKIE"
_saveaccountconf_mutable One984HOSTING_CSRFTOKEN_COOKIE "$One984HOSTING_CSRFTOKEN_COOKIE"
return 0 return 0
fi fi
return 1 return 1
@@ -169,21 +167,24 @@ _check_credentials() {
return 0 return 0
} }
_check_cookie() { _check_cookies() {
One984HOSTING_COOKIE="${One984HOSTING_COOKIE:-$(_readaccountconf_mutable One984HOSTING_COOKIE)}" One984HOSTING_SESSIONID_COOKIE="${One984HOSTING_SESSIONID_COOKIE:-$(_readaccountconf_mutable One984HOSTING_SESSIONID_COOKIE)}"
if [ -z "$One984HOSTING_COOKIE" ]; then One984HOSTING_CSRFTOKEN_COOKIE="${One984HOSTING_CSRFTOKEN_COOKIE:-$(_readaccountconf_mutable One984HOSTING_CSRFTOKEN_COOKIE)}"
_debug "No cached cookie found" if [ -z "$One984HOSTING_SESSIONID_COOKIE" ] || [ -z "$One984HOSTING_CSRFTOKEN_COOKIE" ]; then
_debug "No cached cookie(s) found"
return 1 return 1
fi fi
_authget "https://management.1984hosting.com/accounts/loginstatus/" _authget "https://management.1984hosting.com/accounts/loginstatus/"
if _contains "$response" '"ok": true'; then if _contains "$response" '"ok": true'; then
_debug "Cached cookie still valid" _debug "Cached cookies still valid"
return 0 return 0
fi fi
_debug "Cached cookie no longer valid" _debug "Cached cookies no longer valid"
One984HOSTING_COOKIE="" One984HOSTING_SESSIONID_COOKIE=""
_saveaccountconf_mutable One984HOSTING_COOKIE "$One984HOSTING_COOKIE" One984HOSTING_CSRFTOKEN_COOKIE=""
_saveaccountconf_mutable One984HOSTING_SESSIONID_COOKIE "$One984HOSTING_SESSIONID_COOKIE"
_saveaccountconf_mutable One984HOSTING_CSRFTOKEN_COOKIE "$One984HOSTING_CSRFTOKEN_COOKIE"
return 1 return 1
} }
@@ -215,9 +216,25 @@ _get_root() {
return 1 return 1
} }
#usage: _get_zone_id url domain.com
#returns zone id for domain.com
_get_zone_id() {
url=$1
domain=$2
_htmlget "$url" "$domain"
_debug2 _response "$_response"
_zone_id="$(echo "$_response" | _egrep_o 'zone\/[0-9]+' | _head_n 1)"
_debug2 _zone_id "$_zone_id"
if [ -z "$_zone_id" ]; then
_err "Error getting _zone_id for $2"
return 1
fi
return 0
}
# add extra headers to request # add extra headers to request
_authget() { _authget() {
export _H1="Cookie: $One984HOSTING_COOKIE" export _H1="Cookie: $One984HOSTING_CSRFTOKEN_COOKIE;$One984HOSTING_SESSIONID_COOKIE"
_response=$(_get "$1" | _normalizeJson) _response=$(_get "$1" | _normalizeJson)
_debug2 _response "$_response" _debug2 _response "$_response"
} }
@@ -225,12 +242,20 @@ _authget() {
# truncate huge HTML response # truncate huge HTML response
# echo: Argument list too long # echo: Argument list too long
_htmlget() { _htmlget() {
export _H1="Cookie: $One984HOSTING_COOKIE" export _H1="Cookie: $One984HOSTING_CSRFTOKEN_COOKIE;$One984HOSTING_SESSIONID_COOKIE"
_response=$(_get "$1" | grep "$2" | _head_n 1) _response=$(_get "$1" | grep "$2")
if _contains "$_response" "@$2"; then
_response=$(echo "$_response" | grep -v "[@]" | _head_n 1)
fi
} }
# add extra headers to request # add extra headers to request
_authpost() { _authpost() {
export _H1="Cookie: $One984HOSTING_COOKIE" url="https://management.1984hosting.com/domains"
_get_zone_id "$url" "$_domain"
csrf_header="$(echo "$One984HOSTING_CSRFTOKEN_COOKIE" | _egrep_o "=[^=][0-9a-zA-Z]*" | tr -d "=")"
export _H1="Cookie: $One984HOSTING_CSRFTOKEN_COOKIE;$One984HOSTING_SESSIONID_COOKIE"
export _H2="Referer: https://management.1984hosting.com/domains/$_zone_id"
export _H3="X-CSRFToken: $csrf_header"
_response=$(_post "$1" "$2") _response=$(_post "$1" "$2")
} }
Regular → Executable
+51 -12
View 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 ##################################
+1 -1
View File
@@ -32,7 +32,7 @@ dns_aws_add() {
if [ -z "$AWS_ACCESS_KEY_ID" ] || [ -z "$AWS_SECRET_ACCESS_KEY" ]; then if [ -z "$AWS_ACCESS_KEY_ID" ] || [ -z "$AWS_SECRET_ACCESS_KEY" ]; then
AWS_ACCESS_KEY_ID="" AWS_ACCESS_KEY_ID=""
AWS_SECRET_ACCESS_KEY="" AWS_SECRET_ACCESS_KEY=""
_err "You haven't specifed the aws route53 api key id and and api key secret yet." _err "You haven't specified the aws route53 api key id and and api key secret yet."
_err "Please create your key and try again. see $(__green $AWS_WIKI)" _err "Please create your key and try again. see $(__green $AWS_WIKI)"
return 1 return 1
fi fi
+111 -81
View File
@@ -9,57 +9,72 @@ 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=""
AZUREDNS_APPID="" AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET="" AZUREDNS_CLIENTSECRET=""
_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.
if [ -z "$AZUREDNS_TENANTID" ]; then
AZUREDNS_SUBSCRIPTIONID=""
AZUREDNS_TENANTID=""
AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET=""
_err "You didn't specify the Azure Tenant ID "
return 1
fi
if [ -z "$AZUREDNS_APPID" ]; then
AZUREDNS_SUBSCRIPTIONID=""
AZUREDNS_TENANTID=""
AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET=""
_err "You didn't specify the Azure App ID"
return 1
fi
if [ -z "$AZUREDNS_CLIENTSECRET" ]; then
AZUREDNS_SUBSCRIPTIONID=""
AZUREDNS_TENANTID=""
AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET=""
_err "You didn't specify the Azure Client Secret"
return 1
fi
#save account details to account conf file.
_saveaccountconf_mutable AZUREDNS_SUBSCRIPTIONID "$AZUREDNS_SUBSCRIPTIONID" _saveaccountconf_mutable AZUREDNS_SUBSCRIPTIONID "$AZUREDNS_SUBSCRIPTIONID"
_saveaccountconf_mutable AZUREDNS_TENANTID "$AZUREDNS_TENANTID"
_saveaccountconf_mutable AZUREDNS_APPID "$AZUREDNS_APPID"
_saveaccountconf_mutable AZUREDNS_CLIENTSECRET "$AZUREDNS_CLIENTSECRET"
accesstoken=$(_azure_getaccess_token "$AZUREDNS_TENANTID" "$AZUREDNS_APPID" "$AZUREDNS_CLIENTSECRET") 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
AZUREDNS_SUBSCRIPTIONID=""
AZUREDNS_TENANTID=""
AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET=""
_err "You didn't specify the Azure Tenant ID "
return 1
fi
if [ -z "$AZUREDNS_APPID" ]; then
AZUREDNS_SUBSCRIPTIONID=""
AZUREDNS_TENANTID=""
AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET=""
_err "You didn't specify the Azure App ID"
return 1
fi
if [ -z "$AZUREDNS_CLIENTSECRET" ]; then
AZUREDNS_SUBSCRIPTIONID=""
AZUREDNS_TENANTID=""
AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET=""
_err "You didn't specify the Azure Client Secret"
return 1
fi
#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_APPID "$AZUREDNS_APPID"
_saveaccountconf_mutable AZUREDNS_CLIENTSECRET "$AZUREDNS_CLIENTSECRET"
fi
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,34 +140,44 @@ dns_azure_rm() {
return 1 return 1
fi fi
if [ -z "$AZUREDNS_TENANTID" ]; then AZUREDNS_MANAGEDIDENTITY="${AZUREDNS_MANAGEDIDENTITY:-$(_readaccountconf_mutable AZUREDNS_MANAGEDIDENTITY)}"
AZUREDNS_SUBSCRIPTIONID="" if [ "$AZUREDNS_MANAGEDIDENTITY" = true ]; then
AZUREDNS_TENANTID="" _info "Using Azure managed identity"
AZUREDNS_APPID="" else
AZUREDNS_CLIENTSECRET="" _info "You didn't ask to use Azure managed identity, checking service principal credentials"
_err "You didn't specify the Azure Tenant ID " AZUREDNS_TENANTID="${AZUREDNS_TENANTID:-$(_readaccountconf_mutable AZUREDNS_TENANTID)}"
return 1 AZUREDNS_APPID="${AZUREDNS_APPID:-$(_readaccountconf_mutable AZUREDNS_APPID)}"
AZUREDNS_CLIENTSECRET="${AZUREDNS_CLIENTSECRET:-$(_readaccountconf_mutable AZUREDNS_CLIENTSECRET)}"
if [ -z "$AZUREDNS_TENANTID" ]; then
AZUREDNS_SUBSCRIPTIONID=""
AZUREDNS_TENANTID=""
AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET=""
_err "You didn't specify the Azure Tenant ID "
return 1
fi
if [ -z "$AZUREDNS_APPID" ]; then
AZUREDNS_SUBSCRIPTIONID=""
AZUREDNS_TENANTID=""
AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET=""
_err "You didn't specify the Azure App ID"
return 1
fi
if [ -z "$AZUREDNS_CLIENTSECRET" ]; then
AZUREDNS_SUBSCRIPTIONID=""
AZUREDNS_TENANTID=""
AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET=""
_err "You didn't specify the Azure Client Secret"
return 1
fi
fi fi
if [ -z "$AZUREDNS_APPID" ]; then accesstoken=$(_azure_getaccess_token "$AZUREDNS_MANAGEDIDENTITY" "$AZUREDNS_TENANTID" "$AZUREDNS_APPID" "$AZUREDNS_CLIENTSECRET")
AZUREDNS_SUBSCRIPTIONID=""
AZUREDNS_TENANTID=""
AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET=""
_err "You didn't specify the Azure App ID"
return 1
fi
if [ -z "$AZUREDNS_CLIENTSECRET" ]; then
AZUREDNS_SUBSCRIPTIONID=""
AZUREDNS_TENANTID=""
AZUREDNS_APPID=""
AZUREDNS_CLIENTSECRET=""
_err "You didn't specify the Azure Client Secret"
return 1
fi
accesstoken=$(_azure_getaccess_token "$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,17 +300,25 @@ _azure_getaccess_token() {
fi fi
_debug "getting new bearer token" _debug "getting new bearer token"
export _H1="accept: application/json" if [ "$managedIdentity" = true ]; then
export _H2="Content-Type: application/x-www-form-urlencoded" # 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"
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" response="$(_get http://169.254.169.254/metadata/identity/oauth2/token\?api-version=2018-02-01\&resource=https://management.azure.com/)"
_secure_debug2 "data $body" response="$(echo "$response" | _normalizeJson)"
response="$(_post "$body" "https://login.microsoftonline.com/$tenantID/oauth2/token" "" "POST")" accesstoken=$(echo "$response" | _egrep_o "\"access_token\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \")
_ret="$?" expires_on=$(echo "$response" | _egrep_o "\"expires_on\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \")
_secure_debug2 "response $response" else
response="$(echo "$response" | _normalizeJson)" export _H1="accept: application/json"
accesstoken=$(echo "$response" | _egrep_o "\"access_token\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \") export _H2="Content-Type: application/x-www-form-urlencoded"
expires_on=$(echo "$response" | _egrep_o "\"expires_on\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \") 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"
response="$(_post "$body" "https://login.microsoftonline.com/$tenantID/oauth2/token" "" "POST")"
_ret="$?"
_secure_debug2 "response $response"
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 \")
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"
+24
View File
@@ -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
View 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
}
+2 -2
View File
@@ -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
View 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
}
+4 -1
View File
@@ -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')
} }
+1 -1
View File
@@ -85,7 +85,7 @@ dns_he_rm() {
_debug "The txt record is not found, just skip" _debug "The txt record is not found, just skip"
return 0 return 0
fi fi
_record_id="$(echo "$response" | tr -d "#" | sed "s/<tr/#<tr/g" | tr -d "\n" | tr "#" "\n" | grep "$_full_domain" | grep '"dns_tr"' | grep "$_txt_value" | cut -d '"' -f 4)" _record_id="$(echo "$response" | tr -d "#" | sed "s/<tr/#<tr/g" | tr -d "\n" | tr "#" "\n" | grep "$_full_domain" | grep '"dns_tr"' | grep -- "$_txt_value" | cut -d '"' -f 4)"
_debug2 _record_id "$_record_id" _debug2 _record_id "$_record_id"
if [ -z "$_record_id" ]; then if [ -z "$_record_id" ]; then
_err "Can not find record id" _err "Can not find record id"
+28 -14
View File
@@ -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
_debug "Get Zone ID Success." zoneidlist=$(echo "${response}" | _egrep_o "\"id\": *\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | tr -d " ")
_zoneid=$(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 " ")
printf "%s" "${_zoneid}" _debug2 "Return Zone ID(s):" "${zoneidlist}"
return 0 _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 "ZoneID:" "${_zoneid}"
printf "%s" "${_zoneid}"
return 0
fi
done
fi 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
} }
+1 -1
View File
@@ -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=""
+4 -2
View File
@@ -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
View 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
}
+4 -4
View File
@@ -119,16 +119,16 @@ login() {
tmp=$(_post "{\"action\": \"login\", \"param\": {\"apikey\": \"$NC_Apikey\", \"apipassword\": \"$NC_Apipw\", \"customernumber\": \"$NC_CID\"}}" "$end" "" "POST") tmp=$(_post "{\"action\": \"login\", \"param\": {\"apikey\": \"$NC_Apikey\", \"apipassword\": \"$NC_Apipw\", \"customernumber\": \"$NC_CID\"}}" "$end" "" "POST")
sid=$(echo "$tmp" | tr '{}' '\n' | grep apisessionid | cut -d '"' -f 4) sid=$(echo "$tmp" | tr '{}' '\n' | grep apisessionid | cut -d '"' -f 4)
_debug "$tmp" _debug "$tmp"
if [ "$(_getfield "$msg" "4" | sed s/\"status\":\"//g | sed s/\"//g)" != "success" ]; then if [ "$(_getfield "$tmp" "4" | sed s/\"status\":\"//g | sed s/\"//g)" != "success" ]; then
_err "$msg" _err "$tmp"
return 1 return 1
fi fi
} }
logout() { logout() {
tmp=$(_post "{\"action\": \"logout\", \"param\": {\"apikey\": \"$NC_Apikey\", \"apisessionid\": \"$sid\", \"customernumber\": \"$NC_CID\"}}" "$end" "" "POST") tmp=$(_post "{\"action\": \"logout\", \"param\": {\"apikey\": \"$NC_Apikey\", \"apisessionid\": \"$sid\", \"customernumber\": \"$NC_CID\"}}" "$end" "" "POST")
_debug "$tmp" _debug "$tmp"
if [ "$(_getfield "$msg" "4" | sed s/\"status\":\"//g | sed s/\"//g)" != "success" ]; then if [ "$(_getfield "$tmp" "4" | sed s/\"status\":\"//g | sed s/\"//g)" != "success" ]; then
_err "$msg" _err "$tmp"
return 1 return 1
fi fi
} }
+1 -1
View File
@@ -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"
+3 -2
View File
@@ -7,6 +7,7 @@
RACKSPACE_Endpoint="https://dns.api.rackspacecloud.com/v1.0" RACKSPACE_Endpoint="https://dns.api.rackspacecloud.com/v1.0"
# 20210923 - RS changed the fields in the API response; fix sed
# 20190213 - The name & id fields swapped in the API response; fix sed # 20190213 - The name & id fields swapped in the API response; fix sed
# 20190101 - Duplicating file for new pull request to dev branch # 20190101 - Duplicating file for new pull request to dev branch
# Original - tcocca:rackspace_dnsapi https://github.com/acmesh-official/acme.sh/pull/1297 # Original - tcocca:rackspace_dnsapi https://github.com/acmesh-official/acme.sh/pull/1297
@@ -79,8 +80,8 @@ _get_root_zone() {
_debug2 response "$response" _debug2 response "$response"
if _contains "$response" "\"name\":\"$h\"" >/dev/null; then if _contains "$response" "\"name\":\"$h\"" >/dev/null; then
# Response looks like: # Response looks like:
# {"ttl":300,"accountId":12345,"id":1111111,"name":"example.com","emailAddress": ...<and so on> # {"id":"12345","accountId":"1111111","name": "example.com","ttl":3600,"emailAddress": ... <and so on>
_domain_id=$(echo "$response" | sed -n "s/^.*\"id\":\([^,]*\),\"name\":\"$h\",.*/\1/p") _domain_id=$(echo "$response" | sed -n "s/^.*\"id\":\"\([^,]*\)\",\"accountId\":\"[0-9]*\",\"name\":\"$h\",.*/\1/p")
_debug2 domain_id "$_domain_id" _debug2 domain_id "$_domain_id"
if [ -n "$_domain_id" ]; then if [ -n "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
+3 -2
View File
@@ -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
;; ;;
+12 -10
View File
@@ -1,15 +1,15 @@
#!/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]"
SIMPLY_Api_Default="https://api.simply.com/1" SIMPLY_Api_Default="https://api.simply.com/1"
#This is used for determining success of REST call #This is used for determining success of REST call
SIMPLY_SUCCESS_CODE='"status": 200' SIMPLY_SUCCESS_CODE='"status":200'
######## Public functions ##################### ######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" #Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
@@ -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
+158
View File
@@ -0,0 +1,158 @@
#!/usr/bin/env sh
# bug reports to stepan@plyask.in
#
# export VEESP_User="username"
# export VEESP_Password="password"
VEESP_Api="https://secure.veesp.com/api"
######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_veesp_add() {
fulldomain=$1
txtvalue=$2
VEESP_Password="${VEESP_Password:-$(_readaccountconf_mutable VEESP_Password)}"
VEESP_User="${VEESP_User:-$(_readaccountconf_mutable VEESP_User)}"
VEESP_auth=$(printf "%s" "$VEESP_User:$VEESP_Password" | _base64)
if [ -z "$VEESP_Password" ] || [ -z "$VEESP_User" ]; then
VEESP_Password=""
VEESP_User=""
_err "You don't specify veesp api key and email yet."
_err "Please create you key and try again."
return 1
fi
#save the api key and email to the account conf file.
_saveaccountconf_mutable VEESP_Password "$VEESP_Password"
_saveaccountconf_mutable VEESP_User "$VEESP_User"
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"
return 1
fi
_debug _domain_id "$_domain_id"
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
_info "Adding record"
if VEESP_rest POST "service/$_service_id/dns/$_domain_id/records" "{\"name\":\"$fulldomain\",\"ttl\":1,\"priority\":0,\"type\":\"TXT\",\"content\":\"$txtvalue\"}"; then
if _contains "$response" "\"success\":true"; then
_info "Added"
#todo: check if the record takes effect
return 0
else
_err "Add txt record error."
return 1
fi
fi
}
# Usage: fulldomain txtvalue
# Used to remove the txt record after validation
dns_veesp_rm() {
fulldomain=$1
txtvalue=$2
VEESP_Password="${VEESP_Password:-$(_readaccountconf_mutable VEESP_Password)}"
VEESP_User="${VEESP_User:-$(_readaccountconf_mutable VEESP_User)}"
VEESP_auth=$(printf "%s" "$VEESP_User:$VEESP_Password" | _base64)
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"
return 1
fi
_debug _domain_id "$_domain_id"
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
_debug "Getting txt records"
VEESP_rest GET "service/$_service_id/dns/$_domain_id"
count=$(printf "%s\n" "$response" | _egrep_o "\"type\":\"TXT\",\"content\":\".\"$txtvalue.\"\"" | wc -l | tr -d " ")
_debug count "$count"
if [ "$count" = "0" ]; then
_info "Don't need to remove."
else
record_id=$(printf "%s\n" "$response" | _egrep_o "{\"id\":[^}]*\"type\":\"TXT\",\"content\":\".\"$txtvalue.\"\"" | cut -d\" -f4)
_debug "record_id" "$record_id"
if [ -z "$record_id" ]; then
_err "Can not get record id to remove."
return 1
fi
if ! VEESP_rest DELETE "service/$_service_id/dns/$_domain_id/records/$record_id"; then
_err "Delete record error."
return 1
fi
_contains "$response" "\"success\":true"
fi
}
#################### Private functions below ##################################
#_acme-challenge.www.domain.com
#returns
# _sub_domain=_acme-challenge.www
# _domain=domain.com
# _domain_id=sdjkglgdfewsdfg
_get_root() {
domain=$1
i=2
p=1
if ! VEESP_rest GET "dns"; then
return 1
fi
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
_debug h "$h"
if [ -z "$h" ]; then
#not valid
return 1
fi
if _contains "$response" "\"name\":\"$h\""; then
_domain_id=$(printf "%s\n" "$response" | _egrep_o "\"domain_id\":[^,]*,\"name\":\"$h\"" | cut -d : -f 2 | cut -d , -f 1 | cut -d '"' -f 2)
_debug _domain_id "$_domain_id"
_service_id=$(printf "%s\n" "$response" | _egrep_o "\"name\":\"$h\",\"service_id\":[^}]*" | cut -d : -f 3 | cut -d '"' -f 2)
_debug _service_id "$_service_id"
if [ "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_domain="$h"
return 0
fi
return 1
fi
p=$i
i=$(_math "$i" + 1)
done
return 1
}
VEESP_rest() {
m=$1
ep="$2"
data="$3"
_debug "$ep"
export _H1="Accept: application/json"
export _H2="Authorization: Basic $VEESP_auth"
if [ "$m" != "GET" ]; then
_debug data "$data"
export _H3="Content-Type: application/json"
response="$(_post "$data" "$VEESP_Api/$ep" "" "$m")"
else
response="$(_get "$VEESP_Api/$ep")"
fi
if [ "$?" != "0" ]; then
_err "error $ep"
return 1
fi
_debug2 response "$response"
return 0
}
+4 -10
View File
@@ -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
View 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
View 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
View 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
}
+2 -1
View File
@@ -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
+44
View File
@@ -0,0 +1,44 @@
#!/usr/bin/env sh
#Support for pushbullet.com's api. Push notification, notification sync and message platform for multiple platforms
#PUSHBULLET_TOKEN="" Required, pushbullet application token
#PUSHBULLET_DEVICE="" Optional, Specific device, ignore to send to all devices
PUSHBULLET_URI="https://api.pushbullet.com/v2/pushes"
pushbullet_send() {
_subject="$1"
_content="$2"
_statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped
_debug "_statusCode" "$_statusCode"
PUSHBULLET_TOKEN="${PUSHBULLET_TOKEN:-$(_readaccountconf_mutable PUSHBULLET_TOKEN)}"
if [ -z "$PUSHBULLET_TOKEN" ]; then
PUSHBULLET_TOKEN=""
_err "You didn't specify a Pushbullet application token yet."
return 1
fi
_saveaccountconf_mutable PUSHBULLET_TOKEN "$PUSHBULLET_TOKEN"
PUSHBULLET_DEVICE="${PUSHBULLET_DEVICE:-$(_readaccountconf_mutable PUSHBULLET_DEVICE)}"
if [ -z "$PUSHBULLET_DEVICE" ]; then
_clearaccountconf_mutable PUSHBULLET_DEVICE
else
_saveaccountconf_mutable PUSHBULLET_DEVICE "$PUSHBULLET_DEVICE"
fi
export _H1="Content-Type: application/json"
export _H2="Access-Token: ${PUSHBULLET_TOKEN}"
_content="$(printf "*%s*\n" "$_content" | _json_encode)"
_subject="$(printf "*%s*\n" "$_subject" | _json_encode)"
_data="{\"type\": \"note\",\"title\": \"${_subject}\",\"body\": \"${_content}\",\"device_iden\": \"${PUSHBULLET_DEVICE}\"}"
response="$(_post "$_data" "$PUSHBULLET_URI")"
if [ "$?" != "0" ] || _contains "$response" "\"error_code\""; then
_err "PUSHBULLET send error."
_err "$response"
return 1
fi
_info "PUSHBULLET send success."
return 0
}