카프카 보안 – 3가지

카프카 보안 – 3가지

카프카 보안은 카프카 클러스터의 중요한 측면 중 하나이며, 데이터의 안전한 전송, 인증, 권한 부여, 기밀성 등을 보장하는 데 필요한 기능을 제공합니다. 카프카의 보안 기능은 다음과 같은 주요 측면을 다룹니다:

  1. 인증(Authentication): 카프카는 클라이언트가 시스템에 접근하기 전에 인증을 거치도록 지원합니다. 이를 통해 클라이언트의 신원을 확인하고, 액세스 권한을 검증할 수 있습니다. 카프카는 다양한 인증 메커니즘을 지원하며, 주로 SSL/TLS 기반의 인증과 SASL(Plaintext, SCRAM, GSSAPI 등) 기반의 인증이 사용됩니다.
  2. 권한 부여(Authorization): 인증 후에는 클라이언트가 수행할 수 있는 작업에 대한 권한을 부여해야 합니다. 카프카는 주제(topic) 수준과 클러스터 수준의 권한 부여를 지원합니다. 권한 정책을 설정하여 클라이언트가 특정 주제를 구독하거나 게시할 수 있는지, 어떤 작업을 수행할 수 있는지를 제어할 수 있습니다.
  3. 데이터의 기밀성(Encryption): 카프카는 데이터 전송 과정에서의 기밀성을 제공하기 위해 SSL/TLS를 사용하는 암호화를 지원합니다. 클라이언트와 브로커 간의 통신은 암호화되어 제3자가 데이터를 엿볼 수 없도록 보호됩니다.
  4. 접근 제어(Access Control): 카프카는 클러스터 내에서의 접근 제어를 통해 보안을 강화합니다. 보안 그룹(security group)과 IP 필터링을 설정하여 특정 IP 주소나 네트워크에서의 액세스를 허용하거나 차단할 수 있습니다.
  5. 감사(Auditing): 카프카는 클라이언트의 작업과 관련된 이벤트를 감사하기 위한 감사 로그 기능을 제공합니다. 이를 통해 누가 언제 어떤 작업을 수행했는지 추적하고, 잠재적인 보안 위협에 대한 탐지 및 대응을 할 수 있습니다.

여기서는 카프카 보안에 대한 3가지 관점으로 알아보도록 하겠습니다. 크게 데이타 암호화, 확인된 클라이언트만 접근 가능하게 하는 인증, 기타 기능을 허용해주는 권한 세가지로 설정이 가능합니다.

1. 카프카 보안의 세 가지 요소

  • 암호화 : 데이타 암호화
  • 인증 : 안전이 확인된 클라이언트만 접근 가능하게 설정
  • 권한 : 권한 설정.

1) 암호화(SSL)

  • Secure Socket Layer : 표준 암호 규약
  • 클라이언트 암호화 통신을 위해 SSL 방식을 사용함.

HTTPS와 SSL 인증서 – 생활코딩

2) 인증(SASL)

  • Simple Authentication and Security Layer : 인터넷 프로토콜에서 인증과 데이터 보안을 위한 프레임워크
  • SASL 메커니즘
    • SASL/GSSAPI : 카프카 0.9 버전부터 지원. 커버로스 인증 방식.
    • SASL/PLAIN : 0.10.0 버전부터 지원. 아이디와 비밀번호 텟트 형태 사용 방법. 개발 환경에 적합.
    • SASL/SCRAM-SHA-256, SASL-SCRAM-SHA-512 : 0.10.2 버전 지원. 인증정보를 주키퍼에 저장해 사용하는 방식. 토큰 방식도 지원하므로 별도의 커버로스 서버가 구성되어 있지 않아도 됨.
    • SASL/OAUTHBEARER : 2.0 버전부터 지원. OAUTH 방식은 최근 인증에서 많이 사용. 운영 환경에서 사용하기에는 추가 개발 필요.

SASL

3) 권한(ACL)

  • Access Control List : 접근제어리스트
  • 규칙 기반의 리스트를 만들어 접근 제어하는 것

Apache Kafka

Authorization using ACLs | Confluent Documentation

2. SSL을 이용한 카프카 보안 암호화

  • 자바 기반 애플리케이션 keystore
    • 퍼블릭 키, 프라이빗 키, 인증서를 추상화해 제공함.

