Skip to main content

rocketmq_auth/authentication/manager/
authentication_metadata_manager_impl.rs

1// Copyright 2023 The RocketMQ Rust Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Authentication metadata manager implementation.
16//!
17//! This module provides the default implementation of `AuthenticationMetadataManager`,
18//! coordinating authentication and authorization metadata providers.
19
20use std::sync::Arc;
21
22use rocketmq_error::RocketMQError;
23use tokio::sync::RwLock;
24use tracing::info;
25use tracing::warn;
26
27use super::authentication_metadata_manager::AuthenticationMetadataManager;
28use super::authentication_metadata_manager::ManagerResult;
29use crate::authentication::enums::user_status::UserStatus;
30use crate::authentication::enums::user_type::UserType;
31use crate::authentication::model::user::User;
32use crate::authentication::provider::AuthenticationMetadataProvider;
33use crate::authorization::metadata_provider::AuthorizationMetadataProvider;
34use crate::config::AuthConfig;
35
36/// Default implementation of `AuthenticationMetadataManager`.
37///
38/// This implementation coordinates between:
39/// - `AuthenticationMetadataProvider` - For user CRUD operations
40/// - `AuthorizationMetadataProvider` - For ACL operations (optional)
41///
42/// # Concurrency
43///
44/// Thread-safe through `Arc<RwLock<>>` for mutable provider references.
45/// Read operations acquire read locks, write operations acquire write locks.
46pub struct AuthenticationMetadataManagerImpl<A, B>
47where
48    A: AuthenticationMetadataProvider + 'static,
49    B: AuthorizationMetadataProvider + 'static,
50{
51    /// Authentication metadata provider for user operations.
52    authentication_metadata_provider: Arc<RwLock<Option<A>>>,
53
54    /// Authorization metadata provider for ACL operations (optional).
55    authorization_metadata_provider: Arc<RwLock<Option<B>>>,
56}
57
58impl<A, B> AuthenticationMetadataManagerImpl<A, B>
59where
60    A: AuthenticationMetadataProvider,
61    B: AuthorizationMetadataProvider,
62{
63    /// Create a new authentication metadata manager.
64    ///
65    /// # Arguments
66    ///
67    /// * `auth_provider` - Authentication metadata provider
68    /// * `authz_provider` - Authorization metadata provider (optional)
69    ///
70    /// # Example
71    ///
72    /// ```rust,ignore
73    /// let auth_provider = LocalAuthenticationMetadataProvider::new();
74    /// let authz_provider = Some(LocalAuthorizationMetadataProvider::new());
75    /// let manager = AuthenticationMetadataManagerImpl::new(auth_provider, authz_provider);
76    /// ```
77    pub fn new(auth_provider: Option<A>, authz_provider: Option<B>) -> Self {
78        Self {
79            authentication_metadata_provider: Arc::new(RwLock::new(auth_provider)),
80            authorization_metadata_provider: Arc::new(RwLock::new(authz_provider)),
81        }
82    }
83
84    /// Set the authentication metadata provider.
85    pub async fn set_authentication_provider(&self, provider: A) {
86        let mut guard = self.authentication_metadata_provider.write().await;
87        *guard = Some(provider);
88    }
89
90    /// Set the authorization metadata provider.
91    pub async fn set_authorization_provider(&self, provider: B) {
92        let mut guard = self.authorization_metadata_provider.write().await;
93        *guard = Some(provider);
94    }
95
96    /// Validate user for creation.
97    ///
98    /// # Validation Rules
99    ///
100    /// - Username must not be blank
101    /// - Password must not be blank (for create operation)
102    /// - User type must be set (for create operation)
103    fn validate_user(&self, user: &User, is_create: bool) -> ManagerResult<()> {
104        // Validate username
105        if user.username().is_empty() {
106            return Err(RocketMQError::authentication_failed("username can not be blank"));
107        }
108
109        // Validate password (required for creation)
110        if is_create && user.password().is_none() {
111            return Err(RocketMQError::authentication_failed("password can not be blank"));
112        }
113
114        // Validate user type (required for creation, optional for update)
115        if is_create && user.user_type().is_none() {
116            return Err(RocketMQError::authentication_failed("userType can not be blank"));
117        }
118
119        Ok(())
120    }
121
122    /// Handle exceptions from provider operations.
123    ///
124    /// Converts provider exceptions into consistent RocketMQError types.
125    fn handle_exception(&self, error: RocketMQError) -> RocketMQError {
126        // Log the error
127        warn!("Authentication metadata manager operation failed: {}", error);
128
129        // For now, just pass through the error
130        // In production, you might want to map specific error types
131        error
132    }
133
134    /// Initialize user from string (supports both JSON and "username:password" format)
135    async fn init_user_from_string(&self, init_user_str: &str, provider: &A) -> ManagerResult<()> {
136        // Try to parse as JSON first
137        if init_user_str.trim().starts_with('{') {
138            // JSON format - try to parse as User
139            if let Ok(mut user) = serde_json::from_str::<User>(init_user_str) {
140                user.set_user_type(UserType::Super);
141                self.create_user_if_not_exists(user, provider).await?;
142                return Ok(());
143            }
144            warn!("Failed to parse init_authentication_user as JSON, trying simple format");
145        }
146
147        // Fall back to "username:password" format
148        let parts: Vec<&str> = init_user_str.splitn(2, ':').collect();
149        if parts.len() != 2 {
150            warn!(
151                "Invalid init_authentication_user format: '{}'. Expected 'username:password' or JSON",
152                init_user_str
153            );
154            return Ok(()); // Don't fail initialization
155        }
156
157        let username = parts[0].trim();
158        let password = parts[1].trim();
159
160        if !username.is_empty() && !password.is_empty() {
161            let mut user = User::of_with_type(username, password, UserType::Super);
162            user.set_user_status(UserStatus::Enable);
163            self.create_user_if_not_exists(user, provider).await?;
164        }
165
166        Ok(())
167    }
168
169    /// Initialize inner client user from SessionCredentials format
170    async fn init_inner_client_user(&self, credentials_str: &str, provider: &A) -> ManagerResult<()> {
171        // Try to parse as JSON with accessKey and secretKey fields
172        #[derive(serde::Deserialize)]
173        struct SessionCredentials {
174            #[serde(rename = "accessKey")]
175            access_key: String,
176            #[serde(rename = "secretKey")]
177            secret_key: String,
178        }
179
180        match serde_json::from_str::<SessionCredentials>(credentials_str) {
181            Ok(credentials) => {
182                let mut user = User::of_with_type(credentials.access_key, credentials.secret_key, UserType::Super);
183                user.set_user_status(UserStatus::Enable);
184                self.create_user_if_not_exists(user, provider).await?;
185            }
186            Err(e) => {
187                warn!("Failed to parse inner_client_authentication_credentials: {}", e);
188            }
189        }
190
191        Ok(())
192    }
193
194    /// Create user if it doesn't exist
195    async fn create_user_if_not_exists(&self, user: User, provider: &A) -> ManagerResult<()> {
196        match provider.get_user(user.username().as_str()).await {
197            Ok(_existing) => {
198                info!("User '{}' already exists, skipping creation", user.username());
199                Ok(())
200            }
201            Err(_) => {
202                provider.create_user(user.clone()).await?;
203                info!("Created super user '{}'", user.username());
204                Ok(())
205            }
206        }
207    }
208}
209
210#[allow(async_fn_in_trait)]
211impl<A, B> AuthenticationMetadataManager for AuthenticationMetadataManagerImpl<A, B>
212where
213    A: AuthenticationMetadataProvider,
214    B: AuthorizationMetadataProvider,
215{
216    async fn shutdown(&mut self) -> ManagerResult<()> {
217        info!("Shutting down authentication metadata manager");
218
219        // Shutdown authentication provider
220        let mut auth_guard = self.authentication_metadata_provider.write().await;
221        if let Some(mut provider) = auth_guard.take() {
222            let _ = provider.shutdown().await; // Ignore shutdown errors in cleanup
223        }
224
225        // Shutdown authorization provider
226        let mut authz_guard = self.authorization_metadata_provider.write().await;
227        if let Some(mut provider) = authz_guard.take() {
228            provider.shutdown(); // AuthorizationMetadataProvider::shutdown is synchronous
229        }
230
231        info!("Authentication metadata manager shutdown complete");
232        Ok(())
233    }
234
235    async fn init_user(&self, auth_config: &AuthConfig) -> ManagerResult<()> {
236        info!("Initializing default super user from configuration");
237
238        let guard = self.authentication_metadata_provider.read().await;
239        let provider = match &*guard {
240            Some(p) => p,
241            None => {
242                return Err(RocketMQError::not_initialized(
243                    "Authentication metadata provider is not configured",
244                ));
245            }
246        };
247
248        // 1. Handle init_authentication_user (JSON format or simple "username:password")
249        let init_user_str = auth_config.init_authentication_user.as_str();
250        if !init_user_str.is_empty() {
251            self.init_user_from_string(init_user_str, provider).await?;
252        }
253
254        // 2. Handle inner_client_authentication_credentials (SessionCredentials format)
255        let inner_credentials = auth_config.inner_client_authentication_credentials.as_str();
256        if !inner_credentials.is_empty() {
257            self.init_inner_client_user(inner_credentials, provider).await?;
258        }
259
260        Ok(())
261    }
262
263    async fn create_user(&self, user: User) -> ManagerResult<()> {
264        // Validate user input
265        self.validate_user(&user, true)?;
266
267        let guard = self.authentication_metadata_provider.read().await;
268        let provider = match &*guard {
269            Some(p) => p,
270            None => {
271                return Err(RocketMQError::not_initialized(
272                    "Authentication metadata provider is not configured",
273                ));
274            }
275        };
276
277        // Check if user already exists
278        if let Ok(_existing) = provider.get_user(user.username().as_str()).await {
279            return Err(RocketMQError::authentication_failed("The user already exists"));
280        }
281
282        // Set default values if not provided
283        let mut user_to_create = user.clone();
284        if user_to_create.user_type().is_none() {
285            user_to_create.set_user_type(UserType::Normal);
286        }
287        if user_to_create.user_status().is_none() {
288            user_to_create.set_user_status(UserStatus::Enable);
289        }
290
291        provider
292            .create_user(user_to_create)
293            .await
294            .map_err(|e| self.handle_exception(e))?;
295
296        info!("User '{}' created successfully", user.username());
297        Ok(())
298    }
299
300    async fn update_user(&self, user: User) -> ManagerResult<()> {
301        // Validate user input (password not required for update)
302        self.validate_user(&user, false)?;
303
304        let guard = self.authentication_metadata_provider.read().await;
305        let provider = match &*guard {
306            Some(p) => p,
307            None => {
308                return Err(RocketMQError::not_initialized(
309                    "Authentication metadata provider is not configured",
310                ));
311            }
312        };
313
314        // Get existing user first
315        let existing_user = provider
316            .get_user(user.username().as_str())
317            .await
318            .map_err(|_| RocketMQError::authentication_failed("The user does not exist"))?;
319
320        // Merge fields: update only provided fields
321        let mut updated_user = existing_user.clone();
322
323        // Update password if provided
324        if let Some(new_password) = user.password() {
325            updated_user.set_password(new_password.clone());
326        }
327
328        // Update user type if provided
329        if let Some(new_type) = user.user_type() {
330            updated_user.set_user_type(new_type);
331        }
332
333        // Update user status if provided
334        if let Some(new_status) = user.user_status() {
335            updated_user.set_user_status(new_status);
336        }
337
338        provider
339            .update_user(updated_user)
340            .await
341            .map_err(|e| self.handle_exception(e))?;
342
343        info!("User '{}' updated successfully", user.username());
344        Ok(())
345    }
346
347    async fn delete_user(&self, username: &str) -> ManagerResult<()> {
348        if username.is_empty() {
349            return Err(RocketMQError::authentication_failed("username can not be blank"));
350        }
351
352        let auth_guard = self.authentication_metadata_provider.read().await;
353        let auth_provider = match &*auth_guard {
354            Some(p) => p,
355            None => {
356                return Err(RocketMQError::not_initialized(
357                    "Authentication metadata provider is not configured",
358                ));
359            }
360        };
361
362        // Delete user from authentication provider
363        let delete_user_result = auth_provider
364            .delete_user(username)
365            .await
366            .map_err(|e| self.handle_exception(e));
367
368        // Also delete related ACLs from authorization provider
369        let authz_guard = self.authorization_metadata_provider.read().await;
370        if let Some(authz_provider) = &*authz_guard {
371            let user = User::of(username);
372            let _ = authz_provider.delete_acl(&user).await; // Ignore ACL deletion errors
373        }
374
375        delete_user_result?;
376        info!("User '{}' and related ACLs deleted successfully", username);
377        Ok(())
378    }
379
380    async fn get_user(&self, username: &str) -> ManagerResult<User> {
381        if username.is_empty() {
382            return Err(RocketMQError::authentication_failed("username can not be blank"));
383        }
384
385        let guard = self.authentication_metadata_provider.read().await;
386        let provider = match &*guard {
387            Some(p) => p,
388            None => {
389                return Err(RocketMQError::not_initialized(
390                    "Authentication metadata provider is not configured",
391                ));
392            }
393        };
394
395        provider.get_user(username).await.map_err(|e| self.handle_exception(e))
396    }
397
398    async fn list_users(&self, filter: Option<&str>) -> ManagerResult<Vec<User>> {
399        let guard = self.authentication_metadata_provider.read().await;
400        let provider = match &*guard {
401            Some(p) => p,
402            None => {
403                return Err(RocketMQError::not_initialized(
404                    "Authentication metadata provider is not configured",
405                ));
406            }
407        };
408
409        provider.list_user(filter).await.map_err(|e| self.handle_exception(e))
410    }
411
412    async fn is_super_user(&self, username: &str) -> ManagerResult<bool> {
413        if username.is_empty() {
414            return Ok(false);
415        }
416
417        match self.get_user(username).await {
418            Ok(user) => Ok(matches!(user.user_type(), Some(UserType::Super))),
419            Err(_) => Ok(false), // User not found = not super user
420        }
421    }
422}
423
424impl<A, B> Default for AuthenticationMetadataManagerImpl<A, B>
425where
426    A: AuthenticationMetadataProvider,
427    B: AuthorizationMetadataProvider,
428{
429    fn default() -> Self {
430        Self::new(None, None)
431    }
432}
433
434#[cfg(test)]
435mod tests {
436    use super::*;
437    use crate::authentication::provider::local_authentication_metadata_provider::LocalAuthenticationMetadataProvider;
438    use crate::authorization::metadata_provider::local::LocalAuthorizationMetadataProvider;
439
440    #[tokio::test]
441    async fn test_manager_creation() {
442        let manager = AuthenticationMetadataManagerImpl::<
443            LocalAuthenticationMetadataProvider,
444            LocalAuthorizationMetadataProvider,
445        >::default();
446
447        // Manager should be created successfully
448        assert!(manager.authentication_metadata_provider.read().await.is_none());
449    }
450
451    #[tokio::test]
452    async fn test_validate_user_creation() {
453        let manager = AuthenticationMetadataManagerImpl::<
454            LocalAuthenticationMetadataProvider,
455            LocalAuthorizationMetadataProvider,
456        >::default();
457
458        // Valid user
459        let user = User::of_with_type("test_user", "password", UserType::Normal);
460        assert!(manager.validate_user(&user, true).is_ok());
461
462        // Invalid: empty username
463        let user = User::of_with_type("", "password", UserType::Normal);
464        assert!(manager.validate_user(&user, true).is_err());
465
466        // Invalid: missing password for creation
467        let mut user = User::of("test_user");
468        user.set_user_type(UserType::Normal);
469        assert!(manager.validate_user(&user, true).is_err());
470    }
471
472    #[tokio::test]
473    async fn test_is_super_user_with_empty_username() {
474        let manager = AuthenticationMetadataManagerImpl::<
475            LocalAuthenticationMetadataProvider,
476            LocalAuthorizationMetadataProvider,
477        >::default();
478
479        let result = manager.is_super_user("").await.unwrap();
480        assert!(!result);
481    }
482}