1、Pod 使用 ServiceAccount
参考资料:https://kubernetes.io/zh/docs/tasks/configure-pod-container/configure-service-account/
大致意思这样:
1、创建一个 SA(ServiceAccount)
2、修改已有 yaml 文件指定创建的 SA
3、删除当前命名空间中未绑定 Pod 的 SA
创建一个sa
kubectl create serviceaccount backend-sa
修改yaml指定sa
kubectl get pod/nginx -o yaml > pod-nginx.yml
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- image: nginx
name: nginx
serviceAccountName: backend-sa # 修改这里
# Pod 被创建时服务账户必须存在,否则会被拒绝。
# 你不能更新已经创建好的 Pod 的服务账户。
kubectl delete po/nginx
kubectl create -f pod-nginx.yml
删除未被使用的serviceaccount
# 查询所有名命空间下所有的serviceaccount
kubectl get serviceaccount
# 查询所有被使用的serviceaccount
kubectl get pod -o yaml | grep -i serviceaccountname
# 删除未被使用的
kubectl delete serviceaccount geray
2、kube-bench
解读:使用 kube-bench 工具检查集群组件配置文件存在的问题与修复,并重启对应组件确保
新配置生效。
修复以下 apiserver 发现的问题:
- —authorization-mode 参数不能设置为AlwaysAllow,需要包含Node、RBAC( kube-apiserver.yaml )
修复以下 kubelet 发现的问题:
- 将kubelet中authentication.anonymous.enabled设置问false(/var/lib/kubelet/config.yaml)
- authorization.mode 不能包含AlwaysAllow
修复一下etcd发现的问题:
- —client-cert-auth=true 参数设置为true(/etc/kubernetes/manifests/etcd.yaml)
最后重启kubelet服务
# kubelet 获取配置文件
systemctl cat kubelet | grep -i Environment
# 修改 yaml 后,默认会重启容器,正常可以不用使用这个命令再重启,为确保重启生效可以再执行下
systemctl restart kubelet
3、网络策略
参考资料 : https://kubernetes.io/zh/docs/concepts/services-networking/network-policies/
解读:在 testing 命名空间创建一个名为 denypolicy 的网络策略。拒绝所有 Ingress 和Egress 流量。将网络策略应用到 testing 命名空间中的所有 pod。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: testing
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
- 拒绝所有pod进出流量
4、Pod安全策略(PSP)- 将被启用
参考资料:https://kubernetes.io/zh/docs/concepts/policy/pod-security-policy/
解读:
Create a new PodSecurityPolicy named restrict-policy,which prevents the creation of privieged Pods.
1. 创建一个名为 restrict-policy 的 PodSecurityPolicy,防止创建特权 Pod
2. 创建一个名为 restrict-access-role 的 ClusterRole 能够使用 PSP restrict-policy
3. 在 staging 命名空间创建一个名为 psp-denial-sa 的 ServiceAccount
4. 最后,创建一个名为 dany-access-bind 的 ClusterRoleBinding,绑定 ClusterRolerestrict-access-role 到 ServiceAccount psp-denial-sa
4.1 启用PSP准入控制器
# 启用 PSP 准入控制器
vi /etc/kubernetes/manifests/kube-apiserver.yaml
- --enable-admission-plugins=NodeRestriction,PodSecurityPolicy
systemctl restart kubelet
4.2 配置安全策略
vi psp.yaml
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: restrict-policy
spec:
privileged: false # Don't allow privileged pods!
# The rest fills in some required fields.
seLinux:
rule: RunAsAny
supplementalGroups:
rule: RunAsAny
runAsUser:
rule: RunAsAny
fsGroup:
rule: RunAsAny
volumes:
- '*'
kubectl apply -f psp.yaml
4.3 使用PSP
# 创建clusterrole(使用psp策略)
kubectl create clusterrole restrict-access-role --verb=use --resource=psp --resource-name=restrict-policy
# 创建serviceaccount在staging命名空间
kubectl create sa psp-denial-sa -n staging
# 创建ClusterRoleBinding绑定clusterrole和staging命名空间中的sa
kubectl create clusterrolebinding dany-access-bind --clusterrole=restrict-access-role --serviceaccount=staging:psp-denial-sa
5、RBAC
参考资料:https://kubernetes.io/zh/docs/reference/access-authn-authz/rbac/
解读:
1. 在 db 命名空间存在一个名为 web-pod 的 Pod
2. 编辑该 Pod 绑定的 ServiceAccount service-account-web Role,只允许对 Endpoints 资源类型执行 get 操作
3. 在 db 命名空间创建一个名为 role-2 的 Role,该角色只允许对 namespaces 资源类型执行delete 操作
4. 创建一个名为 role-2-binding 的 RoleBinding,绑定到 ServiceAccount
kubectl edit role -n db
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: db
name: role-1
rules:
- apiGroups: [""]
resources: ["endpoints"]
verbs: ["get"]
# 在 db 命名空间创建一个名为 role-2 的 Role,该角色只允许对 namespaces 资源类型执行delete 操作
kubectl create role role-2 -n db --verb=delete --resource=namespaces
# 创建一个名为 role-2-binding 的 RoleBinding,绑定到 ServiceAccount
kubectl create rolebinding role-2-binding --role=role-2 --serviceaccount=db:
service-account-web -n db
6、日志审计
参考资料:https://kubernetes.io/zh/docs/tasks/debug-application-cluster/audit/
解读:在集群启用审计,并确保:
日志路径为 /var/log/kubernetes/audit-logs.txt
日志文件保留 10 天
最多保留 2 个日志文件
基本策略在/etc/kubernetes/logpolicy/sample-policy.yaml 文件(该文件在 master 节点上)中提供,它指定了不记录的内容编辑和扩展基本策略:
命名空间在 RequestResponse 级别更改
PV 的request请求内容级别在 front-apps 命名空间发生了更改
Configmap 和 secret 在所有命名空间 Metadata 级别更改
做这道题之前最好先备份配置文件
# 配置策略文件
vi /etc/kubernetes/logpolicy/sample-policy.yaml
apiVersion: audit.k8s.io/v1 # This is required.
kind: Policy
omitStages:
- "RequestReceived"
rules:
- level: RequestResponse
resources:
- group: ""
resources: ["namespaces"]
- level: Request
resources:
- group: ""
resources: ["persistentVolumes"]
namespace: front-apps
- level: Metadata
resources:
- group: ""
resources: ["configmaps","secrets"]
- level: Metadata
omitStages:
- "RequestReceived"
# 开启日志审计并设置日志路径、保留天数、日志数量以及策略文件位置
vi /etc/kubernetes/manifests/kube-apiserver.yaml
...
# 设置日志审计参数
- --audit-policy-file=/etc/kubernetes/logpolicy/sample-policy.yaml
- --audit-log-path=/var/log/kubernetes/audit-logs.txt
- --audit-log-maxage=10
- --audit-log-maxbackup=2
...
# volumeMounts挂载日志升级策略到容器
- mountPath: /etc/kubernetes/logpolicy/sample-policy.yaml
name: log-policy
readOnly: true
- mountPath: /var/log/kubernetes/audit-logs.txt
name: log-audit
readOnly: false
...
# volumes中添加挂载
- hostPath:
path: /etc/kubernetes/logpolicy/sample-policy.yaml
type: File
name: log-policy
- hostPath:
path: /var/log/kubernetes/audit-logs.txt
type: FileOrCreate
name: log-audit
# 最后重启kubelet
kubectl restart kubelet
7、创建Secret
参考资料:https://kubernetes.io/zh/docs/concepts/configuration/secret/
解读:
1、在 istio-system 命名空间存在一个名为 db1-test 的 secret,将 username 字段保存到文
件名为/home/candidate/user.txt 和 password 字段保存到文件名为
/home/candidate/pass.txt
注:文件需要自己创建
2、在 istio-system 命名空间创建一个名为 db2-test 的 secret,内容如下:
username: production-instance
password: KvLftKgs4aVH
最后,创建一个新的 Pod,可以通过 volume 方式访问 secret 内容。
kubectl get secret db1-test -n istio-system -o jsonpath={.data.username} | base64 -d > /home/candidate/user.txt
kubectl get secret db1-test -n istio-system -o jsonpath={.data.password} | base64 -d > /home/candidate/pass.txt
kubectl create secret generic db2-test -n istio-system --from-literal=username=production-instance --from-literal=password=KvLftKgs4aVH
apiVersion: v1
kind: Pod
metadata:
name: secret-pod
namespace: istio-system
spec:
containers:
- name: dev-container
image: nginx
volumeMounts:
- name: secret-volume
mountPath: "/etc/secret"
volumes:
- name: secret-volume
secret:
secretName: db2-test
kubectl exec -it pod/secret-pod -n istio-system -- sh
8、Dockerfile和Deployment优化
解读:
分析和编辑给定的 Dockerfile(基于 Ubuntu:16.04 镜像)/home/candidate/KSSC00301/Dockerfile,修复文件中有突出安全性和最佳实践问题。
分析和编辑给定的 YAML 清单文件/home/candidate/KSSC00301/deployment.yaml,修复文件中字段存在安全性和最佳实践问题。
# Dockerfile禁用root用户
vi /home/candidate/KSSC00301/Dockerfile
#USER root
# 这里应该使用USER指定非root用户
vi /home/candidate/KSSC00301/deployment.yaml
…
securityContext:
capabilities:
add: ["NET_BIND_SERVICE"]
#privileged: true # 关闭这个特权启用
- user root 一共有两行
- 对 deploy 也注释2行 true的
9、沙箱运行容器gVisor
参考资料:https://kubernetes.io/zh/docs/concepts/containers/runtime-class/
描述:这个集群使用 containerd 作为 CRI 运行时。Containerd 的默认运行时处理程序是
runc,containerd 也支持额外的运行时处理程序 runsc(gVisor)
解读:创建一个名为 untrusted 的 RuntimeClass,使用准备好的运行时处理程序 runsc。
更新 server 命名空间中的所有 Pod 使其在 gVisor 上运行。
- 注:这个题目前有点变化,可能会让你修改 3 个 deployment
vi /home/candidate/KSMV00301/runtime-class.yaml
apiVersion: node.k8s.io/v1 # RuntimeClass 定义于 node.k8s.io API 组
kind: RuntimeClass
metadata:
name: untrusted # 用来引用 RuntimeClass 的名字
# RuntimeClass 是一个集群层面的资源
handler: runsc # 对应的 CRI 配置的名称
kubectl edit deployment web -n server
spec:
runtimeClassName: untrusted
containers:
- image: nginx
imagePullPolicy: Always
name: nginx
10、删除启用的特权pod
参考资料:https://kubernetes.io/zh/docs/concepts/security/pod-security-standards/
解读:检查在 production 命名空间运行的 Pod,并删除任何不是非无状态(有状态)或非不
可变(可变)的 Pod
以下是对无状态和不可变的解释:
在容器中存储数据的 Pod 视为非无状态(不用担心容器数据持久化)
启用特权的 Pod 都视为潜在的非无状态和非不可变
kubectl get pod -n production
kubectl get pod <pod-name> -n production -o yaml | grep "privileged: true"
kubectl delete pod <pod-name> -n production
11、网络策略
参考资料 : https://kubernetes.io/zh/docs/concepts/services-networking/network-policies
解读:创建一个名为 pod-restriction 的网络策略,以限制命名空间 dev-team 中 products-service Pod。
只允许以下 Pod 连接 products-service Pod:
qa 命名空间中的 Pod
Pod 标签为 environment:testing,在所有命名空间
# 查看products-service的pod的标签
kubectl get pod products-service -n dev-team --show-labels
# 查看qa命名空间的标签
vi network-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: pod-restriction
namespace: dev-team
spec:
podSelector:
matchLabels:
environment: staging
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: qa
- from:
- namespaceSelector: {} # 这个namespace是必须的吗,表示所有命名空间
podSelector:
matchLabels:
environment: testing
12、ImagePolicyWebhook (需要加强)
参考资料 : https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#imagepolicywebhook
提示:必须在集群 master 节点完成任务,其中包含的所有服务和文件已准备好。
解读:在/etc/kubernetes/epconfig 目录下有一个不完整的配置和一个功能容器镜像扫描器HTTPS 端点:https://acme.local:8082/image_policy
1. 启用准入控制插件
2. 验证控制配置并将其更改为默认拒绝。
3. 修改配置文件,指向正确的 HTTPS 端点最后,尝试部署易受供攻击的资源来测试配置是否有效。/root/KSSC00202/ulnerable-manifest.yml
查看容器扫描日志:/var/log/imagepolicy/roadrunner.log
# 第一步
vi /etc/kubernetes/manifests/kube-apiserver.yaml
…
- --enable-admission-plugins=NodeRestriction,ImagePolicyWebhook
- --admission-control-config-file=/
etc/kubernetes/epconfig/admission_configuration.json
...
# 在容器 volumeMounts 增加
- mountPath: /etc/kubernetes/epconfig
name: epconfig
# 在 volumes 增加
- name: epconfig
hostPath:
path: /etc/kubernetes/epconfig
# 第二步
vi /etc/kubernetes/epconfig/admission_configuration.json
defaultAllow: false
# 第三步
vi /etc/kubernetes/epconfig/kubeconfig.yaml
server: https://acme.local:8082/image_policy
systemctl restart kubelet
# 第四步 测试
kubectl apply -f /root/KSSC00202/ulnerable-manifest.yml
tail /var/log/imagepolicy/roadrunner.log
操作顺序:
- 1、修改admission_configuration.yaml配置文件(指定连接镜像服务器配置文件路径&修改defaultAllow为false)
- 2、修改kubeconfig.yaml(指定正确的server地址)
- 3、启动插件策略并指定配置文件以及挂载
- 4、查看日志
13、Trivy扫描镜像安全漏洞
解读:对 kamino 命名空间中 pod 使用 Trivy 工具扫描镜像安全漏洞。查找具有高危或严重漏洞的镜像,并删除使用这些镜像的 Pod。
注:Trivy 已经预装集群的 master 节点,工作节点不可用。
14、AppArmor
参考资料:https://kubernetes.io/zh/docs/tutorials/clusters/apparmor
解读:在集群的工作节点上,执行下面准备好的配置文件/etc/apparmor.d/nginx_apparmor编辑准备好的清单文件/home/candidate/KSSH00401/nginx-deploy.yaml 应用于 AppArmor 文件。
最后,在 Pod 中应用 apparmor 策略文件。
# 先进入工作节点操作
ssh kssh00401-worker1
# 确认策略名称
vi /etc/apparmor.d/nginx_apparmor
# nginx-profile-3
或者
apparmor_status | grep nginx
apparmor_parser /etc/apparmor.d/nginx_apparmor # 加载策略
# 在管理节点操作
vi /home/candidate/KSSH00401/nginx-deploy.yaml
…
annotations:
container.apparmor.security.beta.kubernetes.io/<容器名称>: localhost/nginx-profile-3
kubectl apply -f /home/candidate/KSSH00401/nginx-deploy.yaml
15、启用kubernetes API认证
描述:kubeadm 创建的集群的 Kubernetes API 服务器,出于测试目的,临时配置为允许未经身份验证和未经授权的访问,授予匿名用户集群管理员访问权限。
要求:重新配置集群的 Kubernetes API 服务器以确保只允许经过身份验证和授权的 API 请求。
使用授权模式 Node、RBAC 和准入控制器 NodeRestriction
删除名为 system:anonymous 的 ClusterRoleBinding
vi /etc/kubernetes/manifests/kube-apiserver.yaml
- kube-apiserver
- --authorization-mode=Node,RBAC # 只保留这两个
- --enable-admission-plugins=NodeRestriction # 只保留这一个
systemctl restart kubelet
# 删除角色绑定
kubectl delete clusterrolebinding system:anonymous