OAuth2 プロキシログを収集する

以下でサポートされています。

このドキュメントでは、Google Cloud Storage V2 を使用して OAuth2 Proxy ログを Google Security Operations に取り込む方法について説明します。

OAuth2 Proxy は、OAuth2/OIDC プロバイダ(Google、GitHub、Keycloak、Azure AD など)を使用して認証を行い、メール、ドメイン、グループでアカウントを検証する CNCF Sandbox リバース プロキシです。認証ログ(ログインの成功/失敗)、リクエストログ(ユーザー ID を含むプロキシ HTTP リクエスト)、標準アプリケーション ログが生成されます。OAuth2 Proxy は Kubernetes のコンテナとして実行され、すべてのログを stdout に書き込むため、Kubernetes ネイティブのログコレクタ(Fluentd)を使用して、Google SecOps の取り込み用にログを GCS バケットに転送します。

始める前に

次の前提条件を満たしていることを確認してください。

  • Google SecOps インスタンス
  • Cloud Storage API が有効になっている GCP プロジェクト
  • GCS バケットを作成および管理する権限
  • GCS バケットの IAM ポリシーを管理する権限
  • OAuth2 Proxy がデプロイされた(Helm チャートまたは手動デプロイ)実行中の Kubernetes クラスタ
  • DaemonSet、ConfigMap、Secret、Namespace を作成する権限を持つ Kubernetes クラスタへの kubectl アクセス
  • ターゲット GCS バケットに対する storage.objects.create 権限を持つ GCP サービス アカウントの JSON キー

Google Cloud Storage バケットを作成する

  1. Google Cloud コンソールに移動します。
  2. プロジェクトを選択するか、新しいプロジェクトを作成します。
  3. ナビゲーション メニューで、[Cloud Storage > バケット] に移動します。
  4. [バケットを作成] をクリックします。
  5. 次の構成情報を提供してください。

    設定 値
    バケットに名前を付ける グローバルに一意の名前(oauth2-proxy-logs-bucket など)を入力します。
    ロケーション タイプ ニーズに応じて選択します(リージョン、デュアルリージョン、マルチリージョン)。
    ロケーション 場所を選択します(例: us-central1)。
    ストレージ クラス Standard(アクセス頻度の高いログにおすすめ)
    アクセス制御 均一(推奨)
    保護ツール 省略可: オブジェクトのバージョニングまたは保持ポリシーを有効にする
  6. [作成] をクリックします。

OAuth2 プロキシのロギングを構成する

OAuth2 プロキシは、標準ログ、認証ログ、リクエストログの 3 種類のログを stdout に書き込みます。3 つすべてがデフォルトで有効になっています。ログにセキュリティ関連の詳細が最大限に含まれるように、次のロギング フラグを使用して OAuth2 Proxy を構成します。

オプション 1: Helm チャート値を使用して構成する

  • 公式の Helm チャートを使用して OAuth2 Proxy をデプロイする場合は、次の内容を values.yaml ファイルに追加します。

    config:
      configFile: |-
        standard_logging = true
        auth_logging = true
        request_logging = true
        silence_ping_logging = true
            standard_logging_format = "[{{.Timestamp}}] [{{.File}}] {{.Message}}"
        auth_logging_format = "{{.Client}} - {{.RequestID}} - {{.Username}} [{{.Timestamp}}] [{{.Status}}] {{.Message}}"
        request_logging_format = "{{.Client}} - {{.RequestID}} - {{.Username}} [{{.Timestamp}}] {{.Host}} {{.RequestMethod}} {{.Upstream}} {{.RequestURI}} {{.Protocol}} {{.UserAgent}} {{.StatusCode}} {{.ResponseSize}} {{.RequestDuration}}"
    
  • 更新された Helm 値を適用します。

    helm upgrade oauth2-proxy oauth2-proxy/oauth2-proxy -f values.yaml -n <your-namespace>
    

オプション 2: コマンドライン フラグを使用して構成する

  • Kubernetes Deployment マニフェストを使用して OAuth2 Proxy をデプロイする場合は、次の引数をコンテナ仕様に追加します。

    args:
      - --standard-logging=true
      - --auth-logging=true
      - --request-logging=true
      - --silence-ping-logging=true
    

オプション 3: 環境変数を使用して構成する

  • OAuth2 Proxy コンテナに次の環境変数を設定します。

    env:
      - name: OAUTH2_PROXY_STANDARD_LOGGING
        value: "true"
      - name: OAUTH2_PROXY_AUTH_LOGGING
        value: "true"
      - name: OAUTH2_PROXY_REQUEST_LOGGING
        value: "true"
      - name: OAUTH2_PROXY_SILENCE_PING_LOGGING
        value: "true"
    

OAuth2 プロキシのロギングを確認する

  • 構成を適用したら、OAuth2 Proxy がログを生成していることを確認します。

    kubectl logs -l app=oauth2-proxy -n <your-namespace> --tail=20
    
  • 出力には、次のような行が含まれます。

    10.0.0.1 - abc123 - user@example.com [2024/01/15 10:30:00] [AuthSuccess] Authenticated via OAuth2
    10.0.0.1 - abc123 - user@example.com [2024/01/15 10:30:01] example.com GET 10.0.0.5:8080 "/dashboard" HTTP/1.1 "Mozilla/5.0" 200 1234 0.005
    

Fluentd 用の GCP サービス アカウントを作成する

Fluentd には、GCS バケットに対する書き込み権限を持つ GCP サービス アカウントが必要です。

  1. GCP コンソールで、[IAM と管理>サービス アカウント] に移動します。
  2. [サービス アカウントを作成] をクリックします。
  3. 次の構成情報を指定します。
    • サービス アカウント名: 「fluentd-gcs-writer」と入力します。
    • サービス アカウントの説明: Service account for Fluentd to write OAuth2 Proxy logs to GCS と入力します。
  4. [作成して続行] をクリックします。
  5. [このサービス アカウントにプロジェクトへのアクセスを許可する] セクションで、次の操作を行います。
    1. [ロールを選択] をクリックします。
    2. [ストレージ オブジェクト管理者] を検索して選択します。
  6. [続行] をクリックします。
  7. [完了] をクリックします。

サービス アカウント キーを作成してダウンロードする

  1. [サービス アカウント] リストで、fluentd-gcs-writer サービス アカウントをクリックします。
  2. [キー] タブに移動します。
  3. [鍵を追加>新しい鍵を作成] をクリックします。
  4. キーのタイプとして [JSON] を選択します。
  5. [作成] をクリックします。
  6. ダウンロードした JSON キーファイルを安全に保存します。このファイルは次のステップで使用します。

サービス アカウント キーの Kubernetes Secret を作成する

  • Fluentd がデプロイされる Namespace に、GCP サービス アカウント キーを含む Kubernetes Secret を作成します。

    kubectl create namespace logging
    kubectl create secret generic fluentd-gcs-key \
      --from-file=service-account-key.json=<path-to-downloaded-key>.json \
      -n logging
    

OAuth2 プロキシログを収集する Fluentd DaemonSet をデプロイする

Kubernetes クラスタに Fluentd を DaemonSet としてデプロイし、OAuth2 Proxy Pod からコンテナログを収集して GCS バケットに転送します。