1) 브로커 키스토어 생성

  • 키스토어 : 서버
  • 트러스트스토어 : 클라이언트
#pf-kafka01 브로커에 접속
sudo mkdir -p /usr/local/kafka/ssl
cd /usr/local/kafka/ssl
export SSLPASS=peterpass
# 키스토어 생성
sudo keytool -keystore kafka.server.keystore.jks -alias localhost -keyalg RSA -validity 365 -genkey -storepass $SSLPASS -keypass $SSLPASS -dname "CN=pf-kafka01.sample.test" -storetype pkcs12

# 키스토어 생성 확인
ls
> kafka.server.keystore.jks

#키스토어 내용 확인, 위에 설정한 비번 입력 peterpass
keytool -list -v keystore kafka.server.keystore.jks
  • keystore : 키스토어 이름
  • alias : 별칭
  • keyalg : 키 알고리즘
  • genkey : 키 생성
  • validity : 유효 일자
  • storepass : 저장소 비밀번호
  • keypass : 식별 이름
  • dname : 식별 이름, 현재 접속한 브로커의 호스트 네임으로 설정.
  • storetype : 저장 타입

2) CA 인증서 생성

  • 자체 인증서 생성
# 자체 CA 인증서 생성
sudo openssl req -new -x509 -keyout ca-key -out ca-cert -days 356 -subj "/CN=sample.test" -nodes

# 확인
ls
# 출력
ca-cert ca-key kafka.server.keystore.jks
  • openssl 상세 옵션
    • new : 새로 생성 요청
    • x509 : 표준 인증서 번호
    • keyout : 생성할 키 파일 이름
    • out : 생성할 인증서 파일 이름
    • days : 유효 일자
    • subj : 인증서 제목
    • nodes : 프라이빗 키 파일을 암호화하지 않음.

3) 트러스트스토어 생성

  • 생성한 자세 서명된 CA 인증서를 클라이언트가 신뢰할 수 있도록 트러스트스토어에 추가
sudo keytool -keystore kafka.server.truststore.jks -alias CARoot -importcert -file ca-cert -storepass $SSLPASS -keypass #SSLPASS
  • 트러스트스토어 생성을 위한 keytool의 상세 옵션
    • keytool : 키스토어 이름
    • alias : 별칭
    • importcert : 인증서를 임포트
    • file : 인증서 파일
    • storepass : 저장소 비밀번호
    • keypass : 키 비밀번호
# 트러스트스토어 내용 확인
keytool -list -v keystore kafka.server.truststore.jks

4) 인증서 서명

  • 키스토어 인증서 추출
sudo keytool -keystore kafka.server.keystore.jks -alias localhost -certreq -file cert-file -storepass $SSLPASS -keypass $SSLPASS
ls

# 자체 서명된 CA 서명 적용
sudo openssl x509 -req -CA ca-cert -CAkey ca-key -in cert-file -out cert-signed -days 365 -CAcreateserial -passin pass:$PASSWORD

  • CA 서명을 위한 openssl의 상세 옵션
    • x509 : 표준 인증서 번호
    • req : 인증서 서명 요청
    • ca : 인증서 파일
    • cakey : 프라이빗 키 파일
    • in : 인풋 파일
    • out : 아웃풋 파일
    • days : 유효 일자
    • passin : 소스의 프라이빗 키 비밀번호
  • 키스토어에 자체 서명된 CA 인증서인 ca-cert와 서명된 cert-signed를 추가
sudo keytool -keystore kafka.server.keystore.jks -alias CARoot -importcert -file ca-cert -storepass $SSLPASS -keypass $SSLPASS

sudo keytool -keystore kafka.server.keystore.jks -alias localhost -imporcert -file cert-signed -storepass $SSLPASS -keypass $SSLPASS

# 키스토어 내용 확인
keytool -list -v -keystore kafka.server.keystore.jks
  • 수행한 작업들을 클러스터 내 다른 브로커에서도 동일하게 진행해야 함.

5) 나머지 브로커에 대한 SSL 구성

page. 300 확인.

6) 브로커 설정에 SSL 추가

sudo vi /usr/local/kafka/config/server.properties

