Tighten local auth allow-list matching

This commit is contained in:
fawney19
2026-04-30 00:26:33 +08:00
parent 37392d8774
commit 9e2faa7e5b
10 changed files with 758 additions and 53 deletions

View File

@@ -183,35 +183,36 @@ impl ResolvedAuthApiKeySnapshot {
pub fn effective_allowed_providers(&self) -> Option<&[String]> {
if self.api_key_is_standalone {
return self.api_key_allowed_providers.as_deref();
return non_empty_allowed_list(self.api_key_allowed_providers.as_deref());
}
self.api_key_allowed_providers
.as_deref()
.or(self.user_allowed_providers.as_deref())
non_empty_allowed_list(self.api_key_allowed_providers.as_deref())
.or_else(|| non_empty_allowed_list(self.user_allowed_providers.as_deref()))
}
pub fn effective_allowed_api_formats(&self) -> Option<&[String]> {
if self.api_key_is_standalone {
return self.api_key_allowed_api_formats.as_deref();
return non_empty_allowed_list(self.api_key_allowed_api_formats.as_deref());
}
self.api_key_allowed_api_formats
.as_deref()
.or(self.user_allowed_api_formats.as_deref())
non_empty_allowed_list(self.api_key_allowed_api_formats.as_deref())
.or_else(|| non_empty_allowed_list(self.user_allowed_api_formats.as_deref()))
}
pub fn effective_allowed_models(&self) -> Option<&[String]> {
if self.api_key_is_standalone {
return self.api_key_allowed_models.as_deref();
return non_empty_allowed_list(self.api_key_allowed_models.as_deref());
}
self.api_key_allowed_models
.as_deref()
.or(self.user_allowed_models.as_deref())
non_empty_allowed_list(self.api_key_allowed_models.as_deref())
.or_else(|| non_empty_allowed_list(self.user_allowed_models.as_deref()))
}
}
fn non_empty_allowed_list(values: Option<&[String]>) -> Option<&[String]> {
values.filter(|items| !items.is_empty())
}
#[async_trait]
pub trait ResolvedAuthApiKeySnapshotReader: Send + Sync {
async fn find_stored_auth_api_key_snapshot(
@@ -979,7 +980,7 @@ mod tests {
}
#[test]
fn standalone_snapshot_keeps_empty_key_allowed_lists_as_deny_all() {
fn standalone_snapshot_treats_empty_key_allowed_lists_as_unrestricted() {
let snapshot = StoredAuthApiKeySnapshot::new(
"admin-user".to_string(),
"admin".to_string(),
@@ -1007,9 +1008,9 @@ mod tests {
let resolved = ResolvedAuthApiKeySnapshot::from_stored(snapshot, 150);
assert_eq!(resolved.effective_allowed_providers(), Some(&[][..]));
assert_eq!(resolved.effective_allowed_api_formats(), Some(&[][..]));
assert_eq!(resolved.effective_allowed_models(), Some(&[][..]));
assert_eq!(resolved.effective_allowed_providers(), None);
assert_eq!(resolved.effective_allowed_api_formats(), None);
assert_eq!(resolved.effective_allowed_models(), None);
}
#[test]