Skip to content

Commit 43a6ff1

Browse files
app-storage: ENCLAVEAPP_MOCK_STORAGE env var forces mock backend (#71)
Adds a runtime escape hatch for environments that cannot satisfy a real hardware-backed backend. When ENCLAVEAPP_MOCK_STORAGE is set to a non-empty value, create_encryption_storage returns a fresh MockEncryptionStorage instead of initialising AppEncryptionStorage. Primary use case: GitHub Actions macOS runners running integration tests that would otherwise block indefinitely on a login-keychain ACL confirmation prompt the headless runner cannot answer. The library tests in enclaveapp-apple still exercise the real keychain path locally — this only affects consumer integration tests that opt in via the env var. Mechanical changes: - Move the mock module off the `mock` feature gate and compile it unconditionally; the aes-gcm + rand cost is already paid by the dependency graph. - Re-export MockEncryptionStorage for downstream consumers. - Drop the now-redundant `mock` feature from Cargo.toml. Co-authored-by: Jay Gowdy <jay@gowdy.me>
1 parent 9bff626 commit 43a6ff1

3 files changed

Lines changed: 36 additions & 6 deletions

File tree

crates/enclaveapp-app-storage/Cargo.toml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,16 @@ workspace = true
1212

1313
[features]
1414
default = []
15-
mock = ["aes-gcm", "rand"]
1615

1716
[dependencies]
1817
enclaveapp-core = { workspace = true }
1918
thiserror = { workspace = true }
2019
tracing = "0.1"
2120

22-
# Mock backend (feature-gated)
23-
aes-gcm = { workspace = true, optional = true }
24-
rand = { workspace = true, optional = true }
21+
# Mock backend — always compiled so `ENCLAVEAPP_MOCK_STORAGE=1` can
22+
# swap it in at runtime without any feature flag gymnastics.
23+
aes-gcm = { workspace = true }
24+
rand = { workspace = true }
2525

2626
[dev-dependencies]
2727
enclaveapp-test-support = { workspace = true }

crates/enclaveapp-app-storage/src/lib.rs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,14 @@
4949
5050
pub mod encryption;
5151
pub mod error;
52-
#[cfg(feature = "mock")]
5352
pub mod mock;
5453
pub mod platform;
5554
pub mod signing;
5655

5756
// Re-export primary types for consumers.
5857
pub use encryption::{AppEncryptionStorage, EncryptionStorage};
5958
pub use error::{Result, StorageError};
59+
pub use mock::MockEncryptionStorage;
6060
pub use platform::BackendKind;
6161
pub use signing::AppSigningBackend;
6262

@@ -88,9 +88,34 @@ pub struct StorageConfig {
8888
pub force_keyring: bool,
8989
}
9090

91+
/// Environment variable that, when set to a non-empty value, forces
92+
/// [`create_encryption_storage`] to return a [`MockEncryptionStorage`]
93+
/// instead of the real platform backend.
94+
///
95+
/// This is the sanctioned escape hatch for CI environments that
96+
/// cannot satisfy a real hardware-backed backend — typically GitHub
97+
/// Actions macOS runners, which would otherwise block indefinitely
98+
/// on a login-keychain ACL confirmation prompt. It is **not** a
99+
/// production-safe mode: the mock uses a random in-memory AES key
100+
/// and provides no hardware backing.
101+
pub const MOCK_STORAGE_ENV: &str = "ENCLAVEAPP_MOCK_STORAGE";
102+
91103
/// Create encryption storage with automatic platform detection.
92-
/// Returns a trait object for use with mock backends in tests.
104+
///
105+
/// Honours [`MOCK_STORAGE_ENV`]: when that env var is set to a
106+
/// non-empty value the returned box wraps a fresh
107+
/// [`MockEncryptionStorage`]. Callers get a uniform
108+
/// [`EncryptionStorage`] trait object either way.
93109
pub fn create_encryption_storage(config: StorageConfig) -> Result<Box<dyn EncryptionStorage>> {
110+
if let Ok(val) = std::env::var(MOCK_STORAGE_ENV) {
111+
if !val.is_empty() {
112+
tracing::warn!(
113+
app = %config.app_name,
114+
"{MOCK_STORAGE_ENV} is set — returning MockEncryptionStorage (no hardware backing)"
115+
);
116+
return Ok(Box::new(MockEncryptionStorage::new()));
117+
}
118+
}
94119
let storage = AppEncryptionStorage::init(config)?;
95120
Ok(Box::new(storage))
96121
}

crates/enclaveapp-app-storage/src/mock.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@
66
//! Uses AES-256-GCM with a random in-memory key. Provides no hardware
77
//! backing; suitable only for tests and development.
88
9+
// aes-gcm 0.10 still uses generic-array 0.14 internally and emits a
10+
// deprecation notice on `Nonce::from_slice` — the 1.x migration is
11+
// upstream work, silence here so `-D warnings` doesn't trip.
12+
#![allow(deprecated)]
13+
914
use aes_gcm::aead::Aead;
1015
use aes_gcm::{Aes256Gcm, KeyInit, Nonce};
1116
use rand::RngCore;

0 commit comments

Comments
 (0)