This commit is contained in:
celia-oai
2026-06-10 17:46:57 -07:00
parent 25460ecf71
commit 89901665a2
3 changed files with 73 additions and 32 deletions
+21 -8
View File
@@ -27,9 +27,10 @@ pub use codex_config::types::AuthKeyringBackendKind;
use codex_keyring_store::DefaultKeyringStore;
use codex_keyring_store::KeyringStore;
use codex_protocol::account::PlanType as AccountPlanType;
use codex_secrets::LocalSecretsBackend;
use codex_secrets::SecretName;
use codex_secrets::SecretScope;
use codex_secrets::SecretsBackendKind;
use codex_secrets::SecretsManager;
use once_cell::sync::Lazy;
/// Expected structure for $CODEX_HOME/auth.json.
@@ -258,18 +259,30 @@ impl AuthStorageBackend for DirectKeyringAuthStorage {
}
}
#[derive(Clone, Debug)]
#[derive(Clone)]
struct SecretsKeyringAuthStorage {
codex_home: PathBuf,
secrets_backend: LocalSecretsBackend,
secrets_manager: SecretsManager,
}
impl Debug for SecretsKeyringAuthStorage {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SecretsKeyringAuthStorage")
.field("codex_home", &self.codex_home)
.finish_non_exhaustive()
}
}
impl SecretsKeyringAuthStorage {
fn new(codex_home: PathBuf, keyring_store: Arc<dyn KeyringStore>) -> Self {
let secrets_backend = LocalSecretsBackend::new(codex_home.clone(), keyring_store);
let secrets_manager = SecretsManager::new_with_keyring_store(
codex_home.clone(),
SecretsBackendKind::Local,
keyring_store,
);
Self {
codex_home,
secrets_backend,
secrets_manager,
}
}
}
@@ -277,7 +290,7 @@ impl SecretsKeyringAuthStorage {
impl AuthStorageBackend for SecretsKeyringAuthStorage {
fn load(&self) -> std::io::Result<Option<AuthDotJson>> {
match self
.secrets_backend
.secrets_manager
.get(&SecretScope::Global, &CLI_AUTH_SECRET_NAME)
.map_err(|err| {
std::io::Error::other(format!(
@@ -295,7 +308,7 @@ impl AuthStorageBackend for SecretsKeyringAuthStorage {
fn save(&self, auth: &AuthDotJson) -> std::io::Result<()> {
let serialized = serde_json::to_string(auth).map_err(std::io::Error::other)?;
self.secrets_backend
self.secrets_manager
.set(&SecretScope::Global, &CLI_AUTH_SECRET_NAME, &serialized)
.map_err(|err| {
let message =
@@ -311,7 +324,7 @@ impl AuthStorageBackend for SecretsKeyringAuthStorage {
fn delete(&self) -> std::io::Result<bool> {
let keyring_removed = self
.secrets_backend
.secrets_manager
.delete(&SecretScope::Global, &CLI_AUTH_SECRET_NAME)
.map_err(|err| {
std::io::Error::other(format!(
+20 -10
View File
@@ -2,8 +2,9 @@ use super::*;
use crate::token_data::IdTokenInfo;
use anyhow::Context;
use base64::Engine;
use codex_secrets::LocalSecretsBackend;
use codex_secrets::SecretScope;
use codex_secrets::SecretsBackendKind;
use codex_secrets::SecretsManager;
use codex_secrets::compute_keyring_account;
use pretty_assertions::assert_eq;
use serde_json::json;
@@ -198,9 +199,12 @@ fn seed_secrets_backend_and_fallback_auth_file_for_delete(
codex_home: &Path,
auth: &AuthDotJson,
) -> anyhow::Result<PathBuf> {
let backend =
LocalSecretsBackend::new(codex_home.to_path_buf(), Arc::new(mock_keyring.clone()));
backend.set(
let manager = SecretsManager::new_with_keyring_store(
codex_home.to_path_buf(),
SecretsBackendKind::Local,
Arc::new(mock_keyring.clone()),
);
manager.set(
&SecretScope::Global,
&CLI_AUTH_SECRET_NAME,
&serde_json::to_string(auth)?,
@@ -215,9 +219,12 @@ fn seed_secrets_backend_with_auth(
codex_home: &Path,
auth: &AuthDotJson,
) -> anyhow::Result<()> {
let backend =
LocalSecretsBackend::new(codex_home.to_path_buf(), Arc::new(mock_keyring.clone()));
backend.set(
let manager = SecretsManager::new_with_keyring_store(
codex_home.to_path_buf(),
SecretsBackendKind::Local,
Arc::new(mock_keyring.clone()),
);
manager.set(
&SecretScope::Global,
&CLI_AUTH_SECRET_NAME,
&serde_json::to_string(auth)?,
@@ -230,9 +237,12 @@ fn assert_keyring_saved_auth_and_removed_fallback(
codex_home: &Path,
expected: &AuthDotJson,
) -> anyhow::Result<()> {
let backend =
LocalSecretsBackend::new(codex_home.to_path_buf(), Arc::new(mock_keyring.clone()));
let saved_value = backend
let manager = SecretsManager::new_with_keyring_store(
codex_home.to_path_buf(),
SecretsBackendKind::Local,
Arc::new(mock_keyring.clone()),
);
let saved_value = manager
.get(&SecretScope::Global, &CLI_AUTH_SECRET_NAME)?
.context("encrypted auth entry should exist")?;
let expected_serialized = serde_json::to_string(expected)?;
+32 -14
View File
@@ -21,9 +21,10 @@ use anyhow::Error;
use anyhow::Result;
use codex_config::types::AuthKeyringBackendKind;
use codex_config::types::OAuthCredentialsStoreMode;
use codex_secrets::LocalSecretsBackend;
use codex_secrets::SecretName;
use codex_secrets::SecretScope;
use codex_secrets::SecretsBackendKind;
use codex_secrets::SecretsManager;
use oauth2::AccessToken;
use oauth2::RefreshToken;
use oauth2::Scope;
@@ -219,10 +220,13 @@ fn load_oauth_tokens_from_secrets_keyring<K: KeyringStore + Clone + 'static>(
url: &str,
) -> Result<Option<StoredOAuthTokens>> {
let codex_home = find_codex_home()?;
let backend =
LocalSecretsBackend::new(codex_home.to_path_buf(), Arc::new(keyring_store.clone()));
let manager = SecretsManager::new_with_keyring_store(
codex_home.to_path_buf(),
SecretsBackendKind::Local,
Arc::new(keyring_store.clone()),
);
let secret_name = compute_secret_name(server_name, url)?;
match backend
match manager
.get(&SecretScope::Global, &secret_name)
.context("failed to load MCP OAuth tokens from encrypted storage")?
{
@@ -309,10 +313,13 @@ fn save_oauth_tokens_to_secrets_keyring<K: KeyringStore + Clone + 'static>(
) -> Result<()> {
let serialized = serde_json::to_string(tokens).context("failed to serialize OAuth tokens")?;
let codex_home = find_codex_home()?;
let backend =
LocalSecretsBackend::new(codex_home.to_path_buf(), Arc::new(keyring_store.clone()));
let manager = SecretsManager::new_with_keyring_store(
codex_home.to_path_buf(),
SecretsBackendKind::Local,
Arc::new(keyring_store.clone()),
);
let secret_name = compute_secret_name(server_name, &tokens.url)?;
backend
manager
.set(&SecretScope::Global, &secret_name, &serialized)
.context("failed to write OAuth tokens to encrypted storage")?;
@@ -417,10 +424,13 @@ fn delete_oauth_tokens_from_secrets_keyring<K: KeyringStore + Clone + 'static>(
url: &str,
) -> Result<bool> {
let codex_home = find_codex_home()?;
let backend =
LocalSecretsBackend::new(codex_home.to_path_buf(), Arc::new(keyring_store.clone()));
let manager = SecretsManager::new_with_keyring_store(
codex_home.to_path_buf(),
SecretsBackendKind::Local,
Arc::new(keyring_store.clone()),
);
let secret_name = compute_secret_name(server_name, url)?;
let secrets_removed = backend
let secrets_removed = manager
.delete(&SecretScope::Global, &secret_name)
.context("failed to delete OAuth tokens from encrypted storage")?;
Ok(secrets_removed)
@@ -977,9 +987,13 @@ mod tests {
&tokens,
)?;
let backend = LocalSecretsBackend::new(env.path().to_path_buf(), Arc::new(store.clone()));
let manager = SecretsManager::new_with_keyring_store(
env.path().to_path_buf(),
SecretsBackendKind::Local,
Arc::new(store.clone()),
);
let secret_name = super::compute_secret_name(&tokens.server_name, &tokens.url)?;
let stored = backend
let stored = manager
.get(&SecretScope::Global, &secret_name)?
.expect("tokens should be saved to encrypted storage");
assert_eq!(serde_json::from_str::<StoredOAuthTokens>(&stored)?, tokens);
@@ -1082,10 +1096,14 @@ mod tests {
&tokens.url,
)?;
let backend = LocalSecretsBackend::new(env.path().to_path_buf(), Arc::new(store.clone()));
let manager = SecretsManager::new_with_keyring_store(
env.path().to_path_buf(),
SecretsBackendKind::Local,
Arc::new(store.clone()),
);
let secret_name = super::compute_secret_name(&tokens.server_name, &tokens.url)?;
assert!(removed);
assert!(backend.get(&SecretScope::Global, &secret_name)?.is_none());
assert!(manager.get(&SecretScope::Global, &secret_name)?.is_none());
assert_eq!(store.saved_value(&key), Some(serialized));
assert!(!super::fallback_file_path()?.exists());
Ok(())