# セキュリティ設計書

## 概要

本ドキュメントは、Apache Sparkプロジェクトにおけるセキュリティ設計を記述する。Sparkは分散データ処理フレームワークであり、ネットワーク認証、ACLベースのアクセス制御、通信暗号化（SSL/TLS）、IOデータ暗号化、Kerberos連携、Web UIのXSS/クリックジャッキング対策など、多層的なセキュリティ機構を備えている。セキュリティ機能の中核は `SecurityManager` クラスが担い、各コンポーネントは `SparkConf` の設定値によりセキュリティ動作を制御する。

## 認証設計

### 認証方式

Sparkは以下の認証方式を提供する。

1. **共有秘密鍵ベースのネットワーク認証（SASL/AES）**
   - `spark.authenticate` を `true` に設定することで、ノード間通信に共有秘密鍵（Shared Secret）による認証を有効化する。
   - 秘密鍵は `SecureRandom` を使用して生成される（デフォルト256ビット、`spark.authenticate.secretBitLength` で設定可能）。生成には `Utils.createSecret()` メソッドが使用され、暗号論的に安全な乱数生成器 (`java.security.SecureRandom`) を利用する。
   - 秘密鍵の提供方法: Hadoop UGIの `Credentials`、環境変数 `_SPARK_AUTH_SECRET`、設定値 `spark.authenticate.secret`、またはファイル（Kubernetesモード時のみ `spark.authenticate.secret.file`）。
   - SASL認証ユーザは固定値 `sparkSaslUser` が使用される。

2. **Kerberos認証（Hadoop統合）**
   - `HadoopDelegationTokenManager` を通じてKerberosベースの認証を提供する。
   - `spark.kerberos.principal` と `spark.kerberos.keytab` を指定することで、KDCへの自動ログインと委任トークンの取得・更新を行う。
   - TGT（Ticket Granting Ticket）の自動更新は `spark.kerberos.relogin.period` で制御される。
   - 委任トークンは元のトークンの有効期間の75%（`spark.credentials.renewalRatio` で設定可能）経過時に自動更新される。
   - `spark.kerberos.renewal.credentials` の設定により、`keytab` または `ccache`（クレデンシャルキャッシュ）ベースの更新が可能。

3. **ソケット認証（外部プロセス間通信）**
   - `SocketAuthHelper` クラスにより、JVMと外部プロセス（Python、R等）間のソケット通信に対する認証を提供する。
   - 認証プロトコル: クライアントが秘密鍵をソケットに書き込み、サーバ側が検証後 `ok` または `err` を返却する。
   - 認証タイムアウト: 10秒（ソケットタイムアウト）。
   - Unixドメインソケット使用時（`spark.python.unix.domain.socket.enabled`）は認証をスキップする（ローカル通信のためOSレベルで保護）。

### セッション管理

| 項目 | 設定値 | 備考 |
| --- | --- | --- |
| ソケット認証タイムアウト | 10秒 | `SocketAuthHelper` のクライアント認証時のソケットタイムアウト |
| SocketAuthServer接続タイムアウト | `spark.python.authenticate.socketTimeout` | 外部プロセスからの接続待ちタイムアウト（デフォルト15秒） |
| Kerberos TGT更新間隔 | `spark.kerberos.relogin.period` | KDCへのTGT再認証間隔 |
| 委任トークン更新比率 | `spark.credentials.renewalRatio`（デフォルト0.75） | トークン有効期間の75%経過時に更新 |
| Jetty Idle Timeout | 8000ミリ秒 | Slow DoS攻撃防止のためのアイドルタイムアウト（SPARK-45248） |

## 認可設計

### 権限体系

| ロール | 権限 | 説明 |
| --- | --- | --- |
| Admin | View + Modify + Impersonate | `spark.admin.acls` / `spark.admin.acls.groups` で指定。全権限を持ち、他ユーザへのなりすまし（doAsパラメータ）も許可される |
| View | UIの閲覧 | `spark.ui.view.acls` / `spark.ui.view.acls.groups` で指定。Spark UIの閲覧が可能 |
| Modify | アプリケーションの操作 | `spark.modify.acls` / `spark.modify.acls.groups` で指定。アプリケーションのKill等の操作が可能 |
| Default User | View + Modify | 現在のOSユーザ（`System.getProperty("user.name")`）およびSPARK_USERは自動的にView/Modify権限を付与される |
| ワイルドカード (*) | 全ユーザ許可 | ACLに `*` を指定すると全ユーザにアクセスを許可 |

### アクセス制御