Fluentd ConfigMap を作成する

  • 次の内容で fluentd-configmap.yaml という名前のファイルを作成します。

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: fluentd-gcs-config
      namespace: logging
    data:
      fluent.conf: |
        <source>
          @type tail
          read_from_head true
          tag kubernetes.*
          path /var/log/containers/*oauth2-proxy*.log
          pos_file /var/log/fluentd-oauth2-proxy.log.pos
          <parse>
            @type regexp
            expression /^(?<time>[^ ]+) (?<stream>stdout|stderr) [^ ]* (?<log>.*)$/
            time_format %Y-%m-%dT%H:%M:%S.%N%z
          </parse>
        </source>
    
        <filter kubernetes.**>
          @type kubernetes_metadata
          @id filter_kube_metadata
        </filter>
    
        <match kubernetes.**>
          @type gcs
          project YOUR_GCP_PROJECT_ID
          keyfile /etc/secrets/service-account-key.json
          bucket oauth2-proxy-logs-bucket
          path oauth2-proxy-logs/%Y/%m/%d/
          object_key_format %{path}%{time_slice}_%{hostname}_%{index}.%{file_extension}
          <buffer tag,time>
            @type file
            path /var/log/fluentd/gcs
            timekey 300
            timekey_wait 60
            timekey_use_utc true
            chunk_limit_size 10MB
          </buffer>
          <format>
            @type json
          </format>
        </match>
    

次の値を置き換えます。

  • YOUR_GCP_PROJECT_ID: GCP プロジェクト ID(例: my-project-123456)
  • oauth2-proxy-logs-bucket: 前に作成した GCS バケットの名前

  • ConfigMap を適用します。

    kubectl apply -f fluentd-configmap.yaml
    

Fluentd DaemonSet を作成する

  • 次の内容で fluentd-daemonset.yaml という名前のファイルを作成します。

    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      name: fluentd-gcs
      namespace: logging
      labels:
        k8s-app: fluentd-gcs
    spec:
      selector:
        matchLabels:
          k8s-app: fluentd-gcs
      template:
        metadata:
          labels:
            k8s-app: fluentd-gcs
        spec:
          tolerations:
            - key: node-role.kubernetes.io/control-plane
              effect: NoSchedule
            - key: node-role.kubernetes.io/master
              effect: NoSchedule
          containers:
            - name: fluentd-gcs
              image: fluent/fluentd-kubernetes-daemonset:v1-debian-gcs
              resources:
                limits:
                  memory: 512Mi
                requests:
                  cpu: 100m
                  memory: 200Mi
              volumeMounts:
                - name: fluentd-gcs-config-volume
                  mountPath: /fluentd/etc/fluent.conf
                  subPath: fluent.conf
                  readOnly: true
                - name: fluentd-gcs-secrets-volume
                  mountPath: /etc/secrets/service-account-key.json
                  subPath: service-account-key.json
                  readOnly: true
                - name: varlog
                  mountPath: /var/log
                - name: dockercontainerlogdirectory
                  mountPath: /var/log/pods
                  readOnly: true
                - name: fluentd-buffer
                  mountPath: /var/log/fluentd
          terminationGracePeriodSeconds: 30
          volumes:
            - name: fluentd-gcs-config-volume
              configMap:
                name: fluentd-gcs-config
            - name: fluentd-gcs-secrets-volume
              secret:
                secretName: fluentd-gcs-key
            - name: varlog
              hostPath:
                path: /var/log
            - name: dockercontainerlogdirectory
              hostPath:
                path: /var/log/pods
            - name: fluentd-buffer
              emptyDir: {}
    
  • DaemonSet を適用します。

    kubectl apply -f fluentd-daemonset.yaml
    

Fluentd のデプロイを確認する

  1. 各ノードで Fluentd Pod が実行されていることを確認します。

    kubectl get pods -n logging -l k8s-app=fluentd-gcs
    
  2. Fluentd ログで GCS への書き込みが成功したことを確認します。

    kubectl logs -l k8s-app=fluentd-gcs -n logging --tail=20
    
  3. ログファイルが GCS バケットに表示されることを確認します。

    1. GCP Console で、[Cloud Storage] > [バケット] に移動します。
    2. バケット(oauth2-proxy-logs-bucket など)をクリックします。
    3. oauth2-proxy-logs/ フォルダに移動します。
    4. .json ファイルが存在し、タイムスタンプが最新であることを確認します。

Google SecOps サービス アカウントを取得する

Google SecOps は、一意のサービス アカウントを使用して GCS バケットからデータを読み取ります。このサービス アカウントにバケットへのアクセス権を付与する必要があります。

サービス アカウントのメールアドレスを取得する

  1. [SIEM 設定] > [フィード] に移動します。
  2. [Add New Feed] をクリックします。
  3. [単一フィードを設定] をクリックします。
  4. [フィード名] フィールドに、フィードの名前を入力します(例: OAuth2 Proxy Logs)。
  5. [ソースタイプ] として [Google Cloud Storage V2] を選択します。
  6. [ログタイプ] として [Kubernetes Auth Proxy] を選択します。
  7. [サービス アカウントを取得する] をクリックします。一意のサービス アカウントのメールアドレスが表示されます(例:)。

    chronicle-12345678@chronicle-gcp-prod.iam.gserviceaccount.com
    
  8. このメールアドレスをコピーして、次のステップで使用します。

  9. [次へ] をクリックします。

  10. 次の入力パラメータの値を指定します。

    • ストレージ バケットの URL: 接頭辞パスを含む GCS バケット URI を入力します。

      gs://oauth2-proxy-logs-bucket/oauth2-proxy-logs/
      
    • oauth2-proxy-logs-bucket は、GCS バケット名に置き換えます。

    • Source deletion option: 必要に応じて削除オプションを選択します。

      • なし: 転送後にファイルを削除しません(テストにおすすめ)。
      • 転送されたファイルを削除する: 転送が完了した後にファイルを削除します。
      • 転送されたファイルと空のディレクトリを削除する: 転送が完了した後にファイルと空のディレクトリを削除します。

    • ファイルの最大経過日数: 過去の日数以内に変更されたファイルを含めます(デフォルトは 180 日)。

    • アセットの名前空間: アセットの名前空間

    • Ingestion labels: このフィードのイベントに適用されるラベル

  11. [次へ] をクリックします。

  12. [Finalize] 画面で新しいフィードの設定を確認し、[送信] をクリックします。

Google SecOps サービス アカウントに IAM 権限を付与する

Google SecOps サービス アカウントには、GCS バケットに対する Storage オブジェクト閲覧者のロールが必要です。

  1. [Cloud Storage] > [バケット] に移動します。
  2. バケット名(oauth2-proxy-logs-bucket など)をクリックします。
  3. [権限] タブに移動します。
  4. [アクセス権を付与] をクリックします。
  5. 次の構成情報を指定します。
    • プリンシパルの追加: Google SecOps サービス アカウントのメールアドレス(chronicle-12345678@chronicle-gcp-prod.iam.gserviceaccount.com など)を貼り付けます。
    • ロールを割り当てる: [Storage オブジェクト閲覧者] を選択します。
  6. [保存] をクリックします。

OAuth2 プロキシログのリファレンス

次の表に、OAuth2 Proxy によって生成されるログフィールドとそのセキュリティ関連性を示します。

認証ログのフィールド

フィールド 例 説明
クライアント 10.0.0.1 クライアント/リモート IP アドレス(--reverse-proxy=true の場合は X-Real-IP ヘッダーを使用)
RequestID 00010203-0405-4607-8809-0a0b0c0d0e0f X-Request-Id ヘッダーの ID をリクエストします(空の場合はランダムな UUID)。
ユーザー名 user@example.com 認証リクエストのメールアドレスまたはユーザー名
タイムスタンプ 2024/01/15 10:30:00 認証イベントの日時
ステータス AuthSuccess 認証結果: AuthSuccess、AuthFailure、AuthError
メッセージ Authenticated via OAuth2 認証試行の詳細

リクエストログ フィールド

フィールド 例 説明
クライアント 10.0.0.1 クライアント/リモート IP アドレス
RequestID 00010203-0405-4607-8809-0a0b0c0d0e0f リクエスト ID
ユーザー名 user@example.com 認証済みユーザーのメールアドレス
タイムスタンプ 2024/01/15 10:30:01 リクエストの日時
ホスト app.example.com Host ヘッダーの値
RequestMethod GET HTTP リクエスト メソッド
アップストリーム 10.0.0.5:8080 リクエストを処理したアップストリーム サーバー
RequestURI /dashboard リクエストの URI パス
プロトコル HTTP/1.1 リクエスト プロトコル
UserAgent Mozilla/5.0 完全なユーザー エージェント文字列
StatusCode 200 HTTP レスポンス ステータス コード
ResponseSize 1234 レスポンスのサイズ(バイト単位)
RequestDuration 0.005 リクエスト処理時間(秒)

UDM マッピング テーブル

ログフィールド UDM マッピング ロジック
about about イベントに関する情報
http_req_id_field additional.fields 標準の UDM スキーマでカバーされていない追加フィールド
http_req_path_field additional.fields
k8s_pod_app_field additional.fields
k8s_pod_template_hash_field additional.fields
k8s_pod_tls_mode_field additional.fields
k8s_pod_canonical_revision_field additional.fields
k8s_pod_canonical_name_field additional.fields
pod_name additional.fields
cntnr_name additional.fields
destination_canonical_revision additional.fields
requested_server additional.fields
nodename_label additional.fields
componentName_label additional.fields
componentVersion_label additional.fields
azureResourceID_label additional.fields
producer_label additional.fields
first_label additional.fields
last_label additional.fields
meta_name additional.fields
resource_version_label additional.fields
request_apiVersion additional.fields
request_kind_label additional.fields
request_type_label additional.fields
response_apiVersion additional.fields
response_kind_label additional.fields
response_type_label additional.fields
jsonPayload.message metadata.description イベントの説明
event_type metadata.event_type イベントのタイプ
labels.request_id metadata.product_log_id プロダクト固有のログ識別子
insertId metadata.product_log_id
jsonPayload.chartVersion metadata.product_version プロダクト バージョン
httpRequest.protocol network.application_protocol ネットワーク接続で使用されるアプリケーション プロトコル
network.direction network.direction ネットワーク トラフィックの方向
httpRequest.requestMethod network.http.method HTTP メソッド
http_method network.http.method
httpRequest.status network.http.response_code HTTP レスポンス コード
httpRequest.userAgent network.http.user_agent HTTP ユーザー エージェント
requestMetadata.callerSuppliedUserAgent network.http.user_agent
labels.protocol network.ip_protocol IP プロトコル
httpRequest.responseSize network.received_bytes 受信したバイト数
labels.total_received_bytes network.received_bytes
httpRequest.requestSize network.sent_bytes 送信されたバイト数
labels.total_sent_bytes network.sent_bytes
jsonPayload.session network.session_id セッション ID
labels.service_authentication_policy network.tls.cipher TLS 暗号スイート
プリンシパル プリンシパル イベントに関与するプリンシパル エンティティ
principal_hostname principal.hostname プリンシパルのホスト名
prin_userid principal.user.userid プリンシパルのユーザー ID
security_result security_result セキュリティ評価の結果
ターゲット ターゲット イベントに関与するターゲット エンティティ
target_hostname target.hostname ターゲットのホスト名
resource_sub_type target.resource.resource_subtype ターゲット リソースのサブタイプ
target_userid target.user.userid ターゲットのユーザー ID
metadata.product_name metadata.product_name 製品名
metadata.vendor_name metadata.vendor_name ベンダー名

変更ログ

このパーサーの変更ログを表示する

さらにサポートが必要な場合 コミュニティ メンバーや Google SecOps のプロフェッショナルから回答を得ることができます。