{"id":23773846,"url":"https://github.com/StyraOSS/opa-kafka-plugin","last_synced_at":"2025-09-05T18:31:25.258Z","repository":{"id":38476524,"uuid":"220199630","full_name":"StyraOSS/opa-kafka-plugin","owner":"StyraOSS","description":"Open Policy Agent (OPA) plug-in for Kafka authorization","archived":false,"fork":false,"pushed_at":"2025-04-15T18:51:10.000Z","size":276,"stargazers_count":63,"open_issues_count":8,"forks_count":22,"subscribers_count":11,"default_branch":"main","last_synced_at":"2025-08-15T04:44:00.832Z","etag":null,"topics":["authorization","kafka","kafka-authorization","opa","opa-kafka-plugin","open-policy-agent","openpolicyagent","rego"],"latest_commit_sha":null,"homepage":"","language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/StyraOSS.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2019-11-07T09:31:38.000Z","updated_at":"2025-08-14T19:53:40.000Z","dependencies_parsed_at":"2025-05-20T22:18:14.458Z","dependency_job_id":null,"html_url":"https://github.com/StyraOSS/opa-kafka-plugin","commit_stats":null,"previous_names":["bisnode/opa-kafka-plugin","anderseknert/opa-kafka-plugin","styraoss/opa-kafka-plugin"],"tags_count":13,"template":false,"template_full_name":null,"purl":"pkg:github/StyraOSS/opa-kafka-plugin","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StyraOSS%2Fopa-kafka-plugin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StyraOSS%2Fopa-kafka-plugin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StyraOSS%2Fopa-kafka-plugin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StyraOSS%2Fopa-kafka-plugin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/StyraOSS","download_url":"https://codeload.github.com/StyraOSS/opa-kafka-plugin/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StyraOSS%2Fopa-kafka-plugin/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273799051,"owners_count":25170305,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-05T02:00:09.113Z","response_time":402,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["authorization","kafka","kafka-authorization","opa","opa-kafka-plugin","open-policy-agent","openpolicyagent","rego"],"created_at":"2025-01-01T05:45:48.211Z","updated_at":"2025-09-05T18:31:25.245Z","avatar_url":"https://github.com/StyraOSS.png","language":"Scala","funding_links":[],"categories":["Scala"],"sub_categories":[],"readme":"#  Open Policy Agent plugin for Kafka authorization\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.bisnode.kafka.authorization/opa-authorizer/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.bisnode.kafka.authorization/opa-authorizer)\n![](https://github.com/anderseknert/opa-kafka-plugin/workflows/build/badge.svg)\n[![codecov](https://codecov.io/gh/Bisnode/opa-kafka-plugin/branch/master/graph/badge.svg)](https://codecov.io/gh/Bisnode/opa-kafka-plugin)\n\nOpen Policy Agent (OPA) plugin for Kafka authorization.\n\n### Prerequisites\n\n* Kafka 3.8.0+ (for older Kafka versions, please check previous release)\n* Java 17 or above\n* OPA installed and running on the brokers\n\n## Installation\n\n###\n\nDownload the latest OPA authorizer plugin jar from [Releases](https://github.com/anderseknert/opa-kafka-plugin/releases/) (or [Maven Central](https://search.maven.org/artifact/org.openpolicyagent.kafka/opa-authorizer)) and put the\nfile (`opa-authorizer-{$VERSION}.jar`) somewhere Kafka recognizes it - this could be directly in Kafka's `libs` directory\nor in a separate plugin directory pointed out to Kafka at startup, e.g:\n\n`CLASSPATH=/usr/local/share/kafka/plugins/*`\n\nTo activate the opa-kafka-plugin add the `authorizer.class.name` to server.properties\\\n`authorizer.class.name=org.openpolicyagent.kafka.OpaAuthorizer`\n\n\u003cbr /\u003e\nThe plugin supports the following properties:\n\n| Property Key | Example | Default | Description |\n| --- | --- | --- | --- |\n| `opa.authorizer.url` | `http://opa:8181/v1/data/kafka/authz/allow` |  | Name of the OPA policy to query. [required] |\n| `opa.authorizer.allow.on.error` | `false` | `false` | Fail-closed or fail-open if OPA call fails. |\n| `opa.authorizer.cache.initial.capacity` | `5000` | `5000` | Initial decision cache size. |\n| `opa.authorizer.cache.maximum.size` | `50000` | `50000` | Max decision cache size. |\n| `opa.authorizer.cache.expire.after.seconds` | `3600` | `3600` | Decision cache expiry in seconds. |\n| `opa.authorizer.metrics.enabled` | `true` | `false` | Whether or not expose JMX metrics for monitoring. |\n| `super.users` | `User:alice;User:bob` |  | Super users which are always allowed. |\n| `opa.authorizer.truststore.path` | `/path/to/mytruststore.p12` |  | Path to the PKCS12 truststore for HTTPS requests to OPA. |\n| `opa.authorizer.truststore.password` | `ichangedit` | `changeit` | Password for the truststore. |\n| `opa.authorizer.truststore.type` | `PKCS12`, `JKS` or whatever your JVM supports | `PKCS12` | Type of the truststore. |\n\n## Usage\n\nExample structure of input data provided from opa-kafka-plugin to Open Policy Agent.\n```json\n{\n    \"action\": {\n        \"logIfAllowed\": true,\n        \"logIfDenied\": true,\n        \"operation\": \"DESCRIBE\",\n        \"resourcePattern\": {\n            \"name\": \"alice-topic\",\n            \"patternType\": \"LITERAL\",\n            \"resourceType\": \"TOPIC\",\n            \"unknown\": false\n        },\n        \"resourceReferenceCount\": 1\n    },\n    \"requestContext\": {\n        \"clientAddress\": \"192.168.64.1\",\n        \"clientInformation\": {\n            \"softwareName\": \"unknown\",\n            \"softwareVersion\": \"unknown\"\n        },\n        \"connectionId\": \"192.168.64.4:9092-192.168.64.1:58864-0\",\n        \"header\": {\n            \"data\": {\n                \"clientId\": \"rdkafka\",\n                \"correlationId\": 5,\n                \"requestApiKey\": 3,\n                \"requestApiVersion\": 2\n            },\n            \"headerVersion\": 1\n        },\n        \"listenerName\": \"SASL_PLAINTEXT\",\n        \"principal\": {\n            \"name\": \"alice-consumer\",\n            \"principalType\": \"User\"\n        },\n        \"securityProtocol\": \"SASL_PLAINTEXT\"\n    }\n}\n```\n\nThe following table summarizes the supported resource types and operation names.\n\n| `input.action.resourcePattern.resourceType` | `input.action.operation` |\n| --- | --- |\n| `CLUSTER` | `CLUSTER_ACTION` |\n| `CLUSTER` | `CREATE` |\n| `CLUSTER` | `DESCRIBE` |\n| `GROUP` | `READ` |\n| `GROUP` | `DESCRIPTION` |\n| `TOPIC` | `CREATE` |\n| `TOPIC` | `ALTER` |\n| `TOPIC` | `DELETE` |\n| `TOPIC` | `DESCRIBE` |\n| `TOPIC` | `READ` |\n| `TOPIC` | `WRITE` |\n| `TRANSACTIONAL_ID` | `DESCRIBE` |\n| `TRANSACTIONAL_ID` | `WRITE` |\n\nThese are handled by the method _authorizeAction_, and passed to OPA with an _action_, that identifies\nthe accessed resource and the performed operation. _patternType_ is always _LITERAL_.\n\nCreation of a topic checks for CLUSTER + CREATE. If this is denied, it will check for TOPIC with its name + CREATE.\n\nWhen doing idempotent write to a topic, and the first request for operation=IDEMPOTENT_WRITE on the resourceType=CLUSTER is denied,\nthe method _authorizeByResourceType_ to check, if the user has the right to write to any topic.\nIf yes, the idempotent write is granted by Kafka's ACL-implementation. To allow for a similar check,\nit is mapped to OPA with _patternType=PREFIXED_, _resourceType=TOPIC_, and _name=\"\"_.\n```json\n{\n  \"action\": {\n    \"logIfAllowed\": true,\n    \"logIfDenied\": true,\n    \"operation\": \"DESCRIBE\",\n    \"resourcePattern\": {\n      \"name\": \"\",\n      \"patternType\": \"PREFIXED\",\n      \"resourceType\": \"TOPIC\",\n      \"unknown\": false\n    },\n    \"resourceReferenceCount\": 1\n  },\n  ...\n}\n```\n\nIt's likely possible to use all different resource types and operations described in the Kafka API docs:\nhttps://kafka.apache.org/24/javadoc/org/apache/kafka/common/acl/AclOperation.html\nhttps://kafka.apache.org/24/javadoc/org/apache/kafka/common/resource/ResourceType.html\n\n### Security protocols:\n\n| Protocol | Description |\n|---|---|\n| `PLAINTEXT` | Un-authenticated, non-encrypted channel |\n| `SASL_PLAINTEXT` | authenticated, non-encrypted channel |\n| `SASL` | authenticated, SSL channel |\n| `SSL` | SSL channel |\n\nMore info:\n\nhttps://kafka.apache.org/24/javadoc/org/apache/kafka/common/security/auth/SecurityProtocol.html\n\n### Policy sample\n\nWith the [sample policy rego](src/main/rego/README.md) you will out of the box get\na structure where an \"owner\" can one user per type (`consumer`, `producer`, `mgmt`). The owner and user type is separated by `-`.\n* Username structure: `\u003cowner\u003e-\u003ctype\u003e`\n* Topic name structure: `\u003cowner-\u003e.*`\n\n\\\n\u003cb\u003eExample:\u003c/b\u003e \\\nUser `alice-consumer` will be...\n* allowed to consume on topic `alice-topic1`\n* allowed to consume on topic `alice-topic-test`\n* denied to produce on any topic\n* denied to consume on topic `bob-topic`\n\n[See sample rego](src/main/rego/README.md)\n\n## Build from source\n\nUsing gradle wrapper: `./gradlew clean test shadowJar`\n\nThe resulting jar (with dependencies embedded) will be named `opa-authorizer-{$VERSION}-all.jar` and stored in\n`build/libs`.\n\n## Logging\n\nSet log level `log4j.logger.org.openpolicyagent=INFO` in `config/log4j.properties`\nUse DEBUG or TRACE for debugging.\n\nIn a busy Kafka cluster it might be good to tweak the cache since it may produce a lot of log entries in Open Policy Agent, especially if decision logs are turned on. If the policy isn't dynamically updated very often it's recommended to cache a lot to improve performance and reduce the amount of log entries.\n\n## Monitoring\nThe plugin exposes some metrics that can be useful in operation.\n* `opa.authorizer:type=authorization-result`\n    * `authorized-request-count`: number of allowed requests\n    * `unauthorized-request-count`: number of denied requests\n* `opa.authorizer:type=request-handle`\n    * `request-to-opa-count`: number of HTTP request sent to OPA to get authorization result\n    * `cache-hit-rate`: Cache hit rate. Cache miss rate should be `1 - cache-hit-rate`\n    * `cache-usage-percentage`: the ratio of cache size over maximum cache capacity\n\n## Community\n\nFor questions, discussions and announcements related to Styra products, services and open source projects, please join the Styra community on [Slack](https://communityinviter.com/apps/styracommunity/signup)!","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FStyraOSS%2Fopa-kafka-plugin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FStyraOSS%2Fopa-kafka-plugin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FStyraOSS%2Fopa-kafka-plugin/lists"}