《Kubernetes in action》Kubernetes API权限认证(一)

了解认证机制

API 服务器接收到的请求会经过一个认证插件的列表,列表中的每个插件都可以检查这个请求和尝试确定谁在发送这个请求。列表中的第一个插件可以提取请求中客户端的用户名、用户 ID 和组信息,并返回给 API 服务器。 API服务器会停止调用剩余的认证插件井继续进入授权阶段。目前有几个认证插件是直接可用的。它们使用下列方法获取客户端的身份认证:

  • 客户端证书
  • 传入在 HTTP 头中的认证 token
  • 基础的 HTTP 认证
  • 其他
    启动 API 服务器时,通过命令行边项可以开启认证插件。

用户和组

认证插件会返回已经认证过用户的用户名和组(多个组)。Kubernetes 不会在任何地方存储这些信息,这些信息被用来验证用户是否被授权执行某个操作。

用户
Kubernetes 区分 了两种连接到 PI 服务器的客户端

  • 真实的人 (用户)
  • pod (更准确地说是运行在 pod 中的应用)
    这两种类型的客户端都使用了上述的认证插件进行认证。用户应该被管理在外部系统中,例如单点登录系统CSSO ),但是 pod 使用一种称为 serv ce accounts 的机制,该机制被创建和存储在集群中作为 ServiceAccount 资源。 相反, 没有资源代表用户账户,这也就意味着不能通过 AP 服务器来创建、更新或删除用户。


正常用户和 ServiceAccount 都可以属于一个或多个组。 我们己经讲过认证插会连同用户名和用户 ID 返回组。组可以一次给多个用户赋予权限,而不是必须单独给用户赋予权限
由插件返回的组仅仅是表示组名称的字符串,但是系统 置的组会有一些特殊含义。

  • system unauthenticated 组用于所有认证插件都不会认证客户端身份的请求。
  • system authent cated 组会自动分配给一个成功通过认证的用户
  • system:serviceaccounts 组包含所有在系统中的 ServiceAccount
  • system:serviceaccounts:组包含了所有在特定命名空间中的ServiceAccount。

ServiceAccount介绍

pod是通过发送/var/run/secrets/kubernetes.io/serviceaccount/token文件内容来进行身份认证的 。 这个文件通过加密卷挂载进每个容器的文件系统中。
但是那个文件具体表示了什么呢?每个pod都与 一 个ServiceAccount相关联,它代表了运行在pod中应用程序的身份证明。token文件持有ServiceAccount的认证token。 应用程序使用这个 token连接API服务器时, 身份认证插件会对ServiceAccount进行身份认证, 并将 ServiceAccount的用户名传回API服务器内部。ServiceAccount用户名的格式像下面这样:
system:serviceaccount:<namespace>:<service account name>
API服务器将这个用户名传给己配置好的授权插件,这决定该应用程序所尝试执行的操作是否被ServiceAccount允许执行 。ServiceAccount只不过是一种运行在pod中的应用程序和API服务器身份认证的一种方式

ServiceAccount 资源

ServiceAccount就像Pod、 Secret、 ConfigMap等一 样都是资源, 它们作用在单独的命名空间, 为每个命名空间自动创建一个默认的ServiceAccount:default(你的pod 会一直使用)。
其他额外的ServiceAccount可以在需要时添加。 每个pod都与 一个ServiceAccount相关联, 但是多个pod可以使用同 一个ServiceAccount。
serviceAccount of pod
ServiceAccount 如何和授权进行绑定

在 pod 的 manifest 文件中, 可以用指定账户名称的方式将一个 ServiceAccount赋值给一个 pod。 如果不显式地指定 ServiceAccount 的账户名称, pod 会使用在这个命名空间中的默认 ServiceAccount。
可以通过将不同的 ServiceAccount 赋值给 pod 来控制每个 pod 可以访问的资源。当 API 服务器接收到一个带有认证 token 的请求时, 服务器会用这个 token 来验证发送请求的客户端所关联的 ServiceAccount 是否允许执行请求的操作。 API 服务器通过管理员配置好的系统级别认证插件来获取这些信息。 其中一个现成的授权插件是基千角色控制的插件(RBAC), 这个插件会在本章后续进行讨论。 从 Kubemetes 1.6 版本开始, RBAC 插件是绝大多数集群应该使用的授权插件。

创建ServiceAccount

为什么应该费力去创建新的 ServiceAccount 而不是对所有的 pod 都使用默认的 ServiceAccount ?
显而易见的原因是集群安全性。 不需要读取任何集群元数据的 pod 应该运行在一个受限制的账户下, 这个账户不允许它们检索或修改部署在集群中的任何资源。需要检索资源元数据的 pod 应该运行在只允许读取这些对象元数据的 ServiceAccount下。 反之, 需要修改这些对象的 pod 应该在它们自己的 ServiceAccount 下运行, 这 些 ServiceAccount 允许修改 API 对象。

[root@shpl009030064 hpa]# kubectl describe  sa -n big-data default 
Name:                default
Namespace:           big-data
Labels:              <none>
Annotations:         <none>
Image pull secrets:  <none> # 会被自动地添加到使用这个ServiceAccount的所有Pod
Mountable secrets:   default-token-d54mc # 如果强制使用可挂载的密钥, 那么使用这个ServiceAccount的pod只能挂载这些密钥
Tokens:              default-token-d54mc # 认证token, 第一个token挂载在容器内
Events:              <none>

ServiceAccount中使用的身份认证token就是JWT token 。

ServiceAccount 上的可挂载密钥

在默认情况下,pod可以挂载任何它需要的密钥。但是我们可以通过对ServiceAccount 进行配置,让 pod 只允许挂载ServiceAccount 中列出的可挂载密钥。为了开启这个功能,ServiceAccount 必须包含以下注解: kubernetes.io/enforce-mountable-secrets= “true”
如果 ServiceAccount 被加上了这个注解,任何使用这个 ServiceAccount 的 pod只能挂载进 ServiceAccount 的可挂载密钥 – 这些 pod不能使用其他的密钥。

ServiceAccount 的镜像拉取密钥

kubectl get sa -n big-data default -o yaml

apiVersion: v1
kind: ServiceAccount
metadata:
  creationTimestamp: "2020-04-10T10:06:27Z"
  name: default
  namespace: big-data
  resourceVersion: "6260643"
  selfLink: /api/v1/namespaces/big-data/serviceaccounts/default
  uid: e0982922-e88d-466c-b812-45326f5c5e21
secrets:
- name: default-token-d54mc

ServiceAccount 的镜像拉取密钥和它的可挂载密钥表现有些轻微不同。和可挂载密钥不同的是,ServiceAccount 中的镜像拉取密钥不是用来确定一个pod可以使用哪些镜像拉取密钥的。添加到 ServiceAccount 中的镜像拉取密钥会自动添加到所有使用这个ServiceAccount 的 pod 中。向 ServiceAccount 中添加镜像拉取密钥可以不必对每个pod 都单独进行镜像拉取密钥的添加操作。

将 ServiceAccount 分配给 pod

[root@SHPL009049015 zto-eilinge]# kubectl create sa foo
serviceaccount/foo created

[root@SHPL009049015 hpa]# cat sa-foo.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: curl-custom-sa
spec:
  serviceAccountName: foo
  containers:
  - name: main
    image: tutum/curl
    command: ["sleep", "9999"]
  - name: ambassador
    image: luksa/kubectl-proxy:1.6.2
    
[root@SHPL009049015 zto-eilinge]# kubectl create -f sa-test.yaml 
pod/curl-custom-sa created

[root@SHPL009049015 zto-eilinge]# kubectl get pod curl-custom-sa -oyaml|less
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: "2020-05-18T06:42:12Z"
  name: curl-custom-sa
  namespace: default
  resourceVersion: "13056464"
  selfLink: /api/v1/namespaces/default/pods/curl-custom-sa
  uid: 802a4b81-db2e-4e1d-9b15-d6add3a4d5ed
spec:
  containers:
  - command:
    - sleep
    - "9999"
    image: tutum/curl
    imagePullPolicy: Always
    volumeMounts:
    - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
      name: foo-token-9vxvs
      readOnly: true
      
[root@SHPL009049015 zto-eilinge]# kubectl exec -it curl-custom-sa -c main -- /bin/bash
root@curl-custom-sa:/# cat /var/run/secrets/kubernetes.io/serviceaccount/token
eyJhbGciOiJSUzI1NiIsImtpZCI6Im92M1U4LXI5b3lPdWtGVGx...

