GKE ノードで Linux auditd ログを有効にする

このページでは、Containrer-Optimized OS を実行している Google Kubernetes Engine ノードで、詳細なオペレーティング システム監査ログを有効にする方法を説明します。このページでは、Cloud Logging にログを送信するように fluent-bit の Logging エージェントを構成する方法についても説明します。詳細ログを有効にすると、エラー メッセージ、ログイン試行、バイナリ実行など、クラスタとワークロードの状態に関する有益な情報を確認できます。この情報を活用して、問題のデバッグやセキュリティ インシデントの調査を行えます。

GKE Autopilot クラスタでは、ノードと基盤となる仮想マシン(VM)が Google によって管理されるため、Linux Auditd ロギングの有効化はサポートされていません。

このページは、セキュリティ ログを確認して分析するセキュリティ スペシャリストを対象としています。この情報を使用して、詳細な OS ログの要件と制限事項を理解し、GKE ノードで有効にする際の実装をガイドします。 Google Cloud のコンテンツで使用されている一般的なロールとタスクの例の詳細については、一般的な GKE ユーザーのロールとタスクをご覧ください。

このページを読む前に、Linux オペレーティング システムの監査ログについて理解しておいてください。

オペレーティング システムの監査ロギングは、Cloud Audit Logs や Kubernetes 監査ログとは異なります。

概要

クラスタ内の各ノードからログを収集するには、DaemonSet のスケジュールが可能なクラスタノードごとに DaemonSet を使用して Pod を 1 つずつ実行します。この Pod によって、ホスト上に auditd ロギング デーモンが構成され、ログを Logging などのログ取り込みサービスに送信するように Logging エージェントが構成されます。

監査は定義上、イベントの後に行われるもので、遡及的なセキュリティ対策です。クラスタでフォレンジックを実施する場合、auditd ログだけでは不十分な可能性があります。全体的なセキュリティ戦略の一環として auditd ログの最適な使用方法を検討してください。

制限事項

このページで説明するロギング メカニズムは、GKE Standard クラスタで Container-Optimized OS を実行するノードでのみ動作します。

ロギング DaemonSet の動作の仕組み

このセクションでは、サンプルのロギング DaemonSet が動作する仕組みを説明します。この仕組みを理解することで、DaemonSet を自由に構成できるようになります。後続のセクションでは、DaemonSet をデプロイする方法について説明します。

サンプルのマニフェストで、DaemonSet と ConfigMap およびそれらを格納する名前空間のインスタンスを定義します。

この DaemonSet では、クラスタ内の各ノードにポッドがデプロイされます。このポッドには 2 つのコンテナが格納されます。1 つ目のコンテナは、Container-Optimized OS ノードで利用可能な cloud-audit-setup systemd サービスを起動する init コンテナです。2 つ目のコンテナである cos-auditd-fluent-bit には fluent-bit のインスタンスが含まれており、ノード ジャーナルから Linux の監査ログを収集して、Cloud Logging にエクスポートするように構成されています。

このサンプルのロギング DaemonSet ログでは、次のイベントがログに記録されます。

  • auditd システム構成の変更
  • AppArmor 権限チェック
  • execve()、socket()、setsockopt()、mmap() の実行
  • ネットワーク接続
  • ユーザーのログイン
  • SSH セッションとその他すべての TTY(kubectl exec -t セッションを含む)

ロギング DaemonSet を構成する

ロギング DaemonSet の構成は、cos-auditd-fluent-bit-config という ConfigMap を使って行います。提供されている例では、監査ログは Logging に送信されますが、他の宛先にログが送信されるように構成できます。

auditd は、デフォルトのロギング構成よりもかなり多くのログを生成することがあり、システム リソースを消費します。そのため、追加費用が発生する場合があります。フィルタを設定すると、ロギングのボリュームを管理できます。

