From 130581d61e10bcf4a9e7c1716a6558e397dc6041 Mon Sep 17 00:00:00 2001
From: Brian Picciano
Date: Fri, 12 May 2023 18:17:23 +0200
Subject: [PATCH] got basic system for passing configs back and forth with URL
working
---
.env.dev | 1 +
src/main.rs | 12 +++-
src/service.rs | 89 +++++++++++++++++++++---
src/service/http_tpl/domain_get_new.html | 15 +++-
src/service/util.rs | 37 ++++++++++
5 files changed, 139 insertions(+), 15 deletions(-)
create mode 100644 src/service/util.rs
diff --git a/.env.dev b/.env.dev
index 6b342b6..bd57d5a 100644
--- a/.env.dev
+++ b/.env.dev
@@ -1,3 +1,4 @@
+export GATEWAY_PASSPHRASE=foobar
export GATEWAY_ORIGIN_STORE_GIT_DIR_PATH=/tmp/gateway_dev_env/origin/git
export GATEWAY_DOMAIN_CHECKER_TARGET_CNAME=gateway.example.com
export GATEWAY_DOMAIN_CONFIG_STORE_DIR_PATH=/tmp/gateway_dev_env/domain/config
diff --git a/src/main.rs b/src/main.rs
index 8bdec32..2faa18e 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -15,6 +15,9 @@ struct Cli {
#[arg(long, default_value_t = SocketAddr::from_str("127.0.0.1:3030").unwrap(), env = "GATEWAY_HTTP_LISTEN_ADDR")]
http_listen_addr: SocketAddr,
+ #[arg(long, required = true, env = "GATEWAY_PASSPHRASE")]
+ passphrase: String,
+
#[arg(long, required = true, env = "GATEWAY_ORIGIN_STORE_GIT_DIR_PATH")]
origin_store_git_dir_path: path::PathBuf,
@@ -59,7 +62,7 @@ async fn main() {
.expect("git origin store initialized");
let domain_checker = gateway::domain::checker::new(
- config.domain_checker_target_cname,
+ config.domain_checker_target_cname.clone(),
&config.domain_checker_resolver_addr,
)
.expect("domain checker initialized");
@@ -69,7 +72,12 @@ async fn main() {
let manager = gateway::domain::manager::new(origin_store, domain_config_store, domain_checker);
- let service = gateway::service::new(manager).expect("service initialized");
+ let service = gateway::service::new(
+ manager,
+ config.domain_checker_target_cname,
+ config.passphrase,
+ )
+ .expect("service initialized");
let (addr, server) =
warp::serve(service).bind_with_graceful_shutdown(config.http_listen_addr, async {
diff --git a/src/service.rs b/src/service.rs
index d62057c..d9e97e9 100644
--- a/src/service.rs
+++ b/src/service.rs
@@ -7,6 +7,7 @@ use warp::Filter;
use crate::domain;
pub mod http_tpl;
+mod util;
/*
* POST /domain/config (domain, config, secret, init?) -> token?
@@ -21,6 +22,9 @@ where
DM: domain::manager::Manager,
{
domain_manager: sync::Arc,
+ target_cname: sync::Arc,
+ passphrase: sync::Arc,
+
handlebars: Handlebars<'a>,
query_args: HashMap,
}
@@ -71,6 +75,8 @@ where
pub fn new(
manager: DM,
+ target_cname: domain::Name,
+ passphrase: String,
) -> Result<
impl warp::Filter + Clone + 'static,
Box,
@@ -79,12 +85,16 @@ where
DM: domain::manager::Manager + 'static,
{
let manager = sync::Arc::new(manager);
+ let target_cname = sync::Arc::new(target_cname);
+ let passphrase = sync::Arc::new(passphrase);
let hbs = sync::Arc::new(self::http_tpl::get()?);
let with_render_ctx = warp::any()
.and(warp::query::>())
.map(move |query_args: HashMap| RenderContext {
domain_manager: manager.clone(),
+ target_cname: target_cname.clone(),
+ passphrase: passphrase.clone(),
handlebars: hbs.clone(),
query_args,
});
@@ -111,28 +121,87 @@ where
domain: domain::Name,
}
+ #[derive(Serialize)]
+ struct DomainGetNewResponse {
+ domain: domain::Name,
+ config: Option,
+ }
+
let domain_get = warp::get()
.and(with_render_ctx.clone())
- .and(warp::path("domain.html"))
+ .and(warp::path!("domain.html"))
.and(warp::query::())
+ .and(warp::query::())
.map(
- move |render_ctx: RenderContext<'_, DM>, req: DomainGetNewRequest| {
- #[derive(Serialize)]
- struct DomainGetNewResponse {
- domain: domain::Name,
- }
-
+ |render_ctx: RenderContext<'_, DM>,
+ req: DomainGetNewRequest,
+ domain_config: util::ConfigFromURL| {
match render_ctx.domain_manager.get_config(&req.domain) {
Ok(_config) => panic!("TODO"),
Err(domain::manager::GetConfigError::NotFound) => render_page(
render_ctx,
String::from("/domain_get_new.html"),
- DomainGetNewResponse { domain: req.domain },
+ DomainGetNewResponse {
+ domain: req.domain,
+ config: domain_config.try_into().expect("TODO"),
+ },
),
- Err(_) => panic!("TODO"),
+ Err(domain::manager::GetConfigError::Unexpected(e)) => {
+ panic!("{}", e) // TODO
+ }
}
},
);
- Ok(static_dir.or(index).or(domain_get))
+ #[derive(Deserialize)]
+ struct DomainPostRequest {
+ _init: bool,
+ domain: domain::Name,
+ passphrase: String,
+ }
+
+ let domain_post = warp::post()
+ .and(with_render_ctx.clone())
+ .and(warp::path!("domain.html"))
+ .and(warp::query::())
+ .and(warp::query::())
+ .map(
+ |render_ctx: RenderContext<'_, DM>,
+ req: DomainPostRequest,
+ domain_config: util::ConfigFromURL| {
+ if req.passphrase != render_ctx.passphrase.as_str() {
+ panic!("TODO")
+ }
+
+ //if req.init {
+ #[derive(Serialize)]
+ struct Response {
+ domain: domain::Name,
+ config: domain::config::Config,
+ target_cname: domain::Name,
+ challenge_token: String,
+ }
+
+ let config: Option =
+ domain_config.try_into().expect("TODO");
+ let config = config.expect("TODO");
+
+ let config_hash = config.hash().expect("TODO");
+ let target_cname = (*render_ctx.target_cname).clone();
+
+ return render_page(
+ render_ctx,
+ String::from("/domain_post_init.html"),
+ Response {
+ domain: req.domain,
+ config: config,
+ target_cname: target_cname,
+ challenge_token: config_hash,
+ },
+ );
+ //}
+ },
+ );
+
+ Ok(static_dir.or(index).or(domain_get).or(domain_post))
}
diff --git a/src/service/http_tpl/domain_get_new.html b/src/service/http_tpl/domain_get_new.html
index 024676e..12a8a32 100644
--- a/src/service/http_tpl/domain_get_new.html
+++ b/src/service/http_tpl/domain_get_new.html
@@ -10,19 +10,25 @@ automatically updated too!
In the future Cosmux will support more backends than just git
repos.
-
diff --git a/src/service/util.rs b/src/service/util.rs
new file mode 100644
index 0000000..a93ea25
--- /dev/null
+++ b/src/service/util.rs
@@ -0,0 +1,37 @@
+use std::convert::TryFrom;
+
+use serde::Deserialize;
+
+use crate::{domain, origin};
+
+#[derive(Deserialize)]
+pub struct ConfigFromURL {
+ config_origin_descr_kind: Option,
+ config_origin_descr_git_url: Option,
+ config_origin_descr_git_branch_name: Option,
+}
+
+impl TryFrom for Option {
+ type Error = String;
+
+ fn try_from(v: ConfigFromURL) -> Result {
+ match v
+ .config_origin_descr_kind
+ .unwrap_or("".to_string())
+ .as_str()
+ {
+ "" => Ok(None),
+ "git" => Ok(Some(domain::config::Config {
+ origin_descr: origin::Descr::Git {
+ url: v
+ .config_origin_descr_git_url
+ .ok_or("config_origin_descr_git_url missing")?,
+ branch_name: v
+ .config_origin_descr_git_branch_name
+ .ok_or("config_origin_descr_git_branch_name missing")?,
+ },
+ })),
+ _ => Err("invalid config_origin_descr_kind".to_string()),
+ }
+ }
+}