一文讀懂 TKE 及 Kubernetes 訪問權限控制

你有了解過Kubernetes的認證受權鏈路嗎?是否對TKE的權限控制CAM策略、服務角色傻傻分不清楚?本文將會向你介紹 騰訊雲TKE平臺側的訪問控制Kubernetes訪問控制鏈路,以及演示如何將平臺側帳號對接到Kubernetes內。

當你在使用騰訊雲容器服務TKE(Tencent Kubernetes Engine)的時候,若是多人共用一個帳號的狀況下,是否有遇到如下問題呢?web

  • 密鑰由多人共享,泄密風險高。
  • 沒法限制其餘人的訪問權限,其餘人誤操做易形成安全風險。

爲了解決以上問題,騰訊雲CAM(Cloud Access Management)提供了主帳號和子帳號的認證體系以及基於角色的權限控制。shell

而不一樣的子帳號對於TKE平臺側資源的控制粒度比較粗(cluster實例級別),又會遇到如下問題:後端

  • 同一個集羣由多子帳號可訪問,沒法保證集羣資源級別、命名空間級別的讀寫控制。
  • 集羣的高權限子帳戶沒法對低權限子帳戶進行受權管理。

爲了解決以上兩個問題,TKE針對平臺側資源Kubernetes資源分別進行相應的訪問控制管理。api

平臺側訪問控制

首先介紹下什麼是平臺側資源,平臺側資源即Cluster資源CVM資源CLB資源VPC資源等騰訊雲資源,而訪問的用戶主要分爲用戶服務角色載體緩存

  1. 用戶就是咱們平時登陸控制檯的主帳號、子帳號或者協做者帳號
  2. 服務角色是一種定義好帶有某些權限的角色,能夠將這個角色賦予某個載體,能夠是某個其餘帳戶,也能夠是騰訊雲下一個產品的服務提供者,CAM會默認爲產品提供一個預設的載體和默認的角色,例如TKE的默認角色就是TKE_QCSRole,而載體就是ccs.qcloud.com

而這個角色有什麼用處呢?舉個TKE的例子,好比TKE的service-controller會Watch集羣內的Service資源,若是須要建立LoadBalance類型的Service,會經過雲API購買並建立CLB資源,而service-controller是TKE平臺爲用戶部署的,去訪問雲API須要有身份,這個身份就是ccs.qcloud.com載體,而權限則須要用戶給載體授予一個角色,即TKE_QCSRole。只有用戶在受權TKE載體以後,TKE才能夠經過服務扮演的方式代替用戶購買CLB。
下面我會簡單爲你介紹如何給用戶受權,以及如何給TKE平臺授予角色安全

定製策略

TKE經過接入CAM,對集羣的API接口級別進行權限細分,須要您在CAM控制檯對子帳戶進行不一樣的權限授予。同時TKE也在CAM側提供了預設的權限,提供您默認選擇,例如:
運維

也能夠自定義策略,具體策略定製請參考CAM產品介紹文檔
工具

例如擁有隻讀權限的子帳戶嘗試修改集羣名稱,將會在API接口時校驗CAM權限失敗
ui

劃分用戶組

能夠依據團隊的職責劃分好用戶組,將以前規劃好的自定義策略綁定到一個用戶組上,來方便的進行權限管理。
例如:有新同窗入職時可方便的加入指定用戶組(如運維組),就能夠獲取到該用戶組的權限,避免了繁瑣的權限配置操做。url

授予TKE角色權限

使用TKE容器服務須要授予TKE平臺爲您操做CVMCLBVPCCBS等權限,因此首次訪問TKE控制檯須要確保贊成受權,即建立預設角色TKE_QCSRole,此角色默認授予TKE載體,該載體會經過CAM獲取操做您集羣的臨時密鑰,來進行相應的雲API操做。

更多

更多豐富的平臺側訪問控制用法請訪問CAM產品說明文檔

Kubernetes訪問控制

介紹完平臺側資源的訪問控制,咱們再來看看TKE集羣內的資源如何進行權限管理。當不一樣的子帳戶都擁有訪問同一個TKE Kubernetes集羣權限以後,如何保證不一樣的子帳戶,對於集羣內資源擁有不一樣的角色和權限呢?讓咱們首先從社區的Kubernetes訪問鏈路來分析整個過程,從而向您介紹TKE是如何實現容器服務子帳戶對接Kubernetes認證受權體系的。

Overview

首先從宏觀的角度看下Kubernetes的請求鏈路是如何進行的。圖片來源於k8s社區官網。

能夠大概瞭解到一個請求的鏈路是依次經過Authentication(認證,簡稱Authn)、Authorization(受權,簡稱Authz)、AdmissionControl(准入控制),從而獲取到後端持久化的數據。

從圖中能夠看到Authn、Authz、AdmissionControl是由多個模塊組成的,每一個步驟都有多種方式構成的。

在進入認證模塊以前會將HTTP的Request進行構建context,而context中就包含了用戶的RequestInfo,userInfo、Verb、APIGroup、Version、Namespace、Resource、Path等。

帶着這些信息,下面咱們來一次看下准入過程當中的每一個步驟吧。

Kubernetes認證

認證的過程的證實user身份的過程。

Kubernetes中有兩類用戶,一類是ServiceAccount,一類是集羣真實的用戶。

ServiceAccount帳戶是由Kubernetes提供API(資源)進行建立和管理的,ServiceAccount能夠認爲是特殊的Secret資源,可用戶集羣內資源訪問APIServer的認證所用。經過能夠經過mount的方式掛載到Pod內進行使用。

真實的用戶一般是從外部發起請求訪問APIServer,由管理員進行管理認證憑證,而Kubernetes自己無論理任何的用戶和憑證信息的,即全部的用戶都是邏輯上的用戶,沒法經過API調用Kubernetes API進行建立真實用戶。

Kubernetes認證的方式衆多,常見的有TLS客戶端證書雙向認證、BearerToken認證、BasicAuthorization或認證代理(WebHook)

全部的認證方式都是以插件的形式串聯在認證鏈路中,只要有一種認證方式經過,便可經過認證模塊,且後續的認證方式不會被執行。

在此處參考一點點Kubernetes APIServer Authentication模塊的代碼,能夠發現,任何的認證方式都是一下Interface的實現方式都是接收http Request請求,而後會返回一個user.Info的結構體,一個bool,以及一個error

// Request attempts to extract authentication information from a request and returns
// information about the current user and true if successful, false if not successful,
// or an error if the request could not be checked.
type Request interface {
   AuthenticateRequest(req *http.Request) (user.Info, bool, error)
}

user.Info中包含了用戶的信息,包括UserName、UUID、Group、Extra。

bool返回了用戶是否經過認證,false的話即返回沒法經過認證,即返回401錯誤。

error則返回了當Request沒法被檢查的錯誤,若是遇到錯誤則會繼續進行下一種註冊的方式進行認證。

若是認證經過,則會把user.Info寫入到到請求的context中,後續請求過程能夠隨時獲取用戶信息,好比受權時進行鑑權。

下面我會以Kubernetes代碼中的認證方式順序,挑選幾項認證方式,並結合TKE開啓的認證方式來向你介紹TKE建立的Kubernetes集羣默認的認證策略。

Basic Authentication

APIServer啓動參數--basic-auth-file=SOMEFILE指定basic認證的csv文件,在APIServer啓動以後修改此文件都不會生效,須要重啓APIServer來更新basic authentication的token。csv文件格式爲:token,user,uid,"group1,group2,group3"

請求時,須要指定HTTP Header中Authentication爲Basic,並跟上Base64Encode(user:passward)值。

x509客戶端證書

APIServer啓動參數--client-ca-file=SOMEFILE指定CA證書,而在TKE的K8s集羣建立過程當中,會對集羣進行自簽名CA密鑰和證書用於管理,若是用戶下發的客戶端證書是由此CA證書的密鑰簽發的,那麼就能夠經過客戶端證書認證,並使用客戶端證書中的CommonName、Group字段分別做爲Kubernetes的UserInfo中Username和Group信息。

