From 740e4399af0c78a98a527776949b4ba8d09d73fb Mon Sep 17 00:00:00 2001 From: Alexander Kharkevich Date: Mon, 6 Apr 2026 21:17:39 -0400 Subject: [PATCH] fix: skip missing groups in policy_db_get instead of aborting (#2393) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Claude Opus 4.6 Co-authored-by: 安正超 --- crates/iam/src/manager.rs | 6 +++++- crates/iam/src/sys.rs | 27 ++++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/crates/iam/src/manager.rs b/crates/iam/src/manager.rs index 16dcb53de..393b1eb2b 100644 --- a/crates/iam/src/manager.rs +++ b/crates/iam/src/manager.rs @@ -755,7 +755,11 @@ where if let Some(groups) = groups { for group in groups.iter() { - let (gp, _) = self.policy_db_get_internal(group, true, present).await?; + let (gp, _) = match self.policy_db_get_internal(group, true, present).await { + Ok(result) => result, + Err(err) if is_err_no_such_group(&err) => continue, + Err(err) => return Err(err), + }; gp.iter().for_each(|v| { policies.push(v.clone()); }); diff --git a/crates/iam/src/sys.rs b/crates/iam/src/sys.rs index 04e869fb0..0b6327e12 100644 --- a/crates/iam/src/sys.rs +++ b/crates/iam/src/sys.rs @@ -1337,7 +1337,7 @@ mod tests { } async fn load_group(&self, _name: &str, _m: &mut HashMap) -> Result<()> { - Err(Error::InvalidArgument) + Ok(()) } async fn load_groups(&self, _m: &mut HashMap) -> Result<()> { @@ -1873,4 +1873,29 @@ mod tests { "inherited service account should not require object tag fetch based on session policy hint" ); } + + /// Regression test for rustfs#2392: `policy_db_get` must skip non-existent groups + /// instead of aborting the entire policy resolution. When a JWT contains groups + /// that exist in the IdP but not in IAM, policies from the remaining valid groups + /// must still be returned. + #[tokio::test] + async fn test_policy_db_get_skips_nonexistent_groups() { + let store = StsTestMockStore { empty_policies: false }; + let cache_manager = IamCache::new(store).await; + let iam_sys = IamSys::new(cache_manager); + + // "testgroup" exists with "readwrite" policy; "nonexistent-group" does not exist in IAM. + let groups = Some(vec!["testgroup".to_string(), "nonexistent-group".to_string()]); + + let policies = iam_sys + .policy_db_get("sts-fallback-test-parent", &groups) + .await + .expect("policy_db_get should not fail when some groups are missing"); + + assert!( + policies.iter().any(|p| p == "readwrite"), + "policies from existing group 'testgroup' should be returned even when other groups are missing; got: {:?}", + policies + ); + } }