@@ -22,7 +22,7 @@ use std::{
2222 num:: NonZeroU32 ,
2323 path:: PathBuf ,
2424 str:: FromStr ,
25- sync:: { Arc , RwLock } ,
25+ sync:: { Arc , LazyLock , RwLock } ,
2626} ;
2727
2828use actix_web:: http:: {
@@ -34,6 +34,7 @@ use bytes::Bytes;
3434use chrono:: Utc ;
3535use clap:: { Parser , error:: ErrorKind } ;
3636use once_cell:: sync:: { Lazy , OnceCell } ;
37+ use regex:: Regex ;
3738use relative_path:: RelativePathBuf ;
3839pub use staging:: StagingError ;
3940use streams:: StreamRef ;
@@ -102,6 +103,23 @@ pub const STREAM_EXISTS: &str = "Stream exists";
102103/// OnceCell to return metastore
103104pub static METASTORE : OnceCell < Arc < dyn Metastore > > = OnceCell :: new ( ) ;
104105
106+ /// LazyLock for tenant id regex
107+ pub static TENANT_ID_REGEX : LazyLock < Regex > = LazyLock :: new ( || {
108+ regex:: RegexBuilder :: new ( r"^[a-zA-Z0-9][a-zA-Z0-9_-]{0,35}$" )
109+ . build ( )
110+ . expect ( "Unable to create tenant id validation regex" )
111+ } ) ;
112+
113+ pub fn validate_tenant_id ( tenant_id : & str ) -> Result < ( ) , String > {
114+ if !TENANT_ID_REGEX . is_match ( tenant_id) {
115+ return Err ( "tenant ID should follow regex- ^[a-zA-Z0-9][a-zA-Z0-9_-]{0,35}$" . into ( ) ) ;
116+ }
117+ if tenant_id. eq ( DEFAULT_TENANT ) {
118+ return Err ( format ! ( "tenant ID can't be {DEFAULT_TENANT}" ) ) ;
119+ }
120+ Ok ( ( ) )
121+ }
122+
105123/// For OTel log sources the telemetry_type is fully determined by the log_source.
106124/// When the user explicitly sets x-p-telemetry-type and it disagrees with the
107125/// implied type for an otel-* source, reject the request. When they don't set it,
@@ -1165,7 +1183,7 @@ impl Parseable {
11651183 if !self . options . is_multi_tenant ( ) {
11661184 return Err ( anyhow:: Error :: msg ( "P_MULTI_TENANCY is set to false" ) ) ;
11671185 }
1168-
1186+ validate_tenant_id ( & tenant_id ) . map_err ( |e| anyhow :: anyhow! ( e ) ) ? ;
11691187 let mut tenants = self . tenants . write ( ) . unwrap ( ) ;
11701188 if tenants. contains ( & tenant_id) {
11711189 return Err ( anyhow:: Error :: msg ( format ! (
@@ -1266,6 +1284,8 @@ impl Parseable {
12661284 . await ?
12671285 && is_multi_tenant
12681286 {
1287+ // check if tenantID is valid
1288+ validate_tenant_id ( & tenant_id) . map_err ( |e| anyhow:: anyhow!( e) ) ?;
12691289 let metadata: StorageMetadata = serde_json:: from_slice ( & meta) ?;
12701290
12711291 TENANT_METADATA . insert_tenant ( tenant_id. clone ( ) , metadata. clone ( ) ) ;
0 commit comments