1use std::collections::{HashMap, HashSet};
17use std::hash::RandomState;
18use std::sync::Arc;
19
20use async_trait::async_trait;
21use chrono::{DateTime, Utc};
22use tracing::debug;
23
24use crate::config::Config;
25use crate::keystone::ServiceState;
26use crate::plugin_manager::PluginManagerApi;
27use crate::role::{RoleApi, types::Role};
28use crate::trust::{TrustProviderError, backend::TrustBackend, types::*};
29
30pub struct TrustService {
32 backend_driver: Arc<dyn TrustBackend>,
34}
35
36impl TrustService {
37 pub fn new<P: PluginManagerApi>(
38 config: &Config,
39 plugin_manager: &P,
40 ) -> Result<Self, TrustProviderError> {
41 let backend_driver = plugin_manager
42 .get_trust_backend(config.trust.driver.clone())?
43 .clone();
44 Ok(Self { backend_driver })
45 }
46}
47
48#[async_trait]
49impl TrustApi for TrustService {
50 #[tracing::instrument(level = "debug", skip(self, state))]
52 async fn get_trust<'a>(
53 &self,
54 state: &ServiceState,
55 id: &'a str,
56 ) -> Result<Option<Trust>, TrustProviderError> {
57 if let Some(mut trust) = self.backend_driver.get_trust(state, id).await? {
58 let all_roles: HashMap<String, Role> = HashMap::from_iter(
59 state
60 .provider
61 .get_role_provider()
62 .list_roles(
63 state,
64 &crate::role::types::RoleListParameters {
65 domain_id: Some(None),
66 ..Default::default()
67 },
68 )
69 .await?
70 .iter()
71 .map(|role| (role.id.clone(), role.to_owned())),
72 );
73 if let Some(ref mut roles) = trust.roles {
74 for role in roles.iter_mut() {
75 if let Some(erole) = all_roles.get(&role.id) {
76 role.domain_id = erole.domain_id.clone();
77 role.name = Some(erole.name.clone());
78 }
79 }
80 roles.retain_mut(|role| role.name.is_some());
83 }
84 return Ok(Some(trust));
85 }
86 Ok(None)
87 }
88
89 #[tracing::instrument(level = "debug", skip(self, state))]
91 async fn get_trust_delegation_chain<'a>(
92 &self,
93 state: &ServiceState,
94 id: &'a str,
95 ) -> Result<Option<Vec<Trust>>, TrustProviderError> {
96 self.backend_driver
97 .get_trust_delegation_chain(state, id)
98 .await
99 }
100
101 #[tracing::instrument(level = "debug", skip(self, state))]
103 async fn list_trusts(
104 &self,
105 state: &ServiceState,
106 params: &TrustListParameters,
107 ) -> Result<Vec<Trust>, TrustProviderError> {
108 let mut trusts = self.backend_driver.list_trusts(state, params).await?;
109
110 let all_roles: HashMap<String, Role> = HashMap::from_iter(
111 state
112 .provider
113 .get_role_provider()
114 .list_roles(
115 state,
116 &crate::role::types::RoleListParameters {
117 domain_id: Some(None),
118 ..Default::default()
119 },
120 )
121 .await?
122 .iter()
123 .map(|role| (role.id.clone(), role.to_owned())),
124 );
125 for trust in trusts.iter_mut() {
126 if let Some(ref mut roles) = trust.roles {
127 for role in roles.iter_mut() {
128 if let Some(erole) = all_roles.get(&role.id) {
129 role.domain_id = erole.domain_id.clone();
130 role.name = Some(erole.name.clone());
131 }
132 }
133 roles.retain_mut(|role| role.name.is_some());
136 }
137 }
138
139 Ok(trusts)
140 }
141
142 #[tracing::instrument(level = "debug", skip(self, state))]
150 async fn validate_trust_delegation_chain(
151 &self,
152 state: &ServiceState,
153 trust: &Trust,
154 ) -> Result<bool, TrustProviderError> {
155 if trust.redelegated_trust_id.is_some()
156 && let Some(chain) = self.get_trust_delegation_chain(state, &trust.id).await?
157 {
158 if chain.len() > state.config.trust.max_redelegation_count {
159 return Err(TrustProviderError::RedelegationDeepnessExceed {
160 length: chain.len(),
161 max_depth: state.config.trust.max_redelegation_count,
162 });
163 }
164 let mut parent_trust: Option<Trust> = None;
165 let mut parent_expiration: Option<DateTime<Utc>> = None;
166 for delegation in chain.iter().rev() {
167 if let Some(current_redelegation_count) = delegation.redelegation_count
170 && current_redelegation_count > state.config.trust.max_redelegation_count as u32
171 {
172 return Err(TrustProviderError::RedelegationDeepnessExceed {
173 length: current_redelegation_count as usize,
174 max_depth: state.config.trust.max_redelegation_count,
175 });
176 }
177 if delegation.remaining_uses.is_some() {
178 return Err(TrustProviderError::RemainingUsesMustBeUnset);
179 }
180 if let Some(trust_expiry) = delegation.expires_at {
182 if let Some(parent_expiry) = parent_trust
183 .as_ref()
184 .and_then(|x| x.expires_at)
185 .or(parent_expiration)
186 {
187 if trust_expiry > parent_expiry {
188 return Err(TrustProviderError::ExpirationImpossible);
189 }
190 parent_expiration = Some(trust_expiry);
192 }
193 if parent_expiration.is_none() {
195 parent_expiration = Some(trust_expiry);
196 }
197 }
198 if let Some(parent_trust) = &parent_trust
200 && !HashSet::<String, RandomState>::from_iter(
201 delegation
202 .roles
203 .as_deref()
204 .unwrap_or_default()
205 .iter()
206 .map(|role| role.id.clone()),
207 )
208 .is_subset(&HashSet::from_iter(
209 parent_trust
210 .roles
211 .as_deref()
212 .unwrap_or_default()
213 .iter()
214 .map(|role| role.id.clone()),
215 ))
216 {
217 debug!(
218 "Trust roles {:?} are missing for the trustor {:?}",
219 trust.roles, parent_trust.roles,
220 );
221 return Err(TrustProviderError::RedelegatedRolesNotAvailable);
222 }
223 if delegation.impersonation && !parent_trust.is_some_and(|x| x.impersonation) {
225 return Err(TrustProviderError::RedelegatedImpersonationNotAllowed);
226 }
227 parent_trust = Some(delegation.clone());
228 }
229 }
230
231 Ok(true)
232 }
233}
234
235#[cfg(test)]
236mod tests {
237 use chrono::{DateTime, Utc};
238 use std::sync::Arc;
239
240 use super::*;
241 use crate::provider::Provider;
242 use crate::role::{MockRoleProvider, types::*};
243 use crate::tests::get_mocked_state;
244 use crate::trust::backend::MockTrustBackend;
245
246 #[tokio::test]
247 async fn test_get_trust() {
248 let mut role_mock = MockRoleProvider::default();
249 role_mock
250 .expect_list_roles()
251 .withf(|_, qp: &RoleListParameters| {
252 RoleListParameters {
253 domain_id: Some(None),
254 ..Default::default()
255 } == *qp
256 })
257 .returning(|_, _| Ok(Vec::new()));
258 let provider_builder = Provider::mocked_builder().mock_role(role_mock);
259 let state = get_mocked_state(None, Some(provider_builder));
260
261 let mut backend = MockTrustBackend::new();
262 backend
263 .expect_get_trust()
264 .withf(|_, id: &'_ str| id == "fake_trust")
265 .returning(|_, _| {
266 Ok(Some(Trust {
267 id: "fake_trust".into(),
268 ..Default::default()
269 }))
270 });
271
272 let trust_provider = TrustService {
273 backend_driver: Arc::new(backend),
274 };
275
276 let trust: Trust = trust_provider
277 .get_trust(&state, "fake_trust")
278 .await
279 .unwrap()
280 .expect("trust found");
281 assert_eq!(trust.id, "fake_trust");
282 }
283
284 #[tokio::test]
285 async fn test_get_trust_delegation_chain() {
286 let mut role_mock = MockRoleProvider::default();
287 role_mock
288 .expect_list_roles()
289 .withf(|_, qp: &RoleListParameters| {
290 RoleListParameters {
291 domain_id: Some(None),
292 ..Default::default()
293 } == *qp
294 })
295 .returning(|_, _| Ok(Vec::new()));
296 let provider_builder = Provider::mocked_builder().mock_role(role_mock);
297 let state = get_mocked_state(None, Some(provider_builder));
298
299 let mut backend = MockTrustBackend::new();
300 backend
301 .expect_get_trust_delegation_chain()
302 .withf(|_, id: &'_ str| id == "fake_trust")
303 .returning(|_, _| {
304 Ok(Some(vec![
305 Trust {
306 id: "redelegated_trust".into(),
307 redelegated_trust_id: Some("trust_id".into()),
308 ..Default::default()
309 },
310 Trust {
311 id: "trust_id".into(),
312 ..Default::default()
313 },
314 ]))
315 });
316
317 let trust_provider = TrustService {
318 backend_driver: Arc::new(backend),
319 };
320
321 let chain = trust_provider
322 .get_trust_delegation_chain(&state, "fake_trust")
323 .await
324 .unwrap()
325 .expect("chain fetched");
326 assert_eq!(chain.len(), 2);
327 }
328
329 #[tokio::test]
330 async fn test_validate_trust_delegation_chain_not_redelegated() {
331 let mut role_mock = MockRoleProvider::default();
332 role_mock
333 .expect_list_roles()
334 .withf(|_, qp: &RoleListParameters| {
335 RoleListParameters {
336 domain_id: Some(None),
337 ..Default::default()
338 } == *qp
339 })
340 .returning(|_, _| Ok(Vec::new()));
341 let provider_builder = Provider::mocked_builder().mock_role(role_mock);
342 let state = get_mocked_state(None, Some(provider_builder));
343
344 let mut backend = MockTrustBackend::new();
345 backend
346 .expect_get_trust()
347 .withf(|_, id: &'_ str| id == "fake_trust")
348 .returning(|_, _| {
349 Ok(Some(Trust {
350 id: "fake_trust".into(),
351 ..Default::default()
352 }))
353 });
354
355 let trust_provider = TrustService {
356 backend_driver: Arc::new(backend),
357 };
358 let trust = trust_provider
359 .get_trust(&state, "fake_trust")
360 .await
361 .unwrap()
362 .expect("trust found");
363 trust_provider
364 .validate_trust_delegation_chain(&state, &trust)
365 .await
366 .unwrap();
367 }
368
369 #[tokio::test]
370 async fn test_validate_trust_delegation_chain() {
371 let mut role_mock = MockRoleProvider::default();
372 role_mock
373 .expect_list_roles()
374 .withf(|_, qp: &RoleListParameters| {
375 RoleListParameters {
376 domain_id: Some(None),
377 ..Default::default()
378 } == *qp
379 })
380 .returning(|_, _| Ok(Vec::new()));
381 let provider_builder = Provider::mocked_builder().mock_role(role_mock);
382 let state = get_mocked_state(None, Some(provider_builder));
383 let mut backend = MockTrustBackend::new();
384 backend
385 .expect_get_trust()
386 .withf(|_, id: &'_ str| id == "redelegated_trust")
387 .returning(|_, _| {
388 Ok(Some(Trust {
389 id: "redelegated_trust".into(),
390 redelegated_trust_id: Some("trust_id".into()),
391 ..Default::default()
392 }))
393 });
394 backend
395 .expect_get_trust_delegation_chain()
396 .withf(|_, id: &'_ str| id == "redelegated_trust")
397 .returning(|_, _| {
398 Ok(Some(vec![
399 Trust {
400 id: "redelegated_trust".into(),
401 redelegated_trust_id: Some("trust_id".into()),
402 ..Default::default()
403 },
404 Trust {
405 id: "trust_id".into(),
406 ..Default::default()
407 },
408 ]))
409 });
410
411 let trust_provider = TrustService {
412 backend_driver: Arc::new(backend),
413 };
414 let trust = trust_provider
415 .get_trust(&state, "redelegated_trust")
416 .await
417 .unwrap()
418 .expect("trust found");
419 trust_provider
420 .validate_trust_delegation_chain(&state, &trust)
421 .await
422 .unwrap();
423 }
424
425 #[tokio::test]
426 async fn test_validate_trust_delegation_chain_expiration() {
427 let mut role_mock = MockRoleProvider::default();
428 role_mock
429 .expect_list_roles()
430 .withf(|_, qp: &RoleListParameters| {
431 RoleListParameters {
432 domain_id: Some(None),
433 ..Default::default()
434 } == *qp
435 })
436 .returning(|_, _| Ok(Vec::new()));
437 let provider_builder = Provider::mocked_builder().mock_role(role_mock);
438 let state = get_mocked_state(None, Some(provider_builder));
439 let mut backend = MockTrustBackend::new();
440 backend
441 .expect_get_trust()
442 .withf(|_, id: &'_ str| id == "redelegated_trust2")
443 .returning(|_, _| {
444 Ok(Some(Trust {
445 id: "redelegated_trust2".into(),
446 redelegated_trust_id: Some("redelegated_trust1".into()),
447 ..Default::default()
448 }))
449 });
450 backend
451 .expect_get_trust_delegation_chain()
452 .withf(|_, id: &'_ str| id == "redelegated_trust2")
453 .returning(|_, _| {
454 Ok(Some(vec![
455 Trust {
456 id: "redelegated_trust2".into(),
457 redelegated_trust_id: Some("redelegated_trust1".into()),
458 expires_at: Some(DateTime::<Utc>::MAX_UTC),
459 ..Default::default()
460 },
461 Trust {
462 id: "redelegated_trust1".into(),
463 redelegated_trust_id: Some("trust_id".into()),
464 ..Default::default()
465 },
466 Trust {
467 id: "trust_id".into(),
468 expires_at: Some(Utc::now()),
469 ..Default::default()
470 },
471 ]))
472 });
473
474 let trust_provider = TrustService {
475 backend_driver: Arc::new(backend),
476 };
477 let trust = trust_provider
478 .get_trust(&state, "redelegated_trust2")
479 .await
480 .unwrap()
481 .expect("trust found");
482 if let Err(TrustProviderError::ExpirationImpossible) = trust_provider
483 .validate_trust_delegation_chain(&state, &trust)
484 .await
485 {
486 } else {
487 panic!("redelegated trust cannot expire later than the parent");
488 };
489 }
490
491 #[tokio::test]
492 async fn test_validate_trust_delegation_chain_no_new_roles() {
493 let mut role_mock = MockRoleProvider::default();
494 role_mock
495 .expect_list_roles()
496 .withf(|_, qp: &RoleListParameters| {
497 RoleListParameters {
498 domain_id: Some(None),
499 ..Default::default()
500 } == *qp
501 })
502 .returning(|_, _| Ok(Vec::new()));
503 let provider_builder = Provider::mocked_builder().mock_role(role_mock);
504 let state = get_mocked_state(None, Some(provider_builder));
505 let mut backend = MockTrustBackend::new();
506 backend
507 .expect_get_trust()
508 .withf(|_, id: &'_ str| id == "redelegated_trust")
509 .returning(|_, _| {
510 Ok(Some(Trust {
511 id: "redelegated_trust".into(),
512 redelegated_trust_id: Some("trust_id".into()),
513 ..Default::default()
514 }))
515 });
516 backend
517 .expect_get_trust_delegation_chain()
518 .withf(|_, id: &'_ str| id == "redelegated_trust")
519 .returning(|_, _| {
520 Ok(Some(vec![
521 Trust {
522 id: "redelegated_trust".into(),
523 redelegated_trust_id: Some("trust_id".into()),
524 roles: Some(vec![
525 RoleRef {
526 id: "rid1".into(),
527 name: None,
528 domain_id: None,
529 },
530 RoleRef {
531 id: "rid2".into(),
532 name: None,
533 domain_id: None,
534 },
535 ]),
536 ..Default::default()
537 },
538 Trust {
539 id: "trust_id".into(),
540 roles: Some(vec![RoleRef {
541 id: "rid1".into(),
542 name: None,
543 domain_id: None,
544 }]),
545 ..Default::default()
546 },
547 ]))
548 });
549
550 let trust_provider = TrustService {
551 backend_driver: Arc::new(backend),
552 };
553 let trust = trust_provider
554 .get_trust(&state, "redelegated_trust")
555 .await
556 .unwrap()
557 .expect("trust found");
558
559 if let Err(TrustProviderError::RedelegatedRolesNotAvailable) = trust_provider
560 .validate_trust_delegation_chain(&state, &trust)
561 .await
562 {
563 } else {
564 panic!("adding new roles on redelegation should be disallowed");
565 };
566 }
567
568 #[tokio::test]
569 async fn test_validate_trust_delegation_chain_impersonation() {
570 let mut role_mock = MockRoleProvider::default();
571 role_mock
572 .expect_list_roles()
573 .withf(|_, qp: &RoleListParameters| {
574 RoleListParameters {
575 domain_id: Some(None),
576 ..Default::default()
577 } == *qp
578 })
579 .returning(|_, _| Ok(Vec::new()));
580 let provider_builder = Provider::mocked_builder().mock_role(role_mock);
581 let state = get_mocked_state(None, Some(provider_builder));
582 let mut backend = MockTrustBackend::new();
583 backend
584 .expect_get_trust()
585 .withf(|_, id: &'_ str| id == "redelegated_trust2")
586 .returning(|_, _| {
587 Ok(Some(Trust {
588 id: "redelegated_trust2".into(),
589 redelegated_trust_id: Some("redelegated_trust1".into()),
590 ..Default::default()
591 }))
592 });
593 backend
594 .expect_get_trust_delegation_chain()
595 .withf(|_, id: &'_ str| id == "redelegated_trust2")
596 .returning(|_, _| {
597 Ok(Some(vec![
598 Trust {
599 id: "redelegated_trust2".into(),
600 redelegated_trust_id: Some("redelegated_trust1".into()),
601 ..Default::default()
602 },
603 Trust {
604 id: "redelegated_trust1".into(),
605 redelegated_trust_id: Some("trust_id".into()),
606 impersonation: true,
607 ..Default::default()
608 },
609 Trust {
610 id: "trust_id".into(),
611 impersonation: false,
612 ..Default::default()
613 },
614 ]))
615 });
616
617 let trust_provider = TrustService {
618 backend_driver: Arc::new(backend),
619 };
620 let trust = trust_provider
621 .get_trust(&state, "redelegated_trust2")
622 .await
623 .unwrap()
624 .expect("trust found");
625 match trust_provider
626 .validate_trust_delegation_chain(&state, &trust)
627 .await
628 {
629 Err(TrustProviderError::RedelegatedImpersonationNotAllowed) => {}
630 other => {
631 panic!(
632 "redelegated trust impersonation cannot be enabled, {:?}",
633 other
634 );
635 }
636 }
637 }
638
639 #[tokio::test]
640 async fn test_validate_trust_delegation_chain_deepness() {
641 let mut role_mock = MockRoleProvider::default();
642 role_mock
643 .expect_list_roles()
644 .withf(|_, qp: &RoleListParameters| {
645 RoleListParameters {
646 domain_id: Some(None),
647 ..Default::default()
648 } == *qp
649 })
650 .returning(|_, _| Ok(Vec::new()));
651 let provider_builder = Provider::mocked_builder().mock_role(role_mock);
652 let state = get_mocked_state(None, Some(provider_builder));
653 let mut backend = MockTrustBackend::new();
654 backend
655 .expect_get_trust()
656 .withf(|_, id: &'_ str| id == "redelegated_trust2")
657 .returning(|_, _| {
658 Ok(Some(Trust {
659 id: "redelegated_trust2".into(),
660 redelegated_trust_id: Some("redelegated_trust1".into()),
661 ..Default::default()
662 }))
663 });
664 backend
665 .expect_get_trust()
666 .withf(|_, id: &'_ str| id == "redelegated_trust_long")
667 .returning(|_, _| {
668 Ok(Some(Trust {
669 id: "redelegated_trust_long".into(),
670 redelegated_trust_id: Some("redelegated_trust2".into()),
671 ..Default::default()
672 }))
673 });
674 backend
675 .expect_get_trust_delegation_chain()
676 .withf(|_, id: &'_ str| id == "redelegated_trust2")
677 .returning(|_, _| {
678 Ok(Some(vec![
679 Trust {
680 id: "redelegated_trust2".into(),
681 redelegated_trust_id: Some("redelegated_trust1".into()),
682 redelegation_count: Some(4),
683 ..Default::default()
684 },
685 Trust {
686 id: "redelegated_trust1".into(),
687 redelegated_trust_id: Some("trust_id".into()),
688 ..Default::default()
689 },
690 Trust {
691 id: "trust_id".into(),
692 ..Default::default()
693 },
694 ]))
695 });
696
697 backend
698 .expect_get_trust_delegation_chain()
699 .withf(|_, id: &'_ str| id == "redelegated_trust_long")
700 .returning(|_, _| {
701 Ok(Some(vec![
702 Trust {
703 id: "redelegated_trust_long".into(),
704 redelegated_trust_id: Some("redelegated_trust2".into()),
705 ..Default::default()
706 },
707 Trust {
708 id: "redelegated_trust2".into(),
709 redelegated_trust_id: Some("redelegated_trust1".into()),
710 ..Default::default()
711 },
712 Trust {
713 id: "redelegated_trust1".into(),
714 redelegated_trust_id: Some("trust_id".into()),
715 ..Default::default()
716 },
717 Trust {
718 id: "trust_id".into(),
719 ..Default::default()
720 },
721 ]))
722 });
723
724 let trust_provider = TrustService {
725 backend_driver: Arc::new(backend),
726 };
727 let trust = trust_provider
728 .get_trust(&state, "redelegated_trust2")
729 .await
730 .unwrap()
731 .expect("trust found");
732 match trust_provider
733 .validate_trust_delegation_chain(&state, &trust)
734 .await
735 {
736 Err(TrustProviderError::RedelegationDeepnessExceed { .. }) => {}
737 other => {
738 panic!(
739 "redelegated trust redelegation_count exceeds limit, but {:?}",
740 other
741 );
742 }
743 }
744
745 let trust = trust_provider
746 .get_trust(&state, "redelegated_trust_long")
747 .await
748 .unwrap()
749 .expect("trust found");
750 match trust_provider
751 .validate_trust_delegation_chain(&state, &trust)
752 .await
753 {
754 Err(TrustProviderError::RedelegationDeepnessExceed { .. }) => {}
755 other => {
756 panic!("trust redelegation chain exceeds limit, but {:?}", other);
757 }
758 }
759 }
760
761 #[tokio::test]
762 async fn test_list_trusts() {
763 let mut role_mock = MockRoleProvider::default();
764 role_mock
765 .expect_list_roles()
766 .withf(|_, qp: &RoleListParameters| {
767 RoleListParameters {
768 domain_id: Some(None),
769 ..Default::default()
770 } == *qp
771 })
772 .returning(|_, _| Ok(Vec::new()));
773 let provider_builder = Provider::mocked_builder().mock_role(role_mock);
774 let state = get_mocked_state(None, Some(provider_builder));
775
776 let mut backend = MockTrustBackend::new();
777 backend
778 .expect_list_trusts()
779 .withf(|_, params: &TrustListParameters| *params == TrustListParameters::default())
780 .returning(|_, _| {
781 Ok(vec![
782 Trust {
783 id: "redelegated_trust".into(),
784 redelegated_trust_id: Some("trust_id".into()),
785 ..Default::default()
786 },
787 Trust {
788 id: "trust_id".into(),
789 ..Default::default()
790 },
791 ])
792 });
793
794 let trust_provider = TrustService {
795 backend_driver: Arc::new(backend),
796 };
797
798 let list = trust_provider
799 .list_trusts(&state, &TrustListParameters::default())
800 .await
801 .unwrap();
802 assert_eq!(list.len(), 2);
803 }
804}