Spark セキュリティ
- Spark セキュリティ: 知っておくべきこと
- Spark RPC(Spark プロセス間の通信プロトコル)
- ネットワーク暗号化
- ローカルストレージ暗号化
- Web UI
- ネットワークセキュリティのためのポート設定
- Kerberos
- イベントログ
- クライアントモードでのドライバログの永続化
Spark セキュリティ: 知っておくべきこと
認証などのセキュリティ機能はデフォルトでは有効になっていません。インターネットや信頼できないネットワークに公開されているクラスタを展開する場合、不正なアプリケーションがクラスタ上で実行されるのを防ぐために、クラスタへのアクセスを保護することが重要です。
Spark は複数のデプロイメントタイプをサポートしており、それぞれが異なるレベルのセキュリティをサポートしています。すべてのデプロイメントタイプがすべての環境で安全であるわけではなく、デフォルトではどれも安全ではありません。ご自身の環境、Spark がサポートしていること、および Spark デプロイメントを保護するために適切な措置を講じていることを確認してください。
セキュリティ上の懸念は様々です。Spark は必ずしもすべてに対処するわけではありません。以下に Spark がサポートしているものをいくつか示します。使用しているデプロイメントタイプのデプロイメントドキュメントも、デプロイメント固有の設定について確認してください。ドキュメントに記載されていないものは、Spark はサポートしていません。
Spark RPC(Spark プロセス間の通信プロトコル)
認証
Spark は現在、共有シークレットを使用した RPC チャネルの認証をサポートしています。認証は、`spark.authenticate` 設定パラメータを設定することで有効にできます。
共有シークレットの生成と配布に使用される正確なメカニズムは、デプロイメント固有です。以下に指定されていない限り、`spark.authenticate.secret` 設定オプションを設定することでシークレットを定義する必要があります。この場合、同じシークレットがすべての Spark アプリケーションとデーモンによって共有されるため、特にマルチテナントクラスタでのこれらのデプロイメントのセキュリティが制限されます。
REST Submission Server は、`JWSFilter` を介した暗号学的に署名された JSON Web Token による HTTP `Authorization` ヘッダーをサポートしています。認可を有効にするには、Spark Master で `spark.master.rest.filters=org.apache.spark.ui.JWSFilter` および `spark.org.apache.spark.ui.JWSFilter.param.secretKey=BASE64URL-ENCODED-KEY` の設定が必要であり、クライアントは共有シークレットキーで署名された JSON Web Token を含む HTTP `Authorization` ヘッダーを提供する必要があります。
YARN
Spark on YARN の場合、Spark は共有シークレットの生成と配布を自動的に処理します。各アプリケーションは一意の共有シークレットを使用します。YARN の場合、この機能はシークレットの配布を安全に行うために YARN RPC 暗号化が有効になっていることに依存します。
| プロパティ名 | デフォルト | 意味 | バージョン以降 |
|---|---|---|---|
spark.yarn.shuffle.server.recovery.disabled |
false | セキュリティ要件が高いアプリケーションで、シークレットが DB に保存されるのを避けたい場合に true に設定します。このようなアプリケーションのシャッフルデータは、External Shuffle Service が再起動されても復旧されません。 | 3.5.0 |
Kubernetes
Kubernetes では、Spark は各アプリケーションに固有の認証シークレットを自動的に生成します。シークレットは環境変数を通じてエグゼキュータポッドに伝播されます。これは、Spark アプリケーションが実行されている名前空間のポッドを一覧表示できるユーザーは誰でも、認証シークレットを閲覧できることを意味します。Spark 認証が安全であることを保証するためには、Kubernetes 管理者によってアクセス制御ルールが適切に設定されている必要があります。
| プロパティ名 | デフォルト | 意味 | バージョン以降 |
|---|---|---|---|
spark.authenticate |
false | Spark が内部接続を認証するかどうか。 | 1.0.0 |
spark.authenticate.secret |
なし | 認証に使用されるシークレットキー。この設定を設定すべき時期については、上記を参照してください。 | 1.0.0 |
あるいは、ユーザーがポッドにマウントするファイルや Kubernetes シークレットを使用して認証シークレットをマウントすることもできます。
| プロパティ名 | デフォルト | 意味 | バージョン以降 |
|---|---|---|---|
spark.authenticate.secret.file |
なし | 接続の保護に使用するシークレットキーのパス。ファイルの内容が安全に生成されていることを確認してください。このファイルは、他の設定で上書きされない限り、ドライバとエグゼキュータの両方でロードされます(下記参照)。 | 3.0.0 |
spark.authenticate.secret.driver.file |
spark.authenticate.secret.file の値 |
指定された場合、Spark ドライバがシークレットをロードするために読み込む場所を上書きします。クライアントモードで、ドライバが実行されているノードとポッドでシークレットファイルの場所が異なる場合に役立ちます。これが指定されている場合、ドライバとエグゼキュータの両方がファイルを使用してシークレットキーをロードできるように、`spark.authenticate.secret.executor.file` を指定する必要があります。ドライバのファイルの内容がエグゼキュータのファイルの内容と同一であることを確認してください。 | 3.0.0 |
spark.authenticate.secret.executor.file |
spark.authenticate.secret.file の値 |
指定された場合、Spark エグゼキュータがシークレットをロードするために読み込む場所を上書きします。クライアントモードで、ドライバが実行されているノードとポッドでシークレットファイルの場所が異なる場合に役立ちます。これが指定されている場合、ドライバとエグゼキュータの両方がファイルを使用してシークレットキーをロードできるように、`spark.authenticate.secret.driver.file` を指定する必要があります。ドライバのファイルの内容がエグゼキュータのファイルの内容と同一であることを確認してください。 | 3.0.0 |
ファイルを使用する場合、Spark はこれらのファイルをコンテナにマウントしないことに注意してください。シークレットファイルがコンテナに安全にデプロイされており、ドライバのシークレットファイルがエグゼキュータのシークレットファイルと一致することを確認するのはユーザーの責任です。
ネットワーク暗号化
Spark は RPC 接続に対して、互いに排他的な 2 つの暗号化方式をサポートしています。
**推奨される方法**は、Netty の SSL サポートを介した TLS (SSL とも呼ばれる) 暗号化を使用します。SSL を有効にするには、キーと証明書を適切に設定する必要があります。SSL は標準化されており、より安全と考えられています。
レガシー方法は、共有シークレットに依存する AES ベースの暗号化メカニズムです。これには RPC 認証も有効になっている必要があります。この方法では独自のプロトコルを使用しており、代わりに SSL の使用が推奨されます。
コンプライアンスが特定のプロトコルの使用を義務付けている場合、またはより標準的な暗号化ライブラリのセキュリティを活用したいシナリオでは、SSL ベースの暗号化の使用を好む場合があります。ただし、AES ベースの暗号化は設定が簡単であり、データが転送中に暗号化されることだけが要件である場合に好ましい場合があります。
両方のオプションが設定で有効になっている場合、SSL ベースの RPC 暗号化が優先され、AES ベースの暗号化は使用されません(警告メッセージが表示されます)。
SSL 暗号化(推奨)
Spark は RPC 接続に SSL ベースの暗号化をサポートしています。設定方法については、以下の「SSL 設定」セクションを参照してください。SSL 設定は UI と RPC でほぼ同様ですが、RPC 実装に固有の追加設定がいくつかあります。RPC 実装は内部的に Netty を使用しています(UI は Jetty を使用)が、これは異なるオプションセットをサポートしています。
UI の他の SSL 設定とは異なり、`spark.ssl.enabled` が設定されていても、RPC SSL は自動的には有効になりません。安全な移行パスを確保するために、明示的に有効にする必要があります。
AES ベースの暗号化(レガシー)
Spark は RPC 接続に AES ベースの暗号化をサポートしています。暗号化を有効にするには、RPC 認証を有効にして適切に設定する必要があります。AES 暗号化は Apache Commons Crypto ライブラリを使用しており、Spark の設定システムは高度なユーザーがそのライブラリの設定にアクセスできるようにします。
このレガシープロトコルには、互換性のない 2 つのバージョンがあります。バージョン 1 は、キー交換プロトコルの出力にキー導出関数(KDF)を適用しませんが、バージョン 2 は KDF を適用して、導出されたセッションキーが一様に分散されるようにします。バージョン 1 は後方互換性のためにデフォルトです。セキュリティプロパティを向上させるために、**バージョン 2 の使用を推奨します**。バージョンは、`spark.network.crypto.authEngineVersion` をそれぞれ 1 または 2 に設定することで構成できます。
SASL ベースの暗号化のサポートもありますが、これは非推奨と見なされるべきです。Spark バージョン 2.2.0 より古いバージョンのシャッフルサービスと通信する際には、まだ必要です。
次の表は、この機能の設定に利用できるさまざまなオプションを説明しています。
| プロパティ名 | デフォルト | 意味 | バージョン以降 |
|---|---|---|---|
spark.network.crypto.enabled |
false | AES ベースの RPC 暗号化を有効にします。これには 2.2.0 で追加された新しい認証プロトコルが含まれます。 | 2.2.0 |
spark.network.crypto.cipher |
AES/CTR/NoPadding | 使用する暗号モード。デフォルトは後方互換性のために "AES/CTR/NoPadding" ですが、これは認証されません。認証された暗号モードである "AES/GCM/NoPadding" の使用を推奨します。 | 4.0.0, 3.5.2, 3.4.4 |
spark.network.crypto.authEngineVersion |
1 | 使用する AES ベースの RPC 暗号化のバージョン。有効なバージョンは 1 または 2 です。バージョン 2 を推奨します。 | 4.0.0 |
spark.network.crypto.config.* |
なし | 使用する暗号化実装など、commons-crypto ライブラリの設定値。設定名は `commons.crypto` 接頭辞なしの commons-crypto 設定名である必要があります。 | 2.2.0 |
spark.network.crypto.saslFallback |
true | Spark の内部メカニズムを使用して認証に失敗した場合に、SASL 認証にフォールバックするかどうか。これは、アプリケーションが内部 Spark 認証プロトコルをサポートしていない古いシャッフルサービスに接続している場合に便利です。シャッフルサービス側でこの機能を無効にすると、古いクライアントからの認証がブロックされます。 | 2.2.0 |
spark.authenticate.enableSaslEncryption |
false | SASL ベースの暗号化通信を有効にする。 | 2.2.0 |
spark.network.sasl.serverAlwaysEncrypt |
false | SASL 認証を使用するポートの暗号化されていない接続を無効にします。これにより、認証が有効になっているが SASL ベースの暗号化を要求しないクライアントからの接続が拒否されます。 | 1.4.0 |
ローカルストレージ暗号化
Spark は、ローカルディスクに書き込まれる一時データの暗号化をサポートしています。これには、シャッフルファイル、シャッフルスピル、およびディスクに格納されるデータブロック(キャッシュとブロードキャスト変数両方)が含まれます。これには、`saveAsHadoopFile` や `saveAsTable` のような API を使用してアプリケーションによって生成された出力データを暗号化することは含まれません。また、ユーザーが明示的に作成した一時ファイルも含まれない場合があります。
以下の設定は、ディスクへの書き込みデータの暗号化を有効にするためのものです。
| プロパティ名 | デフォルト | 意味 | バージョン以降 |
|---|---|---|---|
spark.io.encryption.enabled |
false | ローカルディスク I/O 暗号化を有効にします。現在、すべてのモードでサポートされています。この機能を使用する場合は、RPC 暗号化を有効にすることを強く推奨します。 | 2.1.0 |
spark.io.encryption.keySizeBits |
128 | I/O 暗号化キーのサイズ(ビット)。サポートされている値は 128、192、256 です。 | 2.1.0 |
spark.io.encryption.keygen.algorithm |
HmacSHA1 | I/O 暗号化キーの生成に使用するアルゴリズム。サポートされているアルゴリズムは、Java Cryptography Architecture Standard Algorithm Name Documentation の KeyGenerator セクションに記載されています。 | 2.1.0 |
spark.io.encryption.commons.config.* |
なし | 使用する暗号化実装など、commons-crypto ライブラリの設定値。設定名は `commons.crypto` 接頭辞なしの commons-crypto 設定名である必要があります。 | 2.1.0 |
Web UI
認証と認可
Web UI の認証の有効化は、jakarta servlet filters を使用して行われます。デプロイしたい認証方式を実装したフィルタが必要です。Spark は組み込みの認証フィルタを提供していません。
Spark は、認証フィルタが存在する場合に UI へのアクセス制御もサポートしています。各アプリケーションは、独自のアクセス制御リスト(ACL)で構成できます。Spark は、「表示」権限(アプリケーションの UI を誰が見ることができるか)と「変更」権限(実行中のアプリケーションでジョブをキルするなどの操作を誰ができるか)を区別します。
ACL は、ユーザーまたはグループに対して構成できます。設定エントリはコンマ区切りのリストを受け入れるため、複数のユーザーまたはグループに目的の特権を与えることができます。これは、共有クラスタで実行し、自身が開始したものではないアプリケーションを監視する必要がある管理者または開発者のセットがいる場合に役立ちます。特定の ACL にワイルドカード(`*`)を追加すると、すべてのユーザーが対応する権限を持つことになります。デフォルトでは、アプリケーションを送信したユーザーのみが ACL に追加されます。
グループメンバーシップは、構成可能なグループマッピングプロバイダーを使用して確立されます。マッパーは、以下の表で説明されている `spark.user.groups.mapping` 設定オプションを使用して構成されます。
以下のオプションは、Web UI の認証を制御します。
| プロパティ名 | デフォルト | 意味 | バージョン以降 |
|---|---|---|---|
spark.ui.allowFramingFrom |
SAMEORIGIN |
X-Frame-Options を介して、特定の名前付き URI のフレーミングを許可します。デフォルトでは、同じオリジンからのみ許可します。 |
1.6.0 |
spark.ui.filters |
なし | Spark は、`org.apache.spark.ui.JWSFilter` を介した暗号学的に署名された JSON Web Token による HTTP `Authorization` ヘッダーをサポートしています。 フィルタの設定方法については、Spark UI の設定を参照してください。 |
1.0.0 |
spark.acls.enable |
false | UI ACL を有効にするかどうか。有効な場合、ユーザーがアプリケーションを表示または変更するアクセス権限を持っているかを確認します。これはユーザーが認証されている必要があるため、認証フィルタがインストールされていない場合、このオプションは何も行いません。 | 1.1.0 |
spark.admin.acls |
なし | Spark アプリケーションへの表示および変更アクセス権を持つユーザーのコンマ区切りリスト。 | 1.1.0 |
spark.admin.acls.groups |
なし | Spark アプリケーションへの表示および変更アクセス権を持つグループのコンマ区切りリスト。 | 2.0.0 |
spark.modify.acls |
なし | Spark アプリケーションへの変更アクセス権を持つユーザーのコンマ区切りリスト。 | 1.1.0 |
spark.modify.acls.groups |
なし | Spark アプリケーションへの変更アクセス権を持つグループのコンマ区切りリスト。 | 2.0.0 |
spark.ui.view.acls |
なし | Spark アプリケーションへの表示アクセス権を持つユーザーのコンマ区切りリスト。 | 1.0.0 |
spark.ui.view.acls.groups |
なし | Spark アプリケーションへの表示アクセス権を持つグループのコンマ区切りリスト。 | 2.0.0 |
spark.user.groups.mapping |
org.apache.spark.security.ShellBasedGroupsMappingProvider |
ユーザーのグループリストは、このプロパティで構成できる `org.apache.spark.security.GroupMappingServiceProvider` トレイトによって定義されるグループマッピングサービスによって決定されます。 デフォルトでは、Unix シェルベースの実装が使用され、ホスト OS からこの情報を収集します。 注意: この実装は Unix/Linux ベースの環境のみをサポートしています。Windows 環境は現在サポートされていません。ただし、上記のトレイトを実装することで、新しいプラットフォーム/プロトコルをサポートできます。 |
2.0.0 |
YARN では、表示および変更 ACL がアプリケーション送信時に YARN サービスに提供され、YARN インターフェイスを介して誰が対応する権限を持つかを制御します。
Spark History Server ACL
SHS Web UI の認証は、通常のアプリケーションと同様にサーブレットフィルタを使用して有効になります。
SHS で認可を有効にするには、いくつかの追加オプションが使用されます。
| プロパティ名 | デフォルト | 意味 | バージョン以降 |
|---|---|---|---|
spark.history.ui.acls.enable |
false | 履歴サーバーでアプリケーションを表示するユーザーを承認するために ACL をチェックするかどうかを指定します。有効な場合、個々のアプリケーションの `spark.ui.acls.enable` の設定に関係なく、アクセス制御チェックが実行されます。アプリケーションの所有者は、常に自身のアプリケーションを表示する権限を持ち、アプリケーションが実行されたときに `spark.ui.view.acls` および `spark.ui.view.acls.groups` 経由で指定されたユーザーおよびグループも、そのアプリケーションを表示する権限を持ちます。無効な場合、履歴サーバー経由で利用可能なアプリケーション UI に対してアクセス制御チェックは行われません。 | 1.0.1 |
spark.history.ui.admin.acls |
なし | 履歴サーバーのすべての Spark アプリケーションへの表示アクセス権を持つユーザーのコンマ区切りリスト。 | 2.1.1 |
spark.history.ui.admin.acls.groups |
なし | 履歴サーバーのすべての Spark アプリケーションへの表示アクセス権を持つグループのコンマ区切りリスト。 | 2.1.1 |
SHS は、通常のアプリケーションと同じオプションを使用してグループマッピングプロバイダーを構成します。この場合、グループマッピングプロバイダーは SHS によって提供されるすべての UI に適用され、個々のアプリケーションの設定は無視されます。
SSL 設定
SSL の設定は階層的に整理されています。ユーザーは、プロトコル固有の設定で上書きされない限り、すべてのサポートされている通信プロトコルに使用されるデフォルトの SSL 設定を構成できます。これにより、ユーザーは各プロトコルを個別に構成する能力を無効にすることなく、すべてのプロトコルに共通の設定を簡単に提供できます。ただし、`spark.ssl.rpc.enabled` を除くすべて設定はこのように継承されます。これは明示的に設定する必要があります。
次の表は、SSL 設定の名前空間を説明しています。
| 設定名前空間 | Component |
|---|---|
spark.ssl |
デフォルトの SSL 設定。これらの値は、名前空間レベルで明示的にオーバーライドされない限り、以下のすべての名前空間に適用されます。 |
spark.ssl.ui |
Spark アプリケーション Web UI |
spark.ssl.standalone |
スタンドアロンマスター/ワーカー Web UI |
spark.ssl.historyServer |
履歴サーバー Web UI |
spark.ssl.rpc |
Spark RPC 通信 |
利用可能な SSL オプションの完全な内訳は以下のとおりです。`${ns}` プレースホルダーは、上記のいずれかの名前空間に置き換える必要があります。
| プロパティ名 | デフォルト | 意味 | サポートされている名前空間 |
|---|---|---|---|
${ns}.enabled |
false | SSL を有効にします。有効な場合、`${ns}.ssl.protocol` が必要です。 | ui,standalone,historyServer,rpc |
${ns}.port |
なし | SSL サービスがリッスンするポート。 ポートは特定の名前空間設定内で定義する必要があります。デフォルトの名前空間は、この設定を読み取る際には無視されます。 設定されていない場合、SSL ポートは同じサービスで非 SSL ポートから派生します。"0" の値は、サービスがエフェメラルポートにバインドするようにします。 |
ui,standalone,historyServer |
${ns}.enabledAlgorithms |
なし | 暗号スイートのコンマ区切りリスト。指定された暗号スイートは JVM によってサポートされている必要があります。 プロトコルの参照リストは、Java セキュリティガイドの「JSSE Cipher Suite Names」セクションにあります。Java 17 のリストは、このページにあります。 注意: 設定されていない場合、JRE のデフォルトの暗号スイートが使用されます。 |
ui,standalone,historyServer,rpc |
${ns}.keyPassword |
なし | キーストア内の秘密鍵のパスワード。 | ui,standalone,historyServer,rpc |
${ns}.keyStore |
なし | キーストアファイルへのパス。パスは絶対パスまたはプロセスが開始されたディレクトリからの相対パスにできます。 | ui,standalone,historyServer,rpc |
${ns}.keyStorePassword |
なし | キーストアのパスワード。 | ui,standalone,historyServer,rpc |
${ns}.keyStoreType |
JKS | キーストアのタイプ。 | ui,standalone,historyServer |
${ns}.protocol |
なし | 使用する TLS プロトコル。プロトコルは JVM によってサポートされている必要があります。 プロトコルの参照リストは、Java セキュリティガイドの「Additional JSSE Standard Names」セクションにあります。Java 17 のリストは、このページにあります。 |
ui,standalone,historyServer,rpc |
${ns}.needClientAuth |
false | クライアント認証を要求するかどうか。 | ui,standalone,historyServer |
${ns}.trustStore |
なし | トラストストアファイルへのパス。パスは絶対パスまたはプロセスが開始されたディレクトリからの相対パスにできます。 | ui,standalone,historyServer,rpc |
${ns}.trustStorePassword |
なし | トラストストアのパスワード。 | ui,standalone,historyServer,rpc |
${ns}.trustStoreType |
JKS | トラストストアのタイプ。 | ui,standalone,historyServer |
${ns}.openSSLEnabled |
false | JDK SSL プロバイダーの代わりに OpenSSL を暗号化操作に使用するかどうか。この設定には `certChain` および `privateKey` 設定を設定する必要があります。両方が指定されている場合、これは `keyStore` および `trustStore` 設定よりも優先されます。実行時に OpenSSL ライブラリが利用できない場合、JDK プロバイダーにフォールバックします。 | rpc |
${ns}.privateKey |
なし | PEM 形式の秘密鍵ファイルへのパス。パスは絶対パスまたはプロセスが開始されたディレクトリからの相対パスにできます。この設定は、OpenSSL 実装を使用する場合に必要です。 | rpc |
${ns}.privateKeyPassword |
なし | 上記の PEM 形式の秘密鍵ファイルのパスワード。 | rpc |
${ns}.certChain |
なし | PEM 形式の証明書チェーンファイルへのパス。パスは絶対パスまたはプロセスが開始されたディレクトリからの相対パスにできます。この設定は、OpenSSL 実装を使用する場合に必要です。 | rpc |
${ns}.trustStoreReloadingEnabled |
false | トラストストアを定期的にリロードするかどうか。この設定は、主にスタンドアロンデプロイメントで役立ち、k8s や yarn デプロイメントでは役立ちません。 | rpc |
${ns}.trustStoreReloadIntervalMs |
10000 | トラストストアをリロードする間隔(ミリ秒)。この設定は、主にスタンドアロンデプロイメントで役立ち、k8s や yarn デプロイメントでは役立ちません。 | rpc |
Spark は、Hadoop Credential Providers から `${ns}.keyPassword`、`${ns}.keyStorePassword`、および `${ns}.trustStorePassword` を取得することもサポートしています。ユーザーはパスワードをクレデンシャルファイルに保存し、次のような異なるコンポーネントからアクセスできるようにできます。
hadoop credential create spark.ssl.keyPassword -value password \
-provider jceks://hdfs@nn1.example.com:9001/user/backup/ssl.jceks
クレデンシャルプロバイダーの場所を設定するには、Spark が使用する Hadoop 設定で `hadoop.security.credential.provider.path` 設定オプションを設定します。たとえば、
<property>
<name>hadoop.security.credential.provider.path</name>
<value>jceks://hdfs@nn1.example.com:9001/user/backup/ssl.jceks</value>
</property>
または SparkConf を介して `spark.hadoop.hadoop.security.credential.provider.path=jceks://hdfs@nn1.example.com:9001/user/backup/ssl.jceks`。
キーストアの準備
キーストアは `keytool` プログラムで生成できます。Java 17 のこのツールの参照ドキュメントはこちらです。Spark スタンドアロンデプロイメントモードのキーストアとトラストストアを設定するための最も基本的な手順は次のとおりです。
- 各ノードのキーペアを生成します。
- 各ノードのキーペアの公開鍵をファイルにエクスポートします。
- すべてのエクスポートされた公開鍵を 1 つのトラストストアにインポートします。
- トラストストアをクラスタノードに配布します。
YARN モード
クラスタモードで実行されているドライバにローカルトラストストアまたはキーストアファイルを提供するには、`--files` コマンドライン引数(または同等の `spark.files` 設定)を使用してアプリケーションとともに配布できます。ファイルはドライバの作業ディレクトリに配置されるため、TLS 設定は絶対パスなしでファイル名を参照するだけで十分です。
このようにローカルキーストアを配布するには、ファイルが HDFS(またはクラスタによって使用されるその他の同様の分散ファイルシステム)にステージングされる必要がある場合があります。そのため、基盤となるファイルシステムがセキュリティを考慮して設定されている(例: 暗号化とワイヤ暗号化を有効にする)ことをお勧めします。
スタンドアロンモード
ユーザーは、マスターおよびワーカーにキーストアと設定オプションを提供する必要があります。これらは、`SPARK_MASTER_OPTS` および `SPARK_WORKER_OPTS` 環境変数、または単に `SPARK_DAEMON_JAVA_OPTS` に適切な Java システムプロパティをアタッチすることによって設定する必要があります。
ユーザーは、エグゼキュータがワーカープロセスから継承された SSL 設定を使用できるようにすることができます。これは、`spark.ssl.useNodeLocalConf` を `true` に設定することによって達成できます。その場合、クライアント側でユーザーによって提供された設定は使用されません。
HTTP セキュリティヘッダー
Apache Spark は、クロスサイトスクリプティング(XSS)、クロスフレームスクリプティング(XFS)、MIME スニッフィングを防ぐための HTTP ヘッダーを含めるように構成でき、HTTP Strict Transport Security を強制することもできます。
| プロパティ名 | デフォルト | 意味 | バージョン以降 |
|---|---|---|---|
spark.ui.xXssProtection |
1; mode=block |
HTTP X-XSS-Protection レスポンスヘッダーの値。以下から適切な値を選択できます。
|
2.3.0 |
spark.ui.xContentTypeOptions.enabled |
true |
有効にすると、X-Content-Type-Options HTTP レスポンスヘッダーが "nosniff" に設定されます。 | 2.3.0 |
spark.ui.strictTransportSecurity |
なし | HTTP Strict Transport Security (HSTS) レスポンスヘッダーの値。以下から適切な値を選択し、expire-time をそれに応じて設定します。このオプションは、SSL/TLS が有効な場合にのみ使用されます。
|
2.3.0 |
ネットワークセキュリティのためのポート設定
一般的に、Spark クラスタとそのサービスは公開インターネット上にはデプロイされません。それらは通常プライベートサービスであり、Spark をデプロイした組織のネットワーク内からのみアクセス可能であるべきです。Spark サービスが使用するホストとポートへのアクセスは、サービスにアクセスする必要があるオリジンホストに制限されるべきです。
ただし、REST Submission ポートと同様に、Spark はすべての UI ポートに対しても、暗号学的に署名された JSON Web Token(JWT)による HTTP `Authorization` ヘッダーをサポートしています。これを使用するには、ユーザーは `spark.ui.filters=org.apache.spark.ui.JWSFilter` および `spark.org.apache.spark.ui.JWSFilter.param.secretKey=BASE64URL-ENCODED-KEY` を設定する必要があります。
以下は、Spark が通信に使用する主なポートとその設定方法です。
スタンドアロンモードのみ
| 送信元 | 宛先 | デフォルトポート | 目的 | 設定項目 | 注記 |
|---|---|---|---|---|---|
| ブラウザ | スタンドアロンマスター | 8080 | Web UI | spark.master.ui.port / |
Jetty ベース。スタンドアロンモードのみ。 |
| ブラウザ | スタンドアロンワーカー | 8081 | Web UI | spark.worker.ui.port / |
Jetty ベース。スタンドアロンモードのみ。 |
| ドライバ / スタンドアロンワーカー |
スタンドアロンマスター | 7077 | クラスタへのジョブ送信 / クラスタへの参加 |
SPARK_MASTER_PORT |
ランダムなポートを選択するには "0" に設定します。スタンドアロンモードのみ。 |
| 外部サービス | スタンドアロンマスター | 6066 | REST API を介したクラスタへのジョブ送信 | spark.master.rest.port |
このサービスを有効/無効にするには `spark.master.rest.enabled` を使用します。スタンドアロンモードのみ。 |
| スタンドアロンマスター | スタンドアロンワーカー | (ランダム) | エグゼキュータのスケジュール | SPARK_WORKER_PORT |
ランダムなポートを選択するには "0" に設定します。スタンドアロンモードのみ。 |
すべてのクラスタマネージャー
| 送信元 | 宛先 | デフォルトポート | 目的 | 設定項目 | 注記 |
|---|---|---|---|---|---|
| ブラウザ | アプリケーション | 4040 | Web UI | spark.ui.port |
Jetty ベース |
| ブラウザ | 履歴サーバー | 18080 | Web UI | spark.history.ui.port |
Jetty ベース |
| エグゼキュータ / スタンドアロンマスター |
ドライバ | (ランダム) | アプリケーションへの接続 / エグゼキュータ状態変更の通知 |
spark.driver.port |
ランダムなポートを選択するには "0" に設定します。 |
| エグゼキュータ / ドライバ | エグゼキュータ / ドライバ | (ランダム) | ブロックマネージャーポート | spark.blockManager.port |
ServerSocketChannel を介した生のソケット |
Kerberos
Spark は、Kerberos を認証に使用する環境にアプリケーションを送信することをサポートしています。ほとんどの場合、Spark は Kerberos 対応サービスへの認証時に現在ログインしているユーザーの資格情報に依存します。これらの資格情報は、`kinit` のようなツールを使用して、設定された KDC にログインすることで取得できます。
Hadoop ベースのサービスと通信する場合、Spark は非ローカルプロセスが認証できるように委任トークンを取得する必要があります。Spark は HDFS およびその他の Hadoop ファイルシステム、Hive、HBase をサポートしています。
Hadoop ファイルシステム(HDFS や WebHDFS など)を使用する場合、Spark はユーザーのホームディレクトリをホストするサービスに対応するトークンを取得します。
HBase がアプリケーションのクラスパスにあり、HBase 設定で Kerberos 認証が有効になっている場合(`hbase.security.authentication=kerberos`)、HBase トークンが取得されます。
同様に、Hive がクラスパスにあり、設定にリモートメタストアサービスの URI が含まれている場合(`hive.metastore.uris` が空でない)、Hive トークンが取得されます。
アプリケーションが他のセキュアな Hadoop ファイルシステムと対話する必要がある場合、その URI を起動時に Spark に明示的に提供する必要があります。これは、設定セクションで説明されている `spark.kerberos.access.hadoopFileSystems` プロパティにリストすることによって行われます。
Spark は、Java サービスメカニズム(`java.util.ServiceLoader` を参照)を使用したカスタム委任トークンプロバイダーもサポートしています。`org.apache.spark.security.HadoopDelegationTokenProvider` の実装は、JAR の `META-INF/services` ディレクトリにある対応するファイルに名前をリストすることで Spark で利用可能にできます。
委任トークンサポートは現在、YARN と Kubernetes モードでのみサポートされています。詳細については、デプロイメント固有のページを参照してください。
以下のオプションは、この機能のより詳細な制御を提供します。
| プロパティ名 | デフォルト | 意味 | バージョン以降 |
|---|---|---|---|
spark.security.credentials.${service}.enabled |
true |
セキュリティが有効になっている場合に、サービス用の資格情報を取得するかどうかを制御します。デフォルトでは、サポートされているすべてのサービスの資格情報は、これらのサービスが構成されている場合に取得されますが、実行中のアプリケーションと何らかの競合がある場合にその動作を無効にすることも可能です。 | 2.3.0 |
spark.kerberos.access.hadoopFileSystems |
(なし) | Spark アプリケーションがアクセスするセキュアな Hadoop ファイルシステムのコンマ区切りリスト。例: `spark.kerberos.access.hadoopFileSystems=hdfs://nn1.com:8032,hdfs://nn2.com:8032, webhdfs://nn3.com:50070`。Spark アプリケーションはリストされているファイルシステムにアクセスできる必要があり、Kerberos はそれらにアクセスできるように適切に構成されている必要があります(同じレルムまたは信頼されたレルム)。Spark は、各ファイルシステム用のセキュリティトークンを取得するため、Spark アプリケーションはこれらのリモート Hadoop ファイルシステムにアクセスできます。 | 3.0.0 |
ユーザーは、リソーススケジューラでの Kerberos 委任トークン更新を除外できます。現在、YARN のみでサポートされています。設定は、Spark on YARN の実行ページに記載されています。
長時間実行アプリケーション
長時間実行アプリケーションは、その実行時間がアクセスする必要のあるサービスで構成されている最大委任トークン有効期限を超えると、問題が発生する可能性があります。
この機能はすべての場所で利用できるわけではありません。特に、YARN と Kubernetes(クライアントモードとクラスタモードの両方)でのみ実装されています。
Spark は、これらのアプリケーションのために新しいトークンを自動的に作成することをサポートしています。この機能は 2 つの方法で有効にできます。
キータブの使用
Spark にプリンシパルとキータブを提供することによって(例: `--principal` および `--keytab` パラメータを使用した `spark-submit`)、アプリケーションは無期限に委任トークンを取得するために使用できる有効な Kerberos ログインを維持します。
クラスタモードでキータブを使用する場合、それは Spark ドライバを実行しているマシンにコピーされることに注意してください。YARN の場合、これはキータブのステージングエリアとして HDFS を使用することを意味するため、少なくとも YARN と HDFS の両方が暗号化で保護されていることを強く推奨します。
チケットキャッシュの使用
Spark の設定で `spark.kerberos.renewal.credentials` を `ccache` に設定することにより、ローカル Kerberos チケットキャッシュが認証に使用されます。Spark はチケットが更新可能な有効期限の間、チケットを更新しますが、有効期限が切れた後に新しいチケットを取得する必要があります(例: `kinit` を実行して)。
Spark が使用できる更新されたチケットキャッシュを維持するのはユーザーの責任です。
チケットキャッシュの場所は、`KRB5CCNAME` 環境変数を設定することでカスタマイズできます。
Kubernetes とのセキュアな連携
Kerberos の背後にある Hadoop ベースのサービスと通信する場合、Spark は非ローカルプロセスが認証できるように委任トークンを取得する必要があることが指摘されています。Kubernetes のこれらの委任トークンは、ドライバとそのエグゼキュータによって共有されるシークレットに格納されます。そのため、Kerberos ジョブを送信するには 3 つの方法があります。
すべての場合において、環境変数 `HADOOP_CONF_DIR` または `spark.kubernetes.hadoop.configMapName.` を定義する必要があります。
KDC がコンテナの内部から見えることも重要です。
ユーザーが Hadoop 設定ファイルを含むリモート `HADOOP_CONF` ディレクトリを使用したい場合、`spark.kubernetes.hadoop.configMapName` を既存の ConfigMap に設定することで達成できます。
- ローカルチケットキャッシュに TGT を格納する $kinit を使用して送信。
/usr/bin/kinit -kt <keytab_file> <username>/<krb5 realm> /opt/spark/bin/spark-submit \ --deploy-mode cluster \ --class org.apache.spark.examples.HdfsTest \ --master k8s://<KUBERNETES_MASTER_ENDPOINT> \ --conf spark.executor.instances=1 \ --conf spark.app.name=spark-hdfs \ --conf spark.kubernetes.container.image=spark:latest \ --conf spark.kubernetes.kerberos.krb5.path=/etc/krb5.conf \ local:///opt/spark/examples/jars/spark-examples_<VERSION>.jar \ <HDFS_FILE_LOCATION> - ローカルキータブとプリンシパルを使用して送信。
/opt/spark/bin/spark-submit \ --deploy-mode cluster \ --class org.apache.spark.examples.HdfsTest \ --master k8s://<KUBERNETES_MASTER_ENDPOINT> \ --conf spark.executor.instances=1 \ --conf spark.app.name=spark-hdfs \ --conf spark.kubernetes.container.image=spark:latest \ --conf spark.kerberos.keytab=<KEYTAB_FILE> \ --conf spark.kerberos.principal=<PRINCIPAL> \ --conf spark.kubernetes.kerberos.krb5.path=/etc/krb5.conf \ local:///opt/spark/examples/jars/spark-examples_<VERSION>.jar \ <HDFS_FILE_LOCATION> - 名前空間内にすでに存在する委任トークンを含む、事前に入力されたシークレットを使用して送信。
/opt/spark/bin/spark-submit \ --deploy-mode cluster \ --class org.apache.spark.examples.HdfsTest \ --master k8s://<KUBERNETES_MASTER_ENDPOINT> \ --conf spark.executor.instances=1 \ --conf spark.app.name=spark-hdfs \ --conf spark.kubernetes.container.image=spark:latest \ --conf spark.kubernetes.kerberos.tokenSecret.name=<SECRET_TOKEN_NAME> \ --conf spark.kubernetes.kerberos.tokenSecret.itemKey=<SECRET_ITEM_KEY> \ --conf spark.kubernetes.kerberos.krb5.path=/etc/krb5.conf \ local:///opt/spark/examples/jars/spark-examples_<VERSION>.jar \ <HDFS_FILE_LOCATION>
3b. (3) と同様に送信しますが、事前作成された krb5 ConfigMap および事前作成された `HADOOP_CONF_DIR` ConfigMap を指定します。
/opt/spark/bin/spark-submit \
--deploy-mode cluster \
--class org.apache.spark.examples.HdfsTest \
--master k8s://<KUBERNETES_MASTER_ENDPOINT> \
--conf spark.executor.instances=1 \
--conf spark.app.name=spark-hdfs \
--conf spark.kubernetes.container.image=spark:latest \
--conf spark.kubernetes.kerberos.tokenSecret.name=<SECRET_TOKEN_NAME> \
--conf spark.kubernetes.kerberos.tokenSecret.itemKey=<SECRET_ITEM_KEY> \
--conf spark.kubernetes.hadoop.configMapName=<HCONF_CONFIG_MAP_NAME> \
--conf spark.kubernetes.kerberos.krb5.configMapName=<KRB_CONFIG_MAP_NAME> \
local:///opt/spark/examples/jars/spark-examples_<VERSION>.jar \
<HDFS_FILE_LOCATION>
イベントログ
アプリケーションでイベントログ記録を使用している場合、イベントログが保存されるディレクトリ(`spark.eventLog.dir`)は、適切な権限で手動で作成する必要があります。ログファイルを保護するには、ディレクトリの権限を `drwxrwxrwxt` に設定する必要があります。ディレクトリの所有者とグループは、Spark History Server を実行しているスーパーユーザーに対応する必要があります。
これにより、すべてのユーザーがディレクトリに書き込むことができますが、特権のないユーザーは、それらを所有していない限り、ファイルを読み取ったり、削除したり、名前を変更したりすることはできません。イベントログファイルは、所有者とグループのみが読み書きアクセス権を持つような権限で Spark によって作成されます。
クライアントモードでのドライバログの永続化
アプリケーションで `spark.driver.log.persistToDfs.enabled` を有効にしてドライバログをクライアントモードで永続化する場合、ドライバログが保存されるディレクトリ(`spark.driver.log.dfsDir`)は、適切な権限で手動で作成する必要があります。ログファイルを保護するには、ディレクトリの権限を `drwxrwxrwxt` に設定する必要があります。ディレクトリの所有者とグループは、Spark History Server を実行しているスーパーユーザーに対応する必要があります。
これにより、すべてのユーザーがディレクトリに書き込むことができますが、特権のないユーザーは、それらを所有していない限り、ファイルを読み取ったり、削除したり、名前を変更したりすることはできません。ドライバログファイルは、所有者とグループのみが読み書きアクセス権を持つような権限で Spark によって作成されます。