Fail closed when workload identity initialization fails (#38424)

## What changed

- Treat workload identity environment markers as an explicit authentication selection, even when another process credential is present.
- Return initialization errors from `AuthManager` and propagate them through commands and services instead of continuing with an unusable authentication state.
- Make `codex login status` validate workload identity, keep the TUI on an embedded app server for local workload identity, and reject workload identity in `codex mcp-server`, where it is unsupported.

## Testing

- Cover workload identity precedence and partial configuration errors.
- Verify login status reports an unreadable identity assertion and app-server routing enforces the supported workload identity topology.

GitOrigin-RevId: efc6b6b4cd4d61652617de82aaa3d7ffc75d6618
This commit is contained in:
cooper-oai authored and copyberry committed 2026-08-13 19:35:22 +00:00
1 parent 781445f7c6
commit 990218bbbd
33 files changed
+368 -212

No files matched your search

+16 -1
View File
@@ -64,6 +64,7 @@ pub async fn run_main(
cli_config_overrides: CliConfigOverrides,
strict_config: bool,
) -> IoResult<()> {
reject_workload_identity(codex_login::is_workload_identity_selected())?;
// Parse CLI overrides once and derive the base Config eagerly so later
// components do not need to work with raw TOML values.
let cli_kv_overrides = cli_config_overrides.parse_overrides().map_err(|e| {
@@ -161,7 +162,7 @@ pub async fn run_main(
state_db,
installation_id,
)
.await;
.await?;
async move {
while let Some(msg) = incoming_rx.recv().await {
match msg {
@@ -207,6 +208,20 @@ pub async fn run_main(
Ok(())
}
fn reject_workload_identity(workload_identity_selected: bool) -> IoResult<()> {
if workload_identity_selected {
return Err(std::io::Error::new(
ErrorKind::Unsupported,
"workload identity is not supported by `codex mcp-server`",
));
}
Ok(())
}
#[cfg(test)]
#[path = "workload_identity_tests.rs"]
mod workload_identity_tests;
#[cfg(test)]
mod tests {
use super::*;
+5 -4
View File
@@ -54,13 +54,14 @@ impl MessageProcessor {
environment_manager: Arc<EnvironmentManager>,
state_db: Option<StateDbHandle>,
installation_id: String,
) -> Self {
) -> std::io::Result<Self> {
let outgoing = Arc::new(outgoing);
let auth_manager = AuthManager::shared_from_config(
config.as_ref(),
/*enable_codex_api_key_env*/ false,
)
.await;
.await
.map_err(std::io::Error::other)?;
let user_instructions_provider = Arc::new(CodexHomeUserInstructionsProvider::new(
config.codex_home.clone(),
));
@@ -110,13 +111,13 @@ impl MessageProcessor {
/*attestation_provider*/ None,
/*external_time_provider*/ None,
));
Self {
Ok(Self {
outgoing,
initialized: false,
arg0_paths,
thread_manager,
active_turns,
}
})
}
pub(crate) async fn process_request(&mut self, request: JsonRpcRequest<ClientRequest>) {
@@ -0,0 +1,15 @@
use super::reject_workload_identity;
use pretty_assertions::assert_eq;
#[test]
fn workload_identity_markers_are_rejected() {
let error = reject_workload_identity(/*workload_identity_selected*/ true)
.expect_err("mcp-server does not support workload identity");
assert_eq!(
error.to_string(),
"workload identity is not supported by `codex mcp-server`"
);
reject_workload_identity(/*workload_identity_selected*/ false)
.expect("mcp-server remains available without workload identity");
}