Kubernetes 監査ログとは?

SHARE:

一般的に、Kubernetes はセキュリティ監視や脅威検知機能を提供していません。セキュリティの問題は、クラスタ管理者であるお客様がご自身で監視し、対応していただく必要があります。

ただし、Kubernetes は、潜在的なセキュリティイベントを検出するための非常に重要なツールとして、監査ログを提供しています。Kubernetes API に対して発行されたアクセス要求の詳細を体系的に記録することで、監査ログはクラスター全体での不審な活動を検出するための中央集約型のリソースとして活用できます。

この記事では、Kubernetes 監査ログの定義、その使用方法、および監査ログを使用してセキュリティイベントを追跡する例について説明します。

Kubernetes を保護するために監査ログを使用する理由と方法

ここで学ぶ内容

  • Kubernetes 監査ログとは何か、およびその作成方法

  • 監査ログを使用して Kubernetes を保護する方法

  • Kubernetes 監査ログを最大限に活用する方法

Kubernetes 監査ログとは?

簡単に言えば、Kubernetes 監査ログは、Kubernetes 監査サービスからの情報を記録するログです。

監査ログの目的は、クラスタ管理者が、どのリクエストが開始されたか、誰が開始したか、どのリソースが影響を受けたか、および各リクエストの結果を追跡できるようにすることです。

したがって、監査データをログに記録して分析することで、リソースへの不正アクセス要求や、不明なユーザーまたはサービスによって開始された要求など、クラスタ内の潜在的なセキュリティ問題を早期に検出することができます。監査ログは、既存のセキュリティ侵害を調査する際にも非常に役立ちます(ただし、問題が深刻化する前に問題を検出できることを願っています!)。

監査ログは、作成した場合のみ Kubernetes内 に存在します

「Kubernetes 監査ログ」という言葉をよく耳にしますが、この用語は少し誤解を招く可能性があります。なぜなら、Kubernetes は特定の監査ログを直接作成しないからです。つまり、Kubernetes がすべての監査イベントを特定のファイルに自動的に記録し、そのファイルを開いたり tail コマンドで追跡したりしてセキュリティイベントを監視できるわけではありません。


その代わりに、Kubernetes は管理者がオプションで利用可能な機能を提供し、セキュリティイベントを記録し、管理者が選択したバックエンドにストリーム送信できます。したがって、Kubernetes ではさまざまな種類の監査ログを作成できますが、その具体的な性質は設定した構成に依存します。デフォルトでは監査ログは存在せず、最初に設定する必要があります。

Kubernetes 監査イベントとステージ

Kubernetes は、2 つの重要な概念、ステージと監査イベントに基づいて監査データを登録します。

監査イベントとは、API サーバーに対するあらゆるリクエストのことで、ステージは、サーバーが各リクエストを処理する際に経る手順に対応しています。

各イベントには 4 つの「ステージ」があります。

  • RequestReceived: このステージでは、API サーバーはリクエストを受信しましたが、まだ処理を開始していません。
  • ResponseStarted: サーバーはリクエストの処理を開始しましたが、まだ応答を送信していません。
  • ResponseComplete: サーバーはリクエストの処理を完了し、応答を送信しました。
  • パニック:このステージは、API サーバーがリクエストに対して「パニック」状態になった場合に発生します。

クラスタ内で発生するすべての監査イベントの各ステージに関する情報を監査ログに記録するように Kubernetes に指示することができます。これにより、セキュリティに関連するリクエストが発生したタイミングだけでなく、そのリクエストがどのように処理されたかも追跡することができます。

この細かさは、セキュリティインシデントの深刻度を評価するのに役立ちます。たとえば、ResponseStarted 段階でブロックされた悪意のある可能性のあるリクエストは、API サーバーがリクエストを許可するレスポンスを返す場合よりも心配は少なくなります。おそらく、両方のタイプのイベントについて知りたいと思うでしょうが、後者を優先付けするでしょう。Kubernetes 監査を使用すると、その違いを簡単に区別できます。

監査ログのフォーマット

デフォルトでは、Kubernetes は各監査イベントに関するデータを JSON 形式で生成します。ログファイルに保存できるイベントの例は、次のようになります。

