Skip to content

[GRPCRoute] gRPC Well-Known Attributes #317

@mikenairn

Description

@mikenairn

Task 10: gRPC Well-Known Attributes

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

What

Implement grpc.service and grpc.method well-known attributes in the WASM shim to improve UX when writing policy conditions and rate limit counters for gRPC traffic. Update RFC 0002 specification to document the new attributes.

Why

While GRPCRoute support works using request.url_path patterns (e.g., request.url_path == '/UserService/GetUser'), policy authors benefit from dedicated attributes for better readability and easier policy authoring:

# Instead of:
when:
  - predicate: request.url_path == '/UserService/GetUser'

# Policy authors can write:
when:
  - predicate: grpc.service == 'UserService'
  - predicate: grpc.method == 'GetUser'

Done

wasm-shim Implementation

  • Implement gRPC request detection via content-type: application/grpc header
  • Implement path parsing for /Service/Method format
  • Register grpc.service well-known attribute
  • Register grpc.method well-known attribute
  • Attributes return empty string for non-gRPC requests
  • Attributes return empty string if path format doesn't match gRPC pattern
  • Unit tests for path parsing (exact service+method, service-only, method-only)
  • Unit tests for gRPC detection via content-type header
  • Unit tests verifying attributes are empty for HTTP requests
  • Integration tests with actual gRPC traffic

RFC 0002 Updates

  • Add "gRPC Well-Known Attributes" section to RFC 0002
  • Document grpc.service attribute with type, description, examples
  • Document grpc.method attribute with type, description, examples
  • Document behavior with non-gRPC requests (empty string return value)
  • Document best practices for mixed HTTP/gRPC traffic
  • Add implementation notes referencing WASM shim

Notes

This task can be developed in parallel with operator work (Tasks 3-7). The WASM shim implementation is independent, and the kuadrant-operator continues using request.url_path patterns internally.

Key files (wasm-shim):

  • src/data/attribute.rs - Well-known attributes implementation
  • src/filter/http_context.rs - HTTP filter context with header access
  • src/data/cel.rs - CEL expression evaluation

Implementation approach:

// Detect gRPC requests
fn is_grpc_request(&self) -> bool {
    self.get_http_request_header("content-type")
        .map(|ct| ct.starts_with("application/grpc"))
        .unwrap_or(false)
}

// Parse path to extract service and method
fn extract_grpc_service_method(path: &str) -> Option<(String, String)> {
    let parts: Vec<&str> = path.trim_start_matches('/').split('/').collect();
    if parts.len() == 2 {
        Some((parts[0].to_string(), parts[1].to_string()))
    } else {
        None
    }
}

Critical: These attributes are optional for policy authors. All existing predicates using request.url_path continue to work. The kuadrant-operator internal predicate generation continues using request.url_path to avoid hard dependency on this task.

No changes needed in kuadrant-operator: The operator continues generating predicates using request.url_path patterns. These well-known attributes are UX conveniences for policy authors writing custom when conditions and rate limit counters, not for internal operator use.

Edge case handling:

  • Empty string return value for non-gRPC requests is intentional
  • Documentation must warn about negation logic pitfalls (e.g., grpc.service != 'AdminService' matches all HTTP traffic)
  • Recommend protocol checks for Gateway-level policies with mixed HTTP/gRPC traffic:
    when:
      - predicate: request.headers['content-type'].startsWith('application/grpc')
      - predicate: grpc.service == 'UserService'
  • For route-level policies targeting GRPCRoute directly, protocol check is unnecessary

Testing coverage:

  • Path parsing: /Service/Method, /Package.Service/Method, malformed paths
  • Content-type detection: application/grpc, application/grpc+proto, application/json
  • HTTP vs gRPC: Attributes should be empty for HTTP requests
  • Negation logic: Verify behavior of grpc.service != 'X' for HTTP traffic
  • Integration: Real gRPC traffic using grpcbin backend (from Task 2)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    Status

    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions