openstack_keystone_core/federation/
service.rs1use async_trait::async_trait;
19use std::sync::Arc;
20use uuid::Uuid;
21
22use crate::config::Config;
23use crate::federation::{FederationProviderError, backend::FederationBackend, types::*};
24use crate::keystone::ServiceState;
25use crate::plugin_manager::PluginManagerApi;
26
27pub struct FederationService {
28 backend_driver: Arc<dyn FederationBackend>,
29}
30
31impl FederationService {
32 pub fn new<P: PluginManagerApi>(
33 config: &Config,
34 plugin_manager: &P,
35 ) -> Result<Self, FederationProviderError> {
36 let backend_driver = plugin_manager
37 .get_federation_backend(config.federation.driver.clone())?
38 .clone();
39 Ok(Self { backend_driver })
40 }
41}
42
43#[async_trait]
44impl FederationApi for FederationService {
45 #[tracing::instrument(level = "info", skip(self, state))]
47 async fn cleanup(&self, state: &ServiceState) -> Result<(), FederationProviderError> {
48 self.backend_driver.cleanup(state).await
49 }
50
51 #[tracing::instrument(level = "debug", skip(self, state))]
53 async fn create_auth_state(
54 &self,
55 state: &ServiceState,
56 auth_state: AuthState,
57 ) -> Result<AuthState, FederationProviderError> {
58 self.backend_driver
59 .create_auth_state(state, auth_state)
60 .await
61 }
62
63 #[tracing::instrument(level = "debug", skip(self, state))]
65 async fn create_identity_provider(
66 &self,
67 state: &ServiceState,
68 idp: IdentityProviderCreate,
69 ) -> Result<IdentityProvider, FederationProviderError> {
70 let mut mod_idp = idp;
71 if mod_idp.id.is_none() {
72 mod_idp.id = Some(Uuid::new_v4().simple().to_string());
73 }
74
75 self.backend_driver
76 .create_identity_provider(state, mod_idp)
77 .await
78 }
79
80 #[tracing::instrument(level = "debug", skip(self, state))]
82 async fn create_mapping(
83 &self,
84 state: &ServiceState,
85 mapping: Mapping,
86 ) -> Result<Mapping, FederationProviderError> {
87 let mut mod_mapping = mapping;
88 mod_mapping.id = Uuid::new_v4().into();
89 if let Some(_pid) = &mod_mapping.token_project_id {
90 if let Some(_did) = &mod_mapping.domain_id {
92 } else {
94 return Err(FederationProviderError::MappingTokenProjectDomainUnset);
95 }
96 }
98
99 self.backend_driver.create_mapping(state, mod_mapping).await
100 }
101
102 #[tracing::instrument(level = "debug", skip(self, state))]
104 async fn delete_auth_state<'a>(
105 &self,
106 state: &ServiceState,
107 id: &'a str,
108 ) -> Result<(), FederationProviderError> {
109 self.backend_driver.delete_auth_state(state, id).await
110 }
111
112 #[tracing::instrument(level = "debug", skip(self, state))]
114 async fn delete_identity_provider<'a>(
115 &self,
116 state: &ServiceState,
117 id: &'a str,
118 ) -> Result<(), FederationProviderError> {
119 self.backend_driver
120 .delete_identity_provider(state, id)
121 .await
122 }
123
124 #[tracing::instrument(level = "debug", skip(self, state))]
126 async fn delete_mapping<'a>(
127 &self,
128 state: &ServiceState,
129 id: &'a str,
130 ) -> Result<(), FederationProviderError> {
131 self.backend_driver.delete_mapping(state, id).await
132 }
133
134 #[tracing::instrument(level = "debug", skip(self, state))]
136 async fn get_auth_state<'a>(
137 &self,
138 state: &ServiceState,
139 id: &'a str,
140 ) -> Result<Option<AuthState>, FederationProviderError> {
141 self.backend_driver.get_auth_state(state, id).await
142 }
143
144 #[tracing::instrument(level = "info", skip(self, state))]
146 async fn get_identity_provider<'a>(
147 &self,
148 state: &ServiceState,
149 id: &'a str,
150 ) -> Result<Option<IdentityProvider>, FederationProviderError> {
151 self.backend_driver.get_identity_provider(state, id).await
152 }
153
154 #[tracing::instrument(level = "info", skip(self, state))]
156 async fn get_mapping<'a>(
157 &self,
158 state: &ServiceState,
159 id: &'a str,
160 ) -> Result<Option<Mapping>, FederationProviderError> {
161 self.backend_driver.get_mapping(state, id).await
162 }
163
164 #[tracing::instrument(level = "info", skip(self, state))]
166 async fn list_identity_providers(
167 &self,
168 state: &ServiceState,
169 params: &IdentityProviderListParameters,
170 ) -> Result<Vec<IdentityProvider>, FederationProviderError> {
171 self.backend_driver
172 .list_identity_providers(state, params)
173 .await
174 }
175
176 #[tracing::instrument(level = "info", skip(self, state))]
178 async fn list_mappings(
179 &self,
180 state: &ServiceState,
181 params: &MappingListParameters,
182 ) -> Result<Vec<Mapping>, FederationProviderError> {
183 self.backend_driver.list_mappings(state, params).await
184 }
185
186 #[tracing::instrument(level = "debug", skip(self, state))]
188 async fn update_identity_provider<'a>(
189 &self,
190 state: &ServiceState,
191 id: &'a str,
192 idp: IdentityProviderUpdate,
193 ) -> Result<IdentityProvider, FederationProviderError> {
194 self.backend_driver
195 .update_identity_provider(state, id, idp)
196 .await
197 }
198
199 #[tracing::instrument(level = "debug", skip(self, state))]
201 async fn update_mapping<'a>(
202 &self,
203 state: &ServiceState,
204 id: &'a str,
205 mapping: MappingUpdate,
206 ) -> Result<Mapping, FederationProviderError> {
207 let current = self
208 .backend_driver
209 .get_mapping(state, id)
210 .await?
211 .ok_or_else(|| FederationProviderError::MappingNotFound(id.to_string()))?;
212
213 if let Some(_new_idp_id) = &mapping.idp_id {
214 }
216
217 if let Some(_pid) = &mapping.token_project_id {
218 if let Some(_did) = ¤t.domain_id {
220 } else {
222 return Err(FederationProviderError::MappingTokenProjectDomainUnset);
223 }
224 }
226 self.backend_driver.update_mapping(state, id, mapping).await
228 }
229}