官网文档
认证
是谁,识别用户
鉴权
有无操作对象资源的权限
准入
mutating 变形,添加默认值/属性
Admission
validating 对象是否合法,是否符合k8s规范

限流
API 对象实现

主要功能

  • 提供管理集群的REST API接口,包括认证、鉴权、数据校验以及集群状态变更
  • 提供其他模块之间数据交互和通信的枢纽(其他模块通过API查询或修改数据,只有API server才能直接操作etcd)

访问控制概览
image.png

HTTP handler
Authentication 是谁
Authorization 有无操作资源的权限
可以通过webhook自定义mutating和validating

访问控制细节
image.png
conversion 资源转换
Internal Version 面向自己的实现
External Version 面向用户

认证

kubernetes支持多种认证机制,并支持同时开启多个认证插件(只要有一个认证通过即可)。
如果认证成功,则用户的username会传入授权模块作进一步授权验证
对于认证失败的请求返回401

认证插件
x509证书 官网文档
API server启动时配置--client-ca-file=SOMEFILE
在证书认证时,CN(Common Name)域用作用户名,组织机构(Ognization Name)用作group名。

如何将CAA配置到API server

静态token
API server启动时配置 --token-auth-file=SOMEFILE
文件格式有3列,token, username, userid

静态密码文件
API Server启动时指定 --basic-auth-file=SOMEFILE
文件格式为csv,至少3列,group可选。passwd, user, uid,

ServiceAcount
ServiceAcount 是kubernetes自动生成的,并且会自动挂载到容器中。
用处:pod带着这个ServiceAccount去访问API server时,API可以识别是哪个namespace的那个pod
挂载目录/run/secrets/kubernetes.io/serviceaccount

启动引导令牌
为了支持平滑的启动引导新集群,kubernetes 包含了一种动态管理的持有令牌类型,称作启动引导令牌。
该令牌以Secret形式保存在kube-system命名空间中,可以被动态管理和创建。
控制器管理器包含的TokenCleaner控制器能够在启动引导令牌过期时将其删除。
在使用kubeadm部署kubernetes时可通过kubeadm token list 查询。

OpenID
Oauth2.0认证机制

认证插件

webhook令牌身份认证
--authentication-token-webhook-config-file 指向一个配置文件,其中描述如何访问webhook服务
--authentication-token-webhook-cache-ttl 设置身份认证的访问时间,默认2分钟

匿名请求
使用AlwaysAllow以外的认证模式,则匿名请求默认开启,可以使用--anonymous-auth=false禁止匿名请求

基于webhook的认证服务集成

官网文档
官网文档中文
认证服务规范

  1. URL: http://authn.example.com/authenticate
  2. Method: POST
  3. Input:
  4. {
  5. "apiVersion": "authentication.k8s.io/v1",
  6. "kind": "TokenReview",
  7. "spec": {
  8. # 发送到 API 服务器的不透明持有者令牌
  9. "token": "014fbff9a07c...",
  10. # 提供令牌的服务器的受众标识符的可选列表。
  11. # 受众感知令牌验证器(例如,OIDC 令牌验证器)
  12. # 应验证令牌是否针对此列表中的至少一个受众,
  13. # 并返回此列表与响应状态中令牌的有效受众的交集。
  14. # 这确保了令牌对于向其提供给的服务器进行身份验证是有效的。
  15. # 如果未提供受众,则应验证令牌以向 Kubernetes API 服务器进行身份验证。
  16. "audiences": ["https://myserver.example.com", "https://myserver.internal.example.com"]
  17. }
  18. }
  19. OutPut:
  20. {
  21. "apiVersion": "authentication.k8s.io/v1",
  22. "kind": "TokenReview",
  23. "status": {
  24. "authenticated": true,
  25. "user": {
  26. # 必要
  27. "username": "janedoe@example.com",
  28. # 可选
  29. "uid": "42",
  30. # 可选的组成员身份
  31. "groups": ["developers", "qa"],
  32. # 认证者提供的可选附加信息。
  33. # 此字段不可包含机密数据,因为这类数据可能被记录在日志或 API 对象中,
  34. # 并且可能传递给 admission webhook。
  35. "extra": {
  36. "extrafield1": [
  37. "extravalue1",
  38. "extravalue2"
  39. ]
  40. }
  41. },
  42. # 验证器可以返回的、可选的用户感知令牌列表,
  43. # 包含令牌对其有效的、包含于 `spec.audiences` 列表中的受众。
  44. # 如果省略,则认为该令牌可用于对 Kubernetes API 服务器进行身份验证。
  45. "audiences": ["https://myserver.example.com"]
  46. }
  47. }

webhookserver
通过github的Personal access tokens进行身份认证

  1. package main
  2. import (
  3. "context"
  4. "encoding/json"
  5. "log"
  6. "net/http"
  7. "github.com/google/go-github/github"
  8. "golang.org/x/oauth2"
  9. authentication "k8s.io/api/authentication/v1beta1"
  10. )
  11. func Authenticate(w http.ResponseWriter, r *http.Request) {
  12. var tr authentication.TokenReview
  13. err := json.NewDecoder(r.Body).Decode(&tr)
  14. if err != nil {
  15. log.Println("[Error]", err.Error())
  16. w.WriteHeader(http.StatusBadRequest)
  17. _ = json.NewEncoder(w).Encode(map[string]interface{}{
  18. "apiVersion": "authentication.k8s.io/v1beta1",
  19. "kind": "TokenReview",
  20. "status": authentication.TokenReviewStatus{
  21. Authenticated: false,
  22. Error: err.Error(),
  23. },
  24. })
  25. return
  26. }
  27. log.Print("receving request")
  28. // Check User
  29. sts := oauth2.StaticTokenSource(
  30. &oauth2.Token{AccessToken: tr.Spec.Token},
  31. )
  32. oauthClient := oauth2.NewClient(context.Background(), sts)
  33. httpClient := github.NewClient(oauthClient)
  34. githubUser, _, err := httpClient.Users.Get(context.Background(), "")
  35. if err != nil {
  36. log.Println("[Error]", err.Error())
  37. w.WriteHeader(http.StatusUnauthorized)
  38. json.NewEncoder(w).Encode(map[string]interface{}{
  39. "apiVersion": "authentication.k8s.io/v1beta1",
  40. "kind": "TokenReview",
  41. "status": authentication.TokenReviewStatus{
  42. Authenticated: false,
  43. Error: err.Error(),
  44. },
  45. })
  46. return
  47. }
  48. log.Printf("[Success] login as %s", *githubUser.Login)
  49. w.WriteHeader(http.StatusOK)
  50. trs := authentication.TokenReviewStatus{
  51. Authenticated: true,
  52. User: authentication.UserInfo{
  53. Username: *githubUser.Login,
  54. UID: *githubUser.Login,
  55. Groups: []string{"default"},
  56. },
  57. }
  58. json.NewEncoder(w).Encode(map[string]interface{}{
  59. "apiVersion": "authentication.k8s.io/v1beta1",
  60. "kind": "TokenReview",
  61. "status": trs,
  62. })
  63. }
  64. func main() {
  65. http.HandleFunc("/authenticate", Authenticate)
  66. log.Println(http.ListenAndServe(":3000", nil))
  67. }

kubeadm创建的k8s集群默认的证书是1年,可通过脚本进行更新
查看证书情况

  1. # 新版本(1.15+)
  2. kubeadm alpha certs check-expiration
  3. # openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -text | grep GMT

https://github.com/yuyicai/update-kube-cert

授权

授权主要是用于集群资源的访问控制,通过检查属性包含的相关属性值,与对应的访问策略相比较,API请求必须满足某些策略才能被处理。
与认证类似,kubernetes也支持多种授权机制,并支持同时开启多个授权插件,只要有一个验证通过即可。
如果授权成功,则请求会进入准入控制模块做进一步请求验证;授权失败返回403。

kubernetes授权仅处理以下请求属性

  • user,group,extra
  • API、请求方法(get/post/update/patch/delete)和请求路径(如API)
  • 请求资源和子资源
  • Namespace
  • API Group

kubernetes 支持以下授权插件

  • ABAC
  • RBAC(Role Base Access Control)
  • webhook
  • Node

RBAC

授权策略可以利用kubectl进行配置。
RBAC可以授权给用户,让用户有权限进行授权管理,实现权限传递。

