Add a placeholder step in the build-release workflow to download and package FreeRDP3 DLLs (libfreerdp3.dll, libwinpr3.dll, libfreerdp-client3.dll) alongside wraith.exe. The step is currently commented out pending a reliable DLL source URL; the app gracefully falls back to MockBackend when the DLLs are absent. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
224 lines
9.2 KiB
YAML
224 lines
9.2 KiB
YAML
# =============================================================================
|
|
# Wraith — Build & Sign Release
|
|
# =============================================================================
|
|
# Builds the Wails v3 desktop app for Windows amd64, signs it with an
|
|
# Azure Key Vault code-signing certificate via jsign, then uploads the
|
|
# signed binary and version manifest as release artifacts.
|
|
#
|
|
# Trigger: push a tag matching v* (e.g. v1.0.0) or run manually.
|
|
#
|
|
# Required secrets:
|
|
# AZURE_TENANT_ID — Azure AD tenant
|
|
# AZURE_CLIENT_ID — Service principal client ID
|
|
# AZURE_CLIENT_SECRET — Service principal secret
|
|
# AZURE_KEY_VAULT_URL — e.g. https://my-vault.vault.azure.net
|
|
# AZURE_CERT_NAME — Certificate/key name in the vault
|
|
# GIT_TOKEN — PAT for cloning private repo
|
|
# =============================================================================
|
|
|
|
name: Build & Sign Wraith
|
|
|
|
on:
|
|
push:
|
|
tags:
|
|
- 'v*'
|
|
workflow_dispatch:
|
|
|
|
jobs:
|
|
build-and-sign:
|
|
name: Build Windows + Sign
|
|
runs-on: linux
|
|
steps:
|
|
# ---------------------------------------------------------------
|
|
# Checkout
|
|
# ---------------------------------------------------------------
|
|
- name: Checkout code
|
|
run: |
|
|
git clone --depth 1 --branch ${{ github.ref_name }} \
|
|
https://${{ secrets.GIT_TOKEN }}@git.command.vigilcyber.com/vigilcyber/wraith.git .
|
|
|
|
# ---------------------------------------------------------------
|
|
# Extract version from tag
|
|
# ---------------------------------------------------------------
|
|
- name: Get version from tag
|
|
id: version
|
|
run: |
|
|
# Strip leading "v" from the tag (v1.2.3 -> 1.2.3)
|
|
TAG=$(echo "${{ github.ref_name }}" | sed 's/^v//')
|
|
echo "version=${TAG}" >> $GITHUB_OUTPUT
|
|
echo "Building version: ${TAG}"
|
|
|
|
# ---------------------------------------------------------------
|
|
# Install toolchain: Go, Node, npm
|
|
# ---------------------------------------------------------------
|
|
- name: Install Node.js
|
|
run: |
|
|
# Install Node.js LTS if not present
|
|
if ! command -v node >/dev/null 2>&1; then
|
|
curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
|
|
apt-get install -y -qq nodejs
|
|
fi
|
|
node --version
|
|
npm --version
|
|
|
|
# ---------------------------------------------------------------
|
|
# Build frontend assets
|
|
# ---------------------------------------------------------------
|
|
- name: Build frontend
|
|
run: |
|
|
cd frontend
|
|
npm ci
|
|
npm run build
|
|
echo "Frontend build complete:"
|
|
ls -la dist/
|
|
|
|
# ---------------------------------------------------------------
|
|
# Build Windows amd64 binary
|
|
# ---------------------------------------------------------------
|
|
# Wails v3 cross-compilation from Linux to Windows requires CGO
|
|
# for the webview2 bindings. Rather than pull in a full MinGW
|
|
# cross-compiler, we build the Go binary directly — the frontend
|
|
# assets are embedded via //go:embed in main.go, so the result is
|
|
# a single self-contained .exe.
|
|
# ---------------------------------------------------------------
|
|
- name: Build wraith.exe (Windows amd64)
|
|
run: |
|
|
VERSION="${{ steps.version.outputs.version }}"
|
|
echo "=== Cross-compiling wraith.exe for Windows amd64 ==="
|
|
|
|
mkdir -p dist
|
|
|
|
GOOS=windows GOARCH=amd64 CGO_ENABLED=0 \
|
|
go build \
|
|
-ldflags="-s -w -X main.version=${VERSION}" \
|
|
-o dist/wraith.exe \
|
|
.
|
|
|
|
ls -la dist/wraith.exe
|
|
|
|
# ---------------------------------------------------------------
|
|
# FreeRDP3 DLLs — runtime dependency for the real RDP backend
|
|
# ---------------------------------------------------------------
|
|
- name: Download FreeRDP3 DLLs
|
|
run: |
|
|
echo "=== Downloading FreeRDP3 pre-built DLLs for Windows amd64 ==="
|
|
FREERDP_VERSION="3.12.0"
|
|
|
|
# FreeRDP releases pre-built Windows binaries on GitHub.
|
|
# We need: libfreerdp3.dll, libwinpr3.dll, libfreerdp-client3.dll
|
|
#
|
|
# Option 1: Download from FreeRDP GitHub releases
|
|
# curl -sSL -o /tmp/freerdp.zip \
|
|
# "https://github.com/FreeRDP/FreeRDP/releases/download/${FREERDP_VERSION}/FreeRDP-${FREERDP_VERSION}-win64.zip"
|
|
# unzip /tmp/freerdp.zip -d /tmp/freerdp
|
|
# cp /tmp/freerdp/bin/libfreerdp3.dll dist/
|
|
# cp /tmp/freerdp/bin/libwinpr3.dll dist/
|
|
# cp /tmp/freerdp/bin/libfreerdp-client3.dll dist/
|
|
#
|
|
# Option 2: Build from source with cmake + MSVC cross-compiler
|
|
|
|
# For the initial CI run, the app will fall back to MockBackend
|
|
# until the DLLs are provided alongside wraith.exe.
|
|
echo "FreeRDP3 DLLs not yet configured — app will use mock RDP backend"
|
|
echo "To enable real RDP: place libfreerdp3.dll, libwinpr3.dll, libfreerdp-client3.dll alongside wraith.exe"
|
|
|
|
# When DLLs are available, sign them alongside wraith.exe:
|
|
# for dll in dist/lib*.dll; do
|
|
# java -jar /usr/local/bin/jsign.jar \
|
|
# --storetype AZUREKEYVAULT \
|
|
# --keystore "${{ secrets.AZURE_KEY_VAULT_URL }}" \
|
|
# --storepass "${{ steps.azure-token.outputs.token }}" \
|
|
# --alias "${{ secrets.AZURE_CERT_NAME }}" \
|
|
# --tsaurl http://timestamp.digicert.com \
|
|
# --tsmode RFC3161 \
|
|
# "$dll"
|
|
# done
|
|
|
|
# ---------------------------------------------------------------
|
|
# Code signing — jsign + Azure Key Vault
|
|
# ---------------------------------------------------------------
|
|
- name: Install jsign
|
|
run: |
|
|
# jsign: Java-based Authenticode signing tool that runs on
|
|
# Linux and supports Azure Key Vault as a keystore.
|
|
JSIGN_VERSION="7.0"
|
|
curl -sSL -o /usr/local/bin/jsign.jar \
|
|
"https://github.com/ebourg/jsign/releases/download/${JSIGN_VERSION}/jsign-${JSIGN_VERSION}.jar"
|
|
|
|
# Ensure a JRE is available (jsign needs Java)
|
|
command -v java >/dev/null 2>&1 || {
|
|
apt-get update -qq && apt-get install -y -qq default-jre-headless
|
|
}
|
|
|
|
- name: Get Azure Key Vault access token
|
|
id: azure-token
|
|
run: |
|
|
# OAuth2 client credentials flow for Azure Key Vault access
|
|
TOKEN=$(curl -s -X POST \
|
|
"https://login.microsoftonline.com/${{ secrets.AZURE_TENANT_ID }}/oauth2/v2.0/token" \
|
|
-d "client_id=${{ secrets.AZURE_CLIENT_ID }}" \
|
|
-d "client_secret=${{ secrets.AZURE_CLIENT_SECRET }}" \
|
|
-d "scope=https://vault.azure.net/.default" \
|
|
-d "grant_type=client_credentials" \
|
|
| python3 -c "import sys,json; print(json.load(sys.stdin)['access_token'])")
|
|
echo "::add-mask::${TOKEN}"
|
|
echo "token=${TOKEN}" >> $GITHUB_OUTPUT
|
|
|
|
- name: Sign wraith.exe
|
|
run: |
|
|
echo "=== Signing wraith.exe with Azure Key Vault certificate ==="
|
|
java -jar /usr/local/bin/jsign.jar \
|
|
--storetype AZUREKEYVAULT \
|
|
--keystore "${{ secrets.AZURE_KEY_VAULT_URL }}" \
|
|
--storepass "${{ steps.azure-token.outputs.token }}" \
|
|
--alias "${{ secrets.AZURE_CERT_NAME }}" \
|
|
--tsaurl http://timestamp.digicert.com \
|
|
--tsmode RFC3161 \
|
|
dist/wraith.exe
|
|
echo "Signing complete."
|
|
|
|
# ---------------------------------------------------------------
|
|
# Version manifest
|
|
# ---------------------------------------------------------------
|
|
- name: Create version.json
|
|
run: |
|
|
VERSION="${{ steps.version.outputs.version }}"
|
|
SHA256=$(sha256sum dist/wraith.exe | awk '{print $1}')
|
|
|
|
cat > dist/version.json << EOF
|
|
{
|
|
"version": "${VERSION}",
|
|
"filename": "wraith.exe",
|
|
"sha256": "${SHA256}",
|
|
"platform": "windows",
|
|
"architecture": "amd64",
|
|
"released": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")",
|
|
"signed": true
|
|
}
|
|
EOF
|
|
|
|
echo "=== version.json ==="
|
|
cat dist/version.json
|
|
|
|
# ---------------------------------------------------------------
|
|
# Upload release artifacts
|
|
# ---------------------------------------------------------------
|
|
- name: Upload release artifacts
|
|
run: |
|
|
VERSION="${{ steps.version.outputs.version }}"
|
|
ENDPOINT="https://files.command.vigilcyber.com"
|
|
|
|
echo "=== Uploading Wraith ${VERSION} ==="
|
|
|
|
# Versioned path
|
|
aws s3 cp dist/ "s3://agents/wraith/${VERSION}/windows/amd64/" \
|
|
--recursive --endpoint-url "$ENDPOINT" --no-sign-request
|
|
|
|
# Latest path (overwritten on each release)
|
|
aws s3 sync dist/ "s3://agents/wraith/latest/windows/amd64/" \
|
|
--delete --endpoint-url "$ENDPOINT" --no-sign-request
|
|
|
|
echo "=== Upload complete ==="
|
|
echo "Versioned: ${ENDPOINT}/agents/wraith/${VERSION}/windows/amd64/"
|
|
echo "Latest: ${ENDPOINT}/agents/wraith/latest/windows/amd64/"
|