AWS 기술 블로그

Amazon MSK에서 SASL/SCRAM 인증으로 접근제어 하기

배경

Amazon MSK(Managed Streaming for Apache Kafka)는 Apache Kafka를 완전 관리형으로 제공하는 서비스로, 데이터 스트리밍 및 처리에 사용됩니다. Amazon MSK는 클러스터 유형에 따라 클러스터의 확장, 구성 및 최적화에 유연성을 제공하는 Amazon MSK 프로비전과, 용량 관리 없이 자동 확장 및 운영이 가능하도록 설계된 서비스인 MSK Serverless로 구분됩니다. Amazon MSK가 제공하는 주요 기능으로 Apache Kafka 클러스터와 외부 시스템 간의 데이터 스트리밍을 쉽게 관리할 수 있도록 지원하는 완전 관리형 Kafka Connect 서비스인 MSK Connect와 비용 효율적인 장기 데이터 저장을 제공하는 계층형 스토리지, 데이터를 실시간으로 수집하고 처리하는 Amazon Data Firehose 연계 등이 있습니다. 이러한 기능들은 Amazon MSK를 데이터 스트리밍을 위한 강력하고 유연한 플랫폼으로 만들어 줍니다.

AWS에서 보안이 가장 중요한 이유는 고객의 데이터와 애플리케이션을 안전하게 보호함으로써 신뢰를 유지하고, 비즈니스 혁신을 지원하기 위해서입니다. AWS는 보안을 최우선 과제로 삼아 세계에서 가장 안전한 클라우드 인프라를 제공하며, 이를 통해 고객은 빠르고 안전하게 비즈니스를 운영할 수 있습니다. Amazon MSK 역시 데이터 암호화, 접근제어(인증, 권한) 부여, 네트워크 보안, 로깅 및 감사 기능을 제공하여 안전한 데이터 스트리밍 환경을 제공할 수 있도록 하고 있습니다.

이 블로그에서는 Apache Kafka에서 널리 사용되는 SASL/SCRAM 메커니즘을 통해 인증을 수행하고, ACL(Access Control List)을 사용하여 특정 사용자가 Kafka 리소스에서 수행할 수 있는 작업을 허용하거나 거부하는 방법을 설명합니다.

접근 제어 (Access Control)

Amazon MSK는 다음과 같은 네 가지 접근 제어 방법을 제공합니다:

  1. Unauthenticated Access: 별도의 인증 없이 모든 클라이언트가 클러스터에 접근할 수 있는 방법으로, 주로 내부 네트워크에서만 사용됩니다.
  2. IAM Role-Based Authentication: AWS Identity and Access Management(IAM)를 사용하여 MSK 클러스터에 대한 인증과 권한 부여를 처리합니다.
  3. SASL/SCRAM Authentication: 사용자 이름과 비밀번호를 사용하여 인증을 제공하며, AWS Secrets Manager를 통해 자격 증명을 안전하게 저장하고 관리합니다.
  4. TLS Client Authentication through AWS Certificate Manager (ACM): TLS를 사용하여 클라이언트와 MSK 브로커 간의 보안 연결을 설정하며, AWS Private CA를 통한 인증서를 필요로 합니다.

Amazon MSK에서 제공하는 인증/권한 메커니즘으로는 IAM Role-Based Authentication과 SASL/SCRAM Authentication를 제공합니다. IAM Role-Based Authentication 사용 방법을 알고 싶으시면 “IAM을 활용하여 Amazon MSK 주제 접근 제어하기“ 블로그를 참조하세요.

Apache Kafka에서 제공하는 인증 메커니즘으로는 SASL/SCRAM 외에도 SASL/PLAIN, SASL/GSSAPI, SASL/OAUTHBEARER 등이 있습니다.

참고로 SASL/SCRAM(Salted Challenge Response Authentication Mechanism)는 사용자 이름과 비밀번호를 사용하여 인증을 제공하는 메커니즘으로, 암호화된 챌린지-응답 방식을 통해 보안을 강화합니다. SCRAM은 비밀번호를 해시하고 솔트값을 추가하여 저장 및 전송 중 보안을 유지하며, 네트워크에서 비밀번호 스니핑 및 사전 공격을 방지합니다

