go-restful

Kubernetes应用系统API用户认证与鉴权 -- 鉴权篇

上篇文章讲了通过LDAP和Dex实现两种不同的API用户认证的方式,用户认证是识别API请求的来源,让系统知道请求的访问者是谁。应用系统可以根据请求的身份,来判断该用户可以访问哪些API接口获得数据,这就是用户鉴权。下面我们一起来看一下,在Kubernetes平台上,如何通过RBAC来实现资源访问限制,同样我们还是通过Kubesphere的代码来学习。 鉴权实现的过程: 1,构建一个HandlerChain,HandlerChain中包含了:WithAuthentication, WithRequestInfo和WithAuthorization用户认证和鉴权的三个Filter以及WithAuditing Filter用于审计日志。Filter可以理解为web 框架的Middleware。 2,filters.WithAuthentication上篇文章介绍过,完成用户身份识别和分发Token,将用户信息写入Context。 3,filters.WithRequestInfo处理API请求信息,将请求信息保存到context中。请求信息包括:Path, Verb, APIPrefix, APIGroup, APIVersion, Namespace, Resource, Name这些RBAC鉴权需要用到的资源信息,以及客户端信息等。 4,filters.WithAuthorization根据RequestInfo和RBAC规则,判断请求的合法性,终止或者允许请求继续下去。 代码实现: 1,HandlerChain处理请求 这里可以看到有两个鉴权,一个是pathAuthorizer,一个是RBACAuthorizer,pathAuthorizer定义了哪些URL Path不需要鉴权,RBACAuthorizer顾名思义就是通过RBAC鉴权,后面我们详细介绍这两个鉴权。 var authorizers authorizer.Authorizer switch s.Config.AuthorizationOptions.Mode { case authorization.AlwaysAllow: authorizers = authorizerfactory.NewAlwaysAllowAuthorizer() case authorization.AlwaysDeny: authorizers = authorizerfactory.NewAlwaysDenyAuthorizer() default: fallthrough case authorization.RBAC: excludedPaths := []string{"/oauth/*", "/kapis/config.kubesphere.io/*", "/kapis/version", "/kapis/metrics"} pathAuthorizer, _ := path.NewAuthorizer(excludedPaths) amOperator := am.NewReadOnlyOperator(s.InformerFactory, s.DevopsClient) authorizers = unionauthorizer.New(pathAuthorizer, rbac.NewRBACAuthorizer(amOperator)) } handler = filters.WithAuthorization(handler, authorizers) handler = filters.WithAuthentication(handler, authn) handler = filters.WithRequestInfo(handler, requestInfoResolver) s.

继续阅读

Kubernetes应用系统API用户认证与鉴权 -- 认证篇

前面文章介绍了Kubernetes应用系统用户管理,实现了外部用户存储(LDAP)与Kubernetes用户映射,下面以Kubesphere为参考,一起看一下如何实现Kubernetes应用系统用户的认证。 应用平台用户认证主要实现两个功能: 1,用户身份鉴别 用户身份认证可以通过LDAP进行用户名和密码认证,也可以通过第三方认证服务进行OAuth认证。 2,Token管理 Client端认证通过后,带上获取Token请求API。应用系统根据Token提取用户ID,进行请求权限鉴别。同时应用系统负责Token的生命周期管理。 基本概念: OpenID Connect(OIDC)是基于OAuth 2.0身份认证协议,增加了OAuth 2.0中末定义的规范,例如scope, Claim用户信息字段。 代码实现 基本认证方式 API路由 // legacy auth API legacy := &restful.WebService{} legacy.Path("/aiapis/iam.aiscope/v1alpha2/login"). Consumes(restful.MIME_JSON). Produces(restful.MIME_JSON) legacy.Route(legacy.POST(""). To(handler.login). Deprecate(). Doc("Aiscope APIs support token-based authentication via the Authtoken request header. The POST Login API is used to retrieve the authentication token. After the authentication token is obtained, it must be inserted into the Authtoken header for all requests."). Reads(LoginRequest{}). Returns(http.StatusOK, api.StatusOK, oauth.Token{}). Metadata(restfulspec.