目前TKE對接子帳戶都是經過自簽名的CA憑證進行簽發子帳戶Uin對應CN的客戶端證書。

Bearer Token

Bearer Token的認證方式包含不少,好比啓動參數指定的、ServiceAccount(也是一種特殊的BeaerToken)、BootstrapToken、OIDCIssure、WebhookToken

1. 默認指定Token csv文件

APIServer啓動參數--token-auth-file=SOMEFILE指定Bearer Token認證的csv文件。和Basic Authentication方式類似,只不過請求APIServer時,指定的HTTP認證方式爲Bearer方式。此Bearer後直接跟passward便可。csv文件格式爲:password,user,uid,"group1,group2,group3"

請求時,須要指定HTTP Header中Authentication爲Bearer,並跟上Base64Encode(user:passward)值。

2. ServiceAccount

ServiceAccount也是一種特殊beaer token,ServiceAccount在Kubernetes中是一種資源,建立一個ServiceAccount資源以後默認會建立一個Secret資源,而Secret資源中就包含了一個JWT格式的Token字段,以Bearer Token的方式請求到Kube-APIServer,Kube-APIServer解析token中的部分user信息,以及validate如下ServiceAccount是否存在便可進行認證檢查。這種方式即以前提到的「兩種用戶」中常見的集羣內認證方式,ServiceAccount,主要用於集羣內資源訪問APIServer,但不限於集羣內。

3. BootstrapToken

此項開關在Kubernetes v1.18版本中才爲stable版本,此類Token是專門用來引導集羣安裝使用的,須要配合controller-manager的TokenCleaner。

目前TKE默認開啓此配置。

4. OpenID Connect Tokens

OIDCToken的認證方式是結合OAuth2向身份提供方獲取ID Token來訪問APIServer。

如須要開啓此項功能,須要在APIServer的啓動參數中指定oidc的配置參數,例如--oidc-issuer-url指定oidc身份提供方的地址,--oidc-client-id指定身份提供方側的帳戶ID,--oidc-username-claim身份提供方的用戶名。

具體可參考Kubernetes官方文檔,目前公有云TKE沒有使用此參數對接騰訊雲帳戶,由於涉及用戶須要主動登陸受權後纔可返回Id Token,和當前官網交互衝突,能夠在後續CLI工具中實現。

5. Webhook Token Server

Webhook Token是一種hook的方式來校驗是否定證經過。

APIServer啓動參數--authentication-token-webhook-config-file--authentication-token-webhook-cache-ttl來分別指定Webhook地址以及token的cache ttl。

若APiServer開啓此方式進行認證校驗,則在接受到用戶的Request以後,會包裝Bearer Token成一個TokenReview發送給WebHookServer,Server端接收到以後會進行校驗,並返回TokenReview接口,在status字段中進行反饋是否經過校驗經過和user.Info信息。

總結

以上即爲Kubernetes APIServer認證的幾種方式,TKE在每種認證方式都有支持。供用戶靈活使用。

目前TKE正在推使用x509客戶端證書方式來進行認證管理,以方便進行對接子帳戶的建立、受權管理、更新。

Kubernetes受權

Kubernetes的受權模式支持一下幾種,和認證同樣,參考開始說的RequestInfo context,可知用戶Reqeust的context除了認證須要的userInfo,還有一些其餘的字段例如Verb、APIGroup、APIVersion、Resource、Namespaces、Path……

受權就是判斷user是否擁有操做資源的相應權限。

Kubernetes支持AlwaysAllow、AlwaysDeny、Node、ABAC、RBAC、Webhook受權Mode,和認證同樣,只要有一種鑑權模塊經過,便可返回資源。

在這裏重點介紹下面兩種方式

RBAC

RBAC(Role-Based Access Control),Kubernetes提供ClusterRole、Role資源,分別對應集羣維度、Namespace維度角色權限管控,用戶能夠自定義相應的ClusterRole、Role資源,綁定到已經認證的User之上。

以下tke:pod-reader ClusterRole,定義了該角色能夠訪問core apigroup下面對pods資源的get/watch/list操做

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: tke:pod-reader
rules:
- apiGroups: [""] # "" 指定核心 API 組
  resources: ["pods"]
  verbs: ["get", "watch", "list"]
  
