Kubernetes 安全框架

K8S安全控制框架主要由下面3个阶段进行控制,每一个阶段都 支持插件方式,通过API Server配置来启用插件。

  1. Authentication(鉴权)

  2. Authorization(授权)

  3. Admission Control(准入控制)

客户端要想访问K8s集群API Server,一般需要证书、Token或 者用户名+密码;如果Pod访问,需要ServiceAccount

鉴权(Authentication)

三种客户端身份认证:

  • HTTPS 证书认证:基于CA证书签名的数字证书认证

  • HTTP Token认证:通过一个Token来识别用户

  • HTTP Base认证:用户名+密码的方式认证

授权(Authorization)

RBAC(Role-Based Access Control,基于角色的访问控制):负责完成授权(Authorization)工作。

RBAC根据API请求属性,决定允许还是拒绝。

比较常见的授权维度:

  • user:用户名

  • group:用户分组

  • 资源,例如pod、deployment

  • 资源操作方法:get,list,create,update,patch,watch,delete

  • 命名空间

  • API组

准入控制(Admission Control)

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

基于角色的权限访问控制:RBAC

RBAC(Role-Based Access Control,基于角色的访问控 制),允许通过Kubernetes API动态配置策略。

角色

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

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

角色绑定

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

  • ClusterRoleBinding:将集群角色绑定到主体

主体(subject)

  • User:用户

  • Group:用户组

  • ServiceAccount:服务账号

案例:为指定用户授权访问不同命名空间权限

示例:为azhe用户授权default命名空间Pod读取权限

  1. 用K8S CA签发客户端证书

安装cfssl工具

#vim cfssl.sh
wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
chmod +x cfssl*
mv cfssl_linux-amd64 /usr/bin/cfssl
mv cfssljson_linux-amd64 /usr/bin/cfssljson
mv cfssl-certinfo_linux-amd64 /usr/bin/cfssl-certinfo

#bash cfssl.sh

生成证书

#vim cert.sh 

cat > ca-config.json <<EOF
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"kubernetes": {
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
],
"expiry": "87600h"
}
}
}
}
EOF

cat > azhe-csr.json <<EOF
{
"CN": "azhe",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "k8s",
"OU": "System"
}
]
}
EOF

cfssl gencert -ca=/etc/kubernetes/pki/ca.crt -ca-key=/etc/kubernetes/pki/ca.key -config=ca-config.json -profile=kubernetes azhe-csr.json | cfssljson -bare azhe

#bash cert.sh

数字证书和key

  1. 生成kubeconfig授权文件
#生成kubeconfig授权文件:
kubectl config set-cluster kubernetes \
--certificate-authority=/etc/kubernetes/pki/ca.crt \
--embed-certs=true \
--server=https://192.168.1.11:6443 \
--kubeconfig=azhe.kubeconfig

# 设置客户端认证
kubectl config set-credentials azhe \
--client-key=azhe-key.pem \
--client-certificate=azhe.pem \
--embed-certs=true \
--kubeconfig=azhe.kubeconfig

# 设置默认上下文
kubectl config set-context kubernetes \
--cluster=kubernetes \
--user=azhe \
--kubeconfig=azhe.kubeconfig

# 设置当前使用配置
kubectl config use-context kubernetes --kubeconfig=azhe.kubeconfig
  1. 创建RBAC权限策略
#vim rbac.yaml

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]

---

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: read-pods
namespace: default
subjects:
- kind: User
name: azhe
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io

验证查看pod

kubectl apply -f rbac.yaml 
#指定kubeconfig文件测试:
kubectl get pod --kubeconfig=./azhe.kubeconfig

查看deployment和service(修改rbac文件)

#vim rbac.yaml 

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: ["","apps"]
resources: ["pods","deployments","services"] #资源类型权限
verbs: ["get", "watch", "list"]

---

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: read-pods
namespace: default
subjects:
- kind: User
name: azhe
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io

验证查看

kubectl apply -f rbac.yaml 
kubectl get deployments.apps --kubeconfig=./azhe.kubeconfig
kubectl get services --kubeconfig=./azhe.kubeconfig
kubectl api-versions #查看k8s资源组

当客户端使用kubectl时,它会向APIserver发送请求,它会根据你客户端的身份,比如数字认证方式,它会提取证书里面cn字段,cn字段作为你的用户名,会先验证你的身份是不是可信任的,或者证书是不是ca颁发的,验证没问题后会检查有没有给你授权,还有准入控制器插件列表检查,如果通过后你查看就会返回成功。

客户端要想访问k8s集群,需要拿着kubeconfig授权文件去访问。

#拷贝kubeconfig授权文件到客户端
scp azhe.kubeconfig root@192.168.0.13:~
#客户端指定授权文件访问
kubectl get services --kubeconfig=azhe.kubeconfig
#如果不想指定授权文件访问,可以将授权文件移动到kube目录下,这时就不需要指定了
mkdir .kube/
mv azhe.kubeconfig .kube/config

ServiceAccount:服务账号

kubectl get sa -n kubernetes-dashboard
kubectl describe sa -n kubernetes-dashboard
kubectl get secrets -n kubernetes-dashboard

ui——>token(保存至secret中)——>apiserver——>rbac(ServiceAccount)

User和Group是针对用户授权访问APIserver的,ServiceAccount是针对程序访问APIserver的。

例如:ui程序在pod yaml配置文件里面指定ServiceAccount,在创建pod时引用ServiceAccount创建的token,token是保存在secret里面的,这样你的程序就带着token去访问apiserver,然后rbac是对ServiceAccount进行授权的。