{
  "kind": "Event",
  "apiVersion": "audit.k8s.io/v1beta1",
  "metadata": {
    "creationTimestamp": "2018-10-08T08:26:55Z"
  },
  "level": "Request",
  "timestamp": "2018-10-08T08:26:55Z",
  "auditID": "288ace59-97ba-4121-b06e-f648f72c3122",
  "stage": "ResponseComplete",
  "requestURI": "/api/v1/pods?limit=500",
  "verb": "list",
  "user": {
    "username": "admin",
    "groups": ["system:authenticated"]
  },
  "sourceIPs": ["10.0.138.91"],
  "objectRef": {
    "resource": "pods",
    "apiVersion": "v1"
  },
  "responseStatus": {
    "metadata": {},
    "code": 200
  },
  "requestReceivedTimestamp": "2018-10-08T08:26:55.466934Z",
  "stageTimestamp": "2018-10-08T08:26:55.471137Z",
  "annotations": {
    "authorization.k8s.io/decision": "allow",
    "authorization.k8s.io/reason": "RBAC: allowed by
    
    ClusterRoleBinding "admin-cluster-binding" of ClusterRole "cluster-
    admin" to User "admin""
  
  }
}Code language: PHP (php)

Kubernetes API サーバーでの監査の有効化

繰り返しになりますが、Kubernetes は監査イベントをログに記録する機能を提供していますが、デフォルトでは実際にログを記録するわけではありません。監査ログを生成するには、この機能を有効にして設定する必要があります。

そのためには、API サーバーの設定で 2 つのファイルの場所を指定する必要があります。

--audit-policy-file=/etc/kubernetes/audit-policy.yaml \
--audit-log-path=/var/log/audit.logCode language: JavaScript (javascript)

ここで、audit-policy.yaml は、ログに記録する監査イベントと、その記録方法を定義するファイルです。また、audit.log は、ログデータが実際に保存される場所(マスターノード上)です。

監査ポリシーファイルの定義

通常、クラスタ内で発生するすべての API リクエストをログに記録することは望ましくありません。そうすると、データ量が膨大になり、ノイズをフィルタリングすることが困難になります。

そのため、監査ポリシーファイルを作成します。監査ポリシーファイルは、YAML 形式のファイルで、ログに記録するイベントと、各イベントについて記録するデータ量を指定します。

例:

apiVersion: audit.k8s.io/v1 # This is required.
kind: Policy
# Don't generate audit events for all requests in RequestReceived stage.
omitStages:
  - "RequestReceived"
rules:
  # Log pod changes at RequestResponse level
  - level: RequestResponse
    resources:
    - group: ""
      # Resource "pods" doesn't match requests to any subresource of pods,
      # which is consistent with the RBAC policy.
      resources: ["pods"]
  # Only check access to resource "pods"
  - level: Metadata
    resources:
    - group: ""
      resources: ["pods/log", "pods/status"]
  # Don't log watch requests by the "system:kube-proxy" on endpoints or services
  - level: None
    users: ["system:kube-proxy"]
    verbs: ["watch"]
    resources:
    - group: "" # core API group
      resources: ["endpoints", "services"]
  # Don't log authenticated requests to certain non-resource URL paths.
  - level: None
    userGroups: ["system:authenticated"]
    nonResourceURLs:
    - "/api*" # Wildcard matching.
    - "/version"
  # Log the request body of configmap changes in kube-system.
  - level: Request
    resources:
    - group: "" # core API group
      resources: ["configmaps"]
    # This rule only applies to resources in the "kube-system" namespace.
    # The empty string "" can be used to select non-namespaced resources.
    namespaces: ["kube-system"]
  # Log configmap and secret changes in all other namespaces at the Metadata level.
  - level: Metadata
    resources:
    - group: "" # core API group
      resources: ["secrets", "configmaps"]
  # A catch-all rule to log all other requests at the Metadata level.
  - level: Metadata
    # Long-running requests like watches that fall under this rule will not
    # generate an audit event in RequestReceived.
    omitStages:
      - "RequestReceived"Code language: PHP (php)

上記のコメントからわかるように、このポリシーファイルは、記録される監査イベントの種類を絞り込んでいます。たとえば、RequestReceived ステージのイベントは無視し、ポッドへのアクセスのみを追跡します。

監査ログによるセキュリティイベントの検出

Kubernetes の監査の簡単な例として、次のような監査ポリシーファイルを作成したと想像してください。

apiVersion: audit.k8s.io/v1beta1
kind: Policy
omitStages:
- "RequestReceived"
Rules:
  - level: Request
  users: ["admin"]
  Resources:
    - group: ""
    resources: ["*"]
  - level: Request
    user: ["system:anonymous"]
  resources:
    - group: ""
    resources: ["*"]Code language: JavaScript (javascript)