SASL/SCRAM 인증을 사용한 클라이언트에게 Kafka 리소스(예: 주제, 소비자 그룹, 클러스터)에 대하여 권한을 부여하기 위해서는 Apache Kafka의 ACL(Access Control List)를 사용해야 합니다.

Apache Kafka에서 권한을 부여할 수 있는 리소스들은 다음과 같습니다.

  1. Cluster (클러스터): 클러스터 내의 레플리카 추가, 주제 생성, ACL 관리 등의 작업을 제어합니다.
  2. Topic (주제): 주제에 대한 메시지 생산 및 소비, 주제 설정 변경 등의 작업을 제어합니다.
  3. Group (소비자 그룹): 소비자 그룹 데이터의 읽기 및 쓰기, 오프셋 관리 등의 작업을 제어합니다.
  4. Transactional ID: 트랜잭션을 시작하고 커밋할 수 있는 권한을 제어합니다.

각 리소스별로 허용 또는 거부할 수 있는 권한은 다음과 같습니다.

  1. Cluster: All, Create(주제나 파티션을 생성), Alter, Describe, ClusterAction(클러스터 수준의 작업을 수행)
  2. Topic: All, Read, Write, Create, Delete, Alter, Describe(주제의 메타데이터 조회), AlterConfigs, DescribeConfigs(주제의 설정 조회)
  3. Group: All, Read(그룹의 오프셋을 읽기), Delete
  4. Transactional ID: All, Write, Describe

자세한 내용은 Apache Kafka 문서Amazon MSK 개발자 가이드를 참조하세요.

Amazon MSK에서 SASL/SCRAM 인증과 권한 설정하는 방법을 알아보도록 하겠습니다.

SASL/SCRAM 인증(Authentication) – 클러스터 설정

A. AWS Secrets Manager를 이용해서 SASL/SCRAM 인증에 사용할 보안 암호(secret)를 생성합니다. 보안 암호(secret)는 “AmazonMSK_”로 시작해야 하고, 보안 암호 키로 “username”과 “password”를 포함해야 합니다. AWS Secrets Manager의 교체(Rotation) 기능을 이용하여 보안을 강화할 수 있습니다.

AWS Secrets Manager 콘솔에 접속하여 “Store a new secret” 버튼을 클릭하고 다음과 같이 입력하여 보안 암호를 생성합니다.

  • Secret type: “Other type of secret”
  • Key/value pairs
  • Encryption key: AWS 관리형 키(“aws/secretsmanager”)가 아닌 미리 생성한 고객 관리 키(Customer managed key)를 선택합니다. 고객 관리 키가 없는 경우 “Add new key” 버튼을 클릭하고 AWS Key Management Service에서 새 키를 생성합니다.
  • Secret Name: “AmazonMSK_lab-blog/alice”

다음은 ‘alice’ 사용자를 위해 생성한 보안 암호(secret)입니다.


B. MSK 클러스터에서 SASL/SCRAM 인증시 사용할 보안 암호들을 등록해야 합니다.

Amazon MSK 콘솔에 접속하여 MSK 클러스터의 Properties 탭에서 “Associate secrets” 버튼을 클릭합니다.

“Choose secrets” 버튼을 클릭하면 AWS Secrets Manager에서 생성한 보안 암호들이 표시됩니다. 연결할 보안 암호를 체크하고 “Choose secrets” 버튼을 클릭하면 MSK 클러스터에 연결됩니다.

SASL/SCRAM 인증(Authentication) – 클라이언트 설정

Apache Kafka 클라이언트는 MSK 클러스터에 인증을 받기 위해서는 다음과 같은 클라이언트 속성 파일을 생성하고 사용해야 합니다.

# SASL/SCRAM 인증 속성 파일
$ echo -n "security.protocol=SASL_SSL
sasl.mechanism=SCRAM-SHA-512
sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required \\
  username="alice" \\
  password="alice-secret";
" > ~/client.properties_alice 
  • security.protocol: 클라이언트와 Kafka 브로커 간의 통신에 사용되는 프로토콜을 지정합니다. SASL/SCRAM 인증을 사용할 때는 “SASL_SSL”를 설정합니다.
  • sasl.mechanism: SASL 인증에 사용할 메커니즘을 지정합니다. SASL/SCRAM 인증을 위해 SCRAM-SHA-256 또는 SCRAM-SHA-512를 설정할 수 있으며, Amazon MSK는 SCRAM-SHA-512만 지원합니다.
  • sasl.jaas.config: JAAS(Java Authentication and Authorization Service) 설정을 통해 클라이언트의 인증 정보를 구성합니다. 이 설정에는 ScramLoginModule을 사용하여 사용자 이름과 비밀번호를 지정하는 구문을 포함합니다.

