Develop a gRPC-based custom authorization service
Service Mesh (ASM) supports custom authorization services based on HTTP and gRPC protocols. A gRPC-based authorization service receives a gRPC CheckRequest message from Envoy, inspects the request attributes, and returns an allow or deny decision. This guide walks you through implementing such a service and registering it with ASM.
For the overall architecture of custom authorization services, see Develop an HTTP-based custom authorization service.
Unlike an HTTP-based custom authorization service, a gRPC-based service has no header-related configurations. All request headers are embedded directly in the gRPC CheckRequest message from Envoy.
Prerequisites
Before you begin, make sure you have:
A running Container Service for Kubernetes (ACK) cluster connected to ASM
A Go development environment set up locally
Familiarity with Envoy's external authorization API
Implement the authorization server
ASM is compatible with open-source Istio. Istio provides a reference implementation that covers both HTTP and gRPC custom authorization. The gRPC-specific logic lives 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 Envoy AuthorizationServer interface, which requires a single method:
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)
}Core authorization logic
The Check method extracts request attributes, evaluates them, and returns an allow or deny response:
// 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 decision follows two paths:
Header-based check -- If the request contains the
checkHeaderheader, the service compares its value againstallowedValue. A match grants access.Identity-based fallback -- If the header is absent, the service checks whether the source identity (
attrs.Source.Principal) ends with/sa/<serviceAccount>. This allows requests from a specific Kubernetes service account.
CheckRequest fields reference
For the full list of fields in authv3.CheckRequest, see:
API version
Envoy has deprecated v2 APIs. Implement only the v3 gRPC API as shown in the Check method signature above.
Register and apply the authorization service
After you deploy the authorization service to your ACK cluster:
Open the ASM console and go to the Define Custom Authorization Service page.
Register the gRPC-based authorization service.
Create an authorization policy that specifies which mesh proxy uses the authorization service.
For detailed steps, see Implement custom authorization by using the gRPC protocol.
What's next
Implement custom authorization by using the gRPC protocol -- End-to-end setup and configuration.
Develop an HTTP-based custom authorization service -- Alternative approach using HTTP instead of gRPC.