fix(redis): accept a bare service account email for GCP Memorystore IAM (#50676)

The Rust credential source passed gcp_service_account straight into the
IAM credentials URL, so a bare email got a 404 and the stores fell back
to per-worker memory. Address it as projects/-/serviceAccounts/<email>
when it is not already a resource name, like the Python gRPC path did.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
yujonglee 2026-11-10 07:31:12 +09:00 • committed by GitHub
parent 6a232c90e0
commit b09061b640
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -41,6 +41,15 @@ impl GcpIam {
}
}
fn token_url(service_account: &str) -> String {
match service_account.starts_with("projects/") {
true => format!("{IAM_CREDENTIALS}/{service_account}:generateAccessToken"),
false => format!(
"{IAM_CREDENTIALS}/projects/-/serviceAccounts/{service_account}:generateAccessToken"
),
}
}
impl CredentialSource for GcpIam {
fn fetch(&self) -> SourceFuture<'_> {
Box::pin(async move {
@ -52,10 +61,7 @@ impl CredentialSource for GcpIam {
.map_err(Error::credential(CredentialStage::Identity))?;
let response = self
.http
.post(format!(
"{IAM_CREDENTIALS}/{}:generateAccessToken",
self.service_account
))
.post(token_url(&self.service_account))
.bearer_auth(caller.expose())
.json(&serde_json::json!({ "scope": [CLOUD_PLATFORM_SCOPE] }))
.send()
@ -92,9 +98,29 @@ impl CredentialSource for GcpIam {
mod tests {
use rstest::rstest;
use super::GcpIam;
use super::{GcpIam, token_url};
use crate::CredentialSource;
#[rstest]
#[case::bare_email(
"redis@project.iam.gserviceaccount.com",
"https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/redis@project.iam.gserviceaccount.com:generateAccessToken"
)]
#[case::resource_name(
"projects/-/serviceAccounts/redis@project.iam.gserviceaccount.com",
"https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/redis@project.iam.gserviceaccount.com:generateAccessToken"
)]
#[case::project_scoped_resource_name(
"projects/project/serviceAccounts/redis@project.iam.gserviceaccount.com",
"https://iamcredentials.googleapis.com/v1/projects/project/serviceAccounts/redis@project.iam.gserviceaccount.com:generateAccessToken"
)]
fn a_bare_service_account_email_is_addressed_as_a_resource_name(
#[case] service_account: &str,
#[case] expected: &str,
) {
assert_eq!(token_url(service_account), expected);
}
#[rstest]
#[tokio::test]
async fn the_caller_identity_comes_from_application_default_credentials_not_vertex_settings() {