Skip to content
Merged
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
13 changes: 6 additions & 7 deletions src/core/mxc_config_contract/src/dev/experimental.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,13 @@ pub struct OneShotWindowsSandbox {
pub daemon_pipe_name: OptionalField<String>,
}

#[rustfmt::skip]
string_enum! {
/// Transport protocol for a WSLC port mapping.
#[derive(Debug)]
pub enum TransportProtocol {
/// TCP transport.
Tcp => ["tcp"],
}
/// Transport protocol for a WSLC port mapping.
#[derive(Debug)]
pub enum TransportProtocol {
/// TCP transport.
Tcp => ["tcp"],
}
}

/// A host-to-container WSLC port mapping.
Expand Down
56 changes: 49 additions & 7 deletions src/core/mxc_config_contract/src/dev/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,17 +90,59 @@ macro_rules! string_enum {
deserializer.deserialize_str(StringEnumVisitor)
}
}

// Generate a test for each string enum variant and its aliases.
// The test ensures that the enum deserializes from the canonical and
// alias string values (if any), and that it rejects externally tagged
// and non-string values. Emitted here as part of the macro to avoid
// repeating the same test logic for each enum in a separate location
// where the enum's private WIRE_VALUES constant is not accessible.
#[cfg(test)]
#[allow(non_snake_case)]
#[test]
fn $name() {
$(
for wire_value in [
$canonical,
$($alias,)*
] {
let json = serde_json::to_string(wire_value).unwrap();
let parsed: $name = serde_json::from_str(&json).unwrap();

assert!(
matches!(parsed, $name::$variant),
"{wire_value:?} did not map to {}::{}",
stringify!($name),
stringify!($variant),
);

let externally_tagged = format!("{{{json}:null}}");
assert!(
serde_json::from_str::<$name>(&externally_tagged).is_err(),
"{} accepted externally tagged value {externally_tagged}",
stringify!($name),
);
}
)+

for json in ["null", "true", "0", "[]", "{}"] {
assert!(
serde_json::from_str::<$name>(json).is_err(),
"{} accepted non-string value {json}",
stringify!($name),
);
}
}
};
}

#[rustfmt::skip]
string_enum! {
/// The exact version marker accepted by this contract.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Version {
/// The development `0.8.0-alpha` contract.
V0_8_0Alpha => ["0.8.0-alpha"],
}
/// The exact version marker accepted by this contract.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Version {
/// The development `0.8.0-alpha` contract.
V0_8_0Alpha => ["0.8.0-alpha"],
}
}

mod experimental;
Expand Down
38 changes: 18 additions & 20 deletions src/core/mxc_config_contract/src/dev/network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,28 @@ use std::num::NonZeroU16;

use super::primitives::{OptionalField, True};

#[rustfmt::skip]
string_enum! {
/// The default outbound network policy.
#[derive(Debug)]
pub enum DefaultNetworkPolicy {
/// Allow outbound network access by default.
Allow => ["allow"],
/// Block outbound network access by default.
Block => ["block"],
}
/// The default outbound network policy.
#[derive(Debug)]
pub enum DefaultNetworkPolicy {
/// Allow outbound network access by default.
Allow => ["allow"],
/// Block outbound network access by default.
Block => ["block"],
}
}

#[rustfmt::skip]
string_enum! {
/// The mechanism used to enforce network policy.
#[derive(Debug)]
pub enum NetworkEnforcementMode {
/// Enforce policy through containment capabilities.
Capabilities => ["capabilities"],
/// Enforce policy through host firewall rules.
Firewall => ["firewall"],
/// Enforce policy through both capabilities and firewall rules.
Both => ["both"],
}
/// The mechanism used to enforce network policy.
#[derive(Debug)]
pub enum NetworkEnforcementMode {
/// Enforce policy through containment capabilities.
Capabilities => ["capabilities"],
/// Enforce policy through host firewall rules.
Firewall => ["firewall"],
/// Enforce policy through both capabilities and firewall rules.
Both => ["both"],
}
}