[root@SHPL009049015 zto-eilinge]# kubectl exec -it curl-custom-sa -c main curl localhost:8001/api/v1/pods
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {
    
  },
  "status": "Failure",
  "message": "pods is forbidden: User \"system:serviceaccount:default:foo\" cannot list resource \"pods\" in API group \"\" at the cluster scope",
  "reason": "Forbidden",
  "details": {
    "kind": "pods"
  },
  "code": 403 # 当前kubernetes设置了RBAC, 无法list pods

通过基于角色的权限控制加强集群安全

RBAC会阻止未授权的用户查看和修改集群状态。除非你授予默认的Se1-viceAccount额外的特权,否则默认的ServiceAccount不允许查看集群状态,更不用说以任何方式去修改集群状态。
除了RBAC插件,Kubemetes也包含其他的授权插件,比如基于属性的访问控制插件 (ABAC)、WebHook插件和自定义插件实现。但是,RBAC插件是标准的。

介绍RBAC授权插件

Kubernetes API 服务器可以配置使用 一个授权插件来检查是否允许用户请求的动作执行。 因为 API 服务器对外暴露了 REST 接口, 用户可以通过向服务器发送HTTP 请求来执行动作, 通过在请求中包含认证凭证来进行认证(认证 token、 用户名和密码或者客户端证书)。

动作

REST 客户端发送 GET、 POST、 PUT、DELETE 和其他类型的 HTTP 请求到特定的 URL 路径上, 这些路径表示特定的REST 资源。 在 Kubemetes 中, 这些资源是 Pod、 Service、 Secret, 等等。 以下是Kubernetes 请求动作的一些例子:

  • 获取 pod
  • 创建服务
  • 更新密钥
    opentor
    RBAC 插件

顾名思义, RBAC 授权插件将用户角色作为决定用户能否执行操作的关键因素。主体(可以是一个人、 一个 ServiceAccount, 或者一组用户或 ServiceAccount)和 一个或多个角色相关联, 每个角色被允许在特定的资源上执行特定的动词。
如果一个用户有多个角色, 他们可以做任何他们的角色允许他们做的事情。 如果用户的角色都没有包含对应的权限, 例如, 更新密钥, API 服务器会阻止用户 3 个 “他的” 对密钥执行PUT或PATCH请求。

介绍RBAC资源

RBAC 授权规则是通过四种资源来进行配置的, 它们可以分为两个组

  • Role( 角色)和 ClusterRole (集群角色), 它们指定了在资源上可以执行哪些动词
  • RoleBinding (角色绑定) 和 ClusterRoleBinding (集群角色绑定), 它们将上述角色绑定到特定的用户、 组或 ServiceAccounts 上。
    role 权限
    cluster role 权限
    此前kubectl exec -it curl-custom-sa -c main curl localhost:8001/api/v1/pods禁止访问, 需要添加RBAC的操作权限
[root@SHPL009049015 rbac-foo]# cat role-foo.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: service-reader
rules:
- apiGroups: [""]
  verbs: ["get", "list"]
  resources: ["pods", "services"]

[root@SHPL009049015 rbac-foo]# cat rolebinding-foo.yaml
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: read-pods
  namespace: default
subjects: # 赋予sa/user/group权限
- kind: ServiceAccount
  name: foo
  #apiGroup: rbac.authorization.k8s.io
roleRef: # 绑定role权限
  kind: Role
  name: service-reader
  apiGroup: rbac.authorization.k8s.io

[root@SHPL009049015 rbac-foo]# kubectl apply -f role-foo.yaml
[root@SHPL009049015 rbac-foo]# kubectl apply -f rolebinding-foo.yaml

kubectl exec -it curl-custom-sa -c main curl localhost:8001/api/v1/pods 还是无法访问, Pods为集群资源**

绑定集群角色即可

[root@SHPL009049015 rbac-foo]# cat clusterrole-foo.yaml
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: pods-reader
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

[root@SHPL009049015 rbac-foo]# cat clusterrolebinding-foo.yaml
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: read-pods-global
  namespace: default
subjects:
- kind: ServiceAccount
  name: foo
  namespace: default # 必须指定namespace
roleRef:
  kind: ClusterRole
  name: pods-reader
  apiGroup: rbac.authorization.k8s.io

