Update mit Guacamole-Extension
This commit is contained in:
+160
@@ -0,0 +1,160 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user