Kubernetes 集群安全 - 机制说明

  1. kubernetes 作为一个分布式集群的管理工具,保证集群的安全性是其一个重要的任务。
  2. API Server 是集群内部各个组件通信的中介,也是外部控制的入口。
  3. 所以 kubernetes 的安全机制基本就是围绕保护 API Server 来设计的。
  4. kubernetes 使用了 认证(Authentication)、鉴权(Authorization)、准入控制(AdmissionControl),三步来保证 API Server 的安全。

在这里插入图片描述

API Server 是 k8s 一个非常重要的组件,不管是用户还是 Pod,都会访问 API Server。间接到达 Etcd。

这个过程中间需要经历三个模块,也就是认证、鉴权、准入控制。由管理员来选择通过哪一个模块来做安全认证。


Authorization 鉴权

Authentication认证过程,只是确认通信的双方都确认了对方是可信的,可以互相通信。

而鉴权是确定请求方有哪些资源的权限。

API Server 目前支持以下几种授权策略 (通过 API Server 的启动参数 --authorization-mode 设置)

  • AlwaysDeny:标识拒绝所有的请求,一般用于测试

  • AlwaysAllow:允许接受所有请求,如果集群不需要授权流程,则可以采用该策略

  • ABAC:基于属性的访问控制,表示使用用户配置的授权规则对用户请求进行匹配和控制,淘汰

  • Webbook:通过调用外部 REST 服务对用户进行授权

  • RBAC:基于角色的访问控制,现行默认规则,常用


RBAC 授权模式

​ RBAC 基于角色的访问控制,在 kubernetes1.5 中引入,现行版本成为默认标准。相对其他访问控制方式,拥有以下优势:

  • 对集群中的资源和非资源拥有完整的覆盖
  • 整个 RBAC 完全由几个API 对象完成。同其他 API 对象一样,可以用 kubectl 或 API 进行操作。
  • 可以在运行时进行调整,无需重启 API Server。


RBAC 的 API 资源对象说明

RBAC 引入了 4个新的顶级资源对象:Role、ClusterRole、RoleBinding、ClusterRoleBinding、4种对象类型均可以通过 kubectl 与 API 操作。

Role:普通角色 | ClusterRole:集群角色

Rolebinding:普通角色绑定 ClusterRoleBinding:集群角色绑定

在这里插入图片描述

一、Verbs 动作

rules:
verbs: [“get”, “list”, “watch”, “create”, “update”, “patch”, “delete”]

rules.verbs 动作权限
create 创建写入 Pod 动作/资源
update 更新写入 Pod 动作/资源
delete 删除写入 Pod 动作/资源
watch读取 Pod 动作/资源
list 列出读取 Pod 动作/资源
patch写入 Pod 动作/资源
get 查看读取 Pod 动作/资源

可以将不同的动作(create、get、update)创建成 Role 角色。比如创建一个pod,将其设置成 create pod 的角色名,然后进行 RoleBinding 绑定。绑定给后端的 user用户、Group组、ServiceAccount(SA)


二、apiGroups API接口组

rules:
- apiGroups:[“extensions”,“apps”,“batch”]

可以指定多个 apiVersion 的API接口


三、JOSN 证书

kubernetes 并不会提供用户管理,那么 User、Group、ServiceAccount 指定的用户又是从哪里来的呢?kubernetes组件 (kubectl、kube-proxy) 或者是其他自定义的用户向 CA 申请证书时,需要提供一个证书请求文件,如下:API Server 会把客户端证书 CN 字段作为 User,把 names.O 字段作为 Group

{
"CN": "admin",	#国家名=User
"hosts": [],
"key": {
	"algo": "rsa",
	"size": 2048
	},
"names": [
{
	"C": "CN",
	"ST": "HangZhou",
	"L": "XS",
	"O": "system:masters",	#组织=Group
	"OU": "System"
		}
	]
}
  • kubelet 使用 TLS Bootstaping 认证时,API Server 可以使用 Bootstrap Tokens 或者 Token authentication file 验证 token,无论哪一种,kubernetes都会为 token 绑定一个默认的 User 和 Group。
  • Pod 使用 ServiceAccount 认证时,Service-accout-token 中的 JWT 会保存 User信息。
    有了用户信息,再创建一对 角色/角色绑定,集群角色/集群角色绑定 资源对象,就可以完成权限绑定了。