[root@SHPL009049015 rbac-foo]# kubectl apply -f clusterrolebinding-foo.yaml
[root@SHPL009049015 rbac-foo]# kubectl apply -f clusterrole-foo.yaml

kubectl exec -it curl-custom-sa -c main curl localhost:8001/api/v1/pods可以list pods

RoleBinding
rolebinding
rolebing 1
Rolebinding/ClusterRolebinding
rolebinding opertor
clusterrolebinding
clusterRole

允许访问非资源型的URL
non mainfest
和集群级别的资源 样,非资源型的 URL lu sterRole 必须与 ClsterRoleBinding结合使用。把它 RoleBinding 绑定不会有任何效果 system discoveryCluster Role 有一个与之对应的 sys m:discovery ClusterRoleBinding

[root@shpl009030064 prometheus-kubesphere]# kubectl get clusterrolebinding system:discovery -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  creationTimestamp: "2020-03-18T05:15:23Z"
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: system:discovery
  resourceVersion: "98"
  selfLink: /apis/rbac.authorization.k8s.io/v1/clusterrolebindings/system%3Adiscovery
  uid: 836fa2ab-1cb8-4166-bb7c-1f33670750c8
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:discovery
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: Group
  name: system:authenticated

YAML内容显示ClusterRoleBinding正如预期的那样指向system:discovery
ClusterRole。 它绑 定到了两个组, 分别是sys七em:authenticated和system:unauthenticated, 这使得它和所有用户绑定在一起 。 这意味着每个人都绝对可以访问列在ClusterRole中的URL。

clusterrolebind and clusterrole
rolebind and role
总结Role、ClusterRole、 Rolebinding和ClusterRoleBind i ng的组合
summer rolebinding

默认的 ClusterRole 和 ClusterRoleBinding

clusterrole and rolebindings
用view ClusterRole 允许对资源的只读访问

它允许读取一个命名空间中的大多数资源, 除了Role、 RoleBinding和 Secret。
Secrets中的某一个可能包含 一个认证token, 它比定义在view ClusterRole中的资源有更大的权限 并且允许用户伪装成不同的用户来 获取额外的权限(权限扩散)。

editClusterRole允许对资源的修改

它允许你修改一个命名空间中的资源,同时允许读取和修改Secret。 但是,它也不允许查看或修改Role和 RoleBinding, 这是为了防止权限扩散。

adminClusterRole赋予一个命名空间全部的控制权

一个命名空间中的资源的完全控制权是由admin ClusterRole赋予的。 有这个ClusterRole的主体可以读取和修改命名空间中的任何资源, 除了ResourceQuota和 命名空间资源本身。 ed江和adminClusterRole 之间的主要区别是能否在命名空间中查看和修改Role和RoleBinding。

cluster-adminClusterRole得到完全的控制

通过将cluster-adminClusterRole赋给主体, 主体可以获得Kubernetes 集群完全控制的权限。 正如你前面了解的那样, adminClusterRole不允许用户修改命名空间的 ResourceQuota对象或者命名空间 资源本身。 如果你想允许用户这样做, 需要创建一个指向cluster-adminClusterRole的 RoleBinding。 这使得RoleBinding中包含的用户 能够完全控制创建RoleBinding所在命名空间上的所有方面 。

本章小结

对Kubernetes API服务器进行安全防护的基础知识。 已经了解到

  • API 服务器的客户端有真实的用户和 pod 中运行的应用。
  • pod 中的应用与一个 ServiceAccount 关联。
  • 用户和 ServiceAccount 都与组进行关联。
  • 在默认情况下, pod 运行在每个命名空间自动创建的默认 ServiceAccount下。
  • 额外的 ServiceAccount 可以手动创建, 并且和一个 pod 关联。
  • ServiceAccount 通过配置可以允许只挂载给定 pod 中受限的 Secret 列表。
  • 一个 ServiceAccount 也可以用来给pod 添加镜像拉取密钥, 因此你就不需要在每个 pod 里指定密钥了。
  • Role 和 ClusterRole 定义了可以在哪些资源上执行什么操作。
  • RoleBinding 和 ClusterRoleBinding 将 Role 和 ClusterRole 绑定给用户、 组和ServiceAccount
  • 每个集群都有默认的 ClusterRole 和 ClusterRoleBinding。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值