LabHub
学习 学习路径 课程

CKS — Kubernetes 安全专家

从默认拒绝开始搭集群

在 LabHub 中继续学习

目标

熟练掌握先将一个命名空间设为默认拒绝,再逐一重新开放必要通道的顺序,并亲自写出控制平面配置文件中需要检查的内容。

为什么重要

Kubernetes 默认全部开放。没有任何策略的 Pod 可以与集群中任意 Pod 通信,也能直接访问节点元数据地址。因此,安全设计的第一步不是添加阻止某项行为的规则,而是先阻止一切,再恢复必要部分。如果顺序相反,就永远无法知道“遗漏了什么”。配置文件审计也是同一思路。与观察运行中的进程相比,阅读一份清单更快,也能列出缺少的内容。

此实验环境没有真实数据平面,因此无法确认策略是否真的切断了流量。评分检查对象规范是否按意图编写。考试要求的同样是准确的规范。

步骤

  1. 创建命名空间 cks-net,并添加标签 tier=restricted
  2. cks-net 中创建 NetworkPolicy default-deny-all。将 podSelector 留空, 在 policyTypes 中同时写入 IngressEgress,但不设置任何 ingress/egress 规则。
  3. cks-net 中创建 NetworkPolicy allow-dns-egress。目标为所有 Pod, policyTypes 仅为 Egress;egress 目标是带有 kubernetes.io/metadata.name=kube-system 标签的 命名空间中带有 k8s-app=kube-dns 标签的 Pod,端口为 UDP 53 和 TCP 53。
  4. cks-net 中创建 NetworkPolicy allow-frontend-to-api。目标为 app=api Pod, ingress 允许来源为同一命名空间中的 app=frontend Pod,端口为 TCP 8080。
  5. cks-net 中创建 NetworkPolicy deny-node-metadata。目标为所有 Pod,policyTypesEgress;egress 目标使用 ipBlock,设置 cidr: 0.0.0.0/0except: [169.254.169.254/32]
  6. cks-net 中创建类型为 kubernetes.io/tls 的 Secret shop-tlstls.crttls.key 均不得为空。
  7. cks-net 中创建 Ingress shopspec.tls[0]hostsshop.cks.localsecretNameshop-tlsspec.rules[0].host 也为 shop.cks.local,路径 / 将流量 发送到 Service api 的 8080 端口。
  8. /root/cks-cluster-setup/kube-apiserver.yaml 中编写反映 CIS 建议的静态 Pod 清单。 kind: Pod,容器名称为 kube-apiservercommand 数组中包含 --anonymous-auth=false--authorization-mode=Node,RBAC--profiling=false--audit-log-path=/var/log/kubernetes/audit.log--enable-admission-plugins=NodeRestriction,PodSecurity,且不得包含任何以 --insecure-port 开头的标志。

参考

创建要隔离的命名空间

创建命名空间 cks-net,并添加标签 tier=restricted

创建命名空间并添加标签。可先执行 kubectl create ns,再执行 kubectl label ns,也可以用一份清单完成。

默认策略:阻止所有 ingress 与 egress

cks-net 中创建 NetworkPolicy default-deny-all。将 podSelector 留空, 在 policyTypes 中同时写入 IngressEgress,但不设置任何 ingress/egress 规则。

podSelector: {} 会选择命名空间中的所有 Pod。在 policyTypes 中指定方向,但完全不设置 ingress/egress 规则列表,即会拒绝该方向的所有流量。

仅为 DNS 开放 egress 例外

cks-net 中创建 NetworkPolicy allow-dns-egress。目标为所有 Pod, policyTypes 仅为 Egress;egress 目标是带有 kubernetes.io/metadata.name=kube-system 标签的 命名空间中带有 k8s-app=kube-dns 标签的 Pod,端口为 UDP 53 和 TCP 53。

kube-dns Pod 位于 kube-system 命名空间,并带有 k8s-app=kube-dns 标签。可以通过 kubernetes.io/metadata.name 标签选择命名空间。53 端口需要同时开放 UDP 和 TCP。

只开放必要 Pod 对的 ingress

cks-net 中创建 NetworkPolicy allow-frontend-to-api。目标为 app=api Pod, ingress 允许来源为同一命名空间中的 app=frontend Pod,端口为 TCP 8080。

使用 podSelector 选择接收方,使用 ingress[].from[].podSelector 选择发送方。不指定端口会开放所有端口。

排除通往节点元数据的路径

cks-net 中创建 NetworkPolicy deny-node-metadata。目标为所有 Pod,policyTypesEgress;egress 目标使用 ipBlock,设置 cidr: 0.0.0.0/0except: [169.254.169.254/32]

ipBlock 可以为一个 cidr 附加 except 列表,且 except 的网段必须位于 cidr 内。

用于 Ingress 的 TLS Secret

cks-net 中创建类型为 kubernetes.io/tls 的 Secret shop-tlstls.crttls.key 均不得为空。

kubernetes.io/tls 类型的 Secret 必须包含 tls.crttls.key 两个键。可使用 openssl 创建自签名证书,也可以在清单中直接填入 base64 值。

为 Ingress 连接 TLS

cks-net 中创建 Ingress shopspec.tls[0]hostsshop.cks.localsecretNameshop-tlsspec.rules[0].host 也为 shop.cks.local,路径 / 将流量 发送到 Service api 的 8080 端口。

Ingress 的 spec.tlshosts 列表与 secretName 配对。spec.rules 中的主机与 spec.tls[].hosts 不一致时,证书不会生效。

审计 kube-apiserver 清单

/root/cks-cluster-setup/kube-apiserver.yaml 中编写反映 CIS 建议的静态 Pod 清单。 kind: Pod,容器名称为 kube-apiservercommand 数组中包含 --anonymous-auth=false--authorization-mode=Node,RBAC--profiling=false--audit-log-path=/var/log/kubernetes/audit.log--enable-admission-plugins=NodeRestriction,PodSecurity,且不得包含任何以 --insecure-port 开头的标志。

静态 Pod 清单使用 kind: Pod,标志位于 spec.containers[0].command 数组中。CIS 建议禁用匿名认证、使用 Node+RBAC 授权、禁用性能分析并启用 NodeRestriction Admission;同时应完全移除未经认证的明文端口标志。