Files
OpenShell/proto/gateway_interceptor.proto
Drew Newberry 83003e80fc feat(interceptors): initial gateway interceptor implementation and reference example (#2005)
* feat(gateway): add descriptor-driven interceptors

Signed-off-by: Drew Newberry <anewberry@nvidia.com>

* feat(gateway): add service-reflected interceptors

Signed-off-by: Drew Newberry <anewberry@nvidia.com>

* wip

* fix(gateway): harden interceptor evaluation

Signed-off-by: Drew Newberry <anewberry@nvidia.com>

* feat(interceptors): label metrics and harden governance smoke

Signed-off-by: Drew Newberry <anewberry@nvidia.com>

* remove on_error: ignore

* feat(gateway-interceptors): emit log annotations

Signed-off-by: Drew Newberry <anewberry@nvidia.com>

* feat(examples): govern provider profiles in interceptor

Signed-off-by: Drew Newberry <anewberry@nvidia.com>

* fix(gateway): preserve update config annotations

Signed-off-by: Drew Newberry <anewberry@nvidia.com>

* feat(providers): support interceptor profile catalogs

Signed-off-by: Drew Newberry <anewberry@nvidia.com>

* wip

* feat(governance-interceptor): sign provider profiles

Signed-off-by: Drew Newberry <anewberry@nvidia.com>

* fix(providers): use configured profile sources for refresh updates

Signed-off-by: Drew Newberry <anewberry@nvidia.com>

* feat(gateway-interceptors): add phase-specific evaluation payloads

Signed-off-by: Drew Newberry <anewberry@nvidia.com>

* feat(providers): compose provider profile sources

Signed-off-by: Drew Newberry <anewberry@nvidia.com>

* fix(gateway-interceptors): preserve committed responses

Signed-off-by: Drew Newberry <anewberry@nvidia.com>

* fix(gateway-interceptors): reject ambiguous protobuf oneofs

Signed-off-by: Drew Newberry <anewberry@nvidia.com>

* fix(gateway-interceptors): validate patch candidates per binding

Signed-off-by: Drew Newberry <anewberry@nvidia.com>

* refactor(gateway-interceptors): use reflected protobuf codec

Signed-off-by: Drew Newberry <anewberry@nvidia.com>

* fix(governance-example): canonicalize signed protobuf hashes

Signed-off-by: Drew Newberry <anewberry@nvidia.com>

* fix(gateway): commit policy provenance atomically

Signed-off-by: Drew Newberry <anewberry@nvidia.com>

* fix(gateway): close signed governance bypasses

Signed-off-by: Drew Newberry <anewberry@nvidia.com>

* fix(gateway): isolate interceptor secrets and authority

Signed-off-by: Drew Newberry <anewberry@nvidia.com>

* fix(gateway): snapshot provider profiles per request

Signed-off-by: Drew Newberry <anewberry@nvidia.com>

* chore(gateway): resolve server clippy warnings

Signed-off-by: Drew Newberry <anewberry@nvidia.com>

* fix(server): satisfy provider source clippy lint

Signed-off-by: Drew Newberry <anewberry@nvidia.com>

* fix(server): initialize policy test annotations

Signed-off-by: Drew Newberry <anewberry@nvidia.com>

* fix(gateway-interceptors): require explicit route allowlist

Signed-off-by: Drew Newberry <anewberry@nvidia.com>

* docs(proto): clarify update annotation semantics

Signed-off-by: Drew Newberry <anewberry@nvidia.com>

---------

Signed-off-by: Drew Newberry <anewberry@nvidia.com>
2026-07-14 20:58:36 -07:00

140 lines
4.9 KiB
Protocol Buffer

// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
syntax = "proto3";
package openshell.gateway_interceptor.v1;
import "google/protobuf/struct.proto";
import "openshell.proto";
// GatewayInterceptor lets an external governance service evaluate gateway
// control-plane operations after OpenShell admission and before or after the
// gateway applies the operation.
service GatewayInterceptor {
// Describe returns the interceptor manifest and declared bindings.
rpc Describe(DescribeRequest) returns (InterceptorManifest);
// SnapshotProviderProfiles returns the interceptor's current provider
// profile snapshot when the manifest advertises provider_profiles = true.
rpc SnapshotProviderProfiles(ProviderProfileSnapshotRequest)
returns (ProviderProfileSnapshot);
// Evaluate returns an allow, deny, or mutation decision for one operation
// phase.
rpc Evaluate(InterceptorEvaluation) returns (InterceptorResult);
}
message DescribeRequest {}
message ProviderProfileSnapshotRequest {}
enum GatewayInterceptorPhase {
GATEWAY_INTERCEPTOR_PHASE_UNSPECIFIED = 0;
GATEWAY_INTERCEPTOR_PHASE_MODIFY_OPERATION = 2;
GATEWAY_INTERCEPTOR_PHASE_VALIDATE = 3;
GATEWAY_INTERCEPTOR_PHASE_POST_COMMIT = 4;
}
message InterceptorEvaluation {
// Configured interceptor instance name.
string interceptor_name = 1;
// Manifest binding id selected for this evaluation.
string binding_id = 2;
// Public gRPC service name, e.g. "openshell.v1.OpenShell".
string service = 3;
// Public gRPC method name, e.g. "CreateSandbox".
string method = 4;
// Caller identity summary. Values are intentionally non-secret.
map<string, string> principal = 5;
// Exactly one phase payload is set for each evaluation.
oneof phase {
// Evaluation that may modify the prepared gateway operation.
ModifyOperationEvaluation modify_operation = 6;
// Evaluation that may reject, but not mutate, the prepared operation.
ValidateEvaluation validate = 7;
// Evaluation after the gateway operation has completed successfully.
PostCommitEvaluation post_commit = 8;
}
}
message ModifyOperationEvaluation {
// Gateway-prepared operation the gateway proposes to execute.
google.protobuf.Struct proposed_operation = 1;
}
message ValidateEvaluation {
// Gateway-prepared operation after earlier interceptor modifications.
google.protobuf.Struct proposed_operation = 1;
// Optional read-only gateway state loaded before applying the operation.
google.protobuf.Struct current_state = 2;
}
message PostCommitEvaluation {
// Protobuf JSON-shaped response returned by the committed gateway operation.
google.protobuf.Struct committed_response = 1;
}
message InterceptorResult {
// False denies the operation before side effects for modify_operation and
// validate. Post-commit denial is invalid.
bool allowed = 1;
// Human-readable reason for logs and denied gRPC status messages.
string reason = 2;
// Optional gRPC status code name for denials, e.g. "PERMISSION_DENIED".
string status_code = 3;
// RFC 6902 JSON patches. Only valid during modify_operation.
repeated JsonPatch patches = 4;
// Non-secret annotations included in gateway logs.
map<string, string> log_annotations = 5;
}
message InterceptorManifest {
// Human-readable interceptor name declared by the service.
string name = 1;
// Bindings declared by the interceptor service.
repeated InterceptorBinding bindings = 2;
// Optional default failure policy for bindings without their own policy.
// Supported values are "fail_closed" and "fail_open".
string failure_policy = 3;
// True when this interceptor implements SnapshotProviderProfiles.
bool provider_profiles = 4;
}
message ProviderProfileSnapshot {
// Opaque source revision used for cache freshness and sandbox reload checks.
string revision = 1;
// Complete profile snapshot vended by this source.
repeated openshell.v1.ProviderProfile profiles = 2;
}
message InterceptorBinding {
// Stable binding id used for config overrides and audit logs.
string id = 1;
// RPC selector. Selectors are intentionally tied to the public API shape.
InterceptorSelector selector = 2;
// Phases this binding wants to evaluate.
repeated GatewayInterceptorPhase phases = 3;
// Optional binding-specific failure policy.
// Supported values are "fail_closed" and "fail_open".
// Bindings that include post_commit must resolve to "fail_open" because the
// gateway operation has already committed before that phase runs.
string failure_policy = 4;
}
message InterceptorSelector {
// Full selector form: "openshell.v1.OpenShell/CreateSandbox".
string rpc = 1;
// Structured service/method form. If rpc is set, it takes precedence.
string service = 2;
string method = 3;
}
message JsonPatch {
string op = 1;
string path = 2;
google.protobuf.Value value = 3;
string from = 4;
}