- **ACLベースのアクセス制御**: `spark.acls.enable` を `true` に設定することで、ユーザ/グループベースのACLによるアクセス制御を有効化する。デフォルトは `false`（無効）。
- **ACL判定ロジック** (`SecurityManager.isUserInACL`):
  1. ユーザが `null` の場合: 認証が無効とみなし、アクセスを許可。
  2. ACLが無効（`spark.acls.enable=false`）の場合: 全ユーザにアクセスを許可。
  3. ACLユーザリストにワイルドカード `*` が含まれる場合: 全ユーザにアクセスを許可。
  4. ACLユーザリストに対象ユーザが含まれる場合: アクセスを許可。
  5. ACLグループリストにワイルドカード `*` が含まれる場合: 全ユーザにアクセスを許可。
  6. 上記のいずれでもない場合: ユーザが所属するグループを取得し、ACLグループリストと照合する。
- **グループ解決**: `GroupMappingServiceProvider` トレイトに基づくプラガブルな実装。デフォルトは `ShellBasedGroupsMappingProvider`（`id -Gn` コマンドでUNIXグループを取得）。`spark.user.groups.mapping` で変更可能。
- **Impersonation（なりすまし）**: `doAs` パラメータによるプロキシサーバ経由のユーザなりすましは、Admin権限を持つユーザのみが実行可能（`HttpSecurityFilter` で検証）。
- **Master UI Decommission制御**: `spark.master.ui.decommission.allow.mode` により、Worker Kill操作のアクセス元を `LOCAL`（ローカルIPのみ）、`DENY`（完全無効）、`ALLOW`（全IP許可）で制御できる。

## 通信セキュリティ

| 項目 | 対策 |
| --- | --- |
| HTTPS | `SSLOptions` による包括的なSSL/TLS設定。`spark.ssl.enabled` で有効化。Jetty `SslContextFactory` を使用してHTTPSを提供。HTTPS有効時はHTTPからHTTPSへの自動リダイレクトを実施（`HttpsRedirectFilter`） |
| HSTS | `spark.ui.strictTransportSecurity` でHTTP Strict Transport Securityヘッダ値を設定可能。HTTPSスキーム時のみ `Strict-Transport-Security` ヘッダを付与 |
| RPC SSL | `spark.ssl.rpc.enabled` でRPC通信のSSL暗号化を有効化。`SSLOptions` の各種設定（keyStore、trustStore、protocol、enabledAlgorithms等）でカスタマイズ可能 |
| ネットワーク暗号化 | `spark.network.crypto.enabled` でAESベースのネットワーク暗号化を有効化（RPC SSLと排他的。RPC SSL有効時はネットワーク暗号化は無効化される） |
| SASL暗号化 | `spark.authenticate.enableSaslEncryption` でSASLベースの暗号化を有効化（ネットワーク暗号化の一種） |
| サーバ情報秘匿 | `httpConfig.setSendServerVersion(false)` および `httpConfig.setSendXPoweredBy(false)` により、JettyサーバのバージョンおよびX-Powered-Byヘッダを秘匿 |
| TRACE無効化 | `doTrace` メソッドをオーバーライドし、HTTP TRACEメソッドを `405 Method Not Allowed` で拒否（SPARK-5983） |
| mTLS | `spark.ssl.[module].needClientAuth=true` 設定によりクライアント証明書認証（相互TLS）をサポート |

## データセキュリティ

### 暗号化

| 対象 | 暗号化方式 |
| --- | --- |
| 通信（RPC） | SSL/TLS（`SSLOptions`、`spark.ssl.rpc.enabled`）。プロトコルおよび暗号スイートの指定が可能（`spark.ssl.[module].protocol`、`spark.ssl.[module].enabledAlgorithms`）。OpenSSL実装への切り替え対応あり（`spark.ssl.[module].openSslEnabled`） |
| 通信（ネットワーク） | AESベースの暗号化（`spark.network.crypto.enabled`）。SASLフォールバック対応（`spark.network.crypto.saslFallback`） |
| 保存データ（IO暗号化） | AES/CTR/NoPadding（`spark.io.crypto.cipher.transformation`）。`spark.io.encryption.enabled` で有効化。鍵サイズは128/192/256ビット（`spark.io.encryption.keySizeBits`、デフォルト128ビット）。鍵生成アルゴリズムは `HmacSHA1`（`spark.io.encryption.keygen.algorithm`）。`CryptoStreamUtils` がApache Commons Cryptoライブラリを使用してストリーム暗号化/復号を提供。初期化ベクトル（IV）は16バイトで `CryptoRandomFactory` により安全に生成される |

### 機密情報管理

