백엔드 데이터 인프라 116편. Kafka ACL Authorization 깊이 — Principal · Operation · Resource 3 tuple, kafka-acls.sh 명령, LITERAL · PREFIXED · MATCH resource pattern, super.users, team 별 권한 분리 패턴, StandardAuthorizer vs Custom 까지 풀어쓴 학습 노트. Part 5-8 Security 마무리.
이 글은 백엔드 데이터 인프라 시리즈 130편 중 116편이에요. Part 5-8 Security 의 마지막 글. 113~115편 으로 Authentication·Encryption 을 잡았다면, 이번 116편은 Authorization — ACL(접근 제어 목록) 깊이.
ACL이 어렵게 느껴지는 이유
3 tuple (Principal · Operation · Resource) 조합에 resource pattern 까지 더하면 가능한 경우의 수가 한 번에 부푼다.
먼저 resource 타입 5가지에 operation 8가지가 곱해져 40개 조합이 나오는데, 그중 자주 쓰이는 게 어떤 건지 감이 잘 안 잡힌다. 여기에 Pattern 3가지 (LITERAL·PREFIXED·MATCH) 가 또 붙어 조합이 3배로 늘어난다. 마지막 함정이 allow.everyone.if.no.acl.found — 기본값은 false 지만 true 로 두는 순간 ACL 자체가 의미를 잃는다.
이 글에서 3 tuple, pattern, 운영 패턴까지 한 번에 짚는다.
ACL 의 3 tuple
ACL = (Principal, Operation, Resource)
읽는 법은 단순하다. "Principal 이 Resource 에 대해 Operation 을 할 수 있다".
여기에 추가 옵션이 세 개 붙는다. Permission Type 은 ALLOW (기본) 또는 DENY, Host 는 특정 IP 만 받거나 기본값 * 로 전부 열어두고, Resource Pattern Type 으로 LITERAL · PREFIXED · MATCH 중 하나를 고른다.
Principal — 누구
User:alice # 일반 user
User:CN=alice,OU=Eng,O=... # X.509 DN (mTLS)
User:ANONYMOUS # 인증 안 한 user
SASL/SCRAM 이면 User:<username> 형태, SSL/mTLS(양방향 TLS 인증) 이면 User:<dn> 또는 ssl.principal.mapping.rules 로 매핑해서 쓴다.
Operation — 무엇
| Operation | Resource | 설명 |
|---|---|---|
| Read | Topic, Group | 메시지 read, group offset commit |
| Write | Topic, TransactionalId | 메시지 write, transaction commit |
| Create | Topic, Cluster | Topic 생성 |
| Delete | Topic | Topic 삭제 |
| Alter | Topic, Cluster | Config 변경, partition 추가 |
| Describe | Topic, Group, Cluster, TransactionalId | Metadata 조회 |
| ClusterAction | Cluster | Inter-broker (replica fetch 등) |
| DescribeConfigs | Topic, Broker | Config 조회 |
| AlterConfigs | Topic, Broker | Config 변경 |
| IdempotentWrite | Cluster | Idempotent producer |
| All | Any | 모든 operation |
대부분의 application 이 결국 쓰는 건 Read · Write · Describe 세 개로 좁혀진다.
Resource Type 5가지
| Type | 예제 |
|---|---|
| Topic | orders, payments, events.* |
| Group | order-workers, analytics-* |
| Cluster | kafka-cluster (cluster-wide ops) |
| TransactionalId | tx-1, payment-tx-* (transactional producer) |
| DelegationToken | delegation token (분산 인증) |
Resource Pattern — 3가지
LITERAL — 정확 일치
--topic orders --resource-pattern-type LITERAL
정확히 orders topic 하나에만 매칭된다.
PREFIXED — 접두사 일치
--topic prod.order-team. --resource-pattern-type PREFIXED
prod.order-team.* 로 시작하는 모든 topic 에 한 번에 권한이 붙는다. 101편 multi-tenancy 에서 본 패턴이고, 새 topic 이 추가돼도 ACL 을 다시 박을 필요가 없다는 게 가장 큰 장점.
MATCH — 모든 일치 (조회용)
--topic '*' --resource-pattern-type MATCH
ACL 조회할 때만 쓴다. 새 ACL 을 생성하는 용도로는 못 쓴다.
kafka-acls.sh — 명령
ACL 추가
$ kafka-acls.sh --bootstrap-server localhost:9092 \
--add --allow-principal User:alice \
--operation Read --operation Write \
--topic orders
--operation 을 여러 번 붙이면 한 번에 여러 권한이 들어간다.
Consumer Group ACL
$ kafka-acls.sh --bootstrap-server localhost:9092 \
--add --allow-principal User:alice \
--operation Read --operation Describe \
--group order-workers
Consumer 는 Topic Read 뿐 아니라 Group Read · Describe 까지 같이 박아야 동작한다.
PREFIXED
$ kafka-acls.sh --bootstrap-server localhost:9092 \
--add --allow-principal User:order-team-app \
--operation All \
--topic 'prod.order-team.' --resource-pattern-type PREFIXED \
--group 'prod.order-team.' --resource-pattern-type PREFIXED
Producer ACL
$ kafka-acls.sh --bootstrap-server localhost:9092 \
--producer \
--allow-principal User:alice \
--topic orders
--producer 옵션은 Write + Describe + Create 를 Topic · TransactionalId · IdempotentWrite 에 자동으로 박아주는 편의 옵션.
Consumer ACL
$ kafka-acls.sh --bootstrap-server localhost:9092 \
--consumer \
--allow-principal User:alice \
--topic orders \
--group order-workers
--consumer 도 Topic 의 Read · Describe 와 Group 의 Read 를 자동으로 박는 편의 옵션이다.
조회
$ kafka-acls.sh --bootstrap-server localhost:9092 --list
$ kafka-acls.sh --bootstrap-server localhost:9092 --list --topic orders
$ kafka-acls.sh --bootstrap-server localhost:9092 --list --principal User:alice
삭제
$ kafka-acls.sh --bootstrap-server localhost:9092 \
--remove --allow-principal User:alice \
--topic orders --operation Read
Allow vs Deny 우선순위
1. 어떤 DENY ACL 이 매칭? → 거부
2. 어떤 ALLOW ACL 이 매칭? → 허용
3. 둘 다 없음 → allow.everyone.if.no.acl.found 따라
DENY 가 ALLOW 보다 우선이다. "전부 열어주되 특정 user 만 차단" 하는 패턴을 이 우선순위로 만든다.
# 모두 read OK
$ kafka-acls.sh --add --allow-principal User:* --operation Read --topic public
# 단 bob 만 차단
$ kafka-acls.sh --add --deny-principal User:bob --operation Read --topic public
super.users
# broker config
super.users=User:admin;User:CN=admin-cert
여기에 들어간 user 는 모든 ACL 검사를 건너뛴다. 사실상 무제한 권한이다.
운영 환경에서는 운영 admin 한 명 정도가 적당하고, 너무 많이 박으면 ACL 을 둔 의미 자체가 사라진다.
allow.everyone.if.no.acl.found
# broker config
allow.everyone.if.no.acl.found=false # 기본
여기가 정말 중요한 자리다. false (기본·운영 권장) 면 ACL 이 없는 resource 는 전부 거부되고, true 면 ACL 없는 resource 가 전부 열린다 (insecure). 운영 환경은 반드시 false 로 두는데, 일부 환경 (Confluent) 은 기본이 true 라 시작하자마자 바꿔야 한다.
Authorizer — 구현체 선택
StandardAuthorizer (Kafka 3.3+ 권장)
# KRaft mode
authorizer.class.name=org.apache.kafka.metadata.authorizer.StandardAuthorizer
KRaft(ZooKeeper 없는 Kafka 합의 프로토콜) 환경의 표준. ACL 을 metadata log 에 저장한다.
AclAuthorizer (옛 ZK mode)
# ZK mode
authorizer.class.name=kafka.security.authorizer.AclAuthorizer
ZooKeeper 에 ACL 을 저장하던 옛 모드용.
Custom Authorizer
public class MyAuthorizer implements Authorizer {
@Override
public List<AuthorizationResult> authorize(...) {
// 외부 시스템 (OPA·LDAP·DB) 조회
// ...
}
}
authorizer.class.name=com.example.MyAuthorizer
엔터프라이즈 환경에서 기존 권한 관리 시스템 — OPA(정책 엔진), LDAP(디렉터리 인증 프로토콜), 내부 DB — 와 통합할 때 쓴다.
운영 패턴 — Team 별 권한 분리 (101편 종합)
TEAM=order-team
ENV=prod
# 1. SASL user 생성 (115편)
$ kafka-configs.sh --bootstrap-server localhost:9092 \
--alter --add-config 'SCRAM-SHA-512=[iterations=8192,password=...]' \
--entity-type users --entity-name ${TEAM}-app
# 2. Topic ACL (PREFIXED)
$ kafka-acls.sh --bootstrap-server localhost:9092 \
--add --allow-principal User:${TEAM}-app \
--operation All \
--topic "${ENV}.${TEAM}." --resource-pattern-type PREFIXED
# 3. Group ACL (PREFIXED)
$ kafka-acls.sh --bootstrap-server localhost:9092 \
--add --allow-principal User:${TEAM}-app \
--operation All \
--group "${ENV}.${TEAM}." --resource-pattern-type PREFIXED
# 4. Quota (101편)
$ kafka-configs.sh --bootstrap-server localhost:9092 \
--alter --add-config 'producer_byte_rate=20971520,consumer_byte_rate=20971520' \
--entity-type users --entity-name ${TEAM}-app
이 흐름을 자동화 스크립트로 묶어두면 team onboarding 표준이 된다.
자주 헷갈리는 ACL 조합
Consumer 필수 ACL
- Topic Read on orders
- Topic Describe on orders
- Group Read on order-workers
- Group Describe on order-workers
--consumer 옵션이 이 네 가지를 자동으로 박아준다.
Producer 필수 ACL
- Topic Write on orders
- Topic Describe on orders
- (transactional) TransactionalId Write on tx-id
- (idempotent) Cluster IdempotentWrite
--producer 옵션이 자동으로 박아준다.
Admin 필수 ACL
- Cluster Create / Describe / Alter
- Topic Create / Delete / Alter / DescribeConfigs / AlterConfigs
- Group Describe / Delete
이 정도면 그냥 super.users 로 넣는 쪽이 낫다.
모니터링
JMX(자바 모니터링 표준) 로 세 가지를 본다.
authorize-time-ns— ACL 검사 시간failed-authorization-rate— 실패율cache-hit-rate— ACL cache 효율
failed-authorization-rate 가 높게 튄다면 설정이 잘못됐거나 공격 시도가 들어오고 있다는 신호다.
한계·실무 함정
1. allow.everyone.if.no.acl.found=true
가장 위험한 설정. ACL 을 둔 의미가 통째로 사라지니까 반드시 false 로 둔다.
2. super.users 남발
너무 많이 넣으면 ACL 자체가 무의미해진다. 최소 1~2 명으로 유지한다.
3. PREFIXED 누락
새 topic 이 늘어날 때 LITERAL ACL 만 박아두면 매번 ACL 을 추가해야 한다. 운영 표준은 PREFIXED 다.
4. Group ACL 누락
Consumer 에 Topic Read 만 박고 Group Read 를 빼먹으면 consumer group commit 단계에서 실패가 난다.
5. mTLS Principal 매핑 오류
ssl.principal.mapping.rules 가 어긋나면 principal 이름이 달라져서 ACL match 가 안 된다.
6. Custom Authorizer 의 latency
ACL 검사는 모든 request 마다 일어나는 일이라 custom authorizer 가 느리면 전체 throughput 이 같이 떨어진다. caching 이 필수.
Part 5-8 Security 마무리
4편 (113~116):
- 113 Security Overview — 3축 종합 + protocol 4가지
- 114 SSL/TLS — Keystore·Truststore·mTLS·인증서 운영
- 115 SASL — 5가지 메커니즘·JAAS·SCRAM 운영
- 116 ACL — 3 tuple·PREFIXED·super.users·team 패턴
Kafka 보안은 결국 조합 문제다. SASL_SSL + SCRAM-SHA-512 + StandardAuthorizer + ACL PREFIXED 가 운영 황금 조합.
시험 직전 한 번 더 — Kafka ACL 함정 압축 노트
- ACL = (Principal, Operation, Resource) 3 tuple + Permission Type + Host + Pattern
- Principal =
User:<name>(SASL) 또는User:<DN>(mTLS) - Operation 자주 = Read · Write · Describe + Create · Delete · Alter
- Resource Type 5가지 = Topic · Group · Cluster · TransactionalId · DelegationToken
- Resource Pattern 3가지 = LITERAL (정확) · PREFIXED (접두사) · MATCH (조회만)
- PREFIXED = 운영 표준 (새 topic 자동 권한)
kafka-acls.sh—--add·--remove·--list+--allow-principal/--deny-principal--producer= Write + Describe + Topic Create + TransactionalId + IdempotentWrite 자동--consumer= Topic Read + Describe + Group Read 자동- Allow vs Deny — DENY 가 우선
super.users=User:admin= ACL 검사 skip (최소만)allow.everyone.if.no.acl.found=false(기본·운영 권장) — true = ACL 의미 X- Authorizer 구현체 —
StandardAuthorizer(KRaft, Kafka 3.3+) /AclAuthorizer(ZK) / Custom - Team 별 권한 분리 = SASL user + PREFIXED Topic ACL + PREFIXED Group ACL + Quota
- 자동화 스크립트 = team onboarding 표준
- 모니터링 =
failed-authorization-rate·cache-hit-rate - 함정 —
allow.everyone.if.no.acl.found=true가장 위험 - 함정 — super.users 남발
- 함정 — PREFIXED 누락 → 매번 ACL 추가
- 함정 — Group ACL 누락 → commit 실패
- 함정 — mTLS Principal 매핑 오류
- 함정 — Custom Authorizer latency → caching 필수
- Part 5-8 Security 4편 = Overview·SSL·SASL·ACL
- 운영 황금 조합 = SASL_SSL + SCRAM-SHA-512 + StandardAuthorizer + PREFIXED ACL
공식 문서: Kafka Authorization and ACLs 에서 자세한 사양을 확인할 수 있어요.
시리즈 다른 편 (앞뒤 글 모음)
이전 글:
- 111편 — Kafka Consumer Rebalance Protocol (KIP-848 새 모델)
- 112편 — Kafka Transaction Protocol (EOS 내부 메커니즘)
- 113편 — Kafka Security Overview (3축 종합)
- 114편 — Kafka SSL/TLS (Keystore · mTLS · 인증서 운영)
- 115편 — Kafka SASL (SCRAM · PLAIN · OAuth · Kerberos)
다음 글: