k8s的权限管理(rbac、ueradd等)

一、认证、授权、准入控制

kubernetes的安全框架分三层:认证,授权,准入控制

1、认证(authentication):验证身份,使用证书、用户名密码或者token令牌。认证解决用户是谁的问题。

2、授权(authorization):绑定权限,授权过程,分配到指定空间中。授权解决用户能做什么的问题。

3、准入控制(admission control):空间准入控制,可以使用下面哪些资源,调用哪些插件,使用插件前先与etcd去验证,查看etcd是否授权,若是允许,会执行,并将操作记录到etcd中。准入控制则是资源管理方面的作用。

第一模块,认证authentication

三种客户端身份认证

    HTTPS证书认证:基于CA证书签名的数字证书认证
    HTTP token 认证:通过一个token来识别用户——在生产环境中使用广泛
    HTTP base认证:用户名+密码的方式认证

K8S集群的证书认证

https://blog.csdn.net/Lfwthotpt/article/details/105892377

httpd的token认证

cat /k8s/cfg/token.csv 
a031b816095ddada590b24c54a505a9e,kubelet-bootstrap,10001,"system:kubelet-bootstrap"

第二模块授权——authorization

RBAC(role-based access control,基于角色的访问控制),负责完成授权(authorization)工作

kubernetes reviews only the following API request attributes:

user——The user string provided during authentication

身份验证期间提供的用户字符串

group——the list of group names to which the authenticated user belongs

已验证用户所属的组名列表

extra—— a map of arbitrary string keys to string values,provided by the authentication layer

任意字符串键到字符串值的映射,由身份验证层提供

API——indicates whether the request is for an API resource

指示请求是否针对API资源

request path—— path to miscellaneous non-resource endpoints like /ap1 or /healthz

到其他非资源端点(如/ap1或/healthz)的路径

api request verb- api verbs get,list,create,update,patch,watch,proxy,redirect,delete,and deletecollection are used for resource requests. To determine the request verb for a resouce api endpoint, see determine the request verb below.

api动词get、list、create、update、patch、watch、proxy、redirect、delete和deletecollection用于资源请求。要确定resouce api端点的请求谓词,请参见下面的确定请求谓词。

http request verb—— http verbs  get,post,and delete are used for non-resource requests.

http动词get、post和delete用于非资源请求。

resource——the id or name of the resouce that is being accessed (for resource requests only) - for resource requests using get,update,patch and delete verbs,you must provide the resource name

正在访问的资源的id或名称(仅用于资源请求)——对于使用get、update、patch和delete谓词的资源请求,您必须提供资源名称

subresource —— the subresource that is being accessed (for resource requests only)

正在访问的子资源(仅用于资源请求)

namespace—— the subresource that is being accessed ( for resource requests only)

正在访问的子资源(仅用于资源请求)

api group —— the api group being accessed (for resource requests only),an empty string designates the core api group

被访问的api组(仅用于资源请求),一个空字符串指定核心api组

RBAC是基于角色进行控制,所以:

要先创建角色

然后创建要绑定的资源

将角色与目标用户甚至api和请求等绑定

绑定api模式适用于二次开发

查看apiserver启用rbac

ps aux | grep apiserver | grep  authorization-mod
--authorization-mode=Node,RBAC 

第三模块:准入控制(admission control)

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

–enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,ResourceQuota,NodeRestriction

NamespaceLifecycle: 命令空间回收

LimitRanger:配额管理

ServiceAccount:每个pod中导入方便访问API

ResourceQuota:基于命名空间的高级配额管理

NodeRestriction:Node加入到K8S集群中以最小权限运行

查看哪些插件是默认启用的:

kube-apiserver -h | grep enable-admission-plugins

相关的小操作

apiserver使用的是token认证

–enable-bootstrap-token-auth --token-auth-file=/k8s/cfg/token.csv

#ps aux | grep apiserver
root      21679 10.2  8.6 1164540 422616 ?      Ssl  15:24   8:21 kube-apiserver --advertise-address=192.168.74.132 --allow-privileged=true --authorization-mode=Node,RBAC --client-ca-file=/etc/kubernetes/pki/ca.crt --enable-admission-plugins=NodeRestriction --enable-bootstrap-token-auth=true --etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt --etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt --etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key --etcd-servers=https://127.0.0.1:2379 --insecure-port=0 --kubelet-client-certificate=/etc/kubernetes/pki/apiserver-kubelet-client.crt --kubelet-client-key=/etc/kubernetes/pki/apiserver-kubelet-client.key --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname --proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.crt --proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client.key --requestheader-allowed-names=front-proxy-client --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt --requestheader-extra-headers-prefix=X-Remote-Extra- --requestheader-group-headers=X-Remote-Group --requestheader-username-headers=X-Remote-User --secure-port=6443 --service-account-key-file=/etc/kubernetes/pki/sa.pub --service-cluster-ip-range=10.96.0.0/12 --tls-cert-file=/etc/kubernetes/pki/apiserver.crt --tls-private-key-file=/etc/kubernetes/pki/apiserver.key

ServiceAccount

为Pod中的进程和外部用户提供身份信息,系统账户,可以通过serviceaccount在pod中区访问apiserver

# kubectl get sa
NAME      SECRETS   AGE
default   1         7d17h

对外提供的6443端口

#netstat -natp | grep 6443 | grep LISTEN
tcp6       0      0 :::6443                 :::*                    LISTEN      21679/kube-apiserve

k8s集群角色超级管理员cluster-admin,拥有所有权限。

kubectl  get clusterrole | grep cluster
cluster-admin                                                          2020-11-21T15:35:31Z

#kubectl describe clusterrole  cluster-admin
Name:         cluster-admin
Labels:       kubernetes.io/bootstrapping=rbac-defaults
Annotations:  rbac.authorization.kubernetes.io/autoupdate: true
PolicyRule:
  Resources  Non-Resource URLs  Resource Names  Verbs
  ---------  -----------------  --------------  -----
  *.*        []                 []              [*]
             [*]                []              [*]

二、RBAC   基于角色的访问控制(Role-Based Access Control )

属于授权第二阶段

RBAC使用rbac.authorization.k8s.io API Group 来实现授权决策,允许管理员通过 Kubernetes API 动态配置策略,要启用RBAC,需要在 apiserver 中添加参数--authorization-mode=RBAC,如果使用的kubeadm安装的集群,1.6 版本以上的都默认开启了RBAC,可以通过查看 Master 节点上 apiserver 的静态Pod定义文件:

# cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep RBAC
    - --authorization-mode=Node,RBAC

如果是二进制的方式搭建的集群,添加这个参数过后,记得要重启 apiserver 服务。

RBAC API 对象

Kubernetes有一个很基本的特性就是它的所有资源对象都是模型化的 API 对象,允许执行 CRUD(Create、Read、Update、Delete)操作(也就是我们常说的增、删、改、查操作),比如下面的这下资源:

Pods
ConfigMaps
Deployments
Nodes
Secrets
Namespaces

 上面这些资源对象的可能存在的操作有:

create
get
delete
list
update
edit
watch
exec

在更上层,这些资源和 API Group 进行关联,比如Pods属于 Core API Group,而Deployements属于 apps API Group,要在Kubernetes中进行RBAC的管理,除了上面的这些资源和操作以外,我们还需要另外的一些对象:

Rule:规则,规则是一组属于不同 API Group 资源上的一组操作的集合
Role 和 ClusterRole:角色和集群角色,这两个对象都包含上面的 Rules 元素,二者的区别在于,在 Role 中,定义的规则只适用于单个命名空间,也就是和 namespace 关联的,而 ClusterRole 是集群范围内的,因此定义的规则不受命名空间的约束。另外 Role 和 ClusterRole 在Kubernetes中都被定义为集群内部的 API 资源,和我们前面学习过的 Pod、ConfigMap 这些类似,都是我们集群的资源对象,所以同样的可以使用我们前面的kubectl相关的命令来进行操作
Subject:主题,对应在集群中尝试操作的对象,集群中定义了3种类型的主题资源:

