05、K8s安全

3.1 API资源对象NetworkPolicy

NetworkPolicy用来控制Pod与Pod之间的网络通信,它也支持针对

Namespace进行限制。基于白名单模式,符合规则的对象通过,不符

合的拒绝

应用场景:

  • Pod A 不能访问 Pod B
  • 开发环境所有Pod不能访问测试命名空间
  • 提供对外访问时,限制外部IP

官方NetworkPolicy YAML示例

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      role: db
  policyTypes:
  - Ingress
  - Egress
  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

说明:

必须字段:apiVersion \ kind \ metadata

podSelectot:定义目标Pod的匹配标签,即哪些Pod会生效此策略

policyTypes:表示给定的策略是应用于目标Pod的入站流量(ingress)

​ 还是出站流量(Egress),或者两者兼有。

​ 如果NetworkPolicy未指定,policyTypes则默认情况下始终设置Ingress。

ingress:定义入流量限制规则,from用来定义白名单对象,比如网段、命名空间、Pod标签,Ports定义目标端口

egress:定义处流量限制规则,定义可以访问哪些IP和端口

案例一:命名空间限制

需求:aming命名空间下所有Pod可以相互访问,也可以访问其他命名空间Pod,但其他命名空间不能访问aming命名空间Pod

首先创建几个Pod

## default命名空间里创建busybox Pod
kubectl run busybox --image=busybox --sleep 3600

## aming命名空间里创建busybox Pod
kubectl run busybox --image=busybox -n aming --sleep 3600

## aming命名空间里创建web pod
kubectl run web --image=nginx:1.23.2 -n aming

在没有创建networkpolicy的情况下测试

## aming命名空间的busybox ping default命名空间的busybox
## 先查询各个Pod的IP
kubectl exec busybox -n aming -- ping 10.18.235.161

## aming命名空间的busybox ping aming命名空间的web IP
kubectl exec busybox -n aming -- ping 10.18.235.162

## default 命名空间的busybox ping aming命名空间的web IP
## kubectl exec busybox -- ping 10.18.235.162

创建networkpolicy的YAML文件

vim deny-all-namespaces.yaml

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all-namespaces
  namespace: aming
spec:
  podSelector: {} #为空,表示匹配本命名空间所有的Pod
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector: {}
      # 此处的 podSelector 为空,表示只允许来自同一命名空间的流量
      # 没有定义 namespaceSelector,表示不允许其他命名空间的 Pods 访问
## 应用YAML
kubectl apply -f deny-all-namespaces.yaml

## 测试
## aming命名空间的busybox ping default 命名空间的busybox IP
kubectl exec busybox -n aming -- ping 10.18.235.161

## aming 命名空间的busybox ping aming命名空间的web IP
kubectl exec busybox -n aming --ping 10.18.235.162

## default命名空间的busybox ping aming命名空间的web IP 
kubectl exec busybox --ping 10.18.235.162

测试结果

## 将刚刚创建的资源都进行删除
kubectl delete po busybox --force
kubectl delete po busybox -n aming --force
kubectl delete po web -n aming
kubectl delete -f dent-all-namespaces.yaml

案例二:通过PodSelector限制

vim pod-selector.yaml

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: app-to-app
  namespace: aming
spec:
  podSelector:
    matchLabels:
      app: test
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: dev
    ports:
    - protocol: TCP
      port: 80
## 应用YAML
kubectl apply -f pod-selector.yaml

## 创建测试Pod
## 创建Pod时,指定label
kubectl run web01 --image=1.23.2 -n aming -l 'app=test'

## 查看label
kubectl get pod web01 -n aming --show-labels

## 如果label创建错了,也可以修改(此处不需要)
##kubectl label pod busybox app=test123 --overwrite

kubectl run app01 --image=nginx:1.23.2 -n aming -l 'app=dev'

kubectl run app02 --image=nginx:1.23.2 -n aming
## 测试
## 查看web01 的IP
kubectl describe po web01 -n aming | grep -i ip

## 测试
kubectl exec -n aming app01 -- curl 10.18.200.69
kubectl exec -n aming app02 -- curl 10.18.200.69

## 测试成功后,删除创建的资源
kubectl delete po app01 -n aming
kubectl delete po app02 -n aming
kubectl delete po web01 -n aming
kubectl delete -f pod-selector.yaml

![[Pasted image 20240725213730.png]]

案例三:限制namespace

vim allow-ns.yaml

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-ns
  namespace: aming
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: test
    ports:
    - protocol: TCP
      port: 80
## 应用YAML
kubectl apply -f allow-ns.yaml

## 创建测试ns
kubectl create ns test

## 创建测试Pod
kubectl run web01 --image=nginx:1.23.2 -n aming
kubectl run web02 --image=nginx:1.23.2 -n test
kubectl run web03 --image=nginx:1.23.2
kubectl run web04 --image=nginx:1.23.2 -n aming

## 查看web01 的IP
kubectl describe po web01 -n aming | grep -i ip

## 查看 ns label
kubectl get ns --show-labels

## 给ns设置标签
kubectl label namespace test name=test

## 测试
kubectl -n test exec web02 -- curl 10.18.200.71
## -- 可以访问

kubectl exec web03 --curl 10.18.200.71
## -- 不可以访问

