オブジェクトストア監査

S3Aコネクタは、S3へのリクエストを監査するための拡張ポイントを提供します。監査は、すべてのFS操作のエントリポイントで、そしてAWS S3 SDK内で、リクエストが実行される直前に実行できます。

完全なアーキテクチャは監査アーキテクチャで説明されています。このドキュメントでは、その使用方法について説明します。

重要:監査はデフォルトで無効になっています

ThreadLocalフィールドの使用によるメモリリークのため、この監査機能は、S3Aファイルシステムインスタンスが作成および削除されるとメモリリークが発生していました。これは、ファイルシステムインスタンスを再利用しない、または特定のユーザーに属するすべてのインスタンスを削除しようとする長期実行プロセスで問題を引き起こしていました。HADOOP-18091 S3A監査はThreadLocal参照を介してメモリリークが発生しますを参照してください。

これらのメモリリークを回避するために、hadoop 3.3.2リリースでは、監査はデフォルトで無効化されました。

これらのメモリリークが修正されたため、監査が再び有効になりました。

無効にするには、fs.s3a.audit.enabledfalseに設定します。

監査ワークフロー

  1. 各S3A FileSystemインスタンスに対して、FSの初期化時に作成され、FSインスタンスが閉じられると閉じられる監査サービスをインスタンス化できます。
  2. S3A FSは、Hadoop FileSystem API呼び出しごとに、監査サービスから監査スパンを要求します。
  3. 監査スパンには、API呼び出しの実行中に呼び出された各S3操作(AWS SDK内から)中に呼び出されるコールバックがあります。
  4. これにより、監査サービスは、行われたリクエストをログに記録し、ユーザーと操作に関連付けることができます。
  5. および/または操作を拒否します。
  6. バンドルされた「ログ監査」は操作をログに記録し、HTTPリファラーヘッダーに関する情報を呼び出しに添付します。
  7. そのため、パフォーマンス、バケット負荷、S3コストなどに関連する問題のデバッグを支援します。

したがって、監査サービスをプラグインして、(ベストエフォートによる)監査とヒントによる許可/拒否セキュリティを提供できます。

  • ベストエフォートである理由:カバレッジは完全ではありません。以下の制限事項を参照してください。
  • 「ヒントによる」セキュリティである理由:JVMで実行されているカスタムコードは、AWS資格情報チェーンを取得して、この監査メカニズムをバイパスできます。

制限事項

これは、S3リソースへのアクセスを制御する手段ではありません。これは、FileSystem操作API呼び出しのログ記録をサポートするためのベストエフォートであり、特に、単一のFS API呼び出しで複数のオブジェクトリクエストをS3に関連付け、理想的には負荷を生成するプロセス/ジョブを識別することです。

  • 内部使用のみを目的としたパブリックS3Aメソッドを使用する低レベルコードは、スパンを作成しない場合があります。
  • AWS S3クライアントを要求するコードは、スパンの作成をバイパスする場合があります。
  • アプリケーションコードは、新しいS3クライアントを作成(既存の資格情報を再利用)して、S3への監査されていないアクセスを持つこともできます。
  • OpenTelemetryとの連携はありません。
  • TransferManagerによるアップロードとコピー操作は、作業がS3Aコードが更新できないスレッドで実行されるため、アクティブなスパンを取得しません。
  • HTTPリファラーヘッダーの長さには制限があります。長いパスの操作は、不完全にログに記録される場合があります。

監査の使用

監査はデフォルトで無効になっています。監査が有効になっている場合、ログ監査は、S3に行われたリクエストでカスタムHTTPリファラーヘッダーを通じてS3ログに注釈を付けます。代わりに他の監査クラスを使用することもできます。

監査オプション

オプション 意味 デフォルト値
fs.s3a.audit.enabled 監査は有効ですか? true
fs.s3a.audit.service.classname 監査クラス名 org.apache.hadoop.fs.s3a.audit.impl.LoggingAuditor
fs.s3a.audit.request.handlers ハンドラーチェーンに含めるAWS SDK RequestHandler2の追加サブクラスのリスト ""
fs.s3a.audit.referrer.enabled HTTPリファラーヘッダーに監査情報を公開するログ監査 true
fs.s3a.audit.referrer.filter フィルタリングする監査フィールドのリスト ""
fs.s3a.audit.reject.out.of.span.operations スパン外の操作を拒否する監査 false

監査の無効化

このHadoopリリースでは、監査は無効になっています。

これは、グローバルに、または特定のバケットに対して明示的に設定できます。