# 수정
listeners=PLAINTEXT://0.0.0.0:9092,SSL://0.0.0.0:9093
advertised.listeners=PLAINTEXT://pf-kafka01.sample.test:9092,SSL://pf-kafka01.sample.test:9093

# 추가
ssl.truststore.location=/usr/local/kafka/ssl/kafka.server.truststore.jks
ssl.truststore.password=peterpass
ssl.keystore.location=/usr/local/kafka/ssl/kafka.server.keystore.jks
ssl.keystore.password=peterpass
ssl.key.password=peterpass
security.inter.broker.protocol=SSL
#모든 브로커 서버 재시작
sudo systemctl restart kafka-server
# 최종 확인
openssl s_client -connect peter-kafka01.foo.bar:9093 -tls1 </dev/null 2>/dev/null | grep -E 'Verify return code'

7) SSL 기반 메시지 전송

# 클라이언트용 트러스트스토어 생성
cd /usr/local/kafka/ssl/
export SSLPASS=petpass
sudo keytool -keystore kafka.client.truststore.jks -alias CARoot -importcert -file ca-cert -storepass $SSLPASS -keypass $SSLPASS

# 토픽 생성
/usr/local/kafka/bin/kafka-topics.sh --bootstrap-server peter-kafka01.foo.bar:9092 --create --topic peter-test07 --partitions 1 --replication-factor 3

  • SSL 통신이 적용된 콘솔 프로듀서를 사용하기 위한 설정파일 ssl.config
vi /home/ec2-user/ssl.config
security.protocol=SSL
ssl.truststore.location=/usr/local/kafka/ssl/kafka.client.truststore.jks
ssl.truststore.password=peterpass
  • 9093 SSl 포트 사용, ssl.config를 로드함.
# 전송
/usr/local/kafka/bin/kafka-console-producer.sh --bootstrap-server peter-kafka01.foo.bar:9093 --topic peter-test07 --producer.config /home/ec2-user/ssl.config

# 수신
/usr/local/kafka/bin/kafka-console-consumer.sh --bootstrap-server peter-kafka01.foo.bar:9093 --topic peter-test07 --from-beginning --consumer.config /home/ec2-user/ssl.config

3. 커버로스(SASL)를 이용한 카프카 보안 인증

커버로스

1) 커버로스 구성

ansible-playbook -i hosts kerberos.yml
# kerberos.yml
---
- hosts: kerberoshosts
  become: true
  connection: ssh
  roles:
    - common
    - kerberos
  • 현재 디폴트 렐름(REALM) : FOO.BAR
  • pf-zk01 서버 접속 → 프린시펄(principla) 개체 생성 → 프린시펄의 키탭(keytab) 생성해서 인증 받음.
  • kadmin.local 명령어를 이용해 커버로스에서 사용할 유저 생성
# 3명 유저 생서
sudo kadmin.local -q "add_principal -randkey [email protected]"
sudo kadmin.local -q "add_principal -randkey [email protected]"
sudo kadmin.local -q "add_principal -randkey [email protected]"

#프린시펄 생성 '서비스명/각 브로커 호스트네임'
sudo kadmin.local -q "add_principal -randkey kafka/[email protected]"
sudo kadmin.local -q "add_principal -randkey kafka/[email protected]"
sudo kadmin.local -q "add_principal -randkey kafka/[email protected]"

#키탭파일 생성 -> 비번없이 원격시스템에 인증함.
mkdir -p /home/ec2-user/keytabs/
sudo kadmin.local -q "ktadd -k /home/ec2-user/keytabs/peter01.user.keytab [email protected]"
sudo kadmin.local -q "ktadd -k /home/ec2-user/keytabs/peter02.user.keytab [email protected]"
sudo kadmin.local -q "ktadd -k /home/ec2-user/keytabs/admin.user.keytab [email protected]"
sudo kadmin.local -q "ktadd -k /home/ec2-user/keytabs/peter-kafka01.service.keytab kafka/[email protected]"
sudo kadmin.local -q "ktadd -k /home/ec2-user/keytabs/peter-kafka02.service.keytab kafka/[email protected]"
sudo kadmin.local -q "ktadd -k /home/ec2-user/keytabs/peter-kafka03.service.keytab kafka/[email protected]"

#파일소유자 ec-user 변경
sudo chown -R ec2-user.ec2-user keytabs/

