您好,登錄后才能下訂單哦!
這篇文章主要介紹kubernetes API Server權限管理的示例分析,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!
API Server權限控制分為三種:Authentication(身份認證)、Authorization(授權)、AdmissionControl(準入控制)。
當客戶端向Kubernetes非只讀端口發起API請求時,Kubernetes通過三種方式來認證用戶的合法性。kubernetes中,驗證用戶是否有權限操作api的方式有三種:證書認證,token認證,基本信息認證。
證書認證
設置apiserver的啟動參數:--client_ca_file=SOMEFILE ,這個被引用的文件中包含的驗證client的證書,如果被驗證通過,那么這個驗證記錄中的主體對象將會作為請求的username。
Token認證
設置apiserver的啟動參數:--token_auth_file=SOMEFILE。 token file的格式包含三列:token,username,userid。當使用token作為驗證方式時,在對apiserver的http請求中,增加 一個Header字段:Authorization ,將它的值設置為:Bearer SOMETOKEN。
基本信息認證
設置apiserver的啟動參數:--basic_auth_file=SOMEFILE,如果更改了文件中的密碼,只有重新啟動apiserver使 其重新生效。其文件的基本格式包含三列:passwork,username,userid。當使用此作為認證方式時,在對apiserver的http 請求中,增加一個Header字段:Authorization,將它的值設置為: Basic BASE64ENCODEDUSER:PASSWORD。
在Kubernetes中,認證和授權是分開的,而且授權發生在認證完成之后,認證過程是檢驗發起API請求的用戶是不是他所聲稱的那個人。而授權過程則 判斷此用戶是否有執行該API請求的權限,因此授權是以認證的結果作為基礎的。Kubernetes授權模塊應用于所有對APIServer的HTTP訪 問請求(只讀端口除外),訪問只讀端口不需要認證和授權過程。APIServer啟動時默認將authorization_mode設置為 AlwaysAllow模式,即永遠允許。
Kubernetes授權模塊檢查每個HTTP請求并提取請求上下文中的所需屬性(例如:user,resource kind,namespace)與訪問控制規則進行比較。任何一個API請求在被處理前都需要通過一個或多個訪問控制規則的驗證。
目前Kubernetes支持并實現了以下的授權模式(authorization_mode),這些授權模式可以通過在apiserver啟動時傳入參數進行選擇。
--authorization_mode=AlwaysDeny
--authorization_mode=AlwaysAllow
--authorization_mode=ABAC
AlwaysDeny 模式屏蔽所有的請求(一般用于測試)。AlwaysAllow模式允許所有請求,默認apiserver啟動時采用的便是AlwaysAllow模式)。 ABAC(Attribute-Based Access Control,即基于屬性的訪問控制)模式則允許用戶自定義授權訪問控制規則。
ABAC模式:
一個API請求中有4個屬性被用于用戶授權過程:
UserName:String類型,用于標識發起請求的用戶。如果不進行認證、授權操作,則該字符串為空。
ReadOnly:bool類型,標識該請求是否僅進行只讀操作(GET就是只讀操作)。
Kind:String類型,用于標識要訪問的Kubernetes資源對象的類型。當訪問例如/api/v1beta1/pods等API endpoint時,Kind屬性才非空,但訪問其他endpoint時,例如/version,/healthz等,Kind屬性為空。
Namespace:String類型,用于標識要訪問的Kubernetes資源對象所在的namespace。
對ABAC模式,在apiserver啟動時除了需要傳入--authorization_mode=ABAC選項外,還需要指定 --authorization_policy_file=SOME_FILENAME。authorization_policy_file文件的每一 行都是一個JSON對象,該JSON對象是一個沒有嵌套的map數據結構,代表一個訪問控制規則對象。一個訪問控制規則對象是一個有以下字段的map:
user:--token_auth_file指定的user字符串。
readonly:true或false,如果是true則表明該規則只應用于GET請求。
kind:Kubernetes內置資源對象類型,例如pods、events等。
namespace:也可以縮寫成ns。
一個簡單的訪問控制規則文件如下所示,每一行定義一條規則。
{"user":"admin"}
{"user":"alice", "ns": "projectCaribou"}
{"user":"kubelet", "readonly": true, "kind": "pods"}
{"user":"kubelet", "kind": "events"}
{"user":"bob", "kind": "pods", "readonly": true, "ns": "projectCaribou"}
注:缺省的字段與該字段類型的零值(空字符串,0,false等)等價。
規則逐行說明如下。
第一行表明,admin可以做任何事情,不受namespace,資源類型,請求類型的限制。
第二行表明,alice能夠在namespace "projectCaribou"中做任何事情,不受資源類型,請求類型的限制。
第三行表明,kubelet有權限讀任何一個pod的信息。
第四行表明,kubelet有權限讀寫任何一個event。
第五行表明,Bob有權限讀取在namespace "projectCaribou"中所有pod的信息。
一個授權過程就是一個比較API請求中各屬性與訪問控制規則文件中對應的各字段是否匹配的一個過程。當apiserver接收到一個API請求時,該請求 的各屬性就已經確定了,如果有一個屬性未被設置,則apiserver將其設為該類型的空值(空字符串,0,false等)。匹配規則很簡單,如下所示。
如果API請求中的某個屬性為空值,則規定該屬性與訪問控制規則文件中對應的字段匹配。
如果訪問控制規則的某個字段為空值,則規定該字段與API請求的對應屬性匹配。
如果API請求中的屬性值非空且訪問控制規則的某個字段值也非空,則將這兩個值進行比較,如果相同則匹配,反之則不匹配。
API請求的屬性元組(tuple)會與訪問控制規則文件中的所有規則逐條匹配,只要有一條匹配則表示匹配成功,如若不然,則授權失敗。
準入控制admission controller本質上為一段準入代碼,在對kubernetes api的請求過程中,順序為 先經過 認證 & 授權,然后執行準入操作,再對目標對象進行操作。這個準入代碼在apiserver中,而且必須被編譯到二進制文件中才能被執行。
在對集群進行請求時,每個準入控制代碼都按照一定順序執行。如果有一個準入控制拒絕了此次請求,那么整個請求的結果將會立即返回,并提示用戶相應的error信息。
在某些情況下,為了適用于應用系統的配置,準入邏輯可能會改變目標對象。此外,準入邏輯也會改變請求操作的一部分相關資源。
作用
在kubernetes中,一些高級特性正常運行的前提條件為,將一些準入模塊處于enable狀態。總結下,對于kubernetes apiserver,如果不適當的配置準入控制模塊,它就不能稱作是一個完整的server,某些功能也不會正常的生效。
開啟方式
在kubernetes apiserver中有一個參數:admission_control,他的值為一串用逗號連接的 有序的 準入模塊列表,設置后,就可在對象被操作前執行一定順序的準入模塊調用。
模塊功能
AlwaysAdmit:允許所有請求
AlwaysDeny:禁止所有請求,多用于測試環境。
DenyExecOnPrivileged:它會攔截所有想在privileged container上執行命令的請求。如果自己的集群支持privileged container,自己又希望限制用戶在這些privileged container上執行命令,那么強烈推薦使用它。
ServiceAccount:這個plug-in將 serviceAccounts實現了自動化,如果想要使用ServiceAccount 對象,那么強烈推薦使用它。
關于serviceAccount的描述如下: 一個serviceAccount為運行在pod內的進程添加了相應的認證信息。當準入模塊中開啟了此插件(默認開啟),那么當pod創建或修改時他會做一下事情:
如果pod沒有serviceAccount屬性,將這個pod的serviceAccount屬性設為“default”;
確保pod使用de serviceAccount始終存在;
如果LimitSecretReferences 設置為true,當這個pod引用了Secret對象卻沒引用ServiceAccount對象,棄置這個pod;
如果這個pod沒有包含任何ImagePullSecrets,則serviceAccount的ImagePullSecrets被添加給這個pod;
如果MountServiceAccountToken為true,則將pod中的container添加一個VolumeMount 。
SecurityContextDeny:這個插件將會將使用了 SecurityContext的pod中定義的選項全部失效。SecurityContext 在container中定義了操作系統級別的安全設定(uid, gid, capabilities, SELinux等等)。
ResourceQuota:它會觀察所有的請求,確保在namespace中ResourceQuota對象處列舉的container沒有任何異常。 如果在kubernetes中使用了ResourceQuota對象,就必須使用這個插件來約束container。推薦在admission control參數列表中,這個插件排最后一個。
LimitRanger:他會觀察所有的請求,確保沒有違反已經定義好的約束條件,這些條件定義在namespace中LimitRange對象中。如果在kubernetes中使用LimitRange對象,則必須使用這個插件。
NamespaceExists:它會觀察所有的請求,如果請求嘗試創建一個不存在的namespace,則這個請求被拒絕。
推薦插件順序
--admission_control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ServiceAccount, ResourceQuota
1. API Server的初始化參數中設置了一些與權限認證相關的默認屬性:
安全監聽端口: SecurePort: 8443 讀/寫 權限,支持x509安全證書和x509私鑰認證
非安全監聽端口:InsecurePort: 8080 沒有用戶身份認證和授權,有讀/寫 權限
授權模式: AuthorizationMode: "AlwaysAllow",
準入控制插件: AdmissionControl: "AlwaysAdmit"
2. API Server啟動時可以設置與權限認證相關的參數:
--insecure_port 自定義非安全監聽端口
--secure_port 自定義安全監聽端口
--tls_cert_file 設置安全證書文件
--tls_private_key_file 設置私鑰文件
--cert_dir 安全證書文件和私鑰文件被設置時,此屬性忽略。安全證書文件和私鑰文件未設置時,apiserver會自動為該
端口綁定的公有IP地址分別生成一個自注冊的證書文件和密鑰并將它們存儲在/var/run/kubernetes
下
--service_account_key_file 服務賬號文件,包含x509 公私鑰
--client_ca_file client證書文件
--token_auth_file token文件
--basic_auth_file 基本信息認證文件
--authorization_mode 授權模式
--ahtuorization_policy_file 授權文件
--admission_control 準入控制模塊列表
--admission_control_config_file 準入控制配置文件
3. 解析入參,進行認證信息提取:
公 私鑰文件設置:查看ServerAccountKeyFile是否已指定,如果未指定,并且TLSPrivateKeyFile被指定,則判斷 TLSPrivateKeyFile中是否包含有效的RSA key,包含時,將TLSPrivateKeyFile作為ServerAccountKeyFile。
身份認證信息提取:從參 數設置的CSV文件中取出username,userID,password(或者token)封裝成map結構,key為username,value 為三種屬性的struct。從basicAuthFile, clientCAFile, tokenFile, serviceAccountKeyFile(serviceAccountLookup) 中取user信息,得到一個驗證信息的map數組。
授 權信息提取:讀取設置的授權文件,解析字符串,返回授權信息數組。(包含 username,group,resource,read only,namespace)Make the "cluster" Kinds be one API group (minions, bindings,events,endpoints)。The "user" Kinds are another (pods,services,replicationControllers,operations)。
準入控制插件:獲取所有插件名,返回準入控制接口(執行所有插件)
4. 將身份認證信息、授權信息、準入控制插件作為Master的配置,New Master。
5. 請求認證:
調apiserver的NewRequestAttributeGetter方法,從請求中提取授權信息,調用WithAuthorizationCheck方法(授權驗證)。
調 用handler的NewRequestAuthenticator方法,Request中提取authencate信息,調用 AuthenticateRequest方法(對client certificates,token,basic auth分別有不同的驗證方法)。
身份認證:
token認證,請求時,在請求頭中加入 Authorization:bearer token字符串。CSV文件中,三列分別為 token,username,userid。當CSV中有與請求的Authorization匹配行時,認證成功。
basic auth認證,請求時,在請求頭中加入 Authorization:basic base64編碼的user:password字符串。CSV文件中,三列分別為 password,username,userid。當CSV文件中有與請求的Ahtuorization匹配行時,認證成功。
證書校驗:
API Server啟動時,指定服務端數字證書和密鑰(如果不指定,會在server啟動時自動生成),指定客戶端ca文件,server啟動時,會解析ca文 件,遍歷其中的cert,加入certpool。在Server的TLSConfig中指定認證模式:目前使用的是 RequestClientCert(不強制認證,無認證時不拒絕連接,允許其他認證),此外還有其他認證模式 requireAndVerifyClientCert(強制校驗)。使用ListenAndServeTLS(將服務端數字證書和密鑰作為參數)監聽在 安全端口。
啟動server:指定token驗證文件、授權方式、授權文件
./_output/local/bin/linux/amd64/canary-apiserver --logtostderr=true --log-dir=/tmp --v=4 --etcd_servers=http://127.0.0.1:4001 --insecure_bind_address=127.0.0.1 --insecure_port=8088 --secure_port=8442 --kubelet_port=10250 --service-cluster-ip-range=10.1.1.0/24 --allow_privileged=true --runtime-config="api/v1beta3=false" --redis-addr=localhost:6379 --profiling=true --token_auth_file=token.csv --authorization_mode=ABAC --authorization_policy_file=abac.csv
Token文件內容:
abcdef,hankai,123456
abcdefg,hk,123457
abcd,admin,1234
abc,hhh,111
授權文件內容:
{“user”:”admin”}
{“user”:”hankai”,”readonly”:true}
{“user”:”hhh”,”resource”:”apps”}
{“user”:”hk”,”readonly”:true,”resource”:”namespaces”}
驗證:admin(有讀寫所有resource的權限)
curl -X GET -H "Content-Type: application/json" -H "Authorization: bearer abcd" -k https://10.57.104.59:8442/api/v1/apps
curl -X GET -H "Content-Type: application/json" -H "Authorization: bearer abcd" -k https://10.57.104.59:8442/api/v1/namespaces
curl -X POST -H "Content-Type: application/json" -H "Authorization: bearer abcd" -d@'n1.json' -k https://10.57.104.59:8442/api/v1/namespaces
curl -X POST -H "Content-Type: application/json" -H "Authorization: bearer abcd" -d@'app_demo1.json' -k https://10.57.104.59:8442/api/v1/apps
驗證 hankai (只有讀權限GET)
curl -X POST -H "Content-Type: application/json" -H "Authorization: bearer abcdef" -d@'app_demo1.json' -k https://10.57.104.59:8442/api/v1/apps forbidden
curl -X POST -H "Content-Type: application/json" -H "Authorization: bearer abcdef" -d@'n1.json' -k https://10.57.104.59:8442/api/v1/namespaces forbidden
curl -X GET -H "Content-Type: application/json" -H "Authorization: bearer abcdef" -k https://10.57.104.59:8442/api/v1/namespaces
curl -X GET -H "Content-Type: application/json" -H "Authorization: bearer abcdef" -k https://10.57.104.59:8442/api/v1/apps
驗證 hk (只有對namespaces的GET權)
curl -X GET -H "Content-Type: application/json" -H "Authorization: bearer abcdefg" -k https://10.57.104.59:8442/api/v1/apps
forbidden
curl -X GET -H "Content-Type: application/json" -H "Authorization: bearer abcdefg" -k https://10.57.104.59:8442/api/v1/namespaces
curl -X POST -H "Content-Type: application/json" -H "Authorization: bearer abcdefg" -d@'n1.json' -k https://10.57.104.59:8442/api/v1/namespaces forbidden
curl -X POST -H "Content-Type: application/json" -H "Authorization: bearer abcdefg" -d@'app_demo1.json' -k https://10.57.104.59:8442/api/v1/apps forbidden
驗證hhh(擁有對apps的讀寫權)
curl -X POST -H "Content-Type: application/json" -H "Authorization: bearer abc" -d@'app_demo1.json' -k https://10.57.104.59:8442/api/v1/apps
curl -X GET -H "Content-Type: application/json" -H "Authorization: bearer abc" -k https://10.57.104.59:8442/api/v1/apps
curl -X GET -H "Content-Type: application/json" -H "Authorization: bearer abc" -k https://10.57.104.59:8442/api/v1/namespaces
forbidden
curl -X POST -H "Content-Type: application/json" -H "Authorization: bearer abc" -d@'n1.json' -k https://10.57.104.59:8442/api/v1/namespaces
forbidden
注:后續只需要在abac.csv文件的每列中,指定namespace,就可以實現user對指定namespace的操作權限。
新增:TSL 客戶端證書認證
使用自生成證書測試:使用openssl生成server.crt,server.key,ca.key,ca.crt。Server啟動時,傳入 --tls_cert_file=server.crt --tls_private_key_file=server.key --client_ca_file=ca.crt
./_output/local/bin/linux/amd64/canary-apiserver --logtostderr=true --log-dir=/tmp --v=4 --etcd_servers=http://127.0.0.1:4001 --insecure_bind_address=7.0.0.1 --insecure_port=8088 --secure_port=8442 --kubelet_port=10250 --service-cluster-ip-range=10.1.1.0/24 --allow_privileged=true --runtime-config="api/v1beta3=false" --redis-addr=localhost:6379 --profiling=true --tls_cert_file=server.crt --tls_private_key_file=server.key --client_ca_file=ca.crt --token_auth_file=token.csv --authorization_mode=ABAC --authorization_policy_file=abac.csv
請求時,通過-cacert 指定客戶端證書 (可以通過修改opnessl的配置文件指定客戶端證書的路徑,或者瀏覽器中導入客戶端證書) curl -X GET --cacert ca.crt -H "Content-Type: application/json" -H "Authorization: bearer abcd" -k https://10.57.104.59:8442/api/v1/apps 即可實現認證。
以上是“kubernetes API Server權限管理的示例分析”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。