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};
14use std::sync::Arc;
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 Arc<Router<T>> {
46 fn with_policy_check<C: ComponentInstanceInterface + 'static>(
47 self,
48 capability_source: CapabilitySource,
49 policy_checker: GlobalPolicyChecker,
50 ) -> Self {
51 Router::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: Arc<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: Arc<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 fn check_policy(
77 &self,
78 _request: &RouteRequest,
79 target_token: Arc<WeakInstanceToken>,
80 ) -> Result<(), RouterError> {
81 #[cfg(not(target_os = "fuchsia"))]
82 if _request.skip_policy_checks.unwrap_or(false) {
83 return Ok(());
84 }
85 let target = target_token
86 .inner
87 .as_any()
88 .downcast_ref::<WeakExtendedInstanceInterface<C>>()
89 .ok_or(RouterError::Unknown)?;
90 let ExtendedMoniker::ComponentInstance(moniker) = target.extended_moniker() else {
91 return Err(RoutingError::from(
92 ComponentInstanceError::ComponentManagerInstanceUnexpected {},
93 )
94 .into());
95 };
96 match self.policy_checker.can_route_capability(&self.capability_source, &moniker) {
97 Ok(()) => Ok(()),
98 Err(policy_error) => Err(RoutingError::PolicyError(policy_error).into()),
99 }
100 }
101}
102
103#[async_trait]
104impl<C: ComponentInstanceInterface + 'static, T: CapabilityBound> Routable<T>
105 for PolicyCheckRouter<C, T>
106{
107 async fn route(
108 &self,
109 request: RouteRequest,
110 target_token: Arc<WeakInstanceToken>,
111 ) -> Result<Option<Arc<T>>, RouterError> {
112 self.check_policy(&request, target_token.clone())?;
113 self.router.route(request, target_token).await
114 }
115
116 async fn route_debug(
117 &self,
118 request: RouteRequest,
119 target_token: Arc<WeakInstanceToken>,
120 ) -> Result<CapabilitySource, RouterError> {
121 self.check_policy(&request, target_token.clone())?;
122 self.router.route_debug(request, target_token).await
123 }
124}