kubernetes权限控制-授权

认证通过后通信的双方都确认了对方是可信的,可以相互通信。 Authrization 简单来说就是检查这个用户权限是否拥有操作K8S资源的权限,对哪些资源有操作权限,只要存在一个资源的操作权限正确,就允许通过而鉴权是确定请求方有哪些资源的权限。在Kubernetes中,默认使用的,也是使用较多的是RBAC(Role-Based Access Control)。

授权阶段判断请求是否有相应的权限,授权方式有多种:AlwaysDeny,AlwaysAllow,ABAC,RBAC,Node 等。API Server 启动时如果多种授权模式同时被启用,Kubernetes 将检查所有模块,如果其中一种通过授权,则请求授权通过。 如果所有的模块全部拒绝,则请求被拒绝(HTTP状态码403)。高版本 Kubernetes 默认开启的授权方式是 RBAC 和 Node。

kube-apiserver启动时需要配置:

--authorization-mode=Node,RBAC

目前k8s支持的授权模式主要有以下几种:

  • Node Authorization
  • ABAC Authorization
  • RBAC Authorization
  • Webhook Authorization

本文只描述Node Authorization 和 RBAC Authorization,

01.RBAC Authrization

基于角色的访问控制(Role-Based Access Control, 即 RBAC),是 k8s 提供的一种授权策略, 针对 RBAC 机制,k8s 提供了四种 API 资源:

  • Role
  • ClusterRole
  • RoleBinding
  • ClusterRoleBinding

这四种API资源的逻辑关系如下:

0101.角色(Role)

一个角色就是一组权限的集合,这里的权限都是许可模式,不存在拒绝的规则。在一个命名空间中,可以用角色来定义一个角色,如果是集群级别的,就需要使用 ClusterRole 了。

角色只能对命名空间内的资源进行授权,下面的例子中定义的角色具有读取 Pod 的权限:

kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  namespace: default
  name: pod-reader
rules:
- apiGroups: [""] # "" 空字符串,表示核心 API 群
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

rules中参数说明如下:

apiGroups:支持的 API 组列表,例如 “apiVersion: batch/v1” “apiVersion: extensions/v1beta1” "apiVersion: apps/v1beta1" 等。
resource:支持的资源对象列表,例如 pods、deployments、jobs 等。
verbs:对资源对象的操作方法列表,例如 get、watch、list、delete、replace、patch 等。

应该使用哪个 Group 和 Version?

0102.集群角色(Cluster Role)

集群角色除了具有和角色一致的命名空间内资源的管理能力,因其集群级别的范围,还可以用于以下特殊元素的授权。

  • 集群范围的资源,例如 Node(节点)。
  • 非资源型的路径,例如 “/healthz”。
  • 包含全部命名空间的资源,例如 pods(用于 kubectl get pods --all-namespaces 这样的操作授权)。

下面的集群角色可以让用户有权访问任意一个或所有命名空间的 secret:

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  # ClusterRole 不授权与命名空间,所以忽略了 namespace 的定义。
rules:
- apiGroups: [""] # "" 空字符串,表示核心 API 群
  resources: ["secrets"]
  verbs: ["get", "watch", "list"]

0103.角色绑定(RoleBinding)和集群角色绑定(ClusterRoleBinding)

角色绑定或集群角色绑定用来把一个角色绑定到一个目标上,保定目标可以是 User(用户)、Group(组)或者 Service Account。使用 RoleBinding 为某个命名空间授权,使用 ClusterRoleBinding 为集群范围内授权

RoleBinding

RoleBinding 可以引用 Role 进行授权。下例中的 RoleBinding 将在 default 命名空间中把 pod-reader 角色授权用户 jane,这一操作让 jane 可以读取 default 命名空间中的 Pod:

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: default
  namespace: default
subjects:
- kind: User
  name: jane
  apiGroups: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader
  apiGroups: rbac.authorization.k8s.io

RoleBinding 也可以引用 ClusterRole,对属于同一命名空间内 ClusterRole 定义的资源主体进行授权。一种常见的做法是集群管理员为集群范围预先定义好了一组角色(ClusterRole),然后在多个命名空间中重复使用这些 ClusterRole。

例如下面的例子,虽然 secret-reader 是一个集群角色,但是因为使用了 RoleBinding,所以 dave 只能读取 development 命名空间的 secret:

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: read-secrets
  namespace: development # 集群角色中,只有在 development namespace 中的权限才能赋予 dave
subjects:
- kind: User
  name: dave
  apiGroups: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: secret-reader
  apiGroups: rbac.authorization.k8s.io

ClusterRoleBinding

集群角色绑定中的角色只能是集群角色,用于进行集群级别或者对所有命名空间都生效的授权

下面的例子允许 manager 组的用户读取任意 namespace 中的 secret:

kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: read-secrets-global
subjects:
- kind: Group
  name: manager
  apiGroups: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: secret-reader
  apiGroups: rbac.authorization.k8s.io

0104.集群内置role和rolebinding

集群创建后 API Server 默认会创建一些 ClusterRole 和 ClusterRoleBinding 对象;这些对象以 system: 为前缀,这表明这些资源对象由集群基础设施拥有;修改这些集群基础设施拥有的对象可能导致集群不可用。 一个简单的例子是 system:node ClusterRole,这个 ClusterRole 定义了 kubelet 的相关权限,如果该 ClusterRole 被修改可能导致 ClusterRole 不可用。

所有的默认 ClusterRole 和 RoleBinding 都具有 kubernetes.io/bootstrapping=rbac-defaultslable

默认Role

一些默认的 Role 并未以 system: 前缀开头,这表明这些默认的 Role 是面向用户级别的。这其中包括超级用户的一些 Role( cluster-admin ),和为面向集群范围授权的 RoleBinding( cluster-status ),以及在特定命名空间中授权的 RoleBinding( admineditview )

Default ClusterRole Default ClusterRoleBinding Description
cluster-admin system:masters group 允许超级用户对集群内任意资源执行任何动作。当该 Role 绑定到 ClusterRoleBinding 时,将授予目标 subject 在任意 namespace 内对任何 resource 执行任何动作的权限;当绑定到 RoleBinding 时,将授予目标 subject 在当前 namespace 内对任意 resource 执行任何动作的权限,当然也包括 namespace 自己
admin None 管理员权限,用于在单个 namespace 内授权;在与某个 RoleBinding 绑定后提供在单个 namesapce 中对资源的读写权限,包括在单个 namesapce 内创建 Role 和进行 RoleBinding 的权限。该 ClusterRole 不允许对资源配额和 namespace 本身进行修改
edit None 允许读写指定 namespace 中的大多数资源对象;该 ClusterRole 不允许查看或修改 Role 和 RoleBinding
view None 允许以只读方式访问特定 namespace 中的大多数资源对象;该 ClusterRole 不允许查看 Role 或 RoleBinding,同时不允许查看 secrets,因为他们会不断更新

组件默认role

Default ClusterRole Default ClusterRoleBinding Description
system:kube-scheduler system:kube-scheduler user 允许访问 kube-scheduler 所需资源
system:kube-controller-manager system:kube-controller-manager user 允许访问 kube-controller-manager 所需资源;该 ClusterRole 包含每个控制循环所需要的权限
system:node system:nodes group (deprecated in 1.7) 允许访问 kubelet 所需资源;包括对所有的 secrets 读访问权限和对所有 pod 的写权限;在 1.7 中更推荐使用 Node authorizerNodeRestriction admission plugin 而非本 ClusterRole;Node authorizer 和 NodeRestriction admission plugin 可以授权当前 node 上运行的具体 pod 对 kubelet API 的访问权限,在 1.7 版本中,如果开启了 Node authorization mode,那么 system:nodes group将不会被创建和自动绑定
system:node-proxier system:kube-proxy user 允许访问 kube-proxy 所需资源
system:auth-delegator None 允许委托认证和授权检查;此情况下通常由附加的 API Server 来进行统一认证和授权
system:heapster None Heapster 组件相关权限
system:kube-aggregator None kube-aggregator 相关权限
system:kube-dns kube-dns service account in the kube-system namespace kube-dns 相关权限
system:node-bootstrapper None 允许访问 Kubelet TLS bootstrapping 相关资源权限
system:node-problem-detector None node-problem-detector 相关权限
system:persistent-volume-provisioner Node 允许访问 dynamic volume provisioners 相关资源权限

0105.最佳实践

010501.实践一

主要授权zhangsan可以访问develop namespace下的所有的权限

1.创建x509证书

由于使用X509方式时k8s将证书中的CN作为用户名, O作为组名,所以下面为的CSR文件为

cat > developer-csr.json <<EOF
{
  "CN": "zhangsan",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "China",
      "L": "Beijing",
      "O": "Kubernetes",
      "OU": "Kubernetes",
      "ST": "Beijing"
    }
  ]
}
EOF

创建 developer 凭证与私钥:

cfssl gencert \
  -ca=ca.pem \
  -ca-key=ca-key.pem \
  -config=ca-config.json \
  -profile=kubernetes \
  developer-csr.json | cfssljson -bare developer

结果将产生以下两个文件:

developer-key.pem
developer.pem
2.创建kubeconfig文件

先确定apiserver对外提供服务的地址

export KUBE_APISERVER="https://apiserver-p001.svc.gxd88.cn:6443"
  • 设置集群参数

    kubectl config set-cluster kubernetes \
    --certificate-authority=ca.pem \
    --embed-certs=true \
    --server=${KUBE_APISERVER} \
    --kubeconfig=develope.kubeconfig
    
  • 设置客户端认证参数

    kubectl config set-credentials developer-user \
    --client-certificate=developer.pem \
    --client-key=developer-key.pem \
    --embed-certs=true \
    --kubeconfig=develope.kubeconfig
    
  • 设置上下文参数

    kubectl config set-context default \
    --cluster=kubernetes \
    --user=developer-user \
    --kubeconfig=develope.kubeconfig
    
  • 设置默认上下文

    kubectl config use-context default --kubeconfig=develope.kubeconfig
    
3.授权

由于k8s集群中默认已经创建了名称为 admin 的clusterrole, 所以我们只需要创建rolebinding, 指令如下:

创建namespace:

kubectl  create ns develop

创建rolebinding:

kubectl create rolebinding developer-role-binding \
    --clusterrole=admin  \
    --user=zhangsan \
    --namespace=develop
4.验证

获取default namespace下的资源

$ kubectl --kubeconfig=developer.kubeconfig  get pods
Error from server (Forbidden): pods is forbidden: User "zhangsan" cannot list resource "pods" in API group "" in the namespace "default"

获取develop下的资源

$ kubectl --kubeconfig=developer.kubeconfig  get pods -n develop
No resources found in develop namespace.

010502.实践二

用户张三可以操作develop namespace下的deployment、svc、ingresses资源, 对于其它资源没有操作权限。

请根据010501.实践一 完成x509证书和kubeconfig的相关部分

1.role yaml模版文件

执行如下指令获取role文件的字段名称已经文件结构:

$ kubectl explain  role  --recursive
KIND:     Role
VERSION:  rbac.authorization.k8s.io/v1

DESCRIPTION:
     Role is a namespaced, logical grouping of PolicyRules that can be
     referenced as a unit by a RoleBinding.

FIELDS:
   apiVersion   <string>
   kind <string>
   metadata <Object>
      annotations   <map[string]string>
      clusterName   <string>
      creationTimestamp <string>
      deletionGracePeriodSeconds <integer>
      deletionTimestamp <string>
      finalizers    <[]string>
      generateName  <string>
      generation    <integer>
      labels    <map[string]string>
      managedFields <[]Object>
         apiVersion <string>
         fieldsType <string>
         fieldsV1   <map[string]>
         manager    <string>
         operation  <string>
         time   <string>
      name  <string>
      namespace <string>
      ownerReferences   <[]Object>
         apiVersion <string>
         blockOwnerDeletion <boolean>
         controller <boolean>
         kind   <string>
         name   <string>
         uid    <string>
      resourceVersion   <string>
      selfLink  <string>
      uid   <string>
   rules    <[]Object>
      apiGroups <[]string>
      nonResourceURLs   <[]string>
      resourceNames <[]string>
      resources <[]string>
      verbs <[]string>

根据上面文件的KING部分和Version部分获取了api版本, FIELDS部分可以获取到字段名称以及结构, yaml文件的结构如下:

kind:     Role
apiVersion:  rbac.authorization.k8s.io/v1
metadata: 
  name: develop-role
  namespace: develop 
rules: 
- apiGroups:
  - ""
  resources:
  - services
  verbs:
  -  
- apiGroups:
  - ""
  resources:
  - ingress
  verbs:
  -  
- apiGroups:
  - ""
  resources:
  - deployments
  verbs:
  - 
2.获取deployments、services、ingress所属的apigroups

获取资源所属apigroups以及可以进行的操作

$ kubectl api-resources -o wide 

得出资源所对应的apigroup, 汇总如下表:

resource apigroup
deployments apps
services k8s core
ingresses extensions、 networking.k8s.io

最后role文件汇总

cat > developer-role.yaml << EOF

Kind:     Role
apiVersion:  rbac.authorization.k8s.io/v1
metadata: 
  name: develop-role
  namespace: develop 
rules: 
- apiGroups:
  - ""
  resources:
  - services
  verbs:
  - create 
  - delete 
  - get 
  - list 
  - patch 
  - update 
  - watch
- apiGroups:
  - "extensions"
  - "networking.k8s.io"
  resources:
  - ingresses
  verbs:
  - create 
  - delete 
  - deletecollection 
  - get 
  - list 
  - patch 
  - update 
  - watch
- apiGroups:
  - "apps"
  resources:
  - deployments
  verbs:
  - create 
  - delete 
  - get 
  - list 
  - patch 
  - update 
  - watch
EOF

创建role:

$ kubectl  apply -f developer-role.yaml
3.授权

创建rolebinding:

kubectl create rolebinding developer-role-binding \
    --role=develop-role  \
    --user=zhangsan \
    --namespace=develop
4.验证

执行如下指令:

$ kubectl  --kubeconfig=developer.kubeconfig  get deployments -n develop
NAME        READY   UP-TO-DATE   AVAILABLE   AGE
nginx-app   1/1     1            1           18h

$ kubectl  --kubeconfig=developer.kubeconfig  get svc  -n develop
No resources found in develop namespace.

$ kubectl  --kubeconfig=developer.kubeconfig  get ingress  -n develop
No resources found in develop namespace.

$ kubectl  --kubeconfig=developer.kubeconfig  get pods  -n develop
Error from server (Forbidden): pods is forbidden: User "zhangsan" cannot list resource "pods" in API group "" in the namespace "develop"

因为只授权了deployment, svc, ingress 相关的资源所以查看pods会提示没有权限

02.Node Authrization

下面文字摘自官方文档, 具体内部的工作逻辑找了很多文档也没有看出所以然, 只能说node authrization是 kubernetes 的内部机制

Node Authrization 是一种特殊目的的授权模式,主要用来让 kubernetes 遵从 node 的编排规则,实际上是 RBAC 的一部分,相当于只定义了 node 这个角色以及它的权限, 专门对 kubelet 发出的 API 请求进行鉴权。

要启用节点授权器,启用 Node 鉴权模式 (--authorization-mode=Node,RBAC) 和 NodeRestriction 准入插件

节点鉴权器允许 kubelet 执行 API 操作。包括:

读取操作:

  • services
  • endpoints
  • nodes
  • pods
  • secrets、configmaps、以及绑定到 kubelet 的节点的 pod 的持久卷申领和持久卷

写入操作:

  • 节点和节点状态(启用 NodeRestriction 准入插件以限制 kubelet 只能修改自己的节点)
  • Pod 和 Pod 状态 (启用 NodeRestriction 准入插件以限制 kubelet 只能修改绑定到自身的 Pod)
    事件

鉴权相关操作:

  • 对于基于 TLS 的启动引导过程时使用的 certificationsigningrequests API 的读/写权限
  • 为委派的身份验证/授权检查创建 tokenreviews 和 subjectaccessreviews 的能力

在将来的版本中,节点鉴权器可能会添加或删除权限,以确保 kubelet 具有正确操作所需的最小权限集。
为了获得节点鉴权器的授权,kubelet 必须使用一个凭证以表示它在 system:nodes 组中,用户名为 system:node:<nodeName>。 上述的组名和用户名格式要与 kubelet TLS 启动引导过程中为每个 kubelet 创建的标识相匹配。

要启用节点授权器,请使用 --authorization-mode = Node 启动 apiserver。

要限制 kubelet 具有写入权限的 API 对象,请使用--enable-admission-plugins=...,NodeRestriction,...启动 apiserver,从而启用 NodeRestriction 准入插件。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,589评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,615评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,933评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,976评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,999评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,775评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,474评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,359评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,854评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,007评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,146评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,826评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,484评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,029评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,153评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,420评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,107评论 2 356

推荐阅读更多精彩内容