kubectl -n aming exec web04 -- curl 10.18.200.71
## -- 不可以访问,即使同一个命名空间也无法访问

3.2Kubectl用户安全控制

1.安全控制三阶段

  • 认证(Authentication)
  • 授权(Authorization)
  • 准入控制(Admission Control)

1721888555608

  1. 认证:就是验证用户的身份是否合法,比如看看其证书是否合法有效,看看其Token是否正确。
  2. 授权:就是看看这个用户是否有权限来访问或者操作K8s的资源。
  3. 准入控制:就是检查对应客户端的请求是否符合对应请求或操作API规范,检查传递参数是否正确。比如创建Pod,它会检查提交的信息是否符合创建Pod的规范,如果不符合规范就拒绝。另外,准入控制还会帮助我们把对应的字段填充到客户端请求中,然后把填充好的信息一并由 APIserver把客户端请求更新到对应资源在etcd中的对应信息上。

2.K8s认证(Authentication)

两种认证方式:

  1. kubeconfig : 这种是基于 https ca 证书认证,我们的命令行管理K8s用的就是这种认证
  2. Token : 这种通过一个Token来识别用户,比如前面的 dashboard ,有创建一个serviceaccount ,然后再获取其Token

3.K8s授权(Author)

授权模式:

  • AlwaysDeny:表示拒绝所有的请求,一般用于测试
  • AlwaysAllow:允许接收所有请求,如果集群不需要授权流程,则可以采用该策略
  • ABAC(Attribute-Based Access Control):基于属性的访问控制,表示使用用户配置的授权规则对用户请求进行匹配和控制(老版本采用的方式,也就是定义属性的访问类型,如果用户拥有这个属性就能访问对应的资源。需要定义一长串的属性,并且ABAC修改完之后并不能生效,现在淘汰了)
  • Webbook:通过调用外部REST服务对用户进行授权(在集群外部对集群鉴权)
  • RBAC(Role-Based Access Control):基于角色的访问控制,现行的默认规则(拥有角色就代表拥有访问资源某些权限)
## 查看自己的K8s授权模式
cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep authorization-mode

RBAC授权模式

RBAC(Role-Based Access Control)基于角色的访问控制,在 Kubernetes 1.5 中引入,现行版本成为默认标准。

相对其它访问控制方 式,拥有以下优势:

  • 对集群中的资源(Pod deploy cpu ...)和非资源(元信息如pod状态)均拥有完整的覆盖
  • 整个RBAC完全由几个API对象完成,同其他API对象一样,可以用kubectl或API进行操作
  • 可以在运行时进行调整,无需重启API server 即可生效

RBAC的API资源对象说明

RBAC资源对象:Subject(包括:User, Group, ServiceAccount)

Role(角色)、ClusterRole(集群角色)、RoleBinding(角色绑定)、ClusterRoleBinding(集群角色绑定)

主体(subject)

  • User:用户
  • Group:用户组
  • ServiceAccount:服务账号

角色

  • Role:授权特定命名空间的访问权限
  • ClusterRole:授权所有命名空间的访问权限

角色绑定

  • RoleBinding:将角色绑定到主体(即subject)
  • ClusterRoleBinding:将集群角色绑定到主体

RBAC-API资源对象

4.K8s准入控制(Admission Control)

Admission Control 实际上是一个准入控制器插件列表,发送到API Server 的请求都需要经过这个列表中的每个准入控制器插件的检查,检查不通过,则拒绝请求。

## 查看可以启用的准入控制器列表
kubectl exec kube-apiserver-aminglinux01 -n kube-system -- kube-apiserver -h | grep ' --enable-admission-plugins'

## 查看当前K8s启用的准入控制器
grep 'admission' /etc/kubernetes/manifests/kube-apiserver.yaml
## 或者
ps aux | grep apiserver | grep admission

## 更改准入控制器
vim /etc/kubernetes/manifests/kube-apiserver.yaml
## 找到 --enable-admission-plugins 那一行,
## 直接修改 --enable-admission-plugins=NodeRestriction,SecurityContextDeny

admission 控制器列表及说明等待后续补充

参考百度

3.3 Kubernetes创建普通用户示例

需求1:创建一个Role和ServiceAccount并把他们绑定起来

ServiceAccount有get、list、watch的权限

## 创建YAML文件
cat > testsa.yaml <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
  name: testsa
  
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: testsa-role
rules:
- apiGroups: 
# api组,例如apps组,空值表示是核心API组,
#像namespace、pod、service、pv、pvc都在里面
  - ""
  resources: #资源名称(复数),例如pods, deployments,services
  - pods
  verbs: # 允许的操作,这里允许get, list, watch
  - get
  - list
  - watch
  
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: testsa-rolebinding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: testsa-role
subjects:
- kind: ServiceAccount
  name: testsa
EOF
## 应用此YAML
kubectl apply -f testsa.yaml

## 生成Token
kubectl create token testsa

需求2:

给user1 用户授权aming命名空间Pod的读取权限

## 1.生成ca证书
cd /etc/kubernetes/pki/
openssl genrsa -out user1.key 2048

posted @ 2024-07-25 22:31  慢乌龟不出事  阅读(18)  评论(0)    收藏  举报