Align Windows signing with MrTrust contract
This commit is contained in:
@@ -19,13 +19,12 @@ jobs:
|
||||
MODRINTH_SOCKET_URL: wss://api.modrinth.com/
|
||||
MODRINTH_LAUNCHER_META_URL: https://launcher-meta.modrinth.com/
|
||||
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
||||
MRTRUST_CODE_SIGNING_PFX_BASE64: ${{ secrets.MRTRUST_CODE_SIGNING_PFX_BASE64 }}
|
||||
MRTRUST_PFX_PASSWORD: ${{ secrets.MRTRUST_PFX_PASSWORD }}
|
||||
MRTRUST_CODESIGN_PFX_BASE64: ${{ secrets.MRTRUST_CODESIGN_PFX_BASE64 }}
|
||||
MRTRUST_CODESIGN_PFX_PASSWORD: ${{ secrets.MRTRUST_CODESIGN_PFX_PASSWORD }}
|
||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
|
||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
|
||||
TAURI_SIGNING_PUBLIC_KEY: ${{ secrets.TAURI_SIGNING_PUBLIC_KEY }}
|
||||
XWIN_CACHE_DIR: .xwin-cache
|
||||
JSIGN_VERSION: "7.4"
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
@@ -58,7 +57,8 @@ jobs:
|
||||
clang \
|
||||
lld \
|
||||
llvm \
|
||||
nsis
|
||||
nsis \
|
||||
osslsigncode
|
||||
|
||||
- name: Install cargo-xwin
|
||||
run: cargo install --locked cargo-xwin
|
||||
@@ -72,21 +72,11 @@ jobs:
|
||||
- name: Prepare MrTrust Windows code signing
|
||||
shell: bash
|
||||
run: |
|
||||
if [ -z "${MRTRUST_CODE_SIGNING_PFX_BASE64}" ] || [ -z "${MRTRUST_PFX_PASSWORD}" ]; then
|
||||
echo "::error::MRTRUST_CODE_SIGNING_PFX_BASE64 and MRTRUST_PFX_PASSWORD are required so MrTrust-installed users can trust Modrinth Plus."
|
||||
if [ -z "${MRTRUST_CODESIGN_PFX_BASE64}" ] || [ -z "${MRTRUST_CODESIGN_PFX_PASSWORD}" ]; then
|
||||
echo "::error::MRTRUST_CODESIGN_PFX_BASE64 and MRTRUST_CODESIGN_PFX_PASSWORD are required so MrTrust-installed users can trust Modrinth Plus."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p .signing
|
||||
printf '%s' "${MRTRUST_CODE_SIGNING_PFX_BASE64}" | base64 --decode > .signing/MrSphay-CodeSigning.pfx
|
||||
chmod 600 .signing/MrSphay-CodeSigning.pfx
|
||||
|
||||
curl --fail-with-body --location \
|
||||
--output .signing/jsign.jar \
|
||||
"https://github.com/ebourg/jsign/releases/download/${JSIGN_VERSION}/jsign-${JSIGN_VERSION}.jar"
|
||||
|
||||
echo "MRTRUST_PFX_PATH=${GITHUB_WORKSPACE}/.signing/MrSphay-CodeSigning.pfx" >> "${GITHUB_ENV}"
|
||||
echo "JSIGN_JAR=${GITHUB_WORKSPACE}/.signing/jsign.jar" >> "${GITHUB_ENV}"
|
||||
command -v osslsigncode
|
||||
|
||||
- name: Prepare Modrinth Plus update metadata
|
||||
shell: bash
|
||||
@@ -95,13 +85,15 @@ jobs:
|
||||
node -e "const fs=require('fs'); const path='apps/app-frontend/package.json'; const pkg=JSON.parse(fs.readFileSync(path,'utf8')); pkg.version=process.argv[1]; fs.writeFileSync(path, JSON.stringify(pkg,null,'\\t')+'\\n');" "${build_version}"
|
||||
if [ -n "${TAURI_SIGNING_PRIVATE_KEY}" ] && [ -n "${TAURI_SIGNING_PUBLIC_KEY}" ]; then
|
||||
node -e "const fs=require('fs'); const path='apps/app/tauri-release.conf.json'; const config=JSON.parse(fs.readFileSync(path,'utf8')); config.plugins.updater.pubkey=process.env.TAURI_SIGNING_PUBLIC_KEY; fs.writeFileSync(path, JSON.stringify(config,null,'\\t')+'\\n');"
|
||||
echo "TAURI_BUNDLES=nsis,updater" >> "${GITHUB_ENV}"
|
||||
else
|
||||
echo "::error::TAURI_SIGNING_PRIVATE_KEY and TAURI_SIGNING_PUBLIC_KEY are required for release/update builds."
|
||||
exit 1
|
||||
echo "::warning::TAURI_SIGNING_PRIVATE_KEY and TAURI_SIGNING_PUBLIC_KEY are not set. Building the MrTrust-signed installer without publishing Tauri self-update metadata."
|
||||
node -e "const fs=require('fs'); const path='apps/app/tauri-release.conf.json'; const config=JSON.parse(fs.readFileSync(path,'utf8')); config.bundle.createUpdaterArtifacts=false; config.plugins.updater.pubkey='dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDIwMzM5QkE0M0FCOERBMzkKUldRNTJyZzZwSnN6SUdPRGdZREtUUGxMblZqeG9OVHYxRUlRTzJBc2U3MUNJaDMvZDQ1UytZZmYK'; fs.writeFileSync(path, JSON.stringify(config,null,'\\t')+'\\n');"
|
||||
echo "TAURI_BUNDLES=nsis" >> "${GITHUB_ENV}"
|
||||
fi
|
||||
|
||||
- name: Build Windows desktop client
|
||||
run: pnpm --filter @modrinth/app exec tauri build --config tauri-release.conf.json --runner cargo-xwin --target x86_64-pc-windows-msvc --bundles "nsis,updater"
|
||||
run: pnpm --filter @modrinth/app exec tauri build --config tauri-release.conf.json --runner cargo-xwin --target x86_64-pc-windows-msvc --bundles "${TAURI_BUNDLES}"
|
||||
|
||||
- name: Upload Windows desktop client
|
||||
uses: actions/upload-artifact@v3
|
||||
|
||||
@@ -24,6 +24,8 @@ This repository contains two primary packages. For detailed development informat
|
||||
|
||||
Modrinth Plus adds a Connected Library for Git-hosted modpacks. A connected modpack repository must expose a public `modrinth-plus.json` manifest in the repository root. See [Connected Library documentation](docs/connected-library.md) and the [connected modpack template](templates/connected-modpack/README.md).
|
||||
|
||||
Windows release artifacts are signed for MrTrust. Users who want Windows to trust MrSphay-signed builds can download `MrTrust-<version>.zip` from [MrTrust releases](https://git.wilkensxl.de/MrSphay/MrTrust/releases), run `MrTrust.exe`, and choose `Install trust`. Trust can be removed again from the same tool.
|
||||
|
||||
## Contributing
|
||||
|
||||
We welcome contributions! Before submitting any contributions, please read our [contributing guidelines](https://docs.modrinth.com/contributing/getting-started/).
|
||||
|
||||
@@ -1,31 +1,65 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
artifact_path="${1:-}"
|
||||
if [ -z "${artifact_path}" ]; then
|
||||
echo "No artifact path was provided for signing." >&2
|
||||
exit 1
|
||||
if [ "$#" -lt 1 ]; then
|
||||
echo "Usage: sign-windows-artifact.sh <artifact> [artifact...]" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [ -z "${JSIGN_JAR:-}" ] || [ ! -f "${JSIGN_JAR}" ]; then
|
||||
echo "JSIGN_JAR must point to the downloaded jsign jar." >&2
|
||||
exit 1
|
||||
if [ -z "${MRTRUST_CODESIGN_PFX_BASE64:-}" ]; then
|
||||
echo "MRTRUST_CODESIGN_PFX_BASE64 is required." >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [ -z "${MRTRUST_PFX_PATH:-}" ] || [ ! -f "${MRTRUST_PFX_PATH}" ]; then
|
||||
echo "MRTRUST_PFX_PATH must point to the MrTrust code-signing PFX." >&2
|
||||
exit 1
|
||||
if [ -z "${MRTRUST_CODESIGN_PFX_PASSWORD:-}" ]; then
|
||||
echo "MRTRUST_CODESIGN_PFX_PASSWORD is required." >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [ -z "${MRTRUST_PFX_PASSWORD:-}" ]; then
|
||||
echo "MRTRUST_PFX_PASSWORD must be set." >&2
|
||||
exit 1
|
||||
if ! command -v osslsigncode >/dev/null 2>&1; then
|
||||
echo "osslsigncode is required for MrTrust Ubuntu runner signing." >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
java -jar "${JSIGN_JAR}" sign \
|
||||
--verbose \
|
||||
--storetype PKCS12 \
|
||||
--keystore "${MRTRUST_PFX_PATH}" \
|
||||
--storepass env:MRTRUST_PFX_PASSWORD \
|
||||
--tsaurl "https://timestamp.sectigo.com,http://timestamp.digicert.com" \
|
||||
"${artifact_path}"
|
||||
work_dir="$(mktemp -d)"
|
||||
trap 'rm -rf "$work_dir"' EXIT
|
||||
|
||||
pfx_path="$work_dir/mrtrust-codesign.pfx"
|
||||
printf '%s' "$MRTRUST_CODESIGN_PFX_BASE64" | base64 -d > "$pfx_path"
|
||||
|
||||
timestamp_url="${MRTRUST_TIMESTAMP_URL:-http://timestamp.digicert.com}"
|
||||
|
||||
for artifact in "$@"; do
|
||||
if [ ! -f "$artifact" ]; then
|
||||
echo "Artifact not found: $artifact" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
case "${artifact##*.}" in
|
||||
exe | EXE | msi | MSI | dll | DLL | cat | CAT)
|
||||
;;
|
||||
*)
|
||||
echo "Unsupported artifact for osslsigncode: $artifact" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
|
||||
signed_path="$work_dir/$(basename "$artifact").signed"
|
||||
args=(
|
||||
sign
|
||||
-pkcs12 "$pfx_path"
|
||||
-pass "$MRTRUST_CODESIGN_PFX_PASSWORD"
|
||||
-n "MrSphay"
|
||||
-i "https://git.wilkensxl.de/MrSphay"
|
||||
-in "$artifact"
|
||||
-out "$signed_path"
|
||||
)
|
||||
|
||||
if [ -n "$timestamp_url" ]; then
|
||||
args+=(-t "$timestamp_url")
|
||||
fi
|
||||
|
||||
osslsigncode "${args[@]}"
|
||||
mv "$signed_path" "$artifact"
|
||||
echo "Signed $artifact"
|
||||
done
|
||||
|
||||
@@ -8,7 +8,7 @@ Release artifacts are not published yet.
|
||||
|
||||
- Connected Library can track public Git-hosted modpack manifests.
|
||||
- Per-pack auto-update can be enabled after a pack is connected.
|
||||
- Windows release artifacts are signed with the MrTrust code-signing certificate.
|
||||
- Windows release artifacts are signed with the MrTrust code-signing certificate using `osslsigncode` on the Ubuntu Gitea runner.
|
||||
- Gitea Actions are used as the verification runner.
|
||||
|
||||
## Security
|
||||
@@ -16,7 +16,7 @@ Release artifacts are not published yet.
|
||||
- Dependency audit: pending runner/toolchain confirmation.
|
||||
- Secret handling: no tokens are stored by Connected Library v1.
|
||||
- External network calls: public HTTPS manifest and `.mrpack` downloads.
|
||||
- Windows trust: MrTrust-installed users can trust Modrinth Plus only when artifacts are signed with the matching MrSphay certificate chain.
|
||||
- Windows trust: MrTrust-installed users can trust Modrinth Plus only when artifacts are signed with the matching MrSphay certificate chain. MrTrust is distributed separately at `https://git.wilkensxl.de/MrSphay/MrTrust/releases`.
|
||||
|
||||
## Verification
|
||||
|
||||
@@ -25,7 +25,7 @@ Release artifacts are not published yet.
|
||||
| Gitea Actions build | Must pass before release |
|
||||
| Frontend lint | Covered by Gitea build workflow |
|
||||
| Rust clippy | Covered by Gitea build workflow |
|
||||
| MrTrust signing | Required by Gitea build workflow |
|
||||
| MrTrust signing | Required by Gitea build workflow with `MRTRUST_CODESIGN_PFX_BASE64` and `MRTRUST_CODESIGN_PFX_PASSWORD` |
|
||||
| Artifact download | Pending release packaging |
|
||||
|
||||
## Notes
|
||||
|
||||
@@ -4,13 +4,15 @@ Modrinth Plus uses the existing Tauri updater flow from the upstream Modrinth Ap
|
||||
|
||||
The updater requires signing. Tauri does not allow unsigned updater installs, so the Gitea repository must provide these Actions secrets:
|
||||
|
||||
- `MRTRUST_CODE_SIGNING_PFX_BASE64`: base64-encoded `MrSphay-CodeSigning.pfx` from MrTrust.
|
||||
- `MRTRUST_PFX_PASSWORD`: password for the MrTrust code-signing PFX.
|
||||
- `MRTRUST_CODESIGN_PFX_BASE64`: base64-encoded `MrSphay-CodeSigning.pfx` from MrTrust.
|
||||
- `MRTRUST_CODESIGN_PFX_PASSWORD`: password for the MrTrust code-signing PFX.
|
||||
- `TAURI_SIGNING_PRIVATE_KEY`: private key generated by `tauri signer generate`.
|
||||
- `TAURI_SIGNING_PRIVATE_KEY_PASSWORD`: optional key password.
|
||||
- `TAURI_SIGNING_PUBLIC_KEY`: public key generated next to the private key.
|
||||
- `REGISTRY_TOKEN`: Gitea token with package write access.
|
||||
|
||||
MrTrust signing and Tauri updater signing are separate. If only the two `MRTRUST_*` secrets are set, the workflow still builds and publishes a MrTrust-signed Windows installer, but it does not publish `latest.json` for in-app reload updates.
|
||||
|
||||
Generate a keypair with the Tauri CLI:
|
||||
|
||||
```powershell
|
||||
@@ -19,7 +21,7 @@ pnpm --filter @modrinth/app exec tauri signer generate -- -w "$env:USERPROFILE\.
|
||||
|
||||
Use the `.key` file content as `TAURI_SIGNING_PRIVATE_KEY` and the `.key.pub` file content as `TAURI_SIGNING_PUBLIC_KEY`.
|
||||
|
||||
Encode the MrTrust PFX for the `MRTRUST_CODE_SIGNING_PFX_BASE64` secret:
|
||||
Encode the MrTrust PFX for the `MRTRUST_CODESIGN_PFX_BASE64` secret:
|
||||
|
||||
```powershell
|
||||
[Convert]::ToBase64String([IO.File]::ReadAllBytes(".\private\MrSphay-CodeSigning.pfx"))
|
||||
@@ -32,3 +34,11 @@ https://git.wilkensxl.de/api/packages/MrSphay/generic/modrinth-plus/latest/lates
|
||||
```
|
||||
|
||||
The Windows installer and bundled executables are Authenticode-signed with the MrTrust code-signing certificate. Users who installed MrTrust before installing Modrinth Plus should see the artifacts as signed by the trusted MrSphay certificate chain. MrTrust does not disable Defender, SmartScreen, UAC, or enterprise policy.
|
||||
|
||||
MrTrust itself is intentionally separate from Modrinth Plus. Download the current `MrTrust-<version>.zip` from:
|
||||
|
||||
```text
|
||||
https://git.wilkensxl.de/MrSphay/MrTrust/releases
|
||||
```
|
||||
|
||||
Run `MrTrust.exe` once to install trust for MrSphay-signed apps. Open it again and choose `Remove trust` to reverse that trust.
|
||||
|
||||
Reference in New Issue
Block a user