2) 키탭을 이용한 인증

#키탭 파일 복사 -> 모든 브로커에 복사 진행
scp -i keypair.pem -r peter-zk01.foo.bar:~/keytabs /home/ec2-user
sudo mv keytabs /usr/local/kafka

#렐름 정보 확인
cat /etc/krb5.conf

#티켓 발급
kinit -kt /usr/local/kafka/keytabs/peter01.user.keytab peter01

#티켓 확인
klist

# kafka 서비스로 티켓을 잘 발급받는지 확인
kinit -kt /usr/local/kafka/keytabs/peter-kafka01.service.keytab kafka/peter-kafka01.foo.bar

#확인
klist

3) 브로커 커버로스 설정

  • server.properties 설정
# 커버로스 적용
sudo vi /usr/local/kafka/config/server.properties
# server.properties 파일 일부 -> 커버로스 설정
listeners=PLAINTEXT://0.0.0.0:9092,SSL://0.0.0.0:9093,SASL_PLAINTEXT://0.0.0.0:9094
advertised.listeners=PLAINTEXT://peter-kafka01.foo.bar:9092,SSL://peter-kafka01.foo.bar:9093,SASL_PLAINTEXT://peter-kafka01.foo.bar:9094

security.inter.broker.protocol=SASL_PLAINTEXT
sasl.mechanism.inter.broker.protocol=GSSAPI
sasl.enabled.mechanism=GSSAPI
sasl.kerberos.service.name=kafka
  • 커버로스 인증을 위한 jaas.conf 생성
sudo vi /usr/local/kafka/config/kafka_server_jaas.conf
KafkaServer {
    com.sun.security.auth.module.Krb5LoginModule required
    useKeyTab=true
    storeKey=true
    keyTab="/usr/local/kafka/keytabs/peter-kafka01.service.keytab"
    principal="kafka/[email protected]";
};
  • jaas.conf 파일은 모든 브로커에서 설정해야 함.
  • keyTab은 서로 다르므로 각 브로커의 호스트네임과 동일하게 설정.
  • 각 브로커 시작시 이 kafka_server_jaas.conf을 로드할 수 있도록 KAFKA_OPTS 카프카 환경 병수에 설정을 추가함.
sudo vi /usr/local/kafka/config/jmx
KAFKA_OPTS="-Djava.security.auth.login.config=/usr/local/kafka/config/kafka_server_jaas.conf"
  • 위 설정작업을 모든 브로커에 동일하게 설정
  • 브로커 재시작
# 브로커 재시작
sudo systemctl restart kafka-server

# 확인
sudo netstat -ntlp | grep 9094

4) 클라이언트 커버로스 설정

  • 클라이언트 jaas.conf 설정
# 설정
vi kafka_client_jaas.conf
# kafka_client_jaas.conf
KafkaClient {
    com.sun.security.auth.module.Krb5LoginModule required
    useTicketCache=true;
};
  • 자동 로드 설정
export KAFKA_OPTS="-Djava.security.auth.login.config=/home/ec2-user/kafka_client_jaas.conf"
  • 콘솔 프로듀서와 콘솔 컨슈머에서 사용할 파일 생성
vi kerberos.config
# 콘솔 프로듀서와 콘솔 컨슈머를 위한 kerberos.config
sasl.mechanism=GSSAPI
security.protocol=SASL_PLAINTEXT
sasl.kerberos.service.name=kafka
  • 티켓 발급
kinit -kt /usr/local/kafka/keytabs/peter01.user.keytab peter01
#토픽 생성 및 전송
/usr/local/kafka/bin/kafka-console-producer.sh --bootstrap-server peter-kafka01.foo.bar:9094 --topic peter-test08 --producer.config kerberos.config

#확인
/usr/local/kafka/bin/kafka-console-consumer.sh --bootstrap-server peter-kafka01.foo.bar:9094 --topic peter-test08 --from-beginning --consumer.config kerberos.config
# 티켓 삭제
kdestroy

#삭제 확인
klist

#메세지 가져오기 시도 -> 오류 발생 정상
/usr/local/kafka/bin/kafka-console-consumer.sh --bootstrap-server peter-kafka01.foo.bar:9094 --topic peter-test08 --from-beginning --consumer.config kerberos.config
  • 주키퍼를 커버로스와 연동하는 방법

