SSL 설정

SSL 설정 (SSL Setup)

이 문서는 Flink 프로세스 간 및 외부와의 네트워크 통신을 위해 TLS/SSL 인증과 암호화를 활성화하는 방법을 설명합니다. 참고: TLS/SSL 인증은 기본적으로 활성화되어 있지 않습니다.

출처: 문서

본문

이 페이지는 Flink 프로세스 간 및 Flink 프로세스와의 네트워크 통신을 위해 TLS/SSL 인증과 암호화를 활성화하는 방법을 제공합니다. 참고: TLS/SSL 인증은 기본적으로 활성화되어 있지 않습니다.

내부 및 외부 연결 (Internal and External Connectivity)

인증과 암호화로 머신 프로세스 간 네트워크 연결을 보호할 때 Apache Flink는 내부(internal)외부(external) 연결을 구분합니다. 내부 연결(Internal Connectivity) 은 Flink 프로세스 사이에 만들어진 모든 연결을 말합니다. 이 연결들은 Flink 사용자 지정 프로토콜을 실행합니다. 사용자는 내부 연결 엔드포인트에 직접 연결하지 않습니다. 외부 / REST 연결(External / REST Connectivity) 엔드포인트는 외부에서 Flink 프로세스로 만들어진 모든 연결을 말합니다. 여기에는 웹 UI와 실행 중인 Flink 작업/애플리케이션을 시작·제어하는 REST 명령, 그리고 JobManager / Dispatcher와의 Flink CLI 통신이 포함됩니다.

더 큰 유연성을 위해 내부 및 외부 연결에 대한 보안은 별도로 활성화 및 구성할 수 있습니다.

내부 연결 (Internal Connectivity)

내부 연결은 다음을 포함합니다:

  • 제어 메시지: JobManager / TaskManager / Dispatcher / ResourceManager 간 RPC
  • 데이터 플레인: 셔플, 브로드캐스트, 재분배 등 중 TaskManager 간 데이터 교환 연결
  • Blob Service(라이브러리 및 기타 아티팩트 배포)

모든 내부 연결은 SSL 인증 및 암호화됩니다. 연결은 상호 인증(mTLS)을 사용하며, 이는 각 연결의 서버와 클라이언트 양쪽이 서로에게 인증서를 제시해야 한다는 뜻입니다. 전용 CA가 내부 인증서만 전용으로 서명하는 데 사용되면 이 인증서는 효과적으로 공유 비밀(shared secret)로 동작합니다. 내부 통신용 인증서는 다른 주체가 Flink와 상호작용하는 데 필요하지 않으며, 컨테이너 이미지에 추가하거나 YARN 배포에 첨부할 수 있습니다.

  • 이 구성을 실현하는 가장 쉬운 방법은 Flink 배포를 위한 전용 공개/개인 키 쌍과 자체 서명(self-signed) 인증서를 생성하는 것입니다. 키스트어와 트러스트스토어는 동일하며 해당 키 쌍/인증서만 포함합니다. 예시는 아래에 있습니다.

  • 운영자가 기업 전역 내부 CA를 사용하도록 제한된 환경(자체 서명 인증서를 생성할 수 없는)에서는 여전히 Flink 배포를 위한 전용 키 쌍/인증서를 만들되 해당 CA가 서명하도록 권장합니다. 그러나 TrustStore에는 SSL 핸드셰이크 중 배포 인증서를 수락하기 위해 CA의 공개 인증서도 포함되어야 합니다(JDK TrustStore 구현 요구사항).

    참고: 그 때문에 배포 인증서가 자체 서명이 아닐 때, 해당 인증서를 유일하게 신뢰되는 인증서로 고정(pin)하고 TrustStore가 해당 CA가 서명한 모든 인증서를 신뢰하지 않도록, 배포 인증서의 지문(security.ssl.internal.cert.fingerprint)을 지정하는 것이 중요합니다.

참고: 내부 연결이 공유 인증서로 상호 인증되므로 Flink는 호스트 이름 검증을 건너뛸 수 있습니다. 이는 컨테이너 기반 설정을 더 쉽게 만듭니다.

외부 / REST 연결 (External / REST Connectivity)

모든 외부 연결은 HTTP/REST 엔드포인트로 노출되며, 예를 들어 웹 UI와 CLI가 사용합니다:

  • Dispatcher와의 통신 (작업 제출, 세션 클러스터)
  • JobMaster와의 통신 (실행 중인 작업/애플리케이션 검사 및 수정)

REST 엔드포인트는 SSL 연결을 요구하도록 구성할 수 있습니다. 그러나 서버는 기본적으로 모든 클라이언트의 연결을 수락하므로 REST 엔드포인트는 클라이언트를 인증하지 않습니다.

