KafkaUser

API group/version: crabka.io/v1alpha1

Spec

FieldTypeRequiredDefaultDescription
authenticationobjectyesTagged enum on type, mirroring Strimzi. The wire shape is flat (Strimzi-compatible): type is the discriminator and per-variant config fields are siblings of type. The custom schema_with hand-rolls a structural schema because kube-rs 3.x's StructuralSchemaRewriter panics when oneOf branches share a type property with differing enum values (the default schemars output for tagged-union enums). Same workaround as Storage in kafka_node_pool.rs. Cross-variant constraints (e.g. "iterations only valid when type=scram-sha-512") are enforced by the operator at reconcile time, not by the apiserver.
authentication.iterationsintegerno
authentication.maxLifetimeMsintegerno
authentication.passwordLengthintegerno
authentication.renewBeforeExpiryMsintegerno
authentication.renewalDaysintegerno
authentication.renewersarrayno
authentication.typestringyes
authentication.validityDaysintegerno
authorizationobjectnoAuthorization is optional — a user with no ACLs can still authenticate. When absent, ACL reconciliation is skipped.
quotasobjectnoOptional per-user client quotas (KIP-13/124/257). Maps onto Kafka's (user) quota entity via AlterClientQuotas (api_key 49). Absent → operator does not touch the broker's quota state; present → the operator drives the broker's quota keys for User:<name> toward the spec (sets configured fields, tombstones omitted ones).
quotas.consumerByteRateintegernoMaximum consume-side bytes/sec. Backed by consumer_byte_rate.
quotas.controllerMutationRatenumbernoKIP-599 controller-mutation rate (creates/deletes/sec). Backed by controller_mutation_rate.
quotas.producerByteRateintegernoMaximum produce-side bytes/sec. Backed by producer_byte_rate.
quotas.requestPercentageintegernoMaximum percentage of a request-handler thread's time the user may consume (0..=100). Backed by request_percentage.

Status

FieldTypeRequiredDefaultDescription
conditionsarrayno[]Standard Kubernetes-style condition list. Surfaces Ready.
delegationTokenExpiryTimestampMsintegernoCurrent expiry_timestamp_ms of the operator-managed delegation token (extended on each successful renew). Compared against now to decide when to renew per spec.authentication.renewBeforeExpiryMs.
delegationTokenIdstringnoPersisted token_id (UUID) of the operator-managed delegation token for this user. Used across reconciles to find the same token via DescribeDelegationToken. Present once the operator has successfully issued a token via CreateDelegationToken.
delegationTokenMaxTimestampMsintegernoToken's absolute upper bound (max_timestamp_ms). Renew can never push expiry_timestamp_ms past this — the operator stops renewing and surfaces TokenExpiring once further extension is impossible.
externalbooleannofalsetrue once a credential-less user (type: tls-external) has been reconciled. Surfaces in kubectl describe ku so operators can tell at a glance that the operator does not own this user's credentials.
observedGenerationintegernometadata.generation of the last successfully-reconciled spec.
quotasInSyncbooleannofalseTrue once the spec's quotas (if any) have been reflected in the broker's (user) client-quota state. False when spec.quotas is None (the operator does not touch broker quotas).
scramSha256booleannofalseTrue once SCRAM-SHA-256 credentials are provisioned.
scramSha512booleannofalseTrue once SCRAM-SHA-512 credentials are provisioned.
secretstringnoName of the Kubernetes Secret holding the user's password.
tlsbooleannofalsetrue once a TLS user has a current cert Secret. Mirrors scram_sha512.
tlsCertNotAfterstringnoRFC3339 timestamp of the user cert's notAfter. Present when tls == true.
tlsPrincipalstringnoThe principal string the operator pinned in ACLs (e.g. User:CN=alice for TLS users, User:alice for SCRAM and tls-external users). Always populated when the user is provisioned. Load-bearing for debugging "why isn't my ACL matching" issues.
usernamestringnoEffective Kafka principal name (matches metadata.name).