---
apiVersion: rbac.authorization.k8s.io/v1
# 此角色綁定使得用戶 "alex" 可以讀取 "default" 命名空間中的 Pods
kind: ClusterRoleBinding
metadata:
  name: alex-ClusterRole
subjects:
- kind: User
  name: alex
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: tke:pod-reader # 這裏的名稱必須與你想要綁定的 Role 或 ClusterRole 名稱一致
  apiGroup: rbac.authorization.k8s.io

經過以上的yaml配置,經過認證模塊到達受權模塊的requestInfo中userInfo信息是alex的請求,在受權模塊中走到RBAC受權模塊時,則會進行查詢集羣的ClusterRole/ClusterRoleBinding信息。進行判斷是否擁有context相應操做的權限。

TKE的對接子帳戶的權限受權策略就是使用的Kubernetes原生的RBAC進行對子帳戶資源訪問控制,這樣符合原生,符合有K8s使用習慣的用戶。

WebHook

Webhook模式是一種基於HTTP回調的方式,經過配置好受權webhook server地址。當APIServer接收到request的時候,會進行包裝SubjectAccessReview請求Webhook Server,Webhook Server會進行判斷是否能夠訪問,而後返回allow信息。

如下是kubernetes社區一個例子,以供參考。

{
  "apiVersion": "authorization.k8s.io/v1beta1",
  "kind": "SubjectAccessReview",
  "spec": {
    "resourceAttributes": {
      "namespace": "kittensandponies",
      "verb": "get",
      "group": "unicorn.example.org",
      "resource": "pods"
    },
    "user": "alex",
    "group": [
      "group1",
      "group2"
    ]
  }
}
{
  "apiVersion": "authorization.k8s.io/v1beta1",
  "kind": "SubjectAccessReview",
  "status": {
    "allowed": true
  }
}

目前TKE沒有考慮使用Webhook的模式,可是Webhook模式提供了強大的靈活性,好比對接CAM,實現K8s權限對接到平臺側,可是也有必定的風險和挑戰,好比依賴CAM的穩定性;請求延遲、緩存/TTL的配置;CAM action配置與K8s權限對應關係。此項受權模式仍然在考慮中,有需求的用戶能夠反饋。

准入控制

什麼是admission controller?

In a nutshell, Kubernetes admission controllers are plugins that govern and enforce how the cluster is used.

Admission controllers是K8s的插件,用來管理和強制用戶如何來操做集羣。

Admission controllers主要分爲兩個phase,一個是mutating,一個是validating。這兩個階段都是在authn&authz以後的,mutating作的變動准入,就是會對request的resource,進行轉換,好比填充默認的requestLimit?而validating admission的意思就是驗證准入,好比校驗Pod副本數必須大於2。

API Server請求鏈路:

ValidatingAdmissionWebhooks and MutatingAdmissionWebhooks, both of which are in beta status as of Kubernetes 1.13.

k8s支持30多種admission control 插件 ,而其中有兩個具備強大的靈活性,即ValidatingAdmissionWebhooksMutatingAdmissionWebhooks,這兩種控制變換和准入以Webhook的方式提供給用戶使用,大大提升了靈活性,用戶能夠在集羣建立自定義的AdmissionWebhookServer進行調整准入策略。

TKE中1.10及以上版本也默認開啓了ValidatingAdmissionWebhooksMutatingAdmissionWebhooks

瞭解更多Admission Controller參考這裏

kubernetes權限對接子帳戶

TKE權限實現對接子帳戶主要的方案是:x509客戶端認證+Kubernetes RBAC受權

認證

每一個子帳戶都擁有單獨的屬於本身的客戶端證書,用於訪問KubernetesAPIServer。

  • 用戶在使用TKE的新受權模式時,不一樣子帳戶在獲取集羣訪問憑證時,即前臺訪問集羣詳情頁或調用DescribeClusterKubeconfig時,會展現子帳戶本身的x509客戶端證書,此證書是每一個集羣的自簽名CA簽發的。
  • 該用戶在控制檯訪問Kubernetes資源時,後臺默認使用此子帳戶的客戶端證書去訪問用戶Kubernetes APIServer。
  • 支持子帳戶更新本身的證書。
  • 支持主帳戶或集羣tke:admin權限的帳戶進行查看更新其餘子帳戶證書。

