TKG service (vsphere with k8s) はESXiに対して、どこまで悪行を行えるか？

TKG Service (vSphere with k8s)はvSphere ESXi上にVMとPodが同居するという今までにないソリューションでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666491/09f99891-891c-fefd-cf8a-8b3a2e924566.png)
出典：https://blogs.vmware.com/vsphere/2020/04/vsphere-7-kubernetes-namespaces.html

つまりはESXi上に直接Podを立ち上げることができます。
ここで（わたしだけかもしれないですが）気になったのがESXi上のPodがどこまで悪いことができるか知りたいと思いました。

というのもk8sを使えば、悪い人はいくらでもホストを破壊できるためです。それがESXiが対象の場合なおさら、危険なものとなります。

# 注意点

当たり前ですが、この記事は悪いことを推奨しているわけです。
このTKG Serviceがどういう風にデザインしているかをよりよく知るために記載しています。

また、公式マニュアルにないもの全て、今後の実装で変わるかもしれません。あくまで実機の確認結果です。

# TL;DR

調査した結果、TKG ServiceのRBACおよびAdmissionControlはかなり綿密に設計されているようで、簡単にはPodからESXiを破壊できないようになっています。
悪行は諦めましょう。

なお、TKG Serviceをつかいつつ、もっと自由なKubernetesがほしい、という人が否定されているわけではないで誤解なさらないように。[Guest Cluster（正式名称Tanzu Kubernetes Cluster)という概念があり、TKG Service上にさらにVM + k8sを作る機能があります。](https://cormachogan.com/2020/04/07/building-a-tkg-guest-cluster-in-vsphere-with-kubernetes/)
多くの自由が欲しい場合は、そちらで作ることが推奨されています。

# 始めに

まず、そもそもどういう風にTKG Serviceをうごくかしらない方が多いと思うので、こちらの記事を[参照](https://qiita.com/hmachi/items/2ce7e4ca5e68c9e49c85)してください。

今回はこの中で、Can Viewを選択した時の挙動を取り上げたいと思います。

<img width="587" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666491/15587002-71a5-d924-6fdc-c5385cbc5fdb.png">


# Can Viewパーミッションで、「できないこと」

さて、さきの手順にもあったよう、Can Viewパーミッションを付与したことによって、直接ESXi上にPodが作れるようになりました。

まず、知っておくべきなのが、この**Can Viewパーミッションはk8sの最高権限にあたるClusterAdmin Roleではない**です。
内部的にはカスタマイズされたRoleが付与されており、意図的に操作を制限しています。

このロールで**できないこと**を、自分でしらべてみました。
なお、このあたりはあくまで私がわかる範囲であり、もれているかもしれない点ご了承ください。

## Create Namespace

できません。

```
mhoshino@mhoshino bin-2 % kubectl auth can-i create namespace
Warning: resource 'namespaces' is not namespace scoped
no
```

Listはできます。

```
% kubectl auth can-i list namespace
Warning: resource 'namespaces' is not namespace scoped
yes
% kubectl get ns
NAME                                        STATUS   AGE
default                                     Active   125m
hoge                                        Active   58m
...
```

これは、namespaceは先ほどあったよう、vCenterでのみつくることを想定しているためのようです。

## Create List PersistentVolume

できません。Listもできません。

```
% kubectl auth can-i list pv
Warning: resource 'persistentvolumes' is not namespace scoped
no
% kubectl auth can-i create pv
Warning: resource 'persistentvolumes' is not namespace scoped
no
```

PersistantVolumeClaimは作れます

```
% kubectl auth can-i create pvc
yes
```

なぜ、こうなっているか、次のStorageClassで解説します。

## Create StorageClass

できません。

```
% kubectl auth can-i create sc
Warning: resource 'storageclasses' is not namespace scoped in group 'storage.k8s.io'
no
```

Listはできます。

```
% kubectl auth can-i list sc
Warning: resource 'storageclasses' is not namespace scoped in group 'storage.k8s.io'
yes
```

さて、PersistantVolumeもそうですが、なぜストレージの類を制限しているかというと、このTKG Serviceでは、vCenterで定義したストレージのみを使用するようにされているからです。

TKG Serviceでは、VMFS/VVOL/vSANをサポートしており、vCenterでストレージポリシーとして定義されたものがKubernetesでもつかえるようになります。

UIのここです。

<img width="1131" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666491/d2f38c1a-06b8-aa53-5d50-3d45b848a118.png">
<img width="585" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666491/5170adbc-d1f1-478b-46ea-9af7602e5762.png">

なので、このUIをバイパスしたストレージの作成は許可されていないです。

## Create list Role, RoleBindings, ClusterRole, ClusterRoleBindings

なんとなく、予想していましたが、このあたりは全滅です。
新しいRoleをつくることはできません。Can View,Can Editが基本ロールで、それを使い分けてつかうことになります。

```
% kubectl auth can-i list role
no
% kubectl auth can-i create role
no

% kubectl auth can-i list rolebinding
no
% kubectl auth can-i create rolebinding
no

% kubectl auth can-i create clusterrole
Warning: resource 'clusterroles' is not namespace scoped in group 'rbac.authorization.k8s.io'
no
% kubectl auth can-i list clusterrole
Warning: resource 'clusterroles' is not namespace scoped in group 'rbac.authorization.k8s.io'
no

% kubectl auth can-i list clusterrolebinding
Warning: resource 'clusterrolebindings' is not namespace scoped in group 'rbac.authorization.k8s.io'
no
% kubectl auth can-i create clusterrolebinding
Warning: resource 'clusterrolebindings' is not namespace scoped in group 'rbac.authorization.k8s.io'
no
```

## Create list PodSecurityPolicies

このあたりもいじれません。

```
mhoshino@mhoshino bin-2 % kubectl auth can-i create psp
Warning: resource 'podsecuritypolicies' is not namespace scoped in group 'policy'
no
mhoshino@mhoshino bin-2 % kubectl auth can-i list psp
Warning: resource 'podsecuritypolicies' is not namespace scoped in group 'policy'
no
```

なお、PSPの中でも最も悪意のあるHostPID操作は許可されていません。

```
% kubectl apply -f hoge
Error from server (Forbidden): error when creating "hoge": pods "view-pid" is forbidden: unable to validate against any pod security policy: [spec.securityContext.hostPID: Invalid value: true: Host PID is not allowed to be used]
```

ESXi上のファイルシステムを直接マウントするHostPathも許可されていません。

```
% kubectl apply -f hoge
Error from server (Forbidden): error when creating "hoge": pods "view-pid" is forbidden: unable to validate against any pod security policy: [spec.securityContext.hostPID: Invalid value: true: Host PID is not allowed to be used spec.volumes[0]: Invalid value: "hostPath": hostPath volumes are not allowed to be used]
```

このHostPIDとHostPathでできる悪意は以下を参照してください。

https://gist.github.com/jjo/a8243c677f7e79f2f1d610f02365fdd7

## Create list CustomResourseDefinition

一部の人は悲しいかもしれないですが、CRDはだめです。
ほしい人は、GuestCluster上でやりましょう。

```
% kubectl auth can-i create crd
Warning: resource 'customresourcedefinitions' is not namespace scoped in group 'apiextensions.k8s.io'
no
% kubectl auth can-i list crd
Warning: resource 'customresourcedefinitions' is not namespace scoped in group 'apiextensions.k8s.io'
no
```

# AdmissionControlによって制限されていること

RBACとは、別に[AdmissionControl](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/)によってリソース作成がインターセプトされ、勝手にはつくられないようになっている箇所があります。
これも見つけた箇所を記載します。

## Control VMへのPodのデプロイ

AdmissionControlによってNoScheuleのTolerationsが削除されてしまい、デプロイできないです。
これも基本的にはControl VMがセキュアなオブジェクトとしてあつかわれているためのようです。

```
% kubectl apply -f hoge
Error from server: error when creating "hoge": admission webhook "admission.vmware.com" denied the request: Cannot add toleration { key:node-role.kubernetes.io/master, effect:NoSchedule } for master taint
```

## NodePortの作成

これも怒られます。基本的にはサービスは全てLB経由（TKG ServiceはNSXが前提）なので、ESXiノードのポートを直接公開しかねない操作はできないようになっています。

```
% kubectl expose deployment web --type=NodePort --port=8080
Error from server: admission webhook "admission.vmware.com" denied the request: Using ServiceType NodePort is not allowed
```


# まとめ

* TKG Serviceでは、k8sでそうそう簡単にはESXiを壊せない

どうしてもいじり放題のk8sがTKG Service上で欲しい場合、[Guest Cluster（正式名称Tanzu Kubernetes Cluster)](https://cormachogan.com/2020/04/07/building-a-tkg-guest-cluster-in-vsphere-with-kubernetes/)を使ってください。


# それでも悪行を働きたい！

[このブログ](https://www.pramodrane.com/vsphere-7-with-kubernetes-part-4-cloud-native-storage-with-vsphere-csi-for-persistent-volumes/)で公開されていますが、なんとClusterAdmin権限をとってしまう方法が記載されています。あえて詳細にはふれないですが、気になる方はぜひ。

これには**vCenterへのSSH**が必要となります。
あたりまえではありますが、**vCenterのSSHの意味のない公開はしないようにしてください。**