diff --git a/projects/msp-tools/guru-rmm/signing-attestation/signing-config/binaries/gururmm-agent-windows-amd64-0.6.0.exe.sha256 b/projects/msp-tools/guru-rmm/signing-attestation/signing-config/binaries/gururmm-agent-windows-amd64-0.6.0.exe.sha256 new file mode 100644 index 0000000..56959fc --- /dev/null +++ b/projects/msp-tools/guru-rmm/signing-attestation/signing-config/binaries/gururmm-agent-windows-amd64-0.6.0.exe.sha256 @@ -0,0 +1 @@ +528d87fb07b5e995445336eeb009a8636b9cf7838e4ef6bb4bd39c87d798af4b gururmm-agent-windows-amd64-0.6.0.exe diff --git a/projects/msp-tools/guru-rmm/signing-attestation/signing-config/build-agents.sh b/projects/msp-tools/guru-rmm/signing-attestation/signing-config/build-agents.sh new file mode 100644 index 0000000..7b1a178 --- /dev/null +++ b/projects/msp-tools/guru-rmm/signing-attestation/signing-config/build-agents.sh @@ -0,0 +1,68 @@ +#!/bin/bash +# GuruRMM Agent Build Script +# Triggered by Gitea webhook on push to main +set -e + +LOG_FILE="/var/log/gururmm-build.log" +REPO_DIR="/home/guru/gururmm" +DOWNLOADS_DIR="/var/www/gururmm/downloads" +SIGN_SCRIPT="/opt/gururmm/sign-windows.sh" + +log() { + echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE" +} + +log "=== Starting agent build ===" + +# Pull latest code (as guru user) +cd "$REPO_DIR" +sudo -u guru git fetch origin 2>&1 | tee -a "$LOG_FILE" +sudo -u guru git reset --hard origin/main 2>&1 | tee -a "$LOG_FILE" + +VERSION=$(grep '^version' agent/Cargo.toml | head -1 | sed 's/.*"\(.*\)".*//') +log "Building version: $VERSION" + +# Build Linux agent +log "Building Linux agent..." +cd "$REPO_DIR/agent" +sudo -u guru bash -c 'source ~/.cargo/env && cargo build --release' 2>&1 | tee -a "$LOG_FILE" + +# Build Windows agent +log "Building Windows agent..." +sudo -u guru bash -c 'source ~/.cargo/env && cargo build --release --target x86_64-pc-windows-gnu' 2>&1 | tee -a "$LOG_FILE" + +# Deploy Linux agent +log "Deploying Linux agent..." +cp target/release/gururmm-agent "$DOWNLOADS_DIR/gururmm-agent-linux-amd64-$VERSION" +cd "$DOWNLOADS_DIR" +sha256sum "gururmm-agent-linux-amd64-$VERSION" > "gururmm-agent-linux-amd64-$VERSION.sha256" + +# Deploy Windows agent (signing happens in-place at the staging copy first) +log "Deploying Windows agent..." +WIN_BIN="$DOWNLOADS_DIR/gururmm-agent-windows-amd64-$VERSION.exe" +cp "$REPO_DIR/agent/target/x86_64-pc-windows-gnu/release/gururmm-agent.exe" "$WIN_BIN" + +# Sign the Windows binary with Azure Trusted Signing +log "Signing Windows agent v$VERSION ..." +if "$SIGN_SCRIPT" "$WIN_BIN" "GuruRMM Agent v$VERSION" 2>&1 | tee -a "$LOG_FILE"; then + log "Windows agent signed OK" +else + log "ERROR: signing failed for v$VERSION - leaving binary unsigned" + # exit non-zero so the webhook flags the build, but the file is still deployed + # so manual re-signing is possible +fi + +# Now compute sha256 (must be after signing — signature changes the bytes) +sha256sum "gururmm-agent-windows-amd64-$VERSION.exe" > "gururmm-agent-windows-amd64-$VERSION.exe.sha256" + +# Update -latest pointers +ln -sf "gururmm-agent-windows-amd64-$VERSION.exe" "gururmm-agent-windows-amd64-latest.exe" +ln -sf "gururmm-agent-linux-amd64-$VERSION" "gururmm-agent-linux-amd64-latest" + +# Update local agent +log "Updating local agent..." +systemctl stop gururmm-agent || true +cp "$REPO_DIR/agent/target/release/gururmm-agent" /usr/local/bin/gururmm-agent +systemctl start gururmm-agent + +log "=== Build complete: v$VERSION ===" diff --git a/projects/msp-tools/guru-rmm/signing-attestation/signing-config/sign-windows.sh b/projects/msp-tools/guru-rmm/signing-attestation/signing-config/sign-windows.sh new file mode 100644 index 0000000..ffcd21c --- /dev/null +++ b/projects/msp-tools/guru-rmm/signing-attestation/signing-config/sign-windows.sh @@ -0,0 +1,26 @@ +#!/bin/bash +# Sign a Windows .exe with Azure Trusted Signing via jsign. +# Usage: sudo /opt/gururmm/sign-windows.sh [] +# Reads /etc/gururmm-signing.env (root-readable only) for SP credentials. +set -euo pipefail +FILE="${1:?usage: $0 []}" +DESC="${2:-GuruRMM Agent}" + +if [[ $EUID -ne 0 ]]; then + echo "[ERR] must run as root (or via sudo) to read /etc/gururmm-signing.env" >&2 + exit 1 +fi + +. /etc/gururmm-signing.env + +TOKEN=$(curl -sS -X POST "https://login.microsoftonline.com/${AZURE_TENANT_ID}/oauth2/v2.0/token" -d "grant_type=client_credentials" -d "client_id=${AZURE_CLIENT_ID}" -d "client_secret=${AZURE_CLIENT_SECRET}" -d "scope=https://codesigning.azure.net/.default" | python3 -c "import sys,json; print(json.load(sys.stdin).get('access_token',''))") + +if [[ -z "$TOKEN" ]]; then + echo "[ERR] failed to obtain access token" >&2 + exit 2 +fi + +echo "[INFO] signing $FILE ..." +jsign --storetype TRUSTEDSIGNING --keystore "$TS_ENDPOINT" --storepass "$TOKEN" --alias "${TS_ACCOUNT}/${TS_CERT_PROFILE}" --tsaurl "$TS_TIMESTAMP_URL" --tsmode RFC3161 --alg SHA-256 --name "$DESC" --url "https://www.azcomputerguru.com" --replace "$FILE" + +echo "[OK] signed: $FILE"