Google App Engine のログを収集する
このドキュメントでは、Google Cloud Storage V2 を使用して Google App Engine ログを Google Security Operations に取り込む方法について説明します。
Google App Engine は、ウェブ アプリケーションと API の構築とデプロイを行うためのフルマネージドのサーバーレス プラットフォームです。App Engine は、HTTP リクエストのリクエストログと、コードからアプリケーション ログを自動的に生成します。これらのログは Cloud Logging に送信され、Cloud Storage にエクスポートして Google Security Operations に取り込むことができます。
始める前に
次の前提条件を満たしていることを確認します。
- Google SecOps インスタンス
- Cloud Storage API が有効になっている GCP プロジェクト
- GCS バケットを作成および管理する権限
- GCS バケットの IAM ポリシーを管理する権限
- Cloud Logging シンクを作成する権限(roles/logging.configWriter)
- アクティブな App Engine アプリケーション(スタンダード環境またはフレキシブル環境)
Google Cloud Storage バケットを作成する
- Google Cloud Console に移動します。
- プロジェクトを選択するか、新しいプロジェクトを作成します。
- ナビゲーション メニューで、[Cloud Storage > バケット] に移動します。
- [バケットを作成] をクリックします。
次の構成情報を提供してください。
設定 値 バケットに名前を付ける グローバルに一意の名前( appengine-logs-exportなど)を入力します。ロケーション タイプ ニーズに基づいて選択します(リージョン、デュアルリージョン、マルチリージョン)。 ロケーション ロケーションを選択します(例: us-central1)。ストレージ クラス Standard(頻繁にアクセスされるログにおすすめ) アクセス制御 均一(推奨) 保護ツール 省略可: オブジェクトのバージョニングまたは保持ポリシーを有効にする [作成] をクリックします。
App Engine ログを GCS にエクスポートするように Cloud Logging を構成する
Cloud Logging は、ログシンクを使用して、Cloud Storage バケットなどのサポートされている宛先にログエントリを転送します。シンクの書き込み ID には、宛先バケットに対するストレージ オブジェクト作成者ロール(roles/storage.objectCreator)が必要です。
Cloud Logging シンクを作成する
- Google Cloud コンソールで、[ロギング] > [ログルーター] に移動します。
- [シンクを作成] をクリックします。
- 次の構成の詳細を指定します。
- シンク名: わかりやすい名前を入力します(例:
appengine-to-gcs)。 - シンクの説明: 省略可能な説明。
- シンク名: わかりやすい名前を入力します(例:
- [次へ] をクリックします。
- [シンクサービスの選択] セクションで、次の操作を行います。
- シンクサービス: [Cloud Storage バケット] を選択します。
- Cloud Storage バケットを選択: プルダウンから
appengine-logs-exportを選択します。
- [次へ] をクリックします。
[シンクに含めるログの選択] セクションで、App Engine ログを選択するフィルタ クエリを入力します。リソースタイプは "gae_app" でなければなりません。
すべての App Engine ログ(リクエストログとアプリケーション ログ)の場合:
resource.type="gae_app"App Engine リクエストログの場合のみ:
resource.type="gae_app" logName="projects/PROJECT_ID/logs/appengine.googleapis.com/request_log"App Engine アプリケーション ログ(stdout/stderr)の場合:
resource.type="gae_app" (logName="projects/PROJECT_ID/logs/stdout" OR logName="projects/PROJECT_ID/logs/stderr")PROJECT_IDは実際の GCP プロジェクト ID に置き換えます。[次へ] をクリックします。
構成を確認して、[シンクを作成] をクリックします。
シンクの書き込み ID に権限を付与する
シンクを作成したら、シンクの書き込み ID に宛先バケットに対する Storage オブジェクト作成者のロールを付与する必要があります。サービス アカウントの書き込み ID は次のようになります。serviceAccount:service-123456789012@gcp-sa-logging.iam.gserviceaccount.com
- [ログルーター] ページで、新しく作成されたシンクを見つけます。
- シンク名の横にあるメニュー アイコン(縦に 3 つ並んだ点)をクリックします。
- [シンクの詳細を表示する] を選択します。
- 書き込み ID(サービス アカウントのメールアドレス)をコピーします。
- [Cloud Storage] > [バケット] に移動します。
- バケット名(
appengine-logs-export)をクリックします。 - [権限] タブに移動します。
- [アクセス権を付与] をクリックします。
- 次の構成の詳細を指定します。
- プリンシパルを追加: シンクの書き込み ID(サービス アカウントのメールアドレス)を貼り付けます。
- ロールを割り当てる: [Storage オブジェクト作成者] を選択します。
- [保存] をクリックします。
Google SecOps サービス アカウントを取得する
Google SecOps は、一意のサービス アカウントを使用して GCS バケットからデータを読み取ります。このサービス アカウントにバケットへのアクセス権を付与する必要があります。
App Engine のログを取り込むように Google SecOps でフィードを構成する
- [SIEM 設定] > [フィード] に移動します。
- [Add New Feed] をクリックします。
- [単一フィードを設定] をクリックします。
- [フィード名] フィールドに、フィードの名前を入力します(例:
App Engine Logs)。 - [ソースタイプ] として [Google Cloud Storage V2] を選択します。
[ログタイプ] として [GCP_APP_ENGINE] を選択します。
[サービス アカウントを取得する] をクリックします。
一意のサービス アカウント メールアドレスが表示されます(例:)。
chronicle-12345678@chronicle-gcp-prod.iam.gserviceaccount.comこのメールアドレスをコピーします。次のステップでこれを使用します。
[次へ] をクリックします。
次の入力パラメータの値を指定します。
ストレージ バケットの URL: 接頭辞パスを含む GCS バケット URI を入力します。
gs://appengine-logs-export/Cloud Logging は、エクスポートされたログファイルをログタイプと日時別のディレクトリ構造に編成します。ログタイプには、appengine.googleapis.com/request_log のような複合名を指定できます。ファイルはシャーディングされ、期間(08:00:00_08:59:59_S0.json など)で名前が付けられます。
Source deletion option: 必要に応じて削除オプションを選択します。
- なし: 転送後にファイルを削除しません(テストにおすすめ)。
- 転送されたファイルを削除する: 転送が完了した後にファイルを削除します。
- 転送されたファイルと空のディレクトリを削除する: 転送が完了した後にファイルと空のディレクトリを削除します。
ファイルの最大経過日数: 指定した日数以内に変更されたファイルを含めます。デフォルトは 180 日です。
アセットの名前空間: アセットの名前空間。
Ingestion labels: このフィードのイベントに適用されるラベル。
[次へ] をクリックします。
[Finalize] 画面で新しいフィードの設定を確認し、[送信] をクリックします。
Google SecOps サービス アカウントに IAM 権限を付与する
Google SecOps サービス アカウントには、GCS バケットに対する Storage オブジェクト閲覧者ロールが必要です。
- [Cloud Storage] > [バケット] に移動します。
- バケット名(
appengine-logs-export)をクリックします。 - [権限] タブに移動します。
- [アクセス権を付与] をクリックします。
- 次の構成の詳細を指定します。
- プリンシパルを追加: Google SecOps サービス アカウントのメールアドレスを貼り付けます。
- ロールを割り当てる: [ストレージ オブジェクト閲覧者] を選択します。
[保存] をクリックします。
App Engine ログの構造について
App Engine は、リクエストログとアプリログの両方を Cloud Logging に自動的に送信します。App Engine はアプリに送信されたリクエストのログを自動的に出力します。ユーザーがリクエストログを作成する必要はありません。このセクションでは、アプリログを書き込む方法について説明します。
App Engine のリクエストログには、@type が「type.googleapis.com/google.appengine.logging.v1.RequestLog」の RequestLog 型のオブジェクトを保持する protoPayload フィールドを含むログエントリがあります。リソースタイプは「gae_app」です。
デフォルトでは、ログのペイロードはログエントリの textPayload フィールドに保存されたテキスト文字列です。文字列は、ログ エクスプローラにメッセージとして表示され、メッセージを発行した App Engine のサービスとバージョンに関連付けられます。
構造化ログを書き込むには、シリアル化された JSON を 1 行形式でログに書き込みます。構造化ログを JSON ディクショナリとして提供すると、いくつかの特殊フィールドが jsonPayload から削除され、生成された LogEntry の対応フィールドに書き込まれます。たとえば、JSON に severity プロパティが含まれている場合、このプロパティは jsonPayload から削除され、代わりにログエントリの severity として表示されます。
既知の制限事項
ログシンクから Cloud Storage にログを転送した場合、Cloud Storage の転送先にはリクエストログのみが格納されます。App Engine は、複数のフォルダにアプリのログを書き込みます。
転送されたログエントリは、1 時間ごとにまとめて Cloud Storage バケットに保存されます。最初のエントリが表示されるまでに 2 ~ 3 時間かかることがあります。
App Engine フレキシブル環境では、ロギングが自動的に機能します。ただし、収集されるログの形式は異なります。ログはリクエストによってバンドルされず、stdout と stderr からのログが別々に収集されます。
UDM マッピング テーブル
| ログフィールド | UDM マッピング | ロジック |
|---|---|---|
| jsonPayload.logger、taskTypeName、jsonPayload.@type、jsonPayload.backendTargetProjectNumber、jsonPayload.cacheDecision、resource.labels.version_id、resource.labels.module_id、logName、spanId、trace、protoPayload.@type、labels.clone_id、operation.producer | additional.fields | 各フィールドから作成された Key-Value ラベルと統合 |
| メタデータ | メタデータ | メタデータから名前変更 |
| receiveTimestamp | metadata.collected_timestamp | RFC3339 で日付フィルタを使用して解析 |
| metadata.event_type | has_principal、has_target、has_principal_user の場合は「USER_LOGIN」、has_principal と has_target の場合は「NETWORK_CONNECTION」、has_principal ではなく has_target の場合は「USER_UNCATEGORIZED」、has_principal の場合は「STATUS_UPDATE」、has_principal_user の場合は「USER_UNCATEGORIZED」、それ以外の場合は「GENERIC_EVENT」に設定します。 | |
| metadata.extensions.auth.type | has_principal、has_target、has_principal_user の場合は、「AUTHTYPE_UNSPECIFIED」に設定します。 | |
| insertId | metadata.product_log_id | 値を直接コピー |
| httpRequest.requestMethod,protoPayload.method | network.http.method | httpRequest.requestMethod が空でない場合はその値、それ以外の場合は protoPayload.method |
| httpRequest.userAgent | network.http.parsed_user_agent | parseduseragent に変換されました |
| httpRequest.status | network.http.response_code | 文字列に変換してから整数に変換 |
| httpRequest.userAgent | network.http.user_agent | 値を直接コピー |
| httpRequest.responseSize | network.received_bytes | uinteger に変換済み |
| httpRequest.requestSize | network.sent_bytes | uinteger に変換済み |
| プリンシパル | プリンシパル | 空でない場合は principal から名前が変更されます |
| protoPayload.host | principal.asset.hostname | 値を直接コピー |
| httpRequest.serverIp、protoPayload.ip | principal.asset.ip | httpRequest.serverIp または protoPayload.ip の server_ip と統合されました |
| protoPayload.host | principal.hostname | 値を直接コピー |
| httpRequest.serverIp、protoPayload.ip | principal.ip | httpRequest.serverIp または protoPayload.ip の server_ip と統合されました |
| protoPayload.appId | principal.resource.attribute.labels | キー「appId」とフィールドの値を含む appId_label と統合 |
| requestUser | principal.user.email_addresses | メールパターンと一致する場合、requestUser と統合されます |
| security_result | security_result | security_result から統合 |
| resource.labels.forwarding_rule_name | security_result.rule_labels | キー「forwarding_rule_name」とフィールドの値を含む rule_label と統合されます |
| 重要度 | security_result.severity | (?i)ERROR|CRITICAL に一致する場合は重大度に設定、(?i)INFO に一致する場合は INFORMATIONAL に設定、(?i)WARN に一致する場合は MEDIUM に設定、(?i)DEBUG に一致する場合は LOW に設定、それ以外の場合は UNKNOWN_SEVERITY に設定 |
| jsonPayload.statusDetails | security_result.summary | 値を直接コピー |
| ターゲット | ターゲット | ターゲットから名前が変更されます(空でない場合) |
| resource.labels.backend_service_name | target.application | 値を直接コピー |
| httpRequest.remoteIp、jsonPayload.remoteIp | target.asset.ip | httpRequest.remoteIp または jsonPayload.remoteIp から抽出された remote_ip と統合されます |
| resource.labels.project_id | target.cloud.project.name | 値を直接コピー |
| httpRequest.remoteIp、jsonPayload.remoteIp | target.ip | httpRequest.remoteIp または jsonPayload.remoteIp から抽出された remote_ip と統合されます |
| resource.labels.zone | target.resource.attribute.cloud.availability_zone | 値を直接コピー |
| resource.labels.target_proxy_name、resource.labels.url_map_name | target.resource.attribute.labels | 各ソースのラベルと統合 |
| resource.type | target.resource.type | 値を直接コピー |
| httpRequest.requestUrl | target.url | 値を直接コピー |
| metadata.product_name | 「GCP_APP_ENGINE」に設定します。 | |
| metadata.vendor_name | 「GCP」に設定 |
さらにサポートが必要な場合 コミュニティ メンバーや Google SecOps のプロフェッショナルから回答を得ることができます。