Kubernetes中的用戶與身份認證授權
Kubernetes 中的用戶與身份認證授權
原文地址:認識Kubernetes中的用戶與身份認證授權
在安裝集群的時候我們在 master 節點上生成了一堆證書、token,還在 kubelet 的配置中用到了 bootstrap token,安裝各種應用時,為了能夠與 API server 通信創建了各種 service account,在 Dashboard 中使用了 kubeconfig 或 token 登陸,那麼這些都屬於什麼認證方式?如何區分用戶的?我特地翻譯了下這篇官方文檔,想你看了之後你將找到答案。
重點查看 bearer token 和 HTTP 認證中的 token 使用,我們已經有所應用,如 使用kubeconfig或token進行用戶身份認證。
本文已歸檔到 kubernetes-handbook 中,同時加入到了 Kubernetes 中文文檔翻譯計劃 中,歡迎大家斧正。
認識 Kubernetes 中的用戶
Kubernetes 集群中包含兩類用戶:一類是由 Kubernetes 管理的 service account,另一類是普通用戶。
普通用戶被假定為由外部獨立服務管理。管理員分發私鑰,用戶存儲(如 Keystone 或 Google 帳戶),甚至包含用戶名和密碼列表的文件。在這方面,Kubernetes 沒有代表普通用戶帳戶的對象。無法通過 API 調用的方式向集群中添加普通用戶。
相反,service account 是由 Kubernetes API 管理的帳戶。它們都綁定到了特定的 namespace,並由 API server 自動創建,或者通過 API 調用手動創建。Service account 作為憑證而存儲在 Secret
,這些憑證同時被掛載到 pod 中,從而允許 pod 與 kubernetes API 之間的調用。
API 請求被綁定到普通用戶或 serivce account 上,或者作為匿名請求對待。這意味著集群內部或外部的每個進程,無論從在工作站上輸入 kubectl
的人類用戶到節點上的 kubelet,到控制平面的成員,都必須在向 API Server 發出請求時進行身份驗證,或者被視為匿名用戶。
認證策略
Kubernetes 使用客戶端證書、bearer token、身份驗證代理或者 HTTP 基本身份驗證等身份認證插件來對 API 請求進行身份驗證。由於是向 API server 發送 HTTP 請求,插件會嘗試將以下屬性關聯到請求上:
- 用戶名:標識最終用戶的字元串。常用值可能是
kube-admin
或jane@example.com
。 - UID:標識最終用戶的字元串,比用戶名更加一致且唯一。
- 組:一組將用戶用常用組關聯的字元串。
- 其它欄位:包含其他授權人信息的字元串列表的映射。
所有的值對於認證系統都是不透明得,只有 授權人 才能解釋這些值的重要含義。
您可以一次性啟用多種身份驗證方式。通常使用至少以下兩種認證方式:
- 服務帳戶的 service account token
- 至少一種其他的用戶認證的方式
當啟用了多個認證模塊時,第一個認證模塊成功認證後將短路請求,不會進行第二個模塊的認證。API server 不會保證認證的順序。
system:authenticated
組包含在所有已驗證用戶的組列表中。
與其他身份驗證協議(LDAP、SAML、Kerberos、x509 方案等)的集成可以使用 身份驗證代理 或 身份驗證 webhook 來實現。
X509 客戶端證書
通過將 --client-ca-file=SOMEFILE
選項傳遞給 API server 來啟用客戶端證書認證。引用的文件必須包含一個或多個證書頒發機構,用於驗證呈現給 API server 的客戶端證書。如果客戶端證書已提交並驗證,則使用主題的公用名稱作為請求的用戶名。從 Kubernetes 1.4開始,客戶端證書還可以使用證書的組織欄位來指示用戶的組成員身份。要為用戶包含多個組成員身份,請在證書中包含多個組織欄位。
例如,試用 openssl
命令工具生成認證簽名請求:
openssl req -new -key jbeda.pem -out jbeda-csr.pem -subj "/CN=jbeda/O=app1/O=app2"n
這將為一個用戶名為」jbeda「的 CSR,屬於兩個組「app1」和「app2」。
如何生成客戶端證書請參閱 附錄。
靜態 Token 文件
當在命令行上指定 --token-auth-file=SOMEFILE
選項時,API server 從文件讀取 bearer token。目前,token 會無限期地持續下去,並且不重新啟動 API server 的話就無法更改令牌列表。
token 文件是一個 csv 文件,每航至少包含三列:token、用戶名、用戶 uid,其次是可選的祖名。請注意,如果您有多個組,則該列必須使用雙引號。
token,user,uid,"group1,group2,group3"n
在請求中放置 Bearer Token
當使用來自 http 客戶端的 bearer token 時,API server 期望 Authorization
header 中包含 Bearer token
的值。Bearer token 必須是一個字元串序列,只需使用 HTTP 的編碼和引用功能就可以將其放入到 HTTP header 中。例如:如果 bearer token 是 31ada4fd-adec-460c-809a-9e56ceb75269
,那麼它將出現在 HTTP header 中,如下所示:
Authorization: Bearer 31ada4fd-adec-460c-809a-9e56ceb75269n
Bootstrap Token
該功能仍處於 alpha 版本。
為了簡化新集群的初始化引導過程,Kubernetes 中包含了一個名為 Bootstrap Token 的動態管理的 bearer token。這些 token 使用 Secret 存儲在 kube-system
namespace 中,在那裡它們可以被動態管理和創建。Controller Manager 中包含了一個 TokenCleaner 控制器,用於在 bootstrap token 過期時刪除將其刪除。
這些 token 的形式是 [a-z0-9]{6}.[a-z0-9]{16}
。第一部分是 Token ID,第二部分是 Token Secret。您在 HTTP header 中指定的 token 如下所示:
Authorization: Bearer 781292.db7bc3a58fc5f07en
在 API server 的啟動參數中加上 --experimental-bootstrap-token-auth
標誌以啟用 Bootstrap Token Authenticator。您必須通過 Controller Manager 上的 --controllers
標誌啟用 TokenCleaner 控制器,如 --controllers=*,tokencleaner
。如果您使用它來引導集群, kubeadm
會為您完成。
認證者認證為 system:bootstrap:<Token ID>
。被包含在 system:bootstrappers
組中。命名和組是有意限制用戶使用過去的 bootstap token。可以使用用戶名和組(kubeadm
使用)來制定適當的授權策略以支持引導集群。
有關 Bootstrap Token 身份驗證器和控制器的更深入的文檔,以及如何使用 kubeadm
管理這些令牌,請參閱 Bootstrap Token。
靜態密碼文件
通過將 --basic-auth-file=SOMEFILE
選項傳遞給 API server 來啟用基本身份驗證。目前,基本身份驗證憑證將無限期地保留,並且密碼在不重新啟動API伺服器的情況下無法更改。請注意,為了方便起見,目前支持基本身份驗證,而上述模式更安全更容易使用。
基本身份認證是一個 csv 文件,至少包含3列:密碼、用戶名和用戶 ID。在 Kubernetes 1.6 和更高版本中,可以指定包含以逗號分隔的組名稱的可選第四列。如果您有多個組,則必須將第四列值用雙引號(「)括起來,請參閱以下示例:
password,user,uid,"group1,group2,group3"n
當使用來自 HTTP 客戶端的基本身份驗證時,API server 需要Authorization
header 中包含 Basic BASE64ENCODED(USER:PASSWORD)
的值。
Service Account Token
Service account 是使用簽名的 bearer token 來驗證請求的額自動啟用的驗證器。該插件包括兩個可選的標誌:
--service-account-key-file
一個包含簽名 bearer token 的 PEM 編碼文件。如果為指定,將使用 API server 的 TLS 私鑰。--service-account-lookup
如果啟用,從 API 中刪除掉的 token 將被撤銷。
Service account 通常 API server 自動創建,並通過 ServiceAccount
注入控制器 關聯到集群中運行的 Pod 上。Bearer token 掛載到 pod 中眾所周知的位置,並允許集群進程與 API server 通信。 帳戶可以使用 PodSpec
的 serviceAccountName
欄位顯式地與Pod關聯。
注意: serviceAccountName
通常被省略,因為這會自動生成。
apiVersion: apps/v1beta2n kind: Deploymentn metadata:n name: nginx-deploymentn namespace: defaultn spec:n replicas: 3n template:n metadata:n # ...n spec:n containers:n - name: nginxn image: nginx:1.7.9n serviceAccountName: bob-the-botn
Service account bearer token 在集群外使用也是完全有效的,並且可以用於為希望與 Kubernetes 通信的長期運行作業創建身份。要手動創建 service account,只需要使用 kubectl create serviceaccount (NAME)
命令。這將在當前的 namespace 和相關連的 secret 中創建一個 service account。
$ kubectl create serviceaccount jenkinsn serviceaccount "jenkins" createdn $ kubectl get serviceaccounts jenkins -o yamln apiVersion: v1n kind: ServiceAccountn metadata:n # ...n secrets:n - name: jenkins-token-1yvwgn
創建出的 secret 中擁有 API server 的公共 CA 和前面的餓 JSON Web Token(JWT)。
$ kubectl get secret jenkins-token-1yvwg -o yamln apiVersion: v1n data:n ca.crt: (APISERVERS CA BASE64 ENCODED)n namespace: ZGVmYXVsdA==n token: (BEARER TOKEN BASE64 ENCODED)n kind: Secretn metadata:n # ...n type: kubernetes.io/service-account-tokenn
注意:所有值是基於 base64 編碼的,因為 secret 總是基於 base64 編碼。
經過簽名的 JWT 可以用作 bearer token 與給定的 service account 進行身份驗證。請參閱 上面 關於如何在請求中放置 bearer token。通常情況下,這些 secret 被掛載到 pod 中,以便對集群內的 API server 進行訪問,但也可以從集群外訪問。
Service account 驗證時用戶名 system:serviceaccount:(NAMESPACE):(SERVICEACCOUNT)
,被指定到組 system:serviceaccounts
和 system:serviceaccounts:(NAMESPACE)
。
注意:由於 service account 的 token 存儲在 secret 中,所以具有對這些 secret 的讀取許可權的任何用戶都可以作為 service account 進行身份驗證。授予 service account 許可權和讀取 secret 功能時要謹慎。
OpenID Connect Token
OpenID Connect 是由 OAuth2 供應商提供的 OAuth2,特別是 Azure Active Directory、Salesforce 和 Google。對 OAuth2 協議的主要擴展是返回一個稱作 ID Token 的格外欄位。該 token 是一個 JSON Web Token (JWT) ,有伺服器簽名,具有眾所周知的欄位,如用戶的電子郵件。
為了識別用戶,認證者使用 OAuth2 token 響應 中的 id_token
(而不是 access_token
)作為 bearer token。請參閱 上面 的關於將 token 置於請求中。
- 登陸到您的身份提供商
- 您的身份提供商將為您提供一個
access_token
,一個id_token
和一個refresh_token
- 當使用
kubectl
時,使用--token
標誌和id_token
,或者直接加入到您的kubeconfig
文件中 kubectl
在調用 API server 時將id_token
置於 HTTP header 中- API server 將通過檢查配置中指定的證書來確保 JWT 簽名有效
- 檢查以確保
id_token
沒有過期 - 確保用戶已授權
- 授權 API server 後向
kubectl
kubectl
向用戶提供反饋
由於所有需要驗證您身份的數據都在 id_token
中,Kubernetes 不需要向身份提供商 「phone home」。在每個請求都是無狀態的模型中,這為認證提供了非常可擴展的解決方案。它確實提供了一些挑戰:
- Kubernetes 沒有 」web 介面「 來出發驗證進程。沒有瀏覽器或界面來收集憑據,這就是為什麼您需要首先認證您的身份提供商。
id_token
無法撤銷,就像一個證書,所以它應該是短暫的(只有幾分鐘),所以每隔幾分鐘就得到一個新的令牌是非常煩人的。- 沒有使用
kubectl proxy
命令或注入id_token
的反向代理,無法簡單地對 Kubernetes dashboard 進行身份驗證。
配置 API Server
要啟用該插件,需要在 API server 中配置如下標誌:
參數描述示例是否必需--oidc-issuer-url
允許 API server 發現公共簽名密鑰的提供者的 URL。只接受使用 https://
的方案。通常是提供商的 URL 地址,不包含路徑,例如「https://accounts.google.com」 或者 「https://login.salesforce.com」。這個 URL 應該指向下面的 .well-known/openid-configuration如果發現 URL 是 https://accounts.google.com/.well-known/openid-configuration
,值應該是https://accounts.google.com
是--oidc-client-id
所有的 token 必須為其頒發的客戶端 IDkubernetes是--oidc-username-claim
JWT聲明使用的用戶名。默認情況下,sub
是最終用戶的唯一標識符。管理員可以選擇其他聲明,如email
或 name
,具體取決於他們的提供者。不過,email
以外的其他聲明將以發行者的 URL 作為前綴,以防止與其他插件命名衝突。sub否--oidc-groups-claim
JWT聲明試用的用戶組。如果生命存在,它必須是一個字元串數組。groups否--oidc-ca-file
用來簽名您的身份提供商的網路 CA 證書的路徑。默認為主機的跟 CA。/etc/kubernetes/ssl/kc-ca.pem
否
如果為 --oidc-username-claim
選擇了除 email
以外的其他聲明,則該值將以 --oidc-issuer-url
作為前綴,以防止與現有 Kubernetes 名稱(例如 system:users
)衝突。例如,如果提供商網址是 https://accounts.google.com,而用戶名聲明映射到 jane
,則插件會將用戶身份驗證為:
https://accounts.google.com#janen
重要的是,API server 不是 OAuth2 客戶端,而只能配置為信任單個發行者。這允許使用 Google 等公共提供者,而不必信任第三方發行的憑據。希望利用多個 OAuth 客戶端的管理員應該探索支持 azp
(授權方)聲明的提供者,這是允許一個客戶端代表另一個客戶端發放令牌的機制。
Kubernetes不提供 OpenID Connect 身份提供商。您可以使用現有的公共 OpenID Connect 標識提供程序(例如Google 或 其他)。或者,您可以運行自己的身份提供程序,例如 CoreOS dex、Keycloak、CloudFoundry UAA 或 Tremolo Security 的 OpenUnison。
對於身份提供商能夠適用於 Kubernetes,必須滿足如下條件:Kubernetes it must:
- 支持 OpenID connect 發現;不必是全部。
- 使用非過時密碼在TLS中運行
- 擁有 CA 簽名證書(即使 CA 不是商業 CA 或自簽名)
有關上述要求3的說明,需要 CA 簽名證書。如果您部署自己的身份提供商(而不是像 Google 或 Microsoft 之類的雲提供商),則必須讓您的身份提供商的 Web 伺服器證書由 CA 標誌設置為 TRUE 的證書籤名,即使是自簽名的。這是由於 GoLang 的 TLS 客戶端實現對證書驗證的標準非常嚴格。如果您沒有 CA
,可以使用 CoreOS
團隊的 這個腳本 創建一個簡單的 CA 和一個簽名的證書和密鑰對。
或者你可以使用 這個類似的腳本 來生成更長壽命和更長的 SHA256 證書密鑰。
針對特定系統的安裝說明:
- UAA
- Dex
- OpenUnison
使用 kubectl
選項 1 - OIDC 身份驗證器
第一個選項是使用 oidc
身份驗證器。此身份驗證程序將您的 id_token
、refresh_token
和您的 OIDC client_secret
自動刷新您的 token。一旦您對身份提供者進行了身份驗證:
kubectl config set-credentials USER_NAME n --auth-provider=oidc n --auth-provider-arg=idp-issuer-url=( issuer url ) n --auth-provider-arg=client-id=( your client id ) n --auth-provider-arg=client-secret=( your client secret ) n --auth-provider-arg=refresh-token=( your refresh token ) n --auth-provider-arg=idp-certificate-authority=( path to your ca certificate ) n --auth-provider-arg=id-token=( your id_token ) n --auth-provider-arg=extra-scopes=( comma separated list of scopes to add to "openid email profile", optional )n
例如,在向身份提供者進行身份驗證之後運行以下命令:
kubectl config set-credentials mmosley n --auth-provider=oidc n --auth-provider-arg=idp-issuer-url=https://oidcidp.tremolo.lan:8443/auth/idp/OidcIdP n --auth-provider-arg=client-id=kubernetes n --auth-provider-arg=client-secret=1db158f6-177d-4d9c-8a8b-d36869918ec5 n --auth-provider-arg=refresh-token=q1bKLFOyUiosTfawzA93TzZIDzH2TNa2SMm0zEiPKTUwME6BkEo6Sql5yUWVBSWpKUGphaWpxSVAfekBOZbBhaEW+VlFUeVRGcluyVF5JT4+haZmPsluFoFu5XkpXk5BXqHega4GAXlF+ma+vmYpFcHe5eZR+slBFpZKtQA= n --auth-provider-arg=idp-certificate-authority=/root/ca.pem n --auth-provider-arg=extra-scopes=groups n --auth-provider-arg=id-token=eyJraWQiOiJDTj1vaWRjaWRwLnRyZW1vbG8ubGFuLCBPVT1EZW1vLCBPPVRybWVvbG8gU2VjdXJpdHksIEw9QXJsaW5ndG9uLCBTVD1WaXJnaW5pYSwgQz1VUy1DTj1rdWJlLWNhLTEyMDIxNDc5MjEwMzYwNzMyMTUyIiwiYWxnIjoiUlMyNTYifQ.eyJpc3MiOiJodHRwczovL29pZGNpZHAudHJlbW9sby5sYW46ODQ0My9hdXRoL2lkcC9PaWRjSWRQIiwiYXVkIjoia3ViZXJuZXRlcyIsImV4cCI6MTQ4MzU0OTUxMSwianRpIjoiMm96US15TXdFcHV4WDlHZUhQdy1hZyIsImlhdCI6MTQ4MzU0OTQ1MSwibmJmIjoxNDgzNTQ5MzMxLCJzdWIiOiI0YWViMzdiYS1iNjQ1LTQ4ZmQtYWIzMC0xYTAxZWU0MWUyMTgifQ.w6p4J_6qQ1HzTG9nrEOrubxIMb9K5hzcMPxc9IxPx2K4xO9l-oFiUw93daH3m5pluP6K7eOE6txBuRVfEcpJSwlelsOsW8gb8VJcnzMS9EnZpeA0tW_p-mnkFc3VcfyXuhe5R3G7aa5d8uHv70yJ9Y3-UhjiN9EhpMdfPAoEB9fYKKkJRzF7utTTIPGrSaSU6d2pcpfYKaxIwePzEkT4DfcQthoZdy9ucNvvLoi1DIC-UocFD8HLs8LYKEqSxQvOcvnThbObJ9af71EwmuE21fO5KzMW20KtAeget1gnldOosPtz1G5EwvaQ401-RPQzPGMVBld0_zMCAwZttJ4knwn
將產生下面的配置:
users:n - name: mmosleyn user:n auth-provider:n config:n client-id: kubernetesn client-secret: 1db158f6-177d-4d9c-8a8b-d36869918ec5n extra-scopes: groupsn id-token: eyJraWQiOiJDTj1vaWRjaWRwLnRyZW1vbG8ubGFuLCBPVT1EZW1vLCBPPVRybWVvbG8gU2VjdXJpdHksIEw9QXJsaW5ndG9uLCBTVD1WaXJnaW5pYSwgQz1VUy1DTj1rdWJlLWNhLTEyMDIxNDc5MjEwMzYwNzMyMTUyIiwiYWxnIjoiUlMyNTYifQ.eyJpc3MiOiJodHRwczovL29pZGNpZHAudHJlbW9sby5sYW46ODQ0My9hdXRoL2lkcC9PaWRjSWRQIiwiYXVkIjoia3ViZXJuZXRlcyIsImV4cCI6MTQ4MzU0OTUxMSwianRpIjoiMm96US15TXdFcHV4WDlHZUhQdy1hZyIsImlhdCI6MTQ4MzU0OTQ1MSwibmJmIjoxNDgzNTQ5MzMxLCJzdWIiOiI0YWViMzdiYS1iNjQ1LTQ4ZmQtYWIzMC0xYTAxZWU0MWUyMTgifQ.w6p4J_6qQ1HzTG9nrEOrubxIMb9K5hzcMPxc9IxPx2K4xO9l-oFiUw93daH3m5pluP6K7eOE6txBuRVfEcpJSwlelsOsW8gb8VJcnzMS9EnZpeA0tW_p-mnkFc3VcfyXuhe5R3G7aa5d8uHv70yJ9Y3-UhjiN9EhpMdfPAoEB9fYKKkJRzF7utTTIPGrSaSU6d2pcpfYKaxIwePzEkT4DfcQthoZdy9ucNvvLoi1DIC-UocFD8HLs8LYKEqSxQvOcvnThbObJ9af71EwmuE21fO5KzMW20KtAeget1gnldOosPtz1G5EwvaQ401-RPQzPGMVBld0_zMCAwZttJ4knwn idp-certificate-authority: /root/ca.pemn idp-issuer-url: https://oidcidp.tremolo.lan:8443/auth/idp/OidcIdPn refresh-token: q1bKLFOyUiosTfawzA93TzZIDzH2TNa2SMm0zEiPKTUwME6BkEo6Sql5yUWVBSWpKUGphaWpxSVAfekBOZbBhaEW+VlFUeVRGcluyVF5JT4+haZmPsluFoFu5XkpXk5BXqn name: oidcn
一旦您的 id_token
過期,kubectl
將使用 refresh_token
刷新 id_token
,然後在 kube/.config
文件的client_secret
中存儲 id_token
的值和refresh_token
的新值。
選項 2 - 使用 --token
選項
可以在 kubectl
命令的 --token
選項中傳入 token。簡單的拷貝和複製 id_token
到該選項中:
kubectl --token=eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJodHRwczovL21sYi50cmVtb2xvLmxhbjo4MDQzL2F1dGgvaWRwL29pZGMiLCJhdWQiOiJrdWJlcm5ldGVzIiwiZXhwIjoxNDc0NTk2NjY5LCJqdGkiOiI2RDUzNXoxUEpFNjJOR3QxaWVyYm9RIiwiaWF0IjoxNDc0NTk2MzY5LCJuYmYiOjE0NzQ1OTYyNDksInN1YiI6Im13aW5kdSIsInVzZXJfcm9sZSI6WyJ1c2VycyIsIm5ldy1uYW1lc3BhY2Utdmlld2VyIl0sImVtYWlsIjoibXdpbmR1QG5vbW9yZWplZGkuY29tIn0.f2As579n9VNoaKzoF-dOQGmXkFKf1FMyNV0-va_B63jn-_n9LGSCca_6IVMP8pO-Zb4KvRqGyTP0r3HkHxYy5c81AnIh8ijarruczl-TK_yF5akjSTHFZD-0gRzlevBDiH8Q79NAr-ky0P4iIXS8lY9Vnjch5MF74Zx0c3alKJHJUnnpjIACByfF2SCaYzbWFMUNat-K1PaUk5-ujMBG7yYnr95xD-63n8CO8teGUAAEMx6zRjzfhnhbzX-ajwZLGwGUBT4WqjMs70-6a7_8gZmLZb2az1cZynkFRj2BaCkVT3A2RrjeEwZEtGXlMqKJ1_I2ulrOVsYx01_yD35-rw get nodesn
Webhook Token 認證
Webhook 認證是用來認證 bearer token 的 hook。
--authentication-token-webhook-config-file
是一個用來描述如何訪問遠程 webhook 服務的 kubeconfig 文件。--authentication-token-webhook-cache-ttl
緩存身份驗證策略的時間。默認為兩分鐘。
配置文件使用 kubeconfig 文件格式。文件中的 」user「 指的是 API server 的 webhook,」clusters「 是指遠程服務。見下面的例子:
# clusters refers to the remote service.n clusters:n - name: name-of-remote-authn-servicen cluster:n certificate-authority: /path/to/ca.pem # CA for verifying the remote service.n server: https://authn.example.com/authenticate # URL of remote service to query. Must use https.n n # users refers to the API servers webhook configuration.n users:n - name: name-of-api-servern user:n client-certificate: /path/to/cert.pem # cert for the webhook plugin to usen client-key: /path/to/key.pem # key matching the certn n # kubeconfig files require a context. Provide one for the API server.n current-context: webhookn contexts:n - context:n cluster: name-of-remote-authn-servicen user: name-of-api-severn name: webhookn
當客戶端嘗試使用 bearer token 與API server 進行認證是,如 上 論述,認證 webhook 用飽含該 token 的對象查詢遠程服務。Kubernetes 不會挑戰缺少該 header 的請求。
請注意,webhook API對象與其他 Kubernetes API 對象具有相同的 版本控制兼容性規則。實現者應該意識到 Beta 對象的寬鬆兼容性承諾,並檢查請求的 「apiVersion」 欄位以確保正確的反序列化。此外,API server 必須啟用 authentication.k8s.io/v1beta1
API 擴展組(--runtime config =authentication.k8s.io/v1beta1=true
)。
The request body will be of the following format:
{n "apiVersion": "authentication.k8s.io/v1beta1",n "kind": "TokenReview",n "spec": {n "token": "(BEARERTOKEN)"n }n }n
預計遠程服務將填寫請求的 status
欄位以指示登錄成功。響應主體的 spec
欄位被忽略,可以省略。成功驗證後的 bearer token 將返回:
{n "apiVersion": "authentication.k8s.io/v1beta1",n "kind": "TokenReview",n "status": {n "authenticated": true,n "user": {n "username": "janedoe@example.com",n "uid": "42",n "groups": [n "developers",n "qa"n ],n "extra": {n "extrafield1": [n "extravalue1",n "extravalue2"n ]n }n }n }n }n
未成功的請求將返回:
{n "apiVersion": "authentication.k8s.io/v1beta1",n "kind": "TokenReview",n "status": {n "authenticated": falsen }n }n
HTTP狀態代碼可以用來提供額外的錯誤上下文。
認證代理
可以配置 API server 從請求 header 的值中識別用戶,例如 X-Remote-User
。這樣的設計是用來與請求 header 值的驗證代理結合使用。
--requestheader-username-headers
必需,大小寫敏感。按 header 名稱和順序檢查用戶標識。包含值的第一個 header 將被作為用戶名。--requestheader-group-headers
1.6 以上版本。可選。大小寫敏感。建議為 「X-Remote-Group」。按 header 名稱和順序檢查用戶組。所有指定的 header 中的所有值都將作為組名。--requestheader-extra-headers-prefix
1.6 以上版本。可選,大小寫敏感。建議為 「X-Remote-Extra-」。標題前綴可用於查找有關用戶的額外信息(通常由配置的授權插件使用)。以任何指定的前綴開頭的 header 都會刪除前綴,header 名稱的其餘部分將成為額外的鍵值,而 header 值則是額外的值。
例如下面的配置:
--requestheader-username-headers=X-Remote-Usern --requestheader-group-headers=X-Remote-Groupn --requestheader-extra-headers-prefix=X-Remote-Extra-n
該請求:
GET / HTTP/1.1n X-Remote-User: fidon X-Remote-Group: dogsn X-Remote-Group: dachshundsn X-Remote-Extra-Scopes: openidn X-Remote-Extra-Scopes: profilen
將產生如下的用戶信息:
name: fidon groups:n - dogsn - dachshundsn extra:n scopes:n - openidn - profilen
為了防止 header 欺騙,驗證代理需要在驗證請求 header 之前向 API server 提供有效的客戶端證書,以對照指定的 CA 進行驗證。
--requestheader-client-ca-file
必需。PEM 編碼的證書包。在檢查用戶名的請求 header 之前,必須針對指定文件中的證書頒發機構提交並驗證有效的客戶端證書。--requestheader-allowed-names
可選。Common Name (cn)列表。如果設置了,則在檢查用戶名的請求 header 之前, 必須提供指定列表中 Common Name(cn)的有效客戶端證書。如果為空,則允許使用任何 Common Name。
Keystone 密碼
通過在啟動過程中將 --experimental-keystone-url=<AuthURL>
選項傳遞給 API server 來啟用 Keystone 認證。該插件在 plugin/pkg/auth/authenticator/password/keystone/keystone.go
中實現,目前使用基本身份驗證通過用戶名和密碼驗證用戶。
如果您為 Keystone 伺服器配置了自簽名證書,則在啟動 Kubernetes API server 時可能需要設置 --experimental-keystone-ca-file=SOMEFILE
選項。如果您設置了該選項,Keystone 伺服器的證書將由experimental-keystone-ca-file
中的某個權威機構驗證。否則,證書由主機的根證書頒發機構驗證。
有關如何使用 keystone 來管理項目和用戶的詳細信息,請參閱 Keystone 文檔。請注意,這個插件仍處於試驗階段,正在積極開發之中,並可能在後續版本中進行更改。
請參考 討論、藍圖 和 提出的改變 獲取更多信息。
匿名請求
啟用時,未被其他已配置身份驗證方法拒絕的請求將被視為匿名請求,並給予 system:anonymous
的用戶名和system:unuthenticated
的組名。
例如,在配置了令牌認證和啟用了匿名訪問的伺服器上,提供無效的 bearer token 的請求將收到 401 Unauthorized
錯誤。提供 bearer token 的請求將被視為匿名請求。
在 1.5.1 - 1.5.x 版本中,默認情況下命名訪問是被禁用的,可以通過傳遞 --anonymous-auth=false
選項給 API server 來啟用。
在 1.6+ 版本中,如果使用 AlwaysAllow
以外的授權模式,則默認啟用匿名訪問,並且可以通過將 --anonymous-auth=false
選項傳遞給API伺服器來禁用。從 1.6 開始,ABAC 和 RBAC 授權人需要明確授權 system:annoymous
或 system:unauthenticated
組,因此授予對 *
用戶或 *
組訪問權的傳統策略規則不包括匿名用戶。
用戶模擬
用戶可以通過模擬 header 充當另一個用戶。該請求會覆蓋請求認證的用戶信息。例如,管理員可以使用此功能通過暫時模擬其他用戶並查看請求是否被拒絕來調試授權策略。
模擬請求首先認證為請求用戶,然後切換到模擬的用戶信息。
- 用戶使用他們的憑證和模擬 header 進行 API 調用。
- API server 認證用戶
- API server 確保經過身份驗證的用戶具有模擬許可權。
- 請求用戶的信息被替換為模擬值
- 請求被評估,授權作用於模擬的用戶信息。
以下 HTTP header 可用戶執行模擬請求:
Impersonate-User
:充當的用戶名Impersonate-Group
:作為組名。可以多次使用來設置多個組。可選的,需要 「Impersonate-User」Impersonate-Extra-( extra name )
:用於將額外欄位與用戶關聯的動態 header。可選。需要 「Impersonate-User」
一組示例 header:
Impersonate-User: jane.doe@example.comn Impersonate-Group: developersn Impersonate-Group: adminsn Impersonate-Extra-dn: cn=jane,ou=engineers,dc=example,dc=comn Impersonate-Extra-scopes: viewn Impersonate-Extra-scopes: developmentn
當使用 kubectl
的 --as
標誌來配置 Impersonate-User
header 時,可以使用 --as-group
標誌來配置 Impersonate-Group
header。
$ kubectl drain mynoden Error from server (Forbidden): User "clark" cannot get nodes at the cluster scope. (get nodes mynode)n n $ kubectl drain mynode --as=superman --as-group=system:mastersn node "mynode" cordonedn node "mynode" drainen
為模仿用戶、組或設置額外欄位,模擬用戶必須能夠對正在模擬的屬性的種類(「用戶」,「組」等)執行「模擬」動詞。對於啟用了 RBAC 授權插件的集群,以下 ClusterRole 包含設置用戶和組模擬 header 所需的規則:
apiVersion: rbac.authorization.k8s.io/v1n kind: ClusterRolen metadata:n name: impersonatorn rules:n - apiGroups: [""]n resources: ["users", "groups", "serviceaccounts"]n verbs: ["impersonate"]n
額外的欄位被評估為資源 「userextras」 的子資源。為了允許用戶使用額外欄位 「scope」 的模擬 header,應授予用戶以下角色:
apiVersion: rbac.authorization.k8s.io/v1n kind: ClusterRolen metadata:n name: scopes-impersonatorn # Can set "Impersonate-Extra-scopes" header.n - apiGroups: ["authentication.k8s.io"]n resources: ["userextras/scopes"]n verbs: ["impersonate"]n
模擬 header 的可用值可以通過設置 resourceNames
可以使用的資源來限制。
apiVersion: rbac.authorization.k8s.io/v1n kind: ClusterRolen metadata:n name: limited-impersonatorn rules:n # Can impersonate the user "jane.doe@example.com"n - apiGroups: [""]n resources: ["users"]n verbs: ["impersonate"]n resourceNames: ["jane.doe@example.com"]n n # Can impersonate the groups "developers" and "admins"n - apiGroups: [""]n resources: ["groups"]n - verbs: ["impersonate"]n resourceNames: ["developers","admins"]n n # Can impersonate the extras field "scopes" with the values "view" and "development"n - apiGroups: ["authentication.k8s.io"]n resources: ["userextras/scopes"]n verbs: ["impersonate"]n resourceNames: ["view", "development"]n
附錄
創建證書
使用客戶端證書進行身份驗證時,可以使用現有的部署腳本或通過 easyrsa
或 openssl
手動生成證書。
使用已有的部署腳本
已有的部署腳本 在 cluster/saltbase/salt/generate-cert/make-ca-cert.sh
。
執行該腳本時需要船體兩個參數。第一個參數是 API server 的 IP地址。第二個參數是 IP 形式的主題備用名稱列表: IP:<ip-address>
或 DNS:<dns-name>
。
該腳本將生成三個文件: ca.crt
、server.crt
和 server.key
。
最後,將一下參數添加到 API server 的啟動參數中:
--client-ca-file=/srv/kubernetes/ca.crt
--tls-cert-file=/srv/kubernetes/server.crt
--tls-private-key-file=/srv/kubernetes/server.key
easyrsa
easyrsa 可以用來手動為集群生成證書。
- 下載,解壓,並初始化修補版本的easyrsa3。
curl -L -O https://storage.googleapis.com/kubernetes-release/easy-rsa/easy-rsa.tar.gz tar xzf easy-rsa.tar.gz cd easy-rsa-master/easyrsa3 ./easyrsa init-pki
- 生成 CA(使用
--batch
設置為自動模式。使用--req-cn
設置默認的 CN)
./easyrsa --batch "--req-cn=${MASTER_IP}@`date +%s`" build-ca nopass
- 生成伺服器證書和密鑰。(build-server-full [文件名]:生成一個鍵值對,在本地為客戶端和伺服器簽名。)
./easyrsa --subject-alt-name="IP:${MASTER_IP}" build-server-full server nopass
- 複製
pki/ca.crt
,pki/issued/server.crt
和pki/private/server.key
到您的目錄下。 - 將以下參數添加到 API server 的啟動參數中:
--client-ca-file=/yourdirectory/ca.crt --tls-cert-file=/yourdirectory/server.crt --tls-private-key-file=/yourdirectory/server.key
openssl
openssl 可以用來手動為集群生成證書。
- 生成一個 2048 bit 的 ca.key:
openssl genrsa -out ca.key 2048
- 根據 ca.key 生成一個 ca.crt(使用 -days 設置證書的有效時間):
openssl req -x509 -new -nodes -key ca.key -subj "/CN=${MASTER_IP}" -days 10000 -out ca.crt
- 生成一個 2048 bit 的 server.key:
openssl genrsa -out server.key 2048
- 根據 server.key 生成一個 server.csr:
openssl req -new -key server.key -subj "/CN=${MASTER_IP}" -out server.csr
- 根據 ca.key、ca.crt 和 server.csr 生成 server.crt:
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 10000
- 查看證書:
openssl x509 -noout -text -in ./server.crt
最後,不要忘了向 API server 的啟動參數中增加配置。
認證 API
您可以使用 certificates.k8s.io
API將 x509 證書配置為用於身份驗證,如 此處 所述。
官方文檔地址:https://kubernetes.io/docs/admin/authentication/
譯者:Jimmy Song
推薦閱讀:
TAG:Kubernetes |