Jan aceb0509ab
All checks were successful
release-tag / release-image (push) Successful in 2m2s
release-main / release-images (push) Successful in 4m12s
Dockerfile.edgeguard aktualisiert
2026-08-24 06:13:27 +02:00
2026-08-24 05:46:42 +02:00
2026-08-24 05:46:42 +02:00
2026-08-24 05:46:42 +02:00
2026-08-24 05:46:42 +02:00
2026-08-24 05:46:42 +02:00
2026-08-24 05:46:42 +02:00
2026-08-24 05:46:42 +02:00
2026-08-24 05:46:42 +02:00
2026-08-22 15:19:17 +02:00
2026-08-24 05:46:42 +02:00
2026-08-24 05:46:42 +02:00
2026-08-22 16:31:39 +02:00
2026-08-22 16:25:16 +02:00
2026-08-22 15:19:17 +02:00
2026-08-24 05:46:42 +02:00

SessionGuard

SessionGuard is a Go-based RDS control plane for Windows Remote Desktop Session Hosts. It is designed to complement Apache Guacamole: Guacamole remains the HTML5/RDP gateway, while SessionGuard provides Citrix-like broker, Director, policy, profile-lifecycle and operations functions.

Current development version: 0.5.2 (Public EdgeGuard + modal-first responsive Web UI + integrated Guacamole Access Auth)

SessionGuard is not an ICA/HDX implementation and does not replace the Windows RDS runtime. It deliberately reuses standard RDP/WTS, Guacamole and PocketID/OIDC.

0.5.2 Public EdgeGuard

The optional public-VPS deployment now includes sessionguard-edgeguard, a small Go service called by Caddy before requests reach SessionGuard or Guacamole. It provides static CIDR blacklisting, global/per-IP/endpoint token-bucket limits, scanner-path detection, persistent temporary bans, method/host/URI guards and local metrics. Caddy is additionally hardened with strict SNI/Host matching, a request-header timeout and smaller header ceiling. This protects application backends against common Internet abuse; provider-side DDoS filtering is still required for attacks that saturate the network link. See docs/EDGE-SECURITY.md and deploy/public-vps-netbird/.

0.5.1 Web UI refresh

The Master and local Agent consoles now use a modal-first, responsive Vanilla-JavaScript interface. Server drill-down, Farm creation, Resource editing and local Agent policy editing no longer occupy permanent large inline forms. The Master server workspace uses tabs, Farms/Resources use compact cards, and the Agent groups operational data into a tabbed workspace. No Node.js/npm/frontend build step is required.

