---
title: "Delete the converted ACLs"
description: "Generate, review and run the ACL deletion script after verification, with its rollback script and the plan checksum checks."
url: https://monedula.dev/flock/docs/acl-rbac-converter/how-to/delete-converted-acls/
---
`delete-acls` deletes nothing itself: it writes a script of `kafka-acls --remove` commands, and a rollback script, that you read and then run.

## Before you start

- A `verify.json` from [`verify`](/flock/docs/acl-rbac-converter/how-to/verify-effective-access/) against the current plan, with every result you want to delete `EFFECTIVE_OK`.
- At least 24 hours since `verify`, or the cooldown your team agreed on, so that applications exercise their new bindings. ACL and RBAC permissions are additive in Confluent, so the ACLs and the bindings both grant access while you wait, and deleting the verified ACLs afterwards is a cleanup.
- The bootstrap servers and a Kafka client properties file for a principal that may delete ACLs.
- The standard Kafka CLI, with `kafka-acls`, on the host where you run the script.

## Steps

### 1. Generate the deletion script

Generate the script for one principal, or a few, at a time:

```bash
monedula-acl-rbac delete-acls \
  --plan runs/2026-05-21T10-00-00Z/plan.json \
  --verify runs/2026-05-21T10-00-00Z/verify.json \
  --bootstrap-server kafka.example.com:9093 \
  --command-config admin.properties \
  --principal User:alice \
  --principal User:bob \
  --confirm --i-understand-this-is-destructive
```

`--principal` is repeatable, and `--principal-file` reads one principal per line, ignoring blank lines and lines that start with `#`. Without either, the script covers every eligible ACL in the plan. Both `--confirm` and `--i-understand-this-is-destructive` are required; without `--confirm`, the command asks you to type `yes`.

An ACL is eligible only when it is the source of a binding and its `verify` result for that binding is `EFFECTIVE_OK`, or `BINDING_EXISTS` from a `verify --mode bindings-exist`, which only shows that the binding exists. ACLs with missing or unknown access are left out, and so are unmapped and rejected ACLs, including every DENY ACL. If nothing is eligible, `delete-acls` stops with an error. It also refuses a stale `plan.json`, `verify.json` or `acls.json` ([Safety guarantees](/flock/docs/acl-rbac-converter/concepts/safety-guarantees/#stale-plans-are-refused)).

`delete-acls` writes three files into the run directory:

- `delete-acls.sh`: the deletion script.
- `deleted-acls.json`: the exact ACLs that the script removes.
- `rollback.sh`: a `kafka-acls --add` script that recreates them.

### 2. Read the script

Open `delete-acls.sh` and read it. Its header records the tool version, the SHA-256 of `plan.json` and of `verify.json`, the bootstrap servers and the principals it was generated for. Each ACL is one line like this, with `--command-config` added when you passed it:

```bash
if kafka-acls '--bootstrap-server' 'kafka.example.com:9093' '--remove' '--force' '--allow-principal' 'User:alice' '--operation' 'Read' '--resource-pattern-type' 'literal' '--topic' 'orders'; then log 'OK acl_id=1'; else log 'FAIL acl_id=1'; exit 1; fi
```

If something looks wrong, edit the script or abandon it.

### 3. Run the script

<Callout type="warning">
The script deletes the listed ACLs from the cluster. Keep `rollback.sh` until the migration is stable.
</Callout>

```bash
bash runs/2026-05-21T10-00-00Z/delete-acls.sh
```

Before it deletes anything, the script hashes `plan.json` again and refuses to run, with exit code 5, when the plan changed since generation or cannot be hashed. When you run the script on purpose away from its run directory, for example copied into a broker container, set `MONEDULA_SKIP_PLAN_HASH_CHECK=1` to skip that check.

The script removes the ACLs in order and logs each one to `delete.log` in the run directory as `OK` or `FAIL`, with the ACL's `id`. It stops at the first failure; [Recover from a failed run](/flock/docs/acl-rbac-converter/how-to/recover-from-a-failed-run/) covers what to do then.

### 4. Repeat for the next principals

Run `delete-acls` again with the next principals, read the new script and run it. One principal at a time keeps a mistake small.

To undo a deletion, run the matching `rollback.sh` against the same cluster:

```bash
bash runs/2026-05-21T10-00-00Z/rollback.sh
```

Each `delete-acls` run writes the three files again, so copy `rollback.sh` aside before you generate the script for the next principals in the same run directory.

## Check it worked

The script exits 0 and `delete.log` ends with `SUMMARY exit=0`, after an `OK` line for every ACL in `deleted-acls.json`. `kafka-acls --list` no longer shows the deleted ACLs, while the principals keep their access through their role bindings.

## Related

- [Remove DENY ACLs](/flock/docs/acl-rbac-converter/how-to/remove-deny-acls/) handles the DENY ACLs that `delete-acls` never touches.
- The [delete-acls command reference](/flock/docs/acl-rbac-converter/reference/cli/delete-acls/) lists every flag and exit code.
- Runnable version: [live-mds-migration](https://github.com/monedula-dev/monedula-acl-rbac-converter/tree/main/examples/live-mds-migration), which generates the script and runs it in the broker container.