この監査設定を使用すると、既存のロールまたはクラスターロールに関連付けられていない新しいユーザーがリクエストを発行したときにそれを検出できます。


たとえば、ユーザーが次のコマンドでポッドの一覧を表示しようとした場合を考えてみましょう。

kubectl get podsCode language: JavaScript (javascript)

ユーザーはポッドを一覧表示する権限がないため、API サーバーはリクエストを拒否します(kubectl は「サーバーからのエラー (Forbidden): pods is forbidden: User」と応答します)。


同時に、API サーバーは次のような監査イベントを記録します。

{
  "kind": "Event",
  "apiVersion": "audit.k8s.io/v1beta1",
  "metadata": {
    "creationTimestamp": "2018-10-08T10:00:20Z"
  },
  "level": "Request",
  "timestamp": "2018-10-08T10:00:20Z",
  "auditID": "5fc5eab3-82f5-480f-93d2-79bfb47789f1",
  "stage": "ResponseComplete",
  "requestURI": "/api/v1/namespaces/default/pods?limit=500",
  "verb": "list",
  "user": {
    "username": "system:anonymous",
    "groups": ["system:unauthenticated"]
  },
  "sourceIPs": ["10.0.141.137"],
  "objectRef": {
    "resource": "pods",
    "namespace": "default",
    "apiVersion": "v1"
  },
  "responseStatus": {
    "metadata": {},
    "status": "Failure",
    "reason": "Forbidden",
    "code": 403
  },
  "requestReceivedTimestamp": "2018-10-08T10:00:20.605009Z",
  "stageTimestamp": "2018-10-08T10:00:20.605191Z",
  "annotations": {
    "authorization.k8s.io/decision": "forbid",
    "authorization.k8s.io/reason": ""
  }
}Code language: JSON / JSON with Comments (json)

監査ログを追跡することで、管理者はそのリクエストを検出し、おそらく存在してはならないユーザーアカウントの存在を警告することができます。

Kubernetes 監査ログを最大限に活用

API サーバーが 1 時間あたり数百または数千ものリクエストを処理する大規模なクラスタでは、潜在的なリスクを検出するために監査ログを手作業で追跡することは現実的ではありません。

その代わりに、イベントログデータを、監査イベントを自動的に監視し、異常があった場合にアラートを生成する検出ツールにストリーミングすることをお勧めします。

これを行うには2つの方法があります。

  • 監査ログファイルを直接監視する:侵入検知ツールを、マスターノード上の監査ログファイルを直接監視するように設定できます。ただし、この方法ではツールをマスターノード上で実行する必要があります。これは、マスターノードの負荷が増加するため、望ましくない場合があります。(もちろん、マスターノードからログファイルを収集し、ローカルで実行されるログエージェントを使用して外部ツールに送信する方法は試すことができますが、この方法ではマスターノードに追加のソフトウェア(ログエージェント)を実行する必要があるため、根本的な問題解決にはなりません。)
  • HTTP 経由でイベントを送信する:Webhook を使用して、HTTP 経由でイベントデータを外部セキュリティツールに送信することができます。この方法では、セキュリティツールはクラスタから完全に分離して実行することができます。

たとえば、Falco(オープンソースのランタイムセキュリティツール)に監査イベントデータをストリーミングするには、kube-apiserver ファイルで Falco をバックエンド Webhook として設定します。

apiVersion: v1
kind: Config
clusters:
- name: falco
 cluster:
   server: http://$FALCO_SERVICE_CLUSTERIP:8765/k8s_audit
contexts:
- context:
   cluster: falco
   user: ""
 name: default-context
current-context: default-context
preferences: {}
users: []Code language: JavaScript (javascript)

この設定では、Falco(お好みのサーバーでホスト)を使用して、セキュリティイベントが発生したときにアラートを受け取ることができます。Kubernetes 監査ファイルを直接監視したり、クラスタ内でセキュリティソフトウェアを直接実行したりする必要はありません。

監査は、Kubernetes セキュリティ戦略に欠かせない要素です。監査ログは、Kubernetes の多くの機能と同様に、設定や管理がやや複雑ですが、高度にカスタマイズ可能です。Kubernetes では、記録する監査データのタイプ、保存場所、および監査データの操作方法を詳細に制御できます。

ログに記録する監査イベントのタイプを戦略的に決定し(ノイズを回避!)、監査データを、潜在的なリスクをリアルタイムで警告する侵入検知ツール(Falco など)と統合することで、Kubernetes のセキュリティ脅威を重大な問題になる前に発見して修正する能力を最大限に高めることができます。