Files
sessiongurad/docs/BROKER.md
jbergner 7972ed7e38
All checks were successful
release-tag / release-image (push) Successful in 2m5s
release-main / release-images (push) Successful in 5m5s
Update mit Guacamole-Extension
2026-08-22 15:19:17 +02:00

161 lines
4.8 KiB
Markdown

# 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:
1. the agent has the farm ID in `farm_ids`;
2. the farm has the agent ID in `agent_ids`;
3. the agent satisfies all `required_tags` of the farm.
Example:
```json
{
"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:
```json
{
"name": "Office Desktop",
"kind": "desktop",
"farm_id": "office",
"guacamole_connection_name": "Office Desktop",
"enabled": true
}
```
RemoteApp example:
```json
{
"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:
1. Resolve an enabled Resource by explicit resource ID, Guacamole connection ID, or Guacamole connection name.
2. Resolve the farm: Resource farm → explicit request farm → configured default farm.
3. If a non-empty farm does not exist or is disabled, fail closed.
4. If `reconnect_existing` is enabled, search only matching farm members for an existing `Active`, `Connected` or `Disconnected` session for the user.
5. `maintenance` hosts are excluded from reconnect; `drain` hosts are allowed for reconnect.
6. Reuse a non-expired lease if its host is still available and belongs to the farm.
7. For a new session, consider only hosts that are:
- online,
- in `online` maintenance mode,
- members of the farm,
- at or above `min_health_score`.
8. Rank candidates by broker score and select the highest score.
9. Create or refresh the lease and return connection tokens.
## Broker score
The current score deliberately favors health and penalizes load:
```text
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:
```json
"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:
```text
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.