REST 엔드포인트에 대한 연결 인증이 필요하다면 구성으로 단순한 상호 인증을 활성화할 수 있지만, "사이드카 프록시(side car proxy)"를 배포하는 것을 권장합니다: REST 엔드포인트를 루프백 인터페이스(Kubernetes에서는 pod-로컬 인터페이스)에 바인딩하고, 인증 후 요청을 Flink로 전달하는 REST 프록시를 시작하세요. Flink 사용자들이 배포한 프록시 예시는 Envoy Proxy 또는 NGINX with MOD_AUTH입니다.

인증을 프록시에 위임하는 근거는 그러한 프록시가 다양한 인증 옵션을 제공하여 기존 인프라에 더 잘 통합되기 때문입니다.

SSL 구성 (Configuring SSL)

SSL은 내부외부 연결에 대해 별도로 활성화할 수 있습니다:

  • security.ssl.internal.enabled: 모든 내부 연결에 SSL을 활성화.
  • security.ssl.rest.enabled: REST / 외부 연결에 SSL을 활성화.

참고: 역호환성을 위해 security.ssl.enabled 옵션은 여전히 존재하며 내부 및 REST 엔드포인트 모두에 SSL을 활성화합니다.

내부 연결의 경우 서로 다른 연결 유형에 대해 보안을 별도로 비활성화할 수 있습니다. security.ssl.internal.enabledtrue로 설정되면 다음 파라미터를 false로 설정하여 해당 특정 연결 유형에 대해 SSL을 비활성화할 수 있습니다:

  • taskmanager.data.ssl.enabled: TaskManager 간 데이터 통신
  • blob.service.ssl.enabled: JobManager에서 TaskManager로의 BLOB 전송
  • pekko.ssl.enabled: JobManager / TaskManager / ResourceManager 간 Pekko 기반 RPC 연결

키스트어와 트러스트스토어 (Keystores and Truststores)

SSL 구성은 키스트어(keystore)트러스트스토어(truststore) 를 구성해야 합니다. keystore는 공개 인증서(공개 키)와 개인 키를 포함하고, truststore는 신뢰되는 인증서 또는 신뢰되는 인증 기관을 포함합니다. 두 스토어는 truststore가 keystore의 인증서를 신뢰하도록 설정되어야 합니다.

내부 연결 (Internal Connectivity)

내부 통신이 서버와 클라이언트 측 사이에서 상호 인증되므로 keystore와 truststore는 일반적으로 공유 비밀로 작동하는 전용 인증서를 가리킵니다. 이러한 설정에서 인증서는 와일드카드 호스트 이름이나 주소를 사용할 수 있습니다. 자체 서명 인증서를 사용할 때는 같은 파일을 keystore와 truststore로 사용하는 것도 가능합니다.

security.ssl.internal.keystore: /path/to/file.keystore
security.ssl.internal.keystore-password: keystore_password
security.ssl.internal.key-password: key_password
security.ssl.internal.truststore: /path/to/file.truststore
security.ssl.internal.truststore-password: truststore_password

자체 서명이 아닌 CA가 서명한 인증서를 사용할 때는 연결을 수립할 때 특정 인증서만 신뢰되도록 인증서 핀닝(certificate pinning)을 사용해야 합니다.

security.ssl.internal.cert.fingerprint: 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
REST 엔드포인트 (외부 연결)

REST 엔드포인트의 경우 기본적으로 keystore는 서버 엔드포인트가 사용하고, truststore는 REST 클라이언트(CLI 클라이언트 포함)가 서버의 인증서를 수락하는 데 사용합니다. REST keystore가 자체 서명 인증서를 가진 경우 truststore는 그 인증서를 직접 신뢰해야 합니다. REST 엔드포인트가 적절한 인증 계층을 통해 서명된 인증서를 사용한다면 해당 계층의 루트가 트러스트스토어에 있어야 합니다.

상호 인증이 활성화되면 내부 연결과 마찬가지로 keystore와 truststore가 서버 엔드포인트와 REST 클라이언트 모두에 사용됩니다.

security.ssl.rest.keystore: /path/to/file.keystore
security.ssl.rest.keystore-password: keystore_password
security.ssl.rest.key-password: key_password
security.ssl.rest.truststore: /path/to/file.truststore
security.ssl.rest.truststore-password: truststore_password
security.ssl.rest.authentication-enabled: false

암호화 스위트 (Cipher suites)

