Kubernetes のセキュリティの ABC: 認証、認可、監査

Kubernetes のセキュリティの ABC: 認証、認可、監査

遅かれ早かれ、どのようなシステムの運用においても、認証の確保、権利の分離、監査、その他のタスクといったセキュリティの問題が発生します。 Kubernetes用にすでに作成されています 多くの解決策、非常に要求の厳しい環境でも標準への準拠を実現できます...同じ資料が、K8 の組み込みメカニズム内に実装されるセキュリティの基本的な側面に当てられています。 まず第一に、これは、Kubernetes に慣れ始めている人にとって、セキュリティ関連の問題を勉強するための出発点として役立ちます。

認証

Kubernetes には XNUMX 種類のユーザーが存在します。

  • サービスアカウント — Kubernetes API によって管理されるアカウント。
  • ユーザー — 外部の独立したサービスによって管理される「通常の」ユーザー。

これらのタイプの主な違いは、サービス アカウントの場合、Kubernetes API に特別なオブジェクトがあることです (これらは - と呼ばれます)。 ServiceAccounts)、これらは、名前空間と、クラスター内の Secrets タイプのオブジェクトに格納されている承認データのセットに関連付けられています。 このようなユーザー (サービス アカウント) は、主に、Kubernetes クラスター内で実行されているプロセスの Kubernetes API へのアクセス権を管理することを目的としています。

一般ユーザーは Kubernetes API にエントリを持っていないため、外部メカニズムによって管理する必要があります。 これらは、クラスターの外部に存在する人々またはプロセスを対象としています。

各 API リクエストは、サービス アカウント、ユーザーのいずれかに関連付けられているか、匿名とみなされます。

ユーザー認証データには次のものが含まれます。

  • — ユーザー名 (大文字と小文字が区別されます!);
  • UID - 「ユーザー名よりも一貫性があり、一意である」機械可読なユーザー識別文字列。
  • グループ - ユーザーが所属するグループのリスト。
  • 余分 — 認可メカニズムで使用できる追加フィールド。

Kubernetes は、X509 証明書、ベアラー トークン、認証プロキシ、HTTP 基本認証など、多数の認証メカニズムを使用できます。 これらのメカニズムを使用すると、パスワードを含む静的ファイルから OpenID OAuth2 まで、多数の認証スキームを実装できます。

さらに、複数の認証スキームを同時に使用することができます。 デフォルトでは、クラスターは以下を使用します。

  • サービス アカウント トークン - サービス アカウント用。
  • X509 - ユーザー向け。

ServiceAccount の管理に関する質問はこの記事の範囲を超えていますが、この問題についてさらに詳しく知りたい場合は、以下から始めることをお勧めします。 公式ドキュメントページ。 X509 証明書がどのように機能するかという問題を詳しく見ていきます。

ユーザー用の証明書 (X.509)

証明書を扱う古典的な方法には次のようなものがあります。

  • 鍵の生成:
    mkdir -p ~/mynewuser/.certs/
    openssl genrsa -out ~/.certs/mynewuser.key 2048
  • 証明書リクエストの生成:
    openssl req -new -key ~/.certs/mynewuser.key -out ~/.certs/mynewuser.csr -subj "/CN=mynewuser/O=company"
  • Kubernetes クラスター CA キーを使用した証明書リクエストの処理、ユーザー証明書の取得 (証明書を取得するには、デフォルトで次の場所にある Kubernetes クラスター CA キーにアクセスできるアカウントを使用する必要があります) /etc/kubernetes/pki/ca.key):
    openssl x509 -req -in ~/.certs/mynewuser.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out ~/.certs/mynewuser.crt -days 500
  • 設定ファイルの作成:
    • クラスターの説明 (特定のクラスター インストールの CA 証明書ファイルのアドレスと場所を指定します):
      kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/pki/ca.crt --server=https://192.168.100.200:6443
    • あるいはどうやって ノー推奨オプション - ルート証明書を指定する必要はありません (ルート証明書を指定すると、kubectl はクラスターの API サーバーの正確性をチェックしません)。
      kubectl config set-cluster kubernetes  --insecure-skip-tls-verify=true --server=https://192.168.100.200:6443
    • 設定ファイルにユーザーを追加します。
      kubectl config set-credentials mynewuser --client-certificate=.certs/mynewuser.crt  --client-key=.certs/mynewuser.key
    • コンテキストの追加:
      kubectl config set-context mynewuser-context --cluster=kubernetes --namespace=target-namespace --user=mynewuser
    • デフォルトのコンテキスト割り当て:
      kubectl config use-context mynewuser-context

