decadence

個人のメモ帳

eks.privilegedを削除しないpspの設定方法について

これは何

EKSでPodSecurityPolicyを適切に設定しようとすると、必ずはまるeks.privileged。この記事ではeks.privilegedが何なのか、またEKSでpspを適切に設定する方法について1つの方法を記述する。

特に、色々な記事ではeks.privilegedを削除する方法が書かれているが、k8sやterraformのような宣言的resource管理において、管理外resourceを手動で削除しないで良い方法について考える。

PodSecurityPolicyの基本

PodSecurityPolicyを設定していますか?特権を持ったPodをk8s clusterで利用させない、等の制御をいれるためにはpspの設定は必須になる。

pspの基本として、以下のようなpspを作成する。

apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: example-psp
spec:
  privileged: false
...

pspの設定自体は大事だが、このpspを適用する際にどのようなRBACの設定をしているかが運用上は重要になる。

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: example-cluster-role
rules:
- apiGroups: ['policy']
  resources: ['podsecuritypolicies']
  verbs:     ['use']
  resourceNames:
  - example-psp
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: example-cluster-role-binding
roleRef:
  kind: ClusterRole
  name: example-cluster-role
  apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
  name: some-service-account
  namespace: some-namespace

上記のような設定をした場合には、 some-namespacesome-service-account というServiceAccountを付与したpodに対して適用される。

eks.privileged

EKSでは、万人の導入のしやすさのために、eks.privilegedというpspがデフォルトで作成される。*1 先に述べたとおり重要なのは、このデフォルトで作成されるpspが①どのようなpsp設定で、②どのようなRBAC設定がされているか、である。

eks.privilegedはk8s 1.12から1.13のmigrationのために、ガバガバな設定がされている。特に、eks.privilegedのpspを適用するためのRBAC設定として、以下の eks:podsecuritypolicy:authenticated のClusterRoleBindingがデフォルトで作成されており、これは認証済みのユーザ全てに対してeks.privilegedのpspを適用するといった設定になっている。つまり①もガバガバな上に、②もガバガバ設定になっている。

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: eks:podsecuritypolicy:authenticated
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: eks:podsecuritypolicy:privileged
subjects:
  - kind: Group
    apiGroup: rbac.authorization.k8s.io
    name: system:authenticated

きちんとしたpspの設定をeks clusterに対して適用したくても、上記の設定が残っている場合には、ガバガバ設定なままになってしまう。一例として Using Pod Security Policies with Amazon EKS Clusters | AWS Open Source Blog では、使いたいpspの設定をした上で、eks.privileged関連のresourceを削除するといった方法が記述されている

$ kubectl delete psp eks.privileged
$ kubectl delete clusterrole eks:podsecuritypolicy:privileged
$ kubectl delete clusterrolebindings eks:podsecuritypolicy:authenticated

良いpspの設定については Kubernetes - Pod Security Policies | Square Corner Blog を参照したり、EKS Best Practiceに載っている推奨設定を参考にすると良い。

github.com

また、以下のrepositoryでは順にkubectl applyをすることで推奨される設定にするような内容が含まれている。

kubernetes-security/PodSecurityPolicies at 6551896b43594419aa5fc273ecd114eaa0acc218 · therandomsecurityguy/kubernetes-security · GitHub

kubectl deleteをしない適用方法について

ここからが本題ではあるが、そもそもterraformやkubectl等でresourceを管理する場合には、deleteは基本的に使うことはあまり無い。今回はterraformやkubectlで我々が管理したいresource以外に、勝手にEKS側が作ってしまったresourceで困っているのである。特に、複数のclusterを運用している人にとって、新規にclusterを立ち上げる際に毎回deleteのオペレーションが入るのは望ましくないこともある。

1つの解のとして、以下のような方法がある。

---
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: example-granted
spec:
  privileged: false
... (ここにdefaultで適用したいpsp設定を記述)
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: example-granted-cluster-role
rules:
- apiGroups:
  - policy
  resourceNames:
  - example-granted
  resources:
  - podsecuritypolicies
  verbs:
  - use
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: eks:podsecuritypolicy:authenticated # ここをeks:podsecuritypolicy:authenticatedにすることで上書きをしている
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: example-granted-cluster-role
subjects:
# 全てのユーザに対して適用
- apiGroup: rbac.authorization.k8s.io
  kind: Group
  name: system:authenticated
- kind: Group
  name: system:unauthenticated
  apiGroup: rbac.authorization.k8s.io

この方法は、EKSが作成するClusterRoleBindingである eks:podsecuritypolicy:authenticated を上書きする設定となっている。example-grantedpspで権限を絞った上で、これを適用することで、新しく作成されたServiceAccount等にも、上記の設定を適用することが出来る。 上記の適用をする前に、特権が必要なnamespaceには予め別途pspの設定を行う必要があるので注意が必要だ。予め設定をする場合には、helmのCustomHooksのような仕組みを用いて、以下のようなフローで行う等の対応が必要になる。

  1. EKS cluster作成時に、eks.privileged, eks:podsecuritypolicy:authenticated 等が作成される
  2. helm CustomHooks等で、特定のnamespace等に特権等を利用させるpspを付与させる
  3. eks:podsecuritypolicy:authenticated を上書きして、機能制限したpspをdefaultで利用させる
  4. この上書きを行うことで、eks.privileged pspは存在しているが、どのroleにも適用されていない状態となる

このような対応を行うことで、resourceのdeleteを行うことなしに新規cluster等に対して適切なpspデフォルト設定を有効化させることが出来る。権限を絞る対応をする際には、blacklistで権限を絞ると新しく作成されるresourceに対する漏れが発生する。default設定をきつくした上で、 whitelist で特権が利用出来るroleは絞るべきである。


本記事は FOLIO Advent Calendar 2020 - Adventar として書きました。

弊社では、EKSやargoを用いた開発基盤等の導入などがすすめられています。 興味のある方は Ken Kaizu (@krrrr38) | Twitter に声をかけるか、以下のサイトから応募をお願いします。

corp.folio-sec.com

*1:デフォルトで導入されると言えばaws-auth ConfigMapを思い出すが、そういうもん