Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .agents/skills/watch-github-actions/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -344,3 +344,11 @@ gh run rerun <run-id>
```bash
gh run rerun <run-id> --failed
```

## Crypto backend independence

For failures in Branch Checks' crypto independence step, run
`mise run rust:verify:library-crypto` from the checkout. It checks external library
consumer graphs and TLS/JWT behavior separately from workspace tests, then checks
executable backend defaults. Do not add AWS-LC to a shared library to make a test
pass; standalone library tests select their backend in development dependencies.
1 change: 1 addition & 0 deletions .github/workflows/branch-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,7 @@ jobs:
exit 1
fi
cargo test --locked -p openshell-crypto --no-default-features --test independent_backend
mise run rust:verify:library-crypto

- name: Verify OpenSSL backend
shell: nix develop .#crypto -c bash -euo pipefail {0}
Expand Down
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ license = "Apache-2.0"
repository = "https://github.com/NVIDIA/OpenShell"

[workspace.dependencies]
# Product backend selection. Consumer crates inherit this choice.
openshell-crypto = { path = "crates/openshell-crypto", default-features = false, features = ["aws-lc"] }
# Libraries inherit only the facade. Executable packages select their backend.
openshell-crypto = { path = "crates/openshell-crypto", default-features = false }
# Async runtime
tokio = { version = "1.53.3", features = ["full"] }

Expand Down Expand Up @@ -74,7 +74,7 @@ opentelemetry-proto = { version = "0.33", default-features = false, features = [
opentelemetry = "0.33"
opentelemetry_sdk = { version = "0.33", features = ["rt-tokio"] }
opentelemetry-http = { version = "0.33", default-features = false }
opentelemetry-otlp = { version = "0.33", default-features = false, features = ["grpc-tonic", "gzip-tonic", "tls-aws-lc", "tls-roots", "trace"] }
opentelemetry-otlp = { version = "0.33", default-features = false, features = ["grpc-tonic", "gzip-tonic", "tls-provider-agnostic", "tls-roots", "trace"] }
tracing-opentelemetry = { version = "0.34", default-features = false, features = ["tracing-log"] }

# Metrics
Expand Down
3 changes: 3 additions & 0 deletions crates/openshell-binary-identity/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@ openshell-crypto = { workspace = true }

[lints]
workspace = true

[dev-dependencies]
openshell-crypto = { workspace = true, features = ["aws-lc"] }
1 change: 1 addition & 0 deletions crates/openshell-bootstrap/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ tokio = { workspace = true }
tracing = { workspace = true }

[dev-dependencies]
openshell-crypto = { workspace = true, features = ["aws-lc"] }
x509-parser = "0.16"

[lints]
Expand Down
2 changes: 1 addition & 1 deletion crates/openshell-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ name = "openshell"
path = "src/main.rs"

[dependencies]
openshell-crypto = { workspace = true }
openshell-crypto = { workspace = true, features = ["aws-lc"] }
openshell-bootstrap = { path = "../openshell-bootstrap" }
openshell-core = { path = "../openshell-core", default-features = false }
openshell-otel = { path = "../openshell-otel", default-features = false }
Expand Down
1 change: 1 addition & 0 deletions crates/openshell-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ tonic-prost-build = { workspace = true }
protoc-bin-vendored = { workspace = true }

[dev-dependencies]
openshell-crypto = { workspace = true, features = ["aws-lc"] }
h2 = "0.4"
rcgen = { workspace = true }
tempfile = "3"
Expand Down
1 change: 1 addition & 0 deletions crates/openshell-core/src/grpc_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,7 @@ fn configure_gateway_tls(
ca_pem: Vec<u8>,
server_name: Option<&str>,
) -> Result<Endpoint> {
openshell_crypto::tls::ensure_default_provider();
let mut tls_config = ClientTlsConfig::new().ca_certificate(Certificate::from_pem(ca_pem));
if let Some(server_name) = server_name.filter(|name| !name.is_empty()) {
tls_config = tls_config.domain_name(server_name);
Expand Down
8 changes: 8 additions & 0 deletions crates/openshell-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@
//! - Configuration management
//! - Common error types
//! - Build version metadata
//!
//! # Cryptography
//!
//! This library does not select a crypto implementation. Add `openshell-crypto`
//! with its default features for AWS-LC, or disable those defaults and install
//! your own `CryptoContext` before constructing TLS/JWT clients or using crypto.
//! Existing Rustls process providers are preserved by dependency-owned clients;
//! selecting a context does not replace an already installed process provider.

pub mod activity;
pub mod app_listener;
Expand Down
9 changes: 5 additions & 4 deletions crates/openshell-crypto/CRYPTO.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Cryptography and FIPS

OpenShell routes first-party security-sensitive cryptography through
`openshell-crypto`. The workspace selects AWS-LC as the production backend.
`openshell-crypto`. Executable packages select their backend explicitly.
The opt-in `openssl` feature supplies a system-OpenSSL backend for explicit
context selection. Neither backend asserts deployment FIPS compliance, and strict
posture requests fail closed. Application startup, dependency-owned transports,
Expand Down Expand Up @@ -29,9 +29,10 @@ remain compatibility constraints when adding or changing a backend.

## Selection and initialization

Consumer crates inherit the workspace's backend choice and enable integration
features on the facade. A build without the default backend must install a
context before facade use. Select the context before constructing clients,
Reusable libraries inherit a backend-neutral workspace dependency and enable
integration features on the facade. Executable packages select AWS-LC explicitly;
standalone library tests select it through development dependencies. An embedder
must select a backend and install its context before facade use. Select the context before constructing clients,
listeners, or dependencies that initialize process-wide crypto providers.

Explicit context selection controls first-party TLS builders even when a
Expand Down
36 changes: 28 additions & 8 deletions crates/openshell-crypto/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,26 @@ depending on rcgen's compiled crypto implementation.

## Build selection

The crate's default `aws-lc` feature selects the current implementation. The root
workspace declares that choice once in its `openshell-crypto` dependency;
application crates inherit it rather than choosing a backend independently.
Standalone examples select their own default through their path dependency.
Disabling crate defaults removes its AWS-LC implementation and requires an
explicit context before use; use without initialization fails closed with an
initialization panic. This mode is for embedders and backend contract tests, not
an independently runnable OpenShell product configuration.
The crate's default `aws-lc` feature selects the current implementation. The
workspace dependency disables defaults and selects no backend. Reusable libraries
including `openshell-core`, `openshell-sdk`, and `openshell-policy` therefore do
not enable AWS-LC, including through core's optional telemetry and tracing features.
Their development dependencies select AWS-LC only for standalone crate tests.

Executable packages explicitly enable `openshell-crypto/aws-lc`, including builds
with package defaults disabled. This preserves shipped behavior. Cargo features
apply to a whole package: the library targets in CLI, gateway, supervisor, sandbox,
and standalone driver packages also carry that product choice. Embed through the
backend-neutral core/SDK/policy crates when choosing your own implementation.
Standalone examples and test harnesses select their backend explicitly.

An embedder can depend on `openshell-crypto` with `default-features = false`,
implement `CryptoBackend` and `ProtocolBackend`, and call
`install_default_context(CryptoContext::new(Box::new(backend)))` before constructing
clients or performing cryptography. Merely installing a Rustls provider does not
supply primitive, PKI, or JWT operations. To retain OpenShell's AWS-LC behavior,
add `openshell-crypto` with its default features enabled. Using facade operations
without a selected backend fails closed with an initialization panic.

Integration features (`tls-tonic`, `tls-kube`, `tls-sqlx`) activate
dependencies. The `aws-lc` feature supplies their AWS-LC choices conditionally.
Expand Down Expand Up @@ -322,3 +334,11 @@ not target RHEL qualification or product E2E tests.
Existing bootstrap, credential-store, gateway TLS/OIDC, and proxy tests exercise the
migrated consumers. The cargo-deny Ring restrictions and their explicit wrapper
exceptions remain in force.

`mise run rust:verify:library-crypto` checks isolated consumer graphs for core,
SDK, and policy, then runs TLS and JWT probes with consumer-owned Ring/RustCrypto
implementations. The fixture is outside the product workspace, so product and
dev-dependency feature unification cannot hide regressions. Ring here is a test
consumer choice, not a new production backend or a relaxation of `deny.toml`.
The same check verifies AWS-LC remains selected by executable packages both with
and without their default features.
1 change: 1 addition & 0 deletions crates/openshell-driver-db-credstore/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ toml = { workspace = true }
tonic = { workspace = true }

[dev-dependencies]
openshell-crypto = { workspace = true, features = ["aws-lc"] }
tempfile = "3"
tokio = { workspace = true }

Expand Down
2 changes: 2 additions & 0 deletions crates/openshell-driver-docker/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ name = "openshell-driver-docker"
path = "src/main.rs"

[dependencies]
# Product backend selection also applies when building without default features.
openshell-crypto = { workspace = true, features = ["aws-lc"] }
openshell-core = { path = "../openshell-core", default-features = false, features = ["driver-extraction", "otel", "clap"] }
openshell-isolation-interface = { path = "../openshell-isolation-interface" }
openshell-sandbox-backend = { path = "../openshell-sandbox-backend" }
Expand Down
2 changes: 1 addition & 1 deletion crates/openshell-driver-kubernetes-secrets/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ name = "openshell-driver-kubernetes-secrets"
path = "src/main.rs"

[dependencies]
openshell-crypto = { workspace = true, features = ["tls-kube"] }
openshell-crypto = { workspace = true, features = ["aws-lc", "tls-kube"] }
openshell-core = { path = "../openshell-core", default-features = false }

clap = { workspace = true }
Expand Down
2 changes: 1 addition & 1 deletion crates/openshell-driver-kubernetes/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ name = "openshell-driver-kubernetes"
path = "src/main.rs"

[dependencies]
openshell-crypto = { workspace = true, features = ["tls-kube"] }
openshell-crypto = { workspace = true, features = ["aws-lc", "tls-kube"] }
openshell-core = { path = "../openshell-core", default-features = false, features = ["jwt", "otel", "clap"] }
openshell-isolation-interface = { path = "../openshell-isolation-interface" }
openshell-sandbox-backend = { path = "../openshell-sandbox-backend" }
Expand Down
2 changes: 1 addition & 1 deletion crates/openshell-driver-mxc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ openshell-supervisor-network = { path = "../openshell-supervisor-network" }
windows = { workspace = true }

[dev-dependencies]
openshell-crypto = { workspace = true }
openshell-crypto = { workspace = true, features = ["aws-lc"] }
tokio = { workspace = true }
# tempfile is not a workspace dependency; 3.27 is already resolved in Cargo.lock.
tempfile = "3"
Expand Down
2 changes: 2 additions & 0 deletions crates/openshell-driver-podman/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ name = "openshell-driver-podman"
path = "src/main.rs"

[dependencies]
# Product backend selection also applies when building without default features.
openshell-crypto = { workspace = true, features = ["aws-lc"] }
openshell-core = { path = "../openshell-core", default-features = false, features = ["driver-extraction", "otel", "clap"] }
openshell-otel = { path = "../openshell-otel" }
openshell-isolation-interface = { path = "../openshell-isolation-interface" }
Expand Down
2 changes: 1 addition & 1 deletion crates/openshell-driver-vault/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ name = "openshell-driver-vault"
path = "src/main.rs"

[dependencies]
openshell-crypto = { workspace = true }
openshell-crypto = { workspace = true, features = ["aws-lc"] }
openshell-core = { path = "../openshell-core", default-features = false }

clap = { workspace = true }
Expand Down
3 changes: 1 addition & 2 deletions crates/openshell-driver-vm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ opentelemetry = { workspace = true, optional = true }
opentelemetry_sdk = { workspace = true, optional = true }
tracing-opentelemetry = { workspace = true, optional = true }
miette = { workspace = true, optional = true }
openshell-crypto = { workspace = true, optional = true }
openshell-crypto = { workspace = true, features = ["aws-lc"] }
url = { workspace = true, optional = true }
serde = { workspace = true }
serde_json = { workspace = true }
Expand Down Expand Up @@ -89,7 +89,6 @@ compute-driver = [
"dep:polling",
"dep:prost",
"dep:prost-types",
"dep:openshell-crypto",
"dep:sha2",
"dep:tar",
"dep:tokio-stream",
Expand Down
3 changes: 2 additions & 1 deletion crates/openshell-extension-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ license.workspace = true
repository.workspace = true

[dependencies]
openshell-crypto = { workspace = true }
hyper-util = { workspace = true, features = ["tokio"] }
serde = { workspace = true, features = ["derive"] }
thiserror = { workspace = true }
Expand All @@ -19,7 +20,7 @@ tonic = { workspace = true, features = ["channel", "tls-native-roots"] }
tower = { workspace = true }

[dev-dependencies]
openshell-crypto = { workspace = true }
openshell-crypto = { workspace = true, features = ["aws-lc"] }
http = { workspace = true }
rcgen = { workspace = true }
rustls = { workspace = true }
Expand Down
1 change: 1 addition & 0 deletions crates/openshell-extension-core/src/transport.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ pub async fn connect_channel(config: &ExtensionChannelConfig) -> Result<Channel,

let mut endpoint = standard_endpoint(&config.endpoint)?;
if config.endpoint.starts_with("https://") {
openshell_crypto::tls::ensure_default_provider();
let tls = match &config.server_trust {
ExtensionServerTrust::PlatformRoots => ClientTlsConfig::new().with_enabled_roots(),
ExtensionServerTrust::CustomCaPem(pem) => {
Expand Down
2 changes: 2 additions & 0 deletions crates/openshell-gateway/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ name = "openshell-gateway"
path = "src/main.rs"

[dependencies]
# Product backend selection also applies when building without default features.
openshell-crypto = { workspace = true, features = ["aws-lc"] }
serde_json = { workspace = true }
openshell-core = { path = "../openshell-core", default-features = false }
openshell-server = { path = "../openshell-server", default-features = false }
Expand Down
2 changes: 2 additions & 0 deletions crates/openshell-otel-test-support/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ tracing = { workspace = true }
tracing-subscriber = { workspace = true }

[dev-dependencies]
openshell-crypto = { workspace = true, features = ["aws-lc"] }
rcgen = { workspace = true }
tempfile = "3"

[lints]
Expand Down
1 change: 1 addition & 0 deletions crates/openshell-otel/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ tower-http = { workspace = true, optional = true }
zeroize = { workspace = true, optional = true }

[dev-dependencies]
openshell-crypto = { workspace = true, features = ["aws-lc"] }
openshell-otel-test-support = { path = "../openshell-otel-test-support" }
opentelemetry-proto = { workspace = true, features = ["logs"] }
opentelemetry_sdk = { workspace = true, features = ["testing"] }
Expand Down
2 changes: 2 additions & 0 deletions crates/openshell-prover-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ vendored-z3 = ["openshell-prover/vendored-z3"]
prebuilt-z3 = ["openshell-prover/prebuilt-z3"]

[dependencies]
# Product backend selection also applies when building without default features.
openshell-crypto = { workspace = true, features = ["aws-lc"] }
clap.workspace = true
openshell-prover = { path = "../openshell-prover" }
serde.workspace = true
Expand Down
1 change: 1 addition & 0 deletions crates/openshell-sandbox-backend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ libc = "0.2"
rustix = { workspace = true, features = ["fs", "process"] }

[dev-dependencies]
openshell-crypto = { workspace = true, features = ["aws-lc"] }
jsonwebtoken = { workspace = true }

[lints]
Expand Down
2 changes: 1 addition & 1 deletion crates/openshell-sandbox/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ perf-harness = []

[dependencies]
openshell-core = { path = "../openshell-core", default-features = false }
openshell-crypto = { workspace = true }
openshell-crypto = { workspace = true, features = ["aws-lc"] }
openshell-binary-identity = { path = "../openshell-binary-identity" }
openshell-isolation-interface = { path = "../openshell-isolation-interface" }
openshell-sandbox-backend = { path = "../openshell-sandbox-backend" }
Expand Down
1 change: 1 addition & 0 deletions crates/openshell-sdk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ tracing = { workspace = true }
async-stream = "0.3.6"

[dev-dependencies]
openshell-crypto = { workspace = true, features = ["aws-lc"] }
serde_json = { workspace = true }
tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }
tokio-stream = { workspace = true }
Expand Down
3 changes: 3 additions & 0 deletions crates/openshell-sdk/src/edge_tunnel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,9 @@ async fn open_ws(config: &TunnelConfig) -> Result<WebSocketStream<MaybeTlsStream

debug!(url = %config.ws_url, "opening WebSocket to edge");

if config.ws_url.starts_with("wss://") {
openshell_crypto::tls::ensure_default_provider();
}
let (ws_stream, response) = tokio_tungstenite::connect_async(request)
.await
.map_err(|e| SdkError::connect(format!("WebSocket connect failed: {e}")))?;
Expand Down
8 changes: 8 additions & 0 deletions crates/openshell-sdk/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@
//! # Ok(())
//! # }
//! ```
//!
//! # Cryptography
//!
//! This library does not select a crypto implementation. Add `openshell-crypto`
//! with its default features for AWS-LC, or disable those defaults and install
//! your own `CryptoContext` before constructing TLS/JWT clients or using crypto.
//! Existing Rustls process providers are preserved by dependency-owned clients;
//! selecting a context does not replace an already installed process provider.

pub mod auth;
pub mod client;
Expand Down
2 changes: 2 additions & 0 deletions crates/openshell-sdk/src/transport.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ pub async fn build_channel(config: &ClientConfig) -> Result<Channel> {
// is added by the gRPC interceptor at request time, not here —
// `build_channel` only owns the TLS layer.

// Tonic must use the host or facade provider, including backend-free builds.
openshell_crypto::tls::ensure_default_provider();
let mut tls_config = config.ca_cert.as_ref().map_or_else(
|| ClientTlsConfig::new().with_enabled_roots(),
|ca_cert| ClientTlsConfig::new().ca_certificate(Certificate::from_pem(ca_cert)),
Expand Down
1 change: 1 addition & 0 deletions crates/openshell-server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ tonic-prost-build = { workspace = true }
protoc-bin-vendored = { workspace = true }

[dev-dependencies]
openshell-crypto = { workspace = true, features = ["aws-lc"] }
openshell-credential-issuer = { path = "../openshell-credential-issuer", features = ["test-support"] }
tracing-core = "0.1"
rustls-pki-types = "1.9"
Expand Down
1 change: 1 addition & 0 deletions crates/openshell-supervisor-network/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ default = ["bundled-ca-roots"]
bundled-ca-roots = ["dep:webpki-roots"]

[dev-dependencies]
openshell-crypto = { workspace = true, features = ["aws-lc"] }
openshell-sandbox-backend = { path = "../openshell-sandbox-backend", features = ["test-support"] }

openshell-driver-vm = { path = "../openshell-driver-vm", default-features = false, features = ["allocation-tracking"] }
Expand Down
Loading
Loading