mirror of
https://github.com/openai/codex.git
synced 2026-11-07 20:30:33 +00:00
## Why Authentication restrictions must apply before stored or environment-provided credentials can be used, including during bootstrap before cloud requirements are fetched. ## What changed - Add local `requirements.toml` allowlists for login methods and ChatGPT workspaces. Ignore these fields in cloud-provided requirements. - Combine managed workspace allowlists with existing workspace restrictions by intersection, and fail closed when the resulting policy permits no usable login method. - Centralize policy checks in the authentication manager so CLI, TUI, app-server, external-auth, and credential-loading paths consistently reject disallowed authentication before token hydration or network requests. ## Testing - Cover policy composition, workspace intersection, invalid stored and external credentials, bootstrap enforcement, and login endpoint restrictions. GitOrigin-RevId: efef22b248f3c3333e9aa55423e539efa2d2dd48
62 lines
2.0 KiB
Rust
62 lines
2.0 KiB
Rust
use codex_protocol::config_types::ForcedLoginMethod;
|
|
|
|
/// Authentication restrictions supplied by locally managed requirements.
|
|
#[derive(Debug, Clone, Default, PartialEq, Eq)]
|
|
pub struct ManagedAuthPolicy {
|
|
pub allowed_login_methods: Option<Vec<ForcedLoginMethod>>,
|
|
pub allowed_chatgpt_workspaces: Option<Vec<String>>,
|
|
}
|
|
|
|
impl ManagedAuthPolicy {
|
|
pub fn allows_login_method(
|
|
&self,
|
|
method: ForcedLoginMethod,
|
|
forced_login_method: Option<ForcedLoginMethod>,
|
|
forced_workspaces: Option<&[String]>,
|
|
) -> bool {
|
|
forced_login_method.is_none_or(|forced| forced == method)
|
|
&& self
|
|
.allowed_login_methods
|
|
.as_ref()
|
|
.is_none_or(|allowed| allowed.contains(&method))
|
|
&& (method != ForcedLoginMethod::Chatgpt
|
|
|| self
|
|
.effective_chatgpt_workspaces(forced_workspaces)
|
|
.is_none_or(|workspaces| !workspaces.is_empty()))
|
|
}
|
|
|
|
pub fn allowed_login_methods(
|
|
&self,
|
|
forced_login_method: Option<ForcedLoginMethod>,
|
|
forced_workspaces: Option<&[String]>,
|
|
) -> Vec<ForcedLoginMethod> {
|
|
[ForcedLoginMethod::Api, ForcedLoginMethod::Chatgpt]
|
|
.into_iter()
|
|
.filter(|method| {
|
|
self.allows_login_method(*method, forced_login_method, forced_workspaces)
|
|
})
|
|
.collect()
|
|
}
|
|
|
|
pub fn effective_chatgpt_workspaces(
|
|
&self,
|
|
forced_workspaces: Option<&[String]>,
|
|
) -> Option<Vec<String>> {
|
|
match (
|
|
forced_workspaces,
|
|
self.allowed_chatgpt_workspaces.as_deref(),
|
|
) {
|
|
(Some(forced), Some(allowed)) => Some(
|
|
forced
|
|
.iter()
|
|
.filter(|workspace| allowed.contains(workspace))
|
|
.cloned()
|
|
.collect(),
|
|
),
|
|
(Some(forced), None) => Some(forced.to_vec()),
|
|
(None, Some(allowed)) => Some(allowed.to_vec()),
|
|
(None, None) => None,
|
|
}
|
|
}
|
|
}
|