Role and ClusterRole

一、Role

  1. 在 RBAC API 中, Role 表示一组规则权限,权限只会增加(累加权限),不存在一个资源一开始就有很多权限。可以通过 RBAC 对其进行权限减少的操作。
  2. Role 可以定义在一个 namespace 名称空间下,如果要跨 namespace 则需要创建 ClusterRole 实现。
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: Role
metadata: 
  name: pod-reader               # Role角色名称
  namespace: default			 # Role角色名称空间
rules: 							 # 权限规则
  - apiGroups: [""]              # 为空"" 默认API核心组
    resources: ["pods"]			 # 对象 Pod 容器
    verbs: ["get","watch","list"]		#动作:获取信息,监听,列出


二、ClusterRole

clusterRole 具有与 Role 相同的权限角色控制能力,不同的是 ClusterRole 是集群级别的, ClusterRole常用于:

  • 集群级别的资源控制(例如 node访问)
  • 非资源型 endpoints (例如 /healthz访问)
  • 所有命名空间资源控制 (例如 pods)
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: secret-reader
rules: 
  - apiGroups: [""]
    resources: ["secrets"]
    verbs: ["get","watch","list"]


RoleBinding and ClusterRoleBinding

  1. RoleBinding 可以将角色中定义的权限授予用户和用户组。RoleBinding 包含一组权限列表(subjects),权限列表中包含有不同形式的待授予权限资源类型 (users, groups, service Account)。
  2. RoleBinding 同样包含对被 Bind 的 Role 引用;RoleBinding 适用于某个命名空间内授权,而 ClusterRoleBinding 适用于集群范围内的授权。
  3. RoleBinding 可以绑定 Role and ClusterRole;ClusterRoleBinding 只能绑定 ClusterRole。


一、Role - RoleBinding

例:将 default 命名空间的 pod-reader Role 授予 jane 用户,此后 jane 用户可以在 default 命名空间中使用 pod-reader 的权限。

apiVersion: rbac.authorization.k8s.io/v1beta1		#API 接口
kind: RoleBinding					# 剧本类型
metadata: 						# 元数据信息
  name: read-pods					
  namespace: default					# 名称空间
subjects: 						# 对象类型
  - kind: User						# User 对象
    name: jane						# 对象名称
    apiGroup: rbac.authorization.k8s.io 		# 授予对象API组
roleRef: 							
  kind: Role						# Role 角色类型
  name: pod-reader					# Role 角色权限
  apiGroup: rbac.authorization.k8s.io			# Role 角色的API组

RoleBinding 同样可以引用 ClusterRole 来对当前 namespace 内用户、用户组、SA 进行授权。

这种操作允许集群管理员在整个集群内定义一些通用的 ClusterRole ,然后在不同的 namespace 中使用 RoleBinding来引用。


二、ClusterRole - RoleBinding

例:RoleBinding 引用了一个 ClusterRole ,这个 ClusterRole 具有整个集群内对 secrets 的访问权限;但是其授权用户 dave 只能访问 development 空间中的 secrets (因为 RoleBinding 定义在 development 命名空间)。

apiVersion: rbac.authorization.k8s.io/v1beta1		# API接口
kind: RoleBinding					# RoleBinding
metadata: 						
  name: read-secrets					
  namespace: development				# 名称空间
subjects:					
  - kind: User						# 授权对象用户
    name: dave						# 授权对象的用户名称
    apiGroup: rbac.authorization.k8s.io			#授权对象用户API组
roleRef: 
  kind: ClusterRole					# 集群角色
  name: secret-reader					# 集群角色的权限
  apiGroup: rbac.authorization.k8s.io			# 集群角色的API组


三、ClusterRole - ClusterRoleBinding

使用 ClusterRoleBinding 可以对整个集群中的所有命名空间资源权限进行授权;

以下 ClusterRoleBinding 样例展示了授权 manager 组内所有用户在全部命名空间中对 secrets 进行访问。

apiVersion: rbac.authorization.k8s.io/v1beta1		#API接口
kind: ClusterRoleBinding							#剧本类型
metadata: 
  name: read-secrets-global
subjects:
  - kind: Group						#授权对象组
    name: manager					#授权对象组的名称
    apiGroup: rbac.authorization.k8s.io	#授权对象组的API接口
