Skip to content

[GRPCRoute] gRPC Well-Known Attributes #584

@mikenairn

Description

@mikenairn

Task 11: gRPC Well-Known Attributes

Parent epic: Kuadrant/architecture#156
RFC: 0017-grpcroute-support.md

What

Extract grpc.service and grpc.method from gRPC requests and add to authorization JSON for use in OPA policies, CEL authorization rules, and other evaluators.

Why

When GRPCRoute support is added to Kuadrant, policy authors need access to gRPC-specific well-known attributes in Authorino evaluators, not just in WASM CEL predicates.

Example use case:

apiVersion: authorino.kuadrant.io/v1beta3
kind: AuthConfig
spec:
  authorization:
    opa:
      rego: |
        allow {
          input.grpc.service == "UserService"
          input.grpc.method != "DeleteUser"
        }

Without this change, input.grpc.service and input.grpc.method won't exist in the authorization JSON.

Done

  • Add GRPCAttributes struct with service and method fields
  • Add grpc field to RequestAttributes struct
  • Implement gRPC request detection via content-type: application/grpc header
  • Implement path parsing for /Service/Method format in newRequestAttributes()
  • Attributes return nil for non-gRPC requests
  • Attributes return nil if path format doesn't match gRPC pattern
  • Unit tests for gRPC attribute extraction
  • Unit tests for non-gRPC requests (grpc field should be nil)
  • Integration tests verifying gRPC attributes are available in authorization JSON

Notes

This task can be developed in parallel with operator work (Tasks 3-7). Authorino's well-known attribute extraction is independent of the operator implementation.

Key files:

  • pkg/service/well_known_attributes.go - Well-known attributes implementation
  • pkg/service/auth_pipeline.go - Authorization JSON generation
  • pkg/service/well_known_attributes_test.go - Unit tests

Implementation approach (similar to PR #428):

type GRPCAttributes struct {
    Service string `json:"service,omitempty"`
    Method  string `json:"method,omitempty"`
}

type RequestAttributes struct {
    // ... existing fields ...
    GRPC *GRPCAttributes `json:"grpc,omitempty"`
}

func newRequestAttributes(attributes *envoyauth.AttributeContext) *RequestAttributes {
    request := attributes.GetRequest()
    httpRequest := request.GetHttp()
    urlParsed, _ := url.Parse(httpRequest.Path)
    headers := httpRequest.GetHeaders()
    
    var grpcAttrs *GRPCAttributes
    if isGRPCRequest(headers) {
        grpcAttrs = parseGRPCPath(urlParsed.Path)
    }
    
    return &RequestAttributes{
        // ... existing fields ...
        GRPC: grpcAttrs,
    }
}

func isGRPCRequest(headers map[string]string) bool {
    contentType := headers["content-type"]
    return strings.HasPrefix(contentType, "application/grpc")
}

func parseGRPCPath(path string) *GRPCAttributes {
    parts := strings.Split(strings.TrimPrefix(path, "/"), "/")
    if len(parts) == 2 {
        return &GRPCAttributes{
            Service: parts[0],
            Method:  parts[1],
        }
    }
    return nil
}

Reference: PR #428 added the initial well-known attributes support using the same pattern.

Critical: These attributes are optional. Authorino continues to work for HTTP and gRPC traffic without these attributes. They provide additional context for evaluators to make more granular authorization decisions.

Testing coverage:

  • Path parsing: /Service/Method, /Package.Service/Method, malformed paths
  • Content-type detection: application/grpc, application/grpc+proto, application/json
  • HTTP vs gRPC: grpc field should be nil for HTTP requests
  • Integration: Verify attributes appear in authorization JSON for OPA/CEL evaluators

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    Status

    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions