Istio 实现 ext-authz 内部扩大鉴权以及对接基于 k8s 的微服务
能够实现基于 redis
的 token
鉴权以及实现 rbac
鉴权。
转载请注明起源:https://janrs.com/vrsr
Istio
的内部鉴权实质是基于 Envoy
实现的,间接看 Envoy
的代码,链接地址:点击主动跳转
Isio
官网的 Demo
代码,链接:点击主动跳转
实现
Istio
提供了基于 HTTP
形式以及 Grpc
形式的内部鉴权扩大,这里这实现了 Grpc
。
配置
批改 Istio
的 Configmap
配置。在 mesh
字段上面增加以下代码配置:
extensionProviders: - name: "rgrpc-dev-authz-grpc-provider" envoyExtAuthzGrpc: service: "auth.rgrpc-dev.svc.cluster.local" port: 50051
截图如下
创立 Istio
鉴权 Grpc
服务
实质上,Istio
的内部鉴权是基于 Evnoy
实现,只须要实现了 Envoy
的 Grpc
办法后 Istio
就会主动调用。
须要实现的 Envoy
的 external_auth.pb.go
文件 链接:点击主动跳转
只须要实现外面的 Check
办法即可。Envoy
官网提供了 v2
以及 v3
代码的实现,这里我只实现了 v3
的接口。
写好代码后将服务做成镜像部署到 k8s
。
案例代码如下:
package serverV1import ( "encoding/json" authv3 "github.com/envoyproxy/go-control-plane/envoy/service/auth/v3" typev3 "github.com/envoyproxy/go-control-plane/envoy/type/v3" "github.com/go-kit/log" "github.com/go-kit/log/level" "github.com/redis/go-redis/v9" "google.golang.org/genproto/googleapis/rpc/status" "google.golang.org/grpc/codes" "authservice/config" "golang.org/x/net/context")type Server struct { authv3.UnimplementedAuthorizationServer conf *config.Config redis *redis.Client repo *Repository logger log.Logger}func NewServer( conf *config.Config, redis *redis.Client, repo *Repository, logger log.Logger,) authv3.AuthorizationServer { return &Server{ conf: conf, redis: redis, repo: repo, logger: logger, }}var ( UnauthorizedMsg = "没有权限" ForbiddenMsg = "没有权限")// Response 返回 HTTP Body 数据type Response struct { Code int64 `json:"code"` Msg string `json:"msg"` Data struct{} `json:"data"`}// Check istio-grpc 内部鉴权办法func (s *Server) Check(ctx context.Context, req *authv3.CheckRequest) (*authv3.CheckResponse, error) { // 以下是我的逻辑代码。能够全副删除而后自行批改 attrs := req.GetAttributes() httpHeaders := attrs.GetRequest().GetHttp().GetHeaders() // 获取申请门路 path, exists := httpHeaders[":path"] if !exists { _ = level.Info(s.logger).Log("msg", "获取不到 :path 字段") return s.Unauthorized(), nil } // 判断是否是白名单 if s.repo.IsWhiteListApi(path) { return s.Allow(), nil } // 获取头部 token token, exists := httpHeaders["authorization"] duration := 7 * 24 * 60 * 60 if !exists { _ = level.Info(s.logger).Log("msg", "未传递头部 authorization 字段") return s.Unauthorized(), nil } // 去除头部 "Bearer "字符串 if len(token) <= 7 { _ = level.Info(s.logger).Log("msg", "authorization 数据格式谬误。没有设置 Bearer 前缀") return s.Unauthorized(), nil } // 截取前面的 token 字符串 token = token[7:] // 验证 token if err := s.repo.GetAuthentication(ctx, token, int64(duration)); err != nil { _ = level.Info(s.logger).Log("msg", "access token 不存在") return s.Unauthorized(), nil } return s.Allow(), nil}// Allow 通过鉴权。返回 200func (s *Server) Allow() *authv3.CheckResponse { return &authv3.CheckResponse{ Status: &status.Status{Code: int32(codes.OK)}, HttpResponse: &authv3.CheckResponse_OkResponse{ OkResponse: &authv3.OkHttpResponse{}, }, }}// Unauthorized Unauthorized 未受权 401func (s *Server) Unauthorized() *authv3.CheckResponse { resp := &Response{ Code: int64(typev3.StatusCode_Unauthorized), Msg: UnauthorizedMsg, Data: struct{}{}, } respJson, err := json.Marshal(resp) httpBody := "" if err == nil { httpBody = string(respJson) } return &authv3.CheckResponse{ Status: &status.Status{Code: int32(codes.Unauthenticated)}, HttpResponse: &authv3.CheckResponse_DeniedResponse{ DeniedResponse: &authv3.DeniedHttpResponse{ Status: &typev3.HttpStatus{Code: typev3.StatusCode_Unauthorized}, Body: httpBody, }, }, }}// Forbidden Forbidden 没有权限 403func (s *Server) Forbidden() *authv3.CheckResponse { resp := &Response{ Code: int64(typev3.StatusCode_Forbidden), Msg: ForbiddenMsg, Data: struct{}{}, } respJson, err := json.Marshal(resp) httpBody := "" if err == nil { httpBody = string(respJson) } return &authv3.CheckResponse{ Status: &status.Status{Code: int32(codes.PermissionDenied)}, HttpResponse: &authv3.CheckResponse_DeniedResponse{ DeniedResponse: &authv3.DeniedHttpResponse{ Status: &typev3.HttpStatus{Code: typev3.StatusCode_Forbidden}, Body: httpBody, }, }, }}
创立 Istio
的 AuthorizationPolicy
最初设置 Istio
的 AuthorizationPolicy
。设置后,所有通过 Istio
网关的申请都会自行被拦挡,而后调用部署好的 Grpc
鉴权服务进行鉴权。
须要留神的是:provider
须要跟下面Istio
的Configmap
中的extensionProviders.name
字段的值对应上才会调用到配置中的Grpc
地址
应用的是 CUSTOM
配置,配置如下:
apiVersion: security.istio.io/v1kind: AuthorizationPolicymetadata: name: rgrpc-ext-authz namespace: rgrpc-devspec: action: CUSTOM provider: name: rgrpc-dev-authz-grpc-provider rules: - to: - operation: hosts: - api.your-domain.com:31380
转载请注明起源:https://janrs.com/vrsr