// keycloak-provider: keycloak's code, one binary the node's runtime launches and speaks MCP to over // stdio through the Go SDK (novox/hq ADR 0188, 0193). It serves keycloak's tools and, beside them, // runs long: the provisioner that makes keycloak the provider of the mesh `oidc-client` interface, // and the guard that keeps the admin logging in with the mesh's secret (novox/hq issue 179). // // stdout is the MCP channel; everything this module says, it says on stderr. package main import ( "context" "os" stdio "git.novox.be/novox/mesh-sdk/go" ) func say(format string, args ...any) { logStderr("[keycloak] "+format, args...) } // announce emits an event without letting a broker hiccup fail what it announces: the change already // happened in Keycloak. func announce(event string, body map[string]any) { if err := stdio.Emit(event, body); err != nil { say("emit %s failed: %v", event, err) } } func main() { kc, err := ClientFromEnv(os.Getenv) if err != nil { // Without the admin password there is nothing to serve, provision or guard; said, not fatal, // so the runtime does not restart a process that cannot do better. say("%v; serving no tools and provisioning nothing", err) if err := stdio.Serve("", nil); err != nil { say("%v", err) os.Exit(1) } return } guard := &Guard{ KC: kc, Container: os.Getenv("MESH_KEYCLOAK_CONTAINER"), Log: logStderr, Announce: announce, } kc.onRejected = guard.Nudge go guard.Run(context.Background()) var h *Harness if receives := os.Getenv("MESH_RECEIVES"); receives == "" { say("MESH_RECEIVES is not set — the provisioner cannot run without it") } else if issuer, err := Issuer(os.Getenv); err != nil { say("%v — the provisioner cannot run without it", err) } else if realm, err := RealmOf(issuer); err != nil { say("%v — the provisioner cannot run without it", err) } else { h = &Harness{ Resource: "oidc-client", Receives: receives, Adapter: provisioner{clients: OidcClients{KC: kc, Realm: realm}, guard: guard, announce: announce, log: logStderr}, Log: logStderr, // A consumer failed for minutes is said on the bus, where the controller hears it and // `status` names it (novox/hq ADR 0224). Announce: announce, Node: os.Getenv("MESH_NODE"), } go h.Run(context.Background()) } // The retirement tools beside keycloak's own (novox/hq ADR 0230). if err := stdio.Serve("", append(Tools(kc, guard), RetirementTools(h)...)); err != nil { say("%v", err) os.Exit(1) } }