External Authorization这功能主要拿来做request的验证,可以在request里面加了一个header进行判断,
如果有符合的header与value时才会让request导流到後端服务。
有些行为不能直接从request ban掉时,可以透过External Authorization进行加工处理,做到ban ban的动作,这些要怎麽操作就看人啦~~
kubectl edit configmap istio -n istio-system
data:
mesh: |-
# Add the following content to define the external authorizers.
extensionProviders: #可以分成http/gRPC二种,这边的还是以gRPC为主
- name: "sample-ext-authz-grpc" #名称後续会用到,要设定一致
envoyExtAuthzGrpc:
service: "ext-authz.foo.svc.cluster.local" #external service路径
port: "9000"
- name: "sample-ext-authz-http"
envoyExtAuthzHttp:
service: "ext-authz.foo.svc.cluster.local"
port: "8000"
includeHeadersInCheck: ["x-ext-authz"]
重启istiod,重新载入configMap
kubectl rollout restart deployment/istiod -n istio-system
可以参考这个作法 grpc_server
主要是透过这几个lib处理,分成v2跟v3版本
corev2 "github.com/envoyproxy/go-control-plane/envoy/api/v2/core"
corev3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
authv2 "github.com/envoyproxy/go-control-plane/envoy/service/auth/v2"
authv3 "github.com/envoyproxy/go-control-plane/envoy/service/auth/v3"
typev2 "github.com/envoyproxy/go-control-plane/envoy/type"
typev3 "github.com/envoyproxy/go-control-plane/envoy/type/v3"
启动gRPC server时要做这件事情,不然不会做authzore
authv2.RegisterAuthorizationServer(grpc, &extAuthzServerV2{})
authv3.RegisterAuthorizationServer(grpc, &extAuthzServerV3{})
重点就是这个部份啦,这边定义了什麽条件才能http 200,什麽条件 403,再依自己的需求进行调整
func (a *AuthorizationServer) Check(ctx context.Context, req *auth.CheckRequest) (*auth.CheckResponse, error) {
log.Println(">>> Authorization called check()")
authHeader, ok := req.Attributes.Request.Http.Headers["authorization"]
if !ok {
return returnUnAuthenticated("Unable to find Authorization Header"), nil
}
var splitToken []string
log.Printf("Authorization Header %s", authHeader)
if ok {
splitToken = strings.Split(authHeader, "Bearer ")
} else {
log.Println("Unable to parse Header")
return returnUnAuthenticated("Unable to parse Authorization Header"), nil
}
if len(splitToken) == 2 {
token := splitToken[1]
if stringInSlice(token, strings.Split(AUTHZ_ALLOWED_USERS, ",")) {
var aud []string
if token == "alice" {
aud = []string{"http://svc1.default.svc.cluster.local:8080/", "http://be.default.svc.cluster.local:8080/"}
} else if token == "bob" {
aud = []string{"http://svc2.default.svc.cluster.local:8080/"}
} else if token == "carol" {
aud = []string{"http://svc1.default.svc.cluster.local:8080/"}
} else {
aud = []string{}
}
claims := MyCustomClaims{
token,
aud,
jwt.StandardClaims{
Issuer: AUTHZ_ISSUER,
Subject: AUTHZ_ISSUER,
//Audience: aud,
IssuedAt: time.Now().Unix(),
ExpiresAt: time.Now().Add(time.Minute * 1).Unix(),
},
}
log.Println("Using Claim %v", claims)
token := jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
token.Header["kid"] = AUTHZ_SERVER_KEY_ID
ss, err := token.SignedString(privateKey)
if err != nil {
return returnUnAuthenticated("Unable to generate JWT"), nil
}
log.Printf("Issuing outbound Header %s", ss)
return &auth.CheckResponse{
Status: &rpcstatus.Status{
Code: int32(rpc.OK),
},
HttpResponse: &auth.CheckResponse_OkResponse{
OkResponse: &auth.OkHttpResponse{
Headers: []*core.HeaderValueOption{
{
Header: &core.HeaderValue{
Key: "Authorization",
Value: "Bearer " + ss,
},
},
},
},
},
}, nil
} else {
log.Printf("Authorization Header missing")
return returnPermissionDenied("Permission Denied"), nil
}
}
return returnUnAuthenticated("Authorization header not provided"), nil
}
前面的动作都完成了,剩下最一步部署EnvoyFilter
,这边其实跟Rate Limits很雷同,一样是定义名称,指定grpc服务路径,done
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: my-ext-authz
namespace: istio-system
spec:
workloadSelector:
labels:
istio: ingressgateway
configPatches:
- applyTo: HTTP_FILTER
match:
context: GATEWAY
listener:
filterChain:
filter:
name: "envoy.http_connection_manager"
subFilter:
name: "envoy.router"
patch:
operation: INSERT_BEFORE
value:
name: envoy.filters.http.ext_authz
typed_config:
"@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz"
failure_mode_allow: true
grpc_service:
envoy_grpc:
cluster_name: ext_cluster_grpc
timeout: 0.5s
- applyTo: CLUSTER
match:
cluster:
service: test-ext.dev-xbb.svc.cluster.local
patch:
operation: ADD
value:
name: ext_cluster_grpc
type: STRICT_DNS
connect_timeout: 1s
lb_policy: ROUND_ROBIN
http2_protocol_options: {}
load_assignment:
cluster_name: ext_cluster_grpc
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: test-ext.dev-xbb.svc.cluster.local
port_value: 9000
以上步骤完成之後就可以实作出External Authorization罗
>>: 自动化测试,让你上班拥有一杯咖啡的时间 | Day 20 - invoke 的用法
node.js 之所以能够运行 JavaScript 程序码,是因为底层依赖 google 在 ch...
昨天我们完成了 user sheet 的 query & upsert 功能,今天就要正式将...
Laravel 文件中有跟我们介绍一个 request 的生命周期,也就是诞生到结束在 Larave...
说明 我在本系列文章中,主要是采用 IntelliJ-IDEA 作为示范。但我不会在文章中跟你讲述如...
在上一篇我们看到,即便我们能不写程序就设定一些自动回覆,仍然相当麻烦,如果需要的功能更多,更无法应付...