feat: add code signing support for Windows desktop client executables and installers
Add osslsigncode dependency and implement three-step signing workflow. Decode base64-encoded PFX certificate from secrets, sign bundled tunnel helper before build, then sign desktop executable and NSIS installer after build. Use configurable timestamp URL with DigiCert fallback. Clean up certificate file in always-run step to prevent secret leakage.
This commit is contained in:
@@ -39,6 +39,7 @@ jobs:
|
|||||||
wget \
|
wget \
|
||||||
file \
|
file \
|
||||||
nsis \
|
nsis \
|
||||||
|
osslsigncode \
|
||||||
pkg-config \
|
pkg-config \
|
||||||
libssl-dev \
|
libssl-dev \
|
||||||
libayatana-appindicator3-dev \
|
libayatana-appindicator3-dev \
|
||||||
@@ -57,9 +58,66 @@ jobs:
|
|||||||
- name: Build bundled Windows tunnel helper
|
- name: Build bundled Windows tunnel helper
|
||||||
run: npm run helper:windows-x64
|
run: npm run helper:windows-x64
|
||||||
|
|
||||||
|
- name: Prepare signing certificate
|
||||||
|
if: ${{ secrets.WINDOWS_SIGN_PFX_B64 != '' && secrets.WINDOWS_SIGN_PFX_PASSWORD != '' }}
|
||||||
|
run: |
|
||||||
|
printf '%s' "${{ secrets.WINDOWS_SIGN_PFX_B64 }}" | base64 -d > /tmp/nexavpn-signing-cert.pfx
|
||||||
|
|
||||||
|
- name: Sign bundled Windows tunnel helper
|
||||||
|
if: ${{ secrets.WINDOWS_SIGN_PFX_B64 != '' && secrets.WINDOWS_SIGN_PFX_PASSWORD != '' }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
timestamp_url="${{ secrets.WINDOWS_SIGN_TIMESTAMP_URL }}"
|
||||||
|
if [ -z "${timestamp_url}" ]; then
|
||||||
|
timestamp_url="http://timestamp.digicert.com"
|
||||||
|
fi
|
||||||
|
helper_path="src-tauri/bundled/windows-x64/nexavpn-tunnel-helper.exe"
|
||||||
|
signed_path="${helper_path}.signed"
|
||||||
|
osslsigncode sign \
|
||||||
|
-pkcs12 /tmp/nexavpn-signing-cert.pfx \
|
||||||
|
-pass "${{ secrets.WINDOWS_SIGN_PFX_PASSWORD }}" \
|
||||||
|
-h sha256 \
|
||||||
|
-ts "${timestamp_url}" \
|
||||||
|
-in "${helper_path}" \
|
||||||
|
-out "${signed_path}"
|
||||||
|
mv "${signed_path}" "${helper_path}"
|
||||||
|
|
||||||
- name: Build Windows installer
|
- name: Build Windows installer
|
||||||
run: npm run tauri:build:windows-x64:linux
|
run: npm run tauri:build:windows-x64:linux
|
||||||
|
|
||||||
|
- name: Sign Windows desktop executable and installer
|
||||||
|
if: ${{ secrets.WINDOWS_SIGN_PFX_B64 != '' && secrets.WINDOWS_SIGN_PFX_PASSWORD != '' }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
timestamp_url="${{ secrets.WINDOWS_SIGN_TIMESTAMP_URL }}"
|
||||||
|
if [ -z "${timestamp_url}" ]; then
|
||||||
|
timestamp_url="http://timestamp.digicert.com"
|
||||||
|
fi
|
||||||
|
|
||||||
|
sign_file() {
|
||||||
|
local input_path="$1"
|
||||||
|
local output_path="${input_path}.signed"
|
||||||
|
osslsigncode sign \
|
||||||
|
-pkcs12 /tmp/nexavpn-signing-cert.pfx \
|
||||||
|
-pass "${{ secrets.WINDOWS_SIGN_PFX_PASSWORD }}" \
|
||||||
|
-h sha256 \
|
||||||
|
-ts "${timestamp_url}" \
|
||||||
|
-in "${input_path}" \
|
||||||
|
-out "${output_path}"
|
||||||
|
mv "${output_path}" "${input_path}"
|
||||||
|
}
|
||||||
|
|
||||||
|
sign_file "src-tauri/target/x86_64-pc-windows-msvc/release/nexavpn-desktop.exe"
|
||||||
|
|
||||||
|
shopt -s nullglob
|
||||||
|
for installer in src-tauri/target/x86_64-pc-windows-msvc/release/bundle/nsis/*.exe; do
|
||||||
|
sign_file "${installer}"
|
||||||
|
done
|
||||||
|
|
||||||
|
- name: Cleanup signing certificate
|
||||||
|
if: ${{ always() && secrets.WINDOWS_SIGN_PFX_B64 != '' && secrets.WINDOWS_SIGN_PFX_PASSWORD != '' }}
|
||||||
|
run: rm -f /tmp/nexavpn-signing-cert.pfx
|
||||||
|
|
||||||
- name: Upload Windows installer
|
- name: Upload Windows installer
|
||||||
uses: christopherhx/gitea-upload-artifact@v4
|
uses: christopherhx/gitea-upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
|
|||||||
Reference in New Issue
Block a user