/// One of the proxy configurations accepted by the `0.8.0-alpha` contract.
Expand Down
57 changes: 28 additions & 29 deletions src/core/mxc_config_contract/src/dev/one_shot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,37 +9,36 @@ use super::stable::{
};
use crate::dev::Version;

#[rustfmt::skip]
string_enum! {
/// Containment selections available in `0.8.0-alpha`.
#[derive(Debug)]
pub enum Containment {
// Stable-candidate values.
/// Select the host's native process-containment backend.
Process => ["process"],
/// Select the Windows ProcessContainer backend.
ProcessContainer => ["processcontainer", "appcontainer"],
/// Select the Linux LXC backend.
Lxc => ["lxc"],
/// Select the Linux Bubblewrap backend.
Bubblewrap => ["bubblewrap"],
/// Select the macOS Seatbelt backend.
Seatbelt => ["seatbelt", "macos_sandbox"],
/// Containment selections available in `0.8.0-alpha`.
#[derive(Debug)]
pub enum Containment {
// Stable-candidate values.
/// Select the host's native process-containment backend.
Process => ["process"],
/// Select the Windows ProcessContainer backend.
ProcessContainer => ["processcontainer", "appcontainer"],
/// Select the Linux LXC backend.
Lxc => ["lxc"],
/// Select the Linux Bubblewrap backend.
Bubblewrap => ["bubblewrap"],
/// Select the macOS Seatbelt backend.
Seatbelt => ["seatbelt", "macos_sandbox"],

// Development-only values.
/// Select the host's VM-class containment backend.
Vm => ["vm"],
/// Select the Windows Sandbox backend.
WindowsSandbox => ["windows_sandbox"],
/// Select the NanVix micro-VM backend.
Microvm => ["microvm"],
/// Select the Hyperlight micro-VM backend.
Hyperlight => ["hyperlight"],
/// Select the WSL container backend.
Wslc => ["wslc"],
/// Select the Windows IsolationSession backend.
IsolationSession => ["isolation_session"],
}
// Development-only values.
/// Select the host's VM-class containment backend.
Vm => ["vm"],
/// Select the Windows Sandbox backend.
WindowsSandbox => ["windows_sandbox"],
/// Select the NanVix micro-VM backend.
Microvm => ["microvm"],
/// Select the Hyperlight micro-VM backend.
Hyperlight => ["hyperlight"],
/// Select the WSL container backend.
Wslc => ["wslc"],
/// Select the Windows IsolationSession backend.
IsolationSession => ["isolation_session"],
}
}

/// A complete one-shot `0.8.0-alpha` configuration request.
Expand Down
84 changes: 40 additions & 44 deletions src/core/mxc_config_contract/src/dev/stable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,20 +56,19 @@ pub struct Fallback {
pub allow_dacl_mutation: OptionalField<bool>,
}

#[rustfmt::skip]
string_enum! {
/// Clipboard access granted to the contained process.
#[derive(Debug)]
pub enum UiClipboard {
/// Deny clipboard reads and writes.
None => ["none"],
/// Allow clipboard reads.
Read => ["read"],
/// Allow clipboard writes.
Write => ["write"],
/// Allow clipboard reads and writes.
All => ["all"],
}
/// Clipboard access granted to the contained process.
#[derive(Debug)]
pub enum UiClipboard {
/// Deny clipboard reads and writes.
None => ["none"],
/// Allow clipboard reads.
Read => ["read"],
/// Allow clipboard writes.
Write => ["write"],
/// Allow clipboard reads and writes.
All => ["all"],
}
}

/// Cross-platform user-interface policy.
Expand All @@ -87,20 +86,19 @@ pub struct Ui {
pub injection: OptionalField<bool>,
}

#[rustfmt::skip]
string_enum! {
/// Isolation level for ProcessContainer desktop resources.
#[derive(Debug)]
pub enum ProcessContainerUiIsolation {
/// Isolate the complete container user-interface environment.
Container => ["container"],
/// Isolate desktop resources.
Desktop => ["desktop"],
/// Isolate user-interface handles.
Handles => ["handles"],
/// Isolate user-interface atoms.
Atoms => ["atoms"],
}
/// Isolation level for ProcessContainer desktop resources.
#[derive(Debug)]
pub enum ProcessContainerUiIsolation {
/// Isolate the complete container user-interface environment.
Container => ["container"],
/// Isolate desktop resources.
Desktop => ["desktop"],
/// Isolate user-interface handles.
Handles => ["handles"],
/// Isolate user-interface atoms.
Atoms => ["atoms"],
}
}

