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