Cifrado del tráfico entre los nodos de trabajo del clúster

Importante

El script de inicialización (init) de ejemplo al que se hace referencia en este artículo obtiene su secreto de cifrado compartido del hash del almacén de claves almacenado en DBFS. Si rota el secreto actualizando el archivo de almacén de claves en DBFS, se deben reiniciar todos los clústeres en ejecución. De lo contrario, es posible que los trabajos de Spark no se autentiquen con el controlador de Spark debido a un secreto compartido incoherente, lo que hace que los trabajos se ralenticen. Además, dado que el secreto compartido se almacena en DBFS, cualquier usuario con acceso a DBFS puede recuperar el secreto mediante un cuaderno.

Requisitos

  • Esta característica requiere el plan Premium. Póngase en contacto con el equipo de la cuenta de Databricks para obtener más información.

Funcionamiento del script de inicialización

Importante

El script de inicialización (init) de ejemplo al que se hace referencia en este artículo obtiene su secreto de cifrado compartido del hash del almacén de claves almacenado en DBFS. Si rota el secreto actualizando el archivo de almacén de claves en DBFS, se deben reiniciar todos los clústeres en ejecución. De lo contrario, es posible que los trabajos de Spark no se autentiquen con el controlador de Spark debido a un secreto compartido incoherente, lo que hace que los trabajos se ralenticen. Además, dado que el secreto compartido se almacena en DBFS, cualquier usuario con acceso a DBFS puede recuperar el secreto mediante un cuaderno.

Las consultas y transformaciones de usuario normalmente se envían a los clústeres a través de un canal cifrado. Sin embargo, de forma predeterminada, los datos intercambiados entre los nodos de trabajo del clúster no están cifrados. Si el entorno requiere que los datos se cifren en todo momento, ya sea en reposo o en tránsito, puede crear un script de inicialización que configure los clústeres para cifrar el tráfico entre los nodos de trabajo, mediante el cifrado AES de 256 bits a través de una conexión TLS 1.3.

Nota:

Aunque AES permite que las rutinas criptográficas aprovechen la aceleración de hardware, hay una penalización en el rendimiento en comparación con el tráfico no cifrado. Esta penalización puede dar lugar a que las consultas tarden más tiempo en un clúster cifrado, en función de la cantidad de datos que se ordenan aleatoriamente entre los nodos.

La habilitación del cifrado del tráfico entre los nodos de trabajo requiere establecer parámetros de configuración de Spark mediante un script de inicialización. Puede usar un script de inicialización con ámbito de clúster para un único clúster o agregar un script de inicialización con ámbito de clúster a las directivas de clúster si desea que todos los clústeres del área de trabajo usen cifrado de trabajo a trabajo.

Una vez, copie el archivo de almacén de claves en un directorio de DBFS. A continuación, cree el script de inicialización que aplica la configuración de cifrado.

El script de inicialización debe realizar las siguientes tareas:

  1. Obtener el archivo y la contraseña del almacén de claves de JKS.
  2. Establecer la configuración del ejecutor de Spark.
  3. Establecer la configuración del controlador de Spark.

Nota:

El archivo de almacén de claves de JKS que se usa para habilitar SSL/HTTPS se genera dinámicamente para cada área de trabajo. La contraseña del archivo de almacén de claves de JKS está codificada de forma rígida y no está diseñada para proteger la confidencialidad del almacén de claves.

A continuación, se muestra un script de inicialización de ejemplo que implementa estas tres tareas para generar la configuración de cifrado del clúster.

Script de inicialización de ejemplo

#!/bin/bash

set -euo pipefail

keystore_dbfs_file="/dbfs/<keystore-directory>/jetty_ssl_driver_keystore.jks"

## Wait till keystore file is available via Fuse

max_attempts=30
while [ ! -f ${keystore_dbfs_file} ];
do
  if [ "$max_attempts" == 0 ]; then
    echo "ERROR: Unable to find the file : $keystore_dbfs_file .Failing the script."
    exit 1
  fi
  sleep 2s
  ((max_attempts--))
done
## Derive shared internode encryption secret from the hash of the keystore file
sasl_secret=$(sha256sum $keystore_dbfs_file | cut -d' ' -f1)

if [ -z "${sasl_secret}" ]; then
  echo "ERROR: Unable to derive the secret.Failing the script."
  exit 1
fi

# The JKS keystore file used for enabling SSL/HTTPS
local_keystore_file="$DB_HOME/keys/jetty_ssl_driver_keystore.jks"
# Password of the JKS keystore file. This jks password is hardcoded and is not intended to protect the confidentiality
# of the keystore. Do not assume the keystore file itself is protected.
local_keystore_password="gb1gQqZ9ZIHS"

## Updating spark-branch.conf is only needed for driver

if [[ $DB_IS_DRIVER = "TRUE" ]]; then
  driver_conf=${DB_HOME}/driver/conf/spark-branch.conf
  echo "Configuring driver conf at $driver_conf"

  if [ ! -e $driver_conf ] ; then
    touch $driver_conf
  fi

cat << EOF >>  $driver_conf
  [driver] {
    // Configure inter-node authentication
  "spark.authenticate" = true
  "spark.authenticate.secret" = "$sasl_secret"
  // Configure AES encryption
  "spark.network.crypto.enabled" = true
  "spark.network.crypto.saslFallback" = false
  // Configure SSL
  "spark.ssl.enabled" = true
  "spark.ssl.keyPassword" = "$local_keystore_password"
  "spark.ssl.keyStore" = "$local_keystore_file"
  "spark.ssl.keyStorePassword" = "$local_keystore_password"
  "spark.ssl.protocol" ="TLSv1.3"
  "spark.ssl.standalone.enabled" = true
  "spark.ssl.ui.enabled" = true
  }
EOF
  echo "Successfully configured driver conf at $driver_conf"
fi

# Setting configs in spark-defaults.conf for the spark master and worker

spark_defaults_conf="$DB_HOME/spark/conf/spark-defaults.conf"
echo "Configuring spark defaults conf at $spark_defaults_conf"
if [ ! -e $spark_defaults_conf ] ; then
  touch $spark_defaults_conf
fi

cat << EOF >>  $spark_defaults_conf
spark.authenticate true
spark.authenticate.secret $sasl_secret
spark.network.crypto.enabled true
spark.network.crypto.saslFallback false

spark.ssl.enabled true
spark.ssl.keyPassword $local_keystore_password
spark.ssl.keyStore $local_keystore_file
spark.ssl.keyStorePassword $local_keystore_password
spark.ssl.protocol TLSv1.3
spark.ssl.standalone.enabled true
spark.ssl.ui.enabled true
EOF

echo "Successfully configured spark defaults conf at $spark_defaults_conf"

Una vez completada la inicialización del controlador y los nodos de trabajo, todo el tráfico entre estos nodos se cifra mediante el archivo de almacén de claves.

Ejemplo de cuaderno: Instalar un script de inicialización de cifrado

En el siguiente cuaderno se copia el archivo de almacén de claves y se genera el script de inicialización en DBFS. Puede usar el script de inicialización para crear nuevos clústeres con el cifrado habilitado.

Instalación de un cuaderno de script de inicialización de cifrado

Obtener el cuaderno

Deshabilitación del cifrado entre los nodos de trabajo

Para deshabilitar el cifrado entre los nodos de trabajo, quite el script de inicialización de la configuración del clúster y reinicie el clúster.