RBAC Phase 1: membership authority endpoint + fail-closed API auth (#14)
Implements the model-B2 membership authority (ratified compliance auth design) and inbound token verification.
- GET /v1/users/{id}/memberships: Keycloak supplies user->tenant links + org_roles (attribute projection until the realm migrates to Organizations); registered tenants override status/plan/products from registry tables (source: registry|keycloak). Closes the M5.2-deferred org_roles stub.
- New internal/authn: OIDC discovery + JWKS verification (go-oidc/v3), audience tenant-registry. /healthz + /readyz stay PUBLIC_EXPLICIT; all other routes INTERNAL_SERVICE_ONLY. AUTH_ENABLED=true refuses to start on incomplete config (fail-closed); false (dev default) keeps current behavior.
- Full suite green incl. postgres testcontainers; openapi.yaml updated (contract test passes).
Activation is a separate step (Auth-5): requires the orca-infra env merge and a portal service token (portal currently calls with no auth).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Sharang Parnerkar <30073382+mighty840@users.noreply.github.com>
Reviewed-on: #14
This commit was merged in pull request #14.
This commit is contained in:
+16
-1
@@ -10,6 +10,7 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"gitea.meghsakha.com/platform/tenant-registry/internal/authn"
|
||||
"gitea.meghsakha.com/platform/tenant-registry/internal/config"
|
||||
"gitea.meghsakha.com/platform/tenant-registry/internal/keycloak"
|
||||
"gitea.meghsakha.com/platform/tenant-registry/internal/server"
|
||||
@@ -59,7 +60,21 @@ func main() {
|
||||
kc = keycloak.NewMock()
|
||||
}
|
||||
|
||||
handler := server.NewRouter(&server.Server{Cfg: cfg, Log: logger, Store: s, Keycloak: kc})
|
||||
var av *authn.Verifier
|
||||
if cfg.AuthEnabled {
|
||||
av, err = authn.New(bootCtx, cfg.KeycloakIssuer, cfg.AuthAudience)
|
||||
if err != nil {
|
||||
// Fail closed: never start an "authenticated" server that
|
||||
// cannot actually verify tokens.
|
||||
slog.Error("AUTH_CONFIG_INCOMPLETE — AUTH_ENABLED=true but verifier init failed", "err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
slog.Info("api auth enabled", "issuer", cfg.KeycloakIssuer, "audience", cfg.AuthAudience)
|
||||
} else {
|
||||
slog.Warn("AUTH_ENABLED=false — API is unauthenticated (dev only)")
|
||||
}
|
||||
|
||||
handler := server.NewRouter(&server.Server{Cfg: cfg, Log: logger, Store: s, Keycloak: kc, Auth: av})
|
||||
srv := &http.Server{
|
||||
Addr: cfg.Addr,
|
||||
Handler: handler,
|
||||
|
||||
Reference in New Issue
Block a user