routing/bedrock/
with_policy_check.rs1use crate::capability_source::CapabilitySource;
6use crate::component_instance::{ComponentInstanceInterface, WeakExtendedInstanceInterface};
7use crate::error::{ComponentInstanceError, RoutingError};
8use crate::policy::GlobalPolicyChecker;
9use async_trait::async_trait;
10use moniker::ExtendedMoniker;
11use router_error::RouterError;
12#[cfg(not(target_os = "fuchsia"))]
13use sandbox::Capability;
14use sandbox::{CapabilityBound, Request, Routable, Router, RouterResponse};
15
16pub const SKIP_POLICY_CHECKS: &'static str = "skip_policy_checks";
34
35pub trait WithPolicyCheck {
36 fn with_policy_check<C: ComponentInstanceInterface + 'static>(
39 self,
40 capability_source: CapabilitySource,
41 policy_checker: GlobalPolicyChecker,
42 ) -> Self;
43}
44
45impl<T: CapabilityBound> WithPolicyCheck for Router<T> {
46 fn with_policy_check<C: ComponentInstanceInterface + 'static>(
47 self,
48 capability_source: CapabilitySource,
49 policy_checker: GlobalPolicyChecker,
50 ) -> Self {
51 Self::new(PolicyCheckRouter::<C, T>::new(capability_source, policy_checker, self))
52 }
53}
54
55pub struct PolicyCheckRouter<C: ComponentInstanceInterface + 'static, T: CapabilityBound> {
56 capability_source: CapabilitySource,
57 policy_checker: GlobalPolicyChecker,
58 router: Router<T>,
59 _phantom_data: std::marker::PhantomData<C>,
60}
61
62impl<C: ComponentInstanceInterface + 'static, T: CapabilityBound> PolicyCheckRouter<C, T> {
63 pub fn new(
64 capability_source: CapabilitySource,
65 policy_checker: GlobalPolicyChecker,
66 router: Router<T>,
67 ) -> Self {
68 Self {
69 capability_source,
70 policy_checker,
71 router,
72 _phantom_data: std::marker::PhantomData::<C>,
73 }
74 }
75}
76
77#[async_trait]
78impl<C: ComponentInstanceInterface + 'static, T: CapabilityBound> Routable<T>
79 for PolicyCheckRouter<C, T>
80{
81 async fn route(
82 &self,
83 request: Option<Request>,
84 debug: bool,
85 ) -> Result<RouterResponse<T>, RouterError> {
86 let request = request.ok_or_else(|| RouterError::InvalidArgs)?;
87 #[cfg(not(target_os = "fuchsia"))]
88 if let Ok(Some(Capability::Data(sandbox::Data::Uint64(num)))) =
89 request.metadata.get(&cm_types::Name::new(SKIP_POLICY_CHECKS).unwrap())
90 {
91 if num > 0 {
92 return self.router.route(Some(request), debug).await;
93 }
94 }
95 let target = request
96 .target
97 .inner
98 .as_any()
99 .downcast_ref::<WeakExtendedInstanceInterface<C>>()
100 .ok_or(RouterError::Unknown)?;
101 let ExtendedMoniker::ComponentInstance(moniker) = target.extended_moniker() else {
102 return Err(RoutingError::from(
103 ComponentInstanceError::ComponentManagerInstanceUnexpected {},
104 )
105 .into());
106 };
107 match self.policy_checker.can_route_capability(&self.capability_source, &moniker) {
108 Ok(()) => self.router.route(Some(request), debug).await,
109 Err(policy_error) => Err(RoutingError::PolicyError(policy_error).into()),
110 }
111 }
112}