diff --git a/.github/workflows/DNS.yml b/.github/workflows/DNS.yml index 0104595d..00d180b9 100644 --- a/.github/workflows/DNS.yml +++ b/.github/workflows/DNS.yml @@ -229,6 +229,7 @@ jobs: run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - uses: vmactions/freebsd-vm@v1 with: + debug-on-error: ${{ vars.DEBUG_ON_ERROR }} 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 @@ -284,6 +285,7 @@ jobs: run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - uses: vmactions/openbsd-vm@v1 with: + debug-on-error: ${{ vars.DEBUG_ON_ERROR }} 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 libiconv usesh: true @@ -339,6 +341,7 @@ jobs: run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - uses: vmactions/netbsd-vm@v1 with: + debug-on-error: ${{ vars.DEBUG_ON_ERROR }} 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 @@ -395,6 +398,7 @@ jobs: run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - uses: vmactions/dragonflybsd-vm@v1 with: + debug-on-error: ${{ vars.DEBUG_ON_ERROR }} 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 libnghttp2 @@ -430,9 +434,65 @@ jobs: - Solaris: + MidnightBSD: 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 }} + TokenName1: ${{ secrets.TokenName1}} + TokenName2: ${{ secrets.TokenName2}} + TokenName3: ${{ secrets.TokenName3}} + TokenName4: ${{ secrets.TokenName4}} + TokenName5: ${{ secrets.TokenName5}} + steps: + - uses: actions/checkout@v6 + - name: Clone acmetest + run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ + - uses: vmactions/midnightbsd-vm@v1 + with: + debug-on-error: ${{ vars.DEBUG_ON_ERROR }} + 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: mport install socat curl || true + usesh: true + sync: nfs + 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 + - name: DebugOnError + if: ${{ failure() }} + run: | + echo "See how to debug in VM:" + echo "https://github.com/acmesh-official/acme.sh/wiki/debug-in-VM" + + + + Solaris: + runs-on: ubuntu-latest + needs: MidnightBSD env: TEST_DNS : ${{ secrets.TEST_DNS }} TestingDomain: ${{ secrets.TestingDomain }} @@ -456,6 +516,7 @@ jobs: run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - uses: vmactions/solaris-vm@v1 with: + debug-on-error: ${{ vars.DEBUG_ON_ERROR }} 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}}' sync: nfs prepare: | @@ -514,6 +575,7 @@ jobs: run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - uses: vmactions/omnios-vm@v1 with: + debug-on-error: ${{ vars.DEBUG_ON_ERROR }} 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}}' sync: nfs prepare: pkg install socat @@ -569,6 +631,7 @@ jobs: run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - uses: vmactions/openindiana-vm@v1 with: + debug-on-error: ${{ vars.DEBUG_ON_ERROR }} 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}}' sync: nfs prepare: pkg install socat @@ -624,6 +687,7 @@ jobs: run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - uses: vmactions/haiku-vm@v1 with: + debug-on-error: ${{ vars.DEBUG_ON_ERROR }} 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}}' sync: rsync copyback: false diff --git a/.github/workflows/DragonFlyBSD.yml b/.github/workflows/DragonFlyBSD.yml index f32d0916..c8cbc985 100644 --- a/.github/workflows/DragonFlyBSD.yml +++ b/.github/workflows/DragonFlyBSD.yml @@ -31,8 +31,8 @@ jobs: 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_ECDSA: "ZeroSSL ECC DV SSL CA 2" + # CA: "ZeroSSL RSA DV SSL CA 2" # CA_EMAIL: "githubtest@acme.sh" # TEST_PREFERRED_CHAIN: "" runs-on: ubuntu-latest @@ -57,6 +57,7 @@ jobs: run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - uses: vmactions/dragonflybsd-vm@v1 with: + debug-on-error: ${{ vars.DEBUG_ON_ERROR }} envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN ACME_USE_WGET' nat: | "8080": "80" diff --git a/.github/workflows/FreeBSD.yml b/.github/workflows/FreeBSD.yml index 09b544f6..50fcab32 100644 --- a/.github/workflows/FreeBSD.yml +++ b/.github/workflows/FreeBSD.yml @@ -37,8 +37,8 @@ jobs: 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_ECDSA: "ZeroSSL ECC DV SSL CA 2" + # CA: "ZeroSSL RSA DV SSL CA 2" # CA_EMAIL: "githubtest@acme.sh" # TEST_PREFERRED_CHAIN: "" runs-on: ubuntu-latest @@ -63,6 +63,7 @@ jobs: run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - uses: vmactions/freebsd-vm@v1 with: + debug-on-error: ${{ vars.DEBUG_ON_ERROR }} envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN ACME_USE_WGET' nat: | "8080": "80" diff --git a/.github/workflows/Haiku.yml b/.github/workflows/Haiku.yml index 4324545e..9884ebeb 100644 --- a/.github/workflows/Haiku.yml +++ b/.github/workflows/Haiku.yml @@ -38,8 +38,8 @@ jobs: 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_ECDSA: "ZeroSSL ECC DV SSL CA 2" + # CA: "ZeroSSL RSA DV SSL CA 2" # CA_EMAIL: "githubtest@acme.sh" # TEST_PREFERRED_CHAIN: "" runs-on: ubuntu-latest @@ -64,6 +64,7 @@ jobs: run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - uses: vmactions/haiku-vm@v1 with: + debug-on-error: ${{ vars.DEBUG_ON_ERROR }} envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN ACME_USE_WGET' nat: | "8080": "80" diff --git a/.github/workflows/MacOS.yml b/.github/workflows/MacOS.yml index 3869b504..ef9580a6 100644 --- a/.github/workflows/MacOS.yml +++ b/.github/workflows/MacOS.yml @@ -31,8 +31,8 @@ jobs: 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_ECDSA: "ZeroSSL ECC DV SSL CA 2" + # CA: "ZeroSSL RSA DV SSL CA 2" # CA_EMAIL: "githubtest@acme.sh" # TEST_PREFERRED_CHAIN: "" runs-on: macos-latest diff --git a/.github/workflows/MidnightBSD.yml b/.github/workflows/MidnightBSD.yml new file mode 100644 index 00000000..15024833 --- /dev/null +++ b/.github/workflows/MidnightBSD.yml @@ -0,0 +1,74 @@ +name: MidnightBSD +on: + push: + branches: + - '*' + paths: + - '*.sh' + - '.github/workflows/MidnightBSD.yml' + + pull_request: + branches: + - dev + paths: + - '*.sh' + - '.github/workflows/MidnightBSD.yml' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + + + +jobs: + MidnightBSD: + 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 DV SSL CA 2" + # CA: "ZeroSSL RSA DV SSL CA 2" + # 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@v6 + - uses: anyvm-org/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/midnightbsd-vm@v1 + with: + debug-on-error: ${{ vars.DEBUG_ON_ERROR }} + envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN ACME_USE_WGET' + nat: | + "8080": "80" + prepare: mport install socat curl wget || true + usesh: true + sync: nfs + run: | + cd ../acmetest \ + && ./letest.sh + - name: DebugOnError + if: ${{ failure() }} + run: | + echo "See how to debug in VM:" + echo "https://github.com/acmesh-official/acme.sh/wiki/debug-in-VM" diff --git a/.github/workflows/NetBSD.yml b/.github/workflows/NetBSD.yml index 4021cd7e..16d0ae2d 100644 --- a/.github/workflows/NetBSD.yml +++ b/.github/workflows/NetBSD.yml @@ -31,8 +31,8 @@ jobs: 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_ECDSA: "ZeroSSL ECC DV SSL CA 2" + # CA: "ZeroSSL RSA DV SSL CA 2" # CA_EMAIL: "githubtest@acme.sh" # TEST_PREFERRED_CHAIN: "" runs-on: ubuntu-latest @@ -57,6 +57,7 @@ jobs: run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - uses: vmactions/netbsd-vm@v1 with: + debug-on-error: ${{ vars.DEBUG_ON_ERROR }} envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN ACME_USE_WGET' nat: | "8080": "80" diff --git a/.github/workflows/Omnios.yml b/.github/workflows/Omnios.yml index a156800c..eb486b35 100644 --- a/.github/workflows/Omnios.yml +++ b/.github/workflows/Omnios.yml @@ -37,8 +37,8 @@ jobs: 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_ECDSA: "ZeroSSL ECC DV SSL CA 2" + # CA: "ZeroSSL RSA DV SSL CA 2" # CA_EMAIL: "githubtest@acme.sh" # TEST_PREFERRED_CHAIN: "" runs-on: ubuntu-latest @@ -63,6 +63,7 @@ jobs: run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - uses: vmactions/omnios-vm@v1 with: + debug-on-error: ${{ vars.DEBUG_ON_ERROR }} envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN ACME_USE_WGET' nat: | "8080": "80" diff --git a/.github/workflows/OpenBSD.yml b/.github/workflows/OpenBSD.yml index 8a91cd2e..4fdb76c5 100644 --- a/.github/workflows/OpenBSD.yml +++ b/.github/workflows/OpenBSD.yml @@ -37,8 +37,8 @@ jobs: 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_ECDSA: "ZeroSSL ECC DV SSL CA 2" + # CA: "ZeroSSL RSA DV SSL CA 2" # CA_EMAIL: "githubtest@acme.sh" # TEST_PREFERRED_CHAIN: "" runs-on: ubuntu-latest @@ -63,6 +63,7 @@ jobs: run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - uses: vmactions/openbsd-vm@v1 with: + debug-on-error: ${{ vars.DEBUG_ON_ERROR }} envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN ACME_USE_WGET' nat: | "8080": "80" diff --git a/.github/workflows/OpenIndiana.yml b/.github/workflows/OpenIndiana.yml index dca29741..b5061ba7 100644 --- a/.github/workflows/OpenIndiana.yml +++ b/.github/workflows/OpenIndiana.yml @@ -37,8 +37,8 @@ jobs: 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_ECDSA: "ZeroSSL ECC DV SSL CA 2" + # CA: "ZeroSSL RSA DV SSL CA 2" # CA_EMAIL: "githubtest@acme.sh" # TEST_PREFERRED_CHAIN: "" runs-on: ubuntu-latest @@ -63,6 +63,7 @@ jobs: run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - uses: vmactions/openindiana-vm@v1 with: + debug-on-error: ${{ vars.DEBUG_ON_ERROR }} envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN ACME_USE_WGET' nat: | "8080": "80" diff --git a/.github/workflows/Solaris.yml b/.github/workflows/Solaris.yml index 397469b5..3393269a 100644 --- a/.github/workflows/Solaris.yml +++ b/.github/workflows/Solaris.yml @@ -37,8 +37,8 @@ jobs: 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_ECDSA: "ZeroSSL ECC DV SSL CA 2" + # CA: "ZeroSSL RSA DV SSL CA 2" # CA_EMAIL: "githubtest@acme.sh" # TEST_PREFERRED_CHAIN: "" runs-on: ubuntu-latest @@ -63,6 +63,7 @@ jobs: run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - uses: vmactions/solaris-vm@v1 with: + debug-on-error: ${{ vars.DEBUG_ON_ERROR }} envs: 'TEST_LOCAL TestingDomain TEST_ACME_Server CA_ECDSA CA CA_EMAIL TEST_PREFERRED_CHAIN ACME_USE_WGET' nat: | "8080": "80" diff --git a/.github/workflows/Ubuntu.yml b/.github/workflows/Ubuntu.yml index 5ebf2d0d..36dfdbe6 100644 --- a/.github/workflows/Ubuntu.yml +++ b/.github/workflows/Ubuntu.yml @@ -37,8 +37,8 @@ jobs: 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_ECDSA: "ZeroSSL ECC DV SSL CA 2" + CA: "ZeroSSL RSA DV SSL CA 2" CA_EMAIL: "githubtest@acme.sh" TEST_PREFERRED_CHAIN: "" - TEST_ACME_Server: "https://localhost:9000/acme/acme/directory" diff --git a/.github/workflows/Windows.yml b/.github/workflows/Windows.yml index c628ff5b..1de120f9 100644 --- a/.github/workflows/Windows.yml +++ b/.github/workflows/Windows.yml @@ -31,8 +31,8 @@ jobs: 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_ECDSA: "ZeroSSL ECC DV SSL CA 2" + # CA: "ZeroSSL RSA DV SSL CA 2" # CA_EMAIL: "githubtest@acme.sh" # TEST_PREFERRED_CHAIN: "" runs-on: windows-latest diff --git a/README.md b/README.md index 740e5ef0..188af0e1 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ Windows Solaris DragonFlyBSD + MidnightBSD Omnios OpenIndiana Haiku @@ -95,21 +96,22 @@ |7|[![OpenBSD](https://github.com/acmesh-official/acme.sh/actions/workflows/OpenBSD.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/OpenBSD.yml)|OpenBSD |8|[![NetBSD](https://github.com/acmesh-official/acme.sh/actions/workflows/NetBSD.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/NetBSD.yml)|NetBSD |9|[![DragonFlyBSD](https://github.com/acmesh-official/acme.sh/actions/workflows/DragonFlyBSD.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/DragonFlyBSD.yml)|DragonFlyBSD -|10|[![Omnios](https://github.com/acmesh-official/acme.sh/actions/workflows/Omnios.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Omnios.yml)|Omnios -|11|[![OpenIndiana](https://github.com/acmesh-official/acme.sh/actions/workflows/OpenIndiana.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/OpenIndiana.yml)|OpenIndiana -|12|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)| Debian -|13|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|openSUSE -|14|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Alpine Linux (with curl) -|15|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Archlinux -|16|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|fedora -|17|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Kali Linux -|18|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Oracle Linux -|19|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Mageia -|20|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Gentoo Linux -|21|-----| Cloud Linux https://github.com/acmesh-official/acme.sh/issues/111 -|22|-----| OpenWRT: Tested and working. See [wiki page](https://github.com/acmesh-official/acme.sh/wiki/How-to-run-on-OpenWRT) -|23|[![](https://acmesh-official.github.io/acmetest/status/proxmox.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)| Proxmox: See Proxmox VE Wiki. Version [4.x, 5.0, 5.1](https://pve.proxmox.com/wiki/HTTPS_Certificate_Configuration_(Version_4.x,_5.0_and_5.1)#Let.27s_Encrypt_using_acme.sh), version [5.2 and up](https://pve.proxmox.com/wiki/Certificate_Management) -|24|[![Haiku](https://github.com/acmesh-official/acme.sh/actions/workflows/Haiku.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Haiku.yml)|Haiku OS +|10|[![MidnightBSD](https://github.com/acmesh-official/acme.sh/actions/workflows/MidnightBSD.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/MidnightBSD.yml)|MidnightBSD +|11|[![Omnios](https://github.com/acmesh-official/acme.sh/actions/workflows/Omnios.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Omnios.yml)|Omnios +|12|[![OpenIndiana](https://github.com/acmesh-official/acme.sh/actions/workflows/OpenIndiana.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/OpenIndiana.yml)|OpenIndiana +|13|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)| Debian +|14|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|openSUSE +|15|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Alpine Linux (with curl) +|16|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Archlinux +|17|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|fedora +|18|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Kali Linux +|19|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Oracle Linux +|20|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Mageia +|21|[![Linux](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Linux.yml)|Gentoo Linux +|22|-----| Cloud Linux https://github.com/acmesh-official/acme.sh/issues/111 +|23|-----| OpenWRT: Tested and working. See [wiki page](https://github.com/acmesh-official/acme.sh/wiki/How-to-run-on-OpenWRT) +|24|[![](https://acmesh-official.github.io/acmetest/status/proxmox.svg)](https://github.com/acmesh-official/letest#here-are-the-latest-status)| Proxmox: See Proxmox VE Wiki. Version [4.x, 5.0, 5.1](https://pve.proxmox.com/wiki/HTTPS_Certificate_Configuration_(Version_4.x,_5.0_and_5.1)#Let.27s_Encrypt_using_acme.sh), version [5.2 and up](https://pve.proxmox.com/wiki/Certificate_Management) +|25|[![Haiku](https://github.com/acmesh-official/acme.sh/actions/workflows/Haiku.yml/badge.svg)](https://github.com/acmesh-official/acme.sh/actions/workflows/Haiku.yml)|Haiku OS > ๐Ÿงช Check our [testing project](https://github.com/acmesh-official/acmetest) diff --git a/deploy/byteplus_alb.sh b/deploy/byteplus_alb.sh new file mode 100644 index 00000000..8443bb99 --- /dev/null +++ b/deploy/byteplus_alb.sh @@ -0,0 +1,394 @@ +#!/usr/bin/env sh +# shellcheck disable=SC2034,SC2154 +# +# acme.sh deploy hook: BytePlus Application Load Balancer (ALB) +# https://github.com/acmesh-official/acme.sh/wiki/deployhooks +# +# Deploys SSL/TLS certificates issued by acme.sh to BytePlus ALB. +# Supports automatic renewal with zero-downtime certificate rotation +# for certificates that have already been uploaded and have a saved +# BytePlus CertificateId. +# +# โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +# โ”‚ FIRST TIME (new domain) โ”‚ +# โ”‚ 1. acme.sh --issue -d example.com -w /var/www/html/ โ”‚ +# โ”‚ 2. Upload/import the certificate to BytePlus ALB manually โ”‚ +# โ”‚ 3. Save/configure the existing CertificateId for this hook โ”‚ +# โ”‚ 4. Manually assign cert to ALB Listener (one-time only) โ”‚ +# โ”‚ โ”‚ +# โ”‚ RENEWAL (fully automatic after CertificateId is configured) โ”‚ +# โ”‚ acme.sh cron triggers renew โ†’ deploy hook runs automatically โ”‚ +# โ”‚ โ†’ ReplaceCertificate (UpdateMode=new) โ€” single API call โ”‚ +# โ”‚ โ†’ All attached listeners updated, old cert auto-deleted โ”‚ +# โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +# +# Required environment variables: +# export BYTEPLUS_ACCESS_KEY="AKAPxxxxxxxxxx" +# export BYTEPLUS_SECRET_KEY="your-secret-key" +# +# Optional environment variables: +# export BYTEPLUS_REGION="ap-southeast-3" # default: ap-southeast-3 +# export BYTEPLUS_HOST="alb.ap-southeast-3.byteplusapi.com" # custom API host +# export BYTEPLUS_PROJECT_NAME="live" # default: "default" project +# export BYTEPLUS_CERT_NAME="" # default: acme-{domain}-{YYYYMMDD-HHMM} +# export BYTEPLUS_CERT_DESCRIPTION="" # default: empty +# export BYTEPLUS_DELETE_OLD_CERT="true" # default: true โ€” auto-delete after replace +# +# API notes: +# - All BytePlus ALB APIs use GET with query string parameters +# - Request signing: HMAC-SHA256 with signed headers host;x-date +# - PublicKey/PrivateKey are URL-encoded (RFC 3986) in query string +# - ReplaceCertificate with UpdateMode=new uploads + replaces in 1 call +# +# Dependencies: curl, openssl, awk (standard on most Linux) +# +# Docs: +# Signing โ€” https://docs.byteplus.com/en/docs/byteplus-platform/reference-how-to-calculate-a-signature +# ALB API โ€” https://docs.byteplus.com/en/docs/byteplus-alb + +# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• +# Constants +# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• + +# SHA-256 hash of empty string (used for GET requests with no body) +_BYTEPLUS_EMPTY_HASH="e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + +# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• +# Main deploy function โ€” called by acme.sh +# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• + +byteplus_alb_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" + + # โ”€โ”€ 1. Load & validate credentials โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + + # Preserve environment values before _getdeployconf (which may reset them) + _env_project_name="${BYTEPLUS_PROJECT_NAME:-}" + _env_delete_old="${BYTEPLUS_DELETE_OLD_CERT:-}" + + _getdeployconf BYTEPLUS_ACCESS_KEY + _getdeployconf BYTEPLUS_SECRET_KEY + _getdeployconf BYTEPLUS_REGION + _getdeployconf BYTEPLUS_HOST + _getdeployconf BYTEPLUS_PROJECT_NAME + _getdeployconf BYTEPLUS_DELETE_OLD_CERT + _getdeployconf BYTEPLUS_CERT_NAME + + # Restore from environment if _getdeployconf cleared them + if [ -z "$BYTEPLUS_PROJECT_NAME" ] && [ -n "$_env_project_name" ]; then + _debug "Restoring BYTEPLUS_PROJECT_NAME from environment" + BYTEPLUS_PROJECT_NAME="$_env_project_name" + fi + if [ -z "$BYTEPLUS_DELETE_OLD_CERT" ] && [ -n "$_env_delete_old" ]; then + BYTEPLUS_DELETE_OLD_CERT="$_env_delete_old" + fi + + # Validate required credentials + if [ -z "$BYTEPLUS_ACCESS_KEY" ]; then + _err "BYTEPLUS_ACCESS_KEY is not set." + _err "Please run: export BYTEPLUS_ACCESS_KEY=\"your-access-key\"" + return 1 + fi + if [ -z "$BYTEPLUS_SECRET_KEY" ]; then + _err "BYTEPLUS_SECRET_KEY is not set." + _err "Please run: export BYTEPLUS_SECRET_KEY=\"your-secret-key\"" + return 1 + fi + + # Save credentials for future runs + _savedeployconf BYTEPLUS_ACCESS_KEY "$BYTEPLUS_ACCESS_KEY" + _savedeployconf BYTEPLUS_SECRET_KEY "$BYTEPLUS_SECRET_KEY" + + # Region (default: ap-southeast-3) + BYTEPLUS_REGION="${BYTEPLUS_REGION:-ap-southeast-3}" + _savedeployconf BYTEPLUS_REGION "$BYTEPLUS_REGION" + + # Project name + if [ -n "$BYTEPLUS_PROJECT_NAME" ]; then + _savedeployconf BYTEPLUS_PROJECT_NAME "$BYTEPLUS_PROJECT_NAME" + _info "Using project: $BYTEPLUS_PROJECT_NAME" + else + _info "WARNING: BYTEPLUS_PROJECT_NAME is not set. Cert will go to 'default' project." + fi + + # Delete old cert toggle (default: true) + BYTEPLUS_DELETE_OLD_CERT="${BYTEPLUS_DELETE_OLD_CERT:-true}" + _savedeployconf BYTEPLUS_DELETE_OLD_CERT "$BYTEPLUS_DELETE_OLD_CERT" + + # API host โ€” custom override or auto-build from region + if [ -n "$BYTEPLUS_HOST" ]; then + _BYTEPLUS_HOST="$BYTEPLUS_HOST" + _savedeployconf BYTEPLUS_HOST "$BYTEPLUS_HOST" + else + _BYTEPLUS_HOST="alb.${BYTEPLUS_REGION}.byteplusapi.com" + fi + _info "Using API host: $_BYTEPLUS_HOST" + _BYTEPLUS_SERVICE="alb" + + # โ”€โ”€ 2. Build certificate name โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + + _date_tag=$(date -u +%Y%m%d-%H%M) + # Replace wildcard * and dots for a valid cert name + _safe_domain=$(echo "$_cdomain" | sed 's/\*\.//g' | sed 's/\./-/g') + # Safe identifier version for deployconf keys: map all non [A-Za-z0-9_] to _ + _conf_key=$(echo "$_cdomain" | sed 's/^\*\.//' | sed 's/[^A-Za-z0-9_]/_/g') + + if [ -z "$BYTEPLUS_CERT_NAME" ]; then + BYTEPLUS_CERT_NAME="acme-${_safe_domain}-${_date_tag}" + fi + + # Enforce BytePlus naming rules: start with letter, max 128 chars + BYTEPLUS_CERT_NAME=$(echo "$BYTEPLUS_CERT_NAME" | sed 's/[^A-Za-z0-9._-]/-/g') + case "$BYTEPLUS_CERT_NAME" in + [A-Za-z]*) ;; + + *) + BYTEPLUS_CERT_NAME="a$BYTEPLUS_CERT_NAME" + ;; + esac + BYTEPLUS_CERT_NAME=$(echo "$BYTEPLUS_CERT_NAME" | cut -c1-128) + + _info "Certificate name: $BYTEPLUS_CERT_NAME" + + # โ”€โ”€ 3. Read cert and key โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + # BytePlus requires NO blank lines between PEM blocks in the certificate chain + + _public_key=$(sed '/^[[:space:]]*$/d' "$_cfullchain" | tr -d '\r') + _private_key=$(sed '/^[[:space:]]*$/d' "$_ckey" | tr -d '\r') + + if [ -z "$_public_key" ] || [ -z "$_private_key" ]; then + _err "Failed to read certificate or key file." + return 1 + fi + + # โ”€โ”€ 4. Deploy: first-time upload or renewal replace โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + + _getdeployconf "BYTEPLUS_CERT_ID_${_conf_key}" + _old_cert_id=$(eval echo "\$BYTEPLUS_CERT_ID_${_conf_key}") + + if [ -z "$_old_cert_id" ]; then + _byteplus_first_time_deploy + else + _byteplus_renewal_deploy + fi + + # Check if deploy step set _new_cert_id + if [ -z "$_new_cert_id" ]; then + return 1 + fi + + # โ”€โ”€ 5. Save new CertificateId for next renewal โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + + _savedeployconf "BYTEPLUS_CERT_ID_${_conf_key}" "$_new_cert_id" + _info "Saved CertificateId '$_new_cert_id' for domain '$_cdomain'." + + return 0 +} + +# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• +# Deploy: First time โ€” UploadCertificate +# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• + +_byteplus_first_time_deploy() { + _info "No previous CertificateId found." + _err "Refusing to upload certificate material because this hook passes PublicKey/PrivateKey as request parameters." + _err "Uploading a private key in the request URL can leak it via logs, proxies, and process listings." + _err "Please upload the certificate to BytePlus manually for the initial deployment, set BYTEPLUS_CERT_ID_${_conf_key} to that CertificateId, and rerun." + _err "This hook stores CertificateId values per domain using deployconf, so the variable name must include the current domain-specific suffix." + _err "This hook must be updated to send PublicKey and PrivateKey in a POST body before automatic first-time upload can be enabled safely." + return 1 +} + +# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• +# Deploy: Renewal โ€” ReplaceCertificate (UpdateMode=new) +# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• + +_byteplus_renewal_deploy() { + _info "Replacing old certificate '$_old_cert_id' (UpdateMode=new)..." + _err "Refusing to replace certificate material because this hook passes PublicKey/PrivateKey as request parameters." + _err "Uploading a private key in the request URL can leak it via logs, proxies, and process listings." + _err "Please replace the certificate in BytePlus manually for renewal until this hook is updated to send PublicKey and PrivateKey in a POST body safely." + return 1 +} + +# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• +# Delete old certificate (with retry) +# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• + +_byteplus_delete_old_cert() { + _del_cert_id="$1" + + _info "Waiting 5s for cert status to settle..." + _sleep 5 + + _info "Deleting old certificate '$_del_cert_id'..." + _del_response=$(_byteplus_alb_api "DeleteCertificate" "CertificateId=${_del_cert_id}") + + if echo "$_del_response" | grep -q '"Error"'; then + _info "Delete failed, retrying in 10s..." + _sleep 10 + _del_response=$(_byteplus_alb_api "DeleteCertificate" "CertificateId=${_del_cert_id}") + + if echo "$_del_response" | grep -q '"Error"'; then + _info "Warning: Could not delete old certificate '$_del_cert_id'." + _info "Error: $(_byteplus_extract_error "$_del_response")" + _info "Please remove it manually from BytePlus Console." + else + _info "Old certificate '$_del_cert_id' deleted (retry succeeded)." + fi + else + _info "Old certificate '$_del_cert_id' deleted." + fi +} + +# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• +# JSON response helpers +# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• + +# Extract CertificateId from API response JSON +_byteplus_extract_cert_id() { + echo "$1" | _egrep_o '"CertificateId"\s*:\s*"[^"]*"' | head -1 | _egrep_o '"[^"]*"$' | tr -d '"' +} + +# Extract error message from API response JSON +_byteplus_extract_error() { + _code=$(echo "$1" | _egrep_o '"Code"\s*:\s*"[^"]*"' | head -1 | _egrep_o '"[^"]*"$' | tr -d '"') + _msg=$(echo "$1" | _egrep_o '"Message"\s*:\s*"[^"]*"' | head -1 | _egrep_o '"[^"]*"$' | tr -d '"') + if [ -n "$_code" ]; then + printf '%s โ€” %s' "$_code" "$_msg" + else + printf '%s' "$1" + fi +} + +# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• +# BytePlus ALB API caller +# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• + +# Usage: _byteplus_alb_api ACTION [param1=val1] [param2=val2] ... +# All parameters sent via GET query string. Signing: HMAC-SHA256, host;x-date. +_byteplus_alb_api() { + _action="$1" + shift + + # Build query string โ€” all params go in URL + _query_params="Action=${_action}&Version=2020-04-01" + + for _param in "$@"; do + _pname="${_param%%=*}" + _pval="${_param#*=}" + _query_params="${_query_params}&${_pname}=$(_byteplus_urlencode "$_pval")" + done + + # Timestamps + _x_date=$(date -u +%Y%m%dT%H%M%SZ) + _date_only=$(date -u +%Y%m%d) + + # Sort query params for canonical request + _sorted_query=$(echo "$_query_params" | tr '&' '\n' | LC_ALL=C sort | tr '\n' '&' | sed 's/&$//') + + # Canonical headers โ€” only host and x-date + _canonical_headers="host:${_BYTEPLUS_HOST} +x-date:${_x_date} +" + _signed_headers="host;x-date" + + # Canonical request + _canonical_request="GET +/ +${_sorted_query} +${_canonical_headers} +${_signed_headers} +${_BYTEPLUS_EMPTY_HASH}" + + # Do not log _canonical_request because the query string may contain + # URL-encoded certificate or private key material. + + # Hash of canonical request + # _digest is provided by acme.sh and works across OpenSSL versions. + _cr_hash=$(printf '%s' "$_canonical_request" | _digest sha256 hex) + + # Credential scope + _credential_scope="${_date_only}/${BYTEPLUS_REGION}/${_BYTEPLUS_SERVICE}/request" + + # String to sign + _string_to_sign="HMAC-SHA256 +${_x_date} +${_credential_scope} +${_cr_hash}" + + _debug2 _string_to_sign "$_string_to_sign" + + # Signing key derivation (HMAC chain) + # _hmac reads data from stdin and returns a hex digest. + # acme.sh's _hmac abstracts away OpenSSL version differences, so this works + # on both modern (-mac HMAC -macopt hexkey:) and older (-hmac) OpenSSL builds. + # + # The first step seeds the chain from the raw secret key, so we convert it + # to hex first with _hex_dump (also an acme.sh built-in). + _secret_hex=$(printf '%s' "$BYTEPLUS_SECRET_KEY" | _hex_dump | tr -d ' \n') + _k_date=$(printf '%s' "$_date_only" | _hmac sha256 "$_secret_hex" hex) + _k_region=$(printf '%s' "$BYTEPLUS_REGION" | _hmac sha256 "$_k_date" hex) + _k_service=$(printf '%s' "$_BYTEPLUS_SERVICE" | _hmac sha256 "$_k_region" hex) + _k_signing=$(printf '%s' "request" | _hmac sha256 "$_k_service" hex) + + # Final signature + _signature=$(printf '%s' "$_string_to_sign" | _hmac sha256 "$_k_signing" hex) + + # Authorization header + _auth="HMAC-SHA256 Credential=${BYTEPLUS_ACCESS_KEY}/${_credential_scope}, SignedHeaders=${_signed_headers}, Signature=${_signature}" + + _secure_debug2 _auth "$_auth" + + # Send request parameters in the POST body instead of the URL query string. + # This avoids exposing sensitive or large values in debug-logged URLs and + # reduces the risk of exceeding URL length limits. + _url="https://${_BYTEPLUS_HOST}/" + _body="$_sorted_query" + + _saved_H1="${_H1:-}" + _saved_H2="${_H2:-}" + _saved_H3="${_H3:-}" + _saved_H4="${_H4:-}" + _saved_H5="${_H5:-}" + + _H1="Authorization: ${_auth}" + _H2="X-Date: ${_x_date}" + _H3="Host: ${_BYTEPLUS_HOST}" + _H4="Content-Type: application/x-www-form-urlencoded" + _H5="" + + _response="$(_post "$_body" "$_url" "" "POST")" + _request_ret="$?" + + _H1="$_saved_H1" + _H2="$_saved_H2" + _H3="$_saved_H3" + _H4="$_saved_H4" + _H5="$_saved_H5" + + if [ "$_request_ret" != "0" ]; then + _err "byteplus_alb_api request failed for [$_action]" + return 1 + fi + _debug2 "_byteplus_alb_api response [$_action]" "$_response" + printf '%s' "$_response" +} + +# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• +# URL encode (RFC 3986) +# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• + +_byteplus_urlencode() { + printf '%s' "$1" | _url_encode +}