Oracle Cloud Hangout Cafe Season5 #3「Kubernetes のセキュリティ」(2022年3月9日開催)

2023年4月18日(火)
市川 豊
連載第4回の今回は、2022年3月9日に開催された「Oracle Cloud Hangout Cafe Season5 #3『Kubernetes のセキュリティ』」の発表内容に基づいて紹介していきます。

CIS Benchmark

CIS(Center for Internet Security) Benchmarkは、インターネットセキュリティのベストプラクティスを標準化することを目的としたガイドラインです。システムやアプリケーションのセキュリティを強化するための様々な指針やベストプラクティスを確立し、共通の規約としてまとめられています。さらに、政府機関や企業など多様な組織に提供されているため、組織のセキュリティ体制を改善する手引きとして利用されています。

CIS Kubernetes Benchmarkは、Kubernetesクラスタのセキュリティを向上させるために、Kubernetesクラスタを構成する各コンポーネントのセキュリティに対する推奨事項を定義しています。Kubernetesのコンポーネントを軸に章立てされています。

  1. Control Plane Components
  2. etcd
  3. Control Plane Configuration
  4. Worker Nodes
  5. Policies

OSSだけではなく、マネージドサービス(各クラウドベンダー)向けのベンチマークも公開されています。公式サイトからCIS Kubernetes BenchmarkのPDFをダウンロードできます。

CIS Kubernetes Benchmarkに記載されている推奨事項は、数も多く手動で確認するのは現実的ではありません。管理しているKubernetesクラスタが、このCIS Kubernetes Benchmarkの推奨事項に準拠しているかを効率的に確認できるツールがOSSとして公開されています。その代表的なツールがkube-benchです。kube-benchはAqua Security社が公開し、対象のKubernetesクラスタ上でJobとして簡単に実行できます。

kube-bench

発表時のデモでは、以下の流れでkube-benchを実行しました。

  1. 「job-master.yaml」の作成
  2. kube-benchの実行
  3. 結果の確認

最初に、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フェーズを経由してリソースを登録します。

Kubernetesにおける認証認可

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

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に適用することで効率的に管理できます。

ClusterRoleとClusterRoleBinding

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)で紐づけるまでの流れを見ていきます。

Roleと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)で紐づけるまでの流れを見ていきます。

ClusterRoleと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
日本オラクル株式会社

Oracle Groundbreaker Advocate
Principal Cloud Solution Engineer

これまで、インフラエンジニア、フロントエンドエンジニアとして官公庁のシステム基盤を中心としたサーバの設計構築、運用保守、Webシステム開発を担当。技術教育者として専門学校でクラウド技術やOSS(Linux、Docker、Kubernetes)の授業を担当し、企業様向けプライベートトレーニング講師も担当。 アドボケート/エバンジェリストとしてミートアップ、カンファレンスで登壇。現在は、クラウドネイティブ技術を中心とするソリューションエンジニアとして活動。クラウドネイティブ技術に関連するコミュニティの運営にも積極的に参加。

Community:
Oracle Cloud Hangout Cafe メンバー (#ochacafe)
CloudNative Days Tokyo 実行委員会メンバー (#CNDT)

Book:
著書「Dockerコンテナ開発・環境構築の基本」(インプレス)
共著「RancherによるKubernetes活用完全ガイド」(インプレス)、「コンテナ・ベース・オーケストレーション Docker/Kubernetesで作るクラウド時代のシステム基盤」(翔泳社)

連載バックナンバー

仮想化/コンテナ技術解説
第6回

Oracle Cloud Hangout Cafe Season6 #1「Service Mesh がっつり入門!」(2022年9月7日開催)

2023/6/22
連載第6回の今回は、2022年9月7日に開催された「Oracle Cloud Hangout Cafe Season6 #1『Service Mesh がっつり入門!』」の発表内容に基づいて紹介していきます。
仮想化/コンテナ技術解説
第5回

Oracle Cloud Hangout Cafe Season5 #5「実験! カオスエンジニアリング」(2022年5月11日開催)

2023/5/18
連載第5回の今回は、2022年5月11日に開催された「Oracle Cloud Hangout Cafe Season5 #5『実験! カオスエンジニアリング』」の発表内容に基づいて紹介していきます。
仮想化/コンテナ技術解説
第4回

Oracle Cloud Hangout Cafe Season5 #3「Kubernetes のセキュリティ」(2022年3月9日開催)

2023/4/18
連載第4回の今回は、2022年3月9日に開催された「Oracle Cloud Hangout Cafe Season5 #3『Kubernetes のセキュリティ』」の発表内容に基づいて紹介していきます。

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています