クラスター ワーカー ノード間のトラフィックを暗号化する

重要

この記事で参照されている init スクリプトの例では、DBFS に格納されているキーストアのハッシュから共有暗号化シークレットが引き出されます。 DBFS でキーストア ファイルを更新してシークレットをローテーションする場合は、実行中のすべてのクラスターを再起動する必要があります。 そうしないと、一貫性のない共有シークレットが原因で、Spark ワーカーによる Spark ドライバーを使用した認証が失敗し、ジョブの速度が低下する可能性があります。 その上、共有シークレットが DBFS に格納されるため、DBFS へのアクセス権を持つすべてのユーザーが、ノートブックを使用してシークレットを取得できます。

必要条件

  • この機能を使用するには、Premium プランが必要です。 詳細については、Databricks アカウント チームにお問い合わせください。

init スクリプトのしくみ

重要

この記事で参照されている init スクリプトの例では、DBFS に格納されているキーストアのハッシュから共有暗号化シークレットが引き出されます。 DBFS でキーストア ファイルを更新してシークレットをローテーションする場合は、実行中のすべてのクラスターを再起動する必要があります。 そうしないと、一貫性のない共有シークレットが原因で、Spark ワーカーによる Spark ドライバーを使用した認証が失敗し、ジョブの速度が低下する可能性があります。 その上、共有シークレットが DBFS に格納されるため、DBFS へのアクセス権を持つすべてのユーザーが、ノートブックを使用してシークレットを取得できます。

ユーザー クエリと変換は、通常、暗号化されたチャンネルを使用してクラスターに送信されます。 ただし、既定では、クラスターのワーカー ノード間で交換されるデータは暗号化されません。 環境の要件として、保存時や転送時にデータを常時暗号化する必要がある場合は、TLS 1.3 接続で AES 256 ビット暗号化を使用して、ワーカー ノード間のトラフィックを暗号化するようにクラスターを構成する init スクリプトを作成できます。

Note

AES では、ハードウェア アクセラレーションを利用するために、暗号化ルーチンが有効にされますが、暗号化されていないトラフィックと比較してパフォーマンスの点でペナルティが発生します。 このペナルティにより、ノード間でシャッフルされるデータ量によっては、暗号化されたクラスターではクエリに時間がかかる可能性があります。

ワーカー ノード間のトラフィックの暗号化を有効にする場合は、init スクリプトを使用して Spark 構成パラメーターを設定する必要があります。 ワークスペース内のすべてのクラスターでワーカー間暗号化を使用する場合は、1 つのクラスターに対してクラスター スコープの init スクリプトを使用するか、またはクラスター ポリシーにクラスター スコープの init スクリプトを追加します。

キーストア ファイルを DBFS 内のディレクトリに、一度、コピーします。 次に、暗号化設定を適用する init スクリプトを作成します。

init スクリプトでは、次のタスクを実行する必要があります。

  1. JKS キーストア ファイルとパスワードを取得します。
  2. Spark エグゼキューターの構成を設定します。
  3. Spark ドライバーの構成を設定します。

Note

SSL/HTTPS の有効化に使用される JKS キーストア ファイルは、ワークスペースごとに動的に生成されます。 JKS キーストア ファイルのパスワードはハードコーディングされます。また、キーストアの機密性を保護するためのものではありません。

クラスター暗号化構成を生成するための、これら 3 つのタスクを実装する init スクリプトの例を次に示します。

init スクリプトの例

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

ドライバーノードとワーカー ノードの初期化が完了すると、これらのノード間のすべてのトラフィックがキーストア ファイルを使用して暗号化されます。

ノートブックの例: 暗号化 init スクリプトをインストールする

次のノートブックでは、キーストア ファイルがコピーされ、DBFS で init スクリプトが生成されます。 init スクリプトを使用して、暗号化を有効にした新しいクラスターを作成できます。

暗号化 init スクリプト ノートブックをインストールする

ノートブックを入手

ワーカー ノード間の暗号化を無効にする

ワーカー ノード間の暗号化を無効にするには、クラスター構成から init スクリプトを削除してから、クラスターを再起動します。