Szyfrowanie ruchu między węzłami roboczymi klastra

Ważne

Przykładowy skrypt inicjalizacyjny, do którego odwołuje się ten artykuł, wyprowadza współdzielony sekret szyfrowania ze skrótu magazynu kluczy przechowywanego w DBFS. Jeśli wykonasz rotację klucza tajnego, aktualizując plik magazynu kluczy w DBFS, należy ponownie uruchomić wszystkie działające klastry. W przeciwnym razie pracownicy platformy Spark mogą nie uwierzytelniać się za pomocą sterownika Spark z powodu niespójnego wspólnego wpisu tajnego, co powoduje spowolnienie zadań. Ponadto, ponieważ udostępniony wpis tajny jest przechowywany w systemie plików DBFS, każdy użytkownik z dostępem dbFS może pobrać wpis tajny przy użyciu notesu.

Alternatywnie można użyć Azure szyfrowania sieci wirtualnej, które automatycznie szyfruje ruch między Azure maszynami wirtualnymi bez konieczności dodatkowej konfiguracji.

Wymagania

  • Ta funkcja wymaga planu Premium. Aby uzyskać więcej informacji, skontaktuj się z zespołem ds. kont usługi Databricks.

Jak działa skrypt inicjowania

Ważne

Przykładowy skrypt inicjalizacyjny, do którego odwołuje się ten artykuł, wyprowadza współdzielony klucz tajny szyfrowania ze skrótu magazynu kluczy przechowywanego w DBFS. W przypadku rotacji wpisu tajnego przez zaktualizowanie pliku magazynu kluczy w systemie plików DBFS należy ponownie uruchomić wszystkie uruchomione klastry. W przeciwnym razie pracownicy platformy Spark mogą nie uwierzytelniać się za pomocą sterownika Spark z powodu niespójnego wspólnego wpisu tajnego, co powoduje spowolnienie zadań. Ponadto, ponieważ udostępniony wpis tajny jest przechowywany w systemie plików DBFS, każdy użytkownik z dostępem dbFS może pobrać wpis tajny przy użyciu notesu.

Zapytania użytkownika i przekształcenia są zazwyczaj wysyłane do Twoich klastrów przez zaszyfrowany kanał. Domyślnie jednak dane wymieniane pomiędzy węzłami roboczymi w klastrze nie są szyfrowane. Jeśli środowisko wymaga szyfrowania danych przez cały czas, zarówno magazynowanych, jak i przesyłanych, można utworzyć skrypt inicjowania, który konfiguruje klastry do szyfrowania ruchu między węzłami roboczymi przy użyciu szyfrowania AES 256-bitowego za pośrednictwem połączenia TLS 1.3.

Uwaga

Mimo że AES umożliwia kryptograficznym rutynom korzystanie z przyspieszania sprzętowego, istnieje strata wydajności w porównaniu z niezaszyfrowanym ruchem. Ta kara może spowodować, że zapytania będą trwać dłużej w zaszyfrowanym klastrze, w zależności od ilości danych przetasowanych między węzłami.

Włączenie szyfrowania ruchu między węzłami procesu roboczego wymaga ustawienia parametrów konfiguracji platformy Spark za pomocą skryptu inicjowania. Możesz użyć skryptu inicjowania na poziomie klastra dla pojedynczego klastra lub dodać skrypt inicjowania na poziomie klastra do zasad klastra, jeśli chcesz, aby wszystkie klastry w obszarze roboczym korzystały z szyfrowania komunikacji między procesami roboczymi.

Jednorazowo skopiuj plik keystore do katalogu w DBFS. Następnie utwórz skrypt inicjowania, który stosuje ustawienia szyfrowania.

Skrypt inicjowania musi wykonywać następujące zadania:

  1. Pobierz plik i hasło magazynu kluczy JKS.
  2. Ustaw konfigurację funkcji wykonawczej platformy Spark.
  3. Ustaw konfigurację sterownika platformy Spark.

Uwaga

Plik magazynu kluczy JKS używany do włączania protokołu SSL/HTTPS jest generowany dynamicznie dla każdego obszaru roboczego. Hasło pliku magazynu kluczy JKS jest zakodowane na stałe i nie jest przeznaczone do ochrony poufności magazynu kluczy.

Poniżej przedstawiono przykładowy skrypt inicjowania, który implementuje te trzy zadania w celu wygenerowania konfiguracji szyfrowania klastra.

Przykładowy skrypt inicjowania

#!/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"

Po zakończeniu inicjowania sterownika i węzłów roboczych cały ruch między tymi węzłami jest szyfrowany przy użyciu pliku magazynu kluczy.

Przykład notatnika: instalowanie skryptu inicjalizacyjnego szyfrowania

Poniższy notatnik kopiuje plik magazynu kluczy i generuje skrypt inicjalizacyjny w systemie plików DBFS. Skrypt inicjowania umożliwia tworzenie nowych klastrów z włączonym szyfrowaniem.

Zainstaluj notatnik skryptu init szyfrowania

Pobierz notes

Wyłącz szyfrowanie między węzłami roboczymi

Aby wyłączyć szyfrowanie między węzłami procesu roboczego, usuń skrypt inicjowania z konfiguracji klastra, a następnie uruchom ponownie klaster.