上記の操作を行った後、ファイル内で .kube/config 次のような構成が作成されます。

apiVersion: v1
clusters:
- cluster:
    certificate-authority: /etc/kubernetes/pki/ca.crt
    server: https://192.168.100.200:6443
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    namespace: target-namespace
    user: mynewuser
  name: mynewuser-context
current-context: mynewuser-context
kind: Config
preferences: {}
users:
- name: mynewuser
  user:
    client-certificate: /home/mynewuser/.certs/mynewuser.crt
    client-key: /home/mynewuser/.certs/mynewuser.key

アカウントとサーバー間で構成を転送しやすくするには、次のキーの値を編集すると便利です。

  • certificate-authority
  • client-certificate
  • client-key

これを行うには、base64 を使用して指定されたファイルをエンコードし、キーの名前にサフィックスを追加して構成に登録します。 -data、つまり受け取った certificate-authority-data

kubeadm を使用した証明書

リリースに伴い Kubernetes 1.15 アルファ版のサポートのおかげで、証明書の操作がはるかに簡単になりました。 kubeadmユーティリティ。 たとえば、ユーザー キーを含む構成ファイルを生成すると、次のようになります。

kubeadm alpha kubeconfig user --client-name=mynewuser --apiserver-advertise-address 192.168.100.200

NB: 必須 アドバタイズアドレス API サーバー構成内にあります。デフォルトでは次の場所にあります。 /etc/kubernetes/manifests/kube-apiserver.yaml.

結果の構成は標準出力に出力されます。 に保存する必要があります ~/.kube/config ユーザーアカウントまたは環境変数で指定されたファイル KUBECONFIG.

より深く掘り下げる

説明されている問題をさらに詳しく理解したい人向け:

承認

デフォルトの許可されたアカウントには、クラスター上で操作する権限がありません。 権限を付与するために、Kubernetes は承認メカニズムを実装します。

バージョン 1.6 より前の Kubernetes では、次のような認可タイプが使用されていました。 ABAC (属性ベースのアクセス制御)。 詳細については、以下を参照してください。 公式ドキュメント。 このアプローチは現在レガシーとみなされていますが、他の認証タイプと併用することもできます。

クラスターへのアクセス権を分割する現在の (そしてより柔軟な) 方法は、 RBAC (役割ベースのアクセス制御)。 バージョン以来安定していると宣言されています Kubernetes 1.8。 RBAC は、明示的に許可されていないものはすべて禁止される権利モデルを実装しています。
RBACを有効にするには、パラメータを使用して Kubernetes api-server を起動する必要があります --authorization-mode=RBAC。 パラメーターは、API サーバー構成を使用してマニフェストに設定されます。デフォルトでは、パスに沿って配置されます。 /etc/kubernetes/manifests/kube-apiserver.yaml、セクション内 command。 ただし、RBAC はデフォルトですでに有効になっているため、ほとんどの場合、心配する必要はありません。これは値で確認できます。 authorization-mode (すでに述べた中で kube-apiserver.yaml)。 ちなみに、その意味の中には他の種類の認可もあるかもしれません(node, webhook, always allow) ですが、それらの考察は資料の範囲外とさせていただきます。

ちなみに、すでに掲載しておりますが、 статью RBAC を使用する原理と機能についてはかなり詳細に説明されているため、ここでは基本と例の簡単なリストに限定します。

次の API エンティティは、RBAC 経由で Kubernetes でのアクセスを制御するために使用されます。

  • Role и ClusterRole — アクセス権を説明する役割:
  • Role 名前空間内の権利を記述できます。
  • ClusterRole - クラスター内。ノードなどのクラスター固有のオブジェクト、非リソース URL (つまり、Kubernetes リソースに関連しないものなど) を含みます。 /version, /logs, /api*);
  • RoleBinding и ClusterRoleBinding - バインディングに使用されます Role и ClusterRole ユーザー、ユーザー グループ、または ServiceAccount に送信します。

Role エンティティと RoleBinding エンティティは、名前空間によって制限されます。 同じ名前空間内にある必要があります。 ただし、RoleBinding は ClusterRole を参照でき、これにより一連の汎用アクセス許可を作成し、それらを使用してアクセスを制御できます。

ロールは、以下を含むルールのセットを使用して権限を記述します。

  • API グループ - を参照 公式ドキュメント apiGroups と出力による kubectl api-resources;
  • リソース (リソース: pod, namespace, deployment 等々。);
  • 動詞 (動詞: set, update など)。
  • リソース名 (resourceNames) - このタイプのすべてのリソースではなく、特定のリソースへのアクセスを提供する必要がある場合。

Kubernetes での認可のより詳細な分析については、次のページを参照してください。 公式ドキュメント。 その代わりに (というより、これに加えて)、彼女の仕事を説明する例を挙げましょう。

RBAC エンティティの例

シンプル Roleこれにより、ポッドのリストとステータスを取得し、名前空間でそれらを監視できます。 target-namespace:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: target-namespace
  name: pod-reader
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

ClusterRoleこれにより、ポッドのリストとステータスを取得し、クラスター全体でポッドを監視できます。

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  # секции "namespace" нет, так как ClusterRole задействует весь кластер
  name: secret-reader
rules:
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["get", "watch", "list"]

RoleBinding、これによりユーザーは mynewuser 名前空間内のポッドを「読み取る」 my-namespace:

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
  namespace: target-namespace
subjects:
- kind: User
  name: mynewuser # имя пользователя зависимо от регистра!
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role # здесь должно быть “Role” или “ClusterRole”
  name: pod-reader # имя Role, что находится в том же namespace,
                   # или имя ClusterRole, использование которой
                   # хотим разрешить пользователю
  apiGroup: rbac.authorization.k8s.io

イベント監査

概略的には、Kubernetes アーキテクチャは次のように表すことができます。

Kubernetes のセキュリティの ABC: 認証、認可、監査

リクエストの処理を担当する主要な Kubernetes コンポーネントは次のとおりです。 APIサーバー。 クラスター上のすべての操作はそれを経由します。 これらの内部メカニズムの詳細については、記事「kubectl run を実行すると、Kubernetes では何が起こりますか?'。

システム監査は Kubernetes の興味深い機能ですが、デフォルトでは無効になっています。 これにより、Kubernetes API へのすべての呼び出しをログに記録できます。 ご想像のとおり、クラスターの状態の監視と変更に関連するすべてのアクションは、この API を通じて実行されます。 その機能の詳しい説明は (いつものように) 次の場所にあります。 公式ドキュメント K8s。 次に、このトピックをより簡単な言葉で表現してみます。

このように、 監査を有効にするには、以下で詳しく説明する XNUMX つの必須パラメーターを API サーバーのコンテナーに渡す必要があります。

  • --audit-policy-file=/etc/kubernetes/policies/audit-policy.yaml
  • --audit-log-path=/var/log/kube-audit/audit.log
  • --audit-log-format=json

これら XNUMX つの必要なパラメータに加えて、ログのローテーションから Webhook の説明まで、監査に関連する追加の設定が多数あります。 ログローテーションパラメータの例:

  • --audit-log-maxbackup=10
  • --audit-log-maxsize=100
  • --audit-log-maxage=7

ただし、これ以上詳しくは説明しません。詳細はすべて次のとおりです。 kube-apiserver ドキュメント.

すでに述べたように、すべてのパラメーターは API サーバー構成を使用してマニフェストに設定されます (デフォルトでは /etc/kubernetes/manifests/kube-apiserver.yaml)、セクション内 command。 3 つの必須パラメータに戻って分析してみましょう。

  1. audit-policy-file — 監査ポリシーを記述する YAML ファイルへのパス。 後でその内容に戻りますが、ここでは、ファイルが API サーバー プロセスによって読み取れる必要があることに注意してください。 したがって、コンテナ内にマウントする必要があります。そのためには、構成の適切なセクションに次のコードを追加できます。
      volumeMounts:
        - mountPath: /etc/kubernetes/policies
          name: policies
          readOnly: true
      volumes:
      - hostPath:
          path: /etc/kubernetes/policies
          type: DirectoryOrCreate
        name: policies
  2. audit-log-path — ログ ファイルへのパス。 このパスは API サーバー プロセスにもアクセスできる必要があるため、同じ方法でそのマウントを説明します。
      volumeMounts:
        - mountPath: /var/log/kube-audit
          name: logs
          readOnly: false
      volumes:
      - hostPath:
          path: /var/log/kube-audit
          type: DirectoryOrCreate
        name: logs
  3. audit-log-format — 監査ログの形式。 デフォルトは jsonただし、従来のテキスト形式も使用できます (legacy).

監査方針

ここで、ログ ポリシーを記述した前述のファイルについて説明します。 監査ポリシーの最初の概念は、 level, ロギングレベル。 それらは次のとおりです。

  • None - ログを記録しません。
  • Metadata — ログリクエストのメタデータ: ユーザー、リクエスト時間、ターゲットリソース (ポッド、名前空間など)、アクションタイプ (動詞) など。
  • Request - メタデータとリクエスト本文をログに記録します。
  • RequestResponse — ログのメタデータ、リクエスト本文、および応答本文。

最後の XNUMX つのレベル (Request и RequestResponse) リソースにアクセスしなかったリクエスト (いわゆる非リソース URL へのアクセス) はログに記録されません。

また、すべてのリクエストが通過します いくつかの段階:

  • RequestReceived — リクエストがプロセッサーによって受信され、プロセッサーのチェーンに沿ってさらに送信されていない段階。
  • ResponseStarted — 応答ヘッダーは送信されますが、応答本文が送信される前に送信されます。 長時間実行されるクエリに対して生成されます (例: watch);
  • ResponseComplete — 応答本文が送信されたため、それ以上の情報は送信されません。
  • Panic — 異常な状況が検出されるとイベントが生成されます。

手順をスキップするには、使用できるもの omitStages.

ポリシー ファイルでは、異なるログ レベルを持ついくつかのセクションを記述することができます。 ポリシーの説明内で最初に見つかった一致ルールが適用されます。

kubelet デーモンは、api-server 構成を使用してマニフェストの変更を監視し、変更が検出された場合は、api-server を使用してコンテナーを再起動します。 ただし、重要な詳細があります。 ポリシーファイルの変更は無視されます。 ポリシー ファイルに変更を加えた後、API サーバーを手動で再起動する必要があります。 api-server が次のように起動されるため、 静的ポッド、 チーム kubectl delete 再起動の原因にはなりません。 手動で行う必要があります docker stop 監査ポリシーが変更された kube-masters では、次のようになります。

docker stop $(docker ps | grep k8s_kube-apiserver | awk '{print $1}')

監査を有効にする場合は、次の点に留意することが重要です。 kube-apiserver の負荷が増加する。 特に、リクエストコンテキストを格納するためのメモリ消費量が増加します。 ロギングは、応答ヘッダーが送信された後にのみ開始されます。 負荷は監査ポリシーの構成にも依存します。

政策の例

例を使用してポリシー ファイルの構造を見てみましょう。

ここに簡単なファイルがあります policyレベルですべてをログに記録するには Metadata:

apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata

ポリシーではユーザーのリストを指定できます(Users и ServiceAccounts)とユーザーグループ。 たとえば、これはシステム ユーザーを無視する方法ですが、それ以外はすべてレベルでログに記録します。 Request:

apiVersion: audit.k8s.io/v1
kind: Policy
rules:
  - level: None
    userGroups:
      - "system:serviceaccounts"
      - "system:nodes"
    users:
      - "system:anonymous"
      - "system:apiserver"
      - "system:kube-controller-manager"
      - "system:kube-scheduler"
  - level: Request

ターゲットを記述することもできます。

  • 名前空間 (namespaces);
  • 動詞 (動詞: get, update, delete その他);
  • リソース (リソース、次のように: pod, configmaps など) とリソース グループ (apiGroups).

注意! リソースとリソース グループ (API グループ、つまり apiGroups)、およびクラスターにインストールされているそれらのバージョンは、次のコマンドを使用して取得できます。

kubectl api-resources
kubectl api-versions

次の監査ポリシーは、ベスト プラクティスのデモンストレーションとして提供されています。 Alibaba Cloud ドキュメント:

