Skip to main content

rocketmq_auth/
secret_provider.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//! Explicit registry and local development adapters for secret providers.
16
17mod encrypted_file;
18mod environment;
19
20use std::collections::BTreeMap;
21use std::fmt;
22use std::sync::Arc;
23
24use rocketmq_security_api::SecretProvider;
25use rocketmq_security_api::SecretProviderId;
26
27use crate::AuthFailureKind;
28use crate::AuthOperation;
29use crate::AuthServiceError;
30use crate::AuthServiceResult;
31
32pub use encrypted_file::EncryptedFileSecretProvider;
33pub use environment::EnvironmentSecretProvider;
34
35/// Explicit, composition-root-owned provider registry. It deliberately has no global singleton.
36#[derive(Default)]
37pub struct SecretProviderRegistry {
38    providers: BTreeMap<SecretProviderId, Arc<dyn SecretProvider>>,
39}
40
41impl SecretProviderRegistry {
42    pub fn new() -> Self {
43        Self::default()
44    }
45
46    /// Registers one injected provider and rejects identifier replacement.
47    ///
48    /// # Errors
49    ///
50    /// Returns a redacted conflict when the identifier is already present.
51    pub fn register(&mut self, provider: Arc<dyn SecretProvider>) -> AuthServiceResult<()> {
52        let id = provider.id().clone();
53        if self.providers.contains_key(&id) {
54            return Err(AuthServiceError::new(
55                AuthOperation::LoadSecret,
56                AuthFailureKind::Conflict,
57            ));
58        }
59        self.providers.insert(id, provider);
60        Ok(())
61    }
62
63    /// Resolves an explicitly selected provider without falling back to another implementation.
64    ///
65    /// # Errors
66    ///
67    /// Returns a redacted not-found failure when no exact identifier is present.
68    pub fn provider(&self, id: &SecretProviderId) -> AuthServiceResult<&Arc<dyn SecretProvider>> {
69        self.providers
70            .get(id)
71            .ok_or_else(|| AuthServiceError::new(AuthOperation::LoadSecret, AuthFailureKind::NotFound))
72    }
73
74    pub fn len(&self) -> usize {
75        self.providers.len()
76    }
77
78    pub fn is_empty(&self) -> bool {
79        self.providers.is_empty()
80    }
81}
82
83impl fmt::Debug for SecretProviderRegistry {
84    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85        f.debug_struct("SecretProviderRegistry")
86            .field("provider_ids", &self.providers.keys().collect::<Vec<_>>())
87            .finish()
88    }
89}