User Account:用户,这是有外部独立服务进行管理的,管理员进行私钥的分配,用户可以使用 KeyStone或者 Goolge 帐号,甚至一个用户名和密码的文件列表也可以。对于用户的管理集群内部没有一个关联的资源对象,所以用户不能通过集群内部的 API 来进行管理
Group:组,这是用来关联多个账户的,集群中有一些默认创建的组,比如cluster-admin
Service Account:服务帐号,通过Kubernetes API 来管理的一些用户帐号,和 namespace 进行关联的,适用于集群内部运行的应用程序,需要通过 API 来完成权限认证,所以在集群内部进行权限操作,我们都需要使用到 ServiceAccount,这也是我们这节课的重点
RoleBinding 和 ClusterRoleBinding:角色绑定和集群角色绑定,简单来说就是把声明的 Subject 和我们的 Role 进行绑定的过程(给某个用户绑定上操作的权限),二者的区别也是作用范围的区别:RoleBinding 只会影响到当前 namespace 下面的资源操作权限,而 ClusterRoleBinding 会影响到所有的 namespace。
角色:
Role——授权特定命名空间的访问权限
CluserRole——授权所有命名空间的访问权限

角色绑定
RoleBinding       ——将角色绑定到主体(即subject)
CluesterRoleBinding     ——将集群角色绑定到主体(即subject)

主体(subject)
User——用户账号
Group——用户组
ServiceAccount——服务账号

摘自https://mp.weixin.qq.com/s/awnrscX7VfyLGL0kEi0y1w,一个不错的运维技术微信公众号

接下来我们来通过几个示例来演示下RBAC的配置方法。

我们来创建一个 User Account,只能访问 kube-system 这个命名空间:

username: zjz
group: cetc

第1步:创建用户凭证

我们前面已经提到过,Kubernetes没有 User Account 的 API 对象,不过要创建一个用户帐号的话也是挺简单的,利用管理员分配给你的一个私钥就可以创建了,参考https://kubernetes.io/docs/reference/access-authn-authz/authentication/,这里我们来使用OpenSSL证书来创建一个 User,当然我们也可以使用更简单的cfssl工具来创建:
给用户 zjz创建一个私钥,命名成:zjz.key:

# openssl genrsa -out zjz.key 2048
Generating RSA private key, 2048 bit long modulus
..............+++
....................................+++
e is 65537 (0x10001)

使用我们刚刚创建的私钥创建一个证书签名请求文件:zjz.csr,要注意需要确保在-subj参数中指定用户名和组(CN表示用户名,O表示组):

# openssl req -new -key zjz.key -out zjz.csr -subj "/CN=zjz/O=cetc"

然后找到我们的Kubernetes集群的CA,我们使用的是kubeadm安装的集群,CA相关证书位于/etc/kubernetes/pki/目录下面,如果你是二进制方式搭建的,你应该在最开始搭建集群的时候就已经指定好了CA的目录,我们会利用该目录下面的ca.crtca.key两个文件来批准上面的证书请求

生成最终的证书文件,我们这里设置证书的有效期为500天:

# openssl x509 -req -in zjz.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out zjz.crt -days 500
Signature ok subject=/CN=zjz/O=cetc Getting CA Private Key

现在查看我们当前文件夹下面是否生成了一个证书文件:

ls
zjz.crt      zjz.key      zjz.csr

现在我们可以使用刚刚创建的证书文件和私钥文件在集群中创建新的凭证和上下文(Context):

# kubectl config set-credentials zjz --client-certificate=zjz.crt  --client-key=zjz.key
User "zjz" set.

我们可以看到一个用户zjz创建了,然后为这个用户设置新的 Context:

# kubectl config set-context zjz-context --cluster=kubernetes --namespace=kube-system --user=zjz
Context "zjz-context" created.

 到这里,我们的用户zjz就已经创建成功了,现在我们使用当前的这个配置文件来操作kubectl命令的时候,应该会出现错误,因为我们还没有为该用户定义任何操作的权限呢:

