不使用RBAC的鉴权方式 准备工作 参考文档:https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/authorization/
根据文档,我们可以使用Webhook
模式 实现自己的鉴权逻辑
https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/webhook/
实现自己的授权逻辑 根据文档,Webhook
模式需要一个 HTTP 配置文件,通过 --authorization-webhook-config-file=SOME_FILENAME
的参数声明。
webhook的配置文件是kubeconfig格式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 apiVersion: v1 kind: Config clusters: - name: webhook cluster: insecure-skip-tls-verify: true server: https://localhost:9090/authorize users: - name: webhook-user current-context: webhook contexts: - context: cluster: webhook user: webhook-user name: webhook
启动apiserver的脚本需要修改,将授权模式改为webhook
新加的配置:
—authentication-token-webhook-config-file
—runtime-config=authorization.k8s.io/v1beta1=true
将—authorization-mode 改为Webhook模式
1 2 3 4 5 6 7 8 9 10 11 12 go run -mod=mod cmd/kube-apiserver/apiserver.go \ --etcd-servers=http://127.0.0.1:2379 \ --service-account-issuer=https://kubernetes.default.svc.cluster.local \ --authorization-mode=Node,Webhook \ --authorization-webhook-config-file=./001/webhook/config \ --runtime-config=authorization.k8s.io/v1beta1=true \ --service-account-key-file=./certs/sa.pub \ --service-account-signing-key-file=./certs/sa.key \ --tls-cert-file=./certs/apiserver.crt \ --tls-private-key-file=./certs/apiserver.key \ --feature-gates=EphemeralContainers=true \ --service-cluster-ip-range=10.96.0.0/22
webhook服务的证书:
1 2 3 4 5 openssl genrsa -out server.key 2048 openssl req -new -key server.key -out certFile.csr openssl x509 -req -days 365 -in certFile.csr -signkey server.key -out server.pem
authorize代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 package mainimport ( "encoding/json" "fmt" "github.com/gin-gonic/gin" "io" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" ) const ( AccessApiVersion = "authorization.k8s.io/v1beta1" AccessKind = "SubjectAccessReview" ) func authorizeRsp (allowed bool , reason string ) *unstructured.Unstructured { obj := &unstructured.Unstructured{} obj.SetAPIVersion(AccessApiVersion) obj.SetKind(AccessKind) obj.Object["status" ] = map [string ]interface {}{ "allowed" : allowed, "reason" : reason, } return obj } func main () { r := gin.New() r.POST("/authorize" , func (c *gin.Context) { b, err := io.ReadAll(c.Request.Body) if err != nil { c.AbortWithStatusJSON(400 , authorizeRsp(false , err.Error())) } obj := &unstructured.Unstructured{} err = json.Unmarshal(b, obj) if err != nil { c.AbortWithStatusJSON(400 , authorizeRsp(false , err.Error())) } fmt.Println(string (b)) c.AbortWithStatusJSON(200 , authorizeRsp(true , "" )) }) r.RunTLS(":9090" , "./webhook/certs/server.pem" , "./webhook/certs/server.key" ) }
所有成功的请求全都放行
启动
使用client-go请求本地apiserver 上面的操作已经在本地启动了一个apiserver、etcd,使用自己的鉴权(所有请求放行)
现在我想知道 使用 client-go客户端 访问本地的apiserver是个什么效果
K8sClient.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package configimport ( "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" ) func K8sClient () *kubernetes.Clientset { config := &rest.Config{ Host: "https://127.0.0.1:6443" , } config.Insecure = true clientset, err := kubernetes.NewForConfig(config) if err != nil { panic (err.Error()) } return clientset }
test.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 package mainimport ( "context" "fmt" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/kubernetes/001/config" ) func main () { clientset := config.K8sClient() list, err := clientset.CoreV1().Pods("default" ).List(context.Background(), metav1.ListOptions{}) if err != nil { panic (err.Error()) } for _, d := range list.Items { fmt.Println(d.Name) } }
没啥问题
现在我想创建一个pod,看看啥效果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 package mainimport ( "context" "fmt" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/kubernetes/001/config" ) func main () { clientset := config.K8sClient() ngxPod := &corev1.Pod{} ngxPod.Name = "nginx" ngxPod.Namespace = "default" ngxPod.Spec.Containers = []corev1.Container{ {Name: "nginx" , Image: "nginx:latest" }, } _, err := clientset.CoreV1().Pods("default" ).Create(context.Background(), ngxPod, metav1.CreateOptions{}) if err != nil { panic (err.Error()) } }
结果报错:
这个default账号作用:
当在 Kubernetes 中创建一个 Pod 时,如果没有指定其他服务账户,default
服务账户的凭据会自动被挂载到该 Pod 中
具有访问该namespace内的大多数资源的权限
这个default是由 controller-manager创建的
代码位置: pkg/controller/serviceaccount/serviceaccounts_controller.go:185
手动创建default sa