diff --git a/.agents/skills/helm-dev-environment/SKILL.md b/.agents/skills/helm-dev-environment/SKILL.md index 537d390193..4e349098e5 100644 --- a/.agents/skills/helm-dev-environment/SKILL.md +++ b/.agents/skills/helm-dev-environment/SKILL.md @@ -90,6 +90,14 @@ OPENSHELL_E2E_KUBE_IMAGE_PULL_SECRET=e2e-regcred \ mise run e2e:kubernetes:shared-supervisor ``` +`mise run e2e:kubernetes:shared-supervisor-spiffe` installs pinned SPIRE charts +(`ci/values-spire-delegation-stack.yaml`, removed again on exit) and the +`openshell.gateway.experimental_spiffe_delegation` overlay +(`ci/values-supervisor-spiffe.yaml`), then registers sandbox +identities with `ClusterStaticEntry` resources. `mise run test:spire-delegation` +checks delegated issuance and identity selection against a local SPIRE server +and agent without a cluster; the Kubernetes test covers the gateway broker. + ### 2. Deploy OpenShell **Iterative dev** (rebuilds on file changes, recommended during active development): diff --git a/Cargo.lock b/Cargo.lock index 048bd0f2e4..c3e920650b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5067,6 +5067,7 @@ dependencies = [ "tokio-tungstenite 0.26.2", "toml", "tonic", + "tonic-prost", "tonic-prost-build", "tonic-reflection", "tower", diff --git a/crates/openshell-cli/tests/ensure_providers_integration.rs b/crates/openshell-cli/tests/ensure_providers_integration.rs index 53ccb70309..b2c7289755 100644 --- a/crates/openshell-cli/tests/ensure_providers_integration.rs +++ b/crates/openshell-cli/tests/ensure_providers_integration.rs @@ -80,6 +80,14 @@ impl TestOpenShell { #[tonic::async_trait] impl OpenShell for TestOpenShell { + async fn get_sandbox_provider_access_token( + &self, + _request: tonic::Request, + ) -> Result, Status> + { + Err(Status::unimplemented("not used by this test server")) + } + async fn peer_notify_config_update( &self, _request: tonic::Request, diff --git a/crates/openshell-cli/tests/mtls_integration.rs b/crates/openshell-cli/tests/mtls_integration.rs index 2fd266941a..55d963584d 100644 --- a/crates/openshell-cli/tests/mtls_integration.rs +++ b/crates/openshell-cli/tests/mtls_integration.rs @@ -32,6 +32,14 @@ struct TestOpenShell; #[tonic::async_trait] impl OpenShell for TestOpenShell { + async fn get_sandbox_provider_access_token( + &self, + _request: tonic::Request, + ) -> Result, Status> + { + Err(Status::unimplemented("not used by this test server")) + } + async fn peer_notify_config_update( &self, _request: tonic::Request, diff --git a/crates/openshell-cli/tests/provider_commands_integration.rs b/crates/openshell-cli/tests/provider_commands_integration.rs index 8812daeefe..96965dc7a3 100644 --- a/crates/openshell-cli/tests/provider_commands_integration.rs +++ b/crates/openshell-cli/tests/provider_commands_integration.rs @@ -235,6 +235,14 @@ impl TestOpenShell { #[tonic::async_trait] impl OpenShell for TestOpenShell { + async fn get_sandbox_provider_access_token( + &self, + _request: tonic::Request, + ) -> Result, Status> + { + Err(Status::unimplemented("not used by this test server")) + } + async fn peer_notify_config_update( &self, _request: tonic::Request, diff --git a/crates/openshell-cli/tests/sandbox_create_lifecycle_integration.rs b/crates/openshell-cli/tests/sandbox_create_lifecycle_integration.rs index 726b110687..250b67f5fe 100644 --- a/crates/openshell-cli/tests/sandbox_create_lifecycle_integration.rs +++ b/crates/openshell-cli/tests/sandbox_create_lifecycle_integration.rs @@ -101,6 +101,14 @@ struct TestOpenShell { #[tonic::async_trait] impl OpenShell for TestOpenShell { + async fn get_sandbox_provider_access_token( + &self, + _request: tonic::Request, + ) -> Result, Status> + { + Err(Status::unimplemented("not used by this test server")) + } + async fn peer_notify_config_update( &self, _request: tonic::Request, diff --git a/crates/openshell-cli/tests/sandbox_exec_streaming_integration.rs b/crates/openshell-cli/tests/sandbox_exec_streaming_integration.rs index 48b84a3373..d894a466be 100644 --- a/crates/openshell-cli/tests/sandbox_exec_streaming_integration.rs +++ b/crates/openshell-cli/tests/sandbox_exec_streaming_integration.rs @@ -163,6 +163,13 @@ macro_rules! mock_gateway { ) => { #[tonic::async_trait] impl OpenShell for MockGateway { + async fn get_sandbox_provider_access_token( + &self, + _request: Request, + ) -> Result, Status> { + Err(Status::unimplemented("not used by this test server")) + } + $(async fn $method(&self, _: Request<$request>) -> Result, Status> { Err(Status::unimplemented("unused test RPC")) })* diff --git a/crates/openshell-cli/tests/sandbox_name_fallback_integration.rs b/crates/openshell-cli/tests/sandbox_name_fallback_integration.rs index 46f7c31306..1c05460ca2 100644 --- a/crates/openshell-cli/tests/sandbox_name_fallback_integration.rs +++ b/crates/openshell-cli/tests/sandbox_name_fallback_integration.rs @@ -47,6 +47,14 @@ struct TestOpenShell { #[tonic::async_trait] impl OpenShell for TestOpenShell { + async fn get_sandbox_provider_access_token( + &self, + _request: tonic::Request, + ) -> Result, Status> + { + Err(Status::unimplemented("not used by this test server")) + } + async fn peer_notify_config_update( &self, _request: tonic::Request, diff --git a/crates/openshell-core/src/config.rs b/crates/openshell-core/src/config.rs index 7f5d4d1ec0..cc66bc2a0a 100644 --- a/crates/openshell-core/src/config.rs +++ b/crates/openshell-core/src/config.rs @@ -205,6 +205,39 @@ pub fn normalize_compute_driver_name(value: &str) -> Result { Ok(value.to_ascii_lowercase()) } +/// Experimental gateway-owned SPIRE delegation for sandbox provider grants. +#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] +#[serde(deny_unknown_fields)] +pub struct ExperimentalSpiffeDelegationConfig { + pub admin_socket_path: String, + pub spiffe_id_prefix: String, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub admin_socket_group: Option, +} + +impl ExperimentalSpiffeDelegationConfig { + /// Reject ambiguous host paths and identities before opening the SPIRE socket. + pub fn validate(&self, gateway_id: &str) -> Result<(), String> { + let path = std::path::Path::new(&self.admin_socket_path); + if !path.is_absolute() + || path + .parent() + .is_none_or(|parent| parent == std::path::Path::new("/")) + || self + .admin_socket_path + .split('/') + .skip(1) + .any(|part| part.is_empty() || part == "." || part == "..") + || self.admin_socket_group == Some(0) + { + return Err("experimental_spiffe_delegation requires a canonical absolute admin socket path in a dedicated directory and a non-root socket group".into()); + } + crate::spiffe::SandboxSpiffeIdPrefix::parse(&self.spiffe_id_prefix)? + .sandbox_spiffe_id(gateway_id, "sandbox")?; + Ok(()) + } +} + /// Server configuration. /// /// Built programmatically in [`crate::Config::new`] and the gateway CLI from @@ -269,6 +302,8 @@ pub struct Config { /// JWTs as `Principal::Sandbox`. Required for the per-sandbox identity /// flow (issue #1354). pub gateway_jwt: Option, + /// Gateway-only access to SPIRE; shared supervisors receive access tokens. + pub experimental_spiffe_delegation: Option, /// Database URL for persistence. pub database_url: String, @@ -940,6 +975,7 @@ impl Config { provider_profile_sources: vec![GatewayProviderProfileSourceConfig::User], mtls_auth: MtlsAuthConfig::default(), gateway_jwt: None, + experimental_spiffe_delegation: None, database_url: String::new(), database_max_connections: None, database_lock_max_connections: None, diff --git a/crates/openshell-core/src/grpc_client.rs b/crates/openshell-core/src/grpc_client.rs index 75672d0263..992ffdc6b7 100644 --- a/crates/openshell-core/src/grpc_client.rs +++ b/crates/openshell-core/src/grpc_client.rs @@ -1569,6 +1569,46 @@ pub async fn exchange_provider_subject_token( )) } +/// Obtain only the final access token; the gateway selects and verifies the +/// sandbox identity and resolves all grant parameters from its configuration. +#[tracing::instrument(name = "supervisor.gateway.get_provider_access_token", skip_all)] +pub async fn get_sandbox_provider_access_token( + gateway: &GatewayEndpoint, + credential_key: &str, + request_id: Option<&str>, +) -> std::result::Result { + let endpoint = token_grant_gateway_endpoint(gateway.url())?; + let mut client = connect(&gateway.with_url(endpoint.as_str())) + .await + .map_err(|_| gateway_grant_failure(TokenGrantFailureKind::Unavailable))?; + let mut request = tonic::Request::new(crate::proto::GetSandboxProviderAccessTokenRequest { + credential_key: credential_key.to_string(), + }); + if let Some(value) = request_id.and_then(|value| value.parse().ok()) { + request.metadata_mut().insert("x-request-id", value); + } + let response = tokio::time::timeout( + Duration::from_mins(1), + client.get_sandbox_provider_access_token(request), + ) + .await + .map_err(|_| gateway_grant_failure(TokenGrantFailureKind::Timeout))? + .map_err(|status| provider_subject_token_exchange_status(&status, &endpoint))? + .into_inner(); + // connect() and the response boundary both reject locally revoked sandbox + // instance credentials. + if gateway.credentials().is_revoked() { + return Err(gateway_grant_failure( + TokenGrantFailureKind::WorkloadIdentityRejected, + )); + } + provider_subject_token_exchange_result(crate::proto::ExchangeProviderSubjectTokenResponse { + access_token: response.access_token, + expires_after: response.expires_after, + token_type: response.token_type, + }) +} + /// Attach the exchange's request ID as `x-request-id` gRPC metadata. /// /// A value that is not valid metadata is omitted, never rewritten. diff --git a/crates/openshell-core/src/oauth.rs b/crates/openshell-core/src/oauth.rs index dcf56cf5c6..58ae2fa4dd 100644 --- a/crates/openshell-core/src/oauth.rs +++ b/crates/openshell-core/src/oauth.rs @@ -24,6 +24,9 @@ pub const ACCESS_TOKEN_TYPE: &str = "urn:ietf:params:oauth:token-type:access_tok const TOKEN_EXCHANGE_GRANT_TYPE: &str = "urn:ietf:params:oauth:grant-type:token-exchange"; const ERROR_CONTRACT: &str = "openshell.token-grant.v1"; const MAX_TOKEN_RESPONSE_BYTES: usize = 64 * 1024; +pub const DEFAULT_TOKEN_CACHE_TTL_SECONDS: i64 = 300; +pub const TOKEN_CACHE_EXPIRY_SKEW_SECONDS: i64 = 30; +pub const MAX_TOKEN_EXPIRES_IN_SECONDS: i64 = 3600; /// HTTP client that authenticates HTTPS endpoints and never redirects assertions. /// @@ -263,6 +266,28 @@ pub fn effective_token_type(token_type: &str) -> &str { } } +/// Cache lifetime for a granted access token. +/// +/// A configured override is used exactly, including zero to disable caching. +/// Otherwise the response lifetime (capped, or a default when omitted) is +/// shortened by a fixed expiry skew, with a one-second floor. +pub fn token_cache_ttl(cache_ttl_override: Option, expires_in: i64) -> Duration { + if let Some(cache_ttl_override) = cache_ttl_override { + return cache_ttl_override; + } + + let ttl = if expires_in > 0 { + expires_in.min(MAX_TOKEN_EXPIRES_IN_SECONDS) + } else { + DEFAULT_TOKEN_CACHE_TTL_SECONDS + }; + + Duration::from_secs( + u64::try_from(ttl.saturating_sub(TOKEN_CACHE_EXPIRY_SKEW_SECONDS).max(1)) + .unwrap_or(u64::MAX), + ) +} + /// Validate the configured endpoint before acquiring any workload credentials. /// /// HTTPS is accepted; plain HTTP is limited to loopback and Kubernetes service diff --git a/crates/openshell-core/src/spiffe.rs b/crates/openshell-core/src/spiffe.rs index c288dfd81a..6b307587a9 100644 --- a/crates/openshell-core/src/spiffe.rs +++ b/crates/openshell-core/src/spiffe.rs @@ -79,6 +79,77 @@ pub fn trust_domain(subject: &str) -> Option<&str> { (!trust_domain.is_empty()).then_some(trust_domain) } +/// Longest SPIFFE ID the SPIFFE specification permits. +const MAX_SPIFFE_ID_BYTES: usize = 2048; + +/// Operator-configured prefix of the stable SPIFFE IDs the gateway requests +/// for sandboxes using shared supervision. +/// +/// A sandbox's ID is `/gateway//sandbox/`. +/// Both IDs must already be valid SPIFFE path segments; nothing is encoded, +/// so distinct gateway and sandbox IDs always produce distinct SPIFFE IDs. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct SandboxSpiffeIdPrefix(String); + +impl SandboxSpiffeIdPrefix { + /// Accept `spiffe://` optionally followed by path segments, + /// with no trailing slash, query, fragment, or percent-encoding. + pub fn parse(value: &str) -> Result { + let invalid = || { + format!( + "SPIFFE ID prefix must be spiffe://[/...] with lowercase trust domain characters [a-z0-9.-_] and path segment characters [A-Za-z0-9.-_]: {value:?}" + ) + }; + let rest = value.strip_prefix("spiffe://").ok_or_else(invalid)?; + let (domain, path) = rest + .split_once('/') + .map_or((rest, None), |(domain, path)| (domain, Some(path))); + if domain.is_empty() + || !domain.bytes().all(|byte| { + byte.is_ascii_lowercase() || byte.is_ascii_digit() || b".-_".contains(&byte) + }) + { + return Err(invalid()); + } + if let Some(path) = path + && !path.split('/').all(is_spiffe_path_segment) + { + return Err(invalid()); + } + Ok(Self(value.to_string())) + } + + #[must_use] + pub fn as_str(&self) -> &str { + &self.0 + } + + /// Stable SPIFFE ID of `sandbox_id` under `gateway_id`. + pub fn sandbox_spiffe_id(&self, gateway_id: &str, sandbox_id: &str) -> Result { + if !is_spiffe_path_segment(gateway_id) || !is_spiffe_path_segment(sandbox_id) { + return Err( + "gateway and sandbox IDs must be SPIFFE path segments [A-Za-z0-9.-_]".to_string(), + ); + } + let id = format!("{}/gateway/{gateway_id}/sandbox/{sandbox_id}", self.0); + if id.len() > MAX_SPIFFE_ID_BYTES { + return Err("sandbox SPIFFE ID exceeds 2048 bytes".to_string()); + } + Ok(id) + } +} + +/// A non-empty SPIFFE path segment other than `.` and `..`. +#[must_use] +pub fn is_spiffe_path_segment(segment: &str) -> bool { + !segment.is_empty() + && segment != "." + && segment != ".." + && segment + .bytes() + .all(|byte| byte.is_ascii_alphanumeric() || b".-_".contains(&byte)) +} + #[cfg(test)] mod tests { use super::*; @@ -164,6 +235,29 @@ mod tests { )); } + #[test] + fn sandbox_spiffe_ids_are_unambiguous_and_reject_unsafe_input() { + let prefix = SandboxSpiffeIdPrefix::parse("spiffe://example.org/openshell").unwrap(); + assert_eq!( + prefix.sandbox_spiffe_id("gw", "4f1c2b3a-9d8e").unwrap(), + "spiffe://example.org/openshell/gateway/gw/sandbox/4f1c2b3a-9d8e" + ); + for invalid in [ + "spiffe://Example.org", + "spiffe://example.org/", + "spiffe://example.org//a", + "spiffe://example.org/a/../b", + "spiffe://example.org/a%2Fb", + "spiffe://example.org:8443/a", + "https://example.org/a", + ] { + assert!(SandboxSpiffeIdPrefix::parse(invalid).is_err(), "{invalid}"); + } + for (gateway, sandbox) in [("gw/x", "a"), ("gw", "a/b"), ("gw", ".."), ("", "a")] { + assert!(prefix.sandbox_spiffe_id(gateway, sandbox).is_err()); + } + } + #[test] fn trust_domain_extracts_domain_from_spiffe_id() { assert_eq!( diff --git a/crates/openshell-driver-kubernetes/README.md b/crates/openshell-driver-kubernetes/README.md index ac67e373ec..5af76922b4 100644 --- a/crates/openshell-driver-kubernetes/README.md +++ b/crates/openshell-driver-kubernetes/README.md @@ -214,8 +214,15 @@ fails closed. credentials. Sandboxes cannot reach session control, and the routing preface only selects which generation-pinned TLS identity the supervisor demands. -The topology does not support upstream proxies or provider SPIFFE identity, and -the shared supervisor is a single point of failure for the sandboxes it hosts. +- **Workload identity.** The gateway owns SPIRE delegation and provider-token + exchange when `openshell.gateway.experimental_spiffe_delegation` is configured. + Shared supervisors receive final access tokens through their authenticated + sessions. No SPIFFE socket is mounted in a shared supervisor or workload Pod. + The existing Workload API option supplies the gateway's component identity + for the RFC 8693 intermediate exchange. + +The topology does not support upstream proxies, and the shared supervisor is a +single point of failure for the sandboxes it hosts. Shared sandbox instances export no supervisor OTLP traces or OCSF events; the driver warns at startup when the gateway configures that export. When the setting is removed, reconciliation suspends shared generations, and a diff --git a/crates/openshell-driver-kubernetes/src/config.rs b/crates/openshell-driver-kubernetes/src/config.rs index 58fabeba7f..9a6fc108f7 100644 --- a/crates/openshell-driver-kubernetes/src/config.rs +++ b/crates/openshell-driver-kubernetes/src/config.rs @@ -544,9 +544,6 @@ impl KubernetesComputeConfig { "supervisor_topology=gateway requires shared_supervisor".to_string() })?; shared.validate()?; - if self.provider_spiffe_enabled() { - return Err("supervisor_topology=gateway does not support provider_spiffe_workload_api_socket_path; a shared supervisor has no per-sandbox workload identity".into()); - } if self.https_proxy.is_some() || self.proxy_auth_secret_name.is_some() || self.proxy_ca_bundle.is_some() diff --git a/crates/openshell-sdk/tests/client_mock.rs b/crates/openshell-sdk/tests/client_mock.rs index 56ea582109..6ccb747cbe 100644 --- a/crates/openshell-sdk/tests/client_mock.rs +++ b/crates/openshell-sdk/tests/client_mock.rs @@ -234,6 +234,13 @@ fn workload_template_proto(name: &str, workspace: &str) -> proto::SandboxWorkloa #[tonic::async_trait] impl OpenShell for TestOpenShell { + async fn get_sandbox_provider_access_token( + &self, + _request: tonic::Request, + ) -> Result, Status> { + Err(Status::unimplemented("not used by this test server")) + } + async fn peer_notify_config_update( &self, _request: tonic::Request, diff --git a/crates/openshell-server/Cargo.toml b/crates/openshell-server/Cargo.toml index 0066cd8d5b..1ab9b32f99 100644 --- a/crates/openshell-server/Cargo.toml +++ b/crates/openshell-server/Cargo.toml @@ -42,6 +42,7 @@ libc = "0.2" tonic = { workspace = true, features = ["channel", "tls-native-roots"] } tonic-reflection = { workspace = true } prost = { workspace = true } +tonic-prost = { workspace = true } prost-reflect = { workspace = true } prost-types = { workspace = true } diff --git a/crates/openshell-server/README.md b/crates/openshell-server/README.md index 58f735c35c..897db62125 100644 --- a/crates/openshell-server/README.md +++ b/crates/openshell-server/README.md @@ -84,3 +84,22 @@ runs under `mise run test:rust:postgres` (see `TESTING.md`) and still accepts `OPENSHELL_REFRESH_TEST_DATABASE_URL` pointing to a disposable PostgreSQL database. It exercises independent sessions without the local mutex. Do not point this fixture at an existing deployment database. + +## Experimental sandbox identity broker + +`openshell.gateway.experimental_spiffe_delegation` enables gateway-owned SPIRE +acquisition for the Kubernetes shared supervisor. The private admin +socket is mounted only in the gateway. `GetSandboxProviderAccessToken` accepts an +endpoint-bound configured credential key; sandbox identity comes from the +verified, currently authorized session JWT. Provider attachment and profile +configuration determine the endpoint, audience, and scopes. The gateway performs +RFC 7523 or both RFC 8693 exchanges and returns only the final access token. +Its bounded cache is isolated by sandbox generation, credential epoch, provider +revision, and grant. The session is authorized again around each SPIRE and +token-service call. A cache hit and a fresh token then pass the same final +check: the grant configuration still matches and the session is still +authorized. A fresh token is cached only after that check. Startup validates +the delegation settings, and gateway state construction parses them once and +returns a configuration error when they are invalid; each request still fetches +a new SVID and the agent's current JWT bundle. SPIRE still trusts the gateway as a +delegate for its agent's available registration scope. diff --git a/crates/openshell-server/src/cli.rs b/crates/openshell-server/src/cli.rs index 5b2ce01c13..2589ede441 100644 --- a/crates/openshell-server/src/cli.rs +++ b/crates/openshell-server/src/cli.rs @@ -649,6 +649,16 @@ fn prepare_server_config_with_drivers( // the generated TLS bundle so upgrades pick up sandbox auth without a // user-authored config file. config.gateway_jwt = gateway_jwt; + config.experimental_spiffe_delegation = file.as_ref().and_then(|file| { + file.openshell + .gateway + .experimental_spiffe_delegation + .clone() + }); + + // Reject invalid delegation before startup; gateway state parses it later. + crate::spiffe_delegation::SpiffeDelegation::validate_config(&config) + .map_err(|error| miette::miette!("{error}"))?; Ok(ServerStartupConfig { config, diff --git a/crates/openshell-server/src/config_file.rs b/crates/openshell-server/src/config_file.rs index 817a6a02ad..3a260839da 100644 --- a/crates/openshell-server/src/config_file.rs +++ b/crates/openshell-server/src/config_file.rs @@ -189,6 +189,9 @@ pub struct GatewayFileSection { #[serde(default)] pub gateway_jwt: Option, #[serde(default)] + pub experimental_spiffe_delegation: + Option, + #[serde(default)] pub otlp: Option, #[serde(default)] pub ocsf_log: Option, diff --git a/crates/openshell-server/src/grpc/mod.rs b/crates/openshell-server/src/grpc/mod.rs index 35f16c0441..09cb9ea9d8 100644 --- a/crates/openshell-server/src/grpc/mod.rs +++ b/crates/openshell-server/src/grpc/mod.rs @@ -646,6 +646,14 @@ impl OpenShell for OpenShellService { policy::handle_get_sandbox_provider_environment(&self.state, request).await } + async fn get_sandbox_provider_access_token( + &self, + request: Request, + ) -> Result, Status> + { + provider::access_token::handle(&self.state, request).await + } + async fn exchange_provider_subject_token( &self, request: Request, diff --git a/crates/openshell-server/src/grpc/provider.rs b/crates/openshell-server/src/grpc/provider.rs index 8abcbe037e..fa2388fe23 100644 --- a/crates/openshell-server/src/grpc/provider.rs +++ b/crates/openshell-server/src/grpc/provider.rs @@ -5,6 +5,8 @@ #![allow(clippy::result_large_err)] // gRPC handlers return Result, Status> +pub(super) mod access_token; + use crate::compute::MutationScope; #[cfg(test)] use crate::credentials::RefreshMaterialScope; @@ -8674,17 +8676,20 @@ mod tests { // Model a second gateway replica: it shares the durable database and // credential backend, but owns an independent sandbox synchronization // guard, so process-local serialization cannot hide this race. - let second_state = Arc::new(ServerState::new_with_credentials( - first_state.config.clone(), - Arc::clone(&first_state.store), - crate::compute::new_test_runtime(Arc::clone(&first_state.store)).await, - crate::sandbox_index::SandboxIndex::new(), - crate::sandbox_watch::SandboxWatchBus::new(), - crate::tracing_bus::TracingLogBus::new(), - Arc::new(crate::supervisor_session::SupervisorSessionRegistry::new()), - None, - first_state.credentials.clone(), - )); + let second_state = Arc::new( + ServerState::new_with_credentials( + first_state.config.clone(), + Arc::clone(&first_state.store), + crate::compute::new_test_runtime(Arc::clone(&first_state.store)).await, + crate::sandbox_index::SandboxIndex::new(), + crate::sandbox_watch::SandboxWatchBus::new(), + crate::tracing_bus::TracingLogBus::new(), + Arc::new(crate::supervisor_session::SupervisorSessionRegistry::new()), + None, + first_state.credentials.clone(), + ) + .unwrap(), + ); let request = |client_secret: &str| ConfigureProviderRefreshRequest { request_id: String::new(), provider: "configure-create-race".to_string(), diff --git a/crates/openshell-server/src/grpc/provider/access_token.rs b/crates/openshell-server/src/grpc/provider/access_token.rs new file mode 100644 index 0000000000..15cc8829c1 --- /dev/null +++ b/crates/openshell-server/src/grpc/provider/access_token.rs @@ -0,0 +1,356 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +//! Gateway-owned sandbox identity and provider-token acquisition. +//! The caller selects an attached configured credential, never grant parameters. +use super::{ + Arc, HashMap, IntermediateTokenCache, LazyLock, Message, ObjectId, ObjectWorkspace, Principal, + Provider, ProviderCredentialTokenGrantType, Request, Response, Sandbox, ServerState, Status, + TokenExchangeParams, TokenGrantFailure, canonical_request_id, effective_jwt_svid_audience, + fetch_gateway_jwt_svid, get_provider_type_profile_for_scope, + insert_dynamic_credentials_for_profile, log_token_grant_failure, oauth, + perform_intermediate_token_exchange, provider_credential_expiration_ms, + resolve_subject_token_credential, sanitize_token_grant_status, token_exchange_http_client, + token_grant_configuration_status, token_grant_dependency_status, token_grant_identity_rejected, + token_grant_store_status, +}; +use openshell_core::jwt::AuthenticatedSandboxSession; +use openshell_core::proto::{ + GetSandboxProviderAccessTokenRequest, GetSandboxProviderAccessTokenResponse, + ProviderCredentialTokenGrant, +}; + +static ACCESS_TOKENS: LazyLock = LazyLock::new(IntermediateTokenCache::new); + +pub(in crate::grpc) async fn handle( + state: &Arc, + request: Request, +) -> Result, Status> { + let request_id = canonical_request_id(request.metadata()); + let result = obtain(state, request, request_id.as_deref()).await; + result.map_err(|status| { + let status = sanitize_token_grant_status(status); + log_token_grant_failure( + None, + request_id.as_deref(), + TokenGrantFailure::from_status(&status), + ); + status + }) +} + +/// Verify the original bearer again after asynchronous work, including expiry +/// and the persisted generation, epoch, active phase, and current token lineage. +async fn authorize( + state: &ServerState, + bearer: &str, +) -> Result { + let authority = state + .sandbox_session_jwt_authority + .as_ref() + .ok_or_else(|| token_grant_identity_rejected(tonic::Code::Unauthenticated))?; + let session = authority + .verify_gateway_token(bearer) + .map_err(|error| error.status)?; + if session.expires_at == 0 { + return Err(token_grant_identity_rejected(tonic::Code::Unauthenticated)); + } + crate::auth::sandbox_session::authorize_persisted(&state.store, &session) + .await + .map_err(|error| error.status)?; + Ok(session) +} + +/// Resolve the exact endpoint selector from the gateway's approved profile. +/// Audience and scopes (including endpoint overrides) never come from the caller. +async fn grant_configuration( + state: &ServerState, + sandbox_id: &str, + key: &str, +) -> Result<(Provider, ProviderCredentialTokenGrant), Status> { + let invalid = || token_grant_configuration_status(tonic::Code::PermissionDenied); + let identity = + openshell_core::dynamic_credential_key::credential_identity(key).ok_or_else(invalid)?; + let (provider_name, _) = identity.split_once(':').ok_or_else(invalid)?; + let selector = + openshell_core::dynamic_credential_key::endpoint_selector(key).ok_or_else(invalid)?; + let sandbox = state + .store + .get_message::(sandbox_id) + .await + .map_err(|_| token_grant_store_status())? + .ok_or_else(invalid)?; + let spec = sandbox.spec.as_ref().ok_or_else(invalid)?; + if !spec.providers.iter().any(|name| name == provider_name) { + return Err(invalid()); + } + let provider = state + .store + .get_message_by_name::(sandbox.object_workspace(), provider_name) + .await + .map_err(|_| token_grant_store_status())? + .ok_or_else(invalid)?; + let catalog = state + .provider_profile_sources + .snapshot_catalog(&state.store, sandbox.object_workspace()) + .await + .map_err(token_grant_dependency_status)?; + let profile = get_provider_type_profile_for_scope( + &catalog, + &provider.r#type, + &provider.profile_workspace, + ) + .ok_or_else(invalid)?; + let mut configured = HashMap::new(); + insert_dynamic_credentials_for_profile( + &mut configured, + &profile, + provider_name, + provider.object_id(), + )?; + let mut matching = configured.iter().filter(|(candidate, _)| { + let Some(endpoint) = openshell_core::dynamic_credential_key::endpoint_selector(candidate) + else { + return false; + }; + endpoint.host == selector.host + && endpoint.port == selector.port + && endpoint.path == selector.path + && openshell_core::dynamic_credential_key::credential_identity(candidate) + == Some(identity) + }); + let (_, credential) = matching.next().ok_or_else(invalid)?; + if matching.next().is_some() { + return Err(invalid()); + } + let grant = credential.token_grant.clone().ok_or_else(invalid)?; + oauth::parse_token_endpoint_url(&grant.token_endpoint).map_err(TokenGrantFailure::to_status)?; + Ok((provider, grant)) +} + +fn cache_key( + session: &AuthenticatedSandboxSession, + provider: &Provider, + grant: &ProviderCredentialTokenGrant, + credential_key: &str, + gateway_id: &str, +) -> Result { + use sha2::{Digest as _, Sha256}; + let binding = serde_json::to_vec(&( + gateway_id, + session.sandbox_id.as_str(), + session.runtime_generation.as_str(), + session.auth_epoch.get(), + provider.object_id(), + provider + .metadata + .as_ref() + .map(|metadata| metadata.resource_version), + credential_key, + Message::encode_to_vec(grant), + )) + .map_err(|_| token_grant_configuration_status(tonic::Code::Internal))?; + Ok(hex::encode(Sha256::digest(binding))) +} + +#[allow(clippy::too_many_lines)] +async fn obtain( + state: &Arc, + request: Request, + request_id: Option<&str>, +) -> Result, Status> { + let Some(Principal::Sandbox(principal)) = request.extensions().get::() else { + return Err(token_grant_identity_rejected(tonic::Code::PermissionDenied)); + }; + let mut values = request.metadata().get_all("authorization").iter(); + let bearer = values + .next() + .and_then(|value| value.to_str().ok()) + .and_then(openshell_core::auth::strip_bearer_scheme) + .ok_or_else(|| token_grant_identity_rejected(tonic::Code::Unauthenticated))? + .to_string(); + if values.next().is_some() { + return Err(token_grant_identity_rejected(tonic::Code::Unauthenticated)); + } + let session = authorize(state, &bearer).await?; + if principal.sandbox_id != session.sandbox_id.as_str() { + return Err(token_grant_identity_rejected(tonic::Code::PermissionDenied)); + } + let delegation = state + .spiffe_delegation + .as_ref() + .ok_or_else(|| token_grant_configuration_status(tonic::Code::FailedPrecondition))?; + if state.compute.configured_driver_name() != "kubernetes" { + return Err(token_grant_configuration_status( + tonic::Code::FailedPrecondition, + )); + } + let gateway_id = delegation.gateway_id(); + let key = &request.get_ref().credential_key; + let (provider, grant) = grant_configuration(state, session.sandbox_id.as_str(), key).await?; + let fingerprint = cache_key(&session, &provider, &grant, key, gateway_id)?; + let ttl_override = grant + .cache_ttl + .as_ref() + .map(openshell_core::time::duration_to_std) + .transpose() + .map_err(|_| token_grant_configuration_status(tonic::Code::InvalidArgument))?; + let grant_type = ProviderCredentialTokenGrantType::try_from(grant.grant_type) + .map_err(|_| token_grant_configuration_status(tonic::Code::FailedPrecondition))?; + let mut subject_expiry = None; + let subject = if grant_type == ProviderCredentialTokenGrantType::TokenExchange { + let subject = grant + .subject_token + .as_ref() + .filter(|subject| subject.source == "provider_credential") + .ok_or_else(|| token_grant_configuration_status(tonic::Code::FailedPrecondition))?; + subject_expiry = provider_credential_expiration_ms(&provider, &subject.credential)?; + Some( + resolve_subject_token_credential(&state.credentials, &provider, &subject.credential) + .await?, + ) + } else { + None + }; + let cached = if ttl_override == Some(std::time::Duration::ZERO) { + None + } else { + ACCESS_TOKENS.get(&fingerprint) + }; + // A miss also yields when its token may be cached; it is inserted only + // after the final validation below, which a hit passes as well. + let (response, cache_until) = if let Some(cached) = cached { + (cached, None) + } else { + authorize(state, &bearer).await?; + let audience = effective_jwt_svid_audience(&grant.token_endpoint, &grant.jwt_svid_audience); + let (svid, svid_expiry) = delegation + .fetch_jwt_svid(session.sandbox_id.as_str(), &audience) + .await + .map_err(TokenGrantFailure::to_status)?; + authorize(state, &bearer).await?; + let client = token_exchange_http_client()?; + let token = if let Some(subject) = subject { + let component_svid = fetch_gateway_jwt_svid(&audience).await?; + let stable_id = delegation + .sandbox_spiffe_id(session.sandbox_id.as_str()) + .map_err(|_| token_grant_configuration_status(tonic::Code::FailedPrecondition))?; + let intermediate = perform_intermediate_token_exchange( + &grant.token_endpoint, + &TokenExchangeParams { + client_assertion: &component_svid, + client_assertion_type: &grant.client_assertion_type, + subject_token: &subject, + subject_token_type: &grant + .subject_token + .as_ref() + .ok_or_else(|| { + token_grant_configuration_status(tonic::Code::FailedPrecondition) + })? + .subject_token_type, + audience: &stable_id, + scopes: &[], + requested_token_type: &grant.requested_token_type, + }, + request_id, + ) + .await?; + authorize(state, &bearer).await?; + oauth::post_oauth_token_exchange( + client, + &grant.token_endpoint, + &TokenExchangeParams { + client_assertion: &svid, + client_assertion_type: &grant.client_assertion_type, + subject_token: &intermediate.access_token, + subject_token_type: oauth::ACCESS_TOKEN_TYPE, + audience: &grant.audience, + scopes: &grant.scopes, + requested_token_type: &grant.requested_token_type, + }, + request_id, + ) + .await + .map_err(TokenGrantFailure::to_status)? + } else { + oauth::post_oauth_token_grant( + client, + &grant.token_endpoint, + &oauth::TokenGrantParams { + client_assertion: &svid, + client_assertion_type: &grant.client_assertion_type, + audience: &grant.audience, + scopes: &grant.scopes, + }, + request_id, + ) + .await + .map_err(TokenGrantFailure::to_status)? + }; + authorize(state, &bearer).await?; + let cache_ttl = oauth::token_cache_ttl(ttl_override, token.expires_in); + let now = crate::persistence::current_time_ms(); + // Stop serving the token a second before the session, SVID, or subject expires. + let identity_expiry = session + .expires_at + .saturating_mul(1000) + .min(svid_expiry.saturating_mul(1000)) + .min(subject_expiry.unwrap_or(i64::MAX)) + .saturating_sub(1000); + let expires_at = now + .saturating_add(i64::try_from(cache_ttl.as_millis()).unwrap_or(i64::MAX)) + .min(identity_expiry); + (token, (expires_at > now).then_some(expires_at)) + }; + // Re-read attachment, provider revision, and profile, then the session, + // before serving or caching any token. + let (current_provider, current_grant) = + grant_configuration(state, session.sandbox_id.as_str(), key).await?; + if cache_key(&session, ¤t_provider, ¤t_grant, key, gateway_id)? != fingerprint { + return Err(token_grant_configuration_status( + tonic::Code::FailedPrecondition, + )); + } + authorize(state, &bearer).await?; + if let Some(expires_at) = cache_until { + ACCESS_TOKENS.set(fingerprint, &response, expires_at); + } + Ok(Response::new(GetSandboxProviderAccessTokenResponse { + access_token: response.access_token, + token_type: response.token_type, + expires_after: openshell_core::time::duration_from_std(std::time::Duration::from_secs( + u64::try_from(response.expires_in).unwrap_or_default(), + )) + .ok(), + })) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::auth::principal::{SandboxIdentitySource, SandboxPrincipal}; + #[tokio::test] + async fn broker_requires_a_signed_session_even_with_a_sandbox_principal() { + let state = crate::grpc::test_support::test_server_state().await; + for principal in [ + Principal::Anonymous, + Principal::Sandbox(SandboxPrincipal { + sandbox_id: uuid::Uuid::new_v4().to_string(), + source: SandboxIdentitySource::BootstrapJwt { + issuer: "launch-session".into(), + }, + trust_domain: Some("openshell".into()), + }), + ] { + let mut request = Request::new(GetSandboxProviderAccessTokenRequest { + credential_key: "untrusted".into(), + }); + request.extensions_mut().insert(principal); + let error = handle(&state, request).await.unwrap_err(); + assert!(matches!( + error.code(), + tonic::Code::Unauthenticated | tonic::Code::PermissionDenied + )); + } + } +} diff --git a/crates/openshell-server/src/lib.rs b/crates/openshell-server/src/lib.rs index c0a83f4e33..d9ea0b320e 100644 --- a/crates/openshell-server/src/lib.rs +++ b/crates/openshell-server/src/lib.rs @@ -43,6 +43,7 @@ mod reflection; mod sandbox_index; mod sandbox_watch; mod service_routing; +mod spiffe_delegation; mod ssh_identity; mod ssh_sessions; mod storage_proto; @@ -367,6 +368,9 @@ pub struct ServerState { /// on demand when the user source is configured. pub(crate) provider_profile_sources: provider_profile_sources::ProviderProfileSources, + /// Parsed gateway-owned SPIRE delegation settings. `None` when disabled. + pub(crate) spiffe_delegation: Option, + /// OIDC admin role name for workspace-level authorization. /// Empty when OIDC is not configured — `authorize_workspace()` treats /// every authenticated user as Platform Admin in that case. @@ -386,6 +390,12 @@ fn is_benign_connection_close(error: &(dyn std::error::Error + 'static)) -> bool impl ServerState { /// Create new server state. + /// + /// # Panics + /// + /// Panics when `config` holds credential-driver or SPIRE delegation + /// settings that startup validation would reject. Gateway startup uses + /// [`Self::new_with_credentials`], which reports those as errors. #[must_use] #[allow(clippy::too_many_arguments)] pub fn new( @@ -412,10 +422,18 @@ impl ServerState { oidc_cache, credentials, ) + .expect("server config should be validated before ServerState::new") } /// Create new server state with an already-initialized credential runtime. - #[must_use] + /// + /// Parses the SPIRE delegation settings into the state that serves every + /// provider access-token request. + /// + /// # Errors + /// + /// Returns a configuration error when the SPIRE delegation settings are + /// invalid. #[allow(clippy::too_many_arguments)] pub fn new_with_credentials( config: Config, @@ -427,7 +445,9 @@ impl ServerState { supervisor_sessions: Arc, oidc_cache: Option>, credentials: credentials::CredentialRuntime, - ) -> Self { + ) -> Result { + let spiffe_delegation = + spiffe_delegation::SpiffeDelegation::from_config(&config).map_err(Error::config)?; let replica_id = compute::lease::replica_id(); compute.configure_ssh_identities(credentials.clone()); let peer_endpoint = derive_peer_endpoint(&config); @@ -440,7 +460,7 @@ impl ServerState { .map_or_else(String::new, |oidc| oidc.admin_role.clone()); let config_delivery = config_delivery::ConfigDelivery::for_db_connections(store.max_connections()); - Self { + Ok(Self { config, store, compute, @@ -473,8 +493,9 @@ impl ServerState { gateway_interceptors: None, provider_profile_sources: provider_profile_sources::ProviderProfileSources::with_default_sources(), + spiffe_delegation, admin_role, - } + }) } } @@ -735,7 +756,7 @@ pub(crate) async fn run_server( supervisor_sessions, oidc_cache, credentials, - ); + )?; state.middleware_registry = middleware_registry; state.gateway_interceptors = gateway_interceptors; state.provider_profile_sources = provider_profile_sources; diff --git a/crates/openshell-server/src/spiffe_delegation.rs b/crates/openshell-server/src/spiffe_delegation.rs new file mode 100644 index 0000000000..f7766d592d --- /dev/null +++ b/crates/openshell-server/src/spiffe_delegation.rs @@ -0,0 +1,373 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +//! SPIRE delegated issuance owned by the gateway, never by a supervisor or sandbox. +use openshell_core::config::{Config, ExperimentalSpiffeDelegationConfig}; +use openshell_core::spiffe::SandboxSpiffeIdPrefix; +use openshell_core::token_grant_failure::{ + TokenGrantFailure, TokenGrantFailureKind, TokenGrantStage, +}; +use std::collections::HashMap; +use std::path::PathBuf; +use std::time::Duration; +const AGENT_CALL_TIMEOUT: Duration = Duration::from_secs(10); + +/// Validated, immutable settings of gateway-owned SPIRE delegation. +/// +/// Gateway state parses these once when it is constructed. Requests reuse the parsed +/// socket, sandbox SPIFFE ID prefix, trust domain, and gateway identity, but +/// fetch each SVID and the agent's current JWT bundle afresh. +#[derive(Debug)] +pub struct SpiffeDelegation { + admin_socket: PathBuf, + prefix: SandboxSpiffeIdPrefix, + trust_domain: spiffe::TrustDomain, + gateway_id: String, +} + +impl SpiffeDelegation { + /// Check the delegation settings `config` enables without building them. + /// + /// # Errors + /// + /// Rejects delegation without gateway session JWTs and a positive session + /// TTL, and settings [`ExperimentalSpiffeDelegationConfig::validate`] + /// rejects. + pub fn validate_config(config: &Config) -> Result<(), String> { + enabled(config).map(drop) + } + + /// The delegation `config` enables, if any. + /// + /// # Errors + /// + /// Rejects what [`Self::validate_config`] rejects. + pub fn from_config(config: &Config) -> Result, String> { + enabled(config)? + .map(|(delegation, gateway_id)| Self::new(delegation, gateway_id)) + .transpose() + } + + /// Parse `config`, already validated for the gateway `gateway_id`. + fn new(config: &ExperimentalSpiffeDelegationConfig, gateway_id: &str) -> Result { + let prefix = SandboxSpiffeIdPrefix::parse(&config.spiffe_id_prefix)?; + let trust_domain = openshell_core::spiffe::trust_domain(prefix.as_str()) + .and_then(|name| spiffe::TrustDomain::new(name).ok()) + .ok_or("experimental_spiffe_delegation prefix has no valid trust domain")?; + Ok(Self { + admin_socket: PathBuf::from(&config.admin_socket_path), + prefix, + trust_domain, + gateway_id: gateway_id.to_string(), + }) + } + + pub fn gateway_id(&self) -> &str { + &self.gateway_id + } + + /// Stable SPIFFE ID of `sandbox_id` under this gateway. + pub fn sandbox_spiffe_id(&self, sandbox_id: &str) -> Result { + self.prefix + .sandbox_spiffe_id(&self.gateway_id, sandbox_id) + .map_err(|_| configuration_failure()) + } + + /// The caller must authorize the current sandbox session before requesting issuance. + pub async fn fetch_jwt_svid( + &self, + sandbox_id: &str, + audience: &str, + ) -> Result<(String, i64), TokenGrantFailure> { + let expected = self.sandbox_spiffe_id(sandbox_id)?; + let mut agent = AdminClient::connect(&self.admin_socket).await?; + let response = agent + .fetch_jwt_svids(wire::FetchJwtSvidsRequest { + audience: vec![audience.to_string()], + selectors: vec![wire::Selector { + r#type: "openshell".into(), + value: format!("sandbox:{}:{sandbox_id}", self.gateway_id), + }], + pid: 0, + }) + .await?; + let [svid] = response.svids.as_slice() else { + return Err(identity_rejected()); + }; + let reported = svid + .id + .as_ref() + .map(|id| format!("spiffe://{}{}", id.trust_domain, id.path)); + if reported.as_deref() != Some(expected.as_str()) { + return Err(identity_rejected()); + } + let bundles = agent.jwt_bundles(&self.trust_domain).await?; + openshell_crypto::install_jwt_provider(); + let verified = spiffe::JwtSvid::parse_and_validate(&svid.token, &bundles, &[audience]) + .map_err(|_| identity_rejected())?; + if verified.spiffe_id().to_string() != expected { + return Err(identity_rejected()); + } + Ok((svid.token.clone(), verified.claims().exp())) + } +} + +/// Validated delegation settings and gateway ID, when delegation is enabled. +fn enabled(config: &Config) -> Result, String> { + let Some(delegation) = &config.experimental_spiffe_delegation else { + return Ok(None); + }; + let jwt = config + .gateway_jwt + .as_ref() + .ok_or("experimental_spiffe_delegation requires gateway session JWTs")?; + delegation.validate(&jwt.gateway_id)?; + if jwt.ttl_secs.is_none() { + return Err( + "experimental_spiffe_delegation requires a positive gateway_jwt.ttl_secs".into(), + ); + } + Ok(Some((delegation, &jwt.gateway_id))) +} + +fn configuration_failure() -> TokenGrantFailure { + TokenGrantFailure::new( + TokenGrantFailureKind::Configuration, + TokenGrantStage::Configuration, + ) +} + +fn identity_rejected() -> TokenGrantFailure { + TokenGrantFailure::new( + TokenGrantFailureKind::WorkloadIdentityRejected, + TokenGrantStage::WorkloadIdentity, + ) +} + +fn agent_failure(kind: TokenGrantFailureKind) -> TokenGrantFailure { + TokenGrantFailure::new(kind, TokenGrantStage::WorkloadIdentity) +} + +fn status_failure(status: &tonic::Status) -> TokenGrantFailure { + // Classify only by code; the agent's message is not retained. + agent_failure(match status.code() { + tonic::Code::PermissionDenied | tonic::Code::Unauthenticated => { + TokenGrantFailureKind::WorkloadIdentityRejected + } + tonic::Code::DeadlineExceeded => TokenGrantFailureKind::Timeout, + tonic::Code::Unavailable => TokenGrantFailureKind::Unavailable, + tonic::Code::InvalidArgument | tonic::Code::Unimplemented => { + TokenGrantFailureKind::Configuration + } + _ => TokenGrantFailureKind::Unclassified, + }) +} + +/// Client for the SPIRE agent's Delegated Identity API. +struct AdminClient { + grpc: tonic::client::Grpc, +} + +impl AdminClient { + async fn connect(socket: &std::path::Path) -> Result { + // Delegation is authorized by the agent attesting this process over + // a local socket; a TCP endpoint could not attest it. + if !socket.is_absolute() { + return Err(configuration_failure()); + } + let endpoint = + spiffe::transport::endpoint::Endpoint::parse(&format!("unix:{}", socket.display())) + .map_err(|_| configuration_failure())?; + let channel = tokio::time::timeout( + AGENT_CALL_TIMEOUT, + spiffe::transport::connector::connect(&endpoint), + ) + .await + .map_err(|_| agent_failure(TokenGrantFailureKind::Timeout))? + .map_err(|_| agent_failure(TokenGrantFailureKind::Unavailable))?; + Ok(Self { + grpc: tonic::client::Grpc::new(channel), + }) + } + + async fn fetch_jwt_svids( + &mut self, + request: wire::FetchJwtSvidsRequest, + ) -> Result { + tokio::time::timeout(AGENT_CALL_TIMEOUT, async { + self.ready().await?; + self.grpc + .unary( + tonic::Request::new(request), + http::uri::PathAndQuery::from_static(wire::FETCH_JWT_SVIDS), + tonic_prost::ProstCodec::default(), + ) + .await + .map(tonic::Response::into_inner) + .map_err(|status| status_failure(&status)) + }) + .await + .map_err(|_| agent_failure(TokenGrantFailureKind::Timeout))? + } + + /// The agent's current JWT bundle for `trust_domain` only. + async fn jwt_bundles( + &mut self, + trust_domain: &spiffe::TrustDomain, + ) -> Result { + let response: wire::SubscribeToJwtBundlesResponse = + tokio::time::timeout(AGENT_CALL_TIMEOUT, async { + self.ready().await?; + let mut stream = self + .grpc + .server_streaming( + tonic::Request::new(wire::SubscribeToJwtBundlesRequest {}), + http::uri::PathAndQuery::from_static(wire::SUBSCRIBE_TO_JWT_BUNDLES), + tonic_prost::ProstCodec::default(), + ) + .await + .map_err(|status| status_failure(&status))? + .into_inner(); + stream + .message() + .await + .map_err(|status| status_failure(&status))? + .ok_or_else(|| agent_failure(TokenGrantFailureKind::Unavailable)) + }) + .await + .map_err(|_| agent_failure(TokenGrantFailureKind::Timeout))??; + let jwks = response + .bundles + .get(&trust_domain.id_string()) + .ok_or_else(identity_rejected)?; + let bundle = spiffe::JwtBundle::from_jwt_authorities(trust_domain.clone(), jwks) + .map_err(|_| identity_rejected())?; + let mut bundles = spiffe::JwtBundleSet::new(); + bundles.add_bundle(bundle); + Ok(bundles) + } + + async fn ready(&mut self) -> Result<(), TokenGrantFailure> { + self.grpc + .ready() + .await + .map_err(|_| agent_failure(TokenGrantFailureKind::Unavailable)) + } +} + +/// Wire messages of the SPIRE agent Delegated Identity API. +/// +/// Transcribed from `proto/spire/api/agent/delegatedidentity/v1/delegatedidentity.proto` +/// and `proto/spire/api/types/{selector,jwtsvid,spiffeid}.proto` of +/// at tag `v1.15.3` (commit +/// `adb81b3b0fb87a881693d1d42eaf8b2fa1223e42`), Copyright The SPIFFE Authors, +/// licensed under the Apache License, Version 2.0. Only the messages for +/// `FetchJWTSVIDs` and `SubscribeToJWTBundles` are reproduced; field numbers +/// and types are unchanged. +mod wire { + use super::HashMap; + + pub(super) const FETCH_JWT_SVIDS: &str = + "/spire.api.agent.delegatedidentity.v1.DelegatedIdentity/FetchJWTSVIDs"; + pub(super) const SUBSCRIBE_TO_JWT_BUNDLES: &str = + "/spire.api.agent.delegatedidentity.v1.DelegatedIdentity/SubscribeToJWTBundles"; + + /// `spire.api.types.Selector` + #[derive(Clone, PartialEq, prost::Message)] + pub(super) struct Selector { + #[prost(string, tag = "1")] + pub r#type: String, + #[prost(string, tag = "2")] + pub value: String, + } + + /// `spire.api.types.SPIFFEID` + #[derive(Clone, PartialEq, prost::Message)] + pub(super) struct SpiffeId { + #[prost(string, tag = "1")] + pub trust_domain: String, + #[prost(string, tag = "2")] + pub path: String, + } + + /// `spire.api.types.JWTSVID` + #[derive(Clone, PartialEq, prost::Message)] + pub(super) struct JwtSvid { + #[prost(string, tag = "1")] + pub token: String, + #[prost(message, optional, tag = "2")] + pub id: Option, + #[prost(int64, tag = "3")] + pub expires_at: i64, + #[prost(int64, tag = "4")] + pub issued_at: i64, + #[prost(string, tag = "5")] + pub hint: String, + } + + /// `spire.api.agent.delegatedidentity.v1.FetchJWTSVIDsRequest` + #[derive(Clone, PartialEq, prost::Message)] + pub(super) struct FetchJwtSvidsRequest { + #[prost(string, repeated, tag = "1")] + pub audience: Vec, + #[prost(message, repeated, tag = "2")] + pub selectors: Vec, + #[prost(int32, tag = "3")] + pub pid: i32, + } + + /// `spire.api.agent.delegatedidentity.v1.FetchJWTSVIDsResponse` + #[derive(Clone, PartialEq, prost::Message)] + pub(super) struct FetchJwtSvidsResponse { + #[prost(message, repeated, tag = "1")] + pub svids: Vec, + } + + /// `spire.api.agent.delegatedidentity.v1.SubscribeToJWTBundlesRequest` + #[derive(Clone, PartialEq, prost::Message)] + pub(super) struct SubscribeToJwtBundlesRequest {} + + /// `spire.api.agent.delegatedidentity.v1.SubscribeToJWTBundlesResponse` + #[derive(Clone, PartialEq, prost::Message)] + pub(super) struct SubscribeToJwtBundlesResponse { + #[prost(map = "string, bytes", tag = "1")] + pub bundles: HashMap>, + } +} + +#[cfg(test)] +mod tests { + use super::*; + #[tokio::test] + #[ignore = "requires the real SPIRE fixture; run mise run test:spire-delegation"] + async fn gateway_obtains_only_the_expected_sandbox_identity() { + let env = |key| std::env::var(key).expect("SPIRE fixture variable"); + let config = ExperimentalSpiffeDelegationConfig { + admin_socket_path: env("OPENSHELL_TEST_SPIRE_ADMIN_SOCKET"), + spiffe_id_prefix: env("OPENSHELL_TEST_SPIRE_ID_PREFIX"), + admin_socket_group: None, + }; + let gateway = env("OPENSHELL_TEST_SPIRE_GATEWAY_ID"); + config.validate(&gateway).unwrap(); + let delegation = SpiffeDelegation::new(&config, &gateway).unwrap(); + let audience = "https://sts.openshell.test"; + let alpha = env("OPENSHELL_TEST_SPIRE_SANDBOX_ALPHA"); + let beta = env("OPENSHELL_TEST_SPIRE_SANDBOX_BETA"); + let (first, expiry) = delegation.fetch_jwt_svid(&alpha, audience).await.unwrap(); + let (second, _) = delegation.fetch_jwt_svid(&beta, audience).await.unwrap(); + assert_ne!(first, second); + assert!(expiry > 0); + for key in [ + "OPENSHELL_TEST_SPIRE_SANDBOX_UNREGISTERED", + "OPENSHELL_TEST_SPIRE_SANDBOX_MISREGISTERED", + "OPENSHELL_TEST_SPIRE_SANDBOX_AMBIGUOUS", + ] { + assert!( + delegation + .fetch_jwt_svid(&env(key), audience) + .await + .is_err() + ); + } + } +} diff --git a/crates/openshell-server/tests/common/mod.rs b/crates/openshell-server/tests/common/mod.rs index 4d41124c01..2c03654186 100644 --- a/crates/openshell-server/tests/common/mod.rs +++ b/crates/openshell-server/tests/common/mod.rs @@ -53,6 +53,14 @@ pub struct TestOpenShell; #[tonic::async_trait] impl OpenShell for TestOpenShell { + async fn get_sandbox_provider_access_token( + &self, + _request: tonic::Request, + ) -> Result, Status> + { + Err(Status::unimplemented("not used by this test server")) + } + async fn peer_notify_config_update( &self, _request: tonic::Request, diff --git a/crates/openshell-server/tests/supervisor_relay_integration.rs b/crates/openshell-server/tests/supervisor_relay_integration.rs index 910a54daf8..fb56787c20 100644 --- a/crates/openshell-server/tests/supervisor_relay_integration.rs +++ b/crates/openshell-server/tests/supervisor_relay_integration.rs @@ -50,6 +50,14 @@ struct RelayGateway { #[tonic::async_trait] impl OpenShell for RelayGateway { + async fn get_sandbox_provider_access_token( + &self, + _request: tonic::Request, + ) -> Result, Status> + { + Err(Status::unimplemented("not used by this test server")) + } + async fn peer_notify_config_update( &self, _request: tonic::Request, diff --git a/crates/openshell-supervisor-network/README.md b/crates/openshell-supervisor-network/README.md index 7ce403a15e..d07bd7cd3d 100644 --- a/crates/openshell-supervisor-network/README.md +++ b/crates/openshell-supervisor-network/README.md @@ -18,11 +18,23 @@ dependency only. ## Sandbox instance inputs `run_networking` takes a `SandboxInstanceNetwork` with the sandbox identity, -the sandbox instance's `GatewayEndpoint`, the SPIFFE Workload API socket for +the sandbox instance's `GatewayEndpoint`, the `ProviderIdentitySource` for provider token grants, the `policy.local` denial source, and proxy CA files. None of these are read from the process environment, so one process can run -several sandbox instances. Each instance owns its provider token cache and -HTTP client; a token acquired for one sandbox is never served to another. -Without a Workload API socket, token grants fail closed. A process hosting -several instances serves `/v1/denials` from a per-instance -`SandboxInstanceDenialLog` instead of the shared shorthand log files. +several sandbox instances. `run_networking` selects the instance's token grant +resolver once from its identity source; a token acquired for one sandbox is +never served to another. + +A dedicated supervisor uses `SpiffeTokenGrantResolver` with its SPIFFE Workload +API socket. That resolver owns the instance's token cache and HTTP client and +uses the gateway only for the intermediate exchange of RFC 8693 grants. +Without a socket, its grants fail closed. Shared sandbox instances use +`GatewayTokenGrantResolver`, which holds only the instance's authenticated +`GatewayEndpoint`. Each admitted operation forwards a configured dynamic +credential key and request ID; the gateway derives the sandbox identity, +validates current authorization, resolves grant parameters, and obtains the +final access token, which the resolver validates. No SPIRE client, SVID, +intermediate token, or grant cache is used in the shared supervisor. `mise run test:spire-delegation` exercises the gateway's +SPIRE acquisition client against a real server and agent. A process hosting several instances serves +`/v1/denials` from a per-instance `SandboxInstanceDenialLog` instead of the shared +shorthand log files. diff --git a/crates/openshell-supervisor-network/src/l7/token_grant_injection.rs b/crates/openshell-supervisor-network/src/l7/token_grant_injection.rs index 65d7b70d08..85f066d3f5 100644 --- a/crates/openshell-supervisor-network/src/l7/token_grant_injection.rs +++ b/crates/openshell-supervisor-network/src/l7/token_grant_injection.rs @@ -53,42 +53,6 @@ pub trait TokenGrantResolver: Send + Sync { ) -> Pin> + Send + 'a>>; } -/// Resolves provider tokens through one sandbox instance's authenticated grant flow. -pub struct SpiffeTokenGrantResolver { - grants: crate::token_grant::SandboxInstanceTokenGrants, -} - -impl SpiffeTokenGrantResolver { - #[must_use] - pub fn new(grants: crate::token_grant::SandboxInstanceTokenGrants) -> Self { - Self { grants } - } -} - -impl TokenGrantResolver for SpiffeTokenGrantResolver { - fn obtain<'a>( - &'a self, - request: TokenGrantRequest<'a>, - ) -> Pin> + Send + 'a>> { - Box::pin(async move { - self.grants - .obtain_provider_token(crate::token_grant::ObtainProviderTokenRequest { - provider_name: request.provider_key, - token_endpoint: request.token_endpoint, - jwt_svid_audience: request.jwt_svid_audience, - client_assertion_type: request.client_assertion_type, - audience: request.audience, - scopes: request.scopes, - cache_ttl_override: request.cache_ttl, - grant_type: request.grant_type, - requested_token_type: request.requested_token_type, - request_id: request.request_id, - }) - .await - }) - } -} - /// A refused request: the grant failure and the credential whose grant failed. /// /// The credential is the `provider:credential` name pair of the selected diff --git a/crates/openshell-supervisor-network/src/run.rs b/crates/openshell-supervisor-network/src/run.rs index 340b3984c5..d624c70798 100644 --- a/crates/openshell-supervisor-network/src/run.rs +++ b/crates/openshell-supervisor-network/src/run.rs @@ -35,11 +35,12 @@ use crate::l7::tls::{ CertCache, ProxyTlsState, SandboxCa, build_upstream_client_config, read_system_ca_bundle, write_ca_files, }; -use crate::l7::token_grant_injection::SpiffeTokenGrantResolver; +use crate::l7::token_grant_injection::TokenGrantResolver; use crate::opa::OpaEngine; use crate::policy_local::{DenialLogSource, PolicyLocalContext}; use crate::proxy::ProxyHandle; -use crate::token_grant::SandboxInstanceTokenGrants; +pub use crate::token_grant::ProviderIdentitySource; +use crate::token_grant::{GatewayTokenGrantResolver, SpiffeTokenGrantResolver}; use openshell_core::endpoint_status::EndpointObservationSender; use openshell_core::grpc_client::GatewayEndpoint; @@ -203,9 +204,8 @@ pub struct SandboxInstanceNetwork { pub sandbox_name: Option, /// Gateway access with this instance's credentials. pub gateway: Option, - /// SPIFFE Workload API socket for provider token grants. Without one, - /// grants fail closed. - pub provider_workload_api_socket: Option, + /// How this instance obtains provider access tokens. + pub provider_identity: ProviderIdentitySource, /// Source served by `policy.local` `/v1/denials`. pub denial_log: DenialLogSource, /// Proxy interception CA and trust-file directory. @@ -304,15 +304,26 @@ pub async fn run_networking( sandbox_id, sandbox_name, gateway, - provider_workload_api_socket, + provider_identity, denial_log, proxy_tls, } = instance; - let token_grants = SpiffeTokenGrantResolver::new(SandboxInstanceTokenGrants::new( - gateway.clone(), - sandbox_id.clone(), - provider_workload_api_socket, - )); + // Choose how this instance obtains provider tokens once, for every grant. + let token_grants: Arc = match (provider_identity, gateway.clone()) { + (ProviderIdentitySource::Gateway, Some(gateway)) => { + Arc::new(GatewayTokenGrantResolver::new(gateway)) + } + // Nothing can issue this sandbox's tokens without a gateway; a + // resolver without a workload identity fails every grant closed. + (ProviderIdentitySource::Gateway, None) => Arc::new(SpiffeTokenGrantResolver::new( + None, + sandbox_id.clone(), + None, + )), + (ProviderIdentitySource::WorkloadApi(socket), gateway) => Arc::new( + SpiffeTokenGrantResolver::new(gateway, sandbox_id.clone(), socket), + ), + }; let policy_local_ctx = Arc::new( PolicyLocalContext::new( retained_proto.cloned(), @@ -322,7 +333,7 @@ pub async fn run_networking( workspace_rx, ) .with_denial_log(denial_log) - .with_token_grants(Arc::new(token_grants)), + .with_token_grants(token_grants), ); // Readiness signal for the proxy accept loop: the proxy binds the TCP diff --git a/crates/openshell-supervisor-network/src/token_grant.rs b/crates/openshell-supervisor-network/src/token_grant.rs index 83d36d36b3..5c6a91a179 100644 --- a/crates/openshell-supervisor-network/src/token_grant.rs +++ b/crates/openshell-supervisor-network/src/token_grant.rs @@ -29,21 +29,28 @@ //! //! ## Sandbox instance scope //! -//! Each sandbox instance owns a [`SandboxInstanceTokenGrants`]: its token cache, -//! HTTP client, gateway credentials, sandbox ID, and SPIFFE Workload API -//! socket. A token is never served to another sandbox. Without a configured -//! Workload API socket, grants fail closed with a configuration failure. +//! Each sandbox instance selects one resolver when its networking starts, from +//! its [`ProviderIdentitySource`]. A token is never served to another sandbox. +//! +//! A dedicated supervisor uses a [`SpiffeTokenGrantResolver`], which presents +//! the supervisor's own identity from a SPIFFE Workload API socket and owns +//! the instance's token cache and HTTP client. Without a socket, its grants +//! fail closed with a configuration failure. A shared supervisor uses a +//! [`GatewayTokenGrantResolver`], which requests only the final provider access +//! token from the gateway; the gateway owns SPIRE acquisition, exchange, and +//! caching. use std::collections::HashMap; use std::future::Future; use std::path::PathBuf; +use std::pin::Pin; use std::sync::{Arc, RwLock}; use std::time::{Duration, SystemTime, UNIX_EPOCH}; use openshell_core::grpc_client::GatewayEndpoint; use openshell_core::oauth::{ self, ACCESS_TOKEN_TYPE, OAuthTokenResponse, TokenExchangeParams, TokenGrantClient, - TokenGrantParams, effective_client_assertion_type, effective_token_type, + TokenGrantParams, effective_client_assertion_type, effective_token_type, token_cache_ttl, }; use openshell_core::proto::ProviderCredentialTokenGrantType; use openshell_core::token_grant_failure::{ @@ -51,9 +58,7 @@ use openshell_core::token_grant_failure::{ }; use spiffe::{WorkloadApiClient, WorkloadApiError}; -const DEFAULT_TOKEN_CACHE_TTL_SECONDS: i64 = 300; -const TOKEN_CACHE_EXPIRY_SKEW_SECONDS: i64 = 30; -const MAX_TOKEN_EXPIRES_IN_SECONDS: i64 = 3600; +use crate::l7::token_grant_injection::{TokenGrantRequest, TokenGrantResolver}; /// Cached access token with expiration metadata. #[derive(Clone)] @@ -86,7 +91,7 @@ impl TokenCache { } } - /// Store a token with expiration time. + /// Forget every cached token. fn set(&self, provider_name: String, access_token: String, expires_at_ms: i64) { if let Ok(mut tokens) = self.tokens.write() { tokens.insert( @@ -100,12 +105,31 @@ impl TokenCache { } } -/// Provider token grants owned by one supervised sandbox. +/// How a sandbox instance obtains provider access tokens. +#[derive(Debug)] +pub enum ProviderIdentitySource { + /// Acquire tokens with this supervisor's own identity from a SPIFFE + /// Workload API socket, for a supervisor dedicated to one sandbox. + /// Without a socket, every grant fails closed. + WorkloadApi(Option), + /// Request final tokens from the gateway, which owns the sandbox's + /// workload identity. + Gateway, +} + +impl Default for ProviderIdentitySource { + fn default() -> Self { + Self::WorkloadApi(None) + } +} + +/// Provider token grants acquired with this supervisor's SPIFFE identity. /// /// The cache, HTTP connection pool, gateway credentials, sandbox ID, and -/// workload identity socket all belong to this sandbox instance, so a token acquired -/// for one sandbox is never served to another. -pub struct SandboxInstanceTokenGrants { +/// Workload API socket all belong to one sandbox instance, so a token +/// acquired for one sandbox is never served to another. The gateway is used +/// only for the intermediate exchange of RFC 8693 token exchange grants. +pub struct SpiffeTokenGrantResolver { cache: TokenCache, // Initialization failures stay bounded and typed; acquisition must not panic. http_client: Result, @@ -114,9 +138,9 @@ pub struct SandboxInstanceTokenGrants { workload_api_socket: Option, } -impl SandboxInstanceTokenGrants { - /// Grants authenticated as `sandbox_id` through `gateway`. A missing - /// Workload API socket makes every grant fail closed. +impl SpiffeTokenGrantResolver { + /// Grants authenticated as `sandbox_id` through `gateway`. A missing or + /// empty socket makes every grant fail closed. #[must_use] pub fn new( gateway: Option, @@ -132,6 +156,14 @@ impl SandboxInstanceTokenGrants { } } + async fn fetch_jwt_svid(&self, audience: &str) -> Result { + let socket_path = self + .workload_api_socket + .as_deref() + .ok_or_else(configuration_failure)?; + fetch_jwt_svid_from_socket(socket_path, audience).await + } + /// Obtain an `OAuth2` access token for a provider using JWT client assertion grant. /// /// This fetches the sandbox's SPIFFE JWT-SVID from the instance's Workload @@ -150,22 +182,22 @@ impl SandboxInstanceTokenGrants { /// - JWT-SVID fetch fails /// - Token service request fails /// - Token response is invalid - pub async fn obtain_provider_token( + async fn obtain_provider_token( &self, - request: ObtainProviderTokenRequest<'_>, + request: TokenGrantRequest<'_>, ) -> Result { let grant_type = ProviderCredentialTokenGrantType::try_from(request.grant_type) .map_err(|_| configuration_failure())?; - obtain_provider_token_with_grant( + let token = obtain_provider_token_with_grant( ObtainProviderTokenInput { cache: &self.cache, - provider_name: request.provider_name, + provider_name: request.provider_key, token_endpoint: request.token_endpoint, jwt_svid_audience: request.jwt_svid_audience, client_assertion_type: request.client_assertion_type, audience: request.audience, scopes: request.scopes, - cache_ttl_override: request.cache_ttl_override, + cache_ttl_override: request.cache_ttl, grant_type, requested_token_type: request.requested_token_type, }, @@ -176,7 +208,7 @@ impl SandboxInstanceTokenGrants { | ProviderCredentialTokenGrantType::Unspecified => None, ProviderCredentialTokenGrantType::TokenExchange => { let (provider, credential_key) = - parse_provider_credential_key(request.provider_name)?; + parse_provider_credential_key(request.provider_key)?; let gateway = self.gateway.as_ref().ok_or_else(configuration_failure)?; openshell_core::grpc_client::token_grant_gateway_endpoint(gateway.url())?; let sandbox_id = self @@ -187,15 +219,11 @@ impl SandboxInstanceTokenGrants { } }; let http_client = self.http_client.as_ref().map_err(|failure| *failure)?; - let socket_path = self - .workload_api_socket - .as_deref() - .ok_or_else(configuration_failure)?; // Fetch JWT-SVID with authorization server as audience // For RFC 7523, the JWT assertion's aud claim identifies the issuer/realm - let jwt_svid = fetch_jwt_svid_from_socket(socket_path, &jwt_audience).await?; + let jwt_svid = self.fetch_jwt_svid(&jwt_audience).await?; - match exchange_context { + let response = match exchange_context { None => { // Perform OAuth2 JWT client assertion grant. The audience // parameter in the token request specifies the resource server. @@ -240,27 +268,58 @@ impl SandboxInstanceTokenGrants { ) .await } - } + }?; + Ok(response) }, ) - .await + .await?; + Ok(token) + } +} + +impl TokenGrantResolver for SpiffeTokenGrantResolver { + fn obtain<'a>( + &'a self, + request: TokenGrantRequest<'a>, + ) -> Pin> + Send + 'a>> { + Box::pin(self.obtain_provider_token(request)) } } -/// One provider token request; see [`SandboxInstanceTokenGrants::obtain_provider_token`]. -pub struct ObtainProviderTokenRequest<'a> { - pub provider_name: &'a str, - pub token_endpoint: &'a str, - pub jwt_svid_audience: &'a str, - pub client_assertion_type: &'a str, - pub audience: &'a str, - pub scopes: &'a [String], - pub cache_ttl_override: Option, - pub grant_type: i32, - pub requested_token_type: &'a str, - /// Supervisor-minted ID of the HTTP exchange that needs the token. It is - /// sent to the gateway and token service; a cache hit sends nothing. - pub request_id: &'a str, +/// Final provider access tokens from the gateway, for a sandbox instance whose +/// supervisor holds no workload identity of its own. +/// +/// It forwards only the credential key and request ID over the instance's +/// authenticated gateway connection and validates the returned token. The +/// gateway authorizes, acquires, exchanges, and caches; this resolver holds +/// no cache, SVID, intermediate token, or HTTP client. +pub struct GatewayTokenGrantResolver { + gateway: GatewayEndpoint, +} + +impl GatewayTokenGrantResolver { + #[must_use] + pub fn new(gateway: GatewayEndpoint) -> Self { + Self { gateway } + } +} + +impl TokenGrantResolver for GatewayTokenGrantResolver { + fn obtain<'a>( + &'a self, + request: TokenGrantRequest<'a>, + ) -> Pin> + Send + 'a>> { + Box::pin(async move { + let token = openshell_core::grpc_client::get_sandbox_provider_access_token( + &self.gateway, + request.provider_key, + Some(request.request_id), + ) + .await?; + validate_access_token(&token.access_token)?; + Ok(token.access_token) + }) + } } struct ObtainProviderTokenInput<'a> { @@ -413,23 +472,6 @@ async fn perform_token_exchange( pub use oauth::validate_access_token; -fn token_cache_ttl(cache_ttl_override: Option, expires_in: i64) -> Duration { - if let Some(cache_ttl_override) = cache_ttl_override { - return cache_ttl_override; - } - - let ttl = if expires_in > 0 { - expires_in.min(MAX_TOKEN_EXPIRES_IN_SECONDS) - } else { - DEFAULT_TOKEN_CACHE_TTL_SECONDS - }; - - Duration::from_secs( - u64::try_from(ttl.saturating_sub(TOKEN_CACHE_EXPIRY_SKEW_SECONDS).max(1)) - .unwrap_or(u64::MAX), - ) -} - /// Derive the issuer/realm URL from a token endpoint URL. /// /// For Keycloak token endpoints like: @@ -512,9 +554,8 @@ pub mod test_support { //! socket or OAuth service is contacted, and no process-wide cache is used. use super::*; - use crate::l7::token_grant_injection::{TokenGrantRequest, TokenGrantResolver}; + use openshell_core::oauth::MAX_TOKEN_EXPIRES_IN_SECONDS; use std::collections::HashSet; - use std::pin::Pin; use std::sync::Mutex; /// One actual acquisition, excluding requests served from the cache. @@ -652,7 +693,10 @@ pub mod test_support { #[cfg(test)] mod tests { use super::*; - use openshell_core::oauth::{ACCESS_TOKEN_TYPE, DEFAULT_CLIENT_ASSERTION_TYPE}; + use openshell_core::oauth::{ + ACCESS_TOKEN_TYPE, DEFAULT_CLIENT_ASSERTION_TYPE, DEFAULT_TOKEN_CACHE_TTL_SECONDS, + MAX_TOKEN_EXPIRES_IN_SECONDS, TOKEN_CACHE_EXPIRY_SKEW_SECONDS, + }; use std::collections::HashMap; use std::sync::{ Arc, diff --git a/crates/openshell-supervisor/README.md b/crates/openshell-supervisor/README.md index 9fe2429af0..1d6dab7d3a 100644 --- a/crates/openshell-supervisor/README.md +++ b/crates/openshell-supervisor/README.md @@ -64,8 +64,9 @@ is a single path component, then, under the registry lock, accepts the same launch fingerprint for an occupied key again, rejects a different one, and rejects any admission while the key is being removed. A new instance gets an empty private directory under the host root, and `sandbox_instance_launch` -prepares its bindings and body there. A failed admission leaves no entry and -no files. +prepares its bindings and body there. A failed admission retains no entry; +its directory is deleted on a best-effort basis, and the next admission of the +key must delete any stale files before reusing it. Removing an instance stops its workload, shuts down only its runtime, which drops its runtime route, and revokes its gateway credentials; only then is its @@ -156,10 +157,13 @@ onto a supervisor-initiated stream is a separate implementation step. Instance readiness is reported per instance over session control. SIGTERM and SIGINT stop every instance, which ends their workloads' supervision. -Sandbox instances get no upstream proxy, extra CA bundle, or provider workload identity: -the Kubernetes driver refuses the topology when an upstream proxy or provider -SPIFFE identity is configured, so a workload never silently loses them. The -host also initializes no OTLP trace or OCSF exporters, because one process +Sandbox instances get no upstream proxy or extra CA bundle: the Kubernetes driver +refuses the topology when an upstream proxy is configured, so a workload never +silently loses it. The process's own SPIFFE identity never stands in for a +sandbox. Shared sandbox instances obtain final provider access tokens through the gateway's +`GetSandboxProviderAccessToken` RPC. They hold no SPIRE socket, SVID, or +intermediate token. The gateway owns identity authorization, acquisition, +exchange, and caching. The host also initializes no OTLP trace or OCSF exporters, because one process cannot export each instance's records with that instance's collector headers and identity. Its console logs and each instance's gateway log push remain, and the Kubernetes driver warns at startup when the gateway configures supervisor diff --git a/crates/openshell-supervisor/src/backend_setup/tests.rs b/crates/openshell-supervisor/src/backend_setup/tests.rs index b4704bf623..06881602e1 100644 --- a/crates/openshell-supervisor/src/backend_setup/tests.rs +++ b/crates/openshell-supervisor/src/backend_setup/tests.rs @@ -701,7 +701,7 @@ async fn shared_startup_uses_selected_backend_through_readiness_and_shutdown() { admitted_isolation_backend: Some(TEST_BACKEND.into()), main_exit_marker: Some(marker.clone()), trace_context: None, - provider_workload_api_socket: None, + provider_identity: openshell_supervisor_network::run::ProviderIdentitySource::default(), // The binary loads the proxy trust directory from its environment. proxy_tls: openshell_supervisor_network::run::ProxyTlsFiles::from_environment(), }; diff --git a/crates/openshell-supervisor/src/legacy_startup_regression_tests.rs b/crates/openshell-supervisor/src/legacy_startup_regression_tests.rs index 699880f1ad..212d9dd64a 100644 --- a/crates/openshell-supervisor/src/legacy_startup_regression_tests.rs +++ b/crates/openshell-supervisor/src/legacy_startup_regression_tests.rs @@ -302,7 +302,7 @@ async fn config_push_regression_legacy_gateway_never_observes_ready_before_workl admitted_isolation_backend: Some("test-held".into()), main_exit_marker: None, trace_context: None, - provider_workload_api_socket: None, + provider_identity: openshell_supervisor_network::run::ProviderIdentitySource::default(), proxy_tls: openshell_supervisor_network::run::ProxyTlsFiles::default(), }; let bindings = SandboxInstanceBindings::dedicated( diff --git a/crates/openshell-supervisor/src/lib.rs b/crates/openshell-supervisor/src/lib.rs index be119584e3..a549aac8f0 100644 --- a/crates/openshell-supervisor/src/lib.rs +++ b/crates/openshell-supervisor/src/lib.rs @@ -796,8 +796,8 @@ pub struct SandboxInstanceConfig { pub main_exit_marker: Option, /// Parent of the startup span. pub trace_context: Option, - /// SPIFFE Workload API socket for provider token grants; absent fails closed. - pub provider_workload_api_socket: Option, + /// How this instance obtains provider access tokens. + pub provider_identity: openshell_supervisor_network::run::ProviderIdentitySource, pub proxy_tls: openshell_supervisor_network::run::ProxyTlsFiles, } @@ -945,7 +945,7 @@ pub async fn run_sandbox_instance( admitted_isolation_backend, main_exit_marker, trace_context, - provider_workload_api_socket, + provider_identity, proxy_tls, } = config; // The owner binds the event context and log sink to the instance's @@ -1285,7 +1285,7 @@ pub async fn run_sandbox_instance( sandbox_id: sandbox_id.clone(), sandbox_name: sandbox_name_for_agg.clone(), gateway: gateway.clone(), - provider_workload_api_socket, + provider_identity, denial_log, proxy_tls, }, @@ -4373,7 +4373,7 @@ mod tests { admitted_isolation_backend: None, main_exit_marker: None, trace_context: None, - provider_workload_api_socket: None, + provider_identity: openshell_supervisor_network::run::ProviderIdentitySource::default(), proxy_tls: openshell_supervisor_network::run::ProxyTlsFiles::default(), }; let bindings = SandboxInstanceBindings::dedicated( diff --git a/crates/openshell-supervisor/src/main.rs b/crates/openshell-supervisor/src/main.rs index 37abe83a1e..54f0393cab 100644 --- a/crates/openshell-supervisor/src/main.rs +++ b/crates/openshell-supervisor/src/main.rs @@ -587,11 +587,14 @@ fn main() -> Result<()> { admitted_isolation_backend: Some(admitted_backend), main_exit_marker: args.main_exit_marker, trace_context: openshell_supervisor::TraceContext::from_environment(), - provider_workload_api_socket: std::env::var_os( - openshell_core::sandbox_env::PROVIDER_SPIFFE_WORKLOAD_API_SOCKET, - ) - .filter(|path| !path.is_empty()) - .map(PathBuf::from), + provider_identity: + openshell_supervisor_network::run::ProviderIdentitySource::WorkloadApi( + std::env::var_os( + openshell_core::sandbox_env::PROVIDER_SPIFFE_WORKLOAD_API_SOCKET, + ) + .filter(|path| !path.is_empty()) + .map(PathBuf::from), + ), proxy_tls: openshell_supervisor_network::run::ProxyTlsFiles::from_environment(), }; // Log push already shares these credentials and the logging diff --git a/crates/openshell-supervisor/src/sandbox_instance_host.rs b/crates/openshell-supervisor/src/sandbox_instance_host.rs index 3c01aa7002..bd8ddcf863 100644 --- a/crates/openshell-supervisor/src/sandbox_instance_host.rs +++ b/crates/openshell-supervisor/src/sandbox_instance_host.rs @@ -260,7 +260,9 @@ impl SandboxInstanceHost { /// /// Rejects an occupied key with different launch material or one still /// being removed, and fails when the instance cannot be prepared or - /// started. A failed admission leaves no instance and no private files. + /// started. A failed admission retains no instance; deleting its private + /// directory is best effort, and the next admission of the key deletes + /// any stale files before reuse. pub fn admit>( &self, admission: SandboxInstanceAdmission, diff --git a/crates/openshell-supervisor/src/shared_host.rs b/crates/openshell-supervisor/src/shared_host.rs index ba060b3481..f0724f62a3 100644 --- a/crates/openshell-supervisor/src/shared_host.rs +++ b/crates/openshell-supervisor/src/shared_host.rs @@ -207,8 +207,8 @@ impl SharedHost { ssh_socket_path: Some(ssh_socket.to_string_lossy().into_owned()), shared_ssh_socket: false, // The Kubernetes driver refuses the gateway topology when an - // upstream proxy or provider workload identity is configured, - // and it configures no extra CA for dedicated supervisors. + // upstream proxy is configured, and it configures no extra CA + // for dedicated supervisors. upstream_proxy_args: openshell_supervisor_network::upstream_proxy::UpstreamProxyArgs::default(), additional_ca_bundle: None, @@ -222,9 +222,9 @@ impl SharedHost { traceparent: context.traceparent, tracestate: context.tracestate, }), - // One process cannot hold a per-sandbox workload identity, so - // providers that need one fail closed. - provider_workload_api_socket: None, + // The gateway owns each sandbox's workload identity and returns + // only final provider access tokens. + provider_identity: openshell_supervisor_network::run::ProviderIdentitySource::Gateway, proxy_tls: openshell_supervisor_network::run::ProxyTlsFiles { ca_certificate: Some(ca_certificate), ca_private_key: Some(ca_private_key), diff --git a/deploy/helm/openshell/ci/values-spire-delegation-stack.yaml b/deploy/helm/openshell/ci/values-spire-delegation-stack.yaml new file mode 100644 index 0000000000..00bdd6e505 --- /dev/null +++ b/deploy/helm/openshell/ci/values-spire-delegation-stack.yaml @@ -0,0 +1,33 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +# SPIRE hardened chart values for the shared-supervisor SPIRE delegation e2e. +# The agent exposes its admin socket on the host for the gateway +# only, and authorizes the gateway's default SPIFFE ID +# (spiffe:///ns//sa/) as a delegate. +# Sandbox registration entries are created by the test, as an operator would. +global: + spire: + clusterName: openshell-e2e + jwtIssuer: https://spire.openshell.local + trustDomain: openshell.local + +spire-server: + defaultJwtSvidTTL: 5m + +spire-agent: + # The agent keeps root for workload attestation but creates its admin + # socket (mode 0770) with this group, which only the gateway + # joins (experimental_spiffe_delegation.admin_socket_group). + podSecurityContext: + runAsUser: 0 + runAsGroup: 10035 + authorizedDelegates: + - spiffe://openshell.local/ns/openshell/sa/openshell + sockets: + admin: + enabled: true + mountOnHost: true + +spiffe-oidc-discovery-provider: + enabled: false diff --git a/deploy/helm/openshell/ci/values-supervisor-spiffe.yaml b/deploy/helm/openshell/ci/values-supervisor-spiffe.yaml new file mode 100644 index 0000000000..c6162d236e --- /dev/null +++ b/deploy/helm/openshell/ci/values-supervisor-spiffe.yaml @@ -0,0 +1,15 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# E2E overlay: the gateway obtains each sandbox's stable SPIFFE +# identity from the node's SPIRE agent (ci/values-spire-delegation-stack.yaml) +# for provider token grants. The gateway keeps its own Workload API identity +# for the RFC 8693 intermediate exchange. +gatewayConfig: + openshell.drivers.kubernetes: + supervisor_topology: gateway + provider_spiffe_workload_api_socket_path: /spiffe-workload-api/spire-agent.sock + openshell.gateway.experimental_spiffe_delegation: + admin_socket_path: /run/spire/agent/sockets/csi.spiffe.io/admin/admin.sock + spiffe_id_prefix: spiffe://openshell.local/openshell + admin_socket_group: 10035 diff --git a/deploy/helm/openshell/templates/_gateway-workload.tpl b/deploy/helm/openshell/templates/_gateway-workload.tpl index c1c2d511d8..984f2dfa32 100644 --- a/deploy/helm/openshell/templates/_gateway-workload.tpl +++ b/deploy/helm/openshell/templates/_gateway-workload.tpl @@ -9,6 +9,7 @@ Gateway pod template shared by the StatefulSet and Deployment workload shapes. {{- $oidcRuntimeConfig := get $gatewayConfig "openshell.gateway.oidc" | default dict -}} {{- if not (get $oidcRuntimeConfig "issuer") -}}{{- $oidcRuntimeConfig = .Values.server.oidc | default dict -}}{{- end -}} {{- $kubernetesRuntimeConfig := include "openshell.effectiveKubernetesConfig" . | fromYaml -}} +{{- $delegation := get $gatewayConfig "openshell.gateway.experimental_spiffe_delegation" | default dict -}} {{- $spiffeSocketPath := get $kubernetesRuntimeConfig "provider_spiffe_workload_api_socket_path" -}} {{- $hasExternalCredentialDriver := or (eq (include "openshell.credentialDriverEnabled" (list . "kubernetes-secrets")) "true") (eq (include "openshell.credentialDriverEnabled" (list . "vault")) "true") -}} {{- $vaultCredentialDriverEnabled := eq (include "openshell.credentialDriverEnabled" (list . "vault")) "true" -}} @@ -46,7 +47,11 @@ spec: - host.docker.internal - host.openshell.internal {{- end }} - {{- with .Values.podSecurityContext }} + {{- $podSecurity := deepCopy (.Values.podSecurityContext | default dict) }} + {{- with $delegation.admin_socket_group }} + {{- $_ := set $podSecurity "supplementalGroups" (append (get $podSecurity "supplementalGroups" | default list) (int64 .) | uniq) }} + {{- end }} + {{- with $podSecurity }} securityContext: {{- toYaml . | nindent 4 }} {{- end }} @@ -196,6 +201,11 @@ spec: mountPath: {{ dir $spiffeSocketPath | quote }} readOnly: true {{- end }} + {{- if $delegation }} + - name: spire-agent-admin + mountPath: {{ dir (get $delegation "admin_socket_path") | quote }} + readOnly: true + {{- end }} {{- if include "openshell.supervisorEnabled" . }} - name: supervisor-control mountPath: /etc/openshell-tls/supervisor-control @@ -309,6 +319,12 @@ spec: - key: {{ .Values.upstreamProxy.caBundle.key | default "ca.crt" | quote }} path: ca.crt {{- end }} + {{- if $delegation }} + - name: spire-agent-admin + hostPath: + path: {{ dir (get $delegation "admin_socket_path") | quote }} + type: Directory + {{- end }} {{- if $spiffeSocketPath }} - name: spiffe-workload-api csi: diff --git a/deploy/helm/openshell/templates/_helpers.tpl b/deploy/helm/openshell/templates/_helpers.tpl index f122b35c5a..454fbe410c 100644 --- a/deploy/helm/openshell/templates/_helpers.tpl +++ b/deploy/helm/openshell/templates/_helpers.tpl @@ -378,6 +378,26 @@ fullname, so the name never collapses into another release resource's name. {{- printf "%s%s" $base $suffix -}} {{- end }} +{{/* +SPIRE delegation belongs to the gateway. The private node admin socket is +never mounted in a supervisor or sandbox Pod. +*/}} +{{- define "openshell.validateSpiffeDelegation" -}} +{{- $delegation := .delegation -}} +{{- $admin := get $delegation "admin_socket_path" | default "" -}} +{{- $prefix := get $delegation "spiffe_id_prefix" | default "" -}} +{{- $canonical := "^(/[A-Za-z0-9_.-]+){2,}$" -}} +{{- if or (not (regexMatch $canonical $admin)) (regexMatch "/\\.\\.?(/|$)" $admin) -}} +{{- fail "experimental_spiffe_delegation.admin_socket_path must be a canonical absolute UNIX socket path below a dedicated directory" -}} +{{- end -}} +{{- if and (hasKey $delegation "admin_socket_group") (not (regexMatch "^[1-9][0-9]*$" (toString (get $delegation "admin_socket_group")))) -}} +{{- fail "experimental_spiffe_delegation.admin_socket_group must be a positive group ID" -}} +{{- end -}} +{{- if not (regexMatch "^spiffe://[a-z0-9._-]+(/[A-Za-z0-9._-]+)*$" $prefix) -}} +{{- fail "experimental_spiffe_delegation.spiffe_id_prefix must be spiffe://[/...]" -}} +{{- end -}} +{{- end }} + {{/* Pod labels of the shared supervisor; its Service selects exactly these. */}} @@ -641,13 +661,20 @@ Validate chart values that Helm would otherwise accept silently. {{- if ne (get $gateway "compute_driver" | default "kubernetes") "kubernetes" -}} {{- fail "supervisor_topology requires the kubernetes compute driver" -}} {{- end -}} -{{- if or (get $kubernetes "https_proxy") (get $kubernetes "proxy_ca_bundle") (get $kubernetes "proxy_auth_secret_name") (get $kubernetes "provider_spiffe_workload_api_socket_path") -}} -{{- fail "supervisor_topology=gateway does not support upstream proxy settings or provider SPIFFE identity" -}} +{{- if or (get $kubernetes "https_proxy") (get $kubernetes "proxy_ca_bundle") (get $kubernetes "proxy_auth_secret_name") -}} +{{- fail "supervisor_topology=gateway does not support upstream proxy settings" -}} {{- end -}} {{- if and (eq (get $kubernetes "workspace_mode" | default "shared") "operator") (not (regexMatch "^[A-Za-z0-9][-A-Za-z0-9_./]*==?[-A-Za-z0-9_.]*$" (get $kubernetes "operator_namespace_label" | default ""))) -}} {{- fail "supervisor_topology=gateway in operator workspace mode requires operator_namespace_label of the form key=value" -}} {{- end -}} {{- end -}} +{{- $delegation := get (.Values.gatewayConfig | default dict) "openshell.gateway.experimental_spiffe_delegation" | default dict -}} +{{- if $delegation -}} +{{- if ne (get $kubernetes "supervisor_topology" | default "") "gateway" -}} +{{- fail "experimental_spiffe_delegation requires supervisor_topology=gateway" -}} +{{- end -}} +{{- include "openshell.validateSpiffeDelegation" (dict "delegation" $delegation) -}} +{{- end -}} {{- if hasKey (get (.Values.gatewayConfig | default dict) "openshell.drivers.kubernetes" | default dict) "shared_supervisor" -}} {{- fail "shared_supervisor is rendered by the chart; set only supervisor_topology" -}} {{- end -}} diff --git a/deploy/helm/openshell/tests/supervisor_test.yaml b/deploy/helm/openshell/tests/supervisor_test.yaml index e85713e2e1..9ec71d3d9b 100644 --- a/deploy/helm/openshell/tests/supervisor_test.yaml +++ b/deploy/helm/openshell/tests/supervisor_test.yaml @@ -271,7 +271,7 @@ tests: supervisor_topology: gateway asserts: - failedTemplate: - errorMessage: supervisor_topology=gateway does not support upstream proxy settings or provider SPIFFE identity + errorMessage: supervisor_topology=gateway does not support upstream proxy settings - it: rejects workspace until implemented template: templates/supervisor.yaml set: diff --git a/deploy/helm/openshell/tests/supervisor_wiring_test.yaml b/deploy/helm/openshell/tests/supervisor_wiring_test.yaml index aca63a5963..8d92eda549 100644 --- a/deploy/helm/openshell/tests/supervisor_wiring_test.yaml +++ b/deploy/helm/openshell/tests/supervisor_wiring_test.yaml @@ -81,3 +81,49 @@ tests: name: supervisor-control mountPath: /etc/openshell-tls/supervisor-control readOnly: true + - it: omits the gateway admin socket when delegation is disabled + template: templates/statefulset.yaml + set: + gatewayConfig: + openshell.drivers.kubernetes: + supervisor_topology: gateway + provider_spiffe_workload_api_socket_path: /spiffe-workload-api/spire-agent.sock + asserts: + - contains: + path: spec.template.spec.containers[0].volumeMounts + content: + name: spiffe-workload-api + mountPath: /spiffe-workload-api + readOnly: true + - notContains: + path: spec.template.spec.volumes + content: + name: spire-agent-admin + any: true + - it: mounts SPIRE delegation only into the gateway + template: templates/statefulset.yaml + set: + gatewayConfig: + openshell.drivers.kubernetes: + supervisor_topology: gateway + openshell.gateway.experimental_spiffe_delegation: + admin_socket_path: /run/spire/admin/admin.sock + spiffe_id_prefix: spiffe://example.org/openshell + admin_socket_group: 10035 + asserts: + - contains: + path: spec.template.spec.securityContext.supplementalGroups + content: 10035 + - contains: + path: spec.template.spec.containers[0].volumeMounts + content: + name: spire-agent-admin + mountPath: /run/spire/admin + readOnly: true + - contains: + path: spec.template.spec.volumes + content: + name: spire-agent-admin + hostPath: + path: /run/spire/admin + type: Directory diff --git a/e2e/rust/Cargo.toml b/e2e/rust/Cargo.toml index 1dc6f0b1cf..dbb9900885 100644 --- a/e2e/rust/Cargo.toml +++ b/e2e/rust/Cargo.toml @@ -38,6 +38,8 @@ e2e-kubernetes-workspace-managed = ["e2e-kubernetes"] e2e-kubernetes-workspace-operator = ["e2e-kubernetes"] # One supervisor process shared by the gateway's sandboxes. e2e-kubernetes-shared-supervisor = ["e2e-kubernetes", "e2e-host-gateway"] +# The shared supervisor acting as sandbox identities delegated by SPIRE. +e2e-kubernetes-shared-supervisor-spiffe = ["e2e-kubernetes-shared-supervisor"] e2e-podman = ["e2e", "e2e-host-gateway", "e2e-local-container-driver"] e2e-podman-gpu = ["e2e-podman", "e2e-gpu"] e2e-oidc-pkce = [] diff --git a/e2e/rust/tests/kubernetes_shared_supervisor_spiffe.rs b/e2e/rust/tests/kubernetes_shared_supervisor_spiffe.rs new file mode 100644 index 0000000000..0c9aa579d4 --- /dev/null +++ b/e2e/rust/tests/kubernetes_shared_supervisor_spiffe.rs @@ -0,0 +1,877 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +#![cfg(feature = "e2e-kubernetes-shared-supervisor-spiffe")] + +//! Sandbox identities delegated by SPIRE to the shared supervisor. +//! +//! The wrapper installs SPIRE (`ci/values-spire-delegation-stack.yaml`) and +//! the gateway topology with SPIRE delegation +//! (`ci/values-supervisor-spiffe.yaml`). This test registers +//! sandbox identities as an operator would, with `ClusterStaticEntry` +//! resources, and drives the existing RFC 8693 provider exchange: the gateway +//! exchanges the stored subject token with its own SVID for the sandbox's +//! SPIFFE ID, and the shared supervisor exchanges that intermediate token with +//! the sandbox's delegated SVID. The token service is a host fixture reached +//! through a selectorless Service, and it hands out tokens that name the +//! identity they were issued to. + +use std::collections::HashMap; +use std::io::Write as _; +use std::process::Stdio; +use std::sync::{Arc, Mutex}; +use std::time::Duration; + +use base64::Engine as _; +use openshell_e2e::harness::binary::openshell_cmd; +use openshell_e2e::harness::sandbox::SandboxGuard; +use tempfile::NamedTempFile; +use tokio::io::{AsyncReadExt as _, AsyncWriteExt as _}; +use tokio::net::{TcpListener, TcpStream}; + +const TEST_HOST: &str = "host.openshell.internal"; +/// Matches `ci/values-spire-delegation-stack.yaml`. +const TRUST_DOMAIN: &str = "openshell.local"; +const SPIRE_CLUSTER: &str = "openshell-e2e"; +/// Matches `ci/values-supervisor-spiffe.yaml`. +const ID_PREFIX: &str = "spiffe://openshell.local/openshell"; +/// Label on the registration entries this run creates, naming its SPIRE +/// fixture so cleanup never touches another run's entries. +const ENTRY_LABEL: &str = "openshell.ai/e2e-spire-fixture"; +const STS_SERVICE: &str = "openshell-e2e-sts"; +const CLIENT_ASSERTION_TYPE: &str = "urn:ietf:params:oauth:client-assertion-type:jwt-spiffe"; +const TOKEN_TYPE_ACCESS_TOKEN: &str = "urn:ietf:params:oauth:token-type:access_token"; +const TOPOLOGY_ANNOTATION: &str = "openshell.ai/sandbox-runtime-supervisor-topology"; +/// Instance route annotation; the key keeps its established `-session` name. +const INSTANCE_ROUTE_ANNOTATION: &str = "openshell.ai/sandbox-runtime-supervisor-session"; + +fn release_namespace() -> String { + std::env::var("OPENSHELL_E2E_KUBE_NAMESPACE").unwrap_or_else(|_| "openshell".to_string()) +} + +fn kubectl_command() -> tokio::process::Command { + let mut command = tokio::process::Command::new("kubectl"); + if let Ok(context) = std::env::var("OPENSHELL_E2E_KUBE_CONTEXT_ACTIVE") + && !context.trim().is_empty() + { + command.arg("--context").arg(context); + } + command +} + +async fn kubectl_with_input(args: &[&str], input: Option<&str>) -> String { + let mut child = kubectl_command() + .args(args) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn() + .unwrap_or_else(|error| panic!("spawn kubectl {args:?}: {error}")); + let mut stdin = child.stdin.take().expect("kubectl stdin"); + if let Some(input) = input { + stdin + .write_all(input.as_bytes()) + .await + .expect("write kubectl input"); + } + drop(stdin); + let output = child.wait_with_output().await.expect("wait for kubectl"); + assert!( + output.status.success(), + "kubectl {args:?} failed: {}", + String::from_utf8_lossy(&output.stderr) + ); + String::from_utf8_lossy(&output.stdout).into_owned() +} + +async fn kubectl(args: &[&str]) -> String { + kubectl_with_input(args, None).await +} + +async fn cli(args: &[&str]) -> (bool, String) { + let output = openshell_cmd() + .args(args) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .output() + .await + .expect("spawn openshell CLI"); + ( + output.status.success(), + format!( + "{}{}", + String::from_utf8_lossy(&output.stdout), + String::from_utf8_lossy(&output.stderr) + ), + ) +} + +fn temp_yaml(contents: &str) -> NamedTempFile { + let mut file = tempfile::Builder::new() + .suffix(".yaml") + .tempfile() + .expect("create temp file"); + file.write_all(contents.as_bytes()) + .expect("write temp file"); + file.flush().expect("flush temp file"); + file +} + +fn spiffe_id(gateway_id: &str, sandbox_id: &str) -> String { + format!("{ID_PREFIX}/gateway/{gateway_id}/sandbox/{sandbox_id}") +} + +/// Claims of a JWT, decoded for observation only. +fn claims(token: &str) -> serde_json::Value { + let payload = token.split('.').nth(1).unwrap_or_default(); + base64::engine::general_purpose::URL_SAFE_NO_PAD + .decode(payload) + .ok() + .and_then(|bytes| serde_json::from_slice(&bytes).ok()) + .unwrap_or_default() +} + +/// One exchange the token service answered. +#[derive(Clone, Debug)] +struct Exchange { + /// Subject of the client assertion. + assertion_subject: String, + /// `audience` parameter of the request. + audience: String, + /// Whether the subject token was the stored user token (the gateway's + /// intermediate exchange) rather than an intermediate token. + intermediate: bool, +} + +/// RFC 8693 token service that binds each intermediate token to the SPIFFE ID +/// it was issued for, and issues a final token only to that identity. +struct TokenService { + port: u16, + state: Arc>, + task: tokio::task::JoinHandle<()>, +} + +#[derive(Default)] +struct TokenState { + exchanges: Vec, + /// Intermediate token -> the SPIFFE ID it was issued for. + intermediates: HashMap, +} + +impl TokenService { + async fn start(stored_token: String) -> Self { + let listener = TcpListener::bind(("0.0.0.0", 0)) + .await + .expect("bind token service"); + let port = listener.local_addr().expect("token service address").port(); + let state = Arc::new(Mutex::new(TokenState::default())); + let (shared, stored) = (state.clone(), Arc::new(stored_token)); + let task = tokio::spawn(async move { + while let Ok((stream, _)) = listener.accept().await { + let (state, stored) = (shared.clone(), stored.clone()); + tokio::spawn(async move { + let _ = answer_token_request(stream, &state, &stored).await; + }); + } + }); + Self { port, state, task } + } + + fn exchanges(&self) -> Vec { + self.state.lock().unwrap().exchanges.clone() + } +} + +impl Drop for TokenService { + fn drop(&mut self) { + self.task.abort(); + } +} + +async fn read_request(stream: &mut TcpStream) -> std::io::Result<(String, String)> { + let mut request = Vec::new(); + let mut chunk = [0_u8; 8192]; + loop { + let read = stream.read(&mut chunk).await?; + if read == 0 { + break; + } + request.extend_from_slice(&chunk[..read]); + let text = String::from_utf8_lossy(&request); + if let Some((head, body)) = text.split_once("\r\n\r\n") { + let length = head + .lines() + .find_map(|line| { + let (name, value) = line.split_once(':')?; + name.eq_ignore_ascii_case("content-length") + .then(|| value.trim().parse::().ok())? + }) + .unwrap_or(0); + if body.len() >= length { + return Ok((head.to_string(), body.to_string())); + } + } + } + let text = String::from_utf8_lossy(&request).into_owned(); + Ok(text + .split_once("\r\n\r\n") + .map(|(head, body)| (head.to_string(), body.to_string())) + .unwrap_or((text, String::new()))) +} + +fn form(body: &str) -> HashMap { + url::form_urlencoded::parse(body.as_bytes()) + .into_owned() + .collect() +} + +async fn respond(stream: &mut TcpStream, status: &str, body: &str) -> std::io::Result<()> { + let response = format!( + "HTTP/1.1 {status}\r\nContent-Type: application/json\r\nContent-Length: {}\r\nConnection: close\r\n\r\n{body}", + body.len() + ); + stream.write_all(response.as_bytes()).await +} + +async fn answer_token_request( + mut stream: TcpStream, + state: &Mutex, + stored: &str, +) -> std::io::Result<()> { + let (_, body) = read_request(&mut stream).await?; + let fields = form(&body); + let field = |name: &str| fields.get(name).cloned().unwrap_or_default(); + let assertion_subject = claims(&field("client_assertion"))["sub"] + .as_str() + .unwrap_or_default() + .to_string(); + let well_formed = field("grant_type") == "urn:ietf:params:oauth:grant-type:token-exchange" + && field("client_assertion_type") == CLIENT_ASSERTION_TYPE + && field("subject_token_type") == TOKEN_TYPE_ACCESS_TOKEN + && assertion_subject.starts_with("spiffe://"); + let issued = { + let mut state = state.lock().unwrap(); + let subject_token = field("subject_token"); + let audience = field("audience"); + if !well_formed { + None + } else if subject_token == stored { + // The gateway exchanges the user's token for the sandbox identity + // named in `audience`. + let token = format!("intermediate-{}", state.intermediates.len() + 1); + state.intermediates.insert(token.clone(), audience.clone()); + state.exchanges.push(Exchange { + assertion_subject, + audience, + intermediate: true, + }); + Some(token) + } else if state.intermediates.get(&subject_token) == Some(&assertion_subject) { + // Only the identity an intermediate token names may redeem it. + let sandbox = assertion_subject.rsplit('/').next().unwrap_or_default(); + let token = format!("final-{sandbox}-{}", state.exchanges.len() + 1); + state.exchanges.push(Exchange { + assertion_subject, + audience, + intermediate: false, + }); + Some(token) + } else { + None + } + }; + match issued { + Some(token) => { + let body = format!( + r#"{{"access_token":"{token}","issued_token_type":"{TOKEN_TYPE_ACCESS_TOKEN}","token_type":"Bearer","expires_in":300}}"# + ); + respond(&mut stream, "200 OK", &body).await + } + None => { + respond( + &mut stream, + "400 Bad Request", + r#"{"error":"invalid_grant"}"#, + ) + .await + } + } +} + +/// Protected endpoint that reports which sandbox a final token was issued to. +struct Target { + port: u16, + task: tokio::task::JoinHandle<()>, +} + +impl Target { + async fn start() -> Self { + let listener = TcpListener::bind(("0.0.0.0", 0)) + .await + .expect("bind protected target"); + let port = listener.local_addr().expect("target address").port(); + let task = tokio::spawn(async move { + while let Ok((mut stream, _)) = listener.accept().await { + tokio::spawn(async move { + let Ok((head, _)) = read_request(&mut stream).await else { + return; + }; + let authorization = head + .lines() + .find_map(|line| { + let (name, value) = line.split_once(':')?; + name.eq_ignore_ascii_case("authorization") + .then(|| value.trim().to_string()) + }) + .unwrap_or_default(); + // "Bearer final--" -> "SAW:" + let seen = authorization + .strip_prefix("Bearer final-") + .and_then(|rest| rest.rsplit_once('-')) + .map_or_else(|| "SAW:NONE".to_string(), |(id, _)| format!("SAW:{id}")); + let response = format!( + "HTTP/1.1 200 OK\r\nContent-Length: {}\r\nConnection: close\r\n\r\n{seen}", + seen.len() + ); + let _ = stream.write_all(response.as_bytes()).await; + }); + } + }); + Self { port, task } + } +} + +impl Drop for Target { + fn drop(&mut self) { + self.task.abort(); + } +} + +/// A selectorless Service in front of the host token service, so token +/// endpoints are the in-cluster `http://..svc` URLs that +/// gateways and supervisors accept without TLS. +async fn expose_token_service(port: u16) -> String { + let host_ip = std::env::var("OPENSHELL_E2E_HOST_GATEWAY_IP") + .ok() + .filter(|ip| !ip.is_empty()) + .expect("OPENSHELL_E2E_HOST_GATEWAY_IP is set by with-kube-gateway.sh"); + let namespace = release_namespace(); + let manifest = format!( + r"apiVersion: v1 +kind: Service +metadata: + name: {STS_SERVICE} + namespace: {namespace} +spec: + ports: + - name: http + port: 80 + targetPort: {port} +--- +apiVersion: discovery.k8s.io/v1 +kind: EndpointSlice +metadata: + name: {STS_SERVICE} + namespace: {namespace} + labels: + kubernetes.io/service-name: {STS_SERVICE} +addressType: IPv4 +ports: + - name: http + port: {port} +endpoints: + - addresses: [{host_ip}] +" + ); + kubectl_with_input(&["apply", "-f", "-"], Some(&manifest)).await; + format!("http://{STS_SERVICE}.{namespace}.svc.cluster.local/token") +} + +async fn remove_token_service() { + let namespace = release_namespace(); + let _ = kubectl_command() + .args([ + "-n", + &namespace, + "delete", + "service,endpointslice", + STS_SERVICE, + "--ignore-not-found", + ]) + .output() + .await; +} + +/// A provider profile whose bearer credential comes from the existing RFC +/// 8693 exchange, bound to `target_port` on the test host. +fn profile(id: &str, token_endpoint: &str, target_port: u16) -> NamedTempFile { + temp_yaml(&format!( + r"id: {id} +display_name: E2E delegated sandbox identity +description: Token exchange with the sandbox's SPIRE-delegated SVID +category: other +credentials: + - name: subject_token + description: Stored user subject token + required: true + - name: access_token + description: Access token obtained through token exchange + required: false + auth_style: bearer + header_name: Authorization + token_grant: + grant_type: token_exchange + token_endpoint: {token_endpoint} + audience: e2e-service + jwt_svid_audience: {token_endpoint} + client_assertion_type: {CLIENT_ASSERTION_TYPE} + requested_token_type: {TOKEN_TYPE_ACCESS_TOKEN} + cache_ttl_seconds: 300 + subject_token: + source: provider_credential + credential: subject_token + subject_token_type: {TOKEN_TYPE_ACCESS_TOKEN} +endpoints: + - host: {TEST_HOST} + port: {target_port} + path: /** + protocol: rest + access: read-write + enforcement: enforce + allowed_ips: + - 10.0.0.0/8 + - 172.16.0.0/12 + - 192.168.0.0/16 +binaries: + - /** +" + )) +} + +/// What the sandbox saw calling the protected target: `SAW:`, +/// `DENIED` for a refused grant, or a failure description. +fn call_script(port: u16) -> String { + format!( + r#" +import urllib.error, urllib.request, uuid + +try: + with urllib.request.urlopen("http://{TEST_HOST}:{port}/resource", timeout=20) as response: + print(response.read().decode()) +except urllib.error.HTTPError as error: + request_id = error.headers.get("x-openshell-request-id", "") + if error.code == 502 and str(uuid.UUID(request_id)) == request_id: + print("DENIED") + else: + print(f"HTTP-{{error.code}}") +except OSError: + print("UNREACHABLE") +"# + ) +} + +async fn call(sandbox: &SandboxGuard, port: u16) -> String { + let output = sandbox + .exec(&["python3", "-c", &call_script(port)]) + .await + .unwrap_or_else(|error| panic!("call from {}: {error}", sandbox.name)); + output + .lines() + .map(str::trim) + .find(|line| { + line.starts_with("SAW:") + || *line == "DENIED" + || line.starts_with("HTTP-") + || *line == "UNREACHABLE" + }) + .unwrap_or_else(|| panic!("no call result from {}:\n{output}", sandbox.name)) + .to_string() +} + +/// Call until the sandbox sees `expected`, as SPIRE propagates a new entry to +/// its agent and a restarted sandbox instance becomes ready. +async fn call_until(sandbox: &SandboxGuard, port: u16, expected: &str) { + let mut last = String::new(); + let reached = tokio::time::timeout(Duration::from_secs(120), async { + loop { + last = call(sandbox, port).await; + if last == expected { + return; + } + tokio::time::sleep(Duration::from_secs(2)).await; + } + }) + .await; + assert!( + reached.is_ok(), + "{} never saw {expected}; last saw {last}", + sandbox.name + ); +} + +/// The Sandbox resource of an `OpenShell` sandbox. +async fn sandbox_resource(name: &str) -> serde_json::Value { + let output = kubectl(&[ + "get", + "sandboxes.agents.x-k8s.io", + "--all-namespaces", + "-l", + &format!("openshell.ai/sandbox-name={name}"), + "-o", + "json", + ]) + .await; + let list: serde_json::Value = serde_json::from_str(&output).expect("parse Sandbox list"); + let [resource] = list["items"].as_array().expect("Sandbox items").as_slice() else { + panic!("expected one Sandbox resource for {name}: {list}"); + }; + resource.clone() +} + +async fn sandbox_id(name: &str) -> String { + let (ok, output) = cli(&["sandbox", "get", name, "--output", "json"]).await; + assert!(ok, "sandbox get {name} failed:\n{output}"); + let details: serde_json::Value = serde_json::from_str(&output).expect("parse sandbox JSON"); + details["id"].as_str().expect("sandbox id").to_string() +} + +/// The shared-supervisor sandbox instance route of a sandbox's current +/// generation. +async fn instance_route(name: &str) -> String { + let resource = sandbox_resource(name).await; + let annotations = &resource["metadata"]["annotations"]; + assert_eq!(annotations[TOPOLOGY_ANNOTATION], "gateway"); + annotations[INSTANCE_ROUTE_ANNOTATION] + .as_str() + .expect("sandbox instance route") + .to_string() +} + +/// Gateway ID the gateway signs session JWTs with. +async fn gateway_id() -> String { + let output = kubectl(&[ + "-n", + &release_namespace(), + "get", + "configmaps", + "-o", + "jsonpath={.items[*].data.gateway\\.toml}", + ]) + .await; + output + .lines() + .find_map(|line| { + let value = line.trim().strip_prefix("gateway_id = \"")?; + value.strip_suffix('"').map(str::to_string) + }) + .expect("gateway_id in gateway TOML") +} + +/// SPIRE agent ID of the node running the gateway. +async fn gateway_agent_id() -> String { + let node = kubectl(&[ + "-n", + &release_namespace(), + "get", + "pods", + "-l", + "app.kubernetes.io/name=openshell,app.kubernetes.io/instance=openshell", + "-o", + "jsonpath={.items[0].spec.nodeName}", + ]) + .await; + let uid = kubectl(&["get", "node", node.trim(), "-o", "jsonpath={.metadata.uid}"]).await; + format!( + "spiffe://{TRUST_DOMAIN}/spire/agent/k8s_psat/{SPIRE_CLUSTER}/{}", + uid.trim() + ) +} + +fn spire_fixture() -> String { + std::env::var("OPENSHELL_E2E_SPIRE_NAMESPACE") + .ok() + .filter(|namespace| !namespace.is_empty()) + .expect("OPENSHELL_E2E_SPIRE_NAMESPACE is set by with-kube-gateway.sh") +} + +/// Register `sandbox_id`'s SPIFFE ID for delegation, scoped to `agent_id`. +async fn register(gateway_id: &str, sandbox_id: &str, agent_id: &str) { + let fixture = spire_fixture(); + // The SPIRE Controller Manager's class is `-`; the + // wrapper installs release `spire` in the fixture namespace. + let class_name = format!("{fixture}-spire"); + let manifest = format!( + r"apiVersion: spire.spiffe.io/v1alpha1 +kind: ClusterStaticEntry +metadata: + name: openshell-sandbox-{sandbox_id} + labels: + {ENTRY_LABEL}: {fixture} +spec: + className: {class_name} + spiffeID: {} + parentID: {agent_id} + selectors: + - openshell:sandbox:{gateway_id}:{sandbox_id} +", + spiffe_id(gateway_id, sandbox_id) + ); + kubectl_with_input(&["apply", "-f", "-"], Some(&manifest)).await; +} + +async fn unregister_all() { + let _ = kubectl_command() + .args([ + "delete", + "clusterstaticentries.spire.spiffe.io", + "-l", + &format!("{ENTRY_LABEL}={}", spire_fixture()), + "--ignore-not-found", + ]) + .output() + .await; +} + +// Inspect access-bearing fields. Image tags and node names may legitimately +// contain "spiffe" without exposing an identity socket or credential. +fn assert_no_spiffe_access(pod: &serde_json::Value) { + let spec = &pod["spec"]; + let containers = spec["containers"] + .as_array() + .unwrap() + .iter() + .map(|container| { + serde_json::json!({ + "env": container["env"], + "mounts": container["volumeMounts"], + "args": container["args"], + }) + }) + .collect::>(); + let access = serde_json::json!({ "volumes": spec["volumes"], "containers": containers }) + .to_string() + .to_lowercase(); + assert!( + !access.contains("spiffe") && !access.contains("spire"), + "Pod {} carries SPIFFE access", + pod["metadata"]["name"] + ); +} + +/// No sandbox workload Pod receives a SPIFFE socket, SPIRE mount, or SPIFFE +/// environment. +async fn assert_workloads_hold_no_spiffe_material() { + let output = kubectl(&[ + "get", + "pods", + "--all-namespaces", + "-l", + "openshell.ai/boundary-role=workload", + "-o", + "json", + ]) + .await; + let pods: serde_json::Value = serde_json::from_str(&output).expect("parse workload Pods"); + let items = pods["items"].as_array().expect("Pod items"); + assert!(!items.is_empty(), "no sandbox workload Pods found"); + for pod in items { + assert_no_spiffe_access(pod); + } +} + +/// Inside the sandbox: no SPIFFE socket, environment, or SVID. +async fn assert_sandbox_holds_no_spiffe_material(sandbox: &SandboxGuard) { + let script = r#" +import base64, json, os, re +leaks = [name for name in os.environ if "SPIFFE" in name.upper() or "SPIRE" in name.upper()] +leaks += [path for path in ("/spiffe-workload-api", "/run/spire", "/tmp/spire-agent") if os.path.exists(path)] +for value in os.environ.values(): + for token in re.findall(r"[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+", value): + try: + payload = token.split(".")[1] + claims = json.loads(base64.urlsafe_b64decode(payload + "=" * (-len(payload) % 4))) + except (ValueError, UnicodeError): + continue + if str(claims.get("sub", "")).startswith("spiffe://openshell.local/"): + leaks.append("svid-in-environment") +print("LEAKS:" + ",".join(leaks) if leaks else "NO-SPIFFE") +"#; + let output = sandbox + .exec(&["python3", "-c", script]) + .await + .unwrap_or_else(|error| panic!("inspect {}: {error}", sandbox.name)); + assert!( + output.lines().any(|line| line.trim() == "NO-SPIFFE"), + "{} holds SPIFFE material:\n{output}", + sandbox.name + ); +} + +async fn create(name: &str, provider: &str) -> SandboxGuard { + SandboxGuard::create_keep_with_args( + &["--name", name, "--provider", provider], + &["sh", "-c", "echo spiffe-ready; exec sleep infinity"], + "spiffe-ready", + ) + .await + .unwrap_or_else(|error| panic!("create {name}: {error}")) +} + +#[tokio::test] +#[allow(clippy::too_many_lines)] +async fn shared_supervisor_acts_as_each_sandboxs_stable_spiffe_identity() { + let nonce = format!("{:08x}", rand::random::()); + let stored_token = format!("stored-{nonce}"); + let tokens = TokenService::start(stored_token.clone()).await; + let target = Target::start().await; + let token_endpoint = expose_token_service(tokens.port).await; + let provider = format!("e2e-spiffe-{nonce}"); + let profile = profile(&provider, &token_endpoint, target.port); + let (imported, output) = cli(&[ + "profile", + "import", + "--file", + profile.path().to_str().expect("UTF-8 profile path"), + ]) + .await; + assert!(imported, "profile import failed:\n{output}"); + let credential = format!("subject_token={stored_token}"); + let (created, output) = cli(&[ + "provider", + "create", + "--name", + &provider, + "--type", + &provider, + "--credential", + &credential, + ]) + .await; + assert!(created, "provider create failed:\n{output}"); + + // Sandbox names are limited to 19 characters. + let (alpha_name, beta_name) = (format!("spa-{nonce}"), format!("spb-{nonce}")); + let (alpha, beta) = tokio::join!( + create(&alpha_name, &provider), + create(&beta_name, &provider) + ); + let (mut alpha, mut beta) = (alpha, beta); + let gateway_id = gateway_id().await; + let agent_id = gateway_agent_id().await; + let alpha_id = sandbox_id(&alpha.name).await; + let beta_id = sandbox_id(&beta.name).await; + + // Without a registration entry the shared supervisor has no identity to + // act as, and never falls back to its own. + assert_eq!(call(&alpha, target.port).await, "DENIED"); + assert!(tokens.exchanges().is_empty()); + + // Each sandbox exchanges under its own stable SPIFFE ID. + register(&gateway_id, &alpha_id, &agent_id).await; + register(&gateway_id, &beta_id, &agent_id).await; + call_until(&alpha, target.port, &format!("SAW:{alpha_id}")).await; + call_until(&beta, target.port, &format!("SAW:{beta_id}")).await; + let finals = |exchanges: &[Exchange]| { + exchanges + .iter() + .filter(|exchange| !exchange.intermediate) + .map(|exchange| exchange.assertion_subject.clone()) + .collect::>() + }; + let exchanges = tokens.exchanges(); + assert_eq!( + finals(&exchanges), + [ + spiffe_id(&gateway_id, &alpha_id), + spiffe_id(&gateway_id, &beta_id) + ] + ); + // The gateway asked for intermediate tokens for exactly those identities, + // with its own identity rather than a sandbox's. + for exchange in exchanges.iter().filter(|exchange| exchange.intermediate) { + assert!( + [ + spiffe_id(&gateway_id, &alpha_id), + spiffe_id(&gateway_id, &beta_id) + ] + .contains(&exchange.audience), + "unexpected intermediate audience {exchange:?}" + ); + assert!( + !exchange.assertion_subject.starts_with(ID_PREFIX), + "gateway presented a sandbox identity: {exchange:?}" + ); + } + let shared_pods = kubectl(&[ + "-n", + &release_namespace(), + "get", + "pods", + "-l", + "app.kubernetes.io/component=supervisor", + "-o", + "json", + ]) + .await; + let shared: serde_json::Value = serde_json::from_str(&shared_pods).unwrap(); + for pod in shared["items"].as_array().unwrap() { + assert_no_spiffe_access(pod); + } + assert_workloads_hold_no_spiffe_material().await; + assert_sandbox_holds_no_spiffe_material(&alpha).await; + assert_sandbox_holds_no_spiffe_material(&beta).await; + + // A restart is a new generation with a new sandbox instance and an empty + // cache, and it acquires under the same SPIFFE ID. + let alpha_route = instance_route(&alpha.name).await; + let (stopped, output) = cli(&["sandbox", "stop", &alpha.name]).await; + assert!(stopped, "sandbox stop failed:\n{output}"); + let (started, output) = cli(&["sandbox", "start", &alpha.name]).await; + assert!(started, "sandbox start failed:\n{output}"); + assert_ne!(instance_route(&alpha.name).await, alpha_route); + let before_restart = finals(&tokens.exchanges()).len(); + call_until(&alpha, target.port, &format!("SAW:{alpha_id}")).await; + let after_restart = finals(&tokens.exchanges()); + assert!( + after_restart.len() > before_restart, + "the restarted generation reused an earlier generation's token" + ); + assert!( + after_restart[before_restart..] + .iter() + .all(|subject| *subject == spiffe_id(&gateway_id, &alpha_id)) + ); + assert_eq!(call(&beta, target.port).await, format!("SAW:{beta_id}")); + + // A sandbox recreated under the same name is a new sandbox with a new + // identity; the old registration does not apply to it. + alpha.cleanup().await; + let mut recreated = create(&alpha_name, &provider).await; + let recreated_id = sandbox_id(&recreated.name).await; + assert_ne!(recreated_id, alpha_id); + let before_recreate = tokens.exchanges().len(); + assert_eq!(call(&recreated, target.port).await, "DENIED"); + assert_eq!(tokens.exchanges().len(), before_recreate); + register(&gateway_id, &recreated_id, &agent_id).await; + call_until(&recreated, target.port, &format!("SAW:{recreated_id}")).await; + assert_eq!( + finals(&tokens.exchanges()).last(), + Some(&spiffe_id(&gateway_id, &recreated_id)) + ); + assert_sandbox_holds_no_spiffe_material(&recreated).await; + + // Identifiers only: the exchanges' tokens are never printed. + for exchange in tokens.exchanges() { + eprintln!( + "token exchange: intermediate={} assertion_subject={} audience={}", + exchange.intermediate, exchange.assertion_subject, exchange.audience + ); + } + + recreated.cleanup().await; + beta.cleanup().await; + let _ = cli(&["provider", "delete", &provider]).await; + let _ = cli(&["profile", "delete", &provider]).await; + unregister_all().await; + remove_token_service().await; +} diff --git a/e2e/with-kube-gateway.sh b/e2e/with-kube-gateway.sh index ee755b8760..98bff3c9fe 100755 --- a/e2e/with-kube-gateway.sh +++ b/e2e/with-kube-gateway.sh @@ -54,6 +54,14 @@ # installing OpenShell. This is used by HA CI so the gateway can run multiple # replicas without requiring the OpenShell chart to own a database. # +# SPIRE delegation fixture: +# Set OPENSHELL_E2E_KUBE_SPIRE_DELEGATION=1 to install pinned SPIRE hardened +# charts (ci/values-spire-delegation-stack.yaml) before OpenShell, with the +# agent admin socket exposed for the shared supervisor. The fixture needs a +# cluster without SPIRE CRDs and creates a fresh namespace +# (OPENSHELL_E2E_SPIRE_NAMESPACE, default openshell-e2e-spire); it removes +# both, and the registration entries tests label with that namespace, on exit. +# # Credential-driver fixture: # Set OPENSHELL_E2E_CREDENTIAL_DRIVERS=1 to enable one credential storage # backend. Set OPENSHELL_E2E_CREDENTIAL_DRIVER to `kubernetes-secrets` or @@ -114,6 +122,12 @@ VAULT_DEV_ROOT_TOKEN="${OPENSHELL_E2E_VAULT_DEV_ROOT_TOKEN:-root}" VAULT_CA_CONFIG_MAP="openbao-ca" VAULT_DNS_ALIAS="${VAULT_RELEASE_NAME}-0" VAULT_CA_FILE="${WORKDIR}/openbao-ca.crt" +SPIRE_FIXTURE_DEPLOYED=0 +SPIRE_NAMESPACE="${OPENSHELL_E2E_SPIRE_NAMESPACE:-openshell-e2e-spire}" +SPIRE_CRDS=(clusterspiffeids.spire.spiffe.io clusterstaticentries.spire.spiffe.io clusterfederatedtrustdomains.spire.spiffe.io) +SPIRE_CHART_REPO="https://spiffe.github.io/helm-charts-hardened/" +SPIRE_CHART_VERSION="${OPENSHELL_E2E_SPIRE_CHART_VERSION:-0.30.3}" +SPIRE_CRDS_CHART_VERSION="${OPENSHELL_E2E_SPIRE_CRDS_CHART_VERSION:-0.6.1}" CORPORATE_PROXY_FIXTURE_DEPLOYED=0 CORPORATE_PROXY_FIXTURE_SECRET="openshell-e2e-proxy-auth" CORPORATE_PROXY_FIXTURE_CA_CONFIGMAP="openshell-e2e-proxy-ca" @@ -482,6 +496,53 @@ provision_vault_auth() { ttl=1h >/dev/null } +deploy_spire_fixture() { + # The fixture owns only what it creates: refuse a cluster that already has + # the namespace or SPIRE CRDs, so cleanup can never remove another install. + local crd + for crd in "${SPIRE_CRDS[@]}"; do + if kctl get crd "${crd}" >/dev/null 2>&1; then + echo "ERROR: CRD ${crd} already exists; the SPIRE fixture needs a cluster without SPIRE." >&2 + exit 2 + fi + done + if ! kctl create namespace "${SPIRE_NAMESPACE}" >/dev/null; then + echo "ERROR: could not create a fresh SPIRE fixture namespace ${SPIRE_NAMESPACE}; set OPENSHELL_E2E_SPIRE_NAMESPACE to an unused name." >&2 + exit 2 + fi + SPIRE_FIXTURE_DEPLOYED=1 + echo "Installing SPIRE ${SPIRE_CHART_VERSION} fixture in namespace ${SPIRE_NAMESPACE}..." + helmctl install spire-crds spire-crds --repo "${SPIRE_CHART_REPO}" \ + --version "${SPIRE_CRDS_CHART_VERSION}" \ + --namespace "${SPIRE_NAMESPACE}" --wait + helmctl install spire spire --repo "${SPIRE_CHART_REPO}" \ + --version "${SPIRE_CHART_VERSION}" \ + --namespace "${SPIRE_NAMESPACE}" \ + --values "${ROOT}/deploy/helm/openshell/ci/values-spire-delegation-stack.yaml" \ + --wait --timeout 5m + kctl -n "${SPIRE_NAMESPACE}" rollout status daemonset/spire-agent --timeout=180s + # Tests label the registration entries they create with this namespace. + export OPENSHELL_E2E_SPIRE_NAMESPACE="${SPIRE_NAMESPACE}" +} + +cleanup_spire_fixture() { + [ "${SPIRE_FIXTURE_DEPLOYED}" = "1" ] || return 0 + kctl delete clusterstaticentries.spire.spiffe.io \ + -l "openshell.ai/e2e-spire-fixture=${SPIRE_NAMESPACE}" --ignore-not-found \ + >/dev/null 2>&1 || true + helmctl uninstall spire --namespace "${SPIRE_NAMESPACE}" --wait --timeout 120s \ + >/dev/null 2>&1 || true + helmctl uninstall spire-crds --namespace "${SPIRE_NAMESPACE}" --wait --timeout 60s \ + >/dev/null 2>&1 || true + # The CRD chart keeps its CRDs on uninstall. None existed before the + # fixture, so these are the fixture's own. + kctl delete crd "${SPIRE_CRDS[@]}" --ignore-not-found --wait=false \ + >/dev/null 2>&1 || true + kctl delete namespace "${SPIRE_NAMESPACE}" --wait=true --timeout=120s \ + --ignore-not-found >/dev/null 2>&1 || true + SPIRE_FIXTURE_DEPLOYED=0 +} + cleanup_vault_fixture() { [ -n "${KUBE_CONTEXT}" ] || return 0 [ -n "${VAULT_NAMESPACE}" ] || return 0 @@ -568,6 +629,8 @@ cleanup() { cleanup_vault_fixture fi + cleanup_spire_fixture + if [ "${ENVOY_GATEWAY_CONFIG_APPLIED}" = "1" ] && [ -n "${KUBE_CONTEXT}" ]; then if command -v kubectl >/dev/null 2>&1; then kctl -n "${NAMESPACE}" delete backendtrafficpolicy.gateway.envoyproxy.io \ @@ -762,6 +825,7 @@ run_scenario() { export OPENSHELL_E2E_KUBE_CONTEXT="${KUBE_CONTEXT}" export OPENSHELL_E2E_KUBE_NAMESPACE="${NAMESPACE}" export OPENSHELL_E2E_KUBE_RELEASE="${RELEASE_NAME}" + export OPENSHELL_E2E_HOST_GATEWAY_IP="${HOST_GATEWAY_IP}" export OPENSHELL_PROVISION_TIMEOUT="${OPENSHELL_PROVISION_TIMEOUT:-300}" e2e_import_example_provider_profiles \ @@ -1410,6 +1474,9 @@ if use_envoy_gateway; then helm_values_args+=(--values "${ROOT}/deploy/helm/openshell/ci/values-gateway.yaml") install_envoy_gateway fi +if [ "${OPENSHELL_E2E_KUBE_SPIRE_DELEGATION:-0}" = "1" ]; then + deploy_spire_fixture +fi if [ "${OPENSHELL_E2E_KUBE_DB_SCENARIOS:-0}" = "1" ]; then # --- Multi-scenario mode: test all database backends --- @@ -1506,6 +1573,7 @@ else export OPENSHELL_E2E_KUBE_CONTEXT="${KUBE_CONTEXT}" export OPENSHELL_E2E_KUBE_NAMESPACE="${NAMESPACE}" export OPENSHELL_E2E_KUBE_RELEASE="${RELEASE_NAME}" + export OPENSHELL_E2E_HOST_GATEWAY_IP="${HOST_GATEWAY_IP}" export OPENSHELL_PROVISION_TIMEOUT="${OPENSHELL_PROVISION_TIMEOUT:-300}" e2e_import_example_provider_profiles \ diff --git a/proto/openshell.proto b/proto/openshell.proto index 44d5ed81ee..bf4963c276 100644 --- a/proto/openshell.proto +++ b/proto/openshell.proto @@ -537,6 +537,13 @@ service OpenShell { }; } + // Obtain the final provider token for the authenticated sandbox session. + // SPIFFE assertions and intermediate credentials remain in the gateway. + rpc GetSandboxProviderAccessToken(GetSandboxProviderAccessTokenRequest) + returns (GetSandboxProviderAccessTokenResponse) { + option (openshell.options.v1.authorization) = { auth_mode: "sandbox" }; + } + // Fetch recent sandbox logs (one-shot). rpc GetSandboxLogs(GetSandboxLogsRequest) returns (GetSandboxLogsResponse) { option (openshell.options.v1.authorization) = { @@ -2783,6 +2790,19 @@ message ProviderEnvironmentSnapshot { map files = 7; } +// Supervisor-only request. Sandbox/workspace are derived from the verified +// session JWT. No caller-selected identity, endpoint, audience, or scope. +message GetSandboxProviderAccessTokenRequest { + // Endpoint-bound dynamic credential key supplied by gateway configuration. + string credential_key = 1; +} + +message GetSandboxProviderAccessTokenResponse { + string access_token = 1 [(openshell.options.v1.secret) = true]; + google.protobuf.Duration expires_after = 2; + string token_type = 3; +} + message ExchangeProviderSubjectTokenRequest { // The sandbox ID. Must match the authenticated sandbox principal. string sandbox_id = 1; diff --git a/sdk/go/proto/openshellv1/openshell.pb.go b/sdk/go/proto/openshellv1/openshell.pb.go index f180617bf6..8e845e05a5 100644 --- a/sdk/go/proto/openshellv1/openshell.pb.go +++ b/sdk/go/proto/openshellv1/openshell.pb.go @@ -11868,6 +11868,113 @@ func (x *ProviderEnvironmentSnapshot) GetFiles() map[string]string { return nil } +// Supervisor-only request. Sandbox/workspace are derived from the verified +// session JWT. No caller-selected identity, endpoint, audience, or scope. +type GetSandboxProviderAccessTokenRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Endpoint-bound dynamic credential key supplied by gateway configuration. + CredentialKey string `protobuf:"bytes,1,opt,name=credential_key,json=credentialKey,proto3" json:"credential_key,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetSandboxProviderAccessTokenRequest) Reset() { + *x = GetSandboxProviderAccessTokenRequest{} + mi := &file_openshell_proto_msgTypes[143] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetSandboxProviderAccessTokenRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetSandboxProviderAccessTokenRequest) ProtoMessage() {} + +func (x *GetSandboxProviderAccessTokenRequest) ProtoReflect() protoreflect.Message { + mi := &file_openshell_proto_msgTypes[143] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetSandboxProviderAccessTokenRequest.ProtoReflect.Descriptor instead. +func (*GetSandboxProviderAccessTokenRequest) Descriptor() ([]byte, []int) { + return file_openshell_proto_rawDescGZIP(), []int{143} +} + +func (x *GetSandboxProviderAccessTokenRequest) GetCredentialKey() string { + if x != nil { + return x.CredentialKey + } + return "" +} + +type GetSandboxProviderAccessTokenResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + AccessToken string `protobuf:"bytes,1,opt,name=access_token,json=accessToken,proto3" json:"access_token,omitempty"` + ExpiresAfter *durationpb.Duration `protobuf:"bytes,2,opt,name=expires_after,json=expiresAfter,proto3" json:"expires_after,omitempty"` + TokenType string `protobuf:"bytes,3,opt,name=token_type,json=tokenType,proto3" json:"token_type,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetSandboxProviderAccessTokenResponse) Reset() { + *x = GetSandboxProviderAccessTokenResponse{} + mi := &file_openshell_proto_msgTypes[144] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetSandboxProviderAccessTokenResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetSandboxProviderAccessTokenResponse) ProtoMessage() {} + +func (x *GetSandboxProviderAccessTokenResponse) ProtoReflect() protoreflect.Message { + mi := &file_openshell_proto_msgTypes[144] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetSandboxProviderAccessTokenResponse.ProtoReflect.Descriptor instead. +func (*GetSandboxProviderAccessTokenResponse) Descriptor() ([]byte, []int) { + return file_openshell_proto_rawDescGZIP(), []int{144} +} + +func (x *GetSandboxProviderAccessTokenResponse) GetAccessToken() string { + if x != nil { + return x.AccessToken + } + return "" +} + +func (x *GetSandboxProviderAccessTokenResponse) GetExpiresAfter() *durationpb.Duration { + if x != nil { + return x.ExpiresAfter + } + return nil +} + +func (x *GetSandboxProviderAccessTokenResponse) GetTokenType() string { + if x != nil { + return x.TokenType + } + return "" +} + type ExchangeProviderSubjectTokenRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // The sandbox ID. Must match the authenticated sandbox principal. @@ -11885,7 +11992,7 @@ type ExchangeProviderSubjectTokenRequest struct { func (x *ExchangeProviderSubjectTokenRequest) Reset() { *x = ExchangeProviderSubjectTokenRequest{} - mi := &file_openshell_proto_msgTypes[143] + mi := &file_openshell_proto_msgTypes[145] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11897,7 +12004,7 @@ func (x *ExchangeProviderSubjectTokenRequest) String() string { func (*ExchangeProviderSubjectTokenRequest) ProtoMessage() {} func (x *ExchangeProviderSubjectTokenRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[143] + mi := &file_openshell_proto_msgTypes[145] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11910,7 +12017,7 @@ func (x *ExchangeProviderSubjectTokenRequest) ProtoReflect() protoreflect.Messag // Deprecated: Use ExchangeProviderSubjectTokenRequest.ProtoReflect.Descriptor instead. func (*ExchangeProviderSubjectTokenRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{143} + return file_openshell_proto_rawDescGZIP(), []int{145} } func (x *ExchangeProviderSubjectTokenRequest) GetSandboxId() string { @@ -11952,7 +12059,7 @@ type ExchangeProviderSubjectTokenResponse struct { func (x *ExchangeProviderSubjectTokenResponse) Reset() { *x = ExchangeProviderSubjectTokenResponse{} - mi := &file_openshell_proto_msgTypes[144] + mi := &file_openshell_proto_msgTypes[146] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11964,7 +12071,7 @@ func (x *ExchangeProviderSubjectTokenResponse) String() string { func (*ExchangeProviderSubjectTokenResponse) ProtoMessage() {} func (x *ExchangeProviderSubjectTokenResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[144] + mi := &file_openshell_proto_msgTypes[146] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11977,7 +12084,7 @@ func (x *ExchangeProviderSubjectTokenResponse) ProtoReflect() protoreflect.Messa // Deprecated: Use ExchangeProviderSubjectTokenResponse.ProtoReflect.Descriptor instead. func (*ExchangeProviderSubjectTokenResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{144} + return file_openshell_proto_rawDescGZIP(), []int{146} } func (x *ExchangeProviderSubjectTokenResponse) GetAccessToken() string { @@ -12051,7 +12158,7 @@ type UpdateConfigRequest struct { func (x *UpdateConfigRequest) Reset() { *x = UpdateConfigRequest{} - mi := &file_openshell_proto_msgTypes[145] + mi := &file_openshell_proto_msgTypes[147] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12063,7 +12170,7 @@ func (x *UpdateConfigRequest) String() string { func (*UpdateConfigRequest) ProtoMessage() {} func (x *UpdateConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[145] + mi := &file_openshell_proto_msgTypes[147] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12076,7 +12183,7 @@ func (x *UpdateConfigRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateConfigRequest.ProtoReflect.Descriptor instead. func (*UpdateConfigRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{145} + return file_openshell_proto_rawDescGZIP(), []int{147} } func (x *UpdateConfigRequest) GetWorkspaceScope() *datamodelv1.WorkspaceSelector { @@ -12173,7 +12280,7 @@ type PolicyMergeOperation struct { func (x *PolicyMergeOperation) Reset() { *x = PolicyMergeOperation{} - mi := &file_openshell_proto_msgTypes[146] + mi := &file_openshell_proto_msgTypes[148] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12185,7 +12292,7 @@ func (x *PolicyMergeOperation) String() string { func (*PolicyMergeOperation) ProtoMessage() {} func (x *PolicyMergeOperation) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[146] + mi := &file_openshell_proto_msgTypes[148] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12198,7 +12305,7 @@ func (x *PolicyMergeOperation) ProtoReflect() protoreflect.Message { // Deprecated: Use PolicyMergeOperation.ProtoReflect.Descriptor instead. func (*PolicyMergeOperation) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{146} + return file_openshell_proto_rawDescGZIP(), []int{148} } func (x *PolicyMergeOperation) GetOperation() isPolicyMergeOperation_Operation { @@ -12312,7 +12419,7 @@ type AddNetworkRule struct { func (x *AddNetworkRule) Reset() { *x = AddNetworkRule{} - mi := &file_openshell_proto_msgTypes[147] + mi := &file_openshell_proto_msgTypes[149] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12324,7 +12431,7 @@ func (x *AddNetworkRule) String() string { func (*AddNetworkRule) ProtoMessage() {} func (x *AddNetworkRule) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[147] + mi := &file_openshell_proto_msgTypes[149] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12337,7 +12444,7 @@ func (x *AddNetworkRule) ProtoReflect() protoreflect.Message { // Deprecated: Use AddNetworkRule.ProtoReflect.Descriptor instead. func (*AddNetworkRule) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{147} + return file_openshell_proto_rawDescGZIP(), []int{149} } func (x *AddNetworkRule) GetRuleName() string { @@ -12365,7 +12472,7 @@ type RemoveNetworkEndpoint struct { func (x *RemoveNetworkEndpoint) Reset() { *x = RemoveNetworkEndpoint{} - mi := &file_openshell_proto_msgTypes[148] + mi := &file_openshell_proto_msgTypes[150] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12377,7 +12484,7 @@ func (x *RemoveNetworkEndpoint) String() string { func (*RemoveNetworkEndpoint) ProtoMessage() {} func (x *RemoveNetworkEndpoint) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[148] + mi := &file_openshell_proto_msgTypes[150] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12390,7 +12497,7 @@ func (x *RemoveNetworkEndpoint) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoveNetworkEndpoint.ProtoReflect.Descriptor instead. func (*RemoveNetworkEndpoint) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{148} + return file_openshell_proto_rawDescGZIP(), []int{150} } func (x *RemoveNetworkEndpoint) GetRuleName() string { @@ -12423,7 +12530,7 @@ type RemoveNetworkRule struct { func (x *RemoveNetworkRule) Reset() { *x = RemoveNetworkRule{} - mi := &file_openshell_proto_msgTypes[149] + mi := &file_openshell_proto_msgTypes[151] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12435,7 +12542,7 @@ func (x *RemoveNetworkRule) String() string { func (*RemoveNetworkRule) ProtoMessage() {} func (x *RemoveNetworkRule) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[149] + mi := &file_openshell_proto_msgTypes[151] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12448,7 +12555,7 @@ func (x *RemoveNetworkRule) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoveNetworkRule.ProtoReflect.Descriptor instead. func (*RemoveNetworkRule) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{149} + return file_openshell_proto_rawDescGZIP(), []int{151} } func (x *RemoveNetworkRule) GetRuleName() string { @@ -12477,7 +12584,7 @@ type L7RuleTarget struct { func (x *L7RuleTarget) Reset() { *x = L7RuleTarget{} - mi := &file_openshell_proto_msgTypes[150] + mi := &file_openshell_proto_msgTypes[152] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12489,7 +12596,7 @@ func (x *L7RuleTarget) String() string { func (*L7RuleTarget) ProtoMessage() {} func (x *L7RuleTarget) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[150] + mi := &file_openshell_proto_msgTypes[152] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12502,7 +12609,7 @@ func (x *L7RuleTarget) ProtoReflect() protoreflect.Message { // Deprecated: Use L7RuleTarget.ProtoReflect.Descriptor instead. func (*L7RuleTarget) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{150} + return file_openshell_proto_rawDescGZIP(), []int{152} } func (x *L7RuleTarget) GetRuleName() string { @@ -12557,7 +12664,7 @@ type AddDenyRules struct { func (x *AddDenyRules) Reset() { *x = AddDenyRules{} - mi := &file_openshell_proto_msgTypes[151] + mi := &file_openshell_proto_msgTypes[153] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12569,7 +12676,7 @@ func (x *AddDenyRules) String() string { func (*AddDenyRules) ProtoMessage() {} func (x *AddDenyRules) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[151] + mi := &file_openshell_proto_msgTypes[153] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12582,7 +12689,7 @@ func (x *AddDenyRules) ProtoReflect() protoreflect.Message { // Deprecated: Use AddDenyRules.ProtoReflect.Descriptor instead. func (*AddDenyRules) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{151} + return file_openshell_proto_rawDescGZIP(), []int{153} } func (x *AddDenyRules) GetDenyRules() []*sandboxv1.L7DenyRule { @@ -12609,7 +12716,7 @@ type AddAllowRules struct { func (x *AddAllowRules) Reset() { *x = AddAllowRules{} - mi := &file_openshell_proto_msgTypes[152] + mi := &file_openshell_proto_msgTypes[154] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12621,7 +12728,7 @@ func (x *AddAllowRules) String() string { func (*AddAllowRules) ProtoMessage() {} func (x *AddAllowRules) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[152] + mi := &file_openshell_proto_msgTypes[154] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12634,7 +12741,7 @@ func (x *AddAllowRules) ProtoReflect() protoreflect.Message { // Deprecated: Use AddAllowRules.ProtoReflect.Descriptor instead. func (*AddAllowRules) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{152} + return file_openshell_proto_rawDescGZIP(), []int{154} } func (x *AddAllowRules) GetRules() []*sandboxv1.L7Rule { @@ -12661,7 +12768,7 @@ type RemoveNetworkBinary struct { func (x *RemoveNetworkBinary) Reset() { *x = RemoveNetworkBinary{} - mi := &file_openshell_proto_msgTypes[153] + mi := &file_openshell_proto_msgTypes[155] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12673,7 +12780,7 @@ func (x *RemoveNetworkBinary) String() string { func (*RemoveNetworkBinary) ProtoMessage() {} func (x *RemoveNetworkBinary) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[153] + mi := &file_openshell_proto_msgTypes[155] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12686,7 +12793,7 @@ func (x *RemoveNetworkBinary) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoveNetworkBinary.ProtoReflect.Descriptor instead. func (*RemoveNetworkBinary) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{153} + return file_openshell_proto_rawDescGZIP(), []int{155} } func (x *RemoveNetworkBinary) GetRuleName() string { @@ -12722,7 +12829,7 @@ type UpdateConfigResponse struct { func (x *UpdateConfigResponse) Reset() { *x = UpdateConfigResponse{} - mi := &file_openshell_proto_msgTypes[154] + mi := &file_openshell_proto_msgTypes[156] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12734,7 +12841,7 @@ func (x *UpdateConfigResponse) String() string { func (*UpdateConfigResponse) ProtoMessage() {} func (x *UpdateConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[154] + mi := &file_openshell_proto_msgTypes[156] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12747,7 +12854,7 @@ func (x *UpdateConfigResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateConfigResponse.ProtoReflect.Descriptor instead. func (*UpdateConfigResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{154} + return file_openshell_proto_rawDescGZIP(), []int{156} } func (x *UpdateConfigResponse) GetVersion() uint32 { @@ -12801,7 +12908,7 @@ type GetSandboxPolicyStatusRequest struct { func (x *GetSandboxPolicyStatusRequest) Reset() { *x = GetSandboxPolicyStatusRequest{} - mi := &file_openshell_proto_msgTypes[155] + mi := &file_openshell_proto_msgTypes[157] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12813,7 +12920,7 @@ func (x *GetSandboxPolicyStatusRequest) String() string { func (*GetSandboxPolicyStatusRequest) ProtoMessage() {} func (x *GetSandboxPolicyStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[155] + mi := &file_openshell_proto_msgTypes[157] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12826,7 +12933,7 @@ func (x *GetSandboxPolicyStatusRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetSandboxPolicyStatusRequest.ProtoReflect.Descriptor instead. func (*GetSandboxPolicyStatusRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{155} + return file_openshell_proto_rawDescGZIP(), []int{157} } func (x *GetSandboxPolicyStatusRequest) GetWorkspaceScope() *datamodelv1.WorkspaceSelector { @@ -12870,7 +12977,7 @@ type GetSandboxPolicyStatusResponse struct { func (x *GetSandboxPolicyStatusResponse) Reset() { *x = GetSandboxPolicyStatusResponse{} - mi := &file_openshell_proto_msgTypes[156] + mi := &file_openshell_proto_msgTypes[158] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12882,7 +12989,7 @@ func (x *GetSandboxPolicyStatusResponse) String() string { func (*GetSandboxPolicyStatusResponse) ProtoMessage() {} func (x *GetSandboxPolicyStatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[156] + mi := &file_openshell_proto_msgTypes[158] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12895,7 +13002,7 @@ func (x *GetSandboxPolicyStatusResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetSandboxPolicyStatusResponse.ProtoReflect.Descriptor instead. func (*GetSandboxPolicyStatusResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{156} + return file_openshell_proto_rawDescGZIP(), []int{158} } func (x *GetSandboxPolicyStatusResponse) GetRevision() *SandboxPolicyRevision { @@ -12932,7 +13039,7 @@ type ListSandboxPoliciesRequest struct { func (x *ListSandboxPoliciesRequest) Reset() { *x = ListSandboxPoliciesRequest{} - mi := &file_openshell_proto_msgTypes[157] + mi := &file_openshell_proto_msgTypes[159] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12944,7 +13051,7 @@ func (x *ListSandboxPoliciesRequest) String() string { func (*ListSandboxPoliciesRequest) ProtoMessage() {} func (x *ListSandboxPoliciesRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[157] + mi := &file_openshell_proto_msgTypes[159] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12957,7 +13064,7 @@ func (x *ListSandboxPoliciesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListSandboxPoliciesRequest.ProtoReflect.Descriptor instead. func (*ListSandboxPoliciesRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{157} + return file_openshell_proto_rawDescGZIP(), []int{159} } func (x *ListSandboxPoliciesRequest) GetWorkspaceScope() *datamodelv1.WorkspaceSelector { @@ -13009,7 +13116,7 @@ type ListSandboxPoliciesResponse struct { func (x *ListSandboxPoliciesResponse) Reset() { *x = ListSandboxPoliciesResponse{} - mi := &file_openshell_proto_msgTypes[158] + mi := &file_openshell_proto_msgTypes[160] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13021,7 +13128,7 @@ func (x *ListSandboxPoliciesResponse) String() string { func (*ListSandboxPoliciesResponse) ProtoMessage() {} func (x *ListSandboxPoliciesResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[158] + mi := &file_openshell_proto_msgTypes[160] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13034,7 +13141,7 @@ func (x *ListSandboxPoliciesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListSandboxPoliciesResponse.ProtoReflect.Descriptor instead. func (*ListSandboxPoliciesResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{158} + return file_openshell_proto_rawDescGZIP(), []int{160} } func (x *ListSandboxPoliciesResponse) GetRevisions() []*SandboxPolicyRevision { @@ -13068,7 +13175,7 @@ type ReportPolicyStatusRequest struct { func (x *ReportPolicyStatusRequest) Reset() { *x = ReportPolicyStatusRequest{} - mi := &file_openshell_proto_msgTypes[159] + mi := &file_openshell_proto_msgTypes[161] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13080,7 +13187,7 @@ func (x *ReportPolicyStatusRequest) String() string { func (*ReportPolicyStatusRequest) ProtoMessage() {} func (x *ReportPolicyStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[159] + mi := &file_openshell_proto_msgTypes[161] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13093,7 +13200,7 @@ func (x *ReportPolicyStatusRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ReportPolicyStatusRequest.ProtoReflect.Descriptor instead. func (*ReportPolicyStatusRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{159} + return file_openshell_proto_rawDescGZIP(), []int{161} } func (x *ReportPolicyStatusRequest) GetSandboxId() string { @@ -13133,7 +13240,7 @@ type ReportPolicyStatusResponse struct { func (x *ReportPolicyStatusResponse) Reset() { *x = ReportPolicyStatusResponse{} - mi := &file_openshell_proto_msgTypes[160] + mi := &file_openshell_proto_msgTypes[162] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13145,7 +13252,7 @@ func (x *ReportPolicyStatusResponse) String() string { func (*ReportPolicyStatusResponse) ProtoMessage() {} func (x *ReportPolicyStatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[160] + mi := &file_openshell_proto_msgTypes[162] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13158,7 +13265,7 @@ func (x *ReportPolicyStatusResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ReportPolicyStatusResponse.ProtoReflect.Descriptor instead. func (*ReportPolicyStatusResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{160} + return file_openshell_proto_rawDescGZIP(), []int{162} } type SandboxConfigurationAdmission struct { @@ -13176,7 +13283,7 @@ type SandboxConfigurationAdmission struct { func (x *SandboxConfigurationAdmission) Reset() { *x = SandboxConfigurationAdmission{} - mi := &file_openshell_proto_msgTypes[161] + mi := &file_openshell_proto_msgTypes[163] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13188,7 +13295,7 @@ func (x *SandboxConfigurationAdmission) String() string { func (*SandboxConfigurationAdmission) ProtoMessage() {} func (x *SandboxConfigurationAdmission) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[161] + mi := &file_openshell_proto_msgTypes[163] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13201,7 +13308,7 @@ func (x *SandboxConfigurationAdmission) ProtoReflect() protoreflect.Message { // Deprecated: Use SandboxConfigurationAdmission.ProtoReflect.Descriptor instead. func (*SandboxConfigurationAdmission) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{161} + return file_openshell_proto_rawDescGZIP(), []int{163} } func (x *SandboxConfigurationAdmission) GetInstanceId() string { @@ -13265,7 +13372,7 @@ type ReportSandboxConfigurationRequest struct { func (x *ReportSandboxConfigurationRequest) Reset() { *x = ReportSandboxConfigurationRequest{} - mi := &file_openshell_proto_msgTypes[162] + mi := &file_openshell_proto_msgTypes[164] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13277,7 +13384,7 @@ func (x *ReportSandboxConfigurationRequest) String() string { func (*ReportSandboxConfigurationRequest) ProtoMessage() {} func (x *ReportSandboxConfigurationRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[162] + mi := &file_openshell_proto_msgTypes[164] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13290,7 +13397,7 @@ func (x *ReportSandboxConfigurationRequest) ProtoReflect() protoreflect.Message // Deprecated: Use ReportSandboxConfigurationRequest.ProtoReflect.Descriptor instead. func (*ReportSandboxConfigurationRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{162} + return file_openshell_proto_rawDescGZIP(), []int{164} } func (x *ReportSandboxConfigurationRequest) GetSandboxId() string { @@ -13322,7 +13429,7 @@ type ReportSandboxConfigurationResponse struct { func (x *ReportSandboxConfigurationResponse) Reset() { *x = ReportSandboxConfigurationResponse{} - mi := &file_openshell_proto_msgTypes[163] + mi := &file_openshell_proto_msgTypes[165] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13334,7 +13441,7 @@ func (x *ReportSandboxConfigurationResponse) String() string { func (*ReportSandboxConfigurationResponse) ProtoMessage() {} func (x *ReportSandboxConfigurationResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[163] + mi := &file_openshell_proto_msgTypes[165] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13347,7 +13454,7 @@ func (x *ReportSandboxConfigurationResponse) ProtoReflect() protoreflect.Message // Deprecated: Use ReportSandboxConfigurationResponse.ProtoReflect.Descriptor instead. func (*ReportSandboxConfigurationResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{163} + return file_openshell_proto_rawDescGZIP(), []int{165} } // A versioned policy revision with metadata. @@ -13380,7 +13487,7 @@ type SandboxPolicyRevision struct { func (x *SandboxPolicyRevision) Reset() { *x = SandboxPolicyRevision{} - mi := &file_openshell_proto_msgTypes[164] + mi := &file_openshell_proto_msgTypes[166] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13392,7 +13499,7 @@ func (x *SandboxPolicyRevision) String() string { func (*SandboxPolicyRevision) ProtoMessage() {} func (x *SandboxPolicyRevision) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[164] + mi := &file_openshell_proto_msgTypes[166] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13405,7 +13512,7 @@ func (x *SandboxPolicyRevision) ProtoReflect() protoreflect.Message { // Deprecated: Use SandboxPolicyRevision.ProtoReflect.Descriptor instead. func (*SandboxPolicyRevision) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{164} + return file_openshell_proto_rawDescGZIP(), []int{166} } func (x *SandboxPolicyRevision) GetVersion() uint32 { @@ -13485,7 +13592,7 @@ type GetSandboxLogsRequest struct { func (x *GetSandboxLogsRequest) Reset() { *x = GetSandboxLogsRequest{} - mi := &file_openshell_proto_msgTypes[165] + mi := &file_openshell_proto_msgTypes[167] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13497,7 +13604,7 @@ func (x *GetSandboxLogsRequest) String() string { func (*GetSandboxLogsRequest) ProtoMessage() {} func (x *GetSandboxLogsRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[165] + mi := &file_openshell_proto_msgTypes[167] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13510,7 +13617,7 @@ func (x *GetSandboxLogsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetSandboxLogsRequest.ProtoReflect.Descriptor instead. func (*GetSandboxLogsRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{165} + return file_openshell_proto_rawDescGZIP(), []int{167} } func (x *GetSandboxLogsRequest) GetWorkspaceScope() *datamodelv1.WorkspaceSelector { @@ -13568,7 +13675,7 @@ type PushSandboxLogsRequest struct { func (x *PushSandboxLogsRequest) Reset() { *x = PushSandboxLogsRequest{} - mi := &file_openshell_proto_msgTypes[166] + mi := &file_openshell_proto_msgTypes[168] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13580,7 +13687,7 @@ func (x *PushSandboxLogsRequest) String() string { func (*PushSandboxLogsRequest) ProtoMessage() {} func (x *PushSandboxLogsRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[166] + mi := &file_openshell_proto_msgTypes[168] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13593,7 +13700,7 @@ func (x *PushSandboxLogsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PushSandboxLogsRequest.ProtoReflect.Descriptor instead. func (*PushSandboxLogsRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{166} + return file_openshell_proto_rawDescGZIP(), []int{168} } func (x *PushSandboxLogsRequest) GetSandboxId() string { @@ -13619,7 +13726,7 @@ type PushSandboxLogsResponse struct { func (x *PushSandboxLogsResponse) Reset() { *x = PushSandboxLogsResponse{} - mi := &file_openshell_proto_msgTypes[167] + mi := &file_openshell_proto_msgTypes[169] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13631,7 +13738,7 @@ func (x *PushSandboxLogsResponse) String() string { func (*PushSandboxLogsResponse) ProtoMessage() {} func (x *PushSandboxLogsResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[167] + mi := &file_openshell_proto_msgTypes[169] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13644,7 +13751,7 @@ func (x *PushSandboxLogsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PushSandboxLogsResponse.ProtoReflect.Descriptor instead. func (*PushSandboxLogsResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{167} + return file_openshell_proto_rawDescGZIP(), []int{169} } // Get sandbox logs response. @@ -13660,7 +13767,7 @@ type GetSandboxLogsResponse struct { func (x *GetSandboxLogsResponse) Reset() { *x = GetSandboxLogsResponse{} - mi := &file_openshell_proto_msgTypes[168] + mi := &file_openshell_proto_msgTypes[170] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13672,7 +13779,7 @@ func (x *GetSandboxLogsResponse) String() string { func (*GetSandboxLogsResponse) ProtoMessage() {} func (x *GetSandboxLogsResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[168] + mi := &file_openshell_proto_msgTypes[170] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13685,7 +13792,7 @@ func (x *GetSandboxLogsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetSandboxLogsResponse.ProtoReflect.Descriptor instead. func (*GetSandboxLogsResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{168} + return file_openshell_proto_rawDescGZIP(), []int{170} } func (x *GetSandboxLogsResponse) GetLogs() []*SandboxLogLine { @@ -13719,7 +13826,7 @@ type SupervisorMessage struct { func (x *SupervisorMessage) Reset() { *x = SupervisorMessage{} - mi := &file_openshell_proto_msgTypes[169] + mi := &file_openshell_proto_msgTypes[171] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13731,7 +13838,7 @@ func (x *SupervisorMessage) String() string { func (*SupervisorMessage) ProtoMessage() {} func (x *SupervisorMessage) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[169] + mi := &file_openshell_proto_msgTypes[171] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13744,7 +13851,7 @@ func (x *SupervisorMessage) ProtoReflect() protoreflect.Message { // Deprecated: Use SupervisorMessage.ProtoReflect.Descriptor instead. func (*SupervisorMessage) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{169} + return file_openshell_proto_rawDescGZIP(), []int{171} } func (x *SupervisorMessage) GetPayload() isSupervisorMessage_Payload { @@ -13852,7 +13959,7 @@ type GatewayMessage struct { func (x *GatewayMessage) Reset() { *x = GatewayMessage{} - mi := &file_openshell_proto_msgTypes[170] + mi := &file_openshell_proto_msgTypes[172] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13864,7 +13971,7 @@ func (x *GatewayMessage) String() string { func (*GatewayMessage) ProtoMessage() {} func (x *GatewayMessage) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[170] + mi := &file_openshell_proto_msgTypes[172] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13877,7 +13984,7 @@ func (x *GatewayMessage) ProtoReflect() protoreflect.Message { // Deprecated: Use GatewayMessage.ProtoReflect.Descriptor instead. func (*GatewayMessage) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{170} + return file_openshell_proto_rawDescGZIP(), []int{172} } func (x *GatewayMessage) GetPayload() isGatewayMessage_Payload { @@ -14027,7 +14134,7 @@ type SupervisorHello struct { func (x *SupervisorHello) Reset() { *x = SupervisorHello{} - mi := &file_openshell_proto_msgTypes[171] + mi := &file_openshell_proto_msgTypes[173] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14039,7 +14146,7 @@ func (x *SupervisorHello) String() string { func (*SupervisorHello) ProtoMessage() {} func (x *SupervisorHello) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[171] + mi := &file_openshell_proto_msgTypes[173] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14052,7 +14159,7 @@ func (x *SupervisorHello) ProtoReflect() protoreflect.Message { // Deprecated: Use SupervisorHello.ProtoReflect.Descriptor instead. func (*SupervisorHello) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{171} + return file_openshell_proto_rawDescGZIP(), []int{173} } func (x *SupervisorHello) GetSandboxId() string { @@ -14125,7 +14232,7 @@ type SessionAccepted struct { func (x *SessionAccepted) Reset() { *x = SessionAccepted{} - mi := &file_openshell_proto_msgTypes[172] + mi := &file_openshell_proto_msgTypes[174] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14137,7 +14244,7 @@ func (x *SessionAccepted) String() string { func (*SessionAccepted) ProtoMessage() {} func (x *SessionAccepted) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[172] + mi := &file_openshell_proto_msgTypes[174] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14150,7 +14257,7 @@ func (x *SessionAccepted) ProtoReflect() protoreflect.Message { // Deprecated: Use SessionAccepted.ProtoReflect.Descriptor instead. func (*SessionAccepted) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{172} + return file_openshell_proto_rawDescGZIP(), []int{174} } func (x *SessionAccepted) GetSessionId() string { @@ -14199,7 +14306,7 @@ type ConfigUpdate struct { func (x *ConfigUpdate) Reset() { *x = ConfigUpdate{} - mi := &file_openshell_proto_msgTypes[173] + mi := &file_openshell_proto_msgTypes[175] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14211,7 +14318,7 @@ func (x *ConfigUpdate) String() string { func (*ConfigUpdate) ProtoMessage() {} func (x *ConfigUpdate) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[173] + mi := &file_openshell_proto_msgTypes[175] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14224,7 +14331,7 @@ func (x *ConfigUpdate) ProtoReflect() protoreflect.Message { // Deprecated: Use ConfigUpdate.ProtoReflect.Descriptor instead. func (*ConfigUpdate) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{173} + return file_openshell_proto_rawDescGZIP(), []int{175} } func (x *ConfigUpdate) GetUpdateId() string { @@ -14261,7 +14368,7 @@ type ConfigApplyFailure struct { func (x *ConfigApplyFailure) Reset() { *x = ConfigApplyFailure{} - mi := &file_openshell_proto_msgTypes[174] + mi := &file_openshell_proto_msgTypes[176] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14273,7 +14380,7 @@ func (x *ConfigApplyFailure) String() string { func (*ConfigApplyFailure) ProtoMessage() {} func (x *ConfigApplyFailure) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[174] + mi := &file_openshell_proto_msgTypes[176] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14286,7 +14393,7 @@ func (x *ConfigApplyFailure) ProtoReflect() protoreflect.Message { // Deprecated: Use ConfigApplyFailure.ProtoReflect.Descriptor instead. func (*ConfigApplyFailure) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{174} + return file_openshell_proto_rawDescGZIP(), []int{176} } func (x *ConfigApplyFailure) GetCode() string { @@ -14330,7 +14437,7 @@ type ConfigUpdateResult struct { func (x *ConfigUpdateResult) Reset() { *x = ConfigUpdateResult{} - mi := &file_openshell_proto_msgTypes[175] + mi := &file_openshell_proto_msgTypes[177] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14342,7 +14449,7 @@ func (x *ConfigUpdateResult) String() string { func (*ConfigUpdateResult) ProtoMessage() {} func (x *ConfigUpdateResult) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[175] + mi := &file_openshell_proto_msgTypes[177] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14355,7 +14462,7 @@ func (x *ConfigUpdateResult) ProtoReflect() protoreflect.Message { // Deprecated: Use ConfigUpdateResult.ProtoReflect.Descriptor instead. func (*ConfigUpdateResult) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{175} + return file_openshell_proto_rawDescGZIP(), []int{177} } func (x *ConfigUpdateResult) GetUpdateId() string { @@ -14406,7 +14513,7 @@ type PolicyLoadResult struct { func (x *PolicyLoadResult) Reset() { *x = PolicyLoadResult{} - mi := &file_openshell_proto_msgTypes[176] + mi := &file_openshell_proto_msgTypes[178] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14418,7 +14525,7 @@ func (x *PolicyLoadResult) String() string { func (*PolicyLoadResult) ProtoMessage() {} func (x *PolicyLoadResult) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[176] + mi := &file_openshell_proto_msgTypes[178] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14431,7 +14538,7 @@ func (x *PolicyLoadResult) ProtoReflect() protoreflect.Message { // Deprecated: Use PolicyLoadResult.ProtoReflect.Descriptor instead. func (*PolicyLoadResult) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{176} + return file_openshell_proto_rawDescGZIP(), []int{178} } func (x *PolicyLoadResult) GetVersion() uint32 { @@ -14466,7 +14573,7 @@ type SessionRejected struct { func (x *SessionRejected) Reset() { *x = SessionRejected{} - mi := &file_openshell_proto_msgTypes[177] + mi := &file_openshell_proto_msgTypes[179] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14478,7 +14585,7 @@ func (x *SessionRejected) String() string { func (*SessionRejected) ProtoMessage() {} func (x *SessionRejected) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[177] + mi := &file_openshell_proto_msgTypes[179] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14491,7 +14598,7 @@ func (x *SessionRejected) ProtoReflect() protoreflect.Message { // Deprecated: Use SessionRejected.ProtoReflect.Descriptor instead. func (*SessionRejected) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{177} + return file_openshell_proto_rawDescGZIP(), []int{179} } func (x *SessionRejected) GetReason() string { @@ -14520,7 +14627,7 @@ type SessionRedirect struct { func (x *SessionRedirect) Reset() { *x = SessionRedirect{} - mi := &file_openshell_proto_msgTypes[178] + mi := &file_openshell_proto_msgTypes[180] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14532,7 +14639,7 @@ func (x *SessionRedirect) String() string { func (*SessionRedirect) ProtoMessage() {} func (x *SessionRedirect) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[178] + mi := &file_openshell_proto_msgTypes[180] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14545,7 +14652,7 @@ func (x *SessionRedirect) ProtoReflect() protoreflect.Message { // Deprecated: Use SessionRedirect.ProtoReflect.Descriptor instead. func (*SessionRedirect) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{178} + return file_openshell_proto_rawDescGZIP(), []int{180} } func (x *SessionRedirect) GetPeerEndpoint() string { @@ -14571,7 +14678,7 @@ type SupervisorHeartbeat struct { func (x *SupervisorHeartbeat) Reset() { *x = SupervisorHeartbeat{} - mi := &file_openshell_proto_msgTypes[179] + mi := &file_openshell_proto_msgTypes[181] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14583,7 +14690,7 @@ func (x *SupervisorHeartbeat) String() string { func (*SupervisorHeartbeat) ProtoMessage() {} func (x *SupervisorHeartbeat) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[179] + mi := &file_openshell_proto_msgTypes[181] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14596,7 +14703,7 @@ func (x *SupervisorHeartbeat) ProtoReflect() protoreflect.Message { // Deprecated: Use SupervisorHeartbeat.ProtoReflect.Descriptor instead. func (*SupervisorHeartbeat) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{179} + return file_openshell_proto_rawDescGZIP(), []int{181} } // Gateway heartbeat. @@ -14608,7 +14715,7 @@ type GatewayHeartbeat struct { func (x *GatewayHeartbeat) Reset() { *x = GatewayHeartbeat{} - mi := &file_openshell_proto_msgTypes[180] + mi := &file_openshell_proto_msgTypes[182] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14620,7 +14727,7 @@ func (x *GatewayHeartbeat) String() string { func (*GatewayHeartbeat) ProtoMessage() {} func (x *GatewayHeartbeat) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[180] + mi := &file_openshell_proto_msgTypes[182] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14633,7 +14740,7 @@ func (x *GatewayHeartbeat) ProtoReflect() protoreflect.Message { // Deprecated: Use GatewayHeartbeat.ProtoReflect.Descriptor instead. func (*GatewayHeartbeat) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{180} + return file_openshell_proto_rawDescGZIP(), []int{182} } // Terminal result reported before the supervisor shuts down. A successful RPC @@ -14650,7 +14757,7 @@ type ReportMainProcessExitRequest struct { func (x *ReportMainProcessExitRequest) Reset() { *x = ReportMainProcessExitRequest{} - mi := &file_openshell_proto_msgTypes[181] + mi := &file_openshell_proto_msgTypes[183] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14662,7 +14769,7 @@ func (x *ReportMainProcessExitRequest) String() string { func (*ReportMainProcessExitRequest) ProtoMessage() {} func (x *ReportMainProcessExitRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[181] + mi := &file_openshell_proto_msgTypes[183] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14675,7 +14782,7 @@ func (x *ReportMainProcessExitRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ReportMainProcessExitRequest.ProtoReflect.Descriptor instead. func (*ReportMainProcessExitRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{181} + return file_openshell_proto_rawDescGZIP(), []int{183} } func (x *ReportMainProcessExitRequest) GetSandboxId() string { @@ -14707,7 +14814,7 @@ type ReportMainProcessExitResponse struct { func (x *ReportMainProcessExitResponse) Reset() { *x = ReportMainProcessExitResponse{} - mi := &file_openshell_proto_msgTypes[182] + mi := &file_openshell_proto_msgTypes[184] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14719,7 +14826,7 @@ func (x *ReportMainProcessExitResponse) String() string { func (*ReportMainProcessExitResponse) ProtoMessage() {} func (x *ReportMainProcessExitResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[182] + mi := &file_openshell_proto_msgTypes[184] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14732,7 +14839,7 @@ func (x *ReportMainProcessExitResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ReportMainProcessExitResponse.ProtoReflect.Descriptor instead. func (*ReportMainProcessExitResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{182} + return file_openshell_proto_rawDescGZIP(), []int{184} } // Terminal-delivery completion reported after all expected foreground SSH @@ -14747,7 +14854,7 @@ type FinalizeMainProcessExitRequest struct { func (x *FinalizeMainProcessExitRequest) Reset() { *x = FinalizeMainProcessExitRequest{} - mi := &file_openshell_proto_msgTypes[183] + mi := &file_openshell_proto_msgTypes[185] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14759,7 +14866,7 @@ func (x *FinalizeMainProcessExitRequest) String() string { func (*FinalizeMainProcessExitRequest) ProtoMessage() {} func (x *FinalizeMainProcessExitRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[183] + mi := &file_openshell_proto_msgTypes[185] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14772,7 +14879,7 @@ func (x *FinalizeMainProcessExitRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use FinalizeMainProcessExitRequest.ProtoReflect.Descriptor instead. func (*FinalizeMainProcessExitRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{183} + return file_openshell_proto_rawDescGZIP(), []int{185} } func (x *FinalizeMainProcessExitRequest) GetSandboxId() string { @@ -14797,7 +14904,7 @@ type FinalizeMainProcessExitResponse struct { func (x *FinalizeMainProcessExitResponse) Reset() { *x = FinalizeMainProcessExitResponse{} - mi := &file_openshell_proto_msgTypes[184] + mi := &file_openshell_proto_msgTypes[186] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14809,7 +14916,7 @@ func (x *FinalizeMainProcessExitResponse) String() string { func (*FinalizeMainProcessExitResponse) ProtoMessage() {} func (x *FinalizeMainProcessExitResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[184] + mi := &file_openshell_proto_msgTypes[186] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14822,7 +14929,7 @@ func (x *FinalizeMainProcessExitResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use FinalizeMainProcessExitResponse.ProtoReflect.Descriptor instead. func (*FinalizeMainProcessExitResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{184} + return file_openshell_proto_rawDescGZIP(), []int{186} } // Gateway requests the supervisor to open a relay channel. @@ -14851,7 +14958,7 @@ type RelayOpen struct { func (x *RelayOpen) Reset() { *x = RelayOpen{} - mi := &file_openshell_proto_msgTypes[185] + mi := &file_openshell_proto_msgTypes[187] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14863,7 +14970,7 @@ func (x *RelayOpen) String() string { func (*RelayOpen) ProtoMessage() {} func (x *RelayOpen) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[185] + mi := &file_openshell_proto_msgTypes[187] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14876,7 +14983,7 @@ func (x *RelayOpen) ProtoReflect() protoreflect.Message { // Deprecated: Use RelayOpen.ProtoReflect.Descriptor instead. func (*RelayOpen) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{185} + return file_openshell_proto_rawDescGZIP(), []int{187} } func (x *RelayOpen) GetChannelId() string { @@ -14943,7 +15050,7 @@ type SshRelayTarget struct { func (x *SshRelayTarget) Reset() { *x = SshRelayTarget{} - mi := &file_openshell_proto_msgTypes[186] + mi := &file_openshell_proto_msgTypes[188] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14955,7 +15062,7 @@ func (x *SshRelayTarget) String() string { func (*SshRelayTarget) ProtoMessage() {} func (x *SshRelayTarget) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[186] + mi := &file_openshell_proto_msgTypes[188] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14968,7 +15075,7 @@ func (x *SshRelayTarget) ProtoReflect() protoreflect.Message { // Deprecated: Use SshRelayTarget.ProtoReflect.Descriptor instead. func (*SshRelayTarget) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{186} + return file_openshell_proto_rawDescGZIP(), []int{188} } // TCP target dialed by the supervisor from inside the sandbox. @@ -14984,7 +15091,7 @@ type TcpRelayTarget struct { func (x *TcpRelayTarget) Reset() { *x = TcpRelayTarget{} - mi := &file_openshell_proto_msgTypes[187] + mi := &file_openshell_proto_msgTypes[189] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14996,7 +15103,7 @@ func (x *TcpRelayTarget) String() string { func (*TcpRelayTarget) ProtoMessage() {} func (x *TcpRelayTarget) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[187] + mi := &file_openshell_proto_msgTypes[189] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15009,7 +15116,7 @@ func (x *TcpRelayTarget) ProtoReflect() protoreflect.Message { // Deprecated: Use TcpRelayTarget.ProtoReflect.Descriptor instead. func (*TcpRelayTarget) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{187} + return file_openshell_proto_rawDescGZIP(), []int{189} } func (x *TcpRelayTarget) GetHost() string { @@ -15037,7 +15144,7 @@ type RelayInit struct { func (x *RelayInit) Reset() { *x = RelayInit{} - mi := &file_openshell_proto_msgTypes[188] + mi := &file_openshell_proto_msgTypes[190] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15049,7 +15156,7 @@ func (x *RelayInit) String() string { func (*RelayInit) ProtoMessage() {} func (x *RelayInit) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[188] + mi := &file_openshell_proto_msgTypes[190] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15062,7 +15169,7 @@ func (x *RelayInit) ProtoReflect() protoreflect.Message { // Deprecated: Use RelayInit.ProtoReflect.Descriptor instead. func (*RelayInit) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{188} + return file_openshell_proto_rawDescGZIP(), []int{190} } func (x *RelayInit) GetChannelId() string { @@ -15089,7 +15196,7 @@ type RelayFrame struct { func (x *RelayFrame) Reset() { *x = RelayFrame{} - mi := &file_openshell_proto_msgTypes[189] + mi := &file_openshell_proto_msgTypes[191] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15101,7 +15208,7 @@ func (x *RelayFrame) String() string { func (*RelayFrame) ProtoMessage() {} func (x *RelayFrame) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[189] + mi := &file_openshell_proto_msgTypes[191] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15114,7 +15221,7 @@ func (x *RelayFrame) ProtoReflect() protoreflect.Message { // Deprecated: Use RelayFrame.ProtoReflect.Descriptor instead. func (*RelayFrame) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{189} + return file_openshell_proto_rawDescGZIP(), []int{191} } func (x *RelayFrame) GetPayload() isRelayFrame_Payload { @@ -15174,7 +15281,7 @@ type PeerRelayInit struct { func (x *PeerRelayInit) Reset() { *x = PeerRelayInit{} - mi := &file_openshell_proto_msgTypes[190] + mi := &file_openshell_proto_msgTypes[192] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15186,7 +15293,7 @@ func (x *PeerRelayInit) String() string { func (*PeerRelayInit) ProtoMessage() {} func (x *PeerRelayInit) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[190] + mi := &file_openshell_proto_msgTypes[192] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15199,7 +15306,7 @@ func (x *PeerRelayInit) ProtoReflect() protoreflect.Message { // Deprecated: Use PeerRelayInit.ProtoReflect.Descriptor instead. func (*PeerRelayInit) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{190} + return file_openshell_proto_rawDescGZIP(), []int{192} } func (x *PeerRelayInit) GetSandboxId() string { @@ -15237,7 +15344,7 @@ type PeerRelayFrame struct { func (x *PeerRelayFrame) Reset() { *x = PeerRelayFrame{} - mi := &file_openshell_proto_msgTypes[191] + mi := &file_openshell_proto_msgTypes[193] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15249,7 +15356,7 @@ func (x *PeerRelayFrame) String() string { func (*PeerRelayFrame) ProtoMessage() {} func (x *PeerRelayFrame) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[191] + mi := &file_openshell_proto_msgTypes[193] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15262,7 +15369,7 @@ func (x *PeerRelayFrame) ProtoReflect() protoreflect.Message { // Deprecated: Use PeerRelayFrame.ProtoReflect.Descriptor instead. func (*PeerRelayFrame) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{191} + return file_openshell_proto_rawDescGZIP(), []int{193} } func (x *PeerRelayFrame) GetPayload() isPeerRelayFrame_Payload { @@ -15317,7 +15424,7 @@ type PeerConfigSandboxTarget struct { func (x *PeerConfigSandboxTarget) Reset() { *x = PeerConfigSandboxTarget{} - mi := &file_openshell_proto_msgTypes[192] + mi := &file_openshell_proto_msgTypes[194] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15329,7 +15436,7 @@ func (x *PeerConfigSandboxTarget) String() string { func (*PeerConfigSandboxTarget) ProtoMessage() {} func (x *PeerConfigSandboxTarget) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[192] + mi := &file_openshell_proto_msgTypes[194] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15342,7 +15449,7 @@ func (x *PeerConfigSandboxTarget) ProtoReflect() protoreflect.Message { // Deprecated: Use PeerConfigSandboxTarget.ProtoReflect.Descriptor instead. func (*PeerConfigSandboxTarget) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{192} + return file_openshell_proto_rawDescGZIP(), []int{194} } func (x *PeerConfigSandboxTarget) GetSandboxId() string { @@ -15370,7 +15477,7 @@ type PeerConfigProviderTarget struct { func (x *PeerConfigProviderTarget) Reset() { *x = PeerConfigProviderTarget{} - mi := &file_openshell_proto_msgTypes[193] + mi := &file_openshell_proto_msgTypes[195] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15382,7 +15489,7 @@ func (x *PeerConfigProviderTarget) String() string { func (*PeerConfigProviderTarget) ProtoMessage() {} func (x *PeerConfigProviderTarget) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[193] + mi := &file_openshell_proto_msgTypes[195] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15395,7 +15502,7 @@ func (x *PeerConfigProviderTarget) ProtoReflect() protoreflect.Message { // Deprecated: Use PeerConfigProviderTarget.ProtoReflect.Descriptor instead. func (*PeerConfigProviderTarget) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{193} + return file_openshell_proto_rawDescGZIP(), []int{195} } func (x *PeerConfigProviderTarget) GetWorkspace() string { @@ -15427,7 +15534,7 @@ type PeerNotifyConfigUpdateRequest struct { func (x *PeerNotifyConfigUpdateRequest) Reset() { *x = PeerNotifyConfigUpdateRequest{} - mi := &file_openshell_proto_msgTypes[194] + mi := &file_openshell_proto_msgTypes[196] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15439,7 +15546,7 @@ func (x *PeerNotifyConfigUpdateRequest) String() string { func (*PeerNotifyConfigUpdateRequest) ProtoMessage() {} func (x *PeerNotifyConfigUpdateRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[194] + mi := &file_openshell_proto_msgTypes[196] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15452,7 +15559,7 @@ func (x *PeerNotifyConfigUpdateRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PeerNotifyConfigUpdateRequest.ProtoReflect.Descriptor instead. func (*PeerNotifyConfigUpdateRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{194} + return file_openshell_proto_rawDescGZIP(), []int{196} } func (x *PeerNotifyConfigUpdateRequest) GetScope() isPeerNotifyConfigUpdateRequest_Scope { @@ -15536,7 +15643,7 @@ type PeerNotifyConfigUpdateResponse struct { func (x *PeerNotifyConfigUpdateResponse) Reset() { *x = PeerNotifyConfigUpdateResponse{} - mi := &file_openshell_proto_msgTypes[195] + mi := &file_openshell_proto_msgTypes[197] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15548,7 +15655,7 @@ func (x *PeerNotifyConfigUpdateResponse) String() string { func (*PeerNotifyConfigUpdateResponse) ProtoMessage() {} func (x *PeerNotifyConfigUpdateResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[195] + mi := &file_openshell_proto_msgTypes[197] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15561,7 +15668,7 @@ func (x *PeerNotifyConfigUpdateResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PeerNotifyConfigUpdateResponse.ProtoReflect.Descriptor instead. func (*PeerNotifyConfigUpdateResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{195} + return file_openshell_proto_rawDescGZIP(), []int{197} } func (x *PeerNotifyConfigUpdateResponse) GetStaleOwner() bool { @@ -15586,7 +15693,7 @@ type RelayOpenResult struct { func (x *RelayOpenResult) Reset() { *x = RelayOpenResult{} - mi := &file_openshell_proto_msgTypes[196] + mi := &file_openshell_proto_msgTypes[198] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15598,7 +15705,7 @@ func (x *RelayOpenResult) String() string { func (*RelayOpenResult) ProtoMessage() {} func (x *RelayOpenResult) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[196] + mi := &file_openshell_proto_msgTypes[198] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15611,7 +15718,7 @@ func (x *RelayOpenResult) ProtoReflect() protoreflect.Message { // Deprecated: Use RelayOpenResult.ProtoReflect.Descriptor instead. func (*RelayOpenResult) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{196} + return file_openshell_proto_rawDescGZIP(), []int{198} } func (x *RelayOpenResult) GetChannelId() string { @@ -15648,7 +15755,7 @@ type RelayClose struct { func (x *RelayClose) Reset() { *x = RelayClose{} - mi := &file_openshell_proto_msgTypes[197] + mi := &file_openshell_proto_msgTypes[199] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15660,7 +15767,7 @@ func (x *RelayClose) String() string { func (*RelayClose) ProtoMessage() {} func (x *RelayClose) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[197] + mi := &file_openshell_proto_msgTypes[199] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15673,7 +15780,7 @@ func (x *RelayClose) ProtoReflect() protoreflect.Message { // Deprecated: Use RelayClose.ProtoReflect.Descriptor instead. func (*RelayClose) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{197} + return file_openshell_proto_rawDescGZIP(), []int{199} } func (x *RelayClose) GetChannelId() string { @@ -15707,7 +15814,7 @@ type L7RequestSample struct { func (x *L7RequestSample) Reset() { *x = L7RequestSample{} - mi := &file_openshell_proto_msgTypes[198] + mi := &file_openshell_proto_msgTypes[200] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15719,7 +15826,7 @@ func (x *L7RequestSample) String() string { func (*L7RequestSample) ProtoMessage() {} func (x *L7RequestSample) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[198] + mi := &file_openshell_proto_msgTypes[200] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15732,7 +15839,7 @@ func (x *L7RequestSample) ProtoReflect() protoreflect.Message { // Deprecated: Use L7RequestSample.ProtoReflect.Descriptor instead. func (*L7RequestSample) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{198} + return file_openshell_proto_rawDescGZIP(), []int{200} } func (x *L7RequestSample) GetMethod() string { @@ -15806,7 +15913,7 @@ type DenialSummary struct { func (x *DenialSummary) Reset() { *x = DenialSummary{} - mi := &file_openshell_proto_msgTypes[199] + mi := &file_openshell_proto_msgTypes[201] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15818,7 +15925,7 @@ func (x *DenialSummary) String() string { func (*DenialSummary) ProtoMessage() {} func (x *DenialSummary) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[199] + mi := &file_openshell_proto_msgTypes[201] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15831,7 +15938,7 @@ func (x *DenialSummary) ProtoReflect() protoreflect.Message { // Deprecated: Use DenialSummary.ProtoReflect.Descriptor instead. func (*DenialSummary) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{199} + return file_openshell_proto_rawDescGZIP(), []int{201} } func (x *DenialSummary) GetSandboxId() string { @@ -15966,7 +16073,7 @@ type DenialGroupCount struct { func (x *DenialGroupCount) Reset() { *x = DenialGroupCount{} - mi := &file_openshell_proto_msgTypes[200] + mi := &file_openshell_proto_msgTypes[202] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15978,7 +16085,7 @@ func (x *DenialGroupCount) String() string { func (*DenialGroupCount) ProtoMessage() {} func (x *DenialGroupCount) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[200] + mi := &file_openshell_proto_msgTypes[202] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15991,7 +16098,7 @@ func (x *DenialGroupCount) ProtoReflect() protoreflect.Message { // Deprecated: Use DenialGroupCount.ProtoReflect.Descriptor instead. func (*DenialGroupCount) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{200} + return file_openshell_proto_rawDescGZIP(), []int{202} } func (x *DenialGroupCount) GetDenyGroup() string { @@ -16024,7 +16131,7 @@ type NetworkActivitySummary struct { func (x *NetworkActivitySummary) Reset() { *x = NetworkActivitySummary{} - mi := &file_openshell_proto_msgTypes[201] + mi := &file_openshell_proto_msgTypes[203] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16036,7 +16143,7 @@ func (x *NetworkActivitySummary) String() string { func (*NetworkActivitySummary) ProtoMessage() {} func (x *NetworkActivitySummary) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[201] + mi := &file_openshell_proto_msgTypes[203] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16049,7 +16156,7 @@ func (x *NetworkActivitySummary) ProtoReflect() protoreflect.Message { // Deprecated: Use NetworkActivitySummary.ProtoReflect.Descriptor instead. func (*NetworkActivitySummary) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{201} + return file_openshell_proto_rawDescGZIP(), []int{203} } func (x *NetworkActivitySummary) GetNetworkActivityCount() uint32 { @@ -16137,7 +16244,7 @@ type PolicyChunk struct { func (x *PolicyChunk) Reset() { *x = PolicyChunk{} - mi := &file_openshell_proto_msgTypes[202] + mi := &file_openshell_proto_msgTypes[204] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16149,7 +16256,7 @@ func (x *PolicyChunk) String() string { func (*PolicyChunk) ProtoMessage() {} func (x *PolicyChunk) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[202] + mi := &file_openshell_proto_msgTypes[204] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16162,7 +16269,7 @@ func (x *PolicyChunk) ProtoReflect() protoreflect.Message { // Deprecated: Use PolicyChunk.ProtoReflect.Descriptor instead. func (*PolicyChunk) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{202} + return file_openshell_proto_rawDescGZIP(), []int{204} } func (x *PolicyChunk) GetId() string { @@ -16350,7 +16457,7 @@ type DraftPolicyUpdate struct { func (x *DraftPolicyUpdate) Reset() { *x = DraftPolicyUpdate{} - mi := &file_openshell_proto_msgTypes[203] + mi := &file_openshell_proto_msgTypes[205] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16362,7 +16469,7 @@ func (x *DraftPolicyUpdate) String() string { func (*DraftPolicyUpdate) ProtoMessage() {} func (x *DraftPolicyUpdate) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[203] + mi := &file_openshell_proto_msgTypes[205] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16375,7 +16482,7 @@ func (x *DraftPolicyUpdate) ProtoReflect() protoreflect.Message { // Deprecated: Use DraftPolicyUpdate.ProtoReflect.Descriptor instead. func (*DraftPolicyUpdate) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{203} + return file_openshell_proto_rawDescGZIP(), []int{205} } func (x *DraftPolicyUpdate) GetDraftVersion() uint64 { @@ -16434,7 +16541,7 @@ type SubmitPolicyAnalysisRequest struct { func (x *SubmitPolicyAnalysisRequest) Reset() { *x = SubmitPolicyAnalysisRequest{} - mi := &file_openshell_proto_msgTypes[204] + mi := &file_openshell_proto_msgTypes[206] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16446,7 +16553,7 @@ func (x *SubmitPolicyAnalysisRequest) String() string { func (*SubmitPolicyAnalysisRequest) ProtoMessage() {} func (x *SubmitPolicyAnalysisRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[204] + mi := &file_openshell_proto_msgTypes[206] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16459,7 +16566,7 @@ func (x *SubmitPolicyAnalysisRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SubmitPolicyAnalysisRequest.ProtoReflect.Descriptor instead. func (*SubmitPolicyAnalysisRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{204} + return file_openshell_proto_rawDescGZIP(), []int{206} } func (x *SubmitPolicyAnalysisRequest) GetWorkspaceScope() *datamodelv1.WorkspaceSelector { @@ -16522,7 +16629,7 @@ type SubmitPolicyAnalysisResponse struct { func (x *SubmitPolicyAnalysisResponse) Reset() { *x = SubmitPolicyAnalysisResponse{} - mi := &file_openshell_proto_msgTypes[205] + mi := &file_openshell_proto_msgTypes[207] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16534,7 +16641,7 @@ func (x *SubmitPolicyAnalysisResponse) String() string { func (*SubmitPolicyAnalysisResponse) ProtoMessage() {} func (x *SubmitPolicyAnalysisResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[205] + mi := &file_openshell_proto_msgTypes[207] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16547,7 +16654,7 @@ func (x *SubmitPolicyAnalysisResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SubmitPolicyAnalysisResponse.ProtoReflect.Descriptor instead. func (*SubmitPolicyAnalysisResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{205} + return file_openshell_proto_rawDescGZIP(), []int{207} } func (x *SubmitPolicyAnalysisResponse) GetAcceptedChunks() uint32 { @@ -16592,7 +16699,7 @@ type GetDraftPolicyRequest struct { func (x *GetDraftPolicyRequest) Reset() { *x = GetDraftPolicyRequest{} - mi := &file_openshell_proto_msgTypes[206] + mi := &file_openshell_proto_msgTypes[208] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16604,7 +16711,7 @@ func (x *GetDraftPolicyRequest) String() string { func (*GetDraftPolicyRequest) ProtoMessage() {} func (x *GetDraftPolicyRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[206] + mi := &file_openshell_proto_msgTypes[208] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16617,7 +16724,7 @@ func (x *GetDraftPolicyRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetDraftPolicyRequest.ProtoReflect.Descriptor instead. func (*GetDraftPolicyRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{206} + return file_openshell_proto_rawDescGZIP(), []int{208} } func (x *GetDraftPolicyRequest) GetWorkspaceScope() *datamodelv1.WorkspaceSelector { @@ -16657,7 +16764,7 @@ type GetDraftPolicyResponse struct { func (x *GetDraftPolicyResponse) Reset() { *x = GetDraftPolicyResponse{} - mi := &file_openshell_proto_msgTypes[207] + mi := &file_openshell_proto_msgTypes[209] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16669,7 +16776,7 @@ func (x *GetDraftPolicyResponse) String() string { func (*GetDraftPolicyResponse) ProtoMessage() {} func (x *GetDraftPolicyResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[207] + mi := &file_openshell_proto_msgTypes[209] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16682,7 +16789,7 @@ func (x *GetDraftPolicyResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetDraftPolicyResponse.ProtoReflect.Descriptor instead. func (*GetDraftPolicyResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{207} + return file_openshell_proto_rawDescGZIP(), []int{209} } func (x *GetDraftPolicyResponse) GetChunks() []*PolicyChunk { @@ -16733,7 +16840,7 @@ type ApproveDraftChunkRequest struct { func (x *ApproveDraftChunkRequest) Reset() { *x = ApproveDraftChunkRequest{} - mi := &file_openshell_proto_msgTypes[208] + mi := &file_openshell_proto_msgTypes[210] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16745,7 +16852,7 @@ func (x *ApproveDraftChunkRequest) String() string { func (*ApproveDraftChunkRequest) ProtoMessage() {} func (x *ApproveDraftChunkRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[208] + mi := &file_openshell_proto_msgTypes[210] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16758,7 +16865,7 @@ func (x *ApproveDraftChunkRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ApproveDraftChunkRequest.ProtoReflect.Descriptor instead. func (*ApproveDraftChunkRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{208} + return file_openshell_proto_rawDescGZIP(), []int{210} } func (x *ApproveDraftChunkRequest) GetWorkspaceScope() *datamodelv1.WorkspaceSelector { @@ -16808,7 +16915,7 @@ type ApproveDraftChunkResponse struct { func (x *ApproveDraftChunkResponse) Reset() { *x = ApproveDraftChunkResponse{} - mi := &file_openshell_proto_msgTypes[209] + mi := &file_openshell_proto_msgTypes[211] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16820,7 +16927,7 @@ func (x *ApproveDraftChunkResponse) String() string { func (*ApproveDraftChunkResponse) ProtoMessage() {} func (x *ApproveDraftChunkResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[209] + mi := &file_openshell_proto_msgTypes[211] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16833,7 +16940,7 @@ func (x *ApproveDraftChunkResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ApproveDraftChunkResponse.ProtoReflect.Descriptor instead. func (*ApproveDraftChunkResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{209} + return file_openshell_proto_rawDescGZIP(), []int{211} } func (x *ApproveDraftChunkResponse) GetPolicyVersion() uint32 { @@ -16869,7 +16976,7 @@ type RejectDraftChunkRequest struct { func (x *RejectDraftChunkRequest) Reset() { *x = RejectDraftChunkRequest{} - mi := &file_openshell_proto_msgTypes[210] + mi := &file_openshell_proto_msgTypes[212] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16881,7 +16988,7 @@ func (x *RejectDraftChunkRequest) String() string { func (*RejectDraftChunkRequest) ProtoMessage() {} func (x *RejectDraftChunkRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[210] + mi := &file_openshell_proto_msgTypes[212] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16894,7 +17001,7 @@ func (x *RejectDraftChunkRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RejectDraftChunkRequest.ProtoReflect.Descriptor instead. func (*RejectDraftChunkRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{210} + return file_openshell_proto_rawDescGZIP(), []int{212} } func (x *RejectDraftChunkRequest) GetWorkspaceScope() *datamodelv1.WorkspaceSelector { @@ -16940,7 +17047,7 @@ type RejectDraftChunkResponse struct { func (x *RejectDraftChunkResponse) Reset() { *x = RejectDraftChunkResponse{} - mi := &file_openshell_proto_msgTypes[211] + mi := &file_openshell_proto_msgTypes[213] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16952,7 +17059,7 @@ func (x *RejectDraftChunkResponse) String() string { func (*RejectDraftChunkResponse) ProtoMessage() {} func (x *RejectDraftChunkResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[211] + mi := &file_openshell_proto_msgTypes[213] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16965,7 +17072,7 @@ func (x *RejectDraftChunkResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RejectDraftChunkResponse.ProtoReflect.Descriptor instead. func (*RejectDraftChunkResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{211} + return file_openshell_proto_rawDescGZIP(), []int{213} } // Approve all pending chunks. @@ -16979,7 +17086,7 @@ type DraftChunkApproval struct { func (x *DraftChunkApproval) Reset() { *x = DraftChunkApproval{} - mi := &file_openshell_proto_msgTypes[212] + mi := &file_openshell_proto_msgTypes[214] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16991,7 +17098,7 @@ func (x *DraftChunkApproval) String() string { func (*DraftChunkApproval) ProtoMessage() {} func (x *DraftChunkApproval) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[212] + mi := &file_openshell_proto_msgTypes[214] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17004,7 +17111,7 @@ func (x *DraftChunkApproval) ProtoReflect() protoreflect.Message { // Deprecated: Use DraftChunkApproval.ProtoReflect.Descriptor instead. func (*DraftChunkApproval) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{212} + return file_openshell_proto_rawDescGZIP(), []int{214} } func (x *DraftChunkApproval) GetChunkId() string { @@ -17040,7 +17147,7 @@ type ApproveAllDraftChunksRequest struct { func (x *ApproveAllDraftChunksRequest) Reset() { *x = ApproveAllDraftChunksRequest{} - mi := &file_openshell_proto_msgTypes[213] + mi := &file_openshell_proto_msgTypes[215] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17052,7 +17159,7 @@ func (x *ApproveAllDraftChunksRequest) String() string { func (*ApproveAllDraftChunksRequest) ProtoMessage() {} func (x *ApproveAllDraftChunksRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[213] + mi := &file_openshell_proto_msgTypes[215] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17065,7 +17172,7 @@ func (x *ApproveAllDraftChunksRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ApproveAllDraftChunksRequest.ProtoReflect.Descriptor instead. func (*ApproveAllDraftChunksRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{213} + return file_openshell_proto_rawDescGZIP(), []int{215} } func (x *ApproveAllDraftChunksRequest) GetWorkspaceScope() *datamodelv1.WorkspaceSelector { @@ -17120,7 +17227,7 @@ type ApproveAllDraftChunksResponse struct { func (x *ApproveAllDraftChunksResponse) Reset() { *x = ApproveAllDraftChunksResponse{} - mi := &file_openshell_proto_msgTypes[214] + mi := &file_openshell_proto_msgTypes[216] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17132,7 +17239,7 @@ func (x *ApproveAllDraftChunksResponse) String() string { func (*ApproveAllDraftChunksResponse) ProtoMessage() {} func (x *ApproveAllDraftChunksResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[214] + mi := &file_openshell_proto_msgTypes[216] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17145,7 +17252,7 @@ func (x *ApproveAllDraftChunksResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ApproveAllDraftChunksResponse.ProtoReflect.Descriptor instead. func (*ApproveAllDraftChunksResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{214} + return file_openshell_proto_rawDescGZIP(), []int{216} } func (x *ApproveAllDraftChunksResponse) GetPolicyVersion() uint32 { @@ -17195,7 +17302,7 @@ type EditDraftChunkRequest struct { func (x *EditDraftChunkRequest) Reset() { *x = EditDraftChunkRequest{} - mi := &file_openshell_proto_msgTypes[215] + mi := &file_openshell_proto_msgTypes[217] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17207,7 +17314,7 @@ func (x *EditDraftChunkRequest) String() string { func (*EditDraftChunkRequest) ProtoMessage() {} func (x *EditDraftChunkRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[215] + mi := &file_openshell_proto_msgTypes[217] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17220,7 +17327,7 @@ func (x *EditDraftChunkRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use EditDraftChunkRequest.ProtoReflect.Descriptor instead. func (*EditDraftChunkRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{215} + return file_openshell_proto_rawDescGZIP(), []int{217} } func (x *EditDraftChunkRequest) GetWorkspaceScope() *datamodelv1.WorkspaceSelector { @@ -17266,7 +17373,7 @@ type EditDraftChunkResponse struct { func (x *EditDraftChunkResponse) Reset() { *x = EditDraftChunkResponse{} - mi := &file_openshell_proto_msgTypes[216] + mi := &file_openshell_proto_msgTypes[218] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17278,7 +17385,7 @@ func (x *EditDraftChunkResponse) String() string { func (*EditDraftChunkResponse) ProtoMessage() {} func (x *EditDraftChunkResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[216] + mi := &file_openshell_proto_msgTypes[218] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17291,7 +17398,7 @@ func (x *EditDraftChunkResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use EditDraftChunkResponse.ProtoReflect.Descriptor instead. func (*EditDraftChunkResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{216} + return file_openshell_proto_rawDescGZIP(), []int{218} } // Reverse an approval (remove merged rule from active policy). @@ -17311,7 +17418,7 @@ type UndoDraftChunkRequest struct { func (x *UndoDraftChunkRequest) Reset() { *x = UndoDraftChunkRequest{} - mi := &file_openshell_proto_msgTypes[217] + mi := &file_openshell_proto_msgTypes[219] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17323,7 +17430,7 @@ func (x *UndoDraftChunkRequest) String() string { func (*UndoDraftChunkRequest) ProtoMessage() {} func (x *UndoDraftChunkRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[217] + mi := &file_openshell_proto_msgTypes[219] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17336,7 +17443,7 @@ func (x *UndoDraftChunkRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UndoDraftChunkRequest.ProtoReflect.Descriptor instead. func (*UndoDraftChunkRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{217} + return file_openshell_proto_rawDescGZIP(), []int{219} } func (x *UndoDraftChunkRequest) GetWorkspaceScope() *datamodelv1.WorkspaceSelector { @@ -17379,7 +17486,7 @@ type UndoDraftChunkResponse struct { func (x *UndoDraftChunkResponse) Reset() { *x = UndoDraftChunkResponse{} - mi := &file_openshell_proto_msgTypes[218] + mi := &file_openshell_proto_msgTypes[220] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17391,7 +17498,7 @@ func (x *UndoDraftChunkResponse) String() string { func (*UndoDraftChunkResponse) ProtoMessage() {} func (x *UndoDraftChunkResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[218] + mi := &file_openshell_proto_msgTypes[220] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17404,7 +17511,7 @@ func (x *UndoDraftChunkResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UndoDraftChunkResponse.ProtoReflect.Descriptor instead. func (*UndoDraftChunkResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{218} + return file_openshell_proto_rawDescGZIP(), []int{220} } func (x *UndoDraftChunkResponse) GetPolicyVersion() uint32 { @@ -17436,7 +17543,7 @@ type ClearDraftChunksRequest struct { func (x *ClearDraftChunksRequest) Reset() { *x = ClearDraftChunksRequest{} - mi := &file_openshell_proto_msgTypes[219] + mi := &file_openshell_proto_msgTypes[221] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17448,7 +17555,7 @@ func (x *ClearDraftChunksRequest) String() string { func (*ClearDraftChunksRequest) ProtoMessage() {} func (x *ClearDraftChunksRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[219] + mi := &file_openshell_proto_msgTypes[221] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17461,7 +17568,7 @@ func (x *ClearDraftChunksRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ClearDraftChunksRequest.ProtoReflect.Descriptor instead. func (*ClearDraftChunksRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{219} + return file_openshell_proto_rawDescGZIP(), []int{221} } func (x *ClearDraftChunksRequest) GetWorkspaceScope() *datamodelv1.WorkspaceSelector { @@ -17495,7 +17602,7 @@ type ClearDraftChunksResponse struct { func (x *ClearDraftChunksResponse) Reset() { *x = ClearDraftChunksResponse{} - mi := &file_openshell_proto_msgTypes[220] + mi := &file_openshell_proto_msgTypes[222] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17507,7 +17614,7 @@ func (x *ClearDraftChunksResponse) String() string { func (*ClearDraftChunksResponse) ProtoMessage() {} func (x *ClearDraftChunksResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[220] + mi := &file_openshell_proto_msgTypes[222] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17520,7 +17627,7 @@ func (x *ClearDraftChunksResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ClearDraftChunksResponse.ProtoReflect.Descriptor instead. func (*ClearDraftChunksResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{220} + return file_openshell_proto_rawDescGZIP(), []int{222} } func (x *ClearDraftChunksResponse) GetChunksCleared() uint32 { @@ -17542,7 +17649,7 @@ type GetDraftHistoryRequest struct { func (x *GetDraftHistoryRequest) Reset() { *x = GetDraftHistoryRequest{} - mi := &file_openshell_proto_msgTypes[221] + mi := &file_openshell_proto_msgTypes[223] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17554,7 +17661,7 @@ func (x *GetDraftHistoryRequest) String() string { func (*GetDraftHistoryRequest) ProtoMessage() {} func (x *GetDraftHistoryRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[221] + mi := &file_openshell_proto_msgTypes[223] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17567,7 +17674,7 @@ func (x *GetDraftHistoryRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetDraftHistoryRequest.ProtoReflect.Descriptor instead. func (*GetDraftHistoryRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{221} + return file_openshell_proto_rawDescGZIP(), []int{223} } func (x *GetDraftHistoryRequest) GetWorkspaceScope() *datamodelv1.WorkspaceSelector { @@ -17601,7 +17708,7 @@ type DraftHistoryEntry struct { func (x *DraftHistoryEntry) Reset() { *x = DraftHistoryEntry{} - mi := &file_openshell_proto_msgTypes[222] + mi := &file_openshell_proto_msgTypes[224] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17613,7 +17720,7 @@ func (x *DraftHistoryEntry) String() string { func (*DraftHistoryEntry) ProtoMessage() {} func (x *DraftHistoryEntry) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[222] + mi := &file_openshell_proto_msgTypes[224] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17626,7 +17733,7 @@ func (x *DraftHistoryEntry) ProtoReflect() protoreflect.Message { // Deprecated: Use DraftHistoryEntry.ProtoReflect.Descriptor instead. func (*DraftHistoryEntry) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{222} + return file_openshell_proto_rawDescGZIP(), []int{224} } func (x *DraftHistoryEntry) GetEventTime() *timestamppb.Timestamp { @@ -17667,7 +17774,7 @@ type GetDraftHistoryResponse struct { func (x *GetDraftHistoryResponse) Reset() { *x = GetDraftHistoryResponse{} - mi := &file_openshell_proto_msgTypes[223] + mi := &file_openshell_proto_msgTypes[225] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17679,7 +17786,7 @@ func (x *GetDraftHistoryResponse) String() string { func (*GetDraftHistoryResponse) ProtoMessage() {} func (x *GetDraftHistoryResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[223] + mi := &file_openshell_proto_msgTypes[225] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17692,7 +17799,7 @@ func (x *GetDraftHistoryResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetDraftHistoryResponse.ProtoReflect.Descriptor instead. func (*GetDraftHistoryResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{223} + return file_openshell_proto_rawDescGZIP(), []int{225} } func (x *GetDraftHistoryResponse) GetEntries() []*DraftHistoryEntry { @@ -17717,7 +17824,7 @@ type CreateWorkspaceRequest struct { func (x *CreateWorkspaceRequest) Reset() { *x = CreateWorkspaceRequest{} - mi := &file_openshell_proto_msgTypes[224] + mi := &file_openshell_proto_msgTypes[226] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17729,7 +17836,7 @@ func (x *CreateWorkspaceRequest) String() string { func (*CreateWorkspaceRequest) ProtoMessage() {} func (x *CreateWorkspaceRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[224] + mi := &file_openshell_proto_msgTypes[226] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17742,7 +17849,7 @@ func (x *CreateWorkspaceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateWorkspaceRequest.ProtoReflect.Descriptor instead. func (*CreateWorkspaceRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{224} + return file_openshell_proto_rawDescGZIP(), []int{226} } func (x *CreateWorkspaceRequest) GetName() string { @@ -17776,7 +17883,7 @@ type CreateWorkspaceResponse struct { func (x *CreateWorkspaceResponse) Reset() { *x = CreateWorkspaceResponse{} - mi := &file_openshell_proto_msgTypes[225] + mi := &file_openshell_proto_msgTypes[227] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17788,7 +17895,7 @@ func (x *CreateWorkspaceResponse) String() string { func (*CreateWorkspaceResponse) ProtoMessage() {} func (x *CreateWorkspaceResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[225] + mi := &file_openshell_proto_msgTypes[227] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17801,7 +17908,7 @@ func (x *CreateWorkspaceResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateWorkspaceResponse.ProtoReflect.Descriptor instead. func (*CreateWorkspaceResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{225} + return file_openshell_proto_rawDescGZIP(), []int{227} } func (x *CreateWorkspaceResponse) GetWorkspace() *datamodelv1.Workspace { @@ -17822,7 +17929,7 @@ type GetWorkspaceRequest struct { func (x *GetWorkspaceRequest) Reset() { *x = GetWorkspaceRequest{} - mi := &file_openshell_proto_msgTypes[226] + mi := &file_openshell_proto_msgTypes[228] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17834,7 +17941,7 @@ func (x *GetWorkspaceRequest) String() string { func (*GetWorkspaceRequest) ProtoMessage() {} func (x *GetWorkspaceRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[226] + mi := &file_openshell_proto_msgTypes[228] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17847,7 +17954,7 @@ func (x *GetWorkspaceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetWorkspaceRequest.ProtoReflect.Descriptor instead. func (*GetWorkspaceRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{226} + return file_openshell_proto_rawDescGZIP(), []int{228} } func (x *GetWorkspaceRequest) GetName() string { @@ -17867,7 +17974,7 @@ type GetWorkspaceResponse struct { func (x *GetWorkspaceResponse) Reset() { *x = GetWorkspaceResponse{} - mi := &file_openshell_proto_msgTypes[227] + mi := &file_openshell_proto_msgTypes[229] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17879,7 +17986,7 @@ func (x *GetWorkspaceResponse) String() string { func (*GetWorkspaceResponse) ProtoMessage() {} func (x *GetWorkspaceResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[227] + mi := &file_openshell_proto_msgTypes[229] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17892,7 +17999,7 @@ func (x *GetWorkspaceResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetWorkspaceResponse.ProtoReflect.Descriptor instead. func (*GetWorkspaceResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{227} + return file_openshell_proto_rawDescGZIP(), []int{229} } func (x *GetWorkspaceResponse) GetWorkspace() *datamodelv1.Workspace { @@ -17919,7 +18026,7 @@ type ListWorkspacesRequest struct { func (x *ListWorkspacesRequest) Reset() { *x = ListWorkspacesRequest{} - mi := &file_openshell_proto_msgTypes[228] + mi := &file_openshell_proto_msgTypes[230] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17931,7 +18038,7 @@ func (x *ListWorkspacesRequest) String() string { func (*ListWorkspacesRequest) ProtoMessage() {} func (x *ListWorkspacesRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[228] + mi := &file_openshell_proto_msgTypes[230] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17944,7 +18051,7 @@ func (x *ListWorkspacesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListWorkspacesRequest.ProtoReflect.Descriptor instead. func (*ListWorkspacesRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{228} + return file_openshell_proto_rawDescGZIP(), []int{230} } func (x *ListWorkspacesRequest) GetPageSize() int32 { @@ -17980,7 +18087,7 @@ type ListWorkspacesResponse struct { func (x *ListWorkspacesResponse) Reset() { *x = ListWorkspacesResponse{} - mi := &file_openshell_proto_msgTypes[229] + mi := &file_openshell_proto_msgTypes[231] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17992,7 +18099,7 @@ func (x *ListWorkspacesResponse) String() string { func (*ListWorkspacesResponse) ProtoMessage() {} func (x *ListWorkspacesResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[229] + mi := &file_openshell_proto_msgTypes[231] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18005,7 +18112,7 @@ func (x *ListWorkspacesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListWorkspacesResponse.ProtoReflect.Descriptor instead. func (*ListWorkspacesResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{229} + return file_openshell_proto_rawDescGZIP(), []int{231} } func (x *ListWorkspacesResponse) GetWorkspaces() []*datamodelv1.Workspace { @@ -18036,7 +18143,7 @@ type DeleteWorkspaceRequest struct { func (x *DeleteWorkspaceRequest) Reset() { *x = DeleteWorkspaceRequest{} - mi := &file_openshell_proto_msgTypes[230] + mi := &file_openshell_proto_msgTypes[232] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18048,7 +18155,7 @@ func (x *DeleteWorkspaceRequest) String() string { func (*DeleteWorkspaceRequest) ProtoMessage() {} func (x *DeleteWorkspaceRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[230] + mi := &file_openshell_proto_msgTypes[232] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18061,7 +18168,7 @@ func (x *DeleteWorkspaceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteWorkspaceRequest.ProtoReflect.Descriptor instead. func (*DeleteWorkspaceRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{230} + return file_openshell_proto_rawDescGZIP(), []int{232} } func (x *DeleteWorkspaceRequest) GetName() string { @@ -18095,7 +18202,7 @@ type DeleteWorkspaceResponse struct { func (x *DeleteWorkspaceResponse) Reset() { *x = DeleteWorkspaceResponse{} - mi := &file_openshell_proto_msgTypes[231] + mi := &file_openshell_proto_msgTypes[233] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18107,7 +18214,7 @@ func (x *DeleteWorkspaceResponse) String() string { func (*DeleteWorkspaceResponse) ProtoMessage() {} func (x *DeleteWorkspaceResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[231] + mi := &file_openshell_proto_msgTypes[233] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18120,7 +18227,7 @@ func (x *DeleteWorkspaceResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteWorkspaceResponse.ProtoReflect.Descriptor instead. func (*DeleteWorkspaceResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{231} + return file_openshell_proto_rawDescGZIP(), []int{233} } func (x *DeleteWorkspaceResponse) GetOutcome() DeletionOutcome { @@ -18144,7 +18251,7 @@ type WorkspaceMember struct { func (x *WorkspaceMember) Reset() { *x = WorkspaceMember{} - mi := &file_openshell_proto_msgTypes[232] + mi := &file_openshell_proto_msgTypes[234] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18156,7 +18263,7 @@ func (x *WorkspaceMember) String() string { func (*WorkspaceMember) ProtoMessage() {} func (x *WorkspaceMember) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[232] + mi := &file_openshell_proto_msgTypes[234] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18169,7 +18276,7 @@ func (x *WorkspaceMember) ProtoReflect() protoreflect.Message { // Deprecated: Use WorkspaceMember.ProtoReflect.Descriptor instead. func (*WorkspaceMember) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{232} + return file_openshell_proto_rawDescGZIP(), []int{234} } func (x *WorkspaceMember) GetMetadata() *datamodelv1.ObjectMeta { @@ -18210,7 +18317,7 @@ type AddWorkspaceMemberRequest struct { func (x *AddWorkspaceMemberRequest) Reset() { *x = AddWorkspaceMemberRequest{} - mi := &file_openshell_proto_msgTypes[233] + mi := &file_openshell_proto_msgTypes[235] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18222,7 +18329,7 @@ func (x *AddWorkspaceMemberRequest) String() string { func (*AddWorkspaceMemberRequest) ProtoMessage() {} func (x *AddWorkspaceMemberRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[233] + mi := &file_openshell_proto_msgTypes[235] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18235,7 +18342,7 @@ func (x *AddWorkspaceMemberRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use AddWorkspaceMemberRequest.ProtoReflect.Descriptor instead. func (*AddWorkspaceMemberRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{233} + return file_openshell_proto_rawDescGZIP(), []int{235} } func (x *AddWorkspaceMemberRequest) GetWorkspaceScope() *datamodelv1.WorkspaceSelector { @@ -18276,7 +18383,7 @@ type AddWorkspaceMemberResponse struct { func (x *AddWorkspaceMemberResponse) Reset() { *x = AddWorkspaceMemberResponse{} - mi := &file_openshell_proto_msgTypes[234] + mi := &file_openshell_proto_msgTypes[236] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18288,7 +18395,7 @@ func (x *AddWorkspaceMemberResponse) String() string { func (*AddWorkspaceMemberResponse) ProtoMessage() {} func (x *AddWorkspaceMemberResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[234] + mi := &file_openshell_proto_msgTypes[236] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18301,7 +18408,7 @@ func (x *AddWorkspaceMemberResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use AddWorkspaceMemberResponse.ProtoReflect.Descriptor instead. func (*AddWorkspaceMemberResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{234} + return file_openshell_proto_rawDescGZIP(), []int{236} } func (x *AddWorkspaceMemberResponse) GetMember() *WorkspaceMember { @@ -18327,7 +18434,7 @@ type RemoveWorkspaceMemberRequest struct { func (x *RemoveWorkspaceMemberRequest) Reset() { *x = RemoveWorkspaceMemberRequest{} - mi := &file_openshell_proto_msgTypes[235] + mi := &file_openshell_proto_msgTypes[237] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18339,7 +18446,7 @@ func (x *RemoveWorkspaceMemberRequest) String() string { func (*RemoveWorkspaceMemberRequest) ProtoMessage() {} func (x *RemoveWorkspaceMemberRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[235] + mi := &file_openshell_proto_msgTypes[237] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18352,7 +18459,7 @@ func (x *RemoveWorkspaceMemberRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoveWorkspaceMemberRequest.ProtoReflect.Descriptor instead. func (*RemoveWorkspaceMemberRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{235} + return file_openshell_proto_rawDescGZIP(), []int{237} } func (x *RemoveWorkspaceMemberRequest) GetWorkspaceScope() *datamodelv1.WorkspaceSelector { @@ -18393,7 +18500,7 @@ type RemoveWorkspaceMemberResponse struct { func (x *RemoveWorkspaceMemberResponse) Reset() { *x = RemoveWorkspaceMemberResponse{} - mi := &file_openshell_proto_msgTypes[236] + mi := &file_openshell_proto_msgTypes[238] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18405,7 +18512,7 @@ func (x *RemoveWorkspaceMemberResponse) String() string { func (*RemoveWorkspaceMemberResponse) ProtoMessage() {} func (x *RemoveWorkspaceMemberResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[236] + mi := &file_openshell_proto_msgTypes[238] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18418,7 +18525,7 @@ func (x *RemoveWorkspaceMemberResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoveWorkspaceMemberResponse.ProtoReflect.Descriptor instead. func (*RemoveWorkspaceMemberResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{236} + return file_openshell_proto_rawDescGZIP(), []int{238} } func (x *RemoveWorkspaceMemberResponse) GetOutcome() DeletionOutcome { @@ -18445,7 +18552,7 @@ type ListWorkspaceMembersRequest struct { func (x *ListWorkspaceMembersRequest) Reset() { *x = ListWorkspaceMembersRequest{} - mi := &file_openshell_proto_msgTypes[237] + mi := &file_openshell_proto_msgTypes[239] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18457,7 +18564,7 @@ func (x *ListWorkspaceMembersRequest) String() string { func (*ListWorkspaceMembersRequest) ProtoMessage() {} func (x *ListWorkspaceMembersRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[237] + mi := &file_openshell_proto_msgTypes[239] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18470,7 +18577,7 @@ func (x *ListWorkspaceMembersRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListWorkspaceMembersRequest.ProtoReflect.Descriptor instead. func (*ListWorkspaceMembersRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{237} + return file_openshell_proto_rawDescGZIP(), []int{239} } func (x *ListWorkspaceMembersRequest) GetWorkspaceScope() *datamodelv1.WorkspaceSelector { @@ -18506,7 +18613,7 @@ type ListWorkspaceMembersResponse struct { func (x *ListWorkspaceMembersResponse) Reset() { *x = ListWorkspaceMembersResponse{} - mi := &file_openshell_proto_msgTypes[238] + mi := &file_openshell_proto_msgTypes[240] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18518,7 +18625,7 @@ func (x *ListWorkspaceMembersResponse) String() string { func (*ListWorkspaceMembersResponse) ProtoMessage() {} func (x *ListWorkspaceMembersResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[238] + mi := &file_openshell_proto_msgTypes[240] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18531,7 +18638,7 @@ func (x *ListWorkspaceMembersResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListWorkspaceMembersResponse.ProtoReflect.Descriptor instead. func (*ListWorkspaceMembersResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{238} + return file_openshell_proto_rawDescGZIP(), []int{240} } func (x *ListWorkspaceMembersResponse) GetMembers() []*WorkspaceMember { @@ -18566,7 +18673,7 @@ type ExtensionServiceCredential struct { func (x *ExtensionServiceCredential) Reset() { *x = ExtensionServiceCredential{} - mi := &file_openshell_proto_msgTypes[239] + mi := &file_openshell_proto_msgTypes[241] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18578,7 +18685,7 @@ func (x *ExtensionServiceCredential) String() string { func (*ExtensionServiceCredential) ProtoMessage() {} func (x *ExtensionServiceCredential) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[239] + mi := &file_openshell_proto_msgTypes[241] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18591,7 +18698,7 @@ func (x *ExtensionServiceCredential) ProtoReflect() protoreflect.Message { // Deprecated: Use ExtensionServiceCredential.ProtoReflect.Descriptor instead. func (*ExtensionServiceCredential) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{239} + return file_openshell_proto_rawDescGZIP(), []int{241} } func (x *ExtensionServiceCredential) GetServiceName() string { @@ -18631,7 +18738,7 @@ type EndpointObservation struct { func (x *EndpointObservation) Reset() { *x = EndpointObservation{} - mi := &file_openshell_proto_msgTypes[240] + mi := &file_openshell_proto_msgTypes[242] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18643,7 +18750,7 @@ func (x *EndpointObservation) String() string { func (*EndpointObservation) ProtoMessage() {} func (x *EndpointObservation) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[240] + mi := &file_openshell_proto_msgTypes[242] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18656,7 +18763,7 @@ func (x *EndpointObservation) ProtoReflect() protoreflect.Message { // Deprecated: Use EndpointObservation.ProtoReflect.Descriptor instead. func (*EndpointObservation) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{240} + return file_openshell_proto_rawDescGZIP(), []int{242} } func (x *EndpointObservation) GetEndpointId() string { @@ -18709,7 +18816,7 @@ type ReportEndpointStatusRequest struct { func (x *ReportEndpointStatusRequest) Reset() { *x = ReportEndpointStatusRequest{} - mi := &file_openshell_proto_msgTypes[241] + mi := &file_openshell_proto_msgTypes[243] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18721,7 +18828,7 @@ func (x *ReportEndpointStatusRequest) String() string { func (*ReportEndpointStatusRequest) ProtoMessage() {} func (x *ReportEndpointStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[241] + mi := &file_openshell_proto_msgTypes[243] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18734,7 +18841,7 @@ func (x *ReportEndpointStatusRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ReportEndpointStatusRequest.ProtoReflect.Descriptor instead. func (*ReportEndpointStatusRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{241} + return file_openshell_proto_rawDescGZIP(), []int{243} } func (x *ReportEndpointStatusRequest) GetSandboxId() string { @@ -18803,7 +18910,7 @@ type TokenGrantStatus struct { func (x *TokenGrantStatus) Reset() { *x = TokenGrantStatus{} - mi := &file_openshell_proto_msgTypes[242] + mi := &file_openshell_proto_msgTypes[244] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18815,7 +18922,7 @@ func (x *TokenGrantStatus) String() string { func (*TokenGrantStatus) ProtoMessage() {} func (x *TokenGrantStatus) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[242] + mi := &file_openshell_proto_msgTypes[244] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18828,7 +18935,7 @@ func (x *TokenGrantStatus) ProtoReflect() protoreflect.Message { // Deprecated: Use TokenGrantStatus.ProtoReflect.Descriptor instead. func (*TokenGrantStatus) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{242} + return file_openshell_proto_rawDescGZIP(), []int{244} } func (x *TokenGrantStatus) GetLastFailure() *TokenGrantFailureObservation { @@ -18855,7 +18962,7 @@ type TokenGrantFailureObservation struct { func (x *TokenGrantFailureObservation) Reset() { *x = TokenGrantFailureObservation{} - mi := &file_openshell_proto_msgTypes[243] + mi := &file_openshell_proto_msgTypes[245] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18867,7 +18974,7 @@ func (x *TokenGrantFailureObservation) String() string { func (*TokenGrantFailureObservation) ProtoMessage() {} func (x *TokenGrantFailureObservation) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[243] + mi := &file_openshell_proto_msgTypes[245] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18880,7 +18987,7 @@ func (x *TokenGrantFailureObservation) ProtoReflect() protoreflect.Message { // Deprecated: Use TokenGrantFailureObservation.ProtoReflect.Descriptor instead. func (*TokenGrantFailureObservation) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{243} + return file_openshell_proto_rawDescGZIP(), []int{245} } func (x *TokenGrantFailureObservation) GetDestinationHost() string { @@ -18913,7 +19020,7 @@ type ReportEndpointStatusResponse struct { func (x *ReportEndpointStatusResponse) Reset() { *x = ReportEndpointStatusResponse{} - mi := &file_openshell_proto_msgTypes[244] + mi := &file_openshell_proto_msgTypes[246] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18925,7 +19032,7 @@ func (x *ReportEndpointStatusResponse) String() string { func (*ReportEndpointStatusResponse) ProtoMessage() {} func (x *ReportEndpointStatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[244] + mi := &file_openshell_proto_msgTypes[246] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18938,7 +19045,7 @@ func (x *ReportEndpointStatusResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ReportEndpointStatusResponse.ProtoReflect.Descriptor instead. func (*ReportEndpointStatusResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{244} + return file_openshell_proto_rawDescGZIP(), []int{246} } // A configured endpoint and its last accepted network result in one record. @@ -18972,7 +19079,7 @@ type EndpointStatus struct { func (x *EndpointStatus) Reset() { *x = EndpointStatus{} - mi := &file_openshell_proto_msgTypes[245] + mi := &file_openshell_proto_msgTypes[247] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18984,7 +19091,7 @@ func (x *EndpointStatus) String() string { func (*EndpointStatus) ProtoMessage() {} func (x *EndpointStatus) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[245] + mi := &file_openshell_proto_msgTypes[247] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18997,7 +19104,7 @@ func (x *EndpointStatus) ProtoReflect() protoreflect.Message { // Deprecated: Use EndpointStatus.ProtoReflect.Descriptor instead. func (*EndpointStatus) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{245} + return file_openshell_proto_rawDescGZIP(), []int{247} } func (x *EndpointStatus) GetEndpointId() string { @@ -19092,7 +19199,7 @@ type SandboxProvisioning struct { func (x *SandboxProvisioning) Reset() { *x = SandboxProvisioning{} - mi := &file_openshell_proto_msgTypes[246] + mi := &file_openshell_proto_msgTypes[248] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -19104,7 +19211,7 @@ func (x *SandboxProvisioning) String() string { func (*SandboxProvisioning) ProtoMessage() {} func (x *SandboxProvisioning) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[246] + mi := &file_openshell_proto_msgTypes[248] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -19117,7 +19224,7 @@ func (x *SandboxProvisioning) ProtoReflect() protoreflect.Message { // Deprecated: Use SandboxProvisioning.ProtoReflect.Descriptor instead. func (*SandboxProvisioning) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{246} + return file_openshell_proto_rawDescGZIP(), []int{248} } func (x *SandboxProvisioning) GetAttemptId() string { @@ -19240,7 +19347,7 @@ type SandboxServiceExposure struct { func (x *SandboxServiceExposure) Reset() { *x = SandboxServiceExposure{} - mi := &file_openshell_proto_msgTypes[247] + mi := &file_openshell_proto_msgTypes[249] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -19252,7 +19359,7 @@ func (x *SandboxServiceExposure) String() string { func (*SandboxServiceExposure) ProtoMessage() {} func (x *SandboxServiceExposure) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[247] + mi := &file_openshell_proto_msgTypes[249] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -19265,7 +19372,7 @@ func (x *SandboxServiceExposure) ProtoReflect() protoreflect.Message { // Deprecated: Use SandboxServiceExposure.ProtoReflect.Descriptor instead. func (*SandboxServiceExposure) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{247} + return file_openshell_proto_rawDescGZIP(), []int{249} } func (x *SandboxServiceExposure) GetService() string { @@ -19319,7 +19426,7 @@ type EndpointFailure struct { func (x *EndpointFailure) Reset() { *x = EndpointFailure{} - mi := &file_openshell_proto_msgTypes[248] + mi := &file_openshell_proto_msgTypes[250] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -19331,7 +19438,7 @@ func (x *EndpointFailure) String() string { func (*EndpointFailure) ProtoMessage() {} func (x *EndpointFailure) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[248] + mi := &file_openshell_proto_msgTypes[250] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -19344,7 +19451,7 @@ func (x *EndpointFailure) ProtoReflect() protoreflect.Message { // Deprecated: Use EndpointFailure.ProtoReflect.Descriptor instead. func (*EndpointFailure) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{248} + return file_openshell_proto_rawDescGZIP(), []int{250} } func (x *EndpointFailure) GetDomain() EndpointFailureDomain { @@ -20276,7 +20383,14 @@ const file_openshell_proto_rawDesc = "" + "\n" + "FilesEntry\x12\x10\n" + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + - "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"\xbd\x01\n" + + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"M\n" + + "$GetSandboxProviderAccessTokenRequest\x12%\n" + + "\x0ecredential_key\x18\x01 \x01(\tR\rcredentialKey\"\xaf\x01\n" + + "%GetSandboxProviderAccessTokenResponse\x12'\n" + + "\faccess_token\x18\x01 \x01(\tB\x04\x88\xb5\x18\x01R\vaccessToken\x12>\n" + + "\rexpires_after\x18\x02 \x01(\v2\x19.google.protobuf.DurationR\fexpiresAfter\x12\x1d\n" + + "\n" + + "token_type\x18\x03 \x01(\tR\ttokenType\"\xbd\x01\n" + "#ExchangeProviderSubjectTokenRequest\x12\x1d\n" + "\n" + "sandbox_id\x18\x01 \x01(\tR\tsandboxId\x12\x1a\n" + @@ -21008,7 +21122,7 @@ const file_openshell_proto_rawDesc = "" + "-SERVICE_AUTHORIZATION_MODE_BEARER_PASSTHROUGH\x10\x02*i\n" + "\x15EndpointFailureDomain\x12'\n" + "#ENDPOINT_FAILURE_DOMAIN_UNSPECIFIED\x10\x00\x12'\n" + - "#ENDPOINT_FAILURE_DOMAIN_TOKEN_GRANT\x10\x012\xb6W\n" + + "#ENDPOINT_FAILURE_DOMAIN_TOKEN_GRANT\x10\x012\xd0X\n" + "\tOpenShell\x12Z\n" + "\x06Health\x12\x1b.openshell.v1.HealthRequest\x1a\x1c.openshell.v1.HealthResponse\"\x15\x82\xb5\x18\x11\n" + "\x0funauthenticated\x12i\n" + @@ -21121,6 +21235,8 @@ const file_openshell_proto_rawDesc = "" + "\x1dGetSandboxProviderEnvironment\x122.openshell.v1.GetSandboxProviderEnvironmentRequest\x1a3.openshell.v1.GetSandboxProviderEnvironmentResponse\"\r\x82\xb5\x18\t\n" + "\asandbox\x12\x94\x01\n" + "\x1cExchangeProviderSubjectToken\x121.openshell.v1.ExchangeProviderSubjectTokenRequest\x1a2.openshell.v1.ExchangeProviderSubjectTokenResponse\"\r\x82\xb5\x18\t\n" + + "\asandbox\x12\x97\x01\n" + + "\x1dGetSandboxProviderAccessToken\x122.openshell.v1.GetSandboxProviderAccessTokenRequest\x1a3.openshell.v1.GetSandboxProviderAccessTokenResponse\"\r\x82\xb5\x18\t\n" + "\asandbox\x12}\n" + "\x0eGetSandboxLogs\x12#.openshell.v1.GetSandboxLogsRequest\x1a$.openshell.v1.GetSandboxLogsResponse\" \x82\xb5\x18\x1c\n" + "\x06bearer\x12\x04user\"\fsandbox:read\x12o\n" + @@ -21201,7 +21317,7 @@ func file_openshell_proto_rawDescGZIP() []byte { } var file_openshell_proto_enumTypes = make([]protoimpl.EnumInfo, 22) -var file_openshell_proto_msgTypes = make([]protoimpl.MessageInfo, 275) +var file_openshell_proto_msgTypes = make([]protoimpl.MessageInfo, 277) var file_openshell_proto_goTypes = []any{ (ExtensionKind)(0), // 0: openshell.v1.ExtensionKind (SandboxPhase)(0), // 1: openshell.v1.SandboxPhase @@ -21368,164 +21484,166 @@ var file_openshell_proto_goTypes = []any{ (*GetSandboxProviderEnvironmentResponse)(nil), // 162: openshell.v1.GetSandboxProviderEnvironmentResponse (*ProviderEnvironmentValue)(nil), // 163: openshell.v1.ProviderEnvironmentValue (*ProviderEnvironmentSnapshot)(nil), // 164: openshell.v1.ProviderEnvironmentSnapshot - (*ExchangeProviderSubjectTokenRequest)(nil), // 165: openshell.v1.ExchangeProviderSubjectTokenRequest - (*ExchangeProviderSubjectTokenResponse)(nil), // 166: openshell.v1.ExchangeProviderSubjectTokenResponse - (*UpdateConfigRequest)(nil), // 167: openshell.v1.UpdateConfigRequest - (*PolicyMergeOperation)(nil), // 168: openshell.v1.PolicyMergeOperation - (*AddNetworkRule)(nil), // 169: openshell.v1.AddNetworkRule - (*RemoveNetworkEndpoint)(nil), // 170: openshell.v1.RemoveNetworkEndpoint - (*RemoveNetworkRule)(nil), // 171: openshell.v1.RemoveNetworkRule - (*L7RuleTarget)(nil), // 172: openshell.v1.L7RuleTarget - (*AddDenyRules)(nil), // 173: openshell.v1.AddDenyRules - (*AddAllowRules)(nil), // 174: openshell.v1.AddAllowRules - (*RemoveNetworkBinary)(nil), // 175: openshell.v1.RemoveNetworkBinary - (*UpdateConfigResponse)(nil), // 176: openshell.v1.UpdateConfigResponse - (*GetSandboxPolicyStatusRequest)(nil), // 177: openshell.v1.GetSandboxPolicyStatusRequest - (*GetSandboxPolicyStatusResponse)(nil), // 178: openshell.v1.GetSandboxPolicyStatusResponse - (*ListSandboxPoliciesRequest)(nil), // 179: openshell.v1.ListSandboxPoliciesRequest - (*ListSandboxPoliciesResponse)(nil), // 180: openshell.v1.ListSandboxPoliciesResponse - (*ReportPolicyStatusRequest)(nil), // 181: openshell.v1.ReportPolicyStatusRequest - (*ReportPolicyStatusResponse)(nil), // 182: openshell.v1.ReportPolicyStatusResponse - (*SandboxConfigurationAdmission)(nil), // 183: openshell.v1.SandboxConfigurationAdmission - (*ReportSandboxConfigurationRequest)(nil), // 184: openshell.v1.ReportSandboxConfigurationRequest - (*ReportSandboxConfigurationResponse)(nil), // 185: openshell.v1.ReportSandboxConfigurationResponse - (*SandboxPolicyRevision)(nil), // 186: openshell.v1.SandboxPolicyRevision - (*GetSandboxLogsRequest)(nil), // 187: openshell.v1.GetSandboxLogsRequest - (*PushSandboxLogsRequest)(nil), // 188: openshell.v1.PushSandboxLogsRequest - (*PushSandboxLogsResponse)(nil), // 189: openshell.v1.PushSandboxLogsResponse - (*GetSandboxLogsResponse)(nil), // 190: openshell.v1.GetSandboxLogsResponse - (*SupervisorMessage)(nil), // 191: openshell.v1.SupervisorMessage - (*GatewayMessage)(nil), // 192: openshell.v1.GatewayMessage - (*SupervisorHello)(nil), // 193: openshell.v1.SupervisorHello - (*SessionAccepted)(nil), // 194: openshell.v1.SessionAccepted - (*ConfigUpdate)(nil), // 195: openshell.v1.ConfigUpdate - (*ConfigApplyFailure)(nil), // 196: openshell.v1.ConfigApplyFailure - (*ConfigUpdateResult)(nil), // 197: openshell.v1.ConfigUpdateResult - (*PolicyLoadResult)(nil), // 198: openshell.v1.PolicyLoadResult - (*SessionRejected)(nil), // 199: openshell.v1.SessionRejected - (*SessionRedirect)(nil), // 200: openshell.v1.SessionRedirect - (*SupervisorHeartbeat)(nil), // 201: openshell.v1.SupervisorHeartbeat - (*GatewayHeartbeat)(nil), // 202: openshell.v1.GatewayHeartbeat - (*ReportMainProcessExitRequest)(nil), // 203: openshell.v1.ReportMainProcessExitRequest - (*ReportMainProcessExitResponse)(nil), // 204: openshell.v1.ReportMainProcessExitResponse - (*FinalizeMainProcessExitRequest)(nil), // 205: openshell.v1.FinalizeMainProcessExitRequest - (*FinalizeMainProcessExitResponse)(nil), // 206: openshell.v1.FinalizeMainProcessExitResponse - (*RelayOpen)(nil), // 207: openshell.v1.RelayOpen - (*SshRelayTarget)(nil), // 208: openshell.v1.SshRelayTarget - (*TcpRelayTarget)(nil), // 209: openshell.v1.TcpRelayTarget - (*RelayInit)(nil), // 210: openshell.v1.RelayInit - (*RelayFrame)(nil), // 211: openshell.v1.RelayFrame - (*PeerRelayInit)(nil), // 212: openshell.v1.PeerRelayInit - (*PeerRelayFrame)(nil), // 213: openshell.v1.PeerRelayFrame - (*PeerConfigSandboxTarget)(nil), // 214: openshell.v1.PeerConfigSandboxTarget - (*PeerConfigProviderTarget)(nil), // 215: openshell.v1.PeerConfigProviderTarget - (*PeerNotifyConfigUpdateRequest)(nil), // 216: openshell.v1.PeerNotifyConfigUpdateRequest - (*PeerNotifyConfigUpdateResponse)(nil), // 217: openshell.v1.PeerNotifyConfigUpdateResponse - (*RelayOpenResult)(nil), // 218: openshell.v1.RelayOpenResult - (*RelayClose)(nil), // 219: openshell.v1.RelayClose - (*L7RequestSample)(nil), // 220: openshell.v1.L7RequestSample - (*DenialSummary)(nil), // 221: openshell.v1.DenialSummary - (*DenialGroupCount)(nil), // 222: openshell.v1.DenialGroupCount - (*NetworkActivitySummary)(nil), // 223: openshell.v1.NetworkActivitySummary - (*PolicyChunk)(nil), // 224: openshell.v1.PolicyChunk - (*DraftPolicyUpdate)(nil), // 225: openshell.v1.DraftPolicyUpdate - (*SubmitPolicyAnalysisRequest)(nil), // 226: openshell.v1.SubmitPolicyAnalysisRequest - (*SubmitPolicyAnalysisResponse)(nil), // 227: openshell.v1.SubmitPolicyAnalysisResponse - (*GetDraftPolicyRequest)(nil), // 228: openshell.v1.GetDraftPolicyRequest - (*GetDraftPolicyResponse)(nil), // 229: openshell.v1.GetDraftPolicyResponse - (*ApproveDraftChunkRequest)(nil), // 230: openshell.v1.ApproveDraftChunkRequest - (*ApproveDraftChunkResponse)(nil), // 231: openshell.v1.ApproveDraftChunkResponse - (*RejectDraftChunkRequest)(nil), // 232: openshell.v1.RejectDraftChunkRequest - (*RejectDraftChunkResponse)(nil), // 233: openshell.v1.RejectDraftChunkResponse - (*DraftChunkApproval)(nil), // 234: openshell.v1.DraftChunkApproval - (*ApproveAllDraftChunksRequest)(nil), // 235: openshell.v1.ApproveAllDraftChunksRequest - (*ApproveAllDraftChunksResponse)(nil), // 236: openshell.v1.ApproveAllDraftChunksResponse - (*EditDraftChunkRequest)(nil), // 237: openshell.v1.EditDraftChunkRequest - (*EditDraftChunkResponse)(nil), // 238: openshell.v1.EditDraftChunkResponse - (*UndoDraftChunkRequest)(nil), // 239: openshell.v1.UndoDraftChunkRequest - (*UndoDraftChunkResponse)(nil), // 240: openshell.v1.UndoDraftChunkResponse - (*ClearDraftChunksRequest)(nil), // 241: openshell.v1.ClearDraftChunksRequest - (*ClearDraftChunksResponse)(nil), // 242: openshell.v1.ClearDraftChunksResponse - (*GetDraftHistoryRequest)(nil), // 243: openshell.v1.GetDraftHistoryRequest - (*DraftHistoryEntry)(nil), // 244: openshell.v1.DraftHistoryEntry - (*GetDraftHistoryResponse)(nil), // 245: openshell.v1.GetDraftHistoryResponse - (*CreateWorkspaceRequest)(nil), // 246: openshell.v1.CreateWorkspaceRequest - (*CreateWorkspaceResponse)(nil), // 247: openshell.v1.CreateWorkspaceResponse - (*GetWorkspaceRequest)(nil), // 248: openshell.v1.GetWorkspaceRequest - (*GetWorkspaceResponse)(nil), // 249: openshell.v1.GetWorkspaceResponse - (*ListWorkspacesRequest)(nil), // 250: openshell.v1.ListWorkspacesRequest - (*ListWorkspacesResponse)(nil), // 251: openshell.v1.ListWorkspacesResponse - (*DeleteWorkspaceRequest)(nil), // 252: openshell.v1.DeleteWorkspaceRequest - (*DeleteWorkspaceResponse)(nil), // 253: openshell.v1.DeleteWorkspaceResponse - (*WorkspaceMember)(nil), // 254: openshell.v1.WorkspaceMember - (*AddWorkspaceMemberRequest)(nil), // 255: openshell.v1.AddWorkspaceMemberRequest - (*AddWorkspaceMemberResponse)(nil), // 256: openshell.v1.AddWorkspaceMemberResponse - (*RemoveWorkspaceMemberRequest)(nil), // 257: openshell.v1.RemoveWorkspaceMemberRequest - (*RemoveWorkspaceMemberResponse)(nil), // 258: openshell.v1.RemoveWorkspaceMemberResponse - (*ListWorkspaceMembersRequest)(nil), // 259: openshell.v1.ListWorkspaceMembersRequest - (*ListWorkspaceMembersResponse)(nil), // 260: openshell.v1.ListWorkspaceMembersResponse - (*ExtensionServiceCredential)(nil), // 261: openshell.v1.ExtensionServiceCredential - (*EndpointObservation)(nil), // 262: openshell.v1.EndpointObservation - (*ReportEndpointStatusRequest)(nil), // 263: openshell.v1.ReportEndpointStatusRequest - (*TokenGrantStatus)(nil), // 264: openshell.v1.TokenGrantStatus - (*TokenGrantFailureObservation)(nil), // 265: openshell.v1.TokenGrantFailureObservation - (*ReportEndpointStatusResponse)(nil), // 266: openshell.v1.ReportEndpointStatusResponse - (*EndpointStatus)(nil), // 267: openshell.v1.EndpointStatus - (*SandboxProvisioning)(nil), // 268: openshell.v1.SandboxProvisioning - (*SandboxServiceExposure)(nil), // 269: openshell.v1.SandboxServiceExposure - (*EndpointFailure)(nil), // 270: openshell.v1.EndpointFailure - nil, // 271: openshell.v1.SandboxSpec.EnvironmentEntry - nil, // 272: openshell.v1.SandboxTemplate.LabelsEntry - nil, // 273: openshell.v1.SandboxTemplate.AnnotationsEntry - nil, // 274: openshell.v1.SandboxTemplate.EnvironmentEntry - nil, // 275: openshell.v1.SandboxWorkloadConfig.EnvironmentEntry - nil, // 276: openshell.v1.PlatformEvent.MetadataEntry - nil, // 277: openshell.v1.CreateSandboxRequest.LabelsEntry - nil, // 278: openshell.v1.CreateSandboxRequest.AnnotationsEntry - nil, // 279: openshell.v1.SandboxResponse.ServiceUrlsEntry - nil, // 280: openshell.v1.ExecSandboxRequest.EnvironmentEntry - nil, // 281: openshell.v1.SandboxLogLine.FieldsEntry - nil, // 282: openshell.v1.GetProviderCredentialsResponse.CredentialsEntry - nil, // 283: openshell.v1.UpdateProviderRequest.CredentialExpirationTimesEntry - nil, // 284: openshell.v1.ConfigureProviderRefreshRequest.MaterialEntry - nil, // 285: openshell.v1.ProviderProfile.AnnotationsEntry - nil, // 286: openshell.v1.GetSandboxProviderEnvironmentResponse.EnvironmentEntry - nil, // 287: openshell.v1.GetSandboxProviderEnvironmentResponse.CredentialExpirationTimesEntry - nil, // 288: openshell.v1.GetSandboxProviderEnvironmentResponse.DynamicCredentialsEntry - nil, // 289: openshell.v1.GetSandboxProviderEnvironmentResponse.StaticCredentialBindingsEntry - nil, // 290: openshell.v1.GetSandboxProviderEnvironmentResponse.FilesEntry - nil, // 291: openshell.v1.ProviderEnvironmentSnapshot.DynamicCredentialsEntry - nil, // 292: openshell.v1.ProviderEnvironmentSnapshot.FilesEntry - nil, // 293: openshell.v1.UpdateConfigRequest.AnnotationsEntry - nil, // 294: openshell.v1.UpdateConfigResponse.AnnotationsEntry - nil, // 295: openshell.v1.SandboxPolicyRevision.ProvenanceEntry - nil, // 296: openshell.v1.CreateWorkspaceRequest.LabelsEntry - (*timestamppb.Timestamp)(nil), // 297: google.protobuf.Timestamp - (*datamodelv1.ObjectMeta)(nil), // 298: openshell.datamodel.v1.ObjectMeta - (*sandboxv1.SandboxPolicy)(nil), // 299: openshell.sandbox.v1.SandboxPolicy - (*structpb.Struct)(nil), // 300: google.protobuf.Struct - (*durationpb.Duration)(nil), // 301: google.protobuf.Duration - (*datamodelv1.WorkspaceSelector)(nil), // 302: openshell.datamodel.v1.WorkspaceSelector - (*datamodelv1.Provider)(nil), // 303: openshell.datamodel.v1.Provider - (sandboxv1.PolicySource)(0), // 304: openshell.sandbox.v1.PolicySource - (*sandboxv1.NetworkEndpoint)(nil), // 305: openshell.sandbox.v1.NetworkEndpoint - (*sandboxv1.NetworkBinary)(nil), // 306: openshell.sandbox.v1.NetworkBinary - (*sandboxv1.SettingValue)(nil), // 307: openshell.sandbox.v1.SettingValue - (*sandboxv1.NetworkPolicyRule)(nil), // 308: openshell.sandbox.v1.NetworkPolicyRule - (*sandboxv1.L7DenyRule)(nil), // 309: openshell.sandbox.v1.L7DenyRule - (*sandboxv1.L7Rule)(nil), // 310: openshell.sandbox.v1.L7Rule - (*sandboxv1.SandboxConfigSnapshot)(nil), // 311: openshell.sandbox.v1.SandboxConfigSnapshot - (*datamodelv1.Workspace)(nil), // 312: openshell.datamodel.v1.Workspace - (*sandboxv1.GetSandboxConfigRequest)(nil), // 313: openshell.sandbox.v1.GetSandboxConfigRequest - (*sandboxv1.GetGatewayConfigRequest)(nil), // 314: openshell.sandbox.v1.GetGatewayConfigRequest - (*sandboxv1.GetSandboxConfigResponse)(nil), // 315: openshell.sandbox.v1.GetSandboxConfigResponse - (*sandboxv1.GetGatewayConfigResponse)(nil), // 316: openshell.sandbox.v1.GetGatewayConfigResponse + (*GetSandboxProviderAccessTokenRequest)(nil), // 165: openshell.v1.GetSandboxProviderAccessTokenRequest + (*GetSandboxProviderAccessTokenResponse)(nil), // 166: openshell.v1.GetSandboxProviderAccessTokenResponse + (*ExchangeProviderSubjectTokenRequest)(nil), // 167: openshell.v1.ExchangeProviderSubjectTokenRequest + (*ExchangeProviderSubjectTokenResponse)(nil), // 168: openshell.v1.ExchangeProviderSubjectTokenResponse + (*UpdateConfigRequest)(nil), // 169: openshell.v1.UpdateConfigRequest + (*PolicyMergeOperation)(nil), // 170: openshell.v1.PolicyMergeOperation + (*AddNetworkRule)(nil), // 171: openshell.v1.AddNetworkRule + (*RemoveNetworkEndpoint)(nil), // 172: openshell.v1.RemoveNetworkEndpoint + (*RemoveNetworkRule)(nil), // 173: openshell.v1.RemoveNetworkRule + (*L7RuleTarget)(nil), // 174: openshell.v1.L7RuleTarget + (*AddDenyRules)(nil), // 175: openshell.v1.AddDenyRules + (*AddAllowRules)(nil), // 176: openshell.v1.AddAllowRules + (*RemoveNetworkBinary)(nil), // 177: openshell.v1.RemoveNetworkBinary + (*UpdateConfigResponse)(nil), // 178: openshell.v1.UpdateConfigResponse + (*GetSandboxPolicyStatusRequest)(nil), // 179: openshell.v1.GetSandboxPolicyStatusRequest + (*GetSandboxPolicyStatusResponse)(nil), // 180: openshell.v1.GetSandboxPolicyStatusResponse + (*ListSandboxPoliciesRequest)(nil), // 181: openshell.v1.ListSandboxPoliciesRequest + (*ListSandboxPoliciesResponse)(nil), // 182: openshell.v1.ListSandboxPoliciesResponse + (*ReportPolicyStatusRequest)(nil), // 183: openshell.v1.ReportPolicyStatusRequest + (*ReportPolicyStatusResponse)(nil), // 184: openshell.v1.ReportPolicyStatusResponse + (*SandboxConfigurationAdmission)(nil), // 185: openshell.v1.SandboxConfigurationAdmission + (*ReportSandboxConfigurationRequest)(nil), // 186: openshell.v1.ReportSandboxConfigurationRequest + (*ReportSandboxConfigurationResponse)(nil), // 187: openshell.v1.ReportSandboxConfigurationResponse + (*SandboxPolicyRevision)(nil), // 188: openshell.v1.SandboxPolicyRevision + (*GetSandboxLogsRequest)(nil), // 189: openshell.v1.GetSandboxLogsRequest + (*PushSandboxLogsRequest)(nil), // 190: openshell.v1.PushSandboxLogsRequest + (*PushSandboxLogsResponse)(nil), // 191: openshell.v1.PushSandboxLogsResponse + (*GetSandboxLogsResponse)(nil), // 192: openshell.v1.GetSandboxLogsResponse + (*SupervisorMessage)(nil), // 193: openshell.v1.SupervisorMessage + (*GatewayMessage)(nil), // 194: openshell.v1.GatewayMessage + (*SupervisorHello)(nil), // 195: openshell.v1.SupervisorHello + (*SessionAccepted)(nil), // 196: openshell.v1.SessionAccepted + (*ConfigUpdate)(nil), // 197: openshell.v1.ConfigUpdate + (*ConfigApplyFailure)(nil), // 198: openshell.v1.ConfigApplyFailure + (*ConfigUpdateResult)(nil), // 199: openshell.v1.ConfigUpdateResult + (*PolicyLoadResult)(nil), // 200: openshell.v1.PolicyLoadResult + (*SessionRejected)(nil), // 201: openshell.v1.SessionRejected + (*SessionRedirect)(nil), // 202: openshell.v1.SessionRedirect + (*SupervisorHeartbeat)(nil), // 203: openshell.v1.SupervisorHeartbeat + (*GatewayHeartbeat)(nil), // 204: openshell.v1.GatewayHeartbeat + (*ReportMainProcessExitRequest)(nil), // 205: openshell.v1.ReportMainProcessExitRequest + (*ReportMainProcessExitResponse)(nil), // 206: openshell.v1.ReportMainProcessExitResponse + (*FinalizeMainProcessExitRequest)(nil), // 207: openshell.v1.FinalizeMainProcessExitRequest + (*FinalizeMainProcessExitResponse)(nil), // 208: openshell.v1.FinalizeMainProcessExitResponse + (*RelayOpen)(nil), // 209: openshell.v1.RelayOpen + (*SshRelayTarget)(nil), // 210: openshell.v1.SshRelayTarget + (*TcpRelayTarget)(nil), // 211: openshell.v1.TcpRelayTarget + (*RelayInit)(nil), // 212: openshell.v1.RelayInit + (*RelayFrame)(nil), // 213: openshell.v1.RelayFrame + (*PeerRelayInit)(nil), // 214: openshell.v1.PeerRelayInit + (*PeerRelayFrame)(nil), // 215: openshell.v1.PeerRelayFrame + (*PeerConfigSandboxTarget)(nil), // 216: openshell.v1.PeerConfigSandboxTarget + (*PeerConfigProviderTarget)(nil), // 217: openshell.v1.PeerConfigProviderTarget + (*PeerNotifyConfigUpdateRequest)(nil), // 218: openshell.v1.PeerNotifyConfigUpdateRequest + (*PeerNotifyConfigUpdateResponse)(nil), // 219: openshell.v1.PeerNotifyConfigUpdateResponse + (*RelayOpenResult)(nil), // 220: openshell.v1.RelayOpenResult + (*RelayClose)(nil), // 221: openshell.v1.RelayClose + (*L7RequestSample)(nil), // 222: openshell.v1.L7RequestSample + (*DenialSummary)(nil), // 223: openshell.v1.DenialSummary + (*DenialGroupCount)(nil), // 224: openshell.v1.DenialGroupCount + (*NetworkActivitySummary)(nil), // 225: openshell.v1.NetworkActivitySummary + (*PolicyChunk)(nil), // 226: openshell.v1.PolicyChunk + (*DraftPolicyUpdate)(nil), // 227: openshell.v1.DraftPolicyUpdate + (*SubmitPolicyAnalysisRequest)(nil), // 228: openshell.v1.SubmitPolicyAnalysisRequest + (*SubmitPolicyAnalysisResponse)(nil), // 229: openshell.v1.SubmitPolicyAnalysisResponse + (*GetDraftPolicyRequest)(nil), // 230: openshell.v1.GetDraftPolicyRequest + (*GetDraftPolicyResponse)(nil), // 231: openshell.v1.GetDraftPolicyResponse + (*ApproveDraftChunkRequest)(nil), // 232: openshell.v1.ApproveDraftChunkRequest + (*ApproveDraftChunkResponse)(nil), // 233: openshell.v1.ApproveDraftChunkResponse + (*RejectDraftChunkRequest)(nil), // 234: openshell.v1.RejectDraftChunkRequest + (*RejectDraftChunkResponse)(nil), // 235: openshell.v1.RejectDraftChunkResponse + (*DraftChunkApproval)(nil), // 236: openshell.v1.DraftChunkApproval + (*ApproveAllDraftChunksRequest)(nil), // 237: openshell.v1.ApproveAllDraftChunksRequest + (*ApproveAllDraftChunksResponse)(nil), // 238: openshell.v1.ApproveAllDraftChunksResponse + (*EditDraftChunkRequest)(nil), // 239: openshell.v1.EditDraftChunkRequest + (*EditDraftChunkResponse)(nil), // 240: openshell.v1.EditDraftChunkResponse + (*UndoDraftChunkRequest)(nil), // 241: openshell.v1.UndoDraftChunkRequest + (*UndoDraftChunkResponse)(nil), // 242: openshell.v1.UndoDraftChunkResponse + (*ClearDraftChunksRequest)(nil), // 243: openshell.v1.ClearDraftChunksRequest + (*ClearDraftChunksResponse)(nil), // 244: openshell.v1.ClearDraftChunksResponse + (*GetDraftHistoryRequest)(nil), // 245: openshell.v1.GetDraftHistoryRequest + (*DraftHistoryEntry)(nil), // 246: openshell.v1.DraftHistoryEntry + (*GetDraftHistoryResponse)(nil), // 247: openshell.v1.GetDraftHistoryResponse + (*CreateWorkspaceRequest)(nil), // 248: openshell.v1.CreateWorkspaceRequest + (*CreateWorkspaceResponse)(nil), // 249: openshell.v1.CreateWorkspaceResponse + (*GetWorkspaceRequest)(nil), // 250: openshell.v1.GetWorkspaceRequest + (*GetWorkspaceResponse)(nil), // 251: openshell.v1.GetWorkspaceResponse + (*ListWorkspacesRequest)(nil), // 252: openshell.v1.ListWorkspacesRequest + (*ListWorkspacesResponse)(nil), // 253: openshell.v1.ListWorkspacesResponse + (*DeleteWorkspaceRequest)(nil), // 254: openshell.v1.DeleteWorkspaceRequest + (*DeleteWorkspaceResponse)(nil), // 255: openshell.v1.DeleteWorkspaceResponse + (*WorkspaceMember)(nil), // 256: openshell.v1.WorkspaceMember + (*AddWorkspaceMemberRequest)(nil), // 257: openshell.v1.AddWorkspaceMemberRequest + (*AddWorkspaceMemberResponse)(nil), // 258: openshell.v1.AddWorkspaceMemberResponse + (*RemoveWorkspaceMemberRequest)(nil), // 259: openshell.v1.RemoveWorkspaceMemberRequest + (*RemoveWorkspaceMemberResponse)(nil), // 260: openshell.v1.RemoveWorkspaceMemberResponse + (*ListWorkspaceMembersRequest)(nil), // 261: openshell.v1.ListWorkspaceMembersRequest + (*ListWorkspaceMembersResponse)(nil), // 262: openshell.v1.ListWorkspaceMembersResponse + (*ExtensionServiceCredential)(nil), // 263: openshell.v1.ExtensionServiceCredential + (*EndpointObservation)(nil), // 264: openshell.v1.EndpointObservation + (*ReportEndpointStatusRequest)(nil), // 265: openshell.v1.ReportEndpointStatusRequest + (*TokenGrantStatus)(nil), // 266: openshell.v1.TokenGrantStatus + (*TokenGrantFailureObservation)(nil), // 267: openshell.v1.TokenGrantFailureObservation + (*ReportEndpointStatusResponse)(nil), // 268: openshell.v1.ReportEndpointStatusResponse + (*EndpointStatus)(nil), // 269: openshell.v1.EndpointStatus + (*SandboxProvisioning)(nil), // 270: openshell.v1.SandboxProvisioning + (*SandboxServiceExposure)(nil), // 271: openshell.v1.SandboxServiceExposure + (*EndpointFailure)(nil), // 272: openshell.v1.EndpointFailure + nil, // 273: openshell.v1.SandboxSpec.EnvironmentEntry + nil, // 274: openshell.v1.SandboxTemplate.LabelsEntry + nil, // 275: openshell.v1.SandboxTemplate.AnnotationsEntry + nil, // 276: openshell.v1.SandboxTemplate.EnvironmentEntry + nil, // 277: openshell.v1.SandboxWorkloadConfig.EnvironmentEntry + nil, // 278: openshell.v1.PlatformEvent.MetadataEntry + nil, // 279: openshell.v1.CreateSandboxRequest.LabelsEntry + nil, // 280: openshell.v1.CreateSandboxRequest.AnnotationsEntry + nil, // 281: openshell.v1.SandboxResponse.ServiceUrlsEntry + nil, // 282: openshell.v1.ExecSandboxRequest.EnvironmentEntry + nil, // 283: openshell.v1.SandboxLogLine.FieldsEntry + nil, // 284: openshell.v1.GetProviderCredentialsResponse.CredentialsEntry + nil, // 285: openshell.v1.UpdateProviderRequest.CredentialExpirationTimesEntry + nil, // 286: openshell.v1.ConfigureProviderRefreshRequest.MaterialEntry + nil, // 287: openshell.v1.ProviderProfile.AnnotationsEntry + nil, // 288: openshell.v1.GetSandboxProviderEnvironmentResponse.EnvironmentEntry + nil, // 289: openshell.v1.GetSandboxProviderEnvironmentResponse.CredentialExpirationTimesEntry + nil, // 290: openshell.v1.GetSandboxProviderEnvironmentResponse.DynamicCredentialsEntry + nil, // 291: openshell.v1.GetSandboxProviderEnvironmentResponse.StaticCredentialBindingsEntry + nil, // 292: openshell.v1.GetSandboxProviderEnvironmentResponse.FilesEntry + nil, // 293: openshell.v1.ProviderEnvironmentSnapshot.DynamicCredentialsEntry + nil, // 294: openshell.v1.ProviderEnvironmentSnapshot.FilesEntry + nil, // 295: openshell.v1.UpdateConfigRequest.AnnotationsEntry + nil, // 296: openshell.v1.UpdateConfigResponse.AnnotationsEntry + nil, // 297: openshell.v1.SandboxPolicyRevision.ProvenanceEntry + nil, // 298: openshell.v1.CreateWorkspaceRequest.LabelsEntry + (*timestamppb.Timestamp)(nil), // 299: google.protobuf.Timestamp + (*datamodelv1.ObjectMeta)(nil), // 300: openshell.datamodel.v1.ObjectMeta + (*sandboxv1.SandboxPolicy)(nil), // 301: openshell.sandbox.v1.SandboxPolicy + (*structpb.Struct)(nil), // 302: google.protobuf.Struct + (*durationpb.Duration)(nil), // 303: google.protobuf.Duration + (*datamodelv1.WorkspaceSelector)(nil), // 304: openshell.datamodel.v1.WorkspaceSelector + (*datamodelv1.Provider)(nil), // 305: openshell.datamodel.v1.Provider + (sandboxv1.PolicySource)(0), // 306: openshell.sandbox.v1.PolicySource + (*sandboxv1.NetworkEndpoint)(nil), // 307: openshell.sandbox.v1.NetworkEndpoint + (*sandboxv1.NetworkBinary)(nil), // 308: openshell.sandbox.v1.NetworkBinary + (*sandboxv1.SettingValue)(nil), // 309: openshell.sandbox.v1.SettingValue + (*sandboxv1.NetworkPolicyRule)(nil), // 310: openshell.sandbox.v1.NetworkPolicyRule + (*sandboxv1.L7DenyRule)(nil), // 311: openshell.sandbox.v1.L7DenyRule + (*sandboxv1.L7Rule)(nil), // 312: openshell.sandbox.v1.L7Rule + (*sandboxv1.SandboxConfigSnapshot)(nil), // 313: openshell.sandbox.v1.SandboxConfigSnapshot + (*datamodelv1.Workspace)(nil), // 314: openshell.datamodel.v1.Workspace + (*sandboxv1.GetSandboxConfigRequest)(nil), // 315: openshell.sandbox.v1.GetSandboxConfigRequest + (*sandboxv1.GetGatewayConfigRequest)(nil), // 316: openshell.sandbox.v1.GetGatewayConfigRequest + (*sandboxv1.GetSandboxConfigResponse)(nil), // 317: openshell.sandbox.v1.GetSandboxConfigResponse + (*sandboxv1.GetGatewayConfigResponse)(nil), // 318: openshell.sandbox.v1.GetGatewayConfigResponse } var file_openshell_proto_depIdxs = []int32{ - 297, // 0: openshell.v1.IssueSandboxTokenResponse.expiration_time:type_name -> google.protobuf.Timestamp - 297, // 1: openshell.v1.RefreshSandboxTokenResponse.expiration_time:type_name -> google.protobuf.Timestamp - 261, // 2: openshell.v1.RefreshSandboxTokenResponse.extension_credentials:type_name -> openshell.v1.ExtensionServiceCredential - 297, // 3: openshell.v1.RefreshSandboxTokenResponse.sandbox_expiration_time:type_name -> google.protobuf.Timestamp + 299, // 0: openshell.v1.IssueSandboxTokenResponse.expiration_time:type_name -> google.protobuf.Timestamp + 299, // 1: openshell.v1.RefreshSandboxTokenResponse.expiration_time:type_name -> google.protobuf.Timestamp + 263, // 2: openshell.v1.RefreshSandboxTokenResponse.extension_credentials:type_name -> openshell.v1.ExtensionServiceCredential + 299, // 3: openshell.v1.RefreshSandboxTokenResponse.sandbox_expiration_time:type_name -> google.protobuf.Timestamp 14, // 4: openshell.v1.HealthResponse.status:type_name -> openshell.v1.ServiceStatus 14, // 5: openshell.v1.GetGatewayInfoResponse.status:type_name -> openshell.v1.ServiceStatus 33, // 6: openshell.v1.GetGatewayInfoResponse.compute_drivers:type_name -> openshell.v1.ComputeDriverInfo @@ -21536,524 +21654,527 @@ var file_openshell_proto_depIdxs = []int32{ 36, // 11: openshell.v1.ResourceCapabilities.cpu:type_name -> openshell.v1.CpuResourceCapabilities 37, // 12: openshell.v1.ResourceCapabilities.memory:type_name -> openshell.v1.MemoryResourceCapabilities 38, // 13: openshell.v1.ResourceCapabilities.gpu:type_name -> openshell.v1.GpuResourceCapabilities - 298, // 14: openshell.v1.Sandbox.metadata:type_name -> openshell.datamodel.v1.ObjectMeta + 300, // 14: openshell.v1.Sandbox.metadata:type_name -> openshell.datamodel.v1.ObjectMeta 40, // 15: openshell.v1.Sandbox.spec:type_name -> openshell.v1.SandboxSpec 51, // 16: openshell.v1.Sandbox.status:type_name -> openshell.v1.SandboxStatus 50, // 17: openshell.v1.Sandbox.created_from_workload_template:type_name -> openshell.v1.SandboxWorkloadTemplateProvenance - 271, // 18: openshell.v1.SandboxSpec.environment:type_name -> openshell.v1.SandboxSpec.EnvironmentEntry + 273, // 18: openshell.v1.SandboxSpec.environment:type_name -> openshell.v1.SandboxSpec.EnvironmentEntry 43, // 19: openshell.v1.SandboxSpec.template:type_name -> openshell.v1.SandboxTemplate - 299, // 20: openshell.v1.SandboxSpec.policy:type_name -> openshell.sandbox.v1.SandboxPolicy + 301, // 20: openshell.v1.SandboxSpec.policy:type_name -> openshell.sandbox.v1.SandboxPolicy 41, // 21: openshell.v1.SandboxSpec.resource_requirements:type_name -> openshell.v1.ResourceRequirements 17, // 22: openshell.v1.SandboxSpec.restart_policy:type_name -> openshell.v1.SandboxRestartPolicy 42, // 23: openshell.v1.ResourceRequirements.gpu:type_name -> openshell.v1.GpuResourceRequirements - 272, // 24: openshell.v1.SandboxTemplate.labels:type_name -> openshell.v1.SandboxTemplate.LabelsEntry - 273, // 25: openshell.v1.SandboxTemplate.annotations:type_name -> openshell.v1.SandboxTemplate.AnnotationsEntry - 274, // 26: openshell.v1.SandboxTemplate.environment:type_name -> openshell.v1.SandboxTemplate.EnvironmentEntry - 300, // 27: openshell.v1.SandboxTemplate.resources:type_name -> google.protobuf.Struct - 300, // 28: openshell.v1.SandboxTemplate.driver_config:type_name -> google.protobuf.Struct - 298, // 29: openshell.v1.SandboxWorkloadTemplate.metadata:type_name -> openshell.datamodel.v1.ObjectMeta + 274, // 24: openshell.v1.SandboxTemplate.labels:type_name -> openshell.v1.SandboxTemplate.LabelsEntry + 275, // 25: openshell.v1.SandboxTemplate.annotations:type_name -> openshell.v1.SandboxTemplate.AnnotationsEntry + 276, // 26: openshell.v1.SandboxTemplate.environment:type_name -> openshell.v1.SandboxTemplate.EnvironmentEntry + 302, // 27: openshell.v1.SandboxTemplate.resources:type_name -> google.protobuf.Struct + 302, // 28: openshell.v1.SandboxTemplate.driver_config:type_name -> google.protobuf.Struct + 300, // 29: openshell.v1.SandboxWorkloadTemplate.metadata:type_name -> openshell.datamodel.v1.ObjectMeta 45, // 30: openshell.v1.SandboxWorkloadTemplate.spec:type_name -> openshell.v1.SandboxWorkloadTemplateSpec 46, // 31: openshell.v1.SandboxWorkloadTemplateSpec.workload:type_name -> openshell.v1.SandboxWorkloadConfig - 300, // 32: openshell.v1.SandboxWorkloadTemplateSpec.driver_config:type_name -> google.protobuf.Struct + 302, // 32: openshell.v1.SandboxWorkloadTemplateSpec.driver_config:type_name -> google.protobuf.Struct 48, // 33: openshell.v1.SandboxWorkloadTemplateSpec.desired_service_level:type_name -> openshell.v1.SandboxServiceLevel - 275, // 34: openshell.v1.SandboxWorkloadConfig.environment:type_name -> openshell.v1.SandboxWorkloadConfig.EnvironmentEntry + 277, // 34: openshell.v1.SandboxWorkloadConfig.environment:type_name -> openshell.v1.SandboxWorkloadConfig.EnvironmentEntry 47, // 35: openshell.v1.SandboxWorkloadConfig.resources:type_name -> openshell.v1.SandboxResources 42, // 36: openshell.v1.SandboxResources.gpu:type_name -> openshell.v1.GpuResourceRequirements 49, // 37: openshell.v1.SandboxServiceLevel.startup:type_name -> openshell.v1.SandboxStartup - 301, // 38: openshell.v1.SandboxStartup.ready_within:type_name -> google.protobuf.Duration + 303, // 38: openshell.v1.SandboxStartup.ready_within:type_name -> google.protobuf.Duration 52, // 39: openshell.v1.SandboxStatus.conditions:type_name -> openshell.v1.SandboxCondition 1, // 40: openshell.v1.SandboxStatus.phase:type_name -> openshell.v1.SandboxPhase - 267, // 41: openshell.v1.SandboxStatus.endpoint_statuses:type_name -> openshell.v1.EndpointStatus - 183, // 42: openshell.v1.SandboxStatus.configuration_admission:type_name -> openshell.v1.SandboxConfigurationAdmission - 268, // 43: openshell.v1.SandboxStatus.provisioning:type_name -> openshell.v1.SandboxProvisioning - 297, // 44: openshell.v1.SandboxStatus.next_restart_time:type_name -> google.protobuf.Timestamp - 297, // 45: openshell.v1.SandboxStatus.main_process_started_time:type_name -> google.protobuf.Timestamp - 265, // 46: openshell.v1.SandboxStatus.last_token_grant_failure:type_name -> openshell.v1.TokenGrantFailureObservation - 297, // 47: openshell.v1.SandboxCondition.transition_time:type_name -> google.protobuf.Timestamp - 297, // 48: openshell.v1.PlatformEvent.event_time:type_name -> google.protobuf.Timestamp - 276, // 49: openshell.v1.PlatformEvent.metadata:type_name -> openshell.v1.PlatformEvent.MetadataEntry - 302, // 50: openshell.v1.CreateSandboxRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 269, // 41: openshell.v1.SandboxStatus.endpoint_statuses:type_name -> openshell.v1.EndpointStatus + 185, // 42: openshell.v1.SandboxStatus.configuration_admission:type_name -> openshell.v1.SandboxConfigurationAdmission + 270, // 43: openshell.v1.SandboxStatus.provisioning:type_name -> openshell.v1.SandboxProvisioning + 299, // 44: openshell.v1.SandboxStatus.next_restart_time:type_name -> google.protobuf.Timestamp + 299, // 45: openshell.v1.SandboxStatus.main_process_started_time:type_name -> google.protobuf.Timestamp + 267, // 46: openshell.v1.SandboxStatus.last_token_grant_failure:type_name -> openshell.v1.TokenGrantFailureObservation + 299, // 47: openshell.v1.SandboxCondition.transition_time:type_name -> google.protobuf.Timestamp + 299, // 48: openshell.v1.PlatformEvent.event_time:type_name -> google.protobuf.Timestamp + 278, // 49: openshell.v1.PlatformEvent.metadata:type_name -> openshell.v1.PlatformEvent.MetadataEntry + 304, // 50: openshell.v1.CreateSandboxRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector 40, // 51: openshell.v1.CreateSandboxRequest.spec:type_name -> openshell.v1.SandboxSpec - 277, // 52: openshell.v1.CreateSandboxRequest.labels:type_name -> openshell.v1.CreateSandboxRequest.LabelsEntry - 278, // 53: openshell.v1.CreateSandboxRequest.annotations:type_name -> openshell.v1.CreateSandboxRequest.AnnotationsEntry - 269, // 54: openshell.v1.CreateSandboxRequest.service_exposures:type_name -> openshell.v1.SandboxServiceExposure - 302, // 55: openshell.v1.CreateSandboxTemplateRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 279, // 52: openshell.v1.CreateSandboxRequest.labels:type_name -> openshell.v1.CreateSandboxRequest.LabelsEntry + 280, // 53: openshell.v1.CreateSandboxRequest.annotations:type_name -> openshell.v1.CreateSandboxRequest.AnnotationsEntry + 271, // 54: openshell.v1.CreateSandboxRequest.service_exposures:type_name -> openshell.v1.SandboxServiceExposure + 304, // 55: openshell.v1.CreateSandboxTemplateRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector 44, // 56: openshell.v1.CreateSandboxTemplateRequest.template:type_name -> openshell.v1.SandboxWorkloadTemplate - 302, // 57: openshell.v1.GetSandboxTemplateRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector - 302, // 58: openshell.v1.ListSandboxTemplatesRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector - 302, // 59: openshell.v1.DeleteSandboxTemplateRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 304, // 57: openshell.v1.GetSandboxTemplateRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 304, // 58: openshell.v1.ListSandboxTemplatesRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 304, // 59: openshell.v1.DeleteSandboxTemplateRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector 44, // 60: openshell.v1.SandboxTemplateResponse.template:type_name -> openshell.v1.SandboxWorkloadTemplate 44, // 61: openshell.v1.ListSandboxTemplatesResponse.templates:type_name -> openshell.v1.SandboxWorkloadTemplate 18, // 62: openshell.v1.DeleteSandboxTemplateResponse.outcome:type_name -> openshell.v1.DeletionOutcome - 302, // 63: openshell.v1.BeginRootfsTarStagingRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector - 297, // 64: openshell.v1.BeginRootfsTarStagingResponse.expiration_time:type_name -> google.protobuf.Timestamp - 302, // 65: openshell.v1.GetSandboxRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector - 302, // 66: openshell.v1.ListSandboxesRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector - 302, // 67: openshell.v1.ListSandboxProvidersRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector - 302, // 68: openshell.v1.AttachSandboxProviderRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector - 302, // 69: openshell.v1.DetachSandboxProviderRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector - 302, // 70: openshell.v1.DeleteSandboxRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector - 302, // 71: openshell.v1.StopSandboxRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector - 302, // 72: openshell.v1.StartSandboxRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 304, // 63: openshell.v1.BeginRootfsTarStagingRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 299, // 64: openshell.v1.BeginRootfsTarStagingResponse.expiration_time:type_name -> google.protobuf.Timestamp + 304, // 65: openshell.v1.GetSandboxRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 304, // 66: openshell.v1.ListSandboxesRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 304, // 67: openshell.v1.ListSandboxProvidersRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 304, // 68: openshell.v1.AttachSandboxProviderRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 304, // 69: openshell.v1.DetachSandboxProviderRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 304, // 70: openshell.v1.DeleteSandboxRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 304, // 71: openshell.v1.StopSandboxRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 304, // 72: openshell.v1.StartSandboxRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector 39, // 73: openshell.v1.SandboxResponse.sandbox:type_name -> openshell.v1.Sandbox - 279, // 74: openshell.v1.SandboxResponse.service_urls:type_name -> openshell.v1.SandboxResponse.ServiceUrlsEntry + 281, // 74: openshell.v1.SandboxResponse.service_urls:type_name -> openshell.v1.SandboxResponse.ServiceUrlsEntry 39, // 75: openshell.v1.ListSandboxesResponse.sandboxes:type_name -> openshell.v1.Sandbox - 303, // 76: openshell.v1.ListSandboxProvidersResponse.providers:type_name -> openshell.datamodel.v1.Provider + 305, // 76: openshell.v1.ListSandboxProvidersResponse.providers:type_name -> openshell.datamodel.v1.Provider 39, // 77: openshell.v1.AttachSandboxProviderResponse.sandbox:type_name -> openshell.v1.Sandbox 81, // 78: openshell.v1.AttachSandboxProviderResponse.receipt:type_name -> openshell.v1.ProviderMutationReceipt 39, // 79: openshell.v1.DetachSandboxProviderResponse.sandbox:type_name -> openshell.v1.Sandbox 81, // 80: openshell.v1.DetachSandboxProviderResponse.receipt:type_name -> openshell.v1.ProviderMutationReceipt 79, // 81: openshell.v1.ConfigSnapshotRevision.sandbox_config:type_name -> openshell.v1.SandboxConfigRevision 77, // 82: openshell.v1.ConfigSnapshotRevision.provider_target:type_name -> openshell.v1.ProviderDesiredIdentity - 304, // 83: openshell.v1.SandboxConfigRevision.policy_source:type_name -> openshell.sandbox.v1.PolicySource + 306, // 83: openshell.v1.SandboxConfigRevision.policy_source:type_name -> openshell.sandbox.v1.PolicySource 5, // 84: openshell.v1.ConfigUpdateOperation.component:type_name -> openshell.v1.ConfigComponent 78, // 85: openshell.v1.ConfigUpdateOperation.target_revision:type_name -> openshell.v1.ConfigSnapshotRevision 7, // 86: openshell.v1.ConfigUpdateOperation.state:type_name -> openshell.v1.ConfigUpdateOperationState 6, // 87: openshell.v1.ConfigUpdateOperation.outcome:type_name -> openshell.v1.ConfigApplyOutcome - 297, // 88: openshell.v1.ConfigUpdateOperation.created_time:type_name -> google.protobuf.Timestamp - 297, // 89: openshell.v1.ConfigUpdateOperation.updated_time:type_name -> google.protobuf.Timestamp - 297, // 90: openshell.v1.ConfigUpdateOperation.completed_time:type_name -> google.protobuf.Timestamp + 299, // 88: openshell.v1.ConfigUpdateOperation.created_time:type_name -> google.protobuf.Timestamp + 299, // 89: openshell.v1.ConfigUpdateOperation.updated_time:type_name -> google.protobuf.Timestamp + 299, // 90: openshell.v1.ConfigUpdateOperation.completed_time:type_name -> google.protobuf.Timestamp 2, // 91: openshell.v1.ProviderMutationReceipt.kind:type_name -> openshell.v1.ProviderMutationKind 77, // 92: openshell.v1.ProviderMutationReceipt.desired:type_name -> openshell.v1.ProviderDesiredIdentity - 297, // 93: openshell.v1.ProviderMutationReceipt.persisted_time:type_name -> google.protobuf.Timestamp + 299, // 93: openshell.v1.ProviderMutationReceipt.persisted_time:type_name -> google.protobuf.Timestamp 4, // 94: openshell.v1.ProviderReadinessObservation.reason:type_name -> openshell.v1.ProviderReadinessReason 81, // 95: openshell.v1.ProviderReadinessStatus.receipt:type_name -> openshell.v1.ProviderMutationReceipt 3, // 96: openshell.v1.ProviderReadinessStatus.state:type_name -> openshell.v1.ProviderReadinessState 4, // 97: openshell.v1.ProviderReadinessStatus.reason:type_name -> openshell.v1.ProviderReadinessReason 82, // 98: openshell.v1.ProviderReadinessStatus.observed:type_name -> openshell.v1.ProviderReadinessObservation - 297, // 99: openshell.v1.ProviderReadinessStatus.observed_time:type_name -> google.protobuf.Timestamp - 297, // 100: openshell.v1.ProviderReadinessStatus.evaluated_time:type_name -> google.protobuf.Timestamp + 299, // 99: openshell.v1.ProviderReadinessStatus.observed_time:type_name -> google.protobuf.Timestamp + 299, // 100: openshell.v1.ProviderReadinessStatus.evaluated_time:type_name -> google.protobuf.Timestamp 80, // 101: openshell.v1.ProviderReadinessStatus.operation:type_name -> openshell.v1.ConfigUpdateOperation - 302, // 102: openshell.v1.GetSandboxProviderStatusRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 304, // 102: openshell.v1.GetSandboxProviderStatusRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector 83, // 103: openshell.v1.GetSandboxProviderStatusResponse.status:type_name -> openshell.v1.ProviderReadinessStatus 82, // 104: openshell.v1.ReportProviderReadinessRequest.observation:type_name -> openshell.v1.ProviderReadinessObservation - 301, // 105: openshell.v1.ReportProviderReadinessResponse.report_interval:type_name -> google.protobuf.Duration - 301, // 106: openshell.v1.ReportProviderReadinessResponse.observation_ttl:type_name -> google.protobuf.Duration + 303, // 105: openshell.v1.ReportProviderReadinessResponse.report_interval:type_name -> google.protobuf.Duration + 303, // 106: openshell.v1.ReportProviderReadinessResponse.observation_ttl:type_name -> google.protobuf.Duration 18, // 107: openshell.v1.DeleteSandboxResponse.outcome:type_name -> openshell.v1.DeletionOutcome - 302, // 108: openshell.v1.CreateSshSessionRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector - 297, // 109: openshell.v1.CreateSshSessionResponse.expiration_time:type_name -> google.protobuf.Timestamp - 302, // 110: openshell.v1.ExposeServiceRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 304, // 108: openshell.v1.CreateSshSessionRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 299, // 109: openshell.v1.CreateSshSessionResponse.expiration_time:type_name -> google.protobuf.Timestamp + 304, // 110: openshell.v1.ExposeServiceRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector 20, // 111: openshell.v1.ExposeServiceRequest.authorization_mode:type_name -> openshell.v1.ServiceAuthorizationMode - 302, // 112: openshell.v1.GetServiceRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector - 302, // 113: openshell.v1.ListServicesRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 304, // 112: openshell.v1.GetServiceRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 304, // 113: openshell.v1.ListServicesRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector 98, // 114: openshell.v1.ListServicesResponse.services:type_name -> openshell.v1.ServiceEndpointResponse - 302, // 115: openshell.v1.DeleteServiceRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 304, // 115: openshell.v1.DeleteServiceRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector 18, // 116: openshell.v1.DeleteServiceResponse.outcome:type_name -> openshell.v1.DeletionOutcome - 298, // 117: openshell.v1.ServiceEndpoint.metadata:type_name -> openshell.datamodel.v1.ObjectMeta + 300, // 117: openshell.v1.ServiceEndpoint.metadata:type_name -> openshell.datamodel.v1.ObjectMeta 20, // 118: openshell.v1.ServiceEndpoint.authorization_mode:type_name -> openshell.v1.ServiceAuthorizationMode 97, // 119: openshell.v1.ServiceEndpointResponse.endpoint:type_name -> openshell.v1.ServiceEndpoint 18, // 120: openshell.v1.RevokeSshSessionResponse.outcome:type_name -> openshell.v1.DeletionOutcome - 302, // 121: openshell.v1.ExecSandboxRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector - 280, // 122: openshell.v1.ExecSandboxRequest.environment:type_name -> openshell.v1.ExecSandboxRequest.EnvironmentEntry - 301, // 123: openshell.v1.ExecSandboxRequest.execution_timeout:type_name -> google.protobuf.Duration + 304, // 121: openshell.v1.ExecSandboxRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 282, // 122: openshell.v1.ExecSandboxRequest.environment:type_name -> openshell.v1.ExecSandboxRequest.EnvironmentEntry + 303, // 123: openshell.v1.ExecSandboxRequest.execution_timeout:type_name -> google.protobuf.Duration 102, // 124: openshell.v1.ExecSandboxEvent.stdout:type_name -> openshell.v1.ExecSandboxStdout 103, // 125: openshell.v1.ExecSandboxEvent.stderr:type_name -> openshell.v1.ExecSandboxStderr 104, // 126: openshell.v1.ExecSandboxEvent.exit:type_name -> openshell.v1.ExecSandboxExit - 208, // 127: openshell.v1.TcpForwardInit.ssh:type_name -> openshell.v1.SshRelayTarget - 209, // 128: openshell.v1.TcpForwardInit.tcp:type_name -> openshell.v1.TcpRelayTarget + 210, // 127: openshell.v1.TcpForwardInit.ssh:type_name -> openshell.v1.SshRelayTarget + 211, // 128: openshell.v1.TcpForwardInit.tcp:type_name -> openshell.v1.TcpRelayTarget 106, // 129: openshell.v1.TcpForwardFrame.init:type_name -> openshell.v1.TcpForwardInit 101, // 130: openshell.v1.ExecSandboxInput.start:type_name -> openshell.v1.ExecSandboxRequest 109, // 131: openshell.v1.ExecSandboxInput.resize:type_name -> openshell.v1.ExecSandboxWindowResize - 298, // 132: openshell.v1.SshSession.metadata:type_name -> openshell.datamodel.v1.ObjectMeta - 297, // 133: openshell.v1.SshSession.expiration_time:type_name -> google.protobuf.Timestamp - 302, // 134: openshell.v1.WatchSandboxRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector - 297, // 135: openshell.v1.WatchSandboxRequest.since_time:type_name -> google.protobuf.Timestamp + 300, // 132: openshell.v1.SshSession.metadata:type_name -> openshell.datamodel.v1.ObjectMeta + 299, // 133: openshell.v1.SshSession.expiration_time:type_name -> google.protobuf.Timestamp + 304, // 134: openshell.v1.WatchSandboxRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 299, // 135: openshell.v1.WatchSandboxRequest.since_time:type_name -> google.protobuf.Timestamp 39, // 136: openshell.v1.SandboxStreamEvent.sandbox:type_name -> openshell.v1.Sandbox 113, // 137: openshell.v1.SandboxStreamEvent.log:type_name -> openshell.v1.SandboxLogLine 53, // 138: openshell.v1.SandboxStreamEvent.event:type_name -> openshell.v1.PlatformEvent 114, // 139: openshell.v1.SandboxStreamEvent.warning:type_name -> openshell.v1.SandboxStreamWarning - 225, // 140: openshell.v1.SandboxStreamEvent.draft_policy_update:type_name -> openshell.v1.DraftPolicyUpdate - 297, // 141: openshell.v1.SandboxLogLine.event_time:type_name -> google.protobuf.Timestamp - 281, // 142: openshell.v1.SandboxLogLine.fields:type_name -> openshell.v1.SandboxLogLine.FieldsEntry - 302, // 143: openshell.v1.CreateProviderRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector - 303, // 144: openshell.v1.CreateProviderRequest.provider:type_name -> openshell.datamodel.v1.Provider - 302, // 145: openshell.v1.GetProviderRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector - 302, // 146: openshell.v1.GetProviderCredentialsRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector - 301, // 147: openshell.v1.GetProviderCredentialsRequest.minimum_remaining_lifetime:type_name -> google.protobuf.Duration - 297, // 148: openshell.v1.ProviderCredentialValue.expiration_time:type_name -> google.protobuf.Timestamp - 282, // 149: openshell.v1.GetProviderCredentialsResponse.credentials:type_name -> openshell.v1.GetProviderCredentialsResponse.CredentialsEntry - 302, // 150: openshell.v1.ListProvidersRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector - 302, // 151: openshell.v1.UpdateProviderRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector - 303, // 152: openshell.v1.UpdateProviderRequest.provider:type_name -> openshell.datamodel.v1.Provider - 283, // 153: openshell.v1.UpdateProviderRequest.credential_expiration_times:type_name -> openshell.v1.UpdateProviderRequest.CredentialExpirationTimesEntry - 302, // 154: openshell.v1.DeleteProviderRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector - 303, // 155: openshell.v1.ProviderResponse.provider:type_name -> openshell.datamodel.v1.Provider + 227, // 140: openshell.v1.SandboxStreamEvent.draft_policy_update:type_name -> openshell.v1.DraftPolicyUpdate + 299, // 141: openshell.v1.SandboxLogLine.event_time:type_name -> google.protobuf.Timestamp + 283, // 142: openshell.v1.SandboxLogLine.fields:type_name -> openshell.v1.SandboxLogLine.FieldsEntry + 304, // 143: openshell.v1.CreateProviderRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 305, // 144: openshell.v1.CreateProviderRequest.provider:type_name -> openshell.datamodel.v1.Provider + 304, // 145: openshell.v1.GetProviderRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 304, // 146: openshell.v1.GetProviderCredentialsRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 303, // 147: openshell.v1.GetProviderCredentialsRequest.minimum_remaining_lifetime:type_name -> google.protobuf.Duration + 299, // 148: openshell.v1.ProviderCredentialValue.expiration_time:type_name -> google.protobuf.Timestamp + 284, // 149: openshell.v1.GetProviderCredentialsResponse.credentials:type_name -> openshell.v1.GetProviderCredentialsResponse.CredentialsEntry + 304, // 150: openshell.v1.ListProvidersRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 304, // 151: openshell.v1.UpdateProviderRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 305, // 152: openshell.v1.UpdateProviderRequest.provider:type_name -> openshell.datamodel.v1.Provider + 285, // 153: openshell.v1.UpdateProviderRequest.credential_expiration_times:type_name -> openshell.v1.UpdateProviderRequest.CredentialExpirationTimesEntry + 304, // 154: openshell.v1.DeleteProviderRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 305, // 155: openshell.v1.ProviderResponse.provider:type_name -> openshell.datamodel.v1.Provider 81, // 156: openshell.v1.ProviderResponse.target_receipts:type_name -> openshell.v1.ProviderMutationReceipt - 303, // 157: openshell.v1.ListProvidersResponse.providers:type_name -> openshell.datamodel.v1.Provider - 302, // 158: openshell.v1.ListProviderProfilesRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector - 302, // 159: openshell.v1.GetProviderProfileRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 305, // 157: openshell.v1.ListProvidersResponse.providers:type_name -> openshell.datamodel.v1.Provider + 304, // 158: openshell.v1.ListProviderProfilesRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 304, // 159: openshell.v1.GetProviderProfileRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector 146, // 160: openshell.v1.ProviderProfileImportItem.profile:type_name -> openshell.v1.ProviderProfile - 301, // 161: openshell.v1.ProviderCredentialTokenGrant.cache_ttl:type_name -> google.protobuf.Duration + 303, // 161: openshell.v1.ProviderCredentialTokenGrant.cache_ttl:type_name -> google.protobuf.Duration 129, // 162: openshell.v1.ProviderCredentialTokenGrant.audience_overrides:type_name -> openshell.v1.ProviderCredentialTokenGrantAudienceOverride 8, // 163: openshell.v1.ProviderCredentialTokenGrant.grant_type:type_name -> openshell.v1.ProviderCredentialTokenGrantType 130, // 164: openshell.v1.ProviderCredentialTokenGrant.subject_token:type_name -> openshell.v1.ProviderCredentialTokenGrantSubjectToken 135, // 165: openshell.v1.ProviderProfileCredential.refresh:type_name -> openshell.v1.ProviderCredentialRefresh 131, // 166: openshell.v1.ProviderProfileCredential.token_grant:type_name -> openshell.v1.ProviderCredentialTokenGrant 9, // 167: openshell.v1.ProviderCredentialRefresh.strategy:type_name -> openshell.v1.ProviderCredentialRefreshStrategy - 301, // 168: openshell.v1.ProviderCredentialRefresh.refresh_before:type_name -> google.protobuf.Duration - 301, // 169: openshell.v1.ProviderCredentialRefresh.max_lifetime:type_name -> google.protobuf.Duration + 303, // 168: openshell.v1.ProviderCredentialRefresh.refresh_before:type_name -> google.protobuf.Duration + 303, // 169: openshell.v1.ProviderCredentialRefresh.max_lifetime:type_name -> google.protobuf.Duration 133, // 170: openshell.v1.ProviderCredentialRefresh.material:type_name -> openshell.v1.ProviderCredentialRefreshMaterial 134, // 171: openshell.v1.ProviderCredentialRefresh.additional_outputs:type_name -> openshell.v1.ProviderCredentialRefreshOutput 9, // 172: openshell.v1.ProviderCredentialRefreshStatus.strategy:type_name -> openshell.v1.ProviderCredentialRefreshStrategy - 297, // 173: openshell.v1.ProviderCredentialRefreshStatus.expiration_time:type_name -> google.protobuf.Timestamp - 297, // 174: openshell.v1.ProviderCredentialRefreshStatus.next_refresh_time:type_name -> google.protobuf.Timestamp - 297, // 175: openshell.v1.ProviderCredentialRefreshStatus.last_refresh_time:type_name -> google.protobuf.Timestamp + 299, // 173: openshell.v1.ProviderCredentialRefreshStatus.expiration_time:type_name -> google.protobuf.Timestamp + 299, // 174: openshell.v1.ProviderCredentialRefreshStatus.next_refresh_time:type_name -> google.protobuf.Timestamp + 299, // 175: openshell.v1.ProviderCredentialRefreshStatus.last_refresh_time:type_name -> google.protobuf.Timestamp 16, // 176: openshell.v1.ProviderCredentialRefreshStatus.recovery_action:type_name -> openshell.v1.ProviderCredentialRefreshRecoveryAction - 297, // 177: openshell.v1.ProviderCredentialRefreshStatus.last_error_time:type_name -> google.protobuf.Timestamp - 302, // 178: openshell.v1.GetProviderRefreshStatusRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 299, // 177: openshell.v1.ProviderCredentialRefreshStatus.last_error_time:type_name -> google.protobuf.Timestamp + 304, // 178: openshell.v1.GetProviderRefreshStatusRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector 136, // 179: openshell.v1.GetProviderRefreshStatusResponse.credentials:type_name -> openshell.v1.ProviderCredentialRefreshStatus - 302, // 180: openshell.v1.ConfigureProviderRefreshRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 304, // 180: openshell.v1.ConfigureProviderRefreshRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector 9, // 181: openshell.v1.ConfigureProviderRefreshRequest.strategy:type_name -> openshell.v1.ProviderCredentialRefreshStrategy - 284, // 182: openshell.v1.ConfigureProviderRefreshRequest.material:type_name -> openshell.v1.ConfigureProviderRefreshRequest.MaterialEntry - 297, // 183: openshell.v1.ConfigureProviderRefreshRequest.expiration_time:type_name -> google.protobuf.Timestamp + 286, // 182: openshell.v1.ConfigureProviderRefreshRequest.material:type_name -> openshell.v1.ConfigureProviderRefreshRequest.MaterialEntry + 299, // 183: openshell.v1.ConfigureProviderRefreshRequest.expiration_time:type_name -> google.protobuf.Timestamp 136, // 184: openshell.v1.ConfigureProviderRefreshResponse.status:type_name -> openshell.v1.ProviderCredentialRefreshStatus - 302, // 185: openshell.v1.RotateProviderCredentialRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 304, // 185: openshell.v1.RotateProviderCredentialRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector 136, // 186: openshell.v1.RotateProviderCredentialResponse.status:type_name -> openshell.v1.ProviderCredentialRefreshStatus - 302, // 187: openshell.v1.DeleteProviderRefreshRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 304, // 187: openshell.v1.DeleteProviderRefreshRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector 18, // 188: openshell.v1.DeleteProviderRefreshResponse.outcome:type_name -> openshell.v1.DeletionOutcome 10, // 189: openshell.v1.ProviderProfile.category:type_name -> openshell.v1.ProviderProfileCategory 132, // 190: openshell.v1.ProviderProfile.credentials:type_name -> openshell.v1.ProviderProfileCredential - 305, // 191: openshell.v1.ProviderProfile.endpoints:type_name -> openshell.sandbox.v1.NetworkEndpoint - 306, // 192: openshell.v1.ProviderProfile.binaries:type_name -> openshell.sandbox.v1.NetworkBinary + 307, // 191: openshell.v1.ProviderProfile.endpoints:type_name -> openshell.sandbox.v1.NetworkEndpoint + 308, // 192: openshell.v1.ProviderProfile.binaries:type_name -> openshell.sandbox.v1.NetworkBinary 137, // 193: openshell.v1.ProviderProfile.discovery:type_name -> openshell.v1.ProviderProfileDiscovery - 285, // 194: openshell.v1.ProviderProfile.annotations:type_name -> openshell.v1.ProviderProfile.AnnotationsEntry + 287, // 194: openshell.v1.ProviderProfile.annotations:type_name -> openshell.v1.ProviderProfile.AnnotationsEntry 147, // 195: openshell.v1.ProviderProfile.files:type_name -> openshell.v1.ProviderProfileFile 146, // 196: openshell.v1.ProviderProfileResponse.profile:type_name -> openshell.v1.ProviderProfile 146, // 197: openshell.v1.ListProviderProfilesResponse.profiles:type_name -> openshell.v1.ProviderProfile - 302, // 198: openshell.v1.ImportProviderProfilesRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 304, // 198: openshell.v1.ImportProviderProfilesRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector 127, // 199: openshell.v1.ImportProviderProfilesRequest.profiles:type_name -> openshell.v1.ProviderProfileImportItem 128, // 200: openshell.v1.ImportProviderProfilesResponse.diagnostics:type_name -> openshell.v1.ProviderProfileDiagnostic 146, // 201: openshell.v1.ImportProviderProfilesResponse.profiles:type_name -> openshell.v1.ProviderProfile - 302, // 202: openshell.v1.UpdateProviderProfilesRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 304, // 202: openshell.v1.UpdateProviderProfilesRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector 127, // 203: openshell.v1.UpdateProviderProfilesRequest.profile:type_name -> openshell.v1.ProviderProfileImportItem 128, // 204: openshell.v1.UpdateProviderProfilesResponse.diagnostics:type_name -> openshell.v1.ProviderProfileDiagnostic 146, // 205: openshell.v1.UpdateProviderProfilesResponse.profile:type_name -> openshell.v1.ProviderProfile - 302, // 206: openshell.v1.LintProviderProfilesRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 304, // 206: openshell.v1.LintProviderProfilesRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector 127, // 207: openshell.v1.LintProviderProfilesRequest.profiles:type_name -> openshell.v1.ProviderProfileImportItem 128, // 208: openshell.v1.LintProviderProfilesResponse.diagnostics:type_name -> openshell.v1.ProviderProfileDiagnostic 18, // 209: openshell.v1.DeleteProviderResponse.outcome:type_name -> openshell.v1.DeletionOutcome - 302, // 210: openshell.v1.DeleteProviderProfileRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 304, // 210: openshell.v1.DeleteProviderProfileRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector 18, // 211: openshell.v1.DeleteProviderProfileResponse.outcome:type_name -> openshell.v1.DeletionOutcome 160, // 212: openshell.v1.StaticCredentialBinding.endpoints:type_name -> openshell.v1.StaticCredentialEndpointBinding - 286, // 213: openshell.v1.GetSandboxProviderEnvironmentResponse.environment:type_name -> openshell.v1.GetSandboxProviderEnvironmentResponse.EnvironmentEntry - 287, // 214: openshell.v1.GetSandboxProviderEnvironmentResponse.credential_expiration_times:type_name -> openshell.v1.GetSandboxProviderEnvironmentResponse.CredentialExpirationTimesEntry - 288, // 215: openshell.v1.GetSandboxProviderEnvironmentResponse.dynamic_credentials:type_name -> openshell.v1.GetSandboxProviderEnvironmentResponse.DynamicCredentialsEntry - 289, // 216: openshell.v1.GetSandboxProviderEnvironmentResponse.static_credential_bindings:type_name -> openshell.v1.GetSandboxProviderEnvironmentResponse.StaticCredentialBindingsEntry + 288, // 213: openshell.v1.GetSandboxProviderEnvironmentResponse.environment:type_name -> openshell.v1.GetSandboxProviderEnvironmentResponse.EnvironmentEntry + 289, // 214: openshell.v1.GetSandboxProviderEnvironmentResponse.credential_expiration_times:type_name -> openshell.v1.GetSandboxProviderEnvironmentResponse.CredentialExpirationTimesEntry + 290, // 215: openshell.v1.GetSandboxProviderEnvironmentResponse.dynamic_credentials:type_name -> openshell.v1.GetSandboxProviderEnvironmentResponse.DynamicCredentialsEntry + 291, // 216: openshell.v1.GetSandboxProviderEnvironmentResponse.static_credential_bindings:type_name -> openshell.v1.GetSandboxProviderEnvironmentResponse.StaticCredentialBindingsEntry 4, // 217: openshell.v1.GetSandboxProviderEnvironmentResponse.readiness_reason:type_name -> openshell.v1.ProviderReadinessReason - 290, // 218: openshell.v1.GetSandboxProviderEnvironmentResponse.files:type_name -> openshell.v1.GetSandboxProviderEnvironmentResponse.FilesEntry + 292, // 218: openshell.v1.GetSandboxProviderEnvironmentResponse.files:type_name -> openshell.v1.GetSandboxProviderEnvironmentResponse.FilesEntry 11, // 219: openshell.v1.ProviderEnvironmentValue.classification:type_name -> openshell.v1.ProviderEnvironmentValueClassification 161, // 220: openshell.v1.ProviderEnvironmentValue.static_credential_binding:type_name -> openshell.v1.StaticCredentialBinding - 297, // 221: openshell.v1.ProviderEnvironmentValue.expiration_time:type_name -> google.protobuf.Timestamp + 299, // 221: openshell.v1.ProviderEnvironmentValue.expiration_time:type_name -> google.protobuf.Timestamp 163, // 222: openshell.v1.ProviderEnvironmentSnapshot.values:type_name -> openshell.v1.ProviderEnvironmentValue - 291, // 223: openshell.v1.ProviderEnvironmentSnapshot.dynamic_credentials:type_name -> openshell.v1.ProviderEnvironmentSnapshot.DynamicCredentialsEntry + 293, // 223: openshell.v1.ProviderEnvironmentSnapshot.dynamic_credentials:type_name -> openshell.v1.ProviderEnvironmentSnapshot.DynamicCredentialsEntry 4, // 224: openshell.v1.ProviderEnvironmentSnapshot.readiness_reason:type_name -> openshell.v1.ProviderReadinessReason - 292, // 225: openshell.v1.ProviderEnvironmentSnapshot.files:type_name -> openshell.v1.ProviderEnvironmentSnapshot.FilesEntry - 301, // 226: openshell.v1.ExchangeProviderSubjectTokenResponse.expires_after:type_name -> google.protobuf.Duration - 302, // 227: openshell.v1.UpdateConfigRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector - 299, // 228: openshell.v1.UpdateConfigRequest.policy:type_name -> openshell.sandbox.v1.SandboxPolicy - 307, // 229: openshell.v1.UpdateConfigRequest.setting_value:type_name -> openshell.sandbox.v1.SettingValue - 168, // 230: openshell.v1.UpdateConfigRequest.merge_operations:type_name -> openshell.v1.PolicyMergeOperation - 293, // 231: openshell.v1.UpdateConfigRequest.annotations:type_name -> openshell.v1.UpdateConfigRequest.AnnotationsEntry - 169, // 232: openshell.v1.PolicyMergeOperation.add_rule:type_name -> openshell.v1.AddNetworkRule - 170, // 233: openshell.v1.PolicyMergeOperation.remove_endpoint:type_name -> openshell.v1.RemoveNetworkEndpoint - 171, // 234: openshell.v1.PolicyMergeOperation.remove_rule:type_name -> openshell.v1.RemoveNetworkRule - 173, // 235: openshell.v1.PolicyMergeOperation.add_deny_rules:type_name -> openshell.v1.AddDenyRules - 174, // 236: openshell.v1.PolicyMergeOperation.add_allow_rules:type_name -> openshell.v1.AddAllowRules - 175, // 237: openshell.v1.PolicyMergeOperation.remove_binary:type_name -> openshell.v1.RemoveNetworkBinary - 308, // 238: openshell.v1.AddNetworkRule.rule:type_name -> openshell.sandbox.v1.NetworkPolicyRule - 306, // 239: openshell.v1.L7RuleTarget.binaries:type_name -> openshell.sandbox.v1.NetworkBinary - 309, // 240: openshell.v1.AddDenyRules.deny_rules:type_name -> openshell.sandbox.v1.L7DenyRule - 172, // 241: openshell.v1.AddDenyRules.target:type_name -> openshell.v1.L7RuleTarget - 310, // 242: openshell.v1.AddAllowRules.rules:type_name -> openshell.sandbox.v1.L7Rule - 172, // 243: openshell.v1.AddAllowRules.target:type_name -> openshell.v1.L7RuleTarget - 294, // 244: openshell.v1.UpdateConfigResponse.annotations:type_name -> openshell.v1.UpdateConfigResponse.AnnotationsEntry - 302, // 245: openshell.v1.GetSandboxPolicyStatusRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector - 186, // 246: openshell.v1.GetSandboxPolicyStatusResponse.revision:type_name -> openshell.v1.SandboxPolicyRevision - 302, // 247: openshell.v1.ListSandboxPoliciesRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector - 186, // 248: openshell.v1.ListSandboxPoliciesResponse.revisions:type_name -> openshell.v1.SandboxPolicyRevision - 13, // 249: openshell.v1.ReportPolicyStatusRequest.status:type_name -> openshell.v1.PolicyStatus - 12, // 250: openshell.v1.SandboxConfigurationAdmission.state:type_name -> openshell.v1.ConfigurationAdmissionState - 183, // 251: openshell.v1.ReportSandboxConfigurationRequest.admission:type_name -> openshell.v1.SandboxConfigurationAdmission - 13, // 252: openshell.v1.SandboxPolicyRevision.status:type_name -> openshell.v1.PolicyStatus - 297, // 253: openshell.v1.SandboxPolicyRevision.created_time:type_name -> google.protobuf.Timestamp - 297, // 254: openshell.v1.SandboxPolicyRevision.loaded_time:type_name -> google.protobuf.Timestamp - 299, // 255: openshell.v1.SandboxPolicyRevision.policy:type_name -> openshell.sandbox.v1.SandboxPolicy - 295, // 256: openshell.v1.SandboxPolicyRevision.provenance:type_name -> openshell.v1.SandboxPolicyRevision.ProvenanceEntry - 302, // 257: openshell.v1.GetSandboxLogsRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector - 297, // 258: openshell.v1.GetSandboxLogsRequest.since_time:type_name -> google.protobuf.Timestamp - 113, // 259: openshell.v1.PushSandboxLogsRequest.logs:type_name -> openshell.v1.SandboxLogLine - 113, // 260: openshell.v1.GetSandboxLogsResponse.logs:type_name -> openshell.v1.SandboxLogLine - 193, // 261: openshell.v1.SupervisorMessage.hello:type_name -> openshell.v1.SupervisorHello - 201, // 262: openshell.v1.SupervisorMessage.heartbeat:type_name -> openshell.v1.SupervisorHeartbeat - 218, // 263: openshell.v1.SupervisorMessage.relay_open_result:type_name -> openshell.v1.RelayOpenResult - 219, // 264: openshell.v1.SupervisorMessage.relay_close:type_name -> openshell.v1.RelayClose - 197, // 265: openshell.v1.SupervisorMessage.config_update_result:type_name -> openshell.v1.ConfigUpdateResult - 194, // 266: openshell.v1.GatewayMessage.session_accepted:type_name -> openshell.v1.SessionAccepted - 199, // 267: openshell.v1.GatewayMessage.session_rejected:type_name -> openshell.v1.SessionRejected - 202, // 268: openshell.v1.GatewayMessage.heartbeat:type_name -> openshell.v1.GatewayHeartbeat - 207, // 269: openshell.v1.GatewayMessage.relay_open:type_name -> openshell.v1.RelayOpen - 219, // 270: openshell.v1.GatewayMessage.relay_close:type_name -> openshell.v1.RelayClose - 200, // 271: openshell.v1.GatewayMessage.session_redirect:type_name -> openshell.v1.SessionRedirect - 195, // 272: openshell.v1.GatewayMessage.config_update:type_name -> openshell.v1.ConfigUpdate - 195, // 273: openshell.v1.SessionAccepted.bootstrap:type_name -> openshell.v1.ConfigUpdate - 301, // 274: openshell.v1.SessionAccepted.heartbeat_interval:type_name -> google.protobuf.Duration - 311, // 275: openshell.v1.ConfigUpdate.sandbox_config:type_name -> openshell.sandbox.v1.SandboxConfigSnapshot - 164, // 276: openshell.v1.ConfigUpdate.provider_environment:type_name -> openshell.v1.ProviderEnvironmentSnapshot - 6, // 277: openshell.v1.ConfigUpdateResult.outcome:type_name -> openshell.v1.ConfigApplyOutcome - 196, // 278: openshell.v1.ConfigUpdateResult.failure:type_name -> openshell.v1.ConfigApplyFailure - 183, // 279: openshell.v1.ConfigUpdateResult.admission:type_name -> openshell.v1.SandboxConfigurationAdmission - 198, // 280: openshell.v1.ConfigUpdateResult.policy_load:type_name -> openshell.v1.PolicyLoadResult - 208, // 281: openshell.v1.RelayOpen.ssh:type_name -> openshell.v1.SshRelayTarget - 209, // 282: openshell.v1.RelayOpen.tcp:type_name -> openshell.v1.TcpRelayTarget - 210, // 283: openshell.v1.RelayFrame.init:type_name -> openshell.v1.RelayInit - 207, // 284: openshell.v1.PeerRelayInit.relay_open:type_name -> openshell.v1.RelayOpen - 212, // 285: openshell.v1.PeerRelayFrame.init:type_name -> openshell.v1.PeerRelayInit - 214, // 286: openshell.v1.PeerNotifyConfigUpdateRequest.sandbox:type_name -> openshell.v1.PeerConfigSandboxTarget - 215, // 287: openshell.v1.PeerNotifyConfigUpdateRequest.provider:type_name -> openshell.v1.PeerConfigProviderTarget - 297, // 288: openshell.v1.DenialSummary.first_seen_time:type_name -> google.protobuf.Timestamp - 297, // 289: openshell.v1.DenialSummary.last_seen_time:type_name -> google.protobuf.Timestamp - 220, // 290: openshell.v1.DenialSummary.l7_request_samples:type_name -> openshell.v1.L7RequestSample - 222, // 291: openshell.v1.NetworkActivitySummary.denials_by_group:type_name -> openshell.v1.DenialGroupCount - 308, // 292: openshell.v1.PolicyChunk.proposed_rule:type_name -> openshell.sandbox.v1.NetworkPolicyRule - 297, // 293: openshell.v1.PolicyChunk.created_time:type_name -> google.protobuf.Timestamp - 297, // 294: openshell.v1.PolicyChunk.decided_time:type_name -> google.protobuf.Timestamp - 297, // 295: openshell.v1.PolicyChunk.first_seen_time:type_name -> google.protobuf.Timestamp - 297, // 296: openshell.v1.PolicyChunk.last_seen_time:type_name -> google.protobuf.Timestamp - 299, // 297: openshell.v1.PolicyChunk.current_effective_policy:type_name -> openshell.sandbox.v1.SandboxPolicy - 299, // 298: openshell.v1.PolicyChunk.candidate_effective_policy:type_name -> openshell.sandbox.v1.SandboxPolicy - 302, // 299: openshell.v1.SubmitPolicyAnalysisRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector - 221, // 300: openshell.v1.SubmitPolicyAnalysisRequest.summaries:type_name -> openshell.v1.DenialSummary - 224, // 301: openshell.v1.SubmitPolicyAnalysisRequest.proposed_chunks:type_name -> openshell.v1.PolicyChunk - 223, // 302: openshell.v1.SubmitPolicyAnalysisRequest.network_activity_summaries:type_name -> openshell.v1.NetworkActivitySummary - 302, // 303: openshell.v1.GetDraftPolicyRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector - 224, // 304: openshell.v1.GetDraftPolicyResponse.chunks:type_name -> openshell.v1.PolicyChunk - 297, // 305: openshell.v1.GetDraftPolicyResponse.last_analyzed_time:type_name -> google.protobuf.Timestamp - 302, // 306: openshell.v1.ApproveDraftChunkRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector - 302, // 307: openshell.v1.RejectDraftChunkRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector - 302, // 308: openshell.v1.ApproveAllDraftChunksRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector - 234, // 309: openshell.v1.ApproveAllDraftChunksRequest.approvals:type_name -> openshell.v1.DraftChunkApproval - 302, // 310: openshell.v1.EditDraftChunkRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector - 308, // 311: openshell.v1.EditDraftChunkRequest.proposed_rule:type_name -> openshell.sandbox.v1.NetworkPolicyRule - 302, // 312: openshell.v1.UndoDraftChunkRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector - 302, // 313: openshell.v1.ClearDraftChunksRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector - 302, // 314: openshell.v1.GetDraftHistoryRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector - 297, // 315: openshell.v1.DraftHistoryEntry.event_time:type_name -> google.protobuf.Timestamp - 244, // 316: openshell.v1.GetDraftHistoryResponse.entries:type_name -> openshell.v1.DraftHistoryEntry - 296, // 317: openshell.v1.CreateWorkspaceRequest.labels:type_name -> openshell.v1.CreateWorkspaceRequest.LabelsEntry - 312, // 318: openshell.v1.CreateWorkspaceResponse.workspace:type_name -> openshell.datamodel.v1.Workspace - 312, // 319: openshell.v1.GetWorkspaceResponse.workspace:type_name -> openshell.datamodel.v1.Workspace - 312, // 320: openshell.v1.ListWorkspacesResponse.workspaces:type_name -> openshell.datamodel.v1.Workspace - 18, // 321: openshell.v1.DeleteWorkspaceResponse.outcome:type_name -> openshell.v1.DeletionOutcome - 298, // 322: openshell.v1.WorkspaceMember.metadata:type_name -> openshell.datamodel.v1.ObjectMeta - 15, // 323: openshell.v1.WorkspaceMember.role:type_name -> openshell.v1.WorkspaceRole - 302, // 324: openshell.v1.AddWorkspaceMemberRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector - 15, // 325: openshell.v1.AddWorkspaceMemberRequest.role:type_name -> openshell.v1.WorkspaceRole - 254, // 326: openshell.v1.AddWorkspaceMemberResponse.member:type_name -> openshell.v1.WorkspaceMember - 302, // 327: openshell.v1.RemoveWorkspaceMemberRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector - 18, // 328: openshell.v1.RemoveWorkspaceMemberResponse.outcome:type_name -> openshell.v1.DeletionOutcome - 302, // 329: openshell.v1.ListWorkspaceMembersRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector - 254, // 330: openshell.v1.ListWorkspaceMembersResponse.members:type_name -> openshell.v1.WorkspaceMember - 297, // 331: openshell.v1.ExtensionServiceCredential.expiration_time:type_name -> google.protobuf.Timestamp - 19, // 332: openshell.v1.EndpointObservation.result:type_name -> openshell.v1.EndpointResult - 270, // 333: openshell.v1.EndpointObservation.failure:type_name -> openshell.v1.EndpointFailure - 262, // 334: openshell.v1.ReportEndpointStatusRequest.observations:type_name -> openshell.v1.EndpointObservation - 264, // 335: openshell.v1.ReportEndpointStatusRequest.token_grant_status:type_name -> openshell.v1.TokenGrantStatus - 265, // 336: openshell.v1.TokenGrantStatus.last_failure:type_name -> openshell.v1.TokenGrantFailureObservation - 270, // 337: openshell.v1.TokenGrantFailureObservation.failure:type_name -> openshell.v1.EndpointFailure - 19, // 338: openshell.v1.EndpointStatus.last_result:type_name -> openshell.v1.EndpointResult - 297, // 339: openshell.v1.EndpointStatus.last_reported_time:type_name -> google.protobuf.Timestamp - 270, // 340: openshell.v1.EndpointStatus.last_failure:type_name -> openshell.v1.EndpointFailure - 297, // 341: openshell.v1.SandboxProvisioning.configuration_change_time:type_name -> google.protobuf.Timestamp - 297, // 342: openshell.v1.SandboxProvisioning.first_rejection_time:type_name -> google.protobuf.Timestamp - 297, // 343: openshell.v1.SandboxProvisioning.deadline:type_name -> google.protobuf.Timestamp - 297, // 344: openshell.v1.SandboxProvisioning.timeout_time:type_name -> google.protobuf.Timestamp - 297, // 345: openshell.v1.SandboxProvisioning.cleanup_completed_time:type_name -> google.protobuf.Timestamp - 297, // 346: openshell.v1.SandboxProvisioning.cleanup_retry_time:type_name -> google.protobuf.Timestamp - 297, // 347: openshell.v1.SandboxProvisioning.attachment_change_time:type_name -> google.protobuf.Timestamp - 297, // 348: openshell.v1.SandboxProvisioning.preparation_deadline:type_name -> google.protobuf.Timestamp - 297, // 349: openshell.v1.SandboxProvisioning.admission_start_time:type_name -> google.protobuf.Timestamp - 20, // 350: openshell.v1.SandboxServiceExposure.authorization_mode:type_name -> openshell.v1.ServiceAuthorizationMode - 21, // 351: openshell.v1.EndpointFailure.domain:type_name -> openshell.v1.EndpointFailureDomain - 16, // 352: openshell.v1.EndpointFailure.recovery_action:type_name -> openshell.v1.ProviderCredentialRefreshRecoveryAction - 118, // 353: openshell.v1.GetProviderCredentialsResponse.CredentialsEntry.value:type_name -> openshell.v1.ProviderCredentialValue - 297, // 354: openshell.v1.UpdateProviderRequest.CredentialExpirationTimesEntry.value:type_name -> google.protobuf.Timestamp - 297, // 355: openshell.v1.GetSandboxProviderEnvironmentResponse.CredentialExpirationTimesEntry.value:type_name -> google.protobuf.Timestamp - 132, // 356: openshell.v1.GetSandboxProviderEnvironmentResponse.DynamicCredentialsEntry.value:type_name -> openshell.v1.ProviderProfileCredential - 161, // 357: openshell.v1.GetSandboxProviderEnvironmentResponse.StaticCredentialBindingsEntry.value:type_name -> openshell.v1.StaticCredentialBinding - 132, // 358: openshell.v1.ProviderEnvironmentSnapshot.DynamicCredentialsEntry.value:type_name -> openshell.v1.ProviderProfileCredential - 26, // 359: openshell.v1.OpenShell.Health:input_type -> openshell.v1.HealthRequest - 28, // 360: openshell.v1.OpenShell.GetCurrentUser:input_type -> openshell.v1.GetCurrentUserRequest - 30, // 361: openshell.v1.OpenShell.GetGatewayInfo:input_type -> openshell.v1.GetGatewayInfoRequest - 54, // 362: openshell.v1.OpenShell.CreateSandbox:input_type -> openshell.v1.CreateSandboxRequest - 62, // 363: openshell.v1.OpenShell.BeginRootfsTarStaging:input_type -> openshell.v1.BeginRootfsTarStagingRequest - 64, // 364: openshell.v1.OpenShell.GetSandbox:input_type -> openshell.v1.GetSandboxRequest - 65, // 365: openshell.v1.OpenShell.ListSandboxes:input_type -> openshell.v1.ListSandboxesRequest - 55, // 366: openshell.v1.OpenShell.CreateSandboxTemplate:input_type -> openshell.v1.CreateSandboxTemplateRequest - 56, // 367: openshell.v1.OpenShell.GetSandboxTemplate:input_type -> openshell.v1.GetSandboxTemplateRequest - 57, // 368: openshell.v1.OpenShell.ListSandboxTemplates:input_type -> openshell.v1.ListSandboxTemplatesRequest - 58, // 369: openshell.v1.OpenShell.DeleteSandboxTemplate:input_type -> openshell.v1.DeleteSandboxTemplateRequest - 66, // 370: openshell.v1.OpenShell.ListSandboxProviders:input_type -> openshell.v1.ListSandboxProvidersRequest - 67, // 371: openshell.v1.OpenShell.AttachSandboxProvider:input_type -> openshell.v1.AttachSandboxProviderRequest - 68, // 372: openshell.v1.OpenShell.DetachSandboxProvider:input_type -> openshell.v1.DetachSandboxProviderRequest - 84, // 373: openshell.v1.OpenShell.GetSandboxProviderStatus:input_type -> openshell.v1.GetSandboxProviderStatusRequest - 69, // 374: openshell.v1.OpenShell.DeleteSandbox:input_type -> openshell.v1.DeleteSandboxRequest - 70, // 375: openshell.v1.OpenShell.StopSandbox:input_type -> openshell.v1.StopSandboxRequest - 71, // 376: openshell.v1.OpenShell.StartSandbox:input_type -> openshell.v1.StartSandboxRequest - 89, // 377: openshell.v1.OpenShell.CreateSshSession:input_type -> openshell.v1.CreateSshSessionRequest - 91, // 378: openshell.v1.OpenShell.ExposeService:input_type -> openshell.v1.ExposeServiceRequest - 92, // 379: openshell.v1.OpenShell.GetService:input_type -> openshell.v1.GetServiceRequest - 93, // 380: openshell.v1.OpenShell.ListServices:input_type -> openshell.v1.ListServicesRequest - 95, // 381: openshell.v1.OpenShell.DeleteService:input_type -> openshell.v1.DeleteServiceRequest - 99, // 382: openshell.v1.OpenShell.RevokeSshSession:input_type -> openshell.v1.RevokeSshSessionRequest - 101, // 383: openshell.v1.OpenShell.ExecSandbox:input_type -> openshell.v1.ExecSandboxRequest - 107, // 384: openshell.v1.OpenShell.ForwardTcp:input_type -> openshell.v1.TcpForwardFrame - 108, // 385: openshell.v1.OpenShell.ExecSandboxInteractive:input_type -> openshell.v1.ExecSandboxInput - 115, // 386: openshell.v1.OpenShell.CreateProvider:input_type -> openshell.v1.CreateProviderRequest - 116, // 387: openshell.v1.OpenShell.GetProvider:input_type -> openshell.v1.GetProviderRequest - 117, // 388: openshell.v1.OpenShell.GetProviderCredentials:input_type -> openshell.v1.GetProviderCredentialsRequest - 120, // 389: openshell.v1.OpenShell.ListProviders:input_type -> openshell.v1.ListProvidersRequest - 125, // 390: openshell.v1.OpenShell.ListProviderProfiles:input_type -> openshell.v1.ListProviderProfilesRequest - 126, // 391: openshell.v1.OpenShell.GetProviderProfile:input_type -> openshell.v1.GetProviderProfileRequest - 150, // 392: openshell.v1.OpenShell.ImportProviderProfiles:input_type -> openshell.v1.ImportProviderProfilesRequest - 152, // 393: openshell.v1.OpenShell.UpdateProviderProfiles:input_type -> openshell.v1.UpdateProviderProfilesRequest - 154, // 394: openshell.v1.OpenShell.LintProviderProfiles:input_type -> openshell.v1.LintProviderProfilesRequest - 121, // 395: openshell.v1.OpenShell.UpdateProvider:input_type -> openshell.v1.UpdateProviderRequest - 138, // 396: openshell.v1.OpenShell.GetProviderRefreshStatus:input_type -> openshell.v1.GetProviderRefreshStatusRequest - 140, // 397: openshell.v1.OpenShell.ConfigureProviderRefresh:input_type -> openshell.v1.ConfigureProviderRefreshRequest - 142, // 398: openshell.v1.OpenShell.RotateProviderCredential:input_type -> openshell.v1.RotateProviderCredentialRequest - 144, // 399: openshell.v1.OpenShell.DeleteProviderRefresh:input_type -> openshell.v1.DeleteProviderRefreshRequest - 122, // 400: openshell.v1.OpenShell.DeleteProvider:input_type -> openshell.v1.DeleteProviderRequest - 157, // 401: openshell.v1.OpenShell.DeleteProviderProfile:input_type -> openshell.v1.DeleteProviderProfileRequest - 313, // 402: openshell.v1.OpenShell.GetSandboxConfig:input_type -> openshell.sandbox.v1.GetSandboxConfigRequest - 314, // 403: openshell.v1.OpenShell.GetGatewayConfig:input_type -> openshell.sandbox.v1.GetGatewayConfigRequest - 167, // 404: openshell.v1.OpenShell.UpdateConfig:input_type -> openshell.v1.UpdateConfigRequest - 177, // 405: openshell.v1.OpenShell.GetSandboxPolicyStatus:input_type -> openshell.v1.GetSandboxPolicyStatusRequest - 179, // 406: openshell.v1.OpenShell.ListSandboxPolicies:input_type -> openshell.v1.ListSandboxPoliciesRequest - 181, // 407: openshell.v1.OpenShell.ReportPolicyStatus:input_type -> openshell.v1.ReportPolicyStatusRequest - 263, // 408: openshell.v1.OpenShell.ReportEndpointStatus:input_type -> openshell.v1.ReportEndpointStatusRequest - 86, // 409: openshell.v1.OpenShell.ReportProviderReadiness:input_type -> openshell.v1.ReportProviderReadinessRequest - 184, // 410: openshell.v1.OpenShell.ReportSandboxConfiguration:input_type -> openshell.v1.ReportSandboxConfigurationRequest - 159, // 411: openshell.v1.OpenShell.GetSandboxProviderEnvironment:input_type -> openshell.v1.GetSandboxProviderEnvironmentRequest - 165, // 412: openshell.v1.OpenShell.ExchangeProviderSubjectToken:input_type -> openshell.v1.ExchangeProviderSubjectTokenRequest - 187, // 413: openshell.v1.OpenShell.GetSandboxLogs:input_type -> openshell.v1.GetSandboxLogsRequest - 188, // 414: openshell.v1.OpenShell.PushSandboxLogs:input_type -> openshell.v1.PushSandboxLogsRequest - 191, // 415: openshell.v1.OpenShell.ConnectSupervisor:input_type -> openshell.v1.SupervisorMessage - 203, // 416: openshell.v1.OpenShell.ReportMainProcessExit:input_type -> openshell.v1.ReportMainProcessExitRequest - 205, // 417: openshell.v1.OpenShell.FinalizeMainProcessExit:input_type -> openshell.v1.FinalizeMainProcessExitRequest - 211, // 418: openshell.v1.OpenShell.RelayStream:input_type -> openshell.v1.RelayFrame - 213, // 419: openshell.v1.OpenShell.PeerRelay:input_type -> openshell.v1.PeerRelayFrame - 86, // 420: openshell.v1.OpenShell.PeerReportProviderReadiness:input_type -> openshell.v1.ReportProviderReadinessRequest - 263, // 421: openshell.v1.OpenShell.PeerReportEndpointStatus:input_type -> openshell.v1.ReportEndpointStatusRequest - 84, // 422: openshell.v1.OpenShell.PeerGetSandboxProviderStatus:input_type -> openshell.v1.GetSandboxProviderStatusRequest - 216, // 423: openshell.v1.OpenShell.PeerNotifyConfigUpdate:input_type -> openshell.v1.PeerNotifyConfigUpdateRequest - 111, // 424: openshell.v1.OpenShell.WatchSandbox:input_type -> openshell.v1.WatchSandboxRequest - 226, // 425: openshell.v1.OpenShell.SubmitPolicyAnalysis:input_type -> openshell.v1.SubmitPolicyAnalysisRequest - 228, // 426: openshell.v1.OpenShell.GetDraftPolicy:input_type -> openshell.v1.GetDraftPolicyRequest - 230, // 427: openshell.v1.OpenShell.ApproveDraftChunk:input_type -> openshell.v1.ApproveDraftChunkRequest - 232, // 428: openshell.v1.OpenShell.RejectDraftChunk:input_type -> openshell.v1.RejectDraftChunkRequest - 235, // 429: openshell.v1.OpenShell.ApproveAllDraftChunks:input_type -> openshell.v1.ApproveAllDraftChunksRequest - 237, // 430: openshell.v1.OpenShell.EditDraftChunk:input_type -> openshell.v1.EditDraftChunkRequest - 239, // 431: openshell.v1.OpenShell.UndoDraftChunk:input_type -> openshell.v1.UndoDraftChunkRequest - 241, // 432: openshell.v1.OpenShell.ClearDraftChunks:input_type -> openshell.v1.ClearDraftChunksRequest - 243, // 433: openshell.v1.OpenShell.GetDraftHistory:input_type -> openshell.v1.GetDraftHistoryRequest - 22, // 434: openshell.v1.OpenShell.IssueSandboxToken:input_type -> openshell.v1.IssueSandboxTokenRequest - 24, // 435: openshell.v1.OpenShell.RefreshSandboxToken:input_type -> openshell.v1.RefreshSandboxTokenRequest - 246, // 436: openshell.v1.OpenShell.CreateWorkspace:input_type -> openshell.v1.CreateWorkspaceRequest - 248, // 437: openshell.v1.OpenShell.GetWorkspace:input_type -> openshell.v1.GetWorkspaceRequest - 250, // 438: openshell.v1.OpenShell.ListWorkspaces:input_type -> openshell.v1.ListWorkspacesRequest - 252, // 439: openshell.v1.OpenShell.DeleteWorkspace:input_type -> openshell.v1.DeleteWorkspaceRequest - 255, // 440: openshell.v1.OpenShell.AddWorkspaceMember:input_type -> openshell.v1.AddWorkspaceMemberRequest - 257, // 441: openshell.v1.OpenShell.RemoveWorkspaceMember:input_type -> openshell.v1.RemoveWorkspaceMemberRequest - 259, // 442: openshell.v1.OpenShell.ListWorkspaceMembers:input_type -> openshell.v1.ListWorkspaceMembersRequest - 27, // 443: openshell.v1.OpenShell.Health:output_type -> openshell.v1.HealthResponse - 29, // 444: openshell.v1.OpenShell.GetCurrentUser:output_type -> openshell.v1.GetCurrentUserResponse - 31, // 445: openshell.v1.OpenShell.GetGatewayInfo:output_type -> openshell.v1.GetGatewayInfoResponse - 72, // 446: openshell.v1.OpenShell.CreateSandbox:output_type -> openshell.v1.SandboxResponse - 63, // 447: openshell.v1.OpenShell.BeginRootfsTarStaging:output_type -> openshell.v1.BeginRootfsTarStagingResponse - 72, // 448: openshell.v1.OpenShell.GetSandbox:output_type -> openshell.v1.SandboxResponse - 73, // 449: openshell.v1.OpenShell.ListSandboxes:output_type -> openshell.v1.ListSandboxesResponse - 59, // 450: openshell.v1.OpenShell.CreateSandboxTemplate:output_type -> openshell.v1.SandboxTemplateResponse - 59, // 451: openshell.v1.OpenShell.GetSandboxTemplate:output_type -> openshell.v1.SandboxTemplateResponse - 60, // 452: openshell.v1.OpenShell.ListSandboxTemplates:output_type -> openshell.v1.ListSandboxTemplatesResponse - 61, // 453: openshell.v1.OpenShell.DeleteSandboxTemplate:output_type -> openshell.v1.DeleteSandboxTemplateResponse - 74, // 454: openshell.v1.OpenShell.ListSandboxProviders:output_type -> openshell.v1.ListSandboxProvidersResponse - 75, // 455: openshell.v1.OpenShell.AttachSandboxProvider:output_type -> openshell.v1.AttachSandboxProviderResponse - 76, // 456: openshell.v1.OpenShell.DetachSandboxProvider:output_type -> openshell.v1.DetachSandboxProviderResponse - 85, // 457: openshell.v1.OpenShell.GetSandboxProviderStatus:output_type -> openshell.v1.GetSandboxProviderStatusResponse - 88, // 458: openshell.v1.OpenShell.DeleteSandbox:output_type -> openshell.v1.DeleteSandboxResponse - 72, // 459: openshell.v1.OpenShell.StopSandbox:output_type -> openshell.v1.SandboxResponse - 72, // 460: openshell.v1.OpenShell.StartSandbox:output_type -> openshell.v1.SandboxResponse - 90, // 461: openshell.v1.OpenShell.CreateSshSession:output_type -> openshell.v1.CreateSshSessionResponse - 98, // 462: openshell.v1.OpenShell.ExposeService:output_type -> openshell.v1.ServiceEndpointResponse - 98, // 463: openshell.v1.OpenShell.GetService:output_type -> openshell.v1.ServiceEndpointResponse - 94, // 464: openshell.v1.OpenShell.ListServices:output_type -> openshell.v1.ListServicesResponse - 96, // 465: openshell.v1.OpenShell.DeleteService:output_type -> openshell.v1.DeleteServiceResponse - 100, // 466: openshell.v1.OpenShell.RevokeSshSession:output_type -> openshell.v1.RevokeSshSessionResponse - 105, // 467: openshell.v1.OpenShell.ExecSandbox:output_type -> openshell.v1.ExecSandboxEvent - 107, // 468: openshell.v1.OpenShell.ForwardTcp:output_type -> openshell.v1.TcpForwardFrame - 105, // 469: openshell.v1.OpenShell.ExecSandboxInteractive:output_type -> openshell.v1.ExecSandboxEvent - 123, // 470: openshell.v1.OpenShell.CreateProvider:output_type -> openshell.v1.ProviderResponse - 123, // 471: openshell.v1.OpenShell.GetProvider:output_type -> openshell.v1.ProviderResponse - 119, // 472: openshell.v1.OpenShell.GetProviderCredentials:output_type -> openshell.v1.GetProviderCredentialsResponse - 124, // 473: openshell.v1.OpenShell.ListProviders:output_type -> openshell.v1.ListProvidersResponse - 149, // 474: openshell.v1.OpenShell.ListProviderProfiles:output_type -> openshell.v1.ListProviderProfilesResponse - 148, // 475: openshell.v1.OpenShell.GetProviderProfile:output_type -> openshell.v1.ProviderProfileResponse - 151, // 476: openshell.v1.OpenShell.ImportProviderProfiles:output_type -> openshell.v1.ImportProviderProfilesResponse - 153, // 477: openshell.v1.OpenShell.UpdateProviderProfiles:output_type -> openshell.v1.UpdateProviderProfilesResponse - 155, // 478: openshell.v1.OpenShell.LintProviderProfiles:output_type -> openshell.v1.LintProviderProfilesResponse - 123, // 479: openshell.v1.OpenShell.UpdateProvider:output_type -> openshell.v1.ProviderResponse - 139, // 480: openshell.v1.OpenShell.GetProviderRefreshStatus:output_type -> openshell.v1.GetProviderRefreshStatusResponse - 141, // 481: openshell.v1.OpenShell.ConfigureProviderRefresh:output_type -> openshell.v1.ConfigureProviderRefreshResponse - 143, // 482: openshell.v1.OpenShell.RotateProviderCredential:output_type -> openshell.v1.RotateProviderCredentialResponse - 145, // 483: openshell.v1.OpenShell.DeleteProviderRefresh:output_type -> openshell.v1.DeleteProviderRefreshResponse - 156, // 484: openshell.v1.OpenShell.DeleteProvider:output_type -> openshell.v1.DeleteProviderResponse - 158, // 485: openshell.v1.OpenShell.DeleteProviderProfile:output_type -> openshell.v1.DeleteProviderProfileResponse - 315, // 486: openshell.v1.OpenShell.GetSandboxConfig:output_type -> openshell.sandbox.v1.GetSandboxConfigResponse - 316, // 487: openshell.v1.OpenShell.GetGatewayConfig:output_type -> openshell.sandbox.v1.GetGatewayConfigResponse - 176, // 488: openshell.v1.OpenShell.UpdateConfig:output_type -> openshell.v1.UpdateConfigResponse - 178, // 489: openshell.v1.OpenShell.GetSandboxPolicyStatus:output_type -> openshell.v1.GetSandboxPolicyStatusResponse - 180, // 490: openshell.v1.OpenShell.ListSandboxPolicies:output_type -> openshell.v1.ListSandboxPoliciesResponse - 182, // 491: openshell.v1.OpenShell.ReportPolicyStatus:output_type -> openshell.v1.ReportPolicyStatusResponse - 266, // 492: openshell.v1.OpenShell.ReportEndpointStatus:output_type -> openshell.v1.ReportEndpointStatusResponse - 87, // 493: openshell.v1.OpenShell.ReportProviderReadiness:output_type -> openshell.v1.ReportProviderReadinessResponse - 185, // 494: openshell.v1.OpenShell.ReportSandboxConfiguration:output_type -> openshell.v1.ReportSandboxConfigurationResponse - 162, // 495: openshell.v1.OpenShell.GetSandboxProviderEnvironment:output_type -> openshell.v1.GetSandboxProviderEnvironmentResponse - 166, // 496: openshell.v1.OpenShell.ExchangeProviderSubjectToken:output_type -> openshell.v1.ExchangeProviderSubjectTokenResponse - 190, // 497: openshell.v1.OpenShell.GetSandboxLogs:output_type -> openshell.v1.GetSandboxLogsResponse - 189, // 498: openshell.v1.OpenShell.PushSandboxLogs:output_type -> openshell.v1.PushSandboxLogsResponse - 192, // 499: openshell.v1.OpenShell.ConnectSupervisor:output_type -> openshell.v1.GatewayMessage - 204, // 500: openshell.v1.OpenShell.ReportMainProcessExit:output_type -> openshell.v1.ReportMainProcessExitResponse - 206, // 501: openshell.v1.OpenShell.FinalizeMainProcessExit:output_type -> openshell.v1.FinalizeMainProcessExitResponse - 211, // 502: openshell.v1.OpenShell.RelayStream:output_type -> openshell.v1.RelayFrame - 213, // 503: openshell.v1.OpenShell.PeerRelay:output_type -> openshell.v1.PeerRelayFrame - 87, // 504: openshell.v1.OpenShell.PeerReportProviderReadiness:output_type -> openshell.v1.ReportProviderReadinessResponse - 266, // 505: openshell.v1.OpenShell.PeerReportEndpointStatus:output_type -> openshell.v1.ReportEndpointStatusResponse - 85, // 506: openshell.v1.OpenShell.PeerGetSandboxProviderStatus:output_type -> openshell.v1.GetSandboxProviderStatusResponse - 217, // 507: openshell.v1.OpenShell.PeerNotifyConfigUpdate:output_type -> openshell.v1.PeerNotifyConfigUpdateResponse - 112, // 508: openshell.v1.OpenShell.WatchSandbox:output_type -> openshell.v1.SandboxStreamEvent - 227, // 509: openshell.v1.OpenShell.SubmitPolicyAnalysis:output_type -> openshell.v1.SubmitPolicyAnalysisResponse - 229, // 510: openshell.v1.OpenShell.GetDraftPolicy:output_type -> openshell.v1.GetDraftPolicyResponse - 231, // 511: openshell.v1.OpenShell.ApproveDraftChunk:output_type -> openshell.v1.ApproveDraftChunkResponse - 233, // 512: openshell.v1.OpenShell.RejectDraftChunk:output_type -> openshell.v1.RejectDraftChunkResponse - 236, // 513: openshell.v1.OpenShell.ApproveAllDraftChunks:output_type -> openshell.v1.ApproveAllDraftChunksResponse - 238, // 514: openshell.v1.OpenShell.EditDraftChunk:output_type -> openshell.v1.EditDraftChunkResponse - 240, // 515: openshell.v1.OpenShell.UndoDraftChunk:output_type -> openshell.v1.UndoDraftChunkResponse - 242, // 516: openshell.v1.OpenShell.ClearDraftChunks:output_type -> openshell.v1.ClearDraftChunksResponse - 245, // 517: openshell.v1.OpenShell.GetDraftHistory:output_type -> openshell.v1.GetDraftHistoryResponse - 23, // 518: openshell.v1.OpenShell.IssueSandboxToken:output_type -> openshell.v1.IssueSandboxTokenResponse - 25, // 519: openshell.v1.OpenShell.RefreshSandboxToken:output_type -> openshell.v1.RefreshSandboxTokenResponse - 247, // 520: openshell.v1.OpenShell.CreateWorkspace:output_type -> openshell.v1.CreateWorkspaceResponse - 249, // 521: openshell.v1.OpenShell.GetWorkspace:output_type -> openshell.v1.GetWorkspaceResponse - 251, // 522: openshell.v1.OpenShell.ListWorkspaces:output_type -> openshell.v1.ListWorkspacesResponse - 253, // 523: openshell.v1.OpenShell.DeleteWorkspace:output_type -> openshell.v1.DeleteWorkspaceResponse - 256, // 524: openshell.v1.OpenShell.AddWorkspaceMember:output_type -> openshell.v1.AddWorkspaceMemberResponse - 258, // 525: openshell.v1.OpenShell.RemoveWorkspaceMember:output_type -> openshell.v1.RemoveWorkspaceMemberResponse - 260, // 526: openshell.v1.OpenShell.ListWorkspaceMembers:output_type -> openshell.v1.ListWorkspaceMembersResponse - 443, // [443:527] is the sub-list for method output_type - 359, // [359:443] is the sub-list for method input_type - 359, // [359:359] is the sub-list for extension type_name - 359, // [359:359] is the sub-list for extension extendee - 0, // [0:359] is the sub-list for field type_name + 294, // 225: openshell.v1.ProviderEnvironmentSnapshot.files:type_name -> openshell.v1.ProviderEnvironmentSnapshot.FilesEntry + 303, // 226: openshell.v1.GetSandboxProviderAccessTokenResponse.expires_after:type_name -> google.protobuf.Duration + 303, // 227: openshell.v1.ExchangeProviderSubjectTokenResponse.expires_after:type_name -> google.protobuf.Duration + 304, // 228: openshell.v1.UpdateConfigRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 301, // 229: openshell.v1.UpdateConfigRequest.policy:type_name -> openshell.sandbox.v1.SandboxPolicy + 309, // 230: openshell.v1.UpdateConfigRequest.setting_value:type_name -> openshell.sandbox.v1.SettingValue + 170, // 231: openshell.v1.UpdateConfigRequest.merge_operations:type_name -> openshell.v1.PolicyMergeOperation + 295, // 232: openshell.v1.UpdateConfigRequest.annotations:type_name -> openshell.v1.UpdateConfigRequest.AnnotationsEntry + 171, // 233: openshell.v1.PolicyMergeOperation.add_rule:type_name -> openshell.v1.AddNetworkRule + 172, // 234: openshell.v1.PolicyMergeOperation.remove_endpoint:type_name -> openshell.v1.RemoveNetworkEndpoint + 173, // 235: openshell.v1.PolicyMergeOperation.remove_rule:type_name -> openshell.v1.RemoveNetworkRule + 175, // 236: openshell.v1.PolicyMergeOperation.add_deny_rules:type_name -> openshell.v1.AddDenyRules + 176, // 237: openshell.v1.PolicyMergeOperation.add_allow_rules:type_name -> openshell.v1.AddAllowRules + 177, // 238: openshell.v1.PolicyMergeOperation.remove_binary:type_name -> openshell.v1.RemoveNetworkBinary + 310, // 239: openshell.v1.AddNetworkRule.rule:type_name -> openshell.sandbox.v1.NetworkPolicyRule + 308, // 240: openshell.v1.L7RuleTarget.binaries:type_name -> openshell.sandbox.v1.NetworkBinary + 311, // 241: openshell.v1.AddDenyRules.deny_rules:type_name -> openshell.sandbox.v1.L7DenyRule + 174, // 242: openshell.v1.AddDenyRules.target:type_name -> openshell.v1.L7RuleTarget + 312, // 243: openshell.v1.AddAllowRules.rules:type_name -> openshell.sandbox.v1.L7Rule + 174, // 244: openshell.v1.AddAllowRules.target:type_name -> openshell.v1.L7RuleTarget + 296, // 245: openshell.v1.UpdateConfigResponse.annotations:type_name -> openshell.v1.UpdateConfigResponse.AnnotationsEntry + 304, // 246: openshell.v1.GetSandboxPolicyStatusRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 188, // 247: openshell.v1.GetSandboxPolicyStatusResponse.revision:type_name -> openshell.v1.SandboxPolicyRevision + 304, // 248: openshell.v1.ListSandboxPoliciesRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 188, // 249: openshell.v1.ListSandboxPoliciesResponse.revisions:type_name -> openshell.v1.SandboxPolicyRevision + 13, // 250: openshell.v1.ReportPolicyStatusRequest.status:type_name -> openshell.v1.PolicyStatus + 12, // 251: openshell.v1.SandboxConfigurationAdmission.state:type_name -> openshell.v1.ConfigurationAdmissionState + 185, // 252: openshell.v1.ReportSandboxConfigurationRequest.admission:type_name -> openshell.v1.SandboxConfigurationAdmission + 13, // 253: openshell.v1.SandboxPolicyRevision.status:type_name -> openshell.v1.PolicyStatus + 299, // 254: openshell.v1.SandboxPolicyRevision.created_time:type_name -> google.protobuf.Timestamp + 299, // 255: openshell.v1.SandboxPolicyRevision.loaded_time:type_name -> google.protobuf.Timestamp + 301, // 256: openshell.v1.SandboxPolicyRevision.policy:type_name -> openshell.sandbox.v1.SandboxPolicy + 297, // 257: openshell.v1.SandboxPolicyRevision.provenance:type_name -> openshell.v1.SandboxPolicyRevision.ProvenanceEntry + 304, // 258: openshell.v1.GetSandboxLogsRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 299, // 259: openshell.v1.GetSandboxLogsRequest.since_time:type_name -> google.protobuf.Timestamp + 113, // 260: openshell.v1.PushSandboxLogsRequest.logs:type_name -> openshell.v1.SandboxLogLine + 113, // 261: openshell.v1.GetSandboxLogsResponse.logs:type_name -> openshell.v1.SandboxLogLine + 195, // 262: openshell.v1.SupervisorMessage.hello:type_name -> openshell.v1.SupervisorHello + 203, // 263: openshell.v1.SupervisorMessage.heartbeat:type_name -> openshell.v1.SupervisorHeartbeat + 220, // 264: openshell.v1.SupervisorMessage.relay_open_result:type_name -> openshell.v1.RelayOpenResult + 221, // 265: openshell.v1.SupervisorMessage.relay_close:type_name -> openshell.v1.RelayClose + 199, // 266: openshell.v1.SupervisorMessage.config_update_result:type_name -> openshell.v1.ConfigUpdateResult + 196, // 267: openshell.v1.GatewayMessage.session_accepted:type_name -> openshell.v1.SessionAccepted + 201, // 268: openshell.v1.GatewayMessage.session_rejected:type_name -> openshell.v1.SessionRejected + 204, // 269: openshell.v1.GatewayMessage.heartbeat:type_name -> openshell.v1.GatewayHeartbeat + 209, // 270: openshell.v1.GatewayMessage.relay_open:type_name -> openshell.v1.RelayOpen + 221, // 271: openshell.v1.GatewayMessage.relay_close:type_name -> openshell.v1.RelayClose + 202, // 272: openshell.v1.GatewayMessage.session_redirect:type_name -> openshell.v1.SessionRedirect + 197, // 273: openshell.v1.GatewayMessage.config_update:type_name -> openshell.v1.ConfigUpdate + 197, // 274: openshell.v1.SessionAccepted.bootstrap:type_name -> openshell.v1.ConfigUpdate + 303, // 275: openshell.v1.SessionAccepted.heartbeat_interval:type_name -> google.protobuf.Duration + 313, // 276: openshell.v1.ConfigUpdate.sandbox_config:type_name -> openshell.sandbox.v1.SandboxConfigSnapshot + 164, // 277: openshell.v1.ConfigUpdate.provider_environment:type_name -> openshell.v1.ProviderEnvironmentSnapshot + 6, // 278: openshell.v1.ConfigUpdateResult.outcome:type_name -> openshell.v1.ConfigApplyOutcome + 198, // 279: openshell.v1.ConfigUpdateResult.failure:type_name -> openshell.v1.ConfigApplyFailure + 185, // 280: openshell.v1.ConfigUpdateResult.admission:type_name -> openshell.v1.SandboxConfigurationAdmission + 200, // 281: openshell.v1.ConfigUpdateResult.policy_load:type_name -> openshell.v1.PolicyLoadResult + 210, // 282: openshell.v1.RelayOpen.ssh:type_name -> openshell.v1.SshRelayTarget + 211, // 283: openshell.v1.RelayOpen.tcp:type_name -> openshell.v1.TcpRelayTarget + 212, // 284: openshell.v1.RelayFrame.init:type_name -> openshell.v1.RelayInit + 209, // 285: openshell.v1.PeerRelayInit.relay_open:type_name -> openshell.v1.RelayOpen + 214, // 286: openshell.v1.PeerRelayFrame.init:type_name -> openshell.v1.PeerRelayInit + 216, // 287: openshell.v1.PeerNotifyConfigUpdateRequest.sandbox:type_name -> openshell.v1.PeerConfigSandboxTarget + 217, // 288: openshell.v1.PeerNotifyConfigUpdateRequest.provider:type_name -> openshell.v1.PeerConfigProviderTarget + 299, // 289: openshell.v1.DenialSummary.first_seen_time:type_name -> google.protobuf.Timestamp + 299, // 290: openshell.v1.DenialSummary.last_seen_time:type_name -> google.protobuf.Timestamp + 222, // 291: openshell.v1.DenialSummary.l7_request_samples:type_name -> openshell.v1.L7RequestSample + 224, // 292: openshell.v1.NetworkActivitySummary.denials_by_group:type_name -> openshell.v1.DenialGroupCount + 310, // 293: openshell.v1.PolicyChunk.proposed_rule:type_name -> openshell.sandbox.v1.NetworkPolicyRule + 299, // 294: openshell.v1.PolicyChunk.created_time:type_name -> google.protobuf.Timestamp + 299, // 295: openshell.v1.PolicyChunk.decided_time:type_name -> google.protobuf.Timestamp + 299, // 296: openshell.v1.PolicyChunk.first_seen_time:type_name -> google.protobuf.Timestamp + 299, // 297: openshell.v1.PolicyChunk.last_seen_time:type_name -> google.protobuf.Timestamp + 301, // 298: openshell.v1.PolicyChunk.current_effective_policy:type_name -> openshell.sandbox.v1.SandboxPolicy + 301, // 299: openshell.v1.PolicyChunk.candidate_effective_policy:type_name -> openshell.sandbox.v1.SandboxPolicy + 304, // 300: openshell.v1.SubmitPolicyAnalysisRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 223, // 301: openshell.v1.SubmitPolicyAnalysisRequest.summaries:type_name -> openshell.v1.DenialSummary + 226, // 302: openshell.v1.SubmitPolicyAnalysisRequest.proposed_chunks:type_name -> openshell.v1.PolicyChunk + 225, // 303: openshell.v1.SubmitPolicyAnalysisRequest.network_activity_summaries:type_name -> openshell.v1.NetworkActivitySummary + 304, // 304: openshell.v1.GetDraftPolicyRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 226, // 305: openshell.v1.GetDraftPolicyResponse.chunks:type_name -> openshell.v1.PolicyChunk + 299, // 306: openshell.v1.GetDraftPolicyResponse.last_analyzed_time:type_name -> google.protobuf.Timestamp + 304, // 307: openshell.v1.ApproveDraftChunkRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 304, // 308: openshell.v1.RejectDraftChunkRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 304, // 309: openshell.v1.ApproveAllDraftChunksRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 236, // 310: openshell.v1.ApproveAllDraftChunksRequest.approvals:type_name -> openshell.v1.DraftChunkApproval + 304, // 311: openshell.v1.EditDraftChunkRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 310, // 312: openshell.v1.EditDraftChunkRequest.proposed_rule:type_name -> openshell.sandbox.v1.NetworkPolicyRule + 304, // 313: openshell.v1.UndoDraftChunkRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 304, // 314: openshell.v1.ClearDraftChunksRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 304, // 315: openshell.v1.GetDraftHistoryRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 299, // 316: openshell.v1.DraftHistoryEntry.event_time:type_name -> google.protobuf.Timestamp + 246, // 317: openshell.v1.GetDraftHistoryResponse.entries:type_name -> openshell.v1.DraftHistoryEntry + 298, // 318: openshell.v1.CreateWorkspaceRequest.labels:type_name -> openshell.v1.CreateWorkspaceRequest.LabelsEntry + 314, // 319: openshell.v1.CreateWorkspaceResponse.workspace:type_name -> openshell.datamodel.v1.Workspace + 314, // 320: openshell.v1.GetWorkspaceResponse.workspace:type_name -> openshell.datamodel.v1.Workspace + 314, // 321: openshell.v1.ListWorkspacesResponse.workspaces:type_name -> openshell.datamodel.v1.Workspace + 18, // 322: openshell.v1.DeleteWorkspaceResponse.outcome:type_name -> openshell.v1.DeletionOutcome + 300, // 323: openshell.v1.WorkspaceMember.metadata:type_name -> openshell.datamodel.v1.ObjectMeta + 15, // 324: openshell.v1.WorkspaceMember.role:type_name -> openshell.v1.WorkspaceRole + 304, // 325: openshell.v1.AddWorkspaceMemberRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 15, // 326: openshell.v1.AddWorkspaceMemberRequest.role:type_name -> openshell.v1.WorkspaceRole + 256, // 327: openshell.v1.AddWorkspaceMemberResponse.member:type_name -> openshell.v1.WorkspaceMember + 304, // 328: openshell.v1.RemoveWorkspaceMemberRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 18, // 329: openshell.v1.RemoveWorkspaceMemberResponse.outcome:type_name -> openshell.v1.DeletionOutcome + 304, // 330: openshell.v1.ListWorkspaceMembersRequest.workspace_scope:type_name -> openshell.datamodel.v1.WorkspaceSelector + 256, // 331: openshell.v1.ListWorkspaceMembersResponse.members:type_name -> openshell.v1.WorkspaceMember + 299, // 332: openshell.v1.ExtensionServiceCredential.expiration_time:type_name -> google.protobuf.Timestamp + 19, // 333: openshell.v1.EndpointObservation.result:type_name -> openshell.v1.EndpointResult + 272, // 334: openshell.v1.EndpointObservation.failure:type_name -> openshell.v1.EndpointFailure + 264, // 335: openshell.v1.ReportEndpointStatusRequest.observations:type_name -> openshell.v1.EndpointObservation + 266, // 336: openshell.v1.ReportEndpointStatusRequest.token_grant_status:type_name -> openshell.v1.TokenGrantStatus + 267, // 337: openshell.v1.TokenGrantStatus.last_failure:type_name -> openshell.v1.TokenGrantFailureObservation + 272, // 338: openshell.v1.TokenGrantFailureObservation.failure:type_name -> openshell.v1.EndpointFailure + 19, // 339: openshell.v1.EndpointStatus.last_result:type_name -> openshell.v1.EndpointResult + 299, // 340: openshell.v1.EndpointStatus.last_reported_time:type_name -> google.protobuf.Timestamp + 272, // 341: openshell.v1.EndpointStatus.last_failure:type_name -> openshell.v1.EndpointFailure + 299, // 342: openshell.v1.SandboxProvisioning.configuration_change_time:type_name -> google.protobuf.Timestamp + 299, // 343: openshell.v1.SandboxProvisioning.first_rejection_time:type_name -> google.protobuf.Timestamp + 299, // 344: openshell.v1.SandboxProvisioning.deadline:type_name -> google.protobuf.Timestamp + 299, // 345: openshell.v1.SandboxProvisioning.timeout_time:type_name -> google.protobuf.Timestamp + 299, // 346: openshell.v1.SandboxProvisioning.cleanup_completed_time:type_name -> google.protobuf.Timestamp + 299, // 347: openshell.v1.SandboxProvisioning.cleanup_retry_time:type_name -> google.protobuf.Timestamp + 299, // 348: openshell.v1.SandboxProvisioning.attachment_change_time:type_name -> google.protobuf.Timestamp + 299, // 349: openshell.v1.SandboxProvisioning.preparation_deadline:type_name -> google.protobuf.Timestamp + 299, // 350: openshell.v1.SandboxProvisioning.admission_start_time:type_name -> google.protobuf.Timestamp + 20, // 351: openshell.v1.SandboxServiceExposure.authorization_mode:type_name -> openshell.v1.ServiceAuthorizationMode + 21, // 352: openshell.v1.EndpointFailure.domain:type_name -> openshell.v1.EndpointFailureDomain + 16, // 353: openshell.v1.EndpointFailure.recovery_action:type_name -> openshell.v1.ProviderCredentialRefreshRecoveryAction + 118, // 354: openshell.v1.GetProviderCredentialsResponse.CredentialsEntry.value:type_name -> openshell.v1.ProviderCredentialValue + 299, // 355: openshell.v1.UpdateProviderRequest.CredentialExpirationTimesEntry.value:type_name -> google.protobuf.Timestamp + 299, // 356: openshell.v1.GetSandboxProviderEnvironmentResponse.CredentialExpirationTimesEntry.value:type_name -> google.protobuf.Timestamp + 132, // 357: openshell.v1.GetSandboxProviderEnvironmentResponse.DynamicCredentialsEntry.value:type_name -> openshell.v1.ProviderProfileCredential + 161, // 358: openshell.v1.GetSandboxProviderEnvironmentResponse.StaticCredentialBindingsEntry.value:type_name -> openshell.v1.StaticCredentialBinding + 132, // 359: openshell.v1.ProviderEnvironmentSnapshot.DynamicCredentialsEntry.value:type_name -> openshell.v1.ProviderProfileCredential + 26, // 360: openshell.v1.OpenShell.Health:input_type -> openshell.v1.HealthRequest + 28, // 361: openshell.v1.OpenShell.GetCurrentUser:input_type -> openshell.v1.GetCurrentUserRequest + 30, // 362: openshell.v1.OpenShell.GetGatewayInfo:input_type -> openshell.v1.GetGatewayInfoRequest + 54, // 363: openshell.v1.OpenShell.CreateSandbox:input_type -> openshell.v1.CreateSandboxRequest + 62, // 364: openshell.v1.OpenShell.BeginRootfsTarStaging:input_type -> openshell.v1.BeginRootfsTarStagingRequest + 64, // 365: openshell.v1.OpenShell.GetSandbox:input_type -> openshell.v1.GetSandboxRequest + 65, // 366: openshell.v1.OpenShell.ListSandboxes:input_type -> openshell.v1.ListSandboxesRequest + 55, // 367: openshell.v1.OpenShell.CreateSandboxTemplate:input_type -> openshell.v1.CreateSandboxTemplateRequest + 56, // 368: openshell.v1.OpenShell.GetSandboxTemplate:input_type -> openshell.v1.GetSandboxTemplateRequest + 57, // 369: openshell.v1.OpenShell.ListSandboxTemplates:input_type -> openshell.v1.ListSandboxTemplatesRequest + 58, // 370: openshell.v1.OpenShell.DeleteSandboxTemplate:input_type -> openshell.v1.DeleteSandboxTemplateRequest + 66, // 371: openshell.v1.OpenShell.ListSandboxProviders:input_type -> openshell.v1.ListSandboxProvidersRequest + 67, // 372: openshell.v1.OpenShell.AttachSandboxProvider:input_type -> openshell.v1.AttachSandboxProviderRequest + 68, // 373: openshell.v1.OpenShell.DetachSandboxProvider:input_type -> openshell.v1.DetachSandboxProviderRequest + 84, // 374: openshell.v1.OpenShell.GetSandboxProviderStatus:input_type -> openshell.v1.GetSandboxProviderStatusRequest + 69, // 375: openshell.v1.OpenShell.DeleteSandbox:input_type -> openshell.v1.DeleteSandboxRequest + 70, // 376: openshell.v1.OpenShell.StopSandbox:input_type -> openshell.v1.StopSandboxRequest + 71, // 377: openshell.v1.OpenShell.StartSandbox:input_type -> openshell.v1.StartSandboxRequest + 89, // 378: openshell.v1.OpenShell.CreateSshSession:input_type -> openshell.v1.CreateSshSessionRequest + 91, // 379: openshell.v1.OpenShell.ExposeService:input_type -> openshell.v1.ExposeServiceRequest + 92, // 380: openshell.v1.OpenShell.GetService:input_type -> openshell.v1.GetServiceRequest + 93, // 381: openshell.v1.OpenShell.ListServices:input_type -> openshell.v1.ListServicesRequest + 95, // 382: openshell.v1.OpenShell.DeleteService:input_type -> openshell.v1.DeleteServiceRequest + 99, // 383: openshell.v1.OpenShell.RevokeSshSession:input_type -> openshell.v1.RevokeSshSessionRequest + 101, // 384: openshell.v1.OpenShell.ExecSandbox:input_type -> openshell.v1.ExecSandboxRequest + 107, // 385: openshell.v1.OpenShell.ForwardTcp:input_type -> openshell.v1.TcpForwardFrame + 108, // 386: openshell.v1.OpenShell.ExecSandboxInteractive:input_type -> openshell.v1.ExecSandboxInput + 115, // 387: openshell.v1.OpenShell.CreateProvider:input_type -> openshell.v1.CreateProviderRequest + 116, // 388: openshell.v1.OpenShell.GetProvider:input_type -> openshell.v1.GetProviderRequest + 117, // 389: openshell.v1.OpenShell.GetProviderCredentials:input_type -> openshell.v1.GetProviderCredentialsRequest + 120, // 390: openshell.v1.OpenShell.ListProviders:input_type -> openshell.v1.ListProvidersRequest + 125, // 391: openshell.v1.OpenShell.ListProviderProfiles:input_type -> openshell.v1.ListProviderProfilesRequest + 126, // 392: openshell.v1.OpenShell.GetProviderProfile:input_type -> openshell.v1.GetProviderProfileRequest + 150, // 393: openshell.v1.OpenShell.ImportProviderProfiles:input_type -> openshell.v1.ImportProviderProfilesRequest + 152, // 394: openshell.v1.OpenShell.UpdateProviderProfiles:input_type -> openshell.v1.UpdateProviderProfilesRequest + 154, // 395: openshell.v1.OpenShell.LintProviderProfiles:input_type -> openshell.v1.LintProviderProfilesRequest + 121, // 396: openshell.v1.OpenShell.UpdateProvider:input_type -> openshell.v1.UpdateProviderRequest + 138, // 397: openshell.v1.OpenShell.GetProviderRefreshStatus:input_type -> openshell.v1.GetProviderRefreshStatusRequest + 140, // 398: openshell.v1.OpenShell.ConfigureProviderRefresh:input_type -> openshell.v1.ConfigureProviderRefreshRequest + 142, // 399: openshell.v1.OpenShell.RotateProviderCredential:input_type -> openshell.v1.RotateProviderCredentialRequest + 144, // 400: openshell.v1.OpenShell.DeleteProviderRefresh:input_type -> openshell.v1.DeleteProviderRefreshRequest + 122, // 401: openshell.v1.OpenShell.DeleteProvider:input_type -> openshell.v1.DeleteProviderRequest + 157, // 402: openshell.v1.OpenShell.DeleteProviderProfile:input_type -> openshell.v1.DeleteProviderProfileRequest + 315, // 403: openshell.v1.OpenShell.GetSandboxConfig:input_type -> openshell.sandbox.v1.GetSandboxConfigRequest + 316, // 404: openshell.v1.OpenShell.GetGatewayConfig:input_type -> openshell.sandbox.v1.GetGatewayConfigRequest + 169, // 405: openshell.v1.OpenShell.UpdateConfig:input_type -> openshell.v1.UpdateConfigRequest + 179, // 406: openshell.v1.OpenShell.GetSandboxPolicyStatus:input_type -> openshell.v1.GetSandboxPolicyStatusRequest + 181, // 407: openshell.v1.OpenShell.ListSandboxPolicies:input_type -> openshell.v1.ListSandboxPoliciesRequest + 183, // 408: openshell.v1.OpenShell.ReportPolicyStatus:input_type -> openshell.v1.ReportPolicyStatusRequest + 265, // 409: openshell.v1.OpenShell.ReportEndpointStatus:input_type -> openshell.v1.ReportEndpointStatusRequest + 86, // 410: openshell.v1.OpenShell.ReportProviderReadiness:input_type -> openshell.v1.ReportProviderReadinessRequest + 186, // 411: openshell.v1.OpenShell.ReportSandboxConfiguration:input_type -> openshell.v1.ReportSandboxConfigurationRequest + 159, // 412: openshell.v1.OpenShell.GetSandboxProviderEnvironment:input_type -> openshell.v1.GetSandboxProviderEnvironmentRequest + 167, // 413: openshell.v1.OpenShell.ExchangeProviderSubjectToken:input_type -> openshell.v1.ExchangeProviderSubjectTokenRequest + 165, // 414: openshell.v1.OpenShell.GetSandboxProviderAccessToken:input_type -> openshell.v1.GetSandboxProviderAccessTokenRequest + 189, // 415: openshell.v1.OpenShell.GetSandboxLogs:input_type -> openshell.v1.GetSandboxLogsRequest + 190, // 416: openshell.v1.OpenShell.PushSandboxLogs:input_type -> openshell.v1.PushSandboxLogsRequest + 193, // 417: openshell.v1.OpenShell.ConnectSupervisor:input_type -> openshell.v1.SupervisorMessage + 205, // 418: openshell.v1.OpenShell.ReportMainProcessExit:input_type -> openshell.v1.ReportMainProcessExitRequest + 207, // 419: openshell.v1.OpenShell.FinalizeMainProcessExit:input_type -> openshell.v1.FinalizeMainProcessExitRequest + 213, // 420: openshell.v1.OpenShell.RelayStream:input_type -> openshell.v1.RelayFrame + 215, // 421: openshell.v1.OpenShell.PeerRelay:input_type -> openshell.v1.PeerRelayFrame + 86, // 422: openshell.v1.OpenShell.PeerReportProviderReadiness:input_type -> openshell.v1.ReportProviderReadinessRequest + 265, // 423: openshell.v1.OpenShell.PeerReportEndpointStatus:input_type -> openshell.v1.ReportEndpointStatusRequest + 84, // 424: openshell.v1.OpenShell.PeerGetSandboxProviderStatus:input_type -> openshell.v1.GetSandboxProviderStatusRequest + 218, // 425: openshell.v1.OpenShell.PeerNotifyConfigUpdate:input_type -> openshell.v1.PeerNotifyConfigUpdateRequest + 111, // 426: openshell.v1.OpenShell.WatchSandbox:input_type -> openshell.v1.WatchSandboxRequest + 228, // 427: openshell.v1.OpenShell.SubmitPolicyAnalysis:input_type -> openshell.v1.SubmitPolicyAnalysisRequest + 230, // 428: openshell.v1.OpenShell.GetDraftPolicy:input_type -> openshell.v1.GetDraftPolicyRequest + 232, // 429: openshell.v1.OpenShell.ApproveDraftChunk:input_type -> openshell.v1.ApproveDraftChunkRequest + 234, // 430: openshell.v1.OpenShell.RejectDraftChunk:input_type -> openshell.v1.RejectDraftChunkRequest + 237, // 431: openshell.v1.OpenShell.ApproveAllDraftChunks:input_type -> openshell.v1.ApproveAllDraftChunksRequest + 239, // 432: openshell.v1.OpenShell.EditDraftChunk:input_type -> openshell.v1.EditDraftChunkRequest + 241, // 433: openshell.v1.OpenShell.UndoDraftChunk:input_type -> openshell.v1.UndoDraftChunkRequest + 243, // 434: openshell.v1.OpenShell.ClearDraftChunks:input_type -> openshell.v1.ClearDraftChunksRequest + 245, // 435: openshell.v1.OpenShell.GetDraftHistory:input_type -> openshell.v1.GetDraftHistoryRequest + 22, // 436: openshell.v1.OpenShell.IssueSandboxToken:input_type -> openshell.v1.IssueSandboxTokenRequest + 24, // 437: openshell.v1.OpenShell.RefreshSandboxToken:input_type -> openshell.v1.RefreshSandboxTokenRequest + 248, // 438: openshell.v1.OpenShell.CreateWorkspace:input_type -> openshell.v1.CreateWorkspaceRequest + 250, // 439: openshell.v1.OpenShell.GetWorkspace:input_type -> openshell.v1.GetWorkspaceRequest + 252, // 440: openshell.v1.OpenShell.ListWorkspaces:input_type -> openshell.v1.ListWorkspacesRequest + 254, // 441: openshell.v1.OpenShell.DeleteWorkspace:input_type -> openshell.v1.DeleteWorkspaceRequest + 257, // 442: openshell.v1.OpenShell.AddWorkspaceMember:input_type -> openshell.v1.AddWorkspaceMemberRequest + 259, // 443: openshell.v1.OpenShell.RemoveWorkspaceMember:input_type -> openshell.v1.RemoveWorkspaceMemberRequest + 261, // 444: openshell.v1.OpenShell.ListWorkspaceMembers:input_type -> openshell.v1.ListWorkspaceMembersRequest + 27, // 445: openshell.v1.OpenShell.Health:output_type -> openshell.v1.HealthResponse + 29, // 446: openshell.v1.OpenShell.GetCurrentUser:output_type -> openshell.v1.GetCurrentUserResponse + 31, // 447: openshell.v1.OpenShell.GetGatewayInfo:output_type -> openshell.v1.GetGatewayInfoResponse + 72, // 448: openshell.v1.OpenShell.CreateSandbox:output_type -> openshell.v1.SandboxResponse + 63, // 449: openshell.v1.OpenShell.BeginRootfsTarStaging:output_type -> openshell.v1.BeginRootfsTarStagingResponse + 72, // 450: openshell.v1.OpenShell.GetSandbox:output_type -> openshell.v1.SandboxResponse + 73, // 451: openshell.v1.OpenShell.ListSandboxes:output_type -> openshell.v1.ListSandboxesResponse + 59, // 452: openshell.v1.OpenShell.CreateSandboxTemplate:output_type -> openshell.v1.SandboxTemplateResponse + 59, // 453: openshell.v1.OpenShell.GetSandboxTemplate:output_type -> openshell.v1.SandboxTemplateResponse + 60, // 454: openshell.v1.OpenShell.ListSandboxTemplates:output_type -> openshell.v1.ListSandboxTemplatesResponse + 61, // 455: openshell.v1.OpenShell.DeleteSandboxTemplate:output_type -> openshell.v1.DeleteSandboxTemplateResponse + 74, // 456: openshell.v1.OpenShell.ListSandboxProviders:output_type -> openshell.v1.ListSandboxProvidersResponse + 75, // 457: openshell.v1.OpenShell.AttachSandboxProvider:output_type -> openshell.v1.AttachSandboxProviderResponse + 76, // 458: openshell.v1.OpenShell.DetachSandboxProvider:output_type -> openshell.v1.DetachSandboxProviderResponse + 85, // 459: openshell.v1.OpenShell.GetSandboxProviderStatus:output_type -> openshell.v1.GetSandboxProviderStatusResponse + 88, // 460: openshell.v1.OpenShell.DeleteSandbox:output_type -> openshell.v1.DeleteSandboxResponse + 72, // 461: openshell.v1.OpenShell.StopSandbox:output_type -> openshell.v1.SandboxResponse + 72, // 462: openshell.v1.OpenShell.StartSandbox:output_type -> openshell.v1.SandboxResponse + 90, // 463: openshell.v1.OpenShell.CreateSshSession:output_type -> openshell.v1.CreateSshSessionResponse + 98, // 464: openshell.v1.OpenShell.ExposeService:output_type -> openshell.v1.ServiceEndpointResponse + 98, // 465: openshell.v1.OpenShell.GetService:output_type -> openshell.v1.ServiceEndpointResponse + 94, // 466: openshell.v1.OpenShell.ListServices:output_type -> openshell.v1.ListServicesResponse + 96, // 467: openshell.v1.OpenShell.DeleteService:output_type -> openshell.v1.DeleteServiceResponse + 100, // 468: openshell.v1.OpenShell.RevokeSshSession:output_type -> openshell.v1.RevokeSshSessionResponse + 105, // 469: openshell.v1.OpenShell.ExecSandbox:output_type -> openshell.v1.ExecSandboxEvent + 107, // 470: openshell.v1.OpenShell.ForwardTcp:output_type -> openshell.v1.TcpForwardFrame + 105, // 471: openshell.v1.OpenShell.ExecSandboxInteractive:output_type -> openshell.v1.ExecSandboxEvent + 123, // 472: openshell.v1.OpenShell.CreateProvider:output_type -> openshell.v1.ProviderResponse + 123, // 473: openshell.v1.OpenShell.GetProvider:output_type -> openshell.v1.ProviderResponse + 119, // 474: openshell.v1.OpenShell.GetProviderCredentials:output_type -> openshell.v1.GetProviderCredentialsResponse + 124, // 475: openshell.v1.OpenShell.ListProviders:output_type -> openshell.v1.ListProvidersResponse + 149, // 476: openshell.v1.OpenShell.ListProviderProfiles:output_type -> openshell.v1.ListProviderProfilesResponse + 148, // 477: openshell.v1.OpenShell.GetProviderProfile:output_type -> openshell.v1.ProviderProfileResponse + 151, // 478: openshell.v1.OpenShell.ImportProviderProfiles:output_type -> openshell.v1.ImportProviderProfilesResponse + 153, // 479: openshell.v1.OpenShell.UpdateProviderProfiles:output_type -> openshell.v1.UpdateProviderProfilesResponse + 155, // 480: openshell.v1.OpenShell.LintProviderProfiles:output_type -> openshell.v1.LintProviderProfilesResponse + 123, // 481: openshell.v1.OpenShell.UpdateProvider:output_type -> openshell.v1.ProviderResponse + 139, // 482: openshell.v1.OpenShell.GetProviderRefreshStatus:output_type -> openshell.v1.GetProviderRefreshStatusResponse + 141, // 483: openshell.v1.OpenShell.ConfigureProviderRefresh:output_type -> openshell.v1.ConfigureProviderRefreshResponse + 143, // 484: openshell.v1.OpenShell.RotateProviderCredential:output_type -> openshell.v1.RotateProviderCredentialResponse + 145, // 485: openshell.v1.OpenShell.DeleteProviderRefresh:output_type -> openshell.v1.DeleteProviderRefreshResponse + 156, // 486: openshell.v1.OpenShell.DeleteProvider:output_type -> openshell.v1.DeleteProviderResponse + 158, // 487: openshell.v1.OpenShell.DeleteProviderProfile:output_type -> openshell.v1.DeleteProviderProfileResponse + 317, // 488: openshell.v1.OpenShell.GetSandboxConfig:output_type -> openshell.sandbox.v1.GetSandboxConfigResponse + 318, // 489: openshell.v1.OpenShell.GetGatewayConfig:output_type -> openshell.sandbox.v1.GetGatewayConfigResponse + 178, // 490: openshell.v1.OpenShell.UpdateConfig:output_type -> openshell.v1.UpdateConfigResponse + 180, // 491: openshell.v1.OpenShell.GetSandboxPolicyStatus:output_type -> openshell.v1.GetSandboxPolicyStatusResponse + 182, // 492: openshell.v1.OpenShell.ListSandboxPolicies:output_type -> openshell.v1.ListSandboxPoliciesResponse + 184, // 493: openshell.v1.OpenShell.ReportPolicyStatus:output_type -> openshell.v1.ReportPolicyStatusResponse + 268, // 494: openshell.v1.OpenShell.ReportEndpointStatus:output_type -> openshell.v1.ReportEndpointStatusResponse + 87, // 495: openshell.v1.OpenShell.ReportProviderReadiness:output_type -> openshell.v1.ReportProviderReadinessResponse + 187, // 496: openshell.v1.OpenShell.ReportSandboxConfiguration:output_type -> openshell.v1.ReportSandboxConfigurationResponse + 162, // 497: openshell.v1.OpenShell.GetSandboxProviderEnvironment:output_type -> openshell.v1.GetSandboxProviderEnvironmentResponse + 168, // 498: openshell.v1.OpenShell.ExchangeProviderSubjectToken:output_type -> openshell.v1.ExchangeProviderSubjectTokenResponse + 166, // 499: openshell.v1.OpenShell.GetSandboxProviderAccessToken:output_type -> openshell.v1.GetSandboxProviderAccessTokenResponse + 192, // 500: openshell.v1.OpenShell.GetSandboxLogs:output_type -> openshell.v1.GetSandboxLogsResponse + 191, // 501: openshell.v1.OpenShell.PushSandboxLogs:output_type -> openshell.v1.PushSandboxLogsResponse + 194, // 502: openshell.v1.OpenShell.ConnectSupervisor:output_type -> openshell.v1.GatewayMessage + 206, // 503: openshell.v1.OpenShell.ReportMainProcessExit:output_type -> openshell.v1.ReportMainProcessExitResponse + 208, // 504: openshell.v1.OpenShell.FinalizeMainProcessExit:output_type -> openshell.v1.FinalizeMainProcessExitResponse + 213, // 505: openshell.v1.OpenShell.RelayStream:output_type -> openshell.v1.RelayFrame + 215, // 506: openshell.v1.OpenShell.PeerRelay:output_type -> openshell.v1.PeerRelayFrame + 87, // 507: openshell.v1.OpenShell.PeerReportProviderReadiness:output_type -> openshell.v1.ReportProviderReadinessResponse + 268, // 508: openshell.v1.OpenShell.PeerReportEndpointStatus:output_type -> openshell.v1.ReportEndpointStatusResponse + 85, // 509: openshell.v1.OpenShell.PeerGetSandboxProviderStatus:output_type -> openshell.v1.GetSandboxProviderStatusResponse + 219, // 510: openshell.v1.OpenShell.PeerNotifyConfigUpdate:output_type -> openshell.v1.PeerNotifyConfigUpdateResponse + 112, // 511: openshell.v1.OpenShell.WatchSandbox:output_type -> openshell.v1.SandboxStreamEvent + 229, // 512: openshell.v1.OpenShell.SubmitPolicyAnalysis:output_type -> openshell.v1.SubmitPolicyAnalysisResponse + 231, // 513: openshell.v1.OpenShell.GetDraftPolicy:output_type -> openshell.v1.GetDraftPolicyResponse + 233, // 514: openshell.v1.OpenShell.ApproveDraftChunk:output_type -> openshell.v1.ApproveDraftChunkResponse + 235, // 515: openshell.v1.OpenShell.RejectDraftChunk:output_type -> openshell.v1.RejectDraftChunkResponse + 238, // 516: openshell.v1.OpenShell.ApproveAllDraftChunks:output_type -> openshell.v1.ApproveAllDraftChunksResponse + 240, // 517: openshell.v1.OpenShell.EditDraftChunk:output_type -> openshell.v1.EditDraftChunkResponse + 242, // 518: openshell.v1.OpenShell.UndoDraftChunk:output_type -> openshell.v1.UndoDraftChunkResponse + 244, // 519: openshell.v1.OpenShell.ClearDraftChunks:output_type -> openshell.v1.ClearDraftChunksResponse + 247, // 520: openshell.v1.OpenShell.GetDraftHistory:output_type -> openshell.v1.GetDraftHistoryResponse + 23, // 521: openshell.v1.OpenShell.IssueSandboxToken:output_type -> openshell.v1.IssueSandboxTokenResponse + 25, // 522: openshell.v1.OpenShell.RefreshSandboxToken:output_type -> openshell.v1.RefreshSandboxTokenResponse + 249, // 523: openshell.v1.OpenShell.CreateWorkspace:output_type -> openshell.v1.CreateWorkspaceResponse + 251, // 524: openshell.v1.OpenShell.GetWorkspace:output_type -> openshell.v1.GetWorkspaceResponse + 253, // 525: openshell.v1.OpenShell.ListWorkspaces:output_type -> openshell.v1.ListWorkspacesResponse + 255, // 526: openshell.v1.OpenShell.DeleteWorkspace:output_type -> openshell.v1.DeleteWorkspaceResponse + 258, // 527: openshell.v1.OpenShell.AddWorkspaceMember:output_type -> openshell.v1.AddWorkspaceMemberResponse + 260, // 528: openshell.v1.OpenShell.RemoveWorkspaceMember:output_type -> openshell.v1.RemoveWorkspaceMemberResponse + 262, // 529: openshell.v1.OpenShell.ListWorkspaceMembers:output_type -> openshell.v1.ListWorkspaceMembersResponse + 445, // [445:530] is the sub-list for method output_type + 360, // [360:445] is the sub-list for method input_type + 360, // [360:360] is the sub-list for extension type_name + 360, // [360:360] is the sub-list for extension extendee + 0, // [0:360] is the sub-list for field type_name } func init() { file_openshell_proto_init() } @@ -22094,7 +22215,7 @@ func file_openshell_proto_init() { (*SandboxStreamEvent_Warning)(nil), (*SandboxStreamEvent_DraftPolicyUpdate)(nil), } - file_openshell_proto_msgTypes[146].OneofWrappers = []any{ + file_openshell_proto_msgTypes[148].OneofWrappers = []any{ (*PolicyMergeOperation_AddRule)(nil), (*PolicyMergeOperation_RemoveEndpoint)(nil), (*PolicyMergeOperation_RemoveRule)(nil), @@ -22102,15 +22223,15 @@ func file_openshell_proto_init() { (*PolicyMergeOperation_AddAllowRules)(nil), (*PolicyMergeOperation_RemoveBinary)(nil), } - file_openshell_proto_msgTypes[150].OneofWrappers = []any{} - file_openshell_proto_msgTypes[169].OneofWrappers = []any{ + file_openshell_proto_msgTypes[152].OneofWrappers = []any{} + file_openshell_proto_msgTypes[171].OneofWrappers = []any{ (*SupervisorMessage_Hello)(nil), (*SupervisorMessage_Heartbeat)(nil), (*SupervisorMessage_RelayOpenResult)(nil), (*SupervisorMessage_RelayClose)(nil), (*SupervisorMessage_ConfigUpdateResult)(nil), } - file_openshell_proto_msgTypes[170].OneofWrappers = []any{ + file_openshell_proto_msgTypes[172].OneofWrappers = []any{ (*GatewayMessage_SessionAccepted)(nil), (*GatewayMessage_SessionRejected)(nil), (*GatewayMessage_Heartbeat)(nil), @@ -22119,32 +22240,32 @@ func file_openshell_proto_init() { (*GatewayMessage_SessionRedirect)(nil), (*GatewayMessage_ConfigUpdate)(nil), } - file_openshell_proto_msgTypes[185].OneofWrappers = []any{ + file_openshell_proto_msgTypes[187].OneofWrappers = []any{ (*RelayOpen_Ssh)(nil), (*RelayOpen_Tcp)(nil), } - file_openshell_proto_msgTypes[189].OneofWrappers = []any{ + file_openshell_proto_msgTypes[191].OneofWrappers = []any{ (*RelayFrame_Init)(nil), (*RelayFrame_Data)(nil), } - file_openshell_proto_msgTypes[191].OneofWrappers = []any{ + file_openshell_proto_msgTypes[193].OneofWrappers = []any{ (*PeerRelayFrame_Init)(nil), (*PeerRelayFrame_Data)(nil), } - file_openshell_proto_msgTypes[194].OneofWrappers = []any{ + file_openshell_proto_msgTypes[196].OneofWrappers = []any{ (*PeerNotifyConfigUpdateRequest_Sandbox)(nil), (*PeerNotifyConfigUpdateRequest_Workspace)(nil), (*PeerNotifyConfigUpdateRequest_AllConnected)(nil), (*PeerNotifyConfigUpdateRequest_Provider)(nil), } - file_openshell_proto_msgTypes[248].OneofWrappers = []any{} + file_openshell_proto_msgTypes[250].OneofWrappers = []any{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_openshell_proto_rawDesc), len(file_openshell_proto_rawDesc)), NumEnums: 22, - NumMessages: 275, + NumMessages: 277, NumExtensions: 0, NumServices: 1, }, diff --git a/sdk/go/proto/openshellv1/openshell_grpc.pb.go b/sdk/go/proto/openshellv1/openshell_grpc.pb.go index 57f17c466b..16cc664780 100644 --- a/sdk/go/proto/openshellv1/openshell_grpc.pb.go +++ b/sdk/go/proto/openshellv1/openshell_grpc.pb.go @@ -77,6 +77,7 @@ const ( OpenShell_ReportSandboxConfiguration_FullMethodName = "/openshell.v1.OpenShell/ReportSandboxConfiguration" OpenShell_GetSandboxProviderEnvironment_FullMethodName = "/openshell.v1.OpenShell/GetSandboxProviderEnvironment" OpenShell_ExchangeProviderSubjectToken_FullMethodName = "/openshell.v1.OpenShell/ExchangeProviderSubjectToken" + OpenShell_GetSandboxProviderAccessToken_FullMethodName = "/openshell.v1.OpenShell/GetSandboxProviderAccessToken" OpenShell_GetSandboxLogs_FullMethodName = "/openshell.v1.OpenShell/GetSandboxLogs" OpenShell_PushSandboxLogs_FullMethodName = "/openshell.v1.OpenShell/PushSandboxLogs" OpenShell_ConnectSupervisor_FullMethodName = "/openshell.v1.OpenShell/ConnectSupervisor" @@ -252,6 +253,9 @@ type OpenShellClient interface { // Exchange a stored provider subject token for an intermediate token scoped // to the calling supervisor's SPIFFE identity. ExchangeProviderSubjectToken(ctx context.Context, in *ExchangeProviderSubjectTokenRequest, opts ...grpc.CallOption) (*ExchangeProviderSubjectTokenResponse, error) + // Obtain the final provider token for the authenticated sandbox session. + // SPIFFE assertions and intermediate credentials remain in the gateway. + GetSandboxProviderAccessToken(ctx context.Context, in *GetSandboxProviderAccessTokenRequest, opts ...grpc.CallOption) (*GetSandboxProviderAccessTokenResponse, error) // Fetch recent sandbox logs (one-shot). GetSandboxLogs(ctx context.Context, in *GetSandboxLogsRequest, opts ...grpc.CallOption) (*GetSandboxLogsResponse, error) // Push sandbox supervisor logs to the server (client-streaming). @@ -914,6 +918,16 @@ func (c *openShellClient) ExchangeProviderSubjectToken(ctx context.Context, in * return out, nil } +func (c *openShellClient) GetSandboxProviderAccessToken(ctx context.Context, in *GetSandboxProviderAccessTokenRequest, opts ...grpc.CallOption) (*GetSandboxProviderAccessTokenResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetSandboxProviderAccessTokenResponse) + err := c.cc.Invoke(ctx, OpenShell_GetSandboxProviderAccessToken_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *openShellClient) GetSandboxLogs(ctx context.Context, in *GetSandboxLogsRequest, opts ...grpc.CallOption) (*GetSandboxLogsResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(GetSandboxLogsResponse) @@ -1378,6 +1392,9 @@ type OpenShellServer interface { // Exchange a stored provider subject token for an intermediate token scoped // to the calling supervisor's SPIFFE identity. ExchangeProviderSubjectToken(context.Context, *ExchangeProviderSubjectTokenRequest) (*ExchangeProviderSubjectTokenResponse, error) + // Obtain the final provider token for the authenticated sandbox session. + // SPIFFE assertions and intermediate credentials remain in the gateway. + GetSandboxProviderAccessToken(context.Context, *GetSandboxProviderAccessTokenRequest) (*GetSandboxProviderAccessTokenResponse, error) // Fetch recent sandbox logs (one-shot). GetSandboxLogs(context.Context, *GetSandboxLogsRequest) (*GetSandboxLogsResponse, error) // Push sandbox supervisor logs to the server (client-streaming). @@ -1647,6 +1664,9 @@ func (UnimplementedOpenShellServer) GetSandboxProviderEnvironment(context.Contex func (UnimplementedOpenShellServer) ExchangeProviderSubjectToken(context.Context, *ExchangeProviderSubjectTokenRequest) (*ExchangeProviderSubjectTokenResponse, error) { return nil, status.Error(codes.Unimplemented, "method ExchangeProviderSubjectToken not implemented") } +func (UnimplementedOpenShellServer) GetSandboxProviderAccessToken(context.Context, *GetSandboxProviderAccessTokenRequest) (*GetSandboxProviderAccessTokenResponse, error) { + return nil, status.Error(codes.Unimplemented, "method GetSandboxProviderAccessToken not implemented") +} func (UnimplementedOpenShellServer) GetSandboxLogs(context.Context, *GetSandboxLogsRequest) (*GetSandboxLogsResponse, error) { return nil, status.Error(codes.Unimplemented, "method GetSandboxLogs not implemented") } @@ -2701,6 +2721,24 @@ func _OpenShell_ExchangeProviderSubjectToken_Handler(srv interface{}, ctx contex return interceptor(ctx, in, info, handler) } +func _OpenShell_GetSandboxProviderAccessToken_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetSandboxProviderAccessTokenRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(OpenShellServer).GetSandboxProviderAccessToken(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: OpenShell_GetSandboxProviderAccessToken_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(OpenShellServer).GetSandboxProviderAccessToken(ctx, req.(*GetSandboxProviderAccessTokenRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _OpenShell_GetSandboxLogs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(GetSandboxLogsRequest) if err := dec(in); err != nil { @@ -3401,6 +3439,10 @@ var OpenShell_ServiceDesc = grpc.ServiceDesc{ MethodName: "ExchangeProviderSubjectToken", Handler: _OpenShell_ExchangeProviderSubjectToken_Handler, }, + { + MethodName: "GetSandboxProviderAccessToken", + Handler: _OpenShell_GetSandboxProviderAccessToken_Handler, + }, { MethodName: "GetSandboxLogs", Handler: _OpenShell_GetSandboxLogs_Handler, diff --git a/tasks/scripts/test-spire-delegation.sh b/tasks/scripts/test-spire-delegation.sh new file mode 100755 index 0000000000..3212007f7f --- /dev/null +++ b/tasks/scripts/test-spire-delegation.sh @@ -0,0 +1,187 @@ +#!/usr/bin/env bash +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +# Run the gateway's SPIRE delegated-identity test against a real +# SPIRE server and agent. +# +# Downloads a pinned, checksum-verified SPIRE release, starts a server and an +# agent with a private admin socket, authorizes this user's processes as the +# delegate, registers the sandbox entries the test expects, and runs the +# ignored `spire_tests` test in openshell-server. + +set -euo pipefail + +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +SPIRE_VERSION="1.15.4" +case "$(uname -m)" in + x86_64 | amd64) + SPIRE_ARCH=amd64 + SPIRE_SHA256=d8e3ee9a9d48636249484d91af37566dfc0a9d7e71edcbe7acd49cf18bc3c87c + ;; + aarch64 | arm64) + SPIRE_ARCH=arm64 + SPIRE_SHA256=81d9b69d662c7813f905805cafd9f2e6d2255639b65c9e1b7297deb2b1df3eb0 + ;; + *) + echo "unsupported architecture: $(uname -m)" >&2 + exit 2 + ;; +esac +if [ "$(uname -s)" != "Linux" ]; then + echo "test:spire-delegation requires Linux" >&2 + exit 2 +fi + +CACHE="${OPENSHELL_SPIRE_CACHE:-${ROOT}/target/spire}" +ARCHIVE="${CACHE}/spire-${SPIRE_VERSION}-linux-${SPIRE_ARCH}-musl.tar.gz" +BIN="${CACHE}/spire-${SPIRE_VERSION}/bin" +mkdir -p "${CACHE}" +if [ ! -x "${BIN}/spire-server" ] || [ ! -x "${BIN}/spire-agent" ]; then + curl -fsSL -o "${ARCHIVE}" \ + "https://github.com/spiffe/spire/releases/download/v${SPIRE_VERSION}/spire-${SPIRE_VERSION}-linux-${SPIRE_ARCH}-musl.tar.gz" + echo "${SPIRE_SHA256} ${ARCHIVE}" | sha256sum -c - + tar -xzf "${ARCHIVE}" -C "${CACHE}" \ + "spire-${SPIRE_VERSION}/bin/spire-server" "spire-${SPIRE_VERSION}/bin/spire-agent" +fi + +# Unix socket paths must stay short. +WORK="$(mktemp -d /tmp/osspire.XXXXXX)" +PIDS=() +cleanup() { + for pid in "${PIDS[@]}"; do + kill "${pid}" 2>/dev/null || true + wait "${pid}" 2>/dev/null || true + done + rm -rf "${WORK}" +} +trap cleanup EXIT + +TRUST_DOMAIN="openshell.test" +GATEWAY_ID="gw-test" +ID_PREFIX="spiffe://${TRUST_DOMAIN}/openshell" +DELEGATE_ID="spiffe://${TRUST_DOMAIN}/openshell/shared-gateway" +NODE_ID="spiffe://${TRUST_DOMAIN}/node/test" +SERVER_SOCKET="${WORK}/server/api.sock" +ADMIN_SOCKET="${WORK}/agent/private/admin.sock" +SERVER_PORT="$(uv run --no-project python -c 'import socket; s = socket.socket(); s.bind(("127.0.0.1", 0)); print(s.getsockname()[1])')" +mkdir -p "${WORK}/server" "${WORK}/agent/public" "${WORK}/agent/private" + +cat >"${WORK}/server.conf" <"${WORK}/agent.conf" </dev/null 2>&1; then + return 0 + fi + sleep 0.5 + done + echo "${binary} did not become healthy" >&2 + return 1 +} + +server() { + "${BIN}/spire-server" "$@" -socketPath "${SERVER_SOCKET}" +} + +"${BIN}/spire-server" run -config "${WORK}/server.conf" >"${WORK}/server.log" 2>&1 & +PIDS+=($!) +wait_healthy spire-server "${SERVER_SOCKET}" +server bundle show >"${WORK}/bundle.pem" +JOIN_TOKEN="$(server token generate -spiffeID "${NODE_ID}" | awk '/^Token:/ {print $2}')" +"${BIN}/spire-agent" run -config "${WORK}/agent.conf" -joinToken "${JOIN_TOKEN}" >"${WORK}/agent.log" 2>&1 & +PIDS+=($!) +wait_healthy spire-agent "${WORK}/agent/public/api.sock" + +entry() { + server entry create -parentID "${NODE_ID}" -spiffeID "$1" -selector "$2" >/dev/null +} +sandbox_id() { + cat /proc/sys/kernel/random/uuid +} +sandbox_entry() { + entry "${ID_PREFIX}/gateway/${GATEWAY_ID}/sandbox/$2" "openshell:sandbox:${GATEWAY_ID}:$1" +} + +# The delegate: this user's processes, attested over the admin socket. +entry "${DELEGATE_ID}" "unix:uid:$(id -u)" +ALPHA="$(sandbox_id)" +BETA="$(sandbox_id)" +UNREGISTERED="$(sandbox_id)" +MISREGISTERED="$(sandbox_id)" +AMBIGUOUS="$(sandbox_id)" +sandbox_entry "${ALPHA}" "${ALPHA}" +sandbox_entry "${BETA}" "${BETA}" +# Operator mistakes the gateway must refuse rather than resolve. +sandbox_entry "${MISREGISTERED}" "${ALPHA}" +sandbox_entry "${AMBIGUOUS}" "${AMBIGUOUS}" +sandbox_entry "${AMBIGUOUS}" "${AMBIGUOUS}-other" + +status=0 +OPENSHELL_TEST_SPIRE_ADMIN_SOCKET="${ADMIN_SOCKET}" \ + OPENSHELL_TEST_SPIRE_ID_PREFIX="${ID_PREFIX}" \ + OPENSHELL_TEST_SPIRE_GATEWAY_ID="${GATEWAY_ID}" \ + OPENSHELL_TEST_SPIRE_SANDBOX_ALPHA="${ALPHA}" \ + OPENSHELL_TEST_SPIRE_SANDBOX_BETA="${BETA}" \ + OPENSHELL_TEST_SPIRE_SANDBOX_UNREGISTERED="${UNREGISTERED}" \ + OPENSHELL_TEST_SPIRE_SANDBOX_MISREGISTERED="${MISREGISTERED}" \ + OPENSHELL_TEST_SPIRE_SANDBOX_AMBIGUOUS="${AMBIGUOUS}" \ + cargo test -p openshell-server --lib spiffe_delegation::tests \ + -- --ignored --nocapture || status=$? +if [ "${status}" -ne 0 ]; then + echo "--- spire-server log" >&2 + tail -n 50 "${WORK}/server.log" >&2 || true + echo "--- spire-agent log" >&2 + tail -n 50 "${WORK}/agent.log" >&2 || true +fi +exit "${status}" diff --git a/tasks/test.toml b/tasks/test.toml index 8eea7c39be..00b5a9e4fa 100644 --- a/tasks/test.toml +++ b/tasks/test.toml @@ -25,6 +25,11 @@ depends = [ "test:maintainer-approval", ] +["test:spire-delegation"] +description = "Test gateway-owned SPIRE delegated sandbox identities against a real SPIRE server and agent" +run = "tasks/scripts/test-spire-delegation.sh" +run_windows = "echo Skipping test:spire-delegation: SPIRE delegation requires Linux." + ["test:docs-website"] description = "Test the docs-website sync script" # --no-project skips installing the OpenShell package; --with supplies the test @@ -272,6 +277,11 @@ env = { OPENSHELL_E2E_KUBE_TEST = "kubernetes_shared_supervisor", OPENSHELL_E2E_ # Prepend the supervisor overlay to any caller overlays, such as a workspace mode. run = 'OPENSHELL_E2E_KUBE_EXTRA_VALUES="deploy/helm/openshell/ci/values-supervisor.yaml${OPENSHELL_E2E_KUBE_EXTRA_VALUES:+:$OPENSHELL_E2E_KUBE_EXTRA_VALUES}" e2e/rust/e2e-kubernetes.sh' +["e2e:kubernetes:shared-supervisor-spiffe"] +description = "Run Kubernetes e2e with SPIRE delegating sandbox identities to the shared supervisor (installs pinned SPIRE charts)" +env = { OPENSHELL_E2E_KUBE_SPIRE_DELEGATION = "1", OPENSHELL_E2E_KUBE_EXTRA_VALUES = "deploy/helm/openshell/ci/values-supervisor-spiffe.yaml", OPENSHELL_E2E_KUBE_TEST = "kubernetes_shared_supervisor_spiffe", OPENSHELL_E2E_KUBERNETES_FEATURES = "e2e,e2e-host-gateway,e2e-kubernetes,e2e-kubernetes-shared-supervisor-spiffe" } +run = "e2e/rust/e2e-kubernetes.sh" + ["e2e:kubernetes:workspace-operator"] description = "Run Kubernetes e2e with operator workspace mode (pre-provisioned per-workspace namespaces)" env = { OPENSHELL_E2E_KUBE_EXTRA_VALUES = "deploy/helm/openshell/ci/values-workspace-operator.yaml", OPENSHELL_E2E_KUBE_TEST = "workspace_namespace_operator", OPENSHELL_E2E_KUBERNETES_FEATURES = "e2e,e2e-kubernetes,e2e-kubernetes-workspace-operator" }