[v2] Add backend, cli and ui - #604
Conversation
27b1922 to
23e792a
Compare
Signed-off-by: Mangirdas Judeikis <mangirdas@judeikis.lt>
kbind naming and root layout, stateless cookie sessions, one-time pickup via Grant annotations, per-grant Lease link, TokenReview authenticator, krew plugin name kept as 'bind'. Signed-off-by: Mangirdas Judeikis <mangirdas@judeikis.lt>
The catalog is presentation + defaults on top of the core's discovery; the Grant is the issuance record (identity x export, APIs resolved at bind time) and the anchor for revocation, audit and the reaper. Signed-off-by: Mangirdas Judeikis <mangirdas@judeikis.lt>
The Lease lands in the kubeconfig context's namespace when set (the issuer pins it to the per-consumer boundary), named per (connection, consumer cluster) and annotated with the Connection name — so a service-layer reaper gets per-grant staleness, and tenant RBAC for Leases stays namespace-scoped. Signed-off-by: Mangirdas Judeikis <mangirdas@judeikis.lt>
kubeapply applies YAML multi-docs with CRD-establishment retries; konnectorinstall embeds the konnector install (CRDs, RBAC, Deployment); servicecrds embeds the catalog/iam CRDs for the backend's self-install. Signed-off-by: Mangirdas Judeikis <mangirdas@judeikis.lt>
OIDC (code + PKCE) configured kube-apiserver-style, stateless encrypted cookie/bearer sessions (no session store; HA needs only shared keys), a TokenReview authenticator for in-platform callers, and an embedded mock issuer behind a dev flag. Signed-off-by: Mangirdas Judeikis <mangirdas@judeikis.lt>
Per-identity boundary namespace, ServiceAccount with RBAC enumerating exactly the granted APIs (Cluster or Namespace scope), long-lived SA token; Export validation against the exported-CRD labels; the bundle builder emits the core's one-apply file with the context namespace pinned to the boundary. Signed-off-by: Mangirdas Judeikis <mangirdas@judeikis.lt>
Catalog browsing, bind with a single-use short-TTL pickup URL (enforced via Grant annotations with optimistic concurrency — no gateway state), consumer-cluster inventory from heartbeat Leases, per-export synced instances, konnector install manifest, and flag-gated browser-apply. Signed-off-by: Mangirdas Judeikis <mangirdas@judeikis.lt>
Marks grants stale per their own connection's heartbeat (conservative fallback for renamed connections); revocation and boundary deletion are explicit opt-ins. Signed-off-by: Mangirdas Judeikis <mangirdas@judeikis.lt>
Dependency-free SPA: standalone login page, sidebar app with catalog (related-resource chips, synced instances), clusters view, one-time bundle ticket, connect-a-cluster flow. Signed-off-by: Mangirdas Judeikis <mangirdas@judeikis.lt>
--enable-gateway/issuer/reaper/apply, kube-style OIDC flags, cookie keys, CRD self-install, leader-elected controllers. Signed-off-by: Mangirdas Judeikis <mangirdas@judeikis.lt>
login (browser dance), connect (konnector install), catalog, clusters, instances, and binding an export via 'kubectl bind export <name>'. Shipped to krew as the 'bind' plugin (binary kubectl-bind). Signed-off-by: Mangirdas Judeikis <mangirdas@judeikis.lt>
Chart with module values and secret-backed OIDC/cookie config; a two-kind-cluster Tilt setup (provider backend, consumer konnector, seeded catalog with related resources); samples aligned with the seed. Signed-off-by: Mangirdas Judeikis <mangirdas@judeikis.lt>
The Dockerfile gains a backend target (konnector stays the default); image.yaml pushes both images on tags; the CLI releases via goreleaser on final tags only (RCs skip) and krew-release-bot updates the 'bind' plugin; make targets for backend, bind, tilt and cli-snapshot. Signed-off-by: Mangirdas Judeikis <mangirdas@judeikis.lt>
The full-loop test drives catalog -> bind -> pickup -> one apply -> sync through the issued RBAC-fenced credentials -> clusters/instances views -> reaper -> revocation. The Dex test boots the real backend binary against Dex in docker and logs in through its password form. Signed-off-by: Mangirdas Judeikis <mangirdas@judeikis.lt>
There was a problem hiding this comment.
🟡 Not ready to approve
There are concrete correctness/security issues (brittle UID slicing in e2e + Lease name length risk + cookies not reliably marked Secure behind TLS-terminating proxies) that should be addressed before approval.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.
Pull request overview
This PR introduces the v2 “extended” implementation by adding a provider-side backend (gateway + issuer/reaper modules), a new kubectl bind CLI client, and a lightweight embedded static UI for browsing/binding services, along with the supporting CRDs, packaging, and dev/release tooling.
Changes:
- Add provider backend gateway API (catalog/bind/pickup/clusters/apply) plus OIDC + Kubernetes TokenReview authentication and stateless session handling.
- Add new
kubectl bindCLI (login/connect/catalog/export/clusters/instances) and supporting kube-apply/install helpers. - Add embedded static UI, Helm chart for backend, Tilt-based local dev loop, and generated service-layer CRDs (catalog/iam).
File summaries
| File | Description |
|---|---|
| web/static/login.html | New login landing page |
| web/static/index.html | New UI shell + dialogs |
| web/embed.go | Embed static UI FS |
| test/e2e/sync_test.go | Update lease naming/assertions |
| test/e2e/schema_source_test.go | Boilerplate author rename |
| test/e2e/related_resources_test.go | Boilerplate author rename |
| test/e2e/related_resources_more_test.go | Boilerplate author rename |
| test/e2e/policies_test.go | Boilerplate author rename |
| test/e2e/namespaced_binding_test.go | Boilerplate author rename |
| test/e2e/framework/framework.go | Boilerplate author rename |
| test/e2e/disengage_test.go | Boilerplate author rename |
| sdk/config/crd/catalog.kbind.io_collections.yaml | New Collection CRD manifest |
| sdk/apis/iam/v1alpha1/zz_generated.deepcopy.go | Generated deepcopy for IAM |
| sdk/apis/iam/v1alpha1/labels.go | IAM labels/annotations/constants |
| sdk/apis/iam/v1alpha1/groupversion_info.go | IAM scheme registration |
| sdk/apis/iam/v1alpha1/grant_types.go | New Grant API types |
| sdk/apis/iam/v1alpha1/doc.go | IAM package docs |
| sdk/apis/core/v1alpha1/shared_types.go | Boilerplate author rename |
| sdk/apis/core/v1alpha1/labels.go | Boilerplate author rename |
| sdk/apis/core/v1alpha1/helpers.go | Boilerplate author rename |
| sdk/apis/core/v1alpha1/groupversion_info.go | Boilerplate author rename |
| sdk/apis/core/v1alpha1/doc.go | Boilerplate author rename |
| sdk/apis/core/v1alpha1/connection_types.go | Boilerplate author rename |
| sdk/apis/core/v1alpha1/conditions.go | Boilerplate author rename |
| sdk/apis/core/v1alpha1/clusterbinding_types.go | Boilerplate author rename |
| sdk/apis/core/v1alpha1/binding_types.go | Boilerplate author rename |
| sdk/apis/catalog/v1alpha1/zz_generated.deepcopy.go | Generated deepcopy for catalog |
| sdk/apis/catalog/v1alpha1/groupversion_info.go | Catalog scheme registration |
| sdk/apis/catalog/v1alpha1/export_types.go | New Export API types |
| sdk/apis/catalog/v1alpha1/doc.go | Catalog package docs |
| sdk/apis/catalog/v1alpha1/conditions.go | Catalog Ready condition constants |
| sdk/apis/catalog/v1alpha1/collection_types.go | New Collection API types |
| pkg/servicecrds/install.go | Server-side apply service CRDs |
| pkg/servicecrds/crds/catalog.kbind.io_collections.yaml | Embedded CRD copy |
| pkg/kubeapply/kubeapply.go | SSA YAML multi-doc applier |
| pkg/konnectorinstall/manifests/konnector.yaml | Static konnector install YAML |
| pkg/konnectorinstall/install.go | Build/apply konnector install |
| Makefile | Add backend/cli/release/tilt targets |
| hack/tilt/Tiltfile | Two-kind-cluster dev loop |
| hack/tilt/seed/widgets.yaml | Seed demo catalog/widgets |
| hack/tilt/kind.sh | Create dev kind clusters |
| hack/e2e.sh | Boilerplate author rename |
| hack/demo.sh | Boilerplate author rename |
| hack/boilerplate/boilerplate.sh.txt | Boilerplate author rename |
| hack/boilerplate/boilerplate.py.txt | Boilerplate author rename |
| hack/boilerplate/boilerplate.Makefile.txt | Boilerplate author rename |
| hack/boilerplate/boilerplate.go.txt | Boilerplate author rename |
| hack/boilerplate/boilerplate.generatego.txt | Boilerplate author rename |
| hack/boilerplate/boilerplate.Dockerfile.txt | Boilerplate author rename |
| go.mod | Add OIDC/Cobra/YAML deps |
| engine/sync/syncer.go | Boilerplate author rename |
| engine/sync/resolve.go | Boilerplate author rename |
| engine/sync/crd_controller.go | Boilerplate author rename |
| engine/remote/remote.go | Add kubeconfig namespace helper |
| engine/remote/remote_test.go | Boilerplate author rename |
| engine/provider/connection_provider.go | Boilerplate author rename |
| engine/openapi/openapi.go | Boilerplate author rename |
| engine/mapper/mapper.go | Boilerplate author rename |
| engine/mapper/mapper_test.go | Boilerplate author rename |
| engine/crdpull/crdpull.go | Boilerplate author rename |
| engine/crdpull/crdpull_test.go | Boilerplate author rename |
| engine/connection/reconciler.go | Lease naming/namespace improvements |
| engine/binding/related.go | Boilerplate author rename |
| engine/binding/reconciler.go | Boilerplate author rename |
| engine/binding/cleanup.go | Boilerplate author rename |
| Dockerfile | Build backend + konnector targets |
| deploy/charts/backend/values.yaml | Backend chart values |
| deploy/charts/backend/templates/serviceaccount.yaml | Backend ServiceAccount template |
| deploy/charts/backend/templates/service.yaml | Backend Service template |
| deploy/charts/backend/templates/rolebinding.yaml | Leader-election RoleBinding |
| deploy/charts/backend/templates/role.yaml | Leader-election Role |
| deploy/charts/backend/templates/NOTES.txt | Chart install notes |
| deploy/charts/backend/templates/deployment.yaml | Backend Deployment template |
| deploy/charts/backend/templates/crds.yaml | Install CRDs from files |
| deploy/charts/backend/templates/clusterrolebinding.yaml | Backend ClusterRoleBinding |
| deploy/charts/backend/templates/clusterrole.yaml | Backend RBAC rules |
| deploy/charts/backend/templates/_helpers.tpl | Chart helper templates |
| deploy/charts/backend/files/crds/catalog.kbind.io_collections.yaml | Bundled CRD file |
| deploy/charts/backend/Chart.yaml | New backend chart metadata |
| deploy/charts/backend/.helmignore | Helm ignore rules |
| config/samples/widget.yaml | Expand sample w/ related resources |
| config/samples/provider-widget-crd.yaml | Improve provider demo comments |
| config/samples/binding.yaml | Add relatedResources sample |
| cmd/release/main.go | Boilerplate author rename |
| cmd/konnector/main.go | Boilerplate author rename |
| cmd/bind/main.go | New CLI entrypoint |
| cli/login.go | Browser-based login helper |
| cli/config.go | CLI config/token storage |
| cli/cmd/root.go | Cobra root + client resolve |
| cli/cmd/login.go | bind login command |
| cli/cmd/instances.go | bind instances command |
| cli/cmd/connect.go | bind connect command |
| cli/cmd/clusters.go | bind clusters command |
| cli/cmd/catalog.go | bind catalog command |
| cli/cmd/bind.go | bind export bind/apply flow |
| cli/client.go | Gateway API client |
| backend/reaper/reaper_test.go | Reaper staleness unit tests |
| backend/issuer/issuer.go | Issuer interface + naming helpers |
| backend/issuer/issuer_test.go | Issuer helper unit tests |
| backend/issuer/controller.go | Grant reconciler controller |
| backend/issuer/catalog_controller.go | Export readiness validation |
| backend/issuer/bundle.go | Bundle assembly (Secret/Conn/Binding) |
| backend/gateway/server.go | Gateway mux + handlers wiring |
| backend/gateway/clusters.go | Clusters aggregation endpoint |
| backend/gateway/catalog.go | Catalog endpoint + selector summary |
| backend/gateway/apply.go | Browser-apply endpoint |
| backend/gateway/api/types.go | Shared gateway wire types |
| backend/auth/sessions.go | Stateless session tokens/cookies |
| backend/auth/sessions_test.go | Session unit tests |
| backend/auth/oidc_test.go | OIDC flow + redirect tests |
| backend/auth/mock.go | Embedded mock OIDC issuer |
| backend/auth/kubernetes.go | TokenReview authenticator |
| backend/auth/kubernetes_test.go | TokenReview unit tests |
| backend/auth/authenticator.go | Authenticator interface + Identity |
| .krew.yaml | krew-release-bot plugin template |
| .goreleaser.yaml | CLI release config |
| .github/workflows/image.yaml | Build/push backend + konnector |
| .github/workflows/cli.yaml | goreleaser + krew automation |
Review details
- Files reviewed: 139/140 changed files
- Comments generated: 5
- Review effort level: Lite
We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.
| } | ||
| l := &coordinationv1.Lease{} | ||
| key := client.ObjectKey{Namespace: framework.KbindNamespace, Name: "consumer-" + conn.Status.LocalClusterUID} | ||
| key := client.ObjectKey{Namespace: framework.KbindNamespace, Name: "demo-provider-" + conn.Status.LocalClusterUID[:10]} |
| func leaseName(conn *corev1alpha1.Connection) string { | ||
| return "consumer-" + conn.Status.LocalClusterUID | ||
| uid := conn.Status.LocalClusterUID | ||
| if len(uid) > 10 { | ||
| uid = uid[:10] | ||
| } |
| http.SetCookie(w, &http.Cookie{ | ||
| Name: SessionCookie, | ||
| Value: token, | ||
| Path: "/", | ||
| MaxAge: int(s.ttl.Seconds()), | ||
| HttpOnly: true, | ||
| Secure: r.TLS != nil, | ||
| SameSite: http.SameSiteLaxMode, | ||
| }) |
| http.SetCookie(w, &http.Cookie{ | ||
| Name: stateCookie, | ||
| Value: encoded, | ||
| Path: "/api/auth/oidc/", | ||
| MaxAge: int((10 * time.Minute).Seconds()), | ||
| HttpOnly: true, | ||
| Secure: r.TLS != nil, | ||
| SameSite: http.SameSiteLaxMode, | ||
| }) |
| http.SetCookie(w, &http.Cookie{ | ||
| Name: auth.SessionCookie, | ||
| Value: "", | ||
| Path: "/", | ||
| MaxAge: -1, | ||
| HttpOnly: true, | ||
| Secure: r.TLS != nil, | ||
| SameSite: http.SameSiteLaxMode, | ||
| }) |
Summary
Add v2 extended implementation:
What Type of PR Is This?
/kind feature
Related Issue(s)
Fixes #
Release Notes