監査ログで Kubernetes を保護するには?基本と活用方法

SHARE:

一般に、Kubernetes はセキュリティ監視や脅威検知の機能を備えていません。そのため、クラスター管理者自身が問題を検知して対応する必要があります。

そこで役立つのが、Kubernetesが提供するツールから得られる「監査ログ」です。このログは、Kubernetes APIに対して発行されたアクセスリクエストの詳細を体系的に記録し、クラスター全体の疑わしいアクティビティ・潜在的なセキュリティイベントを検出に役立ちます。脅威を正確に検知できれば、適切な対応を素早くおこなえるため、環境を保護しやすくなるでしょう。

この記事では、Kubernetes監査ログの役割と操作方法を説明したうえで、監査ログを使ってセキュリティイベントを追跡する場合の例をご紹介します。

関 連 記 事

Kubernetesとは?Kubernetesセキュリティ
の基礎
Kubernetesアーキテクチャの
設計方法
AWSのEKS
(Elastic Kubernetes Service)
Kubernetesの
クラスターとは?
 
Kubernetes のノードとは?
KubernetesのPodとは?KubernetesのHelmとは?クラウドセキュリティと
ランタイムインサイト

Kubernetes 監査ログとは

Kubernetes 監査ログとは、Kubernetes の監査サービスから収集した情報を記録したログのことです。

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

このように監査データを記録して分析すれば、リソースへの不正アクセスのリクエストや、不明なユーザーやサービスによって開始されたリクエストなど、クラスター内の潜在的なセキュリティの問題を早期に可視化することができます。既存のセキュリティ侵害を調査する際にも極めて有用です。

とはいえ、できればその段階に至る前に問題を発見することが望まれます。

デフォルトでは監査ログは得られない

Kubernetesにはデフォルトの監査ログが存在しないため、ログを得るには最初に設定する必要があります。

前提として、Kubernetes 自体が特定の監査ログを作成するわけではないため、「Kubernetes 監査ログ」という呼び方は誤解を招く恐れがあります。つまり、はすべての監査イベントを自動的に特定のファイルに記録し、それを開いて追跡するだけでセキュリティイベントを把握できるというわけではありません。

そうではなく、Kubernetesで提供されるのは、管理者が必要に応じてセキュリティイベントを記録し、任意のバックエンドにそれらをストリーミングするための機能です。設定さえ適切におこなえば、さまざまな種類の監査ログを作成できます。

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

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

監査イベントとは API サーバーへのあらゆるリクエストを指し、ステージとはサーバーが各リクエストを処理する際の段階を意味します。

各イベントには、考えられる 4 つの「ステージ」があります。

  • RequestReceived: このステージでは、API サーバーがリクエストを受信していますが、処理はまだ開始していません。
  • ResponseStarted: サーバーがリクエストの処理を開始しましたが、レスポンスはまだ送信していません。
  • ResponseComplete: サーバーがリクエストの処理を終了し、レスポンスを送信しました。
  • Panic: このステージは、リクエストへのレスポンスで、API サーバーに「重大なエラー」が生じた場合に発生します。

クラスター内で発生するすべての監査イベントのすべてのステージについて、監査ログに情報を記録するよう設定可能です。これにより、セキュリティ関連のリクエストがいつ発生したかだけでなく、どのように処理されたかも把握できます。

この詳細情報は、セキュリティインシデントの重大度の評価に役立ちます。たとえば、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 はログデータが実際に保存される(マスターノード上の)場所を示しています。

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

監査ポリシーファイルとは、どのイベントを記録し、各イベントについてどの程度のデータを記録するかを指定する YAML 形式のファイルです。

通常、クラスター内で発生するAPIリクエストをすべて記録する必要はありません。すべて記録するとデータが増えすぎ、ノイズの除去が難しくなります。監査ポリシーファイルを作成するのはそのためです。

たとえば、次のようになります。

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)

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

たとえば、そのユーザーが次のコマンドでポッドを一覧表示しようとしたとします。

kubectl get podsCode language: JavaScript (javascript)

このユーザーにはポッドを一覧表示する権限がないため、API サーバーはリクエストを拒否します(kubectl は「Error from server (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 監査ログを最大限に活用する

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 のセキュリティ脅威が大きな問題へと発展する前にそれを発見し、修正する能力を最大限に高めることができます。