권한 (Authorization) 설정

권한 설정은 Apache Kafka 바이너리에 포함된 “kafka-acls.sh” 명령어를 사용하여 권한을 설정 할 수 있습니다.

다음는 ‘alice’ 사용자에게 주제를 생성하거나 삭제할 수 있는 권한을 부여하는 예제입니다.

$ cn=alice
$ {kafka_binary}/bin/kafka-acls.sh --bootstrap-server $BootStrap \
   --add \
   --allow-principal "User:${cn}" \
   --topic=* \
   --operation Create --operation Delete \
   --command-config ~/client.properties_alice

데모

단계1: MSK 클러스터 생성

Amazon MSK 콘솔에 접속하여 “Create cluster” 버튼을 클릭 후 다음과 같이 입력하여 MSK 클러스터를 생성합니다.

  • Cluster name: “lab-blog”
  • Cluster type: “Provisioned”
  • Brokers / Number of zones: 2
  • Networking:
    • MSK 클러스터가 생성될 VPC와 Private subnet이 사전에 구성되어 있어야 합니다.
  • Security settings / Access control methods: “SASL/SCRAM authentication” 선택

MSK 클러스터가 생성이 완료되면 상태가 Active로 표시됩니다.

단계2: Apache Kafka client 환경 구성

본 볼로그에서는 CloudShell를 이용하여 Apache Kafka 바이너리를 설치하고 테스트를 하고자 합니다. Kafka 클라이언트는 MSK 클러스터가 구성된 같은 VPC내에 위치해야 하기 때문에 CloudShell에서 VPC 환경을 생성해야 합니다. 참고로 서울 리전에서는 CloudShell VPC 환경 생성 기능을 지원하지 않으므로, MSK 클러스터가 생성된 VPC내에 EC2를 생성해서 이용해야 합니다. CloudShell에서 “+” 아이콘 선택 후 “Create VPC environment (max 2)”를 선택하고 다음과 같이 입력하여 CloudShell VPC 환경을 생성합니다.

  • Name: “MSK”
  • Virtual private cloud (VPC): MSK 클러스터가 구성된 VPC 선택
  • Subnet: Private subnet 선택 (Public subnet에서는 인터넷 연결할 수 없음)
  • Security group: default

생성한 CloudShell VPC 환경에 접속합니다. Apache Kafka 바이너리와 Amazon Corretto(OpenJDK)을 설치합니다.

$ wget https://downloads.apache.org/kafka/3.8.0/kafka_2.13-3.8.0.tgz && \
  tar xf kafka_2.13-3.8.0.tgz && \
  cd kafka_2.13-3.8.0/bin
$ sudo yum install java-22-amazon-corretto.x86_64 -y

단계3: SASL/SCRAM 인증 구성

AWS Secrets Manager 콘솔에 접속하여 데모에서 사용할 3개의 보안 암호(secret)를 생성하고, 단계1에서 생성한 MSK 클러스터에 보안 암호를 연결합니다.

단계4: 권한 설정 – 관리자

Apache Kafka 명령어를 실행하기 위해서는 MSK 클러스터의 SASL/SCRAM 엔드포인트가 필요합니다. 엔드포인트는 Amazon MSK 콘솔에서 Clusters > {lab-blog} > View client information을 선택하여 확인할 수 있습니다. Apache Kafka 명령어에서 사용할 수 있도록 SASL/SCRAM 엔드포인트를 환경변수에 설정합니다.

BOOTSTRAP=b-1.labblog.vp2i7y.c3.kafka.us-east-1.amazonaws.com:9096,b-2.labblog.vp2i7y.c3.kafka.us-east-1.amazonaws.com:9096

AWS CLI 명령어를 사용해서 MSK 클러스터의 SASL/SCRAM 엔드포인트를 얻고 환경변수에 설정할 수도 있습니다.

