Service Mesh (ASM) supports comprehensive authentication and authorization configurations. It provides flexible extension capabilities, such as custom authorization services based on HTTP and gRPC and the authorization process. This topic describes how to develop a gRPC-based custom authorization service.
Background information
The architecture of a custom authorization service is described in Develop an HTTP-based custom authorization service. Different from an HTTP-based custom authorization service, the message received by a gRPC-based custom authorization service is not an HTTP request, but a gRPC message that is specific to Envoy. The custom authorization service determines whether to allow the request based on the information provided by Envoy.
Configuration introduction
In the ASM console, you can register a custom authorization service on the Define Custom Authorization Service page. After the registration, you can specify the mesh proxy that will use the authorization service in the authorization policy. For more information, see Use the gRPC protocol to connect to the custom authorization service.
Compared with the HTTP-based custom authorization service, the gRPC-based custom authorization service has no header-related configurations. All headers can be directly obtained from the gRPC-based authentication request.
Develop a gRPC-based custom authorization service
ASM is compatible with the open source Istio. The open source Istio provides development examples of custom authorization services. This part of code implements custom authorization services for both HTTP and gRPC protocols. The main logic of a gRPC-based custom authorization service mentioned in this topic is defined in the extAuthzServerV3
struct:
type extAuthzServerV3 struct{}
func (s *extAuthzServerV3) Check(_ context.Context, request *authv3.CheckRequest) (*authv3.CheckResponse, error)
func (s *extAuthzServerV3) allow(request *authv3.CheckRequest) *authv3.CheckResponse
func (s *extAuthzServerV3) deny(request *authv3.CheckRequest) *authv3.CheckResponse
func (s *extAuthzServerV3) logRequest(allow string, request *authv3.CheckRequest)
This struct implements the AuthorizationServer
API, which is defined in the following code:
type AuthorizationServer interface {
// Performs authorization check based on the attributes associated with the
// incoming request, and returns status `OK` or not `OK`.
Check(context.Context, *CheckRequest) (*CheckResponse, error)
}
The main logic is implemented by the Check function:
// Check implements gRPC v3 check request.
func (s *extAuthzServerV3) Check(_ context.Context, request *authv3.CheckRequest) (*authv3.CheckResponse, error) {
attrs := request.GetAttributes()
// Determine whether to allow or deny the request.
allow := false
checkHeaderValue, contains := attrs.GetRequest().GetHttp().GetHeaders()[checkHeader]
if contains {
allow = checkHeaderValue == allowedValue
} else {
allow = attrs.Source != nil && strings.HasSuffix(attrs.Source.Principal, "/sa/"+*serviceAccount)
}
if allow {
return s.allow(request), nil
}
return s.deny(request), nil
}
The Check function checks the header of a request and returns the result of the allow function if the header value is allowedValue
. If this header does not exist, the Check function checks whether the value of attrs.Source.Principal
is a preset value.
For more information about the fields in authv3.CheckRequest
, see the description of Envoy Proto or Envoy go-control-plane.
The sample code provided by Istio also contains an extAuthzServerV2
struct. Envoy has deprecated V2-related APIs. You need to only implement the V3 gRPC API mentioned in the declaration of the Check function.
Configure a custom authorization service
After you deploy the custom authorization service developed in the previous step in the ACK cluster, you can access the custom authorization service. For more information, see Implement custom authorization by using the gRPC protocol.