강력한 보안을 위해 현대적이고 견고한 암호화 스위트를 사용하는 것이 중요합니다. 이전 RFC 7525를 대체하는 IETF RFC 9325는 TLS의 안전한 사용에 대한 현재 권장 사항을 제공합니다.

진화하는 보안 표준에 대응하고 현대 Java 버전과의 호환성을 보장하기 위해 Flink는 기본 암호화 스위트를 갱신했습니다. 최근 JDK 업데이트(11.0.30+, 17.0.18+ 등의 버전에 영향)는 완전 순방향 비밀성(forward secrecy)이 없는 이전 TLS_RSA_* 암호화 스위트를 비활성화했습니다.

secure-by-default JDK 버전을 지원하고 모범 사례에 맞추기 위해 security.ssl.algorithms의 Flink 기본값은 이제:

TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384

입니다. 이 기본값은 강력한 보안과 넓은 호환성을 제공합니다. 환경 요구사항이 다르다면 security.ssl.algorithms 구성 옵션으로 암호화 스위트를 사용자 지정할 수 있습니다. 이 암호화 스위트가 설정에서 지원되지 않으면 Flink 프로세스가 서로 연결할 수 없게 되는 것을 볼 수 있습니다.

SSL 옵션 전체 목록 (Complete List of SSL Options)

{{< generated/security_configuration >}}

키스트어와 트러스트스토어 생성 및 배포 (Creating and Deploying Keystores and Truststores)

키, 인증서, 키스트어 및 트러스트스토어는 keytool 유틸리티로 생성할 수 있습니다. Flink 클러스터의 각 노드에서 접근 가능한 적절한 Java Keystore와 Truststore가 필요합니다.

  • standalone 설정의 경우 각 노드에 파일을 복사하거나 공유 마운트 디렉터리에 추가하는 것을 의미합니다.
  • 컨테이너 기반 설정의 경우 키스트어와 트러스트스토어 파일을 컨테이너 이미지에 추가합니다.
  • Yarn 설정의 경우 클러스터 배포 단계에서 키스트어와 트러스트스토어 파일을 자동으로 배포할 수 있습니다.

외부에 노출되는 REST 엔드포인트의 경우 인증서의 공통 이름(common name) 또는 주체 대체 이름(subject alternative names)이 노드의 호스트 이름과 IP 주소와 일치해야 합니다.

예제 SSL 설정 (Standalone 및 Kubernetes)

내부 연결 (Internal Connectivity)

다음 keytool 명령을 실행하여 키스트어에 키 쌍을 생성합니다:

$ keytool -genkeypair \
  -alias flink.internal \
  -keystore internal.keystore \
  -dname "CN=flink.internal" \
  -storepass internal_store_password \
  -keyalg RSA \
  -keysize 4096 \
  -storetype PKCS12

키스트어의 단일 키/인증서는 서버와 클라이언트 엔드포인트가 같은 방식으로 사용합니다(상호 인증). 키 쌍은 내부 보안의 공유 비밀로 작동하며, 이를 keystore와 truststore로 직접 사용할 수 있습니다.

security.ssl.internal.enabled: true
security.ssl.internal.keystore: /path/to/flink/conf/internal.keystore
security.ssl.internal.truststore: /path/to/flink/conf/internal.keystore
security.ssl.internal.keystore-password: internal_store_password
security.ssl.internal.truststore-password: internal_store_password
security.ssl.internal.key-password: internal_store_password

REST 엔드포인트

REST 엔드포인트는 Flink에 속하지 않은 도구(예: REST API에 대한 curl 요청)를 포함한 외부 프로세스의 연결을 받을 수 있습니다. CA 계층을 통해 서명된 적절한 인증서를 설정하는 것이 REST 엔드포인트에 적합할 수 있습니다.

그러나 위에서 언급했듯이 REST 엔드포인트는 클라이언트를 인증하지 않으므로 일반적으로 어쨌든 프록시로 보호해야 합니다.

REST 엔드포인트 (단순 자체 서명 인증서)

이 예시는 단순한 keystore / truststore 쌍을 생성하는 방법을 보여줍니다. truststore는 기본 키를 포함하지 않아 다른 애플리케이션과 공유할 수 있습니다. 이 예시에서 myhost.company.org / ip:10.0.2.15는 JobManager의 노드(또는 서비스)입니다.

$ keytool -genkeypair -alias flink.rest -keystore rest.keystore -dname "CN=myhost.company.org" -ext "SAN=dns:myhost.company.org,ip:10.0.2.15" -storepass rest_keystore_password -keyalg RSA -keysize 4096 -storetype PKCS12

$ keytool -exportcert -keystore rest.keystore -alias flink.rest -storepass rest_keystore_password -file flink.cer