roleRef: 
  kind: ClusterRole					#集群角色
  name: secret-reader				#集群角色名称
  apiGroup: rbac.authorization.k8s.io	#集群角色的API接口


Resources 资源类型

kubernetes 集群内的一些资源一般会以其名称字符串表示,这些字符串一般会在 API 的 URL 地址中出现;

同时某些资源也会包含子资源,例如 logs 资源就属于 pods 的子资源,API 中 URL 样例如下:

GET /api/v1/namespaces/{namespace}/pods{name}/log

如果要在 RABC 授权模型中控制这些子资源的访问权限,可以通过 / 分隔符来实现,以下是一个定义 Pods 资源 logs 访问权限的 Role 定义样例:

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

resources:[“deployments”,“jobs”,“pods”,“configmaps”,“nodes”] 不管是什么资源控制器都需要加上 s


Subjects 绑定角色

RoleBinding或ClusterRoleBinding可以将Role绑定到主体subjects。Subjects 可以是groups、users和service accounts。

Users:由字符串表示,可用的格式有,如纯字符“alice”,Emai格式“bob@example.com”或表示为字符串的数字。Users除了需要满足Kubernetes管理员配置的 authentication modules,对Users, RBAC授权系统没有做任何格式限定。除了前缀为system:是为Kubernetes系统使用而保留的用户名格式,除此之外RBAC授权系统可以使用任何格式的Users。

Group:信息目前由Authenticator模块提供。和Users 一样,Group 由字符串表示,而且字符串没有格式要求,除了前缀*system:*是保留的。

Service Account: 使用system:serviceaccount:前缀的用户名,并且属于具有system:serviceaccounts:前缀的Group组。


Role Binding 示例

1、user and Group

绑定名为“alice@example.com”的用户:

subjects:
- kind: User
  name: "alice@example.com"
  apiGroup: rbac.authorization.k8s.io

绑定名为“frontend-admins”的Group:

subjects:
- kind: Group
  name: "frontend-admins"
  apiGroup: rbac.authorization.k8s.io
2、ServiceAccount

适合kube-system Namespace中的默认ServiceAccount:

subjects:
- kind: ServiceAccount
  name: default
  namespace: kube-system

适合自定义“shm”Namespace中的所有ServiceAccount:

subjects:
- kind: Group
  name: system:serviceaccounts:shm
  apiGroup: rbac.authorization.k8s.io

适合集群中所有ServiceAccount:

subjects:
- kind: Group
  name: system:serviceaccounts
  apiGroup: rbac.authorization.k8s.io
3、Authenticated 认证

适合所有经过认证的用户(1.5版本以上):

subjects:
- kind: Group
  name: system:authenticated
  apiGroup: rbac.authorization.k8s.io

适合所有未经认证的用户(1.5版本以上):

subjects:
- kind: Group
  name: system:unauthenticated
  apiGroup: rbac.authorization.k8s.io

适合所有用户(1.5版本以上):

subjects:
- kind: Group
  name: system:authenticated
  apiGroup: rbac.authorization.k8s.io
- kind: Group
  name: system:unauthenticated


实战:创建一个用户只能管理 dev 空间

一、创建一个 devuser 的用户
useradd  devuser
echo '123.com' | passwd devuser --stdin
二、创建证书
mkdir -p  /kubernetes/ca/devuser  ; cd /kubernetes/ca/devuser
vim devuser-csr.json
{		
 "CN": "devuser",		//User
 "hosts": ["192.168.168.11"],			//[]代表所有主机使用
 "key": {
    "algo": "rsa",
    "size": 2048 
    },
 "names": [
   {
     "C": "CN",
     "ST": "BeiJing",
     "L": "BeiJing",
     "O": "k8s",		//Group
     "OU": "System"
      }
   ]
}
三、下载证书生成工具
wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
mv cfssl_linux-amd64  /usr/local/bin/cfssl

wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
mv cfssljson_linux-amd64  /usr/local/bin/cfssljson

wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
mv cfssl-certinfo_linux-amd64  /usr/local/bin/cfssl-certinfo

