diff --git a/control-plane/roles/zitadel/README.md b/control-plane/roles/zitadel/README.md index 09eccecce..8c0335cb7 100644 --- a/control-plane/roles/zitadel/README.md +++ b/control-plane/roles/zitadel/README.md @@ -2,9 +2,6 @@ Role that deploys and manages and configures [Zitadel](https://zitadel.com/), an open-source identity and access management system. -> [!IMPORTANT] -> This role was introduced as part of the implementation of [MEP-4](https://metal-stack.io/docs/MEP-4-multi-tenancy-for-the-metal-api) and is currently considered as alpha stage. Please do not use this role for production use-cases at the time being. - ## UI Because `ExternalSecure: true` is set by default, Zitadel is only available over HTTPS. Using Zitadel with HTTP does currently not work due to . @@ -18,28 +15,32 @@ Because `ExternalSecure: true` is set by default, Zitadel is only available over You can look up all the default values of this role [here](defaults/main.yaml). -| Name | Mandatory | Description | -| ----------------------------- | --------- | -------------------------------------------------------------------------------------- | -| zitadel_chart_version | | The chart version for deploying zitadel | -| zitadel_namespace | | The namespace into which zitadel is deployed | -| zitadel_init_image_name | yes | The zitadel-init image tag | -| zitadel_init_image_tag | yes | The zitadel-init image name | -| zitadel_image_tag | | An optional image overwrite for zitadel when not using the default from the helm chart | -| zitadel_tools_kubectl_tag | | The zitadel tools kubectl image tag (of alpine/k8s) | -| zitadel_external_domain | yes | The external domain used by zitadel | -| zitadel_image_pull_policy | | The image pull policy to use for zitadel-init | -| zitadel_ingress_dns | | The DNS ingress domain used for the ingress-controller | -| zitadel_ingress_annotations | | Annotations for the zitadel ingress resource(s) | -| zitadel_initial_instance | | The name of the initial instance | -| zitadel_initial_org | | The name of the initial organization | -| zitadel_admin_password | | The admin password for the login of the administrator in the UI | -| zitadel_master_key | | The master key (must be 32 bytes!) | -| zitadel_db_address | | The address for the zitadel-db | -| zitadel_db_password | | The password for accessing the zitadel-db | -| zitadel_enabled_ingress | | Whether to enable ingress exposal or not | -| zitadel_init_config | | Configuration for zitadel-init | -| zitadel_port | | The port used by zitadel | -| zitadel_skip_verify_tls | | Whether to skip TLS verification for zitadel | -| zitadel_insecure | | Whether to allow insecure connections to zitadel | -| zitadel_httproute_enabled | | Deploys a Gateway API HTTPRoute exposing zitadel via the configured Gateway | -| zitadel_httproute_parent_refs | | List of `parentRefs` (Gateways) the HTTPRoute attaches to | +| Name | Mandatory | Description | +| ----------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------- | +| zitadel_chart_version | | The chart version for deploying zitadel | +| zitadel_namespace | | The namespace into which zitadel is deployed | +| zitadel_init_image_name | yes | The zitadel-init image tag | +| zitadel_init_image_tag | yes | The zitadel-init image name | +| zitadel_actions_enabled | | Whether to deploy the zitadel actions V2 server as a dedicated deployment | +| zitadel_actions_allow_roles | | Roles that must be present in the idp role claims, otherwise login is prevented | +| zitadel_actions_client_ids | | Client ids for which the role policy is enforced; if empty, derived from the client_id in the zitadel-client-credentials secret | +| zitadel_actions_deny_list | | Fully operator-controlled HTTPClient.DenyList; by default only localhost is blocked, all IPs allowed | +| zitadel_image_tag | | An optional image overwrite for zitadel when not using the default from the helm chart | +| zitadel_tools_kubectl_tag | | The zitadel tools kubectl image tag (of alpine/k8s) | +| zitadel_external_domain | yes | The external domain used by zitadel | +| zitadel_image_pull_policy | | The image pull policy to use for zitadel-init | +| zitadel_ingress_dns | | The DNS ingress domain used for the ingress-controller | +| zitadel_ingress_annotations | | Annotations for the zitadel ingress resource(s) | +| zitadel_initial_instance | | The name of the initial instance | +| zitadel_initial_org | | The name of the initial organization | +| zitadel_admin_password | | The admin password for the login of the administrator in the UI | +| zitadel_master_key | | The master key (must be 32 bytes!) | +| zitadel_db_address | | The address for the zitadel-db | +| zitadel_db_password | | The password for accessing the zitadel-db | +| zitadel_enabled_ingress | | Whether to enable ingress exposal or not | +| zitadel_init_config | | Configuration for zitadel-init | +| zitadel_port | | The port used by zitadel | +| zitadel_skip_verify_tls | | Whether to skip TLS verification for zitadel | +| zitadel_insecure | | Whether to allow insecure connections to zitadel | +| zitadel_httproute_enabled | | Deploys a Gateway API HTTPRoute exposing zitadel via the configured Gateway | +| zitadel_httproute_parent_refs | | List of `parentRefs` (Gateways) the HTTPRoute attaches to | diff --git a/control-plane/roles/zitadel/defaults/main.yaml b/control-plane/roles/zitadel/defaults/main.yaml index 211574923..d1ae30c4b 100644 --- a/control-plane/roles/zitadel/defaults/main.yaml +++ b/control-plane/roles/zitadel/defaults/main.yaml @@ -1,6 +1,8 @@ --- zitadel_image_tag: zitadel_tools_kubectl_tag: "1.35.1" +zitadel_actions_image_tag: "{{ zitadel_init_image_tag }}" +zitadel_actions_image_name: "{{ zitadel_init_image_name }}" zitadel_endpoint: >- {% if zitadel_httproute_enabled -%}auth.{{ metal_control_plane_gateway_dns }}{%- else -%}auth.{{ metal_control_plane_ingress_dns }}{%- endif %} @@ -50,3 +52,10 @@ zitadel_init_config: {} # is_auto_update: true zitadel_image_pull_policy: "{{ metal_control_plane_image_pull_policy }}" + +zitadel_actions_enabled: false +zitadel_actions_allow_roles: [] +zitadel_actions_client_ids: [] +# by default zitadel blocks cluster ips, so we overwrite the default deny list +zitadel_actions_deny_list: + - localhost diff --git a/control-plane/roles/zitadel/tasks/main.yaml b/control-plane/roles/zitadel/tasks/main.yaml index 25063f6c9..22347dd9a 100644 --- a/control-plane/roles/zitadel/tasks/main.yaml +++ b/control-plane/roles/zitadel/tasks/main.yaml @@ -60,3 +60,10 @@ until: secret_info.resources | length > 0 retries: 10 delay: 5 + +- name: Create zitadel-actions + kubernetes.core.k8s: + state: present + definition: "{{ lookup('template', 'zitadel-actions.yaml') }}" + namespace: "{{ zitadel_namespace }}" + when: zitadel_actions_enabled diff --git a/control-plane/roles/zitadel/templates/values.yaml.j2 b/control-plane/roles/zitadel/templates/values.yaml.j2 index 881ba4ca2..86542a4a8 100644 --- a/control-plane/roles/zitadel/templates/values.yaml.j2 +++ b/control-plane/roles/zitadel/templates/values.yaml.j2 @@ -24,6 +24,8 @@ zitadel: ExternalDomain: {{ zitadel_external_domain }} TLS: Enabled: false + HTTPClient: + DenyList: {{ zitadel_actions_deny_list | to_json }} Database: Postgres: Host: {{ zitadel_db_address }} diff --git a/control-plane/roles/zitadel/templates/zitadel-actions.yaml b/control-plane/roles/zitadel/templates/zitadel-actions.yaml new file mode 100644 index 000000000..52234115c --- /dev/null +++ b/control-plane/roles/zitadel/templates/zitadel-actions.yaml @@ -0,0 +1,67 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: zitadel-actions + namespace: {{ zitadel_namespace }} +spec: + type: ClusterIP + selector: + app: zitadel-actions + ports: + - name: actions + port: 8443 + targetPort: 8443 + protocol: TCP +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: zitadel-actions + namespace: {{ zitadel_namespace }} + labels: + app: zitadel-actions +spec: + replicas: 1 + selector: + matchLabels: + app: zitadel-actions + template: + metadata: + labels: + app: zitadel-actions + spec: + containers: + - name: zitadel-actions + image: "{{ zitadel_actions_image_name }}:{{ zitadel_actions_image_tag }}" + imagePullPolicy: "{{ zitadel_image_pull_policy }}" + args: + - "--bind-addr=0.0.0.0:8443" + - "--signing-key=$(SIGNING_KEY)" +{% for role in zitadel_actions_allow_roles %} + - "--allow-roles={{ role }}" +{% endfor %} +{% if zitadel_actions_client_ids %} +{% for client_id in zitadel_actions_client_ids %} + - "--client-ids={{ client_id }}" +{% endfor %} +{% else %} + - "--client-ids=$(CLIENT_ID)" +{% endif %} + env: + - name: SIGNING_KEY + valueFrom: + secretKeyRef: + name: zitadel-actions-credentials + key: signing_key +{% if not zitadel_actions_client_ids %} + - name: CLIENT_ID + valueFrom: + secretKeyRef: + name: zitadel-client-credentials + key: client_id +{% endif %} + ports: + - name: actions + containerPort: 8443 + protocol: TCP diff --git a/control-plane/roles/zitadel/templates/zitadel-metal-init.yaml b/control-plane/roles/zitadel/templates/zitadel-metal-init.yaml index 087690056..ca9f98da7 100644 --- a/control-plane/roles/zitadel/templates/zitadel-metal-init.yaml +++ b/control-plane/roles/zitadel/templates/zitadel-metal-init.yaml @@ -48,6 +48,7 @@ spec: - "--zitadel-pat=$(ZITADEL_PAT)" - "--namespace={{ zitadel_namespace }}" - "--secret=zitadel-client-credentials" + - "--actions-secret=zitadel-actions-credentials" - "--zitadel-skip-verify-tls={{ zitadel_skip_verify_tls | lower }}" - "--zitadel-insecure={{ zitadel_insecure | lower }}" - "--config-path=/zitadel/config.yaml"