Role 是一系列权限的集合,只能给特定的Namespace。对多namespace和集群级别的资源或者API使用ClusterRole。
ClusterRole、ClusterRoleBinding 是全局的
Role,RoleBinding 是命名空间内部的
user 可以通过RoleBinding绑定ClusterRole
image.png

Role和RoleBinding常见操作

  1. # 查看当前namespace有哪些role
  2. root@kubernetes-master:~# kubectl get role
  3. NAME CREATED AT
  4. developer 2022-05-28T09:19:13Z
  5. # 查看指定role的详细信息
  6. root@kubernetes-master:~# kubectl get role developer -oyaml
  7. apiVersion: rbac.authorization.k8s.io/v1
  8. kind: Role
  9. metadata:
  10. creationTimestamp: "2022-05-28T09:19:13Z"
  11. name: developer
  12. namespace: default
  13. resourceVersion: "2897263"
  14. uid: 504adaf9-230a-4de6-b98f-e9a9fd2442a2
  15. rules:
  16. - apiGroups:
  17. - ""
  18. resources:
  19. - pods
  20. verbs:
  21. - create
  22. - get
  23. - list
  24. - update
  25. - delete
  26. # 创建role
  27. root@kubernetes-master:~/role# cat dev-role.yml
  28. apiVersion: rbac.authorization.k8s.io/v1
  29. kind: Role
  30. metadata:
  31. name: dev-role-default
  32. namespace: default
  33. rules:
  34. - apiGroups:
  35. - ""
  36. resources:
  37. - pods
  38. verbs:
  39. - create
  40. - get
  41. - list
  42. - update
  43. - delete
  44. root@kubernetes-master:~/role# kubectl create -f dev-role.yml
  45. role.rbac.authorization.k8s.io/dev created
  46. # 绑定role
  47. root@kubernetes-master:~/role# cat dev-role-binding.yaml
  48. apiVersion: rbac.authorization.k8s.io/v1
  49. kind: RoleBinding
  50. metadata:
  51. name: dev-rolebinding
  52. namespace: default
  53. subjects:
  54. - kind: User
  55. name: PoplarYang
  56. apiGroup: rbac.authorization.k8s.io
  57. roleRef:
  58. kind: Role
  59. name: dev-role-default
  60. apiGroup: rbac.authorization.k8s.io
  61. root@kubernetes-master:~/role# kubectl create -f dev-role-binding.yaml
  62. # 在线编辑权限
  63. root@kubernetes-master:~/role# kubectl edit role dev-role-default
  64. # 测试
  65. root@kubernetes-master:~# kubectl get pod --user githubuser

image.png
ClusterRole和ClusterRoleBinding常见操作

  1. # 查看所有cluster role
  2. root@kubernetes-master:~# kubectl get clusterrole
  3. # 查看当前namespace有哪些cluster role
  4. root@kubernetes-master:~/role# cat dev-clusterrole.yml
  5. apiVersion: rbac.authorization.k8s.io/v1
  6. kind: ClusterRole
  7. metadata:
  8. name: dev-clusterrole
  9. rules:
  10. - apiGroups:
  11. - ""
  12. resources:
  13. - pods
  14. verbs:
  15. - create
  16. - get
  17. - list
  18. root@kubernetes-master:~/role# kubectl create -f dev-clusterrole.yml
  19. # 绑定cluster role
  20. root@kubernetes-master:~/role# cat dev-cluster-role-binding.yaml
  21. apiVersion: rbac.authorization.k8s.io/v1
  22. kind: RoleBinding
  23. metadata:
  24. name: dev-cluster-rolebinding
  25. namespace: default
  26. subjects:
  27. - kind: User
  28. name: PoplarYang
  29. apiGroup: rbac.authorization.k8s.io
  30. roleRef:
  31. kind: ClusterRole
  32. name: dev-clusterrole
  33. apiGroup: rbac.authorization.k8s.io
  34. root@kubernetes-master:~/role# kubectl create -f dev-cluster-role-binding.yaml
  35. # 测试
  36. root@kubernetes-master:~# kubectl get pod --user githubuser

测试页面有可以公开访问的minikube
https://v1-23.docs.kubernetes.io/zh/docs/test/