feat: gate network proxy behind experimental feature

This commit is contained in:
viyatb-oai
2026-03-06 09:44:18 -08:00
parent f891f516a5
commit aee0f23c6b
13 changed files with 389 additions and 108 deletions
+17 -7
View File
@@ -83,7 +83,7 @@ pub struct ConfigRequirements {
pub mcp_servers: Option<Sourced<BTreeMap<String, McpServerRequirement>>>,
pub exec_policy: Option<Sourced<RequirementsExecPolicy>>,
pub enforce_residency: ConstrainedWithSource<Option<ResidencyRequirement>>,
/// Managed network constraints derived from requirements.
/// Network constraints derived from requirements.
pub network: Option<Sourced<NetworkConstraints>>,
}
@@ -130,8 +130,8 @@ pub struct McpServerRequirement {
}
#[derive(Deserialize, Debug, Clone, Default, PartialEq, Eq)]
#[serde(deny_unknown_fields)]
pub struct NetworkRequirementsToml {
pub enabled: Option<bool>,
pub http_port: Option<u16>,
pub socks_port: Option<u16>,
pub allow_upstream_proxy: Option<bool>,
@@ -146,7 +146,6 @@ pub struct NetworkRequirementsToml {
/// Normalized network constraints derived from requirements TOML.
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct NetworkConstraints {
pub enabled: Option<bool>,
pub http_port: Option<u16>,
pub socks_port: Option<u16>,
pub allow_upstream_proxy: Option<bool>,
@@ -161,7 +160,6 @@ pub struct NetworkConstraints {
impl From<NetworkRequirementsToml> for NetworkConstraints {
fn from(value: NetworkRequirementsToml) -> Self {
let NetworkRequirementsToml {
enabled,
http_port,
socks_port,
allow_upstream_proxy,
@@ -173,7 +171,6 @@ impl From<NetworkRequirementsToml> for NetworkConstraints {
allow_local_binding,
} = value;
Self {
enabled,
http_port,
socks_port,
allow_upstream_proxy,
@@ -1114,7 +1111,6 @@ mod tests {
fn network_requirements_are_preserved_as_constraints_with_source() -> Result<()> {
let toml_str = r#"
[experimental_network]
enabled = true
allow_upstream_proxy = false
dangerously_allow_all_unix_sockets = true
allowed_domains = ["api.example.com", "*.openai.com"]
@@ -1133,7 +1129,6 @@ mod tests {
.expect("network requirements should be preserved as constraints");
assert_eq!(sourced_network.source, source);
assert_eq!(sourced_network.value.enabled, Some(true));
assert_eq!(sourced_network.value.allow_upstream_proxy, Some(false));
assert_eq!(
sourced_network.value.dangerously_allow_all_unix_sockets,
@@ -1159,6 +1154,21 @@ mod tests {
Ok(())
}
#[test]
fn network_requirements_reject_enabled_flag() {
let toml_str = r#"
[experimental_network]
enabled = true
"#;
let err =
from_str::<ConfigRequirementsToml>(toml_str).expect_err("enabled flag should fail");
assert!(
err.to_string().contains("unknown field `enabled`"),
"unexpected error: {err}"
);
}
#[test]
fn deserialize_mcp_server_requirements() -> Result<()> {
let toml_str = r#"
+59 -56
View File
@@ -347,6 +347,9 @@
"enable_experimental_windows_sandbox": {
"type": "boolean"
},
"enable_network_proxy": {
"type": "boolean"
},
"enable_request_compression": {
"type": "boolean"
},
@@ -794,60 +797,6 @@
],
"type": "string"
},
"NetworkToml": {
"additionalProperties": false,
"properties": {
"allow_local_binding": {
"type": "boolean"
},
"allow_unix_sockets": {
"items": {
"type": "string"
},
"type": "array"
},
"allow_upstream_proxy": {
"type": "boolean"
},
"allowed_domains": {
"items": {
"type": "string"
},
"type": "array"
},
"dangerously_allow_all_unix_sockets": {
"type": "boolean"
},
"dangerously_allow_non_loopback_proxy": {
"type": "boolean"
},
"denied_domains": {
"items": {
"type": "string"
},
"type": "array"
},
"enable_socks5": {
"type": "boolean"
},
"enable_socks5_udp": {
"type": "boolean"
},
"enabled": {
"type": "boolean"
},
"mode": {
"$ref": "#/definitions/NetworkModeSchema"
},
"proxy_url": {
"type": "string"
},
"socks_url": {
"type": "string"
}
},
"type": "object"
},
"Notice": {
"description": "Settings for notices we display to users via the tui and app-server clients (primarily the Codex IDE extension). NOTE: these are different from notifications - notices are warnings, NUX screens, acknowledgements, etc.",
"properties": {
@@ -1089,16 +1038,67 @@
},
"type": "object"
},
"PermissionsNetworkToml": {
"additionalProperties": false,
"properties": {
"allow_local_binding": {
"type": "boolean"
},
"allow_unix_sockets": {
"items": {
"type": "string"
},
"type": "array"
},
"allow_upstream_proxy": {
"type": "boolean"
},
"allowed_domains": {
"items": {
"type": "string"
},
"type": "array"
},
"dangerously_allow_all_unix_sockets": {
"type": "boolean"
},
"dangerously_allow_non_loopback_proxy": {
"type": "boolean"
},
"denied_domains": {
"items": {
"type": "string"
},
"type": "array"
},
"enable_socks5": {
"type": "boolean"
},
"enable_socks5_udp": {
"type": "boolean"
},
"mode": {
"$ref": "#/definitions/NetworkModeSchema"
},
"proxy_url": {
"type": "string"
},
"socks_url": {
"type": "string"
}
},
"type": "object"
},
"PermissionsToml": {
"additionalProperties": false,
"properties": {
"network": {
"allOf": [
{
"$ref": "#/definitions/NetworkToml"
"$ref": "#/definitions/PermissionsNetworkToml"
}
],
"description": "Network proxy settings from `[permissions.network]`. User config can enable the proxy; managed requirements may still constrain values."
"description": "Network proxy settings from `[permissions.network]`. Applies when the `enable_network_proxy` feature or managed requirements start the proxy."
}
},
"type": "object"
@@ -1735,6 +1735,9 @@
"enable_experimental_windows_sandbox": {
"type": "boolean"
},
"enable_network_proxy": {
"type": "boolean"
},
"enable_request_compression": {
"type": "boolean"
},
+1 -1
View File
@@ -1012,7 +1012,7 @@ impl Session {
audit_metadata,
)
.await
.map_err(|err| anyhow::anyhow!("failed to start managed network proxy: {err}"))?;
.map_err(|err| anyhow::anyhow!("failed to start network proxy: {err}"))?;
let session_network_proxy = {
let proxy = network_proxy.proxy();
SessionNetworkProxyRuntime {
+90 -13
View File
@@ -110,6 +110,7 @@ pub use managed_features::ManagedFeatures;
pub use network_proxy_spec::NetworkProxySpec;
pub use network_proxy_spec::StartedNetworkProxy;
pub use permissions::NetworkToml;
pub use permissions::PermissionsNetworkToml;
pub use permissions::PermissionsToml;
pub use service::ConfigService;
pub use service::ConfigServiceError;
@@ -1750,7 +1751,7 @@ impl Config {
.clone(),
None => ConfigProfile::default(),
};
let configured_network_proxy_config =
let mut configured_network_proxy_config =
network_proxy_config_from_permissions(cfg.permissions.as_ref());
let feature_overrides = FeatureOverrides {
@@ -1760,6 +1761,10 @@ impl Config {
let configured_features = Features::from_config(&cfg, &config_profile, feature_overrides);
let features = ManagedFeatures::from_configured(configured_features, feature_requirements)?;
let enable_network_proxy = features.enabled(Feature::EnableNetworkProxy);
if enable_network_proxy {
configured_network_proxy_config.network.enabled = true;
}
let windows_sandbox_mode = resolve_windows_sandbox_mode(&cfg, &config_profile);
let resolved_cwd = normalize_for_native_workdir({
use std::env;
@@ -2108,16 +2113,16 @@ impl Config {
if let Some(source) = network_requirements_source.as_ref() {
std::io::Error::new(
err.kind(),
format!("failed to build managed network proxy from {source}: {err}"),
format!("failed to build network proxy from {source}: {err}"),
)
} else {
err
}
})?;
let network = if has_network_requirements {
let network = if has_network_requirements || enable_network_proxy {
Some(network)
} else {
network.enabled().then_some(network)
None
};
let config = Self {
@@ -2695,7 +2700,6 @@ consolidation_model = "gpt-5"
fn config_toml_deserializes_permissions_network() {
let toml = r#"
[permissions.network]
enabled = true
proxy_url = "http://127.0.0.1:43128"
enable_socks5 = false
allow_upstream_proxy = false
@@ -2708,8 +2712,7 @@ allowed_domains = ["openai.com"]
cfg.permissions
.and_then(|permissions| permissions.network)
.expect("permissions.network should deserialize"),
NetworkToml {
enabled: Some(true),
PermissionsNetworkToml {
proxy_url: Some("http://127.0.0.1:43128".to_string()),
enable_socks5: Some(false),
socks_url: None,
@@ -2727,12 +2730,56 @@ allowed_domains = ["openai.com"]
}
#[test]
fn permissions_network_enabled_populates_runtime_network_proxy_spec() -> std::io::Result<()> {
fn config_toml_rejects_permissions_network_enabled_flag() {
let toml = r#"
[permissions.network]
enabled = true
"#;
let err = toml::from_str::<ConfigToml>(toml)
.expect_err("permissions.network.enabled should be rejected");
assert!(
err.to_string().contains("unknown field `enabled`"),
"unexpected error: {err}"
);
}
#[test]
fn enable_network_proxy_feature_populates_runtime_network_proxy_spec_with_defaults()
-> std::io::Result<()> {
let codex_home = TempDir::new()?;
let cfg = ConfigToml {
features: Some(FeaturesToml {
entries: BTreeMap::from([("enable_network_proxy".to_string(), true)]),
}),
..Default::default()
};
let config = Config::load_from_base_config_with_overrides(
cfg,
ConfigOverrides::default(),
codex_home.path().to_path_buf(),
)?;
let network = config
.permissions
.network
.as_ref()
.expect("enable_network_proxy should produce a NetworkProxySpec");
assert_eq!(network.proxy_host_and_port(), "127.0.0.1:3128");
assert!(network.socks_enabled());
Ok(())
}
#[test]
fn permissions_network_populates_runtime_network_proxy_spec_when_feature_enabled()
-> std::io::Result<()> {
let codex_home = TempDir::new()?;
let cfg = ConfigToml {
features: Some(FeaturesToml {
entries: BTreeMap::from([("enable_network_proxy".to_string(), true)]),
}),
permissions: Some(PermissionsToml {
network: Some(NetworkToml {
enabled: Some(true),
network: Some(PermissionsNetworkToml {
proxy_url: Some("http://127.0.0.1:43128".to_string()),
enable_socks5: Some(false),
..Default::default()
@@ -2750,7 +2797,7 @@ allowed_domains = ["openai.com"]
.permissions
.network
.as_ref()
.expect("enabled permissions.network should produce a NetworkProxySpec");
.expect("enable_network_proxy should produce a NetworkProxySpec");
assert_eq!(network.proxy_host_and_port(), "127.0.0.1:43128");
assert!(!network.socks_enabled());
@@ -2758,11 +2805,11 @@ allowed_domains = ["openai.com"]
}
#[test]
fn permissions_network_disabled_by_default_does_not_start_proxy() -> std::io::Result<()> {
fn permissions_network_without_feature_flag_does_not_start_proxy() -> std::io::Result<()> {
let codex_home = TempDir::new()?;
let cfg = ConfigToml {
permissions: Some(PermissionsToml {
network: Some(NetworkToml {
network: Some(PermissionsNetworkToml {
allowed_domains: Some(vec!["openai.com".to_string()]),
..Default::default()
}),
@@ -6299,6 +6346,36 @@ mcp_oauth_callback_url = "https://example.com/callback"
Ok(())
}
#[tokio::test]
async fn network_requirements_start_proxy_without_enabled_flag() -> std::io::Result<()> {
let codex_home = TempDir::new()?;
let requirements = crate::config_loader::ConfigRequirementsToml {
network: Some(crate::config_loader::NetworkRequirementsToml {
allow_local_binding: Some(true),
..Default::default()
}),
..Default::default()
};
let config = ConfigBuilder::default()
.codex_home(codex_home.path().to_path_buf())
.cloud_requirements(CloudRequirementsLoader::new(async move {
Ok(Some(requirements))
}))
.build()
.await?;
assert!(config.managed_network_requirements_enabled());
let network = config
.permissions
.network
.as_ref()
.expect("network requirements should produce a managed network proxy");
assert_eq!(network.proxy_host_and_port(), "127.0.0.1:3128");
Ok(())
}
#[tokio::test]
async fn requirements_disallowing_default_approval_falls_back_to_required_default()
-> std::io::Result<()> {
@@ -68,10 +68,6 @@ impl ConfigReloader for StaticNetworkProxyReloader {
}
impl NetworkProxySpec {
pub(crate) fn enabled(&self) -> bool {
self.config.network.enabled
}
pub fn proxy_host_and_port(&self) -> String {
host_and_port_from_network_addr(&self.config.network.proxy_url, 3128)
}
@@ -161,10 +157,7 @@ impl NetworkProxySpec {
) -> (NetworkProxyConfig, NetworkProxyConstraints) {
let mut constraints = NetworkProxyConstraints::default();
if let Some(enabled) = requirements.enabled {
config.network.enabled = enabled;
constraints.enabled = Some(enabled);
}
config.network.enabled = true;
if let Some(http_port) = requirements.http_port {
config.network.proxy_url = format!("http://127.0.0.1:{http_port}");
}
+67 -3
View File
@@ -8,8 +8,27 @@ use serde::Serialize;
#[schemars(deny_unknown_fields)]
pub struct PermissionsToml {
/// Network proxy settings from `[permissions.network]`.
/// User config can enable the proxy; managed requirements may still constrain values.
pub network: Option<NetworkToml>,
/// Applies when the `enable_network_proxy` feature or requirements start the proxy.
pub network: Option<PermissionsNetworkToml>,
}
#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, Eq, JsonSchema)]
#[serde(deny_unknown_fields)]
#[schemars(deny_unknown_fields)]
pub struct PermissionsNetworkToml {
pub proxy_url: Option<String>,
pub enable_socks5: Option<bool>,
pub socks_url: Option<String>,
pub enable_socks5_udp: Option<bool>,
pub allow_upstream_proxy: Option<bool>,
pub dangerously_allow_non_loopback_proxy: Option<bool>,
pub dangerously_allow_all_unix_sockets: Option<bool>,
#[schemars(with = "Option<NetworkModeSchema>")]
pub mode: Option<NetworkMode>,
pub allowed_domains: Option<Vec<String>>,
pub denied_domains: Option<Vec<String>>,
pub allow_unix_sockets: Option<Vec<String>>,
pub allow_local_binding: Option<bool>,
}
#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, Eq, JsonSchema)]
@@ -83,6 +102,51 @@ impl NetworkToml {
config.network.allow_local_binding = allow_local_binding;
}
}
}
impl PermissionsNetworkToml {
pub(crate) fn apply_to_network_proxy_config(&self, config: &mut NetworkProxyConfig) {
config.network.enabled = true;
if let Some(proxy_url) = self.proxy_url.as_ref() {
config.network.proxy_url = proxy_url.clone();
}
if let Some(enable_socks5) = self.enable_socks5 {
config.network.enable_socks5 = enable_socks5;
}
if let Some(socks_url) = self.socks_url.as_ref() {
config.network.socks_url = socks_url.clone();
}
if let Some(enable_socks5_udp) = self.enable_socks5_udp {
config.network.enable_socks5_udp = enable_socks5_udp;
}
if let Some(allow_upstream_proxy) = self.allow_upstream_proxy {
config.network.allow_upstream_proxy = allow_upstream_proxy;
}
if let Some(dangerously_allow_non_loopback_proxy) =
self.dangerously_allow_non_loopback_proxy
{
config.network.dangerously_allow_non_loopback_proxy =
dangerously_allow_non_loopback_proxy;
}
if let Some(dangerously_allow_all_unix_sockets) = self.dangerously_allow_all_unix_sockets {
config.network.dangerously_allow_all_unix_sockets = dangerously_allow_all_unix_sockets;
}
if let Some(mode) = self.mode {
config.network.mode = mode;
}
if let Some(allowed_domains) = self.allowed_domains.as_ref() {
config.network.allowed_domains = allowed_domains.clone();
}
if let Some(denied_domains) = self.denied_domains.as_ref() {
config.network.denied_domains = denied_domains.clone();
}
if let Some(allow_unix_sockets) = self.allow_unix_sockets.as_ref() {
config.network.allow_unix_sockets = allow_unix_sockets.clone();
}
if let Some(allow_local_binding) = self.allow_local_binding {
config.network.allow_local_binding = allow_local_binding;
}
}
pub(crate) fn to_network_proxy_config(&self) -> NetworkProxyConfig {
let mut config = NetworkProxyConfig::default();
@@ -98,6 +162,6 @@ pub(crate) fn network_proxy_config_from_permissions(
.and_then(|permissions| permissions.network.as_ref())
.map_or_else(
NetworkProxyConfig::default,
NetworkToml::to_network_proxy_config,
PermissionsNetworkToml::to_network_proxy_config,
)
}
+6 -5
View File
@@ -150,12 +150,13 @@ fn parse_managed_config_base64(encoded: &str) -> io::Result<ManagedAdminConfigLa
}
fn parse_managed_requirements_base64(encoded: &str) -> io::Result<ConfigRequirementsToml> {
toml::from_str::<ConfigRequirementsToml>(&decode_managed_preferences_base64(encoded)?).map_err(
|err| {
tracing::error!("Failed to parse managed requirements TOML: {err}");
io::Error::new(io::ErrorKind::InvalidData, err)
},
super::parse_requirements_toml_with_legacy_network_enabled_compat(
&decode_managed_preferences_base64(encoded)?,
)
.map_err(|err| {
tracing::error!("Failed to parse managed requirements TOML: {err}");
io::Error::new(io::ErrorKind::InvalidData, err)
})
}
fn decode_managed_preferences_base64(encoded: &str) -> io::Result<String> {
+27 -10
View File
@@ -351,16 +351,18 @@ async fn load_requirements_toml(
AbsolutePathBuf::from_absolute_path(requirements_toml_file.as_ref())?;
match tokio::fs::read_to_string(&requirements_toml_file).await {
Ok(contents) => {
let requirements_config: ConfigRequirementsToml =
toml::from_str(&contents).map_err(|e| {
io::Error::new(
io::ErrorKind::InvalidData,
format!(
"Error parsing requirements file {}: {e}",
requirements_toml_file.as_ref().display(),
),
)
})?;
let requirements_config = parse_requirements_toml_with_legacy_network_enabled_compat(
&contents,
)
.map_err(|e| {
io::Error::new(
io::ErrorKind::InvalidData,
format!(
"Error parsing requirements file {}: {e}",
requirements_toml_file.as_ref().display(),
),
)
})?;
config_requirements_toml.merge_unset_fields(
RequirementSource::SystemRequirementsToml {
file: requirements_toml_file.clone(),
@@ -384,6 +386,21 @@ async fn load_requirements_toml(
Ok(())
}
fn parse_requirements_toml_with_legacy_network_enabled_compat(
contents: &str,
) -> Result<ConfigRequirementsToml, toml::de::Error> {
let mut raw_requirements: TomlValue = toml::from_str(contents)?;
if let Some(network_table) = raw_requirements
.as_table_mut()
.and_then(|table| table.get_mut("experimental_network"))
.and_then(TomlValue::as_table_mut)
&& network_table.remove("enabled").is_some()
{
tracing::warn!("Ignoring legacy experimental_network.enabled in requirements input");
}
raw_requirements.try_into()
}
#[cfg(unix)]
fn system_requirements_toml_file() -> io::Result<AbsolutePathBuf> {
AbsolutePathBuf::from_absolute_path(Path::new("/etc/codex/requirements.toml"))
+65
View File
@@ -440,6 +440,45 @@ allowed_sandbox_modes = ["read-only"]
Ok(())
}
#[cfg(target_os = "macos")]
#[tokio::test]
async fn managed_preferences_requirements_ignore_legacy_network_enabled() -> anyhow::Result<()> {
use base64::Engine;
let tmp = tempdir()?;
let state = load_config_layers_state(
tmp.path(),
Some(AbsolutePathBuf::try_from(tmp.path())?),
&[] as &[(String, TomlValue)],
LoaderOverrides {
managed_config_path: Some(tmp.path().join("managed_config.toml")),
managed_preferences_base64: Some(String::new()),
macos_managed_config_requirements_base64: Some(
base64::prelude::BASE64_STANDARD.encode(
r#"
[experimental_network]
enabled = true
allow_local_binding = true
"#
.as_bytes(),
),
),
},
CloudRequirementsLoader::default(),
)
.await?;
let network = state
.requirements()
.network
.as_ref()
.expect("network requirements");
assert_eq!(network.value.allow_local_binding, Some(true));
Ok(())
}
#[cfg(target_os = "macos")]
#[tokio::test]
async fn managed_preferences_requirements_take_precedence() -> anyhow::Result<()> {
@@ -633,6 +672,32 @@ allowed_approval_policies = ["on-request"]
Ok(())
}
#[tokio::test(flavor = "current_thread")]
async fn load_requirements_toml_ignores_legacy_network_enabled() -> anyhow::Result<()> {
let tmp = tempdir()?;
let requirements_file = tmp.path().join("requirements.toml");
tokio::fs::write(
&requirements_file,
r#"
[experimental_network]
enabled = true
allow_local_binding = true
"#,
)
.await?;
let mut config_requirements_toml = ConfigRequirementsWithSources::default();
load_requirements_toml(&mut config_requirements_toml, &requirements_file).await?;
let network = config_requirements_toml
.network
.as_ref()
.expect("network requirements");
assert_eq!(network.value.allow_local_binding, Some(true));
Ok(())
}
#[tokio::test(flavor = "current_thread")]
async fn cloud_requirements_are_not_overwritten_by_system_requirements() -> anyhow::Result<()> {
let tmp = tempdir()?;
+21
View File
@@ -90,6 +90,8 @@ pub enum Feature {
ApplyPatchFreeform,
/// Allow requesting additional filesystem permissions while staying sandboxed.
RequestPermissions,
/// Start the network proxy even without explicit `[permissions.network]` config.
EnableNetworkProxy,
/// Allow the model to request web searches that fetch live content.
WebSearchRequest,
/// Allow the model to request web searches that fetch cached content.
@@ -572,6 +574,16 @@ pub const FEATURES: &[FeatureSpec] = &[
stage: Stage::UnderDevelopment,
default_enabled: false,
},
FeatureSpec {
id: Feature::EnableNetworkProxy,
key: "enable_network_proxy",
stage: Stage::Experimental {
name: "Network proxy",
menu_description: "Start Codex's network proxy with default settings even without explicit [permissions.network] config. Use [permissions.network] to override the proxy defaults.",
announcement: "NEW: Network proxy can now be enabled from /experimental. Restart Codex after enabling it.",
},
default_enabled: false,
},
FeatureSpec {
id: Feature::UseLinuxSandboxBwrap,
key: "use_linux_sandbox_bwrap",
@@ -890,6 +902,15 @@ mod tests {
assert_eq!(Feature::ImageGeneration.default_enabled(), false);
}
#[test]
fn enable_network_proxy_is_experimental() {
assert!(matches!(
Feature::EnableNetworkProxy.stage(),
Stage::Experimental { .. }
));
assert_eq!(Feature::EnableNetworkProxy.default_enabled(), false);
}
#[test]
fn collab_is_legacy_alias_for_multi_agent() {
assert_eq!(feature_for_key("multi_agent"), Some(Feature::Collab));
+1 -1
View File
@@ -81,7 +81,7 @@ pub(crate) fn denied_network_policy_message(blocked: &BlockedRequest) -> Option<
"not_allowed" => "domain is not on the allowlist for the current sandbox mode",
"not_allowed_local" => "local/private network addresses are blocked by policy",
"method_not_allowed" => "request method is blocked by the current network mode",
"proxy_disabled" => "managed network proxy is disabled",
"proxy_disabled" => "network proxy is disabled",
_ => "request is blocked by network policy",
};
+34 -1
View File
@@ -1,4 +1,5 @@
use crate::config::NetworkToml;
use crate::config::PermissionsNetworkToml;
use crate::config::PermissionsToml;
use crate::config::find_codex_home;
use crate::config_loader::CloudRequirementsLoader;
@@ -125,7 +126,7 @@ fn network_constraints_from_trusted_layers(
.permissions
.and_then(|permissions| permissions.network)
{
apply_network_constraints(network, &mut constraints);
apply_permissions_network_constraints(network, &mut constraints);
}
}
Ok(constraints)
@@ -163,6 +164,38 @@ fn apply_network_constraints(network: NetworkToml, constraints: &mut NetworkProx
}
}
fn apply_permissions_network_constraints(
network: PermissionsNetworkToml,
constraints: &mut NetworkProxyConstraints,
) {
if let Some(mode) = network.mode {
constraints.mode = Some(mode);
}
if let Some(allow_upstream_proxy) = network.allow_upstream_proxy {
constraints.allow_upstream_proxy = Some(allow_upstream_proxy);
}
if let Some(dangerously_allow_non_loopback_proxy) = network.dangerously_allow_non_loopback_proxy
{
constraints.dangerously_allow_non_loopback_proxy =
Some(dangerously_allow_non_loopback_proxy);
}
if let Some(dangerously_allow_all_unix_sockets) = network.dangerously_allow_all_unix_sockets {
constraints.dangerously_allow_all_unix_sockets = Some(dangerously_allow_all_unix_sockets);
}
if let Some(allowed_domains) = network.allowed_domains {
constraints.allowed_domains = Some(allowed_domains);
}
if let Some(denied_domains) = network.denied_domains {
constraints.denied_domains = Some(denied_domains);
}
if let Some(allow_unix_sockets) = network.allow_unix_sockets {
constraints.allow_unix_sockets = Some(allow_unix_sockets);
}
if let Some(allow_local_binding) = network.allow_local_binding {
constraints.allow_local_binding = Some(allow_local_binding);
}
}
#[derive(Debug, Clone, Default, Deserialize)]
struct NetworkTablesToml {
network: Option<NetworkToml>,
-3
View File
@@ -2235,7 +2235,6 @@ async fn denying_network_policy_amendment_persists_policy_and_skips_future_netwo
fs::write(
home.path().join("config.toml"),
r#"[permissions.network]
enabled = true
mode = "limited"
allow_local_binding = true
"#,
@@ -2261,7 +2260,6 @@ allow_local_binding = true
let mut requirements = config.config_layer_stack.requirements().clone();
requirements.network = Some(Sourced::new(
NetworkConstraints {
enabled: Some(true),
allow_local_binding: Some(true),
..Default::default()
},
@@ -2269,7 +2267,6 @@ allow_local_binding = true
));
let mut requirements_toml = config.config_layer_stack.requirements_toml().clone();
requirements_toml.network = Some(NetworkRequirementsToml {
enabled: Some(true),
allow_local_binding: Some(true),
..Default::default()
});