securitydept_token_set_context/access_token_substrate/
runtime.rs1use std::sync::Arc;
2
3use securitydept_oauth_resource_server::OAuthResourceServerVerifier;
4
5use super::{
6 capabilities::TokenPropagation,
7 propagation::{TokenPropagator, TokenPropagatorError},
8};
9
10#[derive(Debug)]
12pub enum AccessTokenSubstrateRuntimeError {
13 ResourceServer(securitydept_oauth_resource_server::OAuthResourceServerError),
15 TokenPropagator(TokenPropagatorError),
17}
18
19impl std::fmt::Display for AccessTokenSubstrateRuntimeError {
20 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
21 match self {
22 Self::ResourceServer(e) => write!(f, "resource_server: {e}"),
23 Self::TokenPropagator(e) => write!(f, "token_propagation: {e}"),
24 }
25 }
26}
27
28impl std::error::Error for AccessTokenSubstrateRuntimeError {
29 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
30 match self {
31 Self::ResourceServer(e) => Some(e),
32 Self::TokenPropagator(e) => Some(e),
33 }
34 }
35}
36
37#[derive(Clone)]
44pub struct AccessTokenSubstrateRuntime {
45 token_propagator: Option<Arc<TokenPropagator>>,
46}
47
48impl std::fmt::Debug for AccessTokenSubstrateRuntime {
49 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50 f.debug_struct("AccessTokenSubstrateRuntime")
51 .field("token_propagator", &self.token_propagator)
52 .finish()
53 }
54}
55
56impl AccessTokenSubstrateRuntime {
57 pub async fn from_resolved_config(
71 config: &super::config::ResolvedAccessTokenSubstrateConfig,
72 ) -> Result<(Self, Option<Arc<OAuthResourceServerVerifier>>), AccessTokenSubstrateRuntimeError>
73 {
74 let resource_verifier = if config.resource_server.remote.is_discovery_configured() {
75 let verifier = OAuthResourceServerVerifier::from_config(config.resource_server.clone())
76 .await
77 .map_err(AccessTokenSubstrateRuntimeError::ResourceServer)?;
78 Some(Arc::new(verifier))
79 } else {
80 None
81 };
82
83 let runtime = Self::new(&config.token_propagation)?;
84 Ok((runtime, resource_verifier))
85 }
86
87 pub fn new(
93 token_propagation: &TokenPropagation,
94 ) -> Result<Self, AccessTokenSubstrateRuntimeError> {
95 let token_propagator = match token_propagation {
96 TokenPropagation::Enabled { config } => {
97 let propagator = TokenPropagator::from_config(config)
98 .map_err(AccessTokenSubstrateRuntimeError::TokenPropagator)?;
99 Some(Arc::new(propagator))
100 }
101 TokenPropagation::Disabled => None,
102 };
103
104 Ok(Self { token_propagator })
105 }
106
107 pub fn token_propagator(&self) -> Option<&Arc<TokenPropagator>> {
109 self.token_propagator.as_ref()
110 }
111
112 pub fn propagation_enabled(&self) -> bool {
114 self.token_propagator.is_some()
115 }
116
117 pub fn build_forwarder<C>(&self, config: &C) -> Option<Result<C::Forwarder, C::Error>>
123 where
124 C: super::forwarder::PropagationForwarderConfigSource,
125 {
126 if !self.propagation_enabled() {
127 return None;
128 }
129 Some(config.build_forwarder())
130 }
131}
132
133#[cfg(test)]
134mod tests {
135 use super::*;
136 use crate::access_token_substrate::{
137 capabilities::TokenPropagation,
138 propagation::{PropagationDestinationPolicy, TokenPropagatorConfig},
139 };
140
141 #[test]
142 fn runtime_returns_none_propagator_when_disabled() {
143 let runtime = AccessTokenSubstrateRuntime::new(&TokenPropagation::Disabled)
144 .expect("should not error");
145 assert!(runtime.token_propagator().is_none());
146 assert!(!runtime.propagation_enabled());
147 }
148
149 #[test]
150 fn runtime_returns_some_propagator_when_enabled() {
151 let runtime = AccessTokenSubstrateRuntime::new(&TokenPropagation::Enabled {
152 config: TokenPropagatorConfig {
153 destination_policy: PropagationDestinationPolicy {
154 allowed_targets: vec![],
155 ..Default::default()
156 },
157 ..Default::default()
158 },
159 })
160 .expect("should not error");
161 assert!(runtime.token_propagator().is_some());
162 assert!(runtime.propagation_enabled());
163 }
164}