Skip to content

Implement HTTP RBAC for Waypoint Replacement #119

@Eeshu-Yadav

Description

@Eeshu-Yadav

title: 'Implement HTTP RBAC with SPIFFE Principal Authentication'

Problem

Orion needs HTTP RBAC with SPIFFE principal authentication to replace Kmesh's Envoy waypoint. Currently:

  • ✅ RBAC parser exists, 403 responses work
  • ❌ Missing: Extract SPIFFE ID from mTLS certificates
  • ❌ Missing: Principal::Authenticated matching for Istio AuthorizationPolicy

Istio uses mTLS to identify workloads via SPIFFE IDs embedded in X.509 certificates. AuthorizationPolicies specify which services can communicate:

apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: allow-reviews
spec:
  action: ALLOW
  rules:
  - from:
    - source:
        principals: ["cluster.local/ns/default/sa/productpage"]
    to:
    - operation:
        methods: ["GET"]

This translates to: Only the productpage service can make GET requests.

Envoy receives this as xDS configuration:

- name: envoy.filters.http.rbac
  typed_config:
    rules:
      action: ALLOW
      policies:
        "allow-reviews":
          permissions:
          - any: true
          principals:
          - authenticated:
              principal_name:
                exact: "cluster.local/ns/default/sa/productpage"

Orion must:

  1. Extract the caller's SPIFFE ID from their mTLS certificate
  2. Match it against the authenticated.principal_name policy
  3. Deny requests (403) that don't match

Required Changes

1. Add Principal::Authenticated Variant

File: orion-configuration/.../http_rbac.rs

pub enum Principal {
    Any,
    Header(HeaderMatcher),
    Authenticated { principal_name: StringMatcher },  // NEW
}

Update: has_principal(), Policy::enforce(), HttpRbac::is_permitted() to accept peer_principal: Option<&str>

2. Extract SPIFFE ID from Certificate

  • Add dependency: x509-parser = "0.16"
  • Parse X.509 SAN URI: spiffe://cluster.local/ns/default/sa/productpagecluster.local/ns/default/sa/productpage
  • Hook into Rustls ServerConnection::peer_certificates() after TLS handshake

3. Store in Connection Metadata

File: orion-lib/src/listeners/filter_state.rs

pub struct DownstreamMetadata {
    pub peer_principal: Option<CompactString>,  // NEW
    // ... existing fields
}

4. Pass to HTTP Filters

File: orion-lib/src/listeners/http_connection_manager.rs

  • Update apply_authorization_rules() signature: add peer_principal: Option<&str>
  • Extract from metadata: downstream_metadata.peer_principal.as_deref()

5. Add Metrics

metrics::increment_counter!("http_rbac_allowed_total");
metrics::increment_counter!("http_rbac_denied_total");

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions