1mod acl;
16mod authentication;
17mod authorization;
18mod bootstrap;
19mod config;
20mod credential_rotation;
21mod error;
22mod layered_authorization;
23mod maintenance;
24mod metadata_snapshot;
25mod migration;
26mod permission;
27mod provider_owner;
28mod provider_ports;
29mod remoting_auth_context;
30mod runtime;
31mod secret_provider;
32mod security_api {
34 pub use rocketmq_security_api::*;
35}
36pub(crate) mod runtime_bridge;
37
38pub use authentication::acl_signer::cal_signature;
40pub use authentication::acl_signer::cal_signature_segments;
41pub use authentication::acl_signer::cal_signature_segments_with_algorithm;
42pub use authentication::acl_signer::cal_signature_with_algorithm;
43pub use authentication::acl_signer::SignatureAlgorithm;
44pub use authentication::acl_signer::DEFAULT_CHARSET;
45pub use authentication::builder::AuthenticationContextBuilder;
46pub use authentication::builder::DefaultAuthenticationContextBuilder;
47pub use authentication::context::default_authentication_context::DefaultAuthenticationContext;
48pub use authentication::enums::subject_type::SubjectType;
49pub use authentication::enums::user_status::UserStatus;
50pub use authentication::enums::user_type::UserType;
51pub use authentication::evaluator::AuthenticationEvaluator;
52pub use authentication::factory::AuthenticationFactory;
53pub use authentication::manager::AuthenticationMetadataManager;
54pub use authentication::manager::AuthenticationMetadataManagerImpl;
55pub use authentication::model::subject::Subject;
56pub use authentication::model::user::User;
57pub use authentication::provider::AuthenticationMetadataProvider;
58pub use authentication::provider::AuthenticationProvider;
59pub use authentication::provider::DefaultAuthenticationProvider;
60pub use authentication::provider::LocalAuthenticationMetadataProvider;
61pub use authentication::strategy::AllowAllAuthenticationStrategy;
62pub use authentication::strategy::AuthenticationFuture;
63pub use authentication::strategy::AuthenticationStrategy;
64pub use authentication::strategy::StatefulAuthenticationStrategy;
65pub use authentication::strategy::StatelessAuthenticationStrategy;
66pub use authentication::AclClientRpcHook;
67
68pub use acl::FileAclConfigStore;
70pub use acl::WhiteList;
71pub use authorization::chain::AclAuthorizationHandler;
72pub use authorization::chain::AuthorizationHandler;
73pub use authorization::chain::AuthorizationHandlerChain;
74pub use authorization::context::authentication_context::AuthenticationContext;
75pub use authorization::context::default_authorization_context::DefaultAuthorizationContext;
76pub use authorization::enums::decision::Decision as PolicyDecision;
78pub use authorization::enums::policy_type::PolicyType;
79pub use authorization::evaluator::AuthorizationEvaluator;
80pub use authorization::factory::AuthorizationFactory;
81pub use authorization::manager::metadata_manager::AuthorizationMetadataManager;
82pub use authorization::manager::AuthorizationMetadataManagerImpl;
83pub use authorization::metadata_provider::AuthorizationMetadataProvider;
84pub use authorization::metadata_provider::LocalAuthorizationMetadataProvider;
85pub use authorization::metadata_provider::NoopMetadataProvider;
86pub use authorization::model::acl::Acl;
87pub use authorization::model::environment::Environment;
88pub use authorization::model::policy::Policy;
89pub use authorization::model::policy_entry::PolicyEntry;
90pub use authorization::model::request_context::RequestContext as AuthorizationRequest;
92pub use authorization::model::request_context::RequestContext;
94pub use authorization::model::resource::Resource as PolicyResource;
96pub use authorization::model::resource::Resource;
98pub use authorization::provider::AuthorizationProvider;
99pub use authorization::provider::DefaultAuthorizationProvider;
100pub use authorization::strategy::abstract_authorization_strategy::AuthorizationStrategy;
101pub use authorization::strategy::StatefulAuthorizationStrategy;
102pub use authorization::strategy::StatelessAuthorizationStrategy;
103#[doc(hidden)]
104pub use bench_support::AuthAclWatcherLifecycleProbe;
105pub use bootstrap::BootstrapAdminIdentity;
106pub use bootstrap::BootstrapAdminProvisioner;
107pub use bootstrap::BootstrapEnrollmentRequest;
108pub use bootstrap::BootstrapEnrollmentResult;
109pub use bootstrap::BootstrapGrant;
110pub use bootstrap::BootstrapStatus;
111pub use bootstrap::BootstrapTransportContext;
112pub use bootstrap::OneTimeBootstrap;
113pub use config::AuthConfig;
114pub use credential_rotation::BreakGlassReason;
115pub use credential_rotation::BreakGlassStatus;
116pub use credential_rotation::CredentialAuditAction;
117pub use credential_rotation::CredentialAuditEvent;
118pub use credential_rotation::CredentialAuditOutcome;
119pub use credential_rotation::CredentialAuditSink;
120pub use credential_rotation::CredentialBundleParser;
121pub use credential_rotation::CredentialDescriptor;
122pub use credential_rotation::CredentialId;
123pub use credential_rotation::CredentialRotationManager;
124pub use credential_rotation::CredentialRotationSnapshot;
125pub use credential_rotation::CredentialVerification;
126pub use credential_rotation::CredentialVerificationSource;
127pub use credential_rotation::RetiringCredentialSnapshot;
128pub use credential_rotation::ValidatedCredential;
129pub use error::AuthFailureKind;
130pub use error::AuthOperation;
131pub use error::AuthServiceError;
132pub use error::AuthServiceResult;
133pub use layered_authorization::project_authorization_error;
134pub use layered_authorization::project_policy_decision;
135pub use maintenance::LoadedMaintenancePolicy;
136pub use maintenance::MaintenancePolicyReference;
137pub use permission::Permission;
138pub use provider_owner::AclImportAccount;
139pub use provider_owner::AclMetadataHandle;
140pub use provider_owner::AclSnapshotImport;
141pub use provider_owner::ProviderBundle;
142pub use provider_owner::ProviderCleanupErrors;
143pub use provider_owner::ProviderControl;
144pub use provider_owner::ProviderOperation as AuthRequestGuard;
145pub use provider_owner::UserMetadataHandle;
146pub use provider_ports::AclMetadataPort;
147pub use provider_ports::AclMetadataRead;
148pub use provider_ports::ProviderFuture;
149pub use provider_ports::SubjectKey;
150pub use provider_ports::UserMetadataPort;
151pub use provider_ports::UserMetadataRead;
152pub use remoting_auth_context::RemotingAuthContext;
153pub use rocketmq_observability::metrics::auth::AuthMetricSample;
154pub use rocketmq_observability::metrics::auth::AuthMetrics;
155pub use rocketmq_observability::metrics::auth::AuthMetricsSnapshot;
156pub use rocketmq_security_api::AuthorizationDecision;
157pub use rocketmq_security_api::AuthorizationDenial;
158pub use runtime::AuthRuntime;
159pub use runtime::AuthRuntimeBuilder;
160pub use runtime::AuthStartupFailure;
161pub use runtime::AuthenticationService;
162pub use runtime::AuthorizationService;
163pub use runtime::ProviderRegistry;
164pub use secret_provider::EncryptedFileSecretProvider;
165pub use secret_provider::EnvironmentSecretProvider;
166pub use secret_provider::SecretProviderRegistry;
167#[deprecated(
168 since = "1.1.0",
169 note = "use rocketmq_security_api::Principal; removal is intended for a future 2.0 boundary and remains subject to compatibility, migration, and release gates"
170)]
171pub use security_api::Principal as SecurityPrincipal;
172#[deprecated(
173 since = "1.1.0",
174 note = "use rocketmq_security_api::Resource; removal is intended for a future 2.0 boundary and remains subject to compatibility, migration, and release gates"
175)]
176pub use security_api::Resource as SecurityResource;
177
178#[doc(hidden)]
179pub mod bench_support {
180 use std::fs;
181 use std::path::PathBuf;
182 use std::sync::atomic::AtomicU64;
183 use std::sync::atomic::Ordering;
184 use std::time::Duration;
185 use std::time::Instant;
186
187 use cheetah_string::CheetahString;
188 use rocketmq_runtime::ChildServiceContext;
189 use rocketmq_runtime::ShutdownReport;
190 use serde::Serialize;
191
192 use crate::config::AuthConfig;
193 use crate::runtime::AuthRuntimeBuilder;
194 use crate::AuthFailureKind;
195 use crate::AuthServiceError;
196 use crate::AuthServiceResult;
197
198 static NEXT_ACL_WATCHER_PROBE_ID: AtomicU64 = AtomicU64::new(0);
199
200 #[derive(Clone, Debug, Serialize)]
201 pub struct AuthAclWatcherLifecycleProbe {
202 pub scheduled_runs: u64,
203 pub scheduled_skips: u64,
204 pub scheduled_overlaps: u64,
205 pub scheduled_failures: u64,
206 pub reload_success: bool,
207 pub shutdown_elapsed_us: u128,
208 pub shutdown_report: Option<ShutdownReport>,
209 pub healthy: bool,
210 }
211
212 pub async fn run_auth_acl_watcher_lifecycle_probe(
213 service_context: ChildServiceContext,
214 ) -> AuthServiceResult<AuthAclWatcherLifecycleProbe> {
215 let root = unique_acl_watcher_probe_root();
216 let _ = fs::remove_dir_all(&root);
217 fs::create_dir_all(&root).map_err(AuthServiceError::storage_write_failed)?;
218 let acl_file = root.join("plain_acl.yml");
219 write_acl_file(&acl_file, "first")?;
220
221 let runtime = AuthRuntimeBuilder::new(
222 AuthConfig {
223 acl_file: CheetahString::from(acl_file.to_string_lossy().as_ref()),
224 acl_file_watch_enabled: true,
225 acl_file_watch_interval_millis: 5,
226 ..AuthConfig::default()
227 },
228 service_context,
229 )
230 .build()
231 .await?;
232 let authn_provider = runtime.provider_registry().authentication_metadata_provider();
233 write_acl_file(&acl_file, "second")?;
234
235 let deadline = Instant::now() + Duration::from_secs(2);
236 let reload_success = loop {
237 match authn_provider.get_user("alice").await {
238 Ok(user) if user.password().map(|value| value.as_str()) == Some("second") => {
239 break true;
240 }
241 Ok(_) => {}
242 Err(error) if error.kind() == AuthFailureKind::NotFound => {}
243 Err(error) => return Err(error),
244 }
245 if Instant::now() >= deadline {
246 break false;
247 }
248 tokio::time::sleep(Duration::from_millis(5)).await;
249 };
250
251 let mut snapshots = runtime.acl_file_watcher_snapshot();
252 for _ in 0..50 {
253 if snapshots
254 .iter()
255 .any(|snapshot| snapshot.runs > 0 && snapshot.active_runs == 0)
256 {
257 break;
258 }
259 tokio::time::sleep(Duration::from_millis(1)).await;
260 snapshots = runtime.acl_file_watcher_snapshot();
261 }
262 let scheduled_runs = snapshots.iter().map(|snapshot| snapshot.runs).sum();
263 let scheduled_skips = snapshots.iter().map(|snapshot| snapshot.skips).sum();
264 let scheduled_overlaps = snapshots.iter().map(|snapshot| snapshot.overlaps).sum();
265 let scheduled_failures = snapshots.iter().map(|snapshot| snapshot.failures).sum();
266
267 let shutdown_started_at = Instant::now();
268 let shutdown_report = runtime.shutdown_with_report().await?;
269 let shutdown_elapsed_us = shutdown_started_at.elapsed().as_micros();
270 let shutdown_healthy = shutdown_report
271 .as_ref()
272 .map(ShutdownReport::is_healthy)
273 .unwrap_or(false);
274 let healthy = reload_success
275 && scheduled_runs > 0
276 && scheduled_overlaps == 0
277 && scheduled_failures == 0
278 && shutdown_healthy;
279
280 let _ = fs::remove_dir_all(root);
281 Ok(AuthAclWatcherLifecycleProbe {
282 scheduled_runs,
283 scheduled_skips,
284 scheduled_overlaps,
285 scheduled_failures,
286 reload_success,
287 shutdown_elapsed_us,
288 shutdown_report,
289 healthy,
290 })
291 }
292
293 fn unique_acl_watcher_probe_root() -> PathBuf {
294 let id = NEXT_ACL_WATCHER_PROBE_ID.fetch_add(1, Ordering::Relaxed);
295 std::env::temp_dir().join(format!("rocketmq-auth-acl-watcher-{}-{id}", std::process::id()))
296 }
297
298 fn write_acl_file(path: &std::path::Path, secret: &str) -> AuthServiceResult<()> {
299 let content = format!(
300 r#"
301accounts:
302 - accessKey: alice
303 secretKey: {secret}
304"#
305 );
306 let temp_file = temp_acl_file_path(path);
307 fs::write(&temp_file, content).map_err(AuthServiceError::storage_write_failed)?;
308
309 replace_acl_file(&temp_file, path)
310 }
311
312 fn temp_acl_file_path(path: &std::path::Path) -> PathBuf {
313 let file_name = path
314 .file_name()
315 .and_then(|value| value.to_str())
316 .unwrap_or("plain_acl.yml");
317 let id = NEXT_ACL_WATCHER_PROBE_ID.fetch_add(1, Ordering::Relaxed);
318 path.with_file_name(format!(".{file_name}.{id}.tmp"))
319 }
320
321 #[cfg(not(windows))]
322 fn replace_acl_file(temp_file: &std::path::Path, path: &std::path::Path) -> AuthServiceResult<()> {
323 fs::rename(temp_file, path).map_err(AuthServiceError::storage_write_failed)
324 }
325
326 #[cfg(windows)]
327 fn replace_acl_file(temp_file: &std::path::Path, path: &std::path::Path) -> AuthServiceResult<()> {
328 fs::copy(temp_file, path).map_err(AuthServiceError::storage_write_failed)?;
329 let _ = fs::remove_file(temp_file);
330 Ok(())
331 }
332}
333
334#[cfg(test)]
335mod bench_support_tests {
336 use rocketmq_runtime::RuntimeContext;
337
338 #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
339 async fn auth_acl_watcher_probe_reports_clean_shutdown() {
340 let runtime = RuntimeContext::from_current("auth-acl-watcher-probe-test");
341 let probe = super::bench_support::run_auth_acl_watcher_lifecycle_probe(
342 runtime.service_context("auth-acl-watcher-probe"),
343 )
344 .await
345 .expect("auth ACL watcher lifecycle probe should run");
346
347 assert!(probe.healthy, "{probe:?}");
348 assert!(probe.reload_success, "{probe:?}");
349 assert_eq!(probe.scheduled_overlaps, 0, "{probe:?}");
350 assert_eq!(probe.scheduled_failures, 0, "{probe:?}");
351 }
352}