mirror of
https://github.com/openai/codex.git
synced 2026-11-05 20:10:33 +00:00
Honor the configured credential store in gateway test fixtures (#59495)
## What changed Update `seed_gateway_auth` to seed either the keyring or file credential store according to the provider's configuration, using `GatewayAuthManager::credential_id()` to identify credentials. Use file storage in the gateway model-cache reuse and login-required invalidation tests to keep keyring latency outside the behavior under test. GitOrigin-RevId: 23b4f31b6d9f9561638267723582af73eabefcfc
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
//! Seeds encrypted gateway credentials for provider and agent integration tests.
|
||||
//! Seeds gateway credentials in the configured store for provider and agent integration tests.
|
||||
|
||||
#![allow(clippy::expect_used)] // Fixture setup failures should fail the calling test immediately.
|
||||
|
||||
@@ -11,13 +11,12 @@ use codex_login::AuthManager;
|
||||
use codex_login::GatewayAuthConfig;
|
||||
use codex_login::GatewayAuthManager;
|
||||
use codex_model_provider_info::ModelProviderInfo;
|
||||
use codex_model_provider_info::OAuthCredentialsStore;
|
||||
use codex_secrets::LocalSecretsNamespace;
|
||||
use codex_secrets::SecretName;
|
||||
use codex_secrets::SecretScope;
|
||||
use codex_secrets::SecretsBackendKind;
|
||||
use codex_secrets::SecretsManager;
|
||||
use sha2::Digest;
|
||||
use sha2::Sha256;
|
||||
|
||||
use super::process_shared_state;
|
||||
|
||||
@@ -59,7 +58,7 @@ impl KeyringStore for TestKeyring {
|
||||
}
|
||||
}
|
||||
|
||||
/// Seeds a provider's encrypted gateway store with a test-only keyring passphrase.
|
||||
/// Seeds a provider's configured gateway store, using a test passphrase for the keyring backend.
|
||||
/// Keep the returned manager alive while requests use this fixture.
|
||||
pub fn seed_gateway_auth(
|
||||
info: &ModelProviderInfo,
|
||||
@@ -85,43 +84,51 @@ pub fn seed_gateway_auth(
|
||||
let keyring = Arc::new(TestKeyring(Mutex::new(Some(
|
||||
"gateway-test-passphrase".to_string(),
|
||||
))));
|
||||
let secrets = SecretsManager::new_with_keyring_store_and_namespace(
|
||||
runtime.codex_home.clone(),
|
||||
SecretsBackendKind::Local,
|
||||
keyring.clone(),
|
||||
LocalSecretsNamespace::GatewayOAuth,
|
||||
);
|
||||
// Match the credential identity used by GatewayAuthManager's encrypted store.
|
||||
let mut digest = Sha256::new();
|
||||
digest.update(runtime.codex_home.to_string_lossy().as_bytes());
|
||||
digest.update([0]);
|
||||
for value in [
|
||||
oauth.authorization_url.as_str(),
|
||||
oauth.token_url.as_str(),
|
||||
oauth.client_id.as_str(),
|
||||
oauth.resource.as_deref().unwrap_or_default(),
|
||||
] {
|
||||
digest.update(value.as_bytes());
|
||||
digest.update([0]);
|
||||
}
|
||||
for scope in &oauth.scopes {
|
||||
digest.update(scope.as_bytes());
|
||||
digest.update([0]);
|
||||
}
|
||||
let name = SecretName::new(&format!("PROVIDER_OAUTH_{:X}", digest.finalize()))
|
||||
.expect("gateway test credential name");
|
||||
secrets
|
||||
.set(&SecretScope::Global, &name, &token.to_string())
|
||||
.expect("seed encrypted gateway credentials");
|
||||
let manager = Arc::new(
|
||||
GatewayAuthManager::new(
|
||||
oauth.clone(),
|
||||
runtime.codex_home.clone(),
|
||||
runtime.auth_route_config.http_client_factory(),
|
||||
keyring,
|
||||
keyring.clone(),
|
||||
)
|
||||
.expect("gateway test HTTP client"),
|
||||
);
|
||||
let credential_id = manager.credential_id();
|
||||
match oauth.credentials_store {
|
||||
OAuthCredentialsStore::Keyring => {
|
||||
let secrets = SecretsManager::new_with_keyring_store_and_namespace(
|
||||
runtime.codex_home.clone(),
|
||||
SecretsBackendKind::Local,
|
||||
keyring,
|
||||
LocalSecretsNamespace::GatewayOAuth,
|
||||
);
|
||||
let digest = credential_id
|
||||
.strip_prefix("provider-oauth|")
|
||||
.expect("gateway credential ID");
|
||||
let name = SecretName::new(&format!("PROVIDER_OAUTH_{}", digest.to_ascii_uppercase()))
|
||||
.expect("gateway test credential name");
|
||||
secrets
|
||||
.set(&SecretScope::Global, &name, &token.to_string())
|
||||
.expect("seed encrypted gateway credentials");
|
||||
}
|
||||
OAuthCredentialsStore::File => {
|
||||
let dir = runtime.codex_home.join("secrets");
|
||||
std::fs::create_dir_all(&dir).expect("create test credentials directory");
|
||||
let file = dir.join("gateway_oauth.json");
|
||||
let mut tokens: std::collections::BTreeMap<String, serde_json::Value> =
|
||||
match std::fs::read(&file) {
|
||||
Ok(bytes) => serde_json::from_slice(&bytes).expect("parse test gateway tokens"),
|
||||
Err(err) if err.kind() == std::io::ErrorKind::NotFound => Default::default(),
|
||||
Err(err) => panic!("read test gateway file: {err}"),
|
||||
};
|
||||
tokens.insert(credential_id, token);
|
||||
std::fs::write(
|
||||
file,
|
||||
serde_json::to_vec(&tokens).expect("serialize test gateway tokens"),
|
||||
)
|
||||
.expect("seed test gateway file");
|
||||
}
|
||||
}
|
||||
process_shared_state()
|
||||
.gateway_managers
|
||||
.lock()
|
||||
|
||||
@@ -20,6 +20,7 @@ use codex_login::default_client::ClientRedirectPolicy;
|
||||
use codex_login::default_client::create_client_for_route;
|
||||
use codex_model_provider_info::GatewayOAuthDelivery;
|
||||
use codex_model_provider_info::ModelProviderInfo;
|
||||
use codex_model_provider_info::OAuthCredentialsStore;
|
||||
use codex_models_manager::manager::RefreshStrategy;
|
||||
use codex_protocol::error::CodexErrorDetails;
|
||||
use codex_protocol::protocol::CodexErrorInfo;
|
||||
@@ -408,7 +409,8 @@ async fn models_cache_is_reused_only_for_matching_gateway_configuration() {
|
||||
resource: None,
|
||||
scopes: vec![],
|
||||
redirect_port: None,
|
||||
credentials_store: Default::default(),
|
||||
// Keyring latency is outside the cache behavior under test.
|
||||
credentials_store: OAuthCredentialsStore::File,
|
||||
delivery: GatewayOAuthDelivery::Header {
|
||||
name: "x-gateway-auth".into(),
|
||||
scheme: "Bearer".into(),
|
||||
@@ -672,7 +674,7 @@ async fn gateway_login_required_invalidates_the_last_successful_catalog() {
|
||||
resource: None,
|
||||
scopes: vec![],
|
||||
redirect_port: None,
|
||||
credentials_store: Default::default(),
|
||||
credentials_store: OAuthCredentialsStore::File,
|
||||
delivery: GatewayOAuthDelivery::Header {
|
||||
name: "x-gateway-auth".into(),
|
||||
scheme: "Bearer".into(),
|
||||
|
||||
Reference in New Issue
Block a user