kubectl get pods --context=zjz-context
Error from server (Forbidden): pods is forbidden: User "zjz" cannot list resource "pods" in API group "" in the namespace "kube-system"

第2步:创建角色

用户创建完成后,接下来就需要给该用户添加操作权限,我们来定义一个YAML文件,创建一个允许用户操作 Deployment、Pod、ReplicaSets 的角色,如下定义:(zjz-role.yaml)

# cat zjz-role.yaml 
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: zjz-role
  namespace: kube-system
rules:
- apiGroups: ["", "extensions", "apps"]
  resources: ["deployments", "replicasets", "pods"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] # 也可以使用['*']

其中Pod属于 core 这个 API Group,在YAML中用空字符就可以,而Deployment属于 apps 这个 API Group,ReplicaSets属于extensions这个 API Group(
我怎么知道的?https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/),
所以 rules 下面的 apiGroups 就综合了这几个资源的 API Group:["", "extensions", "apps"],其中verbs就是我们上面提到的可以对这些资源对象执行的操作,
我们这里需要所有的操作方法,所以我们也可以使用['*']来代替。

 然后创建这个Role

kubectl create -f zjz-role.yaml
注意这里我们没有使用上面的zjz-context这个上下文,因为没有权限

第3步:创建角色权限绑定

Role 创建完成了,但是很明显现在我们这个 Role 和我们的用户 zjz 还没有任何关系,对吧?这里我就需要创建一个RoleBinding对象,

在 kube-system 这个命名空间下面将上面的 zjz-role 角色和用户 zjz 进行绑定:(zjz-rolebinding.yaml)

# cat zjz-rolebinding.yaml 
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: zjz-rolebinding
  namespace: kube-system
subjects:
- kind: User
  name: zjz
  apiGroup: ""
roleRef:
  kind: Role
  name: zjz-role
  apiGroup: ""

上面的YAML文件中我们看到了subjects关键字,这里就是我们上面提到的用来尝试操作集群的对象,这里对应上面的 User 帐号 zjz,使用kubectl创建上面的资源对象:

 kubectl create -f zjz-rolebinding.yaml

第4步. 测试

现在我们应该可以上面的haimaxy-context上下文来操作集群了:

# kubectl get pods --context=zjz-context
NAME                             READY   STATUS    RESTARTS   AGE
coredns-66bff467f8-gs592         1/1     Running   0          3h36m
coredns-66bff467f8-vrk4l         1/1     Running   0          3h36m
etcd-master                      1/1     Running   0          3h36m
kube-apiserver-master            1/1     Running   0          3h36m
kube-controller-manager-master   1/1     Running   0          3h36m
kube-flannel-ds-amd64-hcsnq      1/1     Running   0          119m
kube-flannel-ds-amd64-nwlvk      1/1     Running   0          119m
kube-flannel-ds-amd64-pzh5q      1/1     Running   0          119m
kube-proxy-2sbdv                 1/1     Running   0          3h36m
kube-proxy-jj6nh                 1/1     Running   0          174m
kube-proxy-qr625                 1/1     Running   0          175m
kube-scheduler-master            1/1     Running   0          3h36m

我们可以看到我们使用kubectl的使用并没有指定 namespace 了,这是因为我们已经为该用户分配了权限了,如果我们在后面加上一个-n default试看看呢?

$ kubectl --context=zjz-context get pods --namespace=default
Error from server (Forbidden): pods is forbidden: User "haimaxy" cannot list pods in the namespace "default"

 

 一个视频看懂 Kubernetes RBAC 机制_哔哩哔哩_bilibili 推荐

https://segmentfault.com/a/1190000021905208   permission-manager 是一个用于 K8s RBAC 和 用户管理的web工具。

https://www.cnblogs.com/aresxin/p/k8s-sc.html      K8S权限控制,限制用户在多个namespace上的访问权限

https://blog.csdn.net/wangshui898/article/details/110817257   K8S基础-鉴权框架与用户权限分配,总结不错

posted @ 2020-07-06 14:26  凡人半睁眼  阅读(3512)  评论(0编辑  收藏  举报