官网文档
认证
是谁,识别用户
鉴权
有无操作对象资源的权限
准入
mutating 变形,添加默认值/属性
Admission
validating 对象是否合法,是否符合k8s规范
限流
API 对象实现
主要功能
- 提供管理集群的REST API接口,包括认证、鉴权、数据校验以及集群状态变更
- 提供其他模块之间数据交互和通信的枢纽(其他模块通过API查询或修改数据,只有API server才能直接操作etcd)
访问控制概览
HTTP handler
Authentication 是谁
Authorization 有无操作资源的权限
可以通过webhook自定义mutating和validating
访问控制细节
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
查询。
认证插件
webhook令牌身份认证--authentication-token-webhook-config-file
指向一个配置文件,其中描述如何访问webhook服务--authentication-token-webhook-cache-ttl
设置身份认证的访问时间,默认2分钟
匿名请求
使用AlwaysAllow以外的认证模式,则匿名请求默认开启,可以使用--anonymous-auth=false
禁止匿名请求
基于webhook的认证服务集成
URL: http://authn.example.com/authenticate
Method: POST
Input:
{
"apiVersion": "authentication.k8s.io/v1",
"kind": "TokenReview",
"spec": {
# 发送到 API 服务器的不透明持有者令牌
"token": "014fbff9a07c...",
# 提供令牌的服务器的受众标识符的可选列表。
# 受众感知令牌验证器(例如,OIDC 令牌验证器)
# 应验证令牌是否针对此列表中的至少一个受众,
# 并返回此列表与响应状态中令牌的有效受众的交集。
# 这确保了令牌对于向其提供给的服务器进行身份验证是有效的。
# 如果未提供受众,则应验证令牌以向 Kubernetes API 服务器进行身份验证。
"audiences": ["https://myserver.example.com", "https://myserver.internal.example.com"]
}
}
OutPut:
{
"apiVersion": "authentication.k8s.io/v1",
"kind": "TokenReview",
"status": {
"authenticated": true,
"user": {
# 必要
"username": "janedoe@example.com",
# 可选
"uid": "42",
# 可选的组成员身份
"groups": ["developers", "qa"],
# 认证者提供的可选附加信息。
# 此字段不可包含机密数据,因为这类数据可能被记录在日志或 API 对象中,
# 并且可能传递给 admission webhook。
"extra": {
"extrafield1": [
"extravalue1",
"extravalue2"
]
}
},
# 验证器可以返回的、可选的用户感知令牌列表,
# 包含令牌对其有效的、包含于 `spec.audiences` 列表中的受众。
# 如果省略,则认为该令牌可用于对 Kubernetes API 服务器进行身份验证。
"audiences": ["https://myserver.example.com"]
}
}
webhookserver
通过github的Personal access tokens进行身份认证
package main
import (
"context"
"encoding/json"
"log"
"net/http"
"github.com/google/go-github/github"
"golang.org/x/oauth2"
authentication "k8s.io/api/authentication/v1beta1"
)
func Authenticate(w http.ResponseWriter, r *http.Request) {
var tr authentication.TokenReview
err := json.NewDecoder(r.Body).Decode(&tr)
if err != nil {
log.Println("[Error]", err.Error())
w.WriteHeader(http.StatusBadRequest)
_ = json.NewEncoder(w).Encode(map[string]interface{}{
"apiVersion": "authentication.k8s.io/v1beta1",
"kind": "TokenReview",
"status": authentication.TokenReviewStatus{
Authenticated: false,
Error: err.Error(),
},
})
return
}
log.Print("receving request")
// Check User
sts := oauth2.StaticTokenSource(
&oauth2.Token{AccessToken: tr.Spec.Token},
)
oauthClient := oauth2.NewClient(context.Background(), sts)
httpClient := github.NewClient(oauthClient)
githubUser, _, err := httpClient.Users.Get(context.Background(), "")
if err != nil {
log.Println("[Error]", err.Error())
w.WriteHeader(http.StatusUnauthorized)
json.NewEncoder(w).Encode(map[string]interface{}{
"apiVersion": "authentication.k8s.io/v1beta1",
"kind": "TokenReview",
"status": authentication.TokenReviewStatus{
Authenticated: false,
Error: err.Error(),
},
})
return
}
log.Printf("[Success] login as %s", *githubUser.Login)
w.WriteHeader(http.StatusOK)
trs := authentication.TokenReviewStatus{
Authenticated: true,
User: authentication.UserInfo{
Username: *githubUser.Login,
UID: *githubUser.Login,
Groups: []string{"default"},
},
}
json.NewEncoder(w).Encode(map[string]interface{}{
"apiVersion": "authentication.k8s.io/v1beta1",
"kind": "TokenReview",
"status": trs,
})
}
func main() {
http.HandleFunc("/authenticate", Authenticate)
log.Println(http.ListenAndServe(":3000", nil))
}
kubeadm创建的k8s集群默认的证书是1年,可通过脚本进行更新
查看证书情况
# 新版本(1.15+)
kubeadm alpha certs check-expiration
# 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
Role和RoleBinding常见操作
# 查看当前namespace有哪些role
root@kubernetes-master:~# kubectl get role
NAME CREATED AT
developer 2022-05-28T09:19:13Z
# 查看指定role的详细信息
root@kubernetes-master:~# kubectl get role developer -oyaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
creationTimestamp: "2022-05-28T09:19:13Z"
name: developer
namespace: default
resourceVersion: "2897263"
uid: 504adaf9-230a-4de6-b98f-e9a9fd2442a2
rules:
- apiGroups:
- ""
resources:
- pods
verbs:
- create
- get
- list
- update
- delete
# 创建role
root@kubernetes-master:~/role# cat dev-role.yml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: dev-role-default
namespace: default
rules:
- apiGroups:
- ""
resources:
- pods
verbs:
- create
- get
- list
- update
- delete
root@kubernetes-master:~/role# kubectl create -f dev-role.yml
role.rbac.authorization.k8s.io/dev created
# 绑定role
root@kubernetes-master:~/role# cat dev-role-binding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: dev-rolebinding
namespace: default
subjects:
- kind: User
name: PoplarYang
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: dev-role-default
apiGroup: rbac.authorization.k8s.io
root@kubernetes-master:~/role# kubectl create -f dev-role-binding.yaml
# 在线编辑权限
root@kubernetes-master:~/role# kubectl edit role dev-role-default
# 测试
root@kubernetes-master:~# kubectl get pod --user githubuser
ClusterRole和ClusterRoleBinding常见操作
# 查看所有cluster role
root@kubernetes-master:~# kubectl get clusterrole
# 查看当前namespace有哪些cluster role
root@kubernetes-master:~/role# cat dev-clusterrole.yml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: dev-clusterrole
rules:
- apiGroups:
- ""
resources:
- pods
verbs:
- create
- get
- list
root@kubernetes-master:~/role# kubectl create -f dev-clusterrole.yml
# 绑定cluster role
root@kubernetes-master:~/role# cat dev-cluster-role-binding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: dev-cluster-rolebinding
namespace: default
subjects:
- kind: User
name: PoplarYang
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: dev-clusterrole
apiGroup: rbac.authorization.k8s.io
root@kubernetes-master:~/role# kubectl create -f dev-cluster-role-binding.yaml
# 测试
root@kubernetes-master:~# kubectl get pod --user githubuser
测试页面有可以公开访问的minikube
https://v1-23.docs.kubernetes.io/zh/docs/test/