Authorization Concept
This document describes a planned authorization model for the KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows. message bus. It has not been started to be implemented and is subject to review by the Architecture Board.
Objective
The concept defines a KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows. authorization (AuthZ) model for the CIVITAS/CORE V2 data platform that enforces the least privilege principle: every component receives exactly the permissions required for its purpose on working with the central message bus.
Authorization decisions are delegated to Open Policy AgentOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. (OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization.) via a custom KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows. Authorizer plugin. OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. is already the platform's central Policy Decision PointPolicy Decision PointThe component that decides whether a request is authorized. CIVITAS/CORE uses Open Policy Agent (OPA) as its PDP. (PDPPolicy Decision PointThe component that decides whether a request is authorized. CIVITAS/CORE uses Open Policy Agent (OPA) as its PDP.) for API authorization (APISIXApache APISIXAn open-source API gateway for traffic management, security and observability. In CIVITAS/CORE it is used as the centralized entrypoint to route and protect externally exposed APIs. → OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. → AuthZ Repository) and is extended here to cover KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows. topic access. The existing PostgreSQL-based authorization database serves as the single source of truth for both API and KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows. permissions.
The concept covers both message categories handled by the bus:
- Configuration messages -- distributed and consumed via dedicated Configuration AdaptersConfiguration AdapterThe component that consumes data models on behalf of platform components that cannot consume them directly, and configures the component accordingly. In the secrets management flow, the Configuration Adapter is the sole component that resolves Vault references into concrete credentials.. The Outbox and Saga patternsSaga PatternA pattern for coordinating long-running, multi-step operations across several components without a distributed transaction. Each step has a compensating action; if a later step fails, the compensating actions of all previously completed steps are executed in reverse order. In CIVITAS/CORE it is used for provisioning workflows that require sequential, cross-adapter operations. are currently planned and partly implemented for this category.
- Payload data -- distributed via datasetDatasetA data-related element that contains processed data and makes it available for consumption. A Dataset is populated via Pipelines and carries Metadata and access permissions. pipelines with datasetDatasetA data-related element that contains processed data and makes it available for consumption. A Dataset is populated via Pipelines and carries Metadata and access permissions.-specific topic structures. No Outbox or Saga usage is planned for payload data at this time.
Scope and Boundaries
Authentication vs. Authorization
| Aspect | Scope |
|---|---|
| Authentication (AuthN) | Identity of a producer/consumer via SASLSASL (Simple Authentication and Security Layer)A framework defined in RFC 4422 that decouples authentication from application protocols./SCRAMSCRAM (Salted Challenge Response Authentication Mechanism)A challenge-response authentication protocol defined in RFC 5802.-SHA-512 -- out of scope for this document, see Authentication Concept |
| Authorization (AuthZ) | What an authenticated identity may do on which topic -- in scope |
Relation to Existing OPA Infrastructure
The platform already operates an OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization.-based authorization chain for API access:
APISIX → OPA (Rego policies) → AuthZ Repository → PostgreSQL
This concept extends OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. to cover KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows.:
Kafka Broker → Custom Authorizer → OPA (Rego policies, in-memory bundle)
Both paths share the same PostgreSQL database as the single source of truth. The key difference is how OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. accesses policy data at decision time — see OPA Decision-Time Data Flow below.
Both paths share the same PostgreSQL database for permission data, ensuring a single source of truth across API and message bus authorization.
Recommendation: deploy separate OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. instances for API authorization and KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows. authorization.
| Shared Instance | Separate Instances (recommended) | |
|---|---|---|
| Failure domain | OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. down → API + bus both unavailable | Independent — KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows.-OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. down affects bus only |
| Exposure profile | Mixed (external API + internal broker) | Isolated per concern |
| Operational effort | Lower | Higher (two deployments to operate) |
| Data flow pattern | Conflict: API uses runtime-fetch, KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows. uses in-memory bundle | Each instance can be optimised independently |
Two factors make separation the preferred direction: first, the threat model — an OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. failure with fail-secure behaviour would simultaneously block the API and the entire message bus, which is a disproportionate blast radius. Second, the data flow patterns diverge fundamentally: the existing APISIXApache APISIXAn open-source API gateway for traffic management, security and observability. In CIVITAS/CORE it is used as the centralized entrypoint to route and protect externally exposed APIs.–OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. integration fetches assignments from the backend DB at decision time, while KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows. authorization uses an in-memory bundle refreshed event-driven. Running both patterns in the same OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. instance creates operational and reasoning complexity.
The "single PDPPolicy Decision PointThe component that decides whether a request is authorized. CIVITAS/CORE uses Open Policy Agent (OPA) as its PDP." architecture principle (ADR041) refers to the technology choice (OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization.), not the deployment topology, and is satisfied by both options.
Dataset Definition
A datasetDatasetA data-related element that contains processed data and makes it available for consumption. A Dataset is populated via Pipelines and carries Metadata and access permissions. is the central organizing unit for payload data on the message bus. Each datasetDatasetA data-related element that contains processed data and makes it available for consumption. A Dataset is populated via Pipelines and carries Metadata and access permissions. may involve one or more pipelines and requires one or more KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows. topics to support them (e.g., raw ingestion, enrichment, error handling). All topics of a datasetDatasetA data-related element that contains processed data and makes it available for consumption. A Dataset is populated via Pipelines and carries Metadata and access permissions. share a common namespace prefix:
de.civitascore.data.<dataset>.*
Each datasetDatasetA data-related element that contains processed data and makes it available for consumption. A Dataset is populated via Pipelines and carries Metadata and access permissions. has:
- A dedicated namespace within the payload prefix (e.g.,
de.civitascore.data.luftqualitaet.*) - One or more topics within that namespace, one per pipeline stage or concern
- DatasetDatasetA data-related element that contains processed data and makes it available for consumption. A Dataset is populated via Pipelines and carries Metadata and access permissions.-specific principals with dedicated topic grants
Relation to Platform Authorization Model
This concept deliberately uses KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows.-native terminology throughout. The implementation team works directly with Strimzi, OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization., and KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows. documentation — all of which use the same terms. Translating to platform vocabulary inside this document would create a mismatch with every external reference and make implementation harder, not easier.
The translation happens at the boundary: this concept is the bridge between the platform domain model and the KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows. tool domain. The table below provides that translation for readers who need to reason across both models:
| Platform AuthZ Model | KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows. AuthZ Concept | Notes |
|---|---|---|
| Permission (atomic right: READ, CREATE, ...) | Role (config-consumer, data-producer) | Both describe the type of allowed operation. |
| Role (bundle of permissions, e.g. "Data Architect") | (no equivalent) | KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows. principals are assigned operation types directly — there is no bundling layer. |
| Scope (DataSetDatasetA data-related element that contains processed data and makes it available for consumption. A Dataset is populated via Pipelines and carries Metadata and access permissions., DataPool, Platform) | Topic Grant (topic pattern) | Both describe where a right applies. |
| Assignment (Group × Role × Scope) | Principal × Role × Topic Grant | Structurally identical. A KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows. principal is the bearer of the assignment. |
Outside this concept — in platform architecture documents, ADRsArchitecture Decision RecordA document capturing an architecture decision. Each ADR has a stable identifier and short title and is managed through four lifecycle states: Proposed, Accepted, Deprecated and Superseded., and cross-cutting discussions — the platform vocabulary applies.
Principal Model
Each KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows. client instance has a unique principal -- KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows.'s native term for a technical user identity. Clients authenticate via SASLSASL (Simple Authentication and Security Layer)A framework defined in RFC 4422 that decouples authentication from application protocols./SCRAMSCRAM (Salted Challenge Response Authentication Mechanism)A challenge-response authentication protocol defined in RFC 5802.-SHA-512 (see Authentication Concept); the SASLSASL (Simple Authentication and Security Layer)A framework defined in RFC 4422 that decouples authentication from application protocols. username becomes the KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows. principal. Principals are assigned to one or more roles. Roles define the type of access (produce, consume, admin), while topic grants define which specific topics a principal may access.
Ternary Authorization Model
Authorization decisions are always ternary -- they are evaluated along three dimensions:
Key property: Two principal instances can hold the same role but receive different, independent sets of topic grants. Topic grant sets may be disjoint, identical, or overlapping. This enables fine-grained, per-instance access control without role proliferation.
Example:
| Principal | Role | Topic Grants |
|---|---|---|
config-frost-adapter-consumer | config-consumer | de.civitascore.config.frost.* |
config-apisix-adapter-consumer | config-consumer | de.civitascore.config.apisix.* |
dataset-luftqualitaet-producer | data-producer | de.civitascore.data.luftqualitaet.* |
dataset-zaehlstellen-producer | data-producer | de.civitascore.data.zaehlstellen.* |
Both config-consumers share the role but are scoped to their own adapter's config namespace. Both data-producers share the role but have disjoint topic namespaces — the defining property of the ternary model.
Principal Types
| Principal Type | Description | Example |
|---|---|---|
config-producer | Instance that produces configuration events | config-outbox-relay-producer, config-saga-orchestrator-producer |
config-consumer | Instance that consumes configuration events | config-pipeline-a-consumer, config-saga-orchestrator-consumer |
dataset-producer | Producer for a datasetDatasetA data-related element that contains processed data and makes it available for consumption. A Dataset is populated via Pipelines and carries Metadata and access permissions.'s pipelines | dataset-luftqualitaet-producer |
dataset-consumer | Consumer for a datasetDatasetA data-related element that contains processed data and makes it available for consumption. A Dataset is populated via Pipelines and carries Metadata and access permissions.'s pipelines | dataset-luftqualitaet-consumer |
platform-admin | Platform operations (restricted, audited) | admin-mmustermann |
Principal Separation Rules
- Each component receives its own principal -- no credential sharing
- Producer and consumer roles are assigned separately, even if a component acts as both
- Infrastructure components (e.g., outbox relay, saga orchestrator) receive dedicated principals, separate from application principals
- Each principal receives its own set of topic grants -- role assignment alone does not imply topic access
Compatibility with Existing Patterns
The authorization model must be compatible with the platform's established messaging patterns. Both of the following patterns are currently scoped to configuration events only and operate within the de.civitascore.config.* namespace.
Saga PatternSaga PatternA pattern for coordinating long-running, multi-step operations across several components without a distributed transaction. Each step has a compensating action; if a later step fails, the compensating actions of all previously completed steps are executed in reverse order. In CIVITAS/CORE it is used for provisioning workflows that require sequential, cross-adapter operations. (details):
The Saga orchestrator sends commands to and receives results from multiple configuration adapter topics. Its KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows. principal requires both produce and consume access on de.civitascore.config.*. This is achieved by assigning both config-producer and config-consumer roles to the orchestrator's dedicated principal, with topic grants covering the full de.civitascore.config.* namespace.
Outbox PatternTransactional Outbox PatternA pattern for reliably publishing events after a database change: Entity changes and their corresponding outbox events are persisted in a single database transaction. A separate publisher process reads the outbox table and publishes events to Kafka after the transaction has committed. (details):
Application components (esp. the management portalManagement PortalThe central user interface of the Platform that provides access to all functionalities for managing data, configurations, users, and access. It serves as the main entry point for working with data-related elements. backend) write configuration events to a local outbox table. A separate relay process publishes these events to KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows.. The relay process receives a dedicated principal with the config-producer role and corresponding topic grants; the application component itself has no direct KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows. principal.
The Saga Orchestrator and Outbox Relay are high-value targets from a security perspective:
- The Saga Orchestrator holds READ + WRITE access across the entire
de.civitascore.config.*namespace, has access to saga state (internal URLs, project IDs, route IDs), and can trigger compensation cascades (deletions). - The Outbox Relay can inject arbitrary configuration events into the bus.
A compromise of either component would have platform-wide impact. The following hardening measures should be evaluated by the implementation team:
| Measure | Target | Rationale |
|---|---|---|
| Dedicated DB instance for saga state | Saga Orchestrator | Separates saga state from portal and authz data; limits blast radius of a portal-level SQL injection |
| HMAC/checksum on saga state entries | Saga Orchestrator | Detects DB-level tampering without additional infrastructure cost |
| Compensation rate limiting | Saga Orchestrator | Limits impact of a compromised orchestrator triggering deletion cascades |
| Anomaly alerting on compensation events | Saga Orchestrator | Detects unusual compensation patterns that may indicate compromise |
| Dedicated audit log for compensation events | Saga Orchestrator | Enables forensic analysis separate from the general OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. decision log |
Topic Namespace Structure
A consistent namespace structure is a prerequisite for efficient, rule-based access control. The platform uses two distinct namespace prefixes that enable clear separation of configuration and payload traffic.
Configuration Events
Configuration events use the fixed platform prefix de.civitascore.config, structured by adapter, entity, and event type. See Topic Configuration for the full event catalog.
de.civitascore.config.<adapter>.<entity>.<event>
Examples:
de.civitascore.config.frost.project.createdde.civitascore.config.apisix.route.deletedde.civitascore.config.idm.user.created
Saga topics are part of this namespace. SAGA commands and results (e.g. de.civitascore.config.frost.project.create) are routed through de.civitascore.config.* and are therefore fully covered by the config event grant model. There is no separate topic family for saga traffic.
Payload Data
Payload data topics use the fixed platform prefix de.civitascore.data, structured by datasetDatasetA data-related element that contains processed data and makes it available for consumption. A Dataset is populated via Pipelines and carries Metadata and access permissions. and topic name. Each datasetDatasetA data-related element that contains processed data and makes it available for consumption. A Dataset is populated via Pipelines and carries Metadata and access permissions. may require multiple topics for its pipelines (e.g., raw ingestion, enriched output, error handling).
de.civitascore.data.<dataset>.<topic>
Examples (datasetDatasetA data-related element that contains processed data and makes it available for consumption. A Dataset is populated via Pipelines and carries Metadata and access permissions. luftqualitaet with three topics):
de.civitascore.data.luftqualitaet.rawde.civitascore.data.luftqualitaet.enrichedde.civitascore.data.luftqualitaet.errors
Examples (datasetDatasetA data-related element that contains processed data and makes it available for consumption. A Dataset is populated via Pipelines and carries Metadata and access permissions. zaehlstellen with two topics):
de.civitascore.data.zaehlstellen.rawde.civitascore.data.zaehlstellen.enriched
Access is granted per datasetDatasetA data-related element that contains processed data and makes it available for consumption. A Dataset is populated via Pipelines and carries Metadata and access permissions. using a wildcard pattern: de.civitascore.data.<dataset>.*
Permission Matrix
Configuration Event Permissions
| Principal Type | Topic Pattern | Produce | Consume | Description |
|---|---|---|---|---|
config-producer (outbox relay) | de.civitascore.config.<adapter>.* per known adapter | yes | -- | Explicitly scoped per adapter namespace — no wildcard. New adapters require an explicit grant addition. |
config-producer (saga orchestrator) | de.civitascore.config.* | yes | -- | Needs full namespace access to send commands to all adapters |
config-consumer | de.civitascore.config.<adapter>.* | -- | yes | Scoped to own adapter's config namespace (e.g. de.civitascore.config.frost.*) |
config-consumer (saga) | de.civitascore.config.* | -- | yes | Saga orchestrator consumes results across all domains |
A config adapter must not read configuration events intended for other domains. Cross-component configuration is routed exclusively through the central config producer.
Payload Data
| Principal Type | Topic Pattern | Produce | Consume | Description |
|---|---|---|---|---|
data-producer (DatasetDatasetA data-related element that contains processed data and makes it available for consumption. A Dataset is populated via Pipelines and carries Metadata and access permissions. X) | de.civitascore.data.<dataset-x>.* | yes | -- | DatasetDatasetA data-related element that contains processed data and makes it available for consumption. A Dataset is populated via Pipelines and carries Metadata and access permissions. producer writes only own topics |
data-consumer (DatasetDatasetA data-related element that contains processed data and makes it available for consumption. A Dataset is populated via Pipelines and carries Metadata and access permissions. X) | de.civitascore.data.<dataset-x>.* | -- | yes | DatasetDatasetA data-related element that contains processed data and makes it available for consumption. A Dataset is populated via Pipelines and carries Metadata and access permissions. consumer reads only own topics |
A principal that needs read access to another datasetDatasetA data-related element that contains processed data and makes it available for consumption. A Dataset is populated via Pipelines and carries Metadata and access permissions.'s topics simply receives an additional topic grant for that datasetDatasetA data-related element that contains processed data and makes it available for consumption. A Dataset is populated via Pipelines and carries Metadata and access permissions.'s namespace. This is a regular topic grant entry in PostgreSQL -- no separate approval mechanism is required beyond the standard grant process.
Access Control Implementation -- OPA-based Kafka Authorizer
Architecture Overview
Authorization is enforced through a custom KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows. Authorizer that delegates decisions to OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization.. This replaces KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows.'s native ACL mechanism with the platform's central policy engine.
Request Flow
- A KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows. client (authenticated via SASLSASL (Simple Authentication and Security Layer)A framework defined in RFC 4422 that decouples authentication from application protocols./SCRAMSCRAM (Salted Challenge Response Authentication Mechanism)A challenge-response authentication protocol defined in RFC 5802.-SHA-512, see Authentication Concept) issues a produce or consume request
- The KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows. broker invokes the custom Authorizer with the request context:
principal-- the authenticated KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows. identityoperation--WRITE,READ,CREATE,DESCRIBE,DELETE, etc.resource_type--TOPIC,GROUP,CLUSTER,TRANSACTIONAL_IDresource_name-- the specific topic name or consumer group ID
- The Authorizer sends an HTTP POST to OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. with the structured request
- OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. evaluates the request against its RegoRegoOPA's declarative policy language, used to express authorization rules such as checking role assignments at the most specific scope first. policy using pre-loaded policy data from PostgreSQL
- OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. returns
{ "result": { "allow": true/false, "reason": "..." } } - The Authorizer maps the decision to KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows.'s
AuthorizationResult
Kafka Authorizer Plugin
The platform runs on Strimzi, which has an existing community OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. Authorizer plugin that already handles TOPIC, GROUP, CLUSTER, and TRANSACTIONAL_ID resources and delegates decisions to OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. over HTTP. This is the preferred approach: adopt the Strimzi OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. Authorizer and focus platform effort on the RegoRegoOPA's declarative policy language, used to express authorization rules such as checking role assignments at the most specific scope first. policy rather than Java plumbing.
Configuration (Strimzi Kafka CR):
spec:
kafka:
authorization:
type: custom
authorizerClass: org.openpolicyagent.kafka.OpaAuthorizer
superUsers:
- User:admin
configuration:
- name: opa.authorizer.url
value: http://opa-kafka:8181/v1/data/civitas/kafka/authz/allow
- name: opa.authorizer.allow.on.error
value: "false"
- name: opa.authorizer.cache.expire.after.seconds
value: "30"
Fail-secure: If OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. is unreachable, the Authorizer denies all requests (allow.on.error=false). A short-lived local cache reduces latency for repeated decisions without compromising security.
If the implementation team identifies blockers with the Strimzi OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. Authorizer (e.g. incompatibility with the platform's Strimzi version, missing features, or policy data model constraints), a custom Java plugin implementing org.apache.kafka.server.authorizer.Authorizer can be developed as a fallback. The RegoRegoOPA's declarative policy language, used to express authorization rules such as checking role assignments at the most specific scope first. policy and PostgreSQL schema remain identical in both cases.
OPA Policy for Kafka Authorization
OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. evaluates KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows. requests using a dedicated RegoRegoOPA's declarative policy language, used to express authorization rules such as checking role assignments at the most specific scope first. policy package (civitas.kafka.authz) separate from the existing API authorization policies (civitas.authz).
Policy Data Model
OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. receives policy data from PostgreSQL via the Bundle Service (see OPA Bundle Sync from PostgreSQL). The data is structured as follows:
{
"kafka_principals": {
"config-frost-adapter-consumer": {
"roles": ["config-consumer"],
"topic_grants": [
{
"topic_pattern": "de.civitascore.config.frost.*",
"operations": ["READ"]
}
]
},
"config-outbox-relay-producer": {
"roles": ["config-producer"],
"topic_grants": [
{
"topic_pattern": "de.civitascore.config.frost.*",
"operations": ["WRITE", "DESCRIBE"]
},
{
"topic_pattern": "de.civitascore.config.apisix.*",
"operations": ["WRITE", "DESCRIBE"]
}
]
},
"dataset-luftqualitaet-producer": {
"roles": ["data-producer"],
"topic_grants": [
{
"topic_pattern": "de.civitascore.data.luftqualitaet.*",
"operations": ["WRITE", "DESCRIBE"]
}
]
}
}
}
Rego Policy
# CIVITAS CORE Kafka AuthZ Policy
# Evaluates Kafka broker authorization requests against topic grants.
#
# Ternary model: principal × role × topic_grants
# Two principals with the same role can have independent topic grant sets.
package civitas.kafka.authz
import rego.v1
# Default deny -- fail secure
default allow := false
default decision := {"allow": false, "reason": "default_deny"}
# Main decision rule
decision := result if {
result := evaluate_request
}
allow if {
decision.allow
}
# --- Principal lookup ---
principal_entry := data.kafka_principals[input.principal]
# --- Grant evaluation ---
# Allow if at least one topic_grant matches both topic and operation
evaluate_request := {"allow": true, "reason": "topic_grant_matched"} if {
principal_entry
some grant in principal_entry.topic_grants
topic_matches(grant.topic_pattern, input.resource_name)
input.operation in grant.operations
}
# Known principal but no matching grant
evaluate_request := {"allow": false, "reason": "no_matching_grant"} if {
principal_entry
not has_matching_grant
}
# Unknown principal
evaluate_request := {"allow": false, "reason": "unknown_principal"} if {
not principal_entry
}
has_matching_grant if {
some grant in principal_entry.topic_grants
topic_matches(grant.topic_pattern, input.resource_name)
input.operation in grant.operations
}
# --- Topic pattern matching ---
# Supports exact match and wildcard suffix (e.g., "de.civitascore.config.*")
topic_matches(pattern, topic) if {
not endswith(pattern, ".*")
pattern == topic
}
topic_matches(pattern, topic) if {
endswith(pattern, ".*")
prefix := trim_suffix(pattern, "*")
startswith(topic, prefix)
}
# --- Consumer Group access ---
# Consumer groups follow the naming convention: cg-<principal-name>
# e.g. cg-dataset-luftqualitaet-consumer
# A principal may only use consumer groups that match its own name.
evaluate_request := {"allow": true, "reason": "consumer_group_matched"} if {
input.resource_type == "GROUP"
principal_entry
input.resource_name == concat("", ["cg-", input.principal])
}
evaluate_request := {"allow": false, "reason": "consumer_group_not_allowed"} if {
input.resource_type == "GROUP"
principal_entry
input.resource_name != concat("", ["cg-", input.principal])
}
Platform-Admin Override
The platform-admin role receives unrestricted access. This is handled as a dedicated rule:
# Platform admin bypass -- all operations allowed (audited separately)
evaluate_request := {"allow": true, "reason": "platform_admin"} if {
principal_entry
"platform-admin" in principal_entry.roles
}
PostgreSQL Schema Extension
The existing authorization database is extended with tables for KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows. principal management. These tables are part of the same database used by the AuthZ Repository for API permissions.
The platform operates on a shared DB cluster; the level of control available is at the database level, not the server or cluster level. The meaningful separation options are therefore:
| Option | Blast Radius | Notes |
|---|---|---|
| Single database, shared schemas | Portal compromise → access to authz + saga state | Simplest, least isolation |
| Separate databases per concern | Isolated per DB — portal compromise does not automatically reach saga or authz DB | Requires separate connection strings and DB users per component |
| Single database, schema-level role separation | Portal DB user has access only to its own schema | Pragmatic middle ground; relies on correct role configuration |
Note: full isolation is structurally incomplete regardless of approach — the portal backend must write to authz tables (grant provisioning). The most pragmatic mitigation is schema-level role separation: each component's DB user is granted only the minimum required permissions per schema, preventing lateral movement from a portal-level compromise into saga state or unrelated authz data. The implementation team should decide based on the platform's threat model and the DB provisioning model in use.
-- Kafka principal identities
CREATE TABLE kafka_principals (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
principal_name VARCHAR(255) NOT NULL UNIQUE,
description TEXT,
is_active BOOLEAN NOT NULL DEFAULT true,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
);
-- Reuse existing roles table (role_type = 'KAFKA')
-- INSERT INTO roles (name, description, role_type)
-- VALUES ('config-producer', '...', 'KAFKA');
-- Principal-to-role assignment
CREATE TABLE kafka_principal_roles (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
principal_id UUID NOT NULL REFERENCES kafka_principals(id),
role_id UUID NOT NULL REFERENCES roles(id),
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
UNIQUE (principal_id, role_id)
);
-- Topic grants (the per-principal topic access sets)
CREATE TABLE kafka_topic_grants (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
principal_id UUID NOT NULL REFERENCES kafka_principals(id),
topic_pattern VARCHAR(512) NOT NULL,
operations VARCHAR(255)[] NOT NULL, -- e.g., '{READ}', '{WRITE,DESCRIBE}'
valid_from TIMESTAMP NOT NULL DEFAULT NOW(),
valid_until TIMESTAMP, -- NULL = no expiry
granted_by VARCHAR(255), -- who approved the grant
approval_ref VARCHAR(512), -- reference to approval (e.g., ticket ID)
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
UNIQUE (principal_id, topic_pattern)
);
-- Index for OPA bundle export query
CREATE INDEX idx_kafka_topic_grants_principal
ON kafka_topic_grants(principal_id)
WHERE valid_until IS NULL OR valid_until > NOW();
OPA Decision-Time Data Flow
KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows. AuthZ uses an in-memory bundle — not runtime database queries.
At decision time, OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. evaluates KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows. authorization requests entirely against data held in memory. There is no database query per authorization request. This is a deliberate divergence from the existing APISIXApache APISIXAn open-source API gateway for traffic management, security and observability. In CIVITAS/CORE it is used as the centralized entrypoint to route and protect externally exposed APIs.–OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. integration, where OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. fetches assignments from the AuthZ Repository at decision time.
| APISIXApache APISIXAn open-source API gateway for traffic management, security and observability. In CIVITAS/CORE it is used as the centralized entrypoint to route and protect externally exposed APIs.–OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. (existing) | KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows.–OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. (this concept) | |
|---|---|---|
| Data access at decision time | Runtime fetch from AuthZ Repository | In-memory bundle |
| Latency per decision | DB round-trip | Memory lookup |
| Grant freshness | Always current | Eventually consistent (refreshed event-driven) |
| Suitable for | API requests (low frequency, complex queries) | KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows. broker (high frequency, simple lookup) |
The in-memory bundle is the correct pattern for KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows.: every produce and consume request triggers an authorization check, so a database round-trip per decision would have unacceptable throughput impact. Grants change only at known, discrete events (datasetDatasetA data-related element that contains processed data and makes it available for consumption. A Dataset is populated via Pipelines and carries Metadata and access permissions. publish/delete), making event-driven refresh sufficient.
This divergence in data flow pattern is an additional reason to run separate OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. instances for API and KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows. authorization (see Recommended: Separate OPA Instances).
DatasetDatasetA data-related element that contains processed data and makes it available for consumption. A Dataset is populated via Pipelines and carries Metadata and access permissions. publishing as a Saga with compensation:
DatasetDatasetA data-related element that contains processed data and makes it available for consumption. A Dataset is populated via Pipelines and carries Metadata and access permissions. publishing is modelled as a Saga. If any step fails (grant write, OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. refresh, principal creation, or credential distribution), the Saga compensates all completed steps in reverse order — removing the principal from KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows., removing the grants from PostgreSQL, and triggering an OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. bundle refresh. This ensures no dangling principals with grants exist after a failed publish.
OPA Bundle Sync from PostgreSQL
OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. receives policy data as a bundle that is assembled from PostgreSQL by a lightweight Bundle Service. Data is loaded once at OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. startup and then refreshed event-driven when the Bundle Service is triggered (see Caching and Refresh Strategy).
Bundle export query:
SELECT
kp.principal_name,
array_agg(DISTINCT r.name) AS roles,
json_agg(json_build_object(
'topic_pattern', ktg.topic_pattern,
'operations', ktg.operations
)) AS topic_grants
FROM kafka_principals kp
LEFT JOIN kafka_principal_roles kpr ON kpr.principal_id = kp.id
LEFT JOIN roles r ON r.id = kpr.role_id
LEFT JOIN kafka_topic_grants ktg ON ktg.principal_id = kp.id
AND (ktg.valid_until IS NULL OR ktg.valid_until > NOW())
WHERE kp.is_active = true
GROUP BY kp.principal_name;
The bundle service can be implemented as:
- As part of the existing eventhandling for configuration events
- An extension of the existing AuthZ Repository
- An OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. plugin using the
opa-envoy-pluginor custom Go plugin for direct PostgreSQL queries
Caching and Refresh Strategy
The two topic categories have fundamentally different change characteristics, which the caching strategy reflects:
Configuration event topics (de.civitascore.config.*) are defined at installation time and remain static during platform runtime. Changes only occur through platform updates/upgrades. Their topic grants can be loaded at OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. startup and do not require periodic refresh.
Payload data topics (de.civitascore.data.*) change when datasetsDatasetA data-related element that contains processed data and makes it available for consumption. A Dataset is populated via Pipelines and carries Metadata and access permissions. are published or updated through the Management PortalManagement PortalThe central user interface of the Platform that provides access to all functionalities for managing data, configurations, users, and access. It serves as the main entry point for working with data-related elements.. These changes are discrete, known events -- not continuous background changes.
Event-Driven Cache Invalidation
Instead of periodic polling, the Bundle Service supports targeted, event-driven refresh triggered by the Management PortalManagement PortalThe central user interface of the Platform that provides access to all functionalities for managing data, configurations, users, and access. It serves as the main entry point for working with data-related elements. backend:
This approach avoids unnecessary periodic database queries. The Management PortalManagement PortalThe central user interface of the Platform that provides access to all functionalities for managing data, configurations, users, and access. It serves as the main entry point for working with data-related elements. already knows when topic grants change (datasetDatasetA data-related element that contains processed data and makes it available for consumption. A Dataset is populated via Pipelines and carries Metadata and access permissions. publication, principal provisioning) and can trigger a targeted refresh for the affected datasetDatasetA data-related element that contains processed data and makes it available for consumption. A Dataset is populated via Pipelines and carries Metadata and access permissions..
Grant Provisioning
Topic grants for datasetDatasetA data-related element that contains processed data and makes it available for consumption. A Dataset is populated via Pipelines and carries Metadata and access permissions. principals are written to kafka_topic_grants by the Management PortalManagement PortalThe central user interface of the Platform that provides access to all functionalities for managing data, configurations, users, and access. It serves as the main entry point for working with data-related elements. backend as part of the datasetDatasetA data-related element that contains processed data and makes it available for consumption. A Dataset is populated via Pipelines and carries Metadata and access permissions. publish process — not by the Config Adapter. This is an explicit design decision to ensure race-condition-free principal provisioning:
- Backend writes topic grants to
kafka_topic_grants(PostgreSQL) - Backend triggers Bundle Service refresh → OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. receives updated grants
- Backend sends configuration event → Config Adapter creates principal in KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows.
- Config Adapter reports back to SAGA Orchestrator → credentials stored in Secrets Management
This ordering guarantees that OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. already holds the correct grants before the principal exists in KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows.. An authorization failure immediately after principal creation is therefore not possible.
Cache Layers
| Layer | Cache | Refresh | Purpose |
|---|---|---|---|
| KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows. Authorizer | Local decision cache (principal + operation + resource → result) | 30s TTL (configurable) | Reduce HTTP round-trips for repeated operations |
| OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. | In-process policy data | Event-driven (push from Bundle Service) | Fresh policy data without polling |
| Bundle Service | Query cache per datasetDatasetA data-related element that contains processed data and makes it available for consumption. A Dataset is populated via Pipelines and carries Metadata and access permissions. | Invalidated on refresh trigger | Reduce database load |
Refresh Triggers
| Event | Trigger Source | Scope |
|---|---|---|
| DatasetDatasetA data-related element that contains processed data and makes it available for consumption. A Dataset is populated via Pipelines and carries Metadata and access permissions. published / updated | Management PortalManagement PortalThe central user interface of the Platform that provides access to all functionalities for managing data, configurations, users, and access. It serves as the main entry point for working with data-related elements. | Affected datasetDatasetA data-related element that contains processed data and makes it available for consumption. A Dataset is populated via Pipelines and carries Metadata and access permissions. only |
| New principal provisioned | Platform Operations | Affected principal's datasetDatasetA data-related element that contains processed data and makes it available for consumption. A Dataset is populated via Pipelines and carries Metadata and access permissions.(s) |
| Platform update / upgrade | Deployment pipeline | Full reload (all datasetsDatasetA data-related element that contains processed data and makes it available for consumption. A Dataset is populated via Pipelines and carries Metadata and access permissions.) |
| Principal compromise | Platform Operations (emergency) | Immediate full reload + Authorizer cache flush |
Emergency Invalidation
For urgent changes (e.g., principal compromise), the standard event-driven flow is supplemented by direct intervention:
- Setting
is_active = falseon the principal in PostgreSQL - Triggering an immediate full OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. bundle reload (Bundle Service API or OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. API:
POST /v1/data) - Flushing the KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows. Authorizer cache via JMX or KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows. admin API
Audit Logging
OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. provides built-in decision logging that captures every authorization decision with full context:
{
"decision_id": "...",
"input": {
"principal": "config-frost-adapter-consumer",
"operation": "READ",
"resource_type": "TOPIC",
"resource_name": "de.civitascore.config.frost.project.created"
},
"result": {
"allow": true,
"reason": "topic_grant_matched"
},
"timestamp": "2026-03-27T10:15:30Z"
}
- All decisions (allow and deny) are logged by OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. decision logs
- Decision logs can be forwarded to the platform's central logging infrastructure
- For payload data topics, log volume can be managed via OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization.'s decision log sampling configuration
- The existing OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. decision log masking policy (
mask.rego) can be extended for KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows.-specific fields
Periodic Review
- Quarterly review of all topic grants (check
approval_refandvalid_untilinkafka_topic_grants) - Annual review of all principals and topic grants for currency
- Expired grants (
valid_until < NOW()) are automatically excluded from OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. bundle sync
Permission Registry
The permission registry is implemented as the PostgreSQL tables described in PostgreSQL Schema Extension. It replaces a static document artifact with a queryable, machine-enforced data store.
For reporting and review purposes, the following view provides a human-readable registry:
CREATE VIEW kafka_permission_registry AS
SELECT
kp.principal_name,
kp.is_active,
array_agg(DISTINCT r.name) AS roles,
ktg.topic_pattern,
ktg.operations,
ktg.valid_until,
ktg.granted_by,
ktg.approval_ref
FROM kafka_principals kp
LEFT JOIN kafka_principal_roles kpr ON kpr.principal_id = kp.id
LEFT JOIN roles r ON r.id = kpr.role_id
LEFT JOIN kafka_topic_grants ktg ON ktg.principal_id = kp.id
GROUP BY kp.principal_name, kp.is_active, ktg.topic_pattern,
ktg.operations, ktg.valid_until, ktg.granted_by, ktg.approval_ref
ORDER BY kp.principal_name, ktg.topic_pattern;
Implementation Steps Overview
| # | Task |
|---|---|
| 1 | Implement custom KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows. Authorizer plugin (Java) |
| 2 | Extend OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. RegoRegoOPA's declarative policy language, used to express authorization rules such as checking role assignments at the most specific scope first. policies for KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows. (civitas.kafka.authz package) |
| 3 | Implement or extend bundle service for PostgreSQL → OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. sync |
| 4 | Create PostgreSQL schema migration for KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows. AuthZ tables |
| 5 | Populate initial topic grants for existing components |
| 6 | Define audit logging pipeline for OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows. decision logs |
| 7 | Formalize topic grant approval process |
| 8 | Load testing: Measure Authorizer + OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. latency impact on broker throughput |
| 9 | Evaluate Authorizer decision cache TTL vs. refresh latency trade-offs |
Glossary
| Term | Definition |
|---|---|
| AuthN | Authentication -- identity verification |
| AuthZ | Authorization -- access control |
| Bundle Service | Lightweight service that exports PostgreSQL-based policy data as OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. bundles |
| DatasetDatasetA data-related element that contains processed data and makes it available for consumption. A Dataset is populated via Pipelines and carries Metadata and access permissions. | A published data product on the platform; the central organizing unit for payload topics. A datasetDatasetA data-related element that contains processed data and makes it available for consumption. A Dataset is populated via Pipelines and carries Metadata and access permissions. may involve one or more pipelines and one or more KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows. topics within its namespace (de.civitascore.data.<dataset>.*) |
| Custom Authorizer | KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows. plugin implementing org.apache.kafka.server.authorizer.Authorizer that delegates to OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. |
| OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. | Open Policy AgentOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization. -- the platform's central Policy Decision PointPolicy Decision PointThe component that decides whether a request is authorized. CIVITAS/CORE uses Open Policy Agent (OPA) as its PDP. for authorization |
| Outbox PatternTransactional Outbox PatternA pattern for reliably publishing events after a database change: Entity changes and their corresponding outbox events are persisted in a single database transaction. A separate publisher process reads the outbox table and publishes events to Kafka after the transaction has committed. | Transactionally safe event publishing via an intermediate database table |
| PDPPolicy Decision PointThe component that decides whether a request is authorized. CIVITAS/CORE uses Open Policy Agent (OPA) as its PDP. | Policy Decision PointPolicy Decision PointThe component that decides whether a request is authorized. CIVITAS/CORE uses Open Policy Agent (OPA) as its PDP. -- component that evaluates authorization requests (OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization.) |
| Principal | KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows.'s native term for a technical user identity -- the authenticated identity of a KafkaApache KafkaA distributed event streaming platform. In CIVITAS/CORE it is used as the message bus to transport events, models and data in data flows. client. In this platform, the SASLSASL (Simple Authentication and Security Layer)A framework defined in RFC 4422 that decouples authentication from application protocols./SCRAMSCRAM (Salted Challenge Response Authentication Mechanism)A challenge-response authentication protocol defined in RFC 5802. username serves as the principal. Corresponds to java.security.Principal |
| RegoRegoOPA's declarative policy language, used to express authorization rules such as checking role assignments at the most specific scope first. | OPAOpen Policy AgentThe platform's authorization service: it evaluates 'who may do what' against the CIVITAS/CORE authorization model. OPA is the platform's central Policy Decision Point (PDP) for API authorization.'s declarative policy language |
| Saga PatternSaga PatternA pattern for coordinating long-running, multi-step operations across several components without a distributed transaction. Each step has a compensating action; if a later step fails, the compensating actions of all previously completed steps are executed in reverse order. In CIVITAS/CORE it is used for provisioning workflows that require sequential, cross-adapter operations. | Distributed transaction pattern across multiple services/topics |
| Topic Grant | A mapping of a principal to a topic pattern with allowed operations -- the per-instance access control unit |