Cómo instalar un cluster Hadoop con cifrado de red

La funcionalidad de cifrado de red en Hadoop se añadió en la versión Apache Hadoop 2.0.2-alpha y en CDH4.1.

En este artículo de blog repasaremos, primero, las funcionalidades de seguridad que ya existían en Hadoop. Luego, explicaremos por qué puede ser necesario el cifrado de la red. También daremos algunos detalles sobre cómo se está desarrollada esta funcionalidad. Al final de este artículo, el lector tendrá instrucciones paso a paso que le ayudarán a instalar un cluster Hadoop con cifrado de red.

Artículo original de Cloudera: http://blog.cloudera.com/blog/2013/03/how-to-set-up-a-hadoop-cluster-with-network-encryption/

Traducción realizada por Aitor Pérez.

 

Un poco de historia sobre la seguridad en Hadoop

Empezando con Apache Hadoop 0.20.20x y estando disponible en los lanzamientos de Hadoop 1 y Hadoop 2 (así como en CDH3 y CDH4), Hadoop soporta autenticación basada en Kerberos. A esto se suele referir como Hadoop Security. Cuando Hadoop Security está activado, se requiere autenticación de los usuarios (usando Kerberos) para poder leer y escribir en HDFS, o para poder enviar y gestionar trabajos de MapReduce. Además, todos los servicios de Hadoop autentican unos contra otros usando Kerberos.

La autenticación mediante Kerberos está disponible para el protocolo RPC de Hadoop, así como para el protocolo HTTP. Este último se realiza mediante el estándar Kerberos HTTP SPENGO; y puede utilizarse para proteger las interfaces web de Hadoop: WebHDFS y HttpFS.

¿Por qué el cifrado de red?

Pese a que Hadoop Security provee autenticación mediante Kerberos, no protege los datos mientras viajan por la red; todo el tráfico de red va en claro. Hadoop es un sistema distribuido que normalmente se ejecuta en varias máquinas, lo que significa que los datos se tienen que transmitir mediante la red en la mayoría de los casos.

Si tu cluster Hadoop tiene información sensible (datos financieros, transacciones de tarjetas de crédito, información sanitaria, etc), puede ser un requisito tener que asegurar que los datos están protegidos también durante su tránsito por la red (con el fin de evitar espionaje y ataques Man-in-the-middle). Esta situación es muy similar a la necesidad de acceder a la página web de un banco usando una conexión segura.

Para abordar todos estos casos de uso, se añade cifrado de red en Hadoop.

Asegurando las interacciones de red de Hadoop

Primero, vamos a revisar los distintos tipos de interacción mediante red realizados en Hadoop:

  • Llamadas Hadoop RPC - Estas llamadas las realizan los clientes Hadoop usando la API, los trabajos MapReduce, y entre los servicios Hadoop (JobTracker, TaskTracker, NameNodes, DataNodes)
  • Transferencia de datos HDFS - Se realiza durante la lectura o la escritura en HDFS; la realizan los clientes Hadoop usando la API, los trabajos MapReduce, y entre los servicios Hadoop. La transferencia de datos HDFS utiliza sockets TCP/IP directamente.
  • MapReduce Suffle - La fase de mezcla de datos en un trabajo MapReduce es un proceso de transferencia de datos de las tareas Map a las tareas Reduce. Esta transferencia se realiza habitualmente entre distintos nodos del clúster; y la mezcla se realiza mediante el protocolo HTTP.
  • Interfaces Web - Los demonios de Hadoop proveen interfaces web para los usuarios y los administradores, para permitir monitorizar su trabajo y el estado del clúster. Las interfaces web usan el protocolo HTTP.
  • Operaciones FSImage - Estas operaciones son transferencias de metadatos entre el NameNode y el Secondary NameNode. Se realizan mediante HTTP.

Esto significa que Hadoop usa la red con tres protocolos distintos:

  • Hadoop RPC
  • TCP/IP
  • HTTP

Hadoop RPC ya tiene soporte para SASL para proveer cifrado de red. Por tanto, sólo tenemos que preocuparnos de asegurar las transferencias de HDFS y el protocolo HTTP.

Cifrado de Hadoop RPC

Cuando se añadió autenticación al protocolo Hadoop RPC, se usó SASL como protocolo de seguridad. SASL, o Simple Authentication and Security Layer (Autenticación Simple y Capa de Seguridad), es un framework que abstrae a los protocolos de alto nivel de los detalles de la implementación real de la seguridad; los cuales quieren dar soporte para autenticación, verificación de integridad del mensaje o cifrado. SASL no especifica una forma de conexión o los protocolos que lo implementan, sino que especifica un sistema de handshake, donde las partes involucradas en una conexión SASL intermcabiarán mensajes cuando se establece una conexión por primera vez.