继续阅读

Kubernetes应用平台API开发实战

前面文章介绍了通过基于go-restful框架开发API, client-go生成clientset, informers, listers来读取和写入自定义资源,基于kubebuilder开发CRD资源控制器。今天我们通过一个实例来看一下API整个开发过程。 开发步骤 1,通过kubebuilder来开发CRD控制器 2,通过client-gen,lister-gen,informer-gen生成clientset, informers, listers代码 3,开发models实现CRD资源的kubernets读写操作,读取列表时的排序,分页,过滤 4,开发handler实现CRD资源的API处理 CRD资源的读操作 CRD资源的读操作通过Informer来读取,减少API和Etcd集群的压力。 Informer的主要工作原理为:通过Reflector反射来监听Kubernetes对资源的操作事件,把资源对象和操作类型写入到一个DeltaFIFO的队列中。Reflector消费队列,将资源对象存储到indexer,indexer与Etcd集群的数据完全保持一致。 CRD资源的写操作 CRD资源的写通过client-go的clientset来完成对资源的Create,Update,Patch操作。 代码开发 这里我们需要实现上一篇讲的TrackingServer自定义资源的API。TrackingServer主要用于管理机器学习实验跟踪MLflow在k8s里的实例资源。 创建Informer informerFactories结构体实现了InformerFactory接口,这个接口有两个SharedInformerFactory,一个为Kubernetes资源的informerFactory,一个为本项目自定义资源的aiInformerFactory。aiscopeinformers.NewSharedInformerFactory创建了一个aiInformerFactory实例,这里的NewSharedInformerFactory为代码生成器生成的方法。通过代码生成器创建clientset客户端aiClient,作为参数来创建InformerFactory type InformerFactory interface { KubernetesSharedInformerFactory() k8sinformers.SharedInformerFactory AIScopeSharedInformerFactory() aiscopeinformers.SharedInformerFactory // Start shared informer factory one by one if they are not nil Start(stopCh <-chan struct{}) } type informerFactories struct { informerFactory k8sinformers.SharedInformerFactory aiInformerFactory aiscopeinformers.SharedInformerFactory } func NewInformerFactories(client kubernetes.Interface, aiClient versioned.Interface) InformerFactory { factory := &informerFactories{} if client != nil { factory.informerFactory = k8sinformers.

继续阅读

go-restful框架开发Kubernetes应用平台

go-restful是一个golang语言实现的RESTful库,Kubernetes APIServer使用它实现RESTful API。下面我们一起简单看一下Kubesphere如何使用go-restful的。 Container Container逻辑上是WebService的集合,功能上可以实现多终端的效果。 它包括一组restful.WebService和一个http.ServeMux对象,使用RouteSelector进行请求派发。 Webservice WebService逻辑上是Route的集合,功能上主要是为一组Route统一设置包括root path,请求响应的数据类型等一些通用的属性。 Route 路由包含两种,一种是标准JSR311接口规范的实现RouterJSR311,一种是快速路由CurlyRouter。 CurlyRouter支持正则表达式和动态参数,相比RouterJSR11更加轻量级,apiserver中使用的就是这种路由。 一种Route的设定包含:请求方法(http Method),请求路径(URL Path),输入输出类型(JSON/YAML)以及对应的回掉函数restful.RouteFunction,响应内容类型(Accept)等。 代码示例:一个API聚合服务,包含两种服务,一种是/api, /apis两个路径请求代理给Kubernetes,另一种是本地注册API提供服务。 定义APIServer结构体 type APIServer struct { ServerCount int Server *http.Server Config *apiserverconfig.Config // webservice container, where all webservice defines container *restful.Container KubernetesClient k8s.Client } APIServer构造函数 初始化kubernets Client和http server func (s *ServerRunOptions) NewAPIServer(stopCh <-chan struct{}) (*apiserver.APIServer, error) { apiServer := &apiserver.APIServer{ Config: s.Config, } kubernetesClient, err := k8s.NewKubernetesClient(s.KubernetesOptions) if err != nil { return nil, err } apiServer.

继续阅读