ロギング DaemonSet をデプロイする

  1. 既存のクラスタを使用することも、新しいクラスタを作成することもできます。

  2. サンプルのマニフェストをダウンロードします。

    curl https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-node-tools/master/troubleshooting/os-audit/cos-auditd-logging.yaml > cos-auditd-logging.yaml
    
  3. サンプルのマニフェストを必要に応じて編集します。DaemonSet の仕組みについては、前のセクションをご覧ください。このサンプル マニフェストで使用されている fluent-bit イメージはデモ用です。ベスト プラクティスとして、SHA-256 ダイジェストを使用して、制御されたソースの画像に置き換えます。

  4. 共通変数を初期化します。

    export CLUSTER_NAME=CLUSTER_NAME
    export CLUSTER_LOCATION=COMPUTE_REGION
    

    次のように置き換えます。

    • CLUSTER_NAME: クラスタの名前。
    • COMPUTE_REGION: クラスタの Compute Engine のリージョン。ゾーンクラスタの場合は、代わりにゾーンを使用します。
  5. ロギング Namespace、DaemonSet と ConfigMap をデプロイします。

    envsubst '$CLUSTER_NAME,$CLUSTER_LOCATION' < cos-auditd-logging.yaml \
    | kubectl apply -f -
    
  6. ロギング Pod が起動したことを確認します。マニフェストで別の Namespace を定義した場合は、cos-auditd を使用している名前空間の名前に置き換えます。

    kubectl get pods --namespace=cos-auditd
    

    Pod が実行されている場合、出力は次のようになります。

    NAME                                             READY   STATUS    RESTARTS   AGE
    cos-auditd-logging-g5sbq                         1/1     Running   0          27s
    cos-auditd-logging-l5p8m                         1/1     Running   0          27s
    cos-auditd-logging-tgwz6                         1/1     Running   0          27s
    

    クラスタのノードごとに Pod が 1 つデプロイされます。この例のクラスタには 3 つのノードが存在します。

  7. これで、Logging で監査ログにアクセスできるようになりました。ログ エクスプローラで、次のクエリを使用して結果をフィルタリングします。

    LOG_ID("linux-auditd")
    resource.labels.cluster_name = "CLUSTER_NAME"
    resource.labels.location = "COMPUTE_REGION"
    

    また、gcloud CLI を使用することもできます(結果セットが非常に大きくなる可能性があるため、--limit を使用します)。

    gcloud logging read --limit=100 "LOG_ID("linux-auditd") AND resource.labels.cluster_name = "${CLUSTER_NAME}" AND resource.labels.location = "${CLUSTER_LOCATION}""
    

ログをエクスポートする

サポートされている宛先にログを転送する方法については、シンクの構成と管理をご覧ください。

ログを無効化

ノードで auditd によるロギングを無効にするには、ロギング DaemonSet を削除し、 次に cos-auditd-logging-disable DaemonSet をデプロイして、各ノードの systemd サービスの変更を元に戻します。この DaemonSet をデプロイすると、ノードを再作成しない限り、auditd によるロギングを有効にすることはできません。

  1. 元のロギング DaemonSet とその関連リソースを削除します。

    kubectl delete daemonset cos-auditd-logging -n cos-auditd
    kubectl delete configmap fluent-bit-config -n cos-auditd
    # The namespace will be deleted by the cleanup daemonset's namespace definition
    
  2. cos-auditd-logging-disable クリーンアップ DaemonSet を適用します。

    kubectl apply -f 'https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-node-tools/master/troubleshooting/os-audit/cos-auditd-logging-disable.yaml'
    
  3. すべてのノードで cleanup-auditd Pod が実行されていることを確認します。

    kubectl get pods -n cos-auditd -l name=cleanup-auditd -w
    

    すべての Pod が Running になるまで待ちます。

  4. クリーンアップ Pod が実行されたら、新しい linux-auditd ログが生成されないことを、ロギング DaemonSet をデプロイするセクションのクエリを実行して確認します。たとえば、次の gcloud CLI コマンドを使用できます。

    gcloud logging read --limit=10 --freshness="5m" \
      "LOG_ID(\"linux-auditd\") AND \
      resource.labels.cluster_name = \"${CLUSTER_NAME}\" AND \
      resource.labels.location = \"${CLUSTER_LOCATION}\""
    

    このコマンドは、過去 5 分間のログを確認します。クリーンアップが成功した場合、出力は空になります。

    同様に、同じフィルタで Cloud Explorer を使用すると、クリーンアップ後に新しいログエントリが表示されなくなります。

  5. クリーンアップの DaemonSet と名前空間を削除します。

    kubectl delete -f cleanup-auditd-daemonset.yaml
    

    このコマンドは、DaemonSet と cos-auditd 名前空間の両方を削除します。

次のステップ