HBase RPC 통신에서의 전송 계층 보안(TLS)
HBase RPC 통신에서의 전송 계층 보안(TLS)
이 문서는 HBase의 TLS 암호화를 설명해요. 버전 2.6.0부터 HBase는 서버-클라이언트 및 Master-RegionServer 통신에서 TLS 암호화를 지원해요. 웹 브라우저에서 https 접두사로 안전한 웹사이트에 접근하는 것처럼, 한 번 성립되면 채널의 모든 통신이 악의적 접근으로부터 안전하게 숨겨져요.
출처: 문서
본문
버전 2.6.0부터 HBase는 서버-클라이언트 및 Master-RegionServer 통신에서 TLS 암호화를 지원해요. Transport Layer Security (TLS)는 컴퓨터 네트워크에서 통신 보안을 제공하도록 설계된 표준 암호화 프로토콜이에요. HBase TLS 구현은 웹 브라우저에서 https 접두사로 안전한 웹사이트에 접근하는 방식과 똑같이 동작해요. 한 번 성립되면 채널의 모든 통신이 악의적 접근으로부터 안전하게 숨겨져요.
암호화는 전송 계층에서 동작해요. 즉 구성된 인증 방법과 독립적이에요. 이전 섹션에서 언급한 보안 클라이언트 접근은 HBase 인증에 Kerberos를 구성하고 사용해야 하지만, TLS는 다른 어떤 SASL 메커니즘 또는 간단한 클라이언트 접근 방법과도 함께 구성할 수 있어요. 공격자가 통신을 도청하는 것을 효과적으로 막아 주면서 Kerberos KDC나 다른 복잡한 인프라가 필요하지 않아요.
HBase TLS는 Netty 라이브러리를 기반으로 하므로 Netty 클라이언트와 서버 RPC 구현에서만 동작해요. Netty의 강력한 SSL 구현은 항상 최신의 최고 암호화 솔루션을 제공하는, 고도로 안전하고 성능 좋은 통신을 위한 훌륭한 기반이에요.
Region Server는 Master의 관점에서 효과적으로 클라이언트로 동작하므로, TLS는 클러스터 멤버 간의 암호화된 통신도 지원해요.
버전 2.6.0부터 HBase는 Hadoop CredentialProvider API를 지원해서 민감한 정보를 HBase 구성 파일에 저장하지 않을 수 있어요. keystore/truststore 비밀번호를 저장하는 권장 방법은 지원되는 credential provider 중 하나(예: 로컬 jceks 파일 제공자)를 사용하는 것이에요. credential provider 설정 방법에 대한 자세한 내용은 Hadoop 문서에서 확인할 수 있어요.
Hadoop Credential Shell에 접근하기 위한 CLI 인터페이스도 HBase CLI에서 사용할 수 있어요. hbase credential을 입력하면 도움말을 볼 수 있어요.
서버 측 구성
서버용 Java key store를 설정해야 해요. Key store는 서버가 TLS 암호화를 구성하는 데 사용할 수 있는 개인 키 목록이에요. 프로토콜에 대한 자세한 내용은 TLS wikipedia page를 참고하세요. Master, Region Server, HBase 클라이언트의 hbase-site.xml에 다음 구성을 추가하세요.
<property>
<name>hbase.server.netty.tls.enabled</name>
<value>true</value>
</property>
<property>
<name>hbase.rpc.tls.keystore.location</name>
<value>/path/to/keystore.jks</value>
</property>
hbase.rpc.tls.keystore.password 별칭을 사용해 Hadoop credential provider에서 key store 비밀번호를 검색하세요.
지원되는 storefile 형식은 등록된 보안 제공자에 기반하며, 로더는 파일 확장자에서 자동 감지할 수 있어요. 필요하다면 hbase.rpc.tls.keystore.type 프로퍼티로 파일 형식을 명시적으로 지정할 수 있어요.
클라이언트 측 구성
클라이언트용 trust store를 구성해야 해요. Trust store는 서버와의 핸드셰이크 시 클라이언트가 신뢰해야 하는 인증서 목록을 포함해요. hbase-site.xml에 다음을 추가하세요.
<property>
<name>hbase.client.netty.tls.enabled</name>
<value>true</value>
</property>
<property>
<name>hbase.rpc.tls.truststore.location</name>
<value>/path/to/truststore.jks</value>
</property>
hbase.rpc.tls.truststore.password 별칭을 사용해 Hadoop credential provider에서 trust store 비밀번호를 검색하세요.
지원되는 storefile 형식은 등록된 보안 제공자에 기반하며, 로더는 파일 확장자에서 자동 감지할 수 있어요. 필요하다면 hbase.rpc.tls.truststore.type 프로퍼티로 파일 형식을 명시적으로 지정할 수 있어요.
그러나 trust store를 지정하는 것이 항상 필요한 것은 아니에요. 표준 JDK 구현에는 표준 신뢰 인증서 목록(인증 기관의 인증서)이 함께 제공되며, 당신의 개인 키가 그 중 하나가 제공했다면 클라이언트가 그것을 신뢰하도록 구성할 필요가 없어요. 인터넷 브라우저처럼 방문할 모든 웹사이트의 인증서를 설정할 필요가 없는 것과 같아요. 이 문서의 뒷부분에서는 자체 서명 인증서를 만드는 단계를 살펴볼 거예요. 이 경우 trust store 설정이 필요해요.
JDK 구현에 포함된 공용 인증 기관 목록을 확인할 수 있어요.
keytool -keystore $JAVA_HOME/jre/lib/security/cacerts -list
비밀번호는 기본적으로 비어 있어요.
자체 서명 인증서 만들기
인증 기관에서 전 세계적으로 신뢰받는 인증서를 얻는 것이 편리하지만, 자신의 개인/공용 키쌍을 생성해 HBase 클러스터를 위해 특별히 설정하는 것도 완벽히 유효해요. 특히 클러스터에 공용 접근을 활성화하고 싶지 않다면 인증서에 돈을 지불하는 것이 말이 안 되죠.
자체 서명 인증서를 생성하려면 다음 단계를 따르세요.
-
로컬 자격 증명을 저장할 SSL key store JKS 생성
별칭(-alias)과 고유 이름(-dname)이 연관된 머신의 호스트 이름과 일치해야 한다는 점을 주의하세요. 그렇지 않으면 호스트 이름 검증이 동작하지 않아요.
keytool -genkeypair -alias $(hostname -f) -keyalg RSA -keysize 2048 -dname "cn=$(hostname -f)" -keypass password -keystore keystore.jks -storepass password이 작업이 끝나면 클러스터의 서버 수만큼 key store 파일을 갖게 돼요. 각 클러스터 멤버가 자신의 key store를 가져요.
-
각 key store에서 서명된 공용 키(인증서) 추출
keytool -exportcert -alias $(hostname -f) -keystore keystore.jks -file $(hostname -f).cer -rfc -
클라이언트용 인증서를 포함하는 SSL trust store JKS 생성
같은 truststore(모든 허용 인증서를 저장)를 클러스터 참가자 간에 공유해야 해요. 같은 truststore에 여러 인증서를 저장하려면 서로 다른 별칭을 사용해야 해요. 별칭의 이름은 중요하지 않아요.
keytool -importcert -alias [host1..3] -file [host1..3].cer -keystore truststore.jks -storepass password
다운타임 없이 기존 비-TLS 클러스터 업그레이드
포트 통일(port unification) 기능을 활용해 이미 실행 중인 HBase 클러스터를 다운타임 없이 TLS로 업그레이드하는 단계는 다음과 같아요. 서버 측에는 hbase.server.netty.tls.supportplaintext라는 프로퍼티가 있는데, 같은 소켓 포트에서 TLS와 plaintext 연결을 둘 다 허용하게 해 줘요.
이전 섹션에서 설명한 대로 모든 서버 참가자를 위한 필요한 key store와 trust store를 생성하세요.
Master 노드에서 평문 지원과 함께 server-only 모드로 보안 통신 활성화
<property>
<name>hbase.client.netty.tls.enabled</name>
<value>false</value>
</property>
<property>
<name>hbase.server.netty.tls.enabled</name>
<value>true</value>
</property>
<property>
<name>hbase.server.netty.tls.supportplaintext</name>
<value>true</value>
</property>
...keystore / truststore setup ...
Master를 재시작하세요. 이제 Master는 TLS/non-TLS 연결을 둘 다 받아들이고 클라이언트 모드에서는 non-TLS로 동작해요.
Region Server에서 평문 지원과 함께 server와 client 모드 모두에서 보안 통신 활성화
여기서의 클라이언트 모드는 RegionServer의 Master로의 통신이 암호화되도록 보장해요.
복제
클러스터에서 read replicas를 활성화했거나 두 클러스터 간 복제를 하고 있다면 이것을 두 단계로 나눠야 해요. 먼저 서버 측에서 평문 지원과 함께 보안 통신을 활성화하고, 모든 Region Server가 업그레이드되면 클라이언트 측도 활성화해 업그레이드를 반복할 수 있어요.
클라이언트 측을 업그레이드하기 전에 모든 Region Server가 보안 통신을 준비해야 해요.
<property>
<name>hbase.client.netty.tls.enabled</name>
<value>true</value>
</property>
<property>
<name>hbase.server.netty.tls.enabled</name>
<value>true</value>
</property>
<property>
<name>hbase.server.netty.tls.supportplaintext</name>
<value>true</value>
</property>
...keystore / truststore setup ...
롤링 재시작 방식으로 Region Server를 재시작하세요. 이들은 TLS로 요청을 보내고 TLS와 non-TLS 통신을 둘 다 받아들여요.
클라이언트에서 보안 통신 활성화
<property>
<name>hbase.client.netty.tls.enabled</name>
<value>true</value>
</property>
...truststore setup ...
Master에서 클라이언트 모드 TLS 활성화 및 평문 모드 비활성화
<property>
<name>hbase.client.netty.tls.enabled</name>
<value>true</value>
</property>
<property>
<name>hbase.server.netty.tls.enabled</name>
<value>true</value>
</property>
<property>
<name>hbase.server.netty.tls.supportplaintext</name>
<value>false</value>
</property>
Master를 재시작하세요.
Region Server에서 평문 통신 비활성화
supportplaintext 프로퍼티를 제거해 Region Server의 평문 통신을 비활성화하세요. 롤링 재시작 방식으로 RS를 재시작하세요.
서버 측에서 hbase.client.netty.tls.enabled가 활성화되면 클러스터는 TLS가 활성화된 다른 클러스터와만 통신할 수 있어요. 예를 들어 이것은 클러스터 간 복제에 영향을 줘요.
자동 인증서 재로딩 활성화
인증서는 보안을 개선하기 위해 보통 일정 시간 후 만료돼요. 이 경우 Keystore/Truststore 파일을 수정해 교체해야 하고 HBase 프로세스를 재시작해야 해요. 이를 피하려면 다음 옵션으로 자동 파일 변경 감지와 인증서 재로딩을 활성화할 수 있어요. 기본값: false.
<property>
<name>hbase.rpc.tls.certReload</name>
<value>true</value>
</property>
추가 구성
활성화된 프로토콜
활성화할 TLS 프로토콜 버전의 쉼표로 구분된 목록이에요. 기본값은 비어 있어요.
<property>
<name>hbase.client.netty.tls.enabledProtocols</name>
<value>TLSv1.2,TLSv1.3</value>
</property>
기본 프로토콜
사용할 기본 TLS 프로토콜 버전을 설정해요. 기본값은 TLSv1.2예요. 활성화된 프로토콜이 정의되지 않은 경우 이 프로토콜을 사용해요.
<property>
<name>hbase.client.netty.tls.protocol</name>
<value>TLSv1.2</value>
</property>
활성화된 암호 스위트
TLS 프로토콜의 활성화된 암호 스위트 목록이에요. 최근 보안 우려로 특정 암호 스위트를 비활성화하고 싶을 때 유용해요. 기본값은 CBC와 GCM 암호의 혼합이에요. 성능상의 이유로 Java 8에서는 CBC 암호, Java 9+에서는 GCM 암호를 선호해요.
<property>
<name>hbase.client.netty.tls.ciphersuites</name>
<value>TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256</value>
</property>
인증서 폐기 확인
JDK의 TrustManager에는 인증서의 폐기를 자동으로 확인하는 내장 메커니즘이 있어요. Managing Server Certificates를 참고하세요. 기본적으로 비활성화돼 있어요.
<property>
<name>hbase.client.netty.tls.clr</name>
<value>false</value>
</property>
Online Certificate Status Protocol
OCSP stapling을 활성화해요. 모든 SSLProvider 구현이 OCSP stapling을 지원하는 것은 아니며 그 경우 예외가 발생한다는 점에 주의하세요. 기본적으로 비활성화돼 있어요.
<property>
<name>hbase.client.netty.tls.ocsp</name>
<value>false</value>
</property>
클라이언트 핸드셰이크 타임아웃
TLS 클라이언트 핸드셰이크 타임아웃을 밀리초 단위로 설정해요. 기본값은 5초예요.
<property>
<name>hbase.client.netty.tls.handshaketimeout</name>
<value>5000</value>
</property>