mirror of
https://github.com/acmesh-official/acme.sh.git
synced 2025-04-30 17:52:46 +00:00
Merge branch 'acmesh-official:master' into cloudhub-v2
This commit is contained in:
commit
476fb76fba
177
.github/workflows/DNS.yml
vendored
177
.github/workflows/DNS.yml
vendored
@ -65,9 +65,9 @@ jobs:
|
|||||||
TokenName4: ${{ secrets.TokenName4}}
|
TokenName4: ${{ secrets.TokenName4}}
|
||||||
TokenName5: ${{ secrets.TokenName5}}
|
TokenName5: ${{ secrets.TokenName5}}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- 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 --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||||
- name: Set env file
|
- name: Set env file
|
||||||
run: |
|
run: |
|
||||||
cd ../acmetest
|
cd ../acmetest
|
||||||
@ -113,27 +113,27 @@ jobs:
|
|||||||
TokenName4: ${{ secrets.TokenName4}}
|
TokenName4: ${{ secrets.TokenName4}}
|
||||||
TokenName5: ${{ secrets.TokenName5}}
|
TokenName5: ${{ secrets.TokenName5}}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- name: Install tools
|
- name: Install tools
|
||||||
run: brew install socat
|
run: brew install socat
|
||||||
- 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 --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||||
- name: Run acmetest
|
- name: Run acmetest
|
||||||
run: |
|
run: |
|
||||||
if [ "${{ secrets.TokenName1}}" ] ; then
|
if [ "${{ secrets.TokenName1}}" ] ; then
|
||||||
export ${{ secrets.TokenName1}}=${{ secrets.TokenValue1}}
|
export ${{ secrets.TokenName1}}="${{ secrets.TokenValue1}}"
|
||||||
fi
|
fi
|
||||||
if [ "${{ secrets.TokenName2}}" ] ; then
|
if [ "${{ secrets.TokenName2}}" ] ; then
|
||||||
export ${{ secrets.TokenName2}}=${{ secrets.TokenValue2}}
|
export ${{ secrets.TokenName2}}="${{ secrets.TokenValue2}}"
|
||||||
fi
|
fi
|
||||||
if [ "${{ secrets.TokenName3}}" ] ; then
|
if [ "${{ secrets.TokenName3}}" ] ; then
|
||||||
export ${{ secrets.TokenName3}}=${{ secrets.TokenValue3}}
|
export ${{ secrets.TokenName3}}="${{ secrets.TokenValue3}}"
|
||||||
fi
|
fi
|
||||||
if [ "${{ secrets.TokenName4}}" ] ; then
|
if [ "${{ secrets.TokenName4}}" ] ; then
|
||||||
export ${{ secrets.TokenName4}}=${{ secrets.TokenValue4}}
|
export ${{ secrets.TokenName4}}="${{ secrets.TokenValue4}}"
|
||||||
fi
|
fi
|
||||||
if [ "${{ secrets.TokenName5}}" ] ; then
|
if [ "${{ secrets.TokenName5}}" ] ; then
|
||||||
export ${{ secrets.TokenName5}}=${{ secrets.TokenValue5}}
|
export ${{ secrets.TokenName5}}="${{ secrets.TokenValue5}}"
|
||||||
fi
|
fi
|
||||||
cd ../acmetest
|
cd ../acmetest
|
||||||
./letest.sh
|
./letest.sh
|
||||||
@ -164,7 +164,7 @@ jobs:
|
|||||||
- name: Set git to use LF
|
- name: Set git to use LF
|
||||||
run: |
|
run: |
|
||||||
git config --global core.autocrlf false
|
git config --global core.autocrlf false
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- name: Install cygwin base packages with chocolatey
|
- name: Install cygwin base packages with chocolatey
|
||||||
run: |
|
run: |
|
||||||
choco config get cacheLocation
|
choco config get cacheLocation
|
||||||
@ -172,31 +172,31 @@ 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 https://mirrors.kernel.org/sourceware/cygwin/ -P socat,curl,cron,unzip,git
|
||||||
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 >> %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 --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||||
- name: Run acmetest
|
- name: Run acmetest
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
if [ "${{ secrets.TokenName1}}" ] ; then
|
if [ "${{ secrets.TokenName1}}" ] ; then
|
||||||
export ${{ secrets.TokenName1}}=${{ secrets.TokenValue1}}
|
export ${{ secrets.TokenName1}}="${{ secrets.TokenValue1}}"
|
||||||
fi
|
fi
|
||||||
if [ "${{ secrets.TokenName2}}" ] ; then
|
if [ "${{ secrets.TokenName2}}" ] ; then
|
||||||
export ${{ secrets.TokenName2}}=${{ secrets.TokenValue2}}
|
export ${{ secrets.TokenName2}}="${{ secrets.TokenValue2}}"
|
||||||
fi
|
fi
|
||||||
if [ "${{ secrets.TokenName3}}" ] ; then
|
if [ "${{ secrets.TokenName3}}" ] ; then
|
||||||
export ${{ secrets.TokenName3}}=${{ secrets.TokenValue3}}
|
export ${{ secrets.TokenName3}}="${{ secrets.TokenValue3}}"
|
||||||
fi
|
fi
|
||||||
if [ "${{ secrets.TokenName4}}" ] ; then
|
if [ "${{ secrets.TokenName4}}" ] ; then
|
||||||
export ${{ secrets.TokenName4}}=${{ secrets.TokenValue4}}
|
export ${{ secrets.TokenName4}}="${{ secrets.TokenValue4}}"
|
||||||
fi
|
fi
|
||||||
if [ "${{ secrets.TokenName5}}" ] ; then
|
if [ "${{ secrets.TokenName5}}" ] ; then
|
||||||
export ${{ secrets.TokenName5}}=${{ secrets.TokenValue5}}
|
export ${{ secrets.TokenName5}}="${{ secrets.TokenValue5}}"
|
||||||
fi
|
fi
|
||||||
cd ../acmetest
|
cd ../acmetest
|
||||||
./letest.sh
|
./letest.sh
|
||||||
@ -204,7 +204,7 @@ jobs:
|
|||||||
|
|
||||||
|
|
||||||
FreeBSD:
|
FreeBSD:
|
||||||
runs-on: macos-12
|
runs-on: ubuntu-latest
|
||||||
needs: Windows
|
needs: Windows
|
||||||
env:
|
env:
|
||||||
TEST_DNS : ${{ secrets.TEST_DNS }}
|
TEST_DNS : ${{ secrets.TEST_DNS }}
|
||||||
@ -223,10 +223,10 @@ jobs:
|
|||||||
TokenName4: ${{ secrets.TokenName4}}
|
TokenName4: ${{ secrets.TokenName4}}
|
||||||
TokenName5: ${{ secrets.TokenName5}}
|
TokenName5: ${{ secrets.TokenName5}}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- 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 --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||||
- uses: vmactions/freebsd-vm@v0
|
- uses: vmactions/freebsd-vm@v1
|
||||||
with:
|
with:
|
||||||
envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_NO_SUBDOMAIN TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG http_proxy https_proxy TokenName1 TokenName2 TokenName3 TokenName4 TokenName5 ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}'
|
envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_NO_SUBDOMAIN TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG http_proxy https_proxy TokenName1 TokenName2 TokenName3 TokenName4 TokenName5 ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}'
|
||||||
prepare: pkg install -y socat curl
|
prepare: pkg install -y socat curl
|
||||||
@ -234,19 +234,19 @@ jobs:
|
|||||||
copyback: false
|
copyback: false
|
||||||
run: |
|
run: |
|
||||||
if [ "${{ secrets.TokenName1}}" ] ; then
|
if [ "${{ secrets.TokenName1}}" ] ; then
|
||||||
export ${{ secrets.TokenName1}}=${{ secrets.TokenValue1}}
|
export ${{ secrets.TokenName1}}="${{ secrets.TokenValue1}}"
|
||||||
fi
|
fi
|
||||||
if [ "${{ secrets.TokenName2}}" ] ; then
|
if [ "${{ secrets.TokenName2}}" ] ; then
|
||||||
export ${{ secrets.TokenName2}}=${{ secrets.TokenValue2}}
|
export ${{ secrets.TokenName2}}="${{ secrets.TokenValue2}}"
|
||||||
fi
|
fi
|
||||||
if [ "${{ secrets.TokenName3}}" ] ; then
|
if [ "${{ secrets.TokenName3}}" ] ; then
|
||||||
export ${{ secrets.TokenName3}}=${{ secrets.TokenValue3}}
|
export ${{ secrets.TokenName3}}="${{ secrets.TokenValue3}}"
|
||||||
fi
|
fi
|
||||||
if [ "${{ secrets.TokenName4}}" ] ; then
|
if [ "${{ secrets.TokenName4}}" ] ; then
|
||||||
export ${{ secrets.TokenName4}}=${{ secrets.TokenValue4}}
|
export ${{ secrets.TokenName4}}="${{ secrets.TokenValue4}}"
|
||||||
fi
|
fi
|
||||||
if [ "${{ secrets.TokenName5}}" ] ; then
|
if [ "${{ secrets.TokenName5}}" ] ; then
|
||||||
export ${{ secrets.TokenName5}}=${{ secrets.TokenValue5}}
|
export ${{ secrets.TokenName5}}="${{ secrets.TokenValue5}}"
|
||||||
fi
|
fi
|
||||||
cd ../acmetest
|
cd ../acmetest
|
||||||
./letest.sh
|
./letest.sh
|
||||||
@ -255,7 +255,7 @@ jobs:
|
|||||||
|
|
||||||
|
|
||||||
OpenBSD:
|
OpenBSD:
|
||||||
runs-on: macos-12
|
runs-on: ubuntu-latest
|
||||||
needs: FreeBSD
|
needs: FreeBSD
|
||||||
env:
|
env:
|
||||||
TEST_DNS : ${{ secrets.TEST_DNS }}
|
TEST_DNS : ${{ secrets.TEST_DNS }}
|
||||||
@ -274,10 +274,10 @@ jobs:
|
|||||||
TokenName4: ${{ secrets.TokenName4}}
|
TokenName4: ${{ secrets.TokenName4}}
|
||||||
TokenName5: ${{ secrets.TokenName5}}
|
TokenName5: ${{ secrets.TokenName5}}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- 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 --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||||
- uses: vmactions/openbsd-vm@v0
|
- uses: vmactions/openbsd-vm@v1
|
||||||
with:
|
with:
|
||||||
envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_NO_SUBDOMAIN TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG http_proxy https_proxy TokenName1 TokenName2 TokenName3 TokenName4 TokenName5 ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}'
|
envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_NO_SUBDOMAIN TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG http_proxy https_proxy TokenName1 TokenName2 TokenName3 TokenName4 TokenName5 ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}'
|
||||||
prepare: pkg_add socat curl
|
prepare: pkg_add socat curl
|
||||||
@ -285,19 +285,19 @@ jobs:
|
|||||||
copyback: false
|
copyback: false
|
||||||
run: |
|
run: |
|
||||||
if [ "${{ secrets.TokenName1}}" ] ; then
|
if [ "${{ secrets.TokenName1}}" ] ; then
|
||||||
export ${{ secrets.TokenName1}}=${{ secrets.TokenValue1}}
|
export ${{ secrets.TokenName1}}="${{ secrets.TokenValue1}}"
|
||||||
fi
|
fi
|
||||||
if [ "${{ secrets.TokenName2}}" ] ; then
|
if [ "${{ secrets.TokenName2}}" ] ; then
|
||||||
export ${{ secrets.TokenName2}}=${{ secrets.TokenValue2}}
|
export ${{ secrets.TokenName2}}="${{ secrets.TokenValue2}}"
|
||||||
fi
|
fi
|
||||||
if [ "${{ secrets.TokenName3}}" ] ; then
|
if [ "${{ secrets.TokenName3}}" ] ; then
|
||||||
export ${{ secrets.TokenName3}}=${{ secrets.TokenValue3}}
|
export ${{ secrets.TokenName3}}="${{ secrets.TokenValue3}}"
|
||||||
fi
|
fi
|
||||||
if [ "${{ secrets.TokenName4}}" ] ; then
|
if [ "${{ secrets.TokenName4}}" ] ; then
|
||||||
export ${{ secrets.TokenName4}}=${{ secrets.TokenValue4}}
|
export ${{ secrets.TokenName4}}="${{ secrets.TokenValue4}}"
|
||||||
fi
|
fi
|
||||||
if [ "${{ secrets.TokenName5}}" ] ; then
|
if [ "${{ secrets.TokenName5}}" ] ; then
|
||||||
export ${{ secrets.TokenName5}}=${{ secrets.TokenValue5}}
|
export ${{ secrets.TokenName5}}="${{ secrets.TokenValue5}}"
|
||||||
fi
|
fi
|
||||||
cd ../acmetest
|
cd ../acmetest
|
||||||
./letest.sh
|
./letest.sh
|
||||||
@ -306,7 +306,7 @@ jobs:
|
|||||||
|
|
||||||
|
|
||||||
NetBSD:
|
NetBSD:
|
||||||
runs-on: macos-12
|
runs-on: ubuntu-latest
|
||||||
needs: OpenBSD
|
needs: OpenBSD
|
||||||
env:
|
env:
|
||||||
TEST_DNS : ${{ secrets.TEST_DNS }}
|
TEST_DNS : ${{ secrets.TEST_DNS }}
|
||||||
@ -325,31 +325,31 @@ jobs:
|
|||||||
TokenName4: ${{ secrets.TokenName4}}
|
TokenName4: ${{ secrets.TokenName4}}
|
||||||
TokenName5: ${{ secrets.TokenName5}}
|
TokenName5: ${{ secrets.TokenName5}}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- 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 --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||||
- uses: vmactions/netbsd-vm@v0
|
- uses: vmactions/netbsd-vm@v1
|
||||||
with:
|
with:
|
||||||
envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_NO_SUBDOMAIN TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG http_proxy https_proxy TokenName1 TokenName2 TokenName3 TokenName4 TokenName5 ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}'
|
envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_NO_SUBDOMAIN TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG http_proxy https_proxy TokenName1 TokenName2 TokenName3 TokenName4 TokenName5 ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}'
|
||||||
prepare: |
|
prepare: |
|
||||||
pkg_add curl socat
|
/usr/sbin/pkg_add curl socat
|
||||||
usesh: true
|
usesh: true
|
||||||
copyback: false
|
copyback: false
|
||||||
run: |
|
run: |
|
||||||
if [ "${{ secrets.TokenName1}}" ] ; then
|
if [ "${{ secrets.TokenName1}}" ] ; then
|
||||||
export ${{ secrets.TokenName1}}=${{ secrets.TokenValue1}}
|
export ${{ secrets.TokenName1}}="${{ secrets.TokenValue1}}"
|
||||||
fi
|
fi
|
||||||
if [ "${{ secrets.TokenName2}}" ] ; then
|
if [ "${{ secrets.TokenName2}}" ] ; then
|
||||||
export ${{ secrets.TokenName2}}=${{ secrets.TokenValue2}}
|
export ${{ secrets.TokenName2}}="${{ secrets.TokenValue2}}"
|
||||||
fi
|
fi
|
||||||
if [ "${{ secrets.TokenName3}}" ] ; then
|
if [ "${{ secrets.TokenName3}}" ] ; then
|
||||||
export ${{ secrets.TokenName3}}=${{ secrets.TokenValue3}}
|
export ${{ secrets.TokenName3}}="${{ secrets.TokenValue3}}"
|
||||||
fi
|
fi
|
||||||
if [ "${{ secrets.TokenName4}}" ] ; then
|
if [ "${{ secrets.TokenName4}}" ] ; then
|
||||||
export ${{ secrets.TokenName4}}=${{ secrets.TokenValue4}}
|
export ${{ secrets.TokenName4}}="${{ secrets.TokenValue4}}"
|
||||||
fi
|
fi
|
||||||
if [ "${{ secrets.TokenName5}}" ] ; then
|
if [ "${{ secrets.TokenName5}}" ] ; then
|
||||||
export ${{ secrets.TokenName5}}=${{ secrets.TokenValue5}}
|
export ${{ secrets.TokenName5}}="${{ secrets.TokenValue5}}"
|
||||||
fi
|
fi
|
||||||
cd ../acmetest
|
cd ../acmetest
|
||||||
./letest.sh
|
./letest.sh
|
||||||
@ -358,7 +358,7 @@ jobs:
|
|||||||
|
|
||||||
|
|
||||||
DragonFlyBSD:
|
DragonFlyBSD:
|
||||||
runs-on: macos-12
|
runs-on: ubuntu-latest
|
||||||
needs: NetBSD
|
needs: NetBSD
|
||||||
env:
|
env:
|
||||||
TEST_DNS : ${{ secrets.TEST_DNS }}
|
TEST_DNS : ${{ secrets.TEST_DNS }}
|
||||||
@ -377,31 +377,31 @@ jobs:
|
|||||||
TokenName4: ${{ secrets.TokenName4}}
|
TokenName4: ${{ secrets.TokenName4}}
|
||||||
TokenName5: ${{ secrets.TokenName5}}
|
TokenName5: ${{ secrets.TokenName5}}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- 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 --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||||
- uses: vmactions/dragonflybsd-vm@v0
|
- uses: vmactions/dragonflybsd-vm@v1
|
||||||
with:
|
with:
|
||||||
envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_NO_SUBDOMAIN TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG http_proxy https_proxy TokenName1 TokenName2 TokenName3 TokenName4 TokenName5 ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}'
|
envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_NO_SUBDOMAIN TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG http_proxy https_proxy TokenName1 TokenName2 TokenName3 TokenName4 TokenName5 ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}'
|
||||||
prepare: |
|
prepare: |
|
||||||
pkg install -y curl socat
|
pkg install -y curl socat libnghttp2
|
||||||
usesh: true
|
usesh: true
|
||||||
copyback: false
|
copyback: false
|
||||||
run: |
|
run: |
|
||||||
if [ "${{ secrets.TokenName1}}" ] ; then
|
if [ "${{ secrets.TokenName1}}" ] ; then
|
||||||
export ${{ secrets.TokenName1}}=${{ secrets.TokenValue1}}
|
export ${{ secrets.TokenName1}}="${{ secrets.TokenValue1}}"
|
||||||
fi
|
fi
|
||||||
if [ "${{ secrets.TokenName2}}" ] ; then
|
if [ "${{ secrets.TokenName2}}" ] ; then
|
||||||
export ${{ secrets.TokenName2}}=${{ secrets.TokenValue2}}
|
export ${{ secrets.TokenName2}}="${{ secrets.TokenValue2}}"
|
||||||
fi
|
fi
|
||||||
if [ "${{ secrets.TokenName3}}" ] ; then
|
if [ "${{ secrets.TokenName3}}" ] ; then
|
||||||
export ${{ secrets.TokenName3}}=${{ secrets.TokenValue3}}
|
export ${{ secrets.TokenName3}}="${{ secrets.TokenValue3}}"
|
||||||
fi
|
fi
|
||||||
if [ "${{ secrets.TokenName4}}" ] ; then
|
if [ "${{ secrets.TokenName4}}" ] ; then
|
||||||
export ${{ secrets.TokenName4}}=${{ secrets.TokenValue4}}
|
export ${{ secrets.TokenName4}}="${{ secrets.TokenValue4}}"
|
||||||
fi
|
fi
|
||||||
if [ "${{ secrets.TokenName5}}" ] ; then
|
if [ "${{ secrets.TokenName5}}" ] ; then
|
||||||
export ${{ secrets.TokenName5}}=${{ secrets.TokenValue5}}
|
export ${{ secrets.TokenName5}}="${{ secrets.TokenValue5}}"
|
||||||
fi
|
fi
|
||||||
cd ../acmetest
|
cd ../acmetest
|
||||||
./letest.sh
|
./letest.sh
|
||||||
@ -413,7 +413,7 @@ jobs:
|
|||||||
|
|
||||||
|
|
||||||
Solaris:
|
Solaris:
|
||||||
runs-on: macos-12
|
runs-on: ubuntu-latest
|
||||||
needs: DragonFlyBSD
|
needs: DragonFlyBSD
|
||||||
env:
|
env:
|
||||||
TEST_DNS : ${{ secrets.TEST_DNS }}
|
TEST_DNS : ${{ secrets.TEST_DNS }}
|
||||||
@ -433,10 +433,10 @@ jobs:
|
|||||||
TokenName4: ${{ secrets.TokenName4}}
|
TokenName4: ${{ secrets.TokenName4}}
|
||||||
TokenName5: ${{ secrets.TokenName5}}
|
TokenName5: ${{ secrets.TokenName5}}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- 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 --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||||
- uses: vmactions/solaris-vm@v0
|
- uses: vmactions/solaris-vm@v1
|
||||||
with:
|
with:
|
||||||
envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_NO_SUBDOMAIN TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG http_proxy https_proxy HTTPS_INSECURE TokenName1 TokenName2 TokenName3 TokenName4 TokenName5 ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}'
|
envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_NO_SUBDOMAIN TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG http_proxy https_proxy HTTPS_INSECURE TokenName1 TokenName2 TokenName3 TokenName4 TokenName5 ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}'
|
||||||
copyback: false
|
copyback: false
|
||||||
@ -445,19 +445,68 @@ jobs:
|
|||||||
pkg set-mediator -v -I default@1.1 openssl
|
pkg set-mediator -v -I default@1.1 openssl
|
||||||
export PATH=/usr/gnu/bin:$PATH
|
export PATH=/usr/gnu/bin:$PATH
|
||||||
if [ "${{ secrets.TokenName1}}" ] ; then
|
if [ "${{ secrets.TokenName1}}" ] ; then
|
||||||
export ${{ secrets.TokenName1}}=${{ secrets.TokenValue1}}
|
export ${{ secrets.TokenName1}}="${{ secrets.TokenValue1}}"
|
||||||
fi
|
fi
|
||||||
if [ "${{ secrets.TokenName2}}" ] ; then
|
if [ "${{ secrets.TokenName2}}" ] ; then
|
||||||
export ${{ secrets.TokenName2}}=${{ secrets.TokenValue2}}
|
export ${{ secrets.TokenName2}}="${{ secrets.TokenValue2}}"
|
||||||
fi
|
fi
|
||||||
if [ "${{ secrets.TokenName3}}" ] ; then
|
if [ "${{ secrets.TokenName3}}" ] ; then
|
||||||
export ${{ secrets.TokenName3}}=${{ secrets.TokenValue3}}
|
export ${{ secrets.TokenName3}}="${{ secrets.TokenValue3}}"
|
||||||
fi
|
fi
|
||||||
if [ "${{ secrets.TokenName4}}" ] ; then
|
if [ "${{ secrets.TokenName4}}" ] ; then
|
||||||
export ${{ secrets.TokenName4}}=${{ secrets.TokenValue4}}
|
export ${{ secrets.TokenName4}}="${{ secrets.TokenValue4}}"
|
||||||
fi
|
fi
|
||||||
if [ "${{ secrets.TokenName5}}" ] ; then
|
if [ "${{ secrets.TokenName5}}" ] ; then
|
||||||
export ${{ secrets.TokenName5}}=${{ secrets.TokenValue5}}
|
export ${{ secrets.TokenName5}}="${{ secrets.TokenValue5}}"
|
||||||
|
fi
|
||||||
|
cd ../acmetest
|
||||||
|
./letest.sh
|
||||||
|
|
||||||
|
|
||||||
|
Omnios:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: Solaris
|
||||||
|
env:
|
||||||
|
TEST_DNS : ${{ secrets.TEST_DNS }}
|
||||||
|
TestingDomain: ${{ secrets.TestingDomain }}
|
||||||
|
TEST_DNS_NO_WILDCARD: ${{ secrets.TEST_DNS_NO_WILDCARD }}
|
||||||
|
TEST_DNS_NO_SUBDOMAIN: ${{ secrets.TEST_DNS_NO_SUBDOMAIN }}
|
||||||
|
TEST_DNS_SLEEP: ${{ secrets.TEST_DNS_SLEEP }}
|
||||||
|
CASE: le_test_dnsapi
|
||||||
|
TEST_LOCAL: 1
|
||||||
|
DEBUG: ${{ secrets.DEBUG }}
|
||||||
|
http_proxy: ${{ secrets.http_proxy }}
|
||||||
|
https_proxy: ${{ secrets.https_proxy }}
|
||||||
|
HTTPS_INSECURE: 1 # always set to 1 to ignore https error, since Omnios doesn't accept the expired ISRG X1 root
|
||||||
|
TokenName1: ${{ secrets.TokenName1}}
|
||||||
|
TokenName2: ${{ secrets.TokenName2}}
|
||||||
|
TokenName3: ${{ secrets.TokenName3}}
|
||||||
|
TokenName4: ${{ secrets.TokenName4}}
|
||||||
|
TokenName5: ${{ secrets.TokenName5}}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Clone acmetest
|
||||||
|
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||||
|
- uses: vmactions/omnios-vm@v1
|
||||||
|
with:
|
||||||
|
envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_NO_SUBDOMAIN TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG http_proxy https_proxy HTTPS_INSECURE TokenName1 TokenName2 TokenName3 TokenName4 TokenName5 ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}'
|
||||||
|
copyback: false
|
||||||
|
prepare: pkg install socat
|
||||||
|
run: |
|
||||||
|
if [ "${{ secrets.TokenName1}}" ] ; then
|
||||||
|
export ${{ secrets.TokenName1}}="${{ secrets.TokenValue1}}"
|
||||||
|
fi
|
||||||
|
if [ "${{ secrets.TokenName2}}" ] ; then
|
||||||
|
export ${{ secrets.TokenName2}}="${{ secrets.TokenValue2}}"
|
||||||
|
fi
|
||||||
|
if [ "${{ secrets.TokenName3}}" ] ; then
|
||||||
|
export ${{ secrets.TokenName3}}="${{ secrets.TokenValue3}}"
|
||||||
|
fi
|
||||||
|
if [ "${{ secrets.TokenName4}}" ] ; then
|
||||||
|
export ${{ secrets.TokenName4}}="${{ secrets.TokenValue4}}"
|
||||||
|
fi
|
||||||
|
if [ "${{ secrets.TokenName5}}" ] ; then
|
||||||
|
export ${{ secrets.TokenName5}}="${{ secrets.TokenValue5}}"
|
||||||
fi
|
fi
|
||||||
cd ../acmetest
|
cd ../acmetest
|
||||||
./letest.sh
|
./letest.sh
|
||||||
|
18
.github/workflows/DragonFlyBSD.yml
vendored
18
.github/workflows/DragonFlyBSD.yml
vendored
@ -20,7 +20,6 @@ concurrency:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
DragonFlyBSD:
|
DragonFlyBSD:
|
||||||
strategy:
|
strategy:
|
||||||
@ -36,7 +35,7 @@ jobs:
|
|||||||
# CA: "ZeroSSL RSA Domain Secure Site CA"
|
# CA: "ZeroSSL RSA Domain Secure Site CA"
|
||||||
# CA_EMAIL: "githubtest@acme.sh"
|
# CA_EMAIL: "githubtest@acme.sh"
|
||||||
# TEST_PREFERRED_CHAIN: ""
|
# TEST_PREFERRED_CHAIN: ""
|
||||||
runs-on: macos-12
|
runs-on: ubuntu-latest
|
||||||
env:
|
env:
|
||||||
TEST_LOCAL: 1
|
TEST_LOCAL: 1
|
||||||
TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }}
|
TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }}
|
||||||
@ -44,9 +43,10 @@ jobs:
|
|||||||
CA: ${{ matrix.CA }}
|
CA: ${{ matrix.CA }}
|
||||||
CA_EMAIL: ${{ matrix.CA_EMAIL }}
|
CA_EMAIL: ${{ matrix.CA_EMAIL }}
|
||||||
TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }}
|
TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }}
|
||||||
|
ACME_USE_WGET: ${{ matrix.ACME_USE_WGET }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- uses: vmactions/cf-tunnel@v0.0.3
|
- uses: vmactions/cf-tunnel@v0
|
||||||
id: tunnel
|
id: tunnel
|
||||||
with:
|
with:
|
||||||
protocol: http
|
protocol: http
|
||||||
@ -54,16 +54,16 @@ jobs:
|
|||||||
- name: Set envs
|
- name: Set envs
|
||||||
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 --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||||
- uses: vmactions/dragonflybsd-vm@v0
|
- uses: vmactions/dragonflybsd-vm@v1
|
||||||
with:
|
with:
|
||||||
envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN'
|
envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN ACME_USE_WGET'
|
||||||
copyback: "false"
|
|
||||||
nat: |
|
nat: |
|
||||||
"8080": "80"
|
"8080": "80"
|
||||||
prepare: |
|
prepare: |
|
||||||
pkg install -y curl socat
|
pkg install -y curl socat libnghttp2
|
||||||
usesh: true
|
usesh: true
|
||||||
|
copyback: false
|
||||||
run: |
|
run: |
|
||||||
cd ../acmetest \
|
cd ../acmetest \
|
||||||
&& ./letest.sh
|
&& ./letest.sh
|
||||||
|
10
.github/workflows/FreeBSD.yml
vendored
10
.github/workflows/FreeBSD.yml
vendored
@ -41,7 +41,7 @@ jobs:
|
|||||||
# CA: "ZeroSSL RSA Domain Secure Site CA"
|
# CA: "ZeroSSL RSA Domain Secure Site CA"
|
||||||
# CA_EMAIL: "githubtest@acme.sh"
|
# CA_EMAIL: "githubtest@acme.sh"
|
||||||
# TEST_PREFERRED_CHAIN: ""
|
# TEST_PREFERRED_CHAIN: ""
|
||||||
runs-on: macos-12
|
runs-on: ubuntu-latest
|
||||||
env:
|
env:
|
||||||
TEST_LOCAL: 1
|
TEST_LOCAL: 1
|
||||||
TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }}
|
TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }}
|
||||||
@ -51,8 +51,8 @@ jobs:
|
|||||||
TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }}
|
TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }}
|
||||||
ACME_USE_WGET: ${{ matrix.ACME_USE_WGET }}
|
ACME_USE_WGET: ${{ matrix.ACME_USE_WGET }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- uses: vmactions/cf-tunnel@v0.0.3
|
- uses: vmactions/cf-tunnel@v0
|
||||||
id: tunnel
|
id: tunnel
|
||||||
with:
|
with:
|
||||||
protocol: http
|
protocol: http
|
||||||
@ -60,8 +60,8 @@ jobs:
|
|||||||
- name: Set envs
|
- name: Set envs
|
||||||
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 --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||||
- uses: vmactions/freebsd-vm@v0
|
- uses: vmactions/freebsd-vm@v1
|
||||||
with:
|
with:
|
||||||
envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN ACME_USE_WGET'
|
envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN ACME_USE_WGET'
|
||||||
nat: |
|
nat: |
|
||||||
|
4
.github/workflows/Linux.yml
vendored
4
.github/workflows/Linux.yml
vendored
@ -33,11 +33,11 @@ jobs:
|
|||||||
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1
|
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1
|
||||||
TEST_ACME_Server: "LetsEncrypt.org_test"
|
TEST_ACME_Server: "LetsEncrypt.org_test"
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- name: Clone acmetest
|
- name: Clone acmetest
|
||||||
run: |
|
run: |
|
||||||
cd .. \
|
cd .. \
|
||||||
&& git clone https://github.com/acmesh-official/acmetest.git \
|
&& git clone --depth=1 https://github.com/acmesh-official/acmetest.git \
|
||||||
&& cp -r acme.sh acmetest/
|
&& cp -r acme.sh acmetest/
|
||||||
- name: Run acmetest
|
- name: Run acmetest
|
||||||
run: |
|
run: |
|
||||||
|
4
.github/workflows/MacOS.yml
vendored
4
.github/workflows/MacOS.yml
vendored
@ -44,13 +44,13 @@ jobs:
|
|||||||
CA_EMAIL: ${{ matrix.CA_EMAIL }}
|
CA_EMAIL: ${{ matrix.CA_EMAIL }}
|
||||||
TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }}
|
TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- name: Install tools
|
- name: Install tools
|
||||||
run: brew install socat
|
run: brew install socat
|
||||||
- name: Clone acmetest
|
- name: Clone acmetest
|
||||||
run: |
|
run: |
|
||||||
cd .. \
|
cd .. \
|
||||||
&& git clone https://github.com/acmesh-official/acmetest.git \
|
&& git clone --depth=1 https://github.com/acmesh-official/acmetest.git \
|
||||||
&& cp -r acme.sh acmetest/
|
&& cp -r acme.sh acmetest/
|
||||||
- name: Run acmetest
|
- name: Run acmetest
|
||||||
run: |
|
run: |
|
||||||
|
17
.github/workflows/NetBSD.yml
vendored
17
.github/workflows/NetBSD.yml
vendored
@ -20,7 +20,6 @@ concurrency:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
NetBSD:
|
NetBSD:
|
||||||
strategy:
|
strategy:
|
||||||
@ -36,7 +35,7 @@ jobs:
|
|||||||
# CA: "ZeroSSL RSA Domain Secure Site CA"
|
# CA: "ZeroSSL RSA Domain Secure Site CA"
|
||||||
# CA_EMAIL: "githubtest@acme.sh"
|
# CA_EMAIL: "githubtest@acme.sh"
|
||||||
# TEST_PREFERRED_CHAIN: ""
|
# TEST_PREFERRED_CHAIN: ""
|
||||||
runs-on: macos-12
|
runs-on: ubuntu-latest
|
||||||
env:
|
env:
|
||||||
TEST_LOCAL: 1
|
TEST_LOCAL: 1
|
||||||
TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }}
|
TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }}
|
||||||
@ -44,9 +43,10 @@ jobs:
|
|||||||
CA: ${{ matrix.CA }}
|
CA: ${{ matrix.CA }}
|
||||||
CA_EMAIL: ${{ matrix.CA_EMAIL }}
|
CA_EMAIL: ${{ matrix.CA_EMAIL }}
|
||||||
TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }}
|
TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }}
|
||||||
|
ACME_USE_WGET: ${{ matrix.ACME_USE_WGET }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- uses: vmactions/cf-tunnel@v0.0.3
|
- uses: vmactions/cf-tunnel@v0
|
||||||
id: tunnel
|
id: tunnel
|
||||||
with:
|
with:
|
||||||
protocol: http
|
protocol: http
|
||||||
@ -54,15 +54,14 @@ jobs:
|
|||||||
- name: Set envs
|
- name: Set envs
|
||||||
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 --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||||
- uses: vmactions/netbsd-vm@v0
|
- uses: vmactions/netbsd-vm@v1
|
||||||
with:
|
with:
|
||||||
envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN'
|
envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN ACME_USE_WGET'
|
||||||
nat: |
|
nat: |
|
||||||
"8080": "80"
|
"8080": "80"
|
||||||
prepare: |
|
prepare: |
|
||||||
export PKG_PATH="http://cdn.NetBSD.org/pub/pkgsrc/packages/NetBSD/$(uname -p)/$(uname -r|cut -f '1 2' -d.)/All/"
|
/usr/sbin/pkg_add curl socat
|
||||||
pkg_add curl socat
|
|
||||||
usesh: true
|
usesh: true
|
||||||
copyback: false
|
copyback: false
|
||||||
run: |
|
run: |
|
||||||
|
75
.github/workflows/Omnios.yml
vendored
Normal file
75
.github/workflows/Omnios.yml
vendored
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
name: Omnios
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- '*'
|
||||||
|
paths:
|
||||||
|
- '*.sh'
|
||||||
|
- '.github/workflows/Omnios.yml'
|
||||||
|
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- dev
|
||||||
|
paths:
|
||||||
|
- '*.sh'
|
||||||
|
- '.github/workflows/Omnios.yml'
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
Omnios:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- TEST_ACME_Server: "LetsEncrypt.org_test"
|
||||||
|
CA_ECDSA: ""
|
||||||
|
CA: ""
|
||||||
|
CA_EMAIL: ""
|
||||||
|
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1
|
||||||
|
- TEST_ACME_Server: "LetsEncrypt.org_test"
|
||||||
|
CA_ECDSA: ""
|
||||||
|
CA: ""
|
||||||
|
CA_EMAIL: ""
|
||||||
|
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1
|
||||||
|
ACME_USE_WGET: 1
|
||||||
|
#- TEST_ACME_Server: "ZeroSSL.com"
|
||||||
|
# CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA"
|
||||||
|
# CA: "ZeroSSL RSA Domain Secure Site CA"
|
||||||
|
# CA_EMAIL: "githubtest@acme.sh"
|
||||||
|
# TEST_PREFERRED_CHAIN: ""
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
TEST_LOCAL: 1
|
||||||
|
TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }}
|
||||||
|
CA_ECDSA: ${{ matrix.CA_ECDSA }}
|
||||||
|
CA: ${{ matrix.CA }}
|
||||||
|
CA_EMAIL: ${{ matrix.CA_EMAIL }}
|
||||||
|
TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }}
|
||||||
|
ACME_USE_WGET: ${{ matrix.ACME_USE_WGET }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: vmactions/cf-tunnel@v0
|
||||||
|
id: tunnel
|
||||||
|
with:
|
||||||
|
protocol: http
|
||||||
|
port: 8080
|
||||||
|
- name: Set envs
|
||||||
|
run: echo "TestingDomain=${{steps.tunnel.outputs.server}}" >> $GITHUB_ENV
|
||||||
|
- name: Clone acmetest
|
||||||
|
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||||
|
- uses: vmactions/omnios-vm@v1
|
||||||
|
with:
|
||||||
|
envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN ACME_USE_WGET'
|
||||||
|
nat: |
|
||||||
|
"8080": "80"
|
||||||
|
prepare: pkg install socat wget
|
||||||
|
copyback: false
|
||||||
|
run: |
|
||||||
|
cd ../acmetest \
|
||||||
|
&& ./letest.sh
|
||||||
|
|
||||||
|
|
12
.github/workflows/OpenBSD.yml
vendored
12
.github/workflows/OpenBSD.yml
vendored
@ -41,7 +41,7 @@ jobs:
|
|||||||
# CA: "ZeroSSL RSA Domain Secure Site CA"
|
# CA: "ZeroSSL RSA Domain Secure Site CA"
|
||||||
# CA_EMAIL: "githubtest@acme.sh"
|
# CA_EMAIL: "githubtest@acme.sh"
|
||||||
# TEST_PREFERRED_CHAIN: ""
|
# TEST_PREFERRED_CHAIN: ""
|
||||||
runs-on: macos-12
|
runs-on: ubuntu-latest
|
||||||
env:
|
env:
|
||||||
TEST_LOCAL: 1
|
TEST_LOCAL: 1
|
||||||
TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }}
|
TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }}
|
||||||
@ -51,8 +51,8 @@ jobs:
|
|||||||
TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }}
|
TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }}
|
||||||
ACME_USE_WGET: ${{ matrix.ACME_USE_WGET }}
|
ACME_USE_WGET: ${{ matrix.ACME_USE_WGET }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- uses: vmactions/cf-tunnel@v0.0.3
|
- uses: vmactions/cf-tunnel@v0
|
||||||
id: tunnel
|
id: tunnel
|
||||||
with:
|
with:
|
||||||
protocol: http
|
protocol: http
|
||||||
@ -60,13 +60,13 @@ jobs:
|
|||||||
- name: Set envs
|
- name: Set envs
|
||||||
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 --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||||
- uses: vmactions/openbsd-vm@v0
|
- uses: vmactions/openbsd-vm@v1
|
||||||
with:
|
with:
|
||||||
envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN ACME_USE_WGET'
|
envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN ACME_USE_WGET'
|
||||||
nat: |
|
nat: |
|
||||||
"8080": "80"
|
"8080": "80"
|
||||||
prepare: pkg_add socat curl wget
|
prepare: pkg_add socat curl wget libnghttp2
|
||||||
usesh: true
|
usesh: true
|
||||||
copyback: false
|
copyback: false
|
||||||
run: |
|
run: |
|
||||||
|
8
.github/workflows/PebbleStrict.yml
vendored
8
.github/workflows/PebbleStrict.yml
vendored
@ -33,7 +33,7 @@ jobs:
|
|||||||
TEST_CA: "Pebble Intermediate CA"
|
TEST_CA: "Pebble Intermediate CA"
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- name: Install tools
|
- name: Install tools
|
||||||
run: sudo apt-get install -y socat
|
run: sudo apt-get install -y socat
|
||||||
- name: Run Pebble
|
- name: Run Pebble
|
||||||
@ -41,7 +41,7 @@ jobs:
|
|||||||
- name: Set up Pebble
|
- name: Set up Pebble
|
||||||
run: curl --request POST --data '{"ip":"10.30.50.1"}' http://localhost:8055/set-default-ipv4
|
run: curl --request POST --data '{"ip":"10.30.50.1"}' http://localhost:8055/set-default-ipv4
|
||||||
- name: Clone acmetest
|
- name: Clone acmetest
|
||||||
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||||
- name: Run acmetest
|
- name: Run acmetest
|
||||||
run: cd ../acmetest && ./letest.sh
|
run: cd ../acmetest && ./letest.sh
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ jobs:
|
|||||||
TEST_IPCERT: 1
|
TEST_IPCERT: 1
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- name: Install tools
|
- name: Install tools
|
||||||
run: sudo apt-get install -y socat
|
run: sudo apt-get install -y socat
|
||||||
- name: Run Pebble
|
- name: Run Pebble
|
||||||
@ -67,6 +67,6 @@ jobs:
|
|||||||
-e PEBBLE_VA_ALWAYS_VALID=1 \
|
-e PEBBLE_VA_ALWAYS_VALID=1 \
|
||||||
-p 14000:14000 -p 15000:15000 letsencrypt/pebble:latest pebble -config /test/config/pebble-config.json -strict
|
-p 14000:14000 -p 15000:15000 letsencrypt/pebble:latest pebble -config /test/config/pebble-config.json -strict
|
||||||
- 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 --depth=1 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
|
17
.github/workflows/Solaris.yml
vendored
17
.github/workflows/Solaris.yml
vendored
@ -14,12 +14,12 @@ on:
|
|||||||
- '*.sh'
|
- '*.sh'
|
||||||
- '.github/workflows/Solaris.yml'
|
- '.github/workflows/Solaris.yml'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
Solaris:
|
Solaris:
|
||||||
strategy:
|
strategy:
|
||||||
@ -41,7 +41,7 @@ jobs:
|
|||||||
# CA: "ZeroSSL RSA Domain Secure Site CA"
|
# CA: "ZeroSSL RSA Domain Secure Site CA"
|
||||||
# CA_EMAIL: "githubtest@acme.sh"
|
# CA_EMAIL: "githubtest@acme.sh"
|
||||||
# TEST_PREFERRED_CHAIN: ""
|
# TEST_PREFERRED_CHAIN: ""
|
||||||
runs-on: macos-12
|
runs-on: ubuntu-latest
|
||||||
env:
|
env:
|
||||||
TEST_LOCAL: 1
|
TEST_LOCAL: 1
|
||||||
TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }}
|
TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }}
|
||||||
@ -51,8 +51,8 @@ jobs:
|
|||||||
TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }}
|
TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }}
|
||||||
ACME_USE_WGET: ${{ matrix.ACME_USE_WGET }}
|
ACME_USE_WGET: ${{ matrix.ACME_USE_WGET }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- uses: vmactions/cf-tunnel@v0.0.3
|
- uses: vmactions/cf-tunnel@v0
|
||||||
id: tunnel
|
id: tunnel
|
||||||
with:
|
with:
|
||||||
protocol: http
|
protocol: http
|
||||||
@ -60,15 +60,16 @@ jobs:
|
|||||||
- name: Set envs
|
- name: Set envs
|
||||||
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 --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||||
- uses: vmactions/solaris-vm@v0
|
- uses: vmactions/solaris-vm@v1
|
||||||
with:
|
with:
|
||||||
envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN ACME_USE_WGET'
|
envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN ACME_USE_WGET'
|
||||||
copyback: "false"
|
|
||||||
nat: |
|
nat: |
|
||||||
"8080": "80"
|
"8080": "80"
|
||||||
prepare: pkgutil -y -i socat curl wget
|
prepare: pkgutil -y -i socat curl wget
|
||||||
|
copyback: false
|
||||||
run: |
|
run: |
|
||||||
cd ../acmetest \
|
cd ../acmetest \
|
||||||
&& ./letest.sh
|
&& ./letest.sh
|
||||||
|
|
||||||
|
|
||||||
|
13
.github/workflows/Ubuntu.yml
vendored
13
.github/workflows/Ubuntu.yml
vendored
@ -70,7 +70,7 @@ jobs:
|
|||||||
TestingDomain: ${{ matrix.TestingDomain }}
|
TestingDomain: ${{ matrix.TestingDomain }}
|
||||||
ACME_USE_WGET: ${{ matrix.ACME_USE_WGET }}
|
ACME_USE_WGET: ${{ matrix.ACME_USE_WGET }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- name: Install tools
|
- name: Install tools
|
||||||
run: sudo apt-get install -y socat wget
|
run: sudo apt-get install -y socat wget
|
||||||
- name: Start StepCA
|
- name: Start StepCA
|
||||||
@ -80,15 +80,20 @@ jobs:
|
|||||||
-p 9000:9000 \
|
-p 9000:9000 \
|
||||||
-e "DOCKER_STEPCA_INIT_NAME=Smallstep" \
|
-e "DOCKER_STEPCA_INIT_NAME=Smallstep" \
|
||||||
-e "DOCKER_STEPCA_INIT_DNS_NAMES=localhost,$(hostname -f)" \
|
-e "DOCKER_STEPCA_INIT_DNS_NAMES=localhost,$(hostname -f)" \
|
||||||
|
-e "DOCKER_STEPCA_INIT_REMOTE_MANAGEMENT=true" \
|
||||||
|
-e "DOCKER_STEPCA_INIT_PASSWORD=test" \
|
||||||
--name stepca \
|
--name stepca \
|
||||||
smallstep/step-ca \
|
smallstep/step-ca:0.23.1
|
||||||
&& sleep 5 && docker exec stepca step ca provisioner add acme --type ACME \
|
|
||||||
|
sleep 5
|
||||||
|
docker exec stepca bash -c "echo test >test" \
|
||||||
|
&& docker exec stepca step ca provisioner add acme --type ACME --admin-subject step --admin-password-file=/home/step/test \
|
||||||
&& docker exec stepca kill -1 1 \
|
&& 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"
|
&& 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 .. \
|
||||||
&& git clone https://github.com/acmesh-official/acmetest.git \
|
&& git clone --depth=1 https://github.com/acmesh-official/acmetest.git \
|
||||||
&& cp -r acme.sh acmetest/
|
&& cp -r acme.sh acmetest/
|
||||||
- name: Run acmetest
|
- name: Run acmetest
|
||||||
run: |
|
run: |
|
||||||
|
6
.github/workflows/Windows.yml
vendored
6
.github/workflows/Windows.yml
vendored
@ -49,7 +49,7 @@ jobs:
|
|||||||
- name: Set git to use LF
|
- name: Set git to use LF
|
||||||
run: |
|
run: |
|
||||||
git config --global core.autocrlf false
|
git config --global core.autocrlf false
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- name: Install cygwin base packages with chocolatey
|
- name: Install cygwin base packages with chocolatey
|
||||||
run: |
|
run: |
|
||||||
choco config get cacheLocation
|
choco config get cacheLocation
|
||||||
@ -57,7 +57,7 @@ jobs:
|
|||||||
shell: cmd
|
shell: cmd
|
||||||
- name: Install cygwin additional packages
|
- name: Install cygwin additional packages
|
||||||
run: |
|
run: |
|
||||||
C:\tools\cygwin\cygwinsetup.exe -qgnNdO -R C:/tools/cygwin -s http://mirrors.kernel.org/sourceware/cygwin/ -P socat,curl,cron,unzip,git,xxd
|
C:\tools\cygwin\cygwinsetup.exe -qgnNdO -R C:/tools/cygwin -s https://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
|
||||||
@ -69,7 +69,7 @@ jobs:
|
|||||||
echo "PATH=%PATH%"
|
echo "PATH=%PATH%"
|
||||||
- name: Clone acmetest
|
- name: Clone acmetest
|
||||||
shell: cmd
|
shell: cmd
|
||||||
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
|
||||||
- name: Run acmetest
|
- name: Run acmetest
|
||||||
shell: cmd
|
shell: cmd
|
||||||
run: cd ../acmetest && bash.exe -c ./letest.sh
|
run: cd ../acmetest && bash.exe -c ./letest.sh
|
||||||
|
10
.github/workflows/dockerhub.yml
vendored
10
.github/workflows/dockerhub.yml
vendored
@ -28,9 +28,9 @@ jobs:
|
|||||||
id: step_one
|
id: step_one
|
||||||
run: |
|
run: |
|
||||||
if [ "$DOCKER_PASSWORD" ] ; then
|
if [ "$DOCKER_PASSWORD" ] ; then
|
||||||
echo "::set-output name=hasToken::true"
|
echo "hasToken=true" >>$GITHUB_OUTPUT
|
||||||
else
|
else
|
||||||
echo "::set-output name=hasToken::false"
|
echo "hasToken=false" >>$GITHUB_OUTPUT
|
||||||
fi
|
fi
|
||||||
- name: Check the value
|
- name: Check the value
|
||||||
run: echo ${{ steps.step_one.outputs.hasToken }}
|
run: echo ${{ steps.step_one.outputs.hasToken }}
|
||||||
@ -41,11 +41,11 @@ jobs:
|
|||||||
if: "contains(needs.CheckToken.outputs.hasToken, 'true')"
|
if: "contains(needs.CheckToken.outputs.hasToken, 'true')"
|
||||||
steps:
|
steps:
|
||||||
- name: checkout code
|
- name: checkout code
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v1
|
uses: docker/setup-qemu-action@v2
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v1
|
uses: docker/setup-buildx-action@v2
|
||||||
- name: login to docker hub
|
- name: login to docker hub
|
||||||
run: |
|
run: |
|
||||||
echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin
|
echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin
|
||||||
|
6
.github/workflows/pr_dns.yml
vendored
6
.github/workflows/pr_dns.yml
vendored
@ -4,8 +4,6 @@ on:
|
|||||||
pull_request_target:
|
pull_request_target:
|
||||||
types:
|
types:
|
||||||
- opened
|
- opened
|
||||||
branches:
|
|
||||||
- 'dev'
|
|
||||||
paths:
|
paths:
|
||||||
- 'dnsapi/*.sh'
|
- 'dnsapi/*.sh'
|
||||||
|
|
||||||
@ -22,9 +20,11 @@ jobs:
|
|||||||
owner: context.repo.owner,
|
owner: context.repo.owner,
|
||||||
repo: context.repo.repo,
|
repo: context.repo.repo,
|
||||||
body: `**Welcome**
|
body: `**Welcome**
|
||||||
Please make sure you're read our [DNS API Dev Guide](../wiki/DNS-API-Dev-Guide) and [DNS-API-Test](../wiki/DNS-API-Test).
|
First thing: don't send PR to the master branch, please send to the dev branch instead.
|
||||||
|
Please make sure you've read our [DNS API Dev Guide](../wiki/DNS-API-Dev-Guide) and [DNS-API-Test](../wiki/DNS-API-Test).
|
||||||
Then reply on this message, otherwise, your code will not be reviewed or merged.
|
Then reply on this message, otherwise, your code will not be reviewed or merged.
|
||||||
We look forward to reviewing your Pull request shortly ✨
|
We look forward to reviewing your Pull request shortly ✨
|
||||||
|
注意: 必须通过了 [DNS-API-Test](../wiki/DNS-API-Test) 才会被 review. 无论是修改, 还是新加的 dns api, 都必须确保通过这个测试.
|
||||||
`
|
`
|
||||||
})
|
})
|
||||||
|
|
||||||
|
2
.github/workflows/pr_notify.yml
vendored
2
.github/workflows/pr_notify.yml
vendored
@ -22,7 +22,7 @@ jobs:
|
|||||||
owner: context.repo.owner,
|
owner: context.repo.owner,
|
||||||
repo: context.repo.repo,
|
repo: context.repo.repo,
|
||||||
body: `**Welcome**
|
body: `**Welcome**
|
||||||
Please make sure you're read our [Code-of-conduct](../wiki/Code-of-conduct) and add the usage here: [notify](../wiki/notify).
|
Please make sure you've read our [Code-of-conduct](../wiki/Code-of-conduct) and add the usage here: [notify](../wiki/notify).
|
||||||
Then reply on this message, otherwise, your code will not be reviewed or merged.
|
Then reply on this message, otherwise, your code will not be reviewed or merged.
|
||||||
We look forward to reviewing your Pull request shortly ✨
|
We look forward to reviewing your Pull request shortly ✨
|
||||||
`
|
`
|
||||||
|
6
.github/workflows/shellcheck.yml
vendored
6
.github/workflows/shellcheck.yml
vendored
@ -22,16 +22,16 @@ jobs:
|
|||||||
ShellCheck:
|
ShellCheck:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- name: Install Shellcheck
|
- name: Install Shellcheck
|
||||||
run: sudo apt-get install -y shellcheck
|
run: sudo apt-get install -y shellcheck
|
||||||
- name: DoShellcheck
|
- name: DoShellcheck
|
||||||
run: shellcheck -V && shellcheck -e SC2181 **/*.sh && echo "shellcheck OK"
|
run: shellcheck -V && shellcheck -e SC2181 -e SC2089 **/*.sh && echo "shellcheck OK"
|
||||||
|
|
||||||
shfmt:
|
shfmt:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- name: Install shfmt
|
- name: Install shfmt
|
||||||
run: curl -sSL https://github.com/mvdan/sh/releases/download/v3.1.2/shfmt_v3.1.2_linux_amd64 -o ~/shfmt && chmod +x ~/shfmt
|
run: curl -sSL https://github.com/mvdan/sh/releases/download/v3.1.2/shfmt_v3.1.2_linux_amd64 -o ~/shfmt && chmod +x ~/shfmt
|
||||||
- name: shfmt
|
- name: shfmt
|
||||||
|
13
Dockerfile
13
Dockerfile
@ -1,4 +1,4 @@
|
|||||||
FROM alpine:3.15
|
FROM alpine:3.17
|
||||||
|
|
||||||
RUN apk --no-cache add -f \
|
RUN apk --no-cache add -f \
|
||||||
openssl \
|
openssl \
|
||||||
@ -12,7 +12,8 @@ RUN apk --no-cache add -f \
|
|||||||
oath-toolkit-oathtool \
|
oath-toolkit-oathtool \
|
||||||
tar \
|
tar \
|
||||||
libidn \
|
libidn \
|
||||||
jq
|
jq \
|
||||||
|
cronie
|
||||||
|
|
||||||
ENV LE_CONFIG_HOME /acme.sh
|
ENV LE_CONFIG_HOME /acme.sh
|
||||||
|
|
||||||
@ -25,7 +26,7 @@ COPY ./ /install_acme.sh/
|
|||||||
RUN cd /install_acme.sh && ([ -f /install_acme.sh/acme.sh ] && /install_acme.sh/acme.sh --install || curl https://get.acme.sh | sh) && rm -rf /install_acme.sh/
|
RUN cd /install_acme.sh && ([ -f /install_acme.sh/acme.sh ] && /install_acme.sh/acme.sh --install || curl https://get.acme.sh | sh) && rm -rf /install_acme.sh/
|
||||||
|
|
||||||
|
|
||||||
RUN ln -s /root/.acme.sh/acme.sh /usr/local/bin/acme.sh && crontab -l | grep acme.sh | sed 's#> /dev/null##' | crontab -
|
RUN ln -s /root/.acme.sh/acme.sh /usr/local/bin/acme.sh && crontab -l | grep acme.sh | sed 's#> /dev/null#> /proc/1/fd/1 2>/proc/1/fd/2#' | crontab -
|
||||||
|
|
||||||
RUN for verb in help \
|
RUN for verb in help \
|
||||||
version \
|
version \
|
||||||
@ -64,12 +65,10 @@ RUN for verb in help \
|
|||||||
|
|
||||||
RUN printf "%b" '#!'"/usr/bin/env sh\n \
|
RUN printf "%b" '#!'"/usr/bin/env sh\n \
|
||||||
if [ \"\$1\" = \"daemon\" ]; then \n \
|
if [ \"\$1\" = \"daemon\" ]; then \n \
|
||||||
trap \"echo stop && killall crond && exit 0\" SIGTERM SIGINT \n \
|
exec crond -n -s -m off \n \
|
||||||
crond && sleep infinity &\n \
|
|
||||||
wait \n \
|
|
||||||
else \n \
|
else \n \
|
||||||
exec -- \"\$@\"\n \
|
exec -- \"\$@\"\n \
|
||||||
fi" >/entry.sh && chmod +x /entry.sh
|
fi\n" >/entry.sh && chmod +x /entry.sh
|
||||||
|
|
||||||
VOLUME /acme.sh
|
VOLUME /acme.sh
|
||||||
|
|
||||||
|
49
README.md
49
README.md
@ -8,7 +8,7 @@
|
|||||||
[](https://github.com/acmesh-official/acme.sh/actions/workflows/Windows.yml)
|
[](https://github.com/acmesh-official/acme.sh/actions/workflows/Windows.yml)
|
||||||
[](https://github.com/acmesh-official/acme.sh/actions/workflows/Solaris.yml)
|
[](https://github.com/acmesh-official/acme.sh/actions/workflows/Solaris.yml)
|
||||||
[](https://github.com/acmesh-official/acme.sh/actions/workflows/DragonFlyBSD.yml)
|
[](https://github.com/acmesh-official/acme.sh/actions/workflows/DragonFlyBSD.yml)
|
||||||
|
[](https://github.com/acmesh-official/acme.sh/actions/workflows/Omnios.yml)
|
||||||
|
|
||||||

|

|
||||||

|

|
||||||
@ -51,14 +51,12 @@ Twitter: [@neilpangxa](https://twitter.com/neilpangxa)
|
|||||||
- [ruby-china.org](https://ruby-china.org/topics/31983)
|
- [ruby-china.org](https://ruby-china.org/topics/31983)
|
||||||
- [Proxmox](https://pve.proxmox.com/wiki/Certificate_Management)
|
- [Proxmox](https://pve.proxmox.com/wiki/Certificate_Management)
|
||||||
- [pfsense](https://github.com/pfsense/FreeBSD-ports/pull/89)
|
- [pfsense](https://github.com/pfsense/FreeBSD-ports/pull/89)
|
||||||
- [webfaction](https://community.webfaction.com/questions/19988/using-letsencrypt)
|
|
||||||
- [Loadbalancer.org](https://www.loadbalancer.org/blog/loadbalancer-org-with-lets-encrypt-quick-and-dirty)
|
- [Loadbalancer.org](https://www.loadbalancer.org/blog/loadbalancer-org-with-lets-encrypt-quick-and-dirty)
|
||||||
- [discourse.org](https://meta.discourse.org/t/setting-up-lets-encrypt/40709)
|
- [discourse.org](https://meta.discourse.org/t/setting-up-lets-encrypt/40709)
|
||||||
- [Centminmod](https://centminmod.com/letsencrypt-acmetool-https.html)
|
- [Centminmod](https://centminmod.com/letsencrypt-acmetool-https.html)
|
||||||
- [splynx](https://forum.splynx.com/t/free-ssl-cert-for-splynx-lets-encrypt/297)
|
- [splynx](https://forum.splynx.com/t/free-ssl-cert-for-splynx-lets-encrypt/297)
|
||||||
- [archlinux](https://www.archlinux.org/packages/community/any/acme.sh)
|
|
||||||
- [opnsense.org](https://github.com/opnsense/plugins/tree/master/security/acme-client/src/opnsense/scripts/OPNsense/AcmeClient)
|
- [opnsense.org](https://github.com/opnsense/plugins/tree/master/security/acme-client/src/opnsense/scripts/OPNsense/AcmeClient)
|
||||||
- [CentOS Web Panel](http://centos-webpanel.com/)
|
- [CentOS Web Panel](https://control-webpanel.com)
|
||||||
- [lnmp.org](https://lnmp.org/)
|
- [lnmp.org](https://lnmp.org/)
|
||||||
- [more...](https://github.com/acmesh-official/acme.sh/wiki/Blogs-and-tutorials)
|
- [more...](https://github.com/acmesh-official/acme.sh/wiki/Blogs-and-tutorials)
|
||||||
|
|
||||||
@ -75,20 +73,21 @@ Twitter: [@neilpangxa](https://twitter.com/neilpangxa)
|
|||||||
|7|[](https://github.com/acmesh-official/acme.sh/actions/workflows/OpenBSD.yml)|OpenBSD
|
|7|[](https://github.com/acmesh-official/acme.sh/actions/workflows/OpenBSD.yml)|OpenBSD
|
||||||
|8|[](https://github.com/acmesh-official/acme.sh/actions/workflows/NetBSD.yml)|NetBSD
|
|8|[](https://github.com/acmesh-official/acme.sh/actions/workflows/NetBSD.yml)|NetBSD
|
||||||
|9|[](https://github.com/acmesh-official/acme.sh/actions/workflows/DragonFlyBSD.yml)|DragonFlyBSD
|
|9|[](https://github.com/acmesh-official/acme.sh/actions/workflows/DragonFlyBSD.yml)|DragonFlyBSD
|
||||||
|10|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)| Debian
|
|10|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Omnios.yml)|Omnios
|
||||||
|11|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|CentOS
|
|11|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)| Debian
|
||||||
|12|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|openSUSE
|
|12|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|CentOS
|
||||||
|13|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Alpine Linux (with curl)
|
|13|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|openSUSE
|
||||||
|14|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Archlinux
|
|14|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Alpine Linux (with curl)
|
||||||
|15|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|fedora
|
|15|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Archlinux
|
||||||
|16|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Kali Linux
|
|16|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|fedora
|
||||||
|17|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Oracle Linux
|
|17|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Kali Linux
|
||||||
|18|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Mageia
|
|18|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Oracle Linux
|
||||||
|19|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Gentoo Linux
|
|19|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Mageia
|
||||||
|10|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|ClearLinux
|
|10|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Gentoo Linux
|
||||||
|11|-----| Cloud Linux https://github.com/acmesh-official/acme.sh/issues/111
|
|11|[](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|ClearLinux
|
||||||
|22|-----| OpenWRT: Tested and working. See [wiki page](https://github.com/acmesh-official/acme.sh/wiki/How-to-run-on-OpenWRT)
|
|22|-----| Cloud Linux https://github.com/acmesh-official/acme.sh/issues/111
|
||||||
|23|[](https://github.com/acmesh-official/letest#here-are-the-latest-status)| Proxmox: See Proxmox VE Wiki. Version [4.x, 5.0, 5.1](https://pve.proxmox.com/wiki/HTTPS_Certificate_Configuration_(Version_4.x,_5.0_and_5.1)#Let.27s_Encrypt_using_acme.sh), version [5.2 and up](https://pve.proxmox.com/wiki/Certificate_Management)
|
|23|-----| OpenWRT: Tested and working. See [wiki page](https://github.com/acmesh-official/acme.sh/wiki/How-to-run-on-OpenWRT)
|
||||||
|
|24|[](https://github.com/acmesh-official/letest#here-are-the-latest-status)| Proxmox: See Proxmox VE Wiki. Version [4.x, 5.0, 5.1](https://pve.proxmox.com/wiki/HTTPS_Certificate_Configuration_(Version_4.x,_5.0_and_5.1)#Let.27s_Encrypt_using_acme.sh), version [5.2 and up](https://pve.proxmox.com/wiki/Certificate_Management)
|
||||||
|
|
||||||
|
|
||||||
Check our [testing project](https://github.com/acmesh-official/acmetest):
|
Check our [testing project](https://github.com/acmesh-official/acmetest):
|
||||||
@ -361,10 +360,6 @@ Ok, it's done.
|
|||||||
|
|
||||||
# 10. Issue ECC certificates
|
# 10. Issue ECC certificates
|
||||||
|
|
||||||
`Let's Encrypt` can now issue **ECDSA** certificates.
|
|
||||||
|
|
||||||
And we support them too!
|
|
||||||
|
|
||||||
Just set the `keylength` parameter with a prefix `ec-`.
|
Just set the `keylength` parameter with a prefix `ec-`.
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
@ -385,10 +380,12 @@ Please look at the `keylength` parameter above.
|
|||||||
|
|
||||||
Valid values are:
|
Valid values are:
|
||||||
|
|
||||||
1. **ec-256 (prime256v1, "ECDSA P-256")**
|
1. **ec-256 (prime256v1, "ECDSA P-256", which is the default key type)**
|
||||||
2. **ec-384 (secp384r1, "ECDSA P-384")**
|
2. **ec-384 (secp384r1, "ECDSA P-384")**
|
||||||
3. **ec-521 (secp521r1, "ECDSA P-521", which is not supported by Let's Encrypt yet.)**
|
3. **ec-521 (secp521r1, "ECDSA P-521", which is not supported by Let's Encrypt yet.)**
|
||||||
|
4. **2048 (RSA2048)**
|
||||||
|
5. **3072 (RSA3072)**
|
||||||
|
6. **4096 (RSA4096)**
|
||||||
|
|
||||||
|
|
||||||
# 11. Issue Wildcard certificates
|
# 11. Issue Wildcard certificates
|
||||||
@ -510,10 +507,6 @@ Support this project with your organization. Your logo will show up here with a
|
|||||||
<a href="https://opencollective.com/acmesh/organization/9/website"><img src="https://opencollective.com/acmesh/organization/9/avatar.svg"></a>
|
<a href="https://opencollective.com/acmesh/organization/9/website"><img src="https://opencollective.com/acmesh/organization/9/avatar.svg"></a>
|
||||||
|
|
||||||
|
|
||||||
#### Sponsors
|
|
||||||
|
|
||||||
[](https://www.quantumca.com.cn/?__utm_source=acmesh-donation)
|
|
||||||
|
|
||||||
|
|
||||||
# 19. License & Others
|
# 19. License & Others
|
||||||
|
|
||||||
|
391
acme.sh
391
acme.sh
@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
VER=3.0.5
|
VER=3.0.8
|
||||||
|
|
||||||
PROJECT_NAME="acme.sh"
|
PROJECT_NAME="acme.sh"
|
||||||
|
|
||||||
@ -53,8 +53,8 @@ CA_SERVERS="$CA_ZEROSSL,$CA_LETSENCRYPT_V2,$CA_LETSENCRYPT_V2_TEST,$CA_BUYPASS,$
|
|||||||
|
|
||||||
DEFAULT_USER_AGENT="$PROJECT_NAME/$VER ($PROJECT)"
|
DEFAULT_USER_AGENT="$PROJECT_NAME/$VER ($PROJECT)"
|
||||||
|
|
||||||
DEFAULT_ACCOUNT_KEY_LENGTH=2048
|
DEFAULT_ACCOUNT_KEY_LENGTH=ec-256
|
||||||
DEFAULT_DOMAIN_KEY_LENGTH=2048
|
DEFAULT_DOMAIN_KEY_LENGTH=ec-256
|
||||||
|
|
||||||
DEFAULT_OPENSSL_BIN="openssl"
|
DEFAULT_OPENSSL_BIN="openssl"
|
||||||
|
|
||||||
@ -102,12 +102,12 @@ ECC_SUFFIX="${ECC_SEP}ecc"
|
|||||||
LOG_LEVEL_1=1
|
LOG_LEVEL_1=1
|
||||||
LOG_LEVEL_2=2
|
LOG_LEVEL_2=2
|
||||||
LOG_LEVEL_3=3
|
LOG_LEVEL_3=3
|
||||||
DEFAULT_LOG_LEVEL="$LOG_LEVEL_1"
|
DEFAULT_LOG_LEVEL="$LOG_LEVEL_2"
|
||||||
|
|
||||||
DEBUG_LEVEL_1=1
|
DEBUG_LEVEL_1=1
|
||||||
DEBUG_LEVEL_2=2
|
DEBUG_LEVEL_2=2
|
||||||
DEBUG_LEVEL_3=3
|
DEBUG_LEVEL_3=3
|
||||||
DEBUG_LEVEL_DEFAULT=$DEBUG_LEVEL_1
|
DEBUG_LEVEL_DEFAULT=$DEBUG_LEVEL_2
|
||||||
DEBUG_LEVEL_NONE=0
|
DEBUG_LEVEL_NONE=0
|
||||||
|
|
||||||
DOH_CLOUDFLARE=1
|
DOH_CLOUDFLARE=1
|
||||||
@ -923,8 +923,16 @@ _sed_i() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if [ "$(echo abc | egrep -o b 2>/dev/null)" = "b" ]; then
|
||||||
|
__USE_EGREP=1
|
||||||
|
else
|
||||||
|
__USE_EGREP=""
|
||||||
|
fi
|
||||||
|
|
||||||
_egrep_o() {
|
_egrep_o() {
|
||||||
if ! egrep -o "$1" 2>/dev/null; then
|
if [ "$__USE_EGREP" ]; then
|
||||||
|
egrep -o -- "$1" 2>/dev/null
|
||||||
|
else
|
||||||
sed -n 's/.*\('"$1"'\).*/\1/p'
|
sed -n 's/.*\('"$1"'\).*/\1/p'
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
@ -1553,7 +1561,7 @@ createDomainKey() {
|
|||||||
createCSR() {
|
createCSR() {
|
||||||
_info "Creating csr"
|
_info "Creating csr"
|
||||||
if [ -z "$1" ]; then
|
if [ -z "$1" ]; then
|
||||||
_usage "Usage: $PROJECT_ENTRY --create-csr --domain <domain.tld> [--domain <domain2.tld> ...]"
|
_usage "Usage: $PROJECT_ENTRY --create-csr --domain <domain.tld> [--domain <domain2.tld> ...] [--ecc]"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -1637,7 +1645,7 @@ _stat() {
|
|||||||
#keyfile
|
#keyfile
|
||||||
_isRSA() {
|
_isRSA() {
|
||||||
keyfile=$1
|
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
|
if grep "BEGIN RSA PRIVATE KEY" "$keyfile" >/dev/null 2>&1 || ${ACME_OPENSSL_BIN:-openssl} rsa -in "$keyfile" -noout -text 2>&1 | grep "^publicExponent:" 2>&1 >/dev/null; then
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
return 1
|
return 1
|
||||||
@ -1646,7 +1654,7 @@ _isRSA() {
|
|||||||
#keyfile
|
#keyfile
|
||||||
_isEcc() {
|
_isEcc() {
|
||||||
keyfile=$1
|
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
|
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:" 2>&1 >/dev/null; then
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
return 1
|
return 1
|
||||||
@ -1744,7 +1752,7 @@ _calcjwk() {
|
|||||||
_debug3 x64 "$x64"
|
_debug3 x64 "$x64"
|
||||||
|
|
||||||
xend=$(_math "$xend" + 1)
|
xend=$(_math "$xend" + 1)
|
||||||
y="$(printf "%s" "$pubtext" | cut -d : -f "$xend"-10000)"
|
y="$(printf "%s" "$pubtext" | cut -d : -f "$xend"-2048)"
|
||||||
_debug3 y "$y"
|
_debug3 y "$y"
|
||||||
|
|
||||||
y64="$(printf "%s" "$y" | tr -d : | _h2b | _base64 | _url_replace)"
|
y64="$(printf "%s" "$y" | tr -d : | _h2b | _base64 | _url_replace)"
|
||||||
@ -1787,6 +1795,10 @@ _date2time() {
|
|||||||
if date -u -j -f "%Y-%m-%d %H:%M:%S" "$(echo "$1" | tr -d "Z" | tr "T" ' ')" +"%s" 2>/dev/null; then
|
if date -u -j -f "%Y-%m-%d %H:%M:%S" "$(echo "$1" | tr -d "Z" | tr "T" ' ')" +"%s" 2>/dev/null; then
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
#Omnios
|
||||||
|
if da="$(echo "$1" | tr -d "Z" | tr "T" ' ')" perl -MTime::Piece -e 'print Time::Piece->strptime($ENV{da}, "%Y-%m-%d %H:%M:%S")->epoch, "\n";' 2>/dev/null; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
_err "Can not parse _date2time $1"
|
_err "Can not parse _date2time $1"
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
@ -1852,9 +1864,15 @@ _inithttp() {
|
|||||||
_ACME_CURL="$_ACME_CURL --cacert $CA_BUNDLE "
|
_ACME_CURL="$_ACME_CURL --cacert $CA_BUNDLE "
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if _contains "$(curl --help 2>&1)" "--globoff"; then
|
if _contains "$(curl --help 2>&1)" "--globoff" || _contains "$(curl --help curl 2>&1)" "--globoff"; then
|
||||||
_ACME_CURL="$_ACME_CURL -g "
|
_ACME_CURL="$_ACME_CURL -g "
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
#don't use --fail-with-body
|
||||||
|
##from curl 7.76: return fail on HTTP errors but keep the body
|
||||||
|
#if _contains "$(curl --help http 2>&1)" "--fail-with-body"; then
|
||||||
|
# _ACME_CURL="$_ACME_CURL --fail-with-body "
|
||||||
|
#fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "$_ACME_WGET" ] && _exists "wget"; then
|
if [ -z "$_ACME_WGET" ] && _exists "wget"; then
|
||||||
@ -1872,12 +1890,12 @@ _inithttp() {
|
|||||||
elif [ "$CA_BUNDLE" ]; then
|
elif [ "$CA_BUNDLE" ]; then
|
||||||
_ACME_WGET="$_ACME_WGET --ca-certificate=$CA_BUNDLE "
|
_ACME_WGET="$_ACME_WGET --ca-certificate=$CA_BUNDLE "
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
|
|
||||||
#from wget 1.14: do not skip body on 404 error
|
#from wget 1.14: do not skip body on 404 error
|
||||||
if [ "$_ACME_WGET" ] && _contains "$($_ACME_WGET --help 2>&1)" "--content-on-error"; then
|
if _contains "$(wget --help 2>&1)" "--content-on-error"; then
|
||||||
_ACME_WGET="$_ACME_WGET --content-on-error "
|
_ACME_WGET="$_ACME_WGET --content-on-error "
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
__HTTP_INITIALIZED=1
|
__HTTP_INITIALIZED=1
|
||||||
|
|
||||||
@ -2095,12 +2113,18 @@ _head_n() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_tail_n() {
|
_tail_n() {
|
||||||
if ! tail -n "$1" 2>/dev/null; then
|
if _is_solaris; then
|
||||||
#fix for solaris
|
#fix for solaris
|
||||||
tail -"$1"
|
tail -"$1"
|
||||||
|
else
|
||||||
|
tail -n "$1"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_tail_c() {
|
||||||
|
tail -c "$1" 2>/dev/null || tail -"$1"c
|
||||||
|
}
|
||||||
|
|
||||||
# url payload needbase64 keyfile
|
# url payload needbase64 keyfile
|
||||||
_send_signed_request() {
|
_send_signed_request() {
|
||||||
url=$1
|
url=$1
|
||||||
@ -2110,6 +2134,7 @@ _send_signed_request() {
|
|||||||
if [ -z "$keyfile" ]; then
|
if [ -z "$keyfile" ]; then
|
||||||
keyfile="$ACCOUNT_KEY_PATH"
|
keyfile="$ACCOUNT_KEY_PATH"
|
||||||
fi
|
fi
|
||||||
|
_debug "=======Begin Send Signed Request======="
|
||||||
_debug url "$url"
|
_debug url "$url"
|
||||||
_debug payload "$payload"
|
_debug payload "$payload"
|
||||||
|
|
||||||
@ -2223,6 +2248,20 @@ _send_signed_request() {
|
|||||||
_debug3 _body "$_body"
|
_debug3 _body "$_body"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
_retryafter=$(echo "$responseHeaders" | grep -i "^Retry-After *: *[0-9]\+ *" | cut -d : -f 2 | tr -d ' ' | tr -d '\r')
|
||||||
|
if [ "$code" = '503' ]; then
|
||||||
|
_sleep_overload_retry_sec=$_retryafter
|
||||||
|
if [ -z "$_sleep_overload_retry_sec" ]; then
|
||||||
|
_sleep_overload_retry_sec=5
|
||||||
|
fi
|
||||||
|
if [ $_sleep_overload_retry_sec -le 600 ]; then
|
||||||
|
_info "It seems the CA server is currently overloaded, let's wait and retry. Sleeping $_sleep_overload_retry_sec seconds."
|
||||||
|
_sleep $_sleep_overload_retry_sec
|
||||||
|
continue
|
||||||
|
else
|
||||||
|
_info "The retryafter=$_retryafter is too large > 600, not retry anymore."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
if _contains "$_body" "JWS has invalid anti-replay nonce" || _contains "$_body" "JWS has an invalid anti-replay nonce"; then
|
if _contains "$_body" "JWS has invalid anti-replay nonce" || _contains "$_body" "JWS has an invalid anti-replay nonce"; then
|
||||||
_info "It seems the CA server is busy now, let's wait and retry. Sleeping $_sleep_retry_sec seconds."
|
_info "It seems the CA server is busy now, let's wait and retry. Sleeping $_sleep_retry_sec seconds."
|
||||||
_CACHED_NONCE=""
|
_CACHED_NONCE=""
|
||||||
@ -2257,12 +2296,18 @@ _setopt() {
|
|||||||
if [ ! -f "$__conf" ]; then
|
if [ ! -f "$__conf" ]; then
|
||||||
touch "$__conf"
|
touch "$__conf"
|
||||||
fi
|
fi
|
||||||
|
if [ -n "$(_tail_c 1 <"$__conf")" ]; then
|
||||||
|
echo >>"$__conf"
|
||||||
|
fi
|
||||||
|
|
||||||
if grep -n "^$__opt$__sep" "$__conf" >/dev/null; then
|
if grep -n "^$__opt$__sep" "$__conf" >/dev/null; then
|
||||||
_debug3 OK
|
_debug3 OK
|
||||||
if _contains "$__val" "&"; then
|
if _contains "$__val" "&"; then
|
||||||
__val="$(echo "$__val" | sed 's/&/\\&/g')"
|
__val="$(echo "$__val" | sed 's/&/\\&/g')"
|
||||||
fi
|
fi
|
||||||
|
if _contains "$__val" "|"; then
|
||||||
|
__val="$(echo "$__val" | sed 's/|/\\|/g')"
|
||||||
|
fi
|
||||||
text="$(cat "$__conf")"
|
text="$(cat "$__conf")"
|
||||||
printf -- "%s\n" "$text" | sed "s|^$__opt$__sep.*$|$__opt$__sep$__val$__end|" >"$__conf"
|
printf -- "%s\n" "$text" | sed "s|^$__opt$__sep.*$|$__opt$__sep$__val$__end|" >"$__conf"
|
||||||
|
|
||||||
@ -2270,6 +2315,9 @@ _setopt() {
|
|||||||
if _contains "$__val" "&"; then
|
if _contains "$__val" "&"; then
|
||||||
__val="$(echo "$__val" | sed 's/&/\\&/g')"
|
__val="$(echo "$__val" | sed 's/&/\\&/g')"
|
||||||
fi
|
fi
|
||||||
|
if _contains "$__val" "|"; then
|
||||||
|
__val="$(echo "$__val" | sed 's/|/\\|/g')"
|
||||||
|
fi
|
||||||
text="$(cat "$__conf")"
|
text="$(cat "$__conf")"
|
||||||
printf -- "%s\n" "$text" | sed "s|^#$__opt$__sep.*$|$__opt$__sep$__val$__end|" >"$__conf"
|
printf -- "%s\n" "$text" | sed "s|^#$__opt$__sep.*$|$__opt$__sep$__val$__end|" >"$__conf"
|
||||||
|
|
||||||
@ -2343,6 +2391,26 @@ _readdomainconf() {
|
|||||||
_read_conf "$DOMAIN_CONF" "$1"
|
_read_conf "$DOMAIN_CONF" "$1"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#_migratedomainconf oldkey newkey base64encode
|
||||||
|
_migratedomainconf() {
|
||||||
|
_old_key="$1"
|
||||||
|
_new_key="$2"
|
||||||
|
_b64encode="$3"
|
||||||
|
_value=$(_readdomainconf "$_old_key")
|
||||||
|
if [ -z "$_value" ]; then
|
||||||
|
return 1 # oldkey is not found
|
||||||
|
fi
|
||||||
|
_savedomainconf "$_new_key" "$_value" "$_b64encode"
|
||||||
|
_cleardomainconf "$_old_key"
|
||||||
|
_debug "Domain config $_old_key has been migrated to $_new_key"
|
||||||
|
}
|
||||||
|
|
||||||
|
#_migratedeployconf oldkey newkey base64encode
|
||||||
|
_migratedeployconf() {
|
||||||
|
_migratedomainconf "$1" "SAVED_$2" "$3" ||
|
||||||
|
_migratedomainconf "SAVED_$1" "SAVED_$2" "$3" # try only when oldkey itself is not found
|
||||||
|
}
|
||||||
|
|
||||||
#key value base64encode
|
#key value base64encode
|
||||||
_savedeployconf() {
|
_savedeployconf() {
|
||||||
_savedomainconf "SAVED_$1" "$2" "$3"
|
_savedomainconf "SAVED_$1" "$2" "$3"
|
||||||
@ -2357,12 +2425,14 @@ _getdeployconf() {
|
|||||||
if [ "$_rac_value" ]; then
|
if [ "$_rac_value" ]; then
|
||||||
if _startswith "$_rac_value" '"' && _endswith "$_rac_value" '"'; then
|
if _startswith "$_rac_value" '"' && _endswith "$_rac_value" '"'; then
|
||||||
_debug2 "trim quotation marks"
|
_debug2 "trim quotation marks"
|
||||||
eval "export $_rac_key=$_rac_value"
|
eval $_rac_key=$_rac_value
|
||||||
|
export $_rac_key
|
||||||
fi
|
fi
|
||||||
return 0 # do nothing
|
return 0 # do nothing
|
||||||
fi
|
fi
|
||||||
_saved=$(_readdomainconf "SAVED_$_rac_key")
|
_saved="$(_readdomainconf "SAVED_$_rac_key")"
|
||||||
eval "export $_rac_key=\"\$_saved\""
|
eval $_rac_key=\$_saved
|
||||||
|
export $_rac_key
|
||||||
}
|
}
|
||||||
|
|
||||||
#_saveaccountconf key value base64encode
|
#_saveaccountconf key value base64encode
|
||||||
@ -2429,10 +2499,10 @@ _startserver() {
|
|||||||
_debug Le_Listen_V6 "$Le_Listen_V6"
|
_debug Le_Listen_V6 "$Le_Listen_V6"
|
||||||
|
|
||||||
_NC="socat"
|
_NC="socat"
|
||||||
if [ "$Le_Listen_V4" ]; then
|
if [ "$Le_Listen_V6" ]; then
|
||||||
_NC="$_NC -4"
|
|
||||||
elif [ "$Le_Listen_V6" ]; then
|
|
||||||
_NC="$_NC -6"
|
_NC="$_NC -6"
|
||||||
|
else
|
||||||
|
_NC="$_NC -4"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$DEBUG" ] && [ "$DEBUG" -gt "1" ]; then
|
if [ "$DEBUG" ] && [ "$DEBUG" -gt "1" ]; then
|
||||||
@ -2449,22 +2519,34 @@ _startserver() {
|
|||||||
_content_len="$(printf "%s" "$content" | wc -c)"
|
_content_len="$(printf "%s" "$content" | wc -c)"
|
||||||
_debug _content_len "$_content_len"
|
_debug _content_len "$_content_len"
|
||||||
_debug "_NC" "$_NC $SOCAT_OPTIONS"
|
_debug "_NC" "$_NC $SOCAT_OPTIONS"
|
||||||
|
export _SOCAT_ERR="$(_mktemp)"
|
||||||
$_NC $SOCAT_OPTIONS SYSTEM:"sleep 1; \
|
$_NC $SOCAT_OPTIONS SYSTEM:"sleep 1; \
|
||||||
echo 'HTTP/1.0 200 OK'; \
|
echo 'HTTP/1.0 200 OK'; \
|
||||||
echo 'Content-Length\: $_content_len'; \
|
echo 'Content-Length\: $_content_len'; \
|
||||||
echo ''; \
|
echo ''; \
|
||||||
printf '%s' '$content';" &
|
printf '%s' '$content';" 2>"$_SOCAT_ERR" &
|
||||||
serverproc="$!"
|
serverproc="$!"
|
||||||
|
if [ -f "$_SOCAT_ERR" ]; then
|
||||||
|
if grep "Permission denied" "$_SOCAT_ERR" >/dev/null; then
|
||||||
|
_err "socat: $(cat $_SOCAT_ERR)"
|
||||||
|
_err "Can not listen for user: $(whoami)"
|
||||||
|
_err "Maybe try with root again?"
|
||||||
|
rm -f "$_SOCAT_ERR"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
_stopserver() {
|
_stopserver() {
|
||||||
pid="$1"
|
pid="$1"
|
||||||
_debug "pid" "$pid"
|
_debug "pid" "$pid"
|
||||||
if [ -z "$pid" ]; then
|
if [ -z "$pid" ]; then
|
||||||
|
rm -f "$_SOCAT_ERR"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
kill $pid
|
kill $pid
|
||||||
|
rm -f "$_SOCAT_ERR"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2826,12 +2908,14 @@ _initpath() {
|
|||||||
|
|
||||||
if _isEccKey "$_ilength"; then
|
if _isEccKey "$_ilength"; then
|
||||||
DOMAIN_PATH="$domainhomeecc"
|
DOMAIN_PATH="$domainhomeecc"
|
||||||
else
|
elif [ -z "$__SELECTED_RSA_KEY" ]; then
|
||||||
if [ ! -d "$domainhome" ] && [ -d "$domainhomeecc" ]; then
|
if [ ! -d "$domainhome" ] && [ -d "$domainhomeecc" ]; then
|
||||||
_info "The domain '$domain' seems to have a ECC cert already, please add '$(__red "--ecc")' parameter if you want to use that cert."
|
_info "The domain '$domain' seems to have a ECC cert already, lets use ecc cert."
|
||||||
|
DOMAIN_PATH="$domainhomeecc"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
_debug DOMAIN_PATH "$DOMAIN_PATH"
|
_debug DOMAIN_PATH "$DOMAIN_PATH"
|
||||||
|
export DOMAIN_PATH
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "$DOMAIN_BACKUP_PATH" ]; then
|
if [ -z "$DOMAIN_BACKUP_PATH" ]; then
|
||||||
@ -2883,22 +2967,6 @@ _initpath() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_exec() {
|
|
||||||
if [ -z "$_EXEC_TEMP_ERR" ]; then
|
|
||||||
_EXEC_TEMP_ERR="$(_mktemp)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$_EXEC_TEMP_ERR" ]; then
|
|
||||||
eval "$@ 2>>$_EXEC_TEMP_ERR"
|
|
||||||
else
|
|
||||||
eval "$@"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
_exec_err() {
|
|
||||||
[ "$_EXEC_TEMP_ERR" ] && _err "$(cat "$_EXEC_TEMP_ERR")" && echo "" >"$_EXEC_TEMP_ERR"
|
|
||||||
}
|
|
||||||
|
|
||||||
_apachePath() {
|
_apachePath() {
|
||||||
_APACHECTL="apachectl"
|
_APACHECTL="apachectl"
|
||||||
if ! _exists apachectl; then
|
if ! _exists apachectl; then
|
||||||
@ -2911,8 +2979,7 @@ _apachePath() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! _exec $_APACHECTL -V >/dev/null; then
|
if ! $_APACHECTL -V >/dev/null; then
|
||||||
_exec_err
|
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -2964,8 +3031,7 @@ _restoreApache() {
|
|||||||
|
|
||||||
cat "$APACHE_CONF_BACKUP_DIR/$httpdconfname" >"$httpdconf"
|
cat "$APACHE_CONF_BACKUP_DIR/$httpdconfname" >"$httpdconf"
|
||||||
_debug "Restored: $httpdconf."
|
_debug "Restored: $httpdconf."
|
||||||
if ! _exec $_APACHECTL -t; then
|
if ! $_APACHECTL -t; then
|
||||||
_exec_err
|
|
||||||
_err "Sorry, restore apache config error, please contact me."
|
_err "Sorry, restore apache config error, please contact me."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
@ -2983,8 +3049,7 @@ _setApache() {
|
|||||||
#test the conf first
|
#test the conf first
|
||||||
_info "Checking if there is an error in the apache config file before starting."
|
_info "Checking if there is an error in the apache config file before starting."
|
||||||
|
|
||||||
if ! _exec "$_APACHECTL" -t >/dev/null; then
|
if ! $_APACHECTL -t >/dev/null; then
|
||||||
_exec_err
|
|
||||||
_err "The apache config file has error, please fix it first, then try again."
|
_err "The apache config file has error, please fix it first, then try again."
|
||||||
_err "Don't worry, there is nothing changed to your system."
|
_err "Don't worry, there is nothing changed to your system."
|
||||||
return 1
|
return 1
|
||||||
@ -3045,8 +3110,7 @@ Allow from all
|
|||||||
chmod 755 "$ACME_DIR"
|
chmod 755 "$ACME_DIR"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! _exec "$_APACHECTL" graceful; then
|
if ! $_APACHECTL graceful; then
|
||||||
_exec_err
|
|
||||||
_err "$_APACHECTL graceful error, please contact me."
|
_err "$_APACHECTL graceful error, please contact me."
|
||||||
_restoreApache
|
_restoreApache
|
||||||
return 1
|
return 1
|
||||||
@ -3077,7 +3141,7 @@ _setNginx() {
|
|||||||
_err "nginx command is not found."
|
_err "nginx command is not found."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
NGINX_CONF="$(nginx -V 2>&1 | _egrep_o "--conf-path=[^ ]* " | tr -d " ")"
|
NGINX_CONF="$(nginx -V 2>&1 | _egrep_o "\-\-conf-path=[^ ]* " | tr -d " ")"
|
||||||
_debug NGINX_CONF "$NGINX_CONF"
|
_debug NGINX_CONF "$NGINX_CONF"
|
||||||
NGINX_CONF="$(echo "$NGINX_CONF" | cut -d = -f 2)"
|
NGINX_CONF="$(echo "$NGINX_CONF" | cut -d = -f 2)"
|
||||||
_debug NGINX_CONF "$NGINX_CONF"
|
_debug NGINX_CONF "$NGINX_CONF"
|
||||||
@ -3131,8 +3195,8 @@ _setNginx() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
_info "Check the nginx conf before setting up."
|
_info "Check the nginx conf before setting up."
|
||||||
if ! _exec "nginx -t" >/dev/null; then
|
if ! nginx -t >/dev/null 2>&1; then
|
||||||
_exec_err
|
_err "It seems that nginx conf is not correct, cannot continue."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -3159,16 +3223,14 @@ location ~ \"^/\.well-known/acme-challenge/([-_a-zA-Z0-9]+)\$\" {
|
|||||||
fi
|
fi
|
||||||
_debug3 "Modified config:$(cat $FOUND_REAL_NGINX_CONF)"
|
_debug3 "Modified config:$(cat $FOUND_REAL_NGINX_CONF)"
|
||||||
_info "nginx conf is done, let's check it again."
|
_info "nginx conf is done, let's check it again."
|
||||||
if ! _exec "nginx -t" >/dev/null; then
|
if ! nginx -t >/dev/null 2>&1; then
|
||||||
_exec_err
|
|
||||||
_err "It seems that nginx conf was broken, let's restore."
|
_err "It seems that nginx conf was broken, let's restore."
|
||||||
cat "$_backup_conf" >"$FOUND_REAL_NGINX_CONF"
|
cat "$_backup_conf" >"$FOUND_REAL_NGINX_CONF"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_info "Reload nginx"
|
_info "Reload nginx"
|
||||||
if ! _exec "nginx -s reload" >/dev/null; then
|
if ! nginx -s reload >/dev/null 2>&1; then
|
||||||
_exec_err
|
|
||||||
_err "It seems that nginx reload error, let's restore."
|
_err "It seems that nginx reload error, let's restore."
|
||||||
cat "$_backup_conf" >"$FOUND_REAL_NGINX_CONF"
|
cat "$_backup_conf" >"$FOUND_REAL_NGINX_CONF"
|
||||||
return 1
|
return 1
|
||||||
@ -3293,8 +3355,7 @@ _restoreNginx() {
|
|||||||
done
|
done
|
||||||
|
|
||||||
_info "Reload nginx"
|
_info "Reload nginx"
|
||||||
if ! _exec "nginx -s reload" >/dev/null; then
|
if ! nginx -s reload >/dev/null; then
|
||||||
_exec_err
|
|
||||||
_err "It seems that nginx reload error, please report bug."
|
_err "It seems that nginx reload error, please report bug."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
@ -3986,7 +4047,7 @@ _ns_purge_cf() {
|
|||||||
|
|
||||||
#checks if cf server is available
|
#checks if cf server is available
|
||||||
_ns_is_available_cf() {
|
_ns_is_available_cf() {
|
||||||
if _get "https://cloudflare-dns.com" "" 1 >/dev/null 2>&1; then
|
if _get "https://cloudflare-dns.com" "" 10 >/dev/null; then
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
return 1
|
return 1
|
||||||
@ -3994,7 +4055,7 @@ _ns_is_available_cf() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_ns_is_available_google() {
|
_ns_is_available_google() {
|
||||||
if _get "https://dns.google" "" 1 >/dev/null 2>&1; then
|
if _get "https://dns.google" "" 10 >/dev/null; then
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
return 1
|
return 1
|
||||||
@ -4010,7 +4071,7 @@ _ns_lookup_google() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_ns_is_available_ali() {
|
_ns_is_available_ali() {
|
||||||
if _get "https://dns.alidns.com" "" 1 >/dev/null 2>&1; then
|
if _get "https://dns.alidns.com" "" 10 >/dev/null; then
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
return 1
|
return 1
|
||||||
@ -4026,7 +4087,7 @@ _ns_lookup_ali() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_ns_is_available_dp() {
|
_ns_is_available_dp() {
|
||||||
if _get "https://doh.pub" "" 1 >/dev/null 2>&1; then
|
if _get "https://doh.pub" "" 10 >/dev/null; then
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
return 1
|
return 1
|
||||||
@ -4041,8 +4102,7 @@ _ns_lookup_dp() {
|
|||||||
_ns_lookup_impl "$_cf_ep" "$_cf_ld" "$_cf_ld_type"
|
_ns_lookup_impl "$_cf_ep" "$_cf_ld" "$_cf_ld_type"
|
||||||
}
|
}
|
||||||
|
|
||||||
#domain, type
|
_ns_select_doh() {
|
||||||
_ns_lookup() {
|
|
||||||
if [ -z "$DOH_USE" ]; then
|
if [ -z "$DOH_USE" ]; then
|
||||||
_debug "Detect dns server first."
|
_debug "Detect dns server first."
|
||||||
if _ns_is_available_cf; then
|
if _ns_is_available_cf; then
|
||||||
@ -4061,7 +4121,11 @@ _ns_lookup() {
|
|||||||
_err "No doh"
|
_err "No doh"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#domain, type
|
||||||
|
_ns_lookup() {
|
||||||
|
_ns_select_doh
|
||||||
if [ "$DOH_USE" = "$DOH_CLOUDFLARE" ] || [ -z "$DOH_USE" ]; then
|
if [ "$DOH_USE" = "$DOH_CLOUDFLARE" ] || [ -z "$DOH_USE" ]; then
|
||||||
_ns_lookup_cf "$@"
|
_ns_lookup_cf "$@"
|
||||||
elif [ "$DOH_USE" = "$DOH_GOOGLE" ]; then
|
elif [ "$DOH_USE" = "$DOH_GOOGLE" ]; then
|
||||||
@ -4084,6 +4148,7 @@ __check_txt() {
|
|||||||
_debug "_c_txtdomain" "$_c_txtdomain"
|
_debug "_c_txtdomain" "$_c_txtdomain"
|
||||||
_debug "_c_aliasdomain" "$_c_aliasdomain"
|
_debug "_c_aliasdomain" "$_c_aliasdomain"
|
||||||
_debug "_c_txt" "$_c_txt"
|
_debug "_c_txt" "$_c_txt"
|
||||||
|
_ns_select_doh
|
||||||
_answers="$(_ns_lookup "$_c_aliasdomain" TXT)"
|
_answers="$(_ns_lookup "$_c_aliasdomain" TXT)"
|
||||||
_contains "$_answers" "$_c_txt"
|
_contains "$_answers" "$_c_txt"
|
||||||
|
|
||||||
@ -4414,6 +4479,7 @@ issue() {
|
|||||||
_debug "_saved_account_key_hash is not changed, skip register account."
|
_debug "_saved_account_key_hash is not changed, skip register account."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
export Le_Next_Domain_Key="$CERT_KEY_PATH.next"
|
||||||
if [ -f "$CSR_PATH" ] && [ ! -f "$CERT_KEY_PATH" ]; then
|
if [ -f "$CSR_PATH" ] && [ ! -f "$CERT_KEY_PATH" ]; then
|
||||||
_info "Signing from existing CSR."
|
_info "Signing from existing CSR."
|
||||||
else
|
else
|
||||||
@ -4426,6 +4492,11 @@ issue() {
|
|||||||
fi
|
fi
|
||||||
_debug "Read key length:$_key"
|
_debug "Read key length:$_key"
|
||||||
if [ ! -f "$CERT_KEY_PATH" ] || [ "$_key_length" != "$_key" ] || [ "$Le_ForceNewDomainKey" = "1" ]; then
|
if [ ! -f "$CERT_KEY_PATH" ] || [ "$_key_length" != "$_key" ] || [ "$Le_ForceNewDomainKey" = "1" ]; then
|
||||||
|
if [ "$Le_ForceNewDomainKey" = "1" ] && [ -f "$Le_Next_Domain_Key" ]; then
|
||||||
|
_info "Using pre generated key: $Le_Next_Domain_Key"
|
||||||
|
cat "$Le_Next_Domain_Key" >"$CERT_KEY_PATH"
|
||||||
|
echo "" >"$Le_Next_Domain_Key"
|
||||||
|
else
|
||||||
if ! createDomainKey "$_main_domain" "$_key_length"; then
|
if ! createDomainKey "$_main_domain" "$_key_length"; then
|
||||||
_err "Create domain key error."
|
_err "Create domain key error."
|
||||||
_clearup
|
_clearup
|
||||||
@ -4433,7 +4504,18 @@ issue() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
|
if [ "$Le_ForceNewDomainKey" ]; then
|
||||||
|
_info "Generate next pre-generate key."
|
||||||
|
if [ ! -e "$Le_Next_Domain_Key" ]; then
|
||||||
|
touch "$Le_Next_Domain_Key"
|
||||||
|
chmod 600 "$Le_Next_Domain_Key"
|
||||||
|
fi
|
||||||
|
if ! _createkey "$_key_length" "$Le_Next_Domain_Key"; then
|
||||||
|
_err "Can not pre generate domain key"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
if ! _createcsr "$_main_domain" "$_alt_domains" "$CERT_KEY_PATH" "$CSR_PATH" "$DOMAIN_SSL_CONF"; then
|
if ! _createcsr "$_main_domain" "$_alt_domains" "$CERT_KEY_PATH" "$CSR_PATH" "$DOMAIN_SSL_CONF"; then
|
||||||
_err "Create CSR error."
|
_err "Create CSR error."
|
||||||
_clearup
|
_clearup
|
||||||
@ -4446,7 +4528,7 @@ issue() {
|
|||||||
|
|
||||||
vlist="$Le_Vlist"
|
vlist="$Le_Vlist"
|
||||||
_cleardomainconf "Le_Vlist"
|
_cleardomainconf "Le_Vlist"
|
||||||
_info "Getting domain auth token for each domain"
|
_debug "Getting domain auth token for each domain"
|
||||||
sep='#'
|
sep='#'
|
||||||
dvsep=','
|
dvsep=','
|
||||||
if [ -z "$vlist" ]; then
|
if [ -z "$vlist" ]; then
|
||||||
@ -4502,12 +4584,22 @@ issue() {
|
|||||||
if [ "$_notAfter" ]; then
|
if [ "$_notAfter" ]; then
|
||||||
_newOrderObj="$_newOrderObj,\"notAfter\": \"$_notAfter\""
|
_newOrderObj="$_newOrderObj,\"notAfter\": \"$_notAfter\""
|
||||||
fi
|
fi
|
||||||
|
_debug "STEP 1, Ordering a Certificate"
|
||||||
if ! _send_signed_request "$ACME_NEW_ORDER" "$_newOrderObj}"; then
|
if ! _send_signed_request "$ACME_NEW_ORDER" "$_newOrderObj}"; then
|
||||||
_err "Create new order error."
|
_err "Create new order error."
|
||||||
_clearup
|
_clearup
|
||||||
_on_issue_err "$_post_hook"
|
_on_issue_err "$_post_hook"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
if _contains "$response" "invalid"; then
|
||||||
|
if echo "$response" | _normalizeJson | grep '"status":"invalid"' >/dev/null 2>&1; then
|
||||||
|
_err "Create new order with invalid status."
|
||||||
|
_err "$response"
|
||||||
|
_clearup
|
||||||
|
_on_issue_err "$_post_hook"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
Le_LinkOrder="$(echo "$responseHeaders" | grep -i '^Location.*$' | _tail_n 1 | tr -d "\r\n " | cut -d ":" -f 2-)"
|
Le_LinkOrder="$(echo "$responseHeaders" | grep -i '^Location.*$' | _tail_n 1 | tr -d "\r\n " | cut -d ":" -f 2-)"
|
||||||
_debug Le_LinkOrder "$Le_LinkOrder"
|
_debug Le_LinkOrder "$Le_LinkOrder"
|
||||||
@ -4532,6 +4624,7 @@ issue() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
_debug "STEP 2, Get the authorizations of each domain"
|
||||||
#domain and authz map
|
#domain and authz map
|
||||||
_authorizations_map=""
|
_authorizations_map=""
|
||||||
for _authz_url in $(echo "$_authorizations_seg" | tr ',' ' '); do
|
for _authz_url in $(echo "$_authorizations_seg" | tr ',' ' '); do
|
||||||
@ -4540,6 +4633,7 @@ issue() {
|
|||||||
_err "get to authz error."
|
_err "get to authz error."
|
||||||
_err "_authorizations_seg" "$_authorizations_seg"
|
_err "_authorizations_seg" "$_authorizations_seg"
|
||||||
_err "_authz_url" "$_authz_url"
|
_err "_authz_url" "$_authz_url"
|
||||||
|
_err "$response"
|
||||||
_clearup
|
_clearup
|
||||||
_on_issue_err "$_post_hook"
|
_on_issue_err "$_post_hook"
|
||||||
return 1
|
return 1
|
||||||
@ -4547,14 +4641,23 @@ issue() {
|
|||||||
|
|
||||||
response="$(echo "$response" | _normalizeJson)"
|
response="$(echo "$response" | _normalizeJson)"
|
||||||
_debug2 response "$response"
|
_debug2 response "$response"
|
||||||
|
if echo "$response" | grep '"status":"invalid"' >/dev/null 2>&1; then
|
||||||
|
_err "get authz objec with invalid status, please try again later."
|
||||||
|
_err "_authorizations_seg" "$_authorizations_seg"
|
||||||
|
_err "$response"
|
||||||
|
_clearup
|
||||||
|
_on_issue_err "$_post_hook"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
_d="$(echo "$response" | _egrep_o '"value" *: *"[^"]*"' | cut -d : -f 2- | tr -d ' "')"
|
_d="$(echo "$response" | _egrep_o '"value" *: *"[^"]*"' | cut -d : -f 2- | tr -d ' "')"
|
||||||
if _contains "$response" "\"wildcard\" *: *true"; then
|
if _contains "$response" "\"wildcard\" *: *true"; then
|
||||||
_d="*.$_d"
|
_d="*.$_d"
|
||||||
fi
|
fi
|
||||||
_debug2 _d "$_d"
|
_debug2 _d "$_d"
|
||||||
_authorizations_map="$_d,$response
|
_authorizations_map="$_d,$response#$_authz_url
|
||||||
$_authorizations_map"
|
$_authorizations_map"
|
||||||
done
|
done
|
||||||
|
|
||||||
_debug2 _authorizations_map "$_authorizations_map"
|
_debug2 _authorizations_map "$_authorizations_map"
|
||||||
|
|
||||||
_index=0
|
_index=0
|
||||||
@ -4606,24 +4709,24 @@ $_authorizations_map"
|
|||||||
_on_issue_err "$_post_hook"
|
_on_issue_err "$_post_hook"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
_authz_url="$(echo "$_candidates" | sed "s/$_idn_d,//" | _egrep_o "#.*" | sed "s/^#//")"
|
||||||
|
_debug _authz_url "$_authz_url"
|
||||||
if [ -z "$thumbprint" ]; then
|
if [ -z "$thumbprint" ]; then
|
||||||
thumbprint="$(__calc_account_thumbprint)"
|
thumbprint="$(__calc_account_thumbprint)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
entry="$(echo "$response" | _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*')"
|
|
||||||
_debug entry "$entry"
|
|
||||||
keyauthorization=""
|
keyauthorization=""
|
||||||
if [ -z "$entry" ]; then
|
|
||||||
if ! _startswith "$d" '*.'; then
|
|
||||||
_debug "Not a wildcard domain, lets check whether the validation is already valid."
|
|
||||||
if echo "$response" | grep '"status":"valid"' >/dev/null 2>&1; then
|
if echo "$response" | grep '"status":"valid"' >/dev/null 2>&1; then
|
||||||
_debug "$d is already valid."
|
_debug "$d is already valid."
|
||||||
keyauthorization="$STATE_VERIFIED"
|
keyauthorization="$STATE_VERIFIED"
|
||||||
_debug keyauthorization "$keyauthorization"
|
_debug keyauthorization "$keyauthorization"
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
if [ -z "$keyauthorization" ]; then
|
entry="$(echo "$response" | _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*')"
|
||||||
|
_debug entry "$entry"
|
||||||
|
|
||||||
|
if [ -z "$keyauthorization" -a -z "$entry" ]; then
|
||||||
_err "Error, can not get domain token entry $d for $vtype"
|
_err "Error, can not get domain token entry $d for $vtype"
|
||||||
_supported_vtypes="$(echo "$response" | _egrep_o "\"challenges\":\[[^]]*]" | tr '{' "\n" | grep type | cut -d '"' -f 4 | tr "\n" ' ')"
|
_supported_vtypes="$(echo "$response" | _egrep_o "\"challenges\":\[[^]]*]" | tr '{' "\n" | grep type | cut -d '"' -f 4 | tr "\n" ' ')"
|
||||||
if [ "$_supported_vtypes" ]; then
|
if [ "$_supported_vtypes" ]; then
|
||||||
@ -4633,7 +4736,6 @@ $_authorizations_map"
|
|||||||
_on_issue_err "$_post_hook"
|
_on_issue_err "$_post_hook"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$keyauthorization" ]; then
|
if [ -z "$keyauthorization" ]; then
|
||||||
token="$(echo "$entry" | _egrep_o '"token":"[^"]*' | cut -d : -f 2 | tr -d '"')"
|
token="$(echo "$entry" | _egrep_o '"token":"[^"]*' | cut -d : -f 2 | tr -d '"')"
|
||||||
@ -4658,15 +4760,9 @@ $_authorizations_map"
|
|||||||
fi
|
fi
|
||||||
keyauthorization="$token.$thumbprint"
|
keyauthorization="$token.$thumbprint"
|
||||||
_debug keyauthorization "$keyauthorization"
|
_debug keyauthorization "$keyauthorization"
|
||||||
|
|
||||||
if printf "%s" "$response" | grep '"status":"valid"' >/dev/null 2>&1; then
|
|
||||||
_debug "$d is already verified."
|
|
||||||
keyauthorization="$STATE_VERIFIED"
|
|
||||||
_debug keyauthorization "$keyauthorization"
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
dvlist="$d$sep$keyauthorization$sep$uri$sep$vtype$sep$_currentRoot"
|
dvlist="$d$sep$keyauthorization$sep$uri$sep$vtype$sep$_currentRoot$sep$_authz_url"
|
||||||
_debug dvlist "$dvlist"
|
_debug dvlist "$dvlist"
|
||||||
|
|
||||||
vlist="$vlist$dvlist$dvsep"
|
vlist="$vlist$dvlist$dvsep"
|
||||||
@ -4683,6 +4779,7 @@ $_authorizations_map"
|
|||||||
keyauthorization=$(echo "$ventry" | cut -d "$sep" -f 2)
|
keyauthorization=$(echo "$ventry" | cut -d "$sep" -f 2)
|
||||||
vtype=$(echo "$ventry" | cut -d "$sep" -f 4)
|
vtype=$(echo "$ventry" | cut -d "$sep" -f 4)
|
||||||
_currentRoot=$(echo "$ventry" | cut -d "$sep" -f 5)
|
_currentRoot=$(echo "$ventry" | cut -d "$sep" -f 5)
|
||||||
|
_authz_url=$(echo "$ventry" | cut -d "$sep" -f 6)
|
||||||
_debug d "$d"
|
_debug d "$d"
|
||||||
if [ "$keyauthorization" = "$STATE_VERIFIED" ]; then
|
if [ "$keyauthorization" = "$STATE_VERIFIED" ]; then
|
||||||
_debug "$d is already verified, skip $vtype."
|
_debug "$d is already verified, skip $vtype."
|
||||||
@ -4808,7 +4905,7 @@ $_authorizations_map"
|
|||||||
uri=$(echo "$ventry" | cut -d "$sep" -f 3)
|
uri=$(echo "$ventry" | cut -d "$sep" -f 3)
|
||||||
vtype=$(echo "$ventry" | cut -d "$sep" -f 4)
|
vtype=$(echo "$ventry" | cut -d "$sep" -f 4)
|
||||||
_currentRoot=$(echo "$ventry" | cut -d "$sep" -f 5)
|
_currentRoot=$(echo "$ventry" | cut -d "$sep" -f 5)
|
||||||
|
_authz_url=$(echo "$ventry" | cut -d "$sep" -f 6)
|
||||||
if [ "$keyauthorization" = "$STATE_VERIFIED" ]; then
|
if [ "$keyauthorization" = "$STATE_VERIFIED" ]; then
|
||||||
_info "$d is already verified, skip $vtype."
|
_info "$d is already verified, skip $vtype."
|
||||||
continue
|
continue
|
||||||
@ -4818,6 +4915,7 @@ $_authorizations_map"
|
|||||||
_debug "d" "$d"
|
_debug "d" "$d"
|
||||||
_debug "keyauthorization" "$keyauthorization"
|
_debug "keyauthorization" "$keyauthorization"
|
||||||
_debug "uri" "$uri"
|
_debug "uri" "$uri"
|
||||||
|
_debug "_authz_url" "$_authz_url"
|
||||||
removelevel=""
|
removelevel=""
|
||||||
token="$(printf "%s" "$keyauthorization" | cut -d '.' -f 1)"
|
token="$(printf "%s" "$keyauthorization" | cut -d '.' -f 1)"
|
||||||
|
|
||||||
@ -4887,18 +4985,6 @@ $_authorizations_map"
|
|||||||
if ! chmod a+r "$wellknown_path/$token"; then
|
if ! chmod a+r "$wellknown_path/$token"; then
|
||||||
_debug "chmod failed, but we just continue."
|
_debug "chmod failed, but we just continue."
|
||||||
fi
|
fi
|
||||||
if [ ! "$usingApache" ]; then
|
|
||||||
if webroot_owner=$(_stat "$_currentRoot"); then
|
|
||||||
_debug "Changing owner/group of .well-known to $webroot_owner"
|
|
||||||
if ! _exec "chown -R \"$webroot_owner\" \"$_currentRoot/.well-known\""; then
|
|
||||||
_debug "$(cat "$_EXEC_TEMP_ERR")"
|
|
||||||
_exec_err >/dev/null 2>&1
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
_debug "not changing owner/group of webroot"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
fi
|
fi
|
||||||
elif [ "$vtype" = "$VTYPE_ALPN" ]; then
|
elif [ "$vtype" = "$VTYPE_ALPN" ]; then
|
||||||
acmevalidationv1="$(printf "%s" "$keyauthorization" | _digest "sha256" "hex")"
|
acmevalidationv1="$(printf "%s" "$keyauthorization" | _digest "sha256" "hex")"
|
||||||
@ -4937,6 +5023,7 @@ $_authorizations_map"
|
|||||||
MAX_RETRY_TIMES=30
|
MAX_RETRY_TIMES=30
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
_debug "Lets check the status of the authz"
|
||||||
while true; do
|
while true; do
|
||||||
waittimes=$(_math "$waittimes" + 1)
|
waittimes=$(_math "$waittimes" + 1)
|
||||||
if [ "$waittimes" -ge "$MAX_RETRY_TIMES" ]; then
|
if [ "$waittimes" -ge "$MAX_RETRY_TIMES" ]; then
|
||||||
@ -4960,9 +5047,9 @@ $_authorizations_map"
|
|||||||
errordetail="$(echo "$error" | _egrep_o '"detail": *"[^"]*' | cut -d '"' -f 4)"
|
errordetail="$(echo "$error" | _egrep_o '"detail": *"[^"]*' | cut -d '"' -f 4)"
|
||||||
_debug2 errordetail "$errordetail"
|
_debug2 errordetail "$errordetail"
|
||||||
if [ "$errordetail" ]; then
|
if [ "$errordetail" ]; then
|
||||||
_err "$d:Verify error:$errordetail"
|
_err "Invalid status, $d:Verify error detail:$errordetail"
|
||||||
else
|
else
|
||||||
_err "$d:Verify error:$error"
|
_err "Invalid status, $d:Verify error:$error"
|
||||||
fi
|
fi
|
||||||
if [ "$DEBUG" ]; then
|
if [ "$DEBUG" ]; then
|
||||||
if [ "$vtype" = "$VTYPE_HTTP" ]; then
|
if [ "$vtype" = "$VTYPE_HTTP" ]; then
|
||||||
@ -4984,12 +5071,12 @@ $_authorizations_map"
|
|||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$status" = "pending" ]; then
|
if _contains "$status" "pending"; then
|
||||||
_info "Pending, The CA is processing your order, please just wait. ($waittimes/$MAX_RETRY_TIMES)"
|
_info "Pending, The CA is processing your order, please just wait. ($waittimes/$MAX_RETRY_TIMES)"
|
||||||
elif [ "$status" = "processing" ]; then
|
elif _contains "$status" "processing"; then
|
||||||
_info "Processing, The CA is processing your order, please just wait. ($waittimes/$MAX_RETRY_TIMES)"
|
_info "Processing, The CA is processing your order, please just wait. ($waittimes/$MAX_RETRY_TIMES)"
|
||||||
else
|
else
|
||||||
_err "$d:Verify error:$response"
|
_err "Unknown status: $status, $d:Verify error:$response"
|
||||||
_clearupwebbroot "$_currentRoot" "$removelevel" "$token"
|
_clearupwebbroot "$_currentRoot" "$removelevel" "$token"
|
||||||
_clearup
|
_clearup
|
||||||
_on_issue_err "$_post_hook" "$vlist"
|
_on_issue_err "$_post_hook" "$vlist"
|
||||||
@ -4999,10 +5086,10 @@ $_authorizations_map"
|
|||||||
_sleep 2
|
_sleep 2
|
||||||
_debug "checking"
|
_debug "checking"
|
||||||
|
|
||||||
_send_signed_request "$uri"
|
_send_signed_request "$_authz_url"
|
||||||
|
|
||||||
if [ "$?" != "0" ]; then
|
if [ "$?" != "0" ]; then
|
||||||
_err "$d:Verify error:$response"
|
_err "Invalid code, $d:Verify error:$response"
|
||||||
_clearupwebbroot "$_currentRoot" "$removelevel" "$token"
|
_clearupwebbroot "$_currentRoot" "$removelevel" "$token"
|
||||||
_clearup
|
_clearup
|
||||||
_on_issue_err "$_post_hook" "$vlist"
|
_on_issue_err "$_post_hook" "$vlist"
|
||||||
@ -5169,6 +5256,9 @@ $_authorizations_map"
|
|||||||
|
|
||||||
[ -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")"
|
||||||
|
if [ "$Le_ForceNewDomainKey" ] && [ -e "$Le_Next_Domain_Key" ]; then
|
||||||
|
_info "Your pre-generated next key for future cert key change is in: $(__green "$Le_Next_Domain_Key")"
|
||||||
|
fi
|
||||||
|
|
||||||
Le_CertCreateTime=$(_time)
|
Le_CertCreateTime=$(_time)
|
||||||
_savedomainconf "Le_CertCreateTime" "$Le_CertCreateTime"
|
_savedomainconf "Le_CertCreateTime" "$Le_CertCreateTime"
|
||||||
@ -5710,6 +5800,7 @@ deploy() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
_debug2 DOMAIN_CONF "$DOMAIN_CONF"
|
||||||
. "$DOMAIN_CONF"
|
. "$DOMAIN_CONF"
|
||||||
|
|
||||||
_savedomainconf Le_DeployHook "$_hooks"
|
_savedomainconf Le_DeployHook "$_hooks"
|
||||||
@ -5743,7 +5834,8 @@ installcert() {
|
|||||||
_savedomainconf "Le_RealKeyPath" "$_real_key"
|
_savedomainconf "Le_RealKeyPath" "$_real_key"
|
||||||
_savedomainconf "Le_ReloadCmd" "$_reload_cmd" "base64"
|
_savedomainconf "Le_ReloadCmd" "$_reload_cmd" "base64"
|
||||||
_savedomainconf "Le_RealFullChainPath" "$_real_fullchain"
|
_savedomainconf "Le_RealFullChainPath" "$_real_fullchain"
|
||||||
|
export Le_ForceNewDomainKey="$(_readdomainconf Le_ForceNewDomainKey)"
|
||||||
|
export Le_Next_Domain_Key
|
||||||
_installcert "$_main_domain" "$_real_cert" "$_real_key" "$_real_ca" "$_real_fullchain" "$_reload_cmd"
|
_installcert "$_main_domain" "$_real_cert" "$_real_key" "$_real_ca" "$_real_fullchain" "$_reload_cmd"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5835,6 +5927,8 @@ _installcert() {
|
|||||||
export CA_CERT_PATH
|
export CA_CERT_PATH
|
||||||
export CERT_FULLCHAIN_PATH
|
export CERT_FULLCHAIN_PATH
|
||||||
export Le_Domain="$_main_domain"
|
export Le_Domain="$_main_domain"
|
||||||
|
export Le_ForceNewDomainKey
|
||||||
|
export Le_Next_Domain_Key
|
||||||
cd "$DOMAIN_PATH" && eval "$_reload_cmd"
|
cd "$DOMAIN_PATH" && eval "$_reload_cmd"
|
||||||
); then
|
); then
|
||||||
_info "$(__green "Reload success")"
|
_info "$(__green "Reload success")"
|
||||||
@ -5931,6 +6025,7 @@ installcronjob() {
|
|||||||
fi
|
fi
|
||||||
_t=$(_time)
|
_t=$(_time)
|
||||||
random_minute=$(_math $_t % 60)
|
random_minute=$(_math $_t % 60)
|
||||||
|
random_hour=$(_math $_t / 60 % 24)
|
||||||
|
|
||||||
if ! _exists "$_CRONTAB" && _exists "fcrontab"; then
|
if ! _exists "$_CRONTAB" && _exists "fcrontab"; then
|
||||||
_CRONTAB="fcrontab"
|
_CRONTAB="fcrontab"
|
||||||
@ -5955,16 +6050,14 @@ installcronjob() {
|
|||||||
_info "Installing cron job"
|
_info "Installing cron job"
|
||||||
if ! $_CRONTAB -l | grep "$PROJECT_ENTRY --cron"; then
|
if ! $_CRONTAB -l | grep "$PROJECT_ENTRY --cron"; then
|
||||||
if _exists uname && uname -a | grep SunOS >/dev/null; then
|
if _exists uname && uname -a | grep SunOS >/dev/null; then
|
||||||
$_CRONTAB -l | {
|
_CRONTAB_STDIN="$_CRONTAB --"
|
||||||
cat
|
|
||||||
echo "$random_minute 0 * * * $lesh --cron --home \"$LE_WORKING_DIR\" $_c_entry> /dev/null"
|
|
||||||
} | $_CRONTAB --
|
|
||||||
else
|
else
|
||||||
|
_CRONTAB_STDIN="$_CRONTAB -"
|
||||||
|
fi
|
||||||
$_CRONTAB -l | {
|
$_CRONTAB -l | {
|
||||||
cat
|
cat
|
||||||
echo "$random_minute 0 * * * $lesh --cron --home \"$LE_WORKING_DIR\" $_c_entry> /dev/null"
|
echo "$random_minute $random_hour * * * $lesh --cron --home \"$LE_WORKING_DIR\" $_c_entry> /dev/null"
|
||||||
} | $_CRONTAB -
|
} | $_CRONTAB_STDIN
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
if [ "$?" != "0" ]; then
|
if [ "$?" != "0" ]; then
|
||||||
_err "Install cron job failed. You need to manually renew your certs."
|
_err "Install cron job failed. You need to manually renew your certs."
|
||||||
@ -6066,8 +6159,22 @@ revoke() {
|
|||||||
|
|
||||||
uri="${ACME_REVOKE_CERT}"
|
uri="${ACME_REVOKE_CERT}"
|
||||||
|
|
||||||
|
_info "Try account key first."
|
||||||
|
if _send_signed_request "$uri" "$data" "" "$ACCOUNT_KEY_PATH"; then
|
||||||
|
if [ -z "$response" ]; then
|
||||||
|
_info "Revoke success."
|
||||||
|
rm -f "$CERT_PATH"
|
||||||
|
cat "$CERT_KEY_PATH" >"$CERT_KEY_PATH.revoked"
|
||||||
|
cat "$CSR_PATH" >"$CSR_PATH.revoked"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
_err "Revoke error."
|
||||||
|
_debug "$response"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
if [ -f "$CERT_KEY_PATH" ]; then
|
if [ -f "$CERT_KEY_PATH" ]; then
|
||||||
_info "Try domain key first."
|
_info "Try domain key."
|
||||||
if _send_signed_request "$uri" "$data" "" "$CERT_KEY_PATH"; then
|
if _send_signed_request "$uri" "$data" "" "$CERT_KEY_PATH"; then
|
||||||
if [ -z "$response" ]; then
|
if [ -z "$response" ]; then
|
||||||
_info "Revoke success."
|
_info "Revoke success."
|
||||||
@ -6083,21 +6190,6 @@ revoke() {
|
|||||||
else
|
else
|
||||||
_info "Domain key file doesn't exist."
|
_info "Domain key file doesn't exist."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_info "Try account key."
|
|
||||||
|
|
||||||
if _send_signed_request "$uri" "$data" "" "$ACCOUNT_KEY_PATH"; then
|
|
||||||
if [ -z "$response" ]; then
|
|
||||||
_info "Revoke success."
|
|
||||||
rm -f "$CERT_PATH"
|
|
||||||
cat "$CERT_KEY_PATH" >"$CERT_KEY_PATH.revoked"
|
|
||||||
cat "$CSR_PATH" >"$CSR_PATH.revoked"
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
_err "Revoke error."
|
|
||||||
_debug "$response"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6671,6 +6763,13 @@ _send_notify() {
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
_nsource="$NOTIFY_SOURCE"
|
||||||
|
if [ -z "$_nsource" ]; then
|
||||||
|
_nsource="$(hostname)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
_nsubject="$_nsubject by $_nsource"
|
||||||
|
|
||||||
_send_err=0
|
_send_err=0
|
||||||
for _n_hook in $(echo "$_nhooks" | tr ',' " "); do
|
for _n_hook in $(echo "$_nhooks" | tr ',' " "); do
|
||||||
_n_hook_file="$(_findHook "" $_SUB_FOLDER_NOTIFY "$_n_hook")"
|
_n_hook_file="$(_findHook "" $_SUB_FOLDER_NOTIFY "$_n_hook")"
|
||||||
@ -6725,11 +6824,12 @@ setnotify() {
|
|||||||
_nhook="$1"
|
_nhook="$1"
|
||||||
_nlevel="$2"
|
_nlevel="$2"
|
||||||
_nmode="$3"
|
_nmode="$3"
|
||||||
|
_nsource="$4"
|
||||||
|
|
||||||
_initpath
|
_initpath
|
||||||
|
|
||||||
if [ -z "$_nhook$_nlevel$_nmode" ]; then
|
if [ -z "$_nhook$_nlevel$_nmode$_nsource" ]; then
|
||||||
_usage "Usage: $PROJECT_ENTRY --set-notify [--notify-hook <hookname>] [--notify-level <0|1|2|3>] [--notify-mode <0|1>]"
|
_usage "Usage: $PROJECT_ENTRY --set-notify [--notify-hook <hookname>] [--notify-level <0|1|2|3>] [--notify-mode <0|1>] [--notify-source <hostname>]"
|
||||||
_usage "$_NOTIFY_WIKI"
|
_usage "$_NOTIFY_WIKI"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
@ -6746,6 +6846,12 @@ setnotify() {
|
|||||||
_saveaccountconf "NOTIFY_MODE" "$NOTIFY_MODE"
|
_saveaccountconf "NOTIFY_MODE" "$NOTIFY_MODE"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ "$_nsource" ]; then
|
||||||
|
_info "Set notify source to: $_nsource"
|
||||||
|
export "NOTIFY_SOURCE=$_nsource"
|
||||||
|
_saveaccountconf "NOTIFY_SOURCE" "$NOTIFY_SOURCE"
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "$_nhook" ]; then
|
if [ "$_nhook" ]; then
|
||||||
_info "Set notify hook to: $_nhook"
|
_info "Set notify hook to: $_nhook"
|
||||||
if [ "$_nhook" = "$NO_VALUE" ]; then
|
if [ "$_nhook" = "$NO_VALUE" ]; then
|
||||||
@ -6824,7 +6930,7 @@ Parameters:
|
|||||||
|
|
||||||
-f, --force Force install, force cert renewal or override sudo restrictions.
|
-f, --force Force install, force cert renewal or override sudo restrictions.
|
||||||
--staging, --test Use staging server, for testing.
|
--staging, --test Use staging server, for testing.
|
||||||
--debug [0|1|2|3] Output debug info. Defaults to 1 if argument is omitted.
|
--debug [0|1|2|3] Output debug info. Defaults to $DEBUG_LEVEL_DEFAULT if argument is omitted.
|
||||||
--output-insecure Output all the sensitive messages.
|
--output-insecure Output all the sensitive messages.
|
||||||
By default all the credentials/sensitive messages are hidden from the output/debug/log for security.
|
By default all the credentials/sensitive messages are hidden from the output/debug/log for security.
|
||||||
-w, --webroot <directory> Specifies the web root folder for web root mode.
|
-w, --webroot <directory> Specifies the web root folder for web root mode.
|
||||||
@ -6842,7 +6948,7 @@ Parameters:
|
|||||||
-k, --keylength <bits> Specifies the domain key length: 2048, 3072, 4096, 8192 or ec-256, ec-384, ec-521.
|
-k, --keylength <bits> Specifies the domain key length: 2048, 3072, 4096, 8192 or ec-256, ec-384, ec-521.
|
||||||
-ak, --accountkeylength <bits> Specifies the account key length: 2048, 3072, 4096
|
-ak, --accountkeylength <bits> Specifies the account key length: 2048, 3072, 4096
|
||||||
--log [file] Specifies the log file. Defaults to \"$DEFAULT_LOG_FILE\" if argument is omitted.
|
--log [file] Specifies the log file. Defaults to \"$DEFAULT_LOG_FILE\" if argument is omitted.
|
||||||
--log-level <1|2> Specifies the log level, default is 1.
|
--log-level <1|2> Specifies the log level, default is $DEFAULT_LOG_LEVEL.
|
||||||
--syslog <0|3|6|7> Syslog level, 0: disable syslog, 3: error, 6: info, 7: debug.
|
--syslog <0|3|6|7> Syslog level, 0: disable syslog, 3: error, 6: info, 7: debug.
|
||||||
--eab-kid <eab_key_id> Key Identifier for External Account Binding.
|
--eab-kid <eab_key_id> Key Identifier for External Account Binding.
|
||||||
--eab-hmac-key <eab_hmac_key> HMAC key for External Account Binding.
|
--eab-hmac-key <eab_hmac_key> HMAC key for External Account Binding.
|
||||||
@ -6850,7 +6956,7 @@ Parameters:
|
|||||||
|
|
||||||
These parameters are to install the cert to nginx/apache or any other server after issue/renew a cert:
|
These parameters are to install the cert to nginx/apache or any other server after issue/renew a cert:
|
||||||
|
|
||||||
--cert-file <file> Path to copy the cert file to after issue/renew..
|
--cert-file <file> Path to copy the cert file to after issue/renew.
|
||||||
--key-file <file> Path to copy the key file to after issue/renew.
|
--key-file <file> Path to copy the key file to after issue/renew.
|
||||||
--ca-file <file> Path to copy the intermediate cert file to after issue/renew.
|
--ca-file <file> Path to copy the intermediate cert file to after issue/renew.
|
||||||
--fullchain-file <file> Path to copy the fullchain cert file to after issue/renew.
|
--fullchain-file <file> Path to copy the fullchain cert file to after issue/renew.
|
||||||
@ -6880,7 +6986,8 @@ Parameters:
|
|||||||
--no-profile Only valid for '--install' command, which means: do not install aliases to user profile.
|
--no-profile Only valid for '--install' command, which means: do not install aliases to user profile.
|
||||||
--no-color Do not output color text.
|
--no-color Do not output color text.
|
||||||
--force-color Force output of color text. Useful for non-interactive use with the aha tool for HTML E-Mails.
|
--force-color Force output of color text. Useful for non-interactive use with the aha tool for HTML E-Mails.
|
||||||
--ecc Specifies to use the ECC cert. Valid for '--install-cert', '--renew', '--revoke', '--to-pkcs12' and '--create-csr'
|
--ecc Specifies use of the ECC cert. Only valid for '--install-cert', '--renew', '--remove ', '--revoke',
|
||||||
|
'--deploy', '--to-pkcs8', '--to-pkcs12' and '--create-csr'.
|
||||||
--csr <file> Specifies the input csr.
|
--csr <file> Specifies the input csr.
|
||||||
--pre-hook <command> Command to be run before obtaining any certificates.
|
--pre-hook <command> Command to be run before obtaining any certificates.
|
||||||
--post-hook <command> Command to be run after attempting to obtain/renew certificates. Runs regardless of whether obtain/renew succeeded or failed.
|
--post-hook <command> Command to be run after attempting to obtain/renew certificates. Runs regardless of whether obtain/renew succeeded or failed.
|
||||||
@ -6906,6 +7013,7 @@ Parameters:
|
|||||||
0: Bulk mode. Send all the domain's notifications in one message(mail).
|
0: Bulk mode. Send all the domain's notifications in one message(mail).
|
||||||
1: Cert mode. Send a message for every single cert.
|
1: Cert mode. Send a message for every single cert.
|
||||||
--notify-hook <hookname> Set the notify hook
|
--notify-hook <hookname> Set the notify hook
|
||||||
|
--notify-source <server name> Set the server name in the notification message
|
||||||
--revoke-reason <0-10> The reason for revocation, can be used in conjunction with the '--revoke' command.
|
--revoke-reason <0-10> The reason for revocation, can be used in conjunction with the '--revoke' command.
|
||||||
See: $_REVOKE_WIKI
|
See: $_REVOKE_WIKI
|
||||||
|
|
||||||
@ -7063,7 +7171,9 @@ _selectServer() {
|
|||||||
_getCAShortName() {
|
_getCAShortName() {
|
||||||
caurl="$1"
|
caurl="$1"
|
||||||
if [ -z "$caurl" ]; then
|
if [ -z "$caurl" ]; then
|
||||||
caurl="$DEFAULT_CA"
|
#use letsencrypt as default value if the Le_API is empty
|
||||||
|
#this case can only come from the old upgrading.
|
||||||
|
caurl="$CA_LETSENCRYPT_V2"
|
||||||
fi
|
fi
|
||||||
if [ "$CA_SSLCOM_ECC" = "$caurl" ]; then
|
if [ "$CA_SSLCOM_ECC" = "$caurl" ]; then
|
||||||
caurl="$CA_SSLCOM_RSA" #just hack to get the short name
|
caurl="$CA_SSLCOM_RSA" #just hack to get the short name
|
||||||
@ -7180,6 +7290,7 @@ _process() {
|
|||||||
_notify_hook=""
|
_notify_hook=""
|
||||||
_notify_level=""
|
_notify_level=""
|
||||||
_notify_mode=""
|
_notify_mode=""
|
||||||
|
_notify_source=""
|
||||||
_revoke_reason=""
|
_revoke_reason=""
|
||||||
_eab_kid=""
|
_eab_kid=""
|
||||||
_eab_hmac_key=""
|
_eab_hmac_key=""
|
||||||
@ -7425,6 +7536,9 @@ _process() {
|
|||||||
--keylength | -k)
|
--keylength | -k)
|
||||||
_keylength="$2"
|
_keylength="$2"
|
||||||
shift
|
shift
|
||||||
|
if [ "$_keylength" ] && ! _isEccKey "$_keylength"; then
|
||||||
|
export __SELECTED_RSA_KEY=1
|
||||||
|
fi
|
||||||
;;
|
;;
|
||||||
-ak | --accountkeylength)
|
-ak | --accountkeylength)
|
||||||
_accountkeylength="$2"
|
_accountkeylength="$2"
|
||||||
@ -7460,7 +7574,7 @@ _process() {
|
|||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
--home)
|
--home)
|
||||||
export LE_WORKING_DIR="$2"
|
export LE_WORKING_DIR="$(echo "$2" | sed 's|/$||')"
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
--cert-home | --certhome)
|
--cert-home | --certhome)
|
||||||
@ -7672,6 +7786,15 @@ _process() {
|
|||||||
_notify_mode="$_nmode"
|
_notify_mode="$_nmode"
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
|
--notify-source)
|
||||||
|
_nsource="$2"
|
||||||
|
if _startswith "$_nsource" "-"; then
|
||||||
|
_err "'$_nsource' is not valid host name for '$1'"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_notify_source="$_nsource"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
--revoke-reason)
|
--revoke-reason)
|
||||||
_revoke_reason="$2"
|
_revoke_reason="$2"
|
||||||
if _startswith "$_revoke_reason" "-"; then
|
if _startswith "$_revoke_reason" "-"; then
|
||||||
@ -7826,7 +7949,7 @@ _process() {
|
|||||||
createCSR "$_domain" "$_altdomains" "$_ecc"
|
createCSR "$_domain" "$_altdomains" "$_ecc"
|
||||||
;;
|
;;
|
||||||
setnotify)
|
setnotify)
|
||||||
setnotify "$_notify_hook" "$_notify_level" "$_notify_mode"
|
setnotify "$_notify_hook" "$_notify_level" "$_notify_mode" "$_notify_source"
|
||||||
;;
|
;;
|
||||||
setdefaultca)
|
setdefaultca)
|
||||||
setdefaultca
|
setdefaultca
|
||||||
|
@ -273,16 +273,27 @@ _check_curl_version() {
|
|||||||
_minor="$(_getfield "$_cversion" 2 '.')"
|
_minor="$(_getfield "$_cversion" 2 '.')"
|
||||||
_debug2 "_minor" "$_minor"
|
_debug2 "_minor" "$_minor"
|
||||||
|
|
||||||
if [ "$_major$_minor" -lt "740" ]; then
|
if [ "$_major" -ge "8" ]; then
|
||||||
|
#ok
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
if [ "$_major" = "7" ]; then
|
||||||
|
if [ "$_minor" -lt "40" ]; then
|
||||||
_err "curl v$_cversion doesn't support unit socket"
|
_err "curl v$_cversion doesn't support unit socket"
|
||||||
_err "Please upgrade to curl 7.40 or later."
|
_err "Please upgrade to curl 7.40 or later."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
if [ "$_major$_minor" -lt "750" ]; then
|
if [ "$_minor" -lt "50" ]; then
|
||||||
_debug "Use short host name"
|
_debug "Use short host name"
|
||||||
export _CURL_NO_HOST=1
|
export _CURL_NO_HOST=1
|
||||||
else
|
else
|
||||||
export _CURL_NO_HOST=
|
export _CURL_NO_HOST=
|
||||||
fi
|
fi
|
||||||
return 0
|
return 0
|
||||||
|
else
|
||||||
|
_err "curl v$_cversion doesn't support unit socket"
|
||||||
|
_err "Please upgrade to curl 7.40 or later."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
# Here is the script to deploy the cert to G-Core CDN service (https://gcorelabs.com/ru/) using the G-Core Labs API (https://docs.gcorelabs.com/cdn/).
|
# Here is the script to deploy the cert to G-Core CDN service (https://gcore.com/) using the G-Core Labs API (https://apidocs.gcore.com/cdn).
|
||||||
# Returns 0 when success.
|
# Returns 0 when success.
|
||||||
#
|
#
|
||||||
# Written by temoffey <temofffey@gmail.com>
|
# Written by temoffey <temofffey@gmail.com>
|
||||||
# Public domain, 2019
|
# Public domain, 2019
|
||||||
|
# Update by DreamOfIce <admin@dreamofice.cn> in 2023
|
||||||
|
|
||||||
#export DEPLOY_GCORE_CDN_USERNAME=myusername
|
#export DEPLOY_GCORE_CDN_USERNAME=myusername
|
||||||
#export DEPLOY_GCORE_CDN_PASSWORD=mypassword
|
#export DEPLOY_GCORE_CDN_PASSWORD=mypassword
|
||||||
@ -56,7 +57,7 @@ gcore_cdn_deploy() {
|
|||||||
_request="{\"username\":\"$Le_Deploy_gcore_cdn_username\",\"password\":\"$Le_Deploy_gcore_cdn_password\"}"
|
_request="{\"username\":\"$Le_Deploy_gcore_cdn_username\",\"password\":\"$Le_Deploy_gcore_cdn_password\"}"
|
||||||
_debug _request "$_request"
|
_debug _request "$_request"
|
||||||
export _H1="Content-Type:application/json"
|
export _H1="Content-Type:application/json"
|
||||||
_response=$(_post "$_request" "https://api.gcdn.co/auth/jwt/login")
|
_response=$(_post "$_request" "https://api.gcore.com/auth/jwt/login")
|
||||||
_debug _response "$_response"
|
_debug _response "$_response"
|
||||||
_regex=".*\"access\":\"\([-._0-9A-Za-z]*\)\".*$"
|
_regex=".*\"access\":\"\([-._0-9A-Za-z]*\)\".*$"
|
||||||
_debug _regex "$_regex"
|
_debug _regex "$_regex"
|
||||||
@ -69,8 +70,8 @@ gcore_cdn_deploy() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
_info "Find CDN resource with cname $_cdomain"
|
_info "Find CDN resource with cname $_cdomain"
|
||||||
export _H2="Authorization:Token $_token"
|
export _H2="Authorization:Bearer $_token"
|
||||||
_response=$(_get "https://api.gcdn.co/resources")
|
_response=$(_get "https://api.gcore.com/cdn/resources")
|
||||||
_debug _response "$_response"
|
_debug _response "$_response"
|
||||||
_regex="\"primary_resource\":null},"
|
_regex="\"primary_resource\":null},"
|
||||||
_debug _regex "$_regex"
|
_debug _regex "$_regex"
|
||||||
@ -102,7 +103,7 @@ gcore_cdn_deploy() {
|
|||||||
_date=$(date "+%d.%m.%Y %H:%M:%S")
|
_date=$(date "+%d.%m.%Y %H:%M:%S")
|
||||||
_request="{\"name\":\"$_cdomain ($_date)\",\"sslCertificate\":\"$_fullchain\",\"sslPrivateKey\":\"$_key\"}"
|
_request="{\"name\":\"$_cdomain ($_date)\",\"sslCertificate\":\"$_fullchain\",\"sslPrivateKey\":\"$_key\"}"
|
||||||
_debug _request "$_request"
|
_debug _request "$_request"
|
||||||
_response=$(_post "$_request" "https://api.gcdn.co/sslData")
|
_response=$(_post "$_request" "https://api.gcore.com/cdn/sslData")
|
||||||
_debug _response "$_response"
|
_debug _response "$_response"
|
||||||
_regex=".*\"id\":\([0-9]*\).*$"
|
_regex=".*\"id\":\([0-9]*\).*$"
|
||||||
_debug _regex "$_regex"
|
_debug _regex "$_regex"
|
||||||
@ -117,7 +118,7 @@ gcore_cdn_deploy() {
|
|||||||
_info "Update CDN resource"
|
_info "Update CDN resource"
|
||||||
_request="{\"originGroup\":$_originGroup,\"sslData\":$_sslDataAdd}"
|
_request="{\"originGroup\":$_originGroup,\"sslData\":$_sslDataAdd}"
|
||||||
_debug _request "$_request"
|
_debug _request "$_request"
|
||||||
_response=$(_post "$_request" "https://api.gcdn.co/resources/$_resourceId" '' "PUT")
|
_response=$(_post "$_request" "https://api.gcore.com/cdn/resources/$_resourceId" '' "PUT")
|
||||||
_debug _response "$_response"
|
_debug _response "$_response"
|
||||||
_regex=".*\"sslData\":\([0-9]*\).*$"
|
_regex=".*\"sslData\":\([0-9]*\).*$"
|
||||||
_debug _regex "$_regex"
|
_debug _regex "$_regex"
|
||||||
@ -133,7 +134,7 @@ gcore_cdn_deploy() {
|
|||||||
_info "Not found old SSL certificate"
|
_info "Not found old SSL certificate"
|
||||||
else
|
else
|
||||||
_info "Delete old SSL certificate"
|
_info "Delete old SSL certificate"
|
||||||
_response=$(_post '' "https://api.gcdn.co/sslData/$_sslDataOld" '' "DELETE")
|
_response=$(_post '' "https://api.gcore.com/cdn/sslData/$_sslDataOld" '' "DELETE")
|
||||||
_debug _response "$_response"
|
_debug _response "$_response"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ gitlab_deploy() {
|
|||||||
|
|
||||||
error_response="error"
|
error_response="error"
|
||||||
|
|
||||||
if test "${_response#*$error_response}" != "$_response"; then
|
if test "${_response#*"$error_response"}" != "$_response"; then
|
||||||
_err "Error in deploying certificate:"
|
_err "Error in deploying certificate:"
|
||||||
_err "$_response"
|
_err "$_response"
|
||||||
return 1
|
return 1
|
||||||
|
@ -147,7 +147,7 @@ haproxy_deploy() {
|
|||||||
# Create a temporary PEM file
|
# Create a temporary PEM file
|
||||||
_temppem="$(_mktemp)"
|
_temppem="$(_mktemp)"
|
||||||
_debug _temppem "${_temppem}"
|
_debug _temppem "${_temppem}"
|
||||||
cat "${_ckey}" "${_ccert}" "${_cca}" >"${_temppem}"
|
cat "${_ccert}" "${_cca}" "${_ckey}" >"${_temppem}"
|
||||||
_ret="$?"
|
_ret="$?"
|
||||||
|
|
||||||
# Check that we could create the temporary file
|
# Check that we could create the temporary file
|
||||||
|
160
deploy/panos.sh
160
deploy/panos.sh
@ -7,11 +7,15 @@
|
|||||||
#
|
#
|
||||||
# Firewall admin with superuser and IP address is required.
|
# Firewall admin with superuser and IP address is required.
|
||||||
#
|
#
|
||||||
# export PANOS_USER="" # required
|
# REQURED:
|
||||||
# export PANOS_PASS="" # required
|
# export PANOS_HOST=""
|
||||||
# export PANOS_HOST="" # required
|
# export PANOS_USER="" #User *MUST* have Commit and Import Permissions in XML API for Admin Role
|
||||||
|
# export PANOS_PASS=""
|
||||||
|
#
|
||||||
|
# The script will automatically generate a new API key if
|
||||||
|
# no key is found, or if a saved key has expired or is invalid.
|
||||||
|
|
||||||
# This function is to parse the XML
|
# This function is to parse the XML response from the firewall
|
||||||
parse_response() {
|
parse_response() {
|
||||||
type=$2
|
type=$2
|
||||||
if [ "$type" = 'keygen' ]; then
|
if [ "$type" = 'keygen' ]; then
|
||||||
@ -23,25 +27,46 @@ parse_response() {
|
|||||||
message="PAN-OS Key could not be set."
|
message="PAN-OS Key could not be set."
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
status=$(echo "$1" | sed 's/^.*"\([a-z]*\)".*/\1/g')
|
status=$(echo "$1" | tr -d '\n' | sed 's/^.*"\([a-z]*\)".*/\1/g')
|
||||||
message=$(echo "$1" | sed 's/^.*<result>\(.*\)<\/result.*/\1/g')
|
message=$(echo "$1" | tr -d '\n' | sed 's/.*\(<result>\|<msg>\|<line>\)\([^<]*\).*/\2/g')
|
||||||
|
_debug "Firewall message: $message"
|
||||||
|
if [ "$type" = 'keytest' ] && [ "$status" != "success" ]; then
|
||||||
|
_debug "**** API Key has EXPIRED or is INVALID ****"
|
||||||
|
unset _panos_key
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#This function is used to deploy to the firewall
|
||||||
deployer() {
|
deployer() {
|
||||||
content=""
|
content=""
|
||||||
type=$1 # Types are keygen, cert, key, commit
|
type=$1 # Types are keytest, keygen, cert, key, commit
|
||||||
_debug "**** Deploying $type *****"
|
|
||||||
panos_url="https://$_panos_host/api/"
|
panos_url="https://$_panos_host/api/"
|
||||||
|
|
||||||
|
#Test API Key by performing a lookup
|
||||||
|
if [ "$type" = 'keytest' ]; then
|
||||||
|
_debug "**** Testing saved API Key ****"
|
||||||
|
_H1="Content-Type: application/x-www-form-urlencoded"
|
||||||
|
# Get Version Info to test key
|
||||||
|
content="type=version&key=$_panos_key"
|
||||||
|
## Exclude all scopes for the empty commit
|
||||||
|
#_exclude_scope="<policy-and-objects>exclude</policy-and-objects><device-and-network>exclude</device-and-network><shared-object>exclude</shared-object>"
|
||||||
|
#content="type=commit&action=partial&key=$_panos_key&cmd=<commit><partial>$_exclude_scope<admin><member>acmekeytest</member></admin></partial></commit>"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Generate API Key
|
||||||
if [ "$type" = 'keygen' ]; then
|
if [ "$type" = 'keygen' ]; then
|
||||||
|
_debug "**** Generating new API Key ****"
|
||||||
_H1="Content-Type: application/x-www-form-urlencoded"
|
_H1="Content-Type: application/x-www-form-urlencoded"
|
||||||
content="type=keygen&user=$_panos_user&password=$_panos_pass"
|
content="type=keygen&user=$_panos_user&password=$_panos_pass"
|
||||||
# content="$content${nl}--$delim${nl}Content-Disposition: form-data; type=\"keygen\"; user=\"$_panos_user\"; password=\"$_panos_pass\"${nl}Content-Type: application/octet-stream${nl}${nl}"
|
# content="$content${nl}--$delim${nl}Content-Disposition: form-data; type=\"keygen\"; user=\"$_panos_user\"; password=\"$_panos_pass\"${nl}Content-Type: application/octet-stream${nl}${nl}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Deploy Cert or Key
|
||||||
if [ "$type" = 'cert' ] || [ "$type" = 'key' ]; then
|
if [ "$type" = 'cert' ] || [ "$type" = 'key' ]; then
|
||||||
#Generate DEIM
|
_debug "**** Deploying $type ****"
|
||||||
|
#Generate DELIM
|
||||||
delim="-----MultipartDelimiter$(date "+%s%N")"
|
delim="-----MultipartDelimiter$(date "+%s%N")"
|
||||||
nl="\015\012"
|
nl="\015\012"
|
||||||
#Set Header
|
#Set Header
|
||||||
@ -61,7 +86,7 @@ deployer() {
|
|||||||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"key\"\r\n\r\n$_panos_key"
|
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"key\"\r\n\r\n$_panos_key"
|
||||||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"format\"\r\n\r\npem"
|
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"format\"\r\n\r\npem"
|
||||||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"passphrase\"\r\n\r\n123456"
|
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"passphrase\"\r\n\r\n123456"
|
||||||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"file\"; filename=\"$(basename "$_ckey")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ckey")"
|
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"file\"; filename=\"$(basename "$_cdomain.key")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ckey")"
|
||||||
fi
|
fi
|
||||||
#Close multipart
|
#Close multipart
|
||||||
content="$content${nl}--$delim--${nl}${nl}"
|
content="$content${nl}--$delim--${nl}${nl}"
|
||||||
@ -69,16 +94,25 @@ deployer() {
|
|||||||
content=$(printf %b "$content")
|
content=$(printf %b "$content")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Commit changes
|
||||||
if [ "$type" = 'commit' ]; then
|
if [ "$type" = 'commit' ]; then
|
||||||
|
_debug "**** Committing changes ****"
|
||||||
export _H1="Content-Type: application/x-www-form-urlencoded"
|
export _H1="Content-Type: application/x-www-form-urlencoded"
|
||||||
cmd=$(printf "%s" "<commit><partial><$_panos_user></$_panos_user></partial></commit>" | _url_encode)
|
#Check for force commit - will commit ALL uncommited changes to the firewall. Use with caution!
|
||||||
content="type=commit&key=$_panos_key&cmd=$cmd"
|
if [ "$FORCE" ]; then
|
||||||
|
_debug "Force switch detected. Committing ALL changes to the firewall."
|
||||||
|
cmd=$(printf "%s" "<commit><partial><force><admin><member>$_panos_user</member></admin></force></partial></commit>" | _url_encode)
|
||||||
|
else
|
||||||
|
_exclude_scope="<policy-and-objects>exclude</policy-and-objects><device-and-network>exclude</device-and-network>"
|
||||||
|
cmd=$(printf "%s" "<commit><partial>$_exclude_scope<admin><member>$_panos_user</member></admin></partial></commit>" | _url_encode)
|
||||||
fi
|
fi
|
||||||
|
content="type=commit&action=partial&key=$_panos_key&cmd=$cmd"
|
||||||
|
fi
|
||||||
|
|
||||||
response=$(_post "$content" "$panos_url" "" "POST")
|
response=$(_post "$content" "$panos_url" "" "POST")
|
||||||
parse_response "$response" "$type"
|
parse_response "$response" "$type"
|
||||||
# Saving response to variables
|
# Saving response to variables
|
||||||
response_status=$status
|
response_status=$status
|
||||||
#DEBUG
|
|
||||||
_debug response_status "$response_status"
|
_debug response_status "$response_status"
|
||||||
if [ "$response_status" = "success" ]; then
|
if [ "$response_status" = "success" ]; then
|
||||||
_debug "Successfully deployed $type"
|
_debug "Successfully deployed $type"
|
||||||
@ -92,43 +126,85 @@ deployer() {
|
|||||||
|
|
||||||
# This is the main function that will call the other functions to deploy everything.
|
# This is the main function that will call the other functions to deploy everything.
|
||||||
panos_deploy() {
|
panos_deploy() {
|
||||||
_cdomain="$1"
|
_cdomain=$(echo "$1" | sed 's/*/WILDCARD_/g') #Wildcard Safe Filename
|
||||||
_ckey="$2"
|
_ckey="$2"
|
||||||
_cfullchain="$5"
|
_cfullchain="$5"
|
||||||
# PANOS ENV VAR check
|
|
||||||
if [ -z "$PANOS_USER" ] || [ -z "$PANOS_PASS" ] || [ -z "$PANOS_HOST" ]; then
|
# VALID FILE CHECK
|
||||||
_debug "No ENV variables found lets check for saved variables"
|
if [ ! -f "$_ckey" ] || [ ! -f "$_cfullchain" ]; then
|
||||||
_getdeployconf PANOS_USER
|
_err "Unable to find a valid key and/or cert. If this is an ECDSA/ECC cert, use the --ecc flag when deploying."
|
||||||
_getdeployconf PANOS_PASS
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# PANOS_HOST
|
||||||
|
if [ "$PANOS_HOST" ]; then
|
||||||
|
_debug "Detected ENV variable PANOS_HOST. Saving to file."
|
||||||
|
_savedeployconf PANOS_HOST "$PANOS_HOST" 1
|
||||||
|
else
|
||||||
|
_debug "Attempting to load variable PANOS_HOST from file."
|
||||||
_getdeployconf PANOS_HOST
|
_getdeployconf PANOS_HOST
|
||||||
|
fi
|
||||||
|
|
||||||
|
# PANOS USER
|
||||||
|
if [ "$PANOS_USER" ]; then
|
||||||
|
_debug "Detected ENV variable PANOS_USER. Saving to file."
|
||||||
|
_savedeployconf PANOS_USER "$PANOS_USER" 1
|
||||||
|
else
|
||||||
|
_debug "Attempting to load variable PANOS_USER from file."
|
||||||
|
_getdeployconf PANOS_USER
|
||||||
|
fi
|
||||||
|
|
||||||
|
# PANOS_PASS
|
||||||
|
if [ "$PANOS_PASS" ]; then
|
||||||
|
_debug "Detected ENV variable PANOS_PASS. Saving to file."
|
||||||
|
_savedeployconf PANOS_PASS "$PANOS_PASS" 1
|
||||||
|
else
|
||||||
|
_debug "Attempting to load variable PANOS_PASS from file."
|
||||||
|
_getdeployconf PANOS_PASS
|
||||||
|
fi
|
||||||
|
|
||||||
|
# PANOS_KEY
|
||||||
|
_getdeployconf PANOS_KEY
|
||||||
|
if [ "$PANOS_KEY" ]; then
|
||||||
|
_debug "Detected saved key."
|
||||||
|
_panos_key=$PANOS_KEY
|
||||||
|
else
|
||||||
|
_debug "No key detected"
|
||||||
|
unset _panos_key
|
||||||
|
fi
|
||||||
|
|
||||||
|
#Store variables
|
||||||
|
_panos_host=$PANOS_HOST
|
||||||
_panos_user=$PANOS_USER
|
_panos_user=$PANOS_USER
|
||||||
_panos_pass=$PANOS_PASS
|
_panos_pass=$PANOS_PASS
|
||||||
_panos_host=$PANOS_HOST
|
|
||||||
if [ -z "$_panos_user" ] && [ -z "$_panos_pass" ] && [ -z "$_panos_host" ]; then
|
#Test API Key if found. If the key is invalid, the variable _panos_key will be unset.
|
||||||
_err "No host, user and pass found.. If this is the first time deploying please set PANOS_HOST, PANOS_USER and PANOS_PASS in environment variables. Delete them after you have succesfully deployed certs."
|
if [ "$_panos_host" ] && [ "$_panos_key" ]; then
|
||||||
|
_debug "**** Testing API KEY ****"
|
||||||
|
deployer keytest
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check for valid variables
|
||||||
|
if [ -z "$_panos_host" ]; then
|
||||||
|
_err "No host found. If this is your first time deploying, please set PANOS_HOST in ENV variables. You can delete it after you have successfully deployed the certs."
|
||||||
|
return 1
|
||||||
|
elif [ -z "$_panos_user" ]; then
|
||||||
|
_err "No user found. If this is your first time deploying, please set PANOS_USER in ENV variables. You can delete it after you have successfully deployed the certs."
|
||||||
|
return 1
|
||||||
|
elif [ -z "$_panos_pass" ]; then
|
||||||
|
_err "No password found. If this is your first time deploying, please set PANOS_PASS in ENV variables. You can delete it after you have successfully deployed the certs."
|
||||||
return 1
|
return 1
|
||||||
else
|
else
|
||||||
_debug "Using saved env variables."
|
# Generate a new API key if no valid API key is found
|
||||||
fi
|
|
||||||
else
|
|
||||||
_debug "Detected ENV variables to be saved to the deploy conf."
|
|
||||||
# Encrypt and save user
|
|
||||||
_savedeployconf PANOS_USER "$PANOS_USER" 1
|
|
||||||
_savedeployconf PANOS_PASS "$PANOS_PASS" 1
|
|
||||||
_savedeployconf PANOS_HOST "$PANOS_HOST" 1
|
|
||||||
_panos_user="$PANOS_USER"
|
|
||||||
_panos_pass="$PANOS_PASS"
|
|
||||||
_panos_host="$PANOS_HOST"
|
|
||||||
fi
|
|
||||||
_debug "Let's use username and pass to generate token."
|
|
||||||
if [ -z "$_panos_user" ] || [ -z "$_panos_pass" ] || [ -z "$_panos_host" ]; then
|
|
||||||
_err "Please pass username and password and host as env variables PANOS_USER, PANOS_PASS and PANOS_HOST"
|
|
||||||
return 1
|
|
||||||
else
|
|
||||||
_debug "Getting PANOS KEY"
|
|
||||||
deployer keygen
|
|
||||||
if [ -z "$_panos_key" ]; then
|
if [ -z "$_panos_key" ]; then
|
||||||
_err "Missing apikey."
|
_debug "**** Generating new PANOS API KEY ****"
|
||||||
|
deployer keygen
|
||||||
|
_savedeployconf PANOS_KEY "$_panos_key" 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Confirm that a valid key was generated
|
||||||
|
if [ -z "$_panos_key" ]; then
|
||||||
|
_err "Unable to generate an API key. The user and pass may be invalid or not authorized to generate a new key. Please check the PANOS_USER and PANOS_PASS credentials and try again"
|
||||||
return 1
|
return 1
|
||||||
else
|
else
|
||||||
deployer cert
|
deployer cert
|
||||||
|
@ -99,11 +99,11 @@ proxmoxve_deploy() {
|
|||||||
_proxmoxve_api_token_key="$DEPLOY_PROXMOXVE_API_TOKEN_KEY"
|
_proxmoxve_api_token_key="$DEPLOY_PROXMOXVE_API_TOKEN_KEY"
|
||||||
_savedeployconf DEPLOY_PROXMOXVE_API_TOKEN_KEY "$DEPLOY_PROXMOXVE_API_TOKEN_KEY"
|
_savedeployconf DEPLOY_PROXMOXVE_API_TOKEN_KEY "$DEPLOY_PROXMOXVE_API_TOKEN_KEY"
|
||||||
fi
|
fi
|
||||||
_debug2 DEPLOY_PROXMOXVE_API_TOKEN_KEY _proxmoxve_api_token_key
|
_debug2 DEPLOY_PROXMOXVE_API_TOKEN_KEY "$_proxmoxve_api_token_key"
|
||||||
|
|
||||||
# PVE API Token header value. Used in "Authorization: PVEAPIToken".
|
# PVE API Token header value. Used in "Authorization: PVEAPIToken".
|
||||||
_proxmoxve_header_api_token="${_proxmoxve_user}@${_proxmoxve_user_realm}!${_proxmoxve_api_token_name}=${_proxmoxve_api_token_key}"
|
_proxmoxve_header_api_token="${_proxmoxve_user}@${_proxmoxve_user_realm}!${_proxmoxve_api_token_name}=${_proxmoxve_api_token_key}"
|
||||||
_debug2 "Auth Header" _proxmoxve_header_api_token
|
_debug2 "Auth Header" "$_proxmoxve_header_api_token"
|
||||||
|
|
||||||
# Ugly. I hate putting heredocs inside functions because heredocs don't
|
# Ugly. I hate putting heredocs inside functions because heredocs don't
|
||||||
# account for whitespace correctly but it _does_ work and is several times
|
# account for whitespace correctly but it _does_ work and is several times
|
||||||
@ -124,8 +124,8 @@ HEREDOC
|
|||||||
)
|
)
|
||||||
_debug2 Payload "$_json_payload"
|
_debug2 Payload "$_json_payload"
|
||||||
|
|
||||||
# Push certificates to server.
|
_info "Push certificates to server"
|
||||||
export _HTTPS_INSECURE=1
|
export HTTPS_INSECURE=1
|
||||||
export _H1="Authorization: PVEAPIToken=${_proxmoxve_header_api_token}"
|
export _H1="Authorization: PVEAPIToken=${_proxmoxve_header_api_token}"
|
||||||
_post "$_json_payload" "$_target_url" "" POST "application/json"
|
_post "$_json_payload" "$_target_url" "" POST "application/json"
|
||||||
|
|
||||||
|
403
deploy/ssh.sh
403
deploy/ssh.sh
@ -14,7 +14,7 @@
|
|||||||
# The following examples are for QNAP NAS running QTS 4.2
|
# The following examples are for QNAP NAS running QTS 4.2
|
||||||
# export DEPLOY_SSH_CMD="" # defaults to "ssh -T"
|
# export DEPLOY_SSH_CMD="" # defaults to "ssh -T"
|
||||||
# export DEPLOY_SSH_USER="admin" # required
|
# export DEPLOY_SSH_USER="admin" # required
|
||||||
# export DEPLOY_SSH_SERVER="qnap" # defaults to domain name
|
# export DEPLOY_SSH_SERVER="host1 host2:8022 192.168.0.1:9022" # defaults to domain name, support multiple servers with optional port
|
||||||
# export DEPLOY_SSH_KEYFILE="/etc/stunnel/stunnel.pem"
|
# export DEPLOY_SSH_KEYFILE="/etc/stunnel/stunnel.pem"
|
||||||
# export DEPLOY_SSH_CERTFILE="/etc/stunnel/stunnel.pem"
|
# export DEPLOY_SSH_CERTFILE="/etc/stunnel/stunnel.pem"
|
||||||
# export DEPLOY_SSH_CAFILE="/etc/stunnel/uca.pem"
|
# export DEPLOY_SSH_CAFILE="/etc/stunnel/uca.pem"
|
||||||
@ -23,6 +23,8 @@
|
|||||||
# export DEPLOY_SSH_BACKUP="" # yes or no, default to yes or previously saved value
|
# export DEPLOY_SSH_BACKUP="" # yes or no, default to yes or previously saved value
|
||||||
# export DEPLOY_SSH_BACKUP_PATH=".acme_ssh_deploy" # path on remote system. Defaults to .acme_ssh_deploy
|
# export DEPLOY_SSH_BACKUP_PATH=".acme_ssh_deploy" # path on remote system. Defaults to .acme_ssh_deploy
|
||||||
# export DEPLOY_SSH_MULTI_CALL="" # yes or no, default to no or previously saved value
|
# export DEPLOY_SSH_MULTI_CALL="" # yes or no, default to no or previously saved value
|
||||||
|
# export DEPLOY_SSH_USE_SCP="" yes or no, default to no
|
||||||
|
# export DEPLOY_SSH_SCP_CMD="" defaults to "scp -q"
|
||||||
#
|
#
|
||||||
######## Public functions #####################
|
######## Public functions #####################
|
||||||
|
|
||||||
@ -42,72 +44,134 @@ 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.
|
||||||
|
_migratedeployconf Le_Deploy_ssh_user DEPLOY_SSH_USER
|
||||||
_getdeployconf DEPLOY_SSH_USER
|
_getdeployconf DEPLOY_SSH_USER
|
||||||
_debug2 DEPLOY_SSH_USER "$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
|
|
||||||
_err "DEPLOY_SSH_USER not defined."
|
_err "DEPLOY_SSH_USER not defined."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
else
|
_savedeployconf DEPLOY_SSH_USER "$DEPLOY_SSH_USER"
|
||||||
Le_Deploy_ssh_user="$DEPLOY_SSH_USER"
|
|
||||||
_savedomainconf Le_Deploy_ssh_user "$Le_Deploy_ssh_user"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# SERVER is optional. If not provided then use _cdomain
|
# SERVER is optional. If not provided then use _cdomain
|
||||||
|
_migratedeployconf Le_Deploy_ssh_server DEPLOY_SSH_SERVER
|
||||||
_getdeployconf DEPLOY_SSH_SERVER
|
_getdeployconf DEPLOY_SSH_SERVER
|
||||||
_debug2 DEPLOY_SSH_SERVER "$DEPLOY_SSH_SERVER"
|
_debug2 DEPLOY_SSH_SERVER "$DEPLOY_SSH_SERVER"
|
||||||
if [ -n "$DEPLOY_SSH_SERVER" ]; then
|
if [ -z "$DEPLOY_SSH_SERVER" ]; then
|
||||||
Le_Deploy_ssh_server="$DEPLOY_SSH_SERVER"
|
DEPLOY_SSH_SERVER="$_cdomain"
|
||||||
_savedomainconf Le_Deploy_ssh_server "$Le_Deploy_ssh_server"
|
|
||||||
elif [ -z "$Le_Deploy_ssh_server" ]; then
|
|
||||||
Le_Deploy_ssh_server="$_cdomain"
|
|
||||||
fi
|
fi
|
||||||
|
_savedeployconf DEPLOY_SSH_SERVER "$DEPLOY_SSH_SERVER"
|
||||||
|
|
||||||
# CMD is optional. If not provided then use ssh
|
# CMD is optional. If not provided then use ssh
|
||||||
|
_migratedeployconf Le_Deploy_ssh_cmd DEPLOY_SSH_CMD
|
||||||
_getdeployconf DEPLOY_SSH_CMD
|
_getdeployconf DEPLOY_SSH_CMD
|
||||||
_debug2 DEPLOY_SSH_CMD "$DEPLOY_SSH_CMD"
|
_debug2 DEPLOY_SSH_CMD "$DEPLOY_SSH_CMD"
|
||||||
if [ -n "$DEPLOY_SSH_CMD" ]; then
|
if [ -z "$DEPLOY_SSH_CMD" ]; then
|
||||||
Le_Deploy_ssh_cmd="$DEPLOY_SSH_CMD"
|
DEPLOY_SSH_CMD="ssh -T"
|
||||||
_savedomainconf Le_Deploy_ssh_cmd "$Le_Deploy_ssh_cmd"
|
|
||||||
elif [ -z "$Le_Deploy_ssh_cmd" ]; then
|
|
||||||
Le_Deploy_ssh_cmd="ssh -T"
|
|
||||||
fi
|
fi
|
||||||
|
_savedeployconf DEPLOY_SSH_CMD "$DEPLOY_SSH_CMD"
|
||||||
|
|
||||||
# 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.
|
||||||
|
_migratedeployconf Le_Deploy_ssh_backup DEPLOY_SSH_BACKUP
|
||||||
_getdeployconf DEPLOY_SSH_BACKUP
|
_getdeployconf DEPLOY_SSH_BACKUP
|
||||||
_debug2 DEPLOY_SSH_BACKUP "$DEPLOY_SSH_BACKUP"
|
_debug2 DEPLOY_SSH_BACKUP "$DEPLOY_SSH_BACKUP"
|
||||||
if [ "$DEPLOY_SSH_BACKUP" = "no" ]; then
|
if [ -z "$DEPLOY_SSH_BACKUP" ]; then
|
||||||
Le_Deploy_ssh_backup="no"
|
DEPLOY_SSH_BACKUP="yes"
|
||||||
elif [ -z "$Le_Deploy_ssh_backup" ] || [ "$DEPLOY_SSH_BACKUP" = "yes" ]; then
|
|
||||||
Le_Deploy_ssh_backup="yes"
|
|
||||||
fi
|
fi
|
||||||
_savedomainconf Le_Deploy_ssh_backup "$Le_Deploy_ssh_backup"
|
_savedeployconf DEPLOY_SSH_BACKUP "$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
|
||||||
|
_migratedeployconf Le_Deploy_ssh_backup_path DEPLOY_SSH_BACKUP_PATH
|
||||||
_getdeployconf DEPLOY_SSH_BACKUP_PATH
|
_getdeployconf DEPLOY_SSH_BACKUP_PATH
|
||||||
_debug2 DEPLOY_SSH_BACKUP_PATH "$DEPLOY_SSH_BACKUP_PATH"
|
_debug2 DEPLOY_SSH_BACKUP_PATH "$DEPLOY_SSH_BACKUP_PATH"
|
||||||
if [ -n "$DEPLOY_SSH_BACKUP_PATH" ]; then
|
if [ -z "$DEPLOY_SSH_BACKUP_PATH" ]; then
|
||||||
Le_Deploy_ssh_backup_path="$DEPLOY_SSH_BACKUP_PATH"
|
DEPLOY_SSH_BACKUP_PATH=".acme_ssh_deploy"
|
||||||
elif [ -z "$Le_Deploy_ssh_backup_path" ]; then
|
|
||||||
Le_Deploy_ssh_backup_path=".acme_ssh_deploy"
|
|
||||||
fi
|
fi
|
||||||
_savedomainconf Le_Deploy_ssh_backup_path "$Le_Deploy_ssh_backup_path"
|
_savedeployconf DEPLOY_SSH_BACKUP_PATH "$DEPLOY_SSH_BACKUP_PATH"
|
||||||
|
|
||||||
# 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").
|
||||||
|
_migratedeployconf Le_Deploy_ssh_multi_call DEPLOY_SSH_MULTI_CALL
|
||||||
_getdeployconf DEPLOY_SSH_MULTI_CALL
|
_getdeployconf DEPLOY_SSH_MULTI_CALL
|
||||||
_debug2 DEPLOY_SSH_MULTI_CALL "$DEPLOY_SSH_MULTI_CALL"
|
_debug2 DEPLOY_SSH_MULTI_CALL "$DEPLOY_SSH_MULTI_CALL"
|
||||||
if [ "$DEPLOY_SSH_MULTI_CALL" = "yes" ]; then
|
if [ -z "$DEPLOY_SSH_MULTI_CALL" ]; then
|
||||||
Le_Deploy_ssh_multi_call="yes"
|
DEPLOY_SSH_MULTI_CALL="no"
|
||||||
_savedomainconf Le_Deploy_ssh_multi_call "$Le_Deploy_ssh_multi_call"
|
fi
|
||||||
elif [ "$DEPLOY_SSH_MULTI_CALL" = "no" ]; then
|
_savedeployconf DEPLOY_SSH_MULTI_CALL "$DEPLOY_SSH_MULTI_CALL"
|
||||||
Le_Deploy_ssh_multi_call=""
|
|
||||||
_cleardomainconf Le_Deploy_ssh_multi_call
|
# KEYFILE is optional.
|
||||||
|
# If provided then private key will be copied to provided filename.
|
||||||
|
_migratedeployconf Le_Deploy_ssh_keyfile DEPLOY_SSH_KEYFILE
|
||||||
|
_getdeployconf DEPLOY_SSH_KEYFILE
|
||||||
|
_debug2 DEPLOY_SSH_KEYFILE "$DEPLOY_SSH_KEYFILE"
|
||||||
|
if [ -n "$DEPLOY_SSH_KEYFILE" ]; then
|
||||||
|
_savedeployconf DEPLOY_SSH_KEYFILE "$DEPLOY_SSH_KEYFILE"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_deploy_ssh_servers=$Le_Deploy_ssh_server
|
# CERTFILE is optional.
|
||||||
for Le_Deploy_ssh_server in $_deploy_ssh_servers; do
|
# If provided then certificate will be copied or appended to provided filename.
|
||||||
|
_migratedeployconf Le_Deploy_ssh_certfile DEPLOY_SSH_CERTFILE
|
||||||
|
_getdeployconf DEPLOY_SSH_CERTFILE
|
||||||
|
_debug2 DEPLOY_SSH_CERTFILE "$DEPLOY_SSH_CERTFILE"
|
||||||
|
if [ -n "$DEPLOY_SSH_CERTFILE" ]; then
|
||||||
|
_savedeployconf DEPLOY_SSH_CERTFILE "$DEPLOY_SSH_CERTFILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# CAFILE is optional.
|
||||||
|
# If provided then CA intermediate certificate will be copied or appended to provided filename.
|
||||||
|
_migratedeployconf Le_Deploy_ssh_cafile DEPLOY_SSH_CAFILE
|
||||||
|
_getdeployconf DEPLOY_SSH_CAFILE
|
||||||
|
_debug2 DEPLOY_SSH_CAFILE "$DEPLOY_SSH_CAFILE"
|
||||||
|
if [ -n "$DEPLOY_SSH_CAFILE" ]; then
|
||||||
|
_savedeployconf DEPLOY_SSH_CAFILE "$DEPLOY_SSH_CAFILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# FULLCHAIN is optional.
|
||||||
|
# If provided then fullchain certificate will be copied or appended to provided filename.
|
||||||
|
_migratedeployconf Le_Deploy_ssh_fullchain DEPLOY_SSH_FULLCHAIN
|
||||||
|
_getdeployconf DEPLOY_SSH_FULLCHAIN
|
||||||
|
_debug2 DEPLOY_SSH_FULLCHAIN "$DEPLOY_SSH_FULLCHAIN"
|
||||||
|
if [ -n "$DEPLOY_SSH_FULLCHAIN" ]; then
|
||||||
|
_savedeployconf DEPLOY_SSH_FULLCHAIN "$DEPLOY_SSH_FULLCHAIN"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# REMOTE_CMD is optional.
|
||||||
|
# If provided then this command will be executed on remote host.
|
||||||
|
_migratedeployconf Le_Deploy_ssh_remote_cmd DEPLOY_SSH_REMOTE_CMD
|
||||||
|
_getdeployconf DEPLOY_SSH_REMOTE_CMD
|
||||||
|
_debug2 DEPLOY_SSH_REMOTE_CMD "$DEPLOY_SSH_REMOTE_CMD"
|
||||||
|
if [ -n "$DEPLOY_SSH_REMOTE_CMD" ]; then
|
||||||
|
_savedeployconf DEPLOY_SSH_REMOTE_CMD "$DEPLOY_SSH_REMOTE_CMD"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# USE_SCP is optional. If not provided then default to previously saved
|
||||||
|
# value (which may be undefined... equivalent to "no").
|
||||||
|
_getdeployconf DEPLOY_SSH_USE_SCP
|
||||||
|
_debug2 DEPLOY_SSH_USE_SCP "$DEPLOY_SSH_USE_SCP"
|
||||||
|
if [ -z "$DEPLOY_SSH_USE_SCP" ]; then
|
||||||
|
DEPLOY_SSH_USE_SCP="no"
|
||||||
|
fi
|
||||||
|
_savedeployconf DEPLOY_SSH_USE_SCP "$DEPLOY_SSH_USE_SCP"
|
||||||
|
|
||||||
|
# SCP_CMD is optional. If not provided then use scp
|
||||||
|
_getdeployconf DEPLOY_SSH_SCP_CMD
|
||||||
|
_debug2 DEPLOY_SSH_SCP_CMD "$DEPLOY_SSH_SCP_CMD"
|
||||||
|
if [ -z "$DEPLOY_SSH_SCP_CMD" ]; then
|
||||||
|
DEPLOY_SSH_SCP_CMD="scp -q"
|
||||||
|
fi
|
||||||
|
_savedeployconf DEPLOY_SSH_SCP_CMD "$DEPLOY_SSH_SCP_CMD"
|
||||||
|
|
||||||
|
if [ "$DEPLOY_SSH_USE_SCP" = "yes" ]; then
|
||||||
|
DEPLOY_SSH_MULTI_CALL="yes"
|
||||||
|
_info "Using scp as alternate method for copying files. Multicall Mode is implicit"
|
||||||
|
elif [ "$DEPLOY_SSH_MULTI_CALL" = "yes" ]; then
|
||||||
|
_info "Using MULTI_CALL mode... Required commands sent in multiple calls to remote host"
|
||||||
|
else
|
||||||
|
_info "Required commands batched and sent in single call to remote host"
|
||||||
|
fi
|
||||||
|
|
||||||
|
_deploy_ssh_servers="$DEPLOY_SSH_SERVER"
|
||||||
|
for DEPLOY_SSH_SERVER in $_deploy_ssh_servers; do
|
||||||
_ssh_deploy
|
_ssh_deploy
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
@ -117,16 +181,25 @@ _ssh_deploy() {
|
|||||||
_cmdstr=""
|
_cmdstr=""
|
||||||
_backupprefix=""
|
_backupprefix=""
|
||||||
_backupdir=""
|
_backupdir=""
|
||||||
|
_local_cert_file=""
|
||||||
|
_local_ca_file=""
|
||||||
|
_local_full_file=""
|
||||||
|
|
||||||
_info "Deploy certificates to remote server $Le_Deploy_ssh_user@$Le_Deploy_ssh_server"
|
case $DEPLOY_SSH_SERVER in
|
||||||
if [ "$Le_Deploy_ssh_multi_call" = "yes" ]; then
|
*:*)
|
||||||
_info "Using MULTI_CALL mode... Required commands sent in multiple calls to remote host"
|
_host=${DEPLOY_SSH_SERVER%:*}
|
||||||
else
|
_port=${DEPLOY_SSH_SERVER##*:}
|
||||||
_info "Required commands batched and sent in single call to remote host"
|
;;
|
||||||
fi
|
*)
|
||||||
|
_host=$DEPLOY_SSH_SERVER
|
||||||
|
_port=
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
if [ "$Le_Deploy_ssh_backup" = "yes" ]; then
|
_info "Deploy certificates to remote server $DEPLOY_SSH_USER@$_host:$_port"
|
||||||
_backupprefix="$Le_Deploy_ssh_backup_path/$_cdomain-backup"
|
|
||||||
|
if [ "$DEPLOY_SSH_BACKUP" = "yes" ]; then
|
||||||
|
_backupprefix="$DEPLOY_SSH_BACKUP_PATH/$_cdomain-backup"
|
||||||
_backupdir="$_backupprefix-$(_utc_date | tr ' ' '-')"
|
_backupdir="$_backupprefix-$(_utc_date | tr ' ' '-')"
|
||||||
# run cleanup on the backup directory, erase all older
|
# run cleanup on the backup directory, erase all older
|
||||||
# than 180 days (15552000 seconds).
|
# than 180 days (15552000 seconds).
|
||||||
@ -138,7 +211,7 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d
|
|||||||
_cmdstr="mkdir -p $_backupdir; $_cmdstr"
|
_cmdstr="mkdir -p $_backupdir; $_cmdstr"
|
||||||
_info "Backup of old certificate files will be placed in remote directory $_backupdir"
|
_info "Backup of old certificate files will be placed in remote directory $_backupdir"
|
||||||
_info "Backup directories erased after 180 days."
|
_info "Backup directories erased after 180 days."
|
||||||
if [ "$Le_Deploy_ssh_multi_call" = "yes" ]; then
|
if [ "$DEPLOY_SSH_MULTI_CALL" = "yes" ]; then
|
||||||
if ! _ssh_remote_cmd "$_cmdstr"; then
|
if ! _ssh_remote_cmd "$_cmdstr"; then
|
||||||
return $_err_code
|
return $_err_code
|
||||||
fi
|
fi
|
||||||
@ -146,23 +219,11 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# KEYFILE is optional.
|
|
||||||
# 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"
|
if [ "$DEPLOY_SSH_BACKUP" = "yes" ]; then
|
||||||
_savedomainconf Le_Deploy_ssh_keyfile "$Le_Deploy_ssh_keyfile"
|
|
||||||
fi
|
|
||||||
if [ -n "$Le_Deploy_ssh_keyfile" ]; then
|
|
||||||
if [ "$Le_Deploy_ssh_backup" = "yes" ]; then
|
|
||||||
# backup file we are about to overwrite.
|
# backup file we are about to overwrite.
|
||||||
_cmdstr="$_cmdstr cp $Le_Deploy_ssh_keyfile $_backupdir >/dev/null;"
|
_cmdstr="$_cmdstr cp $DEPLOY_SSH_KEYFILE $_backupdir >/dev/null;"
|
||||||
fi
|
if [ "$DEPLOY_SSH_MULTI_CALL" = "yes" ]; then
|
||||||
# copy new certificate into file.
|
|
||||||
_cmdstr="$_cmdstr echo \"$(cat "$_ckey")\" > $Le_Deploy_ssh_keyfile;"
|
|
||||||
_info "will copy private key to remote file $Le_Deploy_ssh_keyfile"
|
|
||||||
if [ "$Le_Deploy_ssh_multi_call" = "yes" ]; then
|
|
||||||
if ! _ssh_remote_cmd "$_cmdstr"; then
|
if ! _ssh_remote_cmd "$_cmdstr"; then
|
||||||
return $_err_code
|
return $_err_code
|
||||||
fi
|
fi
|
||||||
@ -170,27 +231,34 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# CERTFILE is optional.
|
# copy new key into file.
|
||||||
# If provided then certificate will be copied or appended to provided filename.
|
if [ "$DEPLOY_SSH_USE_SCP" = "yes" ]; then
|
||||||
_getdeployconf DEPLOY_SSH_CERTFILE
|
# scp the file
|
||||||
_debug2 DEPLOY_SSH_CERTFILE "$DEPLOY_SSH_CERTFILE"
|
if ! _scp_remote_cmd "$_ckey" "$DEPLOY_SSH_KEYFILE"; then
|
||||||
|
return $_err_code
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# ssh echo to the file
|
||||||
|
_cmdstr="$_cmdstr echo \"$(cat "$_ckey")\" > $DEPLOY_SSH_KEYFILE;"
|
||||||
|
_info "will copy private key to remote file $DEPLOY_SSH_KEYFILE"
|
||||||
|
if [ "$DEPLOY_SSH_MULTI_CALL" = "yes" ]; then
|
||||||
|
if ! _ssh_remote_cmd "$_cmdstr"; then
|
||||||
|
return $_err_code
|
||||||
|
fi
|
||||||
|
_cmdstr=""
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
if [ -n "$DEPLOY_SSH_CERTFILE" ]; then
|
if [ -n "$DEPLOY_SSH_CERTFILE" ]; then
|
||||||
Le_Deploy_ssh_certfile="$DEPLOY_SSH_CERTFILE"
|
|
||||||
_savedomainconf Le_Deploy_ssh_certfile "$Le_Deploy_ssh_certfile"
|
|
||||||
fi
|
|
||||||
if [ -n "$Le_Deploy_ssh_certfile" ]; then
|
|
||||||
_pipe=">"
|
_pipe=">"
|
||||||
if [ "$Le_Deploy_ssh_certfile" = "$Le_Deploy_ssh_keyfile" ]; then
|
if [ "$DEPLOY_SSH_CERTFILE" = "$DEPLOY_SSH_KEYFILE" ]; then
|
||||||
# if filename is same as previous file then append.
|
# if filename is same as previous file then append.
|
||||||
_pipe=">>"
|
_pipe=">>"
|
||||||
elif [ "$Le_Deploy_ssh_backup" = "yes" ]; then
|
elif [ "$DEPLOY_SSH_BACKUP" = "yes" ]; then
|
||||||
# backup file we are about to overwrite.
|
# backup file we are about to overwrite.
|
||||||
_cmdstr="$_cmdstr cp $Le_Deploy_ssh_certfile $_backupdir >/dev/null;"
|
_cmdstr="$_cmdstr cp $DEPLOY_SSH_CERTFILE $_backupdir >/dev/null;"
|
||||||
fi
|
if [ "$DEPLOY_SSH_MULTI_CALL" = "yes" ]; then
|
||||||
# copy new certificate into file.
|
|
||||||
_cmdstr="$_cmdstr echo \"$(cat "$_ccert")\" $_pipe $Le_Deploy_ssh_certfile;"
|
|
||||||
_info "will copy certificate to remote file $Le_Deploy_ssh_certfile"
|
|
||||||
if [ "$Le_Deploy_ssh_multi_call" = "yes" ]; then
|
|
||||||
if ! _ssh_remote_cmd "$_cmdstr"; then
|
if ! _ssh_remote_cmd "$_cmdstr"; then
|
||||||
return $_err_code
|
return $_err_code
|
||||||
fi
|
fi
|
||||||
@ -198,28 +266,40 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# CAFILE is optional.
|
# copy new certificate into file.
|
||||||
# If provided then CA intermediate certificate will be copied or appended to provided filename.
|
if [ "$DEPLOY_SSH_USE_SCP" = "yes" ]; then
|
||||||
_getdeployconf DEPLOY_SSH_CAFILE
|
# scp the file
|
||||||
_debug2 DEPLOY_SSH_CAFILE "$DEPLOY_SSH_CAFILE"
|
_local_cert_file=$(_mktemp)
|
||||||
|
if [ "$DEPLOY_SSH_CERTFILE" = "$DEPLOY_SSH_KEYFILE" ]; then
|
||||||
|
cat "$_ckey" >>"$_local_cert_file"
|
||||||
|
fi
|
||||||
|
cat "$_ccert" >>"$_local_cert_file"
|
||||||
|
if ! _scp_remote_cmd "$_local_cert_file" "$DEPLOY_SSH_CERTFILE"; then
|
||||||
|
return $_err_code
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# ssh echo to the file
|
||||||
|
_cmdstr="$_cmdstr echo \"$(cat "$_ccert")\" $_pipe $DEPLOY_SSH_CERTFILE;"
|
||||||
|
_info "will copy certificate to remote file $DEPLOY_SSH_CERTFILE"
|
||||||
|
if [ "$DEPLOY_SSH_MULTI_CALL" = "yes" ]; then
|
||||||
|
if ! _ssh_remote_cmd "$_cmdstr"; then
|
||||||
|
return $_err_code
|
||||||
|
fi
|
||||||
|
_cmdstr=""
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
if [ -n "$DEPLOY_SSH_CAFILE" ]; then
|
if [ -n "$DEPLOY_SSH_CAFILE" ]; then
|
||||||
Le_Deploy_ssh_cafile="$DEPLOY_SSH_CAFILE"
|
|
||||||
_savedomainconf Le_Deploy_ssh_cafile "$Le_Deploy_ssh_cafile"
|
|
||||||
fi
|
|
||||||
if [ -n "$Le_Deploy_ssh_cafile" ]; then
|
|
||||||
_pipe=">"
|
_pipe=">"
|
||||||
if [ "$Le_Deploy_ssh_cafile" = "$Le_Deploy_ssh_keyfile" ] ||
|
if [ "$DEPLOY_SSH_CAFILE" = "$DEPLOY_SSH_KEYFILE" ] ||
|
||||||
[ "$Le_Deploy_ssh_cafile" = "$Le_Deploy_ssh_certfile" ]; then
|
[ "$DEPLOY_SSH_CAFILE" = "$DEPLOY_SSH_CERTFILE" ]; then
|
||||||
# if filename is same as previous file then append.
|
# if filename is same as previous file then append.
|
||||||
_pipe=">>"
|
_pipe=">>"
|
||||||
elif [ "$Le_Deploy_ssh_backup" = "yes" ]; then
|
elif [ "$DEPLOY_SSH_BACKUP" = "yes" ]; then
|
||||||
# backup file we are about to overwrite.
|
# backup file we are about to overwrite.
|
||||||
_cmdstr="$_cmdstr cp $Le_Deploy_ssh_cafile $_backupdir >/dev/null;"
|
_cmdstr="$_cmdstr cp $DEPLOY_SSH_CAFILE $_backupdir >/dev/null;"
|
||||||
fi
|
if [ "$DEPLOY_SSH_MULTI_CALL" = "yes" ]; then
|
||||||
# copy new certificate into file.
|
|
||||||
_cmdstr="$_cmdstr echo \"$(cat "$_cca")\" $_pipe $Le_Deploy_ssh_cafile;"
|
|
||||||
_info "will copy CA file to remote file $Le_Deploy_ssh_cafile"
|
|
||||||
if [ "$Le_Deploy_ssh_multi_call" = "yes" ]; then
|
|
||||||
if ! _ssh_remote_cmd "$_cmdstr"; then
|
if ! _ssh_remote_cmd "$_cmdstr"; then
|
||||||
return $_err_code
|
return $_err_code
|
||||||
fi
|
fi
|
||||||
@ -227,29 +307,44 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# FULLCHAIN is optional.
|
# copy new certificate into file.
|
||||||
# If provided then fullchain certificate will be copied or appended to provided filename.
|
if [ "$DEPLOY_SSH_USE_SCP" = "yes" ]; then
|
||||||
_getdeployconf DEPLOY_SSH_FULLCHAIN
|
# scp the file
|
||||||
_debug2 DEPLOY_SSH_FULLCHAIN "$DEPLOY_SSH_FULLCHAIN"
|
_local_ca_file=$(_mktemp)
|
||||||
|
if [ "$DEPLOY_SSH_CAFILE" = "$DEPLOY_SSH_KEYFILE" ]; then
|
||||||
|
cat "$_ckey" >>"$_local_ca_file"
|
||||||
|
fi
|
||||||
|
if [ "$DEPLOY_SSH_CAFILE" = "$DEPLOY_SSH_CERTFILE" ]; then
|
||||||
|
cat "$_ccert" >>"$_local_ca_file"
|
||||||
|
fi
|
||||||
|
cat "$_cca" >>"$_local_ca_file"
|
||||||
|
if ! _scp_remote_cmd "$_local_ca_file" "$DEPLOY_SSH_CAFILE"; then
|
||||||
|
return $_err_code
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# ssh echo to the file
|
||||||
|
_cmdstr="$_cmdstr echo \"$(cat "$_cca")\" $_pipe $DEPLOY_SSH_CAFILE;"
|
||||||
|
_info "will copy CA file to remote file $DEPLOY_SSH_CAFILE"
|
||||||
|
if [ "$DEPLOY_SSH_MULTI_CALL" = "yes" ]; then
|
||||||
|
if ! _ssh_remote_cmd "$_cmdstr"; then
|
||||||
|
return $_err_code
|
||||||
|
fi
|
||||||
|
_cmdstr=""
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
if [ -n "$DEPLOY_SSH_FULLCHAIN" ]; then
|
if [ -n "$DEPLOY_SSH_FULLCHAIN" ]; then
|
||||||
Le_Deploy_ssh_fullchain="$DEPLOY_SSH_FULLCHAIN"
|
|
||||||
_savedomainconf Le_Deploy_ssh_fullchain "$Le_Deploy_ssh_fullchain"
|
|
||||||
fi
|
|
||||||
if [ -n "$Le_Deploy_ssh_fullchain" ]; then
|
|
||||||
_pipe=">"
|
_pipe=">"
|
||||||
if [ "$Le_Deploy_ssh_fullchain" = "$Le_Deploy_ssh_keyfile" ] ||
|
if [ "$DEPLOY_SSH_FULLCHAIN" = "$DEPLOY_SSH_KEYFILE" ] ||
|
||||||
[ "$Le_Deploy_ssh_fullchain" = "$Le_Deploy_ssh_certfile" ] ||
|
[ "$DEPLOY_SSH_FULLCHAIN" = "$DEPLOY_SSH_CERTFILE" ] ||
|
||||||
[ "$Le_Deploy_ssh_fullchain" = "$Le_Deploy_ssh_cafile" ]; then
|
[ "$DEPLOY_SSH_FULLCHAIN" = "$DEPLOY_SSH_CAFILE" ]; then
|
||||||
# if filename is same as previous file then append.
|
# if filename is same as previous file then append.
|
||||||
_pipe=">>"
|
_pipe=">>"
|
||||||
elif [ "$Le_Deploy_ssh_backup" = "yes" ]; then
|
elif [ "$DEPLOY_SSH_BACKUP" = "yes" ]; then
|
||||||
# backup file we are about to overwrite.
|
# backup file we are about to overwrite.
|
||||||
_cmdstr="$_cmdstr cp $Le_Deploy_ssh_fullchain $_backupdir >/dev/null;"
|
_cmdstr="$_cmdstr cp $DEPLOY_SSH_FULLCHAIN $_backupdir >/dev/null;"
|
||||||
fi
|
if [ "$DEPLOY_SSH_FULLCHAIN" = "yes" ]; then
|
||||||
# copy new certificate into file.
|
|
||||||
_cmdstr="$_cmdstr echo \"$(cat "$_cfullchain")\" $_pipe $Le_Deploy_ssh_fullchain;"
|
|
||||||
_info "will copy fullchain to remote file $Le_Deploy_ssh_fullchain"
|
|
||||||
if [ "$Le_Deploy_ssh_multi_call" = "yes" ]; then
|
|
||||||
if ! _ssh_remote_cmd "$_cmdstr"; then
|
if ! _ssh_remote_cmd "$_cmdstr"; then
|
||||||
return $_err_code
|
return $_err_code
|
||||||
fi
|
fi
|
||||||
@ -257,18 +352,51 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# REMOTE_CMD is optional.
|
# copy new certificate into file.
|
||||||
# If provided then this command will be executed on remote host.
|
if [ "$DEPLOY_SSH_USE_SCP" = "yes" ]; then
|
||||||
_getdeployconf DEPLOY_SSH_REMOTE_CMD
|
# scp the file
|
||||||
_debug2 DEPLOY_SSH_REMOTE_CMD "$DEPLOY_SSH_REMOTE_CMD"
|
_local_full_file=$(_mktemp)
|
||||||
if [ -n "$DEPLOY_SSH_REMOTE_CMD" ]; then
|
if [ "$DEPLOY_SSH_FULLCHAIN" = "$DEPLOY_SSH_KEYFILE" ]; then
|
||||||
Le_Deploy_ssh_remote_cmd="$DEPLOY_SSH_REMOTE_CMD"
|
cat "$_ckey" >>"$_local_full_file"
|
||||||
_savedomainconf Le_Deploy_ssh_remote_cmd "$Le_Deploy_ssh_remote_cmd"
|
|
||||||
fi
|
fi
|
||||||
if [ -n "$Le_Deploy_ssh_remote_cmd" ]; then
|
if [ "$DEPLOY_SSH_FULLCHAIN" = "$DEPLOY_SSH_CERTFILE" ]; then
|
||||||
_cmdstr="$_cmdstr $Le_Deploy_ssh_remote_cmd;"
|
cat "$_ccert" >>"$_local_full_file"
|
||||||
_info "Will execute remote command $Le_Deploy_ssh_remote_cmd"
|
fi
|
||||||
if [ "$Le_Deploy_ssh_multi_call" = "yes" ]; then
|
if [ "$DEPLOY_SSH_FULLCHAIN" = "$DEPLOY_SSH_CAFILE" ]; then
|
||||||
|
cat "$_cca" >>"$_local_full_file"
|
||||||
|
fi
|
||||||
|
cat "$_cfullchain" >>"$_local_full_file"
|
||||||
|
if ! _scp_remote_cmd "$_local_full_file" "$DEPLOY_SSH_FULLCHAIN"; then
|
||||||
|
return $_err_code
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# ssh echo to the file
|
||||||
|
_cmdstr="$_cmdstr echo \"$(cat "$_cfullchain")\" $_pipe $DEPLOY_SSH_FULLCHAIN;"
|
||||||
|
_info "will copy fullchain to remote file $DEPLOY_SSH_FULLCHAIN"
|
||||||
|
if [ "$DEPLOY_SSH_MULTI_CALL" = "yes" ]; then
|
||||||
|
if ! _ssh_remote_cmd "$_cmdstr"; then
|
||||||
|
return $_err_code
|
||||||
|
fi
|
||||||
|
_cmdstr=""
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# cleanup local files if any
|
||||||
|
if [ -f "$_local_cert_file" ]; then
|
||||||
|
rm -f "$_local_cert_file"
|
||||||
|
fi
|
||||||
|
if [ -f "$_local_ca_file" ]; then
|
||||||
|
rm -f "$_local_ca_file"
|
||||||
|
fi
|
||||||
|
if [ -f "$_local_full_file" ]; then
|
||||||
|
rm -f "$_local_full_file"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$DEPLOY_SSH_REMOTE_CMD" ]; then
|
||||||
|
_cmdstr="$_cmdstr $DEPLOY_SSH_REMOTE_CMD;"
|
||||||
|
_info "Will execute remote command $DEPLOY_SSH_REMOTE_CMD"
|
||||||
|
if [ "$DEPLOY_SSH_MULTI_CALL" = "yes" ]; then
|
||||||
if ! _ssh_remote_cmd "$_cmdstr"; then
|
if ! _ssh_remote_cmd "$_cmdstr"; then
|
||||||
return $_err_code
|
return $_err_code
|
||||||
fi
|
fi
|
||||||
@ -282,17 +410,25 @@ then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; d
|
|||||||
return $_err_code
|
return $_err_code
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
# cleanup in case all is ok
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
#cmd
|
#cmd
|
||||||
_ssh_remote_cmd() {
|
_ssh_remote_cmd() {
|
||||||
_cmd="$1"
|
_cmd="$1"
|
||||||
|
|
||||||
|
_ssh_cmd="$DEPLOY_SSH_CMD"
|
||||||
|
if [ -n "$_port" ]; then
|
||||||
|
_ssh_cmd="$_ssh_cmd -p $_port"
|
||||||
|
fi
|
||||||
|
|
||||||
_secure_debug "Remote commands to execute: $_cmd"
|
_secure_debug "Remote commands to execute: $_cmd"
|
||||||
_info "Submitting sequence of commands to remote server by ssh"
|
_info "Submitting sequence of commands to remote server by $_ssh_cmd"
|
||||||
|
|
||||||
# quotations in bash cmd below intended. Squash travis spellcheck error
|
# quotations in bash cmd below intended. Squash travis spellcheck error
|
||||||
# shellcheck disable=SC2029
|
# shellcheck disable=SC2029
|
||||||
$Le_Deploy_ssh_cmd "$Le_Deploy_ssh_user@$Le_Deploy_ssh_server" sh -c "'$_cmd'"
|
$_ssh_cmd "$DEPLOY_SSH_USER@$_host" sh -c "'$_cmd'"
|
||||||
_err_code="$?"
|
_err_code="$?"
|
||||||
|
|
||||||
if [ "$_err_code" != "0" ]; then
|
if [ "$_err_code" != "0" ]; then
|
||||||
@ -301,3 +437,26 @@ _ssh_remote_cmd() {
|
|||||||
|
|
||||||
return $_err_code
|
return $_err_code
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# cmd scp
|
||||||
|
_scp_remote_cmd() {
|
||||||
|
_src=$1
|
||||||
|
_dest=$2
|
||||||
|
|
||||||
|
_scp_cmd="$DEPLOY_SSH_SCP_CMD"
|
||||||
|
if [ -n "$_port" ]; then
|
||||||
|
_scp_cmd="$_scp_cmd -P $_port"
|
||||||
|
fi
|
||||||
|
|
||||||
|
_secure_debug "Remote copy source $_src to destination $_dest"
|
||||||
|
_info "Submitting secure copy by $_scp_cmd"
|
||||||
|
|
||||||
|
$_scp_cmd "$_src" "$DEPLOY_SSH_USER"@"$_host":"$_dest"
|
||||||
|
_err_code="$?"
|
||||||
|
|
||||||
|
if [ "$_err_code" != "0" ]; then
|
||||||
|
_err "Error code $_err_code returned from scp"
|
||||||
|
fi
|
||||||
|
|
||||||
|
return $_err_code
|
||||||
|
}
|
||||||
|
@ -1,34 +1,40 @@
|
|||||||
#!/usr/bin/env sh
|
#!/bin/bash
|
||||||
|
|
||||||
# Here is a script to deploy cert to Synology DSM
|
################################################################################
|
||||||
#
|
# ACME.sh 3rd party deploy plugin for Synology DSM
|
||||||
# It requires following environment variables:
|
################################################################################
|
||||||
#
|
# Authors: Brian Hartvigsen (creator), https://github.com/tresni
|
||||||
# SYNO_Username - Synology Username to login (must be an administrator)
|
# Martin Arndt (contributor), https://troublezone.net/
|
||||||
# SYNO_Password - Synology Password to login
|
# Updated: 2023-07-03
|
||||||
# SYNO_Certificate - Certificate description to target for replacement
|
# Issues: https://github.com/acmesh-official/acme.sh/issues/2727
|
||||||
#
|
################################################################################
|
||||||
# The following environmental variables may be set if you don't like their
|
# Usage:
|
||||||
# default values:
|
# - Create temp admin user automatically:
|
||||||
#
|
# export SYNO_USE_TEMP_ADMIN=1
|
||||||
# SYNO_Scheme - defaults to http
|
# - Or provide your own admin user credential:
|
||||||
# SYNO_Hostname - defaults to localhost
|
# 1. export SYNO_Username="adminUser"
|
||||||
# SYNO_Port - defaults to 5000
|
# 2. export SYNO_Password="adminPassword"
|
||||||
# SYNO_DID - device ID to skip OTP - defaults to empty
|
# Optional exports (shown values are the defaults):
|
||||||
# SYNO_TOTP_SECRET - TOTP secret to generate OTP - defaults to empty
|
# - export SYNO_Certificate="" - to replace a specific certificate via description
|
||||||
#
|
# - export SYNO_Scheme="http"
|
||||||
|
# - export SYNO_Hostname="localhost"
|
||||||
|
# - export SYNO_Port="5000"
|
||||||
|
# - export SYNO_Create=1 - to allow creating the certificate if it doesn't exist
|
||||||
|
# - export SYNO_Device_Name="CertRenewal" - required if 2FA-OTP enabled
|
||||||
|
# - export SYNO_Device_ID="" - required for skipping 2FA-OTP
|
||||||
|
# 3. acme.sh --deploy --deploy-hook synology_dsm -d example.com
|
||||||
|
################################################################################
|
||||||
# Dependencies:
|
# Dependencies:
|
||||||
# -------------
|
# - jq & curl
|
||||||
# - jq and curl
|
# - synouser & synogroup (When available and SYNO_USE_TEMP_ADMIN is set)
|
||||||
# - oathtool (When using 2 Factor Authentication and SYNO_TOTP_SECRET is set)
|
################################################################################
|
||||||
#
|
# Return value:
|
||||||
#returns 0 means success, otherwise error.
|
# 0 means success, otherwise error.
|
||||||
|
################################################################################
|
||||||
######## Public functions #####################
|
|
||||||
|
|
||||||
|
########## Public functions ####################################################
|
||||||
#domain keyfile certfile cafile fullchain
|
#domain keyfile certfile cafile fullchain
|
||||||
synology_dsm_deploy() {
|
synology_dsm_deploy() {
|
||||||
|
|
||||||
_cdomain="$1"
|
_cdomain="$1"
|
||||||
_ckey="$2"
|
_ckey="$2"
|
||||||
_ccert="$3"
|
_ccert="$3"
|
||||||
@ -36,39 +42,61 @@ synology_dsm_deploy() {
|
|||||||
|
|
||||||
_debug _cdomain "$_cdomain"
|
_debug _cdomain "$_cdomain"
|
||||||
|
|
||||||
# Get Username and Password, but don't save until we successfully authenticate
|
# Get username & password, but don't save until we authenticated successfully
|
||||||
|
_getdeployconf SYNO_USE_TEMP_ADMIN
|
||||||
_getdeployconf SYNO_Username
|
_getdeployconf SYNO_Username
|
||||||
_getdeployconf SYNO_Password
|
_getdeployconf SYNO_Password
|
||||||
_getdeployconf SYNO_Create
|
_getdeployconf SYNO_Create
|
||||||
_getdeployconf SYNO_DID
|
_getdeployconf SYNO_DID
|
||||||
_getdeployconf SYNO_TOTP_SECRET
|
_getdeployconf SYNO_TOTP_SECRET
|
||||||
|
_getdeployconf SYNO_Device_Name
|
||||||
|
_getdeployconf SYNO_Device_ID
|
||||||
|
|
||||||
|
# Prepare temp admin user info if SYNO_USE_TEMP_ADMIN is set
|
||||||
|
if [ -n "${SYNO_USE_TEMP_ADMIN:-}" ]; then
|
||||||
|
if ! _exists synouser; then
|
||||||
|
if ! _exists synogroup; then
|
||||||
|
_err "Tools are missing for creating temp admin user, please set SYNO_Username & SYNO_Password instead."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
_debug "Setting temp admin user credential..."
|
||||||
|
SYNO_Username=sc-acmesh-tmp
|
||||||
|
SYNO_Password=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 16)
|
||||||
|
# Ignore 2FA-OTP settings which won't be needed.
|
||||||
|
SYNO_Device_Name=
|
||||||
|
SYNO_Device_ID=
|
||||||
|
fi
|
||||||
|
|
||||||
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 "You must set either SYNO_USE_TEMP_ADMIN, or set both SYNO_Username and SYNO_Password."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
_debug2 SYNO_Username "$SYNO_Username"
|
_debug2 SYNO_Username "$SYNO_Username"
|
||||||
_secure_debug2 SYNO_Password "$SYNO_Password"
|
_secure_debug2 SYNO_Password "$SYNO_Password"
|
||||||
|
_debug2 SYNO_Create "$SYNO_Create"
|
||||||
|
_debug2 SYNO_Device_Name "$SYNO_Device_Name"
|
||||||
|
_secure_debug2 SYNO_Device_ID "$SYNO_Device_ID"
|
||||||
|
|
||||||
# Optional scheme, hostname, and port for Synology DSM
|
# Optional scheme, hostname & port for Synology DSM
|
||||||
_getdeployconf SYNO_Scheme
|
_getdeployconf SYNO_Scheme
|
||||||
_getdeployconf SYNO_Hostname
|
_getdeployconf SYNO_Hostname
|
||||||
_getdeployconf SYNO_Port
|
_getdeployconf SYNO_Port
|
||||||
|
|
||||||
# default vaules for scheme, hostname, and port
|
# Default values for scheme, hostname & port
|
||||||
# defaulting to localhost and http because it's localhost...
|
# Defaulting to localhost & http, because it's localhost…
|
||||||
[ -n "${SYNO_Scheme}" ] || SYNO_Scheme="http"
|
[ -n "${SYNO_Scheme}" ] || SYNO_Scheme="http"
|
||||||
[ -n "${SYNO_Hostname}" ] || SYNO_Hostname="localhost"
|
[ -n "${SYNO_Hostname}" ] || SYNO_Hostname="localhost"
|
||||||
[ -n "${SYNO_Port}" ] || SYNO_Port="5000"
|
[ -n "${SYNO_Port}" ] || SYNO_Port="5000"
|
||||||
|
_savedeployconf SYNO_USE_TEMP_ADMIN "$SYNO_USE_TEMP_ADMIN"
|
||||||
_savedeployconf SYNO_Scheme "$SYNO_Scheme"
|
_savedeployconf SYNO_Scheme "$SYNO_Scheme"
|
||||||
_savedeployconf SYNO_Hostname "$SYNO_Hostname"
|
_savedeployconf SYNO_Hostname "$SYNO_Hostname"
|
||||||
_savedeployconf SYNO_Port "$SYNO_Port"
|
_savedeployconf SYNO_Port "$SYNO_Port"
|
||||||
|
|
||||||
_debug2 SYNO_Scheme "$SYNO_Scheme"
|
_debug2 SYNO_Scheme "$SYNO_Scheme"
|
||||||
_debug2 SYNO_Hostname "$SYNO_Hostname"
|
_debug2 SYNO_Hostname "$SYNO_Hostname"
|
||||||
_debug2 SYNO_Port "$SYNO_Port"
|
_debug2 SYNO_Port "$SYNO_Port"
|
||||||
|
|
||||||
# Get the certificate description, but don't save it until we verfiy it's real
|
# Get the certificate description, but don't save it until we verify it's real
|
||||||
_getdeployconf SYNO_Certificate
|
_getdeployconf SYNO_Certificate
|
||||||
_debug SYNO_Certificate "${SYNO_Certificate:-}"
|
_debug SYNO_Certificate "${SYNO_Certificate:-}"
|
||||||
|
|
||||||
@ -83,24 +111,28 @@ synology_dsm_deploy() {
|
|||||||
|
|
||||||
_debug "Getting API version"
|
_debug "Getting API version"
|
||||||
response=$(_get "$_base_url/webapi/query.cgi?api=SYNO.API.Info&version=1&method=query&query=SYNO.API.Auth")
|
response=$(_get "$_base_url/webapi/query.cgi?api=SYNO.API.Info&version=1&method=query&query=SYNO.API.Auth")
|
||||||
|
api_path=$(echo "$response" | grep "SYNO.API.Auth" | sed -n 's/.*"path" *: *"\([^"]*\)".*/\1/p')
|
||||||
api_version=$(echo "$response" | grep "SYNO.API.Auth" | sed -n 's/.*"maxVersion" *: *\([0-9]*\).*/\1/p')
|
api_version=$(echo "$response" | grep "SYNO.API.Auth" | sed -n 's/.*"maxVersion" *: *\([0-9]*\).*/\1/p')
|
||||||
_debug3 response "$response"
|
_debug3 response "$response"
|
||||||
|
_debug3 api_path "$api_path"
|
||||||
_debug3 api_version "$api_version"
|
_debug3 api_version "$api_version"
|
||||||
|
|
||||||
# Login, get the token from JSON and session id from cookie
|
# Login, get the session ID & SynoToken from JSON
|
||||||
_info "Logging into $SYNO_Hostname:$SYNO_Port"
|
_info "Logging into $SYNO_Hostname:$SYNO_Port"
|
||||||
encoded_username="$(printf "%s" "$SYNO_Username" | _url_encode)"
|
encoded_username="$(printf "%s" "$SYNO_Username" | _url_encode)"
|
||||||
encoded_password="$(printf "%s" "$SYNO_Password" | _url_encode)"
|
encoded_password="$(printf "%s" "$SYNO_Password" | _url_encode)"
|
||||||
|
|
||||||
otp_code=""
|
otp_code=""
|
||||||
|
# START - DEPRECATED, only kept for legacy compatibility reasons
|
||||||
if [ -n "$SYNO_TOTP_SECRET" ]; then
|
if [ -n "$SYNO_TOTP_SECRET" ]; then
|
||||||
if _exists oathtool; then
|
_info "WARNING: Usage of SYNO_TOTP_SECRET is deprecated!"
|
||||||
otp_code="$(oathtool --base32 --totp "${SYNO_TOTP_SECRET}" 2>/dev/null)"
|
_info " See synology_dsm.sh script or ACME.sh Wiki page for details:"
|
||||||
else
|
_info " https://github.com/acmesh-official/acme.sh/wiki/Synology-NAS-Guide"
|
||||||
|
if ! _exists oathtool; then
|
||||||
_err "oathtool could not be found, install oathtool to use SYNO_TOTP_SECRET"
|
_err "oathtool could not be found, install oathtool to use SYNO_TOTP_SECRET"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
fi
|
DEPRECATED_otp_code="$(oathtool --base32 --totp "${SYNO_TOTP_SECRET}" 2>/dev/null)"
|
||||||
|
|
||||||
if [ -n "$SYNO_DID" ]; then
|
if [ -n "$SYNO_DID" ]; then
|
||||||
_H1="Cookie: did=$SYNO_DID"
|
_H1="Cookie: did=$SYNO_DID"
|
||||||
@ -108,28 +140,66 @@ synology_dsm_deploy() {
|
|||||||
_debug3 H1 "${_H1}"
|
_debug3 H1 "${_H1}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
response=$(_post "method=login&account=$encoded_username&passwd=$encoded_password&api=SYNO.API.Auth&version=$api_version&enable_syno_token=yes&otp_code=$otp_code" "$_base_url/webapi/auth.cgi?enable_syno_token=yes")
|
response=$(_post "method=login&account=$encoded_username&passwd=$encoded_password&api=SYNO.API.Auth&version=$api_version&enable_syno_token=yes&otp_code=$DEPRECATED_otp_code&device_name=certrenewal&device_id=$SYNO_DID" "$_base_url/webapi/auth.cgi?enable_syno_token=yes")
|
||||||
token=$(echo "$response" | grep "synotoken" | sed -n 's/.*"synotoken" *: *"\([^"]*\).*/\1/p')
|
|
||||||
_debug3 response "$response"
|
_debug3 response "$response"
|
||||||
_debug token "$token"
|
# END - DEPRECATED, only kept for legacy compatibility reasons
|
||||||
|
# If SYNO_DeviceDevice_ID & SYNO_Device_Name both empty, just log in normally
|
||||||
|
elif [ -z "${SYNO_Device_ID:-}" ] && [ -z "${SYNO_Device_Name:-}" ]; then
|
||||||
|
if [ -n "$SYNO_USE_TEMP_ADMIN" ]; then
|
||||||
|
_debug "Creating temp admin user in Synology DSM"
|
||||||
|
synouser --del "$SYNO_Username" >/dev/null 2>/dev/null
|
||||||
|
synouser --add "$SYNO_Username" "$SYNO_Password" "" 0 "" 0 >/dev/null
|
||||||
|
synogroup --memberadd administrators "$SYNO_Username" >/dev/null
|
||||||
|
fi
|
||||||
|
response=$(_get "$_base_url/webapi/entry.cgi?api=SYNO.API.Auth&version=$api_version&method=login&format=sid&account=$encoded_username&passwd=$encoded_password&enable_syno_token=yes")
|
||||||
|
_debug3 response "$response"
|
||||||
|
# Get device ID if still empty first, otherwise log in right away
|
||||||
|
# If SYNO_Device_Name is set, we treat that account enabled two-factor authorization, consider SYNO_Device_ID is not set, so it won't be able to login without requiring the OTP code.
|
||||||
|
elif [ -n "${SYNO_Device_Name:-}" ] && [ -z "${SYNO_Device_ID:-}" ]; then
|
||||||
|
printf "Enter OTP code for user '%s': " "$SYNO_Username"
|
||||||
|
read -r otp_code
|
||||||
|
response=$(_get "$_base_url/webapi/$api_path?api=SYNO.API.Auth&version=$api_version&method=login&format=sid&account=$encoded_username&passwd=$encoded_password&otp_code=$otp_code&enable_syno_token=yes&enable_device_token=yes&device_name=$SYNO_Device_Name")
|
||||||
|
_secure_debug3 response "$response"
|
||||||
|
|
||||||
if [ -z "$token" ]; then
|
id_property='device_id'
|
||||||
_err "Unable to authenticate to $SYNO_Hostname:$SYNO_Port using $SYNO_Scheme."
|
[ "${api_version}" -gt '6' ] || id_property='did'
|
||||||
_err "Check your username and password."
|
SYNO_Device_ID=$(echo "$response" | grep "$id_property" | sed -n 's/.*"'$id_property'" *: *"\([^"]*\).*/\1/p')
|
||||||
_err "If two-factor authentication is enabled for the user, set SYNO_TOTP_SECRET."
|
_secure_debug2 SYNO_Device_ID "$SYNO_Device_ID"
|
||||||
|
# Otherwise, if SYNO_Device_ID is set, we can just use it to login.
|
||||||
|
else
|
||||||
|
if [ -z "${SYNO_Device_Name:-}" ]; then
|
||||||
|
printf "Enter device name or leave empty for default (CertRenewal): "
|
||||||
|
read -r SYNO_Device_Name
|
||||||
|
[ -n "${SYNO_Device_Name}" ] || SYNO_Device_Name="CertRenewal"
|
||||||
|
fi
|
||||||
|
response=$(_get "$_base_url/webapi/$api_path?api=SYNO.API.Auth&version=$api_version&method=login&format=sid&account=$encoded_username&passwd=$encoded_password&enable_syno_token=yes&device_name=$SYNO_Device_Name&device_id=$SYNO_Device_ID")
|
||||||
|
_secure_debug3 response "$response"
|
||||||
|
fi
|
||||||
|
|
||||||
|
sid=$(echo "$response" | grep "sid" | sed -n 's/.*"sid" *: *"\([^"]*\).*/\1/p')
|
||||||
|
token=$(echo "$response" | grep "synotoken" | sed -n 's/.*"synotoken" *: *"\([^"]*\).*/\1/p')
|
||||||
|
_debug "Session ID" "$sid"
|
||||||
|
_debug SynoToken "$token"
|
||||||
|
if [ -z "$sid" ] || [ -z "$token" ]; then
|
||||||
|
_err "Unable to authenticate to $_base_url - check your username & password."
|
||||||
|
_err "If two-factor authentication is enabled for the user:"
|
||||||
|
_err "- set SYNO_Device_Name then input *correct* OTP-code manually"
|
||||||
|
_err "- get & set SYNO_Device_ID via your browser cookies"
|
||||||
|
_remove_temp_admin "$SYNO_USE_TEMP_ADMIN" "$SYNO_Username"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
sid=$(echo "$response" | grep "sid" | sed -n 's/.*"sid" *: *"\([^"]*\).*/\1/p')
|
|
||||||
|
|
||||||
_H1="X-SYNO-TOKEN: $token"
|
_H1="X-SYNO-TOKEN: $token"
|
||||||
export _H1
|
export _H1
|
||||||
_debug2 H1 "${_H1}"
|
_debug2 H1 "${_H1}"
|
||||||
|
|
||||||
# Now that we know the username and password are good, save them
|
# Now that we know the username & password are good, save them
|
||||||
_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"
|
if [ -z "${SYNO_USE_TEMP_ADMIN:-}" ]; then
|
||||||
_savedeployconf SYNO_TOTP_SECRET "$SYNO_TOTP_SECRET"
|
_savedeployconf SYNO_Device_Name "$SYNO_Device_Name"
|
||||||
|
_savedeployconf SYNO_Device_ID "$SYNO_Device_ID"
|
||||||
|
fi
|
||||||
|
|
||||||
_info "Getting certificates in Synology DSM"
|
_info "Getting certificates in Synology DSM"
|
||||||
response=$(_post "api=SYNO.Core.Certificate.CRT&method=list&version=1&_sid=$sid" "$_base_url/webapi/entry.cgi")
|
response=$(_post "api=SYNO.Core.Certificate.CRT&method=list&version=1&_sid=$sid" "$_base_url/webapi/entry.cgi")
|
||||||
@ -140,11 +210,12 @@ synology_dsm_deploy() {
|
|||||||
_debug2 id "$id"
|
_debug2 id "$id"
|
||||||
|
|
||||||
if [ -z "$id" ] && [ -z "${SYNO_Create:-}" ]; then
|
if [ -z "$id" ] && [ -z "${SYNO_Create:-}" ]; then
|
||||||
_err "Unable to find certificate: $SYNO_Certificate and \$SYNO_Create is not set"
|
_err "Unable to find certificate: $SYNO_Certificate & \$SYNO_Create is not set"
|
||||||
|
_remove_temp_admin "$SYNO_USE_TEMP_ADMIN" "$SYNO_Username"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# we've verified this certificate description is a thing, so save it
|
# We've verified this certificate description is a thing, so save it
|
||||||
_savedeployconf SYNO_Certificate "$SYNO_Certificate" "base64"
|
_savedeployconf SYNO_Certificate "$SYNO_Certificate" "base64"
|
||||||
|
|
||||||
_info "Generate form POST request"
|
_info "Generate form POST request"
|
||||||
@ -156,10 +227,10 @@ synology_dsm_deploy() {
|
|||||||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"id\"${nl}${nl}$id"
|
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"id\"${nl}${nl}$id"
|
||||||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"desc\"${nl}${nl}${SYNO_Certificate}"
|
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"desc\"${nl}${nl}${SYNO_Certificate}"
|
||||||
if echo "$response" | sed -n "s/.*\"desc\":\"$escaped_certificate\",\([^{]*\).*/\1/p" | grep -- 'is_default":true' >/dev/null; then
|
if echo "$response" | sed -n "s/.*\"desc\":\"$escaped_certificate\",\([^{]*\).*/\1/p" | grep -- 'is_default":true' >/dev/null; then
|
||||||
_debug2 default "this is the default certificate"
|
_debug2 default "This is the default certificate"
|
||||||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"as_default\"${nl}${nl}true"
|
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"as_default\"${nl}${nl}true"
|
||||||
else
|
else
|
||||||
_debug2 default "this is NOT the default certificate"
|
_debug2 default "This is NOT the default certificate"
|
||||||
fi
|
fi
|
||||||
content="$content${nl}--$delim--${nl}"
|
content="$content${nl}--$delim--${nl}"
|
||||||
content="$(printf "%b_" "$content")"
|
content="$(printf "%b_" "$content")"
|
||||||
@ -171,13 +242,34 @@ synology_dsm_deploy() {
|
|||||||
|
|
||||||
if ! echo "$response" | grep '"error":' >/dev/null; then
|
if ! echo "$response" | grep '"error":' >/dev/null; then
|
||||||
if echo "$response" | grep '"restart_httpd":true' >/dev/null; then
|
if echo "$response" | grep '"restart_httpd":true' >/dev/null; then
|
||||||
_info "http services were restarted"
|
_info "Restarting HTTP services succeeded"
|
||||||
else
|
else
|
||||||
_info "http services were NOT restarted"
|
_info "Restarting HTTP services failed"
|
||||||
fi
|
fi
|
||||||
|
_remove_temp_admin "$SYNO_USE_TEMP_ADMIN" "$SYNO_Username"
|
||||||
|
_logout
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
|
_remove_temp_admin "$SYNO_USE_TEMP_ADMIN" "$SYNO_Username"
|
||||||
_err "Unable to update certificate, error code $response"
|
_err "Unable to update certificate, error code $response"
|
||||||
|
_logout
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#################### Private functions below ##################################
|
||||||
|
_logout() {
|
||||||
|
# Logout CERT user only to not occupy a permanent session, e.g. in DSM's "Connected Users" widget (based on previous variables)
|
||||||
|
response=$(_get "$_base_url/webapi/$api_path?api=SYNO.API.Auth&version=$api_version&method=logout&_sid=$sid")
|
||||||
|
_debug3 response "$response"
|
||||||
|
}
|
||||||
|
|
||||||
|
_remove_temp_admin() {
|
||||||
|
flag=$1
|
||||||
|
username=$2
|
||||||
|
|
||||||
|
if [ -n "${flag}" ]; then
|
||||||
|
_debug "Removing temp admin user in Synology DSM"
|
||||||
|
synouser --del "$username" >/dev/null
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
@ -184,6 +184,27 @@ truenas_deploy() {
|
|||||||
_info "S3 certificate is not configured or is not the same as TrueNAS web UI"
|
_info "S3 certificate is not configured or is not the same as TrueNAS web UI"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
_info "Checking if any chart release Apps is using the same certificate as TrueNAS web UI. Tool 'jq' is required"
|
||||||
|
if _exists jq; then
|
||||||
|
_info "Query all chart release"
|
||||||
|
_release_list=$(_get "$_api_url/chart/release")
|
||||||
|
_related_name_list=$(printf "%s" "$_release_list" | jq -r "[.[] | {name,certId: .config.ingress?.main.tls[]?.scaleCert} | select(.certId==$_active_cert_id) | .name ] | unique")
|
||||||
|
_release_length=$(printf "%s" "$_related_name_list" | jq -r "length")
|
||||||
|
_info "Found $_release_length related chart release in list: $_related_name_list"
|
||||||
|
for i in $(seq 0 $((_release_length - 1))); do
|
||||||
|
_release_name=$(echo "$_related_name_list" | jq -r ".[$i]")
|
||||||
|
_info "Updating certificate from $_active_cert_id to $_cert_id for chart release: $_release_name"
|
||||||
|
#Read the chart release configuration
|
||||||
|
_chart_config=$(printf "%s" "$_release_list" | jq -r ".[] | select(.name==\"$_release_name\")")
|
||||||
|
#Replace the old certificate id with the new one in path .config.ingress.main.tls[].scaleCert. Then update .config.ingress
|
||||||
|
_updated_chart_config=$(printf "%s" "$_chart_config" | jq "(.config.ingress?.main.tls[]? | select(.scaleCert==$_active_cert_id) | .scaleCert ) |= $_cert_id | .config.ingress ")
|
||||||
|
_update_chart_result="$(_post "{\"values\" : { \"ingress\" : $_updated_chart_config } }" "$_api_url/chart/release/id/$_release_name" "" "PUT" "application/json")"
|
||||||
|
_debug3 _update_chart_result "$_update_chart_result"
|
||||||
|
done
|
||||||
|
else
|
||||||
|
_info "Tool 'jq' does not exists, skip chart release checking"
|
||||||
|
fi
|
||||||
|
|
||||||
_info "Deleting old certificate"
|
_info "Deleting old certificate"
|
||||||
_delete_result="$(_post "" "$_api_url/certificate/id/$_active_cert_id" "" "DELETE" "application/json")"
|
_delete_result="$(_post "" "$_api_url/certificate/id/$_active_cert_id" "" "DELETE" "application/json")"
|
||||||
|
|
||||||
|
@ -7,6 +7,9 @@
|
|||||||
#
|
#
|
||||||
# VAULT_PREFIX - this contains the prefix path in vault
|
# VAULT_PREFIX - this contains the prefix path in vault
|
||||||
# VAULT_ADDR - vault requires this to find your vault server
|
# VAULT_ADDR - vault requires this to find your vault server
|
||||||
|
# VAULT_SAVE_TOKEN - set to anything if you want to save the token
|
||||||
|
# VAULT_RENEW_TOKEN - set to anything if you want to renew the token to default TTL before deploying
|
||||||
|
# VAULT_KV_V2 - set to anything if you are using v2 of the kv engine
|
||||||
#
|
#
|
||||||
# additionally, you need to ensure that VAULT_TOKEN is avialable
|
# additionally, you need to ensure that VAULT_TOKEN is avialable
|
||||||
# to access the vault server
|
# to access the vault server
|
||||||
@ -45,6 +48,26 @@ vault_deploy() {
|
|||||||
fi
|
fi
|
||||||
_savedeployconf VAULT_ADDR "$VAULT_ADDR"
|
_savedeployconf VAULT_ADDR "$VAULT_ADDR"
|
||||||
|
|
||||||
|
_getdeployconf VAULT_SAVE_TOKEN
|
||||||
|
_savedeployconf VAULT_SAVE_TOKEN "$VAULT_SAVE_TOKEN"
|
||||||
|
|
||||||
|
_getdeployconf VAULT_RENEW_TOKEN
|
||||||
|
_savedeployconf VAULT_RENEW_TOKEN "$VAULT_RENEW_TOKEN"
|
||||||
|
|
||||||
|
_getdeployconf VAULT_KV_V2
|
||||||
|
_savedeployconf VAULT_KV_V2 "$VAULT_KV_V2"
|
||||||
|
|
||||||
|
_getdeployconf VAULT_TOKEN
|
||||||
|
if [ -z "$VAULT_TOKEN" ]; then
|
||||||
|
_err "VAULT_TOKEN needs to be defined"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
if [ -n "$VAULT_SAVE_TOKEN" ]; then
|
||||||
|
_savedeployconf VAULT_TOKEN "$VAULT_TOKEN"
|
||||||
|
fi
|
||||||
|
|
||||||
|
_migratedeployconf FABIO VAULT_FABIO_MODE
|
||||||
|
|
||||||
# JSON does not allow multiline strings.
|
# JSON does not allow multiline strings.
|
||||||
# So replacing new-lines with "\n" here
|
# So replacing new-lines with "\n" here
|
||||||
_ckey=$(sed -z 's/\n/\\n/g' <"$2")
|
_ckey=$(sed -z 's/\n/\\n/g' <"$2")
|
||||||
@ -52,26 +75,56 @@ vault_deploy() {
|
|||||||
_cca=$(sed -z 's/\n/\\n/g' <"$4")
|
_cca=$(sed -z 's/\n/\\n/g' <"$4")
|
||||||
_cfullchain=$(sed -z 's/\n/\\n/g' <"$5")
|
_cfullchain=$(sed -z 's/\n/\\n/g' <"$5")
|
||||||
|
|
||||||
URL="$VAULT_ADDR/v1/$VAULT_PREFIX/$_cdomain"
|
|
||||||
export _H1="X-Vault-Token: $VAULT_TOKEN"
|
export _H1="X-Vault-Token: $VAULT_TOKEN"
|
||||||
|
|
||||||
if [ -n "$FABIO" ]; then
|
if [ -n "$VAULT_RENEW_TOKEN" ]; then
|
||||||
|
URL="$VAULT_ADDR/v1/auth/token/renew-self"
|
||||||
|
_info "Renew the Vault token to default TTL"
|
||||||
|
if ! _post "" "$URL" >/dev/null; then
|
||||||
|
_err "Failed to renew the Vault token"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
URL="$VAULT_ADDR/v1/$VAULT_PREFIX/$_cdomain"
|
||||||
|
|
||||||
|
if [ -n "$VAULT_FABIO_MODE" ]; then
|
||||||
|
_info "Writing certificate and key to $URL in Fabio mode"
|
||||||
if [ -n "$VAULT_KV_V2" ]; then
|
if [ -n "$VAULT_KV_V2" ]; then
|
||||||
_post "{ \"data\": {\"cert\": \"$_cfullchain\", \"key\": \"$_ckey\"} }" "$URL"
|
_post "{ \"data\": {\"cert\": \"$_cfullchain\", \"key\": \"$_ckey\"} }" "$URL" >/dev/null || return 1
|
||||||
else
|
else
|
||||||
_post "{\"cert\": \"$_cfullchain\", \"key\": \"$_ckey\"}" "$URL"
|
_post "{\"cert\": \"$_cfullchain\", \"key\": \"$_ckey\"}" "$URL" >/dev/null || return 1
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
if [ -n "$VAULT_KV_V2" ]; then
|
if [ -n "$VAULT_KV_V2" ]; then
|
||||||
_post "{\"data\": {\"value\": \"$_ccert\"}}" "$URL/cert.pem"
|
_info "Writing certificate to $URL/cert.pem"
|
||||||
_post "{\"data\": {\"value\": \"$_ckey\"}}" "$URL/cert.key"
|
_post "{\"data\": {\"value\": \"$_ccert\"}}" "$URL/cert.pem" >/dev/null || return 1
|
||||||
_post "{\"data\": {\"value\": \"$_cca\"}}" "$URL/chain.pem"
|
_info "Writing key to $URL/cert.key"
|
||||||
_post "{\"data\": {\"value\": \"$_cfullchain\"}}" "$URL/fullchain.pem"
|
_post "{\"data\": {\"value\": \"$_ckey\"}}" "$URL/cert.key" >/dev/null || return 1
|
||||||
|
_info "Writing CA certificate to $URL/ca.pem"
|
||||||
|
_post "{\"data\": {\"value\": \"$_cca\"}}" "$URL/ca.pem" >/dev/null || return 1
|
||||||
|
_info "Writing full-chain certificate to $URL/fullchain.pem"
|
||||||
|
_post "{\"data\": {\"value\": \"$_cfullchain\"}}" "$URL/fullchain.pem" >/dev/null || return 1
|
||||||
else
|
else
|
||||||
_post "{\"value\": \"$_ccert\"}" "$URL/cert.pem"
|
_info "Writing certificate to $URL/cert.pem"
|
||||||
_post "{\"value\": \"$_ckey\"}" "$URL/cert.key"
|
_post "{\"value\": \"$_ccert\"}" "$URL/cert.pem" >/dev/null || return 1
|
||||||
_post "{\"value\": \"$_cca\"}" "$URL/chain.pem"
|
_info "Writing key to $URL/cert.key"
|
||||||
_post "{\"value\": \"$_cfullchain\"}" "$URL/fullchain.pem"
|
_post "{\"value\": \"$_ckey\"}" "$URL/cert.key" >/dev/null || return 1
|
||||||
|
_info "Writing CA certificate to $URL/ca.pem"
|
||||||
|
_post "{\"value\": \"$_cca\"}" "$URL/ca.pem" >/dev/null || return 1
|
||||||
|
_info "Writing full-chain certificate to $URL/fullchain.pem"
|
||||||
|
_post "{\"value\": \"$_cfullchain\"}" "$URL/fullchain.pem" >/dev/null || return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# To make it compatible with the wrong ca path `chain.pem` which was used in former versions
|
||||||
|
if _contains "$(_get "$URL/chain.pem")" "-----BEGIN CERTIFICATE-----"; then
|
||||||
|
_err "The CA certificate has moved from chain.pem to ca.pem, if you don't depend on chain.pem anymore, you can delete it to avoid this warning"
|
||||||
|
_info "Updating CA certificate to $URL/chain.pem for backward compatibility"
|
||||||
|
if [ -n "$VAULT_KV_V2" ]; then
|
||||||
|
_post "{\"data\": {\"value\": \"$_cca\"}}" "$URL/chain.pem" >/dev/null || return 1
|
||||||
|
else
|
||||||
|
_post "{\"value\": \"$_cca\"}" "$URL/chain.pem" >/dev/null || return 1
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
#
|
#
|
||||||
# VAULT_PREFIX - this contains the prefix path in vault
|
# VAULT_PREFIX - this contains the prefix path in vault
|
||||||
# VAULT_ADDR - vault requires this to find your vault server
|
# VAULT_ADDR - vault requires this to find your vault server
|
||||||
|
# VAULT_SAVE_TOKEN - set to anything if you want to save the token
|
||||||
|
# VAULT_RENEW_TOKEN - set to anything if you want to renew the token to default TTL before deploying
|
||||||
#
|
#
|
||||||
# additionally, you need to ensure that VAULT_TOKEN is avialable or
|
# additionally, you need to ensure that VAULT_TOKEN is avialable or
|
||||||
# `vault auth` has applied the appropriate authorization for the vault binary
|
# `vault auth` has applied the appropriate authorization for the vault binary
|
||||||
@ -33,15 +35,36 @@ vault_cli_deploy() {
|
|||||||
_debug _cfullchain "$_cfullchain"
|
_debug _cfullchain "$_cfullchain"
|
||||||
|
|
||||||
# validate required env vars
|
# validate required env vars
|
||||||
|
_getdeployconf VAULT_PREFIX
|
||||||
if [ -z "$VAULT_PREFIX" ]; then
|
if [ -z "$VAULT_PREFIX" ]; then
|
||||||
_err "VAULT_PREFIX needs to be defined (contains prefix path in vault)"
|
_err "VAULT_PREFIX needs to be defined (contains prefix path in vault)"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
_savedeployconf VAULT_PREFIX "$VAULT_PREFIX"
|
||||||
|
|
||||||
|
_getdeployconf VAULT_ADDR
|
||||||
if [ -z "$VAULT_ADDR" ]; then
|
if [ -z "$VAULT_ADDR" ]; then
|
||||||
_err "VAULT_ADDR needs to be defined (contains vault connection address)"
|
_err "VAULT_ADDR needs to be defined (contains vault connection address)"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
_savedeployconf VAULT_ADDR "$VAULT_ADDR"
|
||||||
|
|
||||||
|
_getdeployconf VAULT_SAVE_TOKEN
|
||||||
|
_savedeployconf VAULT_SAVE_TOKEN "$VAULT_SAVE_TOKEN"
|
||||||
|
|
||||||
|
_getdeployconf VAULT_RENEW_TOKEN
|
||||||
|
_savedeployconf VAULT_RENEW_TOKEN "$VAULT_RENEW_TOKEN"
|
||||||
|
|
||||||
|
_getdeployconf VAULT_TOKEN
|
||||||
|
if [ -z "$VAULT_TOKEN" ]; then
|
||||||
|
_err "VAULT_TOKEN needs to be defined"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
if [ -n "$VAULT_SAVE_TOKEN" ]; then
|
||||||
|
_savedeployconf VAULT_TOKEN "$VAULT_TOKEN"
|
||||||
|
fi
|
||||||
|
|
||||||
|
_migratedeployconf FABIO VAULT_FABIO_MODE
|
||||||
|
|
||||||
VAULT_CMD=$(command -v vault)
|
VAULT_CMD=$(command -v vault)
|
||||||
if [ ! $? ]; then
|
if [ ! $? ]; then
|
||||||
@ -49,13 +72,33 @@ vault_cli_deploy() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -n "$FABIO" ]; then
|
if [ -n "$VAULT_RENEW_TOKEN" ]; then
|
||||||
|
_info "Renew the Vault token to default TTL"
|
||||||
|
if ! $VAULT_CMD token renew; then
|
||||||
|
_err "Failed to renew the Vault token"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$VAULT_FABIO_MODE" ]; then
|
||||||
|
_info "Writing certificate and key to ${VAULT_PREFIX}/${_cdomain} in Fabio mode"
|
||||||
$VAULT_CMD kv put "${VAULT_PREFIX}/${_cdomain}" cert=@"$_cfullchain" key=@"$_ckey" || return 1
|
$VAULT_CMD kv put "${VAULT_PREFIX}/${_cdomain}" cert=@"$_cfullchain" key=@"$_ckey" || return 1
|
||||||
else
|
else
|
||||||
|
_info "Writing certificate to ${VAULT_PREFIX}/${_cdomain}/cert.pem"
|
||||||
$VAULT_CMD kv put "${VAULT_PREFIX}/${_cdomain}/cert.pem" value=@"$_ccert" || return 1
|
$VAULT_CMD kv put "${VAULT_PREFIX}/${_cdomain}/cert.pem" value=@"$_ccert" || return 1
|
||||||
|
_info "Writing key to ${VAULT_PREFIX}/${_cdomain}/cert.key"
|
||||||
$VAULT_CMD kv put "${VAULT_PREFIX}/${_cdomain}/cert.key" value=@"$_ckey" || return 1
|
$VAULT_CMD kv put "${VAULT_PREFIX}/${_cdomain}/cert.key" value=@"$_ckey" || return 1
|
||||||
$VAULT_CMD kv put "${VAULT_PREFIX}/${_cdomain}/chain.pem" value=@"$_cca" || return 1
|
_info "Writing CA certificate to ${VAULT_PREFIX}/${_cdomain}/ca.pem"
|
||||||
|
$VAULT_CMD kv put "${VAULT_PREFIX}/${_cdomain}/ca.pem" value=@"$_cca" || return 1
|
||||||
|
_info "Writing full-chain certificate to ${VAULT_PREFIX}/${_cdomain}/fullchain.pem"
|
||||||
$VAULT_CMD kv put "${VAULT_PREFIX}/${_cdomain}/fullchain.pem" value=@"$_cfullchain" || return 1
|
$VAULT_CMD kv put "${VAULT_PREFIX}/${_cdomain}/fullchain.pem" value=@"$_cfullchain" || return 1
|
||||||
|
|
||||||
|
# To make it compatible with the wrong ca path `chain.pem` which was used in former versions
|
||||||
|
if $VAULT_CMD kv get "${VAULT_PREFIX}/${_cdomain}/chain.pem" >/dev/null; then
|
||||||
|
_err "The CA certificate has moved from chain.pem to ca.pem, if you don't depend on chain.pem anymore, you can delete it to avoid this warning"
|
||||||
|
_info "Updating CA certificate to ${VAULT_PREFIX}/${_cdomain}/chain.pem for backward compatibility"
|
||||||
|
$VAULT_CMD kv put "${VAULT_PREFIX}/${_cdomain}/chain.pem" value=@"$_cca" || return 1
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
# Author: Adrian Fedoreanu
|
# Author: Adrian Fedoreanu
|
||||||
# Report Bugs here: https://github.com/acmesh-official/acme.sh
|
# Report Bugs here: https://github.com/acmesh-official/acme.sh
|
||||||
# or here... https://github.com/acmesh-official/acme.sh/issues/2851
|
# or here... https://github.com/acmesh-official/acme.sh/issues/2851
|
||||||
#
|
|
||||||
######## Public functions #####################
|
######## Public functions #####################
|
||||||
|
|
||||||
# Export 1984HOSTING username and password in following variables
|
# Export 1984HOSTING username and password in following variables
|
||||||
@ -15,32 +15,32 @@
|
|||||||
# One984HOSTING_Username=username
|
# One984HOSTING_Username=username
|
||||||
# One984HOSTING_Password=password
|
# One984HOSTING_Password=password
|
||||||
#
|
#
|
||||||
# sessionid cookie is saved in ~/.acme.sh/account.conf
|
# username/password and csrftoken/sessionid cookies are saved in ~/.acme.sh/account.conf
|
||||||
# username/password need to be set only when changed.
|
|
||||||
|
|
||||||
# Usage: dns_1984hosting_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
# Usage: dns_1984hosting_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||||
|
# Add a text record.
|
||||||
dns_1984hosting_add() {
|
dns_1984hosting_add() {
|
||||||
fulldomain=$1
|
fulldomain=$1
|
||||||
txtvalue=$2
|
txtvalue=$2
|
||||||
|
|
||||||
_info "Add TXT record using 1984Hosting"
|
_info "Add TXT record using 1984Hosting."
|
||||||
_debug fulldomain "$fulldomain"
|
_debug fulldomain "$fulldomain"
|
||||||
_debug txtvalue "$txtvalue"
|
_debug txtvalue "$txtvalue"
|
||||||
|
|
||||||
if ! _1984hosting_login; then
|
if ! _1984hosting_login; then
|
||||||
_err "1984Hosting login failed for user $One984HOSTING_Username. Check $HTTP_HEADER file"
|
_err "1984Hosting login failed for user $One984HOSTING_Username. Check $HTTP_HEADER file."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_debug "First detect the root zone"
|
_debug "First detect the root zone."
|
||||||
if ! _get_root "$fulldomain"; then
|
if ! _get_root "$fulldomain"; then
|
||||||
_err "invalid domain" "$fulldomain"
|
_err "Invalid domain '$fulldomain'."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
_debug _sub_domain "$_sub_domain"
|
_debug _sub_domain "$_sub_domain"
|
||||||
_debug _domain "$_domain"
|
_debug _domain "$_domain"
|
||||||
|
|
||||||
_debug "Add TXT record $fulldomain with value '$txtvalue'"
|
_debug "Add TXT record $fulldomain with value '$txtvalue'."
|
||||||
value="$(printf '%s' "$txtvalue" | _url_encode)"
|
value="$(printf '%s' "$txtvalue" | _url_encode)"
|
||||||
url="https://1984.hosting/domains/entry/"
|
url="https://1984.hosting/domains/entry/"
|
||||||
|
|
||||||
@ -53,21 +53,18 @@ dns_1984hosting_add() {
|
|||||||
_debug2 postdata "$postdata"
|
_debug2 postdata "$postdata"
|
||||||
|
|
||||||
_authpost "$postdata" "$url"
|
_authpost "$postdata" "$url"
|
||||||
response="$(echo "$_response" | _normalizeJson)"
|
if _contains "$_response" '"haserrors": true'; then
|
||||||
_debug2 response "$response"
|
_err "1984Hosting failed to add TXT record for $_sub_domain bad RC from _post."
|
||||||
|
|
||||||
if _contains "$response" '"haserrors": true'; then
|
|
||||||
_err "1984Hosting failed to add TXT record for $_sub_domain bad RC from _post"
|
|
||||||
return 1
|
return 1
|
||||||
elif _contains "$response" "html>"; then
|
elif _contains "$_response" "html>"; then
|
||||||
_err "1984Hosting failed to add TXT record for $_sub_domain. Check $HTTP_HEADER file"
|
_err "1984Hosting failed to add TXT record for $_sub_domain. Check $HTTP_HEADER file."
|
||||||
return 1
|
return 1
|
||||||
elif _contains "$response" '"auth": false'; then
|
elif _contains "$_response" '"auth": false'; then
|
||||||
_err "1984Hosting failed to add TXT record for $_sub_domain. Invalid or expired cookie"
|
_err "1984Hosting failed to add TXT record for $_sub_domain. Invalid or expired cookie."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_info "Added acme challenge TXT record for $fulldomain at 1984Hosting"
|
_info "Added acme challenge TXT record for $fulldomain at 1984Hosting."
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,68 +74,75 @@ dns_1984hosting_rm() {
|
|||||||
fulldomain=$1
|
fulldomain=$1
|
||||||
txtvalue=$2
|
txtvalue=$2
|
||||||
|
|
||||||
_info "Delete TXT record using 1984Hosting"
|
_info "Delete TXT record using 1984Hosting."
|
||||||
_debug fulldomain "$fulldomain"
|
_debug fulldomain "$fulldomain"
|
||||||
_debug txtvalue "$txtvalue"
|
_debug txtvalue "$txtvalue"
|
||||||
|
|
||||||
if ! _1984hosting_login; then
|
if ! _1984hosting_login; then
|
||||||
_err "1984Hosting login failed for user $One984HOSTING_Username. Check $HTTP_HEADER file"
|
_err "1984Hosting login failed for user $One984HOSTING_Username. Check $HTTP_HEADER file."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_debug "First detect the root zone"
|
_debug "First detect the root zone."
|
||||||
if ! _get_root "$fulldomain"; then
|
if ! _get_root "$fulldomain"; then
|
||||||
_err "invalid domain" "$fulldomain"
|
_err "Invalid domain '$fulldomain'."
|
||||||
return 1
|
return 1
|
||||||
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://1984.hosting/domains"
|
url="https://1984.hosting/domains"
|
||||||
if ! _get_zone_id "$url" "$_domain"; then
|
if ! _get_zone_id "$url" "$_domain"; then
|
||||||
_err "invalid zone" "$_domain"
|
_err "Invalid zone '$_domain'."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_htmlget "$url/$_zone_id" "$txtvalue"
|
_htmlget "$url/$_zone_id" "$txtvalue"
|
||||||
_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"
|
||||||
if [ -z "$entry_id" ]; then
|
if [ -z "$entry_id" ]; then
|
||||||
_err "Error getting TXT entry_id for $1"
|
_err "Error getting TXT entry_id for $1."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_authpost "entry=$entry_id" "$url/delentry/"
|
_authpost "entry=$entry_id" "$url/delentry/"
|
||||||
response="$(echo "$_response" | _normalizeJson)"
|
if ! _contains "$_response" '"ok": true'; then
|
||||||
_debug2 response "$response"
|
_err "1984Hosting failed to delete TXT record for $entry_id bad RC from _post."
|
||||||
|
|
||||||
if ! _contains "$response" '"ok": true'; then
|
|
||||||
_err "1984Hosting failed to delete TXT record for $entry_id bad RC from _post"
|
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_info "Deleted acme challenge TXT record for $fulldomain at 1984Hosting"
|
_info "Deleted acme challenge TXT record for $fulldomain at 1984Hosting."
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
#################### Private functions below ##################################
|
#################### Private functions below ##################################
|
||||||
|
|
||||||
# usage: _1984hosting_login username password
|
|
||||||
# returns 0 success
|
|
||||||
_1984hosting_login() {
|
_1984hosting_login() {
|
||||||
if ! _check_credentials; then return 1; fi
|
if ! _check_credentials; then return 1; fi
|
||||||
|
|
||||||
if _check_cookies; then
|
if _check_cookies; then
|
||||||
_debug "Already logged in"
|
_debug "Already logged in."
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_debug "Login to 1984Hosting as user $One984HOSTING_Username"
|
_debug "Login to 1984Hosting as user $One984HOSTING_Username."
|
||||||
username=$(printf '%s' "$One984HOSTING_Username" | _url_encode)
|
username=$(printf '%s' "$One984HOSTING_Username" | _url_encode)
|
||||||
password=$(printf '%s' "$One984HOSTING_Password" | _url_encode)
|
password=$(printf '%s' "$One984HOSTING_Password" | _url_encode)
|
||||||
url="https://1984.hosting/accounts/checkuserauth/"
|
url="https://1984.hosting/api/auth/"
|
||||||
|
|
||||||
|
_get "https://1984.hosting/accounts/login/" | grep "csrfmiddlewaretoken"
|
||||||
|
csrftoken="$(grep -i '^set-cookie:' "$HTTP_HEADER" | _egrep_o 'csrftoken=[^;]*;' | tr -d ';')"
|
||||||
|
sessionid="$(grep -i '^set-cookie:' "$HTTP_HEADER" | _egrep_o 'sessionid=[^;]*;' | tr -d ';')"
|
||||||
|
|
||||||
|
if [ -z "$csrftoken" ] || [ -z "$sessionid" ]; then
|
||||||
|
_err "One or more cookies are empty: '$csrftoken', '$sessionid'."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
export _H1="Cookie: $csrftoken; $sessionid"
|
||||||
|
export _H2="Referer: https://1984.hosting/accounts/login/"
|
||||||
|
csrf_header=$(echo "$csrftoken" | sed 's/csrftoken=//' | _head_n 1)
|
||||||
|
export _H3="X-CSRFToken: $csrf_header"
|
||||||
|
|
||||||
response="$(_post "username=$username&password=$password&otpkey=" $url)"
|
response="$(_post "username=$username&password=$password&otpkey=" $url)"
|
||||||
response="$(echo "$response" | _normalizeJson)"
|
response="$(echo "$response" | _normalizeJson)"
|
||||||
@ -149,6 +153,8 @@ _1984hosting_login() {
|
|||||||
One984HOSTING_CSRFTOKEN_COOKIE="$(grep -i '^set-cookie:' "$HTTP_HEADER" | _egrep_o 'csrftoken=[^;]*;' | tr -d ';')"
|
One984HOSTING_CSRFTOKEN_COOKIE="$(grep -i '^set-cookie:' "$HTTP_HEADER" | _egrep_o 'csrftoken=[^;]*;' | tr -d ';')"
|
||||||
export One984HOSTING_SESSIONID_COOKIE
|
export One984HOSTING_SESSIONID_COOKIE
|
||||||
export One984HOSTING_CSRFTOKEN_COOKIE
|
export One984HOSTING_CSRFTOKEN_COOKIE
|
||||||
|
_saveaccountconf_mutable One984HOSTING_Username "$One984HOSTING_Username"
|
||||||
|
_saveaccountconf_mutable One984HOSTING_Password "$One984HOSTING_Password"
|
||||||
_saveaccountconf_mutable One984HOSTING_SESSIONID_COOKIE "$One984HOSTING_SESSIONID_COOKIE"
|
_saveaccountconf_mutable One984HOSTING_SESSIONID_COOKIE "$One984HOSTING_SESSIONID_COOKIE"
|
||||||
_saveaccountconf_mutable One984HOSTING_CSRFTOKEN_COOKIE "$One984HOSTING_CSRFTOKEN_COOKIE"
|
_saveaccountconf_mutable One984HOSTING_CSRFTOKEN_COOKIE "$One984HOSTING_CSRFTOKEN_COOKIE"
|
||||||
return 0
|
return 0
|
||||||
@ -157,9 +163,13 @@ _1984hosting_login() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_check_credentials() {
|
_check_credentials() {
|
||||||
|
One984HOSTING_Username="${One984HOSTING_Username:-$(_readaccountconf_mutable One984HOSTING_Username)}"
|
||||||
|
One984HOSTING_Password="${One984HOSTING_Password:-$(_readaccountconf_mutable One984HOSTING_Password)}"
|
||||||
if [ -z "$One984HOSTING_Username" ] || [ -z "$One984HOSTING_Password" ]; then
|
if [ -z "$One984HOSTING_Username" ] || [ -z "$One984HOSTING_Password" ]; then
|
||||||
One984HOSTING_Username=""
|
One984HOSTING_Username=""
|
||||||
One984HOSTING_Password=""
|
One984HOSTING_Password=""
|
||||||
|
_clearaccountconf_mutable One984HOSTING_Username
|
||||||
|
_clearaccountconf_mutable One984HOSTING_Password
|
||||||
_err "You haven't specified 1984Hosting username or password yet."
|
_err "You haven't specified 1984Hosting username or password yet."
|
||||||
_err "Please export as One984HOSTING_Username / One984HOSTING_Password and try again."
|
_err "Please export as One984HOSTING_Username / One984HOSTING_Password and try again."
|
||||||
return 1
|
return 1
|
||||||
@ -171,25 +181,26 @@ _check_cookies() {
|
|||||||
One984HOSTING_SESSIONID_COOKIE="${One984HOSTING_SESSIONID_COOKIE:-$(_readaccountconf_mutable One984HOSTING_SESSIONID_COOKIE)}"
|
One984HOSTING_SESSIONID_COOKIE="${One984HOSTING_SESSIONID_COOKIE:-$(_readaccountconf_mutable One984HOSTING_SESSIONID_COOKIE)}"
|
||||||
One984HOSTING_CSRFTOKEN_COOKIE="${One984HOSTING_CSRFTOKEN_COOKIE:-$(_readaccountconf_mutable One984HOSTING_CSRFTOKEN_COOKIE)}"
|
One984HOSTING_CSRFTOKEN_COOKIE="${One984HOSTING_CSRFTOKEN_COOKIE:-$(_readaccountconf_mutable One984HOSTING_CSRFTOKEN_COOKIE)}"
|
||||||
if [ -z "$One984HOSTING_SESSIONID_COOKIE" ] || [ -z "$One984HOSTING_CSRFTOKEN_COOKIE" ]; then
|
if [ -z "$One984HOSTING_SESSIONID_COOKIE" ] || [ -z "$One984HOSTING_CSRFTOKEN_COOKIE" ]; then
|
||||||
_debug "No cached cookie(s) found"
|
_debug "No cached cookie(s) found."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_authget "https://1984.hosting/accounts/loginstatus/"
|
_authget "https://1984.hosting/api/auth/"
|
||||||
if _contains "$response" '"ok": true'; then
|
if _contains "$_response" '"ok": true'; then
|
||||||
_debug "Cached cookies still valid"
|
_debug "Cached cookies still valid."
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
_debug "Cached cookies no longer valid"
|
|
||||||
|
_debug "Cached cookies no longer valid. Clearing cookies."
|
||||||
One984HOSTING_SESSIONID_COOKIE=""
|
One984HOSTING_SESSIONID_COOKIE=""
|
||||||
One984HOSTING_CSRFTOKEN_COOKIE=""
|
One984HOSTING_CSRFTOKEN_COOKIE=""
|
||||||
_saveaccountconf_mutable One984HOSTING_SESSIONID_COOKIE "$One984HOSTING_SESSIONID_COOKIE"
|
_clearaccountconf_mutable One984HOSTING_SESSIONID_COOKIE
|
||||||
_saveaccountconf_mutable One984HOSTING_CSRFTOKEN_COOKIE "$One984HOSTING_CSRFTOKEN_COOKIE"
|
_clearaccountconf_mutable One984HOSTING_CSRFTOKEN_COOKIE
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# _acme-challenge.www.domain.com
|
# _acme-challenge.www.domain.com
|
||||||
#returns
|
# Returns
|
||||||
# _sub_domain=_acme-challenge.www
|
# _sub_domain=_acme-challenge.www
|
||||||
# _domain=domain.com
|
# _domain=domain.com
|
||||||
_get_root() {
|
_get_root() {
|
||||||
@ -197,16 +208,16 @@ _get_root() {
|
|||||||
i=1
|
i=1
|
||||||
p=1
|
p=1
|
||||||
while true; do
|
while true; do
|
||||||
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
|
||||||
|
|
||||||
if [ -z "$h" ]; then
|
|
||||||
# not valid
|
# not valid
|
||||||
|
if [ -z "$h" ]; then
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_authget "https://1984.hosting/domains/soacheck/?zone=$h&nameserver=ns0.1984.is."
|
_authget "https://1984.hosting/domains/soacheck/?zone=$h&nameserver=ns0.1984.is."
|
||||||
if _contains "$_response" "serial" && ! _contains "$_response" "null"; then
|
if _contains "$_response" "serial" && ! _contains "$_response" "null"; then
|
||||||
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
|
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
|
||||||
_domain="$h"
|
_domain="$h"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
@ -216,40 +227,40 @@ _get_root() {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
#usage: _get_zone_id url domain.com
|
# Usage: _get_zone_id url domain.com
|
||||||
#returns zone id for domain.com
|
# Returns zone id for domain.com
|
||||||
_get_zone_id() {
|
_get_zone_id() {
|
||||||
url=$1
|
url=$1
|
||||||
domain=$2
|
domain=$2
|
||||||
_htmlget "$url" "$domain"
|
_htmlget "$url" "$domain"
|
||||||
_debug2 _response "$_response"
|
|
||||||
_zone_id="$(echo "$_response" | _egrep_o 'zone\/[0-9]+' | _head_n 1)"
|
_zone_id="$(echo "$_response" | _egrep_o 'zone\/[0-9]+' | _head_n 1)"
|
||||||
_debug2 _zone_id "$_zone_id"
|
_debug2 _zone_id "$_zone_id"
|
||||||
if [ -z "$_zone_id" ]; then
|
if [ -z "$_zone_id" ]; then
|
||||||
_err "Error getting _zone_id for $2"
|
_err "Error getting _zone_id for $2."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
# add extra headers to request
|
# Add extra headers to request
|
||||||
_authget() {
|
_authget() {
|
||||||
export _H1="Cookie: $One984HOSTING_CSRFTOKEN_COOKIE; $One984HOSTING_SESSIONID_COOKIE"
|
export _H1="Cookie: $One984HOSTING_CSRFTOKEN_COOKIE; $One984HOSTING_SESSIONID_COOKIE"
|
||||||
_response=$(_get "$1" | _normalizeJson)
|
_response=$(_get "$1" | _normalizeJson)
|
||||||
_debug2 _response "$_response"
|
_debug2 _response "$_response"
|
||||||
}
|
}
|
||||||
|
|
||||||
# truncate huge HTML response
|
# Truncate huge HTML response
|
||||||
# echo: Argument list too long
|
# Echo: Argument list too long
|
||||||
_htmlget() {
|
_htmlget() {
|
||||||
export _H1="Cookie: $One984HOSTING_CSRFTOKEN_COOKIE; $One984HOSTING_SESSIONID_COOKIE"
|
export _H1="Cookie: $One984HOSTING_CSRFTOKEN_COOKIE; $One984HOSTING_SESSIONID_COOKIE"
|
||||||
_response=$(_get "$1" | grep "$2")
|
_response=$(_get "$1" | grep "$2")
|
||||||
if _contains "$_response" "@$2"; then
|
if _contains "$_response" "@$2"; then
|
||||||
_response=$(echo "$_response" | grep -v "[@]" | _head_n 1)
|
_response=$(echo "$_response" | grep -v "[@]" | _head_n 1)
|
||||||
fi
|
fi
|
||||||
|
_debug2 _response "$_response"
|
||||||
}
|
}
|
||||||
|
|
||||||
# add extra headers to request
|
# Add extra headers to request
|
||||||
_authpost() {
|
_authpost() {
|
||||||
url="https://1984.hosting/domains"
|
url="https://1984.hosting/domains"
|
||||||
_get_zone_id "$url" "$_domain"
|
_get_zone_id "$url" "$_domain"
|
||||||
@ -257,5 +268,6 @@ _authpost() {
|
|||||||
export _H1="Cookie: $One984HOSTING_CSRFTOKEN_COOKIE; $One984HOSTING_SESSIONID_COOKIE"
|
export _H1="Cookie: $One984HOSTING_CSRFTOKEN_COOKIE; $One984HOSTING_SESSIONID_COOKIE"
|
||||||
export _H2="Referer: https://1984.hosting/domains/$_zone_id"
|
export _H2="Referer: https://1984.hosting/domains/$_zone_id"
|
||||||
export _H3="X-CSRFToken: $csrf_header"
|
export _H3="X-CSRFToken: $csrf_header"
|
||||||
_response=$(_post "$1" "$2")
|
_response="$(_post "$1" "$2" | _normalizeJson)"
|
||||||
|
_debug2 _response "$_response"
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
## Acmeproxy DNS provider to be used with acmeproxy (http://github.com/mdbraber/acmeproxy)
|
## Acmeproxy DNS provider to be used with acmeproxy (https://github.com/mdbraber/acmeproxy)
|
||||||
## API integration by Maarten den Braber
|
## API integration by Maarten den Braber
|
||||||
##
|
##
|
||||||
## Report any bugs via https://github.com/mdbraber/acme.sh
|
## Report any bugs via https://github.com/mdbraber/acme.sh
|
||||||
|
@ -117,7 +117,7 @@ _ali_urlencode() {
|
|||||||
_ali_nonce() {
|
_ali_nonce() {
|
||||||
#_head_n 1 </dev/urandom | _digest "sha256" hex | cut -c 1-31
|
#_head_n 1 </dev/urandom | _digest "sha256" hex | cut -c 1-31
|
||||||
#Not so good...
|
#Not so good...
|
||||||
date +"%s%N"
|
date +"%s%N" | sed 's/%N//g'
|
||||||
}
|
}
|
||||||
|
|
||||||
_check_exist_query() {
|
_check_exist_query() {
|
||||||
|
180
dnsapi/dns_artfiles.sh
Normal file
180
dnsapi/dns_artfiles.sh
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# ACME.sh 3rd party DNS API plugin for ArtFiles.de
|
||||||
|
################################################################################
|
||||||
|
# Author: Martin Arndt, https://troublezone.net/
|
||||||
|
# Released: 2022-02-27
|
||||||
|
# Issues: https://github.com/acmesh-official/acme.sh/issues/4718
|
||||||
|
################################################################################
|
||||||
|
# Usage:
|
||||||
|
# 1. export AF_API_USERNAME='api12345678'
|
||||||
|
# 2. export AF_API_PASSWORD='apiPassword'
|
||||||
|
# 3. acme.sh --issue -d example.com --dns dns_artfiles
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
########## API configuration ###################################################
|
||||||
|
|
||||||
|
AF_API_SUCCESS='status":"OK'
|
||||||
|
AF_URL_DCP='https://dcp.c.artfiles.de/api/'
|
||||||
|
AF_URL_DNS=${AF_URL_DCP}'dns/{*}_dns.html?domain='
|
||||||
|
AF_URL_DOMAINS=${AF_URL_DCP}'domain/get_domains.html'
|
||||||
|
|
||||||
|
########## Public functions ####################################################
|
||||||
|
|
||||||
|
# Adds a new TXT record for given ACME challenge value & domain.
|
||||||
|
# Usage: dns_artfiles_add _acme-challenge.www.example.com "ACME challenge value"
|
||||||
|
dns_artfiles_add() {
|
||||||
|
domain="$1"
|
||||||
|
txtValue="$2"
|
||||||
|
_info 'Using ArtFiles.de DNS addition API…'
|
||||||
|
_debug 'Domain' "$domain"
|
||||||
|
_debug 'txtValue' "$txtValue"
|
||||||
|
|
||||||
|
_set_credentials
|
||||||
|
_saveaccountconf_mutable 'AF_API_USERNAME' "$AF_API_USERNAME"
|
||||||
|
_saveaccountconf_mutable 'AF_API_PASSWORD' "$AF_API_PASSWORD"
|
||||||
|
|
||||||
|
_set_headers
|
||||||
|
_get_zone "$domain"
|
||||||
|
_dns 'GET'
|
||||||
|
if ! _contains "$response" 'TXT'; then
|
||||||
|
_err 'Retrieving TXT records failed.'
|
||||||
|
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_clean_records
|
||||||
|
_dns 'SET' "$(printf -- '%s\n_acme-challenge "%s"' "$response" "$txtValue")"
|
||||||
|
if ! _contains "$response" "$AF_API_SUCCESS"; then
|
||||||
|
_err 'Adding ACME challenge value failed.'
|
||||||
|
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Removes the existing TXT record for given ACME challenge value & domain.
|
||||||
|
# Usage: dns_artfiles_rm _acme-challenge.www.example.com "ACME challenge value"
|
||||||
|
dns_artfiles_rm() {
|
||||||
|
domain="$1"
|
||||||
|
txtValue="$2"
|
||||||
|
_info 'Using ArtFiles.de DNS removal API…'
|
||||||
|
_debug 'Domain' "$domain"
|
||||||
|
_debug 'txtValue' "$txtValue"
|
||||||
|
|
||||||
|
_set_credentials
|
||||||
|
_set_headers
|
||||||
|
_get_zone "$domain"
|
||||||
|
if ! _dns 'GET'; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! _contains "$response" "$txtValue"; then
|
||||||
|
_err 'Retrieved TXT records are missing given ACME challenge value.'
|
||||||
|
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_clean_records
|
||||||
|
response="$(printf -- '%s' "$response" | sed '/_acme-challenge "'"$txtValue"'"/d')"
|
||||||
|
_dns 'SET' "$response"
|
||||||
|
if ! _contains "$response" "$AF_API_SUCCESS"; then
|
||||||
|
_err 'Removing ACME challenge value failed.'
|
||||||
|
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
########## Private functions ###################################################
|
||||||
|
|
||||||
|
# Cleans awful TXT records response of ArtFiles's API & pretty prints it.
|
||||||
|
# Usage: _clean_records
|
||||||
|
_clean_records() {
|
||||||
|
_info 'Cleaning TXT records…'
|
||||||
|
# Extract TXT part, strip trailing quote sign (ACME.sh API guidelines forbid
|
||||||
|
# usage of SED's GNU extensions, hence couldn't omit it via regex), strip '\'
|
||||||
|
# from '\"' & turn '\n' into real LF characters.
|
||||||
|
# Yup, awful API to use - but that's all we got to get this working, so… ;)
|
||||||
|
_debug2 'Raw ' "$response"
|
||||||
|
response="$(printf -- '%s' "$response" | sed 's/^.*TXT":"\([^}]*\).*$/\1/;s/,".*$//;s/.$//;s/\\"/"/g;s/\\n/\n/g')"
|
||||||
|
_debug2 'Clean' "$response"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Executes an HTTP GET or POST request for getting or setting DNS records,
|
||||||
|
# containing given payload upon POST.
|
||||||
|
# Usage: _dns [GET | SET] [payload]
|
||||||
|
_dns() {
|
||||||
|
_info 'Executing HTTP request…'
|
||||||
|
action="$1"
|
||||||
|
payload="$(printf -- '%s' "$2" | _url_encode)"
|
||||||
|
url="$(printf -- '%s%s' "$AF_URL_DNS" "$domain" | sed 's/{\*}/'"$(printf -- '%s' "$action" | _lower_case)"'/')"
|
||||||
|
|
||||||
|
if [ "$action" = 'SET' ]; then
|
||||||
|
_debug2 'Payload' "$payload"
|
||||||
|
response="$(_post '' "$url&TXT=$payload" '' 'POST' 'application/x-www-form-urlencoded')"
|
||||||
|
else
|
||||||
|
response="$(_get "$url" '' 10)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! _contains "$response" "$AF_API_SUCCESS"; then
|
||||||
|
_err "DNS API error: $response"
|
||||||
|
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_debug 'Response' "$response"
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Gets the root domain zone for given domain.
|
||||||
|
# Usage: _get_zone _acme-challenge.www.example.com
|
||||||
|
_get_zone() {
|
||||||
|
fqdn="$1"
|
||||||
|
domains="$(_get "$AF_URL_DOMAINS" '' 10)"
|
||||||
|
_info 'Getting domain zone…'
|
||||||
|
_debug2 'FQDN' "$fqdn"
|
||||||
|
_debug2 'Domains' "$domains"
|
||||||
|
|
||||||
|
while _contains "$fqdn" "."; do
|
||||||
|
if _contains "$domains" "$fqdn"; then
|
||||||
|
domain="$fqdn"
|
||||||
|
_info "Found root domain zone: $domain"
|
||||||
|
break
|
||||||
|
else
|
||||||
|
fqdn="${fqdn#*.}"
|
||||||
|
_debug2 'FQDN' "$fqdn"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$domain" = "$fqdn" ]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
_err 'Couldn'\''t find root domain zone.'
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Sets the credentials for accessing ArtFiles's API
|
||||||
|
# Usage: _set_credentials
|
||||||
|
_set_credentials() {
|
||||||
|
_info 'Setting credentials…'
|
||||||
|
AF_API_USERNAME="${AF_API_USERNAME:-$(_readaccountconf_mutable AF_API_USERNAME)}"
|
||||||
|
AF_API_PASSWORD="${AF_API_PASSWORD:-$(_readaccountconf_mutable AF_API_PASSWORD)}"
|
||||||
|
if [ -z "$AF_API_USERNAME" ] || [ -z "$AF_API_PASSWORD" ]; then
|
||||||
|
_err 'Missing ArtFiles.de username and/or password.'
|
||||||
|
_err 'Please ensure both are set via export command & try again.'
|
||||||
|
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Adds the HTTP Authorization & Content-Type headers to a follow-up request.
|
||||||
|
# Usage: _set_headers
|
||||||
|
_set_headers() {
|
||||||
|
_info 'Setting headers…'
|
||||||
|
encoded="$(printf -- '%s:%s' "$AF_API_USERNAME" "$AF_API_PASSWORD" | _base64)"
|
||||||
|
export _H1="Authorization: Basic $encoded"
|
||||||
|
export _H2='Content-Type: application/json'
|
||||||
|
}
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# Arvan_Token="Apikey xxxx"
|
# Arvan_Token="Apikey xxxx"
|
||||||
|
|
||||||
ARVAN_API_URL="https://napi.arvancloud.com/cdn/4.0/domains"
|
ARVAN_API_URL="https://napi.arvancloud.ir/cdn/4.0/domains"
|
||||||
# Author: Vahid Fardi
|
# Author: Vahid Fardi
|
||||||
# Report Bugs here: https://github.com/Neilpang/acme.sh
|
# Report Bugs here: https://github.com/Neilpang/acme.sh
|
||||||
#
|
#
|
||||||
@ -18,7 +18,7 @@ dns_arvan_add() {
|
|||||||
|
|
||||||
if [ -z "$Arvan_Token" ]; then
|
if [ -z "$Arvan_Token" ]; then
|
||||||
_err "You didn't specify \"Arvan_Token\" token yet."
|
_err "You didn't specify \"Arvan_Token\" token yet."
|
||||||
_err "You can get yours from here https://npanel.arvancloud.com/profile/api-keys"
|
_err "You can get yours from here https://npanel.arvancloud.ir/profile/api-keys"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
#save the api token to the account conf file.
|
#save the api token to the account conf file.
|
||||||
@ -40,7 +40,7 @@ dns_arvan_add() {
|
|||||||
_info "response id is $response"
|
_info "response id is $response"
|
||||||
_info "Added, OK"
|
_info "Added, OK"
|
||||||
return 0
|
return 0
|
||||||
elif _contains "$response" "Record Data is Duplicated"; then
|
elif _contains "$response" "Record Data is duplicate"; then
|
||||||
_info "Already exists, OK"
|
_info "Already exists, OK"
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
@ -141,6 +141,7 @@ _arvan_rest() {
|
|||||||
response="$(_post "$data" "$ARVAN_API_URL/$ep" "" "$mtd")"
|
response="$(_post "$data" "$ARVAN_API_URL/$ep" "" "$mtd")"
|
||||||
elif [ "$mtd" = "POST" ]; then
|
elif [ "$mtd" = "POST" ]; then
|
||||||
export _H2="Content-Type: application/json"
|
export _H2="Content-Type: application/json"
|
||||||
|
export _H3="Accept: application/json"
|
||||||
_debug data "$data"
|
_debug data "$data"
|
||||||
response="$(_post "$data" "$ARVAN_API_URL/$ep" "" "$mtd")"
|
response="$(_post "$data" "$ARVAN_API_URL/$ep" "" "$mtd")"
|
||||||
else
|
else
|
||||||
|
@ -157,7 +157,7 @@ _get_root() {
|
|||||||
|
|
||||||
# iterate over names (a.b.c.d -> b.c.d -> c.d -> d)
|
# iterate over names (a.b.c.d -> b.c.d -> c.d -> d)
|
||||||
while true; do
|
while true; do
|
||||||
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
h=$(printf "%s" "$domain" | cut -d . -f $i-100 | sed 's/\./\\./g')
|
||||||
_debug "Checking domain: $h"
|
_debug "Checking domain: $h"
|
||||||
if [ -z "$h" ]; then
|
if [ -z "$h" ]; then
|
||||||
_error "invalid domain"
|
_error "invalid domain"
|
||||||
|
89
dnsapi/dns_bookmyname.sh
Normal file
89
dnsapi/dns_bookmyname.sh
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
#Here is a sample custom api script.
|
||||||
|
#This file name is "dns_bookmyname.sh"
|
||||||
|
#So, here must be a method dns_bookmyname_add()
|
||||||
|
#Which will be called by acme.sh to add the txt record to your api system.
|
||||||
|
#returns 0 means success, otherwise error.
|
||||||
|
#
|
||||||
|
#Author: Neilpang
|
||||||
|
#Report Bugs here: https://github.com/acmesh-official/acme.sh
|
||||||
|
#
|
||||||
|
######## Public functions #####################
|
||||||
|
|
||||||
|
# Please Read this guide first: https://github.com/acmesh-official/acme.sh/wiki/DNS-API-Dev-Guide
|
||||||
|
|
||||||
|
# BookMyName urls:
|
||||||
|
# https://BOOKMYNAME_USERNAME:BOOKMYNAME_PASSWORD@www.bookmyname.com/dyndns/?hostname=_acme-challenge.domain.tld&type=txt&ttl=300&do=add&value="XXXXXXXX"'
|
||||||
|
# https://BOOKMYNAME_USERNAME:BOOKMYNAME_PASSWORD@www.bookmyname.com/dyndns/?hostname=_acme-challenge.domain.tld&type=txt&ttl=300&do=remove&value="XXXXXXXX"'
|
||||||
|
|
||||||
|
# Output:
|
||||||
|
#good: update done, cid 123456, domain id 456789, type txt, ip XXXXXXXX
|
||||||
|
#good: remove done 1, cid 123456, domain id 456789, ttl 300, type txt, ip XXXXXXXX
|
||||||
|
|
||||||
|
# Be careful, BMN DNS servers can be slow to pick up changes; using dnssleep is thus advised.
|
||||||
|
|
||||||
|
# Usage:
|
||||||
|
# export BOOKMYNAME_USERNAME="ABCDE-FREE"
|
||||||
|
# export BOOKMYNAME_PASSWORD="MyPassword"
|
||||||
|
# /usr/local/ssl/acme.sh/acme.sh --dns dns_bookmyname --dnssleep 600 --issue -d domain.tld
|
||||||
|
|
||||||
|
#Usage: dns_bookmyname_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||||
|
dns_bookmyname_add() {
|
||||||
|
fulldomain=$1
|
||||||
|
txtvalue=$2
|
||||||
|
_info "Using bookmyname"
|
||||||
|
_debug fulldomain "$fulldomain"
|
||||||
|
_debug txtvalue "$txtvalue"
|
||||||
|
|
||||||
|
BOOKMYNAME_USERNAME="${BOOKMYNAME_USERNAME:-$(_readaccountconf_mutable BOOKMYNAME_USERNAME)}"
|
||||||
|
BOOKMYNAME_PASSWORD="${BOOKMYNAME_PASSWORD:-$(_readaccountconf_mutable BOOKMYNAME_PASSWORD)}"
|
||||||
|
|
||||||
|
if [ -z "$BOOKMYNAME_USERNAME" ] || [ -z "$BOOKMYNAME_PASSWORD" ]; then
|
||||||
|
BOOKMYNAME_USERNAME=""
|
||||||
|
BOOKMYNAME_PASSWORD=""
|
||||||
|
_err "You didn't specify BookMyName username and password yet."
|
||||||
|
_err "Please specify them and try again."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
#save the credentials to the account conf file.
|
||||||
|
_saveaccountconf_mutable BOOKMYNAME_USERNAME "$BOOKMYNAME_USERNAME"
|
||||||
|
_saveaccountconf_mutable BOOKMYNAME_PASSWORD "$BOOKMYNAME_PASSWORD"
|
||||||
|
|
||||||
|
uri="https://${BOOKMYNAME_USERNAME}:${BOOKMYNAME_PASSWORD}@www.bookmyname.com/dyndns/"
|
||||||
|
data="?hostname=${fulldomain}&type=TXT&ttl=300&do=add&value=${txtvalue}"
|
||||||
|
result="$(_get "${uri}${data}")"
|
||||||
|
_debug "Result: $result"
|
||||||
|
|
||||||
|
if ! _startswith "$result" 'good: update done, cid '; then
|
||||||
|
_err "Can't add $fulldomain"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#Usage: fulldomain txtvalue
|
||||||
|
#Remove the txt record after validation.
|
||||||
|
dns_bookmyname_rm() {
|
||||||
|
fulldomain=$1
|
||||||
|
txtvalue=$2
|
||||||
|
_info "Using bookmyname"
|
||||||
|
_debug fulldomain "$fulldomain"
|
||||||
|
_debug txtvalue "$txtvalue"
|
||||||
|
|
||||||
|
BOOKMYNAME_USERNAME="${BOOKMYNAME_USERNAME:-$(_readaccountconf_mutable BOOKMYNAME_USERNAME)}"
|
||||||
|
BOOKMYNAME_PASSWORD="${BOOKMYNAME_PASSWORD:-$(_readaccountconf_mutable BOOKMYNAME_PASSWORD)}"
|
||||||
|
|
||||||
|
uri="https://${BOOKMYNAME_USERNAME}:${BOOKMYNAME_PASSWORD}@www.bookmyname.com/dyndns/"
|
||||||
|
data="?hostname=${fulldomain}&type=TXT&ttl=300&do=remove&value=${txtvalue}"
|
||||||
|
result="$(_get "${uri}${data}")"
|
||||||
|
_debug "Result: $result"
|
||||||
|
|
||||||
|
if ! _startswith "$result" 'good: remove done 1, cid '; then
|
||||||
|
_info "Can't remove $fulldomain"
|
||||||
|
fi
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#################### Private functions below ##################################
|
@ -78,7 +78,7 @@ dns_cloudns_rm() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
for i in $(echo "$response" | tr '{' "\n" | grep "$record"); do
|
for i in $(echo "$response" | tr '{' "\n" | grep -- "$record"); do
|
||||||
record_id=$(echo "$i" | tr ',' "\n" | grep -E '^"id"' | sed -re 's/^\"id\"\:\"([0-9]+)\"$/\1/g')
|
record_id=$(echo "$i" | tr ',' "\n" | grep -E '^"id"' | sed -re 's/^\"id\"\:\"([0-9]+)\"$/\1/g')
|
||||||
|
|
||||||
if [ -n "$record_id" ]; then
|
if [ -n "$record_id" ]; then
|
||||||
|
185
dnsapi/dns_dnsexit.sh
Normal file
185
dnsapi/dns_dnsexit.sh
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
#use dns-01 at DNSExit.com
|
||||||
|
|
||||||
|
#Author: Samuel Jimenez
|
||||||
|
#Report Bugs here: https://github.com/acmesh-official/acme.sh
|
||||||
|
|
||||||
|
#DNSEXIT_API_KEY=ABCDEFGHIJ0123456789abcdefghij
|
||||||
|
#DNSEXIT_AUTH_USER=login@email.address
|
||||||
|
#DNSEXIT_AUTH_PASS=aStrongPassword
|
||||||
|
DNSEXIT_API_URL="https://api.dnsexit.com/dns/"
|
||||||
|
DNSEXIT_HOSTS_URL="https://update.dnsexit.com/ipupdate/hosts.jsp"
|
||||||
|
|
||||||
|
######## Public functions #####################
|
||||||
|
#Usage: dns_dnsexit_add _acme-challenge.*.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||||
|
dns_dnsexit_add() {
|
||||||
|
fulldomain=$1
|
||||||
|
txtvalue=$2
|
||||||
|
_info "Using DNSExit.com"
|
||||||
|
_debug fulldomain "$fulldomain"
|
||||||
|
_debug txtvalue "$txtvalue"
|
||||||
|
|
||||||
|
_debug 'Load account auth'
|
||||||
|
if ! get_account_info; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_debug 'First detect the root zone'
|
||||||
|
if ! _get_root "$fulldomain"; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_debug _sub_domain "$_sub_domain"
|
||||||
|
_debug _domain "$_domain"
|
||||||
|
|
||||||
|
if ! _dnsexit_rest "{\"domain\":\"$_domain\",\"add\":{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"content\":\"$txtvalue\",\"ttl\":0,\"overwrite\":false}}"; then
|
||||||
|
_err "$response"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_debug2 _response "$response"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
#Usage: fulldomain txtvalue
|
||||||
|
#Remove the txt record after validation.
|
||||||
|
dns_dnsexit_rm() {
|
||||||
|
fulldomain=$1
|
||||||
|
txtvalue=$2
|
||||||
|
_info "Using DNSExit.com"
|
||||||
|
_debug fulldomain "$fulldomain"
|
||||||
|
_debug txtvalue "$txtvalue"
|
||||||
|
|
||||||
|
_debug 'Load account auth'
|
||||||
|
if ! get_account_info; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_debug 'First detect the root zone'
|
||||||
|
if ! _get_root "$fulldomain"; then
|
||||||
|
_err "$response"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_debug _sub_domain "$_sub_domain"
|
||||||
|
_debug _domain "$_domain"
|
||||||
|
|
||||||
|
if ! _dnsexit_rest "{\"domain\":\"$_domain\",\"delete\":{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"content\":\"$txtvalue\"}}"; then
|
||||||
|
_err "$response"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_debug2 _response "$response"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
#################### Private functions below ##################################
|
||||||
|
#_acme-challenge.www.domain.com
|
||||||
|
#returns
|
||||||
|
# _sub_domain=_acme-challenge.www
|
||||||
|
# _domain=domain.com
|
||||||
|
_get_root() {
|
||||||
|
domain=$1
|
||||||
|
i=1
|
||||||
|
while true; do
|
||||||
|
_domain=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
||||||
|
_debug h "$_domain"
|
||||||
|
if [ -z "$_domain" ]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_debug login "$DNSEXIT_AUTH_USER"
|
||||||
|
_debug password "$DNSEXIT_AUTH_PASS"
|
||||||
|
_debug domain "$_domain"
|
||||||
|
|
||||||
|
_dnsexit_http "login=$DNSEXIT_AUTH_USER&password=$DNSEXIT_AUTH_PASS&domain=$_domain"
|
||||||
|
|
||||||
|
if _contains "$response" "0=$_domain"; then
|
||||||
|
_sub_domain="$(echo "$fulldomain" | sed "s/\\.$_domain\$//")"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
_debug "Go to next level of $_domain"
|
||||||
|
fi
|
||||||
|
i=$(_math "$i" + 1)
|
||||||
|
done
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
_dnsexit_rest() {
|
||||||
|
m=POST
|
||||||
|
ep=""
|
||||||
|
data="$1"
|
||||||
|
_debug _dnsexit_rest "$ep"
|
||||||
|
_debug data "$data"
|
||||||
|
|
||||||
|
api_key_trimmed=$(echo "$DNSEXIT_API_KEY" | tr -d '"')
|
||||||
|
|
||||||
|
export _H1="apikey: $api_key_trimmed"
|
||||||
|
export _H2='Content-Type: application/json'
|
||||||
|
|
||||||
|
if [ "$m" != "GET" ]; then
|
||||||
|
_debug data "$data"
|
||||||
|
response="$(_post "$data" "$DNSEXIT_API_URL/$ep" "" "$m")"
|
||||||
|
else
|
||||||
|
response="$(_get "$DNSEXIT_API_URL/$ep")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$?" != "0" ]; then
|
||||||
|
_err "Error $ep"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_debug2 response "$response"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
_dnsexit_http() {
|
||||||
|
m=GET
|
||||||
|
param="$1"
|
||||||
|
_debug param "$param"
|
||||||
|
_debug get "$DNSEXIT_HOSTS_URL?$param"
|
||||||
|
|
||||||
|
response="$(_get "$DNSEXIT_HOSTS_URL?$param")"
|
||||||
|
|
||||||
|
_debug response "$response"
|
||||||
|
|
||||||
|
if [ "$?" != "0" ]; then
|
||||||
|
_err "Error $param"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_debug2 response "$response"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
get_account_info() {
|
||||||
|
|
||||||
|
DNSEXIT_API_KEY="${DNSEXIT_API_KEY:-$(_readaccountconf_mutable DNSEXIT_API_KEY)}"
|
||||||
|
if test -z "$DNSEXIT_API_KEY"; then
|
||||||
|
DNSEXIT_API_KEY=''
|
||||||
|
_err 'DNSEXIT_API_KEY was not exported'
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_saveaccountconf_mutable DNSEXIT_API_KEY "$DNSEXIT_API_KEY"
|
||||||
|
|
||||||
|
DNSEXIT_AUTH_USER="${DNSEXIT_AUTH_USER:-$(_readaccountconf_mutable DNSEXIT_AUTH_USER)}"
|
||||||
|
if test -z "$DNSEXIT_AUTH_USER"; then
|
||||||
|
DNSEXIT_AUTH_USER=""
|
||||||
|
_err 'DNSEXIT_AUTH_USER was not exported'
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_saveaccountconf_mutable DNSEXIT_AUTH_USER "$DNSEXIT_AUTH_USER"
|
||||||
|
|
||||||
|
DNSEXIT_AUTH_PASS="${DNSEXIT_AUTH_PASS:-$(_readaccountconf_mutable DNSEXIT_AUTH_PASS)}"
|
||||||
|
if test -z "$DNSEXIT_AUTH_PASS"; then
|
||||||
|
DNSEXIT_AUTH_PASS=""
|
||||||
|
_err 'DNSEXIT_AUTH_PASS was not exported'
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_saveaccountconf_mutable DNSEXIT_AUTH_PASS "$DNSEXIT_AUTH_PASS"
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
148
dnsapi/dns_do.sh
148
dnsapi/dns_do.sh
@ -1,148 +0,0 @@
|
|||||||
#!/usr/bin/env sh
|
|
||||||
|
|
||||||
# DNS API for Domain-Offensive / Resellerinterface / Domainrobot
|
|
||||||
|
|
||||||
# Report bugs at https://github.com/seidler2547/acme.sh/issues
|
|
||||||
|
|
||||||
# set these environment variables to match your customer ID and password:
|
|
||||||
# DO_PID="KD-1234567"
|
|
||||||
# DO_PW="cdfkjl3n2"
|
|
||||||
|
|
||||||
DO_URL="https://soap.resellerinterface.de/"
|
|
||||||
|
|
||||||
######## Public functions #####################
|
|
||||||
|
|
||||||
#Usage: dns_myapi_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
|
||||||
dns_do_add() {
|
|
||||||
fulldomain=$1
|
|
||||||
txtvalue=$2
|
|
||||||
if _dns_do_authenticate; then
|
|
||||||
_info "Adding TXT record to ${_domain} as ${fulldomain}"
|
|
||||||
_dns_do_soap createRR origin "${_domain}" name "${fulldomain}" type TXT data "${txtvalue}" ttl 300
|
|
||||||
if _contains "${response}" '>success<'; then
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
_err "Could not create resource record, check logs"
|
|
||||||
fi
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
#fulldomain
|
|
||||||
dns_do_rm() {
|
|
||||||
fulldomain=$1
|
|
||||||
if _dns_do_authenticate; then
|
|
||||||
if _dns_do_list_rrs; then
|
|
||||||
_dns_do_had_error=0
|
|
||||||
for _rrid in ${_rr_list}; do
|
|
||||||
_info "Deleting resource record $_rrid for $_domain"
|
|
||||||
_dns_do_soap deleteRR origin "${_domain}" rrid "${_rrid}"
|
|
||||||
if ! _contains "${response}" '>success<'; then
|
|
||||||
_dns_do_had_error=1
|
|
||||||
_err "Could not delete resource record for ${_domain}, id ${_rrid}"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
return $_dns_do_had_error
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
#################### Private functions below ##################################
|
|
||||||
_dns_do_authenticate() {
|
|
||||||
_info "Authenticating as ${DO_PID}"
|
|
||||||
_dns_do_soap authPartner partner "${DO_PID}" password "${DO_PW}"
|
|
||||||
if _contains "${response}" '>success<'; then
|
|
||||||
_get_root "$fulldomain"
|
|
||||||
_debug "_domain $_domain"
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
_err "Authentication failed, are DO_PID and DO_PW set correctly?"
|
|
||||||
fi
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
_dns_do_list_rrs() {
|
|
||||||
_dns_do_soap getRRList origin "${_domain}"
|
|
||||||
if ! _contains "${response}" 'SOAP-ENC:Array'; then
|
|
||||||
_err "getRRList origin ${_domain} failed"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
_rr_list="$(echo "${response}" |
|
|
||||||
tr -d "\n\r\t" |
|
|
||||||
sed -e 's/<item xsi:type="ns2:Map">/\n/g' |
|
|
||||||
grep ">$(_regexcape "$fulldomain")</value>" |
|
|
||||||
sed -e 's/<\/item>/\n/g' |
|
|
||||||
grep '>id</key><value' |
|
|
||||||
_egrep_o '>[0-9]{1,16}<' |
|
|
||||||
tr -d '><')"
|
|
||||||
[ "${_rr_list}" ]
|
|
||||||
}
|
|
||||||
|
|
||||||
_dns_do_soap() {
|
|
||||||
func="$1"
|
|
||||||
shift
|
|
||||||
# put the parameters to xml
|
|
||||||
body="<tns:${func} xmlns:tns=\"${DO_URL}\">"
|
|
||||||
while [ "$1" ]; do
|
|
||||||
_k="$1"
|
|
||||||
shift
|
|
||||||
_v="$1"
|
|
||||||
shift
|
|
||||||
body="$body<$_k>$_v</$_k>"
|
|
||||||
done
|
|
||||||
body="$body</tns:${func}>"
|
|
||||||
_debug2 "SOAP request ${body}"
|
|
||||||
|
|
||||||
# build SOAP XML
|
|
||||||
_xml='<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
|
|
||||||
<env:Body>'"$body"'</env:Body>
|
|
||||||
</env:Envelope>'
|
|
||||||
|
|
||||||
# set SOAP headers
|
|
||||||
export _H1="SOAPAction: ${DO_URL}#${func}"
|
|
||||||
|
|
||||||
if ! response="$(_post "${_xml}" "${DO_URL}")"; then
|
|
||||||
_err "Error <$1>"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
_debug2 "SOAP response $response"
|
|
||||||
|
|
||||||
# retrieve cookie header
|
|
||||||
_H2="$(_egrep_o 'Cookie: [^;]+' <"$HTTP_HEADER" | _head_n 1)"
|
|
||||||
export _H2
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
_get_root() {
|
|
||||||
domain=$1
|
|
||||||
i=1
|
|
||||||
|
|
||||||
_dns_do_soap getDomainList
|
|
||||||
_all_domains="$(echo "${response}" |
|
|
||||||
tr -d "\n\r\t " |
|
|
||||||
_egrep_o 'domain</key><value[^>]+>[^<]+' |
|
|
||||||
sed -e 's/^domain<\/key><value[^>]*>//g')"
|
|
||||||
|
|
||||||
while true; do
|
|
||||||
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
|
||||||
if [ -z "$h" ]; then
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if _contains "${_all_domains}" "^$(_regexcape "$h")\$"; then
|
|
||||||
_domain="$h"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
i=$(_math $i + 1)
|
|
||||||
done
|
|
||||||
_debug "$domain not found"
|
|
||||||
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
_regexcape() {
|
|
||||||
echo "$1" | sed -e 's/\([]\.$*^[]\)/\\\1/g'
|
|
||||||
}
|
|
@ -94,8 +94,8 @@ _get_domain() {
|
|||||||
_your_hosts="$(echo "$_your_hosts" | awk '/\./ {print $1}')"
|
_your_hosts="$(echo "$_your_hosts" | awk '/\./ {print $1}')"
|
||||||
for l in $_your_hosts; do
|
for l in $_your_hosts; do
|
||||||
#echo "host: $l"
|
#echo "host: $l"
|
||||||
if test "${_full_domain#*$l}" != "$_full_domain"; then
|
if test "${_full_domain#*"$l"}" != "$_full_domain"; then
|
||||||
_record="${_full_domain%.$l}"
|
_record=${_full_domain%."$l"}
|
||||||
_host=$l
|
_host=$l
|
||||||
_debug "The host is $_host and the record $_record"
|
_debug "The host is $_host and the record $_record"
|
||||||
return 0
|
return 0
|
||||||
@ -143,7 +143,7 @@ _dns_dynv6_add_http() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
_get_zone_name "$_zone_id"
|
_get_zone_name "$_zone_id"
|
||||||
record="${fulldomain%%.$_zone_name}"
|
record=${fulldomain%%."$_zone_name"}
|
||||||
_set_record TXT "$record" "$txtvalue"
|
_set_record TXT "$record" "$txtvalue"
|
||||||
if _contains "$response" "$txtvalue"; then
|
if _contains "$response" "$txtvalue"; then
|
||||||
_info "Successfully added record"
|
_info "Successfully added record"
|
||||||
@ -161,7 +161,7 @@ _dns_dynv6_rm_http() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
_get_zone_name "$_zone_id"
|
_get_zone_name "$_zone_id"
|
||||||
record="${fulldomain%%.$_zone_name}"
|
record=${fulldomain%%."$_zone_name"}
|
||||||
_get_record_id "$_zone_id" "$record" "$txtvalue"
|
_get_record_id "$_zone_id" "$record" "$txtvalue"
|
||||||
_del_record "$_zone_id" "$_record_id"
|
_del_record "$_zone_id" "$_record_id"
|
||||||
if [ -z "$response" ]; then
|
if [ -z "$response" ]; then
|
||||||
|
@ -418,7 +418,7 @@ _edgedns_make_data_to_sign() {
|
|||||||
_secure_debug2 "hdr" "$hdr"
|
_secure_debug2 "hdr" "$hdr"
|
||||||
_edgedns_make_content_hash
|
_edgedns_make_content_hash
|
||||||
path="$(echo "$_request_url_path" | tr -d "\n\r" | sed 's/https\?:\/\///')"
|
path="$(echo "$_request_url_path" | tr -d "\n\r" | sed 's/https\?:\/\///')"
|
||||||
path="${path#*$AKAMAI_HOST}"
|
path=${path#*"$AKAMAI_HOST"}
|
||||||
_debug "hier path" "$path"
|
_debug "hier path" "$path"
|
||||||
# dont expose headers to sign so use MT string
|
# dont expose headers to sign so use MT string
|
||||||
_mdata="$(printf "%s\thttps\t%s\t%s\t%s\t%s\t%s" "$_request_method" "$AKAMAI_HOST" "$path" "" "$_hash" "$hdr")"
|
_mdata="$(printf "%s\thttps\t%s\t%s\t%s\t%s\t%s" "$_request_method" "$AKAMAI_HOST" "$path" "" "$_hash" "$hdr")"
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
# Gandi LiveDNS v5 API
|
# Gandi LiveDNS v5 API
|
||||||
# http://doc.livedns.gandi.net/
|
# https://api.gandi.net/docs/livedns/
|
||||||
|
# https://api.gandi.net/docs/authentication/ for token + apikey (deprecated) authentication
|
||||||
# currently under beta
|
# currently under beta
|
||||||
#
|
#
|
||||||
# Requires GANDI API KEY set in GANDI_LIVEDNS_KEY set as environment variable
|
# Requires GANDI API KEY set in GANDI_LIVEDNS_KEY set as environment variable
|
||||||
@ -12,20 +13,27 @@
|
|||||||
#
|
#
|
||||||
######## Public functions #####################
|
######## Public functions #####################
|
||||||
|
|
||||||
GANDI_LIVEDNS_API="https://dns.api.gandi.net/api/v5"
|
GANDI_LIVEDNS_API="https://api.gandi.net/v5/livedns"
|
||||||
|
|
||||||
#Usage: dns_gandi_livedns_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
#Usage: dns_gandi_livedns_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||||
dns_gandi_livedns_add() {
|
dns_gandi_livedns_add() {
|
||||||
fulldomain=$1
|
fulldomain=$1
|
||||||
txtvalue=$2
|
txtvalue=$2
|
||||||
|
|
||||||
if [ -z "$GANDI_LIVEDNS_KEY" ]; then
|
if [ -z "$GANDI_LIVEDNS_KEY" ] && [ -z "$GANDI_LIVEDNS_TOKEN" ]; then
|
||||||
_err "No API key specified for Gandi LiveDNS."
|
_err "No Token or API key (deprecated) specified for Gandi LiveDNS."
|
||||||
_err "Create your key and export it as GANDI_LIVEDNS_KEY"
|
_err "Create your token or key and export it as GANDI_LIVEDNS_KEY or GANDI_LIVEDNS_TOKEN respectively"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Keep only one secret in configuration
|
||||||
|
if [ -n "$GANDI_LIVEDNS_TOKEN" ]; then
|
||||||
|
_saveaccountconf GANDI_LIVEDNS_TOKEN "$GANDI_LIVEDNS_TOKEN"
|
||||||
|
_clearaccountconf GANDI_LIVEDNS_KEY
|
||||||
|
elif [ -n "$GANDI_LIVEDNS_KEY" ]; then
|
||||||
_saveaccountconf GANDI_LIVEDNS_KEY "$GANDI_LIVEDNS_KEY"
|
_saveaccountconf GANDI_LIVEDNS_KEY "$GANDI_LIVEDNS_KEY"
|
||||||
|
_clearaccountconf GANDI_LIVEDNS_TOKEN
|
||||||
|
fi
|
||||||
|
|
||||||
_debug "First detect the root zone"
|
_debug "First detect the root zone"
|
||||||
if ! _get_root "$fulldomain"; then
|
if ! _get_root "$fulldomain"; then
|
||||||
@ -157,7 +165,12 @@ _gandi_livedns_rest() {
|
|||||||
_debug "$ep"
|
_debug "$ep"
|
||||||
|
|
||||||
export _H1="Content-Type: application/json"
|
export _H1="Content-Type: application/json"
|
||||||
export _H2="X-Api-Key: $GANDI_LIVEDNS_KEY"
|
|
||||||
|
if [ -n "$GANDI_LIVEDNS_TOKEN" ]; then
|
||||||
|
export _H2="Authorization: Bearer $GANDI_LIVEDNS_TOKEN"
|
||||||
|
else
|
||||||
|
export _H2="Authorization: Apikey $GANDI_LIVEDNS_KEY"
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "$m" = "GET" ]; then
|
if [ "$m" = "GET" ]; then
|
||||||
response="$(_get "$GANDI_LIVEDNS_API/$ep")"
|
response="$(_get "$GANDI_LIVEDNS_API/$ep")"
|
||||||
|
@ -42,7 +42,7 @@ dns_gcloud_rm() {
|
|||||||
echo "$rrdatas" | grep -F -v -- "\"$txtvalue\"" | _dns_gcloud_add_rrs || return $?
|
echo "$rrdatas" | grep -F -v -- "\"$txtvalue\"" | _dns_gcloud_add_rrs || return $?
|
||||||
_dns_gcloud_execute_tr || return $?
|
_dns_gcloud_execute_tr || return $?
|
||||||
|
|
||||||
_info "$fulldomain record added"
|
_info "$fulldomain record removed"
|
||||||
}
|
}
|
||||||
|
|
||||||
#################### Private functions below ##################################
|
#################### Private functions below ##################################
|
||||||
|
187
dnsapi/dns_gcore.sh
Executable file
187
dnsapi/dns_gcore.sh
Executable file
@ -0,0 +1,187 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
#
|
||||||
|
#GCORE_Key='773$7b7adaf2a2b32bfb1b83787b4ff32a67eb178e3ada1af733e47b1411f2461f7f4fa7ed7138e2772a46124377bad7384b3bb8d87748f87b3f23db4b8bbe41b2bb'
|
||||||
|
#
|
||||||
|
|
||||||
|
GCORE_Api="https://api.gcore.com/dns/v2"
|
||||||
|
GCORE_Doc="https://api.gcore.com/docs/dns"
|
||||||
|
|
||||||
|
######## Public functions #####################
|
||||||
|
|
||||||
|
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||||
|
dns_gcore_add() {
|
||||||
|
fulldomain=$1
|
||||||
|
txtvalue=$2
|
||||||
|
|
||||||
|
GCORE_Key="${GCORE_Key:-$(_readaccountconf_mutable GCORE_Key)}"
|
||||||
|
|
||||||
|
if [ -z "$GCORE_Key" ]; then
|
||||||
|
GCORE_Key=""
|
||||||
|
_err "You didn't specify a Gcore api key yet."
|
||||||
|
_err "You can get yours from here $GCORE_Doc"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
#save the api key to the account conf file.
|
||||||
|
_saveaccountconf_mutable GCORE_Key "$GCORE_Key"
|
||||||
|
|
||||||
|
_debug "First detect the zone name"
|
||||||
|
if ! _get_root "$fulldomain"; then
|
||||||
|
_err "invalid domain"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_debug _zone_name "$_zone_name"
|
||||||
|
_debug _sub_domain "$_sub_domain"
|
||||||
|
_debug _domain "$_domain"
|
||||||
|
|
||||||
|
_debug "Getting txt records"
|
||||||
|
_gcore_rest GET "zones/$_zone_name/$fulldomain/TXT"
|
||||||
|
payload=""
|
||||||
|
|
||||||
|
if echo "$response" | grep "record is not found" >/dev/null; then
|
||||||
|
_info "Record doesn't exists"
|
||||||
|
payload="{\"resource_records\":[{\"content\":[\"$txtvalue\"],\"enabled\":true}],\"ttl\":120}"
|
||||||
|
elif echo "$response" | grep "$txtvalue" >/dev/null; then
|
||||||
|
_info "Already exists, OK"
|
||||||
|
return 0
|
||||||
|
elif echo "$response" | tr -d " " | grep \"name\":\""$fulldomain"\",\"type\":\"TXT\" >/dev/null; then
|
||||||
|
_info "Record with mismatch txtvalue, try update it"
|
||||||
|
payload=$(echo "$response" | tr -d " " | sed 's/"updated_at":[0-9]\+,//g' | sed 's/"meta":{}}]}/"meta":{}},{"content":['\""$txtvalue"\"'],"enabled":true}]}/')
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For wildcard cert, the main root domain and the wildcard domain have the same txt subdomain name, so
|
||||||
|
# we can not use updating anymore.
|
||||||
|
# count=$(printf "%s\n" "$response" | _egrep_o "\"count\":[^,]*" | cut -d : -f 2)
|
||||||
|
# _debug count "$count"
|
||||||
|
# if [ "$count" = "0" ]; then
|
||||||
|
_info "Adding record"
|
||||||
|
if _gcore_rest PUT "zones/$_zone_name/$fulldomain/TXT" "$payload"; then
|
||||||
|
if _contains "$response" "$txtvalue"; then
|
||||||
|
_info "Added, OK"
|
||||||
|
return 0
|
||||||
|
elif _contains "$response" "rrset is already exists"; then
|
||||||
|
_info "Already exists, OK"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
_err "Add txt record error."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
_err "Add txt record error."
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
#fulldomain txtvalue
|
||||||
|
dns_gcore_rm() {
|
||||||
|
fulldomain=$1
|
||||||
|
txtvalue=$2
|
||||||
|
|
||||||
|
GCORE_Key="${GCORE_Key:-$(_readaccountconf_mutable GCORE_Key)}"
|
||||||
|
|
||||||
|
_debug "First detect the root zone"
|
||||||
|
if ! _get_root "$fulldomain"; then
|
||||||
|
_err "invalid domain"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_debug _zone_name "$_zone_name"
|
||||||
|
_debug _sub_domain "$_sub_domain"
|
||||||
|
_debug _domain "$_domain"
|
||||||
|
|
||||||
|
_debug "Getting txt records"
|
||||||
|
_gcore_rest GET "zones/$_zone_name/$fulldomain/TXT"
|
||||||
|
|
||||||
|
if echo "$response" | grep "record is not found" >/dev/null; then
|
||||||
|
_info "No such txt recrod"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! echo "$response" | tr -d " " | grep \"name\":\""$fulldomain"\",\"type\":\"TXT\" >/dev/null; then
|
||||||
|
_err "Error: $response"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! echo "$response" | tr -d " " | grep \""$txtvalue"\" >/dev/null; then
|
||||||
|
_info "No such txt recrod"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
count="$(echo "$response" | grep -o "content" | wc -l)"
|
||||||
|
|
||||||
|
if [ "$count" = "1" ]; then
|
||||||
|
if ! _gcore_rest DELETE "zones/$_zone_name/$fulldomain/TXT"; then
|
||||||
|
_err "Delete record error. $response"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
payload="$(echo "$response" | tr -d " " | sed 's/"updated_at":[0-9]\+,//g' | sed 's/{"id":[0-9]\+,"content":\["'"$txtvalue"'"\],"enabled":true,"meta":{}}//' | sed 's/\[,/\[/' | sed 's/,,/,/' | sed 's/,\]/\]/')"
|
||||||
|
if ! _gcore_rest PUT "zones/$_zone_name/$fulldomain/TXT" "$payload"; then
|
||||||
|
_err "Delete record error. $response"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#################### Private functions below ##################################
|
||||||
|
#_acme-challenge.sub.domain.com
|
||||||
|
#returns
|
||||||
|
# _sub_domain=_acme-challenge.sub or _acme-challenge
|
||||||
|
# _domain=domain.com
|
||||||
|
# _zone_name=domain.com or sub.domain.com
|
||||||
|
_get_root() {
|
||||||
|
domain=$1
|
||||||
|
i=1
|
||||||
|
p=1
|
||||||
|
|
||||||
|
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 ! _gcore_rest GET "zones/$h"; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if _contains "$response" "\"name\":\"$h\""; then
|
||||||
|
_zone_name=$h
|
||||||
|
if [ "$_zone_name" ]; 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
|
||||||
|
}
|
||||||
|
|
||||||
|
_gcore_rest() {
|
||||||
|
m=$1
|
||||||
|
ep="$2"
|
||||||
|
data="$3"
|
||||||
|
_debug "$ep"
|
||||||
|
|
||||||
|
key_trimmed=$(echo "$GCORE_Key" | tr -d '"')
|
||||||
|
|
||||||
|
export _H1="Content-Type: application/json"
|
||||||
|
export _H2="Authorization: APIKey $key_trimmed"
|
||||||
|
|
||||||
|
if [ "$m" != "GET" ]; then
|
||||||
|
_debug data "$data"
|
||||||
|
response="$(_post "$data" "$GCORE_Api/$ep" "" "$m")"
|
||||||
|
else
|
||||||
|
response="$(_get "$GCORE_Api/$ep")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$?" != "0" ]; then
|
||||||
|
_err "error $ep"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_debug2 response "$response"
|
||||||
|
return 0
|
||||||
|
}
|
@ -22,8 +22,8 @@ dns_gd_add() {
|
|||||||
if [ -z "$GD_Key" ] || [ -z "$GD_Secret" ]; then
|
if [ -z "$GD_Key" ] || [ -z "$GD_Secret" ]; then
|
||||||
GD_Key=""
|
GD_Key=""
|
||||||
GD_Secret=""
|
GD_Secret=""
|
||||||
_err "You don't specify godaddy api key and secret yet."
|
_err "You didn't specify godaddy api key and secret yet."
|
||||||
_err "Please create you key and try again."
|
_err "Please create your key and try again."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ dns_gd_add() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if _contains "$response" "$txtvalue"; then
|
if _contains "$response" "$txtvalue"; then
|
||||||
_info "The record is existing, skip"
|
_info "This record already exists, skipping"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
173
dnsapi/dns_googledomains.sh
Executable file
173
dnsapi/dns_googledomains.sh
Executable file
@ -0,0 +1,173 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
# Author: Alex Leigh <leigh at alexleigh dot me>
|
||||||
|
# Created: 2023-03-02
|
||||||
|
|
||||||
|
#GOOGLEDOMAINS_ACCESS_TOKEN="xxxx"
|
||||||
|
#GOOGLEDOMAINS_ZONE="xxxx"
|
||||||
|
GOOGLEDOMAINS_API="https://acmedns.googleapis.com/v1/acmeChallengeSets"
|
||||||
|
|
||||||
|
######## Public functions ########
|
||||||
|
|
||||||
|
#Usage: dns_googledomains_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||||
|
dns_googledomains_add() {
|
||||||
|
fulldomain=$1
|
||||||
|
txtvalue=$2
|
||||||
|
|
||||||
|
_info "Invoking Google Domains ACME DNS API."
|
||||||
|
|
||||||
|
if ! _dns_googledomains_setup; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
zone="$(_dns_googledomains_get_zone "$fulldomain")"
|
||||||
|
if [ -z "$zone" ]; then
|
||||||
|
_err "Could not find a Google Domains-managed zone containing the requested domain."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_debug zone "$zone"
|
||||||
|
_debug txtvalue "$txtvalue"
|
||||||
|
|
||||||
|
_info "Adding TXT record for $fulldomain."
|
||||||
|
if _dns_googledomains_api "$zone" ":rotateChallenges" "{\"accessToken\":\"$GOOGLEDOMAINS_ACCESS_TOKEN\",\"recordsToAdd\":[{\"fqdn\":\"$fulldomain\",\"digest\":\"$txtvalue\"}],\"keepExpiredRecords\":true}"; then
|
||||||
|
if _contains "$response" "$txtvalue"; then
|
||||||
|
_info "TXT record added."
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
_err "Error adding TXT record."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
_err "Error adding TXT record."
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
#Usage: dns_googledomains_rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||||
|
dns_googledomains_rm() {
|
||||||
|
fulldomain=$1
|
||||||
|
txtvalue=$2
|
||||||
|
|
||||||
|
_info "Invoking Google Domains ACME DNS API."
|
||||||
|
|
||||||
|
if ! _dns_googledomains_setup; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
zone="$(_dns_googledomains_get_zone "$fulldomain")"
|
||||||
|
if [ -z "$zone" ]; then
|
||||||
|
_err "Could not find a Google Domains-managed domain based on request."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_debug zone "$zone"
|
||||||
|
_debug txtvalue "$txtvalue"
|
||||||
|
|
||||||
|
_info "Removing TXT record for $fulldomain."
|
||||||
|
if _dns_googledomains_api "$zone" ":rotateChallenges" "{\"accessToken\":\"$GOOGLEDOMAINS_ACCESS_TOKEN\",\"recordsToRemove\":[{\"fqdn\":\"$fulldomain\",\"digest\":\"$txtvalue\"}],\"keepExpiredRecords\":true}"; then
|
||||||
|
if _contains "$response" "$txtvalue"; then
|
||||||
|
_err "Error removing TXT record."
|
||||||
|
return 1
|
||||||
|
else
|
||||||
|
_info "TXT record removed."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
_err "Error removing TXT record."
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
######## Private functions ########
|
||||||
|
|
||||||
|
_dns_googledomains_setup() {
|
||||||
|
if [ -n "$GOOGLEDOMAINS_SETUP_COMPLETED" ]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
GOOGLEDOMAINS_ACCESS_TOKEN="${GOOGLEDOMAINS_ACCESS_TOKEN:-$(_readaccountconf_mutable GOOGLEDOMAINS_ACCESS_TOKEN)}"
|
||||||
|
GOOGLEDOMAINS_ZONE="${GOOGLEDOMAINS_ZONE:-$(_readaccountconf_mutable GOOGLEDOMAINS_ZONE)}"
|
||||||
|
|
||||||
|
if [ -z "$GOOGLEDOMAINS_ACCESS_TOKEN" ]; then
|
||||||
|
GOOGLEDOMAINS_ACCESS_TOKEN=""
|
||||||
|
_err "Google Domains access token was not specified."
|
||||||
|
_err "Please visit Google Domains Security settings to provision an ACME DNS API access token."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$GOOGLEDOMAINS_ZONE" ]; then
|
||||||
|
_savedomainconf GOOGLEDOMAINS_ACCESS_TOKEN "$GOOGLEDOMAINS_ACCESS_TOKEN"
|
||||||
|
_savedomainconf GOOGLEDOMAINS_ZONE "$GOOGLEDOMAINS_ZONE"
|
||||||
|
else
|
||||||
|
_saveaccountconf_mutable GOOGLEDOMAINS_ACCESS_TOKEN "$GOOGLEDOMAINS_ACCESS_TOKEN"
|
||||||
|
_clearaccountconf_mutable GOOGLEDOMAINS_ZONE
|
||||||
|
_clearaccountconf GOOGLEDOMAINS_ZONE
|
||||||
|
fi
|
||||||
|
|
||||||
|
_debug GOOGLEDOMAINS_ACCESS_TOKEN "$GOOGLEDOMAINS_ACCESS_TOKEN"
|
||||||
|
_debug GOOGLEDOMAINS_ZONE "$GOOGLEDOMAINS_ZONE"
|
||||||
|
|
||||||
|
GOOGLEDOMAINS_SETUP_COMPLETED=1
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
_dns_googledomains_get_zone() {
|
||||||
|
domain=$1
|
||||||
|
|
||||||
|
# Use zone directly if provided
|
||||||
|
if [ "$GOOGLEDOMAINS_ZONE" ]; then
|
||||||
|
if ! _dns_googledomains_api "$GOOGLEDOMAINS_ZONE"; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$GOOGLEDOMAINS_ZONE"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
i=2
|
||||||
|
while true; do
|
||||||
|
curr=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
||||||
|
_debug curr "$curr"
|
||||||
|
|
||||||
|
if [ -z "$curr" ]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if _dns_googledomains_api "$curr"; then
|
||||||
|
echo "$curr"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
i=$(_math "$i" + 1)
|
||||||
|
done
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
_dns_googledomains_api() {
|
||||||
|
zone=$1
|
||||||
|
apimethod=$2
|
||||||
|
data="$3"
|
||||||
|
|
||||||
|
if [ -z "$data" ]; then
|
||||||
|
response="$(_get "$GOOGLEDOMAINS_API/$zone$apimethod")"
|
||||||
|
else
|
||||||
|
_debug data "$data"
|
||||||
|
export _H1="Content-Type: application/json"
|
||||||
|
response="$(_post "$data" "$GOOGLEDOMAINS_API/$zone$apimethod")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
_debug response "$response"
|
||||||
|
|
||||||
|
if [ "$?" != "0" ]; then
|
||||||
|
_err "Error"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if _contains "$response" "\"error\": {"; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
@ -23,7 +23,7 @@ dns_huaweicloud_add() {
|
|||||||
|
|
||||||
HUAWEICLOUD_Username="${HUAWEICLOUD_Username:-$(_readaccountconf_mutable HUAWEICLOUD_Username)}"
|
HUAWEICLOUD_Username="${HUAWEICLOUD_Username:-$(_readaccountconf_mutable HUAWEICLOUD_Username)}"
|
||||||
HUAWEICLOUD_Password="${HUAWEICLOUD_Password:-$(_readaccountconf_mutable HUAWEICLOUD_Password)}"
|
HUAWEICLOUD_Password="${HUAWEICLOUD_Password:-$(_readaccountconf_mutable HUAWEICLOUD_Password)}"
|
||||||
HUAWEICLOUD_DomainName="${HUAWEICLOUD_DomainName:-$(_readaccountconf_mutable HUAWEICLOUD_Username)}"
|
HUAWEICLOUD_DomainName="${HUAWEICLOUD_DomainName:-$(_readaccountconf_mutable HUAWEICLOUD_DomainName)}"
|
||||||
|
|
||||||
# Check information
|
# Check information
|
||||||
if [ -z "${HUAWEICLOUD_Username}" ] || [ -z "${HUAWEICLOUD_Password}" ] || [ -z "${HUAWEICLOUD_DomainName}" ]; then
|
if [ -z "${HUAWEICLOUD_Username}" ] || [ -z "${HUAWEICLOUD_Password}" ] || [ -z "${HUAWEICLOUD_DomainName}" ]; then
|
||||||
@ -74,7 +74,7 @@ dns_huaweicloud_rm() {
|
|||||||
|
|
||||||
HUAWEICLOUD_Username="${HUAWEICLOUD_Username:-$(_readaccountconf_mutable HUAWEICLOUD_Username)}"
|
HUAWEICLOUD_Username="${HUAWEICLOUD_Username:-$(_readaccountconf_mutable HUAWEICLOUD_Username)}"
|
||||||
HUAWEICLOUD_Password="${HUAWEICLOUD_Password:-$(_readaccountconf_mutable HUAWEICLOUD_Password)}"
|
HUAWEICLOUD_Password="${HUAWEICLOUD_Password:-$(_readaccountconf_mutable HUAWEICLOUD_Password)}"
|
||||||
HUAWEICLOUD_DomainName="${HUAWEICLOUD_DomainName:-$(_readaccountconf_mutable HUAWEICLOUD_Username)}"
|
HUAWEICLOUD_DomainName="${HUAWEICLOUD_DomainName:-$(_readaccountconf_mutable HUAWEICLOUD_DomainName)}"
|
||||||
|
|
||||||
# Check information
|
# Check information
|
||||||
if [ -z "${HUAWEICLOUD_Username}" ] || [ -z "${HUAWEICLOUD_Password}" ] || [ -z "${HUAWEICLOUD_DomainName}" ]; then
|
if [ -z "${HUAWEICLOUD_Username}" ] || [ -z "${HUAWEICLOUD_Password}" ] || [ -z "${HUAWEICLOUD_DomainName}" ]; then
|
||||||
@ -98,19 +98,59 @@ dns_huaweicloud_rm() {
|
|||||||
fi
|
fi
|
||||||
_debug "Zone ID is:" "${zoneid}"
|
_debug "Zone ID is:" "${zoneid}"
|
||||||
|
|
||||||
# Remove all records
|
|
||||||
# Therotically HuaweiCloud does not allow more than one record set
|
|
||||||
# But remove them recurringly to increase robusty
|
|
||||||
while [ "${record_id}" != "0" ]; do
|
|
||||||
_debug "Removing Record"
|
|
||||||
_rm_record "${token}" "${zoneid}" "${record_id}"
|
|
||||||
record_id="$(_get_recordset_id "${token}" "${fulldomain}" "${zoneid}")"
|
record_id="$(_get_recordset_id "${token}" "${fulldomain}" "${zoneid}")"
|
||||||
done
|
_recursive_rm_record "${token}" "${fulldomain}" "${zoneid}" "${record_id}"
|
||||||
|
ret="$?"
|
||||||
|
if [ "${ret}" != "0" ]; then
|
||||||
|
_err "dns_api(dns_huaweicloud): Error removing record."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
################### Private functions below ##################################
|
################### Private functions below ##################################
|
||||||
|
|
||||||
|
# _recursive_rm_record
|
||||||
|
# remove all records from the record set
|
||||||
|
#
|
||||||
|
# _token=$1
|
||||||
|
# _domain=$2
|
||||||
|
# _zoneid=$3
|
||||||
|
# _record_id=$4
|
||||||
|
#
|
||||||
|
# Returns 0 on success
|
||||||
|
_recursive_rm_record() {
|
||||||
|
_token=$1
|
||||||
|
_domain=$2
|
||||||
|
_zoneid=$3
|
||||||
|
_record_id=$4
|
||||||
|
|
||||||
|
# Most likely to have problems will huaweicloud side if more than 50 attempts but still cannot fully remove the record set
|
||||||
|
# Maybe can be removed manually in the dashboard
|
||||||
|
_retry_cnt=50
|
||||||
|
|
||||||
|
# Remove all records
|
||||||
|
# Therotically HuaweiCloud does not allow more than one record set
|
||||||
|
# But remove them recurringly to increase robusty
|
||||||
|
|
||||||
|
while [ "${_record_id}" != "0" ] && [ "${_retry_cnt}" != "0" ]; do
|
||||||
|
_debug "Removing Record"
|
||||||
|
_retry_cnt=$((_retry_cnt - 1))
|
||||||
|
_rm_record "${_token}" "${_zoneid}" "${_record_id}"
|
||||||
|
_record_id="$(_get_recordset_id "${_token}" "${_domain}" "${_zoneid}")"
|
||||||
|
_debug2 "Checking record exists: record_id=${_record_id}"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Check if retry count is reached
|
||||||
|
if [ "${_retry_cnt}" = "0" ]; then
|
||||||
|
_debug "Failed to remove record after 50 attempts, please try removing it manually in the dashboard"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
# _get_zoneid
|
# _get_zoneid
|
||||||
#
|
#
|
||||||
# _token=$1
|
# _token=$1
|
||||||
@ -124,7 +164,7 @@ _get_zoneid() {
|
|||||||
|
|
||||||
i=1
|
i=1
|
||||||
while true; do
|
while true; do
|
||||||
h=$(printf "%s" "${_domain_string}" | cut -d . -f $i-100)
|
h=$(printf "%s" "${_domain_string}" | cut -d . -f "$i"-100)
|
||||||
if [ -z "$h" ]; then
|
if [ -z "$h" ]; then
|
||||||
#not valid
|
#not valid
|
||||||
return 1
|
return 1
|
||||||
@ -135,11 +175,11 @@ _get_zoneid() {
|
|||||||
if _contains "${response}" '"id"'; then
|
if _contains "${response}" '"id"'; then
|
||||||
zoneidlist=$(echo "${response}" | _egrep_o "\"id\": *\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | tr -d " ")
|
zoneidlist=$(echo "${response}" | _egrep_o "\"id\": *\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | tr -d " ")
|
||||||
zonenamelist=$(echo "${response}" | _egrep_o "\"name\": *\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | tr -d " ")
|
zonenamelist=$(echo "${response}" | _egrep_o "\"name\": *\"[^\"]*\"" | cut -d : -f 2 | tr -d \" | tr -d " ")
|
||||||
_debug2 "Return Zone ID(s):" "${zoneidlist}"
|
_debug2 "Returned Zone ID(s):" "${zoneidlist}"
|
||||||
_debug2 "Return Zone Name(s):" "${zonenamelist}"
|
_debug2 "Returned Zone Name(s):" "${zonenamelist}"
|
||||||
zoneidnum=0
|
zoneidnum=0
|
||||||
zoneidcount=$(echo "${zoneidlist}" | grep -c '^')
|
zoneidcount=$(echo "${zoneidlist}" | grep -c '^')
|
||||||
_debug "Retund Zone ID(s) Count:" "${zoneidcount}"
|
_debug "Returned Zone ID(s) Count:" "${zoneidcount}"
|
||||||
while [ "${zoneidnum}" -lt "${zoneidcount}" ]; do
|
while [ "${zoneidnum}" -lt "${zoneidcount}" ]; do
|
||||||
zoneidnum=$(_math "$zoneidnum" + 1)
|
zoneidnum=$(_math "$zoneidnum" + 1)
|
||||||
_zoneid=$(echo "${zoneidlist}" | sed -n "${zoneidnum}p")
|
_zoneid=$(echo "${zoneidlist}" | sed -n "${zoneidnum}p")
|
||||||
@ -206,8 +246,7 @@ _add_record() {
|
|||||||
\"type\": \"TXT\",
|
\"type\": \"TXT\",
|
||||||
\"ttl\": 1,
|
\"ttl\": 1,
|
||||||
\"records\": [
|
\"records\": [
|
||||||
${_exist_record},
|
${_exist_record},\"\\\"${_txtvalue}\\\"\"
|
||||||
\"\\\"${_txtvalue}\\\"\"
|
|
||||||
]
|
]
|
||||||
}"
|
}"
|
||||||
fi
|
fi
|
||||||
@ -215,19 +254,16 @@ _add_record() {
|
|||||||
_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
|
|
||||||
while [ "${_record_id}" != "0" ]; do
|
|
||||||
_debug "Removing Record"
|
|
||||||
_rm_record "${_token}" "${zoneid}" "${_record_id}"
|
|
||||||
_record_id="$(_get_recordset_id "${_token}" "${_domain}" "${zoneid}")"
|
|
||||||
done
|
|
||||||
|
|
||||||
# Add brand new records with all old and new records
|
# Add brand new records with all old and new records
|
||||||
export _H2="Content-Type: application/json"
|
export _H2="Content-Type: application/json"
|
||||||
export _H1="X-Auth-Token: ${_token}"
|
export _H1="X-Auth-Token: ${_token}"
|
||||||
|
|
||||||
_debug2 "${_post_body}"
|
_debug2 "${_post_body}"
|
||||||
|
if [ -z "${_exist_record}" ]; then
|
||||||
_post "${_post_body}" "${dns_api}/v2/zones/${zoneid}/recordsets" >/dev/null
|
_post "${_post_body}" "${dns_api}/v2/zones/${zoneid}/recordsets" >/dev/null
|
||||||
|
else
|
||||||
|
_post "${_post_body}" "${dns_api}/v2/zones/${zoneid}/recordsets/${_record_id}" false "PUT" >/dev/null
|
||||||
|
fi
|
||||||
_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")"
|
||||||
if [ "$_code" != "202" ]; then
|
if [ "$_code" != "202" ]; then
|
||||||
_err "dns_huaweicloud: http code ${_code}"
|
_err "dns_huaweicloud: http code ${_code}"
|
||||||
|
@ -76,7 +76,7 @@ dns_infomaniak_add() {
|
|||||||
domain_id=${zone_and_id#* }
|
domain_id=${zone_and_id#* }
|
||||||
|
|
||||||
# extract first part of domain
|
# extract first part of domain
|
||||||
key=${fulldomain%.$zone}
|
key=${fulldomain%."$zone"}
|
||||||
|
|
||||||
_debug "zone:$zone id:$domain_id key:$key"
|
_debug "zone:$zone id:$domain_id key:$key"
|
||||||
|
|
||||||
@ -149,7 +149,7 @@ dns_infomaniak_rm() {
|
|||||||
domain_id=${zone_and_id#* }
|
domain_id=${zone_and_id#* }
|
||||||
|
|
||||||
# extract first part of domain
|
# extract first part of domain
|
||||||
key=${fulldomain%.$zone}
|
key=${fulldomain%."$zone"}
|
||||||
|
|
||||||
_debug "zone:$zone id:$domain_id key:$key"
|
_debug "zone:$zone id:$domain_id key:$key"
|
||||||
|
|
||||||
|
@ -194,7 +194,7 @@ _inwx_login() {
|
|||||||
|
|
||||||
response="$(_post "$xml_content" "$INWX_Api" "" "POST")"
|
response="$(_post "$xml_content" "$INWX_Api" "" "POST")"
|
||||||
|
|
||||||
INWX_Cookie=$(printf "Cookie: %s" "$(grep "domrobot=" "$HTTP_HEADER" | grep "^Set-Cookie:" | _tail_n 1 | _egrep_o 'domrobot=[^;]*;' | tr -d ';')")
|
INWX_Cookie=$(printf "Cookie: %s" "$(grep "domrobot=" "$HTTP_HEADER" | grep -i "^Set-Cookie:" | _tail_n 1 | _egrep_o 'domrobot=[^;]*;' | tr -d ';')")
|
||||||
_H1=$INWX_Cookie
|
_H1=$INWX_Cookie
|
||||||
export _H1
|
export _H1
|
||||||
export INWX_Cookie
|
export INWX_Cookie
|
||||||
|
157
dnsapi/dns_ipv64.sh
Executable file
157
dnsapi/dns_ipv64.sh
Executable file
@ -0,0 +1,157 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
#Created by Roman Lumetsberger, to use ipv64.net's API to add/remove text records
|
||||||
|
#2022/11/29
|
||||||
|
|
||||||
|
# Pass credentials before "acme.sh --issue --dns dns_ipv64 ..."
|
||||||
|
# --
|
||||||
|
# export IPv64_Token="aaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
# --
|
||||||
|
#
|
||||||
|
|
||||||
|
IPv64_API="https://ipv64.net/api"
|
||||||
|
|
||||||
|
######## Public functions ######################
|
||||||
|
|
||||||
|
#Usage: dns_ipv64_add _acme-challenge.domain.ipv64.net "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||||
|
dns_ipv64_add() {
|
||||||
|
fulldomain=$1
|
||||||
|
txtvalue=$2
|
||||||
|
|
||||||
|
IPv64_Token="${IPv64_Token:-$(_readaccountconf_mutable IPv64_Token)}"
|
||||||
|
if [ -z "$IPv64_Token" ]; then
|
||||||
|
_err "You must export variable: IPv64_Token"
|
||||||
|
_err "The API Key for your IPv64 account is necessary."
|
||||||
|
_err "You can look it up in your IPv64 account."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Now save the credentials.
|
||||||
|
_saveaccountconf_mutable IPv64_Token "$IPv64_Token"
|
||||||
|
|
||||||
|
if ! _get_root "$fulldomain"; then
|
||||||
|
_err "invalid domain" "$fulldomain"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_debug _sub_domain "$_sub_domain"
|
||||||
|
_debug _domain "$_domain"
|
||||||
|
|
||||||
|
# convert to lower case
|
||||||
|
_domain="$(echo "$_domain" | _lower_case)"
|
||||||
|
_sub_domain="$(echo "$_sub_domain" | _lower_case)"
|
||||||
|
# Now add the TXT record
|
||||||
|
_info "Trying to add TXT record"
|
||||||
|
if _ipv64_rest "POST" "add_record=$_domain&praefix=$_sub_domain&type=TXT&content=$txtvalue"; then
|
||||||
|
_info "TXT record has been successfully added."
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
_err "Errors happened during adding the TXT record, response=$_response"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#Usage: fulldomain txtvalue
|
||||||
|
#Usage: dns_ipv64_rm _acme-challenge.domain.ipv64.net "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||||
|
#Remove the txt record after validation.
|
||||||
|
dns_ipv64_rm() {
|
||||||
|
fulldomain=$1
|
||||||
|
txtvalue=$2
|
||||||
|
|
||||||
|
IPv64_Token="${IPv64_Token:-$(_readaccountconf_mutable IPv64_Token)}"
|
||||||
|
if [ -z "$IPv64_Token" ]; then
|
||||||
|
_err "You must export variable: IPv64_Token"
|
||||||
|
_err "The API Key for your IPv64 account is necessary."
|
||||||
|
_err "You can look it up in your IPv64 account."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! _get_root "$fulldomain"; then
|
||||||
|
_err "invalid domain" "$fulldomain"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_debug _sub_domain "$_sub_domain"
|
||||||
|
_debug _domain "$_domain"
|
||||||
|
|
||||||
|
# convert to lower case
|
||||||
|
_domain="$(echo "$_domain" | _lower_case)"
|
||||||
|
_sub_domain="$(echo "$_sub_domain" | _lower_case)"
|
||||||
|
# Now delete the TXT record
|
||||||
|
_info "Trying to delete TXT record"
|
||||||
|
if _ipv64_rest "DELETE" "del_record=$_domain&praefix=$_sub_domain&type=TXT&content=$txtvalue"; then
|
||||||
|
_info "TXT record has been successfully deleted."
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
_err "Errors happened during deleting the TXT record, response=$_response"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#################### Private functions below ##################################
|
||||||
|
#_acme-challenge.www.domain.com
|
||||||
|
#returns
|
||||||
|
# _sub_domain=_acme-challenge.www
|
||||||
|
# _domain=domain.com
|
||||||
|
_get_root() {
|
||||||
|
domain="$1"
|
||||||
|
i=1
|
||||||
|
p=1
|
||||||
|
|
||||||
|
_ipv64_get "get_domains"
|
||||||
|
domain_data=$_response
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
|
||||||
|
if [ -z "$h" ]; then
|
||||||
|
#not valid
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
#if _contains "$domain_data" "\""$h"\"\:"; then
|
||||||
|
if _contains "$domain_data" "\"""$h""\"\:"; then
|
||||||
|
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
|
||||||
|
_domain="$h"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
p=$i
|
||||||
|
i=$(_math "$i" + 1)
|
||||||
|
done
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
#send get request to api
|
||||||
|
# $1 has to set the api-function
|
||||||
|
_ipv64_get() {
|
||||||
|
url="$IPv64_API?$1"
|
||||||
|
export _H1="Authorization: Bearer $IPv64_Token"
|
||||||
|
|
||||||
|
_response=$(_get "$url")
|
||||||
|
_response="$(echo "$_response" | _normalizeJson)"
|
||||||
|
|
||||||
|
if _contains "$_response" "429 Too Many Requests"; then
|
||||||
|
_info "API throttled, sleeping to reset the limit"
|
||||||
|
_sleep 10
|
||||||
|
_response=$(_get "$url")
|
||||||
|
_response="$(echo "$_response" | _normalizeJson)"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
_ipv64_rest() {
|
||||||
|
url="$IPv64_API"
|
||||||
|
export _H1="Authorization: Bearer $IPv64_Token"
|
||||||
|
export _H2="Content-Type: application/x-www-form-urlencoded"
|
||||||
|
_response=$(_post "$2" "$url" "" "$1")
|
||||||
|
|
||||||
|
if _contains "$_response" "429 Too Many Requests"; then
|
||||||
|
_info "API throttled, sleeping to reset the limit"
|
||||||
|
_sleep 10
|
||||||
|
_response=$(_post "$2" "$url" "" "$1")
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! _contains "$_response" "\"info\":\"success\""; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_debug2 response "$_response"
|
||||||
|
return 0
|
||||||
|
}
|
@ -45,8 +45,8 @@ dns_kappernet_add() {
|
|||||||
if _kappernet_api GET "action=new&subject=$_domain&data=$data"; then
|
if _kappernet_api GET "action=new&subject=$_domain&data=$data"; then
|
||||||
|
|
||||||
if _contains "$response" "{\"OK\":true"; then
|
if _contains "$response" "{\"OK\":true"; then
|
||||||
_info "Waiting 120 seconds for DNS to spread the new record"
|
_info "Waiting 1 second for DNS to spread the new record"
|
||||||
_sleep 120
|
_sleep 1
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
_err "Error creating a TXT DNS Record: $fullhostname TXT $txtvalue"
|
_err "Error creating a TXT DNS Record: $fullhostname TXT $txtvalue"
|
||||||
|
@ -215,7 +215,7 @@ _get_record_id() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_record_id="$(echo "$response" | tr -d '\n\r' | sed "s/<item xsi:type=\"ns2:Map\">/\n/g" | grep -i "$_record_name" | grep -i ">TXT<" | sed "s/<item><key xsi:type=\"xsd:string\">record_id<\/key><value xsi:type=\"xsd:string\">/=>/g" | sed "s/<\/value><\/item>/\n/g" | grep "=>" | sed "s/=>//g")"
|
_record_id="$(echo "$response" | tr -d '\n\r' | sed "s/<item xsi:type=\"ns2:Map\">/\n/g" | grep -i "$_record_name" | grep -i ">TXT<" | sed "s/<item><key xsi:type=\"xsd:string\">record_id<\/key><value xsi:type=\"xsd:string\">/=>/g" | grep -i "$_txtvalue" | sed "s/<\/value><\/item>/\n/g" | grep "=>" | sed "s/=>//g")"
|
||||||
_debug "[KAS] -> Record Id: " "$_record_id"
|
_debug "[KAS] -> Record Id: " "$_record_id"
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
############################################################
|
############################################################
|
||||||
# KingHost API support #
|
# KingHost API support #
|
||||||
# http://api.kinghost.net/doc/ #
|
# https://api.kinghost.net/doc/ #
|
||||||
# #
|
# #
|
||||||
# Author: Felipe Keller Braz <felipebraz@kinghost.com.br> #
|
# Author: Felipe Keller Braz <felipebraz@kinghost.com.br> #
|
||||||
# Report Bugs here: https://github.com/kinghost/acme.sh #
|
# Report Bugs here: https://github.com/kinghost/acme.sh #
|
||||||
|
@ -3,10 +3,10 @@
|
|||||||
#Author: Rolph Haspers <r.haspers@global.leaseweb.com>
|
#Author: Rolph Haspers <r.haspers@global.leaseweb.com>
|
||||||
#Utilize leaseweb.com API to finish dns-01 verifications.
|
#Utilize leaseweb.com API to finish dns-01 verifications.
|
||||||
#Requires a Leaseweb API Key (export LSW_Key="Your Key")
|
#Requires a Leaseweb API Key (export LSW_Key="Your Key")
|
||||||
#See http://developer.leaseweb.com for more information.
|
#See https://developer.leaseweb.com for more information.
|
||||||
######## Public functions #####################
|
######## Public functions #####################
|
||||||
|
|
||||||
LSW_API="https://api.leaseweb.com/hosting/v2/domains/"
|
LSW_API="https://api.leaseweb.com/hosting/v2/domains"
|
||||||
|
|
||||||
#Usage: dns_leaseweb_add _acme-challenge.www.domain.com
|
#Usage: dns_leaseweb_add _acme-challenge.www.domain.com
|
||||||
dns_leaseweb_add() {
|
dns_leaseweb_add() {
|
||||||
|
@ -107,7 +107,7 @@ _loopia_load_config() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if _contains "$LOOPIA_Password" "'" || _contains "$LOOPIA_Password" '"'; then
|
if _contains "$LOOPIA_Password" "'" || _contains "$LOOPIA_Password" '"'; then
|
||||||
_err "Password contains quoute or double quoute and this is not supported by dns_loopia.sh"
|
_err "Password contains a quotation mark or double quotation marks and this is not supported by dns_loopia.sh"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ _get_root() {
|
|||||||
_debug "Failed domain lookup via domains.getList api call. Trying domain lookup via domains.dns.getHosts api."
|
_debug "Failed domain lookup via domains.getList api call. Trying domain lookup via domains.dns.getHosts api."
|
||||||
# The above "getList" api will only return hosts *owned* by the calling user. However, if the calling
|
# The above "getList" api will only return hosts *owned* by the calling user. However, if the calling
|
||||||
# user is not the owner, but still has administrative rights, we must query the getHosts api directly.
|
# user is not the owner, but still has administrative rights, we must query the getHosts api directly.
|
||||||
# See this comment and the official namecheap response: http://disq.us/p/1q6v9x9
|
# See this comment and the official namecheap response: https://disq.us/p/1q6v9x9
|
||||||
if ! _get_root_by_getHosts "$fulldomain"; then
|
if ! _get_root_by_getHosts "$fulldomain"; then
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
59
dnsapi/dns_nanelo.sh
Normal file
59
dnsapi/dns_nanelo.sh
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
# Official DNS API for Nanelo.com
|
||||||
|
|
||||||
|
# Provide the required API Key like this:
|
||||||
|
# NANELO_TOKEN="FmD408PdqT1E269gUK57"
|
||||||
|
|
||||||
|
NANELO_API="https://api.nanelo.com/v1/"
|
||||||
|
|
||||||
|
######## Public functions #####################
|
||||||
|
|
||||||
|
# Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||||
|
dns_nanelo_add() {
|
||||||
|
fulldomain=$1
|
||||||
|
txtvalue=$2
|
||||||
|
|
||||||
|
NANELO_TOKEN="${NANELO_TOKEN:-$(_readaccountconf_mutable NANELO_TOKEN)}"
|
||||||
|
if [ -z "$NANELO_TOKEN" ]; then
|
||||||
|
NANELO_TOKEN=""
|
||||||
|
_err "You didn't configure a Nanelo API Key yet."
|
||||||
|
_err "Please set NANELO_TOKEN and try again."
|
||||||
|
_err "Login to Nanelo.com and go to Settings > API Keys to get a Key"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_saveaccountconf_mutable NANELO_TOKEN "$NANELO_TOKEN"
|
||||||
|
|
||||||
|
_info "Adding TXT record to ${fulldomain}"
|
||||||
|
response="$(_get "$NANELO_API$NANELO_TOKEN/dns/addrecord?type=TXT&ttl=60&name=${fulldomain}&value=${txtvalue}")"
|
||||||
|
if _contains "${response}" 'success'; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
_err "Could not create resource record, please check the logs"
|
||||||
|
_err "${response}"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
dns_nanelo_rm() {
|
||||||
|
fulldomain=$1
|
||||||
|
txtvalue=$2
|
||||||
|
|
||||||
|
NANELO_TOKEN="${NANELO_TOKEN:-$(_readaccountconf_mutable NANELO_TOKEN)}"
|
||||||
|
if [ -z "$NANELO_TOKEN" ]; then
|
||||||
|
NANELO_TOKEN=""
|
||||||
|
_err "You didn't configure a Nanelo API Key yet."
|
||||||
|
_err "Please set NANELO_TOKEN and try again."
|
||||||
|
_err "Login to Nanelo.com and go to Settings > API Keys to get a Key"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_saveaccountconf_mutable NANELO_TOKEN "$NANELO_TOKEN"
|
||||||
|
|
||||||
|
_info "Deleting resource record $fulldomain"
|
||||||
|
response="$(_get "$NANELO_API$NANELO_TOKEN/dns/deleterecord?type=TXT&ttl=60&name=${fulldomain}&value=${txtvalue}")"
|
||||||
|
if _contains "${response}" 'success'; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
_err "Could not delete resource record, please check the logs"
|
||||||
|
_err "${response}"
|
||||||
|
return 1
|
||||||
|
}
|
@ -265,6 +265,7 @@ _signed_request() {
|
|||||||
_response="$(_get "https://${_sig_host}${_sig_target}")"
|
_response="$(_get "https://${_sig_host}${_sig_target}")"
|
||||||
elif [ "$_curl_method" = "PATCH" ]; then
|
elif [ "$_curl_method" = "PATCH" ]; then
|
||||||
export _H1="$_date_header"
|
export _H1="$_date_header"
|
||||||
|
# shellcheck disable=SC2090
|
||||||
export _H2="$_sig_body_sha256"
|
export _H2="$_sig_body_sha256"
|
||||||
export _H3="$_sig_body_type"
|
export _H3="$_sig_body_type"
|
||||||
export _H4="$_sig_body_length"
|
export _H4="$_sig_body_length"
|
||||||
|
@ -57,16 +57,16 @@ _dns_openstack_create_recordset() {
|
|||||||
|
|
||||||
if [ -z "$_recordset_id" ]; then
|
if [ -z "$_recordset_id" ]; then
|
||||||
_info "Creating a new recordset"
|
_info "Creating a new recordset"
|
||||||
if ! _recordset_id=$(openstack recordset create -c id -f value --type TXT --record "$txtvalue" "$_zone_id" "$fulldomain."); then
|
if ! _recordset_id=$(openstack recordset create -c id -f value --type TXT --record="$txtvalue" "$_zone_id" "$fulldomain."); then
|
||||||
_err "No recordset ID found after create"
|
_err "No recordset ID found after create"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
_info "Updating existing recordset"
|
_info "Updating existing recordset"
|
||||||
# Build new list of --record <rec> args for update
|
# Build new list of --record=<rec> args for update
|
||||||
_record_args="--record $txtvalue"
|
_record_args="--record=$txtvalue"
|
||||||
for _rec in $_records; do
|
for _rec in $_records; do
|
||||||
_record_args="$_record_args --record $_rec"
|
_record_args="$_record_args --record=$_rec"
|
||||||
done
|
done
|
||||||
# shellcheck disable=SC2086
|
# shellcheck disable=SC2086
|
||||||
if ! _recordset_id=$(openstack recordset set -c id -f value $_record_args "$_zone_id" "$fulldomain."); then
|
if ! _recordset_id=$(openstack recordset set -c id -f value $_record_args "$_zone_id" "$fulldomain."); then
|
||||||
@ -107,13 +107,13 @@ _dns_openstack_delete_recordset() {
|
|||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
_info "Found existing records, updating recordset"
|
_info "Found existing records, updating recordset"
|
||||||
# Build new list of --record <rec> args for update
|
# Build new list of --record=<rec> args for update
|
||||||
_record_args=""
|
_record_args=""
|
||||||
for _rec in $_records; do
|
for _rec in $_records; do
|
||||||
if [ "$_rec" = "$txtvalue" ]; then
|
if [ "$_rec" = "$txtvalue" ]; then
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
_record_args="$_record_args --record $_rec"
|
_record_args="$_record_args --record=$_rec"
|
||||||
done
|
done
|
||||||
# shellcheck disable=SC2086
|
# shellcheck disable=SC2086
|
||||||
if ! openstack recordset set -c id -f value $_record_args "$_zone_id" "$fulldomain." >/dev/null; then
|
if ! openstack recordset set -c id -f value $_record_args "$_zone_id" "$fulldomain." >/dev/null; then
|
||||||
|
@ -137,7 +137,7 @@ _get_root() {
|
|||||||
domain=$1
|
domain=$1
|
||||||
i=2
|
i=2
|
||||||
p=1
|
p=1
|
||||||
if _opns_rest "GET" "/domain/searchMasterDomain"; then
|
if _opns_rest "GET" "/domain/searchPrimaryDomain"; then
|
||||||
_domain_response="$response"
|
_domain_response="$response"
|
||||||
else
|
else
|
||||||
return 1
|
return 1
|
||||||
@ -150,7 +150,7 @@ _get_root() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
_debug h "$h"
|
_debug h "$h"
|
||||||
id=$(echo "$_domain_response" | _egrep_o "\"uuid\":\"[a-z0-9\-]*\",\"enabled\":\"1\",\"type\":\"master\",\"domainname\":\"${h}\"" | cut -d ':' -f 2 | cut -d '"' -f 2)
|
id=$(echo "$_domain_response" | _egrep_o "\"uuid\":\"[a-z0-9\-]*\",\"enabled\":\"1\",\"type\":\"primary\",\"domainname\":\"${h}\"" | cut -d ':' -f 2 | cut -d '"' -f 2)
|
||||||
if [ -n "$id" ]; then
|
if [ -n "$id" ]; then
|
||||||
_debug id "$id"
|
_debug id "$id"
|
||||||
_host=$(printf "%s" "$domain" | cut -d . -f 1-$p)
|
_host=$(printf "%s" "$domain" | cut -d . -f 1-$p)
|
||||||
|
@ -14,6 +14,9 @@
|
|||||||
#'ovh-eu'
|
#'ovh-eu'
|
||||||
OVH_EU='https://eu.api.ovh.com/1.0'
|
OVH_EU='https://eu.api.ovh.com/1.0'
|
||||||
|
|
||||||
|
#'ovh-us'
|
||||||
|
OVH_US='https://api.us.ovhcloud.com/1.0'
|
||||||
|
|
||||||
#'ovh-ca':
|
#'ovh-ca':
|
||||||
OVH_CA='https://ca.api.ovh.com/1.0'
|
OVH_CA='https://ca.api.ovh.com/1.0'
|
||||||
|
|
||||||
@ -29,9 +32,6 @@ SYS_EU='https://eu.api.soyoustart.com/1.0'
|
|||||||
#'soyoustart-ca'
|
#'soyoustart-ca'
|
||||||
SYS_CA='https://ca.api.soyoustart.com/1.0'
|
SYS_CA='https://ca.api.soyoustart.com/1.0'
|
||||||
|
|
||||||
#'runabove-ca'
|
|
||||||
RAV_CA='https://api.runabove.com/1.0'
|
|
||||||
|
|
||||||
wiki="https://github.com/acmesh-official/acme.sh/wiki/How-to-use-OVH-domain-api"
|
wiki="https://github.com/acmesh-official/acme.sh/wiki/How-to-use-OVH-domain-api"
|
||||||
|
|
||||||
ovh_success="https://github.com/acmesh-official/acme.sh/wiki/OVH-Success"
|
ovh_success="https://github.com/acmesh-official/acme.sh/wiki/OVH-Success"
|
||||||
@ -45,6 +45,10 @@ _ovh_get_api() {
|
|||||||
printf "%s" $OVH_EU
|
printf "%s" $OVH_EU
|
||||||
return
|
return
|
||||||
;;
|
;;
|
||||||
|
ovh-us | ovhus)
|
||||||
|
printf "%s" $OVH_US
|
||||||
|
return
|
||||||
|
;;
|
||||||
ovh-ca | ovhca)
|
ovh-ca | ovhca)
|
||||||
printf "%s" $OVH_CA
|
printf "%s" $OVH_CA
|
||||||
return
|
return
|
||||||
@ -65,14 +69,15 @@ _ovh_get_api() {
|
|||||||
printf "%s" $SYS_CA
|
printf "%s" $SYS_CA
|
||||||
return
|
return
|
||||||
;;
|
;;
|
||||||
runabove-ca | runaboveca)
|
# raw API url starts with https://
|
||||||
printf "%s" $RAV_CA
|
https*)
|
||||||
|
printf "%s" "$1"
|
||||||
return
|
return
|
||||||
;;
|
;;
|
||||||
|
|
||||||
*)
|
*)
|
||||||
|
|
||||||
_err "Unknown parameter : $1"
|
_err "Unknown endpoint : $1"
|
||||||
return 1
|
return 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
@ -41,11 +41,15 @@ pleskxml_init_checks_done=0
|
|||||||
NEWLINE='\
|
NEWLINE='\
|
||||||
'
|
'
|
||||||
|
|
||||||
pleskxml_tplt_get_domains="<packet><customer><get-domain-list><filter/></get-domain-list></customer></packet>"
|
pleskxml_tplt_get_domains="<packet><webspace><get><filter/><dataset><gen_info/></dataset></get></webspace></packet>"
|
||||||
# Get a list of domains that PLESK can manage, so we can check root domain + host for acme.sh
|
# Get a list of domains that PLESK can manage, so we can check root domain + host for acme.sh
|
||||||
# Also used to test credentials and URI.
|
# Also used to test credentials and URI.
|
||||||
# No params.
|
# No params.
|
||||||
|
|
||||||
|
pleskxml_tplt_get_additional_domains="<packet><site><get><filter/><dataset><gen_info/></dataset></get></site></packet>"
|
||||||
|
# Get a list of additional domains that PLESK can manage, so we can check root domain + host for acme.sh
|
||||||
|
# No params.
|
||||||
|
|
||||||
pleskxml_tplt_get_dns_records="<packet><dns><get_rec><filter><site-id>%s</site-id></filter></get_rec></dns></packet>"
|
pleskxml_tplt_get_dns_records="<packet><dns><get_rec><filter><site-id>%s</site-id></filter></get_rec></dns></packet>"
|
||||||
# Get all DNS records for a Plesk domain ID.
|
# Get all DNS records for a Plesk domain ID.
|
||||||
# PARAM = Plesk domain id to query
|
# PARAM = Plesk domain id to query
|
||||||
@ -145,22 +149,25 @@ dns_pleskxml_rm() {
|
|||||||
)"
|
)"
|
||||||
|
|
||||||
if [ -z "$reclist" ]; then
|
if [ -z "$reclist" ]; then
|
||||||
_err "No TXT records found for root domain ${root_domain_name} (Plesk domain ID ${root_domain_id}). Exiting."
|
_err "No TXT records found for root domain $fulldomain (Plesk domain ID ${root_domain_id}). Exiting."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_debug "Got list of DNS TXT records for root domain '$root_domain_name':"
|
_debug "Got list of DNS TXT records for root Plesk domain ID ${root_domain_id} of root domain $fulldomain:"
|
||||||
_debug "$reclist"
|
_debug "$reclist"
|
||||||
|
|
||||||
|
# Extracting the id of the TXT record for the full domain (NOT case-sensitive) and corresponding value
|
||||||
recid="$(
|
recid="$(
|
||||||
_value "$reclist" |
|
_value "$reclist" |
|
||||||
grep "<host>${fulldomain}.</host>" |
|
grep -i "<host>${fulldomain}.</host>" |
|
||||||
grep "<value>${txtvalue}</value>" |
|
grep "<value>${txtvalue}</value>" |
|
||||||
sed 's/^.*<id>\([0-9]\{1,\}\)<\/id>.*$/\1/'
|
sed 's/^.*<id>\([0-9]\{1,\}\)<\/id>.*$/\1/'
|
||||||
)"
|
)"
|
||||||
|
|
||||||
|
_debug "Got id from line: $recid"
|
||||||
|
|
||||||
if ! _value "$recid" | grep '^[0-9]\{1,\}$' >/dev/null; then
|
if ! _value "$recid" | grep '^[0-9]\{1,\}$' >/dev/null; then
|
||||||
_err "DNS records for root domain '${root_domain_name}' (Plesk ID ${root_domain_id}) + host '${sub_domain_name}' do not contain the TXT record '${txtvalue}'"
|
_err "DNS records for root domain '${fulldomain}.' (Plesk ID ${root_domain_id}) + host '${sub_domain_name}' do not contain the TXT record '${txtvalue}'"
|
||||||
_err "Cannot delete TXT record. Exiting."
|
_err "Cannot delete TXT record. Exiting."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
@ -251,9 +258,12 @@ _call_api() {
|
|||||||
|
|
||||||
# Detect any <status> that isn't "ok". None of the used calls should fail if the API is working correctly.
|
# Detect any <status> that isn't "ok". None of the used calls should fail if the API is working correctly.
|
||||||
# Also detect if there simply aren't any status lines (null result?) and report that, as well.
|
# Also detect if there simply aren't any status lines (null result?) and report that, as well.
|
||||||
|
# Remove <data></data> structure from result string, since it might contain <status> values that are related to the status of the domain and not to the API request
|
||||||
|
|
||||||
statuslines_count_total="$(echo "$pleskxml_prettyprint_result" | grep -c '^ *<status>[^<]*</status> *$')"
|
statuslines_count_total="$(echo "$pleskxml_prettyprint_result" | sed '/<data>/,/<\/data>/d' | grep -c '^ *<status>[^<]*</status> *$')"
|
||||||
statuslines_count_okay="$(echo "$pleskxml_prettyprint_result" | grep -c '^ *<status>ok</status> *$')"
|
statuslines_count_okay="$(echo "$pleskxml_prettyprint_result" | sed '/<data>/,/<\/data>/d' | grep -c '^ *<status>ok</status> *$')"
|
||||||
|
_debug "statuslines_count_total=$statuslines_count_total."
|
||||||
|
_debug "statuslines_count_okay=$statuslines_count_okay."
|
||||||
|
|
||||||
if [ -z "$statuslines_count_total" ]; then
|
if [ -z "$statuslines_count_total" ]; then
|
||||||
|
|
||||||
@ -369,16 +379,44 @@ _pleskxml_get_root_domain() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Generate a crude list of domains known to this Plesk account.
|
# Generate a crude list of domains known to this Plesk account based on subscriptions.
|
||||||
# We convert <ascii-name> tags to <name> so it'll flag on a hit with either <name> or <ascii-name> fields,
|
# We convert <ascii-name> tags to <name> so it'll flag on a hit with either <name> or <ascii-name> fields,
|
||||||
# for non-Western character sets.
|
# for non-Western character sets.
|
||||||
# Output will be one line per known domain, containing 2 <name> tages and a single <id> tag
|
# Output will be one line per known domain, containing 2 <name> tages and a single <id> tag
|
||||||
# We don't actually need to check for type, name, *and* id, but it guarantees only usable lines are returned.
|
# We don't actually need to check for type, name, *and* id, but it guarantees only usable lines are returned.
|
||||||
|
|
||||||
output="$(_api_response_split "$pleskxml_prettyprint_result" 'domain' '<type>domain</type>' | sed 's/<ascii-name>/<name>/g;s/<\/ascii-name>/<\/name>/g' | grep '<name>' | grep '<id>')"
|
output="$(_api_response_split "$pleskxml_prettyprint_result" 'result' '<status>ok</status>' | sed 's/<ascii-name>/<name>/g;s/<\/ascii-name>/<\/name>/g' | grep '<name>' | grep '<id>')"
|
||||||
|
debug_output="$(printf "%s" "$output" | sed -n 's:.*<name>\(.*\)</name>.*:\1:p')"
|
||||||
|
|
||||||
_debug 'Domains managed by Plesk server are (ignore the hacked output):'
|
_debug 'Domains managed by Plesk server are:'
|
||||||
_debug "$output"
|
_debug "$debug_output"
|
||||||
|
|
||||||
|
_debug "Querying Plesk server for list of additional managed domains..."
|
||||||
|
|
||||||
|
_call_api "$pleskxml_tplt_get_additional_domains"
|
||||||
|
if [ "$pleskxml_retcode" -ne 0 ]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Generate a crude list of additional domains known to this Plesk account based on sites.
|
||||||
|
# We convert <ascii-name> tags to <name> so it'll flag on a hit with either <name> or <ascii-name> fields,
|
||||||
|
# for non-Western character sets.
|
||||||
|
# Output will be one line per known domain, containing 2 <name> tages and a single <id> tag
|
||||||
|
# We don't actually need to check for type, name, *and* id, but it guarantees only usable lines are returned.
|
||||||
|
|
||||||
|
output_additional="$(_api_response_split "$pleskxml_prettyprint_result" 'result' '<status>ok</status>' | sed 's/<ascii-name>/<name>/g;s/<\/ascii-name>/<\/name>/g' | grep '<name>' | grep '<id>')"
|
||||||
|
debug_additional="$(printf "%s" "$output_additional" | sed -n 's:.*<name>\(.*\)</name>.*:\1:p')"
|
||||||
|
|
||||||
|
_debug 'Additional domains managed by Plesk server are:'
|
||||||
|
_debug "$debug_additional"
|
||||||
|
|
||||||
|
# Concate the two outputs together.
|
||||||
|
|
||||||
|
output="$(printf "%s" "$output $NEWLINE $output_additional")"
|
||||||
|
debug_output="$(printf "%s" "$output" | sed -n 's:.*<name>\(.*\)</name>.*:\1:p')"
|
||||||
|
|
||||||
|
_debug 'Domains (including additional) managed by Plesk server are:'
|
||||||
|
_debug "$debug_output"
|
||||||
|
|
||||||
# loop and test if domain, or any parent domain, is managed by Plesk
|
# loop and test if domain, or any parent domain, is managed by Plesk
|
||||||
# Loop until we don't have any '.' in the string we're testing as a candidate Plesk-managed domain
|
# Loop until we don't have any '.' in the string we're testing as a candidate Plesk-managed domain
|
||||||
|
@ -53,7 +53,7 @@ dns_servercow_add() {
|
|||||||
if printf -- "%s" "$response" | grep "{\"name\":\"$_sub_domain\",\"ttl\":20,\"type\":\"TXT\"" >/dev/null; then
|
if printf -- "%s" "$response" | grep "{\"name\":\"$_sub_domain\",\"ttl\":20,\"type\":\"TXT\"" >/dev/null; then
|
||||||
_info "A txt record with the same name already exists."
|
_info "A txt record with the same name already exists."
|
||||||
# trim the string on the left
|
# trim the string on the left
|
||||||
txtvalue_old=${response#*{\"name\":\"$_sub_domain\",\"ttl\":20,\"type\":\"TXT\",\"content\":\"}
|
txtvalue_old=${response#*{\"name\":\""$_sub_domain"\",\"ttl\":20,\"type\":\"TXT\",\"content\":\"}
|
||||||
# trim the string on the right
|
# trim the string on the right
|
||||||
txtvalue_old=${txtvalue_old%%\"*}
|
txtvalue_old=${txtvalue_old%%\"*}
|
||||||
|
|
||||||
|
211
dnsapi/dns_tencent.sh
Normal file
211
dnsapi/dns_tencent.sh
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
Tencent_API="https://dnspod.tencentcloudapi.com"
|
||||||
|
|
||||||
|
#Tencent_SecretId="AKIDz81d2cd22cdcdc2dcd1cc1d1A"
|
||||||
|
#Tencent_SecretKey="Gu5t9abcabcaabcbabcbbbcbcbbccbbcb"
|
||||||
|
|
||||||
|
#Usage: dns_tencent_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||||
|
dns_tencent_add() {
|
||||||
|
fulldomain=$1
|
||||||
|
txtvalue=$2
|
||||||
|
|
||||||
|
Tencent_SecretId="${Tencent_SecretId:-$(_readaccountconf_mutable Tencent_SecretId)}"
|
||||||
|
Tencent_SecretKey="${Tencent_SecretKey:-$(_readaccountconf_mutable Tencent_SecretKey)}"
|
||||||
|
if [ -z "$Tencent_SecretId" ] || [ -z "$Tencent_SecretKey" ]; then
|
||||||
|
Tencent_SecretId=""
|
||||||
|
Tencent_SecretKey=""
|
||||||
|
_err "You don't specify tencent api SecretId and SecretKey yet."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
#save the api SecretId and SecretKey to the account conf file.
|
||||||
|
_saveaccountconf_mutable Tencent_SecretId "$Tencent_SecretId"
|
||||||
|
_saveaccountconf_mutable Tencent_SecretKey "$Tencent_SecretKey"
|
||||||
|
|
||||||
|
_debug "First detect the root zone"
|
||||||
|
if ! _get_root "$fulldomain"; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_debug "Add record"
|
||||||
|
_add_record_query "$_domain" "$_sub_domain" "$txtvalue" && _tencent_rest "CreateRecord"
|
||||||
|
}
|
||||||
|
|
||||||
|
dns_tencent_rm() {
|
||||||
|
fulldomain=$1
|
||||||
|
txtvalue=$2
|
||||||
|
Tencent_SecretId="${Tencent_SecretId:-$(_readaccountconf_mutable Tencent_SecretId)}"
|
||||||
|
Tencent_SecretKey="${Tencent_SecretKey:-$(_readaccountconf_mutable Tencent_SecretKey)}"
|
||||||
|
|
||||||
|
_debug "First detect the root zone"
|
||||||
|
if ! _get_root "$fulldomain"; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_debug "Get record list"
|
||||||
|
attempt=1
|
||||||
|
max_attempts=5
|
||||||
|
while [ -z "$record_id" ] && [ "$attempt" -le $max_attempts ]; do
|
||||||
|
_check_exist_query "$_domain" "$_sub_domain" "$txtvalue" && _tencent_rest "DescribeRecordFilterList"
|
||||||
|
record_id="$(echo "$response" | _egrep_o "\"RecordId\":\s*[0-9]+" | _egrep_o "[0-9]+")"
|
||||||
|
_debug2 record_id "$record_id"
|
||||||
|
if [ -z "$record_id" ]; then
|
||||||
|
_debug "Due to TencentCloud API synchronization delay, record not found, waiting 10 seconds and retrying"
|
||||||
|
_sleep 10
|
||||||
|
attempt=$(_math "$attempt + 1")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
record_id="$(echo "$response" | _egrep_o "\"RecordId\":\s*[0-9]+" | _egrep_o "[0-9]+")"
|
||||||
|
_debug2 record_id "$record_id"
|
||||||
|
|
||||||
|
if [ -z "$record_id" ]; then
|
||||||
|
_debug "record not found after $max_attempts attempts, skip"
|
||||||
|
else
|
||||||
|
_debug "Delete record"
|
||||||
|
_delete_record_query "$record_id" && _tencent_rest "DeleteRecord"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#################### Private functions below ##################################
|
||||||
|
|
||||||
|
_get_root() {
|
||||||
|
domain=$1
|
||||||
|
i=1
|
||||||
|
p=1
|
||||||
|
while true; do
|
||||||
|
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
|
||||||
|
if [ -z "$h" ]; then
|
||||||
|
#not valid
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_describe_records_query "$h" "@"
|
||||||
|
if ! _tencent_rest "DescribeRecordList" "ignore"; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if _contains "$response" "\"TotalCount\":"; then
|
||||||
|
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
|
||||||
|
_debug _sub_domain "$_sub_domain"
|
||||||
|
_domain="$h"
|
||||||
|
_debug _domain "$_domain"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
p="$i"
|
||||||
|
i=$(_math "$i" + 1)
|
||||||
|
done
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
_tencent_rest() {
|
||||||
|
action=$1
|
||||||
|
service="dnspod"
|
||||||
|
payload="${query}"
|
||||||
|
timestamp=$(date -u +%s)
|
||||||
|
|
||||||
|
token=$(tencent_signature_v3 $service "$action" "$payload" "$timestamp")
|
||||||
|
version="2021-03-23"
|
||||||
|
|
||||||
|
if ! response="$(tencent_api_request $service $version "$action" "$payload" "$timestamp")"; then
|
||||||
|
_err "Error <$1>"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_debug2 response "$response"
|
||||||
|
if [ -z "$2" ]; then
|
||||||
|
message="$(echo "$response" | _egrep_o "\"Message\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \")"
|
||||||
|
if [ "$message" ]; then
|
||||||
|
_err "$message"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
_add_record_query() {
|
||||||
|
query="{\"Domain\":\"$1\",\"SubDomain\":\"$2\",\"RecordType\":\"TXT\",\"RecordLineId\":\"0\",\"RecordLine\":\"0\",\"Value\":\"$3\",\"TTL\":600}"
|
||||||
|
}
|
||||||
|
|
||||||
|
_describe_records_query() {
|
||||||
|
query="{\"Domain\":\"$1\",\"Limit\":3000}"
|
||||||
|
}
|
||||||
|
|
||||||
|
_delete_record_query() {
|
||||||
|
query="{\"Domain\":\"$_domain\",\"RecordId\":$1}"
|
||||||
|
}
|
||||||
|
|
||||||
|
_check_exist_query() {
|
||||||
|
_domain="$1"
|
||||||
|
_subdomain="$2"
|
||||||
|
_value="$3"
|
||||||
|
query="{\"Domain\":\"$_domain\",\"SubDomain\":\"$_subdomain\",\"RecordValue\":\"$_value\"}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# shell client for tencent cloud api v3 | @author: rehiy
|
||||||
|
|
||||||
|
tencent_sha256() {
|
||||||
|
printf %b "$@" | _digest sha256 hex
|
||||||
|
}
|
||||||
|
|
||||||
|
tencent_hmac_sha256() {
|
||||||
|
k=$1
|
||||||
|
shift
|
||||||
|
hex_key=$(printf %b "$k" | _hex_dump | tr -d ' ')
|
||||||
|
printf %b "$@" | _hmac sha256 "$hex_key" hex
|
||||||
|
}
|
||||||
|
|
||||||
|
tencent_hmac_sha256_hexkey() {
|
||||||
|
k=$1
|
||||||
|
shift
|
||||||
|
printf %b "$@" | _hmac sha256 "$k" hex
|
||||||
|
}
|
||||||
|
|
||||||
|
tencent_signature_v3() {
|
||||||
|
service=$1
|
||||||
|
action=$(echo "$2" | _lower_case)
|
||||||
|
payload=${3:-'{}'}
|
||||||
|
timestamp=${4:-$(date +%s)}
|
||||||
|
|
||||||
|
domain="$service.tencentcloudapi.com"
|
||||||
|
secretId=${Tencent_SecretId:-'tencent-cloud-secret-id'}
|
||||||
|
secretKey=${Tencent_SecretKey:-'tencent-cloud-secret-key'}
|
||||||
|
|
||||||
|
algorithm='TC3-HMAC-SHA256'
|
||||||
|
date=$(date -u -d "@$timestamp" +%Y-%m-%d 2>/dev/null)
|
||||||
|
[ -z "$date" ] && date=$(date -u -r "$timestamp" +%Y-%m-%d)
|
||||||
|
|
||||||
|
canonicalUri='/'
|
||||||
|
canonicalQuery=''
|
||||||
|
canonicalHeaders="content-type:application/json\nhost:$domain\nx-tc-action:$action\n"
|
||||||
|
|
||||||
|
signedHeaders='content-type;host;x-tc-action'
|
||||||
|
canonicalRequest="POST\n$canonicalUri\n$canonicalQuery\n$canonicalHeaders\n$signedHeaders\n$(tencent_sha256 "$payload")"
|
||||||
|
|
||||||
|
credentialScope="$date/$service/tc3_request"
|
||||||
|
stringToSign="$algorithm\n$timestamp\n$credentialScope\n$(tencent_sha256 "$canonicalRequest")"
|
||||||
|
|
||||||
|
secretDate=$(tencent_hmac_sha256 "TC3$secretKey" "$date")
|
||||||
|
secretService=$(tencent_hmac_sha256_hexkey "$secretDate" "$service")
|
||||||
|
secretSigning=$(tencent_hmac_sha256_hexkey "$secretService" 'tc3_request')
|
||||||
|
signature=$(tencent_hmac_sha256_hexkey "$secretSigning" "$stringToSign")
|
||||||
|
|
||||||
|
echo "$algorithm Credential=$secretId/$credentialScope, SignedHeaders=$signedHeaders, Signature=$signature"
|
||||||
|
}
|
||||||
|
|
||||||
|
tencent_api_request() {
|
||||||
|
service=$1
|
||||||
|
version=$2
|
||||||
|
action=$3
|
||||||
|
payload=${4:-'{}'}
|
||||||
|
timestamp=${5:-$(date +%s)}
|
||||||
|
|
||||||
|
token=$(tencent_signature_v3 "$service" "$action" "$payload" "$timestamp")
|
||||||
|
|
||||||
|
_H1="Content-Type: application/json"
|
||||||
|
_H2="Authorization: $token"
|
||||||
|
_H3="X-TC-Version: $version"
|
||||||
|
_H4="X-TC-Timestamp: $timestamp"
|
||||||
|
_H5="X-TC-Action: $action"
|
||||||
|
|
||||||
|
_post "$payload" "$Tencent_API" "" "POST" "application/json"
|
||||||
|
}
|
@ -69,7 +69,7 @@ dns_variomedia_rm() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_record_id="$(echo "$response" | cut -d '[' -f2 | cut -d']' -f1 | sed 's/},[ \t]*{/\},§\{/g' | tr § '\n' | grep "$_sub_domain" | grep "$txtvalue" | sed 's/^{//;s/}[,]?$//' | tr , '\n' | tr -d '\"' | grep ^id | cut -d : -f2 | tr -d ' ')"
|
_record_id="$(echo "$response" | sed -E 's/,"tags":\[[^]]*\]//g' | cut -d '[' -f2 | cut -d']' -f1 | sed 's/},[ \t]*{/\},§\{/g' | tr § '\n' | grep "$_sub_domain" | grep -- "$txtvalue" | sed 's/^{//;s/}[,]?$//' | tr , '\n' | tr -d '\"' | grep ^id | cut -d : -f2 | tr -d ' ')"
|
||||||
_debug _record_id "$_record_id"
|
_debug _record_id "$_record_id"
|
||||||
if [ "$_record_id" ]; then
|
if [ "$_record_id" ]; then
|
||||||
_info "Successfully retrieved the record id for ACME challenge."
|
_info "Successfully retrieved the record id for ACME challenge."
|
||||||
@ -93,11 +93,11 @@ dns_variomedia_rm() {
|
|||||||
# _sub_domain=_acme-challenge.www
|
# _sub_domain=_acme-challenge.www
|
||||||
# _domain=domain.com
|
# _domain=domain.com
|
||||||
_get_root() {
|
_get_root() {
|
||||||
fulldomain=$1
|
domain=$1
|
||||||
i=1
|
i=1
|
||||||
|
p=1
|
||||||
while true; do
|
while true; do
|
||||||
h=$(printf "%s" "$fulldomain" | cut -d . -f $i-100)
|
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
||||||
_debug h "$h"
|
|
||||||
if [ -z "$h" ]; then
|
if [ -z "$h" ]; then
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
@ -106,17 +106,14 @@ _get_root() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if _startswith "$response" "\{\"data\":"; then
|
|
||||||
if _contains "$response" "\"id\":\"$h\""; then
|
if _contains "$response" "\"id\":\"$h\""; then
|
||||||
_sub_domain="$(echo "$fulldomain" | sed "s/\\.$h\$//")"
|
_sub_domain=$(printf "%s" "$domain" | cut -d '.' -f 1-$p)
|
||||||
_domain=$h
|
_domain="$h"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
fi
|
p=$i
|
||||||
i=$(_math "$i" + 1)
|
i=$(_math "$i" + 1)
|
||||||
done
|
done
|
||||||
|
|
||||||
_debug "root domain not found"
|
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ dns_vultr_rm() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_record_id="$(echo "$response" | tr '{}' '\n' | grep '"TXT"' | grep -- "$txtvalue" | tr ',' '\n' | grep -i 'id' | cut -d : -f 2)"
|
_record_id="$(echo "$response" | tr '{}' '\n' | grep '"TXT"' | grep -- "$txtvalue" | tr ',' '\n' | grep -i 'id' | cut -d : -f 2 | tr -d '"')"
|
||||||
_debug _record_id "$_record_id"
|
_debug _record_id "$_record_id"
|
||||||
if [ "$_record_id" ]; then
|
if [ "$_record_id" ]; then
|
||||||
_info "Successfully retrieved the record id for ACME challenge."
|
_info "Successfully retrieved the record id for ACME challenge."
|
||||||
@ -116,7 +116,7 @@ _get_root() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if printf "%s\n" "$response" | grep '^\{.*\}' >/dev/null; then
|
if printf "%s\n" "$response" | grep -E '^\{.*\}' >/dev/null; then
|
||||||
if _contains "$response" "\"domain\":\"$_domain\""; then
|
if _contains "$response" "\"domain\":\"$_domain\""; then
|
||||||
_sub_domain="$(echo "$fulldomain" | sed "s/\\.$_domain\$//")"
|
_sub_domain="$(echo "$fulldomain" | sed "s/\\.$_domain\$//")"
|
||||||
return 0
|
return 0
|
||||||
@ -139,7 +139,7 @@ _vultr_rest() {
|
|||||||
data="$3"
|
data="$3"
|
||||||
_debug "$ep"
|
_debug "$ep"
|
||||||
|
|
||||||
api_key_trimmed=$(echo $VULTR_API_KEY | tr -d '"')
|
api_key_trimmed=$(echo "$VULTR_API_KEY" | tr -d '"')
|
||||||
|
|
||||||
export _H1="Authorization: Bearer $api_key_trimmed"
|
export _H1="Authorization: Bearer $api_key_trimmed"
|
||||||
export _H2='Content-Type: application/json'
|
export _H2='Content-Type: application/json'
|
||||||
|
105
dnsapi/dns_west_cn.sh
Normal file
105
dnsapi/dns_west_cn.sh
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
# West.cn Domain api
|
||||||
|
#WEST_Username="username"
|
||||||
|
#WEST_Key="sADDsdasdgdsf"
|
||||||
|
#Set key at https://www.west.cn/manager/API/APIconfig.asp
|
||||||
|
|
||||||
|
REST_API="https://api.west.cn/API/v2"
|
||||||
|
|
||||||
|
######## Public functions #####################
|
||||||
|
|
||||||
|
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||||
|
dns_west_cn_add() {
|
||||||
|
fulldomain=$1
|
||||||
|
txtvalue=$2
|
||||||
|
|
||||||
|
WEST_Username="${WEST_Username:-$(_readaccountconf_mutable WEST_Username)}"
|
||||||
|
WEST_Key="${WEST_Key:-$(_readaccountconf_mutable WEST_Key)}"
|
||||||
|
if [ -z "$WEST_Username" ] || [ -z "$WEST_Key" ]; then
|
||||||
|
WEST_Username=""
|
||||||
|
WEST_Key=""
|
||||||
|
_err "You don't specify west api key and username yet."
|
||||||
|
_err "Please set you key and try again."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
#save the api key and email to the account conf file.
|
||||||
|
_saveaccountconf_mutable WEST_Username "$WEST_Username"
|
||||||
|
_saveaccountconf_mutable WEST_Key "$WEST_Key"
|
||||||
|
|
||||||
|
add_record "$fulldomain" "$txtvalue"
|
||||||
|
}
|
||||||
|
|
||||||
|
#Usage: rm _acme-challenge.www.domain.com
|
||||||
|
dns_west_cn_rm() {
|
||||||
|
fulldomain=$1
|
||||||
|
txtvalue=$2
|
||||||
|
|
||||||
|
WEST_Username="${WEST_Username:-$(_readaccountconf_mutable WEST_Username)}"
|
||||||
|
WEST_Key="${WEST_Key:-$(_readaccountconf_mutable WEST_Key)}"
|
||||||
|
|
||||||
|
if ! _rest POST "domain/dns/" "act=dnsrec.list&username=$WEST_Username&apikey=$WEST_Key&domain=$fulldomain&hostname=$fulldomain&record_type=TXT"; then
|
||||||
|
_err "dnsrec.list error."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if _contains "$response" 'no records'; then
|
||||||
|
_info "Don't need to remove."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
record_id=$(echo "$response" | tr "{" "\n" | grep -- "$txtvalue" | grep '^"record_id"' | cut -d : -f 2 | cut -d ',' -f 1)
|
||||||
|
_debug record_id "$record_id"
|
||||||
|
if [ -z "$record_id" ]; then
|
||||||
|
_err "Can not get record id."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! _rest POST "domain/dns/" "act=dnsrec.remove&username=$WEST_Username&apikey=$WEST_Key&domain=$fulldomain&hostname=$fulldomain&record_id=$record_id"; then
|
||||||
|
_err "dnsrec.remove error."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_contains "$response" "success"
|
||||||
|
}
|
||||||
|
|
||||||
|
#add the txt record.
|
||||||
|
#usage: add fulldomain txtvalue
|
||||||
|
add_record() {
|
||||||
|
fulldomain=$1
|
||||||
|
txtvalue=$2
|
||||||
|
|
||||||
|
_info "Adding record"
|
||||||
|
|
||||||
|
if ! _rest POST "domain/dns/" "act=dnsrec.add&username=$WEST_Username&apikey=$WEST_Key&domain=$fulldomain&hostname=$fulldomain&record_type=TXT&record_value=$txtvalue"; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_contains "$response" "success"
|
||||||
|
}
|
||||||
|
|
||||||
|
#Usage: method URI data
|
||||||
|
_rest() {
|
||||||
|
m="$1"
|
||||||
|
ep="$2"
|
||||||
|
data="$3"
|
||||||
|
_debug "$ep"
|
||||||
|
url="$REST_API/$ep"
|
||||||
|
|
||||||
|
_debug url "$url"
|
||||||
|
|
||||||
|
if [ "$m" = "GET" ]; then
|
||||||
|
response="$(_get "$url" | tr -d '\r')"
|
||||||
|
else
|
||||||
|
_debug2 data "$data"
|
||||||
|
response="$(_post "$data" "$url" | tr -d '\r')"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$?" != "0" ]; then
|
||||||
|
_err "error $ep"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_debug2 response "$response"
|
||||||
|
return 0
|
||||||
|
}
|
226
notify/aws_ses.sh
Normal file
226
notify/aws_ses.sh
Normal file
@ -0,0 +1,226 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
#
|
||||||
|
#AWS_ACCESS_KEY_ID="sdfsdfsdfljlbjkljlkjsdfoiwje"
|
||||||
|
#
|
||||||
|
#AWS_SECRET_ACCESS_KEY="xxxxxxx"
|
||||||
|
#
|
||||||
|
#AWS_SES_REGION="us-east-1"
|
||||||
|
#
|
||||||
|
#AWS_SES_TO="xxxx@xxx.com"
|
||||||
|
#
|
||||||
|
#AWS_SES_FROM="xxxx@cccc.com"
|
||||||
|
#
|
||||||
|
#AWS_SES_FROM_NAME="Something something"
|
||||||
|
#This is the Amazon SES api wrapper for acme.sh
|
||||||
|
AWS_WIKI="https://docs.aws.amazon.com/ses/latest/dg/send-email-api.html"
|
||||||
|
|
||||||
|
aws_ses_send() {
|
||||||
|
_subject="$1"
|
||||||
|
_content="$2"
|
||||||
|
_statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped
|
||||||
|
_debug "_statusCode" "$_statusCode"
|
||||||
|
|
||||||
|
AWS_ACCESS_KEY_ID="${AWS_ACCESS_KEY_ID:-$(_readaccountconf_mutable AWS_ACCESS_KEY_ID)}"
|
||||||
|
AWS_SECRET_ACCESS_KEY="${AWS_SECRET_ACCESS_KEY:-$(_readaccountconf_mutable AWS_SECRET_ACCESS_KEY)}"
|
||||||
|
AWS_SES_REGION="${AWS_SES_REGION:-$(_readaccountconf_mutable AWS_SES_REGION)}"
|
||||||
|
|
||||||
|
if [ -z "$AWS_ACCESS_KEY_ID" ] || [ -z "$AWS_SECRET_ACCESS_KEY" ]; then
|
||||||
|
_use_container_role || _use_instance_role
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$AWS_ACCESS_KEY_ID" ] || [ -z "$AWS_SECRET_ACCESS_KEY" ]; then
|
||||||
|
AWS_ACCESS_KEY_ID=""
|
||||||
|
AWS_SECRET_ACCESS_KEY=""
|
||||||
|
_err "You haven't specified the aws SES api key id and and api key secret yet."
|
||||||
|
_err "Please create your key and try again. see $(__green $AWS_WIKI)"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$AWS_SES_REGION" ]; then
|
||||||
|
AWS_SES_REGION=""
|
||||||
|
_err "You haven't specified the aws SES api region yet."
|
||||||
|
_err "Please specify your region and try again. see https://docs.aws.amazon.com/general/latest/gr/ses.html"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_saveaccountconf_mutable AWS_SES_REGION "$AWS_SES_REGION"
|
||||||
|
|
||||||
|
#save for future use, unless using a role which will be fetched as needed
|
||||||
|
if [ -z "$_using_role" ]; then
|
||||||
|
_saveaccountconf_mutable AWS_ACCESS_KEY_ID "$AWS_ACCESS_KEY_ID"
|
||||||
|
_saveaccountconf_mutable AWS_SECRET_ACCESS_KEY "$AWS_SECRET_ACCESS_KEY"
|
||||||
|
fi
|
||||||
|
|
||||||
|
AWS_SES_TO="${AWS_SES_TO:-$(_readaccountconf_mutable AWS_SES_TO)}"
|
||||||
|
if [ -z "$AWS_SES_TO" ]; then
|
||||||
|
AWS_SES_TO=""
|
||||||
|
_err "You didn't specify an email to AWS_SES_TO receive messages."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_saveaccountconf_mutable AWS_SES_TO "$AWS_SES_TO"
|
||||||
|
|
||||||
|
AWS_SES_FROM="${AWS_SES_FROM:-$(_readaccountconf_mutable AWS_SES_FROM)}"
|
||||||
|
if [ -z "$AWS_SES_FROM" ]; then
|
||||||
|
AWS_SES_FROM=""
|
||||||
|
_err "You didn't specify an email to AWS_SES_FROM receive messages."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_saveaccountconf_mutable AWS_SES_FROM "$AWS_SES_FROM"
|
||||||
|
|
||||||
|
AWS_SES_FROM_NAME="${AWS_SES_FROM_NAME:-$(_readaccountconf_mutable AWS_SES_FROM_NAME)}"
|
||||||
|
_saveaccountconf_mutable AWS_SES_FROM_NAME "$AWS_SES_FROM_NAME"
|
||||||
|
|
||||||
|
AWS_SES_SENDFROM="$AWS_SES_FROM_NAME <$AWS_SES_FROM>"
|
||||||
|
|
||||||
|
AWS_SES_ACTION="Action=SendEmail"
|
||||||
|
AWS_SES_SOURCE="Source=$AWS_SES_SENDFROM"
|
||||||
|
AWS_SES_TO="Destination.ToAddresses.member.1=$AWS_SES_TO"
|
||||||
|
AWS_SES_SUBJECT="Message.Subject.Data=$_subject"
|
||||||
|
AWS_SES_MESSAGE="Message.Body.Text.Data=$_content"
|
||||||
|
|
||||||
|
_data="${AWS_SES_ACTION}&${AWS_SES_SOURCE}&${AWS_SES_TO}&${AWS_SES_SUBJECT}&${AWS_SES_MESSAGE}"
|
||||||
|
|
||||||
|
response="$(aws_rest POST "" "" "$_data")"
|
||||||
|
}
|
||||||
|
|
||||||
|
_use_metadata() {
|
||||||
|
_aws_creds="$(
|
||||||
|
_get "$1" "" 1 |
|
||||||
|
_normalizeJson |
|
||||||
|
tr '{,}' '\n' |
|
||||||
|
while read -r _line; do
|
||||||
|
_key="$(echo "${_line%%:*}" | tr -d '"')"
|
||||||
|
_value="${_line#*:}"
|
||||||
|
_debug3 "_key" "$_key"
|
||||||
|
_secure_debug3 "_value" "$_value"
|
||||||
|
case "$_key" in
|
||||||
|
AccessKeyId) echo "AWS_ACCESS_KEY_ID=$_value" ;;
|
||||||
|
SecretAccessKey) echo "AWS_SECRET_ACCESS_KEY=$_value" ;;
|
||||||
|
Token) echo "AWS_SESSION_TOKEN=$_value" ;;
|
||||||
|
esac
|
||||||
|
done |
|
||||||
|
paste -sd' ' -
|
||||||
|
)"
|
||||||
|
_secure_debug "_aws_creds" "$_aws_creds"
|
||||||
|
|
||||||
|
if [ -z "$_aws_creds" ]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
eval "$_aws_creds"
|
||||||
|
_using_role=true
|
||||||
|
}
|
||||||
|
|
||||||
|
#method uri qstr data
|
||||||
|
aws_rest() {
|
||||||
|
mtd="$1"
|
||||||
|
ep="$2"
|
||||||
|
qsr="$3"
|
||||||
|
data="$4"
|
||||||
|
|
||||||
|
_debug mtd "$mtd"
|
||||||
|
_debug ep "$ep"
|
||||||
|
_debug qsr "$qsr"
|
||||||
|
_debug data "$data"
|
||||||
|
|
||||||
|
CanonicalURI="/$ep"
|
||||||
|
_debug2 CanonicalURI "$CanonicalURI"
|
||||||
|
|
||||||
|
CanonicalQueryString="$qsr"
|
||||||
|
_debug2 CanonicalQueryString "$CanonicalQueryString"
|
||||||
|
|
||||||
|
RequestDate="$(date -u +"%Y%m%dT%H%M%SZ")"
|
||||||
|
_debug2 RequestDate "$RequestDate"
|
||||||
|
|
||||||
|
#RequestDate="20161120T141056Z" ##############
|
||||||
|
|
||||||
|
export _H1="x-amz-date: $RequestDate"
|
||||||
|
|
||||||
|
aws_host="email.$AWS_SES_REGION.amazonaws.com"
|
||||||
|
CanonicalHeaders="host:$aws_host\nx-amz-date:$RequestDate\n"
|
||||||
|
SignedHeaders="host;x-amz-date"
|
||||||
|
if [ -n "$AWS_SESSION_TOKEN" ]; then
|
||||||
|
export _H3="x-amz-security-token: $AWS_SESSION_TOKEN"
|
||||||
|
CanonicalHeaders="${CanonicalHeaders}x-amz-security-token:$AWS_SESSION_TOKEN\n"
|
||||||
|
SignedHeaders="${SignedHeaders};x-amz-security-token"
|
||||||
|
fi
|
||||||
|
_debug2 CanonicalHeaders "$CanonicalHeaders"
|
||||||
|
_debug2 SignedHeaders "$SignedHeaders"
|
||||||
|
|
||||||
|
RequestPayload="$data"
|
||||||
|
_debug2 RequestPayload "$RequestPayload"
|
||||||
|
|
||||||
|
Hash="sha256"
|
||||||
|
|
||||||
|
CanonicalRequest="$mtd\n$CanonicalURI\n$CanonicalQueryString\n$CanonicalHeaders\n$SignedHeaders\n$(printf "%s" "$RequestPayload" | _digest "$Hash" hex)"
|
||||||
|
_debug2 CanonicalRequest "$CanonicalRequest"
|
||||||
|
|
||||||
|
HashedCanonicalRequest="$(printf "$CanonicalRequest%s" | _digest "$Hash" hex)"
|
||||||
|
_debug2 HashedCanonicalRequest "$HashedCanonicalRequest"
|
||||||
|
|
||||||
|
Algorithm="AWS4-HMAC-SHA256"
|
||||||
|
_debug2 Algorithm "$Algorithm"
|
||||||
|
|
||||||
|
RequestDateOnly="$(echo "$RequestDate" | cut -c 1-8)"
|
||||||
|
_debug2 RequestDateOnly "$RequestDateOnly"
|
||||||
|
|
||||||
|
Region="$AWS_SES_REGION"
|
||||||
|
Service="ses"
|
||||||
|
|
||||||
|
CredentialScope="$RequestDateOnly/$Region/$Service/aws4_request"
|
||||||
|
_debug2 CredentialScope "$CredentialScope"
|
||||||
|
|
||||||
|
StringToSign="$Algorithm\n$RequestDate\n$CredentialScope\n$HashedCanonicalRequest"
|
||||||
|
|
||||||
|
_debug2 StringToSign "$StringToSign"
|
||||||
|
|
||||||
|
kSecret="AWS4$AWS_SECRET_ACCESS_KEY"
|
||||||
|
|
||||||
|
#kSecret="wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY" ############################
|
||||||
|
|
||||||
|
_secure_debug2 kSecret "$kSecret"
|
||||||
|
|
||||||
|
kSecretH="$(printf "%s" "$kSecret" | _hex_dump | tr -d " ")"
|
||||||
|
_secure_debug2 kSecretH "$kSecretH"
|
||||||
|
|
||||||
|
kDateH="$(printf "$RequestDateOnly%s" | _hmac "$Hash" "$kSecretH" hex)"
|
||||||
|
_debug2 kDateH "$kDateH"
|
||||||
|
|
||||||
|
kRegionH="$(printf "$Region%s" | _hmac "$Hash" "$kDateH" hex)"
|
||||||
|
_debug2 kRegionH "$kRegionH"
|
||||||
|
|
||||||
|
kServiceH="$(printf "$Service%s" | _hmac "$Hash" "$kRegionH" hex)"
|
||||||
|
_debug2 kServiceH "$kServiceH"
|
||||||
|
|
||||||
|
kSigningH="$(printf "%s" "aws4_request" | _hmac "$Hash" "$kServiceH" hex)"
|
||||||
|
_debug2 kSigningH "$kSigningH"
|
||||||
|
|
||||||
|
signature="$(printf "$StringToSign%s" | _hmac "$Hash" "$kSigningH" hex)"
|
||||||
|
_debug2 signature "$signature"
|
||||||
|
|
||||||
|
Authorization="$Algorithm Credential=$AWS_ACCESS_KEY_ID/$CredentialScope, SignedHeaders=$SignedHeaders, Signature=$signature"
|
||||||
|
_debug2 Authorization "$Authorization"
|
||||||
|
|
||||||
|
_H2="Authorization: $Authorization"
|
||||||
|
_debug _H2 "$_H2"
|
||||||
|
|
||||||
|
url="https://$aws_host/$ep"
|
||||||
|
if [ "$qsr" ]; then
|
||||||
|
url="https://$aws_host/$ep?$qsr"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$mtd" = "GET" ]; then
|
||||||
|
response="$(_get "$url")"
|
||||||
|
else
|
||||||
|
response="$(_post "$data" "$url")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
_ret="$?"
|
||||||
|
_debug2 response "$response"
|
||||||
|
if [ "$_ret" = "0" ]; then
|
||||||
|
if _contains "$response" "<ErrorResponse"; then
|
||||||
|
_err "Response error:$response"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
52
notify/mattermost.sh
Normal file
52
notify/mattermost.sh
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
# Support mattermost bots
|
||||||
|
|
||||||
|
#MATTERMOST_API_URL=""
|
||||||
|
#MATTERMOST_CHANNEL_ID=""
|
||||||
|
#MATTERMOST_BOT_TOKEN=""
|
||||||
|
|
||||||
|
mattermost_send() {
|
||||||
|
_subject="$1"
|
||||||
|
_content="$2"
|
||||||
|
_statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped
|
||||||
|
_debug "_statusCode" "$_statusCode"
|
||||||
|
|
||||||
|
MATTERMOST_API_URL="${MATTERMOST_API_URL:-$(_readaccountconf_mutable MATTERMOST_API_URL)}"
|
||||||
|
if [ -z "$MATTERMOST_API_URL" ]; then
|
||||||
|
_err "You didn't specify a Mattermost API URL MATTERMOST_API_URL yet."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_saveaccountconf_mutable MATTERMOST_API_URL "$MATTERMOST_API_URL"
|
||||||
|
|
||||||
|
MATTERMOST_CHANNEL_ID="${MATTERMOST_CHANNEL_ID:-$(_readaccountconf_mutable MATTERMOST_CHANNEL_ID)}"
|
||||||
|
if [ -z "$MATTERMOST_CHANNEL_ID" ]; then
|
||||||
|
_err "You didn't specify a Mattermost channel id MATTERMOST_CHANNEL_ID yet."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_saveaccountconf_mutable MATTERMOST_CHANNEL_ID "$MATTERMOST_CHANNEL_ID"
|
||||||
|
|
||||||
|
MATTERMOST_BOT_TOKEN="${MATTERMOST_BOT_TOKEN:-$(_readaccountconf_mutable MATTERMOST_BOT_TOKEN)}"
|
||||||
|
if [ -z "$MATTERMOST_BOT_TOKEN" ]; then
|
||||||
|
_err "You didn't specify a Mattermost bot API token MATTERMOST_BOT_TOKEN yet."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_saveaccountconf_mutable MATTERMOST_BOT_TOKEN "$MATTERMOST_BOT_TOKEN"
|
||||||
|
|
||||||
|
_content="$(printf "*%s*\n%s" "$_subject" "$_content" | _json_encode)"
|
||||||
|
_data="{\"channel_id\": \"$MATTERMOST_CHANNEL_ID\", "
|
||||||
|
_data="$_data\"message\": \"$_content\"}"
|
||||||
|
|
||||||
|
export _H1="Authorization: Bearer $MATTERMOST_BOT_TOKEN"
|
||||||
|
response=""
|
||||||
|
if _post "$_data" "$MATTERMOST_API_URL" "" "POST" "application/json; charset=utf-8"; then
|
||||||
|
MATTERMOST_RESULT_OK=$(echo "$response" | _egrep_o 'create_at')
|
||||||
|
if [ "$?" = "0" ] && [ "$MATTERMOST_RESULT_OK" ]; then
|
||||||
|
_info "mattermost send success."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
_err "mattermost send error."
|
||||||
|
_err "$response"
|
||||||
|
return 1
|
||||||
|
}
|
@ -169,7 +169,7 @@ _clean_email_header() {
|
|||||||
# email
|
# email
|
||||||
_email_has_display_name() {
|
_email_has_display_name() {
|
||||||
_email="$1"
|
_email="$1"
|
||||||
expr "$_email" : '^.*[<>"]' >/dev/null
|
echo "$_email" | grep -q -E '^.*[<>"]'
|
||||||
}
|
}
|
||||||
|
|
||||||
##
|
##
|
||||||
@ -249,7 +249,7 @@ _mime_encoded_word() {
|
|||||||
_text="$1"
|
_text="$1"
|
||||||
# (regex character ranges like [a-z] can be locale-dependent; enumerate ASCII chars to avoid that)
|
# (regex character ranges like [a-z] can be locale-dependent; enumerate ASCII chars to avoid that)
|
||||||
_ascii='] $`"'"[!#%&'()*+,./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ~^_abcdefghijklmnopqrstuvwxyz{|}~-"
|
_ascii='] $`"'"[!#%&'()*+,./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ~^_abcdefghijklmnopqrstuvwxyz{|}~-"
|
||||||
if expr "$_text" : "^.*[^$_ascii]" >/dev/null; then
|
if echo "$_text" | grep -q -E "^.*[^$_ascii]"; then
|
||||||
# At least one non-ASCII char; convert entire thing to encoded word
|
# At least one non-ASCII char; convert entire thing to encoded word
|
||||||
printf "%s" "=?UTF-8?B?$(printf "%s" "$_text" | _base64)?="
|
printf "%s" "=?UTF-8?B?$(printf "%s" "$_text" | _base64)?="
|
||||||
else
|
else
|
||||||
|
Loading…
x
Reference in New Issue
Block a user