$ keytool -importcert -keystore rest.truststore -alias flink.rest -storepass rest_truststore_password -file flink.cer -noprompt
security.ssl.rest.enabled: true
security.ssl.rest.keystore: /path/to/flink/conf/rest.keystore
security.ssl.rest.truststore: /path/to/flink/conf/rest.truststore
security.ssl.rest.keystore-password: rest_keystore_password
security.ssl.rest.truststore-password: rest_truststore_password
security.ssl.rest.key-password: rest_keystore_password

REST 엔드포인트 (자체 서명 CA 사용)

다음 keytool 명령을 실행하여 자체 서명 CA로 트러스트스토어를 생성합니다.

$ keytool -genkeypair -alias ca -keystore ca.keystore -dname "CN=Sample CA" -storepass ca_keystore_password -keyalg RSA -keysize 4096 -ext "bc=ca:true" -storetype PKCS12

$ keytool -exportcert -keystore ca.keystore -alias ca -storepass ca_keystore_password -file ca.cer

$ keytool -importcert -keystore ca.truststore -alias ca -storepass ca_truststore_password -file ca.cer -noprompt

이제 위의 CA가 서명한 인증서로 REST 엔드포인트용 키스트어를 생성합니다. flink.company.org / ip:10.0.2.15를 JobManager의 호스트 이름으로 하겠습니다.

$ keytool -genkeypair -alias flink.rest -keystore rest.signed.keystore -dname "CN=flink.company.org" -ext "SAN=dns:flink.company.org" -storepass rest_keystore_password -keyalg RSA -keysize 4096 -storetype PKCS12

$ keytool -certreq -alias flink.rest -keystore rest.signed.keystore -storepass rest_keystore_password -file rest.csr

$ keytool -gencert -alias ca -keystore ca.keystore -storepass ca_keystore_password -ext "SAN=dns:flink.company.org,ip:10.0.2.15" -infile rest.csr -outfile rest.cer

$ keytool -importcert -keystore rest.signed.keystore -storepass rest_keystore_password -file ca.cer -alias ca -noprompt

$ keytool -importcert -keystore rest.signed.keystore -storepass rest_keystore_password -file rest.cer -alias flink.rest -noprompt

이제 Flink 구성 파일에 다음 구성을 추가합니다:

security.ssl.rest.enabled: true
security.ssl.rest.keystore: /path/to/flink/conf/rest.signed.keystore
security.ssl.rest.truststore: /path/to/flink/conf/ca.truststore
security.ssl.rest.keystore-password: rest_keystore_password
security.ssl.rest.key-password: rest_keystore_password
security.ssl.rest.truststore-password: ca_truststore_password

curl 유틸리티로 REST 엔드포인트 질의 팁

openssl을 사용하여 키스트어를 PEM 형식으로 변환할 수 있습니다:

$ openssl pkcs12 -passin pass:rest_keystore_password -in rest.keystore -out rest.pem -nodes

그런 다음 curl로 REST 엔드포인트를 질의할 수 있습니다:

$ curl --cacert rest.pem flink_url

상호 SSL이 활성화된 경우:

$ curl --cacert rest.pem --cert rest.pem flink_url

YARN 배포 팁 (Tips for YARN Deployment)

YARN의 경우 Yarn의 도구를 사용할 수 있습니다:

  • 내부 통신 보안 구성은 위 예시와 정확히 동일합니다.
  • REST 엔드포인트를 보호하려면 JobManager가 배포될 수 있는 모든 호스트에 유효하도록 REST 엔드포인트의 인증서를 발급해야 합니다. 이는 와일드카드 DNS 이름 또는 여러 DNS 이름을 추가하여 할 수 있습니다.
  • 키스트어와 트러스트스토어를 배포하는 가장 쉬운 방법은 YARN 클라이언트의 ship files 옵션(-yt)입니다. 키스트어와 트러스트스토어 파일을 로컬 디렉터리(예: deploy-keys/)에 복사하고 다음과 같이 YARN 세션을 시작합니다: flink run -m yarn-cluster -yt deploy-keys/ flinkapp.jar
  • YARN으로 배포하면 Flink의 웹 대시보드는 YARN 프록시의 Tracking URL을 통해 접근할 수 있습니다. YARN 프록시가 Flink의 HTTPS URL에 접근할 수 있게 하려면 YARN 프록시가 Flink의 SSL 인증서를 수락하도록 구성해야 합니다. 그러려면 YARN Proxy 노드의 Java 기본 트러스트스토어에 사용자 지정 CA 인증서를 추가하세요.

더 알아보기 (Learn more)