Repository navigation
feat: add authorization and administrator relationship XRs - #34
patrickleet wants to merge 3 commits into
Conversation
Implements [[tasks/harmony-2506]]. Preserve existing APIs and remote identities while native provider support is reviewed.
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Signed-off-by: Patrick Lee Scott <pat@patscott.io>
|
Added and ran a real relationship e2e suite: test source, fixture/cleanup helpers, run instructions. The run exercised XR -> composition functions -> source-built native provider -> Zitadel v4.13.1. It covers:
All remote assertions call the real Authorization/InternalPermission v2 APIs independently of Ready status. The suite creates disposable organizations, users, project, roles and one shared delegation. Cleanup waits for composed native bindings and Usages to disappear before deleting protected parents; all fixture namespaces were removed. The initial attempts are not counted as passing: one stopped during fixture creation (fixtures now use unique usernames/emails across runs); another passed binding assertions but failed teardown when an XR disappeared before its Usage garbage collection completed. The final run above passes both lifecycle assertions and complete cleanup. No deletion protection was bypassed. Separately, direct HTTPS API reads with CA verification matched nine existing authorization ID/user/project/organization/role tuples and an organization-scoped Administrator with ORG_USER_MANAGER. The adopted assignments and requested running example remain installed; test fixtures were removed. CI distinction: the existing reusable Upbound e2e job had no KCL E2ETest definitions for these bindings. Its prior green result was not evidence of live coverage. This new standard-library Python suite runs against an explicitly prepared source/containing-release test cluster and is not automatically run by that reusable job. The Make target fails without explicit context/endpoint/credential-Secret opt-in; direct unittest discovery reports a skip. Existing render/security/KCL tests remain separate. This suite does not provision or validate every AuthStack Helm/database/routing variation, and containing released provider/configuration dependencies remain required before release. |
Problem
Zitadel role assignments and administrator memberships accept either a human user ID or a machine user ID. A native Crossplane reference targets one resource type, so it cannot express that choice. Consumers otherwise need to resolve remote user IDs themselves or repeat composition logic for each subject and target type.
The existing generic identity/client XRs do not provide this focused relationship API. The desired boundary is an assignment that references independently managed users, organizations, projects, and shared delegation.
Solution
Add two namespaced relationship XRs backed by native stable v2 assignments:
Authorizationresolves a typedHumanUserorMachineUser, project, and explicit granting organization into one native authorization. It can reference an existing project grant and checks that its project and grantee match. It never creates shared delegation per user.Administratorresolves the same subject choice into one native administrator assignment. Exactly one target is required: organization, project, project grant, or explicit instance scope.Both share reference-resolution and rendering logic. Users, organizations, projects, clients, delegation, and credential exports retain their own owners.
Here “v2” identifies the underlying Zitadel Authorization and InternalPermission services; the XR Kubernetes API remains
v1alpha1. The relationship-XR design addresses polymorphic references independently of the backend API migration. Existing AuthStack XRs are retained abstractions; their backend API versions depend on the managed resources they compose. Zitadel still supports its v1 API family while directing new development to resource-based v2 services; retaining an existing XR or using a v1-backed resource does not itself establish deprecation. See the Zitadel API overview.Before / after
With the native provider alone, a consumer must resolve the human or machine resource into
userIdbefore declaring an assignment:With the new XR, the manifest names the subject and the composition resolves its observed ID:
For a service account, change the subject to
kind: MachineUserand its resource name. For administration, usekind: Administratorand replace the project/organization fields with an explicit target, for example:The native example requires the provider changes linked below; these native types are not available in published provider v0.3.0. In both forms, the assignment owns the complete role set, so omitted roles are revoked.
Backward compatibility and adoption
HumanUser,MachineUser,Grant, andOIDCClientXRDs remain packaged. This is additive and does not automatically migrate existing consumers or remove their resources.of.resourceRef.namespaceidentifies the protected source;byis local to the Usage namespace and omits the unsupported namespace field.Validation
Passed locally:
up composition render, withReady=False.Live tests installed both provider and configuration from source on a local Kubernetes cluster running Zitadel v4.13.1. Both subject kinds and all four administrator scopes reached Ready. Checks passed for full role replacement, server-side drift correction, cross-org assignment through an existing shared delegation, cross-namespace Observe imports with working Usage locks, and mismatched imports retaining Observe-only policies without Delete. API reads confirmed removal of the test authorizations and administrator assignments during teardown.
Nine existing grants were first observed through the new XR with exact original IDs and verified user/target identities. A subsequent live cutover transferred all nine assignments to Authorization XRs: old controllers processed Observe-only policies, their Kubernetes handles were removed without Delete, and only then were writes enabled on the new owners. All nine retained remote IDs and full role sets, with 27 dependency Usages and no remaining old Grant handles. Existing users, project settings, OIDC registrations and credential-secret fingerprints were preserved. Headless sign-in, callback and authenticated-dashboard checks passed in three active local environments. The original auth installation remained Ready and the local GitOps watcher was restored. Temporary test namespaces and credentials from the earlier isolated tests were removed; the nine adopted application bindings remain running.
CI run 39474264661 passes 35/35 KCL cases, including both new relationship cases, plus instance-observation and the existing e2e job. The two retained-native example validations still fail against published provider v0.3.0, which lacks these resource schemas. The local Dory-based KCL Docker harness timed out; the direct-render regression suite and installed-cluster checks passed. Live write-ownership transfer is verified for the nine existing role assignments. OIDC registration adoption and upgrades using published containing provider/configuration releases remain separate.
Dependencies and release status
Depends on Terraform provider PR474 and Crossplane provider PR70. This remains a draft: the package dependency must identify a provider build that actually contains these native types before release. An interim downstream build can use an explicitly pinned fork package; an upstream release can replace that dependency when available. Neither provider v0.3.0 nor passing tests for the existing XRs satisfies that requirement.
Reproducible live relationship tests
Added and ran a real relationship e2e suite: test source, fixture/cleanup helpers, run instructions.
make e2enow includese2e-relationshipsrather than succeeding locally without a real relationship suite.The run exercised XR -> composition functions -> source-built native provider -> Zitadel v4.13.1. It covers:
All remote assertions call the real Authorization/InternalPermission v2 APIs independently of Ready status. The suite creates disposable organizations, users, project, roles and one shared delegation. Cleanup waits for composed native bindings and Usages to disappear before deleting protected parents; all fixture namespaces were removed.
The initial attempts are not counted as passing: one stopped during fixture creation (fixtures now use unique usernames/emails across runs); another passed binding assertions but failed teardown when an XR disappeared before its Usage garbage collection completed. The final run above passes both lifecycle assertions and complete cleanup. No deletion protection was bypassed.
Separately, direct HTTPS API reads with CA verification matched nine existing authorization ID/user/project/organization/role tuples and an organization-scoped Administrator with ORG_USER_MANAGER. The adopted assignments and requested running example remain installed; test fixtures were removed.
CI distinction: the existing reusable Upbound e2e job had no KCL E2ETest definitions for these bindings. Its prior green result was not evidence of live coverage. This new standard-library Python suite runs against an explicitly prepared source/containing-release test cluster and is not automatically run by that reusable job. The Make target fails without explicit context/endpoint/credential-Secret opt-in; direct unittest discovery reports a skip. Existing render/security/KCL tests remain separate. This suite does not provision or validate every AuthStack Helm/database/routing variation, and containing released provider/configuration dependencies remain required before release.