From 487558b646e44445d68a218bf392b2c5fe56cb3d Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Sun, 8 Mar 2026 10:28:19 -0400 Subject: [PATCH 1/2] build(windows): sign windows executables --- .github/workflows/ci-windows.yml | 92 ++++++++++++++++++++++++++++++++ .github/workflows/ci.yml | 6 +++ 2 files changed, 98 insertions(+) diff --git a/.github/workflows/ci-windows.yml b/.github/workflows/ci-windows.yml index 783d74c38aa..7892e2bae5b 100644 --- a/.github/workflows/ci-windows.yml +++ b/.github/workflows/ci-windows.yml @@ -5,12 +5,28 @@ permissions: {} on: workflow_call: inputs: + publish_release: + required: true + type: string release_commit: required: true type: string release_version: required: true type: string + secrets: + # SSL.com account username (email) + SSLCOM_USERNAME: + required: false + # SSL.com account password + SSLCOM_PASSWORD: + required: false + # Certificate credential ID on SSL.com + SSLCOM_CREDENTIAL_ID: + required: false + # TOTP secret for 2FA (from SSL.com account) + SSLCOM_TOTP_SECRET: + required: false jobs: build_windows: @@ -186,6 +202,17 @@ jobs: echo "python-path=${python_path}" echo "python-path=${python_path}" >> "${GITHUB_OUTPUT}" + - name: Install SSL.com CodeSignTool + if: inputs.publish_release == 'true' + shell: msys2 {0} + run: | + wget --no-verbose -O /tmp/CodeSignTool.zip \ + "https://www.ssl.com/download/codesigntool-for-windows/" + unzip -q /tmp/CodeSignTool.zip -d /c/CodeSignTool + rm /tmp/CodeSignTool.zip + + echo "C:\\CodeSignTool" >> "${GITHUB_PATH}" + - name: Build Windows shell: msys2 {0} env: @@ -217,6 +244,42 @@ jobs: ninja -C build echo "::remove-matcher owner=gcc::" + - name: Sign Windows executables + if: inputs.publish_release == 'true' + shell: msys2 {0} + env: + SSLCOM_USERNAME: ${{ secrets.SSLCOM_USERNAME }} + SSLCOM_PASSWORD: ${{ secrets.SSLCOM_PASSWORD }} + SSLCOM_CREDENTIAL_ID: ${{ secrets.SSLCOM_CREDENTIAL_ID }} + SSLCOM_TOTP_SECRET: ${{ secrets.SSLCOM_TOTP_SECRET }} + run: | + # Stage files into a single temp dir for batch signing: + # - exe files from build root and tools/ (excludes third-party scripts/vigembus) + # - all PowerShell scripts from source assets + staging=$(mktemp -d) + signed="${staging}-signed" # must not exist; CodeSignTool creates it + find build -maxdepth 1 -name "*.exe" -exec cp {} "${staging}/" \; + find build/tools -maxdepth 1 -name "*.exe" -exec cp {} "${staging}/" \; + find src_assets/windows -name "*.ps1" -exec cp {} "${staging}/" \; + + CodeSignTool.bat batch_sign \ + -username="${SSLCOM_USERNAME}" \ + -password="${SSLCOM_PASSWORD}" \ + -credential_id="${SSLCOM_CREDENTIAL_ID}" \ + -totp_secret="${SSLCOM_TOTP_SECRET}" \ + -input_dir_path="$(cygpath -w "${staging}")" \ + -output_dir_path="$(cygpath -w "${signed}")" + + # Copy signed files back to their original locations + find build -maxdepth 1 -name "*.exe" -exec bash -c \ + 'cp "${signed}/$(basename "$1")" "$1"' _ {} \; + find build/tools -maxdepth 1 -name "*.exe" -exec bash -c \ + 'cp "${signed}/$(basename "$1")" "$1"' _ {} \; + find src_assets/windows -name "*.ps1" -exec bash -c \ + 'cp "${signed}/$(basename "$1")" "$1"' _ {} \; + + rm -rf "${staging}" "${signed}" + - name: Package Windows shell: msys2 {0} run: | @@ -233,6 +296,35 @@ jobs: mv ./cpack_artifacts/Sunshine.msi ../artifacts/Sunshine-${{ matrix.name }}-installer.msi mv ./cpack_artifacts/Sunshine.zip ../artifacts/Sunshine-${{ matrix.name }}-portable.zip + - name: Sign Windows installers + if: inputs.publish_release == 'true' + shell: msys2 {0} + env: + SSLCOM_USERNAME: ${{ secrets.SSLCOM_USERNAME }} + SSLCOM_PASSWORD: ${{ secrets.SSLCOM_PASSWORD }} + SSLCOM_CREDENTIAL_ID: ${{ secrets.SSLCOM_CREDENTIAL_ID }} + SSLCOM_TOTP_SECRET: ${{ secrets.SSLCOM_TOTP_SECRET }} + run: | + # Stage only the installers (not the portable zip) for batch signing + staging=$(mktemp -d) + signed="${staging}-signed" # must not exist; CodeSignTool creates it + find artifacts -maxdepth 1 \( -name "*-installer.exe" -o -name "*-installer.msi" \) \ + -exec cp {} "${staging}/" \; + + CodeSignTool.bat batch_sign \ + -username="${SSLCOM_USERNAME}" \ + -password="${SSLCOM_PASSWORD}" \ + -credential_id="${SSLCOM_CREDENTIAL_ID}" \ + -totp_secret="${SSLCOM_TOTP_SECRET}" \ + -input_dir_path="$(cygpath -w "${staging}")" \ + -output_dir_path="$(cygpath -w "${signed}")" + + # Copy signed installers back + find artifacts -maxdepth 1 \( -name "*-installer.exe" -o -name "*-installer.msi" \) \ + -exec bash -c 'cp "${signed}/$(basename "$1")" "$1"' _ {} \; + + rm -rf "${staging}" "${signed}" + - name: Debug nsis if: always() shell: msys2 {0} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a587b408554..d69bc1ad3d1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -158,8 +158,14 @@ jobs: contents: read uses: ./.github/workflows/ci-windows.yml with: + publish_release: ${{ needs.release-setup.outputs.publish_release }} release_commit: ${{ needs.release-setup.outputs.release_commit }} release_version: ${{ needs.release-setup.outputs.release_version }} + secrets: + SSLCOM_USERNAME: ${{ secrets.SSLCOM_USERNAME }} + SSLCOM_PASSWORD: ${{ secrets.SSLCOM_PASSWORD }} + SSLCOM_CREDENTIAL_ID: ${{ secrets.SSLCOM_CREDENTIAL_ID }} + SSLCOM_TOTP_SECRET: ${{ secrets.SSLCOM_TOTP_SECRET }} bundle-analysis: name: Bundle Analysis From 5e3e0d90f19cb45c38a68a18a48cc8392aa855f6 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Tue, 10 Mar 2026 13:44:05 -0400 Subject: [PATCH 2/2] Switch Windows signing to Azure Trusted Signing Replace SSL.com CodeSignTool-based signing with Azure Artifact Signing via azure/trusted-signing-action. Adds workflow inputs (azure_signing_account, azure_signing_cert_profile, azure_signing_endpoint) and maps AZURE_CLIENT_ID/SECRET/TENANT secrets. Removes CodeSignTool install and legacy SSL.com signing steps, and updates ci.yml to forward Azure signing vars/secrets. Signing steps now conditionally run when publishing and an Azure signing account is provided, and sign both built executables/scripts and installer artifacts. --- .github/workflows/ci-windows.yml | 132 ++++++++++++------------------- .github/workflows/ci.yml | 10 ++- 2 files changed, 57 insertions(+), 85 deletions(-) diff --git a/.github/workflows/ci-windows.yml b/.github/workflows/ci-windows.yml index 7892e2bae5b..8a210a9ba5c 100644 --- a/.github/workflows/ci-windows.yml +++ b/.github/workflows/ci-windows.yml @@ -5,6 +5,22 @@ permissions: {} on: workflow_call: inputs: + # Azure Artifact Signing account name + azure_signing_account: + required: false + type: string + default: '' + # Azure Artifact Signing certificate profile name + azure_signing_cert_profile: + required: false + type: string + default: '' + # Azure Artifact Signing account endpoint + # e.g. https://.codesigning.azure.net + azure_signing_endpoint: + required: false + type: string + default: '' publish_release: required: true type: string @@ -15,17 +31,14 @@ on: required: true type: string secrets: - # SSL.com account username (email) - SSLCOM_USERNAME: - required: false - # SSL.com account password - SSLCOM_PASSWORD: + # Azure Client ID (App Registration) for Artifact Signing + AZURE_CLIENT_ID: required: false - # Certificate credential ID on SSL.com - SSLCOM_CREDENTIAL_ID: + # Azure Client Secret for Artifact Signing + AZURE_CLIENT_SECRET: required: false - # TOTP secret for 2FA (from SSL.com account) - SSLCOM_TOTP_SECRET: + # Azure Tenant ID for Artifact Signing + AZURE_TENANT_ID: required: false jobs: @@ -202,17 +215,6 @@ jobs: echo "python-path=${python_path}" echo "python-path=${python_path}" >> "${GITHUB_OUTPUT}" - - name: Install SSL.com CodeSignTool - if: inputs.publish_release == 'true' - shell: msys2 {0} - run: | - wget --no-verbose -O /tmp/CodeSignTool.zip \ - "https://www.ssl.com/download/codesigntool-for-windows/" - unzip -q /tmp/CodeSignTool.zip -d /c/CodeSignTool - rm /tmp/CodeSignTool.zip - - echo "C:\\CodeSignTool" >> "${GITHUB_PATH}" - - name: Build Windows shell: msys2 {0} env: @@ -245,40 +247,23 @@ jobs: echo "::remove-matcher owner=gcc::" - name: Sign Windows executables - if: inputs.publish_release == 'true' - shell: msys2 {0} - env: - SSLCOM_USERNAME: ${{ secrets.SSLCOM_USERNAME }} - SSLCOM_PASSWORD: ${{ secrets.SSLCOM_PASSWORD }} - SSLCOM_CREDENTIAL_ID: ${{ secrets.SSLCOM_CREDENTIAL_ID }} - SSLCOM_TOTP_SECRET: ${{ secrets.SSLCOM_TOTP_SECRET }} - run: | - # Stage files into a single temp dir for batch signing: - # - exe files from build root and tools/ (excludes third-party scripts/vigembus) - # - all PowerShell scripts from source assets - staging=$(mktemp -d) - signed="${staging}-signed" # must not exist; CodeSignTool creates it - find build -maxdepth 1 -name "*.exe" -exec cp {} "${staging}/" \; - find build/tools -maxdepth 1 -name "*.exe" -exec cp {} "${staging}/" \; - find src_assets/windows -name "*.ps1" -exec cp {} "${staging}/" \; - - CodeSignTool.bat batch_sign \ - -username="${SSLCOM_USERNAME}" \ - -password="${SSLCOM_PASSWORD}" \ - -credential_id="${SSLCOM_CREDENTIAL_ID}" \ - -totp_secret="${SSLCOM_TOTP_SECRET}" \ - -input_dir_path="$(cygpath -w "${staging}")" \ - -output_dir_path="$(cygpath -w "${signed}")" - - # Copy signed files back to their original locations - find build -maxdepth 1 -name "*.exe" -exec bash -c \ - 'cp "${signed}/$(basename "$1")" "$1"' _ {} \; - find build/tools -maxdepth 1 -name "*.exe" -exec bash -c \ - 'cp "${signed}/$(basename "$1")" "$1"' _ {} \; - find src_assets/windows -name "*.ps1" -exec bash -c \ - 'cp "${signed}/$(basename "$1")" "$1"' _ {} \; - - rm -rf "${staging}" "${signed}" + if: inputs.publish_release == 'true' && inputs.azure_signing_account != '' + uses: azure/trusted-signing-action@87c2e83e6868da99d3380aa309851b32ed9a8346 # v1.1.0 + with: + azure-client-id: ${{ secrets.AZURE_CLIENT_ID }} + azure-client-secret: ${{ secrets.AZURE_CLIENT_SECRET }} + azure-tenant-id: ${{ secrets.AZURE_TENANT_ID }} + certificate-profile-name: ${{ inputs.azure_signing_cert_profile }} + endpoint: ${{ inputs.azure_signing_endpoint }} + files: | + ${{ github.workspace }}/build/sunshine.exe + ${{ github.workspace }}/build/tools/audio-info.exe + ${{ github.workspace }}/build/tools/dxgi-info.exe + ${{ github.workspace }}/build/tools/sunshinesvc.exe + files-folder: src_assets/windows + files-folder-filter: ps1 + files-folder-recurse: true + signing-account-name: ${{ inputs.azure_signing_account }} - name: Package Windows shell: msys2 {0} @@ -297,33 +282,18 @@ jobs: mv ./cpack_artifacts/Sunshine.zip ../artifacts/Sunshine-${{ matrix.name }}-portable.zip - name: Sign Windows installers - if: inputs.publish_release == 'true' - shell: msys2 {0} - env: - SSLCOM_USERNAME: ${{ secrets.SSLCOM_USERNAME }} - SSLCOM_PASSWORD: ${{ secrets.SSLCOM_PASSWORD }} - SSLCOM_CREDENTIAL_ID: ${{ secrets.SSLCOM_CREDENTIAL_ID }} - SSLCOM_TOTP_SECRET: ${{ secrets.SSLCOM_TOTP_SECRET }} - run: | - # Stage only the installers (not the portable zip) for batch signing - staging=$(mktemp -d) - signed="${staging}-signed" # must not exist; CodeSignTool creates it - find artifacts -maxdepth 1 \( -name "*-installer.exe" -o -name "*-installer.msi" \) \ - -exec cp {} "${staging}/" \; - - CodeSignTool.bat batch_sign \ - -username="${SSLCOM_USERNAME}" \ - -password="${SSLCOM_PASSWORD}" \ - -credential_id="${SSLCOM_CREDENTIAL_ID}" \ - -totp_secret="${SSLCOM_TOTP_SECRET}" \ - -input_dir_path="$(cygpath -w "${staging}")" \ - -output_dir_path="$(cygpath -w "${signed}")" - - # Copy signed installers back - find artifacts -maxdepth 1 \( -name "*-installer.exe" -o -name "*-installer.msi" \) \ - -exec bash -c 'cp "${signed}/$(basename "$1")" "$1"' _ {} \; - - rm -rf "${staging}" "${signed}" + if: inputs.publish_release == 'true' && inputs.azure_signing_account != '' + uses: azure/trusted-signing-action@87c2e83e6868da99d3380aa309851b32ed9a8346 # v1.1.0 + with: + azure-client-id: ${{ secrets.AZURE_CLIENT_ID }} + azure-client-secret: ${{ secrets.AZURE_CLIENT_SECRET }} + azure-tenant-id: ${{ secrets.AZURE_TENANT_ID }} + certificate-profile-name: ${{ inputs.azure_signing_cert_profile }} + endpoint: ${{ inputs.azure_signing_endpoint }} + files-folder: artifacts + files-folder-filter: exe,msi + files-folder-recurse: false + signing-account-name: ${{ inputs.azure_signing_account }} - name: Debug nsis if: always() diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d69bc1ad3d1..246dc7956f1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -158,14 +158,16 @@ jobs: contents: read uses: ./.github/workflows/ci-windows.yml with: + azure_signing_account: ${{ vars.AZURE_SIGNING_ACCOUNT }} + azure_signing_cert_profile: ${{ vars.AZURE_SIGNING_CERT_PROFILE }} + azure_signing_endpoint: ${{ vars.AZURE_SIGNING_ENDPOINT }} publish_release: ${{ needs.release-setup.outputs.publish_release }} release_commit: ${{ needs.release-setup.outputs.release_commit }} release_version: ${{ needs.release-setup.outputs.release_version }} secrets: - SSLCOM_USERNAME: ${{ secrets.SSLCOM_USERNAME }} - SSLCOM_PASSWORD: ${{ secrets.SSLCOM_PASSWORD }} - SSLCOM_CREDENTIAL_ID: ${{ secrets.SSLCOM_CREDENTIAL_ID }} - SSLCOM_TOTP_SECRET: ${{ secrets.SSLCOM_TOTP_SECRET }} + AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} + AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }} + AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} bundle-analysis: name: Bundle Analysis