routing/bedrock/
with_policy_check.rsuse crate::capability_source::CapabilitySource;
use crate::component_instance::{ComponentInstanceInterface, WeakExtendedInstanceInterface};
use crate::error::{ComponentInstanceError, RoutingError};
use crate::policy::GlobalPolicyChecker;
use async_trait::async_trait;
use moniker::ExtendedMoniker;
use router_error::RouterError;
#[cfg(not(target_os = "fuchsia"))]
use sandbox::Capability;
use sandbox::{CapabilityBound, Request, Routable, Router, RouterResponse};
pub const SKIP_POLICY_CHECKS: &'static str = "skip_policy_checks";
pub trait WithPolicyCheck {
fn with_policy_check<C: ComponentInstanceInterface + 'static>(
self,
capability_source: CapabilitySource,
policy_checker: GlobalPolicyChecker,
) -> Self;
}
impl<T: CapabilityBound> WithPolicyCheck for Router<T> {
fn with_policy_check<C: ComponentInstanceInterface + 'static>(
self,
capability_source: CapabilitySource,
policy_checker: GlobalPolicyChecker,
) -> Self {
Self::new(PolicyCheckRouter::<C, T>::new(capability_source, policy_checker, self))
}
}
pub struct PolicyCheckRouter<C: ComponentInstanceInterface + 'static, T: CapabilityBound> {
capability_source: CapabilitySource,
policy_checker: GlobalPolicyChecker,
router: Router<T>,
_phantom_data: std::marker::PhantomData<C>,
}
impl<C: ComponentInstanceInterface + 'static, T: CapabilityBound> PolicyCheckRouter<C, T> {
pub fn new(
capability_source: CapabilitySource,
policy_checker: GlobalPolicyChecker,
router: Router<T>,
) -> Self {
Self {
capability_source,
policy_checker,
router,
_phantom_data: std::marker::PhantomData::<C>,
}
}
}
#[async_trait]
impl<C: ComponentInstanceInterface + 'static, T: CapabilityBound> Routable<T>
for PolicyCheckRouter<C, T>
{
async fn route(
&self,
request: Option<Request>,
debug: bool,
) -> Result<RouterResponse<T>, RouterError> {
let request = request.ok_or_else(|| RouterError::InvalidArgs)?;
#[cfg(not(target_os = "fuchsia"))]
if let Ok(Some(Capability::Data(sandbox::Data::Uint64(num)))) =
request.metadata.get(&cm_types::Name::new(SKIP_POLICY_CHECKS).unwrap())
{
if num > 0 {
return self.router.route(Some(request), debug).await;
}
}
let target = request
.target
.inner
.as_any()
.downcast_ref::<WeakExtendedInstanceInterface<C>>()
.ok_or(RouterError::Unknown)?;
let ExtendedMoniker::ComponentInstance(moniker) = target.extended_moniker() else {
return Err(RoutingError::from(
ComponentInstanceError::ComponentManagerInstanceUnexpected {},
)
.into());
};
match self.policy_checker.can_route_capability(&self.capability_source, &moniker) {
Ok(()) => self.router.route(Some(request), debug).await,
Err(policy_error) => Err(RoutingError::PolicyError(policy_error).into()),
}
}
}