# Zitadel Resources Operator A Kubernetes operator for managing Zitadel resources across single and multi-cluster environments. ## Description The Zitadel Resources Operator enables declarative management of Zitadel resources through Kubernetes custom resources. It supports both traditional same-cluster deployments and cross-cluster scenarios where resources can reference Zitadel entities across different Kubernetes clusters. ### Key Features - **Cross-Cluster Support**: Reference Zitadel resources across different Kubernetes clusters using direct Zitadel IDs - **Declarative Management**: Define Zitadel resources as Kubernetes custom resources - **Automatic Reconciliation**: Ensures desired state is maintained in Zitadel - **Flexible Reference Types**: Support for both Kubernetes object references and direct Zitadel ID references - **Resource Hierarchy**: Connection → Organization → Project → Applications - **Validation**: Built-in validation rules to ensure correct resource configuration ## Architecture ### Resource Hierarchy The operator follows this resource hierarchy: ``` Connection (Zitadel instance connection) ↓ Organization (Zitadel organization) ↓ Project (Zitadel project) ↓ Applications (OIDCApp, APIApp, MachineUser, etc.) ``` ### Supported Resources - **Connection**: Zitadel instance connection configuration - **Organization**: Zitadel organization management - **Project**: Zitadel project with roles and grants - **OIDCApp**: OIDC application configuration - **APIApp**: API application configuration - **MachineUser**: Machine user management - **Action**: Custom actions - **Flow**: Flow configurations ## Cross-Cluster Support The operator supports two reference modes for flexible deployment scenarios: ### Same-Cluster References (Traditional) Use Kubernetes object references when resources exist in the same cluster: ```yaml apiVersion: zitadel.github.com/v1alpha1 kind: Project metadata: name: my-project namespace: default spec: organizationRef: name: my-organization namespace: default projectName: my-project ``` ### Cross-Cluster References (New) Use direct Zitadel ID references when resources span multiple clusters: ```yaml apiVersion: zitadel.github.com/v1alpha1 kind: Project metadata: name: my-project namespace: workload-dev spec: organizationRef: id: "367990024731427343" connectionRef: name: mgmt-prod-connection namespace: zitadel-system projectName: my-project ``` ### Reference Validation The operator enforces these validation rules: - **Mutual Exclusivity**: Must provide either `name` (K8s reference) or `id` (Zitadel ID), but not both - **Required Field**: At least one reference method must be provided - **Connection Requirement**: When using `id`, `connectionRef.name` is required ## Usage Examples ### Complete Cross-Cluster Setup #### 1. Create Connection in Management Cluster ```yaml apiVersion: zitadel.github.com/v1alpha1 kind: Connection metadata: name: mgmt-prod-connection namespace: zitadel-system spec: host: id.corredorconect.com secure: true authentication: pat: tokenSecretKey: name: mgmt-prod-secret key: pat ``` #### 2. Create Organization in Management Cluster ```yaml apiVersion: zitadel.github.com/v1alpha1 kind: Organization metadata: name: corredorconect namespace: zitadel-system spec: connectionRef: name: mgmt-prod-connection namespace: zitadel-system organizationName: corredorconect ``` #### 3. Create Project in Workload Cluster (Cross-Cluster) ```yaml apiVersion: zitadel.github.com/v1alpha1 kind: Project metadata: name: seguros-dev namespace: zitadel-resources-operator spec: organizationRef: id: "367990024731427343" connectionRef: name: zitadel-connection namespace: zitadel-resources-operator projectName: segurOS-dev projectRoleAssertion: true projectRoleCheck: true hasProjectCheck: true roles: - key: admin displayName: Admin group: system ``` #### 4. Create OIDC App in Workload Cluster (Cross-Cluster) ```yaml apiVersion: zitadel.github.com/v1alpha1 kind: OIDCApp metadata: name: my-oidc-app namespace: workload-dev spec: projectRef: id: "987654321098765432" connectionRef: name: zitadel-connection namespace: zitadel-resources-operator oidcAppName: my-app redirectUris: - https://example.com/callback responseTypes: - OIDC_RESPONSE_TYPE_CODE grantTypes: - OIDC_GRANT_TYPE_AUTHORIZATION_CODE appType: OIDC_APP_TYPE_WEB authMethodType: OIDC_AUTH_METHOD_TYPE_BASIC ``` ## Reference Types ### OrganizationRef References an organization either by Kubernetes object name or direct Zitadel ID. **Fields:** - `name` (string): Kubernetes object name (same-cluster) - `id` (string): Direct Zitadel organization ID (cross-cluster) - `connectionRef` (ConnectionRef): Connection for cross-cluster references - Standard `ObjectReference` fields: `namespace`, `kind`, `apiVersion`, etc. **Validation:** - Must provide either `name` or `id`, but not both - When using `id`, `connectionRef.name` is required ### ProjectRef References a project either by Kubernetes object name or direct Zitadel ID. **Fields:** - `name` (string): Kubernetes object name (same-cluster) - `id` (string): Direct Zitadel project ID (cross-cluster) - `connectionRef` (ConnectionRef): Connection for cross-cluster references - Standard `ObjectReference` fields: `namespace`, `kind`, `apiVersion`, etc. **Validation:** - Must provide either `name` or `id`, but not both - When using `id`, `connectionRef.name` is required ## Getting Started ### Prerequisites - Kubernetes cluster (v1.25+) - kubectl configured to communicate with your cluster - Zitadel instance with appropriate credentials ### Installation 1. **Clone the repository:** ```bash git clone cd zitadel-resources-operator ``` 2. **Install CRDs:** ```bash make install ``` 3. **Deploy the operator:** ```bash make deploy IMG=/zitadel-resources-operator:tag ``` 4. **Verify installation:** ```bash kubectl get pods -n zitadel-resources-operator-system ``` ### Configuration Create a Connection resource to authenticate with your Zitadel instance: ```yaml apiVersion: zitadel.github.com/v1alpha1 kind: Connection metadata: name: zitadel-connection namespace: zitadel-resources-operator spec: host: your-zitadel-instance.com secure: true authentication: pat: tokenSecretKey: name: zitadel-credentials key: pat ``` Create the secret with your credentials: ```bash kubectl create secret generic zitadel-credentials \ --from-literal=pat=your-zitadel-pat-token \ -n zitadel-resources-operator ``` ### Development #### Running Locally 1. **Install CRDs:** ```bash make install ``` 2. **Run the operator locally:** ```bash make run ``` #### Building and Testing 1. **Build the operator:** ```bash make build ``` 2. **Run tests:** ```bash make test ``` 3. **Generate manifests:** ```bash make manifests ``` #### Modifying API Definitions When modifying API types, regenerate the CRDs: ```bash make manifests make install ``` ## Troubleshooting ### Common Issues **Issue:** `Organization.zitadel.github.com "" not found` - **Solution:** Ensure you're using either `name` or `id` in references, not both. Check validation rules. **Issue:** Cross-cluster references not working - **Solution:** Verify that `connectionRef` is properly specified when using `id` references. **Issue:** Resources not reconciling - **Solution:** Check operator logs: `kubectl logs -n zitadel-resources-operator-system deployment/zitadel-resources-operator-controller-manager` ### Debug Mode Enable debug logging by setting the log level: ```bash kubectl set env deployment/zitadel-resources-operator-controller-manager \ -n zitadel-resources-operator-system \ --containers=manager \ LOG_LEVEL=debug ``` ## Contributing Contributions are welcome! Please follow these guidelines: 1. Fork the repository 2. Create a feature branch 3. Make your changes 4. Add tests for new functionality 5. Submit a pull request ### Development Workflow 1. **Make changes to the code** 2. **Run tests:** `make test` 3. **Generate manifests:** `make manifests` 4. **Build locally:** `make build` 5. **Test in cluster:** `make install && make run` ## License Copyright 2024. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.