Monedula
monedula-acl-rbac-converter docs menu

Extract ACLs from any source

Read Kafka ACLs from a live cluster, a kafka-acls dump, JSON, YAML or CSV, a shell script, Strimzi or CFK manifests into acls.json.

How-to guides 2 of 11

5 min read

Updated 6 October 2026

Markdown

On this page

extract reads your Kafka ACLs from wherever they live and writes them into one canonical file, acls.json, that every later step reads. It never changes the source: it reads a cluster, or parses a file without running it.

Before you start

  • For a live cluster: the bootstrap servers and a Kafka client properties file for a principal that can list the cluster’s ACLs, such as the admin.properties you use with kafka-acls.sh.
  • For a running Kubernetes cluster: a kubeconfig whose user may get and list the kafkausers, kafkas, confluentrolebindings and kafkatopics resources.
  • For a file source: the file, or for CFK, a directory of manifests.

Steps

1. Choose the run directory

extract starts a run: it writes acls.json into a run directory, where every later command adds its own artifacts. Name the file with --out, and its parent directory becomes the run directory. The examples on this page use runs/2026-05-21T10-00-00Z/. Without --out or --run-dir, extract creates runs/<UTC timestamp>/ in the current directory.

2. Run extract for your source

--from names the source. There are nine: live, text, json, yaml, csv, script, strimzi, cfk and k8s. Runnable examples lists a runnable example for each.

A live cluster. extract connects with the Kafka client settings in --command-config and lists the ACLs:

monedula-acl-rbac extract --from live \
  --bootstrap-server kafka.example.com:9093 \
  --command-config admin.properties \
  --out runs/2026-05-21T10-00-00Z/acls.json

TLS and SASL settings go in the properties file, as for kafka-acls.sh: security.protocol=SSL, ssl.truststore.location and so on. Truststores and keystores can be PEM (.pem, .crt, .cer), PKCS12 (.p12, .pfx) or JKS (.jks, .keystore), with their passwords in ssl.truststore.password and ssl.keystore.password. An encrypted PEM private key is rejected: decrypt it with openssl rsa -in encrypted.pem -out decrypted.pem, or convert the keystore to PKCS12 with openssl pkcs12 -export -inkey key.pem -in cert.pem -out keystore.p12. To read only part of the cluster, add --principal-filter or --topic-filter, a topic prefix; both are repeatable. --bootstrap is a short alias of --bootstrap-server.

A kafka-acls.sh --list dump. Save the output of kafka-acls.sh --list to a file and read it with the text source:

monedula-acl-rbac extract --from text --input acls.txt \
  --out runs/2026-05-21T10-00-00Z/acls.json

A JSON or YAML file. Files that follow the canonical schema, for example an export from an inventory, are read by the json and yaml sources:

monedula-acl-rbac extract --from yaml --input acls.yaml \
  --out runs/2026-05-21T10-00-00Z/acls.json

Each row names one principal, host, operation, resource and permission:

schema_version: "1"
source:
  type: yaml
  generated_at: "2026-06-13T00:00:00Z"
acls:
  - { id: 1,  principal: "User:svc-orders-consumer",  host: "*", operation: Read,     resource_type: Topic, resource_name: orders,           pattern_type: LITERAL,  permission_type: Allow }
  - { id: 2,  principal: "User:svc-orders-consumer",  host: "*", operation: Describe, resource_type: Topic, resource_name: orders,           pattern_type: LITERAL,  permission_type: Allow }

The acls.v1.json format reference lists every field and its allowed values.

A CSV file. A spreadsheet export works if it has these columns, with one ACL per row (RFC 4180):

id,principal,host,operation,resource_type,resource_name,pattern_type,permission_type
1,User:svc-orders-consumer,*,Read,Topic,orders,LITERAL,Allow
monedula-acl-rbac extract --from csv --input acls.csv \
  --out runs/2026-05-21T10-00-00Z/acls.json

A shell script of kafka-acls --add commands. The script source parses a provisioning script, it never runs it, and turns each kafka-acls --add call into ACL rows. Line continuations, quoting and wrappers such as docker exec or kubectl exec are handled, and the producer and consumer convenience flags are expanded. Give the values of the script’s variables in a vars.yaml:

TOPIC: orders.events
ENV:   prod
monedula-acl-rbac extract --from script --input setup-acls.sh \
  --vars vars.yaml \
  --out runs/2026-05-21T10-00-00Z/acls.json

The parser refuses to guess. A variable without a value in vars.yaml, control flow such as for topic in $TOPICS; do kafka-acls ...; done, or a command substitution makes extract stop and name the line. Add the missing values to vars.yaml, and expand loops and conditions into plain kafka-acls lines. A kafka-acls --remove or --list call is an error too, unless you add --ignore-non-add to skip it.

Strimzi KafkaUser resources. Export the resources, for example with kubectl get kafkausers -o yaml, and read the file:

monedula-acl-rbac extract --from strimzi --input kafka-users.yaml \
  --out runs/2026-05-21T10-00-00Z/acls.json

The principal is User: followed by the resource’s metadata.name, and only users with authorization.type: simple produce ACLs.

CFK manifests on disk. Point the cfk source at a directory of Confluent for Kubernetes manifests:

monedula-acl-rbac extract --from cfk --input cfk-manifests/ \
  --out runs/2026-05-21T10-00-00Z/acls.json

It reads two things. Each superuser in a Kafka resource’s spec.authorization.superUsers becomes an All ACL on the cluster, which the default rules map to SystemAdmin. Existing ConfluentRolebinding resources are written to existing-bindings.json next to acls.json, and plan then marks a binding that already exists as SKIP_EXISTS instead of creating it again.

A running Kubernetes cluster. The k8s source reads Strimzi KafkaUser and CFK Kafka and ConfluentRolebinding resources through the Kubernetes API, with your kubeconfig:

monedula-acl-rbac extract --from k8s \
  --context prod-cluster \
  --namespace kafka \
  --out runs/2026-05-21T10-00-00Z/acls.json

To read every namespace you can see, narrowed by a label selector:

monedula-acl-rbac extract --from k8s \
  --context prod-cluster \
  --all-namespaces \
  --label-selector team=payments \
  --out runs/2026-05-21T10-00-00Z/acls.json

--kubeconfig points at a kubeconfig other than the default one. The repository ships a ClusterRole with the read-only permissions the extractor needs.

3. Inspect acls.json

Open acls.json before you plan. Check that the principals, resources and operations are the ones you expect, and that the number of rows matches your source. Every row has a numeric id; the plan, the verification results and the deletion scripts refer to ACLs by that id.

Check it worked

extract exits 0 and writes acls.json into the run directory, next to extract.log and extract-source.json, which record how and from where the ACLs were read, and, for the cfk and k8s sources, existing-bindings.json when they find role bindings. A row of acls.json looks like this:

{
  "id": 1,
  "principal": "User:svc-orders-consumer",
  "host": "*",
  "operation": "Read",
  "resource_type": "Topic",
  "resource_name": "orders",
  "pattern_type": "LITERAL",
  "permission_type": "Allow"
}

monedula-acl-rbac status runs/2026-05-21T10-00-00Z shows the number of ACLs and the source type on its extract line.