$ CLUSTER_ARN=$(aws kafka list-clusters | \
                jq -r '.ClusterInfoList[] | select(.ClusterName =="lab-blog") |
                      .ClusterArn')
$ BOOTSTRAP=$(aws kafka get-bootstrap-brokers --cluster-arn $CLUSTER_ARN | \
              jq -r '.BootstrapBrokerStringSaslScram')

Apache Kafka 명령어(kafka-acls.sh)로 AWS Secrets Manager에서 생성한 ‘admin’ 사용자에게 Cluster 리소스에 대하여 모든 권한을 부여하고, 설정된 ACL를 조회합니다.

$ echo -n "security.protocol=SASL_SSL
sasl.mechanism=SCRAM-SHA-512
sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required \\
  username="admin" \\
  password="admin1234";
" > ~/client.properties_admin
$
$ ./kafka-acls.sh --bootstrap-server $BOOTSTRAP \
  --add --allow-principal "User:admin" \
  --cluster --operation All \
  --command-config ~/client.properties_admin
$ ./kafka-acls.sh --bootstrap-server $BOOTSTRAP --list \
  --command-config ~/client.properties_admin
Current ACLs for resource `ResourcePattern(resourceType=CLUSTER, name=kafka-cluster, patternType=LITERAL)`: 
        (principal=User:admin, host=*, operation=ALL, permissionType=ALLOW)   

단계5: MSK 클러스터 설정 변경

Apache Kafka의 설정 옵션인 ‘allow.everyone.if.no.acl.found’는 리소스에 대한 명시적인 ACL이 없을 경우 모든 사용자에게 접근을 허용할지를 결정합니다. 이 옵션이 true로 설정되면, 특정 리소스에 ACL이 설정되지 않았을 때 모든 사용자가 해당 리소스에 접근할 수 있습니다. 기본적으로 Amazon MSK에서는 이 옵션이 true로 설정되어 있습니다. 그러나 이 옵션을 프로덕션 환경에서 사용하는 것은 권장되지 않습니다. ACL이 없는 경우 모든 사용자에게 접근을 허용하면 보안 위험이 증가할 수 있기 때문입니다. 따라서, ACL을 통해 명시적으로 접근 권한을 설정하고, 이 옵션을 false로 설정하여 보안을 강화하는 것이 좋습니다.

MSK 클러스터에 ‘allow.everyone.if.no.acl.found=false’를 설정하기에 앞서 ‘admin’ 사용자에게 Cluster 리소스에 대해 모든 권한을 부여하였습니다. Amazon MSK 콘솔에서 Cluster configuration > Create configuration을 선택후 다음과 같이 입력하여 구성 파일을 생성합니다.

  • Configuration name: “lab-blog-conf”
  • Code:
    • allow.everyone.if.no.acl.found=false 추가

Amazon MSK 콘솔에서 MSK Clusters > clusters > {lab-blog} > Actions > Edit cluster configuration을 선택 후 “lab-blog-conf” 을 반영합니다. 이 작업은 MSK 클러스터내에 반영하는데 브로커 수에 따라 영향을 받으면 10분 이상 소요 됩니다.

단계6: 권한 설정 – 사용자

‘admin’ 사용자가 ‘alice’ 사용자에게 ‘ExamTopics’ 주제를 생성, 삭제, 읽기, 쓰기 권한을 부여하고, ‘yoosung’ 사용자에게 ‘ExamTopics’ 주제를 읽을수 있는 권한을 부여합니다.

$ # ACL for alice
$ ./kafka-acls.sh --bootstrap-server $BOOTSTRAP \
  --add --allow-principal "User:alice" \
  --topic=* --operation All \
  --command-config ~/client.properties_admin
$ ./kafka-acls.sh --bootstrap-server $BOOTSTRAP \
  --add --allow-principal "User:alice" \
  --group=* --operation All \
  --command-config ~/client.properties_admin
$
$ # ACL for yoosung
$ ./kafka-acls.sh --bootstrap-server $BOOTSTRAP \
  --add --allow-principal "User:yoosung" \
  --topic=ExamTopic --operation Read --operation Describe \
  --command-config ~/client.properties_admin
$ ./kafka-acls.sh --bootstrap-server $BOOTSTRAP \
  --add --allow-principal "User:yoosung" \
  --group=* --operation All \
  --command-config ~/client.properties_admin

‘admin’ 사용자가 Apache Kafka에 적용된 ACL를 조회합니다.

$ ./kafka-acls.sh --bootstrap-server $BOOTSTRAP --list \
  --command-config ~/client.properties_admin
Current ACLs for resource `ResourcePattern(resourceType=TOPIC, name=ExamTopic, patternType=LITERAL)`: 
        (principal=User:yoosung, host=*, operation=DESCRIBE, permissionType=ALLOW)
        (principal=User:yoosung, host=*, operation=READ, permissionType=ALLOW) 

Current ACLs for resource `ResourcePattern(resourceType=GROUP, name=*, patternType=LITERAL)`: 
        (principal=User:alice, host=*, operation=ALL, permissionType=ALLOW)
        (principal=User:yoosung, host=*, operation=ALL, permissionType=ALLOW) 

Current ACLs for resource `ResourcePattern(resourceType=CLUSTER, name=kafka-cluster, patternType=LITERAL)`: 
        (principal=User:admin, host=*, operation=ALL, permissionType=ALLOW) 

Current ACLs for resource `ResourcePattern(resourceType=TOPIC, name=*, patternType=LITERAL)`: 
        (principal=User:alice, host=*, operation=ALL, permissionType=ALLOW) 

단계7: 테스트

‘alice’와 ‘yoosung’ 사용자의 권한은 상이합니다. 각 사용자에게 리소스에 부여된 권한이 있을 때와 권한이 없는 없을 때를 테스트 해 보겠습니다.

‘alice’ 사용자가 주제 ExamTopic을 생성합니다.

$ # SASL/SCRAM 인증 속성 파일
$ echo -n "security.protocol=SASL_SSL
sasl.mechanism=SCRAM-SHA-512
sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required \\
  username="alice" \\
  password="alic1234";
" > ~/client.properties_alice
$
$ ./kafka-topics.sh --create --bootstrap-server $BOOTSTRAP \
   --topic ExamTopic --replication-factor 2 --partitions 1 \
   --command-config ~/client.properties_alice

‘alice’ 사용자가 ExamTopic 주제에 메시지를 생성합니다.

$ ./kafka-console-producer.sh --bootstrap-server $BOOTSTRAP \
  --topic ExamTopic \
  --producer.config ~/client.properties_alice
> Hi yoosung

‘yoosung’ 사용자가 ExamTopic 주제를 소비합니다.

$ echo -n "security.protocol=SASL_SSL
sasl.mechanism=SCRAM-SHA-512
sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required \\
  username="yoosung" \\
  password="yoos1234";
" > ~/client.properties_yoosung
$
$ ./kafka-console-consumer.sh --bootstrap-server $BOOTSTRAP \
   --topic ExamTopic --from-beginning  \
   --consumer.config ~/client.properties_yoosung
Hi yoosung  

yoosung’ 사용자가 ExamTopic2 주제를 생성하려고 했지만, 권한이 없기 때문에 실패하였습니다.

$ ./kafka-topics.sh --bootstrap-server $BOOTSTRAP \
   --create --topic ExamTopic2 --replication-factor 2 --partitions 1 \
   --command-config ~/client.properties_yoosung
Error while executing topic command : Authorization failed.
[2024-08-31 07:22:38,527] ERROR org.apache.kafka.common.errors.TopicAuthorizationException: Authorization failed.
 (org.apache.kafka.tools.TopicCommand)

결론

Amazon MSK(Managed Streaming for Apache Kafka)의 인증 및 접근 제어 방법에 대해 알아보았습니다. MSK는 IAM Role-Based Authentication과 SASL/SCRAM Authentication을 지원하여 클러스터에 대한 안전한 접근을 제공합니다. SASL/SCRAM 인증은 사용자 이름과 비밀번호를 사용하며, AWS Secrets Manager를 통해 자격 증명을 안전하게 관리할 수 있습니다. 또한, Apache Kafka의 ACL(Access Control List)을 사용하여 특정 사용자에게 Kafka 리소스에 대한 권한을 부여하거나 제한하는 방법을 설명합니다. 이러한 보안 설정은 데이터 스트리밍 환경에서의 안전성과 효율성을 높이는 데 기여합니다.

YooSung Jeon

YooSung Jeon

전유성 솔루션즈 아키텍트는 통신/공공 산업군에서 데이터 분석과 다양한 오픈소스 활용 경험을 바탕으로 DNB(Digital Native Business) 고객을 대상으로 고객의 비즈니스 성과를 달성하도록 최적의 아키텍처를 구성하는 역할을 수행하고 있습니다.