[pkg_resolver] GN target that disables dynamic rewrite rules
Bug: 37520
Change-Id: Ie1768e7c978d749b9289ca3624c983ff2374a95c
diff --git a/garnet/bin/pkg_resolver/BUILD.gn b/garnet/bin/pkg_resolver/BUILD.gn
index 5741ff2..5d98102 100644
--- a/garnet/bin/pkg_resolver/BUILD.gn
+++ b/garnet/bin/pkg_resolver/BUILD.gn
@@ -6,6 +6,7 @@
import("//build/rust/rustc_binary.gni")
import("//build/test/test_package.gni")
import("//build/testing/environments.gni")
+import("//garnet/bin/pkg_resolver/pkg_resolver_config.gni")
rustc_binary("bin") {
name = "pkg_resolver"
@@ -39,9 +40,11 @@
"//third_party/rust_crates:hyper-rustls",
"//third_party/rust_crates:log",
"//third_party/rust_crates:maplit",
+ "//third_party/rust_crates:matches",
"//third_party/rust_crates:parking_lot",
"//third_party/rust_crates:pin-utils",
"//third_party/rust_crates:serde",
+ "//third_party/rust_crates:serde_derive",
"//third_party/rust_crates:serde_json",
"//third_party/rust_crates:tempfile",
"//third_party/rust_crates:url",
@@ -82,3 +85,7 @@
},
]
}
+
+pkg_resolver_config("disable_dynamic_configuration") {
+ disable_dynamic_configuration = true
+}
diff --git a/garnet/bin/pkg_resolver/meta/pkg_resolver_integration_test.cmx b/garnet/bin/pkg_resolver/meta/pkg_resolver_integration_test.cmx
index 69c0e54..05cee1f 100644
--- a/garnet/bin/pkg_resolver/meta/pkg_resolver_integration_test.cmx
+++ b/garnet/bin/pkg_resolver/meta/pkg_resolver_integration_test.cmx
@@ -4,7 +4,6 @@
},
"sandbox": {
"features": [
- "isolated-persistent-storage",
"root-ssl-certificates"
],
"services": [
diff --git a/garnet/bin/pkg_resolver/pkg_resolver_config.gni b/garnet/bin/pkg_resolver/pkg_resolver_config.gni
new file mode 100644
index 0000000..85dc37d
--- /dev/null
+++ b/garnet/bin/pkg_resolver/pkg_resolver_config.gni
@@ -0,0 +1,33 @@
+# Copyright 2019 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config.gni")
+
+# Define pkg_resolver configuration data to be included in the
+# config-data package.
+#
+# disable_dynamic_configuration
+# [bool] Disable editing package URL rewrite rules.
+#
+template("pkg_resolver_config") {
+ cfg = {
+ forward_variables_from(invoker, [ "disable_dynamic_configuration" ])
+ assert(defined(disable_dynamic_configuration),
+ "disable_dynamic_configuration must be defined")
+ }
+
+ config_path = "$target_gen_dir/pkg_resolver_config.json"
+
+ write_file(config_path, cfg, "json")
+
+ config_data(target_name) {
+ for_pkg = "pkg_resolver"
+ outputs = [
+ "config.json",
+ ]
+ sources = [
+ config_path,
+ ]
+ }
+}
diff --git a/garnet/bin/pkg_resolver/src/config.rs b/garnet/bin/pkg_resolver/src/config.rs
new file mode 100644
index 0000000..7e4559d9
--- /dev/null
+++ b/garnet/bin/pkg_resolver/src/config.rs
@@ -0,0 +1,113 @@
+// Copyright 2019 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+use {
+ failure::Fail,
+ fuchsia_syslog::{fx_log_err, fx_log_info},
+ serde_derive::Deserialize,
+ std::{
+ fs::File,
+ io::{BufReader, Read},
+ },
+};
+
+/// Static service configuration options.
+#[derive(Debug, Default, PartialEq, Eq)]
+pub struct Config {
+ disable_dynamic_configuration: bool,
+}
+
+impl Config {
+ pub fn disable_dynamic_configuration(&self) -> bool {
+ self.disable_dynamic_configuration
+ }
+
+ pub fn load_from_config_data_or_default() -> Config {
+ let f = match File::open("/config/data/config.json") {
+ Ok(f) => f,
+ Err(e) => {
+ fx_log_info!("no config found, using defaults: {:?}", e.kind());
+ return Config::default();
+ }
+ };
+
+ Self::load(BufReader::new(f)).unwrap_or_else(|e| {
+ fx_log_err!("unable to load config, using defaults: {:?}", e);
+ Config::default()
+ })
+ }
+
+ fn load(r: impl Read) -> Result<Config, ConfigLoadError> {
+ #[derive(Debug, Deserialize)]
+ #[serde(deny_unknown_fields)]
+ struct ParseConfig {
+ disable_dynamic_configuration: bool,
+ }
+
+ let parse_config = serde_json::from_reader::<_, ParseConfig>(r)?;
+
+ Ok(Config { disable_dynamic_configuration: parse_config.disable_dynamic_configuration })
+ }
+}
+
+#[derive(Debug, Fail)]
+enum ConfigLoadError {
+ #[fail(display = "parse error: {}", _0)]
+ Parse(#[cause] serde_json::Error),
+}
+
+impl From<serde_json::Error> for ConfigLoadError {
+ fn from(e: serde_json::Error) -> Self {
+ Self::Parse(e)
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use {super::*, matches::assert_matches, serde_json::json};
+
+ fn verify_load(input: serde_json::Value, expected: Config) {
+ assert_eq!(
+ Config::load(input.to_string().as_bytes()).expect("json value to be valid"),
+ expected
+ );
+ }
+
+ #[test]
+ fn test_load_valid_configs() {
+ for val in [true, false].iter() {
+ verify_load(
+ json!({
+ "disable_dynamic_configuration": *val,
+ }),
+ Config { disable_dynamic_configuration: *val },
+ );
+ }
+ }
+
+ #[test]
+ fn test_load_errors_on_unknown_field() {
+ assert_matches!(
+ Config::load(
+ json!({
+ "disable_dynamic_configuration": false,
+ "unknown_field": 3
+ })
+ .to_string()
+ .as_bytes()
+ ),
+ Err(ConfigLoadError::Parse(_))
+ );
+ }
+
+ #[test]
+ fn test_no_config_data_is_default() {
+ assert_eq!(Config::load_from_config_data_or_default(), Config::default());
+ }
+
+ #[test]
+ fn test_default_does_not_disable_dynamic_configuraiton() {
+ assert_eq!(Config::default().disable_dynamic_configuration, false);
+ }
+}
diff --git a/garnet/bin/pkg_resolver/src/main.rs b/garnet/bin/pkg_resolver/src/main.rs
index 7587454..68550257 100644
--- a/garnet/bin/pkg_resolver/src/main.rs
+++ b/garnet/bin/pkg_resolver/src/main.rs
@@ -19,6 +19,7 @@
mod amber_connector;
mod cache;
+mod config;
mod experiment;
mod font_package_manager;
mod repository_manager;
@@ -58,6 +59,8 @@
let mut executor = fasync::Executor::new().context("error creating executor")?;
+ let config = config::Config::load_from_config_data_or_default();
+
let pkg_cache =
connect_to_service::<PackageCacheMarker>().context("error connecting to package cache")?;
let pkgfs_install = connect_to_pkgfs("install").context("error connecting to pkgfs/install")?;
@@ -75,8 +78,11 @@
let font_package_manager = Arc::new(load_font_package_manager());
let repo_manager = Arc::new(RwLock::new(load_repo_manager(amber_connector, experiments)));
- let rewrite_manager =
- Arc::new(RwLock::new(load_rewrite_manager(rewrite_inspect_node, &repo_manager.read())));
+ let rewrite_manager = Arc::new(RwLock::new(load_rewrite_manager(
+ rewrite_inspect_node,
+ &repo_manager.read(),
+ config.disable_dynamic_configuration(),
+ )));
let resolver_cb = {
// Capture a clone of repo and rewrite manager's Arc so the new client callback has a copy
@@ -200,8 +206,11 @@
fn load_rewrite_manager(
node: inspect::Node,
repo_manager: &RepositoryManager<AmberConnector>,
+ disable_dynamic_configuration: bool,
) -> RewriteManager {
- let builder = RewriteManagerBuilder::new(DYNAMIC_RULES_PATH)
+ let dynamic_rules_path =
+ if disable_dynamic_configuration { None } else { Some(DYNAMIC_RULES_PATH) };
+ let builder = RewriteManagerBuilder::new(dynamic_rules_path)
.unwrap_or_else(|(builder, err)| {
if err.kind() != io::ErrorKind::NotFound {
fx_log_err!(
diff --git a/garnet/bin/pkg_resolver/src/resolver_service.rs b/garnet/bin/pkg_resolver/src/resolver_service.rs
index 7dd817b..0acb78d 100644
--- a/garnet/bin/pkg_resolver/src/resolver_service.rs
+++ b/garnet/bin/pkg_resolver/src/resolver_service.rs
@@ -452,7 +452,7 @@
let cache = PackageCache::new(cache_proxy, pkgfs_install, pkgfs_needs);
let dynamic_rule_config = make_rule_config(self.dynamic_rewrite_rules);
- let rewrite_manager = RewriteManagerBuilder::new(&dynamic_rule_config)
+ let rewrite_manager = RewriteManagerBuilder::new(Some(&dynamic_rule_config))
.unwrap()
.static_rules(self.static_rewrite_rules)
.build();
diff --git a/garnet/bin/pkg_resolver/src/rewrite_manager.rs b/garnet/bin/pkg_resolver/src/rewrite_manager.rs
index 7db50d8..1a0982f 100644
--- a/garnet/bin/pkg_resolver/src/rewrite_manager.rs
+++ b/garnet/bin/pkg_resolver/src/rewrite_manager.rs
@@ -27,7 +27,7 @@
static_rules: Vec<Rule>,
dynamic_rules: Vec<Rule>,
generation: u32,
- dynamic_rules_path: PathBuf,
+ dynamic_rules_path: Option<PathBuf>,
inspect: RewriteManagerInspectState,
}
@@ -46,6 +46,8 @@
pub enum CommitError {
#[fail(display = "the provided rule set is based on an older generation")]
TooLate,
+ #[fail(display = "editing rewrite rules is permanently disabled")]
+ DynamicConfigurationDisabled,
}
impl RewriteManager {
@@ -67,22 +69,22 @@
url
}
- fn save(&mut self) -> io::Result<()> {
- let config = RuleConfig::Version1(std::mem::replace(&mut self.dynamic_rules, vec![]));
+ fn save(dynamic_rules: &mut Vec<Rule>, dynamic_rules_path: &Path) -> io::Result<()> {
+ let config = RuleConfig::Version1(std::mem::replace(dynamic_rules, vec![]));
let result = (|| {
- let mut temp_path = self.dynamic_rules_path.clone().into_os_string();
+ let mut temp_path = dynamic_rules_path.to_owned().into_os_string();
temp_path.push(".new");
let temp_path = PathBuf::from(temp_path);
{
let f = File::create(&temp_path)?;
serde_json::to_writer(io::BufWriter::new(f), &config)?;
};
- fs::rename(temp_path, &self.dynamic_rules_path)
+ fs::rename(temp_path, dynamic_rules_path)
})();
let RuleConfig::Version1(rules) = config;
- self.dynamic_rules = rules;
+ *dynamic_rules = rules;
result
}
@@ -100,17 +102,21 @@
/// [RewriteRuleStates] have been applied since `transaction` was cloned from this
/// [RewriteManager].
pub fn apply(&mut self, transaction: Transaction) -> Result<(), CommitError> {
- if self.generation != transaction.generation {
- Err(CommitError::TooLate)
- } else {
- self.dynamic_rules = transaction.dynamic_rules.into();
- self.generation += 1;
- // FIXME(kevinwells) synchronous I/O in an async context
- if let Err(err) = self.save() {
- fx_log_err!("error while saving dynamic rewrite rules: {}", err);
+ if let Some(ref dynamic_rules_path) = self.dynamic_rules_path {
+ if self.generation != transaction.generation {
+ Err(CommitError::TooLate)
+ } else {
+ self.dynamic_rules = transaction.dynamic_rules.into();
+ self.generation += 1;
+ // FIXME(kevinwells) synchronous I/O in an async context
+ if let Err(err) = Self::save(&mut self.dynamic_rules, dynamic_rules_path) {
+ fx_log_err!("error while saving dynamic rewrite rules: {}", err);
+ }
+ self.update_inspect_objects();
+ Ok(())
}
- self.update_inspect_objects();
- Ok(())
+ } else {
+ Err(CommitError::DynamicConfigurationDisabled)
}
}
@@ -187,7 +193,7 @@
pub struct RewriteManagerBuilder<N> {
static_rules: Vec<Rule>,
dynamic_rules: Vec<Rule>,
- dynamic_rules_path: PathBuf,
+ dynamic_rules_path: Option<PathBuf>,
inspect_node: N,
}
@@ -196,23 +202,27 @@
/// provided path. If the provided dynamic rule config file does not exist or is corrupt, this
/// method returns an [RewriteManagerBuilder] initialized with no rules and configured with the
/// given dynamic config path.
- pub fn new<T>(dynamic_rules_path: T) -> Result<Self, (Self, io::Error)>
+ pub fn new<T>(dynamic_rules_path: Option<T>) -> Result<Self, (Self, io::Error)>
where
T: Into<PathBuf>,
{
let mut builder = RewriteManagerBuilder {
static_rules: vec![],
dynamic_rules: vec![],
- dynamic_rules_path: dynamic_rules_path.into(),
+ dynamic_rules_path: dynamic_rules_path.map(|p| p.into()),
inspect_node: UnsetInspectNode,
};
- match Self::load_rules(&builder.dynamic_rules_path) {
- Ok(rules) => {
- builder.dynamic_rules = rules;
- Ok(builder)
+ if let Some(ref path) = builder.dynamic_rules_path {
+ match Self::load_rules(path) {
+ Ok(rules) => {
+ builder.dynamic_rules = rules;
+ Ok(builder)
+ }
+ Err(err) => Err((builder, err)),
}
- Err(err) => Err((builder, err)),
+ } else {
+ Ok(builder)
}
}
@@ -292,10 +302,9 @@
dynamic_rules_node: self.inspect_node.create_child("dynamic_rules"),
dynamic_rules_states: vec![],
generation_property: self.inspect_node.create_uint("generation", 0),
- dynamic_rules_path_property: self.inspect_node.create_string(
- "dynamic_rules_path",
- &self.dynamic_rules_path.display().to_string(),
- ),
+ dynamic_rules_path_property: self
+ .inspect_node
+ .create_string("dynamic_rules_path", &format!("{:?}", self.dynamic_rules_path)),
node: self.inspect_node,
};
@@ -318,7 +327,10 @@
#[cfg(test)]
pub(crate) mod tests {
- use {super::*, failure::Error, fuchsia_inspect::assert_inspect_tree, serde_json::json};
+ use {
+ super::*, failure::Error, fuchsia_inspect::assert_inspect_tree, matches::assert_matches,
+ serde_json::json,
+ };
macro_rules! rule {
($host_match:expr => $host_replacement:expr,
@@ -352,7 +364,7 @@
fn test_empty_configs() {
let config = make_rule_config(vec![]);
- let manager = RewriteManagerBuilder::new(&config)
+ let manager = RewriteManagerBuilder::new(Some(&config))
.unwrap()
.static_rules_path(&config)
.unwrap()
@@ -368,7 +380,7 @@
let dynamic_config = make_rule_config(vec![]);
let static_config = make_rule_config(rules.clone());
- let manager = RewriteManagerBuilder::new(&dynamic_config)
+ let manager = RewriteManagerBuilder::new(Some(&dynamic_config))
.unwrap()
.static_rules_path(&static_config)
.unwrap()
@@ -383,7 +395,7 @@
let rules = vec![rule!("fuchsia.com" => "fuchsia.com", "/rolldice" => "/rolldice")];
let dynamic_config = make_rule_config(rules.clone());
- let manager = RewriteManagerBuilder::new(&dynamic_config).unwrap().build();
+ let manager = RewriteManagerBuilder::new(Some(&dynamic_config)).unwrap().build();
assert_eq!(manager.list_static().cloned().collect::<Vec<_>>(), vec![]);
assert_eq!(manager.list().cloned().collect::<Vec<_>>(), rules);
@@ -403,7 +415,7 @@
})
)
});
- let (builder, _) = RewriteManagerBuilder::new(&dynamic_config)
+ let (builder, _) = RewriteManagerBuilder::new(Some(&dynamic_config))
.unwrap()
.static_rules_path(&static_config)
.unwrap_err();
@@ -419,7 +431,7 @@
let rule = rule!("test.com" => "test.com", "/a" => "/b");
{
- let (builder, _) = RewriteManagerBuilder::new(&dynamic_config).unwrap_err();
+ let (builder, _) = RewriteManagerBuilder::new(Some(&dynamic_config)).unwrap_err();
let mut manager = builder.build();
assert_eq!(manager.list().cloned().collect::<Vec<_>>(), vec![]);
@@ -432,7 +444,7 @@
}
// Verify the dynamic config file is no longer corrupt and contains the newly added rule.
- let manager = RewriteManagerBuilder::new(&dynamic_config).unwrap().build();
+ let manager = RewriteManagerBuilder::new(Some(&dynamic_config)).unwrap().build();
assert_eq!(manager.list().cloned().collect::<Vec<_>>(), vec![rule]);
}
@@ -444,7 +456,7 @@
];
let dynamic_config = make_rule_config(rules);
- let manager = RewriteManagerBuilder::new(&dynamic_config).unwrap().build();
+ let manager = RewriteManagerBuilder::new(Some(&dynamic_config)).unwrap().build();
let url: PkgUrl = "fuchsia-pkg://fuchsia.com/c".parse().unwrap();
assert_eq!(manager.rewrite(url.clone()), url);
@@ -458,7 +470,7 @@
];
let dynamic_config = make_rule_config(rules);
- let manager = RewriteManagerBuilder::new(&dynamic_config).unwrap().build();
+ let manager = RewriteManagerBuilder::new(Some(&dynamic_config)).unwrap().build();
let url = "fuchsia-pkg://fuchsia.com/package".parse().unwrap();
assert_eq!(manager.rewrite(url), "fuchsia-pkg://fuchsia.com/remapped".parse().unwrap());
@@ -472,7 +484,7 @@
let static_config = make_rule_config(vec![
rule!("fuchsia.com" => "fuchsia.com", "/package" => "/incorrect"),
]);
- let manager = RewriteManagerBuilder::new(&dynamic_config)
+ let manager = RewriteManagerBuilder::new(Some(&dynamic_config))
.unwrap()
.static_rules_path(&static_config)
.unwrap()
@@ -491,7 +503,7 @@
let static_config = make_rule_config(static_rules);
let dynamic_config = make_rule_config(dynamic_rules);
- let manager = RewriteManagerBuilder::new(&dynamic_config)
+ let manager = RewriteManagerBuilder::new(Some(&dynamic_config))
.unwrap()
.static_rules_path(&static_config)
.unwrap()
@@ -507,7 +519,7 @@
let override_rule = rule!("fuchsia.com" => "fuchsia.com", "/a" => "/c");
let dynamic_config =
make_rule_config(vec![rule!("fuchsia.com" => "fuchsia.com", "/a" => "/b")]);
- let mut manager = RewriteManagerBuilder::new(&dynamic_config).unwrap().build();
+ let mut manager = RewriteManagerBuilder::new(Some(&dynamic_config)).unwrap().build();
let mut transaction = manager.transaction();
transaction.add(override_rule.clone());
@@ -529,7 +541,7 @@
let rules = vec![existing_rule.clone()];
let dynamic_config = make_rule_config(rules.clone());
- let mut manager = RewriteManagerBuilder::new(&dynamic_config).unwrap().build();
+ let mut manager = RewriteManagerBuilder::new(Some(&dynamic_config)).unwrap().build();
assert_eq!(manager.list().cloned().collect::<Vec<_>>(), rules);
// Fork the existing state, add a rule, and verify both instances are distinct
@@ -544,7 +556,7 @@
assert_eq!(manager.list().cloned().collect::<Vec<_>>(), new_rules);
// Ensure new rules are persisted to the dynamic config file
- let manager = RewriteManagerBuilder::new(&dynamic_config).unwrap().build();
+ let manager = RewriteManagerBuilder::new(Some(&dynamic_config)).unwrap().build();
assert_eq!(manager.list().cloned().collect::<Vec<_>>(), new_rules);
}
@@ -556,7 +568,7 @@
];
let dynamic_config = make_rule_config(rules.clone());
- let mut manager = RewriteManagerBuilder::new(&dynamic_config).unwrap().build();
+ let mut manager = RewriteManagerBuilder::new(Some(&dynamic_config)).unwrap().build();
assert_eq!(manager.list().cloned().collect::<Vec<_>>(), rules);
let mut transaction = manager.transaction();
@@ -567,7 +579,7 @@
assert_eq!(manager.apply(transaction).unwrap(), ());
assert_eq!(manager.list().cloned().collect::<Vec<_>>(), vec![]);
- let manager = RewriteManagerBuilder::new(&dynamic_config).unwrap().build();
+ let manager = RewriteManagerBuilder::new(Some(&dynamic_config)).unwrap().build();
assert_eq!(manager.list().cloned().collect::<Vec<_>>(), vec![]);
}
@@ -583,7 +595,7 @@
vec![rule!("example.com" => "example.org", "/this_throwdice" => "/that_throwdice")];
let static_config = make_rule_config(static_rules.clone());
- let _manager = RewriteManagerBuilder::new(&dynamic_config)
+ let _manager = RewriteManagerBuilder::new(Some(&dynamic_config))
.unwrap()
.static_rules_path(&static_config)
.unwrap()
@@ -602,7 +614,7 @@
path_prefix_replacement: "/that_rolldice",
},
},
- dynamic_rules_path: dynamic_config.to_str().unwrap().to_string(),
+ dynamic_rules_path: format!("{:?}", Some(&*dynamic_config)),
static_rules: {
"0": {
host_match: "example.com",
@@ -618,18 +630,39 @@
}
#[test]
- fn test_transaction_updates_inspect() {
+ fn test_inspect_rewrite_manager_no_dynamic_rules_path() {
let inspector = fuchsia_inspect::Inspector::new();
let node = inspector.root().create_child("rewrite_manager");
- let dynamic_config = make_rule_config(vec![]);
- let mut manager =
- RewriteManagerBuilder::new(&dynamic_config).unwrap().inspect_node(node).build();
+
+ let _manager =
+ RewriteManagerBuilder::new(Option::<&Path>::None).unwrap().inspect_node(node).build();
+
assert_inspect_tree!(
inspector,
root: {
rewrite_manager: {
dynamic_rules: {},
- dynamic_rules_path: dynamic_config.to_str().unwrap().to_string(),
+ dynamic_rules_path: format!("{:?}", Option::<&Path>::None),
+ static_rules: {},
+ generation: 0u64,
+ }
+ }
+ );
+ }
+
+ #[test]
+ fn test_transaction_updates_inspect() {
+ let inspector = fuchsia_inspect::Inspector::new();
+ let node = inspector.root().create_child("rewrite_manager");
+ let dynamic_config = make_rule_config(vec![]);
+ let mut manager =
+ RewriteManagerBuilder::new(Some(&dynamic_config)).unwrap().inspect_node(node).build();
+ assert_inspect_tree!(
+ inspector,
+ root: {
+ rewrite_manager: {
+ dynamic_rules: {},
+ dynamic_rules_path: format!("{:?}", Some(&*dynamic_config)),
static_rules: {},
generation: 0u64,
}
@@ -653,11 +686,56 @@
path_prefix_replacement: "/that_rolldice/",
},
},
- dynamic_rules_path: dynamic_config.to_str().unwrap().to_string(),
+ dynamic_rules_path: format!("{:?}", Some(&*dynamic_config)),
static_rules: {},
generation: 1u64,
}
}
);
}
+
+ #[test]
+ fn test_no_dynamic_rules_if_no_dynamic_rules_path() {
+ let manager = RewriteManagerBuilder::new(Option::<&Path>::None).unwrap().build();
+
+ assert_eq!(manager.list().cloned().collect::<Vec<_>>(), vec![]);
+ }
+
+ #[test]
+ fn test_same_dynamic_rules_if_apply_fails() {
+ let dynamic_config = make_rule_config(vec![]);
+ let rule0 = rule!("test0.com" => "test0.com", "/a" => "/b");
+ let rule1 = rule!("test1.com" => "test1.com", "/a" => "/b");
+ let mut manager = RewriteManagerBuilder::new(Some(&dynamic_config)).unwrap().build();
+ assert_eq!(manager.list().collect::<Vec<_>>(), Vec::<&Rule>::new());
+
+ // transaction0 adds a dynamic rule
+ let mut transaction0 = manager.transaction();
+ let mut transaction1 = manager.transaction();
+ transaction0.add(rule0.clone());
+ manager.apply(transaction0).unwrap();
+ assert_eq!(manager.list().cloned().collect::<Vec<_>>(), vec![rule0.clone()]);
+
+ // transaction1 fails to apply b/c it was created before transaction0 was applied
+ // the dynamic rewrite rules should be unchanged
+ transaction1.add(rule1.clone());
+ assert_matches!(manager.apply(transaction1), Err(CommitError::TooLate));
+ assert_eq!(manager.list().cloned().collect::<Vec<_>>(), vec![rule0.clone()]);
+
+ // transaction2 applies the rule from transaction1
+ let mut transaction2 = manager.transaction();
+ transaction2.add(rule1.clone());
+ manager.apply(transaction2).unwrap();
+ assert_eq!(manager.list().cloned().collect::<Vec<_>>(), vec![rule1.clone(), rule0.clone()]);
+ }
+
+ #[test]
+ fn test_apply_fails_with_no_change_if_no_dynamic_rules_path() {
+ let mut manager = RewriteManagerBuilder::new(Option::<&Path>::None).unwrap().build();
+ let mut transaction = manager.transaction();
+ transaction.add(rule!("test0.com" => "test0.com", "/a" => "/b"));
+
+ assert_matches!(manager.apply(transaction), Err(CommitError::DynamicConfigurationDisabled));
+ assert_eq!(manager.list().cloned().collect::<Vec<_>>(), vec![]);
+ }
}
diff --git a/garnet/bin/pkg_resolver/src/rewrite_service.rs b/garnet/bin/pkg_resolver/src/rewrite_service.rs
index 9b99237..f84cb23 100644
--- a/garnet/bin/pkg_resolver/src/rewrite_service.rs
+++ b/garnet/bin/pkg_resolver/src/rewrite_service.rs
@@ -118,6 +118,9 @@
let status = match state.write().apply(transaction) {
Ok(()) => Status::OK,
Err(CommitError::TooLate) => Status::UNAVAILABLE,
+ Err(CommitError::DynamicConfigurationDisabled) => {
+ Status::ACCESS_DENIED
+ }
};
responder.send(status.into_raw())?;
return Ok(());
@@ -237,7 +240,7 @@
rule!("fuchsia.com" => "static.fuchsia.com", "/4" => "/4"),
];
let state = Arc::new(RwLock::new(
- RewriteManagerBuilder::new(&dynamic_config)
+ RewriteManagerBuilder::new(Some(&dynamic_config))
.unwrap()
.static_rules(static_rules.clone())
.build(),
@@ -259,7 +262,7 @@
rule!("fuchsia.com" => "static.fuchsia.com", "/4" => "/4"),
];
let state = Arc::new(RwLock::new(
- RewriteManagerBuilder::new(&dynamic_config)
+ RewriteManagerBuilder::new(Some(&dynamic_config))
.unwrap()
.static_rules(static_rules.clone())
.build(),
@@ -275,8 +278,9 @@
rule!("fuchsia.com" => "fuchsia.com", "/rolldice/" => "/rolldice/"),
];
let dynamic_config = make_rule_config(rules.clone());
- let state =
- Arc::new(RwLock::new(RewriteManagerBuilder::new(&dynamic_config).unwrap().build()));
+ let state = Arc::new(RwLock::new(
+ RewriteManagerBuilder::new(Some(&dynamic_config)).unwrap().build(),
+ ));
let mut service = RewriteService::new(state.clone());
let (client, request_stream) = create_proxy_and_stream::<EditTransactionMarker>().unwrap();
@@ -297,7 +301,10 @@
let dynamic_config = make_rule_config(dynamic_rules.clone());
let static_rules = vec![rule!("fuchsia.com" => "static.fuchsia.com", "/" => "/")];
let state = Arc::new(RwLock::new(
- RewriteManagerBuilder::new(&dynamic_config).unwrap().static_rules(static_rules).build(),
+ RewriteManagerBuilder::new(Some(&dynamic_config))
+ .unwrap()
+ .static_rules(static_rules)
+ .build(),
));
let mut service = RewriteService::new(state.clone());
@@ -328,8 +335,9 @@
rule!("fuchsia.com" => "fuchsia.com", "/rolldice/" => "/rolldice/"),
];
let dynamic_config = make_rule_config(rules.clone());
- let state =
- Arc::new(RwLock::new(RewriteManagerBuilder::new(&dynamic_config).unwrap().build()));
+ let state = Arc::new(RwLock::new(
+ RewriteManagerBuilder::new(Some(&dynamic_config)).unwrap().build(),
+ ));
let mut service = RewriteService::new(state.clone());
let client1 = {
@@ -371,8 +379,9 @@
#[fasync::run_until_stalled(test)]
async fn test_concurrent_list_and_edit() {
let dynamic_config = make_rule_config(vec![]);
- let state =
- Arc::new(RwLock::new(RewriteManagerBuilder::new(&dynamic_config).unwrap().build()));
+ let state = Arc::new(RwLock::new(
+ RewriteManagerBuilder::new(Some(&dynamic_config)).unwrap().build(),
+ ));
let mut service = RewriteService::new(state.clone());
assert_eq!(list_rules(state.clone()).await, vec![]);
@@ -412,7 +421,7 @@
rule!("fuchsia.com" => "fuchsia.com", "/identity" => "/identity"),
];
let state = Arc::new(RwLock::new(
- RewriteManagerBuilder::new(&dynamic_config)
+ RewriteManagerBuilder::new(Some(&dynamic_config))
.unwrap()
.static_rules(static_rules.clone())
.build(),
@@ -439,8 +448,9 @@
#[fasync::run_until_stalled(test)]
async fn test_rewrite_rejects_invalid_inputs() {
let dynamic_config = make_rule_config(vec![]);
- let state =
- Arc::new(RwLock::new(RewriteManagerBuilder::new(&dynamic_config).unwrap().build()));
+ let state = Arc::new(RwLock::new(
+ RewriteManagerBuilder::new(Some(&dynamic_config)).unwrap().build(),
+ ));
let service = RewriteService::new(state.clone());
for url in &["not-fuchsia-pkg://fuchsia.com/test", "fuchsia-pkg://fuchsia.com/a*"] {
@@ -452,8 +462,9 @@
async fn test_concurrent_rewrite_and_edit() {
let dynamic_config =
make_rule_config(vec![rule!("fuchsia.com" => "fuchsia.com", "/a" => "/b")]);
- let state =
- Arc::new(RwLock::new(RewriteManagerBuilder::new(&dynamic_config).unwrap().build()));
+ let state = Arc::new(RwLock::new(
+ RewriteManagerBuilder::new(Some(&dynamic_config)).unwrap().build(),
+ ));
let mut service = RewriteService::new(state.clone());
let (edit_client, request_stream) =
@@ -483,8 +494,9 @@
#[fasync::run_until_stalled(test)]
async fn test_enables_amber_source() {
let dynamic_config = make_rule_config(vec![]);
- let state =
- Arc::new(RwLock::new(RewriteManagerBuilder::new(&dynamic_config).unwrap().build()));
+ let state = Arc::new(RwLock::new(
+ RewriteManagerBuilder::new(Some(&dynamic_config)).unwrap().build(),
+ ));
let mut service = RewriteService::new(state.clone());
let (client, request_stream) = create_proxy_and_stream::<EditTransactionMarker>().unwrap();
@@ -522,8 +534,9 @@
let rules = vec![rule!("fuchsia.com" => "enabled.fuchsia.com", "/" => "/")];
let dynamic_config = make_rule_config(rules);
- let state =
- Arc::new(RwLock::new(RewriteManagerBuilder::new(&dynamic_config).unwrap().build()));
+ let state = Arc::new(RwLock::new(
+ RewriteManagerBuilder::new(Some(&dynamic_config)).unwrap().build(),
+ ));
let mut service = RewriteService::new(state.clone());
let (client, request_stream) = create_proxy_and_stream::<EditTransactionMarker>().unwrap();
@@ -537,4 +550,19 @@
client.reset_all().unwrap();
assert_yields_status!(client.commit(), Status::OK);
}
+
+ #[fasync::run_until_stalled(test)]
+ async fn test_transaction_commit_fails_if_no_dynamic_rules_path() {
+ let state = Arc::new(RwLock::new(
+ RewriteManagerBuilder::new(Option::<&std::path::Path>::None).unwrap().build(),
+ ));
+ let mut service = RewriteService::new(state);
+
+ let (client, request_stream) = create_proxy_and_stream::<EditTransactionMarker>().unwrap();
+ service.serve_edit_transaction(request_stream);
+
+ let status = Status::from_raw(client.commit().await.unwrap());
+
+ assert_eq!(status, Status::ACCESS_DENIED);
+ }
}
diff --git a/garnet/tests/pkg-resolver/BUILD.gn b/garnet/tests/pkg-resolver/BUILD.gn
index c4c1eda..d108979 100644
--- a/garnet/tests/pkg-resolver/BUILD.gn
+++ b/garnet/tests/pkg-resolver/BUILD.gn
@@ -25,13 +25,18 @@
"//garnet/public/rust/fuchsia-zircon",
"//sdk/fidl/fuchsia.amber:fuchsia.amber-rustc",
"//sdk/fidl/fuchsia.pkg:fuchsia.pkg-rustc",
+ "//sdk/fidl/fuchsia.pkg.rewrite:fuchsia.pkg.rewrite-rustc",
"//sdk/fidl/fuchsia.sys:fuchsia.sys-rustc",
+ "//src/sys/lib/fuchsia_url_rewrite",
"//third_party/rust_crates:failure",
"//third_party/rust_crates:futures-preview",
"//third_party/rust_crates:hyper",
"//third_party/rust_crates:matches",
"//third_party/rust_crates:openat",
"//third_party/rust_crates:parking_lot",
+ "//third_party/rust_crates:serde",
+ "//third_party/rust_crates:serde_derive",
+ "//third_party/rust_crates:serde_json",
"//third_party/rust_crates:tempfile",
"//third_party/rust_crates:void",
"//zircon/system/fidl/fuchsia-io:fuchsia-io-rustc",
diff --git a/garnet/tests/pkg-resolver/src/dynamic_rewrite_disabled.rs b/garnet/tests/pkg-resolver/src/dynamic_rewrite_disabled.rs
new file mode 100644
index 0000000..14c1265
--- /dev/null
+++ b/garnet/tests/pkg-resolver/src/dynamic_rewrite_disabled.rs
@@ -0,0 +1,215 @@
+// Copyright 2019 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/// This module tests pkg_resolver's RewriteManager when
+/// dynamic rewrite rules have been disabled.
+use {
+ crate::{DirOrProxy, Mounts, TestEnv},
+ fidl::endpoints::RequestStream,
+ fidl_fuchsia_io::{
+ DirectoryObject, DirectoryProxy, DirectoryRequest, DirectoryRequestStream,
+ OPEN_FLAG_DESCRIBE,
+ },
+ fidl_fuchsia_pkg_rewrite::EngineProxy as RewriteEngineProxy,
+ fuchsia_async as fasync,
+ fuchsia_url_rewrite::{Rule, RuleConfig},
+ fuchsia_zircon::Status,
+ futures::{
+ future::{BoxFuture, FutureExt},
+ stream::StreamExt,
+ },
+ parking_lot::Mutex,
+ serde_derive::Serialize,
+ std::{collections::HashMap, convert::TryInto, fs::File, io::BufWriter, sync::Arc},
+};
+
+#[derive(Serialize)]
+struct Config {
+ disable_dynamic_configuration: bool,
+}
+
+impl Mounts {
+ fn add_dynamic_rewrite_rules(&self, rule_config: &RuleConfig) {
+ if let DirOrProxy::Dir(ref d) = self.pkg_resolver_data {
+ let f = File::create(d.path().join("rewrites.json")).unwrap();
+ serde_json::to_writer(BufWriter::new(f), rule_config).unwrap();
+ } else {
+ panic!("not supported");
+ }
+ }
+ fn add_config(&self, config: &Config) {
+ if let DirOrProxy::Dir(ref d) = self.pkg_resolver_config_data {
+ let f = File::create(d.path().join("config.json")).unwrap();
+ serde_json::to_writer(BufWriter::new(f), &config).unwrap();
+ } else {
+ panic!("not supported");
+ }
+ }
+}
+
+fn make_rule_config(rule: &Rule) -> RuleConfig {
+ RuleConfig::Version1(vec![rule.clone()])
+}
+
+fn make_rule() -> Rule {
+ Rule::new("example.com", "example.com", "/", "/").unwrap()
+}
+
+async fn get_rules(rewrite_engine: &RewriteEngineProxy) -> Vec<Rule> {
+ let (rule_iterator, rule_iterator_server) =
+ fidl::endpoints::create_proxy().expect("create rule iterator proxy");
+ rewrite_engine.list(rule_iterator_server).expect("list rules");
+ let mut ret = vec![];
+ loop {
+ let rules = rule_iterator.next().await.expect("advance rule iterator");
+ if rules.is_empty() {
+ return ret;
+ }
+ ret.extend(rules.into_iter().map(|r| r.try_into().unwrap()))
+ }
+}
+
+#[fasync::run_singlethreaded(test)]
+async fn load_dynamic_rules() {
+ let mounts = Mounts::new();
+ let rule = make_rule();
+ mounts.add_dynamic_rewrite_rules(&make_rule_config(&rule));
+ mounts.add_config(&Config { disable_dynamic_configuration: false });
+ let env = TestEnv::new_with_mounts(mounts);
+
+ assert_eq!(get_rules(&env.proxies.rewrite_engine).await, vec![rule]);
+
+ env.stop().await;
+}
+
+#[fasync::run_singlethreaded(test)]
+async fn no_load_dynamic_rules_if_disabled() {
+ let mounts = Mounts::new();
+ mounts.add_dynamic_rewrite_rules(&make_rule_config(&make_rule()));
+ mounts.add_config(&Config { disable_dynamic_configuration: true });
+ let env = TestEnv::new_with_mounts(mounts);
+
+ assert_eq!(get_rules(&env.proxies.rewrite_engine).await, vec![]);
+
+ env.stop().await;
+}
+
+#[fasync::run_singlethreaded(test)]
+async fn commit_transaction_succeeds() {
+ let env = TestEnv::new();
+
+ let (edit_transaction, edit_transaction_server) = fidl::endpoints::create_proxy().unwrap();
+ env.proxies.rewrite_engine.start_edit_transaction(edit_transaction_server).unwrap();
+ let rule = make_rule();
+ Status::ok(edit_transaction.add(&mut rule.clone().into()).await.unwrap()).unwrap();
+
+ assert_eq!(Status::from_raw(edit_transaction.commit().await.unwrap()), Status::OK);
+ assert_eq!(get_rules(&env.proxies.rewrite_engine).await, vec![rule]);
+
+ env.stop().await;
+}
+
+#[fasync::run_singlethreaded(test)]
+async fn commit_transaction_fails_if_disabled() {
+ let mounts = Mounts::new();
+ mounts.add_config(&Config { disable_dynamic_configuration: true });
+ let env = TestEnv::new_with_mounts(mounts);
+
+ let (edit_transaction, edit_transaction_server) = fidl::endpoints::create_proxy().unwrap();
+ env.proxies.rewrite_engine.start_edit_transaction(edit_transaction_server).unwrap();
+ Status::ok(edit_transaction.add(&mut make_rule().into()).await.unwrap()).unwrap();
+
+ assert_eq!(Status::from_raw(edit_transaction.commit().await.unwrap()), Status::ACCESS_DENIED);
+ assert_eq!(get_rules(&env.proxies.rewrite_engine).await, vec![]);
+
+ env.stop().await;
+}
+
+type OpenCounter = Arc<Mutex<HashMap<String, u64>>>;
+
+fn handle_directory_request_stream(
+ mut stream: DirectoryRequestStream,
+ open_counts: OpenCounter,
+) -> BoxFuture<'static, ()> {
+ async move {
+ while let Some(req) = stream.next().await {
+ handle_directory_request(req.unwrap(), Arc::clone(&open_counts)).await;
+ }
+ }
+ .boxed()
+}
+
+async fn handle_directory_request(req: DirectoryRequest, open_counts: OpenCounter) {
+ match req {
+ DirectoryRequest::Clone { flags, object, control_handle: _control_handle } => {
+ let stream = DirectoryRequestStream::from_channel(
+ fasync::Channel::from_channel(object.into_channel()).unwrap(),
+ );
+ describe_dir(flags, &stream);
+ fasync::spawn(handle_directory_request_stream(stream, Arc::clone(&open_counts)));
+ }
+ DirectoryRequest::Open {
+ flags: _flags,
+ mode: _mode,
+ path,
+ object: _object,
+ control_handle: _control_handle,
+ } => {
+ *open_counts.lock().entry(path).or_insert(0) += 1;
+ }
+ other => panic!("unhandled request type: {:?}", other),
+ }
+}
+
+fn describe_dir(flags: u32, stream: &DirectoryRequestStream) {
+ let ch = stream.control_handle();
+ if flags & OPEN_FLAG_DESCRIBE != 0 {
+ let mut ni = fidl_fuchsia_io::NodeInfo::Directory(DirectoryObject);
+ ch.send_on_open_(Status::OK.into_raw(), Some(fidl::encoding::OutOfLine(&mut ni)))
+ .expect("send_on_open");
+ }
+}
+
+fn spawn_directory_handler() -> (DirectoryProxy, OpenCounter) {
+ let (proxy, stream) =
+ fidl::endpoints::create_proxy_and_stream::<fidl_fuchsia_io::DirectoryMarker>().unwrap();
+ let open_counts = Arc::new(Mutex::new(HashMap::<String, u64>::new()));
+ fasync::spawn(handle_directory_request_stream(stream, Arc::clone(&open_counts)));
+ (proxy, open_counts)
+}
+
+#[fasync::run_singlethreaded(test)]
+async fn attempt_to_open_persisted_dynamic_rules() {
+ let (proxy, open_counts) = spawn_directory_handler();
+ let mounts = Mounts {
+ pkg_resolver_data: DirOrProxy::Proxy(proxy),
+ pkg_resolver_config_data: DirOrProxy::Dir(tempfile::tempdir().expect("/tmp to exist")),
+ };
+ let env = TestEnv::new_with_mounts(mounts);
+
+ // Waits for pkg_resolver to be initialized
+ get_rules(&env.proxies.rewrite_engine).await;
+
+ assert_eq!(open_counts.lock().get("rewrites.json"), Some(&1));
+
+ env.stop().await;
+}
+
+#[fasync::run_singlethreaded(test)]
+async fn no_attempt_to_open_persisted_dynamic_rules_if_disabled() {
+ let (proxy, open_counts) = spawn_directory_handler();
+ let mounts = Mounts {
+ pkg_resolver_data: DirOrProxy::Proxy(proxy),
+ pkg_resolver_config_data: DirOrProxy::Dir(tempfile::tempdir().expect("/tmp to exist")),
+ };
+ mounts.add_config(&Config { disable_dynamic_configuration: true });
+ let env = TestEnv::new_with_mounts(mounts);
+
+ // Waits for pkg_resolver to be initialized
+ get_rules(&env.proxies.rewrite_engine).await;
+
+ assert_eq!(open_counts.lock().get("rewrites.json"), None);
+
+ env.stop().await;
+}
diff --git a/garnet/tests/pkg-resolver/src/lib.rs b/garnet/tests/pkg-resolver/src/lib.rs
index 0364bb9..9c0f664 100644
--- a/garnet/tests/pkg-resolver/src/lib.rs
+++ b/garnet/tests/pkg-resolver/src/lib.rs
@@ -8,12 +8,15 @@
failure::Error,
fidl::endpoints::ClientEnd,
fidl_fuchsia_amber::ControlMarker as AmberMarker,
- fidl_fuchsia_io::{DirectoryMarker, DirectoryProxy},
+ fidl_fuchsia_io::{DirectoryMarker, DirectoryProxy, CLONE_FLAG_SAME_RIGHTS},
fidl_fuchsia_pkg::{
ExperimentToggle as Experiment, PackageCacheMarker, PackageResolverAdminMarker,
PackageResolverAdminProxy, PackageResolverMarker, PackageResolverProxy,
RepositoryManagerMarker, RepositoryManagerProxy, UpdatePolicy,
},
+ fidl_fuchsia_pkg_rewrite::{
+ EngineMarker as RewriteEngineMarker, EngineProxy as RewriteEngineProxy,
+ },
fidl_fuchsia_sys::LauncherProxy,
fuchsia_async as fasync,
fuchsia_component::{
@@ -21,10 +24,13 @@
server::{NestedEnvironment, ServiceFs},
},
fuchsia_pkg_testing::{pkgfs::TestPkgFs, Package, PackageBuilder},
- fuchsia_zircon::Status,
+ fuchsia_zircon::{self as zx, Status},
futures::prelude::*,
+ std::fs::File,
+ tempfile::TempDir,
};
+mod dynamic_rewrite_disabled;
mod resolve_propagates_pkgfs_failure;
mod resolve_recovers_from_http_errors;
mod resolve_succeeds;
@@ -39,6 +45,56 @@
}
}
+struct Mounts {
+ pkg_resolver_data: DirOrProxy,
+ pkg_resolver_config_data: DirOrProxy,
+}
+
+enum DirOrProxy {
+ Dir(TempDir),
+ Proxy(DirectoryProxy),
+}
+
+trait AppBuilderExt {
+ fn add_dir_or_proxy_to_namespace(
+ self,
+ path: impl Into<String>,
+ dir_or_proxy: &DirOrProxy,
+ ) -> Self;
+}
+
+impl AppBuilderExt for AppBuilder {
+ fn add_dir_or_proxy_to_namespace(
+ self,
+ path: impl Into<String>,
+ dir_or_proxy: &DirOrProxy,
+ ) -> Self {
+ match dir_or_proxy {
+ DirOrProxy::Dir(d) => {
+ self.add_dir_to_namespace(path.into(), File::open(d.path()).unwrap()).unwrap()
+ }
+ DirOrProxy::Proxy(p) => {
+ self.add_handle_to_namespace(path.into(), clone_directory_proxy(p))
+ }
+ }
+ }
+}
+
+fn clone_directory_proxy(proxy: &DirectoryProxy) -> zx::Handle {
+ let (client, server) = fidl::endpoints::create_endpoints().unwrap();
+ proxy.clone(CLONE_FLAG_SAME_RIGHTS, server).unwrap();
+ client.into()
+}
+
+impl Mounts {
+ fn new() -> Self {
+ Self {
+ pkg_resolver_data: DirOrProxy::Dir(tempfile::tempdir().expect("/tmp to exist")),
+ pkg_resolver_config_data: DirOrProxy::Dir(tempfile::tempdir().expect("/tmp to exist")),
+ }
+ }
+}
+
struct Apps {
_amber: App,
_pkg_cache: App,
@@ -49,6 +105,7 @@
resolver_admin: PackageResolverAdminProxy,
resolver: PackageResolverProxy,
repo_manager: RepositoryManagerProxy,
+ rewrite_engine: RewriteEngineProxy,
}
struct TestEnv<P = TestPkgFs> {
@@ -56,6 +113,7 @@
env: NestedEnvironment,
apps: Apps,
proxies: Proxies,
+ _mounts: Mounts,
}
impl TestEnv<TestPkgFs> {
@@ -63,6 +121,10 @@
Self::new_with_pkg_fs(TestPkgFs::start(None).expect("pkgfs to start"))
}
+ fn new_with_mounts(mounts: Mounts) -> Self {
+ Self::new_with_pkg_fs_and_mounts(TestPkgFs::start(None).expect("pkgfs to start"), mounts)
+ }
+
async fn stop(self) {
// Tear down the environment in reverse order, ending with the storage.
drop(self.proxies);
@@ -74,6 +136,10 @@
impl<P: PkgFs> TestEnv<P> {
fn new_with_pkg_fs(pkgfs: P) -> Self {
+ Self::new_with_pkg_fs_and_mounts(pkgfs, Mounts::new())
+ }
+
+ fn new_with_pkg_fs_and_mounts(pkgfs: P, mounts: Mounts) -> Self {
let mut amber =
AppBuilder::new("fuchsia-pkg://fuchsia.com/pkg-resolver-tests#meta/amber.cmx")
.add_handle_to_namespace(
@@ -95,7 +161,9 @@
.add_handle_to_namespace(
"/pkgfs".to_owned(),
pkgfs.root_dir_client_end().expect("pkgfs dir to open").into(),
- );
+ )
+ .add_dir_or_proxy_to_namespace("/data", &mounts.pkg_resolver_data)
+ .add_dir_or_proxy_to_namespace("/config/data", &mounts.pkg_resolver_config_data);
let mut fs = ServiceFs::new();
fs.add_proxy_service::<fidl_fuchsia_net::NameLookupMarker, _>()
@@ -131,6 +199,9 @@
let repo_manager_proxy = env
.connect_to_service::<RepositoryManagerMarker>()
.expect("connect to repository manager");
+ let rewrite_engine_proxy = pkg_resolver
+ .connect_to_service::<RewriteEngineMarker>()
+ .expect("connect to rewrite engine");
Self {
env,
@@ -140,7 +211,9 @@
resolver: resolver_proxy,
resolver_admin: resolver_admin_proxy,
repo_manager: repo_manager_proxy,
+ rewrite_engine: rewrite_engine_proxy,
},
+ _mounts: mounts,
}
}
diff --git a/sdk/fidl/fuchsia.pkg.rewrite/rewrite.fidl b/sdk/fidl/fuchsia.pkg.rewrite/rewrite.fidl
index bdcf490..649f75c 100644
--- a/sdk/fidl/fuchsia.pkg.rewrite/rewrite.fidl
+++ b/sdk/fidl/fuchsia.pkg.rewrite/rewrite.fidl
@@ -156,8 +156,8 @@
///
/// * status `ZX_OK` the staged edits were successfully committed.
/// * status `ZX_ERR_UNAVAILABLE` another transaction committed before this one.
+ /// * status `ZX_ERR_ACCESS_DENIED` editing dynamic rewrite rules is permanently disabled.
Commit() -> (zx.status status);
-
};
/// The iterator over all the rewrite rules defined in a [`Engine`].