4.8 KiB
Broker, Farms and Published Resources
Goal
The SessionGuard broker provides the Citrix-like placement functions that Guacamole's generic RDP connections do not know about: reconnect affinity, farm boundaries, drain/maintenance state, health-aware placement and user leases.
Farms
A farm is a logical group of RDS hosts.
Membership can be expressed in three ways:
- the agent has the farm ID in
farm_ids; - the farm has the agent ID in
agent_ids; - the agent satisfies all
required_tagsof the farm.
Example:
{
"id": "office",
"name": "Office",
"required_tags": {
"role": "office",
"environment": "production"
},
"enabled": true
}
Tags are exact key/value matches. Explicit membership and tag membership can coexist.
Published resources
A Resource maps a Guacamole connection to a farm and optionally to a RemoteApp definition.
Desktop example:
{
"name": "Office Desktop",
"kind": "desktop",
"farm_id": "office",
"guacamole_connection_name": "Office Desktop",
"enabled": true
}
RemoteApp example:
{
"name": "Sage",
"kind": "remoteapp",
"farm_id": "erp",
"guacamole_connection_name": "Sage",
"remote_app": "||Sage",
"remote_app_dir": "C:\\Program Files\\Sage",
"remote_app_args": "",
"enabled": true
}
Connection ID matching is preferred where stable IDs are known; connection-name matching is case-insensitive and convenient for initial deployment.
Placement algorithm
Given username, optional resource_id, farm_id, and Guacamole connection identity:
- Resolve an enabled Resource by explicit resource ID, Guacamole connection ID, or Guacamole connection name.
- Resolve the farm: Resource farm → explicit request farm → configured default farm.
- If a non-empty farm does not exist or is disabled, fail closed.
- If
reconnect_existingis enabled, search only matching farm members for an existingActive,ConnectedorDisconnectedsession for the user. maintenancehosts are excluded from reconnect;drainhosts are allowed for reconnect.- Reuse a non-expired lease if its host is still available and belongs to the farm.
- For a new session, consider only hosts that are:
- online,
- in
onlinemaintenance mode, - members of the farm,
- at or above
min_health_score.
- Rank candidates by broker score and select the highest score.
- Create or refresh the lease and return connection tokens.
Broker score
The current score deliberately favors health and penalizes load:
health score * 10
- active sessions * 20
- disconnected sessions * 5
- CPU percent * 2
- memory-used percent
This is an intentionally understandable heuristic rather than an opaque ML model. Thresholds and formula can be evolved without changing the Guacamole integration.
User leases
A lease reduces races between two nearly simultaneous connection attempts.
With:
"single_session_per_user": true
the normalized username is the global lease key. The intent is that a user is directed back to one RDS host whenever possible.
With it disabled, the lease key is scoped by:
user | farm | resource
This permits independent sessions in separate published resources/farms.
Leases expire after lease_seconds; successful broker use refreshes the expiry.
Username normalization
Broker comparisons are case-insensitive. DOMAIN\user and matching WTS domain/user fields are normalized before comparison.
In environments with ambiguous duplicate short usernames across domains, pass the domain-qualified username from the identity/gateway layer.
Drain and maintenance
Drain
Use before patching or planned retirement of a server:
- new sessions: blocked
- existing-session reconnect: allowed
- existing sessions: untouched
Optionally set restart_when_drained=true. When zero user sessions remain, a restart command is queued.
Maintenance
Use for a host that must not receive any brokered access:
- new sessions: blocked
- reconnect: blocked
Existing Windows sessions are not forcefully killed merely by changing this state; use bulk session actions if required.
Farm policy inheritance
Farm policies are independent from broker selection but use the same membership concepts. Explicit agent.farm_ids determine precedence when an agent intentionally belongs to multiple farms. Centrally inferred memberships are evaluated deterministically by farm ID.
Broker API security
The broker endpoints are not user-OIDC endpoints. They are server-to-server APIs protected by SESSIONGUARD_BROKER_API_KEY.
Recommendations:
- generate a high-entropy secret;
- keep Guacamole and Master on a private Docker/network path;
- do not reuse the enrollment token, OIDC client secret or PostgreSQL password;
- rotate the key by updating Master and Guacamole together during a controlled maintenance window.