/// ProcessContainer-specific user-interface policy.
Expand All @@ -121,16 +119,15 @@ pub struct ProcessContainerUi {
pub ime: OptionalField<bool>,
}

#[rustfmt::skip]
string_enum! {
/// Mode for capture denials
#[derive(Debug)]
pub enum CaptureDenialsMode {
/// Access stays **denied** and the denial is recorded. Deny-by-default containment is preserved; this is the safe default.
Block => ["block"],
/// Access is **allowed** and recorded (audit mode). This relaxes deny-by-default for the run, so it is a security-sensitive choice and the runner emits a security warning.
Allow => ["allow"],
}
/// Mode for capture denials
#[derive(Debug)]
pub enum CaptureDenialsMode {
/// Access stays **denied** and the denial is recorded. Deny-by-default containment is preserved; this is the safe default.
Block => ["block"],
/// Access is **allowed** and recorded (audit mode). This relaxes deny-by-default for the run, so it is a security-sensitive choice and the runner emits a security warning.
Allow => ["allow"],
}
}

/// Windows denial-capture settings.
Expand Down Expand Up @@ -181,16 +178,15 @@ pub struct Lxc {
pub release: String,
}

#[rustfmt::skip]
string_enum! {
/// Launch method for macOS Seatbelt config.
#[derive(Debug)]
pub enum LaunchMethod {
/// Launch the contained process directly through `exec`.
Exec => ["exec"],
/// Launch the contained application through macOS LaunchServices.
Open => ["open"],
}
/// Launch method for macOS Seatbelt config.
#[derive(Debug)]
pub enum LaunchMethod {
/// Launch the contained process directly through `exec`.
Exec => ["exec"],
/// Launch the contained application through macOS LaunchServices.
Open => ["open"],
}
}

/// macOS Seatbelt backend settings.
Expand Down
47 changes: 44 additions & 3 deletions src/core/mxc_config_contract/src/published/v0_6_0_alpha/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@
// Serde's default fieldless-enum deserializer also accepts externally
// tagged object forms such as {"process": null}. Published contracts accept
// only string values. This macro generates a string-only deserializer while
// supporting explicit compatibility aliases. Note that this macro should be
// preceded by `#[rustfmt::skip]` because it uses a syntax pattern that is not
// supported by rustfmt.
// supporting explicit compatibility aliases.
macro_rules! string_enum {
(
$(#[$enum_meta:meta])*
Expand Down Expand Up @@ -92,6 +90,49 @@ macro_rules! string_enum {
deserializer.deserialize_str(StringEnumVisitor)
}
}

// Generate a test for each string enum variant and its aliases.
// The test ensures that the enum deserializes from the canonical and
// alias string values (if any), and that it rejects externally tagged
// and non-string values. Emitted here as part of the macro to avoid
// repeating the same test logic for each enum in a separate location
// where the enum's private WIRE_VALUES constant is not accessible.
#[cfg(test)]
#[allow(non_snake_case)]
#[test]
fn $name() {
$(
for wire_value in [
$canonical,
$($alias,)*
] {
let json = serde_json::to_string(wire_value).unwrap();
let parsed: $name = serde_json::from_str(&json).unwrap();

assert!(
matches!(parsed, $name::$variant),
"{wire_value:?} did not map to {}::{}",
stringify!($name),
stringify!($variant),
);

let externally_tagged = format!("{{{json}:null}}");
assert!(
serde_json::from_str::<$name>(&externally_tagged).is_err(),
"{} accepted externally tagged value {externally_tagged}",
stringify!($name),
);
}
)+

for json in ["null", "true", "0", "[]", "{}"] {
assert!(
serde_json::from_str::<$name>(json).is_err(),
"{} accepted non-string value {json}",
stringify!($name),
);
}
}
};
}

Expand Down
Loading
Loading