SASL permite el uso de distintos mecanismos de seguridad para distintos contextos (por ejemplo, resumen MD5, GSSAPI o mecanismo SASL plano). Para que los protocolos implementen adecuadamente el framework SASL, cualquiera de estos mecanismos tiene que poder usarse indistintamente. Dejando aparte los detalles de cómo un mecanismo SASL implemente su seguridad, la mayoría de los mecanismos son capaces de proveer distintos niveles de protección. Esto permite que un mecanismo (por ejemplo, resumen MD5) ofrezca sólamente autenticación (auth), verificación de integridad (auth-in) o cifrado del mensaje (auth-conf).

¿Qué significa todo esto dentro del contexto de Hadoop RPC? Desde que Hadoop RPC implementa el framework SASL, podemos usar todas estas funcionalidades sin ninguna complejidad adicional. Cuando un cliente Hadoop que tiene credenciales Kerberos disponibles conecta con un demonio Hadoop, el mecanismo SASL GSSAPI puede ser usado para la atenticación. Aunque por defecto sólo se autentica la conexión, en cualquier caso se puede aumentar el nivel de seguridad mediante la propiedad hadoop.rpc.protection, para así comprobar la integridad de las llamadas RPC, o para transmitirlas cifradas.

TPC/IP (Transferencia cifrada de datos HDFS)

Aunque Hadoop RPC siempre ha soportado cifrado desde la introducción de Hadoop Security, la lectura/escritura de datos entre clientes y DataNodes no utiliza llamadas RPC Hadoop. En lugar de eso, los datos se transmiten entre clientes y DNs mediante Hadoop Data Transfer Protocol, el cual no usa SASL. En cambio, los clientes obtienen un Block Token del NameNode cuando solicitan las localizaciones de un bloque para un archivo; luego el cliente presenta el token al DN durante la conexión para la lectura/escritura. El DN es capaz de verificar la autenticidad de los tokens mediante una clave secreta compartida entre los NNs y los DNs del clúster.

Pese a que este sistema es suficiente para autenticar a los clientes que se conectan a los DN, la realidad es que, al no usar SASL, no podemos añadir verificación de integridad ni cifrado de manera trivial.

Para abordar esta deficiencia del protocolo de transferencia de datos, elegimos envolver el protocolo existente con un handshake SASL. Hemos envuelto el protocolo existente en lugar de reemplazarlo por el protocolo actual con SASL, ya que queremos mantener compatibilidad en el caso de que el cifrado de red esta desactivado. Este envoltorio de SASL se puede activar cambiando el valor de la propiedad dfs.encrypt.data.transfer a true en la configuración del NameNode y del DataNode, mas luego reiniciando ambos demonios. Cuando está activado, el NameNode generará y devolverá a los clientes claves de cifrado de datos (Data Encryption keys), las cuales pueden ser usadas como credenciales para el mecanismo MD5-DIGEST SASL y cuya autenticidad puede ser verificada por los DataNodes, basada en un clave compartida entre el NN y el DN; de manera similar a como se autentican los Block Tokens cuando sólo está activada la autenticación. Hay que resaltar que, desde que las claves de cifrado en si mismas son enviadas a los clientes a través de Hadoop RPC, es necesario establecer la propiedad hadoop.rpc.protection a privacy para que el sistema esté realmente protegido.

Para ver todos los detalles de la implementación del cifrado en el transporte de HDFS, visitar HDFS-3637.

Cifrado HTTP

La solución para el cifrado HTTP estaba claro: HTTPS es un estándar probado y ampliamente adoptado para el cifrado HTTP. Java soporta HTTPS, los navegadores soportan HTTPS, y muchas librerías y herramientas en la mayoría de sistemas operativos tienen soporte para HTTPS.

Como hemos mencionado antes, Hadoop usa HTTP para sus interfaces web, para la fase de mezcla de FSImage entre el NameNode y el Secondary Name node. Ya que Hadoop HttpServer (basado en Jetty) ya ofrece soporte para HTTPS, los cambios requeridos son mínimos. Sólo tenemos que garantizar que el servidor http usado por Hadoop se inicie usando HTTPS.

Los nodos en un clúster se añaden y se sustraen dinámicamente. Para cada nodo que se añade al clúster, la clave pública del certificado tiene que añadirse a todos los otros nodos. De forma similar, para cada nodo que se sustrae del clúster, su clave pública se tiene que eliminar de los otros nodos. Además, este proceso de gestión de claves públicas debe realizarse sin interrumpir tareas que estén en ejecución. Puesto que el almacén de claves de Java por defecto sólo carga los certificados en tiempo de inicialización, debemos implementar un almacén de claves propio para recargar las claves públicas de los certificados en caso de que el archivo del almacén de claves cambie.

