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:
Simon Scatton
2026-09-09 17:57:42 +00:00
committed by GitHub
parent 8af79a7f4b
commit 48c449d8c8
76 changed files with 927 additions and 660 deletions
+1 -1
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+12 -10
View File
@@ -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"] }
+10
View File
@@ -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
+2 -2
View File
@@ -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"
+1 -1
View File
@@ -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(), || {
-6
View File
@@ -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();
+2 -1
View File
@@ -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);
+1 -1
View File
@@ -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) {
+1 -13
View File
@@ -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);
+1 -1
View File
@@ -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)]
+2 -2
View File
@@ -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 }
+1 -1
View File
@@ -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)))
);
}
+1
View File
@@ -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()
+1
View File
@@ -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>>,
+125 -88
View File
@@ -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"
);
+1 -1
View File
@@ -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?;
+1
View File
@@ -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 }
+1
View File
@@ -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()
+1 -1
View File
@@ -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);
+1
View File
@@ -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 }
+22
View File
@@ -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",
+1 -1
View File
@@ -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 {
+1
View File
@@ -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()
-4
View File
@@ -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)
+1
View File
@@ -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);
+1 -1
View File
@@ -175,7 +175,7 @@ impl TokenSource {
})),
refresher,
flight: Arc::new(Mutex::new(Flight::default())),
skew: Duration::from_secs(60),
skew: Duration::from_mins(1),
}
}
+1 -1
View File
@@ -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()
}
+3 -3
View File
@@ -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));
+2 -1
View File
@@ -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);
+11 -11
View File
@@ -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()
);
-4
View File
@@ -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");
+1 -1
View File
@@ -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));
+2 -2
View File
@@ -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;
+2 -2
View File
@@ -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));
+9 -3
View File
@@ -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))
+1
View File
@@ -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()
+6 -9
View File
@@ -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"),
),
);
+2 -24
View File
@@ -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()
+1
View File
@@ -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"
+1 -3
View File
@@ -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 \
+117 -102
View File
@@ -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
View File
@@ -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
View File
@@ -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"
+3 -3
View File
@@ -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
View File
@@ -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