{"id":13783588,"url":"https://github.com/Dabz/kafka-security-playbook","last_synced_at":"2025-05-11T19:31:07.620Z","repository":{"id":34205257,"uuid":"133977968","full_name":"Dabz/kafka-security-playbook","owner":"Dabz","description":"Example of different security configurations for Apache Kafka and the Confluent Platform","archived":false,"fork":false,"pushed_at":"2024-01-22T14:04:27.000Z","size":1351,"stargazers_count":180,"open_issues_count":13,"forks_count":75,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-11-17T20:47:28.942Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://docs.confluent.io/current/security/index.html","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Dabz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":"auditlog/README.md","citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-05-18T16:18:11.000Z","updated_at":"2024-11-17T14:13:48.000Z","dependencies_parsed_at":"2024-01-18T15:57:04.226Z","dependency_job_id":"4034c0fb-23ef-4bc7-891d-7b11d4c1ee29","html_url":"https://github.com/Dabz/kafka-security-playbook","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dabz%2Fkafka-security-playbook","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dabz%2Fkafka-security-playbook/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dabz%2Fkafka-security-playbook/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dabz%2Fkafka-security-playbook/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Dabz","download_url":"https://codeload.github.com/Dabz/kafka-security-playbook/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253621003,"owners_count":21937458,"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","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":[],"created_at":"2024-08-03T19:00:25.525Z","updated_at":"2025-05-11T19:31:07.151Z","avatar_url":"https://github.com/Dabz.png","language":"Shell","funding_links":[],"categories":["Operations"],"sub_categories":["Security"],"readme":"# Kafka security playbook\n\nThis repository contains a set of docker images to demonstrate the security configuration of Kafka and the Confluent Platform. The purpose of this repository is **NOT** to provide production's ready images. It has been designed to be used as an example and to assist peoples configuring the security module of Apache Kafka.\n\nAll images has been created from scratch without reusing previously created images, this, to emphasize code and configuration readability over best-practices. For official images, I would recommend you to rely on the [Docker Images for the Confluent Platform](https://github.com/confluentinc/cp-docker-images)\n\n## Plain authentication (challenge response)\nPlain authentication is a simple mechanism based on username/password. It should be used with TLS for encryption to implement secure authentication. This playbook contains a simple configuration where SASL-Plain authentication is used for Kafka.\n\n### Usage\n```bash\ncd plain\n./up\nkafka-console-producer --broker-list kafka:9093 --producer.config /etc/kafka/consumer.properties --topic test\nkafka-console-consumer --bootstrap-server kafka:9093 --consumer.config /etc/kafka/consumer.properties --topic test --from-beginning\n```\n\n### Important configuration files\n\u003cdetails\u003e\n\u003csummary\u003e\u003ca href=\"plain/kafka/server.properties\"\u003ekafka server.properties\u003c/a\u003e\u003c/summary\u003e,\n\u003cpre\u003e\nsasl.enabled.mechanisms=PLAIN\nsasl.mechanism.inter.broker.protocol=PLAIN\nallow.everyone.if.no.acl.found=false\nsuper.users=User:kafka\nauthorizer.class.name=kafka.security.auth.SimpleAclAuthorizer\n\u003c/pre\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ca href=\"plain/kafka/consumer.properties\"\u003ekafka consumer and producer configuration\u003c/a\u003e\u003c/summary\u003e\n\u003cpre\u003e\nsasl.mechanism=PLAIN\nsecurity.protocol=SASL_PLAINTEXT\nsasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule required \\\n  username=\"kafka\" \\\npassword=\"kafka\";\n\u003c/pre\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ca href=\"plain/kafka/kafka.jaas.config\"\u003ekafka server jaas configuration\u003c/a\u003e\u003c/summary\u003e\n\u003cpre\u003e\nKafkaServer {\n   org.apache.kafka.common.security.plain.PlainLoginModule required\n   username=\"kafka\"\n   password=\"kafka\"\n   user_kafka=\"kafka\"\n   user_producer=\"producer-secret\"\n   user_consumer=\"consumer-secret\";\n};\n\u003c/pre\u003e\n\u003c/details\u003e\n\n#### For further information\n* [Confluent documentation on SASL Plain](https://docs.confluent.io/current/kafka/authentication_sasl_plain.html)\n\n\n## Scram authentication (challenge response)\nScram is an authentication mechanism that perform username/password authentication in a secure way. This playbook contains a simple configuration where SASL-Scram authentication is used for Zookeeper and Kafka. In it:\n* kafka use a username/password to connect to zookeeper\n* consumer and producer must use a username/password to access the cluster\n\n### Usage\n```bash\ncd scram\n# Scripts starting the docker services and generating the kafka user\n./up\ndocker-compose exec kafka kafka-console-producer --broker-list kafka:9093 --producer.config /etc/kafka/consumer.properties --topic test\ndocker-compose exec kafka kafka-console-consumer --bootstrap-server kafka:9093 --consumer.config /etc/kafka/consumer.properties --topic test --from-beginning\n```\n\n### Important configuration files\n\u003cdetails\u003e\n\u003csummary\u003e\u003ca href=\"scram/kafka/server.properties\"\u003ekafka server.properties\u003c/a\u003e\u003c/summary\u003e\n\u003cpre\u003e\nsasl.enabled.mechanisms=SCRAM-SHA-256\nsasl.mechanism.inter.broker.protocol=SCRAM-SHA-256\nsecurity.inter.broker.protocol=SASL_PLAINTEXT\nauthorizer.class.name=kafka.security.auth.SimpleAclAuthorizer\n\u003c/pre\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ca href=\"scram/kafka/consumer.properties\"\u003ekafka consumer and producer configuration\u003c/a\u003e\u003c/summary\u003e\n\u003cpre\u003e\nsasl.mechanism=SCRAM-SHA-256\nsecurity.protocol=SASL_PLAINTEXT\nsasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required \\\n  username=\"kafka\" \\\n  password=\"kafka\";\n\u003c/pre\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ca href=\"scram/kafka/kafka.sasl.jaas.config\"\u003ekafka server jaas configuration\u003c/a\u003e\u003c/summary\u003e\n\u003cpre\u003e\nKafkaServer {\n   org.apache.kafka.common.security.scram.ScramLoginModule required\n   username=\"kafka\"\n   password=\"kafka\";\n};\n\u003c/pre\u003e\n\u003c/details\u003e\n\n#### For further information\n* [Confluent documentation on SASL Scram](https://docs.confluent.io/current/kafka/authentication_sasl_scram.html)\n* [Zookeeper documentation on SASL Scram](https://cwiki.apache.org/confluence/display/ZOOKEEPER/Client-Server+mutual+authentication)\n\n## TLS with x509 authentication\nTLS, previously known as SSL, is a cryptography protocol providing network encryption via asymetric certificates and keys.\nThis playbook contains a basic configuration to enforce TLS between the broker and a client. Be aware that right now zookeeper didn't release TLS as an official feature, thus only the broker is configured for TLS. In this playbook, TLS is used for both encryption, authentication and authorization. the _up_ script generates the following file before starting docker-compose services:\n1. __certs/ca.key, certs/ca.crt__ - public and private key of the certificate authority\n2. __certs/server.keystore.jks__ - keystore containing the signed certificate of the kafka broker  \n3. __certs/client.keystore.jks__ - keystore containing the signed certificate of a kafka client. It has been granted super user permision   \n\n\n### Usage\n```bash\ncd tls\n# Scripts generating the required certificate and starting docker-compose services\n./up\ndocker-compose exec kafka kafka-console-producer --broker-list kafka.confluent.local:9093 --topic test --producer.config /etc/kafka/consumer.properties\ndocker-compose exec kafka kafka-console-consumer --bootstrap-server kafka.confluent.local:9093 --topic test --consumer.config /etc/kafka/consumer.properties --from-beginning\n\n#Avro consumer/producer using schema registry\ndocker-compose exec kafka kafka-avro-console-producer --broker-list kafka.confluent.local:9093 --topic avro_test --property value.schema='{\"type\":\"record\",\"name\":\"myrecord\",\"fields\":[{\"name\":\"f1\",\"type\":\"string\"}]}' --property schema.registry.url=https://schema-registry.confluent.local:8443 --producer.config /etc/kafka/consumer.properties\n#example message: {\"f1\": \"value1\"}\nkafka-avro-console-consumer --topic avro_test --from-beginning --property schema.registry.url=https://schema-registry.confluent.local:8443 --consumer.config /etc/kafka/consumer.properties --bootstrap-server kafka.confluent.local:9093\n\n```\n\nTo connect from a producer/consumer running on your local machine:\n\n```bash\ndocker-compose exec kafka kafka-acls --authorizer-properties zookeeper.connect=zookeeper.confluent.local:2181 --add --allow-principal User:CN=\u003cYOUR LOCAL HOSTNAME\u003e,L=London,O=Confluent,C=UK --operation All --topic '*' --cluster;\n```\nSet the following JVM parameters:\n\n```\n-Djavax.net.ssl.keyStore=\u003ckafka-security-playbook DIR\u003e/tls/certs/local-client.keystore.jks\n-Djavax.net.ssl.trustStore=\u003ckafka-security-playbook DIR\u003e/tls/certs/truststore.jks\n-Djavax.net.ssl.keyStorePassword=test1234\n-Djavax.net.ssl.trustStorePassword=test1234\n```\n\n### Important configuration files\n\u003cdetails\u003e\n\u003csummary\u003e\u003ca href=\"tls/kafka/server.properties\"\u003e kafka server.properties\u003c/a\u003e\u003c/summary\u003e\n\u003cpre\u003e\nlisteners=SSL://kafka.confluent.local:9093\nadvertised.listeners=SSL://kafka.confluent.local:9093\nsecurity.inter.broker.protocol=SSL\nssl.truststore.location=/var/lib/secret/truststore.jks\nssl.truststore.password=test1234\nssl.keystore.location=/var/lib/secret/server.keystore.jks\nssl.keystore.password=test1234\nssl.client.auth=required\n# To use TLS based authorization\nauthorizer.class.name=kafka.security.auth.SimpleAclAuthorizer\nsuper.users=User:CN=kafka.confluent.local,L=London,O=Confluent,C=UK\n\u003c/pre\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003e\u003ca href=\"tls/kafka/consumer.properties\"\u003ekafka consumer and producer configuration\u003c/a\u003e\u003c/summary\u003e\n\u003cpre\u003e\nbootstrap.servers=kafka.conflent.local:9093\nsecurity.protocol=SSL\nssl.truststore.location=/var/lib/secret/truststore.jks\nssl.truststore.password=test1234\nssl.keystore.location=/var/lib/secret/client.keystore.jks\nssl.keystore.password=test1234\nssl.key.password=test1234\n\u003c/pre\u003e\n\u003c/details\u003e\n\n#### For further information\n* [kafka documentation on TLS](http://kafka.apache.org/documentation.html#security_ssl)\n* [Confluent documentation on TLS authentication](https://docs.confluent.io/current/kafka/authentication_ssl.html)\n* [Confluent documentation on TLS key generation](https://docs.confluent.io/current/tutorials/security_tutorial.html#generating-keys-certs)\n\n## Kerberos (GSSAPI) authentication without TLS\nThis example contains a basic KDC server and configure both zookeeper and kafka with Kerberos authentication and authorization. Credentials are created without password, a keytab containing credentials is available in a Docker volume named \"secret\". The following credential are automatically created in the KDC database:\n1. __kafka/admin__ - to access zookeeper\n2. __kafka_producer/producer__  - to access kafka as a producer\n3. __kafka_consumer/consumer__  - to access kafka as a consumer\n\n### Usage\n```bash\ncd kerberos\n# Scripts orchestrating the docker-compose services\n./up\n# Using kinit with a keytab for authentication then invoking kafka interfaces\ndocker-compose exec kafka bash -c 'kinit -k -t /var/lib/secret/kafka.key kafka_producer/producer \u0026\u0026 kafka-console-producer --broker-list kafka:9093 --topic test --producer.config /etc/kafka/consumer.properties'\ndocker-compose exec kafka bash -c 'kinit -k -t /var/lib/secret/kafka.key kafka_consumer/consumer \u0026\u0026 kafka-console-consumer --bootstrap-server kafka:9093 --topic test --consumer.config /etc/kafka/consumer.properties --from-beginning'\n```\n\n### Important configuration files\n\u003cdetails\u003e\n\u003csummary\u003e\u003ca href=\"kerberos/zookeeper/zookeeper.properties\"\u003ezookeeper properties\u003c/a\u003e\u003c/summary\u003e\n\u003cpre\u003e\nauthProvider.1 = org.apache.zookeeper.server.auth.SASLAuthenticationProvider\nrequireClientAuthScheme=sasl\n\u003c/pre\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003e\u003ca href=\"kerberos/zookeeper/zookeeper.sasl.jaas.config\"\u003ezookeeper server and client jaas configuration\u003c/a\u003e\u003c/summary\u003e\n\u003cpre\u003e\nServer {\n    com.sun.security.auth.module.Krb5LoginModule required\n    useKeyTab=true\n    storeKey=true\n\t\tuseTicketCache=false\n    keyTab=\"/var/lib/secret/kafka.key\"\n    principal=\"zookeeper/zookeeper.kerberos_default@TEST.CONFLUENT.IO\";\n};\n\u003c/pre\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003e\u003ca href=\"kerberos/kafka/server.properties\"\u003ekafka server.properties\u003c/a\u003e\u003c/summary\u003e\n\u003cpre\u003e\nlisteners=SASL_PLAINTEXT://kafka:9093\nadvertised.listeners=SASL_PLAINTEXT://kafka:9093\nsecurity.inter.broker.protocol=SASL_PLAINTEXT\nsasl.enabled.mechanisms=GSSAPI\nsasl.mechanism.inter.broker.protocol=GSSAPI\nsecurity.inter.broker.protocol=SASL_PLAINTEXT\nsasl.kerberos.service.name=kafka\nallow.everyone.if.no.acl.found=false\nsuper.users=User:admin;User:kafka\nauthorizer.class.name=kafka.security.auth.SimpleAclAuthorizer\n\u003c/pre\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003e\u003ca href=\"kerberos/kafka/kafka.sasl.jaas.config\"\u003ekafka server and client jaas configuration\u003c/a\u003e\u003c/summary\u003e\n\u003cpre\u003e\n/*\n * Cluster kerberos services\n */\nKafkaServer {\n    com.sun.security.auth.module.Krb5LoginModule required\n    useKeyTab=true\n    storeKey=true\n    keyTab=\"/var/lib/secret/kafka.key\"\n    principal=\"kafka/kafka.kerberos_default@TEST.CONFLUENT.IO\";\n};\n\n/*\n * For client and broker identificatoin\n */\nKafkaClient {\n    com.sun.security.auth.module.Krb5LoginModule required\n    useKeyTab=true\n    storeKey=true\n    keyTab=\"/var/lib/secret/kafka.key\"\n    principal=\"admin/kafka.kerberos_default@TEST.CONFLUENT.IO\";\n};\n\n/*\n * For Zookeeper authentication\n */\nClient {\n    com.sun.security.auth.module.Krb5LoginModule required\n    useKeyTab=true\n    storeKey=true\n\t\tuseTicketCache=false\n    keyTab=\"/var/lib/secret/kafka.key\"\n    principal=\"kafka/kafka.kerberos_default@TEST.CONFLUENT.IO\";\n};\n\u003c/pre\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\t\u003csummary\u003e\u003ca href=\"kerberos/kafka/consumer.properties\"\u003ekafka consumer and producer configuration\u003c/a\u003e\u003c/summary\u003e\n\u003cpre\u003e\nbootstrap.servers=kafka:9093\nsecurity.protocol=SASL_PLAINTEXT\nsasl.kerberos.service.name=kafka\nsasl.jaas.config=com.sun.security.auth.module.Krb5LoginModule required \\\n\t\t\t\t\t\t\t\t useTicketCache=true\n\u003c/pre\u003e\n\u003c/details\u003e\n\n\n#### For further information\n* [Confluent documentation on GSSAPI authentication](https://docs.confluent.io/current/kafka/authentication_sasl_gssapi.html)\n* [Confluent documentation on ACL](https://docs.confluent.io/current/kafka/authorization.html)\n\n## Oauth authentication via TLS encryption\n\nKafka supports SASL authentication via Oauth bearer tokens. A sample playbook for secured oauth token authentication is contained in the oauth subfolder of this repository.\n\n### Usage\n\nPrerequisites: jdk8, maven, docker-compose, openssl.\n\n```bash\ncd oauth\n./up\n```\n\nIn this sample playbook both the identity of brokers (`sasl.mechanism.inter.broker.protocol=OAUTHBEARER` within server.properties) and the identity of clients (`sasl.mechanism=OAUTHBEARER` within consumer.properties) are verified by the brokers using oauth bearer tokens.\n\nWithin this sample playbook oauth bearer tokens are generated and validated using the `jjwt` library without communication to an authorization server. In real life, this would be different.\n\nThe class `OauthBearerLoginCallbackHandler` is used by the clients and by brokers to generate a JWT token using a shared secret. This class is configured within the `client.properties` file:\n\nNote that the client does not need to have a keystore configured, since client authentication is achieved using bearer tokens.\nStill it needs a truststore to store the brokers certificate authorities.\n\n\u003cdetails\u003e\n\t\u003csummary\u003e\u003ca href=\"oauth/kafka/client.properties\"\u003ekafka consumer and producer configuration\u003c/a\u003e\u003c/summary\u003e\n\u003cpre\u003e\nsecurity.protocol=SASL_SSL\nsasl.mechanism=OAUTHBEARER\nsasl.login.callback.handler.class=io.confluent.examples.authentication.oauth.OauthBearerLoginCallbackHandler\nssl.truststore.location=/etc/kafka/kafka.client.truststore.jks\nssl.truststore.password=secret\n\u003c/pre\u003e\n\u003c/details\u003e\n\nThe `OauthBearerLoginCallbackHandler` class is also configured for broker clients within the `server.properties` file (see below). The `server.properties` file must also include a reference to the token validator class (`OauthBearerValidatorCallbackHandler`):\n\n\u003cdetails\u003e\n\t\u003csummary\u003e\u003ca href=\"oauth/kafka/server.properties\"\u003ekafka broker configuration\u003c/a\u003e\u003c/summary\u003e\n\u003cpre\u003e\nlisteners=SASL_SSL://kafka.confluent.local:9093\nadvertised.listeners=SASL_SSL://kafka.confluent.local:9093\nsecurity.inter.broker.protocol=SASL_SSL\nsasl.mechanism.inter.broker.protocol=OAUTHBEARER\nsasl.enabled.mechanisms=OAUTHBEARER\nlistener.name.sasl_ssl.oauthbearer.sasl.server.callback.handler.class=io.confluent.examples.authentication.oauth.OauthBearerValidatorCallbackHandler\nlistener.name.sasl_ssl.oauthbearer.sasl.login.callback.handler.class=io.confluent.examples.authentication.oauth.OauthBearerLoginCallbackHandler\nssl.truststore.location=/etc/kafka/kafka.server.truststore.jks\nssl.truststore.password=secret\nssl.keystore.location=/etc/kafka/kafka.server.keystore.jks\nssl.keystore.password=secret\nssl.key.password=secret\n\u003c/pre\u003e\n\u003c/details\u003e\n\nKafka brokers need a keystore to store its private certificate as well as a truststore to verify the identity of other brokers.\n\n### Further information\n\n* [Confluent documentation on Oauth authentication](https://docs.confluent.io/current/kafka/authentication_sasl/authentication_sasl_oauth.html)\n* [Blog Post](https://medium.com/@jairsjunior/how-to-setup-oauth2-mechanism-to-a-kafka-broker-e42e72839fe)\n\n## Schema registry basic security\n\nAccording to documentation the schema registry plugin only supports SSL principals, but there is an undocumented separate authentication possibility via Jetty Authentication.\n\n```bash\ncd schema-registry-basic-auth\n./up\n```\n\nNow you can access the schema registry REST interface on `http://localhost:8089`\n\nNote that in order to test the schema registry properly, you need to either `curl` into it, or use the `kafka-avro-consule-producer` and consumer. The latter require special considerations.\n\nFirst, access via `curl`:\n\n```\ncurl -X GET http://localhost:8089 -u admin:admin\n```\n\nIf you want to try out the console producer, you need to exec into the schema-registry docker image and then run the producer:\n\n```\ndocker-compose exec schema-registry bash\nkafka-avro-console-producer --broker-list kafka:9092 --topic avro-test --property \\\n   value.schema='{\"type\":\"record\",\"name\":\"myrecord\",\"fields\":[{\"name\":\"f1\",\"type\":\"string\"}]}' \\\n   --property basic.auth.credentials.source=USER_INFO \\\n   --property schema.registry.basic.auth.user.info=write:write\n\n\u003e {\"f1\": \"value1\"}\n\u003e {\"f1\": \"value2\"}\n\u003e ^D\n```\n\nNote that the official documentation is wrong on two accounts. First, to define the source, you need to use `basic.auth.credentials.source` without the `schema.registry` in front of it.\n\nSecond, user authentication via a property file gets ignored, you need to pass the credentials via `--property`.\n\n## Schema registry semi-open security\n\nThis playbook is an example of configuration where Schema Registry is configured for accepting request on `http` and `https`.\nRequests on the `http` endpoint are actually identified as the `ANONYMOUS` user. This is possible thanks to the `confluent.schema.registry.anonymous.principal=true` option.\n\nThe following ACLs are configured:\n- `sr-acl-cli --config /etc/schema-registry/schema-registry.properties --add -s '*' -p 'ANONYMOUS' -o 'SUBJECT_READ'`\n- `sr-acl-cli --config /etc/schema-registry/schema-registry.properties --add -p 'ANONYMOUS' -o 'GLOBAL_SUBJECTS_READ'`\n- `sr-acl-cli --config /etc/schema-registry/schema-registry.properties --add -p 'ANONYMOUS' -o 'GLOBAL_COMPATIBILITY_READ'`\n- `sr-acl-cli --config /etc/schema-registry/schema-registry.properties --add -s '*' -p 'C=UK,O=Confluent,L=London,CN=schema-registry' -o '*'`\n\nWith this configuration, ` curl  -X GET http://localhost:8089/subjects/` is successful, but the `ANONYMOUS` user does not have the privileges to write new schemas.\nOnly the client with the TLS client certificate `C=UK,O=Confluent,L=London,CN=schema-registry` can write new schemas, this could be for example your CI tool or an admin user.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FDabz%2Fkafka-security-playbook","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FDabz%2Fkafka-security-playbook","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FDabz%2Fkafka-security-playbook/lists"}