From 100b01e85916d57ebff2eb63c915e2c4d2801b47 Mon Sep 17 00:00:00 2001 From: Jonathan Davies Date: Thu, 12 Jan 2023 13:35:14 +0000 Subject: Implemented website hosting authorization endpoint. Fixes: #468 --- src/api/admin/api_server.rs | 48 +++++++++++++++++++++++++++++++++++++++++++++ src/api/admin/router.rs | 3 +++ 2 files changed, 51 insertions(+) (limited to 'src/api/admin') diff --git a/src/api/admin/api_server.rs b/src/api/admin/api_server.rs index 2d325fb1..7a534f32 100644 --- a/src/api/admin/api_server.rs +++ b/src/api/admin/api_server.rs @@ -77,6 +77,53 @@ impl AdminApiServer { .body(Body::empty())?) } + async fn handle_check_website_enabled( + &self, + req: Request, + ) -> Result, Error> { + let has_domain_header = req.headers().contains_key("domain"); + + if !has_domain_header { + return Err(Error::bad_request("No domain header found")); + } + + let domain = &req + .headers() + .get("domain") + .ok_or_internal_error("Could not parse domain header")?; + + let domain_string = String::from( + domain + .to_str() + .ok_or_bad_request("Invalid characters found in domain header")?, + ); + + let bucket_id = self + .garage + .bucket_helper() + .resolve_global_bucket_name(&domain_string) + .await? + .ok_or_else(|| HelperError::NoSuchBucket(domain_string))?; + + let bucket = self + .garage + .bucket_helper() + .get_existing_bucket(bucket_id) + .await?; + + let bucket_state = bucket.state.as_option().unwrap(); + let bucket_website_config = bucket_state.website_config.get(); + + match bucket_website_config { + Some(_v) => Ok(Response::builder() + .status(StatusCode::OK) + .body(Body::from("Bucket authorized for website hosting"))?), + None => Err(Error::bad_request( + "Bucket is not authorized for website hosting", + )), + } + } + fn handle_health(&self) -> Result, Error> { let health = self.garage.system.health(); @@ -174,6 +221,7 @@ impl ApiHandler for AdminApiServer { match endpoint { Endpoint::Options => self.handle_options(&req), + Endpoint::CheckWebsiteEnabled => self.handle_check_website_enabled(req).await, Endpoint::Health => self.handle_health(), Endpoint::Metrics => self.handle_metrics(), Endpoint::GetClusterStatus => handle_get_cluster_status(&self.garage).await, diff --git a/src/api/admin/router.rs b/src/api/admin/router.rs index 62e6abc3..0dcb1546 100644 --- a/src/api/admin/router.rs +++ b/src/api/admin/router.rs @@ -17,6 +17,7 @@ router_match! {@func #[derive(Debug, Clone, PartialEq, Eq)] pub enum Endpoint { Options, + CheckWebsiteEnabled, Health, Metrics, GetClusterStatus, @@ -91,6 +92,7 @@ impl Endpoint { let res = router_match!(@gen_path_parser (req.method(), path, query) [ OPTIONS _ => Options, + GET "/check" => CheckWebsiteEnabled, GET "/health" => Health, GET "/metrics" => Metrics, GET "/v0/status" => GetClusterStatus, @@ -136,6 +138,7 @@ impl Endpoint { pub fn authorization_type(&self) -> Authorization { match self { Self::Health => Authorization::None, + Self::CheckWebsiteEnabled => Authorization::None, Self::Metrics => Authorization::MetricsToken, _ => Authorization::AdminToken, } -- cgit v1.2.3 From 8e93d6997415d60ba5c371da8b27065a57254a8c Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Thu, 26 Jan 2023 17:26:32 +0100 Subject: More clippy fixes --- src/api/admin/api_server.rs | 2 +- src/api/admin/bucket.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/api/admin') diff --git a/src/api/admin/api_server.rs b/src/api/admin/api_server.rs index 7a534f32..a115d732 100644 --- a/src/api/admin/api_server.rs +++ b/src/api/admin/api_server.rs @@ -103,7 +103,7 @@ impl AdminApiServer { .bucket_helper() .resolve_global_bucket_name(&domain_string) .await? - .ok_or_else(|| HelperError::NoSuchBucket(domain_string))?; + .ok_or(HelperError::NoSuchBucket(domain_string))?; let bucket = self .garage diff --git a/src/api/admin/bucket.rs b/src/api/admin/bucket.rs index 65034852..e60f07ca 100644 --- a/src/api/admin/bucket.rs +++ b/src/api/admin/bucket.rs @@ -167,7 +167,7 @@ async fn bucket_info_results( let quotas = state.quotas.get(); let res = GetBucketInfoResult { - id: hex::encode(&bucket.id), + id: hex::encode(bucket.id), global_aliases: state .aliases .items() @@ -575,6 +575,6 @@ pub async fn handle_local_unalias_bucket( // ---- HELPER ---- fn parse_bucket_id(id: &str) -> Result { - let id_hex = hex::decode(&id).ok_or_bad_request("Invalid bucket id")?; + let id_hex = hex::decode(id).ok_or_bad_request("Invalid bucket id")?; Ok(Uuid::try_from(&id_hex).ok_or_bad_request("Invalid bucket id")?) } -- cgit v1.2.3 From 004bb5b4f1b2086914376265425fd46df5059db3 Mon Sep 17 00:00:00 2001 From: Jonathan Davies Date: Sun, 29 Jan 2023 01:16:04 +0000 Subject: api_server.rs: Adapted to use query string per Caddy upstream change. --- src/api/admin/api_server.rs | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) (limited to 'src/api/admin') diff --git a/src/api/admin/api_server.rs b/src/api/admin/api_server.rs index a115d732..dae42059 100644 --- a/src/api/admin/api_server.rs +++ b/src/api/admin/api_server.rs @@ -1,3 +1,4 @@ +use std::collections::HashMap; use std::net::SocketAddr; use std::sync::Arc; @@ -81,29 +82,32 @@ impl AdminApiServer { &self, req: Request, ) -> Result, Error> { - let has_domain_header = req.headers().contains_key("domain"); - - if !has_domain_header { - return Err(Error::bad_request("No domain header found")); + let query_params: HashMap = req + .uri() + .query() + .map(|v| { + url::form_urlencoded::parse(v.as_bytes()) + .into_owned() + .collect() + }) + .unwrap_or_else(HashMap::new); + + let has_domain_key = query_params.contains_key("domain"); + + if !has_domain_key { + return Err(Error::bad_request("No domain query string found")); } - let domain = &req - .headers() + let domain = query_params .get("domain") - .ok_or_internal_error("Could not parse domain header")?; - - let domain_string = String::from( - domain - .to_str() - .ok_or_bad_request("Invalid characters found in domain header")?, - ); + .ok_or_internal_error("Could not parse domain query string")?; let bucket_id = self .garage .bucket_helper() - .resolve_global_bucket_name(&domain_string) + .resolve_global_bucket_name(&domain) .await? - .ok_or(HelperError::NoSuchBucket(domain_string))?; + .ok_or(HelperError::NoSuchBucket(domain.to_string()))?; let bucket = self .garage -- cgit v1.2.3 From 9c354f0a8ff258872aa3a4b7c116e1d66815afd1 Mon Sep 17 00:00:00 2001 From: Jonathan Davies Date: Sun, 29 Jan 2023 20:27:15 +0000 Subject: Improved bucket authorization response strings. --- src/api/admin/api_server.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'src/api/admin') diff --git a/src/api/admin/api_server.rs b/src/api/admin/api_server.rs index dae42059..58dd38d8 100644 --- a/src/api/admin/api_server.rs +++ b/src/api/admin/api_server.rs @@ -119,12 +119,16 @@ impl AdminApiServer { let bucket_website_config = bucket_state.website_config.get(); match bucket_website_config { - Some(_v) => Ok(Response::builder() - .status(StatusCode::OK) - .body(Body::from("Bucket authorized for website hosting"))?), - None => Err(Error::bad_request( - "Bucket is not authorized for website hosting", - )), + Some(_v) => { + Ok(Response::builder() + .status(StatusCode::OK) + .body(Body::from(format!( + "Bucket '{domain}' is authorized for website hosting" + )))?) + } + None => Err(Error::bad_request(format!( + "Bucket '{domain}' is not authorized for website hosting" + ))), } } -- cgit v1.2.3 From 9ea154ae9c6b12175192419679ec1bc40da827d1 Mon Sep 17 00:00:00 2001 From: Jonathan Davies Date: Fri, 10 Mar 2023 14:45:18 +0000 Subject: admin/cluster.rs: Added rust_version. --- src/api/admin/cluster.rs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/api/admin') diff --git a/src/api/admin/cluster.rs b/src/api/admin/cluster.rs index 182a4f6f..98bf2b5a 100644 --- a/src/api/admin/cluster.rs +++ b/src/api/admin/cluster.rs @@ -20,6 +20,7 @@ pub async fn handle_get_cluster_status(garage: &Arc) -> Result, + rust_version: &'static str, db_engine: String, known_nodes: HashMap, layout: GetClusterLayoutResponse, -- cgit v1.2.3