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: Project requirements:
- Rust 1.90+ - Rust 1.94+
- Python 3.11+ - Python 3.11+
- Docker (running) - Docker (running)
- CMake 3.16+ (only required when building with the `bundled-z3` feature) - 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] [workspace.package]
version = "0.0.0" version = "0.0.0"
edition = "2024" edition = "2024"
rust-version = "1.90" rust-version = "1.94"
license = "Apache-2.0" license = "Apache-2.0"
repository = "https://github.com/NVIDIA/OpenShell" repository = "https://github.com/NVIDIA/OpenShell"
@@ -35,10 +35,10 @@ http-body = "1.0"
http-body-util = "0.1" http-body-util = "0.1"
# TLS # TLS
tokio-rustls = { version = "0.26", default-features = false, features = ["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", "ring"] } rustls = { version = "0.23", default-features = false, features = ["std", "logging", "tls12", "aws_lc_rs"] }
rustls-pemfile = "2" 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" webpki-roots = "1"
rustls-native-certs = "0.8" rustls-native-certs = "0.8"
@@ -87,7 +87,7 @@ tower-mcp-types = "0.12.0"
regex = "1" regex = "1"
# HTTP client # 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 SDK
aws-config = { version = "1", default-features = false, features = ["default-https-client", "rt-tokio", "behavior-version-latest"] } 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" rand = "0.9"
jsonwebtoken = { version = "10", features = ["aws_lc_rs"] } jsonwebtoken = { version = "10", features = ["aws_lc_rs"] }
getrandom = "0.3" 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"] } spiffe = { version = "0.15", default-features = false, features = ["workload-api-jwt", "jwt-verify-rust-crypto", "tracing"] }
# Filesystem embedding # Filesystem embedding
@@ -124,12 +124,14 @@ url = "2"
indexmap = "2" indexmap = "2"
# Database # 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 # Kubernetes
kube = { version = "0.90", default-features = false, features = ["client", "runtime", "derive", "rustls-tls"] } kube = { version = "0.99", default-features = false, features = ["client", "runtime", "derive", "rustls-tls", "aws-lc-rs"] }
kube-runtime = "0.90" kube-runtime = "0.99"
k8s-openapi = { version = "0.21.1", features = ["v1_26"] } k8s-openapi = { version = "0.24", features = ["v1_29"] }
# IDs # IDs
uuid = { version = "1.10", features = ["v4"] } uuid = { version = "1.10", features = ["v4"] }
+10
View File
@@ -25,6 +25,16 @@ Sandbox community images are built outside this repository.
## Build Features ## 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 Anonymous telemetry emission is gated behind a default-on `telemetry` Cargo
feature. It is defined in `openshell-core` (where the emission code, HTTP 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 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 } http-body-util = { workspace = true }
hyper = { workspace = true } hyper = { workspace = true }
hyper-util = { 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 = { workspace = true }
rustls-pemfile = { workspace = true } rustls-pemfile = { workspace = true }
tokio-rustls = { workspace = true } tokio-rustls = { workspace = true }
@@ -91,7 +91,7 @@ nix = { workspace = true }
[dev-dependencies] [dev-dependencies]
futures = { workspace = true } futures = { workspace = true }
rcgen = { version = "0.13", features = ["crypto", "pem"] } rcgen = { workspace = true }
reqwest = { workspace = true } reqwest = { workspace = true }
serde_json = { workspace = true } serde_json = { workspace = true }
temp-env = "0.3" temp-env = "0.3"
+1 -1
View File
@@ -35,7 +35,7 @@ use tokio::sync::oneshot;
use tracing::debug; use tracing::debug;
/// Timeout for the browser auth flow. /// 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). /// Length of the confirmation code (alphanumeric characters).
const CODE_LENGTH: usize = 7; const CODE_LENGTH: usize = 7;
@@ -1970,7 +1970,6 @@ mod tests {
#[test] #[test]
fn gateway_add_registers_plaintext_loopback_gateway_without_local_flag() { 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"); let tmpdir = tempfile::tempdir().expect("create tmpdir");
with_tmp_xdg(tmpdir.path(), || { with_tmp_xdg(tmpdir.path(), || {
let runtime = tokio::runtime::Runtime::new().expect("create runtime"); let runtime = tokio::runtime::Runtime::new().expect("create runtime");
@@ -2002,7 +2001,6 @@ mod tests {
#[test] #[test]
fn gateway_add_respects_local_flag_for_plaintext_registrations() { fn gateway_add_respects_local_flag_for_plaintext_registrations() {
let _ = rustls::crypto::ring::default_provider().install_default();
let tmpdir = tempfile::tempdir().expect("create tmpdir"); let tmpdir = tempfile::tempdir().expect("create tmpdir");
with_tmp_xdg(tmpdir.path(), || { with_tmp_xdg(tmpdir.path(), || {
let runtime = tokio::runtime::Runtime::new().expect("create runtime"); let runtime = tokio::runtime::Runtime::new().expect("create runtime");
@@ -2032,7 +2030,6 @@ mod tests {
#[tokio::test] #[tokio::test]
async fn http_health_check_supports_plain_http_endpoints() { 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 listener = TcpListener::bind("127.0.0.1:0").expect("bind listener");
let addr = listener.local_addr().expect("listener addr"); let addr = listener.local_addr().expect("listener addr");
let server = thread::spawn(move || { let server = thread::spawn(move || {
@@ -2061,7 +2058,6 @@ mod tests {
#[test] #[test]
fn gateway_add_oidc_rolls_back_on_auth_failure() { fn gateway_add_oidc_rolls_back_on_auth_failure() {
let _ = rustls::crypto::ring::default_provider().install_default();
let tmpdir = tempfile::tempdir().expect("create tmpdir"); let tmpdir = tempfile::tempdir().expect("create tmpdir");
with_tmp_xdg(tmpdir.path(), || { with_tmp_xdg(tmpdir.path(), || {
let runtime = tokio::runtime::Runtime::new().expect("create runtime"); let runtime = tokio::runtime::Runtime::new().expect("create runtime");
@@ -2118,7 +2114,6 @@ mod tests {
} }
#[test] #[test]
fn gateway_add_oidc_rollback_keeps_system_active_fallback_userless() { 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 user = tempfile::tempdir().expect("create user tmpdir");
let system = tempfile::tempdir().expect("create system tmpdir"); let system = tempfile::tempdir().expect("create system tmpdir");
with_tmp_xdg_and_system(user.path(), system.path(), || { with_tmp_xdg_and_system(user.path(), system.path(), || {
@@ -2159,7 +2154,6 @@ mod tests {
#[test] #[test]
fn gateway_add_cloud_rolls_back_on_auth_failure() { fn gateway_add_cloud_rolls_back_on_auth_failure() {
let _ = rustls::crypto::ring::default_provider().install_default();
let tmpdir = tempfile::tempdir().expect("create tmpdir"); let tmpdir = tempfile::tempdir().expect("create tmpdir");
with_tmp_xdg(tmpdir.path(), || { with_tmp_xdg(tmpdir.path(), || {
let _no_browser = EnvVarGuard::set("OPENSHELL_NO_BROWSER", "0"); let _no_browser = EnvVarGuard::set("OPENSHELL_NO_BROWSER", "0");
@@ -2217,7 +2211,6 @@ mod tests {
} }
#[test] #[test]
fn gateway_add_cloud_rollback_keeps_system_active_fallback_userless() { 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 user = tempfile::tempdir().expect("create user tmpdir");
let system = tempfile::tempdir().expect("create system tmpdir"); let system = tempfile::tempdir().expect("create system tmpdir");
with_tmp_xdg_and_system(user.path(), system.path(), || { 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. #[allow(clippy::large_stack_frames)] // CLI dispatch holds many futures; run on an expanded Windows stack.
async fn run_async() -> Result<()> { 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(); CompleteEnv::with_factory(Cli::command).complete();
let cli = Cli::parse(); let cli = Cli::parse();
+2 -1
View File
@@ -29,7 +29,7 @@ use tokio::net::TcpListener;
use tokio::sync::oneshot; use tokio::sync::oneshot;
use tracing::debug; 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). /// OIDC discovery document (subset of fields we need).
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
@@ -93,6 +93,7 @@ async fn discover(issuer: &str, insecure: bool) -> Result<OidcDiscovery> {
} }
fn http_client(insecure: bool) -> reqwest::Client { 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()); let mut builder = reqwest::ClientBuilder::new().redirect(reqwest::redirect::Policy::none());
if insecure { if insecure {
builder = builder.danger_accept_invalid_certs(true); 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> { fn supported_verify_schemes(&self) -> Vec<rustls::SignatureScheme> {
rustls::crypto::ring::default_provider() rustls::crypto::aws_lc_rs::default_provider()
.signature_verification_algorithms .signature_verification_algorithms
.supported_schemes() .supported_schemes()
} }
@@ -7,9 +7,7 @@
mod helpers; mod helpers;
use helpers::{ use helpers::{EnvVarGuard, build_ca, build_client_cert, build_server_cert};
EnvVarGuard, build_ca, build_client_cert, build_server_cert, install_rustls_provider,
};
use openshell_cli::run; use openshell_cli::run;
use openshell_cli::tls::TlsOptions; use openshell_cli::tls::TlsOptions;
use openshell_core::proto::open_shell_server::{OpenShell, OpenShellServer}; use openshell_core::proto::open_shell_server::{OpenShell, OpenShellServer};
@@ -733,8 +731,6 @@ struct TestServer {
} }
async fn run_server() -> TestServer { async fn run_server() -> TestServer {
install_rustls_provider();
let (ca, ca_key) = build_ca(); let (ca, ca_key) = build_ca();
let (server_cert, server_key) = build_server_cert(&ca, &ca_key); let (server_cert, server_key) = build_server_cert(&ca, &ca_key);
let (client_cert, client_key) = build_client_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 ────────────────────────────────────────────────────────────── // ── 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. /// Generate a self-signed CA certificate and its key pair.
#[allow(dead_code)] #[allow(dead_code)]
pub fn build_ca() -> (Certificate, KeyPair) { pub fn build_ca() -> (Certificate, KeyPair) {
+1 -13
View File
@@ -3,9 +3,7 @@
mod helpers; mod helpers;
use helpers::{ use helpers::{EnvVarGuard, build_ca, build_client_cert, build_server_cert};
EnvVarGuard, build_ca, build_client_cert, build_server_cert, install_rustls_provider,
};
use openshell_bootstrap::{get_gateway_metadata, load_active_gateway}; use openshell_bootstrap::{get_gateway_metadata, load_active_gateway};
use openshell_cli::{ use openshell_cli::{
run, run,
@@ -651,8 +649,6 @@ fn isolated_gateway_add_env(
#[tokio::test] #[tokio::test]
async fn gateway_add_mtls_loopback_uses_explicit_gateway_name() { async fn gateway_add_mtls_loopback_uses_explicit_gateway_name() {
install_rustls_provider();
let (ca, ca_key) = build_ca(); let (ca, ca_key) = build_ca();
let (server_cert, server_key) = build_server_cert(&ca, &ca_key); let (server_cert, server_key) = build_server_cert(&ca, &ca_key);
let (client_cert, client_key) = build_client_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] #[tokio::test]
async fn gateway_add_mtls_loopback_without_name_uses_openshell_default() { async fn gateway_add_mtls_loopback_without_name_uses_openshell_default() {
install_rustls_provider();
let (ca, ca_key) = build_ca(); let (ca, ca_key) = build_ca();
let (server_cert, server_key) = build_server_cert(&ca, &ca_key); let (server_cert, server_key) = build_server_cert(&ca, &ca_key);
let (client_cert, client_key) = build_client_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] #[tokio::test]
async fn gateway_add_mtls_loopback_explicit_name_does_not_fallback_to_openshell_certs() { async fn gateway_add_mtls_loopback_explicit_name_does_not_fallback_to_openshell_certs() {
install_rustls_provider();
let (ca, ca_key) = build_ca(); let (ca, ca_key) = build_ca();
let (client_cert, client_key) = build_client_cert(&ca, &ca_key); let (client_cert, client_key) = build_client_cert(&ca, &ca_key);
let ca_cert = ca.pem(); let ca_cert = ca.pem();
@@ -777,7 +769,6 @@ async fn gateway_add_mtls_loopback_explicit_name_does_not_fallback_to_openshell_
#[tokio::test] #[tokio::test]
async fn cli_connects_with_client_cert() { async fn cli_connects_with_client_cert() {
let _env = EnvVarGuard::set(&[]); let _env = EnvVarGuard::set(&[]);
install_rustls_provider();
let (ca, ca_key) = build_ca(); let (ca, ca_key) = build_ca();
let (server_cert, server_key) = build_server_cert(&ca, &ca_key); let (server_cert, server_key) = build_server_cert(&ca, &ca_key);
@@ -803,8 +794,6 @@ async fn cli_connects_with_client_cert() {
#[tokio::test] #[tokio::test]
async fn cli_requires_client_cert_for_https() { async fn cli_requires_client_cert_for_https() {
install_rustls_provider();
let (ca, ca_key) = build_ca(); let (ca, ca_key) = build_ca();
let (server_cert, server_key) = build_server_cert(&ca, &ca_key); let (server_cert, server_key) = build_server_cert(&ca, &ca_key);
let ca_cert = ca.pem(); let ca_cert = ca.pem();
@@ -851,7 +840,6 @@ async fn run_server_no_client_auth(
#[tokio::test] #[tokio::test]
async fn cli_connects_with_gateway_insecure() { async fn cli_connects_with_gateway_insecure() {
let _env = EnvVarGuard::set(&[]); let _env = EnvVarGuard::set(&[]);
install_rustls_provider();
let (ca, ca_key) = build_ca(); let (ca, ca_key) = build_ca();
let (server_cert, server_key) = build_server_cert(&ca, &ca_key); let (server_cert, server_key) = build_server_cert(&ca, &ca_key);
@@ -3,9 +3,7 @@
mod helpers; mod helpers;
use helpers::{ use helpers::{EnvVarGuard, build_ca, build_client_cert, build_server_cert};
EnvVarGuard, build_ca, build_client_cert, build_server_cert, install_rustls_provider,
};
use openshell_cli::run; use openshell_cli::run;
use openshell_cli::tls::TlsOptions; use openshell_cli::tls::TlsOptions;
use openshell_core::proto::open_shell_server::{OpenShell, OpenShellServer}; use openshell_core::proto::open_shell_server::{OpenShell, OpenShellServer};
@@ -1162,8 +1160,6 @@ struct TestServer {
} }
async fn run_server() -> TestServer { async fn run_server() -> TestServer {
install_rustls_provider();
let (ca, ca_key) = build_ca(); let (ca, ca_key) = build_ca();
let (server_cert, server_key) = build_server_cert(&ca, &ca_key); let (server_cert, server_key) = build_server_cert(&ca, &ca_key);
let (client_cert, client_key) = build_client_cert(&ca, &ca_key); let (client_cert, client_key) = build_client_cert(&ca, &ca_key);
@@ -5,9 +5,7 @@
mod helpers; mod helpers;
use helpers::{ use helpers::{EnvVarGuard, build_ca, build_client_cert, build_server_cert};
EnvVarGuard, build_ca, build_client_cert, build_server_cert, install_rustls_provider,
};
use openshell_bootstrap::load_last_sandbox; use openshell_bootstrap::load_last_sandbox;
use openshell_cli::run; use openshell_cli::run;
use openshell_cli::tls::TlsOptions; use openshell_cli::tls::TlsOptions;
@@ -944,8 +942,6 @@ struct TestServer {
} }
async fn run_server() -> TestServer { async fn run_server() -> TestServer {
install_rustls_provider();
let (ca, ca_key) = build_ca(); let (ca, ca_key) = build_ca();
let (server_cert, server_key) = build_server_cert(&ca, &ca_key); let (server_cert, server_key) = build_server_cert(&ca, &ca_key);
let (client_cert, client_key) = build_client_cert(&ca, &ca_key); let (client_cert, client_key) = build_client_cert(&ca, &ca_key);
@@ -3,9 +3,7 @@
mod helpers; mod helpers;
use helpers::{ use helpers::{EnvVarGuard, build_ca, build_client_cert, build_server_cert};
EnvVarGuard, build_ca, build_client_cert, build_server_cert, install_rustls_provider,
};
use openshell_bootstrap::{load_last_sandbox, save_last_sandbox}; use openshell_bootstrap::{load_last_sandbox, save_last_sandbox};
use openshell_cli::run; use openshell_cli::run;
use openshell_cli::tls::TlsOptions; use openshell_cli::tls::TlsOptions;
@@ -682,8 +680,6 @@ struct TestServer {
} }
async fn run_server() -> TestServer { async fn run_server() -> TestServer {
install_rustls_provider();
let (ca, ca_key) = build_ca(); let (ca, ca_key) = build_ca();
let (server_cert, server_key) = build_server_cert(&ca, &ca_key); let (server_cert, server_key) = build_server_cert(&ca, &ca_key);
let (client_cert, client_key) = build_client_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) .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); pub const STATUS_TIMEOUT: Duration = Duration::from_secs(30);
const GATEWAY_STATUS_ATTEMPT_TIMEOUT: Duration = Duration::from_secs(10); const GATEWAY_STATUS_ATTEMPT_TIMEOUT: Duration = Duration::from_secs(10);
const GATEWAY_STATUS_INTERVAL: Duration = Duration::from_secs(2); const GATEWAY_STATUS_INTERVAL: Duration = Duration::from_secs(2);
@@ -11,9 +11,9 @@ use crate::{
HostAction, OpenShellRunner, PlanRun, Poll, Scenario, ScenarioFuture, WorkloadExpectation, HostAction, OpenShellRunner, PlanRun, Poll, Scenario, ScenarioFuture, WorkloadExpectation,
}; };
const CREATE_TIMEOUT: Duration = Duration::from_secs(600); const CREATE_TIMEOUT: Duration = Duration::from_mins(10);
const COMMAND_TIMEOUT: Duration = Duration::from_secs(120); const COMMAND_TIMEOUT: Duration = Duration::from_mins(2);
const RECOVERY_TIMEOUT: Duration = Duration::from_secs(240); const RECOVERY_TIMEOUT: Duration = Duration::from_mins(4);
const RECOVERY_INTERVAL: Duration = Duration::from_secs(2); const RECOVERY_INTERVAL: Duration = Duration::from_secs(2);
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
@@ -9,11 +9,11 @@ use crate::{OpenShellRunner, PlanRun, STATUS_TIMEOUT, Scenario, ScenarioFuture};
use serde::Deserialize; use serde::Deserialize;
use tokio::time::sleep; 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_ATTEMPT_TIMEOUT: Duration = Duration::from_secs(10);
const LIST_PAGE_SIZE: u32 = 1_000; const LIST_PAGE_SIZE: u32 = 1_000;
const EXEC_TIMEOUT: Duration = Duration::from_secs(120); const EXEC_TIMEOUT: Duration = Duration::from_mins(2);
const DELETE_TIMEOUT: Duration = Duration::from_secs(120); const DELETE_TIMEOUT: Duration = Duration::from_mins(2);
const DELETE_POLL_INTERVAL: Duration = Duration::from_secs(1); const DELETE_POLL_INTERVAL: Duration = Duration::from_secs(1);
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
+2 -2
View File
@@ -16,7 +16,7 @@ openshell-extension-core = { path = "../openshell-extension-core" }
glob = { workspace = true } glob = { workspace = true }
prost = { workspace = true } prost = { workspace = true }
prost-types = { 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 } tonic-prost = { workspace = true }
tokio = { workspace = true } tokio = { workspace = true }
tokio-stream = { workspace = true } tokio-stream = { workspace = true }
@@ -31,7 +31,7 @@ rustls = { workspace = true }
rustls-pemfile = { workspace = true } rustls-pemfile = { workspace = true }
base64 = { workspace = true } base64 = { workspace = true }
chrono = { version = "0.4", default-features = false, features = ["clock", "std"], optional = 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 } tar = { version = "0.4", optional = true }
tempfile = { version = "3", optional = true } tempfile = { version = "3", optional = true }
+1 -1
View File
@@ -995,7 +995,7 @@ mod tests {
Config::new(None) Config::new(None)
.with_grpc_rate_limit(Some(10), Some(60)) .with_grpc_rate_limit(Some(10), Some(60))
.grpc_rate_limit(), .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 { fn test_client() -> reqwest::Client {
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
reqwest::Client::builder() reqwest::Client::builder()
.timeout(std::time::Duration::from_secs(5)) .timeout(std::time::Duration::from_secs(5))
.no_proxy() .no_proxy()
+1
View File
@@ -426,6 +426,7 @@ fn telemetry_worker(rx: mpsc::Receiver<TelemetryEvent>) {
#[cfg(feature = "telemetry")] #[cfg(feature = "telemetry")]
fn publish_payload(endpoint: &str, payload: Value) -> Result<(), reqwest::Error> { fn publish_payload(endpoint: &str, payload: Value) -> Result<(), reqwest::Error> {
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
Client::builder() Client::builder()
.use_rustls_tls() .use_rustls_tls()
.tls_built_in_root_certs(true) .tls_built_in_root_certs(true)
@@ -16,7 +16,7 @@ openshell-core = { path = "../openshell-core", default-features = false }
async-trait = "0.1" async-trait = "0.1"
base64 = { workspace = true } base64 = { workspace = true }
futures = { workspace = true } futures = { workspace = true }
ring = { workspace = true } aws-lc-rs = { workspace = true }
serde = { workspace = true } serde = { workspace = true }
serde_json = { workspace = true } serde_json = { workspace = true }
sha2 = { workspace = true } sha2 = { workspace = true }
@@ -17,6 +17,8 @@ use std::path::{Path, PathBuf};
use std::sync::Arc; use std::sync::Arc;
use async_trait::async_trait; 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::{ use base64::{
Engine as _, Engine as _,
engine::general_purpose::{STANDARD as BASE64, STANDARD_NO_PAD as BASE64_NO_PAD}, 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, DeleteCredentialRequest, ResolveCredentialRequest, ResolvedCredential, StoreCredentialRequest,
}; };
use openshell_core::{Error, Result as CoreResult}; 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 serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256}; use sha2::{Digest, Sha256};
use tonic::Status; use tonic::Status;
@@ -933,6 +933,46 @@ mod tests {
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use tonic::Code; 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)] #[derive(Debug, Default)]
struct MemoryObjectStore { struct MemoryObjectStore {
objects: Mutex<HashMap<String, StoredCredentialObject>>, 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 openshell_core::proto_struct::{struct_to_json_object, value_to_json};
use serde::Deserialize; use serde::Deserialize;
use std::collections::{BTreeMap, HashSet}; use std::collections::{BTreeMap, BTreeSet, HashSet};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::pin::Pin; use std::pin::Pin;
use std::sync::Arc; use std::sync::Arc;
@@ -1965,7 +1965,7 @@ impl KubernetesComputeDriver {
loop { loop {
tokio::select! { tokio::select! {
event = sandbox_stream.next() => match event { 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) { 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); update_indexes(&mut sandbox_name_to_id, &mut agent_pod_to_id, &kube_name, &sandbox);
let event = WatchSandboxesEvent { let event = WatchSandboxesEvent {
@@ -1978,7 +1978,7 @@ impl KubernetesComputeDriver {
} }
} }
} }
Some(Event::Deleted(obj)) => { Some(Event::Delete(obj)) => {
if is_openshell_managed(&obj) if is_openshell_managed(&obj)
&& let Ok(sandbox_id) = sandbox_id_from_object(&obj) && let Ok(sandbox_id) = sandbox_id_from_object(&obj)
{ {
@@ -1993,21 +1993,7 @@ impl KubernetesComputeDriver {
} }
} }
} }
Some(Event::Restarted(objs)) => { Some(Event::Init | Event::InitDone) => {}
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;
}
}
}
}
None => { None => {
let _ = tx.send(Err(KubernetesDriverError::Message( let _ = tx.send(Err(KubernetesDriverError::Message(
"sandbox watcher stream ended unexpectedly".to_string() "sandbox watcher stream ended unexpectedly".to_string()
@@ -2016,7 +2002,7 @@ impl KubernetesComputeDriver {
} }
}, },
event = event_stream.next() => match event { 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( if let Some((sandbox_id, event)) = map_kube_event_to_platform(
&sandbox_name_to_id, &sandbox_name_to_id,
&agent_pod_to_id, &agent_pod_to_id,
@@ -2032,8 +2018,8 @@ impl KubernetesComputeDriver {
} }
} }
} }
Some(Event::Deleted(_)) => {} Some(Event::Delete(_) | Event::InitApply(_) | Event::InitDone) => {}
Some(Event::Restarted(_)) => { Some(Event::Init) => {
debug!(namespace = %namespace, "Kubernetes event watcher restarted"); debug!(namespace = %namespace, "Kubernetes event watcher restarted");
} }
None => { None => {
@@ -2082,7 +2068,7 @@ where
loop { loop {
tokio::select! { tokio::select! {
event = sandbox_stream.next() => match event { event = sandbox_stream.next() => match event {
Some(Event::Applied(obj)) => { Some(Event::Apply(obj) | Event::InitApply(obj)) => {
let ns = obj.metadata.namespace.clone() let ns = obj.metadata.namespace.clone()
.unwrap_or_else(|| default_namespace.clone()); .unwrap_or_else(|| default_namespace.clone());
if let Ok((_kube_name, sandbox)) = sandbox_from_object(&ns, obj) { 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) if is_openshell_managed(&obj)
&& let Ok(sandbox_id) = sandbox_id_from_object(&obj) && let Ok(sandbox_id) = sandbox_id_from_object(&obj)
{ {
@@ -2110,22 +2096,7 @@ where
} }
} }
} }
Some(Event::Restarted(objs)) => { Some(Event::Init | Event::InitDone) => {}
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;
}
}
}
}
None => { None => {
let _ = tx.send(Err(KubernetesDriverError::Message( let _ = tx.send(Err(KubernetesDriverError::Message(
"sandbox watcher stream ended unexpectedly".to_string() "sandbox watcher stream ended unexpectedly".to_string()
@@ -2318,7 +2289,6 @@ fn managed_ssh_network_policy(namespace: &str, config: &KubernetesComputeConfig)
}]), }]),
..Default::default() ..Default::default()
}), }),
status: None,
} }
} }
@@ -4723,6 +4693,7 @@ fn spawn_namespace_label_watcher(
let mut retry_attempt = 0; let mut retry_attempt = 0;
loop { loop {
let mut stream = watcher::watcher(ns_api.clone(), watcher_config.clone()).boxed(); let mut stream = watcher::watcher(ns_api.clone(), watcher_config.clone()).boxed();
let mut relisted_names = BTreeSet::new();
loop { loop {
let event = tokio::select! { let event = tokio::select! {
@@ -4735,37 +4706,9 @@ fn spawn_namespace_label_watcher(
} }
}; };
match event { match event {
Ok(Some(Event::Applied(ns))) => { Ok(Some(event)) => {
retry_attempt = 0; retry_attempt = 0;
if let Some(name) = ns.metadata.name.as_deref() apply_namespace_watch_event(&allowlist, &mut relisted_names, event);
&& 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"
);
} }
Ok(None) => { Ok(None) => {
warn!("operator namespace watcher stream ended unexpectedly"); 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) 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) let contents = std::fs::read_to_string(path)
.map_err(|e| format!("failed to read {}: {e}", path.display()))?; .map_err(|e| format!("failed to read {}: {e}", path.display()))?;
let names: Vec<String> = serde_json::from_str(&contents) 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()) 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( fn spawn_namespace_file_watcher(
path: PathBuf, path: PathBuf,
allowlist: OperatorNamespaceAllowlist, allowlist: OperatorNamespaceAllowlist,
@@ -5062,7 +5046,7 @@ mod tests {
} }
#[tokio::test] #[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 { let recovered = DynamicObject {
types: None, types: None,
metadata: ObjectMeta { metadata: ObjectMeta {
@@ -5073,22 +5057,22 @@ mod tests {
}; };
let source = futures::stream::iter([ let source = futures::stream::iter([
Err(expired_watch_error()), 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"); let mut stream = continue_on_watcher_errors(source, "sandbox-resource");
assert!(matches!(stream.next().await, Some(Event::Init)));
let event = stream let event = stream
.next() .next()
.await .await
.expect("410 Expired must not terminate the watcher stream"); .expect("410 Expired must not terminate the watcher stream");
let Event::Restarted(objects) = event else { let Event::InitApply(object) = event else {
panic!("expected kube-runtime recovery to emit Restarted"); panic!("expected kube-runtime recovery to emit InitApply");
}; };
assert_eq!(objects.len(), 1); assert_eq!(object.metadata.name.as_deref(), Some("recovered-sandbox"));
assert_eq!( assert!(matches!(stream.next().await, Some(Event::InitDone)));
objects[0].metadata.name.as_deref(),
Some("recovered-sandbox")
);
assert!( assert!(
stream.next().await.is_none(), stream.next().await.is_none(),
"source closure must be preserved" "source closure must be preserved"
@@ -5117,7 +5101,9 @@ mod tests {
}; };
let source = futures::stream::iter([ let source = futures::stream::iter([
Err(expired_watch_error()), Err(expired_watch_error()),
Ok(Event::Restarted(vec![recovered])), Ok(Event::Init),
Ok(Event::InitApply(recovered)),
Ok(Event::InitDone),
]) ])
.chain(futures::stream::pending()); .chain(futures::stream::pending());
let sandbox_stream = recovering_watcher_stream(source, "sandbox-resource").boxed(); let sandbox_stream = recovering_watcher_stream(source, "sandbox-resource").boxed();
@@ -5144,10 +5130,12 @@ mod tests {
} }
#[tokio::test] #[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([ let source = futures::stream::iter([
Err(expired_watch_error()), 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"); let mut stream = continue_on_watcher_errors(source, "kubernetes-event");
@@ -5155,16 +5143,65 @@ mod tests {
.next() .next()
.await .await
.expect("410 Expired must not terminate the watcher stream"); .expect("410 Expired must not terminate the watcher stream");
let Event::Restarted(events) = event else { assert!(matches!(event, Event::Init));
panic!("expected kube-runtime recovery to emit Restarted"); assert!(matches!(stream.next().await, Some(Event::InitApply(_))));
}; assert!(matches!(stream.next().await, Some(Event::InitDone)));
assert_eq!(events.len(), 1);
assert!( assert!(
stream.next().await.is_none(), stream.next().await.is_none(),
"source closure must be preserved" "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 { fn authenticated_token_review(username: &str) -> TokenReviewStatus {
TokenReviewStatus { TokenReviewStatus {
authenticated: Some(true), authenticated: Some(true),
@@ -5372,7 +5409,7 @@ mod tests {
assert_eq!( assert_eq!(
kubernetes_sandbox_stop_timeout(&sandbox), kubernetes_sandbox_stop_timeout(&sandbox),
Duration::from_secs(60), Duration::from_mins(1),
"an omitted grace period uses the Kubernetes 30-second default" "an omitted grace period uses the Kubernetes 30-second default"
); );
+1 -1
View File
@@ -719,7 +719,7 @@ impl PodmanClient {
url_encode(policy), url_encode(policy),
); );
// Image pulls can be slow — use a generous timeout. // 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 let (status, bytes) = self
.request(hyper::Method::POST, &path, None, pull_timeout) .request(hyper::Method::POST, &path, None, pull_timeout)
.await?; .await?;
+1
View File
@@ -21,6 +21,7 @@ clap = { workspace = true }
futures = { workspace = true } futures = { workspace = true }
miette = { workspace = true } miette = { workspace = true }
reqwest = { workspace = true } reqwest = { workspace = true }
rustls = { workspace = true }
serde = { workspace = true } serde = { workspace = true }
serde_json = { workspace = true } serde_json = { workspace = true }
sha2 = { workspace = true } sha2 = { workspace = true }
+1
View File
@@ -126,6 +126,7 @@ impl VaultCredentialDriver {
pub fn from_config(config: &toml::Table) -> CoreResult<Self> { pub fn from_config(config: &toml::Table) -> CoreResult<Self> {
let settings = VaultDriverSettings::from_table(config)?; let settings = VaultDriverSettings::from_table(config)?;
let timeout_secs = timeout_secs(config)?; let timeout_secs = timeout_secs(config)?;
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
let client = reqwest::Client::builder() let client = reqwest::Client::builder()
.timeout(Duration::from_secs(timeout_secs)) .timeout(Duration::from_secs(timeout_secs))
.build() .build()
+1 -1
View File
@@ -9,7 +9,7 @@ use serde::{Deserialize, Serialize};
/// ///
/// Extension credentials cross the gateway trust boundary and must remain /// Extension credentials cross the gateway trust boundary and must remain
/// short-lived even when legacy sandbox bootstrap credentials do not expire. /// 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. /// Explicit `typ` header value carried by every extension bearer token.
/// ///
@@ -292,7 +292,6 @@ mod tests {
#[tokio::test] #[tokio::test]
async fn custom_ca_verifies_certificate_and_hostname() { async fn custom_ca_verifies_certificate_and_hostname() {
let _ = rustls::crypto::ring::default_provider().install_default();
let ca_key = KeyPair::generate().unwrap(); let ca_key = KeyPair::generate().unwrap();
let mut ca_params = CertificateParams::new(Vec::<String>::new()).unwrap(); let mut ca_params = CertificateParams::new(Vec::<String>::new()).unwrap();
ca_params.is_ca = IsCa::Ca(BasicConstraints::Unconstrained); 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 } openshell-core = { path = "../openshell-core", default-features = false }
bytes = { workspace = true } bytes = { workspace = true }
reqwest = { workspace = true } reqwest = { workspace = true }
rustls = { workspace = true }
serde = { workspace = true } serde = { workspace = true }
serde_json = { workspace = true } serde_json = { workspace = true }
thiserror = { workspace = true } thiserror = { workspace = true }
+22
View File
@@ -1104,6 +1104,7 @@ mod tests {
.await; .await;
let route = test_route(&mock_server.uri(), &["model_discovery"], AuthHeader::Bearer); 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 client = reqwest::Client::new();
let result = proxy_to_backend( let result = proxy_to_backend(
&client, &client,
@@ -1151,6 +1152,7 @@ mod tests {
#[tokio::test] #[tokio::test]
async fn read_capped_response_body_rejects_over_cap_chunked() { async fn read_capped_response_body_rejects_over_cap_chunked() {
let addr = spawn_chunked_upstream(&["aaaa", "bbbb", "cccc"]).await; let addr = spawn_chunked_upstream(&["aaaa", "bbbb", "cccc"]).await;
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
let response = reqwest::Client::new() let response = reqwest::Client::new()
.get(format!("http://{addr}/")) .get(format!("http://{addr}/"))
.send() .send()
@@ -1172,6 +1174,7 @@ mod tests {
#[tokio::test] #[tokio::test]
async fn read_capped_response_body_accepts_body_at_cap() { async fn read_capped_response_body_accepts_body_at_cap() {
let addr = spawn_chunked_upstream(&["aaaa", "bbbb"]).await; let addr = spawn_chunked_upstream(&["aaaa", "bbbb"]).await;
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
let response = reqwest::Client::new() let response = reqwest::Client::new()
.get(format!("http://{addr}/")) .get(format!("http://{addr}/"))
.send() .send()
@@ -1358,6 +1361,7 @@ mod tests {
.mount(&mock_server) .mount(&mock_server)
.await; .await;
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
let client = reqwest::Client::builder().build().unwrap(); let client = reqwest::Client::builder().build().unwrap();
let validated = verify_backend_endpoint(&client, &route).await.unwrap(); let validated = verify_backend_endpoint(&client, &route).await.unwrap();
@@ -1373,6 +1377,7 @@ mod tests {
AuthHeader::Bearer, AuthHeader::Bearer,
); );
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
let client = reqwest::Client::builder().build().unwrap(); let client = reqwest::Client::builder().build().unwrap();
let validated = verify_backend_endpoint(&client, &route).await.unwrap(); let validated = verify_backend_endpoint(&client, &route).await.unwrap();
@@ -1402,6 +1407,7 @@ mod tests {
.mount(&mock_server) .mount(&mock_server)
.await; .await;
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
let client = reqwest::Client::builder().build().unwrap(); let client = reqwest::Client::builder().build().unwrap();
let validated = verify_backend_endpoint(&client, &route).await.unwrap(); let validated = verify_backend_endpoint(&client, &route).await.unwrap();
@@ -1445,6 +1451,7 @@ mod tests {
.mount(&mock_server) .mount(&mock_server)
.await; .await;
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
let client = reqwest::Client::builder().build().unwrap(); let client = reqwest::Client::builder().build().unwrap();
let validated = verify_backend_endpoint(&client, &route).await.unwrap(); let validated = verify_backend_endpoint(&client, &route).await.unwrap();
@@ -1491,6 +1498,7 @@ mod tests {
.mount(&mock_server) .mount(&mock_server)
.await; .await;
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
let client = reqwest::Client::new(); let client = reqwest::Client::new();
let validated = verify_backend_endpoint(&client, &route) let validated = verify_backend_endpoint(&client, &route)
.await .await
@@ -1526,6 +1534,7 @@ mod tests {
.mount(&mock_server) .mount(&mock_server)
.await; .await;
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
let client = reqwest::Client::new(); let client = reqwest::Client::new();
let err = verify_backend_endpoint(&client, &route) let err = verify_backend_endpoint(&client, &route)
.await .await
@@ -1629,6 +1638,7 @@ mod tests {
/// Helper: run `verify_backend_endpoint` and return the expected failure. /// Helper: run `verify_backend_endpoint` and return the expected failure.
async fn reqwest_verify(route: &ResolvedRoute) -> ValidationFailure { async fn reqwest_verify(route: &ResolvedRoute) -> ValidationFailure {
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
verify_backend_endpoint(&reqwest::Client::new(), route) verify_backend_endpoint(&reqwest::Client::new(), route)
.await .await
.expect_err("validation should fail") .expect_err("validation should fail")
@@ -1651,6 +1661,7 @@ mod tests {
.mount(&mock_server) .mount(&mock_server)
.await; .await;
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
let client = reqwest::Client::builder().build().unwrap(); let client = reqwest::Client::builder().build().unwrap();
let result = verify_backend_endpoint(&client, &route).await; let result = verify_backend_endpoint(&client, &route).await;
@@ -1691,6 +1702,7 @@ mod tests {
.mount(&mock_server) .mount(&mock_server)
.await; .await;
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
let client = reqwest::Client::builder().build().unwrap(); let client = reqwest::Client::builder().build().unwrap();
let validated = verify_backend_endpoint(&client, &route).await.unwrap(); let validated = verify_backend_endpoint(&client, &route).await.unwrap();
assert!( assert!(
@@ -1897,6 +1909,7 @@ mod tests {
.mount(&mock_server) .mount(&mock_server)
.await; .await;
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
let client = reqwest::Client::builder().build().unwrap(); let client = reqwest::Client::builder().build().unwrap();
let body = bytes::Bytes::from( let body = bytes::Bytes::from(
serde_json::to_vec(&serde_json::json!({ serde_json::to_vec(&serde_json::json!({
@@ -1966,6 +1979,7 @@ mod tests {
.mount(&mock_server) .mount(&mock_server)
.await; .await;
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
let client = reqwest::Client::builder().build().unwrap(); let client = reqwest::Client::builder().build().unwrap();
// Simulate a client (e.g. Claude Code) that always sends "model" in the body. // Simulate a client (e.g. Claude Code) that always sends "model" in the body.
let body = bytes::Bytes::from( let body = bytes::Bytes::from(
@@ -2028,6 +2042,7 @@ mod tests {
.mount(&mock_server) .mount(&mock_server)
.await; .await;
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
let client = reqwest::Client::builder().build().unwrap(); let client = reqwest::Client::builder().build().unwrap();
let body = bytes::Bytes::from( let body = bytes::Bytes::from(
serde_json::to_vec(&serde_json::json!({ serde_json::to_vec(&serde_json::json!({
@@ -2086,6 +2101,7 @@ mod tests {
request_path_override: None, request_path_override: None,
}; };
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
let client = reqwest::Client::builder().build().unwrap(); let client = reqwest::Client::builder().build().unwrap();
let body = bytes::Bytes::from( let body = bytes::Bytes::from(
serde_json::to_vec(&serde_json::json!({ serde_json::to_vec(&serde_json::json!({
@@ -2212,6 +2228,7 @@ mod tests {
.mount(&mock_server) .mount(&mock_server)
.await; .await;
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
let client = reqwest::Client::builder().build().unwrap(); let client = reqwest::Client::builder().build().unwrap();
let body = bytes::Bytes::from( let body = bytes::Bytes::from(
serde_json::to_vec(&serde_json::json!({ serde_json::to_vec(&serde_json::json!({
@@ -2274,6 +2291,7 @@ mod tests {
.mount(&mock_server) .mount(&mock_server)
.await; .await;
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
let client = reqwest::Client::builder().build().unwrap(); let client = reqwest::Client::builder().build().unwrap();
let body = bytes::Bytes::from( let body = bytes::Bytes::from(
serde_json::to_vec(&serde_json::json!({ serde_json::to_vec(&serde_json::json!({
@@ -2338,6 +2356,7 @@ mod tests {
.mount(&mock_server) .mount(&mock_server)
.await; .await;
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
let client = reqwest::Client::builder().build().unwrap(); let client = reqwest::Client::builder().build().unwrap();
let body = bytes::Bytes::from( let body = bytes::Bytes::from(
serde_json::to_vec(&serde_json::json!({ serde_json::to_vec(&serde_json::json!({
@@ -2557,6 +2576,7 @@ mod tests {
.mount(&mock_server) .mount(&mock_server)
.await; .await;
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
let client = reqwest::Client::builder() let client = reqwest::Client::builder()
.timeout(Duration::from_secs(5)) .timeout(Duration::from_secs(5))
.build() .build()
@@ -2674,6 +2694,7 @@ mod tests {
})) }))
.unwrap(); .unwrap();
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
let client = reqwest::Client::new(); let client = reqwest::Client::new();
let result = proxy_to_backend( let result = proxy_to_backend(
&client, &client,
@@ -2701,6 +2722,7 @@ mod tests {
/// but if it ever did, we must not silently forward. /// but if it ever did, we must not silently forward.
#[test] #[test]
fn bedrock_route_rejects_non_bedrock_path() { fn bedrock_route_rejects_non_bedrock_path() {
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
let client = reqwest::Client::new(); let client = reqwest::Client::new();
let route = test_route( let route = test_route(
"https://bedrock-bridge.example", "https://bedrock-bridge.example",
+1 -1
View File
@@ -9,7 +9,7 @@ pub use openshell_core::inference::AuthHeader;
use crate::RouterError; 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)] #[derive(Debug, Clone, Deserialize)]
pub struct RouterConfig { pub struct RouterConfig {
+1
View File
@@ -37,6 +37,7 @@ pub struct Router {
impl Router { impl Router {
pub fn new() -> Result<Self, RouterError> { pub fn new() -> Result<Self, RouterError> {
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
let client = reqwest::Client::builder() let client = reqwest::Client::builder()
.connect_timeout(Duration::from_secs(30)) .connect_timeout(Duration::from_secs(30))
.build() .build()
-4
View File
@@ -533,7 +533,6 @@ fn main() -> Result<()> {
.build() .build()
.into_diagnostic()?; .into_diagnostic()?;
return runtime.block_on(async move { 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?; let exit = openshell_supervisor_process::debug_rpc::run(&raw_args[2..]).await?;
std::process::exit(exit); std::process::exit(exit);
}); });
@@ -578,9 +577,6 @@ fn main() -> Result<()> {
.into_diagnostic()?; .into_diagnostic()?;
let result = runtime.block_on(async move { 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). // Set up optional log push layer (gRPC mode only).
let log_push_state = if let (Some(sandbox_id), Some(endpoint)) = let log_push_state = if let (Some(sandbox_id), Some(endpoint)) =
(&args.sandbox_id, &args.openshell_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. /// followed; OIDC providers should not redirect on the token endpoint.
/// When `insecure` is true, TLS certificate verification is disabled. /// When `insecure` is true, TLS certificate verification is disabled.
pub fn http_client(insecure: bool) -> reqwest::Client { 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()); let mut builder = reqwest::ClientBuilder::new().redirect(reqwest::redirect::Policy::none());
if insecure { if insecure {
builder = builder.danger_accept_invalid_certs(true); builder = builder.danger_accept_invalid_certs(true);
+1 -1
View File
@@ -175,7 +175,7 @@ impl TokenSource {
})), })),
refresher, refresher,
flight: Arc::new(Mutex::new(Flight::default())), 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> { fn supported_verify_schemes(&self) -> Vec<rustls::SignatureScheme> {
rustls::crypto::ring::default_provider() rustls::crypto::aws_lc_rs::default_provider()
.signature_verification_algorithms .signature_verification_algorithms
.supported_schemes() .supported_schemes()
} }
+3 -3
View File
@@ -84,12 +84,12 @@ base64 = { workspace = true }
futures = { workspace = true } futures = { workspace = true }
bytes = { workspace = true } bytes = { workspace = true }
pin-project-lite = { workspace = true } pin-project-lite = { workspace = true }
ring = { workspace = true }
serde = { workspace = true } serde = { workspace = true }
serde_json = { workspace = true } serde_json = { workspace = true }
toml = { workspace = true } toml = { workspace = true }
tokio-stream = { workspace = true } tokio-stream = { workspace = true }
sqlx = { workspace = true } sqlx = { workspace = true }
sqlx-core = { workspace = true }
reqwest = { workspace = true } reqwest = { workspace = true }
aws-config = { workspace = true } aws-config = { workspace = true }
aws-sdk-sts = { workspace = true } aws-sdk-sts = { workspace = true }
@@ -123,8 +123,8 @@ test-support = []
[dev-dependencies] [dev-dependencies]
base64 = { workspace = true } base64 = { workspace = true }
hyper-rustls = { version = "0.27", default-features = false, features = ["native-tokio", "http1", "tls12", "logging", "ring"] } hyper-rustls = { version = "0.27", default-features = false, features = ["native-tokio", "http1", "tls12", "logging", "aws-lc-rs"] }
rcgen = { version = "0.13", features = ["crypto", "pem"] } rcgen = { workspace = true }
rsa = { version = "0.9", features = ["pem"] } rsa = { version = "0.9", features = ["pem"] }
tokio-tungstenite = { workspace = true } tokio-tungstenite = { workspace = true }
futures-util = "0.3" futures-util = "0.3"
@@ -18,7 +18,7 @@ use std::collections::HashMap;
use std::sync::Mutex; use std::sync::Mutex;
use std::time::{Duration, Instant}; 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; const DEFAULT_MAX_PER_WINDOW: u32 = 10;
/// Number of tracked sandboxes above which expired windows are pruned. /// Number of tracked sandboxes above which expired windows are pruned.
@@ -102,7 +102,7 @@ mod tests {
#[test] #[test]
fn allows_a_burst_then_refuses_within_the_window() { 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(); let start = Instant::now();
for _ in 0..3 { for _ in 0..3 {
@@ -113,17 +113,17 @@ mod tests {
#[test] #[test]
fn window_rollover_restores_capacity() { 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(); let start = Instant::now();
assert!(limiter.try_acquire_at("sandbox-a", start)); 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(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] #[test]
fn sandboxes_are_limited_independently() { 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(); let start = Instant::now();
assert!(limiter.try_acquire_at("sandbox-a", start)); assert!(limiter.try_acquire_at("sandbox-a", start));
@@ -147,7 +147,7 @@ mod tests {
#[test] #[test]
fn a_zero_bound_disables_limiting() { 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(); let start = Instant::now();
for _ in 0..1_000 { for _ in 0..1_000 {
assert!(limiter.try_acquire_at("sandbox-a", start)); 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() let http = Client::builder()
.timeout(Duration::from_secs(10)) .timeout(Duration::from_secs(10))
.build() .build()
@@ -1607,7 +1608,7 @@ mod tests {
// cooldown window, even if the test task is descheduled while the // cooldown window, even if the test task is descheduled while the
// rest of the server suite runs in parallel. // rest of the server suite runs in parallel.
*cache.last_kid_miss_refresh.write().await = *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 { for _ in 0..4 {
let err = cache.validate_token(&unknown_kid_token).await.unwrap_err(); let err = cache.validate_token(&unknown_kid_token).await.unwrap_err();
assert_eq!(err.code(), tonic::Code::Unauthenticated); assert_eq!(err.code(), tonic::Code::Unauthenticated);
+11 -11
View File
@@ -417,7 +417,7 @@ mod tests {
} }
fn pair() -> (SandboxJwtIssuer, SandboxJwtAuthenticator) { 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) { fn pair_with_ttl(ttl: Duration) -> (SandboxJwtIssuer, SandboxJwtAuthenticator) {
@@ -472,7 +472,7 @@ mod tests {
mat.signing_key_pem.as_bytes(), mat.signing_key_pem.as_bytes(),
mat.kid.clone(), mat.kid.clone(),
"test-gateway", "test-gateway",
Duration::from_secs(3600), Duration::from_hours(1),
) )
.expect("issuer"); .expect("issuer");
let auth = SandboxJwtAuthenticator::from_pem( let auth = SandboxJwtAuthenticator::from_pem(
@@ -582,7 +582,7 @@ mod tests {
mat.signing_key_pem.as_bytes(), mat.signing_key_pem.as_bytes(),
mat.kid.clone(), mat.kid.clone(),
"g", "g",
Duration::from_secs(3600), Duration::from_hours(1),
) )
.unwrap(); .unwrap();
let auth = let auth =
@@ -623,7 +623,7 @@ mod tests {
&extension_audience("urn:openshell:extension:middleware:scanner"), &extension_audience("urn:openshell:extension:middleware:scanner"),
ExtensionCallerKind::Gateway, ExtensionCallerKind::Gateway,
None, None,
Duration::from_secs(300), Duration::from_mins(5),
) )
.expect("gateway token"); .expect("gateway token");
let mut validation = Validation::new(Algorithm::EdDSA); let mut validation = Validation::new(Algorithm::EdDSA);
@@ -644,7 +644,7 @@ mod tests {
&extension_audience("urn:openshell:extension:middleware:scanner"), &extension_audience("urn:openshell:extension:middleware:scanner"),
ExtensionCallerKind::Supervisor, ExtensionCallerKind::Supervisor,
Some("sandbox-a"), Some("sandbox-a"),
Duration::from_secs(300), Duration::from_mins(5),
) )
.expect("supervisor token"); .expect("supervisor token");
let claims = decode::<ExtensionJwtClaims>(&supervisor.token, &decoding_key, &validation) let claims = decode::<ExtensionJwtClaims>(&supervisor.token, &decoding_key, &validation)
@@ -662,7 +662,7 @@ mod tests {
mat.signing_key_pem.as_bytes(), mat.signing_key_pem.as_bytes(),
mat.kid.clone(), mat.kid.clone(),
"gateway-a", "gateway-a",
Duration::from_secs(3600), Duration::from_hours(1),
) )
.expect("issuer"); .expect("issuer");
@@ -671,7 +671,7 @@ mod tests {
&extension_audience("urn:openshell:extension:middleware:scanner"), &extension_audience("urn:openshell:extension:middleware:scanner"),
ExtensionCallerKind::Gateway, ExtensionCallerKind::Gateway,
None, None,
Duration::from_secs(300), Duration::from_mins(5),
) )
.expect("extension token"); .expect("extension token");
assert_eq!( assert_eq!(
@@ -704,7 +704,7 @@ mod tests {
&extension_audience("service-a"), &extension_audience("service-a"),
ExtensionCallerKind::Gateway, ExtensionCallerKind::Gateway,
None, None,
Duration::from_secs(60), Duration::from_mins(1),
) )
.expect("token"); .expect("token");
let decoding_key = DecodingKey::from_ed_pem(mat.public_key_pem.as_bytes()).unwrap(); 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"), &extension_audience("openshell-gateway:test-gateway"),
ExtensionCallerKind::Supervisor, ExtensionCallerKind::Supervisor,
Some("sandbox-a"), Some("sandbox-a"),
Duration::from_secs(60), Duration::from_mins(1),
) )
.expect_err("gateway sandbox audience must be reserved"); .expect_err("gateway sandbox audience must be reserved");
assert_eq!(error.code(), tonic::Code::InvalidArgument); assert_eq!(error.code(), tonic::Code::InvalidArgument);
@@ -755,7 +755,7 @@ mod tests {
&extension_audience("service"), &extension_audience("service"),
ExtensionCallerKind::Supervisor, ExtensionCallerKind::Supervisor,
None, None,
Duration::from_secs(60), Duration::from_mins(1),
) )
.is_err() .is_err()
); );
@@ -765,7 +765,7 @@ mod tests {
&extension_audience("service"), &extension_audience("service"),
ExtensionCallerKind::Gateway, ExtensionCallerKind::Gateway,
Some("sandbox-a"), Some("sandbox-a"),
Duration::from_secs(60), Duration::from_mins(1),
) )
.is_err() .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. /// Run the gateway CLI with the compute drivers linked by the binary.
pub async fn run_cli_with_compute_drivers(compute_drivers: ComputeDriverRegistry) -> Result<()> { 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 matches = command().get_matches();
let cli = Cli::from_arg_matches(&matches).expect("clap validated args"); 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(); l2.renew(&mut guard2).await.unwrap();
// Replica-1 cannot re-acquire (lease exists) // 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(); let err = l1_retry.try_acquire().await.unwrap_err();
assert!(matches!(err, LeaseError::AlreadyHeld)); assert!(matches!(err, LeaseError::AlreadyHeld));
+2 -2
View File
@@ -315,11 +315,11 @@ pub struct ComputeDriverInfoSnapshot {
} }
/// Interval between store-vs-backend reconciliation sweeps. /// 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 /// How long a sandbox can remain provisioning in the store without a
/// corresponding backend resource before it is considered orphaned. /// 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. // Re-export the shared error type under the name used by this module.
pub use openshell_core::ComputeDriverError as ComputeError; pub use openshell_core::ComputeDriverError as ComputeError;
@@ -23,7 +23,7 @@ use tonic::Status;
use tracing::{info, warn}; use tracing::{info, warn};
/// How long an allocated slot survives without being consumed. /// 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 /// Outstanding slots one caller may hold. Bounds the directories a single
/// authenticated caller can create by calling `begin` in a loop. /// authenticated caller can create by calling `begin` in a loop.
const MAX_SLOTS_PER_CALLER: usize = 4; 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 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)] #[allow(clippy::result_large_err)]
fn mint_extension_credentials( fn mint_extension_credentials(
@@ -323,7 +323,7 @@ mod tests {
mat.signing_key_pem.as_bytes(), mat.signing_key_pem.as_bytes(),
mat.kid, mat.kid,
"test-gateway", "test-gateway",
Duration::from_secs(3600), Duration::from_hours(1),
) )
.unwrap(); .unwrap();
state.sandbox_jwt_issuer = Some(Arc::new(issuer)); 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 update = request.get_ref();
let should_emit_policy_failure = should_emit_config_update_policy_telemetry(sandbox_caller) let should_emit_policy_failure = should_emit_config_update_policy_telemetry(sandbox_caller)
&& (update.policy.is_some() || !update.merge_operations.is_empty()); && (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 { if result.is_err() && should_emit_policy_failure {
emit_sandbox_policy_update_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 // string means findings or infrastructure error, both of which
// require human attention. // require human attention.
if auto_approve_enabled if auto_approve_enabled
&& let Err(err) = auto_approve_chunk( && let Err(err) = Box::pin(auto_approve_chunk(
state, state,
&effective_id, &effective_id,
AutoApproveChunkContext { AutoApproveChunkContext {
@@ -4608,7 +4614,7 @@ pub(super) async fn handle_submit_policy_analysis(
source: &req.analysis_mode, source: &req.analysis_mode,
resolved_from, resolved_from,
}, },
) ))
.await .await
{ {
persist_pending_application_error(state, &effective_id, &err).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>> = static TOKEN_EXCHANGE_HTTP_CLIENT: LazyLock<Result<reqwest::Client, String>> =
LazyLock::new(|| { LazyLock::new(|| {
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
reqwest::Client::builder() reqwest::Client::builder()
.timeout(std::time::Duration::from_secs(30)) .timeout(std::time::Duration::from_secs(30))
.connect_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, model_id: &str,
route: &ResolvedProviderRoute, route: &ResolvedProviderRoute,
) -> Result<ValidatedEndpoint, Status> { ) -> Result<ValidatedEndpoint, Status> {
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
let client = reqwest::Client::builder() let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30)) .timeout(Duration::from_secs(30))
.build() .build()
+6 -9
View File
@@ -98,7 +98,7 @@ struct GatewayExtensionCredential {
fn extension_token_ttl(issuer: &auth::sandbox_jwt::SandboxJwtIssuer) -> Duration { fn extension_token_ttl(issuer: &auth::sandbox_jwt::SandboxJwtIssuer) -> Duration {
if issuer.ttl().is_zero() { if issuer.ttl().is_zero() {
Duration::from_secs(15 * 60) Duration::from_mins(15)
} else { } else {
issuer.ttl().min(MAX_EXTENSION_TOKEN_TTL) issuer.ttl().min(MAX_EXTENSION_TOKEN_TTL)
} }
@@ -703,9 +703,9 @@ pub(crate) async fn run_server(
} }
state.compute.spawn_watchers(shutdown_rx.clone()); 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)); 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 // Create the multiplexed service
let service = MultiplexService::new(state.clone()); let service = MultiplexService::new(state.clone());
@@ -1610,9 +1610,8 @@ mod tests {
use tokio::sync::watch; use tokio::sync::watch;
use crate::{ use crate::{
compute::GatewayListenerRequirement, compute::GatewayListenerRequirement, gateway_listener::GatewayListenerSpec,
gateway_listener::GatewayListenerSpec, tls_test_utils::generate_test_certs_with_ca,
tls_test_utils::{generate_test_certs_with_ca, install_rustls_provider},
}; };
static DETECTION_PROBE_ORDER: LazyLock<Mutex<Vec<&'static str>>> = static DETECTION_PROBE_ORDER: LazyLock<Mutex<Vec<&'static str>>> =
@@ -1642,7 +1641,7 @@ mod tests {
material.signing_key_pem.as_bytes(), material.signing_key_pem.as_bytes(),
material.kid, material.kid,
"gateway-a", "gateway-a",
Duration::from_secs(900), Duration::from_mins(15),
) )
.expect("issuer"), .expect("issuer"),
) )
@@ -1773,8 +1772,6 @@ mod tests {
} }
fn test_tls_acceptor() -> (TempDir, TlsAcceptor) { fn test_tls_acceptor() -> (TempDir, TlsAcceptor) {
install_rustls_provider();
let dir = tempdir().expect("failed to create tempdir"); let dir = tempdir().expect("failed to create tempdir");
generate_test_certs_with_ca(dir.path()); generate_test_certs_with_ca(dir.path());
@@ -822,7 +822,8 @@ AND EXISTS (
) )
.unwrap(); .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(object_type)
.bind(member_type) .bind(member_type)
.bind(member_name); .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() let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30)) .timeout(Duration::from_secs(30))
.build() .build()
@@ -2401,6 +2402,7 @@ mod tests {
.mount(&mock_server) .mount(&mock_server)
.await; .await;
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
let response = reqwest::get(format!("{}/oversized", mock_server.uri())) let response = reqwest::get(format!("{}/oversized", mock_server.uri()))
.await .await
.unwrap(); .unwrap();
@@ -1663,7 +1663,7 @@ mod tests {
"sbx-test", "sbx-test",
relay_tx, relay_tx,
Instant::now() Instant::now()
.checked_sub(Duration::from_secs(60)) .checked_sub(Duration::from_mins(1))
.expect("test duration should be before now"), .expect("test duration should be before now"),
), ),
); );
@@ -1741,7 +1741,7 @@ mod tests {
"sbx-test", "sbx-test",
relay_tx, relay_tx,
Instant::now() Instant::now()
.checked_sub(Duration::from_secs(60)) .checked_sub(Duration::from_mins(1))
.expect("test duration should be before now"), .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, ConfigStateChangeBuilder, OCSF_TARGET, SandboxContext, SeverityId, StateId, StatusId,
}; };
use rustls::ServerConfig; use rustls::ServerConfig;
use rustls::crypto::ring::sign; use rustls::crypto::aws_lc_rs::sign;
use rustls::pki_types::{CertificateDer, PrivateKeyDer}; use rustls::pki_types::{CertificateDer, PrivateKeyDer};
use rustls::server::{ClientHello, ResolvesServerCert, WebPkiClientVerifier}; use rustls::server::{ClientHello, ResolvesServerCert, WebPkiClientVerifier};
use rustls::sign::CertifiedKey; use rustls::sign::CertifiedKey;
@@ -488,9 +488,7 @@ fn tls_ocsf_ctx() -> SandboxContext {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::tls_test_utils::{ use crate::tls_test_utils::{generate_test_certs_with_ca, write_test_file};
generate_test_certs_with_ca, install_rustls_provider, write_test_file,
};
use rcgen::{CertificateParams, IsCa, KeyPair, KeyUsagePurpose}; use rcgen::{CertificateParams, IsCa, KeyPair, KeyUsagePurpose};
use tokio::net::{TcpListener, TcpStream}; use tokio::net::{TcpListener, TcpStream};
@@ -532,7 +530,6 @@ mod tests {
#[test] #[test]
fn test_build_server_config() { fn test_build_server_config() {
install_rustls_provider();
let dir = tempfile::tempdir().expect("failed to create tempdir"); let dir = tempfile::tempdir().expect("failed to create tempdir");
let _ = generate_test_certs_with_ca(dir.path()); let _ = generate_test_certs_with_ca(dir.path());
@@ -553,7 +550,6 @@ mod tests {
#[test] #[test]
fn test_reload_success() { fn test_reload_success() {
install_rustls_provider();
let dir = tempfile::tempdir().expect("failed to create tempdir"); let dir = tempfile::tempdir().expect("failed to create tempdir");
let (ca_cert, ca_key) = generate_test_certs_with_ca(dir.path()); let (ca_cert, ca_key) = generate_test_certs_with_ca(dir.path());
@@ -574,7 +570,6 @@ mod tests {
#[test] #[test]
fn test_reload_invalid_preserves_old() { fn test_reload_invalid_preserves_old() {
install_rustls_provider();
let dir = tempfile::tempdir().expect("failed to create tempdir"); let dir = tempfile::tempdir().expect("failed to create tempdir");
generate_test_certs_with_ca(dir.path()); generate_test_certs_with_ca(dir.path());
@@ -607,8 +602,6 @@ mod tests {
#[tokio::test(flavor = "multi_thread")] #[tokio::test(flavor = "multi_thread")]
async fn test_concurrent_handshake_and_reload() { async fn test_concurrent_handshake_and_reload() {
install_rustls_provider();
let dir = tempfile::tempdir().expect("failed to create tempdir"); let dir = tempfile::tempdir().expect("failed to create tempdir");
let (ca_cert, ca_key) = generate_test_certs_with_ca(dir.path()); let (ca_cert, ca_key) = generate_test_certs_with_ca(dir.path());
let acceptor = TlsAcceptor::from_files( let acceptor = TlsAcceptor::from_files(
@@ -702,8 +695,6 @@ mod tests {
#[tokio::test] #[tokio::test]
async fn test_reload_serves_new_cert() { async fn test_reload_serves_new_cert() {
install_rustls_provider();
let dir = tempfile::tempdir().expect("failed to create tempdir"); let dir = tempfile::tempdir().expect("failed to create tempdir");
let (ca_cert, ca_key) = generate_test_certs_with_ca(dir.path()); let (ca_cert, ca_key) = generate_test_certs_with_ca(dir.path());
let acceptor = TlsAcceptor::from_files( let acceptor = TlsAcceptor::from_files(
@@ -778,8 +769,6 @@ mod tests {
#[tokio::test] #[tokio::test]
async fn test_reload_worker_shutdown() { async fn test_reload_worker_shutdown() {
install_rustls_provider();
let dir = tempfile::tempdir().expect("failed to create tempdir"); let dir = tempfile::tempdir().expect("failed to create tempdir");
generate_test_certs_with_ca(dir.path()); generate_test_certs_with_ca(dir.path());
let acceptor = TlsAcceptor::from_files( let acceptor = TlsAcceptor::from_files(
@@ -812,8 +801,6 @@ mod tests {
#[tokio::test] #[tokio::test]
async fn test_reload_worker_detects_file_change() { async fn test_reload_worker_detects_file_change() {
install_rustls_provider();
let dir = tempfile::tempdir().expect("failed to create tempdir"); let dir = tempfile::tempdir().expect("failed to create tempdir");
let (ca_cert, ca_key) = generate_test_certs_with_ca(dir.path()); let (ca_cert, ca_key) = generate_test_certs_with_ca(dir.path());
let acceptor = TlsAcceptor::from_files( let acceptor = TlsAcceptor::from_files(
@@ -902,8 +889,6 @@ mod tests {
#[tokio::test] #[tokio::test]
async fn test_reload_mtls_ca_rotation() { async fn test_reload_mtls_ca_rotation() {
install_rustls_provider();
let dir = tempfile::tempdir().expect("failed to create tempdir"); let dir = tempfile::tempdir().expect("failed to create tempdir");
let (initial_ca_cert, initial_ca_key) = generate_test_certs_with_ca(dir.path()); let (initial_ca_cert, initial_ca_key) = generate_test_certs_with_ca(dir.path());
@@ -1110,7 +1095,6 @@ mod tests {
#[test] #[test]
fn test_build_cert_resolver_returns_none_when_no_external() { fn test_build_cert_resolver_returns_none_when_no_external() {
install_rustls_provider();
let dir = tempfile::tempdir().expect("failed to create tempdir"); let dir = tempfile::tempdir().expect("failed to create tempdir");
generate_test_certs_with_ca(dir.path()); generate_test_certs_with_ca(dir.path());
@@ -1127,7 +1111,6 @@ mod tests {
#[test] #[test]
fn test_build_cert_resolver_errors_on_cert_without_key() { fn test_build_cert_resolver_errors_on_cert_without_key() {
install_rustls_provider();
let dir = tempfile::tempdir().expect("failed to create tempdir"); let dir = tempfile::tempdir().expect("failed to create tempdir");
generate_test_certs_with_ca(dir.path()); generate_test_certs_with_ca(dir.path());
@@ -1147,7 +1130,6 @@ mod tests {
#[test] #[test]
fn test_build_cert_resolver_errors_on_key_without_cert() { fn test_build_cert_resolver_errors_on_key_without_cert() {
install_rustls_provider();
let dir = tempfile::tempdir().expect("failed to create tempdir"); let dir = tempfile::tempdir().expect("failed to create tempdir");
generate_test_certs_with_ca(dir.path()); generate_test_certs_with_ca(dir.path());
@@ -1167,7 +1149,6 @@ mod tests {
#[test] #[test]
fn test_build_cert_resolver_errors_on_empty_server_names() { fn test_build_cert_resolver_errors_on_empty_server_names() {
install_rustls_provider();
let dir = tempfile::tempdir().expect("failed to create tempdir"); let dir = tempfile::tempdir().expect("failed to create tempdir");
let (ca_cert, ca_key) = generate_test_certs_with_ca(dir.path()); let (ca_cert, ca_key) = generate_test_certs_with_ca(dir.path());
generate_named_cert( generate_named_cert(
@@ -1195,7 +1176,6 @@ mod tests {
#[test] #[test]
fn test_dual_cert_resolver_returns_external_on_sni_match() { fn test_dual_cert_resolver_returns_external_on_sni_match() {
install_rustls_provider();
let dir = tempfile::tempdir().expect("failed to create tempdir"); let dir = tempfile::tempdir().expect("failed to create tempdir");
let (ca_cert, ca_key) = generate_test_certs_with_ca(dir.path()); let (ca_cert, ca_key) = generate_test_certs_with_ca(dir.path());
generate_named_cert( generate_named_cert(
@@ -1233,8 +1213,6 @@ mod tests {
#[tokio::test(flavor = "multi_thread")] #[tokio::test(flavor = "multi_thread")]
async fn test_dual_cert_resolver_sni_selects_correct_cert() { async fn test_dual_cert_resolver_sni_selects_correct_cert() {
install_rustls_provider();
let dir = tempfile::tempdir().expect("failed to create tempdir"); let dir = tempfile::tempdir().expect("failed to create tempdir");
let (ca_cert, ca_key) = generate_test_certs_with_ca(dir.path()); let (ca_cert, ca_key) = generate_test_certs_with_ca(dir.path());
generate_named_cert( generate_named_cert(
@@ -9,14 +9,6 @@ use std::path::Path;
use rcgen::{CertificateParams, IsCa, KeyPair}; 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. /// Write bytes to a file inside `dir`, panicking on failure.
pub fn write_test_file(dir: &Path, name: &str, data: &[u8]) { pub fn write_test_file(dir: &Path, name: &str, data: &[u8]) {
let path = dir.join(name); let path = dir.join(name);
@@ -613,11 +613,6 @@ impl OpenShell for TestOpenShell {
// TLS / PKI helpers (used by TLS integration tests) // 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). /// PKI bundle: CA cert, server cert+key, client cert+key (all PEM).
#[allow(clippy::struct_field_names)] #[allow(clippy::struct_field_names)]
pub struct PkiBundle { pub struct PkiBundle {
@@ -29,7 +29,7 @@ mod common;
use bytes::Bytes; use bytes::Bytes;
use common::{ use common::{
PkiBundle, build_tls_root, generate_pki, generate_rogue_pki, grpc_client_mtls, 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 http_body_util::Empty;
use hyper::{Request, StatusCode}; use hyper::{Request, StatusCode};
@@ -160,7 +160,6 @@ fn https_client_no_cert(
/// Valid client cert is accepted when a CA is configured. /// Valid client cert is accepted when a CA is configured.
#[tokio::test] #[tokio::test]
async fn mtls_valid_client_cert_accepted() { async fn mtls_valid_client_cert_accepted() {
install_rustls_provider();
let (temp, pki) = generate_pki(); let (temp, pki) = generate_pki();
let tls_acceptor = TlsAcceptor::from_files( 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. /// always optional. Auth is deferred to the application layer.
#[tokio::test] #[tokio::test]
async fn no_client_cert_accepted_with_ca_configured() { async fn no_client_cert_accepted_with_ca_configured() {
install_rustls_provider();
let (temp, pki) = generate_pki(); let (temp, pki) = generate_pki();
let tls_acceptor = TlsAcceptor::from_files( let tls_acceptor = TlsAcceptor::from_files(
@@ -250,7 +248,6 @@ async fn no_client_cert_accepted_with_ca_configured() {
/// cert is presented. /// cert is presented.
#[tokio::test] #[tokio::test]
async fn bearer_header_reaches_server_without_client_cert() { async fn bearer_header_reaches_server_without_client_cert() {
install_rustls_provider();
let (temp, pki) = generate_pki(); let (temp, pki) = generate_pki();
let tls_acceptor = TlsAcceptor::from_files( 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. /// client certs are optional — presented certs are still validated.
#[tokio::test] #[tokio::test]
async fn rogue_cert_rejected() { async fn rogue_cert_rejected() {
install_rustls_provider();
let (temp, pki) = generate_pki(); let (temp, pki) = generate_pki();
let tls_acceptor = TlsAcceptor::from_files( let tls_acceptor = TlsAcceptor::from_files(
@@ -333,7 +329,6 @@ async fn rogue_cert_rejected() {
/// client certificates. Clients connect with server-only TLS. /// client certificates. Clients connect with server-only TLS.
#[tokio::test] #[tokio::test]
async fn https_only_no_client_cert_required() { async fn https_only_no_client_cert_required() {
install_rustls_provider();
let (temp, pki) = generate_pki(); let (temp, pki) = generate_pki();
let tls_acceptor = TlsAcceptor::from_files( let tls_acceptor = TlsAcceptor::from_files(
@@ -6,7 +6,7 @@ mod common;
use bytes::Bytes; use bytes::Bytes;
use common::{ use common::{
PkiBundle, build_tls_root, generate_pki, generate_rogue_pki, grpc_client_mtls, 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 http_body_util::Empty;
use hyper::Request; use hyper::Request;
@@ -54,7 +54,6 @@ fn https_client_mtls(
#[tokio::test] #[tokio::test]
async fn serves_grpc_and_http_over_tls_on_same_port() { async fn serves_grpc_and_http_over_tls_on_same_port() {
install_rustls_provider();
let (temp, pki) = generate_pki(); let (temp, pki) = generate_pki();
let tls_acceptor = openshell_server::TlsAcceptor::from_files( 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] #[tokio::test]
async fn mtls_valid_client_cert_accepted() { async fn mtls_valid_client_cert_accepted() {
install_rustls_provider();
let (temp, pki) = generate_pki(); let (temp, pki) = generate_pki();
let tls_acceptor = openshell_server::TlsAcceptor::from_files( let tls_acceptor = openshell_server::TlsAcceptor::from_files(
@@ -127,7 +125,6 @@ async fn mtls_valid_client_cert_accepted() {
#[tokio::test] #[tokio::test]
async fn no_client_cert_accepted_with_ca() { async fn no_client_cert_accepted_with_ca() {
install_rustls_provider();
let (temp, pki) = generate_pki(); let (temp, pki) = generate_pki();
let tls_acceptor = openshell_server::TlsAcceptor::from_files( let tls_acceptor = openshell_server::TlsAcceptor::from_files(
@@ -166,7 +163,6 @@ async fn no_client_cert_accepted_with_ca() {
#[tokio::test] #[tokio::test]
async fn no_client_cert_rejected_when_required() { async fn no_client_cert_rejected_when_required() {
install_rustls_provider();
let (temp, pki) = generate_pki(); let (temp, pki) = generate_pki();
let tls_acceptor = openshell_server::TlsAcceptor::from_files( let tls_acceptor = openshell_server::TlsAcceptor::from_files(
@@ -206,7 +202,6 @@ async fn no_client_cert_rejected_when_required() {
#[tokio::test] #[tokio::test]
async fn mtls_wrong_ca_client_cert_rejected() { async fn mtls_wrong_ca_client_cert_rejected() {
install_rustls_provider();
let (temp, pki) = generate_pki(); let (temp, pki) = generate_pki();
let tls_acceptor = openshell_server::TlsAcceptor::from_files( let tls_acceptor = openshell_server::TlsAcceptor::from_files(
@@ -472,7 +472,7 @@ mod tests {
); );
assert_eq!( assert_eq!(
routes[1].timeout, routes[1].timeout,
Duration::from_secs(120), Duration::from_mins(2),
"timeout_secs=120 should map to 120s" "timeout_secs=120 should map to 120s"
); );
} }
@@ -7732,7 +7732,7 @@ network_policies:
.await .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( 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", 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] #[test]
fn upstream_config_alpn() { fn upstream_config_alpn() {
let _ = rustls::crypto::ring::default_provider().install_default();
let config = build_upstream_client_config("").unwrap(); let config = build_upstream_client_config("").unwrap();
assert_eq!(config.alpn_protocols, vec![b"http/1.1".to_vec()]); 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_RAW_FRAME_PAYLOAD_BYTES: u64 = 16 * 1024 * 1024;
const MAX_MESSAGE_FRAGMENTS: usize = 4096; const MAX_MESSAGE_FRAGMENTS: usize = 4096;
const TEXT_MESSAGE_ASSEMBLY_IDLE_TIMEOUT: StdDuration = StdDuration::from_secs(30); 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_ASSEMBLY_TOTAL_TIMEOUT: StdDuration = StdDuration::from_mins(2);
const TEXT_MESSAGE_FORWARD_TOTAL_TIMEOUT: StdDuration = StdDuration::from_secs(120); const TEXT_MESSAGE_FORWARD_TOTAL_TIMEOUT: StdDuration = StdDuration::from_mins(2);
const COPY_BUF_SIZE: usize = 8192; const COPY_BUF_SIZE: usize = 8192;
const OPCODE_CONTINUATION: u8 = 0x0; const OPCODE_CONTINUATION: u8 = 0x0;
const OPCODE_TEXT: u8 = 0x1; const OPCODE_TEXT: u8 = 0x1;
@@ -580,7 +580,7 @@ mod tests {
calls: AtomicUsize::new(0), calls: AtomicUsize::new(0),
answer: TrustedAnswer { answer: TrustedAnswer {
addresses, addresses,
ttl: Duration::from_secs(300), ttl: Duration::from_mins(5),
}, },
}, },
Arc::new(ResolvedEndpointStore::new( Arc::new(ResolvedEndpointStore::new(
@@ -984,6 +984,6 @@ process: { run_as_user: sandbox, run_as_group: sandbox }
clamp_mapping_ttl(Duration::from_secs(10)), clamp_mapping_ttl(Duration::from_secs(10)),
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 /// between "thinking" and output phases. 120s provides headroom while still
/// catching genuinely stuck streams. /// catching genuinely stuck streams.
#[cfg(not(test))] #[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. // Exercise idle-timeout truncation without slowing the full package test suite.
#[cfg(test)] #[cfg(test)]
const CHUNK_IDLE_TIMEOUT: std::time::Duration = std::time::Duration::from_millis(100); const CHUNK_IDLE_TIMEOUT: std::time::Duration = std::time::Duration::from_millis(100);
@@ -6783,7 +6783,7 @@ network_policies:
) )
.await .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); let (client, upstream) = tokio::join!(client, upstream);
client.expect("join plaintext WebSocket client"); client.expect("join plaintext WebSocket client");
assert_eq!( assert_eq!(
@@ -49,6 +49,7 @@ use spiffe::WorkloadApiClient;
/// Token cache shared across all provider token grants. /// Token cache shared across all provider token grants.
static TOKEN_CACHE: LazyLock<TokenCache> = LazyLock::new(TokenCache::new); static TOKEN_CACHE: LazyLock<TokenCache> = LazyLock::new(TokenCache::new);
static TOKEN_GRANT_HTTP_CLIENT: LazyLock<reqwest::Client> = LazyLock::new(|| { static TOKEN_GRANT_HTTP_CLIENT: LazyLock<reqwest::Client> = LazyLock::new(|| {
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
reqwest::Client::builder() reqwest::Client::builder()
.timeout(Duration::from_secs(30)) .timeout(Duration::from_secs(30))
.connect_timeout(Duration::from_secs(30)) .connect_timeout(Duration::from_secs(30))
@@ -1129,13 +1129,6 @@ mod tests {
config_from(pairs).unwrap().unwrap() 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] #[test]
fn no_env_yields_none() { fn no_env_yields_none() {
assert!(config_from(&[]).unwrap().is_none()); assert!(config_from(&[]).unwrap().is_none());
@@ -1270,7 +1263,6 @@ mod tests {
#[test] #[test]
fn https_proxy_scheme_enables_tls_and_requires_explicit_port() { fn https_proxy_scheme_enables_tls_and_requires_explicit_port() {
install_crypto_provider();
// An explicit port is required (no scheme-default fallback), matching // An explicit port is required (no scheme-default fallback), matching
// the http:// grammar. // the http:// grammar.
let err = config_from(&[(HTTPS_PROXY, "https://proxy.corp.com")]).unwrap_err(); let err = config_from(&[(HTTPS_PROXY, "https://proxy.corp.com")]).unwrap_err();
@@ -1314,7 +1306,6 @@ mod tests {
#[test] #[test]
fn unreadable_ca_bundle_is_fatal_for_https_proxy() { fn unreadable_ca_bundle_is_fatal_for_https_proxy() {
install_crypto_provider();
let err = config_from(&[ let err = config_from(&[
(HTTPS_PROXY, "https://proxy.corp.com:3130"), (HTTPS_PROXY, "https://proxy.corp.com:3130"),
(PROXY_CA_BUNDLE, "/nonexistent/proxy-ca.pem"), (PROXY_CA_BUNDLE, "/nonexistent/proxy-ca.pem"),
@@ -1338,7 +1329,6 @@ mod tests {
#[test] #[test]
fn ca_bundle_with_no_certificates_is_fatal() { fn ca_bundle_with_no_certificates_is_fatal() {
install_crypto_provider();
let bundle = tempfile::NamedTempFile::new().unwrap(); let bundle = tempfile::NamedTempFile::new().unwrap();
std::fs::write(bundle.path(), "not a certificate\n").unwrap(); std::fs::write(bundle.path(), "not a certificate\n").unwrap();
let path = bundle.path().to_string_lossy().into_owned(); let path = bundle.path().to_string_lossy().into_owned();
@@ -1352,7 +1342,6 @@ mod tests {
#[test] #[test]
fn ca_bundle_with_invalid_der_certificates_is_fatal() { fn ca_bundle_with_invalid_der_certificates_is_fatal() {
install_crypto_provider();
let bundle = tempfile::NamedTempFile::new().unwrap(); let bundle = tempfile::NamedTempFile::new().unwrap();
std::fs::write( std::fs::write(
bundle.path(), bundle.path(),
@@ -1439,7 +1428,6 @@ mod tests {
#[test] #[test]
fn auth_file_without_insecure_acknowledgement_is_allowed_for_https_proxy() { fn auth_file_without_insecure_acknowledgement_is_allowed_for_https_proxy() {
install_crypto_provider();
let file = tempfile::NamedTempFile::new().unwrap(); let file = tempfile::NamedTempFile::new().unwrap();
std::fs::write(file.path(), "user:secret\n").unwrap(); std::fs::write(file.path(), "user:secret\n").unwrap();
let path = file.path().to_str().unwrap().to_string(); let path = file.path().to_str().unwrap().to_string();
@@ -2013,8 +2001,6 @@ mod tests {
const SERVER_HOSTNAME: &str = "upstream.example.test"; 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 // Trusted CA; the client config trusts it, and the fake upstream
// server presents a leaf for SERVER_HOSTNAME signed by it. // server presents a leaf for SERVER_HOSTNAME signed by it.
let ca = tls::SandboxCa::generate().unwrap(); let ca = tls::SandboxCa::generate().unwrap();
@@ -2246,7 +2232,6 @@ mod tests {
/// the server task (yielding the received CONNECT request), and the /// the server task (yielding the received CONNECT request), and the
/// server certificate PEM to use as the corporate CA bundle. /// server certificate PEM to use as the corporate CA bundle.
async fn fake_tls_proxy() -> (SocketAddr, tokio::task::JoinHandle<String>, String) { async fn fake_tls_proxy() -> (SocketAddr, tokio::task::JoinHandle<String>, String) {
install_crypto_provider();
let key = rcgen::KeyPair::generate().unwrap(); let key = rcgen::KeyPair::generate().unwrap();
let cert = rcgen::CertificateParams::new(vec!["127.0.0.1".to_string()]) let cert = rcgen::CertificateParams::new(vec!["127.0.0.1".to_string()])
.unwrap() .unwrap()
+1
View File
@@ -53,6 +53,7 @@ registries = []
# -- Bans ---------------------------------------------------------------------- # -- Bans ----------------------------------------------------------------------
[bans] [bans]
deny = [{ name = "ring", reason = "Use the AWS-LC crypto backend instead." }]
multiple-versions = "warn" multiple-versions = "warn"
wildcards = "allow" wildcards = "allow"
highlight = "all" 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 crates/openshell-core/build.rs crates/openshell-core/build.rs
COPY proto/ proto/ COPY proto/ proto/
# Scope workspace to CLI crates only — avoids compiling aws-lc-sys (pulled # Scope workspace to CLI crates only to avoid compiling unrelated runtimes.
# by russh in openshell-sandbox/openshell-server) which is difficult to
# cross-compile and unnecessary for the CLI binary.
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 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 \ 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" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" 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]] [[package]]
name = "axum" name = "axum"
version = "0.8.9" version = "0.8.9"
@@ -157,6 +181,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5add81bb678e6cb321aff7fa0dc7689ad82b112dbc032cea19f91d6b8e3582b9" checksum = "5add81bb678e6cb321aff7fa0dc7689ad82b112dbc032cea19f91d6b8e3582b9"
dependencies = [ dependencies = [
"find-msvc-tools", "find-msvc-tools",
"jobserver",
"libc",
"shlex", "shlex",
] ]
@@ -172,6 +198,15 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527" checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527"
[[package]]
name = "cmake"
version = "0.1.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678"
dependencies = [
"cc",
]
[[package]] [[package]]
name = "cpufeatures" name = "cpufeatures"
version = "0.2.17" version = "0.2.17"
@@ -218,6 +253,12 @@ dependencies = [
"syn 3.0.3", "syn 3.0.3",
] ]
[[package]]
name = "dunce"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
[[package]] [[package]]
name = "either" name = "either"
version = "1.17.0" version = "1.17.0"
@@ -237,7 +278,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
dependencies = [ dependencies = [
"libc", "libc",
"windows-sys 0.61.2", "windows-sys",
] ]
[[package]] [[package]]
@@ -267,6 +308,12 @@ dependencies = [
"percent-encoding", "percent-encoding",
] ]
[[package]]
name = "fs_extra"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
[[package]] [[package]]
name = "futures-channel" name = "futures-channel"
version = "0.3.33" version = "0.3.33"
@@ -346,10 +393,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"js-sys",
"libc", "libc",
"wasi", "wasi",
"wasm-bindgen",
] ]
[[package]] [[package]]
@@ -665,6 +710,16 @@ version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" 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]] [[package]]
name = "js-sys" name = "js-sys"
version = "0.3.103" version = "0.3.103"
@@ -678,17 +733,20 @@ dependencies = [
[[package]] [[package]]
name = "jsonwebtoken" name = "jsonwebtoken"
version = "9.3.1" version = "10.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a87cc7a48537badeae96744432de36f4be2b4a34a05a5ef32e9dd8a1c169dde" checksum = "eba32bfb4ffdeaca3e34431072faf01745c9b26d25504aa7a6cf5684334fc4fc"
dependencies = [ dependencies = [
"aws-lc-rs",
"base64", "base64",
"getrandom 0.2.17",
"js-sys", "js-sys",
"pem", "pem",
"ring",
"serde", "serde",
"serde_json", "serde_json",
"signature",
"simple_asn1", "simple_asn1",
"zeroize",
] ]
[[package]] [[package]]
@@ -756,7 +814,7 @@ checksum = "30d65c71f1ce40ab09135ce117d742b9f8a19ff91a41a8b57ed50bc2de59c427"
dependencies = [ dependencies = [
"libc", "libc",
"wasi", "wasi",
"windows-sys 0.61.2", "windows-sys",
] ]
[[package]] [[package]]
@@ -923,6 +981,12 @@ version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
[[package]]
name = "pkg-config"
version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548"
[[package]] [[package]]
name = "potential_utf" name = "potential_utf"
version = "0.1.5" version = "0.1.5"
@@ -1007,7 +1071,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41" checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41"
dependencies = [ dependencies = [
"rand_chacha", "rand_chacha",
"rand_core", "rand_core 0.9.5",
] ]
[[package]] [[package]]
@@ -1017,7 +1081,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
dependencies = [ dependencies = [
"ppv-lite86", "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]] [[package]]
@@ -1038,20 +1111,6 @@ dependencies = [
"bitflags", "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]] [[package]]
name = "rustc-hash" name = "rustc-hash"
version = "2.1.3" version = "2.1.3"
@@ -1068,7 +1127,7 @@ dependencies = [
"errno", "errno",
"libc", "libc",
"linux-raw-sys", "linux-raw-sys",
"windows-sys 0.61.2", "windows-sys",
] ]
[[package]] [[package]]
@@ -1218,6 +1277,15 @@ dependencies = [
"libc", "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]] [[package]]
name = "simple_asn1" name = "simple_asn1"
version = "0.6.4" version = "0.6.4"
@@ -1249,7 +1317,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4" checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4"
dependencies = [ dependencies = [
"libc", "libc",
"windows-sys 0.61.2", "windows-sys",
] ]
[[package]] [[package]]
@@ -1307,7 +1375,7 @@ dependencies = [
"getrandom 0.4.3", "getrandom 0.4.3",
"once_cell", "once_cell",
"rustix", "rustix",
"windows-sys 0.61.2", "windows-sys",
] ]
[[package]] [[package]]
@@ -1384,7 +1452,7 @@ dependencies = [
"signal-hook-registry", "signal-hook-registry",
"socket2", "socket2",
"tokio-macros", "tokio-macros",
"windows-sys 0.61.2", "windows-sys",
] ]
[[package]] [[package]]
@@ -1545,9 +1613,9 @@ checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
[[package]] [[package]]
name = "untrusted" name = "untrusted"
version = "0.9.0" version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
[[package]] [[package]]
name = "url" name = "url"
@@ -1670,15 +1738,6 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" 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]] [[package]]
name = "windows-sys" name = "windows-sys"
version = "0.61.2" version = "0.61.2"
@@ -1688,70 +1747,6 @@ dependencies = [
"windows-link", "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]] [[package]]
name = "wit-bindgen" name = "wit-bindgen"
version = "0.57.1" version = "0.57.1"
@@ -1828,6 +1823,26 @@ dependencies = [
"synstructure", "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]] [[package]]
name = "zerotrie" name = "zerotrie"
version = "0.2.4" version = "0.2.4"
+1 -1
View File
@@ -211,7 +211,7 @@ futures-util = "0.3"
http-body-util = "0.1" http-body-util = "0.1"
hyper = { version = "1", features = ["client", "http1"] } hyper = { version = "1", features = ["client", "http1"] }
hyper-util = { version = "0.1", features = ["tokio"] } hyper-util = { version = "0.1", features = ["tokio"] }
jsonwebtoken = "9" jsonwebtoken = { version = "10", features = ["aws_lc_rs"] }
prost = "0.14" prost = "0.14"
tokio = { version = "1.43", features = ["full"] } tokio = { version = "1.43", features = ["full"] }
tokio-stream = { version = "0.1", features = ["net"] } 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" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" 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]] [[package]]
name = "axum" name = "axum"
version = "0.8.9" version = "0.8.9"
@@ -162,6 +186,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e228eec9be7c17ccb640b59b36a5cd805ea2a564a4c5e162c2f659fea30d3b96" checksum = "e228eec9be7c17ccb640b59b36a5cd805ea2a564a4c5e162c2f659fea30d3b96"
dependencies = [ dependencies = [
"find-msvc-tools", "find-msvc-tools",
"jobserver",
"libc",
"shlex", "shlex",
] ]
@@ -185,7 +211,16 @@ checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"cpufeatures 0.3.0", "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]] [[package]]
@@ -281,6 +316,12 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "dunce"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
[[package]] [[package]]
name = "either" name = "either"
version = "1.16.0" version = "1.16.0"
@@ -342,6 +383,12 @@ dependencies = [
"percent-encoding", "percent-encoding",
] ]
[[package]]
name = "fs_extra"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
[[package]] [[package]]
name = "futures-channel" name = "futures-channel"
version = "0.3.32" version = "0.3.32"
@@ -398,10 +445,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"js-sys",
"libc", "libc",
"wasi", "wasi",
"wasm-bindgen",
] ]
[[package]] [[package]]
@@ -413,7 +458,7 @@ dependencies = [
"cfg-if", "cfg-if",
"libc", "libc",
"r-efi", "r-efi",
"rand_core", "rand_core 0.10.1",
] ]
[[package]] [[package]]
@@ -778,6 +823,16 @@ dependencies = [
"syn", "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]] [[package]]
name = "js-sys" name = "js-sys"
version = "0.3.103" version = "0.3.103"
@@ -791,17 +846,20 @@ dependencies = [
[[package]] [[package]]
name = "jsonwebtoken" name = "jsonwebtoken"
version = "9.3.1" version = "10.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a87cc7a48537badeae96744432de36f4be2b4a34a05a5ef32e9dd8a1c169dde" checksum = "eba32bfb4ffdeaca3e34431072faf01745c9b26d25504aa7a6cf5684334fc4fc"
dependencies = [ dependencies = [
"aws-lc-rs",
"base64", "base64",
"getrandom 0.2.17",
"js-sys", "js-sys",
"pem", "pem",
"ring",
"serde", "serde",
"serde_json", "serde_json",
"signature",
"simple_asn1", "simple_asn1",
"zeroize",
] ]
[[package]] [[package]]
@@ -1183,6 +1241,12 @@ version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
[[package]]
name = "pkg-config"
version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548"
[[package]] [[package]]
name = "portable-atomic" name = "portable-atomic"
version = "1.15.0" version = "1.15.0"
@@ -1396,7 +1460,16 @@ checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80"
dependencies = [ dependencies = [
"chacha20", "chacha20",
"getrandom 0.4.3", "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]] [[package]]
@@ -1411,8 +1484,8 @@ version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75e669e5202259b5314d1ea5397316ad400819437857b90861765f24c4cf80a2" checksum = "75e669e5202259b5314d1ea5397316ad400819437857b90861765f24c4cf80a2"
dependencies = [ dependencies = [
"aws-lc-rs",
"pem", "pem",
"ring",
"rustls-pki-types", "rustls-pki-types",
"time", "time",
"yasna", "yasna",
@@ -1466,7 +1539,7 @@ dependencies = [
"cfg-if", "cfg-if",
"getrandom 0.2.17", "getrandom 0.2.17",
"libc", "libc",
"untrusted", "untrusted 0.9.0",
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
@@ -1510,9 +1583,9 @@ version = "0.23.41"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b92b125634d9b795e7beca796cc790df15a7fb38323bf3196fda83292d06b1f" checksum = "6b92b125634d9b795e7beca796cc790df15a7fb38323bf3196fda83292d06b1f"
dependencies = [ dependencies = [
"aws-lc-rs",
"log", "log",
"once_cell", "once_cell",
"ring",
"rustls-pki-types", "rustls-pki-types",
"rustls-webpki", "rustls-webpki",
"subtle", "subtle",
@@ -1555,9 +1628,10 @@ version = "0.103.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e"
dependencies = [ dependencies = [
"aws-lc-rs",
"ring", "ring",
"rustls-pki-types", "rustls-pki-types",
"untrusted", "untrusted 0.9.0",
] ]
[[package]] [[package]]
@@ -1699,6 +1773,15 @@ dependencies = [
"libc", "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]] [[package]]
name = "simd_cesu8" name = "simd_cesu8"
version = "1.2.0" version = "1.2.0"
@@ -2154,6 +2237,12 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254"
[[package]]
name = "untrusted"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
[[package]] [[package]]
name = "untrusted" name = "untrusted"
version = "0.9.0" version = "0.9.0"
@@ -2415,6 +2504,20 @@ name = "zeroize"
version = "1.9.0" version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" 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]] [[package]]
name = "zerotrie" name = "zerotrie"
+3 -3
View File
@@ -7,18 +7,18 @@
name = "openshell-governance-interceptor-example" name = "openshell-governance-interceptor-example"
version = "0.0.0" version = "0.0.0"
edition = "2024" edition = "2024"
rust-version = "1.90" rust-version = "1.94"
license = "Apache-2.0" license = "Apache-2.0"
[dependencies] [dependencies]
jsonwebtoken = "9" jsonwebtoken = { version = "10", features = ["aws_lc_rs"] }
openshell-core = { path = "../../crates/openshell-core", default-features = false } openshell-core = { path = "../../crates/openshell-core", default-features = false }
openshell-policy = { path = "../../crates/openshell-policy" } openshell-policy = { path = "../../crates/openshell-policy" }
openshell-providers = { path = "../../crates/openshell-providers" } openshell-providers = { path = "../../crates/openshell-providers" }
prost = "0.14" prost = "0.14"
prost-reflect = { version = "0.16.5", features = ["serde"] } prost-reflect = { version = "0.16.5", features = ["serde"] }
prost-types = "0.14" 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 = { version = "1", features = ["derive"] }
serde_json = "1" serde_json = "1"
serde_yml = { package = "noyalib", version = "0.0.28", default-features = false, features = ["std", "compat-serde-yaml"] } 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" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" 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]] [[package]]
name = "axum" name = "axum"
version = "0.8.9" version = "0.8.9"
@@ -191,6 +214,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e228eec9be7c17ccb640b59b36a5cd805ea2a564a4c5e162c2f659fea30d3b96" checksum = "e228eec9be7c17ccb640b59b36a5cd805ea2a564a4c5e162c2f659fea30d3b96"
dependencies = [ dependencies = [
"find-msvc-tools", "find-msvc-tools",
"jobserver",
"libc",
"shlex", "shlex",
] ]
@@ -246,6 +271,15 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9"
[[package]]
name = "cmake"
version = "0.1.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678"
dependencies = [
"cc",
]
[[package]] [[package]]
name = "colorchoice" name = "colorchoice"
version = "1.0.5" version = "1.0.5"
@@ -279,6 +313,12 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "dunce"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
[[package]] [[package]]
name = "either" name = "either"
version = "1.16.0" version = "1.16.0"
@@ -340,6 +380,12 @@ dependencies = [
"percent-encoding", "percent-encoding",
] ]
[[package]]
name = "fs_extra"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
[[package]] [[package]]
name = "futures-channel" name = "futures-channel"
version = "0.3.32" version = "0.3.32"
@@ -699,6 +745,16 @@ version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" 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]] [[package]]
name = "libc" name = "libc"
version = "0.2.186" version = "0.2.186"
@@ -970,6 +1026,12 @@ version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
[[package]]
name = "pkg-config"
version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548"
[[package]] [[package]]
name = "potential_utf" name = "potential_utf"
version = "0.1.5" version = "0.1.5"
@@ -1227,9 +1289,9 @@ version = "0.23.41"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b92b125634d9b795e7beca796cc790df15a7fb38323bf3196fda83292d06b1f" checksum = "6b92b125634d9b795e7beca796cc790df15a7fb38323bf3196fda83292d06b1f"
dependencies = [ dependencies = [
"aws-lc-rs",
"log", "log",
"once_cell", "once_cell",
"ring",
"rustls-pki-types", "rustls-pki-types",
"rustls-webpki", "rustls-webpki",
"subtle", "subtle",
@@ -1272,6 +1334,7 @@ version = "0.103.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e"
dependencies = [ dependencies = [
"aws-lc-rs",
"ring", "ring",
"rustls-pki-types", "rustls-pki-types",
"untrusted", "untrusted",
@@ -8,7 +8,7 @@ name = "openshell-supervisor-middleware-content-guard"
description = "Example OpenShell supervisor middleware service" description = "Example OpenShell supervisor middleware service"
version = "0.0.0" version = "0.0.0"
edition = "2024" edition = "2024"
rust-version = "1.90" rust-version = "1.94"
license = "Apache-2.0" license = "Apache-2.0"
publish = false publish = false