mirror of
https://github.com/NVIDIA/OpenShell.git
synced 2026-10-17 05:31:16 +08:00
* 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>
140 lines
4.9 KiB
Protocol Buffer
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;
|
|
}
|