Cluster Hardening
CIS Benchmark
CIS(Center for Internet Security) Benchmarkは、インターネットセキュリティのベストプラクティスを標準化することを目的としたガイドラインです。システムやアプリケーションのセキュリティを強化するための様々な指針やベストプラクティスを確立し、共通の規約としてまとめられています。さらに、政府機関や企業など多様な組織に提供されているため、組織のセキュリティ体制を改善する手引きとして利用されています。
CIS Kubernetes Benchmarkは、Kubernetesクラスタのセキュリティを向上させるために、Kubernetesクラスタを構成する各コンポーネントのセキュリティに対する推奨事項を定義しています。Kubernetesのコンポーネントを軸に章立てされています。
- Control Plane Components
- etcd
- Control Plane Configuration
- Worker Nodes
- Policies
OSSだけではなく、マネージドサービス(各クラウドベンダー)向けのベンチマークも公開されています。公式サイトからCIS Kubernetes BenchmarkのPDFをダウンロードできます。
CIS Kubernetes Benchmarkに記載されている推奨事項は、数も多く手動で確認するのは現実的ではありません。管理しているKubernetesクラスタが、このCIS Kubernetes Benchmarkの推奨事項に準拠しているかを効率的に確認できるツールがOSSとして公開されています。その代表的なツールがkube-benchです。kube-benchはAqua Security社が公開し、対象のKubernetesクラスタ上でJobとして簡単に実行できます。
発表時のデモでは、以下の流れでkube-benchを実行しました。
- 「job-master.yaml」の作成
- kube-benchの実行
- 結果の確認
最初に、kube-bench公式のGitHubで公開されているjob-master.yamlの一部を編集します。
【マニフェストファイル:job-master.yaml】apiVersion: batch/v1
kind: Job
metadata:
name: kube-bench-master
spec:
template:
spec:
hostPID: true
nodeSelector:
node-role.kubernetes.io/master: ""
tolerations:
- key: node-role.kubernetes.io/master
operator: Exists
effect: NoSchedule
containers:
- name: kube-bench
image: aquasec/kube-bench:latest
#command: ["kube-bench", "run", "--targets", "master"]
command: ["kube-bench"] #変更
args: ["--version=1.23"] #追加
・
・(省略)
・
Kubernetesクラスタにjob-master.yamlを適用します。
$ kubectl apply -f job-master.yaml
job.batch/kube-bench-master created
結果を確認する上で必要となる、Pod名を確認しておきます。
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
kube-bench-master-64mwj 0/1 Completed 0 40s
結果を確認します。CIS Kubernetes Benchmarkの章立てベースに結果が表示されます。[FAIL]については設定方法まで出力されるので、その内容に従って管理しているKubernetesクラスタに適用するか検討します。この場合では、コントロールプレーンノードにある「/etc/kubernetes/manifests/kube-apiserver.yaml」の「--enable-admission-plugins」の箇所に「PodSecurityPolicy」を追加することになります。
$ kubectl logs kube-bench-master-64mwj
・
・(省略)
・
[FAIL] 1.2.15 Ensure that the admission control plugin PodSecurityPolicy is set (Automated)
・
・(省略)
・
== Remediations master ==
・
・(省略)
・
1.2.15 Follow the documentation and create Pod Security Policy objects as per your environment.
Then, edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
on the master node and set the --enable-admission-plugins parameter to a
value that includes PodSecurityPolicy:
--enable-admission-plugins=...,PodSecurityPolicy,...
Then restart the API Server.
・
・(省略)
・
== Summary master ==
42 checks PASS
11 checks FAIL
11 checks WARN
0 checks INFO
・
・(省略)
・
== Summary etcd ==
7 checks PASS
0 checks FAIL
0 checks WARN
0 checks INFO
・
・(省略)
・
== Summary controlplane ==
0 checks PASS
0 checks FAIL
3 checks WARN
0 checks INFO
・
・(省略)
・
== Summary node ==
19 checks PASS
1 checks FAIL
3 checks WARN
0 checks INFO
・
・(省略)
・
== Summary policies ==
0 checks PASS
0 checks FAIL
26 checks WARN
0 checks INFO
== Summary total ==
68 checks PASS
12 checks FAIL
43 checks WARN
0 checks INFO
※発表時はKubernetesクラスタ v1.25以前、CIS Kubernetes Benchmark v1.23の環境で実行したため、Kubernetes v1.25で廃止されたPodSecurityPolicyが提示される内容となっています。
Cluster Hardening
Kubernetesには、クラスタのセキュリティを強化する手段が実装されています。ここでは、Kubernetesにおける認証認可を整理して、RoleとRoleBinding、ClusterRoleとClusterRoleBindingを中心に、KubernetesのRBAC(Role-based Access Control)を理解します。
RBAC
1. Kubernetesにおける認証認可
Kubernetesにおける認証認可は、ユーザからKubernetesのAPI サーバにリクエスト送信後、以下の3フェーズを経由してリソースを登録します。
Authentication(認証)では、ユーザの正当性を確認します。Authorization(認可)では、ユーザがリクエストに対する権限を持っているかを確認します。Admission Controlでは、リクエスト内容が適切であるかを確認、設定に応じてリクエスト内容を処理します。
Kubernetesでは、認可方法の1つとしてRBACがあります。RBACについては「3. Kubenretesにおける認可」の箇所で説明します。
2. Kubernetesにおけるアカウントの種類
次に、Kubernetesに関連するServiceAccoutとUserAccoutの2つについて整理します。
ServiceAccountはKubernetesが管理するアカウントで、Namespaceに紐づいてPodで実行されるプロセスのために割り当てます。UserAccountは、Kubernetesが管理しないクラスタレベルの外部アカウントです。その特性からNamespaceの影響は受けません。例としては、クラウドプロバイダーやLDAPで管理されているアカウントです。
3. Kubernetesにおける認可
ここからは、さらにKubernetesにおける認可について解説します。
Kubernetesの認可方法は、Attribute-based Access Control(ABAC)とRole-based Access Control(RBAC)の2種類があります。ここではRBACを中心に見ていきます。
KubernetesにおけるRBACでは、RoleとRoleBindingの2種類のリソースを利用して権限を管理します。許可する操作を定めたRoleを作成し、Service AccountなどにそのRoleを紐づけるRoleBindingを利用して権限を付与します。
RoleとRoleBindingには、NamespaceとClusterレベルにおいて2種類のスコープがあり、各スコープのリソースに権限を設定できます。NamespaceスコープがRoleとRoleBindingで、ClusterスコープがClusterRoleとClusterRoleBindingです。Namespaceスコープの主なリソースはPod、Deployment、Service、ServiceAccout、PersistentVolumeClaimです。Clusterスコープの主なリソースはPersistentVolume、Namespace、Nodeです。
ClusterRoleとClusterRoleBindingは、全てのNamespaceに権限が付与されているため、Namespaceを横断して権限を管理できます。また、ClusterRoleはクラスタを横断して定義できるため、各クラスタのNamespaceからRoleBindingでClusterRoleを参照できます。クラスタ管理者が共通の定義を各クラスタのNamespaceに適用することで効率的に管理できます。
4. マニフェストを作成して適用する
ここからは、実際にKubernetesクラスタに適用することをベースに理解します。RoleとRoleBinding 、ClusterRoleとClusterRoleBindingをKubernetesクラスタに適用する場合は、PodやDeploymentなどと同様にマニフェストを作成します。
以下は、ServiceAccountを作成して、そのServiceAccountに特定の権限を定義したRole/ClusterRoleをRoleBinding/ClusterRoleBindingで紐づけるマニフェスト適用の流れと、マニフェストの適用例です。
a. RoleとRoleBindingのマニフェスト適用例
「$ kubectl get pods」による一覧取得(list)はOK、それ以外はNGという条件のRole(pod-role)を作成して、ServiceAccount(pod-sa)にRoleBinding(pod-rolebinding)で紐づけるまでの流れを見ていきます。
最初に、ServiceAccount(pod-sa)を作成します。
$ kubectl create serviceaccount pod-sa
serviceaccount/pod-sa created
ServiceAccount(pod-sa)が作成できたことを確認します。
$ kubectl get serviceaccounts
NAME SECRETS AGE
default 1 3h28m
pod-sa 1 9s
次に、条件とするRole(pod-role)のマニフェストを作成します。
$ kubectl create role pod-role --resource pods --verb list -o yaml --dry-run=client > pod-role.yaml
このマニフェストの内容は、以下です。
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
creationTimestamp: null
name: pod-role
rules:
- apiGroups:
- ""
resources:
- pods
verbs:
- list
「apiGroups」「resources」「verbs」の3つを指定し、「apiGroups」「resources」で指定するリソースに「verbs」の権限を定義します。RoleとClusterRoleの定義方法は基本的に同じです。
「verbs」については、表にまとめておきます。
| 種別 | 内容 |
|---|---|
| * | 全ての処理 |
| create | 作成 |
| delete | 削除 |
| get | 取得 |
| list | 一覧取得 |
| patch | 一部変更 |
| update | 更新 |
| watch | 変更の監視 |
マニフェストを適用します。
$ kubectl apply -f pod-role.yaml
role.rbac.authorization.k8s.io/pod-role created
適用されたことを確認します。
$ kubectl get roles
NAME CREATED AT
pod-role 2022-03-02T08:15:22Z
最後に、このRole(pod-role)をServiceAccount(pod-sa)にRoleBinding(pod-rolebinding)で紐づけます。最初にマニフェストを作成します。
$ kubectl create rolebinding pod-rolebinding --role pod-role --serviceaccount default:pod-sa -o yaml --dry-run=client > pod-rolebinding.yaml
このマニフェストの内容は、以下です。
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
creationTimestamp: null
name: pod-rolebinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: pod-role
subjects:
- kind: ServiceAccount
name: pod-sa
namespace: default
「roleRef」でClusterRoleに紐づける1ClusterRoleBindingに対して1ClusterRoleを指定、「subjects」でClusterRoleに紐づける複数のUserやServiceAccountを指定する仕様です。
マニフェストを適用します。
$ kubectl apply -f pod-rolebinding.yaml
rolebinding.rbac.authorization.k8s.io/pod-rolebinding created
適用されたことを確認します。
$ kubectl get rolebindings
NAME ROLE AGE
pod-rolebinding Role/pod-role 45s
実際に動作を確認してみます。ServiceAccout pod-saはPodの一覧取得のみ許可されているため、Podの一覧を取得できます。
$ kubectl --as=system:serviceaccount:default:pod-sa get pods
No resources found in default namespace.
Podを作成しようとすると、エラーが出て実行できません。
$ kubectl --as=system:serviceaccount:default:pod-sa run nginx --image=nginx
Error from server (Forbidden): pods is forbidden: User "system:serviceaccount:default:pod-sa" cannot create resource "pods" in API group "" in the namespace "default"
b. ClusterRoleとClusterRoleBindingのマニフェスト適用例
「$ kubectl get namespaces」による一覧取得(list)はOK、それ以外はNGという条件の ClusterRole(namespace-clusterrole)を作成し、ServiceAccount(namespace-sa)にClusterRoleBinding(namespace-clusterrolebinding)で紐づけるまでの流れを見ていきます。
最初に、ServiceAccount(namespace-sa)を作成します。
$ kubectl create serviceaccount namespace-sa
serviceaccount/namespace-sa created
作成できたことを確認します。
$ kubectl get serviceaccounts
NAME SECRETS AGE
default 1 4h
namespace-sa 1 9s
pod-sa 1 32m
次に、条件とするClusterRole(namespace-clusterrole)のマニフェストを作成します。
$ kubectl create clusterrole namespace-clusterrole --resource namespaces --verb list -o yaml --dry-run=client > namespace-clusterrole.yaml
このマニフェストの内容は、以下です。
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
creationTimestamp: null
name: namespace-clusterrole
rules:
- apiGroups:
- ""
resources:
- namespaces
verbs:
- list
マニフェストを適用します。
$ kubectl apply -f namespace-clusterrole.yaml
clusterrole.rbac.authorization.k8s.io/namespace-clusterrole created
適用されたことを確認します。
$ kubectl get clusterroles | grep namespace-clusterrole
namespace-clusterrole 2022-03-02T08:49:55Z
最後に、このClusterRole(namespace-role)をServiceAccount(namespace-sa)にClusterRoleBinding(namespace-rolebinding)で紐づけます。最初にマニフェストを作成します。
$ kubectl create clusterrolebinding namespace-clusterrolebinding \
--clusterrole namespace-clusterrole \
--serviceaccount default:namespace-sa \
-o yaml \
--dry-run=client > namespace-clusterrolebinding.yaml
このマニフェストの内容は、以下です。
kind: ClusterRoleBinding
metadata:
creationTimestamp: null
name: namespace-clusterrolebinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: namespace-clusterrole
subjects:
- kind: ServiceAccount
name: namespace-sa
namespace: default
「roleRef」でClusterRoleに紐づける1ClusterRoleBindingに対して1ClusterRoleを指定、「subjects」でClusterRoleに紐づける複数のUserやServiceAccountを指定する仕様です。
マニフェストを適用します。
$ kubectl apply -f namespace-clusterrolebinding.yaml
clusterrolebinding.rbac.authorization.k8s.io/namespace-clusterrolebinding created
適用されたことを確認します。
$ kubectl get clusterrolebindings | grep namespace-clusterrolebinding
namespace-clusterrolebinding ClusterRole/namespace-clusterrole
実際に動作を確認します。ServiceAccout namespace-saは、defaultのNamespaceでNamespaceの一覧のみ取得が許可されているため、Namespaceの一覧を取得できます。
kubectl --as=system:serviceaccount:default:namespace-sa get namespaces
NAME STATUS AGE
calico-apiserver Active 4h15m
calico-system Active 4h16m
default Active 4h18m
kube-node-lease Active 4h18m
kube-public Active 4h18m
kube-system Active 4h18m
tigera-operator Active 4h16m
Namespaceを作成しようとすると、エラーが出て実行できません。
kubectl --as=system:serviceaccount:default:namespace-sa create namespace mynamespace
Error from server (Forbidden): namespaces is forbidden: User "system:serviceaccount:default:namespace-sa" cannot create resource "namespaces" in API group "" at the cluster scope
- この記事のキーワード