Release: object viewer, roles, cert/firewall automation, API key fix #12

Merged
gsadmin merged 11 commits from development into main 2026-09-03 02:26:20 +00:00
Owner

Summary

Second release batch from development since #11.

Fixes

  • API keys List 500created_utc scanned as a string (modernc.org/sqlite TEXT timestamp). Regression test TestAPIKeyListRoundTrip.
  • Final sweep: no remaining direct time.Time scans anywhere in the backend.
  • objectGUID / objectSid / sIDHistory now decode correctly (mixed-endian GUID, S-1-… SID) in the Object Viewer and query preview.

Features

  • Object Viewer page: connection selector, search, per-object attribute drill-in with copy-to-clipboard for building filters.
  • User roles (Administrator / Operator / Viewer) with OIDC default-role dropdown, dynamic callback URL with copy button, issuer example; confusing redirect URL field removed.
  • Auto-managed TLS: self-managed root/intermediate certs are installed into the Windows LocalMachine ROOT/CA stores and kept updated.
  • Idempotent Windows firewall rule (RFC1918 + CGNAT inbound on the service port) created on initialize, removed on remove.
  • MSI: blank EULA page skipped; standard license notice retained for build safety.
  • Backups: keep last 3.
  • Connections: LDAPS toggle auto-flips port 636/389 and enables allow-invalid-certs.
  • Paging on Object Viewer, Windows cert list, rule preview and history result lists.

Merging this cuts a release (binaries, container image, MSI).

## Summary Second release batch from `development` since #11. ### Fixes - **API keys `List` 500** — `created_utc` scanned as a string (modernc.org/sqlite TEXT timestamp). Regression test `TestAPIKeyListRoundTrip`. - Final sweep: no remaining direct `time.Time` scans anywhere in the backend. - **objectGUID / objectSid / sIDHistory** now decode correctly (mixed-endian GUID, `S-1-…` SID) in the Object Viewer and query preview. ### Features - **Object Viewer** page: connection selector, search, per-object attribute drill-in with copy-to-clipboard for building filters. - **User roles** (Administrator / Operator / Viewer) with OIDC default-role dropdown, dynamic callback URL with copy button, issuer example; confusing redirect URL field removed. - **Auto-managed TLS**: self-managed root/intermediate certs are installed into the Windows LocalMachine `ROOT`/`CA` stores and kept updated. - **Idempotent Windows firewall rule** (RFC1918 + CGNAT inbound on the service port) created on `initialize`, removed on `remove`. - MSI: blank EULA page skipped; standard license notice retained for build safety. - Backups: keep last 3. - Connections: LDAPS toggle auto-flips port 636/389 and enables allow-invalid-certs. - Paging on Object Viewer, Windows cert list, rule preview and history result lists. ### Merging this cuts a release (binaries, container image, MSI).
gsadmin added 11 commits 2026-09-03 02:26:03 +00:00
The SQLite database now lives at data/db/orchestrad.db instead of the data
root. db.New creates the db/ directory (SQLite will not) and, on first run,
moves a legacy data/orchestrad.db plus its -wal/-shm sidecars into db/ so
existing installations keep their data. Verified live: an existing demo
database migrated into data/db and all data (connections, rules, schedules)
was retained. Test covers the move + idempotency.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The Windows-store certificate list only loaded after clicking a separate
"List certificates" button, so selecting the Windows-store option appeared
to show nothing. Fetch the certificates automatically when the source is
chosen (and the store is supported); the button becomes a Refresh. The
backend endpoint and windowsStoreSupported flag were already correct.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Make the API browsable/usable from Swagger UI without dev tools:
- Normalize chi's trailing slash on collection roots (Post("/")) so registry
  detail and pagination attach — previously POST /ad-connections etc. showed
  no request body.
- Document request bodies for the main create/update operations (connections,
  credentials, schedules, api-keys, users, settings, tls mode/certificate,
  query-preview, config import) with component schemas.
- Add standard page/pageSize query params to collection GETs.
- Add the X-API-Key security scheme alongside bearer so both auth methods
  show in the Authorize dialog.

Test covers the trailing-slash normalization + body attachment.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Roles:
- Add GET /api/v1/roles (built-in SuperAdmin/Admin/Operator/Viewer) and
  wire role assignment into user create/update (UserRepository.SetRoles /
  GetRoleNames / ListRoles). User responses now include roles.
- User dialog gains a roles multi-select; the users list shows role chips.

OIDC / SSO config UI:
- Default role is now a dropdown populated from /roles.
- Issuer URL shows real provider examples (Entra/Okta/Google).
- Replace the confusing manual "Redirect URL" field with a read-only,
  auto-derived callback URL (from the browser origin / public URL) plus a
  copy button — the exact value to register at the IdP. The backend still
  auto-derives the callback and honors an env override.

Verified: /roles lists the four roles; creating/updating a user with roles
round-trips through GET.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A new Object Viewer page: pick a connection, choose an object type and search
by name (or drop in a raw LDAP filter and a search base), list the matches,
and drill into any object to see all its attributes with copy buttons for the
attribute name and value — so operators can discover the exact attributes and
values to put in a rule filter.

Built on the existing query-preview endpoint (now typed as QueryPreviewResult);
the detail view requests all attributes (["*"]). Added to the Directory nav.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
When TLS is in auto (self-managed) mode, install the generated root into the
LocalMachine "Root" (Trusted Root CAs) store and the intermediate into the
"CA" (Intermediate CAs) store, so clients on this host trust the served
chain without manual import. Runs on every ensure/renewal with a replace
disposition, so it is idempotent and a renewed CA supersedes the previous
one. Best-effort (needs admin; the Windows service runs as LocalSystem);
a no-op on non-Windows.

Verified: OrchestrAD Root CA appears in LocalMachine\Root and the
Intermediate in LocalMachine\CA after startup.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Firewall:
- On service initialize/install, create an idempotent inbound allow rule
  ("OrchestrAD") for the configured listen port, scoped to RFC 1918 private
  ranges plus CGNAT (10/8, 172.16/12, 192.168/16, 100.64/10). The rule is
  deleted-then-added so it always reflects the current port, and removed on
  service uninstall. Best-effort (needs admin; the MSI custom action and
  service run elevated); no-op off Windows. Verified the netsh rule lands
  with the expected port and remote-address scoping.

MSI:
- Skip the license/EULA page (Welcome now goes straight to the install
  directory), since it was blank. A standard short notice is kept in
  license.rtf only so the stock license control resolves at build time.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Toggling LDAPS in the connection form now auto-sets the port (636 on / 389
  off when it's still the other default) and enables "Allow invalid certs",
  because a non-domain-joined host usually can't validate the DC's LDAPS
  certificate. This fixes the common "existing connection was forcibly
  closed" seen when LDAPS was enabled while the port stayed 389 (dialing TLS
  to the plaintext port). Helper text explains the traffic is still encrypted.
- LDAP client sets tls ServerName to the host so verification succeeds when a
  DC cert IS trusted (ignored under InsecureSkipVerify).
- Backups retention reduced from 10 to 3.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The object viewer showed raw bytes for binary attributes. Format them for
display: objectGUID as a canonical GUID, objectSid/sIDHistory as S-1-… SID
strings, and any other non-printable value as base64. Applied in the
query-preview path that the object viewer uses; printable values pass through.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add client-side pagination (TablePagination) to lists that could grow long
and cause endless scroll:
- Object Viewer search results
- Object attribute detail dialog
- Windows certificate store list (Security)
- Rule preview matched objects (previously hard-capped at 100 with no paging)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
APIKeyService.List scanned created_utc straight into time.Time, which the
modernc.org/sqlite driver returns as a string — surfacing as a 500 "Failed
to list API keys". Scan it into a string and parse. Regression test covers
the create+list round-trip (created_utc parsed, scope preserved).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
gsadmin merged commit 4a7cc9b69e into main 2026-09-03 02:26:20 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: gsadmin/OrchestrAD#12