- **秘密情報の秘匿（Redaction）**: `spark.redaction.regex` パターン（デフォルト: `(?i)secret|password|token|access[.]?key`）に一致する設定キーの値は、UIおよびログにおいて `*********(redacted)` にマスキングされる。`spark.redaction.string.regex` により文字列内の部分的なマスキングも可能。
- **SSLパスワードの秘匿**: `SSLOptions.toString` においてパスワード関連フィールド（`keyStorePassword`、`keyPassword`、`privateKeyPassword`、`trustStorePassword`）は `xxx` にマスキングされてログ出力される。
- **RPC SSLパスワードの環境変数伝播**: SSLパスワードは環境変数（`_SPARK_SSL_RPC_KEY_PASSWORD` 等）を通じてExecutorに伝播され、設定ファイルへの平文保存を回避する。
- **秘密鍵ファイルの制限**: ファイルベースの秘密鍵（`spark.authenticate.secret.file`）はKubernetesモードでのみ許可される。
- **JVMセキュリティ設定の同期**: `SecurityConfigurationLock` オブジェクトにより、グローバルJVMセキュリティ設定の変更時にレースコンディションを防止する。

## 入出力対策

| 脅威 | 対策 |
| --- | --- |
| XSS | `HttpSecurityFilter` 内の `XssSafeRequest` クラスにより、全リクエストパラメータに対して: (1) 改行文字およびシングルクォートの除去（`(?i)(\r\n|\n|\r|%0D%0A|%0A|%0D|'|%27)` パターン）、(2) `StringEscapeUtils.escapeHtml4` によるHTMLエスケープを実施。`X-XSS-Protection: 1; mode=block` レスポンスヘッダを設定（`spark.ui.xXssProtection`）。`X-Content-Type-Options: nosniff` ヘッダを設定（`spark.ui.xContentTypeOptions.enabled`）。`Content-Security-Policy: default-src 'self'` ヘッダを設定 |
| SQLインジェクション | Sparkは直接的にユーザ入力からSQLを組み立てるWebアプリケーションではないため、従来型のSQLインジェクション対策は該当しない。Spark SQLのクエリはプログラムAPIまたはDataFrame APIを通じて構築される |
| CSRF | 明示的なCSRFトークン機構はコード上確認されない。Web UIはデフォルトでGETリクエストのみを処理し、TRACEメソッドは無効化されている。`X-Frame-Options` ヘッダによるクリックジャッキング対策は実装されている |
| クリックジャッキング | `X-Frame-Options` レスポンスヘッダを設定（デフォルト `SAMEORIGIN`）。`spark.ui.allowFramingFrom` で特定URIからのフレーミングを許可可能（SPARK-10589） |
| キャッシュ制御 | `Cache-Control: no-cache, no-store, must-revalidate` ヘッダを全レスポンスに設定 |

## 監査ログ

| ログ種別 | 記録内容 | 保持期間 |
| --- | --- | --- |
| イベントログ（EventLog） | アプリケーションの起動、ジョブ/ステージの開始・完了、Executor追加・削除、ブロック更新等のSparkイベント。`spark.eventLog.enabled` で有効化。出力先は `spark.eventLog.dir` で指定 | 設定による（Spark History Serverの保持設定に依存） |
| セキュリティ認証ログ | 認証の有効/無効状態、ACL設定変更、View/Modify ACLのユーザ/グループリスト、RPC SSLの有効/無効状態がINFOレベルで記録される（`SecurityManager` 初期化時） | アプリケーションログの保持ポリシーに依存 |
| ACL変更ログ | View ACL、Modify ACL、Admin ACL、及びそれらのグループACLの変更がINFOレベルで記録される | アプリケーションログの保持ポリシーに依存 |
| Kerberos認証ログ | KDCへのログイン試行・成功、委任トークンの更新、更新スケジュールがINFOレベルで記録される | アプリケーションログの保持ポリシーに依存 |
| 機密情報秘匿 | `spark.redaction.regex` パターンに一致する設定値はログ出力時に自動マスキングされる | N/A |

## 備考

- **SSL設定のモジュール構成**: SSL設定は `spark.ssl` をデフォルトとし、`spark.ssl.rpc` 等のモジュール固有設定で上書き可能な階層構造を持つ。RPC SSLのみ、後方互換性のためデフォルトの `enabled` 設定を継承しない。
- **Trust Store動的更新**: `spark.ssl.[module].trustStoreReloadingEnabled` を有効にすることで、Trust Storeファイルの変更を動的に検知・再読込可能（デフォルト更新間隔: 10000ミリ秒）。
- **Slow DoS対策**: JettyコネクタのアイドルタイムアウトをSPARK-45248の対策として8000ミリ秒に設定し、Slow DoS攻撃を軽減。
- **CORS設定**: コード解析の範囲では、明示的なCORS（Cross-Origin Resource Sharing）設定は確認されなかった。
- **Content-Security-Policy**: `default-src 'self'` が設定されており、外部リソースの読み込みを制限している。
- **委任トークンプロバイダ**: `HadoopDelegationTokenProvider` インタフェースに基づくプラガブルな委任トークン取得機構を持ち、HBase（`HBaseDelegationTokenProvider`）やHadoopファイルシステム（`HadoopFSDelegationTokenProvider`）等のサービス向け委任トークンを管理する。各プロバイダは `spark.security.credentials.{service}.enabled` で個別に有効/無効を制御できる。
