~muirrum/hamlog

f19293316c0d71d421e8b75084eac1f91bbd208a — Cara Salter 10 months ago 1c3e3f2 master
autodiscover: Create CA cert autodiscovery server

Allows for TOFU-ish trusting of CA certificate
4 files changed, 103 insertions(+), 1 deletions(-)

M Cargo.lock
M Cargo.toml
A autodiscover/Cargo.toml
A autodiscover/src/main.rs
M Cargo.lock => Cargo.lock +12 -0
@@ 291,6 291,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"

[[package]]
name = "autodiscover"
version = "0.1.0"
dependencies = [
 "hyper 0.14.27",
 "serde",
 "tokio",
 "tokio-util",
 "toml 0.7.6",
]

[[package]]
name = "backtrace"
version = "0.3.68"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 3159,6 3170,7 @@ dependencies = [
 "libc",
 "mio 0.8.8",
 "num_cpus",
 "parking_lot 0.12.1",
 "pin-project-lite",
 "signal-hook-registry",
 "socket2",

M Cargo.toml => Cargo.toml +2 -1
@@ 1,5 1,6 @@
[workspace]
members= [
    "hamlogd",
    "libhamlog"
    "libhamlog",
    "autodiscover"
    ]

A autodiscover/Cargo.toml => autodiscover/Cargo.toml +14 -0
@@ 0,0 1,14 @@
[package]
name = "autodiscover"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
hyper={version="0.14", features=["full"]}
tokio = {version="1", features = ["full"]}

serde = {version="1", features=["derive"]}
toml = "0.7"
tokio-util = { version = "0.7.8", features = ["codec"] }

A autodiscover/src/main.rs => autodiscover/src/main.rs +75 -0
@@ 0,0 1,75 @@
use std::convert::Infallible;
use tokio::fs::File;
use std::fs::{self};
use std::net::SocketAddr;
use std::str::FromStr;
use std::sync::Arc;
use tokio_util::codec::{BytesCodec, FramedRead};
use hyper::{body, Request, Response, Server, Result, Body, Method, StatusCode};
use hyper::service::{make_service_fn, service_fn};
use serde::Deserialize;

type GenericError = Box<dyn std::error::Error + Send + Sync>;

static NOTFOUND: &[u8] = b"NOT FOUND";

#[derive(Deserialize, Clone)]
struct Configuration {
    pub cert_path: String,
    pub bind: String
}

#[tokio::main]
async fn main() {
    // TODO: set up configuration file
    let config = parse_config();
    let addr = SocketAddr::from_str(&config.bind).unwrap();  

    let make_service = make_service_fn(move |_| {
        let config = config.clone();

        async {
            Ok::<_, GenericError>(
            service_fn(move |req| {
                response_handler(req, config.to_owned())
            }))
        }
    });

    let server = Server::bind(&addr).serve(make_service);

    println!("Listening on: {}", addr.to_string());

    server.await.unwrap();
}

fn parse_config() -> Configuration {
        let config_str = fs::read_to_string("/etc/hamlogd/autodiscover.toml").unwrap();

        toml::from_str(&config_str).unwrap()
}

async fn response_handler(req: Request<Body>, config: Configuration) -> Result<Response<Body>> {
    match (req.method(), req.uri().path()) {
        (&Method::GET, "/cert.pem") => cert_send(config).await,
        (_, _) => Ok(not_found()),
    }
}

fn not_found() -> Response<Body> {
    Response::builder()
        .status(StatusCode::NOT_FOUND)
        .body(NOTFOUND.into())
        .unwrap()
}

async fn cert_send(config: Configuration) -> Result<Response<Body>> {
    println!("Cert path: {}", config.cert_path);
   if let Ok(file) = File::open(config.cert_path).await {
        let stream = FramedRead::new(file, BytesCodec::new());
        let body = Body::wrap_stream(stream);
        return Ok(Response::new(body));
   }

   Ok(not_found())
}