docs: sync runner-topology and SEC-36 rotation prose with 2026-08-07 executed state
This commit is contained in:
@@ -249,7 +249,7 @@ dev/test GLAuth posture (`glauth.md`), not a production posture.
|
|||||||
| `MxGateway:Ldap:AllowInsecure` | `true` | Permits a plaintext bind. Must be `true` when `Transport` is `None`; set `false` (with `Ldaps`/`StartTls`) in production. |
|
| `MxGateway:Ldap:AllowInsecure` | `true` | Permits a plaintext bind. Must be `true` when `Transport` is `None`; set `false` (with `Ldaps`/`StartTls`) in production. |
|
||||||
| `MxGateway:Ldap:SearchBase` | `dc=zb,dc=local` | Search base DN. |
|
| `MxGateway:Ldap:SearchBase` | `dc=zb,dc=local` | Search base DN. |
|
||||||
| `MxGateway:Ldap:ServiceAccountDn` | `cn=serviceaccount,dc=zb,dc=local` | Bind DN for the search account. |
|
| `MxGateway:Ldap:ServiceAccountDn` | `cn=serviceaccount,dc=zb,dc=local` | Bind DN for the search account. |
|
||||||
| `MxGateway:Ldap:ServiceAccountPassword` | `${secret:ldap/mxgateway/bind}` | Search-account password. **Never a committed plaintext value (SEC-36):** the shared GLAuth bind credential is supplied out-of-band through one of three channels, all binding to this key. **(1) Encrypted secrets store (shipped default):** `appsettings.json` ships the reference `${secret:ldap/mxgateway/bind}`, which the pre-host `${secret:}` expander resolves at startup from the encrypted secrets store (the code-side design default is blank, so a missing/unresolved value fails closed rather than falling back to a leaked credential). Seed it once with `secret set ldap/mxgateway/bind <value>` (the store's master key must be present via `ZB_SECRETS_MASTER_KEY`); startup aborts with `SecretNotFoundException` if the secret is absent. **(2) Deployed hosts — env var:** override directly with `MxGateway__Ldap__ServiceAccountPassword` (double-underscore form) in the NSSM service environment — a plain literal there is used as-is and the store lookup is skipped. **(3) Dev boxes — user-secrets:** `dotnet user-secrets set "MxGateway:Ldap:ServiceAccountPassword" <value>` (the server carries `<UserSecretsId>mxaccessgw-server</UserSecretsId>`; user-secrets load automatically in the Development environment and live under the user profile, outside the tree). The value comes from the GLAuth source of truth `scadaproj/infra/glauth/`, never from a repo file. **Rotation:** because the credential was historically committed, rotating it in `scadaproj/infra/glauth/` (and redeploying the shared GLAuth on `10.100.0.35`) is required — see `docs/runbooks/SEC-36-ldap-credential-rotation.md` for the cutover order. A blank/unresolved value fails startup validation with a message naming the two supported channels. |
|
| `MxGateway:Ldap:ServiceAccountPassword` | `${secret:ldap/mxgateway/bind}` | Search-account password. **Never a committed plaintext value (SEC-36):** the shared GLAuth bind credential is supplied out-of-band through one of three channels, all binding to this key. **(1) Encrypted secrets store (shipped default):** `appsettings.json` ships the reference `${secret:ldap/mxgateway/bind}`, which the pre-host `${secret:}` expander resolves at startup from the encrypted secrets store (the code-side design default is blank, so a missing/unresolved value fails closed rather than falling back to a leaked credential). Seed it once with `secret set ldap/mxgateway/bind <value>` (the store's master key must be present via `ZB_SECRETS_MASTER_KEY`); startup aborts with `SecretNotFoundException` if the secret is absent. **(2) Deployed hosts — env var:** override directly with `MxGateway__Ldap__ServiceAccountPassword` (double-underscore form) in the NSSM service environment — a plain literal there is used as-is and the store lookup is skipped. **(3) Dev boxes — user-secrets:** `dotnet user-secrets set "MxGateway:Ldap:ServiceAccountPassword" <value>` (the server carries `<UserSecretsId>mxaccessgw-server</UserSecretsId>`; user-secrets load automatically in the Development environment and live under the user profile, outside the tree). The value comes from the GLAuth source of truth `scadaproj/infra/glauth/`, never from a repo file. **Rotation:** because the credential was historically committed, it was rotated in `scadaproj/infra/glauth/` (and the shared GLAuth on `10.100.0.35` redeployed) on 2026-08-07 (SEC-36) — see `docs/runbooks/SEC-36-ldap-credential-rotation.md` for the cutover procedure used, and for future rotations. A blank/unresolved value fails startup validation with a message naming the two supported channels. |
|
||||||
| `MxGateway:Ldap:UserNameAttribute` | `cn` | LDAP attribute holding the login user name. |
|
| `MxGateway:Ldap:UserNameAttribute` | `cn` | LDAP attribute holding the login user name. |
|
||||||
| `MxGateway:Ldap:DisplayNameAttribute` | `cn` | LDAP attribute holding the display name. |
|
| `MxGateway:Ldap:DisplayNameAttribute` | `cn` | LDAP attribute holding the display name. |
|
||||||
| `MxGateway:Ldap:GroupAttribute` | `memberOf` | LDAP attribute enumerating group membership (mapped to dashboard roles via `MxGateway:Dashboard:GroupToRole`). |
|
| `MxGateway:Ldap:GroupAttribute` | `memberOf` | LDAP attribute enumerating group membership (mapped to dashboard roles via `MxGateway:Dashboard:GroupToRole`). |
|
||||||
|
|||||||
+16
-14
@@ -455,20 +455,22 @@ runtime because the x86 Worker cannot build on Linux:
|
|||||||
|
|
||||||
### Runner capacity is shared and finite
|
### Runner capacity is shared and finite
|
||||||
|
|
||||||
All CI runs on a co-located `gitea-runner` container on docker host `10.100.0.35` with
|
CI runs on two co-located runner containers on docker host `10.100.0.35` — `gitea-runner`
|
||||||
`maxParallel=1`, and that runner instance is **shared across repos** — it interleaves
|
(capacity 4) and `gitea-runner-2` (capacity 2, registered 2026-08-07 per
|
||||||
`dohertj2/mxaccessgw` and `dohertj2/lmxopcua` jobs on the single slot rather than being
|
`docs/runbooks/TST-30-second-ci-runner.md`) — and both runner instances are **shared across
|
||||||
scoped to this repo (`GET /repos/dohertj2/mxaccessgw/actions/runners` returns
|
repos**: they interleave `dohertj2/mxaccessgw` and `dohertj2/lmxopcua` jobs across the
|
||||||
`total_count: 0`; the runner is registered at the instance level). Every job in a run
|
combined slots rather than being scoped to this repo (`GET
|
||||||
(`portable`, `java`, `windows-x86`) executes serially, so queue latency is additive within
|
/repos/dohertj2/mxaccessgw/actions/runners` returns `total_count: 0`; both runners are
|
||||||
a run and an active `lmxopcua` run blocks `mxaccessgw` entirely — expect ~20–30 minutes of
|
registered at the instance level). Every job in a run (`portable`, `java`, `windows-x86`)
|
||||||
queue depth under cross-repo contention, not a stuck pipeline. This Gitea version (1.26)
|
still executes serially within that run, so queue latency is additive within a run, but an
|
||||||
also exposes **no run cancel or delete via the API** (`POST .../actions/runs/{id}/cancel`
|
active `lmxopcua` run no longer blocks `mxaccessgw` entirely the way a single shared slot
|
||||||
returns 404, `DELETE .../actions/runs/{id}` returns 400), so a superseded or hung run cannot
|
did — the two runners relieve cross-repo contention. This Gitea version (1.26) also exposes
|
||||||
be cleared and holds the slot until it finishes or times out. See
|
**no run cancel or delete via the API** (`POST .../actions/runs/{id}/cancel` returns 404,
|
||||||
`docs/runbooks/TST-30-second-ci-runner.md` for the operator runbook that registers a second
|
`DELETE .../actions/runs/{id}` returns 400), so a superseded or hung run cannot be cleared
|
||||||
runner to relieve this; until that lands, treat single-runner contention as expected, not a
|
and holds the slot until it finishes or times out — with two runners this means a single
|
||||||
CI outage.
|
wedged run can still hold slots, because the no-cancel reality is unchanged. See
|
||||||
|
`docs/runbooks/TST-30-second-ci-runner.md` for the operator runbook that registered the
|
||||||
|
second runner.
|
||||||
|
|
||||||
When queue depth (or the missing-cancel reality) makes waiting impractical, verify a
|
When queue depth (or the missing-cancel reality) makes waiting impractical, verify a
|
||||||
specific commit out of band instead of waiting behind the queue: run
|
specific commit out of band instead of waiting behind the queue: run
|
||||||
|
|||||||
@@ -40,8 +40,9 @@ gw-specific role.
|
|||||||
> it out-of-band (encrypted secrets store reference `${secret:ldap/mxgateway/bind}`, the
|
> it out-of-band (encrypted secrets store reference `${secret:ldap/mxgateway/bind}`, the
|
||||||
> `MxGateway__Ldap__ServiceAccountPassword` env var on deployed hosts, or `dotnet user-secrets`
|
> `MxGateway__Ldap__ServiceAccountPassword` env var on deployed hosts, or `dotnet user-secrets`
|
||||||
> on dev boxes — see `docs/GatewayConfiguration.md`). The credential was historically committed
|
> on dev boxes — see `docs/GatewayConfiguration.md`). The credential was historically committed
|
||||||
> to this repo (and remains recoverable from git history), so **rotation is required**; the
|
> to this repo (and remains recoverable from git history); it **was rotated on 2026-08-07**
|
||||||
> operator runbook is `docs/runbooks/SEC-36-ldap-credential-rotation.md`.
|
> (SEC-36, executed per `docs/runbooks/SEC-36-ldap-credential-rotation.md`) and the old
|
||||||
|
> committed value no longer binds.
|
||||||
|
|
||||||
## Pre-existing groups (LmxOpcUa role taxonomy)
|
## Pre-existing groups (LmxOpcUa role taxonomy)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user