From e7a38863ab8d5d0432cea7f448ff29377a3ad354 Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Thu, 18 Dec 2025 11:31:30 -0700 Subject: [PATCH] fix registry auth --- core/startos/src/middleware/auth/mod.rs | 25 ++++---- core/startos/src/registry/context.rs | 57 ++++++++++--------- core/startos/src/registry/info.rs | 1 + core/startos/src/registry/os/asset/get.rs | 21 ++++++- core/startos/src/registry/os/mod.rs | 2 + core/startos/src/registry/os/version/mod.rs | 1 + .../startos/src/registry/os/version/signer.rs | 1 + core/startos/src/registry/package/category.rs | 1 + core/startos/src/registry/package/mod.rs | 1 + core/startos/src/registry/package/signer.rs | 1 + 10 files changed, 69 insertions(+), 42 deletions(-) diff --git a/core/startos/src/middleware/auth/mod.rs b/core/startos/src/middleware/auth/mod.rs index 8f933aa49..3cee14769 100644 --- a/core/startos/src/middleware/auth/mod.rs +++ b/core/startos/src/middleware/auth/mod.rs @@ -81,22 +81,23 @@ impl Middleware for Auth { ) -> Result<(), RpcResponse> { let m: Metadata = from_value(metadata.clone()).map_err(|e| RpcResponse::from_result(Err(e)))?; - if m.authenticated { - let mut err = None; - for middleware in self.0.iter_mut() { - if let Err(e) = middleware - .process_rpc_request(context, metadata.clone(), request) - .await - { + let mut err = None; + for middleware in self.0.iter_mut() { + if let Err(e) = middleware + .process_rpc_request(context, metadata.clone(), request) + .await + { + if m.authenticated { err = Some(e); - } else { - return Ok(()); } - } - if let Some(e) = err { - return Err(e); + } else { + return Ok(()); } } + if let Some(e) = err { + return Err(e); + } + Ok(()) } async fn process_rpc_response(&mut self, context: &C, response: &mut RpcResponse) { diff --git a/core/startos/src/registry/context.rs b/core/startos/src/registry/context.rs index 9c4b4f269..0375a46d3 100644 --- a/core/startos/src/registry/context.rs +++ b/core/startos/src/registry/context.rs @@ -174,26 +174,11 @@ impl CallRemote for CliContext { params: Value, _: Empty, ) -> Result { - let mut has_cookie = false; - if let Ok(local) = read_file_to_string(RegistryContext::LOCAL_AUTH_COOKIE_PATH).await { - self.cookie_store - .lock() - .unwrap() - .insert_raw( - &Cookie::build(("local", local)) - .domain("localhost") - .expires(Expiration::Session) - .same_site(SameSite::Strict) - .build(), - &"http://localhost".parse()?, - ) - .with_kind(crate::ErrorKind::Network)?; - has_cookie = true; - } + let cookie = read_file_to_string(RegistryContext::LOCAL_AUTH_COOKIE_PATH).await; let url = if let Some(url) = self.registry_url.clone() { url - } else if has_cookie || !self.registry_hostname.is_empty() { + } else if cookie.is_ok() || !self.registry_hostname.is_empty() { let mut url: Url = format!( "http://{}", self.registry_listen.unwrap_or(DEFAULT_REGISTRY_LISTEN) @@ -201,7 +186,8 @@ impl CallRemote for CliContext { .parse() .map_err(Error::from)?; url.path_segments_mut() - .map_err(|_| Error::new(eyre!("cannot extend URL path"), ErrorKind::ParseUrl))? + .map_err(|_| eyre!("Url cannot be base")) + .with_kind(crate::ErrorKind::ParseUrl)? .push("rpc") .push("v0"); url @@ -211,6 +197,26 @@ impl CallRemote for CliContext { ); }; + if let Ok(local) = cookie { + let cookie_url = match url.host() { + Some(url::Host::Ipv4(ip)) if ip.is_loopback() => url.clone(), + Some(url::Host::Ipv6(ip)) if ip.is_loopback() => url.clone(), + _ => format!("http://{DEFAULT_REGISTRY_LISTEN}").parse()?, + }; + self.cookie_store + .lock() + .unwrap() + .insert_raw( + &Cookie::build(("local", local)) + .domain(cookie_url.host_str().unwrap_or("localhost")) + .expires(Expiration::Session) + .same_site(SameSite::Strict) + .build(), + &cookie_url, + ) + .with_kind(crate::ErrorKind::Network)?; + } + method = method.strip_prefix("registry.").unwrap_or(method); let sig_context = self .registry_hostname @@ -302,17 +308,14 @@ impl SignatureAuthContext for RegistryContext { pubkey: Option<&AnyVerifyingKey>, metadata: Self::AdditionalMetadata, ) -> Result { - if metadata.admin { - if let Some(pubkey) = pubkey { - let (guid, admin) = db.as_index().as_signers().get_signer_info(pubkey)?; - if db.as_admins().de()?.contains(&guid) { - return Ok(Some((pubkey.clone(), admin))); - } + if let Some(pubkey) = pubkey { + let (guid, admin) = db.as_index().as_signers().get_signer_info(pubkey)?; + if !metadata.admin || db.as_admins().de()?.contains(&guid) { + return Ok(Some((pubkey.clone(), admin))); } - Err(Error::new(eyre!("UNAUTHORIZED"), ErrorKind::Authorization)) - } else { - Ok(None) } + + Err(Error::new(eyre!("UNAUTHORIZED"), ErrorKind::Authorization)) } async fn post_auth_hook( &self, diff --git a/core/startos/src/registry/info.rs b/core/startos/src/registry/info.rs index c80057a13..5d18885e4 100644 --- a/core/startos/src/registry/info.rs +++ b/core/startos/src/registry/info.rs @@ -19,6 +19,7 @@ pub fn info_api() -> ParentHandler> { ParentHandler::>::new() .root_handler( from_fn_async(get_info) + .with_metadata("authenticated", Value::Bool(false)) .with_display_serializable() .with_about("Display registry name, icon, and package categories") .with_call_remote::(), diff --git a/core/startos/src/registry/os/asset/get.rs b/core/startos/src/registry/os/asset/get.rs index 604b4dad4..5904e9b0d 100644 --- a/core/startos/src/registry/os/asset/get.rs +++ b/core/startos/src/registry/os/asset/get.rs @@ -24,21 +24,36 @@ use crate::util::io::{AtomicFile, open_file}; pub fn get_api() -> ParentHandler { ParentHandler::new() - .subcommand("iso", from_fn_async(get_iso).no_cli()) + .subcommand( + "iso", + from_fn_async(get_iso) + .with_metadata("authenticated", Value::Bool(false)) + .no_cli(), + ) .subcommand( "iso", from_fn_async(cli_get_os_asset) .no_display() .with_about("Download iso"), ) - .subcommand("img", from_fn_async(get_img).no_cli()) + .subcommand( + "img", + from_fn_async(get_img) + .with_metadata("authenticated", Value::Bool(false)) + .no_cli(), + ) .subcommand( "img", from_fn_async(cli_get_os_asset) .no_display() .with_about("Download img"), ) - .subcommand("squashfs", from_fn_async(get_squashfs).no_cli()) + .subcommand( + "squashfs", + from_fn_async(get_squashfs) + .with_metadata("authenticated", Value::Bool(false)) + .no_cli(), + ) .subcommand( "squashfs", from_fn_async(cli_get_os_asset) diff --git a/core/startos/src/registry/os/mod.rs b/core/startos/src/registry/os/mod.rs index 3c2b95864..d4d308281 100644 --- a/core/startos/src/registry/os/mod.rs +++ b/core/startos/src/registry/os/mod.rs @@ -1,6 +1,7 @@ use rpc_toolkit::{Context, HandlerExt, ParentHandler, from_fn_async}; use crate::context::CliContext; +use crate::prelude::*; use crate::util::serde::HandlerExtSerde; pub const SIG_CONTEXT: &str = "startos"; @@ -14,6 +15,7 @@ pub fn os_api() -> ParentHandler { .subcommand( "index", from_fn_async(index::get_os_index) + .with_metadata("authenticated", Value::Bool(false)) .with_display_serializable() .with_about("List index of OS versions") .with_call_remote::(), diff --git a/core/startos/src/registry/os/version/mod.rs b/core/startos/src/registry/os/version/mod.rs index 29105d577..d6b68652f 100644 --- a/core/startos/src/registry/os/version/mod.rs +++ b/core/startos/src/registry/os/version/mod.rs @@ -45,6 +45,7 @@ pub fn version_api() -> ParentHandler { .subcommand( "get", from_fn_async(get_version) + .with_metadata("authenticated", Value::Bool(false)) .with_metadata("get_device_info", Value::Bool(true)) .with_display_serializable() .with_custom_display_fn(|handle, result| { diff --git a/core/startos/src/registry/os/version/signer.rs b/core/startos/src/registry/os/version/signer.rs index eab8215a3..a668e1c17 100644 --- a/core/startos/src/registry/os/version/signer.rs +++ b/core/startos/src/registry/os/version/signer.rs @@ -35,6 +35,7 @@ pub fn signer_api() -> ParentHandler { .subcommand( "list", from_fn_async(list_version_signers) + .with_metadata("authenticated", Value::Bool(false)) .with_display_serializable() .with_custom_display_fn(|handle, result| display_signers(handle.params, result)) .with_about("List version signers and related signer info") diff --git a/core/startos/src/registry/package/category.rs b/core/startos/src/registry/package/category.rs index 92d9e7f99..131ab42f2 100644 --- a/core/startos/src/registry/package/category.rs +++ b/core/startos/src/registry/package/category.rs @@ -50,6 +50,7 @@ pub fn category_api() -> ParentHandler { .subcommand( "list", from_fn_async(list_categories) + .with_metadata("authenticated", Value::Bool(false)) .with_display_serializable() .with_custom_display_fn(|params, categories| { display_categories(params.params, categories) diff --git a/core/startos/src/registry/package/mod.rs b/core/startos/src/registry/package/mod.rs index b8bd7d506..d868c4364 100644 --- a/core/startos/src/registry/package/mod.rs +++ b/core/startos/src/registry/package/mod.rs @@ -15,6 +15,7 @@ pub fn package_api() -> ParentHandler { .subcommand( "index", from_fn_async(index::get_package_index) + .with_metadata("authenticated", Value::Bool(false)) .with_display_serializable() .with_about("List packages and categories") .with_call_remote::(), diff --git a/core/startos/src/registry/package/signer.rs b/core/startos/src/registry/package/signer.rs index d577d1e7a..3ab73d521 100644 --- a/core/startos/src/registry/package/signer.rs +++ b/core/startos/src/registry/package/signer.rs @@ -36,6 +36,7 @@ pub fn signer_api() -> ParentHandler { .subcommand( "list", from_fn_async(list_package_signers) + .with_metadata("authenticated", Value::Bool(false)) .with_display_serializable() .with_custom_display_fn(|handle, result| { display_package_signers(handle.params, result)