mirror of
https://github.com/NVIDIA/OpenShell.git
synced 2026-10-02 07:34:45 +08:00
chore(deps): replace ring with AWS-LC (#3243)
* chore(deps): replace ring with AWS-LC Signed-off-by: Simon Scatton <sscatton@nvidia.com> * fix(lint): address warnings after dependency upgrades Signed-off-by: Simon Scatton <sscatton@nvidia.com> * fix(tls): limit provider initialization to reqwest clients Signed-off-by: Simon Scatton <sscatton@nvidia.com> --------- Signed-off-by: Simon Scatton <sscatton@nvidia.com>
This commit is contained in:
+1
-1
@@ -306,7 +306,7 @@ echo 'eval "$(~/.local/bin/mise activate zsh)"' >> ~/.zshrc
|
||||
|
||||
Project requirements:
|
||||
|
||||
- Rust 1.90+
|
||||
- Rust 1.94+
|
||||
- Python 3.11+
|
||||
- Docker (running)
|
||||
- CMake 3.16+ (only required when building with the `bundled-z3` feature)
|
||||
|
||||
Generated
+314
-237
File diff suppressed because it is too large
Load Diff
+12
-10
@@ -8,7 +8,7 @@ members = ["crates/*"]
|
||||
[workspace.package]
|
||||
version = "0.0.0"
|
||||
edition = "2024"
|
||||
rust-version = "1.90"
|
||||
rust-version = "1.94"
|
||||
license = "Apache-2.0"
|
||||
repository = "https://github.com/NVIDIA/OpenShell"
|
||||
|
||||
@@ -35,10 +35,10 @@ http-body = "1.0"
|
||||
http-body-util = "0.1"
|
||||
|
||||
# TLS
|
||||
tokio-rustls = { version = "0.26", default-features = false, features = ["logging", "tls12", "ring"] }
|
||||
rustls = { version = "0.23", default-features = false, features = ["std", "logging", "tls12", "ring"] }
|
||||
tokio-rustls = { version = "0.26", default-features = false, features = ["logging", "tls12", "aws_lc_rs"] }
|
||||
rustls = { version = "0.23", default-features = false, features = ["std", "logging", "tls12", "aws_lc_rs"] }
|
||||
rustls-pemfile = "2"
|
||||
rcgen = { version = "0.13", features = ["crypto", "pem"] }
|
||||
rcgen = { version = "0.13", default-features = false, features = ["crypto", "pem", "aws_lc_rs"] }
|
||||
webpki-roots = "1"
|
||||
rustls-native-certs = "0.8"
|
||||
|
||||
@@ -87,7 +87,7 @@ tower-mcp-types = "0.12.0"
|
||||
regex = "1"
|
||||
|
||||
# HTTP client
|
||||
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls-native-roots"] }
|
||||
reqwest = { version = "0.12.28", default-features = false, features = ["json", "rustls-tls-native-roots-no-provider"] }
|
||||
|
||||
# AWS SDK
|
||||
aws-config = { version = "1", default-features = false, features = ["default-https-client", "rt-tokio", "behavior-version-latest"] }
|
||||
@@ -104,7 +104,7 @@ sha2 = "0.10"
|
||||
rand = "0.9"
|
||||
jsonwebtoken = { version = "10", features = ["aws_lc_rs"] }
|
||||
getrandom = "0.3"
|
||||
ring = "0.17"
|
||||
aws-lc-rs = "1.16"
|
||||
spiffe = { version = "0.15", default-features = false, features = ["workload-api-jwt", "jwt-verify-rust-crypto", "tracing"] }
|
||||
|
||||
# Filesystem embedding
|
||||
@@ -124,12 +124,14 @@ url = "2"
|
||||
indexmap = "2"
|
||||
|
||||
# Database
|
||||
sqlx = { version = "0.8", default-features = false, features = ["runtime-tokio", "tls-rustls-ring-native-roots", "postgres", "sqlite", "migrate", "macros"] }
|
||||
sqlx = { version = "0.9", default-features = false, features = ["runtime-tokio", "tls-rustls-aws-lc-rs", "postgres", "sqlite", "migrate", "macros"] }
|
||||
# SQLx's facade couples native roots to ring; select native roots independently.
|
||||
sqlx-core = { version = "0.9", default-features = false, features = ["rustls-native-certs"] }
|
||||
|
||||
# Kubernetes
|
||||
kube = { version = "0.90", default-features = false, features = ["client", "runtime", "derive", "rustls-tls"] }
|
||||
kube-runtime = "0.90"
|
||||
k8s-openapi = { version = "0.21.1", features = ["v1_26"] }
|
||||
kube = { version = "0.99", default-features = false, features = ["client", "runtime", "derive", "rustls-tls", "aws-lc-rs"] }
|
||||
kube-runtime = "0.99"
|
||||
k8s-openapi = { version = "0.24", features = ["v1_29"] }
|
||||
|
||||
# IDs
|
||||
uuid = { version = "1.10", features = ["v4"] }
|
||||
|
||||
@@ -25,6 +25,16 @@ Sandbox community images are built outside this repository.
|
||||
|
||||
## Build Features
|
||||
|
||||
Rust builds require Rust 1.94 or newer. TLS and certificate generation use
|
||||
AWS-LC, including the CLI and standalone examples. Native and cross-build
|
||||
environments must provide the C toolchain required by aws-lc-sys; the Nix
|
||||
development shells provide static AWS-LC libraries.
|
||||
|
||||
SQLx uses AWS-LC with native certificate roots. The server enables
|
||||
`sqlx-core/rustls-native-certs` directly because SQLx's facade does not expose
|
||||
that root selection independently of the crypto provider. Credential storage
|
||||
continues to use the same AES-256-GCM envelope format across backend changes.
|
||||
|
||||
Anonymous telemetry emission is gated behind a default-on `telemetry` Cargo
|
||||
feature. It is defined in `openshell-core` (where the emission code, HTTP
|
||||
client, and endpoint live) and forwarded by the binary crates that emit or
|
||||
|
||||
@@ -49,7 +49,7 @@ bytes = { workspace = true }
|
||||
http-body-util = { workspace = true }
|
||||
hyper = { workspace = true }
|
||||
hyper-util = { workspace = true }
|
||||
hyper-rustls = { version = "0.27", default-features = false, features = ["native-tokio", "http1", "http2", "tls12", "logging", "ring"] }
|
||||
hyper-rustls = { version = "0.27", default-features = false, features = ["native-tokio", "http1", "http2", "tls12", "logging", "aws-lc-rs"] }
|
||||
rustls = { workspace = true }
|
||||
rustls-pemfile = { workspace = true }
|
||||
tokio-rustls = { workspace = true }
|
||||
@@ -91,7 +91,7 @@ nix = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
futures = { workspace = true }
|
||||
rcgen = { version = "0.13", features = ["crypto", "pem"] }
|
||||
rcgen = { workspace = true }
|
||||
reqwest = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
temp-env = "0.3"
|
||||
|
||||
@@ -35,7 +35,7 @@ use tokio::sync::oneshot;
|
||||
use tracing::debug;
|
||||
|
||||
/// Timeout for the browser auth flow.
|
||||
const AUTH_TIMEOUT: Duration = Duration::from_secs(120);
|
||||
const AUTH_TIMEOUT: Duration = Duration::from_mins(2);
|
||||
|
||||
/// Length of the confirmation code (alphanumeric characters).
|
||||
const CODE_LENGTH: usize = 7;
|
||||
|
||||
@@ -1970,7 +1970,6 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn gateway_add_registers_plaintext_loopback_gateway_without_local_flag() {
|
||||
let _ = rustls::crypto::ring::default_provider().install_default();
|
||||
let tmpdir = tempfile::tempdir().expect("create tmpdir");
|
||||
with_tmp_xdg(tmpdir.path(), || {
|
||||
let runtime = tokio::runtime::Runtime::new().expect("create runtime");
|
||||
@@ -2002,7 +2001,6 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn gateway_add_respects_local_flag_for_plaintext_registrations() {
|
||||
let _ = rustls::crypto::ring::default_provider().install_default();
|
||||
let tmpdir = tempfile::tempdir().expect("create tmpdir");
|
||||
with_tmp_xdg(tmpdir.path(), || {
|
||||
let runtime = tokio::runtime::Runtime::new().expect("create runtime");
|
||||
@@ -2032,7 +2030,6 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn http_health_check_supports_plain_http_endpoints() {
|
||||
let _ = rustls::crypto::ring::default_provider().install_default();
|
||||
let listener = TcpListener::bind("127.0.0.1:0").expect("bind listener");
|
||||
let addr = listener.local_addr().expect("listener addr");
|
||||
let server = thread::spawn(move || {
|
||||
@@ -2061,7 +2058,6 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn gateway_add_oidc_rolls_back_on_auth_failure() {
|
||||
let _ = rustls::crypto::ring::default_provider().install_default();
|
||||
let tmpdir = tempfile::tempdir().expect("create tmpdir");
|
||||
with_tmp_xdg(tmpdir.path(), || {
|
||||
let runtime = tokio::runtime::Runtime::new().expect("create runtime");
|
||||
@@ -2118,7 +2114,6 @@ mod tests {
|
||||
}
|
||||
#[test]
|
||||
fn gateway_add_oidc_rollback_keeps_system_active_fallback_userless() {
|
||||
let _ = rustls::crypto::ring::default_provider().install_default();
|
||||
let user = tempfile::tempdir().expect("create user tmpdir");
|
||||
let system = tempfile::tempdir().expect("create system tmpdir");
|
||||
with_tmp_xdg_and_system(user.path(), system.path(), || {
|
||||
@@ -2159,7 +2154,6 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn gateway_add_cloud_rolls_back_on_auth_failure() {
|
||||
let _ = rustls::crypto::ring::default_provider().install_default();
|
||||
let tmpdir = tempfile::tempdir().expect("create tmpdir");
|
||||
with_tmp_xdg(tmpdir.path(), || {
|
||||
let _no_browser = EnvVarGuard::set("OPENSHELL_NO_BROWSER", "0");
|
||||
@@ -2217,7 +2211,6 @@ mod tests {
|
||||
}
|
||||
#[test]
|
||||
fn gateway_add_cloud_rollback_keeps_system_active_fallback_userless() {
|
||||
let _ = rustls::crypto::ring::default_provider().install_default();
|
||||
let user = tempfile::tempdir().expect("create user tmpdir");
|
||||
let system = tempfile::tempdir().expect("create system tmpdir");
|
||||
with_tmp_xdg_and_system(user.path(), system.path(), || {
|
||||
|
||||
@@ -2390,12 +2390,6 @@ fn run_main() -> Result<()> {
|
||||
|
||||
#[allow(clippy::large_stack_frames)] // CLI dispatch holds many futures; run on an expanded Windows stack.
|
||||
async fn run_async() -> Result<()> {
|
||||
// Install the rustls crypto provider before completion runs — completers may
|
||||
// establish TLS connections to the gateway.
|
||||
rustls::crypto::ring::default_provider()
|
||||
.install_default()
|
||||
.map_err(|e| miette::miette!("failed to install rustls crypto provider: {e:?}"))?;
|
||||
|
||||
CompleteEnv::with_factory(Cli::command).complete();
|
||||
|
||||
let cli = Cli::parse();
|
||||
|
||||
@@ -29,7 +29,7 @@ use tokio::net::TcpListener;
|
||||
use tokio::sync::oneshot;
|
||||
use tracing::debug;
|
||||
|
||||
const AUTH_TIMEOUT: Duration = Duration::from_secs(120);
|
||||
const AUTH_TIMEOUT: Duration = Duration::from_mins(2);
|
||||
|
||||
/// OIDC discovery document (subset of fields we need).
|
||||
#[derive(Debug, Deserialize)]
|
||||
@@ -93,6 +93,7 @@ async fn discover(issuer: &str, insecure: bool) -> Result<OidcDiscovery> {
|
||||
}
|
||||
|
||||
fn http_client(insecure: bool) -> reqwest::Client {
|
||||
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
||||
let mut builder = reqwest::ClientBuilder::new().redirect(reqwest::redirect::Policy::none());
|
||||
if insecure {
|
||||
builder = builder.danger_accept_invalid_certs(true);
|
||||
|
||||
@@ -287,7 +287,7 @@ impl ServerCertVerifier for InsecureServerCertVerifier {
|
||||
}
|
||||
|
||||
fn supported_verify_schemes(&self) -> Vec<rustls::SignatureScheme> {
|
||||
rustls::crypto::ring::default_provider()
|
||||
rustls::crypto::aws_lc_rs::default_provider()
|
||||
.signature_verification_algorithms
|
||||
.supported_schemes()
|
||||
}
|
||||
|
||||
@@ -7,9 +7,7 @@
|
||||
|
||||
mod helpers;
|
||||
|
||||
use helpers::{
|
||||
EnvVarGuard, build_ca, build_client_cert, build_server_cert, install_rustls_provider,
|
||||
};
|
||||
use helpers::{EnvVarGuard, build_ca, build_client_cert, build_server_cert};
|
||||
use openshell_cli::run;
|
||||
use openshell_cli::tls::TlsOptions;
|
||||
use openshell_core::proto::open_shell_server::{OpenShell, OpenShellServer};
|
||||
@@ -733,8 +731,6 @@ struct TestServer {
|
||||
}
|
||||
|
||||
async fn run_server() -> TestServer {
|
||||
install_rustls_provider();
|
||||
|
||||
let (ca, ca_key) = build_ca();
|
||||
let (server_cert, server_key) = build_server_cert(&ca, &ca_key);
|
||||
let (client_cert, client_key) = build_client_cert(&ca, &ca_key);
|
||||
|
||||
@@ -160,14 +160,6 @@ impl Drop for EnvVarGuard {
|
||||
|
||||
// ── TLS helpers ──────────────────────────────────────────────────────────────
|
||||
|
||||
/// Install the `rustls` ring crypto provider as the process default.
|
||||
///
|
||||
/// Safe to call multiple times — subsequent calls are no-ops.
|
||||
#[allow(dead_code)]
|
||||
pub fn install_rustls_provider() {
|
||||
let _ = rustls::crypto::ring::default_provider().install_default();
|
||||
}
|
||||
|
||||
/// Generate a self-signed CA certificate and its key pair.
|
||||
#[allow(dead_code)]
|
||||
pub fn build_ca() -> (Certificate, KeyPair) {
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
|
||||
mod helpers;
|
||||
|
||||
use helpers::{
|
||||
EnvVarGuard, build_ca, build_client_cert, build_server_cert, install_rustls_provider,
|
||||
};
|
||||
use helpers::{EnvVarGuard, build_ca, build_client_cert, build_server_cert};
|
||||
use openshell_bootstrap::{get_gateway_metadata, load_active_gateway};
|
||||
use openshell_cli::{
|
||||
run,
|
||||
@@ -651,8 +649,6 @@ fn isolated_gateway_add_env(
|
||||
|
||||
#[tokio::test]
|
||||
async fn gateway_add_mtls_loopback_uses_explicit_gateway_name() {
|
||||
install_rustls_provider();
|
||||
|
||||
let (ca, ca_key) = build_ca();
|
||||
let (server_cert, server_key) = build_server_cert(&ca, &ca_key);
|
||||
let (client_cert, client_key) = build_client_cert(&ca, &ca_key);
|
||||
@@ -695,8 +691,6 @@ async fn gateway_add_mtls_loopback_uses_explicit_gateway_name() {
|
||||
|
||||
#[tokio::test]
|
||||
async fn gateway_add_mtls_loopback_without_name_uses_openshell_default() {
|
||||
install_rustls_provider();
|
||||
|
||||
let (ca, ca_key) = build_ca();
|
||||
let (server_cert, server_key) = build_server_cert(&ca, &ca_key);
|
||||
let (client_cert, client_key) = build_client_cert(&ca, &ca_key);
|
||||
@@ -738,8 +732,6 @@ async fn gateway_add_mtls_loopback_without_name_uses_openshell_default() {
|
||||
|
||||
#[tokio::test]
|
||||
async fn gateway_add_mtls_loopback_explicit_name_does_not_fallback_to_openshell_certs() {
|
||||
install_rustls_provider();
|
||||
|
||||
let (ca, ca_key) = build_ca();
|
||||
let (client_cert, client_key) = build_client_cert(&ca, &ca_key);
|
||||
let ca_cert = ca.pem();
|
||||
@@ -777,7 +769,6 @@ async fn gateway_add_mtls_loopback_explicit_name_does_not_fallback_to_openshell_
|
||||
#[tokio::test]
|
||||
async fn cli_connects_with_client_cert() {
|
||||
let _env = EnvVarGuard::set(&[]);
|
||||
install_rustls_provider();
|
||||
|
||||
let (ca, ca_key) = build_ca();
|
||||
let (server_cert, server_key) = build_server_cert(&ca, &ca_key);
|
||||
@@ -803,8 +794,6 @@ async fn cli_connects_with_client_cert() {
|
||||
|
||||
#[tokio::test]
|
||||
async fn cli_requires_client_cert_for_https() {
|
||||
install_rustls_provider();
|
||||
|
||||
let (ca, ca_key) = build_ca();
|
||||
let (server_cert, server_key) = build_server_cert(&ca, &ca_key);
|
||||
let ca_cert = ca.pem();
|
||||
@@ -851,7 +840,6 @@ async fn run_server_no_client_auth(
|
||||
#[tokio::test]
|
||||
async fn cli_connects_with_gateway_insecure() {
|
||||
let _env = EnvVarGuard::set(&[]);
|
||||
install_rustls_provider();
|
||||
|
||||
let (ca, ca_key) = build_ca();
|
||||
let (server_cert, server_key) = build_server_cert(&ca, &ca_key);
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
|
||||
mod helpers;
|
||||
|
||||
use helpers::{
|
||||
EnvVarGuard, build_ca, build_client_cert, build_server_cert, install_rustls_provider,
|
||||
};
|
||||
use helpers::{EnvVarGuard, build_ca, build_client_cert, build_server_cert};
|
||||
use openshell_cli::run;
|
||||
use openshell_cli::tls::TlsOptions;
|
||||
use openshell_core::proto::open_shell_server::{OpenShell, OpenShellServer};
|
||||
@@ -1162,8 +1160,6 @@ struct TestServer {
|
||||
}
|
||||
|
||||
async fn run_server() -> TestServer {
|
||||
install_rustls_provider();
|
||||
|
||||
let (ca, ca_key) = build_ca();
|
||||
let (server_cert, server_key) = build_server_cert(&ca, &ca_key);
|
||||
let (client_cert, client_key) = build_client_cert(&ca, &ca_key);
|
||||
|
||||
@@ -5,9 +5,7 @@
|
||||
|
||||
mod helpers;
|
||||
|
||||
use helpers::{
|
||||
EnvVarGuard, build_ca, build_client_cert, build_server_cert, install_rustls_provider,
|
||||
};
|
||||
use helpers::{EnvVarGuard, build_ca, build_client_cert, build_server_cert};
|
||||
use openshell_bootstrap::load_last_sandbox;
|
||||
use openshell_cli::run;
|
||||
use openshell_cli::tls::TlsOptions;
|
||||
@@ -944,8 +942,6 @@ struct TestServer {
|
||||
}
|
||||
|
||||
async fn run_server() -> TestServer {
|
||||
install_rustls_provider();
|
||||
|
||||
let (ca, ca_key) = build_ca();
|
||||
let (server_cert, server_key) = build_server_cert(&ca, &ca_key);
|
||||
let (client_cert, client_key) = build_client_cert(&ca, &ca_key);
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
|
||||
mod helpers;
|
||||
|
||||
use helpers::{
|
||||
EnvVarGuard, build_ca, build_client_cert, build_server_cert, install_rustls_provider,
|
||||
};
|
||||
use helpers::{EnvVarGuard, build_ca, build_client_cert, build_server_cert};
|
||||
use openshell_bootstrap::{load_last_sandbox, save_last_sandbox};
|
||||
use openshell_cli::run;
|
||||
use openshell_cli::tls::TlsOptions;
|
||||
@@ -682,8 +680,6 @@ struct TestServer {
|
||||
}
|
||||
|
||||
async fn run_server() -> TestServer {
|
||||
install_rustls_provider();
|
||||
|
||||
let (ca, ca_key) = build_ca();
|
||||
let (server_cert, server_key) = build_server_cert(&ca, &ca_key);
|
||||
let (client_cert, client_key) = build_client_cert(&ca, &ca_key);
|
||||
|
||||
@@ -92,7 +92,7 @@ pub fn default_scenarios() -> impl Iterator<Item = &'static Scenario> {
|
||||
.filter(|scenario| !scenario.requires_plan)
|
||||
}
|
||||
|
||||
const CLEANUP_TIMEOUT: Duration = Duration::from_secs(120);
|
||||
const CLEANUP_TIMEOUT: Duration = Duration::from_mins(2);
|
||||
pub const STATUS_TIMEOUT: Duration = Duration::from_secs(30);
|
||||
const GATEWAY_STATUS_ATTEMPT_TIMEOUT: Duration = Duration::from_secs(10);
|
||||
const GATEWAY_STATUS_INTERVAL: Duration = Duration::from_secs(2);
|
||||
|
||||
@@ -11,9 +11,9 @@ use crate::{
|
||||
HostAction, OpenShellRunner, PlanRun, Poll, Scenario, ScenarioFuture, WorkloadExpectation,
|
||||
};
|
||||
|
||||
const CREATE_TIMEOUT: Duration = Duration::from_secs(600);
|
||||
const COMMAND_TIMEOUT: Duration = Duration::from_secs(120);
|
||||
const RECOVERY_TIMEOUT: Duration = Duration::from_secs(240);
|
||||
const CREATE_TIMEOUT: Duration = Duration::from_mins(10);
|
||||
const COMMAND_TIMEOUT: Duration = Duration::from_mins(2);
|
||||
const RECOVERY_TIMEOUT: Duration = Duration::from_mins(4);
|
||||
const RECOVERY_INTERVAL: Duration = Duration::from_secs(2);
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
|
||||
@@ -9,11 +9,11 @@ use crate::{OpenShellRunner, PlanRun, STATUS_TIMEOUT, Scenario, ScenarioFuture};
|
||||
use serde::Deserialize;
|
||||
use tokio::time::sleep;
|
||||
|
||||
const CREATE_TIMEOUT: Duration = Duration::from_secs(600);
|
||||
const CREATE_TIMEOUT: Duration = Duration::from_mins(10);
|
||||
const LIST_ATTEMPT_TIMEOUT: Duration = Duration::from_secs(10);
|
||||
const LIST_PAGE_SIZE: u32 = 1_000;
|
||||
const EXEC_TIMEOUT: Duration = Duration::from_secs(120);
|
||||
const DELETE_TIMEOUT: Duration = Duration::from_secs(120);
|
||||
const EXEC_TIMEOUT: Duration = Duration::from_mins(2);
|
||||
const DELETE_TIMEOUT: Duration = Duration::from_mins(2);
|
||||
const DELETE_POLL_INTERVAL: Duration = Duration::from_secs(1);
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
|
||||
@@ -16,7 +16,7 @@ openshell-extension-core = { path = "../openshell-extension-core" }
|
||||
glob = { workspace = true }
|
||||
prost = { workspace = true }
|
||||
prost-types = { workspace = true }
|
||||
tonic = { workspace = true, features = ["channel", "tls-ring"] }
|
||||
tonic = { workspace = true, features = ["channel", "tls-aws-lc"] }
|
||||
tonic-prost = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
tokio-stream = { workspace = true }
|
||||
@@ -31,7 +31,7 @@ rustls = { workspace = true }
|
||||
rustls-pemfile = { workspace = true }
|
||||
base64 = { workspace = true }
|
||||
chrono = { version = "0.4", default-features = false, features = ["clock", "std"], optional = true }
|
||||
reqwest = { workspace = true, features = ["blocking", "rustls-tls-native-roots"], optional = true }
|
||||
reqwest = { workspace = true, features = ["blocking", "rustls-tls-native-roots-no-provider"], optional = true }
|
||||
tar = { version = "0.4", optional = true }
|
||||
tempfile = { version = "3", optional = true }
|
||||
|
||||
|
||||
@@ -995,7 +995,7 @@ mod tests {
|
||||
Config::new(None)
|
||||
.with_grpc_rate_limit(Some(10), Some(60))
|
||||
.grpc_rate_limit(),
|
||||
Some((10, Duration::from_secs(60)))
|
||||
Some((10, Duration::from_mins(1)))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -312,6 +312,7 @@ mod tests {
|
||||
}
|
||||
|
||||
fn test_client() -> reqwest::Client {
|
||||
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
||||
reqwest::Client::builder()
|
||||
.timeout(std::time::Duration::from_secs(5))
|
||||
.no_proxy()
|
||||
|
||||
@@ -426,6 +426,7 @@ fn telemetry_worker(rx: mpsc::Receiver<TelemetryEvent>) {
|
||||
|
||||
#[cfg(feature = "telemetry")]
|
||||
fn publish_payload(endpoint: &str, payload: Value) -> Result<(), reqwest::Error> {
|
||||
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
||||
Client::builder()
|
||||
.use_rustls_tls()
|
||||
.tls_built_in_root_certs(true)
|
||||
|
||||
@@ -16,7 +16,7 @@ openshell-core = { path = "../openshell-core", default-features = false }
|
||||
async-trait = "0.1"
|
||||
base64 = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
ring = { workspace = true }
|
||||
aws-lc-rs = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
sha2 = { workspace = true }
|
||||
|
||||
@@ -17,6 +17,8 @@ use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use aws_lc_rs::aead::{AES_256_GCM, Aad, LessSafeKey, Nonce, UnboundKey};
|
||||
use aws_lc_rs::rand::{SecureRandom, SystemRandom};
|
||||
use base64::{
|
||||
Engine as _,
|
||||
engine::general_purpose::{STANDARD as BASE64, STANDARD_NO_PAD as BASE64_NO_PAD},
|
||||
@@ -26,8 +28,6 @@ use openshell_core::proto::credentials::v1::{
|
||||
DeleteCredentialRequest, ResolveCredentialRequest, ResolvedCredential, StoreCredentialRequest,
|
||||
};
|
||||
use openshell_core::{Error, Result as CoreResult};
|
||||
use ring::aead::{AES_256_GCM, Aad, LessSafeKey, Nonce, UnboundKey};
|
||||
use ring::rand::{SecureRandom, SystemRandom};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sha2::{Digest, Sha256};
|
||||
use tonic::Status;
|
||||
@@ -933,6 +933,46 @@ mod tests {
|
||||
use std::sync::{Arc, Mutex};
|
||||
use tonic::Code;
|
||||
|
||||
#[test]
|
||||
fn persisted_aes_gcm_ciphertexts_remain_compatible() {
|
||||
// Fixed, non-secret ciphertexts produced by the previous crypto backend.
|
||||
let cases = [
|
||||
(
|
||||
[0x11; KEY_LEN],
|
||||
[0x22; NONCE_LEN],
|
||||
dek_aad("fixture", "provider", "api_key"),
|
||||
vec![0x33; KEY_LEN],
|
||||
"JMQ0evP8rGzWDO0Pe5Xa5iyg/tFZsp94YXw52zrSVjCoSMvKkAYj5kygMADT9jIW",
|
||||
),
|
||||
(
|
||||
[0x33; KEY_LEN],
|
||||
[0x44; NONCE_LEN],
|
||||
value_aad("fixture", "provider", "api_key"),
|
||||
b"fixture-secret".to_vec(),
|
||||
"Vvi85r906kbT58fgk+mUIc/KA4ar8d3Syu8Jz5h1",
|
||||
),
|
||||
];
|
||||
for (key, nonce, aad, plaintext, ciphertext) in cases {
|
||||
let encrypted = EncryptedBytes {
|
||||
nonce: BASE64.encode(nonce),
|
||||
ciphertext: ciphertext.to_string(),
|
||||
};
|
||||
assert_eq!(decrypt_bytes(&key, &aad, &encrypted).unwrap(), plaintext);
|
||||
let mut sealed = plaintext;
|
||||
aead_key(&key)
|
||||
.unwrap()
|
||||
.seal_in_place_append_tag(
|
||||
Nonce::assume_unique_for_key(nonce),
|
||||
Aad::from(aad.as_slice()),
|
||||
&mut sealed,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(BASE64.encode(sealed), ciphertext);
|
||||
assert!(decrypt_bytes(&key, b"wrong-aad", &encrypted).is_err());
|
||||
assert!(decrypt_bytes(&[0xff; KEY_LEN], &aad, &encrypted).is_err());
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
struct MemoryObjectStore {
|
||||
objects: Mutex<HashMap<String, StoredCredentialObject>>,
|
||||
|
||||
@@ -54,7 +54,7 @@ use openshell_core::proto::compute::v1::{
|
||||
};
|
||||
use openshell_core::proto_struct::{struct_to_json_object, value_to_json};
|
||||
use serde::Deserialize;
|
||||
use std::collections::{BTreeMap, HashSet};
|
||||
use std::collections::{BTreeMap, BTreeSet, HashSet};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
@@ -1965,7 +1965,7 @@ impl KubernetesComputeDriver {
|
||||
loop {
|
||||
tokio::select! {
|
||||
event = sandbox_stream.next() => match event {
|
||||
Some(Event::Applied(obj)) => {
|
||||
Some(Event::Apply(obj) | Event::InitApply(obj)) => {
|
||||
if let Ok((kube_name, sandbox)) = sandbox_from_object(&namespace, obj) {
|
||||
update_indexes(&mut sandbox_name_to_id, &mut agent_pod_to_id, &kube_name, &sandbox);
|
||||
let event = WatchSandboxesEvent {
|
||||
@@ -1978,7 +1978,7 @@ impl KubernetesComputeDriver {
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(Event::Deleted(obj)) => {
|
||||
Some(Event::Delete(obj)) => {
|
||||
if is_openshell_managed(&obj)
|
||||
&& let Ok(sandbox_id) = sandbox_id_from_object(&obj)
|
||||
{
|
||||
@@ -1993,21 +1993,7 @@ impl KubernetesComputeDriver {
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(Event::Restarted(objs)) => {
|
||||
for obj in objs {
|
||||
if let Ok((kube_name, sandbox)) = sandbox_from_object(&namespace, obj) {
|
||||
update_indexes(&mut sandbox_name_to_id, &mut agent_pod_to_id, &kube_name, &sandbox);
|
||||
let event = WatchSandboxesEvent {
|
||||
payload: Some(watch_sandboxes_event::Payload::Sandbox(
|
||||
WatchSandboxesSandboxEvent { sandbox: Some(sandbox) }
|
||||
)),
|
||||
};
|
||||
if tx.send(Ok(event)).await.is_err() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(Event::Init | Event::InitDone) => {}
|
||||
None => {
|
||||
let _ = tx.send(Err(KubernetesDriverError::Message(
|
||||
"sandbox watcher stream ended unexpectedly".to_string()
|
||||
@@ -2016,7 +2002,7 @@ impl KubernetesComputeDriver {
|
||||
}
|
||||
},
|
||||
event = event_stream.next() => match event {
|
||||
Some(Event::Applied(obj)) => {
|
||||
Some(Event::Apply(obj)) => {
|
||||
if let Some((sandbox_id, event)) = map_kube_event_to_platform(
|
||||
&sandbox_name_to_id,
|
||||
&agent_pod_to_id,
|
||||
@@ -2032,8 +2018,8 @@ impl KubernetesComputeDriver {
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(Event::Deleted(_)) => {}
|
||||
Some(Event::Restarted(_)) => {
|
||||
Some(Event::Delete(_) | Event::InitApply(_) | Event::InitDone) => {}
|
||||
Some(Event::Init) => {
|
||||
debug!(namespace = %namespace, "Kubernetes event watcher restarted");
|
||||
}
|
||||
None => {
|
||||
@@ -2082,7 +2068,7 @@ where
|
||||
loop {
|
||||
tokio::select! {
|
||||
event = sandbox_stream.next() => match event {
|
||||
Some(Event::Applied(obj)) => {
|
||||
Some(Event::Apply(obj) | Event::InitApply(obj)) => {
|
||||
let ns = obj.metadata.namespace.clone()
|
||||
.unwrap_or_else(|| default_namespace.clone());
|
||||
if let Ok((_kube_name, sandbox)) = sandbox_from_object(&ns, obj) {
|
||||
@@ -2096,7 +2082,7 @@ where
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(Event::Deleted(obj)) => {
|
||||
Some(Event::Delete(obj)) => {
|
||||
if is_openshell_managed(&obj)
|
||||
&& let Ok(sandbox_id) = sandbox_id_from_object(&obj)
|
||||
{
|
||||
@@ -2110,22 +2096,7 @@ where
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(Event::Restarted(objs)) => {
|
||||
for obj in objs {
|
||||
let ns = obj.metadata.namespace.clone()
|
||||
.unwrap_or_else(|| default_namespace.clone());
|
||||
if let Ok((_kube_name, sandbox)) = sandbox_from_object(&ns, obj) {
|
||||
let event = WatchSandboxesEvent {
|
||||
payload: Some(watch_sandboxes_event::Payload::Sandbox(
|
||||
WatchSandboxesSandboxEvent { sandbox: Some(sandbox) }
|
||||
)),
|
||||
};
|
||||
if tx.send(Ok(event)).await.is_err() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(Event::Init | Event::InitDone) => {}
|
||||
None => {
|
||||
let _ = tx.send(Err(KubernetesDriverError::Message(
|
||||
"sandbox watcher stream ended unexpectedly".to_string()
|
||||
@@ -2318,7 +2289,6 @@ fn managed_ssh_network_policy(namespace: &str, config: &KubernetesComputeConfig)
|
||||
}]),
|
||||
..Default::default()
|
||||
}),
|
||||
status: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4723,6 +4693,7 @@ fn spawn_namespace_label_watcher(
|
||||
let mut retry_attempt = 0;
|
||||
loop {
|
||||
let mut stream = watcher::watcher(ns_api.clone(), watcher_config.clone()).boxed();
|
||||
let mut relisted_names = BTreeSet::new();
|
||||
|
||||
loop {
|
||||
let event = tokio::select! {
|
||||
@@ -4735,37 +4706,9 @@ fn spawn_namespace_label_watcher(
|
||||
}
|
||||
};
|
||||
match event {
|
||||
Ok(Some(Event::Applied(ns))) => {
|
||||
Ok(Some(event)) => {
|
||||
retry_attempt = 0;
|
||||
if let Some(name) = ns.metadata.name.as_deref()
|
||||
&& allowlist.insert(name.to_string())
|
||||
{
|
||||
info!(namespace = name, "operator namespace added to allowlist");
|
||||
}
|
||||
}
|
||||
Ok(Some(Event::Deleted(ns))) => {
|
||||
retry_attempt = 0;
|
||||
if let Some(name) = ns.metadata.name.as_deref()
|
||||
&& allowlist.remove(name)
|
||||
{
|
||||
info!(
|
||||
namespace = name,
|
||||
"operator namespace removed from allowlist"
|
||||
);
|
||||
}
|
||||
}
|
||||
Ok(Some(Event::Restarted(namespaces))) => {
|
||||
retry_attempt = 0;
|
||||
let names: std::collections::BTreeSet<String> = namespaces
|
||||
.into_iter()
|
||||
.filter_map(|ns| ns.metadata.name)
|
||||
.collect();
|
||||
let count = names.len();
|
||||
allowlist.replace(names);
|
||||
info!(
|
||||
total = count,
|
||||
"operator namespace allowlist replaced from full relist"
|
||||
);
|
||||
apply_namespace_watch_event(&allowlist, &mut relisted_names, event);
|
||||
}
|
||||
Ok(None) => {
|
||||
warn!("operator namespace watcher stream ended unexpectedly");
|
||||
@@ -4807,7 +4750,7 @@ fn namespace_watcher_retry_delay(attempt: u32, jitter_seed: u64) -> Duration {
|
||||
Duration::from_secs(base_secs + jitter_secs)
|
||||
}
|
||||
|
||||
fn load_namespace_file(path: &Path) -> Result<std::collections::BTreeSet<String>, String> {
|
||||
fn load_namespace_file(path: &Path) -> Result<BTreeSet<String>, String> {
|
||||
let contents = std::fs::read_to_string(path)
|
||||
.map_err(|e| format!("failed to read {}: {e}", path.display()))?;
|
||||
let names: Vec<String> = serde_json::from_str(&contents)
|
||||
@@ -4815,6 +4758,47 @@ fn load_namespace_file(path: &Path) -> Result<std::collections::BTreeSet<String>
|
||||
Ok(names.into_iter().collect())
|
||||
}
|
||||
|
||||
fn apply_namespace_watch_event(
|
||||
allowlist: &OperatorNamespaceAllowlist,
|
||||
relisted_names: &mut BTreeSet<String>,
|
||||
event: Event<Namespace>,
|
||||
) {
|
||||
match event {
|
||||
Event::Apply(ns) => {
|
||||
if let Some(name) = ns.metadata.name
|
||||
&& allowlist.insert(name.clone())
|
||||
{
|
||||
info!(namespace = name, "operator namespace added to allowlist");
|
||||
}
|
||||
}
|
||||
Event::Delete(ns) => {
|
||||
if let Some(name) = ns.metadata.name
|
||||
&& allowlist.remove(&name)
|
||||
{
|
||||
info!(
|
||||
namespace = name,
|
||||
"operator namespace removed from allowlist"
|
||||
);
|
||||
}
|
||||
}
|
||||
Event::Init => relisted_names.clear(),
|
||||
Event::InitApply(ns) => {
|
||||
if let Some(name) = ns.metadata.name {
|
||||
relisted_names.insert(name);
|
||||
}
|
||||
}
|
||||
Event::InitDone => {
|
||||
// Readers must see a complete snapshot, including during interrupted relists.
|
||||
let count = relisted_names.len();
|
||||
allowlist.replace(std::mem::take(relisted_names));
|
||||
info!(
|
||||
total = count,
|
||||
"operator namespace allowlist replaced from full relist"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn spawn_namespace_file_watcher(
|
||||
path: PathBuf,
|
||||
allowlist: OperatorNamespaceAllowlist,
|
||||
@@ -5062,7 +5046,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn sandbox_watcher_error_does_not_hide_restarted_recovery_event() {
|
||||
async fn sandbox_watcher_error_does_not_hide_relist() {
|
||||
let recovered = DynamicObject {
|
||||
types: None,
|
||||
metadata: ObjectMeta {
|
||||
@@ -5073,22 +5057,22 @@ mod tests {
|
||||
};
|
||||
let source = futures::stream::iter([
|
||||
Err(expired_watch_error()),
|
||||
Ok(Event::Restarted(vec![recovered])),
|
||||
Ok(Event::Init),
|
||||
Ok(Event::InitApply(recovered)),
|
||||
Ok(Event::InitDone),
|
||||
]);
|
||||
let mut stream = continue_on_watcher_errors(source, "sandbox-resource");
|
||||
|
||||
assert!(matches!(stream.next().await, Some(Event::Init)));
|
||||
let event = stream
|
||||
.next()
|
||||
.await
|
||||
.expect("410 Expired must not terminate the watcher stream");
|
||||
let Event::Restarted(objects) = event else {
|
||||
panic!("expected kube-runtime recovery to emit Restarted");
|
||||
let Event::InitApply(object) = event else {
|
||||
panic!("expected kube-runtime recovery to emit InitApply");
|
||||
};
|
||||
assert_eq!(objects.len(), 1);
|
||||
assert_eq!(
|
||||
objects[0].metadata.name.as_deref(),
|
||||
Some("recovered-sandbox")
|
||||
);
|
||||
assert_eq!(object.metadata.name.as_deref(), Some("recovered-sandbox"));
|
||||
assert!(matches!(stream.next().await, Some(Event::InitDone)));
|
||||
assert!(
|
||||
stream.next().await.is_none(),
|
||||
"source closure must be preserved"
|
||||
@@ -5117,7 +5101,9 @@ mod tests {
|
||||
};
|
||||
let source = futures::stream::iter([
|
||||
Err(expired_watch_error()),
|
||||
Ok(Event::Restarted(vec![recovered])),
|
||||
Ok(Event::Init),
|
||||
Ok(Event::InitApply(recovered)),
|
||||
Ok(Event::InitDone),
|
||||
])
|
||||
.chain(futures::stream::pending());
|
||||
let sandbox_stream = recovering_watcher_stream(source, "sandbox-resource").boxed();
|
||||
@@ -5144,10 +5130,12 @@ mod tests {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn kubernetes_event_watcher_error_does_not_hide_restarted_recovery_event() {
|
||||
async fn kubernetes_event_watcher_error_does_not_hide_relist() {
|
||||
let source = futures::stream::iter([
|
||||
Err(expired_watch_error()),
|
||||
Ok(Event::Restarted(vec![KubeEventObj::default()])),
|
||||
Ok(Event::Init),
|
||||
Ok(Event::InitApply(KubeEventObj::default())),
|
||||
Ok(Event::InitDone),
|
||||
]);
|
||||
let mut stream = continue_on_watcher_errors(source, "kubernetes-event");
|
||||
|
||||
@@ -5155,16 +5143,65 @@ mod tests {
|
||||
.next()
|
||||
.await
|
||||
.expect("410 Expired must not terminate the watcher stream");
|
||||
let Event::Restarted(events) = event else {
|
||||
panic!("expected kube-runtime recovery to emit Restarted");
|
||||
};
|
||||
assert_eq!(events.len(), 1);
|
||||
assert!(matches!(event, Event::Init));
|
||||
assert!(matches!(stream.next().await, Some(Event::InitApply(_))));
|
||||
assert!(matches!(stream.next().await, Some(Event::InitDone)));
|
||||
assert!(
|
||||
stream.next().await.is_none(),
|
||||
"source closure must be preserved"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn namespace_relist_replaces_only_completed_snapshots() {
|
||||
let allowlist = OperatorNamespaceAllowlist::from_set(BTreeSet::from(["old".to_string()]));
|
||||
let mut pending = BTreeSet::new();
|
||||
let namespace = |name: &str| Namespace {
|
||||
metadata: ObjectMeta {
|
||||
name: Some(name.to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
};
|
||||
let config = KubernetesComputeConfig {
|
||||
workspace_mode: WorkspaceMode::Operator,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
apply_namespace_watch_event(&allowlist, &mut pending, Event::Init);
|
||||
apply_namespace_watch_event(
|
||||
&allowlist,
|
||||
&mut pending,
|
||||
Event::InitApply(namespace("partial")),
|
||||
);
|
||||
assert!(accepts_auth_namespace(&config, Some(&allowlist), "old"));
|
||||
assert!(!accepts_auth_namespace(
|
||||
&config,
|
||||
Some(&allowlist),
|
||||
"partial"
|
||||
));
|
||||
|
||||
apply_namespace_watch_event(&allowlist, &mut pending, Event::Init);
|
||||
apply_namespace_watch_event(&allowlist, &mut pending, Event::InitApply(namespace("new")));
|
||||
apply_namespace_watch_event(&allowlist, &mut pending, Event::InitDone);
|
||||
assert!(accepts_auth_namespace(&config, Some(&allowlist), "new"));
|
||||
assert!(!accepts_auth_namespace(&config, Some(&allowlist), "old"));
|
||||
assert!(!accepts_auth_namespace(
|
||||
&config,
|
||||
Some(&allowlist),
|
||||
"partial"
|
||||
));
|
||||
|
||||
apply_namespace_watch_event(&allowlist, &mut pending, Event::Apply(namespace("live")));
|
||||
assert!(accepts_auth_namespace(&config, Some(&allowlist), "live"));
|
||||
apply_namespace_watch_event(&allowlist, &mut pending, Event::Delete(namespace("live")));
|
||||
assert!(!accepts_auth_namespace(&config, Some(&allowlist), "live"));
|
||||
|
||||
apply_namespace_watch_event(&allowlist, &mut pending, Event::Init);
|
||||
apply_namespace_watch_event(&allowlist, &mut pending, Event::InitDone);
|
||||
assert!(!accepts_auth_namespace(&config, Some(&allowlist), "new"));
|
||||
}
|
||||
|
||||
fn authenticated_token_review(username: &str) -> TokenReviewStatus {
|
||||
TokenReviewStatus {
|
||||
authenticated: Some(true),
|
||||
@@ -5372,7 +5409,7 @@ mod tests {
|
||||
|
||||
assert_eq!(
|
||||
kubernetes_sandbox_stop_timeout(&sandbox),
|
||||
Duration::from_secs(60),
|
||||
Duration::from_mins(1),
|
||||
"an omitted grace period uses the Kubernetes 30-second default"
|
||||
);
|
||||
|
||||
|
||||
@@ -719,7 +719,7 @@ impl PodmanClient {
|
||||
url_encode(policy),
|
||||
);
|
||||
// Image pulls can be slow — use a generous timeout.
|
||||
let pull_timeout = Duration::from_secs(600);
|
||||
let pull_timeout = Duration::from_mins(10);
|
||||
let (status, bytes) = self
|
||||
.request(hyper::Method::POST, &path, None, pull_timeout)
|
||||
.await?;
|
||||
|
||||
@@ -21,6 +21,7 @@ clap = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
miette = { workspace = true }
|
||||
reqwest = { workspace = true }
|
||||
rustls = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
sha2 = { workspace = true }
|
||||
|
||||
@@ -126,6 +126,7 @@ impl VaultCredentialDriver {
|
||||
pub fn from_config(config: &toml::Table) -> CoreResult<Self> {
|
||||
let settings = VaultDriverSettings::from_table(config)?;
|
||||
let timeout_secs = timeout_secs(config)?;
|
||||
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
||||
let client = reqwest::Client::builder()
|
||||
.timeout(Duration::from_secs(timeout_secs))
|
||||
.build()
|
||||
|
||||
@@ -9,7 +9,7 @@ use serde::{Deserialize, Serialize};
|
||||
///
|
||||
/// Extension credentials cross the gateway trust boundary and must remain
|
||||
/// short-lived even when legacy sandbox bootstrap credentials do not expire.
|
||||
pub const MAX_EXTENSION_TOKEN_TTL: Duration = Duration::from_secs(3_600);
|
||||
pub const MAX_EXTENSION_TOKEN_TTL: Duration = Duration::from_hours(1);
|
||||
|
||||
/// Explicit `typ` header value carried by every extension bearer token.
|
||||
///
|
||||
|
||||
@@ -292,7 +292,6 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn custom_ca_verifies_certificate_and_hostname() {
|
||||
let _ = rustls::crypto::ring::default_provider().install_default();
|
||||
let ca_key = KeyPair::generate().unwrap();
|
||||
let mut ca_params = CertificateParams::new(Vec::<String>::new()).unwrap();
|
||||
ca_params.is_ca = IsCa::Ca(BasicConstraints::Unconstrained);
|
||||
|
||||
@@ -14,6 +14,7 @@ repository.workspace = true
|
||||
openshell-core = { path = "../openshell-core", default-features = false }
|
||||
bytes = { workspace = true }
|
||||
reqwest = { workspace = true }
|
||||
rustls = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
|
||||
@@ -1104,6 +1104,7 @@ mod tests {
|
||||
.await;
|
||||
|
||||
let route = test_route(&mock_server.uri(), &["model_discovery"], AuthHeader::Bearer);
|
||||
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
||||
let client = reqwest::Client::new();
|
||||
let result = proxy_to_backend(
|
||||
&client,
|
||||
@@ -1151,6 +1152,7 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn read_capped_response_body_rejects_over_cap_chunked() {
|
||||
let addr = spawn_chunked_upstream(&["aaaa", "bbbb", "cccc"]).await;
|
||||
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
||||
let response = reqwest::Client::new()
|
||||
.get(format!("http://{addr}/"))
|
||||
.send()
|
||||
@@ -1172,6 +1174,7 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn read_capped_response_body_accepts_body_at_cap() {
|
||||
let addr = spawn_chunked_upstream(&["aaaa", "bbbb"]).await;
|
||||
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
||||
let response = reqwest::Client::new()
|
||||
.get(format!("http://{addr}/"))
|
||||
.send()
|
||||
@@ -1358,6 +1361,7 @@ mod tests {
|
||||
.mount(&mock_server)
|
||||
.await;
|
||||
|
||||
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
||||
let client = reqwest::Client::builder().build().unwrap();
|
||||
let validated = verify_backend_endpoint(&client, &route).await.unwrap();
|
||||
|
||||
@@ -1373,6 +1377,7 @@ mod tests {
|
||||
AuthHeader::Bearer,
|
||||
);
|
||||
|
||||
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
||||
let client = reqwest::Client::builder().build().unwrap();
|
||||
let validated = verify_backend_endpoint(&client, &route).await.unwrap();
|
||||
|
||||
@@ -1402,6 +1407,7 @@ mod tests {
|
||||
.mount(&mock_server)
|
||||
.await;
|
||||
|
||||
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
||||
let client = reqwest::Client::builder().build().unwrap();
|
||||
let validated = verify_backend_endpoint(&client, &route).await.unwrap();
|
||||
|
||||
@@ -1445,6 +1451,7 @@ mod tests {
|
||||
.mount(&mock_server)
|
||||
.await;
|
||||
|
||||
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
||||
let client = reqwest::Client::builder().build().unwrap();
|
||||
let validated = verify_backend_endpoint(&client, &route).await.unwrap();
|
||||
|
||||
@@ -1491,6 +1498,7 @@ mod tests {
|
||||
.mount(&mock_server)
|
||||
.await;
|
||||
|
||||
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
||||
let client = reqwest::Client::new();
|
||||
let validated = verify_backend_endpoint(&client, &route)
|
||||
.await
|
||||
@@ -1526,6 +1534,7 @@ mod tests {
|
||||
.mount(&mock_server)
|
||||
.await;
|
||||
|
||||
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
||||
let client = reqwest::Client::new();
|
||||
let err = verify_backend_endpoint(&client, &route)
|
||||
.await
|
||||
@@ -1629,6 +1638,7 @@ mod tests {
|
||||
|
||||
/// Helper: run `verify_backend_endpoint` and return the expected failure.
|
||||
async fn reqwest_verify(route: &ResolvedRoute) -> ValidationFailure {
|
||||
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
||||
verify_backend_endpoint(&reqwest::Client::new(), route)
|
||||
.await
|
||||
.expect_err("validation should fail")
|
||||
@@ -1651,6 +1661,7 @@ mod tests {
|
||||
.mount(&mock_server)
|
||||
.await;
|
||||
|
||||
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
||||
let client = reqwest::Client::builder().build().unwrap();
|
||||
let result = verify_backend_endpoint(&client, &route).await;
|
||||
|
||||
@@ -1691,6 +1702,7 @@ mod tests {
|
||||
.mount(&mock_server)
|
||||
.await;
|
||||
|
||||
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
||||
let client = reqwest::Client::builder().build().unwrap();
|
||||
let validated = verify_backend_endpoint(&client, &route).await.unwrap();
|
||||
assert!(
|
||||
@@ -1897,6 +1909,7 @@ mod tests {
|
||||
.mount(&mock_server)
|
||||
.await;
|
||||
|
||||
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
||||
let client = reqwest::Client::builder().build().unwrap();
|
||||
let body = bytes::Bytes::from(
|
||||
serde_json::to_vec(&serde_json::json!({
|
||||
@@ -1966,6 +1979,7 @@ mod tests {
|
||||
.mount(&mock_server)
|
||||
.await;
|
||||
|
||||
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
||||
let client = reqwest::Client::builder().build().unwrap();
|
||||
// Simulate a client (e.g. Claude Code) that always sends "model" in the body.
|
||||
let body = bytes::Bytes::from(
|
||||
@@ -2028,6 +2042,7 @@ mod tests {
|
||||
.mount(&mock_server)
|
||||
.await;
|
||||
|
||||
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
||||
let client = reqwest::Client::builder().build().unwrap();
|
||||
let body = bytes::Bytes::from(
|
||||
serde_json::to_vec(&serde_json::json!({
|
||||
@@ -2086,6 +2101,7 @@ mod tests {
|
||||
request_path_override: None,
|
||||
};
|
||||
|
||||
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
||||
let client = reqwest::Client::builder().build().unwrap();
|
||||
let body = bytes::Bytes::from(
|
||||
serde_json::to_vec(&serde_json::json!({
|
||||
@@ -2212,6 +2228,7 @@ mod tests {
|
||||
.mount(&mock_server)
|
||||
.await;
|
||||
|
||||
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
||||
let client = reqwest::Client::builder().build().unwrap();
|
||||
let body = bytes::Bytes::from(
|
||||
serde_json::to_vec(&serde_json::json!({
|
||||
@@ -2274,6 +2291,7 @@ mod tests {
|
||||
.mount(&mock_server)
|
||||
.await;
|
||||
|
||||
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
||||
let client = reqwest::Client::builder().build().unwrap();
|
||||
let body = bytes::Bytes::from(
|
||||
serde_json::to_vec(&serde_json::json!({
|
||||
@@ -2338,6 +2356,7 @@ mod tests {
|
||||
.mount(&mock_server)
|
||||
.await;
|
||||
|
||||
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
||||
let client = reqwest::Client::builder().build().unwrap();
|
||||
let body = bytes::Bytes::from(
|
||||
serde_json::to_vec(&serde_json::json!({
|
||||
@@ -2557,6 +2576,7 @@ mod tests {
|
||||
.mount(&mock_server)
|
||||
.await;
|
||||
|
||||
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
||||
let client = reqwest::Client::builder()
|
||||
.timeout(Duration::from_secs(5))
|
||||
.build()
|
||||
@@ -2674,6 +2694,7 @@ mod tests {
|
||||
}))
|
||||
.unwrap();
|
||||
|
||||
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
||||
let client = reqwest::Client::new();
|
||||
let result = proxy_to_backend(
|
||||
&client,
|
||||
@@ -2701,6 +2722,7 @@ mod tests {
|
||||
/// but if it ever did, we must not silently forward.
|
||||
#[test]
|
||||
fn bedrock_route_rejects_non_bedrock_path() {
|
||||
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
||||
let client = reqwest::Client::new();
|
||||
let route = test_route(
|
||||
"https://bedrock-bridge.example",
|
||||
|
||||
@@ -9,7 +9,7 @@ pub use openshell_core::inference::AuthHeader;
|
||||
|
||||
use crate::RouterError;
|
||||
|
||||
pub const DEFAULT_ROUTE_TIMEOUT: Duration = Duration::from_secs(60);
|
||||
pub const DEFAULT_ROUTE_TIMEOUT: Duration = Duration::from_mins(1);
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct RouterConfig {
|
||||
|
||||
@@ -37,6 +37,7 @@ pub struct Router {
|
||||
|
||||
impl Router {
|
||||
pub fn new() -> Result<Self, RouterError> {
|
||||
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
||||
let client = reqwest::Client::builder()
|
||||
.connect_timeout(Duration::from_secs(30))
|
||||
.build()
|
||||
|
||||
@@ -533,7 +533,6 @@ fn main() -> Result<()> {
|
||||
.build()
|
||||
.into_diagnostic()?;
|
||||
return runtime.block_on(async move {
|
||||
let _ = rustls::crypto::ring::default_provider().install_default();
|
||||
let exit = openshell_supervisor_process::debug_rpc::run(&raw_args[2..]).await?;
|
||||
std::process::exit(exit);
|
||||
});
|
||||
@@ -578,9 +577,6 @@ fn main() -> Result<()> {
|
||||
.into_diagnostic()?;
|
||||
|
||||
let result = runtime.block_on(async move {
|
||||
// Install rustls crypto provider before any TLS connections (including log push).
|
||||
let _ = rustls::crypto::ring::default_provider().install_default();
|
||||
|
||||
// Set up optional log push layer (gRPC mode only).
|
||||
let log_push_state = if let (Some(sandbox_id), Some(endpoint)) =
|
||||
(&args.sandbox_id, &args.openshell_endpoint)
|
||||
|
||||
@@ -139,6 +139,7 @@ pub async fn discover(issuer: &str, insecure: bool) -> Result<OidcDiscovery> {
|
||||
/// followed; OIDC providers should not redirect on the token endpoint.
|
||||
/// When `insecure` is true, TLS certificate verification is disabled.
|
||||
pub fn http_client(insecure: bool) -> reqwest::Client {
|
||||
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
||||
let mut builder = reqwest::ClientBuilder::new().redirect(reqwest::redirect::Policy::none());
|
||||
if insecure {
|
||||
builder = builder.danger_accept_invalid_certs(true);
|
||||
|
||||
@@ -175,7 +175,7 @@ impl TokenSource {
|
||||
})),
|
||||
refresher,
|
||||
flight: Arc::new(Mutex::new(Flight::default())),
|
||||
skew: Duration::from_secs(60),
|
||||
skew: Duration::from_mins(1),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -183,7 +183,7 @@ impl ServerCertVerifier for InsecureServerCertVerifier {
|
||||
}
|
||||
|
||||
fn supported_verify_schemes(&self) -> Vec<rustls::SignatureScheme> {
|
||||
rustls::crypto::ring::default_provider()
|
||||
rustls::crypto::aws_lc_rs::default_provider()
|
||||
.signature_verification_algorithms
|
||||
.supported_schemes()
|
||||
}
|
||||
|
||||
@@ -84,12 +84,12 @@ base64 = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
bytes = { workspace = true }
|
||||
pin-project-lite = { workspace = true }
|
||||
ring = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
toml = { workspace = true }
|
||||
tokio-stream = { workspace = true }
|
||||
sqlx = { workspace = true }
|
||||
sqlx-core = { workspace = true }
|
||||
reqwest = { workspace = true }
|
||||
aws-config = { workspace = true }
|
||||
aws-sdk-sts = { workspace = true }
|
||||
@@ -123,8 +123,8 @@ test-support = []
|
||||
|
||||
[dev-dependencies]
|
||||
base64 = { workspace = true }
|
||||
hyper-rustls = { version = "0.27", default-features = false, features = ["native-tokio", "http1", "tls12", "logging", "ring"] }
|
||||
rcgen = { version = "0.13", features = ["crypto", "pem"] }
|
||||
hyper-rustls = { version = "0.27", default-features = false, features = ["native-tokio", "http1", "tls12", "logging", "aws-lc-rs"] }
|
||||
rcgen = { workspace = true }
|
||||
rsa = { version = "0.9", features = ["pem"] }
|
||||
tokio-tungstenite = { workspace = true }
|
||||
futures-util = "0.3"
|
||||
|
||||
@@ -18,7 +18,7 @@ use std::collections::HashMap;
|
||||
use std::sync::Mutex;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
const DEFAULT_WINDOW: Duration = Duration::from_secs(60);
|
||||
const DEFAULT_WINDOW: Duration = Duration::from_mins(1);
|
||||
const DEFAULT_MAX_PER_WINDOW: u32 = 10;
|
||||
|
||||
/// Number of tracked sandboxes above which expired windows are pruned.
|
||||
@@ -102,7 +102,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn allows_a_burst_then_refuses_within_the_window() {
|
||||
let limiter = ExtensionMintLimiter::new(Duration::from_secs(60), 3);
|
||||
let limiter = ExtensionMintLimiter::new(Duration::from_mins(1), 3);
|
||||
let start = Instant::now();
|
||||
|
||||
for _ in 0..3 {
|
||||
@@ -113,17 +113,17 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn window_rollover_restores_capacity() {
|
||||
let limiter = ExtensionMintLimiter::new(Duration::from_secs(60), 1);
|
||||
let limiter = ExtensionMintLimiter::new(Duration::from_mins(1), 1);
|
||||
let start = Instant::now();
|
||||
|
||||
assert!(limiter.try_acquire_at("sandbox-a", start));
|
||||
assert!(!limiter.try_acquire_at("sandbox-a", start + Duration::from_secs(59)));
|
||||
assert!(limiter.try_acquire_at("sandbox-a", start + Duration::from_secs(60)));
|
||||
assert!(limiter.try_acquire_at("sandbox-a", start + Duration::from_mins(1)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sandboxes_are_limited_independently() {
|
||||
let limiter = ExtensionMintLimiter::new(Duration::from_secs(60), 1);
|
||||
let limiter = ExtensionMintLimiter::new(Duration::from_mins(1), 1);
|
||||
let start = Instant::now();
|
||||
|
||||
assert!(limiter.try_acquire_at("sandbox-a", start));
|
||||
@@ -147,7 +147,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn a_zero_bound_disables_limiting() {
|
||||
let limiter = ExtensionMintLimiter::new(Duration::from_secs(60), 0);
|
||||
let limiter = ExtensionMintLimiter::new(Duration::from_mins(1), 0);
|
||||
let start = Instant::now();
|
||||
for _ in 0..1_000 {
|
||||
assert!(limiter.try_acquire_at("sandbox-a", start));
|
||||
|
||||
@@ -407,6 +407,7 @@ impl JwksCache {
|
||||
);
|
||||
}
|
||||
|
||||
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
||||
let http = Client::builder()
|
||||
.timeout(Duration::from_secs(10))
|
||||
.build()
|
||||
@@ -1607,7 +1608,7 @@ mod tests {
|
||||
// cooldown window, even if the test task is descheduled while the
|
||||
// rest of the server suite runs in parallel.
|
||||
*cache.last_kid_miss_refresh.write().await =
|
||||
Instant::now().checked_add(Duration::from_secs(60)).unwrap();
|
||||
Instant::now().checked_add(Duration::from_mins(1)).unwrap();
|
||||
for _ in 0..4 {
|
||||
let err = cache.validate_token(&unknown_kid_token).await.unwrap_err();
|
||||
assert_eq!(err.code(), tonic::Code::Unauthenticated);
|
||||
|
||||
@@ -417,7 +417,7 @@ mod tests {
|
||||
}
|
||||
|
||||
fn pair() -> (SandboxJwtIssuer, SandboxJwtAuthenticator) {
|
||||
pair_with_ttl(Duration::from_secs(3600))
|
||||
pair_with_ttl(Duration::from_hours(1))
|
||||
}
|
||||
|
||||
fn pair_with_ttl(ttl: Duration) -> (SandboxJwtIssuer, SandboxJwtAuthenticator) {
|
||||
@@ -472,7 +472,7 @@ mod tests {
|
||||
mat.signing_key_pem.as_bytes(),
|
||||
mat.kid.clone(),
|
||||
"test-gateway",
|
||||
Duration::from_secs(3600),
|
||||
Duration::from_hours(1),
|
||||
)
|
||||
.expect("issuer");
|
||||
let auth = SandboxJwtAuthenticator::from_pem(
|
||||
@@ -582,7 +582,7 @@ mod tests {
|
||||
mat.signing_key_pem.as_bytes(),
|
||||
mat.kid.clone(),
|
||||
"g",
|
||||
Duration::from_secs(3600),
|
||||
Duration::from_hours(1),
|
||||
)
|
||||
.unwrap();
|
||||
let auth =
|
||||
@@ -623,7 +623,7 @@ mod tests {
|
||||
&extension_audience("urn:openshell:extension:middleware:scanner"),
|
||||
ExtensionCallerKind::Gateway,
|
||||
None,
|
||||
Duration::from_secs(300),
|
||||
Duration::from_mins(5),
|
||||
)
|
||||
.expect("gateway token");
|
||||
let mut validation = Validation::new(Algorithm::EdDSA);
|
||||
@@ -644,7 +644,7 @@ mod tests {
|
||||
&extension_audience("urn:openshell:extension:middleware:scanner"),
|
||||
ExtensionCallerKind::Supervisor,
|
||||
Some("sandbox-a"),
|
||||
Duration::from_secs(300),
|
||||
Duration::from_mins(5),
|
||||
)
|
||||
.expect("supervisor token");
|
||||
let claims = decode::<ExtensionJwtClaims>(&supervisor.token, &decoding_key, &validation)
|
||||
@@ -662,7 +662,7 @@ mod tests {
|
||||
mat.signing_key_pem.as_bytes(),
|
||||
mat.kid.clone(),
|
||||
"gateway-a",
|
||||
Duration::from_secs(3600),
|
||||
Duration::from_hours(1),
|
||||
)
|
||||
.expect("issuer");
|
||||
|
||||
@@ -671,7 +671,7 @@ mod tests {
|
||||
&extension_audience("urn:openshell:extension:middleware:scanner"),
|
||||
ExtensionCallerKind::Gateway,
|
||||
None,
|
||||
Duration::from_secs(300),
|
||||
Duration::from_mins(5),
|
||||
)
|
||||
.expect("extension token");
|
||||
assert_eq!(
|
||||
@@ -704,7 +704,7 @@ mod tests {
|
||||
&extension_audience("service-a"),
|
||||
ExtensionCallerKind::Gateway,
|
||||
None,
|
||||
Duration::from_secs(60),
|
||||
Duration::from_mins(1),
|
||||
)
|
||||
.expect("token");
|
||||
let decoding_key = DecodingKey::from_ed_pem(mat.public_key_pem.as_bytes()).unwrap();
|
||||
@@ -722,7 +722,7 @@ mod tests {
|
||||
&extension_audience("openshell-gateway:test-gateway"),
|
||||
ExtensionCallerKind::Supervisor,
|
||||
Some("sandbox-a"),
|
||||
Duration::from_secs(60),
|
||||
Duration::from_mins(1),
|
||||
)
|
||||
.expect_err("gateway sandbox audience must be reserved");
|
||||
assert_eq!(error.code(), tonic::Code::InvalidArgument);
|
||||
@@ -755,7 +755,7 @@ mod tests {
|
||||
&extension_audience("service"),
|
||||
ExtensionCallerKind::Supervisor,
|
||||
None,
|
||||
Duration::from_secs(60),
|
||||
Duration::from_mins(1),
|
||||
)
|
||||
.is_err()
|
||||
);
|
||||
@@ -765,7 +765,7 @@ mod tests {
|
||||
&extension_audience("service"),
|
||||
ExtensionCallerKind::Gateway,
|
||||
Some("sandbox-a"),
|
||||
Duration::from_secs(60),
|
||||
Duration::from_mins(1),
|
||||
)
|
||||
.is_err()
|
||||
);
|
||||
|
||||
@@ -230,10 +230,6 @@ pub async fn run_cli() -> Result<()> {
|
||||
|
||||
/// Run the gateway CLI with the compute drivers linked by the binary.
|
||||
pub async fn run_cli_with_compute_drivers(compute_drivers: ComputeDriverRegistry) -> Result<()> {
|
||||
rustls::crypto::ring::default_provider()
|
||||
.install_default()
|
||||
.map_err(|e| miette::miette!("failed to install rustls crypto provider: {e:?}"))?;
|
||||
|
||||
let matches = command().get_matches();
|
||||
let cli = Cli::from_arg_matches(&matches).expect("clap validated args");
|
||||
|
||||
|
||||
@@ -505,7 +505,7 @@ mod tests {
|
||||
l2.renew(&mut guard2).await.unwrap();
|
||||
|
||||
// Replica-1 cannot re-acquire (lease exists)
|
||||
let l1_retry = lease(store.clone(), "replica-1", Duration::from_secs(60));
|
||||
let l1_retry = lease(store.clone(), "replica-1", Duration::from_mins(1));
|
||||
let err = l1_retry.try_acquire().await.unwrap_err();
|
||||
assert!(matches!(err, LeaseError::AlreadyHeld));
|
||||
|
||||
|
||||
@@ -315,11 +315,11 @@ pub struct ComputeDriverInfoSnapshot {
|
||||
}
|
||||
|
||||
/// Interval between store-vs-backend reconciliation sweeps.
|
||||
const RECONCILE_INTERVAL: Duration = Duration::from_secs(60);
|
||||
const RECONCILE_INTERVAL: Duration = Duration::from_mins(1);
|
||||
|
||||
/// How long a sandbox can remain provisioning in the store without a
|
||||
/// corresponding backend resource before it is considered orphaned.
|
||||
const ORPHAN_GRACE_PERIOD: Duration = Duration::from_secs(300);
|
||||
const ORPHAN_GRACE_PERIOD: Duration = Duration::from_mins(5);
|
||||
|
||||
// Re-export the shared error type under the name used by this module.
|
||||
pub use openshell_core::ComputeDriverError as ComputeError;
|
||||
|
||||
@@ -23,7 +23,7 @@ use tonic::Status;
|
||||
use tracing::{info, warn};
|
||||
|
||||
/// How long an allocated slot survives without being consumed.
|
||||
const STAGING_TOKEN_TTL: Duration = Duration::from_secs(30 * 60);
|
||||
const STAGING_TOKEN_TTL: Duration = Duration::from_mins(30);
|
||||
/// Outstanding slots one caller may hold. Bounds the directories a single
|
||||
/// authenticated caller can create by calling `begin` in a loop.
|
||||
const MAX_SLOTS_PER_CALLER: usize = 4;
|
||||
|
||||
@@ -193,7 +193,7 @@ pub async fn handle_refresh_sandbox_token(
|
||||
}
|
||||
|
||||
const MAX_EXTENSION_CREDENTIALS_PER_REFRESH: usize = 64;
|
||||
const DEFAULT_EXTENSION_TOKEN_TTL: Duration = Duration::from_secs(15 * 60);
|
||||
const DEFAULT_EXTENSION_TOKEN_TTL: Duration = Duration::from_mins(15);
|
||||
|
||||
#[allow(clippy::result_large_err)]
|
||||
fn mint_extension_credentials(
|
||||
@@ -323,7 +323,7 @@ mod tests {
|
||||
mat.signing_key_pem.as_bytes(),
|
||||
mat.kid,
|
||||
"test-gateway",
|
||||
Duration::from_secs(3600),
|
||||
Duration::from_hours(1),
|
||||
)
|
||||
.unwrap();
|
||||
state.sandbox_jwt_issuer = Some(Arc::new(issuer));
|
||||
|
||||
@@ -3215,7 +3215,13 @@ pub(super) async fn handle_update_config(
|
||||
let update = request.get_ref();
|
||||
let should_emit_policy_failure = should_emit_config_update_policy_telemetry(sandbox_caller)
|
||||
&& (update.policy.is_some() || !update.merge_operations.is_empty());
|
||||
let result = handle_update_config_inner(state, request, &principal, sandbox_caller).await;
|
||||
let result = Box::pin(handle_update_config_inner(
|
||||
state,
|
||||
request,
|
||||
&principal,
|
||||
sandbox_caller,
|
||||
))
|
||||
.await;
|
||||
if result.is_err() && should_emit_policy_failure {
|
||||
emit_sandbox_policy_update_failure();
|
||||
}
|
||||
@@ -4599,7 +4605,7 @@ pub(super) async fn handle_submit_policy_analysis(
|
||||
// string means findings or infrastructure error, both of which
|
||||
// require human attention.
|
||||
if auto_approve_enabled
|
||||
&& let Err(err) = auto_approve_chunk(
|
||||
&& let Err(err) = Box::pin(auto_approve_chunk(
|
||||
state,
|
||||
&effective_id,
|
||||
AutoApproveChunkContext {
|
||||
@@ -4608,7 +4614,7 @@ pub(super) async fn handle_submit_policy_analysis(
|
||||
source: &req.analysis_mode,
|
||||
resolved_from,
|
||||
},
|
||||
)
|
||||
))
|
||||
.await
|
||||
{
|
||||
persist_pending_application_error(state, &effective_id, &err).await;
|
||||
|
||||
@@ -2362,6 +2362,7 @@ const MAX_INTERMEDIATE_TOKEN_CACHE_ENTRIES: usize = 1024;
|
||||
|
||||
static TOKEN_EXCHANGE_HTTP_CLIENT: LazyLock<Result<reqwest::Client, String>> =
|
||||
LazyLock::new(|| {
|
||||
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
||||
reqwest::Client::builder()
|
||||
.timeout(std::time::Duration::from_secs(30))
|
||||
.connect_timeout(std::time::Duration::from_secs(30))
|
||||
|
||||
@@ -940,6 +940,7 @@ async fn verify_provider_endpoint(
|
||||
model_id: &str,
|
||||
route: &ResolvedProviderRoute,
|
||||
) -> Result<ValidatedEndpoint, Status> {
|
||||
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
||||
let client = reqwest::Client::builder()
|
||||
.timeout(Duration::from_secs(30))
|
||||
.build()
|
||||
|
||||
@@ -98,7 +98,7 @@ struct GatewayExtensionCredential {
|
||||
|
||||
fn extension_token_ttl(issuer: &auth::sandbox_jwt::SandboxJwtIssuer) -> Duration {
|
||||
if issuer.ttl().is_zero() {
|
||||
Duration::from_secs(15 * 60)
|
||||
Duration::from_mins(15)
|
||||
} else {
|
||||
issuer.ttl().min(MAX_EXTENSION_TOKEN_TTL)
|
||||
}
|
||||
@@ -703,9 +703,9 @@ pub(crate) async fn run_server(
|
||||
}
|
||||
|
||||
state.compute.spawn_watchers(shutdown_rx.clone());
|
||||
ssh_sessions::spawn_session_reaper(store.clone(), Duration::from_secs(3600));
|
||||
ssh_sessions::spawn_session_reaper(store.clone(), Duration::from_hours(1));
|
||||
supervisor_session::spawn_relay_reaper(state.clone(), Duration::from_secs(30));
|
||||
provider_refresh::spawn_refresh_worker(state.clone(), Duration::from_secs(60));
|
||||
provider_refresh::spawn_refresh_worker(state.clone(), Duration::from_mins(1));
|
||||
|
||||
// Create the multiplexed service
|
||||
let service = MultiplexService::new(state.clone());
|
||||
@@ -1610,9 +1610,8 @@ mod tests {
|
||||
use tokio::sync::watch;
|
||||
|
||||
use crate::{
|
||||
compute::GatewayListenerRequirement,
|
||||
gateway_listener::GatewayListenerSpec,
|
||||
tls_test_utils::{generate_test_certs_with_ca, install_rustls_provider},
|
||||
compute::GatewayListenerRequirement, gateway_listener::GatewayListenerSpec,
|
||||
tls_test_utils::generate_test_certs_with_ca,
|
||||
};
|
||||
|
||||
static DETECTION_PROBE_ORDER: LazyLock<Mutex<Vec<&'static str>>> =
|
||||
@@ -1642,7 +1641,7 @@ mod tests {
|
||||
material.signing_key_pem.as_bytes(),
|
||||
material.kid,
|
||||
"gateway-a",
|
||||
Duration::from_secs(900),
|
||||
Duration::from_mins(15),
|
||||
)
|
||||
.expect("issuer"),
|
||||
)
|
||||
@@ -1773,8 +1772,6 @@ mod tests {
|
||||
}
|
||||
|
||||
fn test_tls_acceptor() -> (TempDir, TlsAcceptor) {
|
||||
install_rustls_provider();
|
||||
|
||||
let dir = tempdir().expect("failed to create tempdir");
|
||||
generate_test_certs_with_ca(dir.path());
|
||||
|
||||
|
||||
@@ -822,7 +822,8 @@ AND EXISTS (
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut query = sqlx::query(&sql)
|
||||
// Label paths above escape SQL quotes; all values remain bound parameters.
|
||||
let mut query = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.bind(object_type)
|
||||
.bind(member_type)
|
||||
.bind(member_name);
|
||||
|
||||
@@ -1537,6 +1537,7 @@ async fn request_token(
|
||||
}
|
||||
}
|
||||
|
||||
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
||||
let client = reqwest::Client::builder()
|
||||
.timeout(Duration::from_secs(30))
|
||||
.build()
|
||||
@@ -2401,6 +2402,7 @@ mod tests {
|
||||
.mount(&mock_server)
|
||||
.await;
|
||||
|
||||
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
||||
let response = reqwest::get(format!("{}/oversized", mock_server.uri()))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
@@ -1663,7 +1663,7 @@ mod tests {
|
||||
"sbx-test",
|
||||
relay_tx,
|
||||
Instant::now()
|
||||
.checked_sub(Duration::from_secs(60))
|
||||
.checked_sub(Duration::from_mins(1))
|
||||
.expect("test duration should be before now"),
|
||||
),
|
||||
);
|
||||
@@ -1741,7 +1741,7 @@ mod tests {
|
||||
"sbx-test",
|
||||
relay_tx,
|
||||
Instant::now()
|
||||
.checked_sub(Duration::from_secs(60))
|
||||
.checked_sub(Duration::from_mins(1))
|
||||
.expect("test duration should be before now"),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -18,7 +18,7 @@ use openshell_ocsf::{
|
||||
ConfigStateChangeBuilder, OCSF_TARGET, SandboxContext, SeverityId, StateId, StatusId,
|
||||
};
|
||||
use rustls::ServerConfig;
|
||||
use rustls::crypto::ring::sign;
|
||||
use rustls::crypto::aws_lc_rs::sign;
|
||||
use rustls::pki_types::{CertificateDer, PrivateKeyDer};
|
||||
use rustls::server::{ClientHello, ResolvesServerCert, WebPkiClientVerifier};
|
||||
use rustls::sign::CertifiedKey;
|
||||
@@ -488,9 +488,7 @@ fn tls_ocsf_ctx() -> SandboxContext {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::tls_test_utils::{
|
||||
generate_test_certs_with_ca, install_rustls_provider, write_test_file,
|
||||
};
|
||||
use crate::tls_test_utils::{generate_test_certs_with_ca, write_test_file};
|
||||
use rcgen::{CertificateParams, IsCa, KeyPair, KeyUsagePurpose};
|
||||
use tokio::net::{TcpListener, TcpStream};
|
||||
|
||||
@@ -532,7 +530,6 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_build_server_config() {
|
||||
install_rustls_provider();
|
||||
let dir = tempfile::tempdir().expect("failed to create tempdir");
|
||||
let _ = generate_test_certs_with_ca(dir.path());
|
||||
|
||||
@@ -553,7 +550,6 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_reload_success() {
|
||||
install_rustls_provider();
|
||||
let dir = tempfile::tempdir().expect("failed to create tempdir");
|
||||
let (ca_cert, ca_key) = generate_test_certs_with_ca(dir.path());
|
||||
|
||||
@@ -574,7 +570,6 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_reload_invalid_preserves_old() {
|
||||
install_rustls_provider();
|
||||
let dir = tempfile::tempdir().expect("failed to create tempdir");
|
||||
generate_test_certs_with_ca(dir.path());
|
||||
|
||||
@@ -607,8 +602,6 @@ mod tests {
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_concurrent_handshake_and_reload() {
|
||||
install_rustls_provider();
|
||||
|
||||
let dir = tempfile::tempdir().expect("failed to create tempdir");
|
||||
let (ca_cert, ca_key) = generate_test_certs_with_ca(dir.path());
|
||||
let acceptor = TlsAcceptor::from_files(
|
||||
@@ -702,8 +695,6 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_reload_serves_new_cert() {
|
||||
install_rustls_provider();
|
||||
|
||||
let dir = tempfile::tempdir().expect("failed to create tempdir");
|
||||
let (ca_cert, ca_key) = generate_test_certs_with_ca(dir.path());
|
||||
let acceptor = TlsAcceptor::from_files(
|
||||
@@ -778,8 +769,6 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_reload_worker_shutdown() {
|
||||
install_rustls_provider();
|
||||
|
||||
let dir = tempfile::tempdir().expect("failed to create tempdir");
|
||||
generate_test_certs_with_ca(dir.path());
|
||||
let acceptor = TlsAcceptor::from_files(
|
||||
@@ -812,8 +801,6 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_reload_worker_detects_file_change() {
|
||||
install_rustls_provider();
|
||||
|
||||
let dir = tempfile::tempdir().expect("failed to create tempdir");
|
||||
let (ca_cert, ca_key) = generate_test_certs_with_ca(dir.path());
|
||||
let acceptor = TlsAcceptor::from_files(
|
||||
@@ -902,8 +889,6 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_reload_mtls_ca_rotation() {
|
||||
install_rustls_provider();
|
||||
|
||||
let dir = tempfile::tempdir().expect("failed to create tempdir");
|
||||
let (initial_ca_cert, initial_ca_key) = generate_test_certs_with_ca(dir.path());
|
||||
|
||||
@@ -1110,7 +1095,6 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_build_cert_resolver_returns_none_when_no_external() {
|
||||
install_rustls_provider();
|
||||
let dir = tempfile::tempdir().expect("failed to create tempdir");
|
||||
generate_test_certs_with_ca(dir.path());
|
||||
|
||||
@@ -1127,7 +1111,6 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_build_cert_resolver_errors_on_cert_without_key() {
|
||||
install_rustls_provider();
|
||||
let dir = tempfile::tempdir().expect("failed to create tempdir");
|
||||
generate_test_certs_with_ca(dir.path());
|
||||
|
||||
@@ -1147,7 +1130,6 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_build_cert_resolver_errors_on_key_without_cert() {
|
||||
install_rustls_provider();
|
||||
let dir = tempfile::tempdir().expect("failed to create tempdir");
|
||||
generate_test_certs_with_ca(dir.path());
|
||||
|
||||
@@ -1167,7 +1149,6 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_build_cert_resolver_errors_on_empty_server_names() {
|
||||
install_rustls_provider();
|
||||
let dir = tempfile::tempdir().expect("failed to create tempdir");
|
||||
let (ca_cert, ca_key) = generate_test_certs_with_ca(dir.path());
|
||||
generate_named_cert(
|
||||
@@ -1195,7 +1176,6 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_dual_cert_resolver_returns_external_on_sni_match() {
|
||||
install_rustls_provider();
|
||||
let dir = tempfile::tempdir().expect("failed to create tempdir");
|
||||
let (ca_cert, ca_key) = generate_test_certs_with_ca(dir.path());
|
||||
generate_named_cert(
|
||||
@@ -1233,8 +1213,6 @@ mod tests {
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_dual_cert_resolver_sni_selects_correct_cert() {
|
||||
install_rustls_provider();
|
||||
|
||||
let dir = tempfile::tempdir().expect("failed to create tempdir");
|
||||
let (ca_cert, ca_key) = generate_test_certs_with_ca(dir.path());
|
||||
generate_named_cert(
|
||||
|
||||
@@ -9,14 +9,6 @@ use std::path::Path;
|
||||
|
||||
use rcgen::{CertificateParams, IsCa, KeyPair};
|
||||
|
||||
/// Install the default rustls crypto provider.
|
||||
///
|
||||
/// Must be called once at the start of any test that exercises TLS handshakes.
|
||||
/// Multiple calls are harmless (subsequent calls return an error, ignored).
|
||||
pub fn install_rustls_provider() {
|
||||
let _ = rustls::crypto::ring::default_provider().install_default();
|
||||
}
|
||||
|
||||
/// Write bytes to a file inside `dir`, panicking on failure.
|
||||
pub fn write_test_file(dir: &Path, name: &str, data: &[u8]) {
|
||||
let path = dir.join(name);
|
||||
|
||||
@@ -613,11 +613,6 @@ impl OpenShell for TestOpenShell {
|
||||
// TLS / PKI helpers (used by TLS integration tests)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// Initialise the rustls crypto provider (idempotent).
|
||||
pub fn install_rustls_provider() {
|
||||
let _ = rustls::crypto::ring::default_provider().install_default();
|
||||
}
|
||||
|
||||
/// PKI bundle: CA cert, server cert+key, client cert+key (all PEM).
|
||||
#[allow(clippy::struct_field_names)]
|
||||
pub struct PkiBundle {
|
||||
|
||||
@@ -29,7 +29,7 @@ mod common;
|
||||
use bytes::Bytes;
|
||||
use common::{
|
||||
PkiBundle, build_tls_root, generate_pki, generate_rogue_pki, grpc_client_mtls,
|
||||
install_rustls_provider, start_test_server,
|
||||
start_test_server,
|
||||
};
|
||||
use http_body_util::Empty;
|
||||
use hyper::{Request, StatusCode};
|
||||
@@ -160,7 +160,6 @@ fn https_client_no_cert(
|
||||
/// Valid client cert is accepted when a CA is configured.
|
||||
#[tokio::test]
|
||||
async fn mtls_valid_client_cert_accepted() {
|
||||
install_rustls_provider();
|
||||
let (temp, pki) = generate_pki();
|
||||
|
||||
let tls_acceptor = TlsAcceptor::from_files(
|
||||
@@ -204,7 +203,6 @@ async fn mtls_valid_client_cert_accepted() {
|
||||
/// always optional. Auth is deferred to the application layer.
|
||||
#[tokio::test]
|
||||
async fn no_client_cert_accepted_with_ca_configured() {
|
||||
install_rustls_provider();
|
||||
let (temp, pki) = generate_pki();
|
||||
|
||||
let tls_acceptor = TlsAcceptor::from_files(
|
||||
@@ -250,7 +248,6 @@ async fn no_client_cert_accepted_with_ca_configured() {
|
||||
/// cert is presented.
|
||||
#[tokio::test]
|
||||
async fn bearer_header_reaches_server_without_client_cert() {
|
||||
install_rustls_provider();
|
||||
let (temp, pki) = generate_pki();
|
||||
|
||||
let tls_acceptor = TlsAcceptor::from_files(
|
||||
@@ -284,7 +281,6 @@ async fn bearer_header_reaches_server_without_client_cert() {
|
||||
/// client certs are optional — presented certs are still validated.
|
||||
#[tokio::test]
|
||||
async fn rogue_cert_rejected() {
|
||||
install_rustls_provider();
|
||||
let (temp, pki) = generate_pki();
|
||||
|
||||
let tls_acceptor = TlsAcceptor::from_files(
|
||||
@@ -333,7 +329,6 @@ async fn rogue_cert_rejected() {
|
||||
/// client certificates. Clients connect with server-only TLS.
|
||||
#[tokio::test]
|
||||
async fn https_only_no_client_cert_required() {
|
||||
install_rustls_provider();
|
||||
let (temp, pki) = generate_pki();
|
||||
|
||||
let tls_acceptor = TlsAcceptor::from_files(
|
||||
|
||||
@@ -6,7 +6,7 @@ mod common;
|
||||
use bytes::Bytes;
|
||||
use common::{
|
||||
PkiBundle, build_tls_root, generate_pki, generate_rogue_pki, grpc_client_mtls,
|
||||
install_rustls_provider, start_test_server,
|
||||
start_test_server,
|
||||
};
|
||||
use http_body_util::Empty;
|
||||
use hyper::Request;
|
||||
@@ -54,7 +54,6 @@ fn https_client_mtls(
|
||||
|
||||
#[tokio::test]
|
||||
async fn serves_grpc_and_http_over_tls_on_same_port() {
|
||||
install_rustls_provider();
|
||||
let (temp, pki) = generate_pki();
|
||||
|
||||
let tls_acceptor = openshell_server::TlsAcceptor::from_files(
|
||||
@@ -96,7 +95,6 @@ async fn serves_grpc_and_http_over_tls_on_same_port() {
|
||||
|
||||
#[tokio::test]
|
||||
async fn mtls_valid_client_cert_accepted() {
|
||||
install_rustls_provider();
|
||||
let (temp, pki) = generate_pki();
|
||||
|
||||
let tls_acceptor = openshell_server::TlsAcceptor::from_files(
|
||||
@@ -127,7 +125,6 @@ async fn mtls_valid_client_cert_accepted() {
|
||||
|
||||
#[tokio::test]
|
||||
async fn no_client_cert_accepted_with_ca() {
|
||||
install_rustls_provider();
|
||||
let (temp, pki) = generate_pki();
|
||||
|
||||
let tls_acceptor = openshell_server::TlsAcceptor::from_files(
|
||||
@@ -166,7 +163,6 @@ async fn no_client_cert_accepted_with_ca() {
|
||||
|
||||
#[tokio::test]
|
||||
async fn no_client_cert_rejected_when_required() {
|
||||
install_rustls_provider();
|
||||
let (temp, pki) = generate_pki();
|
||||
|
||||
let tls_acceptor = openshell_server::TlsAcceptor::from_files(
|
||||
@@ -206,7 +202,6 @@ async fn no_client_cert_rejected_when_required() {
|
||||
|
||||
#[tokio::test]
|
||||
async fn mtls_wrong_ca_client_cert_rejected() {
|
||||
install_rustls_provider();
|
||||
let (temp, pki) = generate_pki();
|
||||
|
||||
let tls_acceptor = openshell_server::TlsAcceptor::from_files(
|
||||
|
||||
@@ -472,7 +472,7 @@ mod tests {
|
||||
);
|
||||
assert_eq!(
|
||||
routes[1].timeout,
|
||||
Duration::from_secs(120),
|
||||
Duration::from_mins(2),
|
||||
"timeout_secs=120 should map to 120s"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7732,7 +7732,7 @@ network_policies:
|
||||
.await
|
||||
});
|
||||
|
||||
let scenario = tokio::time::timeout(std::time::Duration::from_secs(60), async {
|
||||
let scenario = tokio::time::timeout(std::time::Duration::from_mins(1), async {
|
||||
app.write_all(
|
||||
b"GET /ws HTTP/1.1\r\nHost: api.example.test\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Extensions: permessage-deflate; client_no_context_takeover\r\n\r\n",
|
||||
)
|
||||
|
||||
@@ -465,7 +465,6 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn upstream_config_alpn() {
|
||||
let _ = rustls::crypto::ring::default_provider().install_default();
|
||||
let config = build_upstream_client_config("").unwrap();
|
||||
assert_eq!(config.alpn_protocols, vec![b"http/1.1".to_vec()]);
|
||||
}
|
||||
|
||||
@@ -30,8 +30,8 @@ pub const MAX_QUEUED_WEBSOCKET_ASSEMBLIES: usize = MAX_CONCURRENT_WEBSOCKET_ASSE
|
||||
const MAX_RAW_FRAME_PAYLOAD_BYTES: u64 = 16 * 1024 * 1024;
|
||||
const MAX_MESSAGE_FRAGMENTS: usize = 4096;
|
||||
const TEXT_MESSAGE_ASSEMBLY_IDLE_TIMEOUT: StdDuration = StdDuration::from_secs(30);
|
||||
const TEXT_MESSAGE_ASSEMBLY_TOTAL_TIMEOUT: StdDuration = StdDuration::from_secs(120);
|
||||
const TEXT_MESSAGE_FORWARD_TOTAL_TIMEOUT: StdDuration = StdDuration::from_secs(120);
|
||||
const TEXT_MESSAGE_ASSEMBLY_TOTAL_TIMEOUT: StdDuration = StdDuration::from_mins(2);
|
||||
const TEXT_MESSAGE_FORWARD_TOTAL_TIMEOUT: StdDuration = StdDuration::from_mins(2);
|
||||
const COPY_BUF_SIZE: usize = 8192;
|
||||
const OPCODE_CONTINUATION: u8 = 0x0;
|
||||
const OPCODE_TEXT: u8 = 0x1;
|
||||
|
||||
@@ -580,7 +580,7 @@ mod tests {
|
||||
calls: AtomicUsize::new(0),
|
||||
answer: TrustedAnswer {
|
||||
addresses,
|
||||
ttl: Duration::from_secs(300),
|
||||
ttl: Duration::from_mins(5),
|
||||
},
|
||||
},
|
||||
Arc::new(ResolvedEndpointStore::new(
|
||||
@@ -984,6 +984,6 @@ process: { run_as_user: sandbox, run_as_group: sandbox }
|
||||
clamp_mapping_ttl(Duration::from_secs(10)),
|
||||
Duration::from_secs(10)
|
||||
);
|
||||
assert_eq!(clamp_mapping_ttl(Duration::from_secs(300)), MAX_MAPPING_TTL);
|
||||
assert_eq!(clamp_mapping_ttl(Duration::from_mins(5)), MAX_MAPPING_TTL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ const MAX_STREAMING_BODY: usize = 1024;
|
||||
/// between "thinking" and output phases. 120s provides headroom while still
|
||||
/// catching genuinely stuck streams.
|
||||
#[cfg(not(test))]
|
||||
const CHUNK_IDLE_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(120);
|
||||
const CHUNK_IDLE_TIMEOUT: std::time::Duration = std::time::Duration::from_mins(2);
|
||||
// Exercise idle-timeout truncation without slowing the full package test suite.
|
||||
#[cfg(test)]
|
||||
const CHUNK_IDLE_TIMEOUT: std::time::Duration = std::time::Duration::from_millis(100);
|
||||
@@ -6783,7 +6783,7 @@ network_policies:
|
||||
)
|
||||
.await
|
||||
});
|
||||
let scenario = tokio::time::timeout(std::time::Duration::from_secs(60), async {
|
||||
let scenario = tokio::time::timeout(std::time::Duration::from_mins(1), async {
|
||||
let (client, upstream) = tokio::join!(client, upstream);
|
||||
client.expect("join plaintext WebSocket client");
|
||||
assert_eq!(
|
||||
|
||||
@@ -49,6 +49,7 @@ use spiffe::WorkloadApiClient;
|
||||
/// Token cache shared across all provider token grants.
|
||||
static TOKEN_CACHE: LazyLock<TokenCache> = LazyLock::new(TokenCache::new);
|
||||
static TOKEN_GRANT_HTTP_CLIENT: LazyLock<reqwest::Client> = LazyLock::new(|| {
|
||||
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
||||
reqwest::Client::builder()
|
||||
.timeout(Duration::from_secs(30))
|
||||
.connect_timeout(Duration::from_secs(30))
|
||||
|
||||
@@ -1129,13 +1129,6 @@ mod tests {
|
||||
config_from(pairs).unwrap().unwrap()
|
||||
}
|
||||
|
||||
/// Install the process-wide rustls crypto provider once. Building a
|
||||
/// `ClientConfig` (for an `https://` proxy) requires it; the install is
|
||||
/// idempotent, so tests that build TLS configs call this first.
|
||||
fn install_crypto_provider() {
|
||||
let _ = rustls::crypto::ring::default_provider().install_default();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn no_env_yields_none() {
|
||||
assert!(config_from(&[]).unwrap().is_none());
|
||||
@@ -1270,7 +1263,6 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn https_proxy_scheme_enables_tls_and_requires_explicit_port() {
|
||||
install_crypto_provider();
|
||||
// An explicit port is required (no scheme-default fallback), matching
|
||||
// the http:// grammar.
|
||||
let err = config_from(&[(HTTPS_PROXY, "https://proxy.corp.com")]).unwrap_err();
|
||||
@@ -1314,7 +1306,6 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn unreadable_ca_bundle_is_fatal_for_https_proxy() {
|
||||
install_crypto_provider();
|
||||
let err = config_from(&[
|
||||
(HTTPS_PROXY, "https://proxy.corp.com:3130"),
|
||||
(PROXY_CA_BUNDLE, "/nonexistent/proxy-ca.pem"),
|
||||
@@ -1338,7 +1329,6 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn ca_bundle_with_no_certificates_is_fatal() {
|
||||
install_crypto_provider();
|
||||
let bundle = tempfile::NamedTempFile::new().unwrap();
|
||||
std::fs::write(bundle.path(), "not a certificate\n").unwrap();
|
||||
let path = bundle.path().to_string_lossy().into_owned();
|
||||
@@ -1352,7 +1342,6 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn ca_bundle_with_invalid_der_certificates_is_fatal() {
|
||||
install_crypto_provider();
|
||||
let bundle = tempfile::NamedTempFile::new().unwrap();
|
||||
std::fs::write(
|
||||
bundle.path(),
|
||||
@@ -1439,7 +1428,6 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn auth_file_without_insecure_acknowledgement_is_allowed_for_https_proxy() {
|
||||
install_crypto_provider();
|
||||
let file = tempfile::NamedTempFile::new().unwrap();
|
||||
std::fs::write(file.path(), "user:secret\n").unwrap();
|
||||
let path = file.path().to_str().unwrap().to_string();
|
||||
@@ -2013,8 +2001,6 @@ mod tests {
|
||||
|
||||
const SERVER_HOSTNAME: &str = "upstream.example.test";
|
||||
|
||||
let _ = rustls::crypto::ring::default_provider().install_default();
|
||||
|
||||
// Trusted CA; the client config trusts it, and the fake upstream
|
||||
// server presents a leaf for SERVER_HOSTNAME signed by it.
|
||||
let ca = tls::SandboxCa::generate().unwrap();
|
||||
@@ -2246,7 +2232,6 @@ mod tests {
|
||||
/// the server task (yielding the received CONNECT request), and the
|
||||
/// server certificate PEM to use as the corporate CA bundle.
|
||||
async fn fake_tls_proxy() -> (SocketAddr, tokio::task::JoinHandle<String>, String) {
|
||||
install_crypto_provider();
|
||||
let key = rcgen::KeyPair::generate().unwrap();
|
||||
let cert = rcgen::CertificateParams::new(vec!["127.0.0.1".to_string()])
|
||||
.unwrap()
|
||||
|
||||
@@ -53,6 +53,7 @@ registries = []
|
||||
|
||||
# -- Bans ----------------------------------------------------------------------
|
||||
[bans]
|
||||
deny = [{ name = "ring", reason = "Use the AWS-LC crypto backend instead." }]
|
||||
multiple-versions = "warn"
|
||||
wildcards = "allow"
|
||||
highlight = "all"
|
||||
|
||||
@@ -74,9 +74,7 @@ COPY crates/openshell-prover/Cargo.toml crates/openshell-prover/Cargo.toml
|
||||
COPY crates/openshell-core/build.rs crates/openshell-core/build.rs
|
||||
COPY proto/ proto/
|
||||
|
||||
# Scope workspace to CLI crates only — avoids compiling aws-lc-sys (pulled
|
||||
# by russh in openshell-sandbox/openshell-server) which is difficult to
|
||||
# cross-compile and unnecessary for the CLI binary.
|
||||
# Scope workspace to CLI crates only to avoid compiling unrelated runtimes.
|
||||
RUN sed -i 's|members = \["crates/\*"\]|members = ["crates/openshell-cli", "crates/openshell-core", "crates/openshell-bootstrap", "crates/openshell-policy", "crates/openshell-prover", "crates/openshell-providers", "crates/openshell-tui"]|' Cargo.toml
|
||||
|
||||
RUN mkdir -p crates/openshell-cli/src \
|
||||
|
||||
Generated
+117
-102
@@ -31,6 +31,30 @@ version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
|
||||
|
||||
[[package]]
|
||||
name = "aws-lc-rs"
|
||||
version = "1.18.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b281d307588d634de920874890732659e2e7672f72b5e10e81badc1a8a83621e"
|
||||
dependencies = [
|
||||
"aws-lc-sys",
|
||||
"untrusted",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-lc-sys"
|
||||
version = "0.45.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9bff6c3b54fad79a2e60b8102caf565819711497c1f5f092f49508e2f5c31b27"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cmake",
|
||||
"dunce",
|
||||
"fs_extra",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "axum"
|
||||
version = "0.8.9"
|
||||
@@ -157,6 +181,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5add81bb678e6cb321aff7fa0dc7689ad82b112dbc032cea19f91d6b8e3582b9"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"jobserver",
|
||||
"libc",
|
||||
"shlex",
|
||||
]
|
||||
|
||||
@@ -172,6 +198,15 @@ version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527"
|
||||
|
||||
[[package]]
|
||||
name = "cmake"
|
||||
version = "0.1.58"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.17"
|
||||
@@ -218,6 +253,12 @@ dependencies = [
|
||||
"syn 3.0.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dunce"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.17.0"
|
||||
@@ -237,7 +278,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -267,6 +308,12 @@ dependencies = [
|
||||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fs_extra"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
|
||||
|
||||
[[package]]
|
||||
name = "futures-channel"
|
||||
version = "0.3.33"
|
||||
@@ -346,10 +393,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
"libc",
|
||||
"wasi",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -665,6 +710,16 @@ version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
|
||||
|
||||
[[package]]
|
||||
name = "jobserver"
|
||||
version = "0.1.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1c00acbd29eabad4a2392fa0e921c874934dbbf4194312ad20f04a0ed67a3cb3"
|
||||
dependencies = [
|
||||
"getrandom 0.4.3",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.103"
|
||||
@@ -678,17 +733,20 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "jsonwebtoken"
|
||||
version = "9.3.1"
|
||||
version = "10.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a87cc7a48537badeae96744432de36f4be2b4a34a05a5ef32e9dd8a1c169dde"
|
||||
checksum = "eba32bfb4ffdeaca3e34431072faf01745c9b26d25504aa7a6cf5684334fc4fc"
|
||||
dependencies = [
|
||||
"aws-lc-rs",
|
||||
"base64",
|
||||
"getrandom 0.2.17",
|
||||
"js-sys",
|
||||
"pem",
|
||||
"ring",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"signature",
|
||||
"simple_asn1",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -756,7 +814,7 @@ checksum = "30d65c71f1ce40ab09135ce117d742b9f8a19ff91a41a8b57ed50bc2de59c427"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"wasi",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -923,6 +981,12 @@ version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548"
|
||||
|
||||
[[package]]
|
||||
name = "potential_utf"
|
||||
version = "0.1.5"
|
||||
@@ -1007,7 +1071,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41"
|
||||
dependencies = [
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
"rand_core 0.9.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1017,7 +1081,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
"rand_core 0.9.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom 0.2.17",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1038,20 +1111,6 @@ dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.17.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"getrandom 0.2.17",
|
||||
"libc",
|
||||
"untrusted",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "2.1.3"
|
||||
@@ -1068,7 +1127,7 @@ dependencies = [
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1218,6 +1277,15 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signature"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
|
||||
dependencies = [
|
||||
"rand_core 0.6.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simple_asn1"
|
||||
version = "0.6.4"
|
||||
@@ -1249,7 +1317,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1307,7 +1375,7 @@ dependencies = [
|
||||
"getrandom 0.4.3",
|
||||
"once_cell",
|
||||
"rustix",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1384,7 +1452,7 @@ dependencies = [
|
||||
"signal-hook-registry",
|
||||
"socket2",
|
||||
"tokio-macros",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1545,9 +1613,9 @@ checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||
|
||||
[[package]]
|
||||
name = "untrusted"
|
||||
version = "0.9.0"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
|
||||
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
@@ -1670,15 +1738,6 @@ version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.61.2"
|
||||
@@ -1688,70 +1747,6 @@ dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
|
||||
[[package]]
|
||||
name = "wit-bindgen"
|
||||
version = "0.57.1"
|
||||
@@ -1828,6 +1823,26 @@ dependencies = [
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zeroize"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e"
|
||||
dependencies = [
|
||||
"zeroize_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zeroize_derive"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c50655cbb0fe3fc43170059e702f1ce5e19b84cec58dc87b037a09935c2f328"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerotrie"
|
||||
version = "0.2.4"
|
||||
|
||||
+1
-1
@@ -211,7 +211,7 @@ futures-util = "0.3"
|
||||
http-body-util = "0.1"
|
||||
hyper = { version = "1", features = ["client", "http1"] }
|
||||
hyper-util = { version = "0.1", features = ["tokio"] }
|
||||
jsonwebtoken = "9"
|
||||
jsonwebtoken = { version = "10", features = ["aws_lc_rs"] }
|
||||
prost = "0.14"
|
||||
tokio = { version = "1.43", features = ["full"] }
|
||||
tokio-stream = { version = "0.1", features = ["net"] }
|
||||
|
||||
+115
-12
@@ -55,6 +55,30 @@ version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
|
||||
|
||||
[[package]]
|
||||
name = "aws-lc-rs"
|
||||
version = "1.18.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b281d307588d634de920874890732659e2e7672f72b5e10e81badc1a8a83621e"
|
||||
dependencies = [
|
||||
"aws-lc-sys",
|
||||
"untrusted 0.7.1",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-lc-sys"
|
||||
version = "0.45.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9bff6c3b54fad79a2e60b8102caf565819711497c1f5f092f49508e2f5c31b27"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cmake",
|
||||
"dunce",
|
||||
"fs_extra",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "axum"
|
||||
version = "0.8.9"
|
||||
@@ -162,6 +186,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e228eec9be7c17ccb640b59b36a5cd805ea2a564a4c5e162c2f659fea30d3b96"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"jobserver",
|
||||
"libc",
|
||||
"shlex",
|
||||
]
|
||||
|
||||
@@ -185,7 +211,16 @@ checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures 0.3.0",
|
||||
"rand_core",
|
||||
"rand_core 0.10.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cmake"
|
||||
version = "0.1.58"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -281,6 +316,12 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dunce"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.16.0"
|
||||
@@ -342,6 +383,12 @@ dependencies = [
|
||||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fs_extra"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
|
||||
|
||||
[[package]]
|
||||
name = "futures-channel"
|
||||
version = "0.3.32"
|
||||
@@ -398,10 +445,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
"libc",
|
||||
"wasi",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -413,7 +458,7 @@ dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"r-efi",
|
||||
"rand_core",
|
||||
"rand_core 0.10.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -778,6 +823,16 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jobserver"
|
||||
version = "0.1.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1c00acbd29eabad4a2392fa0e921c874934dbbf4194312ad20f04a0ed67a3cb3"
|
||||
dependencies = [
|
||||
"getrandom 0.4.3",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.103"
|
||||
@@ -791,17 +846,20 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "jsonwebtoken"
|
||||
version = "9.3.1"
|
||||
version = "10.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a87cc7a48537badeae96744432de36f4be2b4a34a05a5ef32e9dd8a1c169dde"
|
||||
checksum = "eba32bfb4ffdeaca3e34431072faf01745c9b26d25504aa7a6cf5684334fc4fc"
|
||||
dependencies = [
|
||||
"aws-lc-rs",
|
||||
"base64",
|
||||
"getrandom 0.2.17",
|
||||
"js-sys",
|
||||
"pem",
|
||||
"ring",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"signature",
|
||||
"simple_asn1",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1183,6 +1241,12 @@ version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548"
|
||||
|
||||
[[package]]
|
||||
name = "portable-atomic"
|
||||
version = "1.15.0"
|
||||
@@ -1396,7 +1460,16 @@ checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80"
|
||||
dependencies = [
|
||||
"chacha20",
|
||||
"getrandom 0.4.3",
|
||||
"rand_core",
|
||||
"rand_core 0.10.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom 0.2.17",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1411,8 +1484,8 @@ version = "0.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75e669e5202259b5314d1ea5397316ad400819437857b90861765f24c4cf80a2"
|
||||
dependencies = [
|
||||
"aws-lc-rs",
|
||||
"pem",
|
||||
"ring",
|
||||
"rustls-pki-types",
|
||||
"time",
|
||||
"yasna",
|
||||
@@ -1466,7 +1539,7 @@ dependencies = [
|
||||
"cfg-if",
|
||||
"getrandom 0.2.17",
|
||||
"libc",
|
||||
"untrusted",
|
||||
"untrusted 0.9.0",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
@@ -1510,9 +1583,9 @@ version = "0.23.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b92b125634d9b795e7beca796cc790df15a7fb38323bf3196fda83292d06b1f"
|
||||
dependencies = [
|
||||
"aws-lc-rs",
|
||||
"log",
|
||||
"once_cell",
|
||||
"ring",
|
||||
"rustls-pki-types",
|
||||
"rustls-webpki",
|
||||
"subtle",
|
||||
@@ -1555,9 +1628,10 @@ version = "0.103.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e"
|
||||
dependencies = [
|
||||
"aws-lc-rs",
|
||||
"ring",
|
||||
"rustls-pki-types",
|
||||
"untrusted",
|
||||
"untrusted 0.9.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1699,6 +1773,15 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signature"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
|
||||
dependencies = [
|
||||
"rand_core 0.6.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simd_cesu8"
|
||||
version = "1.2.0"
|
||||
@@ -2154,6 +2237,12 @@ version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254"
|
||||
|
||||
[[package]]
|
||||
name = "untrusted"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
|
||||
|
||||
[[package]]
|
||||
name = "untrusted"
|
||||
version = "0.9.0"
|
||||
@@ -2415,6 +2504,20 @@ name = "zeroize"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e"
|
||||
dependencies = [
|
||||
"zeroize_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zeroize_derive"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c50655cbb0fe3fc43170059e702f1ce5e19b84cec58dc87b037a09935c2f328"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerotrie"
|
||||
|
||||
@@ -7,18 +7,18 @@
|
||||
name = "openshell-governance-interceptor-example"
|
||||
version = "0.0.0"
|
||||
edition = "2024"
|
||||
rust-version = "1.90"
|
||||
rust-version = "1.94"
|
||||
license = "Apache-2.0"
|
||||
|
||||
[dependencies]
|
||||
jsonwebtoken = "9"
|
||||
jsonwebtoken = { version = "10", features = ["aws_lc_rs"] }
|
||||
openshell-core = { path = "../../crates/openshell-core", default-features = false }
|
||||
openshell-policy = { path = "../../crates/openshell-policy" }
|
||||
openshell-providers = { path = "../../crates/openshell-providers" }
|
||||
prost = "0.14"
|
||||
prost-reflect = { version = "0.16.5", features = ["serde"] }
|
||||
prost-types = "0.14"
|
||||
rcgen = { version = "0.13", features = ["crypto", "pem"] }
|
||||
rcgen = { version = "0.13", default-features = false, features = ["crypto", "pem", "aws_lc_rs"] }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
serde_yml = { package = "noyalib", version = "0.0.28", default-features = false, features = ["std", "compat-serde-yaml"] }
|
||||
|
||||
+64
-1
@@ -99,6 +99,29 @@ version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
|
||||
|
||||
[[package]]
|
||||
name = "aws-lc-rs"
|
||||
version = "1.18.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b281d307588d634de920874890732659e2e7672f72b5e10e81badc1a8a83621e"
|
||||
dependencies = [
|
||||
"aws-lc-sys",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-lc-sys"
|
||||
version = "0.45.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9bff6c3b54fad79a2e60b8102caf565819711497c1f5f092f49508e2f5c31b27"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cmake",
|
||||
"dunce",
|
||||
"fs_extra",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "axum"
|
||||
version = "0.8.9"
|
||||
@@ -191,6 +214,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e228eec9be7c17ccb640b59b36a5cd805ea2a564a4c5e162c2f659fea30d3b96"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"jobserver",
|
||||
"libc",
|
||||
"shlex",
|
||||
]
|
||||
|
||||
@@ -246,6 +271,15 @@ version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9"
|
||||
|
||||
[[package]]
|
||||
name = "cmake"
|
||||
version = "0.1.58"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.5"
|
||||
@@ -279,6 +313,12 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dunce"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.16.0"
|
||||
@@ -340,6 +380,12 @@ dependencies = [
|
||||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fs_extra"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
|
||||
|
||||
[[package]]
|
||||
name = "futures-channel"
|
||||
version = "0.3.32"
|
||||
@@ -699,6 +745,16 @@ version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
|
||||
|
||||
[[package]]
|
||||
name = "jobserver"
|
||||
version = "0.1.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1c00acbd29eabad4a2392fa0e921c874934dbbf4194312ad20f04a0ed67a3cb3"
|
||||
dependencies = [
|
||||
"getrandom 0.4.3",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.186"
|
||||
@@ -970,6 +1026,12 @@ version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548"
|
||||
|
||||
[[package]]
|
||||
name = "potential_utf"
|
||||
version = "0.1.5"
|
||||
@@ -1227,9 +1289,9 @@ version = "0.23.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b92b125634d9b795e7beca796cc790df15a7fb38323bf3196fda83292d06b1f"
|
||||
dependencies = [
|
||||
"aws-lc-rs",
|
||||
"log",
|
||||
"once_cell",
|
||||
"ring",
|
||||
"rustls-pki-types",
|
||||
"rustls-webpki",
|
||||
"subtle",
|
||||
@@ -1272,6 +1334,7 @@ version = "0.103.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e"
|
||||
dependencies = [
|
||||
"aws-lc-rs",
|
||||
"ring",
|
||||
"rustls-pki-types",
|
||||
"untrusted",
|
||||
|
||||
@@ -8,7 +8,7 @@ name = "openshell-supervisor-middleware-content-guard"
|
||||
description = "Example OpenShell supervisor middleware service"
|
||||
version = "0.0.0"
|
||||
edition = "2024"
|
||||
rust-version = "1.90"
|
||||
rust-version = "1.94"
|
||||
license = "Apache-2.0"
|
||||
publish = false
|
||||
|
||||
|
||||
Reference in New Issue
Block a user