遅かれ早かれ、どのようなシステムの運用においても、認証の確保、権利の分離、監査、その他のタスクといったセキュリティの問題が発生します。 Kubernetes用にすでに作成されています
認証
Kubernetes には XNUMX 種類のユーザーが存在します。
- サービスアカウント — Kubernetes API によって管理されるアカウント。
- ユーザー — 外部の独立したサービスによって管理される「通常の」ユーザー。
これらのタイプの主な違いは、サービス アカウントの場合、Kubernetes API に特別なオブジェクトがあることです (これらは - と呼ばれます)。 ServiceAccounts
)、これらは、名前空間と、クラスター内の Secrets タイプのオブジェクトに格納されている承認データのセットに関連付けられています。 このようなユーザー (サービス アカウント) は、主に、Kubernetes クラスター内で実行されているプロセスの Kubernetes API へのアクセス権を管理することを目的としています。
一般ユーザーは Kubernetes API にエントリを持っていないため、外部メカニズムによって管理する必要があります。 これらは、クラスターの外部に存在する人々またはプロセスを対象としています。
各 API リクエストは、サービス アカウント、ユーザーのいずれかに関連付けられているか、匿名とみなされます。
ユーザー認証データには次のものが含まれます。
- — ユーザー名 (大文字と小文字が区別されます!);
- UID - 「ユーザー名よりも一貫性があり、一意である」機械可読なユーザー識別文字列。
- グループ - ユーザーが所属するグループのリスト。
- 余分 — 認可メカニズムで使用できる追加フィールド。
Kubernetes は、X509 証明書、ベアラー トークン、認証プロキシ、HTTP 基本認証など、多数の認証メカニズムを使用できます。 これらのメカニズムを使用すると、パスワードを含む静的ファイルから OpenID OAuth2 まで、多数の認証スキームを実装できます。
さらに、複数の認証スキームを同時に使用することができます。 デフォルトでは、クラスターは以下を使用します。
- サービス アカウント トークン - サービス アカウント用。
- X509 - ユーザー向け。
ServiceAccount の管理に関する質問はこの記事の範囲を超えていますが、この問題についてさらに詳しく知りたい場合は、以下から始めることをお勧めします。
ユーザー用の証明書 (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
- クラスターの説明 (特定のクラスター インストールの CA 証明書ファイルのアドレスと場所を指定します):
上記の操作を行った後、ファイル内で .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 を使用した証明書
リリースに伴い
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 の公式ドキュメントの証明書の操作について。 -
Bitnami からの良い記事 では、証明書の発行について実務的な観点から触れています。 -
一般的なドキュメント Kubernetes での認証について。
承認
デフォルトの許可されたアカウントには、クラスター上で操作する権限がありません。 権限を付与するために、Kubernetes は承認メカニズムを実装します。
バージョン 1.6 より前の Kubernetes では、次のような認可タイプが使用されていました。 ABAC (属性ベースのアクセス制御)。 詳細については、以下を参照してください。
クラスターへのアクセス権を分割する現在の (そしてより柔軟な) 方法は、 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
) ですが、それらの考察は資料の範囲外とさせていただきます。
ちなみに、すでに掲載しておりますが、
次の 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 コンポーネントは次のとおりです。 APIサーバー。 クラスター上のすべての操作はそれを経由します。 これらの内部メカニズムの詳細については、記事「
システム監査は Kubernetes の興味深い機能ですが、デフォルトでは無効になっています。 これにより、Kubernetes API へのすべての呼び出しをログに記録できます。 ご想像のとおり、クラスターの状態の監視と変更に関連するすべてのアクションは、この API を通じて実行されます。 その機能の詳しい説明は (いつものように) 次の場所にあります。
このように、 監査を有効にするには、以下で詳しく説明する 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
ただし、これ以上詳しくは説明しません。詳細はすべて次のとおりです。
すでに述べたように、すべてのパラメーターは API サーバー構成を使用してマニフェストに設定されます (デフォルトでは /etc/kubernetes/manifests/kube-apiserver.yaml
)、セクション内 command
。 3 つの必須パラメータに戻って分析してみましょう。
-
audit-policy-file
— 監査ポリシーを記述する YAML ファイルへのパス。 後でその内容に戻りますが、ここでは、ファイルが API サーバー プロセスによって読み取れる必要があることに注意してください。 したがって、コンテナ内にマウントする必要があります。そのためには、構成の適切なセクションに次のコードを追加できます。volumeMounts: - mountPath: /etc/kubernetes/policies name: policies readOnly: true volumes: - hostPath: path: /etc/kubernetes/policies type: DirectoryOrCreate name: policies
-
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
-
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
次の監査ポリシーは、ベスト プラクティスのデモンストレーションとして提供されています。
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 つの良い例は次のとおりです。
監査イベントに迅速に対応するには、次のことが可能です。 Webhook について説明する。 この問題については、次の記事で取り上げています。
結果
この記事では、Kubernetes クラスターの基本的なセキュリティ メカニズムの概要を説明します。これにより、パーソナライズされたユーザー アカウントの作成、権限の分離、アクションの記録が可能になります。 理論上または実践上、このような問題に直面している人々にとって役立つことを願っています。 また、「PS」に記載されている、Kubernetes のセキュリティのトピックに関する他の資料のリストを読むことをお勧めします。おそらく、その中に、あなたに関連する問題について必要な詳細が見つかるでしょう。
PS
私たちのブログもお読みください:
- «
33 以上の Kubernetes セキュリティ ツール "; - «
セキュリティ専門家のための Kubernetes ネットワーク ポリシーの概要 "; - «
Kubernetes の RBAC を理解する "; - «
9 Kubernetes セキュリティのベスト プラクティス "; - «
Kubernetes ハッキングの被害者にならない (被害者にならない) 11 の方法 '。
出所: habr.com