fix registry auth

This commit is contained in:
Aiden McClelland
2025-12-18 11:31:30 -07:00
parent bf8ff84522
commit e7a38863ab
10 changed files with 69 additions and 42 deletions

View File

@@ -81,14 +81,15 @@ impl<C: Context> Middleware<C> for Auth<C> {
) -> 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
{
if m.authenticated {
err = Some(e);
}
} else {
return Ok(());
}
@@ -96,7 +97,7 @@ impl<C: Context> Middleware<C> for Auth<C> {
if let Some(e) = err {
return Err(e);
}
}
Ok(())
}
async fn process_rpc_response(&mut self, context: &C, response: &mut RpcResponse) {

View File

@@ -174,26 +174,11 @@ impl CallRemote<RegistryContext> for CliContext {
params: Value,
_: Empty,
) -> Result<Value, RpcError> {
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<RegistryContext> 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<RegistryContext> 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<Self::CheckPubkeyRes, Error> {
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) {
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)
}
}
async fn post_auth_hook(
&self,

View File

@@ -19,6 +19,7 @@ pub fn info_api<C: Context>() -> ParentHandler<C, WithIoFormat<Empty>> {
ParentHandler::<C, WithIoFormat<Empty>>::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::<CliContext>(),

View File

@@ -24,21 +24,36 @@ use crate::util::io::{AtomicFile, open_file};
pub fn get_api<C: Context>() -> ParentHandler<C> {
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)

View File

@@ -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<C: Context>() -> ParentHandler<C> {
.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::<CliContext>(),

View File

@@ -45,6 +45,7 @@ pub fn version_api<C: Context>() -> ParentHandler<C> {
.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| {

View File

@@ -35,6 +35,7 @@ pub fn signer_api<C: Context>() -> ParentHandler<C> {
.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")

View File

@@ -50,6 +50,7 @@ pub fn category_api<C: Context>() -> ParentHandler<C> {
.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)

View File

@@ -15,6 +15,7 @@ pub fn package_api<C: Context>() -> ParentHandler<C> {
.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::<CliContext>(),

View File

@@ -36,6 +36,7 @@ pub fn signer_api<C: Context>() -> ParentHandler<C> {
.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)