受權

TKE控制檯經過Kubernetes原生的RBAC受權策略,對子帳戶提供細粒度的Kubernetes資源粒度權限控制。

  • 提供受權管理頁,讓主帳號集羣建立者默認擁有管理員權限,能夠對其餘擁有此集羣DescribeCluster Action權限的子帳戶進行權限管理。
  • 並提供預設的ClusterRole。

    • 全部命名空間維度:

      • 管理員(tke:admin):對全部命名空間下資源的讀寫權限, 對集羣節點,存儲卷,命名空間,配額的讀寫權限, 可子帳號和權限的讀寫權限
      • 運維人員(tke:ops):對全部命名空間下控制檯可見資源的讀寫權限, 對集羣節點,存儲卷,命名空間,配額的讀寫權限
      • 開發人員(tke:dev):對全部命名空間下控制檯可見資源的讀寫權限
      • 受限人員(tke:ro):對全部命名空間下控制檯可見資源的只讀權限
      • 用戶自定義ClusterRole
    • 指定命名空間維度:

      • 開發人員(tke:ns:dev): 對所選命名空間下控制檯可見資源的讀寫權限, 須要選擇指定命名空間。
      • 只讀用戶(tke:ns:ro):對所選命名空間下控制檯可見資源的只讀權限, 須要選擇指定命名空間。

  • 全部預設的ClusterRole都將帶有固定label:cloud.tencent.com/tke-rbac-generated: "true"
  • 全部預設的ClusterRoleBinding都帶有固定的annotations:cloud.tencent.com/tke-account-nickname: yournickname,及label:cloud.tencent.com/tke-account: "yourUIN"

更多

固然,除了TKE控制檯提供的預設受權策略,管理員也能夠經過kubectl操做ClusterRole/Role來實現自定義角色的靈活配置細粒度權限,以及操做ClusterRoleBinding/RoleBinding進行權限綁定,綁定到任意的角色權限之上。

例如你想設置CAM側用戶組爲productA產品的pod-dev的用戶權限只可以get/list/watch product-a命名空間下的pods資源,則你能夠這樣操做:

  • 建立自定義ClusterRole/Role:dev-pod-reader,yaml實例以下,文件名爲developer.yaml

    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole # 這裏使用ClusterRole能夠複用給產品其餘命名空間
    metadata:
      name: pod-dev # pod-dev此角色爲只能讀取pod的開發
    rules:
    - apiGroups: [""] # "" 指定核心 API 組
      resources: ["pods"]
      verbs: ["get", "watch", "list"]
  • 使用kubectl或者經過TKE控制檯YAML建立資源建立上述Role
  • 綁定dev用戶組下的dev一、dev二、dev3用戶,綁定自定義權限pod-dev到product-a命名空間下
  • 今後dev1,dev2,dev3用戶則只能使用get/list/watch訪問product-a下的pods資源

$ kubectl --kubeconfig=./dev.kubeconfig get pods
Error from server (Forbidden): pods is forbidden: User "10000001xxxx-1592395536" cannot list resource "pods" in API group "" in the namespace "default"
$ kubectl --kubeconfig=./dev.kubeconfig get pods -n product-a
No resources found.

### 參考

1. [kubernetes認證介紹](https://kubernetes.io/docs/reference/access-authn-authz/authentication/)
2. [kubernetes受權介紹](https://kubernetes.io/docs/reference/access-authn-authz/authorization/)
3. [kubernetesRBAC介紹](https://kubernetes.io/docs/reference/access-authn-authz/rbac/)
>【騰訊雲原生】雲說新品、雲研新術、雲遊新活、雲賞資訊,掃碼關注同名公衆號,及時獲取更多幹貨!!
相關文章
相關標籤/搜索