generated from MrSphay/codex-agent-repository-kit
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a5cea35069 | ||
|
|
f3c353b821 | ||
|
|
d3234e03b8 | ||
| 631a66dab1 | |||
| 16e5d1377c | |||
| 7a2a643d15 | |||
| e885978aba | |||
| d6e2d5ab52 | |||
| 84a5df7216 | |||
| 01148f4703 | |||
| 93ca15a881 |
@@ -10,6 +10,8 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
MRTRUST_VERSION: 0.1.3
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
@@ -24,32 +26,25 @@ jobs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
version="0.1.1"
|
|
||||||
dotnet publish src/MrTrustLauncher.csproj \
|
dotnet publish src/MrTrustLauncher.csproj \
|
||||||
--configuration Release \
|
--configuration Release \
|
||||||
--runtime win-x64 \
|
--runtime win-x64 \
|
||||||
--output dist/build \
|
--output dist/build \
|
||||||
-p:EnableWindowsTargeting=true \
|
-p:EnableWindowsTargeting=true \
|
||||||
-p:PublishSingleFile=true \
|
-p:PublishSingleFile=true \
|
||||||
-p:SelfContained=false
|
-p:SelfContained=true
|
||||||
cp dist/build/MrTrust.exe dist/MrTrust.exe
|
cp dist/build/MrTrust.exe dist/MrTrust.exe
|
||||||
|
|
||||||
- name: Build release ZIP
|
- name: Build release ZIP
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
version="0.1.1"
|
version="${MRTRUST_VERSION}"
|
||||||
package_root="dist/MrTrust-${version}"
|
package_root="dist/MrTrust-${version}"
|
||||||
rm -rf "$package_root" "dist/MrTrust-${version}.zip"
|
rm -rf "$package_root" "dist/MrTrust-${version}.zip"
|
||||||
mkdir -p "$package_root/scripts" "$package_root/assets/certificates" "$package_root/docs"
|
mkdir -p "$package_root"
|
||||||
cp dist/MrTrust.exe "$package_root/"
|
cp dist/MrTrust.exe "$package_root/"
|
||||||
cp MrTrust.ps1 README.md "$package_root/"
|
cp README.md "$package_root/"
|
||||||
cp assets/MrTrust.ico "$package_root/assets/"
|
|
||||||
cp scripts/Install-MrTrust.ps1 scripts/Uninstall-MrTrust.ps1 scripts/Start-MrTrustGui.ps1 "$package_root/scripts/"
|
|
||||||
cp assets/certificates/MrSphay-LocalTrust-Root.cer "$package_root/assets/certificates/"
|
|
||||||
cp assets/certificates/MrSphay-CodeSigning.cer "$package_root/assets/certificates/"
|
|
||||||
cp assets/certificates/thumbprints.txt "$package_root/assets/certificates/"
|
|
||||||
cp docs/security-model.md "$package_root/docs/"
|
|
||||||
(cd dist && zip -r "MrTrust-${version}.zip" "MrTrust-${version}")
|
(cd dist && zip -r "MrTrust-${version}.zip" "MrTrust-${version}")
|
||||||
|
|
||||||
- name: Show package contents
|
- name: Show package contents
|
||||||
@@ -60,5 +55,48 @@ jobs:
|
|||||||
- name: Upload release artifact
|
- name: Upload release artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: MrTrust-0.1.1
|
name: MrTrust-${{ env.MRTRUST_VERSION }}
|
||||||
path: dist/MrTrust-0.1.1.zip
|
path: dist/MrTrust-${{ env.MRTRUST_VERSION }}.zip
|
||||||
|
|
||||||
|
- name: Attach ZIP to Gitea release
|
||||||
|
if: github.ref == 'refs/heads/main'
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
GITEA_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
version="${MRTRUST_VERSION}"
|
||||||
|
asset_name="MrTrust-${version}.zip"
|
||||||
|
api="https://git.wilkensxl.de/api/v1/repos/MrSphay/MrTrust"
|
||||||
|
release_response="$(mktemp)"
|
||||||
|
status="$(curl -sS -o "$release_response" -w "%{http_code}" -H "Authorization: token ${GITEA_TOKEN}" "${api}/releases/tags/v${version}")"
|
||||||
|
if [ "$status" = "404" ]; then
|
||||||
|
release_json="$(VERSION="$version" python3 -c 'import json, os; version = os.environ["VERSION"]; print(json.dumps({"tag_name": f"v{version}", "target_commitish": "main", "name": f"MrTrust v{version}", "body": f"MrTrust v{version} release built by the Gitea runner.", "draft": False, "prerelease": False}))')"
|
||||||
|
curl -fsS \
|
||||||
|
-X POST \
|
||||||
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "$release_json" \
|
||||||
|
"${api}/releases" > "$release_response"
|
||||||
|
elif [ "$status" != "200" ]; then
|
||||||
|
cat "$release_response" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
release_json="$(cat "$release_response")"
|
||||||
|
release_id="$(printf '%s' "$release_json" | python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])')"
|
||||||
|
if [ -z "$release_id" ]; then
|
||||||
|
echo "Could not resolve release id for v${version}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
existing_asset_id="$(RELEASE_JSON="$release_json" ASSET_NAME="$asset_name" python3 -c 'import json, os; release = json.loads(os.environ["RELEASE_JSON"]); asset_name = os.environ["ASSET_NAME"]; print(next((str(asset.get("id", "")) for asset in release.get("assets", []) if asset.get("name") == asset_name), ""))')"
|
||||||
|
if [ -n "$existing_asset_id" ]; then
|
||||||
|
curl -fsS \
|
||||||
|
-X DELETE \
|
||||||
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||||
|
"${api}/releases/${release_id}/assets/${existing_asset_id}"
|
||||||
|
fi
|
||||||
|
curl -fsS \
|
||||||
|
-X POST \
|
||||||
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||||
|
-F "attachment=@dist/${asset_name}" \
|
||||||
|
"${api}/releases/${release_id}/assets?name=${asset_name}"
|
||||||
|
|||||||
@@ -16,8 +16,10 @@ MrTrust manages explicit Windows certificate trust for MrSphay software.
|
|||||||
- `assets/certificates/` contains public certificates only.
|
- `assets/certificates/` contains public certificates only.
|
||||||
- `private/` is ignored and may contain local signing material.
|
- `private/` is ignored and may contain local signing material.
|
||||||
- `docs/integration-prompt.md` is the prompt for adding MrTrust to other projects.
|
- `docs/integration-prompt.md` is the prompt for adding MrTrust to other projects.
|
||||||
|
- `docs/agent-target-integration.md` is the autonomous runbook for agents modifying target projects.
|
||||||
|
- `mrtrust.integration.json` is the machine-readable integration contract.
|
||||||
- `docs/security-model.md` documents the intended behavior and limits.
|
- `docs/security-model.md` documents the intended behavior and limits.
|
||||||
- `MrTrust.ps1 gui` is the user-facing GUI entry point.
|
- `MrTrust.exe` is the user-facing standalone trust installer. The PowerShell scripts are source/build internals.
|
||||||
|
|
||||||
## Verification
|
## Verification
|
||||||
|
|
||||||
|
|||||||
11
CHANGELOG.md
11
CHANGELOG.md
@@ -1,5 +1,16 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 0.1.3
|
||||||
|
|
||||||
|
- Added Ubuntu-runner signing support through `osslsigncode` and PFX secrets.
|
||||||
|
|
||||||
|
## 0.1.2
|
||||||
|
|
||||||
|
- Made `MrTrust.exe` a standalone user-facing release artifact.
|
||||||
|
- Added an autonomous target-project integration runbook for agents.
|
||||||
|
- Added `mrtrust.integration.json` as a machine-readable integration contract.
|
||||||
|
- Updated agent-facing documentation to prefer the standalone `MrTrust.exe` integration path.
|
||||||
|
|
||||||
## 0.1.1
|
## 0.1.1
|
||||||
|
|
||||||
- Added a custom MrTrust application icon and embedded it into the launcher.
|
- Added a custom MrTrust application icon and embedded it into the launcher.
|
||||||
|
|||||||
48
README.md
48
README.md
@@ -13,13 +13,18 @@ MrTrust does not bypass Microsoft Defender or SmartScreen. Windows can still sca
|
|||||||
|
|
||||||
## What It Contains
|
## What It Contains
|
||||||
|
|
||||||
- `MrTrust.ps1 gui` opens a simple Windows interface for installing or removing trust.
|
- `MrTrust.exe` opens a standalone Windows interface for installing or removing trust.
|
||||||
|
- `MrTrust.ps1` and `scripts/` are source and maintainer tools for building, signing, and local development.
|
||||||
- `scripts/New-MrTrustCertificate.ps1` creates a local root certificate and a code-signing certificate for the publisher.
|
- `scripts/New-MrTrustCertificate.ps1` creates a local root certificate and a code-signing certificate for the publisher.
|
||||||
- `scripts/Install-MrTrust.ps1` installs the public trust certificate for the current user or the local machine.
|
- `scripts/Install-MrTrust.ps1` installs the public trust certificate for the current user or the local machine.
|
||||||
- `scripts/Uninstall-MrTrust.ps1` removes the MrTrust certificate again.
|
- `scripts/Uninstall-MrTrust.ps1` removes the MrTrust certificate again.
|
||||||
- `scripts/Sign-MrTrustProject.ps1` signs `.exe`, `.msi`, `.ps1`, and other Authenticode-compatible files.
|
- `scripts/Sign-MrTrustProject.ps1` signs `.exe`, `.msi`, `.ps1`, and other Authenticode-compatible files.
|
||||||
|
- `scripts/Sign-MrTrustProjectLinux.sh` signs Windows PE/MSI/CAT artifacts on Ubuntu Gitea runners with `osslsigncode`.
|
||||||
- `scripts/New-MrTrustRelease.ps1` builds a distributable ZIP package.
|
- `scripts/New-MrTrustRelease.ps1` builds a distributable ZIP package.
|
||||||
- `docs/integration-prompt.md` is a prompt you can paste into other Windows projects.
|
- `docs/integration-prompt.md` is a prompt you can paste into other Windows projects.
|
||||||
|
- `docs/agent-target-integration.md` is the autonomous target-project integration runbook for agents.
|
||||||
|
- `mrtrust.integration.json` is the machine-readable integration contract.
|
||||||
|
- `MrTrust.exe` is standalone for normal users. It embeds the public certificates and runtime scripts.
|
||||||
|
|
||||||
## Quick Start For MrSphay
|
## Quick Start For MrSphay
|
||||||
|
|
||||||
@@ -65,25 +70,14 @@ Remove the trust certificate:
|
|||||||
Build a user-facing ZIP release:
|
Build a user-facing ZIP release:
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
.\scripts\New-MrTrustRelease.ps1 -Version 0.1.1
|
.\scripts\New-MrTrustRelease.ps1 -Version 0.1.3
|
||||||
```
|
```
|
||||||
|
|
||||||
The Gitea workflow `.gitea/workflows/build.yml` builds the Windows launcher EXE on an `ubuntu-latest` runner with .NET Windows cross-targeting, then uploads the ZIP as an artifact.
|
The Gitea workflow `.gitea/workflows/build.yml` builds the Windows launcher EXE on an `ubuntu-latest` runner with .NET Windows cross-targeting, then uploads the ZIP as an artifact.
|
||||||
|
|
||||||
## User Installation
|
## User Installation
|
||||||
|
|
||||||
For normal users, distribute MrTrust with the public certificate file:
|
For normal users, distribute `MrTrust.exe`. The executable embeds the public certificate files and opens the GUI by default.
|
||||||
|
|
||||||
```text
|
|
||||||
assets\certificates\MrSphay-LocalTrust-Root.cer
|
|
||||||
assets\certificates\MrSphay-CodeSigning.cer
|
|
||||||
```
|
|
||||||
|
|
||||||
The user runs:
|
|
||||||
|
|
||||||
```powershell
|
|
||||||
.\MrTrust.ps1 gui
|
|
||||||
```
|
|
||||||
|
|
||||||
By default, MrTrust installs trust only for the current Windows user:
|
By default, MrTrust installs trust only for the current Windows user:
|
||||||
|
|
||||||
@@ -95,18 +89,34 @@ Code-signing certificate -> Cert:\CurrentUser\TrustedPublisher
|
|||||||
For all users on the machine, run PowerShell as Administrator:
|
For all users on the machine, run PowerShell as Administrator:
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
.\MrTrust.ps1 install -Scope LocalMachine
|
.\MrTrust.exe
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Then choose the all-users option in the GUI.
|
||||||
|
|
||||||
## Using This Repo With Other Agents
|
## Using This Repo With Other Agents
|
||||||
|
|
||||||
Yes. Give another agent this repository URL and the target Windows project, then paste `docs/integration-prompt.md`.
|
Yes. Give another agent this repository URL, the target Windows project, and `docs/integration-prompt.md`.
|
||||||
|
|
||||||
|
For autonomous work, the agent should read these files in order:
|
||||||
|
|
||||||
|
1. `mrtrust.integration.json`
|
||||||
|
2. `docs/agent-target-integration.md`
|
||||||
|
3. `docs/integration-prompt.md`
|
||||||
|
|
||||||
|
The agent's job is to modify the target project, not this repository:
|
||||||
|
|
||||||
|
- expose a visible "Open MrTrust" or trust setup path for users
|
||||||
|
- link to or bundle the standalone `MrTrust.exe`
|
||||||
|
- sign Windows release artifacts with the MrSphay code-signing certificate
|
||||||
|
- keep trust installation explicit, reversible, and user-confirmed
|
||||||
|
- keep private signing material out of the target repository and release artifacts
|
||||||
|
|
||||||
Both sides have to be wired:
|
Both sides have to be wired:
|
||||||
|
|
||||||
- MrTrust side: users install the public trust certificates once.
|
- MrTrust side: users install the public trust certificates once.
|
||||||
- Target project side: release artifacts are signed with the MrSphay code-signing certificate.
|
- Target project side: release artifacts are signed with the MrSphay code-signing certificate.
|
||||||
- Installer side, optional: the target app can offer "Open MrTrust" or bundle the MrTrust ZIP, but it must not silently change trust.
|
- Installer side, optional: the target app can offer "Open MrTrust" or bundle `MrTrust.exe`, but it must not silently change trust.
|
||||||
|
|
||||||
If the target project is not signed, MrTrust cannot make it trusted.
|
If the target project is not signed, MrTrust cannot make it trusted.
|
||||||
|
|
||||||
@@ -119,4 +129,6 @@ If the target project is not signed, MrTrust cannot make it trusted.
|
|||||||
|
|
||||||
## Recommended Project Integration
|
## Recommended Project Integration
|
||||||
|
|
||||||
Use `docs/integration-prompt.md` in another Windows project. The prompt tells Codex or another assistant to add a visible trust check, a link or bundled copy of MrTrust, and a signing step without hiding security changes from the user.
|
Use `docs/integration-prompt.md` in another Windows project. The prompt tells Codex or another assistant to add a visible trust check, a link or bundled copy of the standalone `MrTrust.exe`, and a signing step without hiding security changes from the user.
|
||||||
|
|
||||||
|
For agents that can inspect files autonomously, `docs/agent-target-integration.md` gives the decision tree, installer patterns, signing commands, and completion checklist.
|
||||||
|
|||||||
209
docs/agent-target-integration.md
Normal file
209
docs/agent-target-integration.md
Normal file
@@ -0,0 +1,209 @@
|
|||||||
|
# Agent Target Integration Runbook
|
||||||
|
|
||||||
|
Use this file when you are an agent modifying another Windows project to support MrTrust.
|
||||||
|
|
||||||
|
## Non-Negotiable Goal
|
||||||
|
|
||||||
|
Modify the target project so that, after a user has installed trust with `MrTrust.exe`, the target project's MrSphay-signed Windows release artifacts start and validate normally.
|
||||||
|
|
||||||
|
Do not modify Windows security policy, Defender, SmartScreen, UAC, or certificate stores silently. MrTrust must remain visible, optional, and reversible.
|
||||||
|
|
||||||
|
## Inputs To Read First
|
||||||
|
|
||||||
|
1. Read `mrtrust.integration.json`.
|
||||||
|
2. Read `docs/integration-prompt.md`.
|
||||||
|
3. Inspect the target project for:
|
||||||
|
- build commands
|
||||||
|
- release artifact paths
|
||||||
|
- installer technology
|
||||||
|
- existing signing steps
|
||||||
|
- user-facing docs
|
||||||
|
- CI workflows
|
||||||
|
|
||||||
|
If the target project already has equivalent trust or signing integration, update it instead of duplicating it.
|
||||||
|
|
||||||
|
## Required Target Project Changes
|
||||||
|
|
||||||
|
Apply every item that fits the target project:
|
||||||
|
|
||||||
|
1. Add a user-facing MrTrust entry point.
|
||||||
|
- If the project has an installer, add an optional action named `Open MrTrust` or `Trust MrSphay signed apps`.
|
||||||
|
- If the project has an app settings/about/help screen, add a button or menu item that launches `MrTrust.exe`.
|
||||||
|
- If the project has no UI or installer, add release documentation linking to or bundling `MrTrust.exe`.
|
||||||
|
|
||||||
|
2. Bundle or link the standalone executable.
|
||||||
|
- Preferred bundled path: `MrTrust\MrTrust.exe`.
|
||||||
|
- Source repository: `https://git.wilkensxl.de/MrSphay/MrTrust`.
|
||||||
|
- Release page: `https://git.wilkensxl.de/MrSphay/MrTrust/releases`.
|
||||||
|
- Do not require users to run `MrTrust.ps1`.
|
||||||
|
- Do not copy MrTrust source scripts into user-facing release output unless the target project explicitly ships source.
|
||||||
|
|
||||||
|
3. Add signing for Windows artifacts.
|
||||||
|
- Sign `.exe`, `.msi`, `.dll`, `.ps1`, `.psm1`, `.psd1`, and `.cat` release artifacts.
|
||||||
|
- Use the public thumbprint from `mrtrust.integration.json`.
|
||||||
|
- Only run signing where private signing material is securely available.
|
||||||
|
- Do not commit `.pfx`, private keys, passwords, tokens, or signing secrets.
|
||||||
|
- On the available `ubuntu-latest` Gitea runners, use `osslsigncode` with PFX secrets for `.exe`, `.dll`, `.msi`, and `.cat`.
|
||||||
|
- PowerShell script signing (`.ps1`, `.psm1`, `.psd1`) still requires a Windows signing environment. If no Windows runner exists, document that limitation instead of blocking PE/MSI signing.
|
||||||
|
|
||||||
|
4. Add verification.
|
||||||
|
- Verify the target project still builds.
|
||||||
|
- Verify the release output contains the app artifacts and either `MrTrust.exe` or clear MrTrust download instructions.
|
||||||
|
- Verify signing status where the OS/tooling is available.
|
||||||
|
- Verify no private signing material is tracked or present in release output.
|
||||||
|
|
||||||
|
## Default Commands
|
||||||
|
|
||||||
|
Open MrTrust from a bundled release:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
.\MrTrust\MrTrust.exe
|
||||||
|
```
|
||||||
|
|
||||||
|
Sign one artifact from a Windows release runner:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
.\MrTrust\MrTrust.exe sign -Path .\dist\App.exe -CertificateThumbprint A024A89200469F099EC4A172B4F96F6428AFD41B
|
||||||
|
```
|
||||||
|
|
||||||
|
Sign a release directory:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
.\MrTrust\MrTrust.exe sign -Path .\dist -CertificateThumbprint A024A89200469F099EC4A172B4F96F6428AFD41B
|
||||||
|
```
|
||||||
|
|
||||||
|
Check a signature:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
Get-AuthenticodeSignature .\dist\App.exe | Format-List Status,SignerCertificate,StatusMessage
|
||||||
|
```
|
||||||
|
|
||||||
|
Sign a release directory on an Ubuntu Gitea runner:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash ./MrTrust/scripts/Sign-MrTrustProjectLinux.sh ./dist
|
||||||
|
```
|
||||||
|
|
||||||
|
## Installer Patterns
|
||||||
|
|
||||||
|
### Inno Setup
|
||||||
|
|
||||||
|
Bundle `MrTrust.exe` and add an optional task or post-install action:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[Files]
|
||||||
|
Source: "MrTrust\MrTrust.exe"; DestDir: "{app}\MrTrust"; Flags: ignoreversion
|
||||||
|
|
||||||
|
[Run]
|
||||||
|
Filename: "{app}\MrTrust\MrTrust.exe"; Description: "Open MrTrust"; Flags: postinstall skipifsilent nowait
|
||||||
|
```
|
||||||
|
|
||||||
|
### NSIS
|
||||||
|
|
||||||
|
```nsis
|
||||||
|
SetOutPath "$INSTDIR\MrTrust"
|
||||||
|
File "MrTrust\MrTrust.exe"
|
||||||
|
CreateShortcut "$SMPROGRAMS\$StartMenuFolder\Open MrTrust.lnk" "$INSTDIR\MrTrust\MrTrust.exe"
|
||||||
|
```
|
||||||
|
|
||||||
|
### WiX
|
||||||
|
|
||||||
|
Install `MrTrust.exe` as a regular file under an application `MrTrust` folder and expose a Start Menu shortcut or installer UI action. Do not run it silently during install.
|
||||||
|
|
||||||
|
### Electron Builder
|
||||||
|
|
||||||
|
Add `MrTrust\MrTrust.exe` to `extraResources`, then add a Help/About action that launches the copied executable with the platform shell API. Keep the action user-initiated.
|
||||||
|
|
||||||
|
### Portable ZIP
|
||||||
|
|
||||||
|
Place `MrTrust.exe` next to the app under:
|
||||||
|
|
||||||
|
```text
|
||||||
|
MrTrust\MrTrust.exe
|
||||||
|
```
|
||||||
|
|
||||||
|
Document that users should run it once before launching signed MrSphay apps if Windows does not yet trust the publisher.
|
||||||
|
|
||||||
|
## CI Signing Patterns
|
||||||
|
|
||||||
|
### Gitea Actions On Ubuntu Runner
|
||||||
|
|
||||||
|
Use this when only `ubuntu-latest`, `ubuntu-24.04`, or `ubuntu-22.04` runners are available.
|
||||||
|
|
||||||
|
Required Gitea secrets:
|
||||||
|
|
||||||
|
```text
|
||||||
|
MRTRUST_CODESIGN_PFX_BASE64
|
||||||
|
MRTRUST_CODESIGN_PFX_PASSWORD
|
||||||
|
```
|
||||||
|
|
||||||
|
Create `MRTRUST_CODESIGN_PFX_BASE64` locally from the private `.pfx`:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
[Convert]::ToBase64String([IO.File]::ReadAllBytes(".\private\MrSphay-CodeSigning.pfx")) | Set-Clipboard
|
||||||
|
```
|
||||||
|
|
||||||
|
Then paste the clipboard value into the Gitea secret. Do not commit the `.pfx` or the base64 value.
|
||||||
|
|
||||||
|
Ubuntu workflow step:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Install signing tool
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y osslsigncode
|
||||||
|
|
||||||
|
- name: Sign Windows artifacts
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
MRTRUST_CODESIGN_PFX_BASE64: ${{ secrets.MRTRUST_CODESIGN_PFX_BASE64 }}
|
||||||
|
MRTRUST_CODESIGN_PFX_PASSWORD: ${{ secrets.MRTRUST_CODESIGN_PFX_PASSWORD }}
|
||||||
|
run: |
|
||||||
|
bash ./MrTrust/scripts/Sign-MrTrustProjectLinux.sh ./dist
|
||||||
|
```
|
||||||
|
|
||||||
|
This signs `.exe`, `.dll`, `.msi`, and `.cat` artifacts. It does not sign PowerShell script files.
|
||||||
|
|
||||||
|
### Gitea Actions On Windows Runner
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Sign Windows artifacts
|
||||||
|
shell: powershell
|
||||||
|
run: |
|
||||||
|
.\MrTrust\MrTrust.exe sign -Path .\dist -CertificateThumbprint A024A89200469F099EC4A172B4F96F6428AFD41B
|
||||||
|
```
|
||||||
|
|
||||||
|
Use this only on a runner where the matching private code-signing certificate is installed in `Cert:\CurrentUser\My` or `Cert:\LocalMachine\My`.
|
||||||
|
|
||||||
|
### Local Secure Release Machine
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
.\MrTrust\MrTrust.exe sign -Path .\dist -CertificateThumbprint A024A89200469F099EC4A172B4F96F6428AFD41B
|
||||||
|
```
|
||||||
|
|
||||||
|
Run this after build and before packaging.
|
||||||
|
|
||||||
|
## Autonomy Rules
|
||||||
|
|
||||||
|
Make reasonable target-project-specific choices without asking the user when:
|
||||||
|
|
||||||
|
- artifact paths are discoverable from existing build scripts
|
||||||
|
- installer technology is obvious from repository files
|
||||||
|
- there is already a docs or release notes location
|
||||||
|
- CI already has a Windows release job you can extend
|
||||||
|
|
||||||
|
Stop and ask the user only when:
|
||||||
|
|
||||||
|
- signing requires a private certificate that is not present and no secret mechanism exists
|
||||||
|
- the target project has multiple conflicting release systems and no primary release path is identifiable
|
||||||
|
- a requested change would silently alter trust or weaken security policy
|
||||||
|
|
||||||
|
## Completion Checklist
|
||||||
|
|
||||||
|
- Target project has a visible MrTrust user path.
|
||||||
|
- Target project links to or bundles standalone `MrTrust.exe`.
|
||||||
|
- Supported Windows release artifacts are signed or the blocker is explicitly documented.
|
||||||
|
- User docs explain install and remove trust.
|
||||||
|
- No private signing material is committed.
|
||||||
|
- Target project build/release verification ran, or the exact blocker is documented.
|
||||||
@@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
Use this prompt in another Windows project when you want Codex or another agent to add MrTrust support.
|
Use this prompt in another Windows project when you want Codex or another agent to add MrTrust support.
|
||||||
|
|
||||||
|
Before changing the target project, read:
|
||||||
|
- `mrtrust.integration.json`
|
||||||
|
- `docs/agent-target-integration.md`
|
||||||
|
|
||||||
```text
|
```text
|
||||||
Integrate MrTrust support into this Windows project.
|
Integrate MrTrust support into this Windows project.
|
||||||
|
|
||||||
@@ -10,22 +14,33 @@ Goal:
|
|||||||
- The project must not disable Defender, SmartScreen, UAC, or Windows security policy.
|
- The project must not disable Defender, SmartScreen, UAC, or Windows security policy.
|
||||||
- All trust changes must be visible and require explicit user confirmation.
|
- All trust changes must be visible and require explicit user confirmation.
|
||||||
|
|
||||||
|
Agent contract:
|
||||||
|
- You are modifying the target Windows project, not MrTrust itself.
|
||||||
|
- Use `mrtrust.integration.json` and `docs/agent-target-integration.md` as the authoritative integration contract.
|
||||||
|
- Add MrTrust as a visible, optional trust-onboarding path for users.
|
||||||
|
- Add or update the target project's release/signing pipeline so produced Windows artifacts are signed.
|
||||||
|
- Do not mark the task complete after only copying documentation. The target project needs user-facing integration and signing support where applicable.
|
||||||
|
|
||||||
Implementation requirements:
|
Implementation requirements:
|
||||||
- Add a docs section that explains MrTrust and links to or bundles the MrTrust release ZIP.
|
- Add a docs section that explains MrTrust and links to or bundles the MrTrust release ZIP.
|
||||||
|
- Treat `MrTrust.exe` from the release ZIP as the user-facing integration point. Do not require users to copy or run MrTrust PowerShell source files.
|
||||||
- Add a build or release signing step that signs Windows artifacts with the MrSphay code-signing certificate.
|
- Add a build or release signing step that signs Windows artifacts with the MrSphay code-signing certificate.
|
||||||
- Do not commit any .pfx file, private key, certificate password, or signing secret.
|
- Do not commit any .pfx file, private key, certificate password, or signing secret.
|
||||||
- If the project has an installer, add an optional "Open MrTrust" action that runs:
|
- If the project has an installer, add an optional "Open MrTrust" action that runs:
|
||||||
powershell.exe -ExecutionPolicy Bypass -File .\MrTrust\MrTrust.ps1 gui
|
.\MrTrust\MrTrust.exe
|
||||||
- Prefer CurrentUser certificate installation by default.
|
- Prefer CurrentUser certificate installation by default.
|
||||||
- Only offer LocalMachine installation when the user explicitly chooses an all-users install and the process is elevated.
|
- Only offer LocalMachine installation when the user explicitly chooses an all-users install and the process is elevated.
|
||||||
- Add an uninstall path or documentation that runs:
|
- Add an uninstall path or documentation that opens MrTrust again and tells the user to choose "Remove trust".
|
||||||
powershell.exe -ExecutionPolicy Bypass -File .\MrTrust\MrTrust.ps1 uninstall
|
|
||||||
- Keep the UI wording clear: the user is trusting MrSphay signed software, not bypassing Windows security.
|
- Keep the UI wording clear: the user is trusting MrSphay signed software, not bypassing Windows security.
|
||||||
- If this project produces an .exe, .msi, .dll, .ps1, .psm1, .psd1, or .cat release artifact, sign it with:
|
- If this project produces an .exe, .msi, .dll, or .cat release artifact on an Ubuntu Gitea runner, sign it with:
|
||||||
powershell.exe -ExecutionPolicy Bypass -File .\MrTrust\MrTrust.ps1 sign -Path <artifact-path> -CertificateThumbprint A024A89200469F099EC4A172B4F96F6428AFD41B
|
bash ./MrTrust/scripts/Sign-MrTrustProjectLinux.sh <artifact-path>
|
||||||
- Treat the certificate thumbprint as public metadata, but never commit private signing material.
|
- Treat the certificate thumbprint as public metadata, but never commit private signing material.
|
||||||
|
- Configure Gitea secrets `MRTRUST_CODESIGN_PFX_BASE64` and `MRTRUST_CODESIGN_PFX_PASSWORD` for Ubuntu runner signing.
|
||||||
|
- If the target project needs .ps1, .psm1, or .psd1 signing, use a Windows signing environment or document that script signing is not available on the current Ubuntu-only runners.
|
||||||
|
- Do not put private signing material into the target repository or user-facing release ZIP.
|
||||||
|
|
||||||
Verification:
|
Verification:
|
||||||
|
- Confirm the target project's user-facing release contains either a link to the MrTrust release ZIP or a bundled copy of `MrTrust.exe`.
|
||||||
- Confirm unsigned builds still show as unsigned.
|
- Confirm unsigned builds still show as unsigned.
|
||||||
- Confirm signed builds validate after MrTrust installation.
|
- Confirm signed builds validate after MrTrust installation.
|
||||||
- Confirm the MrTrust certificate can be removed again.
|
- Confirm the MrTrust certificate can be removed again.
|
||||||
|
|||||||
@@ -1,7 +1,16 @@
|
|||||||
{
|
{
|
||||||
"name": "codex-agent-repository-kit",
|
"name": "codex-agent-repository-kit",
|
||||||
"version": "1.0.5",
|
"version": "1.0.6",
|
||||||
"description": "Universal repository baseline for Codex-assisted projects.",
|
"description": "Universal repository baseline for Codex-assisted projects.",
|
||||||
|
"mrtrustIntegration": {
|
||||||
|
"contract": "mrtrust.integration.json",
|
||||||
|
"agentRunbook": "docs/agent-target-integration.md",
|
||||||
|
"prompt": "docs/integration-prompt.md",
|
||||||
|
"standaloneExecutable": "MrTrust.exe",
|
||||||
|
"publicThumbprint": "A024A89200469F099EC4A172B4F96F6428AFD41B",
|
||||||
|
"sourceRepository": "https://git.wilkensxl.de/MrSphay/MrTrust",
|
||||||
|
"releasePage": "https://git.wilkensxl.de/MrSphay/MrTrust/releases"
|
||||||
|
},
|
||||||
"agentResponsibilities": [
|
"agentResponsibilities": [
|
||||||
"Read manifest.json before copying files.",
|
"Read manifest.json before copying files.",
|
||||||
"Use copyMap target paths unless the repository already has an equivalent convention.",
|
"Use copyMap target paths unless the repository already has an equivalent convention.",
|
||||||
|
|||||||
@@ -13,6 +13,34 @@
|
|||||||
"description": {
|
"description": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"mrtrustIntegration": {
|
||||||
|
"type": "object",
|
||||||
|
"required": ["contract", "agentRunbook", "prompt", "standaloneExecutable", "publicThumbprint"],
|
||||||
|
"properties": {
|
||||||
|
"contract": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"agentRunbook": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"prompt": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"standaloneExecutable": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"publicThumbprint": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"sourceRepository": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"releasePage": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": true
|
||||||
|
},
|
||||||
"agentResponsibilities": {
|
"agentResponsibilities": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
|
|||||||
86
mrtrust.integration.json
Normal file
86
mrtrust.integration.json
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
{
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"name": "MrTrust",
|
||||||
|
"purpose": "Add explicit MrSphay trust onboarding and signing support to Windows target projects.",
|
||||||
|
"sourceRepository": "https://git.wilkensxl.de/MrSphay/MrTrust",
|
||||||
|
"releasePage": "https://git.wilkensxl.de/MrSphay/MrTrust/releases",
|
||||||
|
"userFacingReleaseArtifact": {
|
||||||
|
"fileName": "MrTrust.exe",
|
||||||
|
"releaseZipNamePattern": "MrTrust-<version>.zip",
|
||||||
|
"recommendedBundledPath": "MrTrust\\MrTrust.exe",
|
||||||
|
"distribution": "Bundle this file directly or link to the MrTrust release ZIP.",
|
||||||
|
"launchCommand": ".\\MrTrust\\MrTrust.exe",
|
||||||
|
"removeTrustInstruction": "Open MrTrust and choose Remove trust."
|
||||||
|
},
|
||||||
|
"certificate": {
|
||||||
|
"publisher": "MrSphay",
|
||||||
|
"publicThumbprint": "A024A89200469F099EC4A172B4F96F6428AFD41B",
|
||||||
|
"defaultTrustScope": "CurrentUser",
|
||||||
|
"allUsersTrustScope": "LocalMachine",
|
||||||
|
"privateMaterialPolicy": "Never commit .pfx files, private keys, passwords, tokens, or signing secrets."
|
||||||
|
},
|
||||||
|
"signing": {
|
||||||
|
"supportedExtensions": [
|
||||||
|
".exe",
|
||||||
|
".msi",
|
||||||
|
".dll",
|
||||||
|
".ps1",
|
||||||
|
".psm1",
|
||||||
|
".psd1",
|
||||||
|
".cat"
|
||||||
|
],
|
||||||
|
"ubuntuRunner": {
|
||||||
|
"supportedExtensions": [
|
||||||
|
".exe",
|
||||||
|
".msi",
|
||||||
|
".dll",
|
||||||
|
".cat"
|
||||||
|
],
|
||||||
|
"requiredTool": "osslsigncode",
|
||||||
|
"helperScript": "scripts/Sign-MrTrustProjectLinux.sh",
|
||||||
|
"requiredSecrets": [
|
||||||
|
"MRTRUST_CODESIGN_PFX_BASE64",
|
||||||
|
"MRTRUST_CODESIGN_PFX_PASSWORD"
|
||||||
|
],
|
||||||
|
"preferredCommand": "bash ./MrTrust/scripts/Sign-MrTrustProjectLinux.sh <artifact-path>"
|
||||||
|
},
|
||||||
|
"windowsRunner": {
|
||||||
|
"supportedExtensions": [
|
||||||
|
".exe",
|
||||||
|
".msi",
|
||||||
|
".dll",
|
||||||
|
".ps1",
|
||||||
|
".psm1",
|
||||||
|
".psd1",
|
||||||
|
".cat"
|
||||||
|
],
|
||||||
|
"preferredCommand": ".\\MrTrust\\MrTrust.exe sign -Path <artifact-path> -CertificateThumbprint A024A89200469F099EC4A172B4F96F6428AFD41B"
|
||||||
|
},
|
||||||
|
"preferredCommand": "bash ./MrTrust/scripts/Sign-MrTrustProjectLinux.sh <artifact-path>",
|
||||||
|
"ciGuidance": "On ubuntu-latest runners, sign PE/MSI/CAT artifacts with osslsigncode using a PFX stored in Gitea secrets. Use Windows runners only when signing PowerShell scripts or when Windows certificate store signing is required.",
|
||||||
|
"unsignedBehavior": "Unsigned builds should remain unsigned. MrTrust only makes correctly signed MrSphay artifacts validate after the user has installed trust."
|
||||||
|
},
|
||||||
|
"targetProjectAgentContract": {
|
||||||
|
"modifyTargetProject": true,
|
||||||
|
"requiredOutcomes": [
|
||||||
|
"Expose a visible optional Open MrTrust or trust setup path.",
|
||||||
|
"Link to or bundle the standalone MrTrust.exe.",
|
||||||
|
"Sign Windows release artifacts when the target project produces supported artifact types.",
|
||||||
|
"Document how users install and remove MrTrust trust.",
|
||||||
|
"Verify no private signing material is present in the target repository or release artifacts."
|
||||||
|
],
|
||||||
|
"forbiddenOutcomes": [
|
||||||
|
"Do not silently install certificates.",
|
||||||
|
"Do not bypass Defender, SmartScreen, UAC, firewall, or Windows security policy.",
|
||||||
|
"Do not claim MrTrust makes unsigned software trusted.",
|
||||||
|
"Do not commit private signing material."
|
||||||
|
],
|
||||||
|
"fallbackWhenNoInstallerExists": [
|
||||||
|
"Add release documentation that links to or bundles MrTrust.exe.",
|
||||||
|
"Add a release signing step for supported Windows artifacts.",
|
||||||
|
"Add verification notes explaining that the app starts normally after the user installs MrTrust and the artifact signature validates."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"agentRunbook": "docs/agent-target-integration.md",
|
||||||
|
"prompt": "docs/integration-prompt.md"
|
||||||
|
}
|
||||||
@@ -16,6 +16,22 @@ $sourcePath = Join-Path $root "src\MrTrustLauncher.cs"
|
|||||||
$iconPath = Join-Path $root "assets\MrTrust.ico"
|
$iconPath = Join-Path $root "assets\MrTrust.ico"
|
||||||
$resolvedOutputPath = Resolve-FullPath $OutputPath
|
$resolvedOutputPath = Resolve-FullPath $OutputPath
|
||||||
$outputDirectory = Split-Path -Parent $resolvedOutputPath
|
$outputDirectory = Split-Path -Parent $resolvedOutputPath
|
||||||
|
$payloadFiles = @(
|
||||||
|
@{ Path = "MrTrust.ps1"; ResourceName = "MrTrust.Payload.MrTrust.ps1" },
|
||||||
|
@{ Path = "scripts\Build-MrTrustExe.ps1"; ResourceName = "MrTrust.Payload.scripts.Build-MrTrustExe.ps1" },
|
||||||
|
@{ Path = "scripts\Install-MrTrust.ps1"; ResourceName = "MrTrust.Payload.scripts.Install-MrTrust.ps1" },
|
||||||
|
@{ Path = "scripts\New-MrTrustCertificate.ps1"; ResourceName = "MrTrust.Payload.scripts.New-MrTrustCertificate.ps1" },
|
||||||
|
@{ Path = "scripts\New-MrTrustIcon.ps1"; ResourceName = "MrTrust.Payload.scripts.New-MrTrustIcon.ps1" },
|
||||||
|
@{ Path = "scripts\New-MrTrustRelease.ps1"; ResourceName = "MrTrust.Payload.scripts.New-MrTrustRelease.ps1" },
|
||||||
|
@{ Path = "scripts\Sign-MrTrustProject.ps1"; ResourceName = "MrTrust.Payload.scripts.Sign-MrTrustProject.ps1" },
|
||||||
|
@{ Path = "scripts\Sign-MrTrustProjectLinux.sh"; ResourceName = "MrTrust.Payload.scripts.Sign-MrTrustProjectLinux.sh" },
|
||||||
|
@{ Path = "scripts\Start-MrTrustGui.ps1"; ResourceName = "MrTrust.Payload.scripts.Start-MrTrustGui.ps1" },
|
||||||
|
@{ Path = "scripts\Uninstall-MrTrust.ps1"; ResourceName = "MrTrust.Payload.scripts.Uninstall-MrTrust.ps1" },
|
||||||
|
@{ Path = "assets\MrTrust.ico"; ResourceName = "MrTrust.Payload.assets.MrTrust.ico" },
|
||||||
|
@{ Path = "assets\certificates\MrSphay-LocalTrust-Root.cer"; ResourceName = "MrTrust.Payload.assets.certificates.MrSphay-LocalTrust-Root.cer" },
|
||||||
|
@{ Path = "assets\certificates\MrSphay-CodeSigning.cer"; ResourceName = "MrTrust.Payload.assets.certificates.MrSphay-CodeSigning.cer" },
|
||||||
|
@{ Path = "assets\certificates\thumbprints.txt"; ResourceName = "MrTrust.Payload.assets.certificates.thumbprints.txt" }
|
||||||
|
)
|
||||||
|
|
||||||
if (-not (Test-Path -LiteralPath $sourcePath)) {
|
if (-not (Test-Path -LiteralPath $sourcePath)) {
|
||||||
throw "Launcher source not found: $sourcePath"
|
throw "Launcher source not found: $sourcePath"
|
||||||
@@ -25,6 +41,13 @@ if (-not (Test-Path -LiteralPath $iconPath)) {
|
|||||||
& (Join-Path $root "scripts\New-MrTrustIcon.ps1") -OutputPath $iconPath
|
& (Join-Path $root "scripts\New-MrTrustIcon.ps1") -OutputPath $iconPath
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach ($payloadFile in $payloadFiles) {
|
||||||
|
$payloadPath = Join-Path $root $payloadFile.Path
|
||||||
|
if (-not (Test-Path -LiteralPath $payloadPath)) {
|
||||||
|
throw "Payload file not found: $payloadPath"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
New-Item -ItemType Directory -Force -Path $outputDirectory | Out-Null
|
New-Item -ItemType Directory -Force -Path $outputDirectory | Out-Null
|
||||||
|
|
||||||
$compilerCandidates = @(
|
$compilerCandidates = @(
|
||||||
@@ -37,20 +60,29 @@ if (-not $compiler) {
|
|||||||
throw "csc.exe was not found. Run this build on a Windows Gitea runner with .NET Framework installed."
|
throw "csc.exe was not found. Run this build on a Windows Gitea runner with .NET Framework installed."
|
||||||
}
|
}
|
||||||
|
|
||||||
& $compiler `
|
$compilerArguments = @(
|
||||||
/nologo `
|
"/nologo",
|
||||||
/target:winexe `
|
"/target:winexe",
|
||||||
/optimize+ `
|
"/optimize+",
|
||||||
/platform:anycpu `
|
"/platform:anycpu",
|
||||||
/out:$resolvedOutputPath `
|
"/out:$resolvedOutputPath",
|
||||||
/win32icon:$iconPath `
|
"/win32icon:$iconPath",
|
||||||
/reference:System.Windows.Forms.dll `
|
"/reference:System.Windows.Forms.dll",
|
||||||
/reference:System.Drawing.dll `
|
"/reference:System.Drawing.dll"
|
||||||
$sourcePath
|
)
|
||||||
|
|
||||||
|
foreach ($payloadFile in $payloadFiles) {
|
||||||
|
$payloadPath = Join-Path $root $payloadFile.Path
|
||||||
|
$compilerArguments += "/resource:$payloadPath,$($payloadFile.ResourceName)"
|
||||||
|
}
|
||||||
|
|
||||||
|
$compilerArguments += $sourcePath
|
||||||
|
|
||||||
|
& $compiler @compilerArguments
|
||||||
|
|
||||||
if ($LASTEXITCODE -ne 0) {
|
if ($LASTEXITCODE -ne 0) {
|
||||||
throw "csc.exe failed with exit code $LASTEXITCODE."
|
throw "csc.exe failed with exit code $LASTEXITCODE."
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Host "Created EXE:"
|
Write-Host "Created standalone EXE:"
|
||||||
Write-Host " $resolvedOutputPath"
|
Write-Host " $resolvedOutputPath"
|
||||||
|
|||||||
@@ -27,9 +27,6 @@ if (Test-Path -LiteralPath $packageRoot) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
New-Item -ItemType Directory -Force -Path $packageRoot | Out-Null
|
New-Item -ItemType Directory -Force -Path $packageRoot | Out-Null
|
||||||
New-Item -ItemType Directory -Force -Path (Join-Path $packageRoot "scripts") | Out-Null
|
|
||||||
New-Item -ItemType Directory -Force -Path (Join-Path $packageRoot "assets\certificates") | Out-Null
|
|
||||||
New-Item -ItemType Directory -Force -Path (Join-Path $packageRoot "docs") | Out-Null
|
|
||||||
|
|
||||||
if (-not (Test-Path -LiteralPath $iconPath)) {
|
if (-not (Test-Path -LiteralPath $iconPath)) {
|
||||||
& (Join-Path $root "scripts\New-MrTrustIcon.ps1") -OutputPath $iconPath
|
& (Join-Path $root "scripts\New-MrTrustIcon.ps1") -OutputPath $iconPath
|
||||||
@@ -55,16 +52,7 @@ if ($SigningThumbprint) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Copy-Item -LiteralPath $exePath -Destination $packageRoot
|
Copy-Item -LiteralPath $exePath -Destination $packageRoot
|
||||||
Copy-Item -LiteralPath (Join-Path $root "MrTrust.ps1") -Destination $packageRoot
|
|
||||||
Copy-Item -LiteralPath (Join-Path $root "README.md") -Destination $packageRoot
|
Copy-Item -LiteralPath (Join-Path $root "README.md") -Destination $packageRoot
|
||||||
Copy-Item -LiteralPath $iconPath -Destination (Join-Path $packageRoot "assets")
|
|
||||||
Copy-Item -LiteralPath (Join-Path $root "scripts\Install-MrTrust.ps1") -Destination (Join-Path $packageRoot "scripts")
|
|
||||||
Copy-Item -LiteralPath (Join-Path $root "scripts\Uninstall-MrTrust.ps1") -Destination (Join-Path $packageRoot "scripts")
|
|
||||||
Copy-Item -LiteralPath (Join-Path $root "scripts\Start-MrTrustGui.ps1") -Destination (Join-Path $packageRoot "scripts")
|
|
||||||
Copy-Item -LiteralPath (Join-Path $root "assets\certificates\MrSphay-LocalTrust-Root.cer") -Destination (Join-Path $packageRoot "assets\certificates")
|
|
||||||
Copy-Item -LiteralPath (Join-Path $root "assets\certificates\MrSphay-CodeSigning.cer") -Destination (Join-Path $packageRoot "assets\certificates")
|
|
||||||
Copy-Item -LiteralPath (Join-Path $root "assets\certificates\thumbprints.txt") -Destination (Join-Path $packageRoot "assets\certificates")
|
|
||||||
Copy-Item -LiteralPath (Join-Path $root "docs\security-model.md") -Destination (Join-Path $packageRoot "docs")
|
|
||||||
|
|
||||||
if (Test-Path -LiteralPath $zipPath) {
|
if (Test-Path -LiteralPath $zipPath) {
|
||||||
Remove-Item -LiteralPath $zipPath -Force
|
Remove-Item -LiteralPath $zipPath -Force
|
||||||
|
|||||||
71
scripts/Sign-MrTrustProjectLinux.sh
Normal file
71
scripts/Sign-MrTrustProjectLinux.sh
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if [ "$#" -lt 1 ]; then
|
||||||
|
echo "Usage: Sign-MrTrustProjectLinux.sh <artifact> [artifact...]" >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${MRTRUST_CODESIGN_PFX_BASE64:-}" ]; then
|
||||||
|
echo "MRTRUST_CODESIGN_PFX_BASE64 is required." >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${MRTRUST_CODESIGN_PFX_PASSWORD:-}" ]; then
|
||||||
|
echo "MRTRUST_CODESIGN_PFX_PASSWORD is required." >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! command -v osslsigncode >/dev/null 2>&1; then
|
||||||
|
if command -v apt-get >/dev/null 2>&1; then
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y osslsigncode
|
||||||
|
else
|
||||||
|
echo "osslsigncode is not installed and apt-get is unavailable." >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
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
|
||||||
@@ -1,34 +1,50 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
|
||||||
namespace MrTrust
|
namespace MrTrust
|
||||||
{
|
{
|
||||||
internal static class MrTrustLauncher
|
internal static class MrTrustLauncher
|
||||||
{
|
{
|
||||||
[STAThread]
|
private const string PayloadResourcePrefix = "MrTrust.Payload.";
|
||||||
private static int Main()
|
|
||||||
{
|
|
||||||
string baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
|
|
||||||
string scriptPath = Path.Combine(baseDirectory, "MrTrust.ps1");
|
|
||||||
|
|
||||||
if (!File.Exists(scriptPath))
|
private static readonly PayloadFile[] PayloadFiles =
|
||||||
{
|
{
|
||||||
MessageBox.Show(
|
new PayloadFile("MrTrust.ps1", "MrTrust.ps1"),
|
||||||
"MrTrust.ps1 was not found next to MrTrust.exe.",
|
new PayloadFile("scripts.Build-MrTrustExe.ps1", Path.Combine("scripts", "Build-MrTrustExe.ps1")),
|
||||||
"MrTrust",
|
new PayloadFile("scripts.Install-MrTrust.ps1", Path.Combine("scripts", "Install-MrTrust.ps1")),
|
||||||
MessageBoxButtons.OK,
|
new PayloadFile("scripts.New-MrTrustCertificate.ps1", Path.Combine("scripts", "New-MrTrustCertificate.ps1")),
|
||||||
MessageBoxIcon.Error);
|
new PayloadFile("scripts.New-MrTrustIcon.ps1", Path.Combine("scripts", "New-MrTrustIcon.ps1")),
|
||||||
return 1;
|
new PayloadFile("scripts.New-MrTrustRelease.ps1", Path.Combine("scripts", "New-MrTrustRelease.ps1")),
|
||||||
}
|
new PayloadFile("scripts.Sign-MrTrustProject.ps1", Path.Combine("scripts", "Sign-MrTrustProject.ps1")),
|
||||||
|
new PayloadFile("scripts.Sign-MrTrustProjectLinux.sh", Path.Combine("scripts", "Sign-MrTrustProjectLinux.sh")),
|
||||||
|
new PayloadFile("scripts.Start-MrTrustGui.ps1", Path.Combine("scripts", "Start-MrTrustGui.ps1")),
|
||||||
|
new PayloadFile("scripts.Uninstall-MrTrust.ps1", Path.Combine("scripts", "Uninstall-MrTrust.ps1")),
|
||||||
|
new PayloadFile("assets.MrTrust.ico", Path.Combine("assets", "MrTrust.ico")),
|
||||||
|
new PayloadFile("assets.certificates.MrSphay-LocalTrust-Root.cer", Path.Combine("assets", "certificates", "MrSphay-LocalTrust-Root.cer")),
|
||||||
|
new PayloadFile("assets.certificates.MrSphay-CodeSigning.cer", Path.Combine("assets", "certificates", "MrSphay-CodeSigning.cer")),
|
||||||
|
new PayloadFile("assets.certificates.thumbprints.txt", Path.Combine("assets", "certificates", "thumbprints.txt"))
|
||||||
|
};
|
||||||
|
|
||||||
|
[STAThread]
|
||||||
|
private static int Main(string[] args)
|
||||||
|
{
|
||||||
|
string baseDirectory = string.Empty;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
baseDirectory = ExtractPayload();
|
||||||
|
string scriptPath = Path.Combine(baseDirectory, "MrTrust.ps1");
|
||||||
|
string commandArguments = BuildCommandArguments(args);
|
||||||
|
|
||||||
ProcessStartInfo startInfo = new ProcessStartInfo
|
ProcessStartInfo startInfo = new ProcessStartInfo
|
||||||
{
|
{
|
||||||
FileName = "powershell.exe",
|
FileName = "powershell.exe",
|
||||||
Arguments = "-NoProfile -ExecutionPolicy Bypass -File \"" + scriptPath + "\" gui",
|
Arguments = "-NoProfile -ExecutionPolicy Bypass -File " + QuoteArgument(scriptPath) + " " + commandArguments,
|
||||||
UseShellExecute = false,
|
UseShellExecute = false,
|
||||||
CreateNoWindow = true,
|
CreateNoWindow = true,
|
||||||
WorkingDirectory = baseDirectory
|
WorkingDirectory = baseDirectory
|
||||||
@@ -40,9 +56,10 @@ namespace MrTrust
|
|||||||
{
|
{
|
||||||
throw new InvalidOperationException("PowerShell could not be started.");
|
throw new InvalidOperationException("PowerShell could not be started.");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
process.WaitForExit();
|
||||||
|
return process.ExitCode;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -53,6 +70,123 @@ namespace MrTrust
|
|||||||
MessageBoxIcon.Error);
|
MessageBoxIcon.Error);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
TryDeleteDirectory(baseDirectory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ExtractPayload()
|
||||||
|
{
|
||||||
|
Assembly assembly = Assembly.GetExecutingAssembly();
|
||||||
|
string versionKey = GetPayloadVersionKey(assembly);
|
||||||
|
string targetDirectory = Path.Combine(
|
||||||
|
Path.GetTempPath(),
|
||||||
|
"MrTrust",
|
||||||
|
"standalone",
|
||||||
|
versionKey,
|
||||||
|
Guid.NewGuid().ToString("N"));
|
||||||
|
|
||||||
|
foreach (PayloadFile payloadFile in PayloadFiles)
|
||||||
|
{
|
||||||
|
string targetPath = Path.Combine(targetDirectory, payloadFile.RelativePath);
|
||||||
|
string targetParent = Path.GetDirectoryName(targetPath);
|
||||||
|
if (!string.IsNullOrEmpty(targetParent))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(targetParent);
|
||||||
|
}
|
||||||
|
|
||||||
|
using (Stream stream = assembly.GetManifestResourceStream(PayloadResourcePrefix + payloadFile.ResourceName))
|
||||||
|
{
|
||||||
|
if (stream == null)
|
||||||
|
{
|
||||||
|
throw new FileNotFoundException("Embedded MrTrust payload file was not found.", payloadFile.RelativePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
using (FileStream file = File.Create(targetPath))
|
||||||
|
{
|
||||||
|
stream.CopyTo(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return targetDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void TryDeleteDirectory(string directory)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(directory) || !Directory.Exists(directory))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Directory.Delete(directory, true);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Best-effort cleanup only. A locked icon or antivirus scan should not mask the command result.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetPayloadVersionKey(Assembly assembly)
|
||||||
|
{
|
||||||
|
string location = Application.ExecutablePath;
|
||||||
|
if (File.Exists(location))
|
||||||
|
{
|
||||||
|
FileInfo fileInfo = new FileInfo(location);
|
||||||
|
return fileInfo.Length.ToString("x") + "-" + fileInfo.LastWriteTimeUtc.Ticks.ToString("x");
|
||||||
|
}
|
||||||
|
|
||||||
|
return assembly.GetName().Version.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string BuildCommandArguments(string[] args)
|
||||||
|
{
|
||||||
|
string[] effectiveArgs = args.Length == 0 ? new[] { "gui" } : args;
|
||||||
|
return string.Join(" ", effectiveArgs.Select(QuoteArgument).ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string QuoteArgument(string value)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(value))
|
||||||
|
{
|
||||||
|
return "\"\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.IndexOfAny(new[] { ' ', '\t', '\n', '\r', '"' }) < 0)
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
builder.Append('"');
|
||||||
|
foreach (char character in value)
|
||||||
|
{
|
||||||
|
if (character == '"')
|
||||||
|
{
|
||||||
|
builder.Append('\\');
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.Append(character);
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.Append('"');
|
||||||
|
return builder.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class PayloadFile
|
||||||
|
{
|
||||||
|
public PayloadFile(string resourceName, string relativePath)
|
||||||
|
{
|
||||||
|
ResourceName = resourceName;
|
||||||
|
RelativePath = relativePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ResourceName { get; private set; }
|
||||||
|
|
||||||
|
public string RelativePath { get; private set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,24 @@
|
|||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<PublishSingleFile>true</PublishSingleFile>
|
<PublishSingleFile>true</PublishSingleFile>
|
||||||
<SelfContained>false</SelfContained>
|
<SelfContained>true</SelfContained>
|
||||||
|
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||||
<ApplicationIcon>..\assets\MrTrust.ico</ApplicationIcon>
|
<ApplicationIcon>..\assets\MrTrust.ico</ApplicationIcon>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="..\MrTrust.ps1" LogicalName="MrTrust.Payload.MrTrust.ps1" />
|
||||||
|
<EmbeddedResource Include="..\scripts\Build-MrTrustExe.ps1" LogicalName="MrTrust.Payload.scripts.Build-MrTrustExe.ps1" />
|
||||||
|
<EmbeddedResource Include="..\scripts\Install-MrTrust.ps1" LogicalName="MrTrust.Payload.scripts.Install-MrTrust.ps1" />
|
||||||
|
<EmbeddedResource Include="..\scripts\New-MrTrustCertificate.ps1" LogicalName="MrTrust.Payload.scripts.New-MrTrustCertificate.ps1" />
|
||||||
|
<EmbeddedResource Include="..\scripts\New-MrTrustIcon.ps1" LogicalName="MrTrust.Payload.scripts.New-MrTrustIcon.ps1" />
|
||||||
|
<EmbeddedResource Include="..\scripts\New-MrTrustRelease.ps1" LogicalName="MrTrust.Payload.scripts.New-MrTrustRelease.ps1" />
|
||||||
|
<EmbeddedResource Include="..\scripts\Sign-MrTrustProject.ps1" LogicalName="MrTrust.Payload.scripts.Sign-MrTrustProject.ps1" />
|
||||||
|
<EmbeddedResource Include="..\scripts\Sign-MrTrustProjectLinux.sh" LogicalName="MrTrust.Payload.scripts.Sign-MrTrustProjectLinux.sh" />
|
||||||
|
<EmbeddedResource Include="..\scripts\Start-MrTrustGui.ps1" LogicalName="MrTrust.Payload.scripts.Start-MrTrustGui.ps1" />
|
||||||
|
<EmbeddedResource Include="..\scripts\Uninstall-MrTrust.ps1" LogicalName="MrTrust.Payload.scripts.Uninstall-MrTrust.ps1" />
|
||||||
|
<EmbeddedResource Include="..\assets\MrTrust.ico" LogicalName="MrTrust.Payload.assets.MrTrust.ico" />
|
||||||
|
<EmbeddedResource Include="..\assets\certificates\MrSphay-LocalTrust-Root.cer" LogicalName="MrTrust.Payload.assets.certificates.MrSphay-LocalTrust-Root.cer" />
|
||||||
|
<EmbeddedResource Include="..\assets\certificates\MrSphay-CodeSigning.cer" LogicalName="MrTrust.Payload.assets.certificates.MrSphay-CodeSigning.cer" />
|
||||||
|
<EmbeddedResource Include="..\assets\certificates\thumbprints.txt" LogicalName="MrTrust.Payload.assets.certificates.thumbprints.txt" />
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
Reference in New Issue
Block a user