1、k8s安全配置 - 网络策略

官方文档:https://kubernetes.io/zh/docs/concepts/services-networking/network-policies/

测试案例:

kubectl run network-pod1 --image=busybox:1.28 -n network-test -- sleep 24h

kubectl run network-pod2 --image=busybox:1.28 -n network-test -- sleep 24h

kubectl run network-pod --image=busybox:1.28 -n network-test1 -- sleep 24h

kubectl run nginx1 --image=nginx -n network-test

kubectl run test1 --image=busybox:1.28 -- sleep 24h

kubectl run test2 --image=busybox:1.28 -- sleep 24h

案例1:拒绝命名空间下所有Pod出入站流量

拒绝network-test名称空间下的所有pod的出、入站流量

  1. apiVersion: networking.k8s.io/v1
  2. kind: NetworkPolicy
  3. metadata:
  4. name: network-test-deny
  5. namespace: network-test
  6. spec:
  7. podSelector: {}
  8. policyTypes:
  9. - Ingress
  10. - Egress
  • pod完全孤立

案例2:拒绝其他命名空间Pod访问

network-test命名空间下所有pod可以互相访问,也可以访问其他 命名空间Pod,但其他命名空间不能访问test命名空间Pod。

  1. apiVersion: networking.k8s.io/v1
  2. kind: NetworkPolicy
  3. metadata:
  4. name: network-test-deny
  5. namespace: network-test
  6. spec:
  7. podSelector: {}
  8. policyTypes:
  9. - Ingress
  10. ingress:
  11. - from:
  12. - podSelector: {}

案例3:允许其他命名空间Pod访问指定应用

允许其他命名空间访问network-test命名空间指定Pod(带有run=network-pod1标签的Pod)

  • 无法添加策略(比较复杂)

案例4:同一个命名空间下应用之间限制访问

将network-test命名空间中标签为run=nginx1的pod隔离, 只允许标签为run=test1的pod访问80端口

  1. apiVersion: networking.k8s.io/v1
  2. kind: NetworkPolicy
  3. metadata:
  4. name: network-test-deny
  5. namespace: network-test
  6. spec:
  7. podSelector:
  8. matchLabels:
  9. run: nginx1
  10. policyTypes:
  11. - Ingress
  12. ingress:
  13. - from:
  14. - podSelector:
  15. matchLabels:
  16. run: test1
  17. ports:
  18. - protocol: TCP
  19. port: 80
  • 该策略是,只允许同一名称空间的带有run=test1标签的pod访问(测试时需要添加pod)

案例5:只允许指定命名空间中的应用访问

允许指定名称空间(ns=network-test2)的所有pod以及其他名称空间中带有指定标签(run=test1)的pod访问network-test名称空间中带有run=nginx1的Pod

  1. apiVersion: networking.k8s.io/v1
  2. kind: NetworkPolicy
  3. metadata:
  4. name: network-test-deny
  5. namespace: network-test
  6. spec:
  7. podSelector:
  8. matchLabels:
  9. run: nginx1
  10. policyTypes:
  11. - Ingress
  12. ingress:
  13. - from:
  14. - namespaceSelector:
  15. matchLabels:
  16. ns: network-test2
  17. - from:
  18. - namespaceSelector: {}
  19. podSelector:
  20. matchLabels:
  21. run: test1

2、k8s集群强化讲义

案例1:对用户授权访问K8s(TLS证书)

  • 用户组:用户组的好处是无需单独为某个用户创建权限,统一为这个组名进 行授权,所有的用户都以组的身份访问资源

CKS-学习案例 - 图1

为dev用户组统一授权

1、将certs.sh文件中的aliang-csr.json下的O字段改为dev,并重新生成证书和kubeconfig文件

2、将dev用户组绑定Role(pod-reader)

3、测试,只要O字段都是dev,这些用户持有的kubeconfig文件都拥有相同的权限

案例2:对应用程序授权访问K8s(ServiceAccount)

先了解下ServiceAccount,简称SA,是一种用于让程序访问K8s API的服务账号。

• 当创建naamespace时,会自动创建一个名为default的SA,这个SA没有绑定任何权限

• 当default SA创建时,会自动创建一个default-token-xxx的secret,并自动关联到SA