<property>
  <name>fs.s3a.audit.enabled</name>
  <value>false</value>
</property>

グローバルに有効になっている場合でも、特定のバケットで監査を無効にすることができます。

<property>
  <name>fs.s3a.bucket.landsat-pds.audit.enabled</name>
  <value>false</value>
  <description>Do not audit landsat bucket operations</description>
</property>

ログ監査を使用した監査

「ログ監査」はデフォルトの監査です。2種類のログを提供します。

  1. アクティブなslf4j実装を介したクライアントでの操作のログ記録。
  2. S3リクエストに対するHTTPリファラーヘッダーの動的生成。

ログ監査は、オプションfs.s3a.audit.service.classnameにクラス名を提供することで有効になります。

<property>
  <name>fs.s3a.audit.enabled</name>
  <value>true</value>
</property>

<property>
  <name>fs.s3a.audit.service.classname</name>
  <value>org.apache.hadoop.fs.s3a.audit.impl.LoggingAuditor</value>
</property>

ローカルクライアントログに監査イベントを出力するには、関連付けられたLog4Jログをデバッグでログに記録するように設定します。

# Auditing
log4j.logger.org.apache.hadoop.fs.s3a.audit.impl.LoggingAuditor=DEBUG

S3サーバーアクセスログとの統合

AWS S3バケットは、バケットに行われたすべてのHTTPリクエストのログを別のS3バケットに保存するように構成できます。S3サーバーアクセスログログ監査では、すべてのAWS S3リクエストのHTTPrefererフィールドが、コンテキストとスパン情報を提供するURLに構築されます。このフィールドはS3ログに保存されるため、S3バケットログが有効になっている場合、ログはS3クライアントによるアクセスを実際に発生している操作に関連付けることができます。

注:このログは「ベストエフォート」として記述されています。ログがいつ到着するかについての保証はありません。

スパン外の操作の拒否

ログ監査は、監査されたスパンの外でS3へのリクエストが行われるたびに例外を発生させるように構成できます。つまり、S3AFileSystemインスタンス(監査を作成したインスタンス)を介してS3と対話するスレッドは、アクティブなスパンがありません。

これは主に開発用であり、パブリックAPI呼び出しを通じてスパンが入力されていることを保証するために使用できます。

<property>
  <name>fs.s3a.audit.reject.out.of.span.operations</name>
  <value>true</value>
</property>

この拒否プロセスは、一部のAWS S3リクエストクラスに対して無効になっています。これらのクラスは、より大規模な操作の一部としてAWS SDK内で作成され、スパンをアタッチできません。

常に許可されるAWSリクエスト 理由
GetBucketLocationRequest AWS SDKで使用され、S3エンドポイントを決定します。
CopyPartRequest AWS SDKのコピー操作中に使用されます。
CompleteMultipartUploadRequest AWS SDKで使用され、コピー操作を完了します。

コピー/マルチパートアップロードを開始するリクエストは常に監査されるため、監査プロセスは名前変更とマルチパートIOのカバレッジを持っています。ただし、AWS S3ログには、関連付けられたコピー/完了呼び出しのリファラーヘッダーに完全なトレース情報は含まれません。

監査とHTTPリファラーヘッダー

HTTPリファラーヘッダーは、ログ監査によって添付されます。S3バケットが別のバケットへのリクエストをログに記録するように構成されている場合、これらのログエントリには、リファラーとして監査情報が含まれます。

これは解析でき(正規表現についてはAWSのドキュメントを参照)、HTTPリファラーヘッダーを抽出できます。

https://audit.example.org/hadoop/1/op_rename/3c0d9b7e-2a63-43d9-a220-3c574d768ef3-3/
    ?op=op_rename
    &p1=s3a://alice-london/path1
    &pr=alice
    &p2=s3a://alice-london/path2
    &ps=235865a0-d399-4696-9978-64568db1b51c
    &ks=5
    &id=3c0d9b7e-2a63-43d9-a220-3c574d768ef3-3
    &t0=12
    &fs=af5943a9-b6f6-4eec-9c58-008982fc492a
    &t1=12
    &ts=1617116985923

リクエストで見つけることができるフィールドを次に示します。フィールド値がnullの場合、フィールドは省略されます。

