skip to content

Explain Kafka's ACL evaluation precedence — how are ALLOW and DENY rules combined, and what happens when both match?

level: seniorimportance: must knowfreq 65%

answer

  1. deny-by-default
  2. DENY > ALLOW > nothing
  3. no 'most specific wins'
  4. broad PREFIXED ALLOW + targeted DENY carve-out
  5. no rule ordering / no override of DENY

basics

~10 s

Kafka is deny-by-default: if nothing matches, access is denied. If any matching DENY exists, access is denied even if an ALLOW also matches. An ALLOW grants only when no DENY matches.

solid answer

~40 s

Authorization is deny-by-default and DENY-wins. For a given (principal, host, operation, resource), the authorizer gathers every matching ACL across all pattern types — LITERAL, PREFIXED, and the literal wildcard `*`. If any matching rule is DENY, the result is DENIED regardless of how many ALLOWs also match. Only if there is at least one matching ALLOW and zero matching DENY is the request authorized. There is no notion of "most specific rule wins" or rule ordering — precedence is purely DENY > ALLOW > (nothing → deny). This means you can grant broad access with a PREFIXED `*` ALLOW and carve out exceptions with targeted DENY rules. Super users bypass this evaluation entirely, and allow.everyone.if.no.acl.found changes only the empty-match case — but those are authorizer defaults, separate from precedence itself.

go deeper

for a junior

Know deny-by-default and that DENY beats ALLOW.

for a middle

Explain the three-state decision and that pattern types are pooled together when matching.

for a senior

Articulate the broad-ALLOW + targeted-DENY carve-out pattern and that there is no specificity/ordering tie-breaker.

for a principal

Critique reliance on DENY carve-outs at scale (auditability, accidental over-deny) and prefer narrow positive grants.

## The three-state decision For any access attempt, the authorizer reduces all matching ACLs to one of three outcomes, in strict precedence: 1. **Any matching DENY** → **DENIED** (highest priority, always wins). 2. **No DENY but at least one matching ALLOW** → **ALLOWED**. 3. **No matching ACL at all** → **DENIED** (deny-by-default). ## What "matching" means An ACL matches an attempt when its principal matches (the exact user or the `User:*` wildcard principal), its host matches (the client IP or `*`), its operation matches (the exact op or `All`), and its resource pattern matches the resource name. Pattern matching spans: - **LITERAL** rules on the exact resource name, - **LITERAL** `*` rules (all resources of that type), - **PREFIXED** rules whose prefix is a prefix of the resource name. All of these are collected together — there is no precedence between pattern types. ## DENY beats ALLOW — and why it's a feature Because a single matching DENY overrides everything, you can express "grant broadly, then subtract": - ALLOW Read on PREFIXED `team-a-` (all of team A's topics), - DENY Read on LITERAL `team-a-secrets` (one sensitive topic). The combination gives team A every topic except the secret one. There is **no** way for an ALLOW to override a DENY, and there is **no** "more specific rule wins" tie-breaker — specificity is irrelevant. ## Common trap Engineers coming from firewall/IAM systems sometimes assume the most specific rule, or the last-added rule, wins. In Kafka neither is true: DENY is absolute. Adding a broad ALLOW will never "unblock" a resource that any DENY covers. ## Boundaries (owned elsewhere) Two things sit outside pure precedence: **super.users** bypass the authorizer entirely (always allowed, never even evaluated against ACLs), and **allow.everyone.if.no.acl.found** only changes outcome #3 (the empty-match case). Both are authorizer defaults covered by a sibling topic.

  • User:alice has ALLOW Read on PREFIXED 'logs-' and DENY Read on LITERAL 'logs-pii'. Can she read 'logs-pii'?
    No. The DENY matches and DENY always wins over the ALLOW, regardless of which is more specific.
  • If two ALLOW rules and no DENY match, does ordering matter?
    No. ACLs are unordered; any single matching ALLOW (with no DENY) authorizes the request. Multiple ALLOWs don't conflict.

saying these in an interview costs you the question

  • Saying the most specific rule wins — Kafka has no specificity tie-breaker.
  • Saying the last-added or first-added rule wins — ACLs are unordered.
  • Claiming an ALLOW can override a DENY — it never can.
  • Forgetting deny-by-default for the no-match case.

context