ZooKeeper and SASL – Apache ZooKeeper – Apache Software Foundation

4. ACL을 이용한 카프카 보안 권한 설정

  • 유저별로 특정 토픽에 접근을 허용여부 설정.
  • 브로커의 설정 파일을 수정한 후 kafka-acls.sh 명령을 이용해 유저별 권한을 설정.

1) 브로커 카프카 보안 권한 설정

sudo vi /usr/local/kafka/config/server.properties
security.inter.broker.protocol=SASL_PLAINTEXT
sasl.mechanism.inter.broker.protocol=GSSAPI
sasl.enabled.mechanism=GSSAPI
sasl.kerberos.service.name=kafka
# 아래 내용 추가
authorizer.class.name=kafka.security.authorizer.AclAuthorizer
super.users=User:admin;User:kafka
  • 브로커 재시작
sudo systemctl restart kafka-server
  • 환경변수 초기화
unset KAFKA_OPTS

#토픽 생성
/usr/local/kafka/bin/kafka-topics.sh --zookeeper peter-zk01.foo.bar:2181 --create --topic peter-test09 --partitions 1 --replication-factor 1
/usr/local/kafka/bin/kafka-topics.sh --zookeeper peter-zk01.foo.bar:2181 --create --topic peter-test10 --partitions 1 --replication-factor 1

2) 유저별 권한 설정

  • 설정 예시
    • peter01 유저 : peter-test09 토픽 읽기, 쓰기 가능
    • peter02 유저 : peter-test10 토픽 읽기, 쓰기 가능
    • admin 유저 : peter-test09, peter-test10 토픽 읽기, 쓰기 가능
  • peter01 유저에 대해 ACL 규칙 생성
/usr/local/kafka/bin/kafka-acls.sh --authorizer-properties zookeeper.connect=peter-zk01.foo.bar:2181 --add --allow-principal User:peter01 --operation Read --operation Write --operation DESCRIBE --topic peter-test09
  • peter02 유저에 대해 peter-test01 토픽 권한 추가
# 추가
/usr/local/kafka/bin/kafka-acls.sh --authorizer-properties zookeeper.connect=peter-zk01.foo.bar:2181 --add --allow-principal User:peter02 --operation Read --operation Write --operation DESCRIBE --topic peter-test10

# 확인
/usr/local/kafka/bin/kafka-acls.sh --authorizer-properties zookeeper.connect=peter-zk01.foo.bar:2181 --list
  • 전송 테스트
kinit -kt /usr/local/kafka/keytabs/peter01.user.keytab peter01
export KAFKA_OPTS="-Djava.security.auth.login.config=/home/ec2-user/kafka_client_jaas.conf"
/usr/local/kafka/bin/kafka-console-producer.sh --bootstrap-server peter-kafka01.foo.bar:9094 --topic peter-test09 --producer.config kerberos.config
  • 수신 테스트
/usr/local/kafka/bin/kafka-console-consumer.sh --bootstrap-server peter-kafka01.foo.bar:9094 --topic peter-test09 --from-beginning --consumer.config kerberos.config
# 에러남.
  • ACL 규칙의 대상은 리소스 타입이 토픽이었고, 그룹 리소스 타입에 대해서는 ACL 규칙을 추가하지 않았음.
# ACL 규칙 추가
/usr/local/kafka/bin/kafka-acls.sh --authorizer-properties zookeeper.connect=peter-zk01.foo.bar:2181 --add --allow-principal User:peter01 --operation Read --group '*'

# 확인
/usr/local/kafka/bin/kafka-acls.sh --authorizer-properties zookeeper.connect=peter-zk01.foo.bar:2181 --list

# 토픽 메세지 수신
/usr/local/kafka/bin/kafka-console-consumer.sh --bootstrap-server peter-kafka01.foo.bar:9094 --topic peter-test09 --from-beginning --consumer.config kerberos.config
  • peter02 유저의 권한을 확인하기 위해 peter-test10 토픽으로 메시지 전송
# 전송
kinit -kt /usr/local/kafka/keytabs/peter02.user.keytab peter02
export KAFKA_OPTS="-Djava.security.auth.login.config=/home/ec2-user/kafka_client_jaas.conf"
/usr/local/kafka/bin/kafka-console-producer.sh --bootstrap-server peter-kafka01.foo.bar:9094 --topic peter-test10 --producer.config kerberos.config