chmod +x  /usr/local/bin/*

生成证书 cd /etc/kubernetes/pki

cfssl gencert -ca=ca.crt -ca-key=ca.key -profile=kubernetes /kubernetes/ca/devuser/devuser-csr.json | cfssljson -bare devuser

-ca=ca.crt   		#指定证书
-ca-key=ca.key		#指定私钥
-profile=kubernetes /kubernetes/ca/devuser/devuser-csr.json	#指定证书申请文件
-bare devuser  		#输出格式证书文件名devuser
2020/06/24 10:06:33 [INFO] generate received request
2020/06/24 10:06:33 [INFO] received CSR
2020/06/24 10:06:33 [INFO] generating key: rsa-2048
2020/06/24 10:06:34 [INFO] encoded CSR
2020/06/24 10:06:34 [INFO] signed certificate with serial number 65125129704757264070550525068465845596301305983
2020/06/24 10:06:34 [WARNING] This certificate lacks a "hosts" field. This makes it unsuitable for
websites. For more information see the Baseline Requirements for the Issuance and Management
of Publicly-Trusted Certificates, v.1.1.6, from the CA/Browser Forum (https://cabforum.org);
specifically, section 10.2.3 ("Information Requirements").

在这里插入图片描述


四、设置集群用户 config 文件参数

①、设置集群环境变量

**export KUBE_APISERVER=“https://192.168.168.11:6443” **

②、设置 kubernetes 集群的 用户config文件

cd /kubernetes/ca/devuser/

kubectl config set-cluster kubernetes
–certificate-authority=/etc/kubernetes/pki/ca.crt
–embed-certs=true
–server=${KUBE_APISERVER}
–kubeconfig=devuser.kubeconfig

kubectl config set-cluster kubernetes \						#生成kubernetes的config文件
--certificate-authority=/etc/kubernetes/pki/ca.crt \		#指定CA证书
--embed-certs=true \					#是否加密认证
--server=${KUBE_APISERVER} \			#指定服务器地址信息
--kubeconfig=devuser.kubeconfig			#创建出一个用户的 kubeconfig文件

成功后会出现一个 devuser.kubeconfig 文件


五、写入客户端认证参数

kubectl config set-credentials devuser
–client-certificate=/etc/kubernetes/pki/devuser.pem
–client-key=/etc/kubernetes/pki/devuser-key.pem
–embed-certs=true
–kubeconfig=devuser.kubeconfig

kubectl config set-credentials devuser \		#创建客户端 devuser的认证
--client-certificate=/etc/kubernetes/pki/devuser.pem \	#指定 devuser 的证书
--client-key=/etc/kubernetes/pki/devuser-key.pem \	#指定 devuser 的私钥
--embed-certs=true \					#开启证书认证
--kubeconfig=devuser.kubeconfig				#指定写入到集群的 config 文件


六、写入上下文参数,绑定名称空间信息

创建 dev 的名称空间:kubectl create namespace dev

绑定 dev 名称空间

kubectl config set-context kubernetes
–cluster=kubernetes
–user=devuser
–namespace=dev
–kubeconfig=devuser.kubeconfig


七、Role/ClusterRole 的角色绑定

将 ClusterRole 的 admin 角色, RoleBinding绑定给 devuser 用户,绑定在 dev 名称空间下,拥有admin角色权限。

kubectl create rolebinding devuser-admin-binding --clusterrole=admin --user=devuser --namespace=dev


八、 devuser 用户的 K8S 上下文设置

①、将 devuser.kubeconfig 文件移动到自己的家目录下并赋权

mkdir -pv /home/devuser/.kube
cp devuser.kubeconfig  /home/devuser/.kube
chown devuser:devuser  -R  /home/devuser/.kube
	

②、采用 devuser 用户登录 xshell: k8s-master 节点

[devuser@k8s-master ~]$ cd .kube/

[devuser@k8s-master .kube]$ mv devuser.kubeconfig config

③、设置 devuser 用户与 kubernetes 集群的默认上下文

[devuser@k8s-master .kube]$ kubectl config use-context kubernetes --kubeconfig=config


九、验证 devuser 用户 是否具有 dev 空间的所有权限

创建一个 nginx Pod

[devuser@k8s-master .kube]$ kubectl run nginx --image=nginx:1.9.1

查看其在哪个名称空间下运行

[devuser@k8s-master .kube]$ kubectl get pod -n dev
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 11m

Logo

开源、云原生的融合云平台

更多推荐