名前 意味
cm コマンド S3GuardTool$BucketInfo
fs ファイルシステムID af5943a9-b6f6-4eec-9c58-008982fc492a
id スパンID 3c0d9b7e-2a63-43d9-a220-3c574d768ef3-3
ji ジョブID(S3Aコミッター) (クエリエンジンによって生成)
op ファイルシステムAPI呼び出し op_rename
p1 操作のパス1 s3a://alice-london/path1
p2 操作のパス2 s3a://alice-london/path2
pr プリンシパル alice
ps 一意のプロセスUUID 235865a0-d399-4696-9978-64568db1b51c
rg GETリクエスト範囲 100-200
ta タスク試行ID(S3Aコミッター)
t0 スレッド0:スパンが作成されたスレッド 100
t1 スレッド1:この操作が実行されたスレッド 200
ts タイムスタンプ(UTCエポックミリ秒) 1617116985923
ks 与えられたリクエストの一部として削除するキーサイズ(ファイル数)(削除と名前変更の操作に適用可能) 5

備考

  • スレッドIDはJVM内の現在のスレッドからのものであるため、Log4Jログ内のスレッドIDと比較できます。ただし、一意であるとは限りません。
  • タスク試行/ジョブIDは、S3Aコミッターを含む操作、具体的にはコミッターによって実行されるすべての操作中にのみ設定されます。コミッターのインスタンス化と同じスレッドで実行される操作でも、実際のタスクとは無関係な場合でも、IDが報告される可能性があります。「ベストエフォート」と考えてください。
Long.toString(Thread.currentThread().getId())

t0t1が異なる場合、元の操作に代わって別のスレッドに処理が引き継がれたことを意味します。これはクライアント側のログエントリと関連付けることで、特定のスレッドへの作業を分離できます。

HTTP Refererヘッダーの制限事項

ヘッダーの長さにはサイズ制限があります。長いパスの操作では、この制限を超える可能性があります。そのような状況では、監査ログが不完全になります。

そのため、span IDはHTTPクエリパラメータだけでなく、常にURLの一部として渡されます。ヘッダーが切り詰められても、span IDは常に存在するからです。

HTTP Referer監査のプライバシーへの影響

S3AクライアントがS3バケットにリクエストを行うと、監査者はヘッダーにspan情報を追加し、それがログに保存されます。

S3バケットがクライアントと同じ組織が所有している場合、このspan情報は組織内部の情報です。

S3バケットが別のエンティティによって所有/管理されている場合、そのエンティティによって収集されたS3バケットログにspan情報が表示されます。これには、プリンシパル名と、アプリケーションがToolsまたはサービスランチャーAPIを介して起動された場合に実行されたコマンドが含まれます。

この情報の共有は、特定のヘッダーをフィルタリングするか、Refererヘッダーの生成全体を明示的に無効にすることで無効にできます。

注:HTTP Refererが無効になっている場合、またはプリンシパルがフィルタリングされている場合でも、AWS S3ログにはリクエストを行ったユーザーまたはIAMロールのARNが含まれます。

Refererヘッダーのフィルタリング

Refererヘッダーから特定のフィールドをフィルタリングできるため、S3Aログに含まれません。

<property>
  <name>fs.s3a.audit.referrer.filter</name>
  <value>pr, cm</value>
  <description>Strip out principal and command from referrer headers</description>
</property>

Refererヘッダーの無効化

ログ監査者は、オプションfs.s3a.audit.referrer.enabledfalseに設定することで、グローバルに、または特定のバケットに対してRefererヘッダーを追加しないように設定できます。

<property>
  <name>fs.s3a.audit.referrer.enabled</name>
  <value>false</value>
  <description>Disable referrer for all buckets</description>
</property>

<property>
  <name>fs.s3a.bucket.landsat-pds.audit.referrer.enabled</name>
  <value>false</value>
  <description>Do not add the referrer header to landsat operations</description>
</property>

分析のためのAWS S3ログの収集

S3バケットは、サーバーアクセスロギング用に設定する必要があります。

これにより、AWS S3はすべてのHTTPリクエストのアクセスログを収集し、同じリージョンの別のバケットに保存します。ログは、数秒分のログデータを含むファイルとして到着し、設定されたパス下に保存されます。

