Ranger KMS high availability¶
If the KMS is down, no client can open a file in an encryption zone and the NameNode cannot create new ones, so a production KMS should not be a single process. Ranger KMS instances are stateless apart from the database: run two or more of them against the same database with the same master key, and put a load balancer (or a client-side host list) in front. This page shows the KMS settings that must agree between instances, an Apache HTTP Server load balancer configuration with and without TLS, and the client-side changes.
Requirements¶
Every instance must:
- Use the same database (
ranger.ks.jpa.jdbc.url,.userand password indbks-site.xml). Keys are stored inranger_keystore; an instance loads keys it has not seen yet from the database on demand and caches them in memory, so there is no local key state to replicate. - Use the same master key - the same master key password (
ranger.db.encrypt.key.password, or the alias named byranger.ks.masterkey.credential.alias) and the sameranger.kms.service.masterkey.*parameters for the database provider, or the same HSM partition / cloud key for the other providers. The master key is created by whichever instance starts first; the others load it. -
Share the authentication cookie secret. The Hadoop auth filter signs its cookie with a secret that is random per process by default, so a request that lands on a different instance would be rejected. Set in
kms-site.xmlon all instances:<property> <name>hadoop.kms.authentication.signer.secret.provider</name> <value>zookeeper</value> </property> <property> <name>hadoop.kms.authentication.signer.secret.provider.zookeeper.path</name> <value>/hadoop-kms/hadoop-auth-signature-secret</value> </property> <property> <name>hadoop.kms.authentication.signer.secret.provider.zookeeper.connection.string</name> <value>zk1.example.com:2181,zk2.example.com:2181,zk3.example.com:2181</value> </property> <property> <name>hadoop.kms.authentication.signer.secret.provider.zookeeper.auth.type</name> <value>kerberos</value> <!-- or none --> </property> <property> <name>hadoop.kms.authentication.signer.secret.provider.zookeeper.kerberos.keytab</name> <value>/etc/security/keytabs/rangerkms.keytab</value> </property> <property> <name>hadoop.kms.authentication.signer.secret.provider.zookeeper.kerberos.principal</name> <value>rangerkms/kms1.example.com@EXAMPLE.COM</value> </property>Sticky sessions on the load balancer (shown below) reduce, but do not remove, the need for this.
-
Register with the same Ranger KMS service (
ranger.plugin.kms.service.nameinranger-kms-security.xml) so that policies are identical, and use the samehadoop.kms.blacklist.DECRYPT_EEKand proxy-user settings. - With Kerberos, have a keytab that contains the
HTTP/<load-balancer-host>principal clients will negotiate against (they address the balancer by name, so the SPNEGO service ticket is issued for that host), and sethadoop.kms.authentication.kerberos.principalaccordingly on every instance.
Client-side host list¶
Hadoop's KMS client (LoadBalancingKMSClientProvider) accepts several hosts in one URI and fails over
between them, which avoids a separate load balancer:
<property>
<name>hadoop.security.key.provider.path</name>
<value>kms://http@kms1.example.com;kms2.example.com:9292/kms</value>
</property>
Use this when all clients are Hadoop components. A load balancer is still useful for non-Hadoop clients,
for the Ranger Admin Key Manager UI (its provider setting holds one URL), and for a stable name.
Load balancer with Apache HTTP Server¶
The example uses mod_proxy_balancer with sticky sessions. Install httpd with mod_proxy,
mod_proxy_http, mod_proxy_balancer, mod_slotmem_shm and mod_lbmethod_byrequests enabled (they are
part of the standard build; enable the LoadModule lines in httpd.conf), then include a file such as:
Listen 9292
<VirtualHost *:9292>
ProxyRequests off
ProxyPreserveHost on
Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/" env=BALANCER_ROUTE_CHANGED
<Proxy balancer://rangerkmscluster>
BalancerMember http://kms1.example.com:9292 loadfactor=1 route=1
BalancerMember http://kms2.example.com:9292 loadfactor=1 route=2
ProxySet lbmethod=byrequests scolonpathdelim=On stickysession=ROUTEID maxattempts=1 failonstatus=500,501,502,503 nofailover=Off
</Proxy>
<Location /balancer-manager>
SetHandler balancer-manager
Require ip 10.0.0.0/8
</Location>
ProxyPass /balancer-manager !
ProxyPass / balancer://rangerkmscluster/
ProxyPassReverse / balancer://rangerkmscluster/
</VirtualHost>
Add Include conf/ranger-kms-cluster.conf to httpd.conf, restart httpd, and check
curl http://lb.example.com:9292/kms/v1/keys/names?user.name=keyadmin returns from both members (the
balancer-manager page shows the routes).
TLS on the load balancer¶
Build or install httpd with mod_ssl, create a key and certificate for the balancer host, and terminate
TLS at the balancer:
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt # or use your CA
cp server.crt server.key /usr/local/apache2/conf/
Listen 9393
<VirtualHost *:9393>
SSLEngine On
SSLProxyEngine On
SSLCertificateFile /usr/local/apache2/conf/server.crt
SSLCertificateKeyFile /usr/local/apache2/conf/server.key
SSLVerifyClient optional
SSLOptions +ExportCertData
ProxyRequests off
Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/" env=BALANCER_ROUTE_CHANGED
<Proxy balancer://rangerkmscluster>
BalancerMember http://kms1.example.com:9292 loadfactor=1 route=1
BalancerMember http://kms2.example.com:9292 loadfactor=1 route=2
ProxySet lbmethod=byrequests scolonpathdelim=On stickysession=ROUTEID maxattempts=1 failonstatus=500,501,502,503 nofailover=Off
</Proxy>
ProxyPass /balancer-manager !
ProxyPass / balancer://rangerkmscluster/
ProxyPassReverse / balancer://rangerkmscluster/
</VirtualHost>
If the KMS instances themselves run HTTPS (ranger.service.https.attrib.ssl.enabled=true, port 9393), use https://
members and either import their certificates into the balancer's trust store or, for a private network,
SSLProxyVerify none. Export the balancer certificate (server.crt) and import it into the truststore of
every client:
keytool -import -file server.crt -alias kms-lb -keystore /etc/security/clientKeys/truststore.jks
The Ranger KMS plugin inside each KMS talks to Ranger Admin, not to the balancer, so it needs no change;
only if Ranger Admin itself sits behind a TLS balancer must the truststore named by
xasecure.policymgr.clientssl.truststore (in the file that ranger.plugin.kms.policy.rest.ssl.config.file
points to) trust that certificate.
Client and Ranger Admin changes¶
After the balancer is up:
core-site.xmlon all Hadoop nodes:hadoop.security.key.provider.path=kms://http@lb.example.com:9292/kms(orkms://https@lb.example.com:9393/kms); older Hadoop alsodfs.encryption.key.provider.uriinhdfs-site.xml. Restart the NameNode(s) and any long-running clients.- Ranger Admin: edit the KMS service and set
providerto the balancer URL so Test Connection and the Key Manager UI go through it. - Restart the KMS instances; then verify in Audit > Plugins that each KMS host reports HTTP
200for policy downloads, and runhadoop key listfrom a client.
HSM and cloud providers¶
With Luna HSM, all instances must point at the same partition or, better, an HSM HA group (see HSM and key stores). With KeySecure, Azure Key Vault, AWS KMS, Google Cloud KMS or Tencent KMS, all instances use the same master key name/id. Do not mix providers between instances of one cluster.
Further reading¶
- Ranger KMS overview
- Ranger Admin high availability for the same pattern on the admin side
- cwiki: Configuring Ranger KMS in HA