Además, tenemos que modificar el Hadoop HttpServer, el cliente HTTP MapReduce shuffle, y el cliente HTTP de FSImage para poder usar este nuevo almacén de claves propio.

El cifrado HTTP se realizó en dos Apache JIRA, MAPREDUCE-4417 y HADOOP-8581.

Estableciendo cifrado de red con CDH4

Ahora vamos a explicar cómo crear certificados HTTPS usando la herramienta Java Keytool para un clúster Hadoop. Una vez que se hayan creado los certificados y se hayan añadido a todos los nodos del clúster, visita CDH4 documentation para completar la configuración de cifrado de red en Hadoop.

Los siguientes pasos explican cómo crear certificados para HTTPS, el almacén de claves (keystore) necesario y los ficheros de almacenes de confianza (truststore); asumiendo que tenemos un clúster con dos máquinas - h001.foo.com y h002.foo.com - y que todos los servicios de Hadoop están iniciados por un usuario que pertenece al grupo "hadoop".

Cada fichero del almacén de claves contiene la clave privada de cada certificado, de forma que el archivo contiene todos las claves de todos los certificados. El archivo de almacén de claves (keystore) se usa en el Hadoop HttpServer mientras que el almacén de confianza (truststore) se usará en las conexiones HTTPS de los clientes.

Para cada nodo se crea un certificado con el host correspondiente en un keystore diferente:

$ keytool -genkey -keystore  h001.keystore -keyalg RSA -alias h001 \ -dname "CN=h001.foo.com,O=Hadoop"  -keypass pepepe -storepass pepepe 
$ keytool -genkey -keystore  h002.keystore -keyalg RSA -alias h002 \> -dname "CN=h002.foo.com,O=Hadoop"  -keypass pepepe -storepass pepepe

Para cada nodo, exportamos la clave pública del certificado en un archivo diferente:

$ keytool -exportcert -keystore  h001.keystore -alias h001 \ -file h001.cert -storepass pepepe  
$ keytool -exportcert -keystore  h002.keystore -alias h002 \ -file h002.cert -storepass pepepe

Creamos un truststore con todos las claves públicas de todos los certificados:

$ keytool -import -keystore hadoop.truststore -alias h001 \ -file h001.cert -noprompt -storepass pepepe
$ keytool -import -keystore hadoop.truststore -alias h002 \ -file h002.cert -noprompt -storepass pepepe

Copiamos el keystore y el truststore en los nodos correspondientes:

$ scp h001.keystore hadoop.truststore root@h001.foo.com:/etc/hadoop/conf/
$ scp h002.keystore hadoop.truststore root@h002.foo.com:/etc/hadoop/conf/

Cambiamos los permisos del keystore para que sólo lo puedan leer el usuario y el grupo. Añadirlos al grupo Hadoop; hacer el truststore visible para todo el mundo:

$ ssh root@h001.foo.com "cd /etc/hadoop/conf;chgrp hadoop h001.keystore;\ chmod 0440 h001.keystore;chmod 0444 hadoop.truststore"
$ ssh root@h002.foo.com "cd /etc/hadoop/conf;chgrp hadoop h002.keystore;\ chmod 0440 h002.keystore;chmod 0444 hadoop.truststore"

Generamos un certificado público para instalar en el navegador:

$ openssl x509 -inform der -in h001.cert >> hadoop.PEM
$ openssl x509 -inform der -in h002.cert >> hadoop.PEM

Seguir las instrucciones del navegador/OS para installar el fichero hadoop.pem.

Ahora que los ficheros HTTPS están creados y distribuidos en todas las máquinas del clúster, necesitaremos configurar Hadoop con cifrado de red. Para ello, por favor visite la documentación CDH4, Configuring Encrypted Shuffle, Encrypted Web UIs, and Encrypted HDFS Transport, para instrucciones detalladas sobre cómo configurar cifrado de red en Hadoop.

¡En este punto, tu clúster está listo para usar cifrado de red!

Artículo original de Cloudera: http://blog.cloudera.com/blog/2013/03/how-to-set-up-a-hadoop-cluster-with-network-encryption/

Autores originales:

Alejandro Abdelnur; es Ingeniero del Software en el Platform team, y un miembro PMC de Apache Oozie, Hadoop y Bigtop.

Aaron T. Myers (ATM) es un Ingniero del SOftware en Platform team y un miembro PMC de Hadoop.