---
title: "Extract ACLs from any source"
description: "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."
url: https://monedula.dev/flock/docs/acl-rbac-converter/how-to/extract-acls/
---

`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](/flock/docs/acl-rbac-converter/reference/examples/) lists a runnable example for each.

**A live cluster.** `extract` connects with the Kafka client settings in `--command-config` and lists the ACLs:

```bash
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:

```bash
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:

```bash
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:

```yaml
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](/flock/docs/acl-rbac-converter/reference/formats/acls-v1/) 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):

```text
id,principal,host,operation,resource_type,resource_name,pattern_type,permission_type
1,User:svc-orders-consumer,*,Read,Topic,orders,LITERAL,Allow
```

```bash
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`:

```yaml
TOPIC: orders.events
ENV:   prod
```

```bash
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:

```bash
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:

```bash
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:

```bash
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:

```bash
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](https://github.com/monedula-dev/monedula-acl-rbac-converter/blob/main/pkg/aclrbac/extract/k8s/rbac/clusterrole.yaml) 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:

```json
{
  "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.

## Related

- [Plan and review role bindings](/flock/docs/acl-rbac-converter/how-to/plan-and-review/) is the next step.
- The [extract command reference](/flock/docs/acl-rbac-converter/reference/cli/extract/) lists every flag.
- [Config files](/flock/docs/acl-rbac-converter/reference/config-files/) describes `vars.yaml`.