Skip to main content
Version: 2.0-rc2

Authorization Concept

Status: Concept -- Draft

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​

AspectScope
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.

Recommended: Separate OPA Instances for API and Kafka

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 InstanceSeparate Instances (recommended)
Failure domainOPAOpen 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 unavailableIndependent — 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 profileMixed (external API + internal broker)Isolated per concern
Operational effortLowerHigher (two deployments to operate)
Data flow patternConflict: 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 bundleEach 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 ModelKafkaApache 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 ConceptNotes
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 GrantStructurally 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:

PrincipalRoleTopic Grants
config-frost-adapter-consumerconfig-consumerde.civitascore.config.frost.*
config-apisix-adapter-consumerconfig-consumerde.civitascore.config.apisix.*
dataset-luftqualitaet-producerdata-producerde.civitascore.data.luftqualitaet.*
dataset-zaehlstellen-producerdata-producerde.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 TypeDescriptionExample
config-producerInstance that produces configuration eventsconfig-outbox-relay-producer, config-saga-orchestrator-producer
config-consumerInstance that consumes configuration eventsconfig-pipeline-a-consumer, config-saga-orchestrator-consumer
dataset-producerProducer 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 pipelinesdataset-luftqualitaet-producer
dataset-consumerConsumer 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 pipelinesdataset-luftqualitaet-consumer
platform-adminPlatform 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.

High-Value Targets

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:

MeasureTargetRationale
Dedicated DB instance for saga stateSaga OrchestratorSeparates saga state from portal and authz data; limits blast radius of a portal-level SQL injection
HMAC/checksum on saga state entriesSaga OrchestratorDetects DB-level tampering without additional infrastructure cost
Compensation rate limitingSaga OrchestratorLimits impact of a compromised orchestrator triggering deletion cascades
Anomaly alerting on compensation eventsSaga OrchestratorDetects unusual compensation patterns that may indicate compromise
Dedicated audit log for compensation eventsSaga OrchestratorEnables 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.created
  • de.civitascore.config.apisix.route.deleted
  • de.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.raw
  • de.civitascore.data.luftqualitaet.enriched
  • de.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.raw
  • de.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 TypeTopic PatternProduceConsumeDescription
config-producer (outbox relay)de.civitascore.config.<adapter>.* per known adapteryes--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-consumerde.civitascore.config.<adapter>.*--yesScoped to own adapter's config namespace (e.g. de.civitascore.config.frost.*)
config-consumer (saga)de.civitascore.config.*--yesSaga 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 TypeTopic PatternProduceConsumeDescription
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>.*--yesDatasetDatasetA 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​

  1. 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
  2. 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. identity
    • operation -- WRITE, READ, CREATE, DESCRIBE, DELETE, etc.
    • resource_type -- TOPIC, GROUP, CLUSTER, TRANSACTIONAL_ID
    • resource_name -- the specific topic name or consumer group ID
  3. 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
  4. 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
  5. 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": "..." } }
  6. 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.

Fallback: Custom Authorizer

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.

Open Design Decision: Database Separation

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:

OptionBlast RadiusNotes
Single database, shared schemasPortal compromise → access to authz + saga stateSimplest, least isolation
Separate databases per concernIsolated per DB — portal compromise does not automatically reach saga or authz DBRequires separate connection strings and DB users per component
Single database, schema-level role separationPortal DB user has access only to its own schemaPragmatic 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 timeRuntime fetch from AuthZ RepositoryIn-memory bundle
Latency per decisionDB round-tripMemory lookup
Grant freshnessAlways currentEventually consistent (refreshed event-driven)
Suitable forAPI 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-plugin or 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:

  1. Backend writes topic grants to kafka_topic_grants (PostgreSQL)
  2. 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
  3. 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.
  4. 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​

LayerCacheRefreshPurpose
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. AuthorizerLocal 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 dataEvent-driven (push from Bundle Service)Fresh policy data without polling
Bundle ServiceQuery 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 triggerReduce database load

Refresh Triggers​

EventTrigger SourceScope
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 / updatedManagement 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 provisionedPlatform OperationsAffected 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 / upgradeDeployment pipelineFull 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 compromisePlatform 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:

  1. Setting is_active = false on the principal in PostgreSQL
  2. 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)
  3. 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_ref and valid_until in kafka_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
1Implement 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)
2Extend 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)
3Implement 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
4Create 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
5Populate initial topic grants for existing components
6Define 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
7Formalize topic grant approval process
8Load 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
9Evaluate Authorizer decision cache TTL vs. refresh latency trade-offs

Glossary​

TermDefinition
AuthNAuthentication -- identity verification
AuthZAuthorization -- access control
Bundle ServiceLightweight 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 AuthorizerKafkaApache 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.)
PrincipalKafkaApache 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 GrantA mapping of a principal to a topic pattern with allowed operations -- the per-instance access control unit