apiVersion: audit.k8s.io/v1beta1
kind: Policy
# Не логировать стадию RequestReceived
omitStages:
  - "RequestReceived"
rules:
  # Не логировать события, считающиеся малозначительными и не опасными:
  - level: None
    users: ["system:kube-proxy"]
    verbs: ["watch"]
    resources:
      - group: "" # это api group с пустым именем, к которому относятся
                  # базовые ресурсы Kubernetes, называемые “core”
        resources: ["endpoints", "services"]
  - level: None
    users: ["system:unsecured"]
    namespaces: ["kube-system"]
    verbs: ["get"]
    resources:
      - group: "" # core
        resources: ["configmaps"]
  - level: None
    users: ["kubelet"]
    verbs: ["get"]
    resources:
      - group: "" # core
        resources: ["nodes"]
  - level: None
    userGroups: ["system:nodes"]
    verbs: ["get"]
    resources:
      - group: "" # core
        resources: ["nodes"]
  - level: None
    users:
      - system:kube-controller-manager
      - system:kube-scheduler
      - system:serviceaccount:kube-system:endpoint-controller
    verbs: ["get", "update"]
    namespaces: ["kube-system"]
    resources:
      - group: "" # core
        resources: ["endpoints"]
  - level: None
    users: ["system:apiserver"]
    verbs: ["get"]
    resources:
      - group: "" # core
        resources: ["namespaces"]
  # Не логировать обращения к read-only URLs:
  - level: None
    nonResourceURLs:
      - /healthz*
      - /version
      - /swagger*
  # Не логировать сообщения, относящиеся к типу ресурсов “события”:
  - level: None
    resources:
      - group: "" # core
        resources: ["events"]
  # Ресурсы типа Secret, ConfigMap и TokenReview могут содержать  секретные данные,
  # поэтому логируем только метаданные связанных с ними запросов
  - level: Metadata
    resources:
      - group: "" # core
        resources: ["secrets", "configmaps"]
      - group: authentication.k8s.io
        resources: ["tokenreviews"]
  # Действия типа get, list и watch могут быть ресурсоёмкими; не логируем их
  - level: Request
    verbs: ["get", "list", "watch"]
    resources:
      - group: "" # core
      - group: "admissionregistration.k8s.io"
      - group: "apps"
      - group: "authentication.k8s.io"
      - group: "authorization.k8s.io"
      - group: "autoscaling"
      - group: "batch"
      - group: "certificates.k8s.io"
      - group: "extensions"
      - group: "networking.k8s.io"
      - group: "policy"
      - group: "rbac.authorization.k8s.io"
      - group: "settings.k8s.io"
      - group: "storage.k8s.io"
  # Уровень логирования по умолчанию для стандартных ресурсов API
  - level: RequestResponse
    resources:
      - group: "" # core
      - group: "admissionregistration.k8s.io"
      - group: "apps"
      - group: "authentication.k8s.io"
      - group: "authorization.k8s.io"
      - group: "autoscaling"
      - group: "batch"
      - group: "certificates.k8s.io"
      - group: "extensions"
      - group: "networking.k8s.io"
      - group: "policy"
      - group: "rbac.authorization.k8s.io"
      - group: "settings.k8s.io"
      - group: "storage.k8s.io"
  # Уровень логирования по умолчанию для всех остальных запросов
  - level: Metadata

監査ポリシーのもう XNUMX つの良い例は次のとおりです。 GCEで使用されるプロファイル.

監査イベントに迅速に対応するには、次のことが可能です。 Webhook について説明する。 この問題については、次の記事で取り上げています。 公式ドキュメント, この記事の範囲外としておきます。

結果

この記事では、Kubernetes クラスターの基本的なセキュリティ メカニズムの概要を説明します。これにより、パーソナライズされたユーザー アカウントの作成、権限の分離、アクションの記録が可能になります。 理論上または実践上、このような問題に直面している人々にとって役立つことを願っています。 また、「PS」に記載されている、Kubernetes のセキュリティのトピックに関する他の資料のリストを読むことをお勧めします。おそらく、その中に、あなたに関連する問題について必要な詳細が見つかるでしょう。

PS

私たちのブログもお読みください:

出所: habr.com

コメントを追加します