# 전송 -> 실패 : peter02는 peter-test09 토픽에 대한 권한이 없음.
/usr/local/kafka/bin/kafka-console-producer.sh --bootstrap-server peter-kafka01.foo.bar:9094 --topic peter-test09 --producer.config kerberos.config
kinit -kt /usr/local/kafka/keytabs/admin.user.keytab admin

# 전송 : admin 유저
/usr/local/kafka/bin/kafka-console-producer.sh --bootstrap-server peter-kafka01.foo.bar:9094 --topic peter-test09 --producer.config kerberos.config
/usr/local/kafka/bin/kafka-console-producer.sh --bootstrap-server peter-kafka01.foo.bar:9094 --topic peter-test10 --producer.config kerberos.config
/usr/local/kafka/bin/kafka-console-consumer.sh --bootstrap-server peter-kafka01.foo.bar:9094 --topic peter-test09 --from-beginning --consumer.config kerberos.config
/usr/local/kafka/bin/kafka-console-consumer.sh --bootstrap-server peter-kafka01.foo.bar:9094 --topic peter-test10 --from-beginning --consumer.config kerberos.config
  • admin 유저는 별도의 ACL을 설정하지 않아도 토픽 전송, 수신 가능함.

SSL 보안 카프카 클러스터로 마이크레이션 작업 순서

  1. 인증서 준비 및 적용
  2. 브로커의 server.properties에 SSL을 위한 9093 listeners, advertised.linsteners 추가
  3. 클라이언트와 브로커 간 SSL 통신 테스트
  4. 모든 클라이언트에서 브로커 접속 포트를 9092에서 9093으로 변경
  5. 브로커의 server.properties에 security.inter.broker.protocol=SSL 추가
  6. 브로커의 server.properties에 9092 listeners, advertised.listeners 삭제

이상으로 카프카 보안 활용법에 대해 알아봤습니다.

카프카 도입 사례에 대한 설명이 필요하신 분은 여기 링크를 참고바랍니다.

좀더 자세한 설명을 원하시는 분은 실전 카프카 개발부터 운영까지 도서를 참고바립니다.


참고 : 실전 카프카 개발부터 운영까지

아래는 카프카 관련 국내 도서입니다.

실전 카프카 개발부터 운영까지:데이터플랫폼의 중추 아파치 카프카의 내부동작과 개발 운영 보안의 모든것, 책만 아파치 카프카의 모든 것 세트 : 카프카 데이터 플랫폼의 최강자+실전 카프카 개발부터 운영까지, 책만 (서점추천) 헤드 퍼스트 디자인 패턴 + 실전 카프카 개발부터 운영까지 (전2권) (서점추천) 24단계 실습으로 정복하는 쿠버네티스 + 실전 카프카 개발부터 운영까지 (전2권), 위키북스 (서점추천) 데이터 파이프라인 핵심 가이드 + 실전 카프카 개발부터 운영까지 (전2권) (서점추천) 몽고DB 완벽 가이드 + 실전 카프카 개발부터 운영까지 (전2권) (서점추천) 클린 코드의 기술 + 실전 카프카 개발부터 운영까지 (전2권), 영진닷컴 (서점추천) 카프카 핵심 가이드 + 디지털 플랫폼 전략 수립을 위한 쿠버네티스 실전 활용서 (전2권), 제이펍 아파치 카프카 애플리케이션 프로그래밍 with 자바:카프카의 개념부터 스트림즈 커넥트 스프링 카프카까지, 비제이퍼블릭 카프카 핵심 가이드 개정증보판, 제이펍 실전 아파치 카프카:애플리케이션 개발부터 파이프라인 사물인터넷 데이터 허브 구축까지, 한빛미디어 카프카 데이터 플랫폼의 최강자:실시간 비동기 스트리밍 솔루션 Kafka의 기본부터 확장 응용까지, 책만 카프카 스트림즈와 ksqlDB 정복:실시간 데이터 처리, 에이콘출판 카프카 핵심가이드:실시간 데이터와 스트림 프로세싱, 제이펍

“이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.”

Back to top