Research: steward orders on Windows hosts (JEA, Ansible win_*, Intune Remediations and EPM, Windows OpenSSH, PIM, CyberArk, Teleport) and Starfire/Raven body facts
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
ecb2ae0995
commit
e4fd4ae09c
1 changed files with 155 additions and 0 deletions
|
|
@ -128,3 +128,158 @@ says about this design.
|
||||||
is its projection.
|
is its projection.
|
||||||
- Break-glass, when it lands, waits on an announcement and a window, and is
|
- Break-glass, when it lands, waits on an announcement and a window, and is
|
||||||
recorded in full.
|
recorded in full.
|
||||||
|
|
||||||
|
## 5. Windows hosts: Starfire and Raven
|
||||||
|
|
||||||
|
Serves follow-up `steward-orders-windows-hosts` under ruling
|
||||||
|
`remote-admin-on-desktops` (operator 2026-10-31: "We'll need a way to do this
|
||||||
|
kind of thing remotely"). The trigger: on 2026-10-31 she approved through UAC,
|
||||||
|
sitting at Starfire, an elevated script that added an inbound firewall rule for
|
||||||
|
Ollama on the WireGuard interface and registered a SYSTEM startup task. She is
|
||||||
|
away from today, possibly for months; a hard reboot already needs a call.
|
||||||
|
|
||||||
|
### Body, as read on 2026-10-31 (read-only)
|
||||||
|
|
||||||
|
- Both hosts answer TCP 22 and 3389 from Yggdrasil over WireGuard: Starfire
|
||||||
|
10.77.0.2, Raven 10.77.0.4. WinRM is stopped (start type Manual) on both.
|
||||||
|
winget v1.29 is present; choco is not on Raven.
|
||||||
|
- Yggdrasil holds no SSH client config and no private key for either host:
|
||||||
|
`gamecultadmin` has only `authorized_keys` and `known_hosts`, root has no
|
||||||
|
client key, and the mind users have no home. Nothing on Yggdrasil can reach a
|
||||||
|
Windows shell today.
|
||||||
|
- Starfire: sshd runs, the stock `Match Group administrators` stanza is in
|
||||||
|
force, `C:\ProgramData\ssh\administrators_authorized_keys` does not exist and
|
||||||
|
the operator's user has no `authorized_keys`. Its admins are the operator's
|
||||||
|
user (`Meta`) and the built-in Administrator. No key reaches Starfire; RDP,
|
||||||
|
Sunshine/Moonlight and her own UAC click are the only privileged paths in.
|
||||||
|
- Raven: `administrators_authorized_keys` holds one key, commented
|
||||||
|
`192.168.1.84 access key`, whose private half is on Starfire (the `raven`
|
||||||
|
host entry in the operator's `~/.ssh/config`). A session with it is
|
||||||
|
`BUILTIN\Administrators` at High Mandatory Level: Starfire already holds raw,
|
||||||
|
unaudited admin on Raven.
|
||||||
|
- Raven already runs Idunn's host actuator (`idunn-host serve`, task
|
||||||
|
`GameCult-Idunn-Host`, at logon, interactive, Limited): it dials
|
||||||
|
`10.77.0.1:17890/udp` over CultNet RUDP, accepts only requests Idunn's
|
||||||
|
service identity signed, and signs its reports with its own host identity
|
||||||
|
(`docs/host-actuator.md`; runbook `gamecult-ops/runbooks/idunn-host-raven.md`).
|
||||||
|
It is unelevated by design: Muninn must live in the desktop session. Starfire
|
||||||
|
has no actuator.
|
||||||
|
- Memory, not re-proven here: Starfire has frozen under load (PSU or GPU
|
||||||
|
suspected), and nothing that must survive may depend on Starfire or Raven
|
||||||
|
staying up (`workstation-load-budget.md`, 2026-10-29).
|
||||||
|
|
||||||
|
### PowerShell JEA (Just Enough Administration)
|
||||||
|
|
||||||
|
- A session configuration (`.pssc`, registered with
|
||||||
|
`Register-PSSessionConfiguration`) maps caller groups to role capabilities
|
||||||
|
(`.psrc`); a role lists `VisibleCmdlets` with per-parameter `ValidateSet` or
|
||||||
|
`ValidatePattern`, the session runs in `NoLanguage` mode and executes as a
|
||||||
|
temporary virtual account (`RunAsVirtualAccount`) or a gMSA, so the caller
|
||||||
|
holds no admin right. `TranscriptDirectory` records every session.
|
||||||
|
(Microsoft Learn: "JEA overview", "JEA role capabilities", "JEA session
|
||||||
|
configurations", "Auditing and reporting on JEA".)
|
||||||
|
- JEA rides WinRM. SSH-based PowerShell remoting has not supported endpoint
|
||||||
|
configurations or JEA (Microsoft Learn, "PowerShell remoting over SSH",
|
||||||
|
limitations; the current page may have changed, check before relying on it).
|
||||||
|
- Microsoft's own warning: a role that exposes a command able to run arbitrary
|
||||||
|
code (`Start-Process`, `Invoke-Expression`, `Register-ScheduledTask` with a
|
||||||
|
free action, `New-Service` with a free path) is an escape to the run-as
|
||||||
|
account ("JEA security considerations").
|
||||||
|
- On a workgroup desktop, WinRM needs a listener (HTTPS for anything but
|
||||||
|
Kerberos), a local Windows account for the caller, and that account's
|
||||||
|
password or certificate mapping held by the caller.
|
||||||
|
- Lesson: JEA is the platform's answer to "typed, parameter-validated admin
|
||||||
|
with a transcript", and its role file is the same shape as a typed order. It
|
||||||
|
brings WinRM (off today), a Windows credential that would live on Yggdrasil,
|
||||||
|
and no order id, brake or post: those would still be Idunn's, so the grammar
|
||||||
|
would live twice, once in PowerShell attributes on each host and once in the
|
||||||
|
order record.
|
||||||
|
|
||||||
|
### Ansible `win_*` modules over WinRM or SSH
|
||||||
|
|
||||||
|
- `ansible.windows.win_service` (state started, stopped, restarted; start
|
||||||
|
mode), `community.windows.win_firewall_rule` (name, direction, action,
|
||||||
|
protocol, localport, remoteip, profiles, interfacetypes),
|
||||||
|
`community.windows.win_scheduled_task` (actions, triggers, principal, run
|
||||||
|
level), `ansible.windows.win_package` and the community `win_chocolatey` and
|
||||||
|
winget modules. Each takes typed parameters, declares desired state, is
|
||||||
|
idempotent and reports changed, ok or failed. Transport is WinRM or OpenSSH
|
||||||
|
with `ansible_shell_type: powershell`; over OpenSSH an admin key already has
|
||||||
|
the elevated token, so no `become`. (Ansible docs: "Windows Remote
|
||||||
|
Management", "Windows SSH", module pages.)
|
||||||
|
- Lesson: these modules are the order vocabulary to copy, with desired-state
|
||||||
|
semantics ("rule X exists with these fields") rather than imperative verbs.
|
||||||
|
Agentless push means the controller holds admin credentials for every host,
|
||||||
|
which is the shape the brief rules out.
|
||||||
|
|
||||||
|
### Intune Remediations and Endpoint Privilege Management
|
||||||
|
|
||||||
|
- The Intune Management Extension runs on the device as SYSTEM, polls the
|
||||||
|
service outbound over HTTPS, runs a detection script and, when it reports
|
||||||
|
non-compliant, the remediation script, and returns both outputs to the
|
||||||
|
console. No inbound port; the device authenticates by its enrolment
|
||||||
|
certificate. (Microsoft Learn: "Remediations", "Intune Management
|
||||||
|
Extension".)
|
||||||
|
- Endpoint Privilege Management adds support-approved elevation: the user asks
|
||||||
|
to elevate one file, the request reaches the console, an admin approves
|
||||||
|
there, and the device elevates that file hash only, logged. (Microsoft
|
||||||
|
Learn: "Endpoint Privilege Management", "support approved elevation".)
|
||||||
|
- Lesson: the mature Windows pattern for an absent administrator is a SYSTEM
|
||||||
|
agent that dials out, executes only what its authority signed and reports
|
||||||
|
back, and EPM is the nearest thing to "remote approval in place of a UAC
|
||||||
|
click". It is the shape `idunn-host` already has on Raven, minus elevation.
|
||||||
|
|
||||||
|
### Windows OpenSSH and administrators
|
||||||
|
|
||||||
|
- For a member of Administrators, sshd reads only
|
||||||
|
`%ProgramData%\ssh\administrators_authorized_keys` (ACL Administrators and
|
||||||
|
SYSTEM), and a key-authenticated session gets the full token: UAC does not
|
||||||
|
apply. Observed on Raven at High Mandatory Level. (Win32-OpenSSH wiki;
|
||||||
|
issue #1942 on the file's location.)
|
||||||
|
- Forced commands: `ForceCommand` in a `Match` block is the documented route;
|
||||||
|
whether `command=` in an authorized_keys line is honoured on Windows has an
|
||||||
|
open report of it being ignored (Win32-OpenSSH issue #473). Unproven on
|
||||||
|
these hosts.
|
||||||
|
- Lesson: an admin key is a remote UAC bypass with nothing but sshd's event log
|
||||||
|
for a record. As an order transport it needs a forced command that parses
|
||||||
|
the order on the host, and that parser is the whole boundary.
|
||||||
|
|
||||||
|
### How remote approval replaces a local UAC click
|
||||||
|
|
||||||
|
- Entra PIM: a user eligible for a role activates it for a bounded time with a
|
||||||
|
justification, optional MFA, and optional approval by a named approver who
|
||||||
|
is notified and approves in the portal or app; every activation is logged.
|
||||||
|
(Microsoft Learn, "Privileged Identity Management".)
|
||||||
|
- CyberArk dual control: use of a privileged account needs an approver's
|
||||||
|
confirmation in the vault's web or mobile client; sessions run through a
|
||||||
|
recording proxy (PSM). (CyberArk docs: "Dual control", "Privileged Session
|
||||||
|
Manager".)
|
||||||
|
- Teleport access requests: a role is requested with a reason; reviewers
|
||||||
|
approve or deny, thresholds can require N approvals, and plugins put the
|
||||||
|
request in Slack, Mattermost or PagerDuty with approve buttons; the grant is
|
||||||
|
time-boxed and sessions are recorded. (Teleport docs: "Access Requests",
|
||||||
|
"Access Request plugins".)
|
||||||
|
- Shared shape: the approval arrives over an out-of-band channel authenticated
|
||||||
|
as the approver, is scoped to one request, expires, and is recorded beside
|
||||||
|
the request. A request nobody answers is denied, never run. Shared
|
||||||
|
assumption: an approver who answers in minutes.
|
||||||
|
- Lesson for an operator away for months: positive approval is only as live as
|
||||||
|
her reachability. Where her approval is kept, the channel is her Matrix
|
||||||
|
account replying in #operator to one order id (Synapse authenticates the
|
||||||
|
sender; a Mind cannot forge her mxid without root on Yggdrasil), with an
|
||||||
|
expiry after which the order is refused. Where it is not, the order's type
|
||||||
|
is the defence, as for Linux (section 3).
|
||||||
|
|
||||||
|
### What this gives the Windows design
|
||||||
|
|
||||||
|
- A SYSTEM agent on each host dials out to an authority that signs every
|
||||||
|
request; no inbound port, no Windows credential and no admin key on
|
||||||
|
Yggdrasil (Intune, Salt minion, `idunn-host`).
|
||||||
|
- The four Ansible modules become typed, desired-state orders, and JEA's
|
||||||
|
warning becomes the grammar rule: no order field names a free program,
|
||||||
|
script, or path to run outside a root the host binding declares.
|
||||||
|
- A Windows host is often absent (a frozen Starfire, a reboot waiting on a
|
||||||
|
call): an order to an unattached host is refused at once, never queued to
|
||||||
|
fire days later.
|
||||||
|
- Approval, where kept, is a Matrix reply from her account to one order id,
|
||||||
|
scoped and expiring; anything outside the grammar is break-glass.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue