Skip to content

Commit

Permalink
Merge pull request #38 from dfinity/rjb/optionally-serve-http
Browse files Browse the repository at this point in the history
chore: first try to optionally serve all endpoints also on HTTP
  • Loading branch information
r-birkner authored Sep 25, 2024
2 parents 6cb2b75 + 9d3e931 commit 1d969ca
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 54 deletions.
4 changes: 4 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,10 @@ pub struct HttpServer {
/// Lifetime of a TLS1.3 ticket, due to key rotation the actual lifetime will be twice than this.
#[clap(env, long, default_value = "9h", value_parser = parse_duration)]
pub http_server_tls_ticket_lifetime: Duration,

/// Option to only serve HTTP instead for testing.
#[clap(env, long)]
pub http_server_insecure_serve_http_only: bool,
}

#[derive(Args)]
Expand Down
84 changes: 51 additions & 33 deletions src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,6 @@ pub async fn main(cli: &Cli) -> Result<(), Error> {
let reqwest_client = http::client::new(http_client_opts.clone())?;
let http_client = Arc::new(http::ReqwestClient::new(http_client_opts)?);

// TLS session cache
let tls_session_cache = Arc::new(sessions::Storage::new(
cli.http_server.http_server_tls_session_cache_size,
cli.http_server.http_server_tls_session_cache_tti,
));

// Event sinks
let clickhouse = if cli.log.clickhouse.log_clickhouse_url.is_some() {
Some(Arc::new(
Expand All @@ -103,23 +97,28 @@ pub async fn main(cli: &Cli) -> Result<(), Error> {
let handler_token = token.clone();
ctrlc::set_handler(move || handler_token.cancel())?;

// Prepare TLS related stuff
let (rustls_cfg, custom_domain_providers) = tls::setup(
cli,
&mut tasks,
domains.clone(),
http_client.clone(),
Arc::new(dns_resolver),
tls_session_cache.clone(),
&registry,
)
.await
.context("unable to setup TLS")?;
// TLS session cache
let tls_session_cache = Arc::new(sessions::Storage::new(
cli.http_server.http_server_tls_session_cache_size,
cli.http_server.http_server_tls_session_cache_tti,
));

// HTTP server metrics
let http_metrics = http::server::Metrics::new(&registry);

// Custom domains
let (issuer_certificate_providers, issuer_custom_domain_providers) =
tls::cert::providers::setup_issuer_providers(
cli,
&mut tasks,
http_client.clone(),
&registry,
);

// Create routers
let https_router = routing::setup_router(
// Create gateway router to serve all endpoints
let gateway_router = routing::setup_router(
cli,
custom_domain_providers,
issuer_custom_domain_providers,
&mut tasks,
http_client.clone(),
reqwest_client,
Expand All @@ -128,12 +127,15 @@ pub async fn main(cli: &Cli) -> Result<(), Error> {
vector.clone(),
)
.await?;
let http_router = Router::new().fallback(routing::redirect_to_https);

// HTTP server metrics
let http_metrics = http::server::Metrics::new(&registry);
// Set up HTTP router (redirecting to HTTPS or serving all endpoints)
let http_router = if !cli.http_server.http_server_insecure_serve_http_only {
Router::new().fallback(routing::redirect_to_https)
} else {
gateway_router.clone()
};

// Set up HTTP
// Create HTTP server
let http_server = Arc::new(http::Server::new(
http::server::Addr::Tcp(cli.http_server.http_server_listen_plain),
http_router,
Expand All @@ -143,14 +145,30 @@ pub async fn main(cli: &Cli) -> Result<(), Error> {
));
tasks.add("http_server", http_server);

let https_server = Arc::new(http::Server::new(
http::server::Addr::Tcp(cli.http_server.http_server_listen_tls),
https_router,
(&cli.http_server).into(),
http_metrics.clone(),
Some(rustls_cfg),
));
tasks.add("https_server", https_server);
// Create HTTPS server
if !cli.http_server.http_server_insecure_serve_http_only {
// Prepare TLS related stuff
let rustls_cfg = tls::setup(
cli,
&mut tasks,
domains.clone(),
Arc::new(dns_resolver),
issuer_certificate_providers,
tls_session_cache.clone(),
&registry,
)
.await
.context("unable to setup TLS")?;

let https_server = Arc::new(http::Server::new(
http::server::Addr::Tcp(cli.http_server.http_server_listen_tls),
gateway_router,
(&cli.http_server).into(),
http_metrics.clone(),
Some(rustls_cfg),
));
tasks.add("https_server", https_server);
}

// Setup metrics
if let Some(addr) = cli.metrics.metrics_listen {
Expand Down
34 changes: 34 additions & 0 deletions src/tls/cert/providers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ pub use dir::Provider as Dir;
pub use issuer::CertificatesImporter as Issuer;

use async_trait::async_trait;
use ic_bn_lib::{http::Client, tasks::TaskManager};
use prometheus::Registry;
use std::sync::Arc;

use crate::{cli::Cli, routing::domain::ProvidesCustomDomains};

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Pem {
Expand All @@ -18,3 +23,32 @@ pub struct Pem {
pub trait ProvidesCertificates: Sync + Send + std::fmt::Debug {
async fn get_certificates(&self) -> Result<Vec<Pem>, anyhow::Error>;
}

pub fn setup_issuer_providers(
cli: &Cli,
tasks: &mut TaskManager,
http_client: Arc<dyn Client>,
registry: &Registry,
) -> (
Vec<Arc<dyn ProvidesCertificates>>,
Vec<Arc<dyn ProvidesCustomDomains>>,
) {
let mut cert_providers: Vec<Arc<dyn ProvidesCertificates>> = vec![];
let mut custom_domain_providers: Vec<Arc<dyn ProvidesCustomDomains>> = vec![];

let issuer_metrics = issuer::Metrics::new(registry);
for v in &cli.cert.cert_provider_issuer_url {
let issuer = Arc::new(Issuer::new(
http_client.clone(),
v.clone(),
cli.cert.cert_provider_issuer_poll_interval,
issuer_metrics.clone(),
));

cert_providers.push(issuer.clone());
custom_domain_providers.push(issuer.clone());
tasks.add(&format!("{issuer:?}"), issuer);
}

(cert_providers, custom_domain_providers)
}
27 changes: 6 additions & 21 deletions src/tls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use anyhow::{anyhow, Context, Error};
use async_trait::async_trait;
use fqdn::FQDN;
use ic_bn_lib::{
http::{dns::Resolves, Client, ALPN_ACME, ALPN_H1, ALPN_H2},
http::{dns::Resolves, ALPN_ACME, ALPN_H1, ALPN_H2},
tasks::{Run, TaskManager},
tls::{
acme::{
Expand All @@ -31,7 +31,6 @@ use tokio_util::sync::CancellationToken;

use crate::{
cli::Cli,
routing::domain::ProvidesCustomDomains,
tls::{
cert::{providers, Aggregator},
resolver::AggregatingResolver,
Expand Down Expand Up @@ -136,40 +135,26 @@ pub async fn setup(
cli: &Cli,
tasks: &mut TaskManager,
domains: Vec<FQDN>,
http_client: Arc<dyn Client>,
dns_resolver: Arc<dyn Resolves>,
custom_domain_providers: Vec<Arc<dyn ProvidesCertificates>>,
tls_session_storage: Arc<dyn StoresServerSessions + Send + Sync>,
registry: &Registry,
) -> Result<(ServerConfig, Vec<Arc<dyn ProvidesCustomDomains>>), Error> {
) -> Result<ServerConfig, Error> {
// Prepare certificate storage
let cert_storage = Arc::new(storage::Storage::new(
cli.cert.cert_default.clone(),
storage::Metrics::new(registry),
));

let mut cert_providers: Vec<Arc<dyn ProvidesCertificates>> = vec![];
let mut custom_domain_providers: Vec<Arc<dyn ProvidesCustomDomains>> = vec![];

// Create Dir providers
for v in &cli.cert.cert_provider_dir {
cert_providers.push(Arc::new(providers::Dir::new(v.clone())));
}

// Create CertIssuer providers
// It's a custom domain & cert provider at the same time.
let issuer_metrics = providers::issuer::Metrics::new(registry);
for v in &cli.cert.cert_provider_issuer_url {
let issuer = Arc::new(providers::Issuer::new(
http_client.clone(),
v.clone(),
cli.cert.cert_provider_issuer_poll_interval,
issuer_metrics.clone(),
));

cert_providers.push(issuer.clone());
custom_domain_providers.push(issuer.clone());
tasks.add(&format!("{issuer:?}"), issuer);
}
// Add custom domain certificate providers
cert_providers.extend(custom_domain_providers);

// Prepare ACME if configured
let acme_resolver = if let Some(v) = &cli.acme.acme_challenge {
Expand Down Expand Up @@ -228,5 +213,5 @@ pub async fn setup(
registry,
);

Ok((config, custom_domain_providers))
Ok(config)
}

0 comments on commit 1d969ca

Please sign in to comment.