grpc/grpc-go · error

rbac: Policy.condition is present

Error message

rbac: Policy.condition is present

What it means

When the RBAC HTTP filter parses its config (internal/xds/httpfilter/rbac/rbac.go:59, parseConfig), it enforces gRFC A41: the `condition` field of an RBAC Policy is not supported by gRPC and must cause a validation failure if present. The check at line 64-66 returns this error for any policy whose `Condition` is non-nil. gRPC deliberately rejects CEL-based conditions because the gRPC RBAC engine does not evaluate CEL expressions.

Solutions

  1. Remove the `condition` field from any RBAC policy that will be consumed by gRPC clients — express the same logic via permissions/principals matchers instead.
  2. If the policy must keep the condition for Envoy, scope it (e.g. via RBACPerRoute or a separate filter chain) so it does not reach gRPC.
  3. Upgrade the control plane to a version that omits `condition` for gRPC-targeted policies, or filter it at the xDS server.

Example fix

// before (Envoy/Istio RBAC policy)
policies:
  p1:
    condition: "request.host == 'x'"
    permissions: [...]

// after: express via principal/permission matchers only
policies:
  p1:
    permissions:
      - any: true
    principals:
      - header: { name: "host", exactMatch: "x" }
Defensive patterns

Strategy: validation

Validate before calling

// Validate an RBAC policy proto before it is sent on to gRPC clients.
func validateRBACPolicyForGRPC(rbac *rpb.RBAC) error {
    for name, p := range rbac.GetRules().GetPolicies() {
        if p.GetCondition() != nil {
            return fmt.Errorf("policy %q: gRPC does not support Policy.condition", name)
        }
        // also see error 73 for CheckedCondition
    }
    return nil
}

Prevention

When it happens

Trigger: Triggered when an xDS server delivers an RBAC HTTP filter config (envoy.extensions.filters.http.rbac.v3.RBAC) whose Rules.Policies entry has a non-nil `condition` field. The error surfaces during xDS resource processing, NACKing the response.

Common situations: An Envoy/Istio configuration authored for Envoy that uses CEL `condition` blocks is applied to a gRPC client; a control-plane policy written without awareness of gRPC's A41 restrictions; sharing an RBAC policy between Envoy sidecars and gRPC xDS clients.

Related errors


AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11). Data as JSON: /api/errors/51eb67bae2ad6a48. Report an issue: GitHub.

Appendix: source

Thrown at internal/xds/httpfilter/rbac/rbac.go:65

	httpfilter.FilterConfig
	chainEngine *rbac.ChainEngine
}

func (builder) TypeURLs() []string {
	return []string{
		"type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC",
		"type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBACPerRoute",
	}
}

// Parsing is the same for the base config and the override config.
func parseConfig(rbacCfg *rpb.RBAC) (httpfilter.FilterConfig, error) {
	// All the validation logic described in A41.
	for _, policy := range rbacCfg.GetRules().GetPolicies() {
		// "Policy.condition and Policy.checked_condition must cause a
		// validation failure if present." - A41
		if policy.Condition != nil {
			return nil, errors.New("rbac: Policy.condition is present")
		}
		if policy.CheckedCondition != nil {
			return nil, errors.New("rbac: policy.CheckedCondition is present")
		}

		// "It is also a validation failure if Permission or Principal has a
		// header matcher for a grpc- prefixed header name or :scheme." - A41.
		//
		// "Envoy aliases :authority and Host in its header map implementation,
		// so they should be treated equivalent for the RBAC matchers; there must
		// be no behavior change depending on which of the two header names is
		// used in the RBAC policy." - A41. Any header matcher with value "host"
		// is rewritten to ":authority", as that is what grpc-go shifts both
		// headers to in the transport layer.
		//
		// Both rules apply to header matchers nested inside and/or/not rules, so
		// the whole permission and principal trees are walked.
		for _, principal := range policy.GetPrincipals() {

View on GitHub (pinned to 0c51461d27)