0.4.0
This commit is contained in:
29
docs/API.md
29
docs/API.md
@@ -1,4 +1,4 @@
|
||||
# HTTP API (v0.3)
|
||||
# HTTP API (v0.4)
|
||||
|
||||
All JSON APIs return an error object with an `error` field on failure unless otherwise stated.
|
||||
|
||||
@@ -114,7 +114,26 @@ Farm fields include `name`, `description`, `agent_ids`, `required_tags`, optiona
|
||||
- `PUT /api/v1/resources/{id}` – `manage`
|
||||
- `DELETE /api/v1/resources/{id}` – `manage`
|
||||
|
||||
Resource fields include desktop/RemoteApp kind, farm ID, Guacamole connection ID/name and RemoteApp parameters.
|
||||
Resource fields include desktop/RemoteApp kind, farm ID, Guacamole connection ID/name and RemoteApp parameters. RemoteApp resources additionally support Agent-managed local publication:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "Sage",
|
||||
"kind": "remoteapp",
|
||||
"farm_id": "erp",
|
||||
"remote_app": "||Sage",
|
||||
"manage_remote_app": true,
|
||||
"remote_app_path": "C:\\Program Files\\Sage\\Sage.exe",
|
||||
"remote_app_icon_path": "",
|
||||
"remote_app_icon_index": 0,
|
||||
"remote_app_command_line_setting": 0,
|
||||
"remote_app_required_command_line": "",
|
||||
"remote_app_show_in_portal": false,
|
||||
"enabled": true
|
||||
}
|
||||
```
|
||||
|
||||
`remote_app_command_line_setting` is `0` (deny client-provided arguments), `1` (allow), or `2` (require the configured command line). For Agent-managed RemoteApps the broker mirrors this policy into Guacamole tokens: setting `0` emits no RemoteApp arguments, setting `1` uses `remote_app_args`, and setting `2` forces `remote_app_required_command_line`.
|
||||
|
||||
## Director/history
|
||||
|
||||
@@ -128,6 +147,8 @@ Resource fields include desktop/RemoteApp kind, farm ID, Guacamole connection ID
|
||||
|
||||
## Agent protocol
|
||||
|
||||
`model.ProtocolVersion` is `3` for v0.3.
|
||||
`model.ProtocolVersion` is `4` for v0.4. Master and Agent must use the same protocol version.
|
||||
|
||||
Heartbeat snapshots contain server/health/session/process/telemetry/profile/event state. The response contains effective desired policy and pending commands. Agents acknowledge completed commands in later heartbeats.
|
||||
Heartbeat snapshots contain server/health/session/process/telemetry/profile/event state plus `remote_apps`. Each RemoteApp status can report `resource_id`, `alias`, `path`, `path_exists`, `published`, `managed`, `in_sync` and `error`.
|
||||
|
||||
Heartbeat responses contain effective desired policy, pending commands and `desired_remote_apps`. The latter is intentionally always present (including an empty array) so an Agent can safely remove SessionGuard-owned registrations that are no longer desired. Agents acknowledge completed commands in later heartbeats.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# SessionGuard 0.3 Architecture
|
||||
# SessionGuard 0.4 Architecture
|
||||
|
||||
## Purpose
|
||||
|
||||
@@ -9,7 +9,7 @@ SessionGuard separates the functions commonly bundled into a Citrix deployment i
|
||||
- **Apache Guacamole**: browser gateway and RDP transport.
|
||||
- **Windows RDS**: Windows session runtime.
|
||||
- **SessionGuard Master**: broker, Director, policy control plane, history, alerting and command queue.
|
||||
- **SessionGuard Agent**: Windows/RDS integration, profile lifecycle, templates, telemetry and local fallback administration.
|
||||
- **SessionGuard Agent**: Windows/RDS integration, profile lifecycle, templates, telemetry, local RemoteApp reconciliation and fallback administration.
|
||||
|
||||
SessionGuard intentionally does not implement a new remote-display protocol.
|
||||
|
||||
@@ -76,6 +76,7 @@ Persistent agent state under `data_dir` contains:
|
||||
- profile status
|
||||
- bounded event history
|
||||
- bounded logon telemetry
|
||||
- desired/managed RemoteApp state and last observed RemoteApp inventory
|
||||
|
||||
The service can therefore continue cleanup/profile/session policy during a master outage using the last accepted policy.
|
||||
|
||||
@@ -103,6 +104,29 @@ A request contains the authenticated username plus Guacamole connection ID/name
|
||||
|
||||
The response contains tokens rather than Guacamole-specific mutable state. The extension injects them into the current user context immediately before the connection parameters are resolved.
|
||||
|
||||
|
||||
## RemoteApp desired-state model
|
||||
|
||||
For a Resource with Agent-managed publication enabled, the Master derives a `RemoteAppSpec` for each member of the Resource farm and returns it in the normal outbound heartbeat response. No inbound WMI/WinRM connection from Master to the RDS host is introduced.
|
||||
|
||||
```text
|
||||
Master Resource desired state
|
||||
|
|
||||
| heartbeat response
|
||||
v
|
||||
Windows Agent
|
||||
|
|
||||
| local Terminal Services WMI provider
|
||||
v
|
||||
Win32_TSPublishedApplication
|
||||
|
|
||||
| observed state in next snapshot
|
||||
v
|
||||
Master / Broker readiness
|
||||
```
|
||||
|
||||
The Agent discovers all local RemoteApps but mutates only explicitly desired SessionGuard resources. Deletion is limited to aliases recorded in Agent state as having been created by SessionGuard. For managed RemoteApps, the broker treats missing executable, missing publication, desired-state mismatch, or reconciliation errors as host-specific unavailability for that Resource.
|
||||
|
||||
## Policy hierarchy
|
||||
|
||||
Policy precedence:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Broker, Farms and Published Resources
|
||||
# Broker, Farms, Apps and Desktops
|
||||
|
||||
## Goal
|
||||
|
||||
@@ -46,7 +46,7 @@ Desktop example:
|
||||
}
|
||||
```
|
||||
|
||||
RemoteApp example:
|
||||
RemoteApp example (Guacamole parameters only):
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -61,6 +61,19 @@ RemoteApp example:
|
||||
}
|
||||
```
|
||||
|
||||
To let SessionGuard publish and continuously reconcile the RemoteApp on all members of the farm, additionally set:
|
||||
|
||||
```json
|
||||
{
|
||||
"manage_remote_app": true,
|
||||
"remote_app_path": "C:\\Program Files\\Sage\\Sage.exe",
|
||||
"remote_app_command_line_setting": 0,
|
||||
"remote_app_show_in_portal": false
|
||||
}
|
||||
```
|
||||
|
||||
The Master sends this desired state only to Agents that are members of the Resource farm. Agents use the local Terminal Services WMI provider, report the observed state, and never delete unrelated/manual RemoteApps.
|
||||
|
||||
Connection ID matching is preferred where stable IDs are known; connection-name matching is case-insensitive and convenient for initial deployment.
|
||||
|
||||
## Placement algorithm
|
||||
@@ -73,13 +86,15 @@ Given `username`, optional `resource_id`, `farm_id`, and Guacamole connection id
|
||||
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:
|
||||
7. For a managed RemoteApp Resource, require the Agent to report that exact Resource as `published`, `path_exists` and `in_sync` with no error. This readiness gate also applies to reconnect and lease reuse.
|
||||
8. 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.
|
||||
- at or above `min_health_score`,
|
||||
- application-ready when Agent-managed RemoteApp publication is enabled.
|
||||
9. Rank candidates by broker score and select the highest score.
|
||||
10. Create or refresh the lease and return connection tokens.
|
||||
|
||||
## Broker score
|
||||
|
||||
|
||||
@@ -52,7 +52,9 @@ remote-app-dir: ${SESSIONGUARD_REMOTE_APP_DIR}
|
||||
remote-app-args: ${SESSIONGUARD_REMOTE_APP_ARGS}
|
||||
```
|
||||
|
||||
Create a matching Published Resource in SessionGuard by Guacamole connection ID or name.
|
||||
If your Agents report short Windows computer names and your DNS requires a suffix, a Guacamole hostname such as `${SESSIONGUARD_HOST}.example.org` is valid.
|
||||
|
||||
Create a matching Published Resource in SessionGuard by Guacamole connection ID or name. In v0.4 the Resource can optionally enable **Agent-managed RemoteApp publication** and specify the executable path. The Master then distributes the desired alias/path to every Agent in the farm. A managed RemoteApp is not brokered to a host until the Agent reports that it is present and in sync. The broker also aligns `${SESSIONGUARD_REMOTE_APP_ARGS}` with the Windows command-line policy (deny/allow/require).
|
||||
|
||||
## Header-auth security boundary
|
||||
|
||||
|
||||
@@ -350,16 +350,16 @@ git describe --tags --always | sed 's/^v//'
|
||||
Für einen sauberen Release:
|
||||
|
||||
```bash
|
||||
git tag v0.3.1
|
||||
git push origin v0.3.1
|
||||
git tag v0.4.0
|
||||
git push origin v0.4.0
|
||||
git push origin main
|
||||
```
|
||||
|
||||
Ein Commit exakt auf Tag `v0.3.1` erzeugt dann:
|
||||
Ein Commit exakt auf Tag `v0.4.0` erzeugt dann:
|
||||
|
||||
```text
|
||||
git.send.nrw/sendnrw/sessionguard:0.3.1
|
||||
git.send.nrw/sendnrw/sessionguard-guacamole:0.3.1
|
||||
git.send.nrw/sendnrw/sessionguard:0.4.0
|
||||
git.send.nrw/sendnrw/sessionguard-guacamole:0.4.0
|
||||
```
|
||||
|
||||
`latest` wird ebenfalls aktualisiert.
|
||||
@@ -367,8 +367,8 @@ git.send.nrw/sendnrw/sessionguard-guacamole:0.3.1
|
||||
### 7.3 Release prüfen
|
||||
|
||||
```bash
|
||||
docker pull git.send.nrw/sendnrw/sessionguard:0.3.1
|
||||
docker pull git.send.nrw/sendnrw/sessionguard-guacamole:0.3.1
|
||||
docker pull git.send.nrw/sendnrw/sessionguard:0.4.0
|
||||
docker pull git.send.nrw/sendnrw/sessionguard-guacamole:0.4.0
|
||||
```
|
||||
|
||||
Für Produktion möglichst einen festen Versions-Tag und nicht ausschließlich `latest` verwenden.
|
||||
@@ -402,7 +402,7 @@ Anlegen:
|
||||
Beispiel:
|
||||
|
||||
```dotenv
|
||||
SESSIONGUARD_VERSION=0.3.1
|
||||
SESSIONGUARD_VERSION=0.4.0
|
||||
POSTGRES_VERSION=17
|
||||
|
||||
TRAEFIK_NETWORK=aio_proxy
|
||||
@@ -655,7 +655,7 @@ image: guacamole/guacamole:${GUACAMOLE_VERSION:-1.6.0}
|
||||
Nachher:
|
||||
|
||||
```yaml
|
||||
image: git.send.nrw/sendnrw/sessionguard-guacamole:${SESSIONGUARD_VERSION:-0.3.1}
|
||||
image: git.send.nrw/sendnrw/sessionguard-guacamole:${SESSIONGUARD_VERSION:-0.4.0}
|
||||
```
|
||||
|
||||
`guac-init` kann weiterhin das offizielle Guacamole-Image verwenden.
|
||||
@@ -675,7 +675,7 @@ SESSIONGUARD_BROKER_TIMEOUT_MS: "2500"
|
||||
In die Guacamole `.env` zusätzlich:
|
||||
|
||||
```dotenv
|
||||
SESSIONGUARD_VERSION=0.3.1
|
||||
SESSIONGUARD_VERSION=0.4.0
|
||||
SESSIONGUARD_BROKER_API_KEY=<EXAKT_DERSELBE_BROKER_API_KEY_WIE_AM_MASTER>
|
||||
```
|
||||
|
||||
@@ -1909,7 +1909,7 @@ Vorher PostgreSQL sichern.
|
||||
Dann neuen Tag setzen, beispielsweise:
|
||||
|
||||
```dotenv
|
||||
SESSIONGUARD_VERSION=0.3.1
|
||||
SESSIONGUARD_VERSION=0.4.0
|
||||
```
|
||||
|
||||
Update:
|
||||
@@ -1942,7 +1942,7 @@ Broker
|
||||
Gleichen SessionGuard-Release-Tag verwenden:
|
||||
|
||||
```dotenv
|
||||
SESSIONGUARD_VERSION=0.3.1
|
||||
SESSIONGUARD_VERSION=0.4.0
|
||||
```
|
||||
|
||||
Dann:
|
||||
@@ -2299,3 +2299,37 @@ docs/TESTING.md
|
||||
```
|
||||
|
||||
Diese Anleitung sollte zusammen mit `docs/TESTING.md` als Go-Live-Grundlage verwendet werden.
|
||||
|
||||
## SessionGuard-managed RemoteApps (v0.4)
|
||||
|
||||
This mode is intended for RD Session Hosts where you want SessionGuard Agents to maintain the local RemoteApp allow-list instead of manually publishing the same alias on every farm member. It uses the documented Terminal Services WMI provider in `root\CIMv2\TerminalServices`. Administrator rights are required for changes; the normal SessionGuard Windows service account must therefore retain its existing local system/administrative privileges.
|
||||
|
||||
Before enabling it for a production farm, verify the provider on a canary RDS host:
|
||||
|
||||
```powershell
|
||||
Get-WmiObject `
|
||||
-Namespace 'root\cimv2\TerminalServices' `
|
||||
-Class Win32_TSPublishedApplication `
|
||||
-Authentication PacketPrivacy |
|
||||
Select-Object Alias,Path,PathExists,CommandLineSetting
|
||||
```
|
||||
|
||||
An empty result is valid when no RemoteApps are published. A class/provider error means this SessionGuard mode should not be enabled on that host until the Windows RDS installation is corrected.
|
||||
|
||||
In **Master → Apps & Desktops**, create/edit a Resource:
|
||||
|
||||
```text
|
||||
Type: RemoteApp
|
||||
Farm: <target farm>
|
||||
RemoteApp Alias: ||Sage
|
||||
Agent-managed publication: enabled
|
||||
Executable: C:\Program Files\Sage\Sage.exe
|
||||
Command-line policy: deny / allow / require
|
||||
```
|
||||
|
||||
The executable must exist at the configured path on each eligible farm member. The Agent reconciles on desired-state changes and periodically thereafter. The Master UI shows per-host readiness. A managed RemoteApp remains unavailable on any host that has not yet reported a healthy synchronized registration.
|
||||
|
||||
SessionGuard only removes aliases that the same Agent originally created and recorded as owned. Existing manually published RemoteApps are discovered and can be adopted for desired-state checks, but are not deleted when management is later disabled. Canary-test this behavior on the exact Windows Server version used in your environment.
|
||||
|
||||
Because v0.4 changes the heartbeat protocol to version 4, upgrade Master and Agents as one coordinated rollout. A v0.3 Agent will be rejected by a v0.4 Master with a protocol-version mismatch until upgraded.
|
||||
|
||||
|
||||
105
docs/REMOTEAPP.md
Normal file
105
docs/REMOTEAPP.md
Normal file
@@ -0,0 +1,105 @@
|
||||
# Agent-managed RemoteApps (v0.4)
|
||||
|
||||
SessionGuard v0.4 can maintain the local Windows RemoteApp registration on every RD Session Host that belongs to a Resource farm. The Master carries the desired state; the Agent reconciles it locally through the Terminal Services WMI provider and reports observed readiness back to the broker.
|
||||
|
||||
## Safety model
|
||||
|
||||
- No inbound WMI/WinRM connection from Master to Windows is introduced.
|
||||
- The Windows Agent performs all WMI calls locally.
|
||||
- Existing unrelated RemoteApps are discovered but not modified.
|
||||
- If a pre-existing alias is explicitly put under SessionGuard management, SessionGuard may update that registration to the configured desired state, but records it as **adopted** rather than owned.
|
||||
- Automatic removal is limited to aliases that the Agent itself originally created and persisted as owned.
|
||||
- A managed RemoteApp is brokered fail-closed per host until the Agent reports: executable exists, registration exists, desired state is in sync, and no reconciliation error is present.
|
||||
|
||||
## Windows prerequisite / canary check
|
||||
|
||||
Run on one RD Session Host in an elevated Windows PowerShell:
|
||||
|
||||
```powershell
|
||||
Get-WmiObject `
|
||||
-Namespace 'root\cimv2\TerminalServices' `
|
||||
-Class Win32_TSPublishedApplication `
|
||||
-Authentication PacketPrivacy |
|
||||
Select-Object Alias,Path,VPath,PathExists,CommandLineSetting,RequiredCommandLine,ShowInPortal
|
||||
```
|
||||
|
||||
An empty result is valid. A class/provider error means the RemoteApp WMI provider is not available on this server and Agent-managed publication must not yet be enabled there.
|
||||
|
||||
The Agent service must run with administrative/local-system privileges because Windows requires administrative rights to change these WMI objects.
|
||||
|
||||
## Create the Resource in Master
|
||||
|
||||
Open **Apps & Desktops** and create/edit a Resource:
|
||||
|
||||
```text
|
||||
Name: Sage 100
|
||||
Type: RemoteApp
|
||||
Farm: ERP
|
||||
Guacamole Connection: Sage 100
|
||||
RemoteApp Alias: ||Sage
|
||||
Agent-managed publication: enabled
|
||||
Executable: C:\Program Files\Sage\Sage.exe
|
||||
Icon path: optional
|
||||
Icon index: 0
|
||||
Command-line policy: deny / allow / require
|
||||
Required arguments: only for require
|
||||
Show in RD Web Access: optional
|
||||
```
|
||||
|
||||
The managed alias must be globally unique across enabled SessionGuard-managed Resources. This prevents collisions when a Windows Agent belongs to multiple farms.
|
||||
|
||||
### Command-line policy
|
||||
|
||||
- `deny (0)`: Windows disallows RemoteApp command-line arguments and SessionGuard sends an empty `${SESSIONGUARD_REMOTE_APP_ARGS}` token.
|
||||
- `allow (1)`: Windows permits arguments and SessionGuard sends the Resource's Guacamole arguments.
|
||||
- `require (2)`: Windows requires the configured arguments and SessionGuard forces those same required arguments into `${SESSIONGUARD_REMOTE_APP_ARGS}`.
|
||||
|
||||
## Agent reconciliation
|
||||
|
||||
The desired Resource is sent in the normal outbound heartbeat only to members of its farm. The Agent reconciles immediately when desired state changes and then periodically (60 seconds) from persisted local desired state, including during a temporary Master outage.
|
||||
|
||||
The local Agent UI contains **RemoteApps**. The Master server detail page also contains the observed inventory.
|
||||
|
||||
Typical states:
|
||||
|
||||
```text
|
||||
Ready published=yes, path_exists=yes, in_sync=yes
|
||||
Not ready executable missing / WMI publication failed / mismatch
|
||||
SessionGuard currently managed desired state
|
||||
(created) registration was originally created by SessionGuard
|
||||
(adopted) registration existed before SessionGuard took it over
|
||||
locally discovered visible only; not modified by SessionGuard
|
||||
```
|
||||
|
||||
The Master Resource table shows `ready/total`, for example `3/3 ready`. The broker excludes only the non-ready hosts for this particular managed application; other desktops/resources can still use those hosts if their own health/rules allow it.
|
||||
|
||||
## Guacamole
|
||||
|
||||
Create one logical Guacamole RDP connection for the application:
|
||||
|
||||
```text
|
||||
hostname: ${SESSIONGUARD_HOST}.stadt-hilden.de
|
||||
remote-app: ${SESSIONGUARD_REMOTE_APP}
|
||||
remote-app-dir: ${SESSIONGUARD_REMOTE_APP_DIR}
|
||||
remote-app-args: ${SESSIONGUARD_REMOTE_APP_ARGS}
|
||||
```
|
||||
|
||||
Map its Guacamole connection ID (preferred) or connection name to the SessionGuard Resource.
|
||||
|
||||
## Upgrade order
|
||||
|
||||
v0.4 uses Agent protocol version 4. Upgrade Master and Agents as a coordinated rollout. Until an Agent is upgraded, a v0.4 Master will reject its old protocol heartbeat. For a production farm, update one canary Agent first, verify local RemoteApp status, and then roll out the remaining hosts quickly within the maintenance window.
|
||||
|
||||
## Rollback behavior
|
||||
|
||||
If you disable Agent-managed publication or delete the Resource:
|
||||
|
||||
- SessionGuard-created aliases are removed on the Agent after it receives the new desired state.
|
||||
- Adopted/pre-existing aliases remain locally published.
|
||||
- Unrelated manually published RemoteApps are never part of SessionGuard cleanup.
|
||||
|
||||
If an Agent loses its local ownership state, SessionGuard errs on the safe side and will not infer ownership merely from the alias; a stale registration may remain and can be removed manually.
|
||||
|
||||
## Microsoft provider reference
|
||||
|
||||
SessionGuard uses Microsoft's documented `Win32_TSPublishedApplication` / `Win32_TSPublishedApplicationList` provider in `Root\CIMv2\TerminalServices` with packet-privacy authentication. This feature manages the local RDSH RemoteApp provider; it does not attempt to reproduce every RD Connection Broker/Collection management semantic.
|
||||
Reference in New Issue
Block a user