ロギングの有効化:ソースバケット

  1. まだない場合は、同じリージョンにログ用の別個のバケットを作成します。
  2. S3コンソールで、ログのソースとして機能させたいバケットを見つけ、「プロパティ」に移動します。
  3. 「サーバーアクセスロギング」までスクロールダウンします。
  4. 「編集」を選択してロギングを有効にし、ログ用の近くのバケットにパスを入力します。(ヒント:複数のバケットを同じログバケットに簡単にロギングするには、logs/$BUCKET/log-のようなプレフィックスを使用して、異なるバケットのログを分離します。たとえば、dev data londonからのログデータのパスはs3://london-log-bucket/logs/dev-data-lon/log-になります。)
  5. これを保存します。

S3リクエストが行われてからログが表示されるまでに約1時間遅延があります。設定中に動作していないように見えても心配しないでください。ログを有効にし、「hadoop fs」コマンドラインを介してバケットを操作し、1時間待ってから、ログバケットにエントリがないか確認します。ログファイル名には、これらのログが開始された時間が含まれています。

古いログを削除してコストを抑える。

ログはS3バケットに保存されるため、これも料金が発生します。一定期間後にログを削除するか、ワークフローを設定してログエントリを圧縮形式およびより大きなファイルにロードして統合することで、コストを抑えましょう。

古いログファイルを自動的に削除するルールを設定するのは簡単です。

  1. S3コンソールで、ログの宛先となるバケット(例:london-log-bucket)を表示します。
  2. 「管理」タブに移動します。
  3. (既に存在する「保留中のアップロードのキャンセル」ルールとともに)ライフサイクルルールを追加します。
  4. ルール名「古いログファイルを削除」を追加します。
  5. 「範囲を制限」を選択します。
  6. プレフィックスlogs/を追加して、すべてバケットのすべてのログを削除します。重要:/logs/など、先頭に「/」を含めてはいけません。一致せず、ルールは機能しません。
  7. 「ライフサイクルルールの動作」で、「現在のバージョンの有効期限切れ」を選択します。これにより、ログエントリが削除されます。
  8. 「オブジェクトの現在のバージョンの有効期限切れ」で、ログエントリを保持する日数を設定します。
  9. 「ルールの作成」ボタンを押して終了します。

削除が機能していることを確認するためにバケットを監視してください。プレフィックスでエラーを起こしやすいので、ログは制限なく作成されるため、コストが急上昇します。

Refererヘッダーを抽出するためのAWS S3ログの解析

AWS S3ドキュメントはログ形式について説明しており、これを使用するためのHive外部テーブル宣言が含まれています。

hadoop-awsテストスイートでヘッダーを抽出するために使用されるJavaパターン正規表現は、次のように定義されています。

(?<owner>[^ ]*) (?<bucket>[^ ]*) (?<timestamp>\[(.*?)\]) (?<remoteip>[^ ]*) (?<requester>[^ ]*) (?<requestid>[^ ]*) (?<operation>[^ ]*) (?<key>[^ ]*) (?<requesturi>(-|"[^"]*")) (?<http>(-|[0-9]*)) (?<awserrorcode>[^ ]*) (?<bytessent>[^ ]*) (?<objectsize>[^ ]*) (?<totaltime>[^ ]*) (?<turnaroundtime>[^ ]*) (?<referrer>(-|"[^"]*")) (?<useragent>(-|"[^"]*")) (?<version>[^ ]*) (?<hostid>[^ ]*) (?<sigv>[^ ]*) (?<cypher>[^ ]*) (?<auth>[^ ]*) (?<endpoint>[^ ]*) (?<tls>[^ ]*)*$

クラスorg.apache.hadoop.fs.s3a.audit.S3LogParserは、このパターンと各グループの定数を提供します。これはPublic/Unstableとして宣言されています。

デバッグ

org.apache.hadoop.fs.s3a.auditログコンテキストには、監査を実装するさまざまなコンポーネントのログが含まれています。

LoggingAuditServiceを使用して監査されたリクエストのロギングは、そのログをデバッグに設定することで有効にできます。

# Log before a request is made to S3
log4j.logger.org.apache.hadoop.fs.s3a.audit.impl.LoggingAuditor=DEBUG

これにより、リクエストごとに1行のログが追加され、S3AクライアントとAWS S3間の通信に関するいくつかの洞察が得られます。

スパンの開始と終了など、監査システムの低レベルのデバッグには、ログをTRACEに設定します。

# log request creation, span lifecycle and other low-level details
log4j.logger.org.apache.hadoop.fs.s3a.audit=TRACE

これは非常にノイズが多く、通常の運用では推奨されません。

S3Aコミッターとの統合

S3Aコミッターを介して送信された作業には、そのスレッド内のすべてのS3Aファイルシステムに対して行われるS3操作に関連付けられたジョブ(クエリ)IDがあります。

これを有効にするには、タスクで実行される作業は、コミッターでjobSetup()またはtaskSetup()を呼び出したのと同じスレッド内にある必要があります。