Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 24 additions & 64 deletions iroh-gateway/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 5 additions & 2 deletions iroh-gateway/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ edition = "2021"

[dependencies]
axum = "0.7.2"
axum-server = { version = "0.6.0", features = ["tls-rustls", "tokio-rustls"] }
tokio = { version = "1", features = ["full"] }
headers = { version = "0.4" }
hyper = "1"
Expand All @@ -26,4 +25,8 @@ futures = "0.3.29"
lru = "0.12.1"
tracing-subscriber = "0.3.18"
indicatif = "0.17.7"
rustls = "0.22.1"
rustls = "0.21"
tokio-rustls-acme = { version = "0.2.0", features = ["axum"] }
hyper-util = "0.1.2"
rustls-pemfile = "1.0.2"
tower-service = "0.3.2"
41 changes: 33 additions & 8 deletions iroh-gateway/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,18 @@ use std::path::PathBuf;

use clap::Parser;

#[derive(clap::ValueEnum, Debug, Clone, Copy, PartialEq, Eq)]
pub enum CertMode {
/// No certificates at all, we serve http.
None,
/// Use a self-signed certificate in the cert_path directory.
Manual,
/// Use a letsencrypt certificate, in staging mode.
LetsEncryptStaging,
/// Use a letsencrypt certificate, in production mode.
LetsEncrypt,
}

#[derive(Parser, Debug)]
pub struct Args {
/// Ticket for the default node.
Expand All @@ -15,19 +27,32 @@ pub struct Args {
pub default_node: Option<String>,

/// Http or https listen addr.
///
///
/// Will listen on http if cert_path is not specified, https otherwise.
#[clap(long, default_value = "0.0.0.0:8080")]
pub addr: String,

/// Https certificate path.
///
/// If this is specified, the server will listen on https.
/// The path should be a directory containing `cert.pem` and `key.pem`.
#[clap(long)]
pub cert_path: Option<PathBuf>,

/// Magic port for the node, random if not specified.
#[clap(long)]
pub magic_port: Option<u16>,

/// Certificate mode, default is none.
#[clap(long, default_value = "None")]
pub cert_mode: CertMode,

/// Hostnames for letsencrypt.
#[clap(long, required_if_eq_any([("cert_mode", "LetsEncryptStaging"), ("cert_mode", "LetsEncrypt")]))]
pub hostname: Vec<String>,

/// Contact email for letsencrypt.
#[clap(long, required_if_eq_any([("cert_mode", "LetsEncryptStaging"), ("cert_mode", "LetsEncrypt")]))]
pub contact: Option<String>,

/// Certificate path.
///
/// Not needed if cert_mode is None.
/// In manual mode, this is the directory containing the cert.pem and key.pem files.
/// In letsencrypt mode, this is the directory used by the acme acceptor.
#[clap(long, required_if_eq_any([("cert_mode", "LetsEncryptStaging"), ("cert_mode", "LetsEncrypt"), ("cert_mode", "Manual")]))]
pub cert_path: Option<PathBuf>,
}
37 changes: 37 additions & 0 deletions iroh-gateway/src/cert_util.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//! Utilities for loading certificates and keys.
use anyhow::{Context, Result};
use std::path::Path;

pub fn load_certs(filename: impl AsRef<Path>) -> Result<Vec<rustls::Certificate>> {
println!("loading certs from {}", filename.as_ref().display());
let certfile = std::fs::File::open(filename).context("cannot open certificate file")?;
let mut reader = std::io::BufReader::new(certfile);

let certs = rustls_pemfile::certs(&mut reader)?
.iter()
.map(|v| rustls::Certificate(v.clone()))
.collect();

Ok(certs)
}

pub fn load_secret_key(filename: impl AsRef<Path>) -> Result<rustls::PrivateKey> {
println!("loading secret key from {}", filename.as_ref().display());
let keyfile = std::fs::File::open(filename.as_ref()).context("cannot open secret key file")?;
let mut reader = std::io::BufReader::new(keyfile);

loop {
match rustls_pemfile::read_one(&mut reader).context("cannot parse secret key .pem file")? {
Some(rustls_pemfile::Item::RSAKey(key)) => return Ok(rustls::PrivateKey(key)),
Some(rustls_pemfile::Item::PKCS8Key(key)) => return Ok(rustls::PrivateKey(key)),
Some(rustls_pemfile::Item::ECKey(key)) => return Ok(rustls::PrivateKey(key)),
None => break,
_ => {}
}
}

anyhow::bail!(
"no keys found in {} (encrypted keys not supported)",
filename.as_ref().display()
);
}
Loading