최근 몇개월간 개발환경에서 개발되었던 앱을 드디어 운영환경에 배포하게 되었습니다.
해당 앱에는 kafka에 대한 의존성이 있었고, kafka클러스터가 Amazone msk환경에서 구축됨에 따라 이 과정에서 권한 설정과 관련한 여러가지 트러블 슈팅이 있었습니다.
그 과정에서 배우게 된 것들 중 첫번째로 kafka ACL에 대해서 정리해보고자 합니다.
ACL이란?
Kafka에서는 ACL 규칙을 통해 토픽(topic), 컨슈머 그룹(group), 클러스터(cluster) 등 특정 리소스에 대한 사용자/애플리케이션의 접근을 제어합니다. 각 ACL 항목에는 주체(principal), 호스트(host), 권한 유형(permission type), 작업(operation), 리소스 유형(resource type) 및 리소스 이름(resource name)이 정의됩니다.
예를 들어, 하나의 ACL 엔트리는 “User:Alice에게 Topic:customer에 Write 작업을 허용(Allow)”과 같이 해석될 수 있습니다.
번외) RBAC(Role-Based Access Control, 역할 기반 접근 제어)*:사용자를 개별 권한으로 관리하는 대신 **역할(Role)**이라는 추상 그룹에 권한을 묶어 관리하는 방법
ACL 항목 구성 요소
- 주체 (Principal): Kafka에 인증된 사용자 또는 애플리케이션 계정을 가리킵니다 (예: User:alice, User:app1 등). 주체 이름은 보안 프로토콜에 따라 정해지며, SASL/PLAIN일 경우 간단한 아이디, SSL 인증일 경우 인증서의 DN, Kerberos일 경우 credential principal 등이 사용됩니다.
- 저의 경우 여기에서 sasl/plain 방식으로 연결하였습니다.
- 호스트 (Host): 해당 권한이 허용되거나 거부되는 클라이언트의 호스트(또는 IP 주소)를 지정합니다. 특정 호스트에서만 접근을 허용하거나 전체 호스트(*)에 대해 허용할지를 설정할 수 있습니다 (와일드카드 * 사용 가능)
. 호스트를 지정하지 않으면 기본적으로 **모든 호스트(*)**에서의 접근에 적용됩니다. - 리소스 유형 (Resource Type): 권한을 적용할 Kafka 리소스의 종류를 나타냅니다. 주로 사용되는 리소스 유형에는 토픽(Topic), 컨슈머 그룹(Group), 클러스터(Cluster), 트랜잭션 ID(TransactionalId) 등이 있습니다. 예를 들어 --topic, --group, --cluster 등의 옵션으로 지정합니다.
- 리소스 이름 (Resource Name): 권한을 적용할 구체적인 리소스의 이름입니다. 예를 들어 토픽 이름이나 그룹 ID 등이 해당됩니다. 기본적으로 **정확히 일치(LITERAL)**하는 이름으로 간주되지만, Prefix 일치로 설정하여 특정 접두사로 시작하는 다수의 리소스에 한꺼번에 권한을 부여할 수도 있고, * 와일드카드를 사용하여 모든 리소스를 가리킬 수도 있습니다
- (예: --topic sales_*로 접두사 일치, --topic '*'로 모든 토픽 지정 등)
- 작업 (Operation): 주체가 해당 리소스에서 수행하려는 동작을 나타냅니다. Kafka에서 정의된 주요 Operation 종류로는 READ(읽기), WRITE(쓰기), CREATE(리소스 생성), DELETE(삭제), ALTER(수정), DESCRIBE(메타데이터 조회) 등이 있고, 이 외에 ClusterAction, IdempotentWrite (멱등 프로듀서용) 등의 내부적으로 사용하는 동작도 있습니다.
- --operation 옵션으로 지정하며, All을 선택하면 모든 종류의 작업에 대한 권한을 한 번에 지정할 수도 있습니다
- 권한 유형 (Permission Type): 해당 ACL이 허용(Allow)인지 거부(Deny)인지를 나타냅니다. 일반적으로 필요한 권한을 Allow로 부여하며, 특정 경우에 우선 차단이 필요하면 Deny를 설정합니다. (예: 기본 허용 범위를 설정한 후 일부 사용자만 예외적으로 거부할 때 등)
PLAIN/SASL 방식?
위의 여러가지 인증 방식 중에서 plain/sasl에 대해서 조금 더 알아보도록 하겠습니다.
nodejs환경에서 kafka연결시 kafkajs라는 라이브러리를 사용하여 카프카 클러스터에 연결을 할 수 있는데 해당 라이브러리의 공시문서와 msk kafka 문서를 함께 참고해보겠습니다.
포트에 따라 달라지는 Amazone msk kafka 인증방식
https://docs.aws.amazon.com/ko_kr/msk/latest/developerguide/port-info.html 다음 문서를 통해서 포트에 따라
9092포트에서는 PLAINTEXT, 그리고 sasl로 인증하기 위해서는 9096포트를 사용해야함을 알 수 있습니다.
저는 이 과정에서 9092포트의 브로커에 sasl인증방식을 넣었다가 연결을 거부당했었습니다,,,,
앱단에서는 다음과 같은 코드를 통해서 연결을 할 수 있는데, 여기에서 9096+ sasl scram-sha-512 해당 조합으로 연결을 해야합니다.
사실 plain 방식의 경우 username과 password에 대한 검증을 따로 하지 않는 것으로 확인되어 보안상 결코 좋은 선택이라 보기는 어렵습니다. 따라서 되도록이면 9096포트에 sasl/scram 방식으로 연결하는 것이 좋습니다. 그렇게 되어야 위의 acl에서 설정한 user로 접근하는 것이 되니까요!
ACL 그래서 뭐가 좋은데?
처음에는 복잡하게만 느껴지고 굳이 이렇게까지 리소스에 접근하는 유저를 구분해야 할 필요가 있을까? 라고 생각하였습니다.
하지만, acl을 설정하여 각 사용자나 애플리케이션이 업무에 필요한 최소한의 kafka 리소스에 대해서만 권한을 갖도록 하면, 예상치 못하게 다른 유저가 특정 리소스에 접근하는 것을 예방할 수 있어, 저희 서비스 같이 메시지를 컨슘하여 정제를 해야하는 경우에는 예상치 못하게 데이터가 유실되는 것을 방지할 수 있어 매우 합리적이라 생각되었습니다.
추후에는 앱단에서 로직을 모두 살펴보고 최소한의 권한만 갖도록 설정을 해야겠다는 추가적인 생각도 해보았습니다!
여기까지 간단하게 acl 그 중에서도 plain방식과 sasl/scram 방식으로 연결하는 것에 대해 살펴보았습니다.
이 외에도 schema registry에 대한 접근 권한도 생성이 필요하다는 것도 이번 배포를 통해서 알게되었습니다.
'인프라 > kafka' 카테고리의 다른 글
[KAFKA] consumer lag와 consumer group rebalancing 해결하기 (0) | 2025.03.15 |
---|