Commit Graph

6 Commits

Author SHA1 Message Date
Claude (gsc-ops-api init)
90f98671fc feat(ldap): perform user/group writes via the FreeIPA API
Raw LDAP adds/modifies bypassed FreeIPA's framework, so group/user creates
failed with Object Class Violation (no gidNumber/uidNumber/ipaUniqueID) and
deletes/mods needed ACIs the bind account couldn't exercise as a plain LDAP
write. Route all MUTATIONS through the FreeIPA JSON-RPC API instead; reads
stay on direct LDAP.

- internal/client/freeipa.go: new JSON-RPC client (form login_password →
  ipa_session cookie, re-auth on 401, multi-server failover, TLS via the
  configured CA). Derives the API host + login uid from the LDAP config.
- internal/service/ldap.go: CreateGroup/UpdateGroup/DeleteGroup/AddGroupMembers/
  RemoveGroupMember → group_add/_mod/_del/_add_member/_remove_member;
  CreateUser/UpdateUser/DisableUser/ResetPassword → user_add/_mod/_disable
  (+_enable)/passwd. Services map → addattr(objectclass)/setattr. Writes error
  cleanly when the IPA client is unconfigured.
- cmd/server/main.go: build the FreeIPA client from the LDAP config and inject
  it into the LDAP service.

Verified live: group create (IPA-assigned gidNumber), get, add/remove member,
delete all succeed; reads unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 14:05:19 +02:00
f6a9d5e312 Merge pull request 'fix(certs): default to active certs when no search term' (#2) from fix/certs-list-default into main 2026-06-01 10:14:15 +00:00
Claude (gsc-ops-api init)
30268db4be fix(certs): default to active certs when no search term
EJBCA's certificate/search REST endpoint rejects an empty criteria list
("Invalid criteria value, cannot be empty"), so GET /certs with no ?search
returned a 500. Default to a STATUS=CERT_ACTIVE criterion in that case so the
list endpoint returns active certificates. Search-by-query is unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 12:13:52 +02:00
2de3fb0ead Merge pull request 'Dynamic, scoped API keys (+ restore cmd/server entrypoint)' (#1) from feat/dynamic-scoped-api-keys into main 2026-06-01 09:33:16 +00:00
Claude (gsc-ops-api init)
9fd11afa00 feat: dynamic, scoped API keys (+ restore cmd/server entrypoint)
Validate X-API-Key against a DB-backed, self-managed key store in addition
to the static Infisical keys, so new consumers (e.g. gsc_admin) no longer
require a rebuild. Keys carry scopes (e.g. {ldap:read}); the required scope
is derived per-request from path + method and enforced by ScopeEnforce.
Static Infisical keys keep an implicit wildcard scope (no regression).

- service/apikey.go: DB store (admin.api_keys, SHA-256 hashes only), 30s
  validation cache, generate/list/revoke. EnsureSchema is existence-first
  (to_regclass) so a least-privilege DB role starts cleanly when the table
  is provisioned out-of-band; startup is non-fatal if the store is absent.
- handler/apikeys.go + routes: POST/GET/DELETE /api/v1/admin/api-keys.
- middleware/apikey.go: APIKeyWithValidator + Principal + ScopeEnforce.
- pkg/types/scopes.go: scope vocabulary + matching.
- migrations/002_api_keys.sql.

Also restore cmd/server/main.go, which the `.gitignore` `server` pattern
was silently excluding (it matched cmd/server/); anchored that pattern and
`gsc-ops-api` to the repo root so only the built binaries are ignored.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 11:13:33 +02:00
Claude (gsc-ops-api init)
3847eb2036 Initial import — snapshot from admin host /srv/gosec/gsc-ops-api
This repo had no version control prior to this commit. The import is a
straight snapshot of the working tree at 2026-05-03; the deployed
binary on fihelvop01 was being rebuilt from this source via `make
build` + scp into place, with no upstream review path.

The snapshot already includes one in-flight fix made on 2026-05-03 to
internal/service/persona.go:GetSelfModel — the handler queried
`source` and `strength` columns plus an `is_active = true` filter on
persona.persona_commitments, none of which exist on that table (its
shape is session-bound commitments with `status`, `commitment_meta`,
etc.). The query returned a 500 every time SynapseHub bootstrapped a
persona's self-model, dropping the IdentityConstraints / Commitments /
ConscienceStandards layer from the assembled prompt. The patched
query reads existing columns only (commitment_text, commitment_type),
filters on `status='active'`, and synthesises Source="learned" /
Strength=1.0 to keep the SelfModel response shape stable for callers.

Verified live: `GET /api/v1/personas/70f7cfd9-.../self-model` now
returns 200 with `{identityConstraints:[],commitments:[],
conscienceStandards:[]}` instead of 500.

Future changes go through PRs against this repo — no more bin-only
deploys.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 20:06:02 +02:00