committed by
GitHub
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
195 changed files with 10048 additions and 3319 deletions
-
2.github/FUNDING.yml
-
768.github/workflows/DNS.yml
-
71.github/workflows/DragonFlyBSD.yml
-
39.github/workflows/FreeBSD.yml
-
15.github/workflows/Linux.yml
-
21.github/workflows/MacOS.yml
-
71.github/workflows/NetBSD.yml
-
75.github/workflows/Omnios.yml
-
76.github/workflows/OpenBSD.yml
-
26.github/workflows/PebbleStrict.yml
-
136.github/workflows/Solaris.yml
-
29.github/workflows/Ubuntu.yml
-
23.github/workflows/Windows.yml
-
16.github/workflows/dockerhub.yml
-
19.github/workflows/issue.yml
-
30.github/workflows/pr_dns.yml
-
30.github/workflows/pr_notify.yml
-
11.github/workflows/shellcheck.yml
-
13Dockerfile
-
54README.md
-
1558acme.sh
-
185deploy/cpanel_uapi.sh
-
27deploy/docker.sh
-
15deploy/gcore_cdn.sh
-
2deploy/gitlab.sh
-
141deploy/haproxy.sh
-
36deploy/mailcow.sh
-
156deploy/openmediavault.sh
-
177deploy/panos.sh
-
132deploy/proxmoxve.sh
-
4deploy/qiniu.sh
-
113deploy/routeros.sh
-
409deploy/ssh.sh
-
465deploy/synology_dsm.sh
-
93deploy/truenas.sh
-
87deploy/vault.sh
-
47deploy/vault_cli.sh
-
185dnsapi/dns_1984hosting.sh
-
28dnsapi/dns_acmedns.sh
-
18dnsapi/dns_acmeproxy.sh
-
11dnsapi/dns_active24.sh
-
17dnsapi/dns_ad.sh
-
14dnsapi/dns_ali.sh
-
13dnsapi/dns_anx.sh
-
177dnsapi/dns_artfiles.sh
-
22dnsapi/dns_arvan.sh
-
16dnsapi/dns_aurora.sh
-
23dnsapi/dns_autodns.sh
-
103dnsapi/dns_aws.sh
-
14dnsapi/dns_azion.sh
-
195dnsapi/dns_azure.sh
-
88dnsapi/dns_bookmyname.sh
-
245dnsapi/dns_bunny.sh
-
42dnsapi/dns_cf.sh
-
17dnsapi/dns_clouddns.sh
-
19dnsapi/dns_cloudns.sh
-
13dnsapi/dns_cn.sh
-
11dnsapi/dns_conoha.sh
-
14dnsapi/dns_constellix.sh
-
35dnsapi/dns_cpanel.sh
-
165dnsapi/dns_curanet.sh
-
185dnsapi/dns_cx.sh
-
30dnsapi/dns_cyon.sh
-
37dnsapi/dns_da.sh
-
27dnsapi/dns_ddnss.sh
-
16dnsapi/dns_desec.sh
-
25dnsapi/dns_df.sh
-
25dnsapi/dns_dgon.sh
-
188dnsapi/dns_dnsexit.sh
-
21dnsapi/dns_dnshome.sh
-
16dnsapi/dns_dnsimple.sh
-
251dnsapi/dns_dnsservices.sh
-
148dnsapi/dns_do.sh
-
19dnsapi/dns_doapi.sh
-
9dnsapi/dns_domeneshop.sh
-
14dnsapi/dns_dp.sh
-
14dnsapi/dns_dpi.sh
-
14dnsapi/dns_dreamhost.sh
-
18dnsapi/dns_duckdns.sh
-
12dnsapi/dns_durabledns.sh
-
25dnsapi/dns_dyn.sh
-
21dnsapi/dns_dynu.sh
-
23dnsapi/dns_dynv6.sh
-
19dnsapi/dns_easydns.sh
-
31dnsapi/dns_edgedns.sh
-
24dnsapi/dns_euserv.sh
-
8dnsapi/dns_exoscale.sh
-
153dnsapi/dns_fornex.sh
-
19dnsapi/dns_freedns.sh
-
52dnsapi/dns_gandi_livedns.sh
-
18dnsapi/dns_gcloud.sh
-
191dnsapi/dns_gcore.sh
-
70dnsapi/dns_gd.sh
-
177dnsapi/dns_gdnsdk.sh
-
232dnsapi/dns_geoscaling.sh
-
178dnsapi/dns_googledomains.sh
-
21dnsapi/dns_he.sh
-
12dnsapi/dns_hetzner.sh
-
14dnsapi/dns_hexonet.sh
-
15dnsapi/dns_hostingde.sh
@ -1,254 +1,514 @@ |
|||||
name: DNS |
|
||||
on: |
|
||||
push: |
|
||||
paths: |
|
||||
- 'dnsapi/*.sh' |
|
||||
- '.github/workflows/DNS.yml' |
|
||||
pull_request: |
|
||||
branches: |
|
||||
- 'dev' |
|
||||
paths: |
|
||||
- 'dnsapi/*.sh' |
|
||||
- '.github/workflows/DNS.yml' |
|
||||
|
|
||||
|
|
||||
jobs: |
|
||||
CheckToken: |
|
||||
runs-on: ubuntu-latest |
|
||||
outputs: |
|
||||
hasToken: ${{ steps.step_one.outputs.hasToken }} |
|
||||
steps: |
|
||||
- name: Set the value |
|
||||
id: step_one |
|
||||
run: | |
|
||||
if [ "${{secrets.TokenName1}}" ] ; then |
|
||||
echo "::set-output name=hasToken::true" |
|
||||
else |
|
||||
echo "::set-output name=hasToken::false" |
|
||||
fi |
|
||||
- name: Check the value |
|
||||
run: echo ${{ steps.step_one.outputs.hasToken }} |
|
||||
|
|
||||
Fail: |
|
||||
runs-on: ubuntu-latest |
|
||||
needs: CheckToken |
|
||||
if: "contains(needs.CheckToken.outputs.hasToken, 'false')" |
|
||||
steps: |
|
||||
- name: "Read this: https://github.com/acmesh-official/acme.sh/wiki/DNS-API-Test" |
|
||||
run: | |
|
||||
echo "Read this: https://github.com/acmesh-official/acme.sh/wiki/DNS-API-Test" |
|
||||
if [ "${{github.repository_owner}}" != "acmesh-official" ]; then |
|
||||
false |
|
||||
fi |
|
||||
|
|
||||
Docker: |
|
||||
runs-on: ubuntu-latest |
|
||||
needs: CheckToken |
|
||||
if: "contains(needs.CheckToken.outputs.hasToken, 'true')" |
|
||||
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: 1 |
|
||||
steps: |
|
||||
- uses: actions/checkout@v2 |
|
||||
- name: Clone acmetest |
|
||||
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ |
|
||||
- name: Set env file |
|
||||
run: | |
|
||||
cd ../acmetest |
|
||||
if [ "${{ secrets.TokenName1}}" ] ; then |
|
||||
echo "${{ secrets.TokenName1}}=${{ secrets.TokenValue1}}" >> docker.env |
|
||||
fi |
|
||||
if [ "${{ secrets.TokenName2}}" ] ; then |
|
||||
echo "${{ secrets.TokenName2}}=${{ secrets.TokenValue2}}" >> docker.env |
|
||||
fi |
|
||||
if [ "${{ secrets.TokenName3}}" ] ; then |
|
||||
echo "${{ secrets.TokenName3}}=${{ secrets.TokenValue3}}" >> docker.env |
|
||||
fi |
|
||||
if [ "${{ secrets.TokenName4}}" ] ; then |
|
||||
echo "${{ secrets.TokenName4}}=${{ secrets.TokenValue4}}" >> docker.env |
|
||||
fi |
|
||||
if [ "${{ secrets.TokenName5}}" ] ; then |
|
||||
echo "${{ secrets.TokenName5}}=${{ secrets.TokenValue5}}" >> docker.env |
|
||||
fi |
|
||||
echo "TEST_DNS_NO_WILDCARD" >> docker.env |
|
||||
echo "TEST_DNS_SLEEP" >> docker.env |
|
||||
- name: Run acmetest |
|
||||
run: cd ../acmetest && ./rundocker.sh testall |
|
||||
|
|
||||
MacOS: |
|
||||
runs-on: macos-latest |
|
||||
needs: Docker |
|
||||
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: 1 |
|
||||
steps: |
|
||||
- uses: actions/checkout@v2 |
|
||||
- name: Install tools |
|
||||
run: brew install socat |
|
||||
- name: Clone acmetest |
|
||||
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ |
|
||||
- name: Run acmetest |
|
||||
run: | |
|
||||
if [ "${{ secrets.TokenName1}}" ] ; then |
|
||||
export ${{ secrets.TokenName1}}=${{ secrets.TokenValue1}} |
|
||||
fi |
|
||||
if [ "${{ secrets.TokenName2}}" ] ; then |
|
||||
export ${{ secrets.TokenName2}}=${{ secrets.TokenValue2}} |
|
||||
fi |
|
||||
if [ "${{ secrets.TokenName3}}" ] ; then |
|
||||
export ${{ secrets.TokenName3}}=${{ secrets.TokenValue3}} |
|
||||
fi |
|
||||
if [ "${{ secrets.TokenName4}}" ] ; then |
|
||||
export ${{ secrets.TokenName4}}=${{ secrets.TokenValue4}} |
|
||||
fi |
|
||||
if [ "${{ secrets.TokenName5}}" ] ; then |
|
||||
export ${{ secrets.TokenName5}}=${{ secrets.TokenValue5}} |
|
||||
fi |
|
||||
cd ../acmetest |
|
||||
./letest.sh |
|
||||
|
|
||||
Windows: |
|
||||
runs-on: windows-latest |
|
||||
needs: MacOS |
|
||||
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: 1 |
|
||||
steps: |
|
||||
- name: Set git to use LF |
|
||||
run: | |
|
||||
git config --global core.autocrlf false |
|
||||
- uses: actions/checkout@v2 |
|
||||
- name: Install cygwin base packages with chocolatey |
|
||||
run: | |
|
||||
choco config get cacheLocation |
|
||||
choco install --no-progress cygwin |
|
||||
shell: cmd |
|
||||
- name: Install cygwin additional packages |
|
||||
run: | |
|
||||
C:\tools\cygwin\cygwinsetup.exe -qgnNdO -R C:/tools/cygwin -s http://mirrors.kernel.org/sourceware/cygwin/ -P socat,curl,cron,unzip,git |
|
||||
shell: cmd |
|
||||
- name: Set ENV |
|
||||
shell: cmd |
|
||||
run: | |
|
||||
echo PATH=C:\tools\cygwin\bin;C:\tools\cygwin\usr\bin >> %GITHUB_ENV% |
|
||||
- name: Clone acmetest |
|
||||
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ |
|
||||
- name: Run acmetest |
|
||||
shell: bash |
|
||||
run: | |
|
||||
if [ "${{ secrets.TokenName1}}" ] ; then |
|
||||
export ${{ secrets.TokenName1}}=${{ secrets.TokenValue1}} |
|
||||
fi |
|
||||
if [ "${{ secrets.TokenName2}}" ] ; then |
|
||||
export ${{ secrets.TokenName2}}=${{ secrets.TokenValue2}} |
|
||||
fi |
|
||||
if [ "${{ secrets.TokenName3}}" ] ; then |
|
||||
export ${{ secrets.TokenName3}}=${{ secrets.TokenValue3}} |
|
||||
fi |
|
||||
if [ "${{ secrets.TokenName4}}" ] ; then |
|
||||
export ${{ secrets.TokenName4}}=${{ secrets.TokenValue4}} |
|
||||
fi |
|
||||
if [ "${{ secrets.TokenName5}}" ] ; then |
|
||||
export ${{ secrets.TokenName5}}=${{ secrets.TokenValue5}} |
|
||||
fi |
|
||||
cd ../acmetest |
|
||||
./letest.sh |
|
||||
|
|
||||
FreeBSD: |
|
||||
runs-on: macos-10.15 |
|
||||
needs: Windows |
|
||||
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: 1 |
|
||||
steps: |
|
||||
- uses: actions/checkout@v2 |
|
||||
- name: Clone acmetest |
|
||||
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ |
|
||||
- uses: vmactions/freebsd-vm@v0.1.4 |
|
||||
with: |
|
||||
envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_NO_SUBDOMAIN TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}' |
|
||||
prepare: pkg install -y socat curl |
|
||||
usesh: true |
|
||||
run: | |
|
||||
if [ "${{ secrets.TokenName1}}" ] ; then |
|
||||
export ${{ secrets.TokenName1}}=${{ secrets.TokenValue1}} |
|
||||
fi |
|
||||
if [ "${{ secrets.TokenName2}}" ] ; then |
|
||||
export ${{ secrets.TokenName2}}=${{ secrets.TokenValue2}} |
|
||||
fi |
|
||||
if [ "${{ secrets.TokenName3}}" ] ; then |
|
||||
export ${{ secrets.TokenName3}}=${{ secrets.TokenValue3}} |
|
||||
fi |
|
||||
if [ "${{ secrets.TokenName4}}" ] ; then |
|
||||
export ${{ secrets.TokenName4}}=${{ secrets.TokenValue4}} |
|
||||
fi |
|
||||
if [ "${{ secrets.TokenName5}}" ] ; then |
|
||||
export ${{ secrets.TokenName5}}=${{ secrets.TokenValue5}} |
|
||||
fi |
|
||||
cd ../acmetest |
|
||||
./letest.sh |
|
||||
|
|
||||
Solaris: |
|
||||
runs-on: macos-10.15 |
|
||||
needs: FreeBSD |
|
||||
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: 1 |
|
||||
steps: |
|
||||
- uses: actions/checkout@v2 |
|
||||
- name: Clone acmetest |
|
||||
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ |
|
||||
- uses: vmactions/solaris-vm@v0.0.5 |
|
||||
with: |
|
||||
envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_NO_SUBDOMAIN TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}' |
|
||||
prepare: pkgutil -y -i socat |
|
||||
run: | |
|
||||
pkg set-mediator -v -I default@1.1 openssl |
|
||||
export PATH=/usr/gnu/bin:$PATH |
|
||||
if [ "${{ secrets.TokenName1}}" ] ; then |
|
||||
export ${{ secrets.TokenName1}}=${{ secrets.TokenValue1}} |
|
||||
fi |
|
||||
if [ "${{ secrets.TokenName2}}" ] ; then |
|
||||
export ${{ secrets.TokenName2}}=${{ secrets.TokenValue2}} |
|
||||
fi |
|
||||
if [ "${{ secrets.TokenName3}}" ] ; then |
|
||||
export ${{ secrets.TokenName3}}=${{ secrets.TokenValue3}} |
|
||||
fi |
|
||||
if [ "${{ secrets.TokenName4}}" ] ; then |
|
||||
export ${{ secrets.TokenName4}}=${{ secrets.TokenValue4}} |
|
||||
fi |
|
||||
if [ "${{ secrets.TokenName5}}" ] ; then |
|
||||
export ${{ secrets.TokenName5}}=${{ secrets.TokenValue5}} |
|
||||
fi |
|
||||
cd ../acmetest |
|
||||
./letest.sh |
|
||||
|
name: DNS |
||||
|
on: |
||||
|
push: |
||||
|
paths: |
||||
|
- 'dnsapi/*.sh' |
||||
|
- '.github/workflows/DNS.yml' |
||||
|
pull_request: |
||||
|
branches: |
||||
|
- 'dev' |
||||
|
paths: |
||||
|
- 'dnsapi/*.sh' |
||||
|
- '.github/workflows/DNS.yml' |
||||
|
|
||||
|
concurrency: |
||||
|
group: ${{ github.workflow }}-${{ github.ref }} |
||||
|
cancel-in-progress: true |
||||
|
|
||||
|
jobs: |
||||
|
CheckToken: |
||||
|
runs-on: ubuntu-latest |
||||
|
outputs: |
||||
|
hasToken: ${{ steps.step_one.outputs.hasToken }} |
||||
|
steps: |
||||
|
- name: Set the value |
||||
|
id: step_one |
||||
|
run: | |
||||
|
if [ "${{secrets.TokenName1}}" ] ; then |
||||
|
echo "::set-output name=hasToken::true" |
||||
|
else |
||||
|
echo "::set-output name=hasToken::false" |
||||
|
fi |
||||
|
- name: Check the value |
||||
|
run: echo ${{ steps.step_one.outputs.hasToken }} |
||||
|
|
||||
|
Fail: |
||||
|
runs-on: ubuntu-latest |
||||
|
needs: CheckToken |
||||
|
if: "contains(needs.CheckToken.outputs.hasToken, 'false')" |
||||
|
steps: |
||||
|
- name: "Read this: https://github.com/acmesh-official/acme.sh/wiki/DNS-API-Test" |
||||
|
run: | |
||||
|
echo "Read this: https://github.com/acmesh-official/acme.sh/wiki/DNS-API-Test" |
||||
|
if [ "${{github.repository_owner}}" != "acmesh-official" ]; then |
||||
|
false |
||||
|
fi |
||||
|
|
||||
|
Docker: |
||||
|
runs-on: ubuntu-latest |
||||
|
needs: CheckToken |
||||
|
if: "contains(needs.CheckToken.outputs.hasToken, 'true')" |
||||
|
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 }} |
||||
|
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/ |
||||
|
- name: Set env file |
||||
|
run: | |
||||
|
cd ../acmetest |
||||
|
if [ "${{ secrets.TokenName1}}" ] ; then |
||||
|
echo "${{ secrets.TokenName1}}=${{ secrets.TokenValue1}}" >> docker.env |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName2}}" ] ; then |
||||
|
echo "${{ secrets.TokenName2}}=${{ secrets.TokenValue2}}" >> docker.env |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName3}}" ] ; then |
||||
|
echo "${{ secrets.TokenName3}}=${{ secrets.TokenValue3}}" >> docker.env |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName4}}" ] ; then |
||||
|
echo "${{ secrets.TokenName4}}=${{ secrets.TokenValue4}}" >> docker.env |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName5}}" ] ; then |
||||
|
echo "${{ secrets.TokenName5}}=${{ secrets.TokenValue5}}" >> docker.env |
||||
|
fi |
||||
|
|
||||
|
- name: Run acmetest |
||||
|
run: cd ../acmetest && ./rundocker.sh testall |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
MacOS: |
||||
|
runs-on: macos-latest |
||||
|
needs: Docker |
||||
|
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 }} |
||||
|
TokenName1: ${{ secrets.TokenName1}} |
||||
|
TokenName2: ${{ secrets.TokenName2}} |
||||
|
TokenName3: ${{ secrets.TokenName3}} |
||||
|
TokenName4: ${{ secrets.TokenName4}} |
||||
|
TokenName5: ${{ secrets.TokenName5}} |
||||
|
steps: |
||||
|
- uses: actions/checkout@v4 |
||||
|
- name: Install tools |
||||
|
run: brew install socat |
||||
|
- name: Clone acmetest |
||||
|
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ |
||||
|
- name: Run acmetest |
||||
|
run: | |
||||
|
if [ "${{ secrets.TokenName1}}" ] ; then |
||||
|
export ${{ secrets.TokenName1}}="${{ secrets.TokenValue1}}" |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName2}}" ] ; then |
||||
|
export ${{ secrets.TokenName2}}="${{ secrets.TokenValue2}}" |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName3}}" ] ; then |
||||
|
export ${{ secrets.TokenName3}}="${{ secrets.TokenValue3}}" |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName4}}" ] ; then |
||||
|
export ${{ secrets.TokenName4}}="${{ secrets.TokenValue4}}" |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName5}}" ] ; then |
||||
|
export ${{ secrets.TokenName5}}="${{ secrets.TokenValue5}}" |
||||
|
fi |
||||
|
cd ../acmetest |
||||
|
./letest.sh |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
Windows: |
||||
|
runs-on: windows-latest |
||||
|
needs: MacOS |
||||
|
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 }} |
||||
|
TokenName1: ${{ secrets.TokenName1}} |
||||
|
TokenName2: ${{ secrets.TokenName2}} |
||||
|
TokenName3: ${{ secrets.TokenName3}} |
||||
|
TokenName4: ${{ secrets.TokenName4}} |
||||
|
TokenName5: ${{ secrets.TokenName5}} |
||||
|
steps: |
||||
|
- name: Set git to use LF |
||||
|
run: | |
||||
|
git config --global core.autocrlf false |
||||
|
- uses: actions/checkout@v4 |
||||
|
- name: Install cygwin base packages with chocolatey |
||||
|
run: | |
||||
|
choco config get cacheLocation |
||||
|
choco install --no-progress cygwin |
||||
|
shell: cmd |
||||
|
- name: Install cygwin additional packages |
||||
|
run: | |
||||
|
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 |
||||
|
- name: Set ENV |
||||
|
shell: cmd |
||||
|
run: | |
||||
|
echo PATH=C:\tools\cygwin\bin;C:\tools\cygwin\usr\bin >> %GITHUB_ENV% |
||||
|
- name: Clone acmetest |
||||
|
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ |
||||
|
- name: Run acmetest |
||||
|
shell: bash |
||||
|
run: | |
||||
|
if [ "${{ secrets.TokenName1}}" ] ; then |
||||
|
export ${{ secrets.TokenName1}}="${{ secrets.TokenValue1}}" |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName2}}" ] ; then |
||||
|
export ${{ secrets.TokenName2}}="${{ secrets.TokenValue2}}" |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName3}}" ] ; then |
||||
|
export ${{ secrets.TokenName3}}="${{ secrets.TokenValue3}}" |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName4}}" ] ; then |
||||
|
export ${{ secrets.TokenName4}}="${{ secrets.TokenValue4}}" |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName5}}" ] ; then |
||||
|
export ${{ secrets.TokenName5}}="${{ secrets.TokenValue5}}" |
||||
|
fi |
||||
|
cd ../acmetest |
||||
|
./letest.sh |
||||
|
|
||||
|
|
||||
|
|
||||
|
FreeBSD: |
||||
|
runs-on: ubuntu-latest |
||||
|
needs: Windows |
||||
|
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 }} |
||||
|
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/freebsd-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 TokenName1 TokenName2 TokenName3 TokenName4 TokenName5 ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}' |
||||
|
prepare: pkg install -y socat curl |
||||
|
usesh: true |
||||
|
copyback: false |
||||
|
run: | |
||||
|
if [ "${{ secrets.TokenName1}}" ] ; then |
||||
|
export ${{ secrets.TokenName1}}="${{ secrets.TokenValue1}}" |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName2}}" ] ; then |
||||
|
export ${{ secrets.TokenName2}}="${{ secrets.TokenValue2}}" |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName3}}" ] ; then |
||||
|
export ${{ secrets.TokenName3}}="${{ secrets.TokenValue3}}" |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName4}}" ] ; then |
||||
|
export ${{ secrets.TokenName4}}="${{ secrets.TokenValue4}}" |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName5}}" ] ; then |
||||
|
export ${{ secrets.TokenName5}}="${{ secrets.TokenValue5}}" |
||||
|
fi |
||||
|
cd ../acmetest |
||||
|
./letest.sh |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
OpenBSD: |
||||
|
runs-on: ubuntu-latest |
||||
|
needs: FreeBSD |
||||
|
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 }} |
||||
|
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/openbsd-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 TokenName1 TokenName2 TokenName3 TokenName4 TokenName5 ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}' |
||||
|
prepare: pkg_add socat curl |
||||
|
usesh: true |
||||
|
copyback: false |
||||
|
run: | |
||||
|
if [ "${{ secrets.TokenName1}}" ] ; then |
||||
|
export ${{ secrets.TokenName1}}="${{ secrets.TokenValue1}}" |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName2}}" ] ; then |
||||
|
export ${{ secrets.TokenName2}}="${{ secrets.TokenValue2}}" |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName3}}" ] ; then |
||||
|
export ${{ secrets.TokenName3}}="${{ secrets.TokenValue3}}" |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName4}}" ] ; then |
||||
|
export ${{ secrets.TokenName4}}="${{ secrets.TokenValue4}}" |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName5}}" ] ; then |
||||
|
export ${{ secrets.TokenName5}}="${{ secrets.TokenValue5}}" |
||||
|
fi |
||||
|
cd ../acmetest |
||||
|
./letest.sh |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
NetBSD: |
||||
|
runs-on: ubuntu-latest |
||||
|
needs: OpenBSD |
||||
|
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 }} |
||||
|
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/netbsd-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 TokenName1 TokenName2 TokenName3 TokenName4 TokenName5 ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}' |
||||
|
prepare: | |
||||
|
/usr/sbin/pkg_add curl socat |
||||
|
usesh: true |
||||
|
copyback: false |
||||
|
run: | |
||||
|
if [ "${{ secrets.TokenName1}}" ] ; then |
||||
|
export ${{ secrets.TokenName1}}="${{ secrets.TokenValue1}}" |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName2}}" ] ; then |
||||
|
export ${{ secrets.TokenName2}}="${{ secrets.TokenValue2}}" |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName3}}" ] ; then |
||||
|
export ${{ secrets.TokenName3}}="${{ secrets.TokenValue3}}" |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName4}}" ] ; then |
||||
|
export ${{ secrets.TokenName4}}="${{ secrets.TokenValue4}}" |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName5}}" ] ; then |
||||
|
export ${{ secrets.TokenName5}}="${{ secrets.TokenValue5}}" |
||||
|
fi |
||||
|
cd ../acmetest |
||||
|
./letest.sh |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
DragonFlyBSD: |
||||
|
runs-on: ubuntu-latest |
||||
|
needs: NetBSD |
||||
|
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 }} |
||||
|
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/dragonflybsd-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 TokenName1 TokenName2 TokenName3 TokenName4 TokenName5 ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}' |
||||
|
prepare: | |
||||
|
pkg install -y curl socat libnghttp2 |
||||
|
usesh: true |
||||
|
copyback: false |
||||
|
run: | |
||||
|
if [ "${{ secrets.TokenName1}}" ] ; then |
||||
|
export ${{ secrets.TokenName1}}="${{ secrets.TokenValue1}}" |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName2}}" ] ; then |
||||
|
export ${{ secrets.TokenName2}}="${{ secrets.TokenValue2}}" |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName3}}" ] ; then |
||||
|
export ${{ secrets.TokenName3}}="${{ secrets.TokenValue3}}" |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName4}}" ] ; then |
||||
|
export ${{ secrets.TokenName4}}="${{ secrets.TokenValue4}}" |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName5}}" ] ; then |
||||
|
export ${{ secrets.TokenName5}}="${{ secrets.TokenValue5}}" |
||||
|
fi |
||||
|
cd ../acmetest |
||||
|
./letest.sh |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
Solaris: |
||||
|
runs-on: ubuntu-latest |
||||
|
needs: DragonFlyBSD |
||||
|
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 Solaris 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/solaris-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: pkgutil -y -i socat |
||||
|
run: | |
||||
|
pkg set-mediator -v -I default@1.1 openssl |
||||
|
export PATH=/usr/gnu/bin:$PATH |
||||
|
if [ "${{ secrets.TokenName1}}" ] ; then |
||||
|
export ${{ secrets.TokenName1}}="${{ secrets.TokenValue1}}" |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName2}}" ] ; then |
||||
|
export ${{ secrets.TokenName2}}="${{ secrets.TokenValue2}}" |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName3}}" ] ; then |
||||
|
export ${{ secrets.TokenName3}}="${{ secrets.TokenValue3}}" |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName4}}" ] ; then |
||||
|
export ${{ secrets.TokenName4}}="${{ secrets.TokenValue4}}" |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName5}}" ] ; then |
||||
|
export ${{ secrets.TokenName5}}="${{ secrets.TokenValue5}}" |
||||
|
fi |
||||
|
cd ../acmetest |
||||
|
./letest.sh |
||||
|
|
||||
|
|
||||
|
Omnios: |
||||
|
runs-on: ubuntu-latest |
||||
|
needs: Solaris |
||||
|
env: |
||||
|
TEST_DNS : ${{ secrets.TEST_DNS }} |
||||
|
TestingDomain: ${{ secrets.TestingDomain }} |
||||
|
TEST_DNS_NO_WILDCARD: ${{ secrets.TEST_DNS_NO_WILDCARD }} |
||||
|
TEST_DNS_NO_SUBDOMAIN: ${{ secrets.TEST_DNS_NO_SUBDOMAIN }} |
||||
|
TEST_DNS_SLEEP: ${{ secrets.TEST_DNS_SLEEP }} |
||||
|
CASE: le_test_dnsapi |
||||
|
TEST_LOCAL: 1 |
||||
|
DEBUG: ${{ secrets.DEBUG }} |
||||
|
http_proxy: ${{ secrets.http_proxy }} |
||||
|
https_proxy: ${{ secrets.https_proxy }} |
||||
|
HTTPS_INSECURE: 1 # always set to 1 to ignore https error, since Omnios doesn't accept the expired ISRG X1 root |
||||
|
TokenName1: ${{ secrets.TokenName1}} |
||||
|
TokenName2: ${{ secrets.TokenName2}} |
||||
|
TokenName3: ${{ secrets.TokenName3}} |
||||
|
TokenName4: ${{ secrets.TokenName4}} |
||||
|
TokenName5: ${{ secrets.TokenName5}} |
||||
|
steps: |
||||
|
- uses: actions/checkout@v4 |
||||
|
- name: Clone acmetest |
||||
|
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ |
||||
|
- uses: vmactions/omnios-vm@v1 |
||||
|
with: |
||||
|
envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_NO_SUBDOMAIN TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG http_proxy https_proxy HTTPS_INSECURE TokenName1 TokenName2 TokenName3 TokenName4 TokenName5 ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}' |
||||
|
copyback: false |
||||
|
prepare: pkg install socat |
||||
|
run: | |
||||
|
if [ "${{ secrets.TokenName1}}" ] ; then |
||||
|
export ${{ secrets.TokenName1}}="${{ secrets.TokenValue1}}" |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName2}}" ] ; then |
||||
|
export ${{ secrets.TokenName2}}="${{ secrets.TokenValue2}}" |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName3}}" ] ; then |
||||
|
export ${{ secrets.TokenName3}}="${{ secrets.TokenValue3}}" |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName4}}" ] ; then |
||||
|
export ${{ secrets.TokenName4}}="${{ secrets.TokenValue4}}" |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName5}}" ] ; then |
||||
|
export ${{ secrets.TokenName5}}="${{ secrets.TokenValue5}}" |
||||
|
fi |
||||
|
cd ../acmetest |
||||
|
./letest.sh |
||||
|
|
||||
|
|
@ -0,0 +1,71 @@ |
|||||
|
name: DragonFlyBSD |
||||
|
on: |
||||
|
push: |
||||
|
branches: |
||||
|
- '*' |
||||
|
paths: |
||||
|
- '*.sh' |
||||
|
- '.github/workflows/DragonFlyBSD.yml' |
||||
|
|
||||
|
pull_request: |
||||
|
branches: |
||||
|
- dev |
||||
|
paths: |
||||
|
- '*.sh' |
||||
|
- '.github/workflows/DragonFlyBSD.yml' |
||||
|
|
||||
|
concurrency: |
||||
|
group: ${{ github.workflow }}-${{ github.ref }} |
||||
|
cancel-in-progress: true |
||||
|
|
||||
|
|
||||
|
|
||||
|
jobs: |
||||
|
DragonFlyBSD: |
||||
|
strategy: |
||||
|
matrix: |
||||
|
include: |
||||
|
- TEST_ACME_Server: "LetsEncrypt.org_test" |
||||
|
CA_ECDSA: "" |
||||
|
CA: "" |
||||
|
CA_EMAIL: "" |
||||
|
TEST_PREFERRED_CHAIN: (STAGING) |
||||
|
#- 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/dragonflybsd-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 -y curl socat libnghttp2 |
||||
|
usesh: true |
||||
|
copyback: false |
||||
|
run: | |
||||
|
cd ../acmetest \ |
||||
|
&& ./letest.sh |
||||
|
|
||||
|
|
@ -0,0 +1,71 @@ |
|||||
|
name: NetBSD |
||||
|
on: |
||||
|
push: |
||||
|
branches: |
||||
|
- '*' |
||||
|
paths: |
||||
|
- '*.sh' |
||||
|
- '.github/workflows/NetBSD.yml' |
||||
|
|
||||
|
pull_request: |
||||
|
branches: |
||||
|
- dev |
||||
|
paths: |
||||
|
- '*.sh' |
||||
|
- '.github/workflows/NetBSD.yml' |
||||
|
|
||||
|
concurrency: |
||||
|
group: ${{ github.workflow }}-${{ github.ref }} |
||||
|
cancel-in-progress: true |
||||
|
|
||||
|
|
||||
|
|
||||
|
jobs: |
||||
|
NetBSD: |
||||
|
strategy: |
||||
|
matrix: |
||||
|
include: |
||||
|
- TEST_ACME_Server: "LetsEncrypt.org_test" |
||||
|
CA_ECDSA: "" |
||||
|
CA: "" |
||||
|
CA_EMAIL: "" |
||||
|
TEST_PREFERRED_CHAIN: (STAGING) |
||||
|
#- 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/netbsd-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: | |
||||
|
/usr/sbin/pkg_add curl socat |
||||
|
usesh: true |
||||
|
copyback: false |
||||
|
run: | |
||||
|
cd ../acmetest \ |
||||
|
&& ./letest.sh |
||||
|
|
||||
|
|
@ -0,0 +1,75 @@ |
|||||
|
name: Omnios |
||||
|
on: |
||||
|
push: |
||||
|
branches: |
||||
|
- '*' |
||||
|
paths: |
||||
|
- '*.sh' |
||||
|
- '.github/workflows/Omnios.yml' |
||||
|
|
||||
|
pull_request: |
||||
|
branches: |
||||
|
- dev |
||||
|
paths: |
||||
|
- '*.sh' |
||||
|
- '.github/workflows/Omnios.yml' |
||||
|
|
||||
|
concurrency: |
||||
|
group: ${{ github.workflow }}-${{ github.ref }} |
||||
|
cancel-in-progress: true |
||||
|
|
||||
|
|
||||
|
|
||||
|
jobs: |
||||
|
Omnios: |
||||
|
strategy: |
||||
|
matrix: |
||||
|
include: |
||||
|
- TEST_ACME_Server: "LetsEncrypt.org_test" |
||||
|
CA_ECDSA: "" |
||||
|
CA: "" |
||||
|
CA_EMAIL: "" |
||||
|
TEST_PREFERRED_CHAIN: (STAGING) |
||||
|
- TEST_ACME_Server: "LetsEncrypt.org_test" |
||||
|
CA_ECDSA: "" |
||||
|
CA: "" |
||||
|
CA_EMAIL: "" |
||||
|
TEST_PREFERRED_CHAIN: (STAGING) |
||||
|
ACME_USE_WGET: 1 |
||||
|
#- TEST_ACME_Server: "ZeroSSL.com" |
||||
|
# CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" |
||||
|
# CA: "ZeroSSL RSA Domain Secure Site CA" |
||||
|
# CA_EMAIL: "githubtest@acme.sh" |
||||
|
# TEST_PREFERRED_CHAIN: "" |
||||
|
runs-on: ubuntu-latest |
||||
|
env: |
||||
|
TEST_LOCAL: 1 |
||||
|
TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }} |
||||
|
CA_ECDSA: ${{ matrix.CA_ECDSA }} |
||||
|
CA: ${{ matrix.CA }} |
||||
|
CA_EMAIL: ${{ matrix.CA_EMAIL }} |
||||
|
TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }} |
||||
|
ACME_USE_WGET: ${{ matrix.ACME_USE_WGET }} |
||||
|
steps: |
||||
|
- uses: actions/checkout@v4 |
||||
|
- uses: vmactions/cf-tunnel@v0 |
||||
|
id: tunnel |
||||
|
with: |
||||
|
protocol: http |
||||
|
port: 8080 |
||||
|
- name: Set envs |
||||
|
run: echo "TestingDomain=${{steps.tunnel.outputs.server}}" >> $GITHUB_ENV |
||||
|
- name: Clone acmetest |
||||
|
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ |
||||
|
- uses: vmactions/omnios-vm@v1 |
||||
|
with: |
||||
|
envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN ACME_USE_WGET' |
||||
|
nat: | |
||||
|
"8080": "80" |
||||
|
prepare: pkg install socat wget |
||||
|
copyback: false |
||||
|
run: | |
||||
|
cd ../acmetest \ |
||||
|
&& ./letest.sh |
||||
|
|
||||
|
|
@ -0,0 +1,76 @@ |
|||||
|
name: OpenBSD |
||||
|
on: |
||||
|
push: |
||||
|
branches: |
||||
|
- '*' |
||||
|
paths: |
||||
|
- '*.sh' |
||||
|
- '.github/workflows/OpenBSD.yml' |
||||
|
|
||||
|
pull_request: |
||||
|
branches: |
||||
|
- dev |
||||
|
paths: |
||||
|
- '*.sh' |
||||
|
- '.github/workflows/OpenBSD.yml' |
||||
|
|
||||
|
concurrency: |
||||
|
group: ${{ github.workflow }}-${{ github.ref }} |
||||
|
cancel-in-progress: true |
||||
|
|
||||
|
|
||||
|
|
||||
|
jobs: |
||||
|
OpenBSD: |
||||
|
strategy: |
||||
|
matrix: |
||||
|
include: |
||||
|
- TEST_ACME_Server: "LetsEncrypt.org_test" |
||||
|
CA_ECDSA: "" |
||||
|
CA: "" |
||||
|
CA_EMAIL: "" |
||||
|
TEST_PREFERRED_CHAIN: (STAGING) |
||||
|
- TEST_ACME_Server: "LetsEncrypt.org_test" |
||||
|
CA_ECDSA: "" |
||||
|
CA: "" |
||||
|
CA_EMAIL: "" |
||||
|
TEST_PREFERRED_CHAIN: (STAGING) |
||||
|
ACME_USE_WGET: 1 |
||||
|
#- TEST_ACME_Server: "ZeroSSL.com" |
||||
|
# CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" |
||||
|
# CA: "ZeroSSL RSA Domain Secure Site CA" |
||||
|
# CA_EMAIL: "githubtest@acme.sh" |
||||
|
# TEST_PREFERRED_CHAIN: "" |
||||
|
runs-on: ubuntu-latest |
||||
|
env: |
||||
|
TEST_LOCAL: 1 |
||||
|
TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }} |
||||
|
CA_ECDSA: ${{ matrix.CA_ECDSA }} |
||||
|
CA: ${{ matrix.CA }} |
||||
|
CA_EMAIL: ${{ matrix.CA_EMAIL }} |
||||
|
TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }} |
||||
|
ACME_USE_WGET: ${{ matrix.ACME_USE_WGET }} |
||||
|
steps: |
||||
|
- uses: actions/checkout@v4 |
||||
|
- uses: vmactions/cf-tunnel@v0 |
||||
|
id: tunnel |
||||
|
with: |
||||
|
protocol: http |
||||
|
port: 8080 |
||||
|
- name: Set envs |
||||
|
run: echo "TestingDomain=${{steps.tunnel.outputs.server}}" >> $GITHUB_ENV |
||||
|
- name: Clone acmetest |
||||
|
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ |
||||
|
- uses: vmactions/openbsd-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_add socat curl wget libnghttp2 |
||||
|
usesh: true |
||||
|
copyback: false |
||||
|
run: | |
||||
|
cd ../acmetest \ |
||||
|
&& ./letest.sh |
||||
|
|
||||
|
|
@ -1,61 +1,75 @@ |
|||||
name: Solaris |
|
||||
on: |
|
||||
push: |
|
||||
branches: |
|
||||
- '*' |
|
||||
paths: |
|
||||
- '*.sh' |
|
||||
- '.github/workflows/Solaris.yml' |
|
||||
|
|
||||
pull_request: |
|
||||
branches: |
|
||||
- dev |
|
||||
paths: |
|
||||
- '*.sh' |
|
||||
- '.github/workflows/Solaris.yml' |
|
||||
|
|
||||
|
|
||||
jobs: |
|
||||
Solaris: |
|
||||
strategy: |
|
||||
matrix: |
|
||||
include: |
|
||||
- TEST_ACME_Server: "LetsEncrypt.org_test" |
|
||||
CA_ECDSA: "" |
|
||||
CA: "" |
|
||||
CA_EMAIL: "" |
|
||||
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1 |
|
||||
- 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: macos-10.15 |
|
||||
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 }} |
|
||||
steps: |
|
||||
- uses: actions/checkout@v2 |
|
||||
- uses: vmactions/cf-tunnel@v0.0.3 |
|
||||
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 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ |
|
||||
- uses: vmactions/solaris-vm@v0.0.5 |
|
||||
with: |
|
||||
envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN' |
|
||||
nat: | |
|
||||
"8080": "80" |
|
||||
prepare: pkgutil -y -i socat curl |
|
||||
run: | |
|
||||
cd ../acmetest \ |
|
||||
&& ./letest.sh |
|
||||
|
|
||||
|
name: Solaris |
||||
|
on: |
||||
|
push: |
||||
|
branches: |
||||
|
- '*' |
||||
|
paths: |
||||
|
- '*.sh' |
||||
|
- '.github/workflows/Solaris.yml' |
||||
|
|
||||
|
pull_request: |
||||
|
branches: |
||||
|
- dev |
||||
|
paths: |
||||
|
- '*.sh' |
||||
|
- '.github/workflows/Solaris.yml' |
||||
|
|
||||
|
concurrency: |
||||
|
group: ${{ github.workflow }}-${{ github.ref }} |
||||
|
cancel-in-progress: true |
||||
|
|
||||
|
|
||||
|
|
||||
|
jobs: |
||||
|
Solaris: |
||||
|
strategy: |
||||
|
matrix: |
||||
|
include: |
||||
|
- TEST_ACME_Server: "LetsEncrypt.org_test" |
||||
|
CA_ECDSA: "" |
||||
|
CA: "" |
||||
|
CA_EMAIL: "" |
||||
|
TEST_PREFERRED_CHAIN: (STAGING) |
||||
|
- TEST_ACME_Server: "LetsEncrypt.org_test" |
||||
|
CA_ECDSA: "" |
||||
|
CA: "" |
||||
|
CA_EMAIL: "" |
||||
|
TEST_PREFERRED_CHAIN: (STAGING) |
||||
|
ACME_USE_WGET: 1 |
||||
|
#- TEST_ACME_Server: "ZeroSSL.com" |
||||
|
# CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" |
||||
|
# CA: "ZeroSSL RSA Domain Secure Site CA" |
||||
|
# CA_EMAIL: "githubtest@acme.sh" |
||||
|
# TEST_PREFERRED_CHAIN: "" |
||||
|
runs-on: ubuntu-latest |
||||
|
env: |
||||
|
TEST_LOCAL: 1 |
||||
|
TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }} |
||||
|
CA_ECDSA: ${{ matrix.CA_ECDSA }} |
||||
|
CA: ${{ matrix.CA }} |
||||
|
CA_EMAIL: ${{ matrix.CA_EMAIL }} |
||||
|
TEST_PREFERRED_CHAIN: ${{ matrix.TEST_PREFERRED_CHAIN }} |
||||
|
ACME_USE_WGET: ${{ matrix.ACME_USE_WGET }} |
||||
|
steps: |
||||
|
- uses: actions/checkout@v4 |
||||
|
- uses: vmactions/cf-tunnel@v0 |
||||
|
id: tunnel |
||||
|
with: |
||||
|
protocol: http |
||||
|
port: 8080 |
||||
|
- name: Set envs |
||||
|
run: echo "TestingDomain=${{steps.tunnel.outputs.server}}" >> $GITHUB_ENV |
||||
|
- name: Clone acmetest |
||||
|
run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ |
||||
|
- uses: vmactions/solaris-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: pkgutil -y -i socat curl wget |
||||
|
copyback: false |
||||
|
run: | |
||||
|
cd ../acmetest \ |
||||
|
&& ./letest.sh |
||||
|
|
||||
|
|
@ -0,0 +1,19 @@ |
|||||
|
name: "Update issues" |
||||
|
on: |
||||
|
issues: |
||||
|
types: [opened] |
||||
|
|
||||
|
jobs: |
||||
|
comment: |
||||
|
runs-on: ubuntu-latest |
||||
|
steps: |
||||
|
- uses: actions/github-script@v6 |
||||
|
with: |
||||
|
script: | |
||||
|
github.rest.issues.createComment({ |
||||
|
issue_number: context.issue.number, |
||||
|
owner: context.repo.owner, |
||||
|
repo: context.repo.repo, |
||||
|
body: "Please upgrade to the latest code and try again first. Maybe it's already fixed. ```acme.sh --upgrade``` If it's still not working, please provide the log with `--debug 2`, otherwise, nobody can help you." |
||||
|
|
||||
|
}) |
@ -0,0 +1,30 @@ |
|||||
|
name: Check dns api |
||||
|
|
||||
|
on: |
||||
|
pull_request_target: |
||||
|
types: |
||||
|
- opened |
||||
|
paths: |
||||
|
- 'dnsapi/*.sh' |
||||
|
|
||||
|
|
||||
|
jobs: |
||||
|
welcome: |
||||
|
runs-on: ubuntu-latest |
||||
|
steps: |
||||
|
- uses: actions/github-script@v6 |
||||
|
with: |
||||
|
script: | |
||||
|
await github.rest.issues.createComment({ |
||||
|
issue_number: context.issue.number, |
||||
|
owner: context.repo.owner, |
||||
|
repo: context.repo.repo, |
||||
|
body: `**Welcome** |
||||
|
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. |
||||
|
We look forward to reviewing your Pull request shortly ✨ |
||||
|
注意: 必须通过了 [DNS-API-Test](../wiki/DNS-API-Test) 才会被 review. 无论是修改, 还是新加的 dns api, 都必须确保通过这个测试. |
||||
|
` |
||||
|
}) |
||||
|
|
@ -0,0 +1,30 @@ |
|||||
|
name: Check dns api |
||||
|
|
||||
|
on: |
||||
|
pull_request_target: |
||||
|
types: |
||||
|
- opened |
||||
|
branches: |
||||
|
- 'dev' |
||||
|
paths: |
||||
|
- 'notify/*.sh' |
||||
|
|
||||
|
|
||||
|
jobs: |
||||
|
welcome: |
||||
|
runs-on: ubuntu-latest |
||||
|
steps: |
||||
|
- uses: actions/github-script@v6 |
||||
|
with: |
||||
|
script: | |
||||
|
await github.rest.issues.createComment({ |
||||
|
issue_number: context.issue.number, |
||||
|
owner: context.repo.owner, |
||||
|
repo: context.repo.repo, |
||||
|
body: `**Welcome** |
||||
|
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. |
||||
|
We look forward to reviewing your Pull request shortly ✨ |
||||
|
` |
||||
|
}) |
||||
|
|
1558
acme.sh
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,156 @@ |
|||||
|
#!/usr/bin/env sh |
||||
|
|
||||
|
# This deploy hook is tested on OpenMediaVault 5.x. It supports both local and remote deployment. |
||||
|
# The way it works is that if a cert with the matching domain name is not found, it will firstly create a dummy cert to get its uuid, and then replace it with your cert. |
||||
|
# |
||||
|
# DEPLOY_OMV_WEBUI_ADMIN - This is OMV web gui admin account. Default value is admin. It's required as the user parameter (-u) for the omv-rpc command. |
||||
|
# DEPLOY_OMV_HOST and DEPLOY_OMV_SSH_USER are optional. They are used for remote deployment through ssh (support public key authentication only). Per design, OMV web gui admin doesn't have ssh permission, so another account is needed for ssh. |
||||
|
# |
||||
|
# returns 0 means success, otherwise error. |
||||
|
|
||||
|
######## Public functions ##################### |
||||
|
|
||||
|
#domain keyfile certfile cafile fullchain |
||||
|
openmediavault_deploy() { |
||||
|
_cdomain="$1" |
||||
|
_ckey="$2" |
||||
|
_ccert="$3" |
||||
|
_cca="$4" |
||||
|
_cfullchain="$5" |
||||
|
|
||||
|
_debug _cdomain "$_cdomain" |
||||
|
_debug _ckey "$_ckey" |
||||
|
_debug _ccert "$_ccert" |
||||
|
_debug _cca "$_cca" |
||||
|
_debug _cfullchain "$_cfullchain" |
||||
|
|
||||
|
_getdeployconf DEPLOY_OMV_WEBUI_ADMIN |
||||
|
|
||||
|
if [ -z "$DEPLOY_OMV_WEBUI_ADMIN" ]; then |
||||
|
DEPLOY_OMV_WEBUI_ADMIN="admin" |
||||
|
fi |
||||
|
|
||||
|
_savedeployconf DEPLOY_OMV_WEBUI_ADMIN "$DEPLOY_OMV_WEBUI_ADMIN" |
||||
|
|
||||
|
_getdeployconf DEPLOY_OMV_HOST |
||||
|
_getdeployconf DEPLOY_OMV_SSH_USER |
||||
|
|
||||
|
if [ -n "$DEPLOY_OMV_HOST" ] && [ -n "$DEPLOY_OMV_SSH_USER" ]; then |
||||
|
_info "[OMV deploy-hook] Deploy certificate remotely through ssh." |
||||
|
_savedeployconf DEPLOY_OMV_HOST "$DEPLOY_OMV_HOST" |
||||
|
_savedeployconf DEPLOY_OMV_SSH_USER "$DEPLOY_OMV_SSH_USER" |
||||
|
else |
||||
|
_info "[OMV deploy-hook] Deploy certificate locally." |
||||
|
fi |
||||
|
|
||||
|
if [ -n "$DEPLOY_OMV_HOST" ] && [ -n "$DEPLOY_OMV_SSH_USER" ]; then |
||||
|
|
||||
|
_command="omv-rpc -u $DEPLOY_OMV_WEBUI_ADMIN 'CertificateMgmt' 'getList' '{\"start\": 0, \"limit\": -1}' | jq -r '.data[] | select(.name==\"/CN='$_cdomain'\") | .uuid'" |
||||
|
# shellcheck disable=SC2029 |
||||
|
_uuid=$(ssh "$DEPLOY_OMV_SSH_USER@$DEPLOY_OMV_HOST" "$_command") |
||||
|
_debug _command "$_command" |
||||
|
|
||||
|
if [ -z "$_uuid" ]; then |
||||
|
_info "[OMV deploy-hook] Domain $_cdomain has no certificate in openmediavault, creating it!" |
||||
|
_command="omv-rpc -u $DEPLOY_OMV_WEBUI_ADMIN 'CertificateMgmt' 'create' '{\"cn\": \"test.example.com\", \"size\": 4096, \"days\": 3650, \"c\": \"\", \"st\": \"\", \"l\": \"\", \"o\": \"\", \"ou\": \"\", \"email\": \"\"}' | jq -r '.uuid'" |
||||
|
# shellcheck disable=SC2029 |
||||
|
_uuid=$(ssh "$DEPLOY_OMV_SSH_USER@$DEPLOY_OMV_HOST" "$_command") |
||||
|
_debug _command "$_command" |
||||
|
|
||||
|
if [ -z "$_uuid" ]; then |
||||
|
_err "[OMV deploy-hook] An error occured while creating the certificate" |
||||
|
return 1 |
||||
|
fi |
||||
|
fi |
||||
|
|
||||
|
_info "[OMV deploy-hook] Domain $_cdomain has uuid: $_uuid" |
||||
|
_fullchain=$(jq <"$_cfullchain" -aRs .) |
||||
|
_key=$(jq <"$_ckey" -aRs .) |
||||
|
|
||||
|
_debug _fullchain "$_fullchain" |
||||
|
_debug _key "$_key" |
||||
|
|
||||
|
_info "[OMV deploy-hook] Updating key and certificate in openmediavault" |
||||
|
_command="omv-rpc -u $DEPLOY_OMV_WEBUI_ADMIN 'CertificateMgmt' 'set' '{\"uuid\":\"$_uuid\", \"certificate\":$_fullchain, \"privatekey\":$_key, \"comment\":\"acme.sh deployed $(date)\"}'" |
||||
|
# shellcheck disable=SC2029 |
||||
|
_result=$(ssh "$DEPLOY_OMV_SSH_USER@$DEPLOY_OMV_HOST" "$_command") |
||||
|
|
||||
|
_debug _command "$_command" |
||||
|
_debug _result "$_result" |
||||
|
|
||||
|
_command="omv-rpc -u $DEPLOY_OMV_WEBUI_ADMIN 'WebGui' 'setSettings' \$(omv-rpc -u $DEPLOY_OMV_WEBUI_ADMIN 'WebGui' 'getSettings' | jq -c '.sslcertificateref=\"$_uuid\"')" |
||||
|
# shellcheck disable=SC2029 |
||||
|
_result=$(ssh "$DEPLOY_OMV_SSH_USER@$DEPLOY_OMV_HOST" "$_command") |
||||
|
|
||||
|
_debug _command "$_command" |
||||
|
_debug _result "$_result" |
||||
|
|
||||
|
_info "[OMV deploy-hook] Asking openmediavault to apply changes... (this could take some time, hang in there)" |
||||
|
_command="omv-rpc -u $DEPLOY_OMV_WEBUI_ADMIN 'Config' 'applyChanges' '{\"modules\":[], \"force\": false}'" |
||||
|
# shellcheck disable=SC2029 |
||||
|
_result=$(ssh "$DEPLOY_OMV_SSH_USER@$DEPLOY_OMV_HOST" "$_command") |
||||
|
|
||||
|
_debug _command "$_command" |
||||
|
_debug _result "$_result" |
||||
|
|
||||
|
_info "[OMV deploy-hook] Asking nginx to reload" |
||||
|
_command="nginx -s reload" |
||||
|
# shellcheck disable=SC2029 |
||||
|
_result=$(ssh "$DEPLOY_OMV_SSH_USER@$DEPLOY_OMV_HOST" "$_command") |
||||
|
|
||||
|
_debug _command "$_command" |
||||
|
_debug _result "$_result" |
||||
|
|
||||
|
else |
||||
|
|
||||
|
# shellcheck disable=SC2086 |
||||
|
_uuid=$(omv-rpc -u $DEPLOY_OMV_WEBUI_ADMIN 'CertificateMgmt' 'getList' '{"start": 0, "limit": -1}' | jq -r '.data[] | select(.name=="/CN='$_cdomain'") | .uuid') |
||||
|
if [ -z "$_uuid" ]; then |
||||
|
_info "[OMV deploy-hook] Domain $_cdomain has no certificate in openmediavault, creating it!" |
||||
|
# shellcheck disable=SC2086 |
||||
|
_uuid=$(omv-rpc -u $DEPLOY_OMV_WEBUI_ADMIN 'CertificateMgmt' 'create' '{"cn": "test.example.com", "size": 4096, "days": 3650, "c": "", "st": "", "l": "", "o": "", "ou": "", "email": ""}' | jq -r '.uuid') |
||||
|
|
||||
|
if [ -z "$_uuid" ]; then |
||||
|
_err "[OMB deploy-hook] An error occured while creating the certificate" |
||||
|
return 1 |
||||
|
fi |
||||
|
fi |
||||
|
|
||||
|
_info "[OMV deploy-hook] Domain $_cdomain has uuid: $_uuid" |
||||
|
_fullchain=$(jq <"$_cfullchain" -aRs .) |
||||
|
_key=$(jq <"$_ckey" -aRs .) |
||||
|
|
||||
|
_debug _fullchain "$_fullchain" |
||||
|
_debug _key "$_key" |
||||
|
|
||||
|
_info "[OMV deploy-hook] Updating key and certificate in openmediavault" |
||||
|
_command="omv-rpc -u $DEPLOY_OMV_WEBUI_ADMIN 'CertificateMgmt' 'set' '{\"uuid\":\"$_uuid\", \"certificate\":$_fullchain, \"privatekey\":$_key, \"comment\":\"acme.sh deployed $(date)\"}'" |
||||
|
_result=$(eval "$_command") |
||||
|
|
||||
|
_debug _command "$_command" |
||||
|
_debug _result "$_result" |
||||
|
|
||||
|
_command="omv-rpc -u $DEPLOY_OMV_WEBUI_ADMIN 'WebGui' 'setSettings' \$(omv-rpc -u $DEPLOY_OMV_WEBUI_ADMIN 'WebGui' 'getSettings' | jq -c '.sslcertificateref=\"$_uuid\"')" |
||||
|
_result=$(eval "$_command") |
||||
|
|
||||
|
_debug _command "$_command" |
||||
|
_debug _result "$_result" |
||||
|
|
||||
|
_info "[OMV deploy-hook] Asking openmediavault to apply changes... (this could take some time, hang in there)" |
||||
|
_command="omv-rpc -u $DEPLOY_OMV_WEBUI_ADMIN 'Config' 'applyChanges' '{\"modules\":[], \"force\": false}'" |
||||
|
_result=$(eval "$_command") |
||||
|
|
||||
|
_debug _command "$_command" |
||||
|
_debug _result "$_result" |
||||
|
|
||||
|
_info "[OMV deploy-hook] Asking nginx to reload" |
||||
|
_command="nginx -s reload" |
||||
|
_result=$(eval "$_command") |
||||
|
|
||||
|
_debug _command "$_command" |
||||
|
_debug _result "$_result" |
||||
|
|
||||
|
fi |
||||
|
|
||||
|
return 0 |
||||
|
} |
@ -0,0 +1,132 @@ |
|||||
|
#!/usr/bin/env sh |
||||
|
|
||||
|
# Deploy certificates to a proxmox virtual environment node using the API. |
||||
|
# |
||||
|
# Environment variables that can be set are: |
||||
|
# `DEPLOY_PROXMOXVE_SERVER`: The hostname of the proxmox ve node. Defaults to |
||||
|
# _cdomain. |
||||
|
# `DEPLOY_PROXMOXVE_SERVER_PORT`: The port number the management interface is on. |
||||
|
# Defaults to 8006. |
||||
|
# `DEPLOY_PROXMOXVE_NODE_NAME`: The name of the node we'll be connecting to. |
||||
|
# Defaults to the host portion of the server |
||||
|
# domain name. |
||||
|
# `DEPLOY_PROXMOXVE_USER`: The user we'll connect as. Defaults to root. |
||||
|
# `DEPLOY_PROXMOXVE_USER_REALM`: The authentication realm the user authenticates |
||||
|
# with. Defaults to pam. |
||||
|
# `DEPLOY_PROXMOXVE_API_TOKEN_NAME`: The name of the API token created for the |
||||
|
# user account. Defaults to acme. |
||||
|
# `DEPLOY_PROXMOXVE_API_TOKEN_KEY`: The API token. Required. |
||||
|
|
||||
|
proxmoxve_deploy() { |
||||
|
_cdomain="$1" |
||||
|
_ckey="$2" |
||||
|
_ccert="$3" |
||||
|
_cca="$4" |
||||
|
_cfullchain="$5" |
||||
|
|
||||
|
_debug _cdomain "$_cdomain" |
||||
|
_debug2 _ckey "$_ckey" |
||||
|
_debug _ccert "$_ccert" |
||||
|
_debug _cca "$_cca" |
||||
|
_debug _cfullchain "$_cfullchain" |
||||
|
|
||||
|
# "Sane" defaults. |
||||
|
_getdeployconf DEPLOY_PROXMOXVE_SERVER |
||||
|
if [ -z "$DEPLOY_PROXMOXVE_SERVER" ]; then |
||||
|
_target_hostname="$_cdomain" |
||||
|
else |
||||
|
_target_hostname="$DEPLOY_PROXMOXVE_SERVER" |
||||
|
_savedeployconf DEPLOY_PROXMOXVE_SERVER "$DEPLOY_PROXMOXVE_SERVER" |
||||
|
fi |
||||
|
_debug2 DEPLOY_PROXMOXVE_SERVER "$_target_hostname" |
||||
|
|
||||
|
_getdeployconf DEPLOY_PROXMOXVE_SERVER_PORT |
||||
|
if [ -z "$DEPLOY_PROXMOXVE_SERVER_PORT" ]; then |
||||
|
_target_port="8006" |
||||
|
else |
||||
|
_target_port="$DEPLOY_PROXMOXVE_SERVER_PORT" |
||||
|
_savedeployconf DEPLOY_PROXMOXVE_SERVER_PORT "$DEPLOY_PROXMOXVE_SERVER_PORT" |
||||
|
fi |
||||
|
_debug2 DEPLOY_PROXMOXVE_SERVER_PORT "$_target_port" |
||||
|
|
||||
|
_getdeployconf DEPLOY_PROXMOXVE_NODE_NAME |
||||
|
if [ -z "$DEPLOY_PROXMOXVE_NODE_NAME" ]; then |
||||
|
_node_name=$(echo "$_target_hostname" | cut -d. -f1) |
||||
|
else |
||||
|
_node_name="$DEPLOY_PROXMOXVE_NODE_NAME" |
||||
|
_savedeployconf DEPLOY_PROXMOXVE_NODE_NAME "$DEPLOY_PROXMOXVE_NODE_NAME" |
||||
|
fi |
||||
|
_debug2 DEPLOY_PROXMOXVE_NODE_NAME "$_node_name" |
||||
|
|
||||
|
# Complete URL. |
||||
|
_target_url="https://${_target_hostname}:${_target_port}/api2/json/nodes/${_node_name}/certificates/custom" |
||||
|
_debug TARGET_URL "$_target_url" |
||||
|
|
||||
|
# More "sane" defaults. |
||||
|
_getdeployconf DEPLOY_PROXMOXVE_USER |
||||
|
if [ -z "$DEPLOY_PROXMOXVE_USER" ]; then |
||||
|
_proxmoxve_user="root" |
||||
|
else |
||||
|
_proxmoxve_user="$DEPLOY_PROXMOXVE_USER" |
||||
|
_savedeployconf DEPLOY_PROXMOXVE_USER "$DEPLOY_PROXMOXVE_USER" |
||||
|
fi |
||||
|
_debug2 DEPLOY_PROXMOXVE_USER "$_proxmoxve_user" |
||||
|
|
||||
|
_getdeployconf DEPLOY_PROXMOXVE_USER_REALM |
||||
|
if [ -z "$DEPLOY_PROXMOXVE_USER_REALM" ]; then |
||||
|
_proxmoxve_user_realm="pam" |
||||
|
else |
||||
|
_proxmoxve_user_realm="$DEPLOY_PROXMOXVE_USER_REALM" |
||||
|
_savedeployconf DEPLOY_PROXMOXVE_USER_REALM "$DEPLOY_PROXMOXVE_USER_REALM" |
||||
|
fi |
||||
|
_debug2 DEPLOY_PROXMOXVE_USER_REALM "$_proxmoxve_user_realm" |
||||
|
|
||||
|
_getdeployconf DEPLOY_PROXMOXVE_API_TOKEN_NAME |
||||
|
if [ -z "$DEPLOY_PROXMOXVE_API_TOKEN_NAME" ]; then |
||||
|
_proxmoxve_api_token_name="acme" |
||||
|
else |
||||
|
_proxmoxve_api_token_name="$DEPLOY_PROXMOXVE_API_TOKEN_NAME" |
||||
|
_savedeployconf DEPLOY_PROXMOXVE_API_TOKEN_NAME "$DEPLOY_PROXMOXVE_API_TOKEN_NAME" |
||||
|
fi |
||||
|
_debug2 DEPLOY_PROXMOXVE_API_TOKEN_NAME "$_proxmoxve_api_token_name" |
||||
|
|
||||
|
# This is required. |
||||
|
_getdeployconf DEPLOY_PROXMOXVE_API_TOKEN_KEY |
||||
|
if [ -z "$DEPLOY_PROXMOXVE_API_TOKEN_KEY" ]; then |
||||
|
_err "API key not provided." |
||||
|
return 1 |
||||
|
else |
||||
|
_proxmoxve_api_token_key="$DEPLOY_PROXMOXVE_API_TOKEN_KEY" |
||||
|
_savedeployconf DEPLOY_PROXMOXVE_API_TOKEN_KEY "$DEPLOY_PROXMOXVE_API_TOKEN_KEY" |
||||
|
fi |
||||
|
_debug2 DEPLOY_PROXMOXVE_API_TOKEN_KEY "$_proxmoxve_api_token_key" |
||||
|
|
||||
|
# 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}" |
||||
|
_debug2 "Auth Header" "$_proxmoxve_header_api_token" |
||||
|
|
||||
|
# Ugly. I hate putting heredocs inside functions because heredocs don't |
||||
|
# account for whitespace correctly but it _does_ work and is several times |
||||
|
# cleaner than anything else I had here. |
||||
|
# |
||||
|
# This dumps the json payload to a variable that should be passable to the |
||||
|
# _psot function. |
||||
|
_json_payload=$( |
||||
|
cat <<HEREDOC |
||||
|
{ |
||||
|
"certificates": "$(tr '\n' ':' <"$_cfullchain" | sed 's/:/\\n/g')", |
||||
|
"key": "$(tr '\n' ':' <"$_ckey" | sed 's/:/\\n/g')", |
||||
|
"node":"$_node_name", |
||||
|
"restart":"1", |
||||
|
"force":"1" |
||||
|
} |
||||
|
HEREDOC |
||||
|
) |
||||
|
_debug2 Payload "$_json_payload" |
||||
|
|
||||
|
_info "Push certificates to server" |
||||
|
export HTTPS_INSECURE=1 |
||||
|
export _H1="Authorization: PVEAPIToken=${_proxmoxve_header_api_token}" |
||||
|
_post "$_json_payload" "$_target_url" "" POST "application/json" |
||||
|
|
||||
|
} |
@ -0,0 +1,177 @@ |
|||||
|
#!/usr/bin/env sh |
||||
|
# shellcheck disable=SC2034 |
||||
|
dns_artfiles_info='ArtFiles.de |
||||
|
Site: ArtFiles.de |
||||
|
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_artfiles |
||||
|
Options: |
||||
|
AF_API_USERNAME API Username |
||||
|
AF_API_PASSWORD API Password |
||||
|
Issues: github.com/acmesh-official/acme.sh/issues/4718 |
||||
|
Author: Martin Arndt <https://troublezone.net/> |
||||
|
' |
||||
|
|
||||
|
########## 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' |
||||
|
} |
@ -0,0 +1,88 @@ |
|||||
|
#!/usr/bin/env sh |
||||
|
# shellcheck disable=SC2034 |
||||
|
dns_bookmyname_info='BookMyName.com |
||||
|
Site: BookMyName.com |
||||
|
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_bookmyname |
||||
|
Options: |
||||
|
BOOKMYNAME_USERNAME Username |
||||
|
BOOKMYNAME_PASSWORD Password |
||||
|
Issues: github.com/acmesh-official/acme.sh/issues/3209 |
||||
|
Author: Neilpang |
||||
|
' |
||||
|
|
||||
|
######## Public functions ##################### |
||||
|
|
||||
|
# 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 ################################## |
@ -0,0 +1,245 @@ |
|||||
|
#!/usr/bin/env sh |
||||
|
# shellcheck disable=SC2034 |
||||
|
dns_bunny_info='Bunny.net |
||||
|
Site: Bunny.net/dns/ |
||||
|
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_bunny |
||||
|
Options: |
||||
|
BUNNY_API_KEY API Key |
||||
|
Issues: github.com/acmesh-official/acme.sh/issues/4296 |
||||
|
Author: <nosilver4u@ewww.io> |
||||
|
' |
||||
|
|
||||
|
##################### Public functions ##################### |
||||
|
|
||||
|
## Create the text record for validation. |
||||
|
## Usage: fulldomain txtvalue |
||||
|
## EG: "_acme-challenge.www.other.domain.com" "XKrxpRBosdq0HG9i01zxXp5CPBs" |
||||
|
dns_bunny_add() { |
||||
|
fulldomain="$(echo "$1" | _lower_case)" |
||||
|
txtvalue=$2 |
||||
|
|
||||
|
BUNNY_API_KEY="${BUNNY_API_KEY:-$(_readaccountconf_mutable BUNNY_API_KEY)}" |
||||
|
# Check if API Key is set |
||||
|
if [ -z "$BUNNY_API_KEY" ]; then |
||||
|
BUNNY_API_KEY="" |
||||
|
_err "You did not specify Bunny.net API key." |
||||
|
_err "Please export BUNNY_API_KEY and try again." |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
_info "Using Bunny.net dns validation - add record" |
||||
|
_debug fulldomain "$fulldomain" |
||||
|
_debug txtvalue "$txtvalue" |
||||
|
|
||||
|
## save the env vars (key and domain split location) for later automated use |
||||
|
_saveaccountconf_mutable BUNNY_API_KEY "$BUNNY_API_KEY" |
||||
|
|
||||
|
## split the domain for Bunny API |
||||
|
if ! _get_base_domain "$fulldomain"; then |
||||
|
_err "domain not found in your account for addition" |
||||
|
return 1 |
||||
|
fi |
||||
|
_debug _sub_domain "$_sub_domain" |
||||
|
_debug _domain "$_domain" |
||||
|
_debug _domain_id "$_domain_id" |
||||
|
|
||||
|
## Set the header with our post type and auth key |
||||
|
export _H1="Accept: application/json" |
||||
|
export _H2="AccessKey: $BUNNY_API_KEY" |
||||
|
export _H3="Content-Type: application/json" |
||||
|
PURL="https://api.bunny.net/dnszone/$_domain_id/records" |
||||
|
PBODY='{"Id":'$_domain_id',"Type":3,"Name":"'$_sub_domain'","Value":"'$txtvalue'","ttl":120}' |
||||
|
|
||||
|
_debug PURL "$PURL" |
||||
|
_debug PBODY "$PBODY" |
||||
|
|
||||
|
## the create request - POST |
||||
|
## args: BODY, URL, [need64, httpmethod] |
||||
|
response="$(_post "$PBODY" "$PURL" "" "PUT")" |
||||
|
|
||||
|
## check response |
||||
|
if [ "$?" != "0" ]; then |
||||
|
_err "error in response: $response" |
||||
|
return 1 |
||||
|
fi |
||||
|
_debug2 response "$response" |
||||
|
|
||||
|
## finished correctly |
||||
|
return 0 |
||||
|
} |
||||
|
|
||||
|
## Remove the txt record after validation. |
||||
|
## Usage: fulldomain txtvalue |
||||
|
## EG: "_acme-challenge.www.other.domain.com" "XKrxpRBosdq0HG9i01zxXp5CPBs" |
||||
|
dns_bunny_rm() { |
||||
|
fulldomain="$(echo "$1" | _lower_case)" |
||||
|
txtvalue=$2 |
||||
|
|
||||
|
BUNNY_API_KEY="${BUNNY_API_KEY:-$(_readaccountconf_mutable BUNNY_API_KEY)}" |
||||
|
# Check if API Key Exists |
||||
|
if [ -z "$BUNNY_API_KEY" ]; then |
||||
|
BUNNY_API_KEY="" |
||||
|
_err "You did not specify Bunny.net API key." |
||||
|
_err "Please export BUNNY_API_KEY and try again." |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
_info "Using Bunny.net dns validation - remove record" |
||||
|
_debug fulldomain "$fulldomain" |
||||
|
_debug txtvalue "$txtvalue" |
||||
|
|
||||
|
## split the domain for Bunny API |
||||
|
if ! _get_base_domain "$fulldomain"; then |
||||
|
_err "Domain not found in your account for TXT record removal" |
||||
|
return 1 |
||||
|
fi |
||||
|
_debug _sub_domain "$_sub_domain" |
||||
|
_debug _domain "$_domain" |
||||
|
_debug _domain_id "$_domain_id" |
||||
|
|
||||
|
## Set the header with our post type and key auth key |
||||
|
export _H1="Accept: application/json" |
||||
|
export _H2="AccessKey: $BUNNY_API_KEY" |
||||
|
## get URL for the list of DNS records |
||||
|
GURL="https://api.bunny.net/dnszone/$_domain_id" |
||||
|
|
||||
|
## 1) Get the domain/zone records |
||||
|
## the fetch request - GET |
||||
|
## args: URL, [onlyheader, timeout] |
||||
|
domain_list="$(_get "$GURL")" |
||||
|
|
||||
|
## check response |
||||
|
if [ "$?" != "0" ]; then |
||||
|
_err "error in domain_list response: $domain_list" |
||||
|
return 1 |
||||
|
fi |
||||
|
_debug2 domain_list "$domain_list" |
||||
|
|
||||
|
## 2) search through records |
||||
|
## check for what we are looking for: "Type":3,"Value":"$txtvalue","Name":"$_sub_domain" |
||||
|
record="$(echo "$domain_list" | _egrep_o "\"Id\"\s*\:\s*\"*[0-9]+\"*,\s*\"Type\"[^}]*\"Value\"\s*\:\s*\"$txtvalue\"[^}]*\"Name\"\s*\:\s*\"$_sub_domain\"")" |
||||
|
|
||||
|
if [ -n "$record" ]; then |
||||
|
|
||||
|
## We found records |
||||
|
rec_ids="$(echo "$record" | _egrep_o "Id\"\s*\:\s*\"*[0-9]+" | _egrep_o "[0-9]+")" |
||||
|
_debug rec_ids "$rec_ids" |
||||
|
if [ -n "$rec_ids" ]; then |
||||
|
echo "$rec_ids" | while IFS= read -r rec_id; do |
||||
|
## delete the record |
||||
|
## delete URL for removing the one we dont want |
||||
|
DURL="https://api.bunny.net/dnszone/$_domain_id/records/$rec_id" |
||||
|
|
||||
|
## the removal request - DELETE |
||||
|
## args: BODY, URL, [need64, httpmethod] |
||||
|
response="$(_post "" "$DURL" "" "DELETE")" |
||||
|
|
||||
|
## check response (sort of) |
||||
|
if [ "$?" != "0" ]; then |
||||
|
_err "error in remove response: $response" |
||||
|
return 1 |
||||
|
fi |
||||
|
_debug2 response "$response" |
||||
|
|
||||
|
done |
||||
|
fi |
||||
|
fi |
||||
|
|
||||
|
## finished correctly |
||||
|
return 0 |
||||
|
} |
||||
|
|
||||
|
##################### Private functions below ##################### |
||||
|
|
||||
|
## Split the domain provided into the "base domain" and the "start prefix". |
||||
|
## This function searches for the longest subdomain in your account |
||||
|
## for the full domain given and splits it into the base domain (zone) |
||||
|
## and the prefix/record to be added/removed |
||||
|
## USAGE: fulldomain |
||||
|
## EG: "_acme-challenge.two.three.four.domain.com" |
||||
|
## returns |
||||
|
## _sub_domain="_acme-challenge.two" |
||||
|
## _domain="three.four.domain.com" *IF* zone "three.four.domain.com" exists |
||||
|
## _domain_id=234 |
||||
|
## if only "domain.com" exists it will return |
||||
|
## _sub_domain="_acme-challenge.two.three.four" |
||||
|
## _domain="domain.com" |
||||
|
## _domain_id=234 |
||||
|
_get_base_domain() { |
||||
|
# args |
||||
|
fulldomain="$(echo "$1" | _lower_case)" |
||||
|
_debug fulldomain "$fulldomain" |
||||
|
|
||||
|
# domain max legal length = 253 |
||||
|
MAX_DOM=255 |
||||
|
page=1 |
||||
|
|
||||
|
## get a list of domains for the account to check thru |
||||
|
## Set the headers |
||||
|
export _H1="Accept: application/json" |
||||
|
export _H2="AccessKey: $BUNNY_API_KEY" |
||||
|
_debug BUNNY_API_KEY "$BUNNY_API_KEY" |
||||
|
## get URL for the list of domains |
||||
|
## may get: "links":{"pages":{"last":".../v2/domains/DOM/records?page=2","next":".../v2/domains/DOM/records?page=2"}} |
||||
|
DOMURL="https://api.bunny.net/dnszone" |
||||
|
|
||||
|
## while we dont have a matching domain we keep going |
||||
|
while [ -z "$found" ]; do |
||||
|
## get the domain list (current page) |
||||
|
domain_list="$(_get "$DOMURL")" |
||||
|
|
||||
|
## check response |
||||
|
if [ "$?" != "0" ]; then |
||||
|
_err "error in domain_list response: $domain_list" |
||||
|
return 1 |
||||
|
fi |
||||
|
_debug2 domain_list "$domain_list" |
||||
|
|
||||
|
i=1 |
||||
|
while [ $i -gt 0 ]; do |
||||
|
## get next longest domain |
||||
|
_domain=$(printf "%s" "$fulldomain" | cut -d . -f "$i"-"$MAX_DOM") |
||||
|
## check we got something back from our cut (or are we at the end) |
||||
|
if [ -z "$_domain" ]; then |
||||
|
break |
||||
|
fi |
||||
|
## we got part of a domain back - grep it out |
||||
|
found="$(echo "$domain_list" | _egrep_o "\"Id\"\s*:\s*\"*[0-9]+\"*,\s*\"Domain\"\s*\:\s*\"$_domain\"")" |
||||
|
## check if it exists |
||||
|
if [ -n "$found" ]; then |
||||
|
## exists - exit loop returning the parts |
||||
|
sub_point=$(_math $i - 1) |
||||
|
_sub_domain=$(printf "%s" "$fulldomain" | cut -d . -f 1-"$sub_point") |
||||
|
_domain_id="$(echo "$found" | _egrep_o "Id\"\s*\:\s*\"*[0-9]+" | _egrep_o "[0-9]+")" |
||||
|
_debug _domain_id "$_domain_id" |
||||
|
_debug _domain "$_domain" |
||||
|
_debug _sub_domain "$_sub_domain" |
||||
|
found="" |
||||
|
return 0 |
||||
|
fi |
||||
|
## increment cut point $i |
||||
|
i=$(_math $i + 1) |
||||
|
done |
||||
|
|
||||
|
if [ -z "$found" ]; then |
||||
|
page=$(_math $page + 1) |
||||
|
nextpage="https://api.bunny.net/dnszone?page=$page" |
||||
|
## Find the next page if we don't have a match. |
||||
|
hasnextpage="$(echo "$domain_list" | _egrep_o "\"HasMoreItems\"\s*:\s*true")" |
||||
|
if [ -z "$hasnextpage" ]; then |
||||
|
_err "No record and no nextpage in Bunny.net domain search." |
||||
|
found="" |
||||
|
return 1 |
||||
|
fi |
||||
|
_debug2 nextpage "$nextpage" |
||||
|
DOMURL="$nextpage" |
||||
|
fi |
||||
|
|
||||
|
done |
||||
|
|
||||
|
## We went through the entire domain zone list and didn't find one that matched. |
||||
|
## If we ever get here, something is broken in the code... |
||||
|
_err "Domain not found in Bunny.net account, but we should never get here!" |
||||
|
found="" |
||||
|
return 1 |
||||
|
} |
@ -0,0 +1,165 @@ |
|||||
|
#!/usr/bin/env sh |
||||
|
# shellcheck disable=SC2034 |
||||
|
dns_curanet_info='Curanet.dk |
||||
|
Domains: scannet.dk wannafind.dk dandomain.dk |
||||
|
Site: Curanet.dk |
||||
|
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_curanet |
||||
|
Options: |
||||
|
CURANET_AUTHCLIENTID Auth ClientID. Requires scope dns |
||||
|
CURANET_AUTHSECRET Auth Secret |
||||
|
Issues: github.com/acmesh-official/acme.sh/issues/3933 |
||||
|
Author: Peter L. Hansen <peter@r12.dk> |
||||
|
' |
||||
|
|
||||
|
CURANET_REST_URL="https://api.curanet.dk/dns/v1/Domains" |
||||
|
CURANET_AUTH_URL="https://apiauth.dk.team.blue/auth/realms/Curanet/protocol/openid-connect/token" |
||||
|
CURANET_ACCESS_TOKEN="" |
||||
|
|
||||
|
######## Public functions ##################### |
||||
|
|
||||
|
#Usage: dns_curanet_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" |
||||
|
dns_curanet_add() { |
||||
|
fulldomain=$1 |
||||
|
txtvalue=$2 |
||||
|
_info "Using curanet" |
||||
|
_debug fulldomain "$fulldomain" |
||||
|
_debug txtvalue "$txtvalue" |
||||
|
|
||||
|
CURANET_AUTHCLIENTID="${CURANET_AUTHCLIENTID:-$(_readaccountconf_mutable CURANET_AUTHCLIENTID)}" |
||||
|
CURANET_AUTHSECRET="${CURANET_AUTHSECRET:-$(_readaccountconf_mutable CURANET_AUTHSECRET)}" |
||||
|
if [ -z "$CURANET_AUTHCLIENTID" ] || [ -z "$CURANET_AUTHSECRET" ]; then |
||||
|
CURANET_AUTHCLIENTID="" |
||||
|
CURANET_AUTHSECRET="" |
||||
|
_err "You don't specify curanet api client and secret." |
||||
|
_err "Please create your auth info and try again." |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
#save the credentials to the account conf file. |
||||
|
_saveaccountconf_mutable CURANET_AUTHCLIENTID "$CURANET_AUTHCLIENTID" |
||||
|
_saveaccountconf_mutable CURANET_AUTHSECRET "$CURANET_AUTHSECRET" |
||||
|
|
||||
|
if ! _get_token; then |
||||
|
_err "Unable to get token" |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
if ! _get_root "$fulldomain"; then |
||||
|
_err "Invalid domain" |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
export _H1="Content-Type: application/json-patch+json" |
||||
|
export _H2="Accept: application/json" |
||||
|
export _H3="Authorization: Bearer $CURANET_ACCESS_TOKEN" |
||||
|
data="{\"name\": \"$fulldomain\",\"type\": \"TXT\",\"ttl\": 60,\"priority\": 0,\"data\": \"$txtvalue\"}" |
||||
|
response="$(_post "$data" "$CURANET_REST_URL/${_domain}/Records" "" "")" |
||||
|
|
||||
|
if _contains "$response" "$txtvalue"; then |
||||
|
_debug "TXT record added OK" |
||||
|
else |
||||
|
_err "Unable to add TXT record" |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
return 0 |
||||
|
} |
||||
|
|
||||
|
#Usage: fulldomain txtvalue |
||||
|
#Remove the txt record after validation. |
||||
|
dns_curanet_rm() { |
||||
|
fulldomain=$1 |
||||
|
txtvalue=$2 |
||||
|
_info "Using curanet" |
||||
|
_debug fulldomain "$fulldomain" |
||||
|
_debug txtvalue "$txtvalue" |
||||
|
|
||||
|
CURANET_AUTHCLIENTID="${CURANET_AUTHCLIENTID:-$(_readaccountconf_mutable CURANET_AUTHCLIENTID)}" |
||||
|
CURANET_AUTHSECRET="${CURANET_AUTHSECRET:-$(_readaccountconf_mutable CURANET_AUTHSECRET)}" |
||||
|
|
||||
|
if ! _get_token; then |
||||
|
_err "Unable to get token" |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
if ! _get_root "$fulldomain"; then |
||||
|
_err "Invalid domain" |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
_debug "Getting current record list to identify TXT to delete" |
||||
|
|
||||
|
export _H1="Content-Type: application/json" |
||||
|
export _H2="Accept: application/json" |
||||
|
export _H3="Authorization: Bearer $CURANET_ACCESS_TOKEN" |
||||
|
|
||||
|
response="$(_get "$CURANET_REST_URL/${_domain}/Records" "" "")" |
||||
|
|
||||
|
if ! _contains "$response" "$txtvalue"; then |
||||
|
_err "Unable to delete record (does not contain $txtvalue )" |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
recordid=$(echo "$response" | _egrep_o "{\"id\":[0-9]+,\"name\":\"$fulldomain\",\"type\":\"TXT\",\"ttl\":60,\"priority\":0,\"data\":\"..$txtvalue" | _egrep_o "id\":[0-9]+" | cut -c 5-) |
||||
|
|
||||
|
if [ -z "$recordid" ]; then |
||||
|
_err "Unable to get recordid" |
||||
|
_debug "regex {\"id\":[0-9]+,\"name\":\"$fulldomain\",\"type\":\"TXT\",\"ttl\":60,\"priority\":0,\"data\":\"..$txtvalue" |
||||
|
_debug "response $response" |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
_debug "Deleting recordID $recordid" |
||||
|
response="$(_post "" "$CURANET_REST_URL/${_domain}/Records/$recordid" "" "DELETE")" |
||||
|
return 0 |
||||
|
} |
||||
|
|
||||
|
#################### Private functions below ################################## |
||||
|
|
||||
|
_get_token() { |
||||
|
response="$(_post "grant_type=client_credentials&client_id=$CURANET_AUTHCLIENTID&client_secret=$CURANET_AUTHSECRET&scope=dns" "$CURANET_AUTH_URL" "" "")" |
||||
|
if ! _contains "$response" "access_token"; then |
||||
|
_err "Unable get access token" |
||||
|
return 1 |
||||
|
fi |
||||
|
CURANET_ACCESS_TOKEN=$(echo "$response" | _egrep_o "\"access_token\":\"[^\"]+" | cut -c 17-) |
||||
|
|
||||
|
if [ -z "$CURANET_ACCESS_TOKEN" ]; then |
||||
|
_err "Unable to get token" |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
return 0 |
||||
|
|
||||
|
} |
||||
|
|
||||
|
#_acme-challenge.www.domain.com |
||||
|
#returns |
||||
|
# _domain=domain.com |
||||
|
# _domain_id=sdjkglgdfewsdfg |
||||
|
_get_root() { |
||||
|
domain=$1 |
||||
|
i=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 |
||||
|
|
||||
|
export _H1="Content-Type: application/json" |
||||
|
export _H2="Accept: application/json" |
||||
|
export _H3="Authorization: Bearer $CURANET_ACCESS_TOKEN" |
||||
|
response="$(_get "$CURANET_REST_URL/$h/Records" "" "")" |
||||
|
|
||||
|
if [ ! "$(echo "$response" | _egrep_o "Entity not found")" ]; then |
||||
|
_domain=$h |
||||
|
return 0 |
||||
|
fi |
||||
|
|
||||
|
i=$(_math "$i" + 1) |
||||
|
done |
||||
|
return 1 |
||||
|
} |
@ -1,185 +0,0 @@ |
|||||
#!/usr/bin/env sh |
|
||||
|
|
||||
# CloudXNS Domain api |
|
||||
# |
|
||||
#CX_Key="1234" |
|
||||
# |
|
||||
#CX_Secret="sADDsdasdgdsf" |
|
||||
|
|
||||
CX_Api="https://www.cloudxns.net/api2" |
|
||||
|
|
||||
#REST_API |
|
||||
######## Public functions ##################### |
|
||||
|
|
||||
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" |
|
||||
dns_cx_add() { |
|
||||
fulldomain=$1 |
|
||||
txtvalue=$2 |
|
||||
|
|
||||
CX_Key="${CX_Key:-$(_readaccountconf_mutable CX_Key)}" |
|
||||
CX_Secret="${CX_Secret:-$(_readaccountconf_mutable CX_Secret)}" |
|
||||
if [ -z "$CX_Key" ] || [ -z "$CX_Secret" ]; then |
|
||||
CX_Key="" |
|
||||
CX_Secret="" |
|
||||
_err "You don't specify cloudxns.net api key or secret yet." |
|
||||
_err "Please create you key and try again." |
|
||||
return 1 |
|
||||
fi |
|
||||
|
|
||||
REST_API="$CX_Api" |
|
||||
|
|
||||
#save the api key and email to the account conf file. |
|
||||
_saveaccountconf_mutable CX_Key "$CX_Key" |
|
||||
_saveaccountconf_mutable CX_Secret "$CX_Secret" |
|
||||
|
|
||||
_debug "First detect the root zone" |
|
||||
if ! _get_root "$fulldomain"; then |
|
||||
_err "invalid domain" |
|
||||
return 1 |
|
||||
fi |
|
||||
|
|
||||
add_record "$_domain" "$_sub_domain" "$txtvalue" |
|
||||
} |
|
||||
|
|
||||
#fulldomain txtvalue |
|
||||
dns_cx_rm() { |
|
||||
fulldomain=$1 |
|
||||
txtvalue=$2 |
|
||||
CX_Key="${CX_Key:-$(_readaccountconf_mutable CX_Key)}" |
|
||||
CX_Secret="${CX_Secret:-$(_readaccountconf_mutable CX_Secret)}" |
|
||||
REST_API="$CX_Api" |
|
||||
if _get_root "$fulldomain"; then |
|
||||
record_id="" |
|
||||
existing_records "$_domain" "$_sub_domain" "$txtvalue" |
|
||||
if [ "$record_id" ]; then |
|
||||
_rest DELETE "record/$record_id/$_domain_id" "{}" |
|
||||
_info "Deleted record ${fulldomain}" |
|
||||
fi |
|
||||
fi |
|
||||
} |
|
||||
|
|
||||
#usage: root sub |
|
||||
#return if the sub record already exists. |
|
||||
#echos the existing records count. |
|
||||
# '0' means doesn't exist |
|
||||
existing_records() { |
|
||||
_debug "Getting txt records" |
|
||||
root=$1 |
|
||||
sub=$2 |
|
||||
if ! _rest GET "record/$_domain_id?:domain_id?host_id=0&offset=0&row_num=100"; then |
|
||||
return 1 |
|
||||
fi |
|
||||
|
|
||||
seg=$(printf "%s\n" "$response" | _egrep_o '"record_id":[^{]*host":"'"$_sub_domain"'"[^}]*\}') |
|
||||
_debug seg "$seg" |
|
||||
if [ -z "$seg" ]; then |
|
||||
return 0 |
|
||||
fi |
|
||||
|
|
||||
if printf "%s" "$response" | grep '"type":"TXT"' >/dev/null; then |
|
||||
record_id=$(printf "%s\n" "$seg" | _egrep_o '"record_id":"[^"]*"' | cut -d : -f 2 | tr -d \" | _head_n 1) |
|
||||
_debug record_id "$record_id" |
|
||||
return 0 |
|
||||
fi |
|
||||
|
|
||||
} |
|
||||
|
|
||||
#add the txt record. |
|
||||
#usage: root sub txtvalue |
|
||||
add_record() { |
|
||||
root=$1 |
|
||||
sub=$2 |
|
||||
txtvalue=$3 |
|
||||
fulldomain="$sub.$root" |
|
||||
|
|
||||
_info "Adding record" |
|
||||
|
|
||||
if ! _rest POST "record" "{\"domain_id\": $_domain_id, \"host\":\"$_sub_domain\", \"value\":\"$txtvalue\", \"type\":\"TXT\",\"ttl\":600, \"line_id\":1}"; then |
|
||||
return 1 |
|
||||
fi |
|
||||
|
|
||||
return 0 |
|
||||
} |
|
||||
|
|
||||
#################### Private functions below ################################## |
|
||||
#_acme-challenge.www.domain.com |
|
||||
#returns |
|
||||
# _sub_domain=_acme-challenge.www |
|
||||
# _domain=domain.com |
|
||||
# _domain_id=sdjkglgdfewsdfg |
|
||||
_get_root() { |
|
||||
domain=$1 |
|
||||
i=2 |
|
||||
p=1 |
|
||||
|
|
||||
if ! _rest GET "domain"; then |
|
||||
return 1 |
|
||||
fi |
|
||||
|
|
||||
while true; do |
|
||||
h=$(printf "%s" "$domain" | cut -d . -f $i-100) |
|
||||
_debug h "$h" |
|
||||
if [ -z "$h" ]; then |
|
||||
#not valid |
|
||||
return 1 |
|
||||
fi |
|
||||
|
|
||||
if _contains "$response" "$h."; then |
|
||||
seg=$(printf "%s\n" "$response" | _egrep_o '"id":[^{]*"'"$h"'."[^}]*}') |
|
||||
_debug seg "$seg" |
|
||||
_domain_id=$(printf "%s\n" "$seg" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \") |
|
||||
_debug _domain_id "$_domain_id" |
|
||||
if [ "$_domain_id" ]; then |
|
||||
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) |
|
||||
_debug _sub_domain "$_sub_domain" |
|
||||
_domain="$h" |
|
||||
_debug _domain "$_domain" |
|
||||
return 0 |
|
||||
fi |
|
||||
return 1 |
|
||||
fi |
|
||||
p="$i" |
|
||||
i=$(_math "$i" + 1) |
|
||||
done |
|
||||
return 1 |
|
||||
} |
|
||||
|
|
||||
#Usage: method URI data |
|
||||
_rest() { |
|
||||
m=$1 |
|
||||
ep="$2" |
|
||||
_debug ep "$ep" |
|
||||
url="$REST_API/$ep" |
|
||||
_debug url "$url" |
|
||||
|
|
||||
cdate=$(date -u "+%Y-%m-%d %H:%M:%S UTC") |
|
||||
_debug cdate "$cdate" |
|
||||
|
|
||||
data="$3" |
|
||||
_debug data "$data" |
|
||||
|
|
||||
sec="$CX_Key$url$data$cdate$CX_Secret" |
|
||||
_debug sec "$sec" |
|
||||
hmac=$(printf "%s" "$sec" | _digest md5 hex) |
|
||||
_debug hmac "$hmac" |
|
||||
|
|
||||
export _H1="API-KEY: $CX_Key" |
|
||||
export _H2="API-REQUEST-DATE: $cdate" |
|
||||
export _H3="API-HMAC: $hmac" |
|
||||
export _H4="Content-Type: application/json" |
|
||||
|
|
||||
if [ "$data" ]; then |
|
||||
response="$(_post "$data" "$url" "" "$m")" |
|
||||
else |
|
||||
response="$(_get "$url")" |
|
||||
fi |
|
||||
|
|
||||
if [ "$?" != "0" ]; then |
|
||||
_err "error $ep" |
|
||||
return 1 |
|
||||
fi |
|
||||
_debug2 response "$response" |
|
||||
|
|
||||
_contains "$response" '"code":1' |
|
||||
|
|
||||
} |
|
@ -0,0 +1,188 @@ |
|||||
|
#!/usr/bin/env sh |
||||
|
# shellcheck disable=SC2034 |
||||
|
dns_dnsexit_info='DNSExit.com |
||||
|
Site: DNSExit.com |
||||
|
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_dnsexit |
||||
|
Options: |
||||
|
DNSEXIT_API_KEY API Key |
||||
|
DNSEXIT_AUTH_USER Username |
||||
|
DNSEXIT_AUTH_PASS Password |
||||
|
Issues: github.com/acmesh-official/acme.sh/issues/4719 |
||||
|
Author: Samuel Jimenez |
||||
|
' |
||||
|
|
||||
|
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 |
||||
|
} |
@ -0,0 +1,251 @@ |
|||||
|
#!/usr/bin/env sh |
||||
|
# shellcheck disable=SC2034 |
||||
|
dns_dnsservices_info='DNS.Services |
||||
|
Site: DNS.Services |
||||
|
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_dnsservices |
||||
|
Options: |
||||
|
DnsServices_Username Username |
||||
|
DnsServices_Password Password |
||||
|
Issues: github.com/acmesh-official/acme.sh/issues/4152 |
||||
|
Author: Bjarke Bruun <bbruun@gmail.com> |
||||
|
' |
||||
|
|
||||
|
DNSServices_API=https://dns.services/api |
||||
|
|
||||
|
######## Public functions ##################### |
||||
|
|
||||
|
#Usage: dns_dnsservices_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" |
||||
|
dns_dnsservices_add() { |
||||
|
fulldomain="$1" |
||||
|
txtvalue="$2" |
||||
|
|
||||
|
_info "Using dns.services to create ACME DNS challenge" |
||||
|
_debug2 add_fulldomain "$fulldomain" |
||||
|
_debug2 add_txtvalue "$txtvalue" |
||||
|
|
||||
|
# Read username/password from environment or .acme.sh/accounts.conf |
||||
|
DnsServices_Username="${DnsServices_Username:-$(_readaccountconf_mutable DnsServices_Username)}" |
||||
|
DnsServices_Password="${DnsServices_Password:-$(_readaccountconf_mutable DnsServices_Password)}" |
||||
|
if [ -z "$DnsServices_Username" ] || [ -z "$DnsServices_Password" ]; then |
||||
|
DnsServices_Username="" |
||||
|
DnsServices_Password="" |
||||
|
_err "You didn't specify dns.services api username and password yet." |
||||
|
_err "Set environment variables DnsServices_Username and DnsServices_Password" |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
# Setup GET/POST/DELETE headers |
||||
|
_setup_headers |
||||
|
|
||||
|
#save the credentials to the account conf file. |
||||
|
_saveaccountconf_mutable DnsServices_Username "$DnsServices_Username" |
||||
|
_saveaccountconf_mutable DnsServices_Password "$DnsServices_Password" |
||||
|
|
||||
|
if ! _contains "$DnsServices_Username" "@"; then |
||||
|
_err "It seems that the username variable DnsServices_Username has not been set/left blank" |
||||
|
_err "or is not a valid email. Please correct and try again." |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
if ! _get_root "${fulldomain}"; then |
||||
|
_err "Invalid domain ${fulldomain}" |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
if ! createRecord "$fulldomain" "${txtvalue}"; then |
||||
|
_err "Error creating TXT record in domain $fulldomain in $rootZoneName" |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
_debug2 challenge-created "Created $fulldomain" |
||||
|
return 0 |
||||
|
} |
||||
|
|
||||
|
#Usage: fulldomain txtvalue |
||||
|
#Description: Remove the txt record after validation. |
||||
|
dns_dnsservices_rm() { |
||||
|
fulldomain="$1" |
||||
|
txtvalue="$2" |
||||
|
|
||||
|
_info "Using dns.services to remove DNS record $fulldomain TXT $txtvalue" |
||||
|
_debug rm_fulldomain "$fulldomain" |
||||
|
_debug rm_txtvalue "$txtvalue" |
||||
|
|
||||
|
# Read username/password from environment or .acme.sh/accounts.conf |
||||
|
DnsServices_Username="${DnsServices_Username:-$(_readaccountconf_mutable DnsServices_Username)}" |
||||
|
DnsServices_Password="${DnsServices_Password:-$(_readaccountconf_mutable DnsServices_Password)}" |
||||
|
if [ -z "$DnsServices_Username" ] || [ -z "$DnsServices_Password" ]; then |
||||
|
DnsServices_Username="" |
||||
|
DnsServices_Password="" |
||||
|
_err "You didn't specify dns.services api username and password yet." |
||||
|
_err "Set environment variables DnsServices_Username and DnsServices_Password" |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
# Setup GET/POST/DELETE headers |
||||
|
_setup_headers |
||||
|
|
||||
|
if ! _get_root "${fulldomain}"; then |
||||
|
_err "Invalid domain ${fulldomain}" |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
_debug2 rm_rootDomainInfo "found root domain $rootZoneName for $fulldomain" |
||||
|
|
||||
|
if ! deleteRecord "${fulldomain}" "${txtvalue}"; then |
||||
|
_err "Error removing record: $fulldomain TXT ${txtvalue}" |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
return 0 |
||||
|
} |
||||
|
|
||||
|
#################### Private functions below ################################## |
||||
|
|
||||
|
_setup_headers() { |
||||
|
# Set up API Headers for _get() and _post() |
||||
|
# The <function>_add or <function>_rm must have been called before to work |
||||
|
|
||||
|
if [ -z "$DnsServices_Username" ] || [ -z "$DnsServices_Password" ]; then |
||||
|
_err "Could not setup BASIC authentication headers, they are missing" |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
DnsServiceCredentials="$(printf "%s" "$DnsServices_Username:$DnsServices_Password" | _base64)" |
||||
|
export _H1="Authorization: Basic $DnsServiceCredentials" |
||||
|
export _H2="Content-Type: application/json" |
||||
|
|
||||
|
# Just return if headers are set |
||||
|
return 0 |
||||
|
} |
||||
|
|
||||
|
_get_root() { |
||||
|
domain="$1" |
||||
|
_debug2 _get_root "Get the root domain of ${domain} for DNS API" |
||||
|
|
||||
|
# Setup _get() and _post() headers |
||||
|
#_setup_headers |
||||
|
|
||||
|
result=$(_H1="$_H1" _H2="$_H2" _get "$DNSServices_API/dns") |
||||
|
result2="$(printf "%s\n" "$result" | tr '[' '\n' | grep '"name"')" |
||||
|
result3="$(printf "%s\n" "$result2" | tr '}' '\n' | grep '"name"' | sed "s,^\,,,g" | sed "s,$,},g")" |
||||
|
useResult="" |
||||
|
_debug2 _get_root "Got the following root domain(s) $result" |
||||
|
_debug2 _get_root "- JSON: $result" |
||||
|
|
||||
|
if [ "$(printf "%s\n" "$result" | tr '}' '\n' | grep -c '"name"')" -gt "1" ]; then |
||||
|
checkMultiZones="true" |
||||
|
_debug2 _get_root "- multiple zones found" |
||||
|
else |
||||
|
checkMultiZones="false" |
||||
|
_debug2 _get_root "- single zone found" |
||||
|
fi |
||||
|
|
||||
|
# Find/isolate the root zone to work with in createRecord() and deleteRecord() |
||||
|
rootZone="" |
||||
|
if [ "$checkMultiZones" = "true" ]; then |
||||
|
#rootZone=$(for x in $(printf "%s" "${result3}" | tr ',' '\n' | sed -n 's/.*"name":"\(.*\)",.*/\1/p'); do if [ "$(echo "$domain" | grep "$x")" != "" ]; then echo "$x"; fi; done) |
||||
|
rootZone=$(for x in $(printf "%s\n" "${result3}" | tr ',' '\n' | grep name | cut -d'"' -f4); do if [ "$(echo "$domain" | grep "$x")" != "" ]; then echo "$x"; fi; done) |
||||
|
if [ "$rootZone" != "" ]; then |
||||
|
_debug2 _rootZone "- root zone for $domain is $rootZone" |
||||
|
else |
||||
|
_err "Could not find root zone for $domain, is it correctly typed?" |
||||
|
return 1 |
||||
|
fi |
||||
|
else |
||||
|
rootZone=$(echo "$result" | tr '}' '\n' | _egrep_o '"name":"[^"]*' | cut -d'"' -f4) |
||||
|
_debug2 _get_root "- only found 1 domain in API: $rootZone" |
||||
|
fi |
||||
|
|
||||
|
if [ -z "$rootZone" ]; then |
||||
|
_err "Could not find root domain for $domain - is it correctly typed?" |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
# Make sure we use the correct API zone data |
||||
|
useResult="$(printf "%s\n" "${result3}" tr ',' '\n' | grep "$rootZone")" |
||||
|
_debug2 _useResult "useResult=$useResult" |
||||
|
|
||||
|
# Setup variables used by other functions to communicate with DNS.Services API |
||||
|
#zoneInfo=$(printf "%s\n" "$useResult" | sed -E 's,.*(zones)(.*),\1\2,g' | sed -E 's,^(.*"name":")([^"]*)"(.*)$,\2,g') |
||||
|
zoneInfo=$(printf "%s\n" "$useResult" | tr ',' '\n' | grep '"name"' | cut -d'"' -f4) |
||||
|
rootZoneName="$rootZone" |
||||
|
subDomainName="$(printf "%s\n" "$domain" | sed "s,\.$rootZone,,g")" |
||||
|
subDomainNameClean="$(printf "%s\n" "$domain" | sed "s,_acme-challenge.,,g")" |
||||
|
rootZoneDomainID=$(printf "%s\n" "$useResult" | tr ',' '\n' | grep domain_id | cut -d'"' -f4) |
||||
|
rootZoneServiceID=$(printf "%s\n" "$useResult" | tr ',' '\n' | grep service_id | cut -d'"' -f4) |
||||
|
|
||||
|
_debug2 _zoneInfo "Zone info from API : $zoneInfo" |
||||
|
_debug2 _get_root "Root zone name : $rootZoneName" |
||||
|
_debug2 _get_root "Root zone domain ID : $rootZoneDomainID" |
||||
|
_debug2 _get_root "Root zone service ID: $rootZoneServiceID" |
||||
|
_debug2 _get_root "Sub domain : $subDomainName" |
||||
|
|
||||
|
_debug _get_root "Found valid root domain $rootZone for $subDomainNameClean" |
||||
|
return 0 |
||||
|
} |
||||
|
|
||||
|
createRecord() { |
||||
|
fulldomain="$1" |
||||
|
txtvalue="$2" |
||||
|
|
||||
|
# Get root domain information - needed for DNS.Services API communication |
||||
|
if [ -z "$rootZoneName" ] || [ -z "$rootZoneDomainID" ] || [ -z "$rootZoneServiceID" ]; then |
||||
|
_get_root "$fulldomain" |
||||
|
fi |
||||
|
if [ -z "$rootZoneName" ] || [ -z "$rootZoneDomainID" ] || [ -z "$rootZoneServiceID" ]; then |
||||
|
_err "Something happend - could not get the API zone information" |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
_debug2 createRecord "CNAME TXT value is: $txtvalue" |
||||
|
|
||||
|
# Prepare data to send to API |
||||
|
data="{\"name\":\"${fulldomain}\",\"type\":\"TXT\",\"content\":\"${txtvalue}\", \"ttl\":\"10\"}" |
||||
|
|
||||
|
_debug2 createRecord "data to API: $data" |
||||
|
result=$(_post "$data" "$DNSServices_API/service/$rootZoneServiceID/dns/$rootZoneDomainID/records" "" "POST") |
||||
|
_debug2 createRecord "result from API: $result" |
||||
|
|
||||
|
if [ "$(echo "$result" | _egrep_o "\"success\":true")" = "" ]; then |
||||
|
_err "Failed to create TXT record $fulldomain with content $txtvalue in zone $rootZoneName" |
||||
|
_err "$result" |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
_info "Record \"$fulldomain TXT $txtvalue\" has been created" |
||||
|
return 0 |
||||
|
} |
||||
|
|
||||
|
deleteRecord() { |
||||
|
fulldomain="$1" |
||||
|
txtvalue="$2" |
||||
|
|
||||
|
_log deleteRecord "Deleting $fulldomain TXT $txtvalue record" |
||||
|
|
||||
|
if [ -z "$rootZoneName" ] || [ -z "$rootZoneDomainID" ] || [ -z "$rootZoneServiceID" ]; then |
||||
|
_get_root "$fulldomain" |
||||
|
fi |
||||
|
|
||||
|
result="$(_H1="$_H1" _H2="$_H2" _get "$DNSServices_API/service/$rootZoneServiceID/dns/$rootZoneDomainID")" |
||||
|
#recordInfo="$(echo "$result" | sed -e 's/:{/:{\n/g' -e 's/},/\n},\n/g' | grep "${txtvalue}")" |
||||
|
#recordID="$(echo "$recordInfo" | sed -e 's/:{/:{\n/g' -e 's/},/\n},\n/g' | grep "${txtvalue}" | sed -E 's,.*(zones)(.*),\1\2,g' | sed -E 's,^(.*"id":")([^"]*)"(.*)$,\2,g')" |
||||
|
recordID="$(printf "%s\n" "$result" | tr '}' '\n' | grep -- "$txtvalue" | tr ',' '\n' | grep '"id"' | cut -d'"' -f4)" |
||||
|
_debug2 _recordID "recordID used for deletion of record: $recordID" |
||||
|
|
||||
|
if [ -z "$recordID" ]; then |
||||
|
_info "Record $fulldomain TXT $txtvalue not found or already deleted" |
||||
|
return 0 |
||||
|
else |
||||
|
_debug2 deleteRecord "Found recordID=$recordID" |
||||
|
fi |
||||
|
|
||||
|
_debug2 deleteRecord "DELETE request $DNSServices_API/service/$rootZoneServiceID/dns/$rootZoneDomainID/records/$recordID" |
||||
|
_log "curl DELETE request $DNSServices_API/service/$rootZoneServiceID/dns/$rootZoneDomainID/records/$recordID" |
||||
|
result="$(_H1="$_H1" _H2="$_H2" _post "" "$DNSServices_API/service/$rootZoneServiceID/dns/$rootZoneDomainID/records/$recordID" "" "DELETE")" |
||||
|
_debug2 deleteRecord "API Delete result \"$result\"" |
||||
|
_log "curl API Delete result \"$result\"" |
||||
|
|
||||
|
# Return OK regardless |
||||
|
return 0 |
||||
|
} |
@ -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' |
|
||||
} |
|
@ -0,0 +1,153 @@ |
|||||
|
#!/usr/bin/env sh |
||||
|
# shellcheck disable=SC2034 |
||||
|
dns_fornex_info='Fornex.com |
||||
|
Site: Fornex.com |
||||
|
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_fornex |
||||
|
Options: |
||||
|
FORNEX_API_KEY API Key |
||||
|
Issues: github.com/acmesh-official/acme.sh/issues/3998 |
||||
|
Author: Timur Umarov <inbox@tumarov.com> |
||||
|
' |
||||
|
|
||||
|
FORNEX_API_URL="https://fornex.com/api/dns/v0.1" |
||||
|
|
||||
|
######## Public functions ##################### |
||||
|
|
||||
|
#Usage: dns_fornex_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" |
||||
|
dns_fornex_add() { |
||||
|
fulldomain=$1 |
||||
|
txtvalue=$2 |
||||
|
|
||||
|
if ! _Fornex_API; then |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
if ! _get_root "$fulldomain"; then |
||||
|
_err "Unable to determine root domain" |
||||
|
return 1 |
||||
|
else |
||||
|
_debug _domain "$_domain" |
||||
|
fi |
||||
|
|
||||
|
_info "Adding record" |
||||
|
if _rest POST "$_domain/entry_set/add/" "host=$fulldomain&type=TXT&value=$txtvalue&apikey=$FORNEX_API_KEY"; then |
||||
|
_debug _response "$response" |
||||
|
if _contains "$response" '"ok": true' || _contains "$response" 'Такая запись уже существует.'; then |
||||
|
_info "Added, OK" |
||||
|
return 0 |
||||
|
fi |
||||
|
fi |
||||
|
_err "Add txt record error." |
||||
|
return 1 |
||||
|
} |
||||
|
|
||||
|
#Usage: dns_fornex_rm _acme-challenge.www.domain.com |
||||
|
dns_fornex_rm() { |
||||
|
fulldomain=$1 |
||||
|
txtvalue=$2 |
||||
|
|
||||
|
if ! _Fornex_API; then |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
if ! _get_root "$fulldomain"; then |
||||
|
_err "Unable to determine root domain" |
||||
|
return 1 |
||||
|
else |
||||
|
_debug _domain "$_domain" |
||||
|
fi |
||||
|
|
||||
|
_debug "Getting txt records" |
||||
|
_rest GET "$_domain/entry_set.json?apikey=$FORNEX_API_KEY" |
||||
|
|
||||
|
if ! _contains "$response" "$txtvalue"; then |
||||
|
_err "Txt record not found" |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
_record_id="$(echo "$response" | _egrep_o "{[^{]*\"value\"*:*\"$txtvalue\"[^}]*}" | sed -n -e 's#.*"id": \([0-9]*\).*#\1#p')" |
||||
|
_debug "_record_id" "$_record_id" |
||||
|
if [ -z "$_record_id" ]; then |
||||
|
_err "can not find _record_id" |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
if ! _rest POST "$_domain/entry_set/$_record_id/delete/" "apikey=$FORNEX_API_KEY"; then |
||||
|
_err "Delete record error." |
||||
|
return 1 |
||||
|
fi |
||||
|
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 |
||||
|
h=$(printf "%s" "$domain" | cut -d . -f $i-100) |
||||
|
_debug h "$h" |
||||
|
if [ -z "$h" ]; then |
||||
|
#not valid |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
if ! _rest GET "domain_list.json?q=$h&apikey=$FORNEX_API_KEY"; then |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
if _contains "$response" "\"$h\"" >/dev/null; then |
||||
|
_domain=$h |
||||
|
return 0 |
||||
|
else |
||||
|
_debug "$h not found" |
||||
|
fi |
||||
|
i=$(_math "$i" + 1) |
||||
|
done |
||||
|
|
||||
|
return 1 |
||||
|
} |
||||
|
|
||||
|
_Fornex_API() { |
||||
|
FORNEX_API_KEY="${FORNEX_API_KEY:-$(_readaccountconf_mutable FORNEX_API_KEY)}" |
||||
|
if [ -z "$FORNEX_API_KEY" ]; then |
||||
|
FORNEX_API_KEY="" |
||||
|
|
||||
|
_err "You didn't specify the Fornex API key yet." |
||||
|
_err "Please create your key and try again." |
||||
|
|
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
_saveaccountconf_mutable FORNEX_API_KEY "$FORNEX_API_KEY" |
||||
|
} |
||||
|
|
||||
|
#method method action data |
||||
|
_rest() { |
||||
|
m=$1 |
||||
|
ep="$2" |
||||
|
data="$3" |
||||
|
_debug "$ep" |
||||
|
|
||||
|
export _H1="Accept: application/json" |
||||
|
|
||||
|
if [ "$m" != "GET" ]; then |
||||
|
_debug data "$data" |
||||
|
response="$(_post "$data" "$FORNEX_API_URL/$ep" "" "$m")" |
||||
|
else |
||||
|
response="$(_get "$FORNEX_API_URL/$ep" | _normalizeJson)" |
||||
|
fi |
||||
|
|
||||
|
_ret="$?" |
||||
|
if [ "$_ret" != "0" ]; then |
||||
|
_err "error $ep" |
||||
|
return 1 |
||||
|
fi |
||||
|
_debug2 response "$response" |
||||
|
return 0 |
||||
|
} |
@ -0,0 +1,191 @@ |
|||||
|
#!/usr/bin/env sh |
||||
|
# shellcheck disable=SC2034 |
||||
|
dns_gcore_info='Gcore.com |
||||
|
Site: Gcore.com |
||||
|
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_gcore |
||||
|
Options: |
||||
|
GCORE_Key API Key |
||||
|
Issues: github.com/acmesh-official/acme.sh/issues/4460 |
||||
|
' |
||||
|
|
||||
|
GCORE_Api="https://api.gcore.com/dns/v2" |
||||
|
GCORE_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 |
||||
|
} |
@ -1,177 +0,0 @@ |
|||||
#!/usr/bin/env sh |
|
||||
#Author: Herman Sletteng |
|
||||
#Report Bugs here: https://github.com/loial/acme.sh |
|
||||
# |
|
||||
# |
|
||||
# Note, gratisdns requires a login first, so the script needs to handle |
|
||||
# temporary cookies. Since acme.sh _get/_post currently don't directly support |
|
||||
# cookies, I've defined wrapper functions _myget/_mypost to set the headers |
|
||||
|
|
||||
GDNSDK_API="https://admin.gratisdns.com" |
|
||||
######## Public functions ##################### |
|
||||
#Usage: dns_gdnsdk_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" |
|
||||
dns_gdnsdk_add() { |
|
||||
fulldomain=$1 |
|
||||
txtvalue=$2 |
|
||||
_info "Using gratisdns.dk" |
|
||||
_debug fulldomain "$fulldomain" |
|
||||
_debug txtvalue "$txtvalue" |
|
||||
if ! _gratisdns_login; then |
|
||||
_err "Login failed!" |
|
||||
return 1 |
|
||||
fi |
|
||||
#finding domain zone |
|
||||
if ! _get_domain; then |
|
||||
_err "No matching root domain for $fulldomain found" |
|
||||
return 1 |
|
||||
fi |
|
||||
# adding entry |
|
||||
_info "Adding the entry" |
|
||||
_mypost "action=dns_primary_record_added_txt&user_domain=$_domain&name=$fulldomain&txtdata=$txtvalue&ttl=1" |
|
||||
if _successful_update; then return 0; fi |
|
||||
_err "Couldn't create entry!" |
|
||||
return 1 |
|
||||
} |
|
||||
|
|
||||
#Usage: fulldomain txtvalue |
|
||||
#Remove the txt record after validation. |
|
||||
dns_gdnsdk_rm() { |
|
||||
fulldomain=$1 |
|
||||
txtvalue=$2 |
|
||||
_info "Using gratisdns.dk" |
|
||||
_debug fulldomain "$fulldomain" |
|
||||
_debug txtvalue "$txtvalue" |
|
||||
if ! _gratisdns_login; then |
|
||||
_err "Login failed!" |
|
||||
return 1 |
|
||||
fi |
|
||||
if ! _get_domain; then |
|
||||
_err "No matching root domain for $fulldomain found" |
|
||||
return 1 |
|
||||
fi |
|
||||
_findentry "$fulldomain" "$txtvalue" |
|
||||
if [ -z "$_id" ]; then |
|
||||
_info "Entry doesn't exist, nothing to delete" |
|
||||
return 0 |
|
||||
fi |
|
||||
_debug "Deleting record..." |
|
||||
_mypost "action=dns_primary_delete_txt&user_domain=$_domain&id=$_id" |
|
||||
# removing entry |
|
||||
|
|
||||
if _successful_update; then return 0; fi |
|
||||
_err "Couldn't delete entry!" |
|
||||
return 1 |
|
||||
} |
|
||||
|
|
||||
#################### Private functions below ################################## |
|
||||
|
|
||||
_checkcredentials() { |
|
||||
GDNSDK_Username="${GDNSDK_Username:-$(_readaccountconf_mutable GDNSDK_Username)}" |
|
||||
GDNSDK_Password="${GDNSDK_Password:-$(_readaccountconf_mutable GDNSDK_Password)}" |
|
||||
|
|
||||
if [ -z "$GDNSDK_Username" ] || [ -z "$GDNSDK_Password" ]; then |
|
||||
GDNSDK_Username="" |
|
||||
GDNSDK_Password="" |
|
||||
_err "You haven't specified gratisdns.dk username and password yet." |
|
||||
_err "Please add credentials and try again." |
|
||||
return 1 |
|
||||
fi |
|
||||
#save the credentials to the account conf file. |
|
||||
_saveaccountconf_mutable GDNSDK_Username "$GDNSDK_Username" |
|
||||
_saveaccountconf_mutable GDNSDK_Password "$GDNSDK_Password" |
|
||||
return 0 |
|
||||
} |
|
||||
|
|
||||
_checkcookie() { |
|
||||
GDNSDK_Cookie="${GDNSDK_Cookie:-$(_readaccountconf_mutable GDNSDK_Cookie)}" |
|
||||
if [ -z "$GDNSDK_Cookie" ]; then |
|
||||
_debug "No cached cookie found" |
|
||||
return 1 |
|
||||
fi |
|
||||
_myget "action=" |
|
||||
if (echo "$_result" | grep -q "logmeout"); then |
|
||||
_debug "Cached cookie still valid" |
|
||||
return 0 |
|
||||
fi |
|
||||
_debug "Cached cookie no longer valid" |
|
||||
GDNSDK_Cookie="" |
|
||||
_saveaccountconf_mutable GDNSDK_Cookie "$GDNSDK_Cookie" |
|
||||
return 1 |
|
||||
} |
|
||||
|
|
||||
_gratisdns_login() { |
|
||||
if ! _checkcredentials; then return 1; fi |
|
||||
|
|
||||
if _checkcookie; then |
|
||||
_debug "Already logged in" |
|
||||
return 0 |
|
||||
fi |
|
||||
_debug "Logging into GratisDNS with user $GDNSDK_Username" |
|
||||
|
|
||||
if ! _mypost "login=$GDNSDK_Username&password=$GDNSDK_Password&action=logmein"; then |
|
||||
_err "GratisDNS login failed for user $GDNSDK_Username bad RC from _post" |
|
||||
return 1 |
|
||||
fi |
|
||||
|
|
||||
GDNSDK_Cookie="$(grep -A 15 '302 Found' "$HTTP_HEADER" | _egrep_o 'Cookie: [^;]*' | _head_n 1 | cut -d ' ' -f2)" |
|
||||
|
|
||||
if [ -z "$GDNSDK_Cookie" ]; then |
|
||||
_err "GratisDNS login failed for user $GDNSDK_Username. Check $HTTP_HEADER file" |
|
||||
return 1 |
|
||||
fi |
|
||||
export GDNSDK_Cookie |
|
||||
_saveaccountconf_mutable GDNSDK_Cookie "$GDNSDK_Cookie" |
|
||||
return 0 |
|
||||
} |
|
||||
|
|
||||
_myget() { |
|
||||
#Adds cookie to request |
|
||||
export _H1="Cookie: $GDNSDK_Cookie" |
|
||||
_result=$(_get "$GDNSDK_API?$1") |
|
||||
} |
|
||||
_mypost() { |
|
||||
#Adds cookie to request |
|
||||
export _H1="Cookie: $GDNSDK_Cookie" |
|
||||
_result=$(_post "$1" "$GDNSDK_API") |
|
||||
} |
|
||||
|
|
||||
_get_domain() { |
|
||||
_myget 'action=dns_primarydns' |
|
||||
_domains=$(echo "$_result" | _egrep_o ' domain="[[:alnum:]._-]+' | sed 's/^.*"//') |
|
||||
if [ -z "$_domains" ]; then |
|
||||
_err "Primary domain list not found!" |
|
||||
return 1 |
|
||||
fi |
|
||||
for _domain in $_domains; do |
|
||||
if (_endswith "$fulldomain" "$_domain"); then |
|
||||
_debug "Root domain: $_domain" |
|
||||
return 0 |
|
||||
fi |
|
||||
done |
|
||||
return 1 |
|
||||
} |
|
||||
|
|
||||
_successful_update() { |
|
||||
if (echo "$_result" | grep -q 'table-success'); then return 0; fi |
|
||||
return 1 |
|
||||
} |
|
||||
|
|
||||
_findentry() { |
|
||||
#args $1: fulldomain, $2: txtvalue |
|
||||
#returns id of dns entry, if it exists |
|
||||
_myget "action=dns_primary_changeDNSsetup&user_domain=$_domain" |
|
||||
_debug3 "_result: $_result" |
|
||||
|
|
||||
_tmp_result=$(echo "$_result" | tr -d '\n\r' | _egrep_o "<td>$1</td>\s*<td>$2</td>[^?]*[^&]*&id=[^&]*") |
|
||||
_debug _tmp_result "$_tmp_result" |
|
||||
if [ -z "${_tmp_result:-}" ]; then |
|
||||
_debug "The variable is _tmp_result is not supposed to be empty, there may be something wrong with the script" |
|
||||
fi |
|
||||
|
|
||||
_id=$(echo "$_tmp_result" | sed 's/^.*=//') |
|
||||
if [ -n "$_id" ]; then |
|
||||
_debug "Entry found with _id=$_id" |
|
||||
return 0 |
|
||||
fi |
|
||||
return 1 |
|
||||
} |
|
@ -0,0 +1,232 @@ |
|||||
|
#!/usr/bin/env sh |
||||
|
# shellcheck disable=SC2034 |
||||
|
dns_geoscaling_info='GeoScaling.com |
||||
|
Site: GeoScaling.com |
||||
|
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_geoscaling |
||||
|
Options: |
||||
|
GEOSCALING_Username Username. This is usually NOT an email address |
||||
|
GEOSCALING_Password Password |
||||
|
' |
||||
|
|
||||
|
#-- dns_geoscaling_add() - Add TXT record -------------------------------------- |
||||
|
# Usage: dns_geoscaling_add _acme-challenge.subdomain.domain.com "XyZ123..." |
||||
|
|
||||
|
dns_geoscaling_add() { |
||||
|
full_domain=$1 |
||||
|
txt_value=$2 |
||||
|
_info "Using DNS-01 Geoscaling DNS2 hook" |
||||
|
|
||||
|
GEOSCALING_Username="${GEOSCALING_Username:-$(_readaccountconf_mutable GEOSCALING_Username)}" |
||||
|
GEOSCALING_Password="${GEOSCALING_Password:-$(_readaccountconf_mutable GEOSCALING_Password)}" |
||||
|
if [ -z "$GEOSCALING_Username" ] || [ -z "$GEOSCALING_Password" ]; then |
||||
|
GEOSCALING_Username= |
||||
|
GEOSCALING_Password= |
||||
|
_err "No auth details provided. Please set user credentials using the \$GEOSCALING_Username and \$GEOSCALING_Password environment variables." |
||||
|
return 1 |
||||
|
fi |
||||
|
_saveaccountconf_mutable GEOSCALING_Username "${GEOSCALING_Username}" |
||||
|
_saveaccountconf_mutable GEOSCALING_Password "${GEOSCALING_Password}" |
||||
|
|
||||
|
# Fills in the $zone_id and $zone_name |
||||
|
find_zone "${full_domain}" || return 1 |
||||
|
_debug "Zone id '${zone_id}' will be used." |
||||
|
|
||||
|
# We're logged in here |
||||
|
|
||||
|
# we should add ${full_domain} minus the trailing ${zone_name} |
||||
|
|
||||
|
prefix=$(echo "${full_domain}" | sed "s|\\.${zone_name}\$||") |
||||
|
|
||||
|
body="id=${zone_id}&name=${prefix}&type=TXT&content=${txt_value}&ttl=300&prio=0" |
||||
|
|
||||
|
do_post "$body" "https://www.geoscaling.com/dns2/ajax/add_record.php" |
||||
|
exit_code="$?" |
||||
|
if [ "${exit_code}" -eq 0 ]; then |
||||
|
_info "TXT record added successfully." |
||||
|
else |
||||
|
_err "Couldn't add the TXT record." |
||||
|
fi |
||||
|
do_logout |
||||
|
return "${exit_code}" |
||||
|
} |
||||
|
|
||||
|
#-- dns_geoscaling_rm() - Remove TXT record ------------------------------------ |
||||
|
# Usage: dns_geoscaling_rm _acme-challenge.subdomain.domain.com "XyZ123..." |
||||
|
|
||||
|
dns_geoscaling_rm() { |
||||
|
full_domain=$1 |
||||
|
txt_value=$2 |
||||
|
_info "Cleaning up after DNS-01 Geoscaling DNS2 hook" |
||||
|
|
||||
|
GEOSCALING_Username="${GEOSCALING_Username:-$(_readaccountconf_mutable GEOSCALING_Username)}" |
||||
|
GEOSCALING_Password="${GEOSCALING_Password:-$(_readaccountconf_mutable GEOSCALING_Password)}" |
||||
|
if [ -z "$GEOSCALING_Username" ] || [ -z "$GEOSCALING_Password" ]; then |
||||
|
GEOSCALING_Username= |
||||
|
GEOSCALING_Password= |
||||
|
_err "No auth details provided. Please set user credentials using the \$GEOSCALING_Username and \$GEOSCALING_Password environment variables." |
||||
|
return 1 |
||||
|
fi |
||||
|
_saveaccountconf_mutable GEOSCALING_Username "${GEOSCALING_Username}" |
||||
|
_saveaccountconf_mutable GEOSCALING_Password "${GEOSCALING_Password}" |
||||
|
|
||||
|
# fills in the $zone_id |
||||
|
find_zone "${full_domain}" || return 1 |
||||
|
_debug "Zone id '${zone_id}' will be used." |
||||
|
|
||||
|
# Here we're logged in |
||||
|
# Find the record id to clean |
||||
|
|
||||
|
# get the domain |
||||
|
response=$(do_get "https://www.geoscaling.com/dns2/index.php?module=domain&id=${zone_id}") |
||||
|
_debug2 "response" "$response" |
||||
|
|
||||
|
table="$(echo "${response}" | tr -d '\n' | sed 's|.*<div class="box"><div class="boxtitle">Basic Records</div><div class="boxtext"><table|<table|; s|</table>.*|</table>|')" |
||||
|
_debug2 table "${table}" |
||||
|
names=$(echo "${table}" | _egrep_o 'id="[0-9]+\.name">[^<]*</td>' | sed 's|</td>||; s|.*>||') |
||||
|
ids=$(echo "${table}" | _egrep_o 'id="[0-9]+\.name">[^<]*</td>' | sed 's|\.name">.*||; s|id="||') |
||||
|
types=$(echo "${table}" | _egrep_o 'id="[0-9]+\.type">[^<]*</td>' | sed 's|</td>||; s|.*>||') |
||||
|
values=$(echo "${table}" | _egrep_o 'id="[0-9]+\.content">[^<]*</td>' | sed 's|</td>||; s|.*>||') |
||||
|
|
||||
|
_debug2 names "${names}" |
||||
|
_debug2 ids "${ids}" |
||||
|
_debug2 types "${types}" |
||||
|
_debug2 values "${values}" |
||||
|
|
||||
|
# look for line whose name is ${full_domain}, whose type is TXT, and whose value is ${txt_value} |
||||
|
line_num="$(echo "${values}" | grep -F -n -- "${txt_value}" | _head_n 1 | cut -d ':' -f 1)" |
||||
|
_debug2 line_num "${line_num}" |
||||
|
found_id= |
||||
|
if [ -n "$line_num" ]; then |
||||
|
type=$(echo "${types}" | sed -n "${line_num}p") |
||||
|
name=$(echo "${names}" | sed -n "${line_num}p") |
||||
|
id=$(echo "${ids}" | sed -n "${line_num}p") |
||||
|
|
||||
|
_debug2 type "$type" |
||||
|
_debug2 name "$name" |
||||
|
_debug2 id "$id" |
||||
|
_debug2 full_domain "$full_domain" |
||||
|
|
||||
|
if [ "${type}" = "TXT" ] && [ "${name}" = "${full_domain}" ]; then |
||||
|
found_id=${id} |
||||
|
fi |
||||
|
fi |
||||
|
|
||||
|
if [ "${found_id}" = "" ]; then |
||||
|
_err "Can not find record id." |
||||
|
return 0 |
||||
|
fi |
||||
|
|
||||
|
# Remove the record |
||||
|
body="id=${zone_id}&record_id=${found_id}" |
||||
|
response=$(do_post "$body" "https://www.geoscaling.com/dns2/ajax/delete_record.php") |
||||
|
exit_code="$?" |
||||
|
if [ "$exit_code" -eq 0 ]; then |
||||
|
_info "Record removed successfully." |
||||
|
else |
||||
|
_err "Could not clean (remove) up the record. Please go to Geoscaling administration interface and clean it by hand." |
||||
|
fi |
||||
|
do_logout |
||||
|
return "${exit_code}" |
||||
|
} |
||||
|
|
||||
|
########################## PRIVATE FUNCTIONS ########################### |
||||
|
|
||||
|
do_get() { |
||||
|
_url=$1 |
||||
|
export _H1="Cookie: $geoscaling_phpsessid_cookie" |
||||
|
_get "${_url}" |
||||
|
} |
||||
|
|
||||
|
do_post() { |
||||
|
_body=$1 |
||||
|
_url=$2 |
||||
|
export _H1="Cookie: $geoscaling_phpsessid_cookie" |
||||
|
_post "${_body}" "${_url}" |
||||
|
} |
||||
|
|
||||
|
do_login() { |
||||
|
|
||||
|
_info "Logging in..." |
||||
|
|
||||
|
username_encoded="$(printf "%s" "${GEOSCALING_Username}" | _url_encode)" |
||||
|
password_encoded="$(printf "%s" "${GEOSCALING_Password}" | _url_encode)" |
||||
|
body="username=${username_encoded}&password=${password_encoded}" |
||||
|
|
||||
|
response=$(_post "$body" "https://www.geoscaling.com/dns2/index.php?module=auth") |
||||
|
_debug2 response "${response}" |
||||
|
|
||||
|
#retcode=$(grep '^HTTP[^ ]*' "${HTTP_HEADER}" | _head_n 1 | _egrep_o '[0-9]+$') |
||||
|
retcode=$(grep '^HTTP[^ ]*' "${HTTP_HEADER}" | _head_n 1 | cut -d ' ' -f 2) |
||||
|
|
||||
|
if [ "$retcode" != "302" ]; then |
||||
|
_err "Geoscaling login failed for user ${GEOSCALING_Username}. Check ${HTTP_HEADER} file" |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
geoscaling_phpsessid_cookie="$(grep -i '^set-cookie:' "${HTTP_HEADER}" | _egrep_o 'PHPSESSID=[^;]*;' | tr -d ';')" |
||||
|
return 0 |
||||
|
|
||||
|
} |
||||
|
|
||||
|
do_logout() { |
||||
|
_info "Logging out." |
||||
|
response="$(do_get "https://www.geoscaling.com/dns2/index.php?module=auth")" |
||||
|
_debug2 response "$response" |
||||
|
return 0 |
||||
|
} |
||||
|
|
||||
|
find_zone() { |
||||
|
domain="$1" |
||||
|
|
||||
|
# do login |
||||
|
do_login || return 1 |
||||
|
|
||||
|
# get zones |
||||
|
response="$(do_get "https://www.geoscaling.com/dns2/index.php?module=domains")" |
||||
|
|
||||
|
table="$(echo "${response}" | tr -d '\n' | sed 's|.*<div class="box"><div class="boxtitle">Your domains</div><div class="boxtext"><table|<table|; s|</table>.*|</table>|')" |
||||
|
_debug2 table "${table}" |
||||
|
zone_names="$(echo "${table}" | _egrep_o '<b>[^<]*</b>' | sed 's|<b>||;s|</b>||')" |
||||
|
_debug2 _matches "${zone_names}" |
||||
|
# Zone names and zone IDs are in same order |
||||
|
zone_ids=$(echo "${table}" | _egrep_o '<a href=.index\.php\?module=domain&id=[0-9]+. onclick="javascript:show_loader\(\);">' | sed 's|.*id=||;s|. .*||') |
||||
|
|
||||
|
_debug2 "These are the zones on this Geoscaling account:" |
||||
|
_debug2 "zone_names" "${zone_names}" |
||||
|
_debug2 "And these are their respective IDs:" |
||||
|
_debug2 "zone_ids" "${zone_ids}" |
||||
|
if [ -z "${zone_names}" ] || [ -z "${zone_ids}" ]; then |
||||
|
_err "Can not get zone names or IDs." |
||||
|
return 1 |
||||
|
fi |
||||
|
# Walk through all possible zone names |
||||
|
strip_counter=1 |
||||
|
while true; do |
||||
|
attempted_zone=$(echo "${domain}" | cut -d . -f ${strip_counter}-) |
||||
|
|
||||
|
# All possible zone names have been tried |
||||
|
if [ -z "${attempted_zone}" ]; then |
||||
|
_err "No zone for domain '${domain}' found." |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
_debug "Looking for zone '${attempted_zone}'" |
||||
|
|
||||
|
line_num="$(echo "${zone_names}" | grep -n "^${attempted_zone}\$" | _head_n 1 | cut -d : -f 1)" |
||||
|
_debug2 line_num "${line_num}" |
||||
|
if [ "$line_num" ]; then |
||||
|
zone_id=$(echo "${zone_ids}" | sed -n "${line_num}p") |
||||
|
zone_name=$(echo "${zone_names}" | sed -n "${line_num}p") |
||||
|
if [ -z "${zone_id}" ]; then |
||||
|
_err "Can not find zone id." |
||||
|
return 1 |
||||
|
fi |
||||
|
_debug "Found relevant zone '${attempted_zone}' with id '${zone_id}' - will be used for domain '${domain}'." |
||||
|
return 0 |
||||
|
fi |
||||
|
|
||||
|
_debug "Zone '${attempted_zone}' doesn't exist, let's try a less specific zone." |
||||
|
strip_counter=$(_math "${strip_counter}" + 1) |
||||
|
done |
||||
|
} |
||||
|
# vim: et:ts=2:sw=2: |
@ -0,0 +1,178 @@ |
|||||
|
#!/usr/bin/env sh |
||||
|
# shellcheck disable=SC2034 |
||||
|
dns_googledomains_info='Google Domains |
||||
|
Site: Domains.Google.com |
||||
|
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_googledomains |
||||
|
Options: |
||||
|
GOOGLEDOMAINS_ACCESS_TOKEN API Access Token |
||||
|
GOOGLEDOMAINS_ZONE Zone |
||||
|
Issues: github.com/acmesh-official/acme.sh/issues/4545 |
||||
|
Author: Alex Leigh <leigh@alexleigh.me> |
||||
|
' |
||||
|
|
||||
|
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 |
||||
|
} |
Some files were not shown because too many files changed in this diff
Write
Preview
Loading…
Cancel
Save
Reference in new issue