• 当创建Pod时,如果没有指定SA,会自动为pod以volume方式挂载这个default SA,在容器目录:/var/run/secrets/kubernetes.io/serviceaccount

验证默认SA权限:kubectl —as=system:serviceaccount:default:default get pods

kubectl —as=system:serviceaccount:命名空间:sa名称 get pods

CKS-学习案例 - 图2

授权容器中Python程序对K8s API访问权限

  1. 创建Role

  2. 创建ServiceAccount

  3. 将ServiceAccount与Role绑定

  4. 为Pod指定自定义的SA

  5. 进入容器里执行Python程序测试操作K8s API权限

3、k8s容器运行环境安全加固

案例:容器文件系统访问限制

步骤:

1、将自定义策略配置文件保存到/etc/apparmor.d/

2、加载配置文件到内核:apparmor_parser

3、Pod注解指定策略配置名

工作流程:

CKS-学习案例 - 图3

CKS-学习案例 - 图4

CKS-学习案例 - 图5

4、最小化微服务漏洞

案例1:设置容器以普通用户运行

背景:容器中的应用程序默认以root账号运行的,这个root与宿主机root账号是相同的,拥有大部分对Linux内核的系统调用权限,这样是不安全的,所以我们应该将容器以普通用户运行,减少应用程序对权限的使用。

可以通过两种方法设置普通用户:

  • Dockerfile里使用USER指定运行用户
  • K8s里指定spec.securityContext.runAsUser,指定容器默认用户UID

CKS-学习案例 - 图6

  1. cat security-context.yaml
  2. apiVersion: v1
  3. kind: Pod
  4. metadata:
  5. name: security-context-demo
  6. spec:
  7. securityContext:
  8. runAsUser: 1000
  9. runAsGroup: 3000
  10. fsGroup: 2000
  11. containers:
  12. - name: web
  13. image: lizhenliang/flask-demo:root
  14. securityContext:
  15. allowPrivilegeEscalation: false

案例2:容器使用特权

背景:容器中有些应用程序可能需要访问宿主机设备、修改内核等需求,在默认情况下,容器没这个有这个能力,因此这时会考虑给容器设置特权模式。

启用特权模式:

CKS-学习案例 - 图7

启用特权模式就意味着,你要为容器提供了访问Linux内核的所有能力,这是很危险的,为了减少系统调用的供给,可以使用Capabilities为容器赋予仅所需的能力。

  1. cat privileged-pod.yaml
  2. apiVersion: v1
  3. kind: Pod
  4. metadata:
  5. name: privileged-pod
  6. spec:
  7. containers:
  8. - name: web
  9. image: nginx
  10. securityContext:
  11. privileged: true

6、监控、审计和运行时安全

  • 验证:tail -f /var/log/messages(告警通知默认输出到标准输出和系统日志)

1、监控系统二进制文件目录读写(默认规则)

  1. vi /etc/falco/falco_rules.yaml
  2. # File categories
  3. - macro: bin_dir
  4. condition: fd.directory in (/bin, /sbin, /usr/bin, /usr/sbin)
  5. - macro: bin_dir_mkdir
  6. condition: >
  7. (evt.arg.path startswith /bin/ or
  8. evt.arg.path startswith /sbin/ or
  9. evt.arg.path startswith /usr/bin/ or
  10. evt.arg.path startswith /usr/sbin/)

2、监控根目录或者/root目录写入文件(默认规则)

  1. vi /etc/falco/falco_rules.yaml
  2. # This detects writes immediately below / or any write anywhere below /root
  3. - macro: root_dir
  4. condition: (fd.directory=/ or fd.name startswith /root/)

3、监控运行交互式Shell的容器(默认规则)

  1. vi /etc/falco/falco_rules.yaml

4、监控容器创建的不可信任进程(自定义规则)

  1. vi /etc/falco/falco_rules.yaml
  2. # 监控容器创建的不可信任进程规则,在falco_rules.local.yaml文件添加:
  3. - rule: Unauthorized process on nginx containers
  4. condition: spawned_process and container and container.image startswith nginx and not proc.name in (nginx)
  5. desc: test
  6. output: "Unauthorized process on nginx containers (user=%user.name container_name=%container.name container_id=%container.id image=%container.image.repository shell=%proc.name parent=%proc.pname cmdline=%proc.cmdline terminal=%proc.tty)"
  7. priority: WARNING