micromegas_auth/default_provider.rs
1//! Default authentication provider initialization for Micromegas services.
2//!
3//! This module provides the standard way to initialize authentication with both
4//! API key and OIDC providers from environment variables.
5
6use crate::api_key::{ApiKeyAuthProvider, parse_key_ring};
7use crate::multi::MultiAuthProvider;
8use crate::oidc::{OidcAuthProvider, OidcConfig};
9use crate::types::AuthProvider;
10use micromegas_tracing::info;
11use std::sync::Arc;
12
13/// Initializes the default authentication provider with API key and OIDC from environment.
14///
15/// Reads configuration from:
16/// - `MICROMEGAS_API_KEYS`: JSON array of API keys
17/// - `MICROMEGAS_OIDC_CONFIG`: OIDC configuration JSON
18/// - `MICROMEGAS_ADMINS`: JSON array of admin user emails/subjects
19///
20/// Returns `Ok(Some(...))` if at least one provider is configured.
21/// Returns `Ok(None)` if no providers are configured (auth disabled).
22/// Returns `Err` on configuration errors.
23///
24/// # Example
25///
26/// ```rust,no_run
27/// use micromegas_auth::default_provider::provider;
28///
29/// # async fn example() -> anyhow::Result<()> {
30/// let auth_provider = provider().await?;
31/// if let Some(provider) = auth_provider {
32/// println!("Authentication enabled");
33/// } else {
34/// println!("No authentication configured");
35/// }
36/// # Ok(())
37/// # }
38/// ```
39pub async fn provider() -> anyhow::Result<Option<Arc<dyn AuthProvider>>> {
40 provider_with_prefix("").await
41}
42
43/// Initializes auth providers using env vars scoped to a prefix.
44///
45/// For prefix `"MICROMEGAS_INGESTION"`:
46/// - API keys: tries `MICROMEGAS_INGESTION_API_KEYS`, falls back to `MICROMEGAS_API_KEYS`
47/// - OIDC: tries `MICROMEGAS_INGESTION_OIDC_CONFIG`, falls back to `MICROMEGAS_OIDC_CONFIG`
48/// - Admins: tries `MICROMEGAS_INGESTION_ADMINS`, falls back to `MICROMEGAS_ADMINS`
49///
50/// With an empty prefix the behaviour is identical to [`provider`].
51pub async fn provider_with_prefix(prefix: &str) -> anyhow::Result<Option<Arc<dyn AuthProvider>>> {
52 // Resolve API keys var with fallback
53 let api_keys_json = if prefix.is_empty() {
54 std::env::var("MICROMEGAS_API_KEYS").ok()
55 } else {
56 std::env::var(format!("{prefix}_API_KEYS"))
57 .or_else(|_| std::env::var("MICROMEGAS_API_KEYS"))
58 .ok()
59 };
60
61 // Resolve OIDC config var with fallback
62 let oidc_config_var: String = if prefix.is_empty() {
63 "MICROMEGAS_OIDC_CONFIG".to_string()
64 } else if std::env::var(format!("{prefix}_OIDC_CONFIG")).is_ok() {
65 format!("{prefix}_OIDC_CONFIG")
66 } else {
67 "MICROMEGAS_OIDC_CONFIG".to_string()
68 };
69
70 // Resolve admin users var with fallback
71 let admin_var: String = if prefix.is_empty() {
72 "MICROMEGAS_ADMINS".to_string()
73 } else {
74 let prefixed = format!("{prefix}_ADMINS");
75 if std::env::var(&prefixed).is_ok() {
76 prefixed
77 } else {
78 "MICROMEGAS_ADMINS".to_string()
79 }
80 };
81
82 // Initialize API key provider if configured
83 let api_key_provider = if let Some(keys_json) = api_keys_json {
84 let keyring = parse_key_ring(&keys_json)?;
85 info!("API key authentication enabled");
86 Some(Arc::new(ApiKeyAuthProvider::new(keyring)) as Arc<dyn AuthProvider>)
87 } else {
88 info!("API key auth not configured");
89 None
90 };
91
92 // Initialize OIDC provider if configured
93 let oidc_provider = match OidcConfig::from_env_var(&oidc_config_var) {
94 Ok(config) => {
95 info!("Initializing OIDC authentication");
96 Some(Arc::new(OidcAuthProvider::new(config, &admin_var).await?) as Arc<dyn AuthProvider>)
97 }
98 Err(e) => {
99 info!("OIDC not configured ({e}) - OIDC auth disabled");
100 None
101 }
102 };
103
104 // Build multi-provider from available providers
105 let mut multi = MultiAuthProvider::new();
106 if let Some(p) = api_key_provider {
107 multi = multi.with_provider(p);
108 }
109 if let Some(p) = oidc_provider {
110 multi = multi.with_provider(p);
111 }
112
113 // Return None if no providers configured
114 if multi.is_empty() {
115 return Ok(None);
116 }
117
118 Ok(Some(Arc::new(multi) as Arc<dyn AuthProvider>))
119}