Kubernetes勉強会第2回 〜RBAC、セキュリティを高める方法、PodSecurityPolicy、NetworkPolicy〜
- 作者: Marko Luksa
- 出版社/メーカー: Manning Pubns Co
- 発売日: 2018/01/20
- メディア: ペーパーバック
- この商品を含むブログを見る
「Kubernetes in Action」を読んで学んだ結果を社内で共有しました。 その第2回の内容です。
RBAC
13. Securing cluster nodes and the network
nodeのネットワークを使用する方法
- podが自身のvirtualネットワークではなく、nodeのネットワークを使いたい場合、
hostNetwork
プロパティを設定すればOK。
apiVersion: v1 kind: Pod metadata: name: pod-with-host-network spec: hostNetwork: true #これ containers: - name: main image: alpine command: ["/bin/sleep", "999999"]
hostNetwork
プロパティをtrueにすれば、nodeあてのネットワークアクセスはそのpodに届くことになるKubernetes Control Plane components がpodとしてdeployされるとき、hostNetworkがONでデプロイされる。
- なのでまるでpodの中で動いていないように振る舞う
- 同じようにnodeのportを使いたい場合は、hostPortを設定すればOK。
- しかしその場合、そのpodはnodeに1つしか配置できない。なぜなら同じportを複数のpodで使えないから。
- 同じように hostPID: true、 hostIPC: true もできる
- もしGCP上でこれらを試したい場合は、
gcloud compute firewall-rules
コマンドを使って設定する必要がある。参考
コンテナのプロセス実行ユーザを制限する
- podのコンテナのプロセスの実行ユーザを限定する方法として、以下のようにユーザidを指定できる
apiVersion: v1 kind: Pod metadata: name: pod-as-user-guest spec: containers: - name: main image: alpine command: ["/bin/sleep", "999999"] securityContext: runAsUser: 405 # これ
またrootユーザとしてコンテナのプロセスを実行することを防ぐことができる 例えばhostディレクトリをマウントするコンテナが会った場合、rootユーザであればそのマウントしたディレクトリにフルアクセスできてしまう。しかしrootユーザ以外で動かせばそうではない。
apiVersion: v1 kind: Pod metadata: name: pod-run-as-non-root spec: containers: - name: main image: alpine command: ["/bin/sleep", "999999"] securityContext: runAsNonRoot: true #これ
セキュリティをあげるための方法
- podのコンテナのプロセスの実行ユーザを限定する(user idを指定)
- コンテナのプロセスをrootで動かさない
- コンテナをprivilegedで動かすと、nodeのカーネルにフルアクセスできてしまうので避ける
- SELinuxを設定する
- コンテナがfileシステムに書き込めないようにする(=read only)に設定する。
- コンテナの
readOnlyRootFilesystem
をtrueに
- コンテナの
- readonlyにしつつ、特定のvolumeは書き込めるようにもできる
またlinuxのcapabilities
をコンテナに指定することができる
SecurityContextをもっと詳しく知るためには以下を参照
13.3 Restricting the use of security-related features in pods
PodSecurityPolicyリソース
PodSecurityPolicyリソースとは
PodSecurityPolicy とはクラスタ全体のセキュリティ上のポリシーを定義する機能です。ホストに影響を与える可能性がある 特権 (privileged) や HostIPC などの機能を制限し Pod に脆弱性があった場合にクラスタを守ることができます。
引用元: Kubernetes: Pod Security Policy によるセキュリティの設定 PodSecurityPolicyに関しては上記の記事を読めば十分。(Z Labのエンジニアは本当に強い…)
PodSecurityPolicyはクラスタレベルのリソースです。 pod内でどんな機能が使えるのかもしくは使えないのかを定義することができます。 PodSecurityPolicyは働くためにはPodSecurityPolicy admission control pluginが API serverで動いている必要があります。
もし誰かがPodリソースを作成(API Serverへpost)しようとした場合、PodSecurityPolicy admission control pluginはPodの定義を定義されたPodSecurityPolicyに反していないかバリデートします。 もしクラスタのPolicyに従っていれば受け入れられetcdに保存されます。従っていなければ即時に却下されます。 PodSecurityPolicy admission control pluginはPodリソースをpolicyの設定に沿って変更するかもしれません(例えばコンテナ実行ユーザをPodSecurityPolicyで指定したユーザにoverrideすることができる)。 ちなみにpolicyを新しく作成しても既存のpodには影響を与えません。なぜならPodSecurityPoliciesはpodが作成/更新されるとき適用されるため。
PodSecurityPolicyで制限できること
- どのpodがホストのIPC, PID or Network namespaceを使用できるか
- どのホストポートをpodが使えるか
- どのユーザでコンテナのプロセスを動かすか
- privileged containeを持ったpodを作れるかどうか
- どの kernel capabilitieを許可するか、またデフォルトでどのkernel capabilitieを追加or削除するか
- どんな SELinuxLabelをコンテナが使うか
- コンテナがrootファイルシステムを書き込み許可するかどうか
- コンテナがどのfile system groupを実行できるか
- podがどのvolumeタイプを使用できるか
例
apiVersion: extensions/v1beta1 kind: PodSecurityPolicy metadata: name: restricted-psp spec: hostIPC: false hostPID: false hostNetwork: false hostPorts: # 使用できるport rangeを指定 - min: 10000 max: 11000 - min: 13000 max: 14000 privileged: false readOnlyRootFilesystem: true runAsUser: rule: RunAsAny fsGroup: rule: RunAsAny supplementalGroups: rule: RunAsAny seLinux: rule: RunAsAny # コンテナが必要とするどんなSELinux groupも使用することができる volumes: - '*' # 全てのvolume typeを使用することができる
PodSecurityPolicyをRoleとして定義でき、RBACによって、ServiceAccountに紐付ける(bindingする)ことができる。
# 先のPodSecurityPolicyリソースを作成 & kubectl create -f restricted-psp.yaml # PodSecurityPolicyをClusterRoleとして定義 $ kubectl create clusterrole psp-cluster-role --verb=use --resource=podsecuritypolicies --resource-name=restricted-psp # ServiceAccountを作成 $ kubectl create serviceaccount psp-service-account # ClusterRoleをServiceAccountに紐付ける(binding) $ kubectl create clusterrolebinding psp-restricted --clusterrole=psp-cluster-role \ --serviceaccount=default:psp-service-account # あとはpodにServiceAccount:psp-service-accountを指定して、例えばprivileged: trueにするとpodは作成できなくなる。
13.4 Isolating the pod network
もしnetworking pluginがpod間のネットワーク通信制限機能をサポートしていれば、NetworkPolicy
リソースを作成することによって、
ネットワークの隔離をすることができる。
NetworkPolicy
リソースはlabel selectorにマッチしたpodに対して適用される。そしてpodへの外への通信とpodの中への通信を制限することができる。
ingress rule
, egress rule
と呼ばれる。Ingressリソースとは関係がない。
ingressはネットワークの流入、egressはネットワークの流出のルールを定義できる。
このpodはこのpodへしかリクエストを送れないor受け取れないとかこのportを使ってしかあのpodへリクエストを送れないor受け取れないとかが設定できる。 また特定のlabelがついたnamespace内のpodからリクエストを受け取らないということができる。 もしくはcidrを使ってリクエストを制限することもできる。
例:
以下のingress/egressルールにマッチするものだけ通信が許可される。
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: test-network-policy spec: podSelector: matchLabels: role: db # このlabelを持ったpodがこのNetworkPolicyルールの対象になる ingress: - from: - ipBlock: cidr: 172.17.0.0/16 except: - 172.17.1.0/24 - namespaceSelector: matchLabels: project: myproject - podSelector: matchLabels: role: frontend ports: - protocol: TCP port: 6379 egress: - to: - ipBlock: cidr: 10.0.0.0/24 ports: - protocol: TCP port: 5978
13.5 Summary
- podは自分のではなくnodeの Linux namespacesを使うことができる
- コンテナはコンテナイメージで指定されたユーザ/グループとは別のユーザ/グループで実行するように設定することができる
- コンテナはprivileged modeで動かすことができ、privileged modeだとpodに公開されていないnodeのdeviceにアクセスすることができる。
- コンテナはプロセスがファイル書き込みをしないようにread onlyで動くように設定することができる(また特定のvolumeのみ書き込みが可能に設定できる)
- Cluster-levelリソースであるPodSecurityPolicyは、nodeの安全を脅かすpodの生成を防ぐことができる。
- PodSecurityPolicyはRBACのClusterRoleとClusterRoleBindingを使って特定のuserに紐付けることができる。
- NetworkPolicyリソースはpodのinbound/outbound trafficを制限することができる。
Podのセキュリティを高めるためには以下を参照
Kubernetesのセキュリティを高めるためには以下を参照
- Kubernetes Security Best Practices
- Kubernetes Best Practices with Sandeep Dinesh (Google) にもセキュリティの Best Practicesが紹介されている