routing/bedrock/
with_rights.rs1use crate::bedrock::request_metadata::Metadata;
6use crate::error::RoutingError;
7use crate::rights::{Rights, RightsWalker};
8use crate::walk_state::WalkStateUnit;
9use async_trait::async_trait;
10use fidl_fuchsia_component_sandbox as fsandbox;
11use moniker::ExtendedMoniker;
12use router_error::RouterError;
13use sandbox::{CapabilityBound, Request, Routable, Router, RouterResponse};
14
15struct RightsRouter<T: CapabilityBound> {
16 router: Router<T>,
17 rights: Rights,
18 moniker: ExtendedMoniker,
19}
20
21#[async_trait]
22impl<T: CapabilityBound> Routable<T> for RightsRouter<T> {
23 async fn route(
24 &self,
25 request: Option<Request>,
26 debug: bool,
27 ) -> Result<RouterResponse<T>, router_error::RouterError> {
28 let request = request.ok_or_else(|| RouterError::InvalidArgs)?;
29 let RightsRouter { router, rights, moniker } = self;
30 let request_rights: Rights =
31 request.metadata.get_metadata().ok_or(fsandbox::RouterError::InvalidArgs)?;
32 let request_rights = RightsWalker::new(request_rights, moniker.clone());
33 let router_rights = RightsWalker::new(*rights, moniker.clone());
34 match request_rights.validate_next(&router_rights) {
37 Ok(()) => router.route(Some(request), debug).await,
38 Err(e) => Err(RoutingError::from(e).into()),
39 }
40 }
41}
42
43pub trait WithRights {
44 fn with_rights(self, moniker: impl Into<ExtendedMoniker>, rights: Rights) -> Self;
47}
48
49impl<T: CapabilityBound> WithRights for Router<T> {
50 fn with_rights(self, moniker: impl Into<ExtendedMoniker>, rights: Rights) -> Self {
51 Router::<T>::new(RightsRouter { rights, router: self, moniker: moniker.into() })
52 }
53}
54
55#[cfg(test)]
56mod tests {
57 use super::*;
58 use assert_matches::assert_matches;
59 use fidl_fuchsia_io as fio;
60 use router_error::{DowncastErrorForTest, RouterError};
61 use sandbox::{Data, Dict, WeakInstanceToken};
62 use std::sync::Arc;
63
64 #[derive(Debug)]
65 struct FakeComponentToken {}
66
67 impl FakeComponentToken {
68 fn new() -> WeakInstanceToken {
69 WeakInstanceToken { inner: Arc::new(FakeComponentToken {}) }
70 }
71 }
72
73 impl sandbox::WeakInstanceTokenAny for FakeComponentToken {
74 fn as_any(&self) -> &dyn std::any::Any {
75 self
76 }
77 }
78
79 #[fuchsia::test]
80 async fn rights_good() {
81 let source = Data::String("hello".to_string());
82 let base = Router::<Data>::new_ok(source);
83 let proxy = base.with_rights(ExtendedMoniker::ComponentManager, fio::RW_STAR_DIR.into());
84 let metadata = Dict::new();
85 metadata.set_metadata(Into::<Rights>::into(fio::R_STAR_DIR));
86 let capability = proxy
87 .route(Some(Request { target: FakeComponentToken::new(), metadata }), false)
88 .await
89 .unwrap();
90 let capability = match capability {
91 RouterResponse::<Data>::Capability(d) => d,
92 c => panic!("Bad enum {:#?}", c),
93 };
94 assert_eq!(capability, Data::String("hello".to_string()));
95 }
96
97 #[fuchsia::test]
98 async fn rights_bad() {
99 let source = Data::String("hello".to_string());
100 let base = Router::<Data>::new_ok(source);
101 let proxy = base.with_rights(ExtendedMoniker::ComponentManager, fio::R_STAR_DIR.into());
102 let metadata = Dict::new();
103 metadata.set_metadata(Into::<Rights>::into(fio::RW_STAR_DIR));
104 let error = proxy
105 .route(Some(Request { target: FakeComponentToken::new(), metadata }), false)
106 .await
107 .unwrap_err();
108 assert_matches!(
109 error,
110 RouterError::NotFound(err)
111 if matches!(
112 err.downcast_for_test::<RoutingError>(),
113 RoutingError::RightsRoutingError(
114 crate::error::RightsRoutingError::Invalid { moniker: ExtendedMoniker::ComponentManager, requested, provided }
115 ) if *requested == <fio::Operations as Into<Rights>>::into(fio::RW_STAR_DIR) && *provided == <fio::Operations as Into<Rights>>::into(fio::R_STAR_DIR)
116 )
117 );
118 }
119}