0.5.0 Integrated Guacamole Access Auth

  • sessionguard-master can now act directly as Traefik ForwardAuth for Guacamole; no separate forward-auth container is required.
  • PocketID OIDC login for Guacamole uses a separate access_auth configuration/cookie scope from the SessionGuard admin UI.
  • Browser sessions are opaque, server-side and persisted in the existing Master store; expired/revoked sessions are denied even if Guacamole still has an old auth token.
  • X-Guacamole-User is emitted only after a valid SessionGuard access-session check. There is no fallback identity.
  • OIDC RP-initiated logout and PocketID back-channel logout are supported; back-channel tokens are signature/audience/event/time/JTI checked with replay protection.
  • The Guacamole extension now includes plain JavaScript which detects Guacamole logout and performs the full SessionGuard/PocketID logout, while also polling access-session status to close stale browser sessions.
  • Recommended deployment exposes /_sessionguard/auth/* on the Guacamole hostname and routes that prefix to the same Master container.

See docs/ACCESS-AUTH.md for the PocketID and Traefik migration.

0.4.1 RemoteApp robustness

Windows PowerShell auxiliary streams are now isolated from the JSON protocol used by RemoteApp discovery/reconciliation. CLIXML/progress noise no longer breaks RemoteApp status decoding.

0.4.0 RemoteApp control plane

  • The Master can define RemoteApp desired state per Published Resource/Farm.
  • Windows Agents discover the local Win32_TSPublishedApplication inventory through the documented Terminal Services WMI provider.
  • For resources with Agent-managed RemoteApp publication enabled, the Agent creates/updates the local RemoteApp registration and removes only aliases that the Agent itself originally created. Existing/manual RemoteApps may be adopted for desired-state checks but are never deleted merely because management is later disabled.
  • Executable presence, publication state and desired-state convergence are reported back in every Agent snapshot.
  • The broker fails closed per managed RemoteApp: a host is eligible only when that application is present, published and in sync. Desktop resources and unmanaged RemoteApps keep their previous placement behavior.
  • Master and Agent WebUIs show RemoteApp configuration/readiness without Node.js or a frontend build chain.
  • Agent protocol version is now 4; upgrade Master and Agents together.

The local Terminal Services WMI provider is used instead of direct registry manipulation. This mode should be canary-tested on the exact Windows Server/RDSH versions in your environment; it does not claim to recreate every Microsoft Connection Broker/Collection management semantic.

See docs/REMOTEAPP.md for the canary, ownership/rollback behavior and Guacamole mapping.

0.3.4 Modern Web UI

  • Master and Agent consoles use a responsive enterprise-style sidebar and dashboard layout.
  • Dark/light theme switching is implemented with plain CSS and Vanilla JavaScript.
  • Modern status badges, cards, forms, switches and tables without Node.js, npm, Vue, React or a frontend build step.
  • The existing refresh-safe editor behavior remains intact: live telemetry can update without replacing forms currently being edited.

0.3.3 Farm UI regression fix

The master UI now maintains an explicit agentCache from the dashboard response before rendering farm membership. This fixes ReferenceError: agentCache is not defined introduced by the v0.3.2 farm-count display correction.

0.3.1 UI stability fix

  • Live dashboard refresh no longer recreates editable Master forms.
  • Server live metrics and server-control inputs are rendered independently.
  • Farm and Published Resource editors remain mounted while their live tables refresh.
  • Agent policy edits are protected by a dirty-state guard and an explicit reload action.
  • HTML and app.js are served with Cache-Control: no-store to prevent stale UI code after upgrades.

0.3.0 at a glance

Smart broker and farms

  • Logical farms with explicit agent membership and/or required tags.
  • Published resources for full desktops and RemoteApps.
  • Existing-session reconnect affinity before new load balancing.
  • Persistent user leases to reduce duplicate sessions across hosts.
  • Optional global single-session-per-user behavior.
  • Health-aware placement using server health, sessions, CPU and memory pressure.
  • online, drain and maintenance server modes.
  • restart_when_drained: stop new allocations, wait for all user sessions to leave, then queue a controlled restart.
  • Farm and global policy inheritance, plus per-agent override.

Guacamole 1.6 bridge

guacamole-extension/ contains a small Java extension using Guacamole's extension API. It does not authenticate users. It decorates the already authenticated Guacamole user context, asks the SessionGuard broker for connection tokens and injects:

  • ${SESSIONGUARD_HOST}
  • ${SESSIONGUARD_AGENT_ID}
  • ${SESSIONGUARD_RESOURCE_ID}
  • ${SESSIONGUARD_REMOTE_APP}
  • ${SESSIONGUARD_REMOTE_APP_DIR}
  • ${SESSIONGUARD_REMOTE_APP_ARGS}

This keeps PocketID / header authentication and the browser gateway separate from broker logic. See docs/GUACAMOLE.md.

Director-style operations

  • Consolidated server and session inventory.
  • RDS logon/connect/last-input timestamps and calculated idle time.
  • Per-session process inventory and remote process termination.
  • CPU, memory and system-disk telemetry.
  • RDP-listener and profile-store health checks.
  • Composite server health score used by both the UI and broker.
  • Session history for logon, reconnect, disconnect, logoff and SessionGuard logon_ready events.
  • Logon telemetry including SessionGuard restore duration and observed time until the post-restore/template stage is ready.
  • Active alerts for offline agents, CPU/RAM/disk/health, profile failures, disconnected-session count and slow observed logon.
  • Optional generic JSON webhook notifications with notification throttling.
  • Prometheus-compatible /metrics endpoint.

Enterprise control plane

  • PostgreSQL persistence for production with a database advisory lock preventing accidental active/active masters.
  • Append-only audit and session-history tables with retention and indexes.
  • JSONB control-plane state for agents, farms, resources, leases, policies and alerts.
  • JSON-file persistence remains available as a small single-node fallback / migration path.
  • PocketID / generic OIDC authentication.
  • Group-to-role RBAC.
  • Policy version history and rollback for global, farm and agent policies.
  • Agent-initiated HTTPS heartbeats and command delivery only; no inbound management port from master to RDS hosts.
  • Expiring, deduplicated command queue with result acknowledgement and audit trail.

Windows agent and profile lifecycle

The v0.2 functionality remains:

  • Windows service with native WTS session inventory and session-change wakeups.
  • Send message, disconnect and logoff user sessions.
  • Automatic logoff of disconnected sessions after a persistent configurable timeout.
  • Backup of selected profile folders after logoff.
  • Versioned transactional profile snapshots (staging -> current).
  • Restore of the last successful snapshot on a newly observed logon.
  • A failed backup blocks local profile deletion.
  • Cleanup with grace period, exclusions, allowed profile roots, final WTS recheck and DeleteProfileW.
  • Structured templates for files, folders, .url and .lnk shortcuts.
  • Local PocketID/OIDC-protected fallback UI on every agent.

See docs/PROFILE-LIFECYCLE.md for the deliberately limited scope of profile synchronization.

Target architecture

PocketID
   |
Traefik / trusted header-auth boundary
   |
Apache Guacamole 1.6
 + sessionguard-guacamole extension
   |
   | broker token request
   v
SessionGuard Master  ---------------- PostgreSQL
   |
   | outbound agent heartbeats carry policy/commands/results
   |
   +-------------+-------------+
   |             |             |
 RDS01         RDS02         RDS03
 Agent         Agent         Agent

Quick start: master

Copy the example configuration and environment file:

cp configs/master.example.json deploy/master.json
cp deploy/.env.example deploy/.env

Set at least:

  • SESSIONGUARD_DB_PASSWORD
  • SESSIONGUARD_ENROLLMENT_TOKEN
  • SESSIONGUARD_BROKER_API_KEY
  • SESSIONGUARD_OIDC_CLIENT_SECRET
  • PocketID issuer/client/redirect values in master.json
  • TRAEFIK_NETWORK

Then:

cd deploy
docker compose up -d --build

For production, expose the master only through your existing TLS reverse proxy. The bundled compose publishes port 8080 only on 127.0.0.1 as an additional safety measure.

Quick start: Windows agent

Build on a machine with Go module access:

.\scripts\build.ps1

Copy configs/agent.example.json, configure PocketID, the master URL and your initial policy, then install from an elevated PowerShell:

.\scripts\install-agent.ps1 -BinaryPath .\dist\sessionguard-agent.exe -ConfigPath .\configs\agent.json

For SMB profile stores, prefer a gMSA and grant it the required share/NTFS permissions. Do not store SMB passwords in the agent JSON.

Guacamole integration

Build a Guacamole image containing the extension using deploy/guacamole/Dockerfile.guacamole. Add these environment variables to Guacamole:

SESSIONGUARD_MASTER_URL: http://sessionguard-master:8080
SESSIONGUARD_BROKER_API_KEY: ${SESSIONGUARD_BROKER_API_KEY}
SESSIONGUARD_BROKER_TIMEOUT_MS: "2500"

A brokered desktop connection uses:

hostname = ${SESSIONGUARD_HOST}

A RemoteApp can additionally use the SESSIONGUARD_REMOTE_APP* tokens. Map the Guacamole connection ID or name to a SessionGuard Resource in the master UI.

Important: with Guacamole header authentication, untrusted containers or networks must not be able to reach Guacamole directly and forge the authentication header. See docs/GUACAMOLE.md and docs/SECURITY.md.

Master environment overrides

Secrets do not need to be stored in JSON:

Variable Purpose
SESSIONGUARD_DATABASE_URL PostgreSQL DSN
SESSIONGUARD_ENROLLMENT_TOKEN one-time agent enrollment shared secret
SESSIONGUARD_BROKER_API_KEY Guacamole-extension → broker credential
SESSIONGUARD_OIDC_CLIENT_SECRET master PocketID/OIDC client secret
SESSIONGUARD_ALERT_WEBHOOK_URL optional alert webhook

Agent overrides:

Variable Purpose
SESSIONGUARD_MASTER_URL master URL
SESSIONGUARD_ENROLLMENT_TOKEN enrollment secret
SESSIONGUARD_OIDC_CLIENT_SECRET local agent UI OIDC secret

Broker placement order

  1. Resolve an enabled Published Resource if one matches the requested Guacamole connection ID/name.
  2. Determine the requested/default farm.
  3. If enabled, reconnect a matching existing Active/Connected/Disconnected session in that farm. A drain host may be used for this; maintenance may not.
  4. Reuse a non-expired matching user lease if possible.
  5. Select only online, healthy, online-mode members of the farm.
  6. Score candidates using health, active/disconnected sessions, CPU and memory pressure.
  7. Create/refresh the user lease and return connection tokens.

A farm boundary is fail-closed: a session on another farm is not reused for a request for the selected farm.

Policy precedence

agent override
    > explicit farm membership (order in agent.farm_ids)
    > centrally selected farm (agent_ids / required_tags, deterministic farm-ID order)
    > global policy

All policy writes are normalized and validated before activation. Every global/farm/agent policy write creates a version that can be rolled back from the UI/API.

RBAC roles

Built-in roles are:

  • viewer
  • helpdesk
  • operator
  • profile_admin
  • policy_admin
  • auditor
  • admin

PocketID groups claims are mapped in master.json. If the RBAC group mapping is intentionally empty, SessionGuard preserves backwards compatibility and grants authenticated users the admin role; do not leave it empty in a multi-admin production environment.

See docs/RBAC.md.

Profile scope and safety

SessionGuard synchronizes selected profile folders, not a complete Windows profile. Do not configure NTUSER.DAT, registry hives, the whole profile root, EFS material or Windows-owned profile internals as roaming content.

Good candidates include:

  • AppData\Roaming\Vendor\Product
  • Desktop
  • Documents
  • application-owned configuration folders safe to merge after logon

If the profile backup fails, cleanup is not scheduled. If the user reconnects before snapshot activation or immediately before cleanup, the dangerous operation is cancelled.

Build and test

Requirements:

  • Go 1.23+
  • Windows Server 2019/2022/2025 x64 for agent integration testing
  • Maven/JDK 11+ for the Guacamole extension
  • PostgreSQL 17 recommended for production

Go:

go mod tidy
go test ./...
go vet ./...

Guacamole extension:

cd guacamole-extension
mvn -DskipTests package

The current source tree contains unit tests for configuration, templates, profile snapshot behavior and broker placement invariants. A real release should additionally pass the Windows/RDS/SMB/PostgreSQL integration matrix in docs/TESTING.md.

Documentation

  • docs/ARCHITECTURE.md components, state and trust boundaries
  • docs/BROKER.md farms, resources, leases, scoring and maintenance states
  • docs/DIRECTOR.md telemetry, history, processes, alerts and health scoring
  • docs/GUACAMOLE.md extension and integration with Guacamole/PocketID
  • docs/PROFILE-LIFECYCLE.md profile backup/restore/cleanup pipeline
  • docs/RBAC.md roles and PocketID group mapping
  • docs/API.md HTTP API
  • docs/OPERATIONS.md deployment, upgrade, backup and recovery
  • docs/SECURITY.md security model and hardening
  • docs/TESTING.md release and failure-mode test matrix
  • CHANGELOG.md release changes

Production-candidate status

The design intentionally fails closed around destructive profile operations and broker farm boundaries. Nevertheless, v0.5.0 should be introduced as a canary before broad production rollout. In particular, validate native WTS behavior, SMB failure/recovery, PostgreSQL backup/restore, Guacamole extension loading and your exact PocketID group claims in your environment.

Description
No description provided
Readme 14 MiB
2026-08-25 06:27:08 +02:00
Languages
Go 96.6%
Java 1.3%
PowerShell 1%
JavaScript 0.8%
Dockerfile 0.3%