From 83463fcdefe9b52f1d74a94f321ca6c167c1686c Mon Sep 17 00:00:00 2001 From: Igor Novgorodov Date: Wed, 12 Jun 2024 13:06:34 +0000 Subject: [PATCH] refactor domain resolving a bit, add API domains --- .github/workflows/build.yml | 5 +- src/cli.rs | 4 + src/core.rs | 6 +- src/http/mod.rs | 2 +- src/http/server.rs | 4 +- src/metrics/mod.rs | 8 +- src/routing/domain.rs | 425 +++++++++++++++-------------- src/routing/middleware/validate.rs | 9 +- src/routing/mod.rs | 11 +- src/tls/cert/storage.rs | 4 +- src/tls/mod.rs | 4 +- 11 files changed, 253 insertions(+), 229 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ac06c69..9c134a6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,7 +10,10 @@ env: jobs: build: - runs-on: ubuntu-latest + runs-on: bazel-runner-small + container: + image: ghcr.io/catthehacker/ubuntu:full-22.04 + permissions: contents: write diff --git a/src/cli.rs b/src/cli.rs index 6a2a629..78dd2ed 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -190,6 +190,10 @@ pub struct Domain { #[clap(env, long, value_delimiter = ',')] pub domain: Vec, + /// List of domains that will serve only IC API (no HTTP) + #[clap(env, long, value_delimiter = ',')] + pub domain_api: Vec, + /// List of domains that we serve system subnets from. This enables domain-canister matching for these domains & adds them to the list of served domains above, do not list them there separately. /// Requires --domain-app. #[clap(env, long, requires = "domain_app", value_delimiter = ',')] diff --git a/src/core.rs b/src/core.rs index 56b07ab..ec537ca 100644 --- a/src/core.rs +++ b/src/core.rs @@ -23,15 +23,16 @@ pub async fn main(cli: &Cli) -> Result<(), Error> { let mut domains = cli.domain.domain.clone(); domains.extend_from_slice(&cli.domain.domain_system); domains.extend_from_slice(&cli.domain.domain_app); + domains.extend_from_slice(&cli.domain.domain_api); if domains.is_empty() { return Err(anyhow!( - "No domains to serve specified (use --domain/--domain-system/--domain-app)" + "No domains to serve specified (use --domain* args)" )); } // Leave only unique domains - domains = domains.into_iter().unique().collect::>(); + domains = domains.into_iter().unique().collect(); warn!( "Running with domains: {:?}", @@ -86,7 +87,6 @@ pub async fn main(cli: &Cli) -> Result<(), Error> { // Create routers let https_router = routing::setup_router( cli, - domains, custom_domain_providers, &mut tasks, http_client.clone(), diff --git a/src/http/mod.rs b/src/http/mod.rs index 353fc46..370c7ab 100644 --- a/src/http/mod.rs +++ b/src/http/mod.rs @@ -21,7 +21,7 @@ pub use server::{ConnInfo, Server}; pub const ALPN_H1: &[u8] = b"http/1.1"; pub const ALPN_H2: &[u8] = b"h2"; -pub const ACME_TLS_ALPN_NAME: &[u8] = b"acme-tls/1"; +pub const ALPN_ACME: &[u8] = b"acme-tls/1"; // Calculate very approximate HTTP request/response headers size in bytes. // More or less accurate only for http/1.1 since in h2 headers are in HPACK-compressed. diff --git a/src/http/server.rs b/src/http/server.rs index ee3b548..3f56802 100644 --- a/src/http/server.rs +++ b/src/http/server.rs @@ -33,7 +33,7 @@ use tower_service::Service; use tracing::{debug, warn}; use uuid::Uuid; -use super::{AsyncCounter, Stats, ACME_TLS_ALPN_NAME}; +use super::{AsyncCounter, Stats, ALPN_ACME}; pub const CONN_DURATION_BUCKETS: &[f64] = &[1.0, 8.0, 32.0, 64.0, 256.0, 512.0, 1024.0]; pub const CONN_REQUESTS: &[f64] = &[1.0, 4.0, 8.0, 16.0, 32.0, 64.0, 256.0]; @@ -298,7 +298,7 @@ impl Conn { if tls_info .alpn .as_ref() - .map(|x| x.as_bytes() == ACME_TLS_ALPN_NAME) + .map(|x| x.as_bytes() == ALPN_ACME) .unwrap_or(false) { debug!("{}: ACME ALPN - closing connection", self); diff --git a/src/metrics/mod.rs b/src/metrics/mod.rs index 810b355..962460b 100644 --- a/src/metrics/mod.rs +++ b/src/metrics/mod.rs @@ -35,7 +35,7 @@ use crate::{ log::clickhouse::{Clickhouse, Row}, routing::{ error_cause::ErrorCause, ic::IcResponseStatus, middleware::request_id::RequestId, - RequestCtx, + CanisterId, RequestCtx, }, tasks::{Run, TaskManager}, tls::sessions, @@ -320,6 +320,7 @@ pub async fn middleware( let duration = start.elapsed(); let ctx = response.extensions().get::>().cloned(); + let canister_id = response.extensions().get::().cloned(); let error_cause = response.extensions().get::().cloned(); let ic_status = response.extensions().get::().cloned(); let status = response.status().as_u16(); @@ -382,9 +383,8 @@ pub async fn middleware( let host = uri.host().unwrap_or(""); let path = uri.path(); - let canister_id = ctx - .as_ref() - .and_then(|x| x.domain.canister_id.map(|v| v.to_string())) + let canister_id = canister_id + .map(|x| x.0.to_string()) .unwrap_or_else(|| "unknown".into()); let conn_rcvd = conn_info.traffic.rcvd(); diff --git a/src/routing/domain.rs b/src/routing/domain.rs index 7d9407c..450ee07 100644 --- a/src/routing/domain.rs +++ b/src/routing/domain.rs @@ -4,7 +4,8 @@ use anyhow::{anyhow, Context, Error}; use arc_swap::ArcSwapOption; use async_trait::async_trait; use candid::Principal; -use fqdn::{Fqdn, FQDN}; +use derive_new::new; +use fqdn::{fqdn, Fqdn, FQDN}; use tokio::select; use tokio_util::sync::CancellationToken; use tracing::warn; @@ -19,9 +20,29 @@ macro_rules! principal { }}; } +/// Domain entity with certain metadata +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct Domain { + pub name: FQDN, + // Whether it's custom domain + pub custom: bool, + // Whether we serve HTTP on this domain + pub http: bool, + // Whether we serve IC API on this domain + pub api: bool, +} + +/// Result of a domain lookup +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct DomainLookup { + pub domain: Domain, + pub canister_id: Option, + pub verify: bool, +} + // Resolves hostname to a canister id pub trait ResolvesDomain: Send + Sync { - fn resolve(&self, host: &Fqdn) -> Option; + fn resolve(&self, host: &Fqdn) -> Option; } #[derive(Clone, Debug, PartialEq, Eq)] @@ -36,11 +57,6 @@ pub trait ProvidesCustomDomains: Sync + Send { async fn get_custom_domains(&self) -> Result, Error>; } -// Looks up custom domain canister id by hostname -pub trait LooksupCustomDomain: Sync + Send { - fn lookup_custom_domain(&self, hostname: &Fqdn) -> Option; -} - // Alias for a canister under all served domains. // E.g. an alias 'nns' would resolve under both 'nns.ic0.app' and 'nns.icp0.io' #[derive(Clone)] @@ -70,14 +86,10 @@ impl FromStr for CanisterAlias { } } -struct CustomDomainStorageInner { - // BTreeMap seems to be faster than HashMap - // for smaller datasets due to cache locality - custom_domains: BTreeMap, -} +struct CustomDomainStorageInner(BTreeMap); // Custom domain storage -#[derive(derive_new::new)] +#[derive(new)] pub struct CustomDomainStorage { providers: Vec>, poll_interval: Duration, @@ -92,11 +104,23 @@ impl CustomDomainStorage { buf.push(p.get_custom_domains().await?); } - let inner = CustomDomainStorageInner { - custom_domains: BTreeMap::from_iter( - buf.into_iter().flatten().map(|x| (x.name.clone(), x)), - ), - }; + let domains = buf.into_iter().flatten().map(|x| { + ( + x.name.clone(), + DomainLookup { + domain: Domain { + name: x.name, + custom: true, + http: true, + api: true, + }, + canister_id: Some(x.canister_id), + verify: true, + }, + ) + }); + + let inner = CustomDomainStorageInner(BTreeMap::from_iter(domains)); self.inner.store(Some(Arc::new(inner))); Ok(()) @@ -125,87 +149,101 @@ impl Run for CustomDomainStorage { } } -// Implement looking up custom domain canister id by hostname -impl LooksupCustomDomain for CustomDomainStorage { - fn lookup_custom_domain(&self, hostname: &Fqdn) -> Option { - self.inner - .load_full()? - .custom_domains - .get(hostname) - .cloned() +/// Implement looking up custom domain by hostname +impl ResolvesDomain for CustomDomainStorage { + fn resolve(&self, host: &Fqdn) -> Option { + self.inner.load_full()?.0.get(host).cloned() } } -// Combination of canister id and whether we need to verify the response -#[derive(Clone, Debug, Eq, PartialEq)] -pub struct Domain { - pub name: FQDN, - pub canister_id: Option, - pub verify: bool, - // Whether it's custom domain - pub custom: bool, -} - pub struct DomainResolver { - domains: Vec, - aliases: Vec<(FQDN, Domain)>, - custom_domains: Arc, + domains_base: Vec, + domains_all: BTreeMap, + custom_domains: Arc, } impl DomainResolver { pub fn new( - domains: Vec, - aliases_in: Vec, - custom_domains: Arc, - ) -> Result { - let mut aliases = vec![]; - // Generate a list of all alias+domain combinations - for a in aliases_in { - for d in &domains { - aliases.push(( - FQDN::from_str(&format!("{}.{d}", a.0))?, - Domain { - name: d.clone(), - canister_id: Some(a.1), - verify: true, - custom: false, - }, - )); + domains_base: Vec, + domains_api: Vec, + aliases: Vec, + custom_domains: Arc, + ) -> Self { + fn domain(f: &Fqdn, http: bool) -> Domain { + Domain { + name: f.into(), + custom: false, + http, + api: true, } } - Ok(Self { - domains, - aliases, - custom_domains, - }) - } + let domains_base = domains_base + .into_iter() + .map(|x| domain(&x, true)) + .collect::>(); + + let domains_api = domains_api + .into_iter() + .map(|x| domain(&x, false)) + .collect::>(); + + // Generate all alias+base_domain combinations + let aliases = aliases.into_iter().flat_map(|alias| { + domains_base.iter().map(move |domain| { + ( + // FQDN.FQDN is a valid FQDN, so macro is safe + fqdn!(&format!("{}.{}", alias.0, domain.name)), + DomainLookup { + domain: domain.clone(), + canister_id: Some(alias.1), + verify: true, + }, + ) + }) + }); - // Iterate over aliases and see if given host is a subdomain of any. - // Host is a subdomain of itself also so 'nns.ic0.app' will match the alias 'nns' and domain 'ic0.app'. - // This will also match any subdomains of the alias - TODO discuss - fn resolve_alias(&self, host: &Fqdn) -> Option { - self.aliases - .iter() - .find(|x| host.is_subdomain_of(&x.0)) - .map(|x| x.1.clone()) + let domains_all = domains_base + .clone() + .into_iter() + .chain(domains_api) + .map(|x| { + ( + x.name.clone(), + DomainLookup { + domain: x, + canister_id: None, + verify: true, + }, + ) + }) + .chain(aliases); + + Self { + domains_all: BTreeMap::from_iter(domains_all), + domains_base, + custom_domains, + } } // Tries to find the base domain that corresponds to the given host and resolve a canister id - // Expects . or .raw. where can have - // an optional prefix of `--` which is discarded - fn resolve_domain(&self, host: &Fqdn) -> Option { + fn resolve_domain(&self, host: &Fqdn) -> Option { + // First try to find an exact match + // This covers base domains and their aliases, plus API domains + if let Some(v) = self.domains_all.get(host) { + return Some(v.clone()); + } + + // Next we try to lookup dynamic subdomains like .ic0.app or .raw.ic0.app // Check if the host is a subdomain of any of our base domains. - // The host is also a subdomain of itself, so they can be equal. - let name = self - .domains + let domain = self + .domains_base .iter() - .find(|&x| host.is_subdomain_of(x))? - .to_owned(); + .find(|&x| host.is_subdomain_of(&x.name))?; // Host can be 1 or 2 levels below base domain only: . or .raw. // Fail the lookup if it's deeper. - let depth = host.labels().count() - name.labels().count(); + let depth = host.labels().count() - domain.name.labels().count(); if depth > 2 { return None; } @@ -220,34 +258,24 @@ impl DomainResolver { // the base subdomain is not raw or . // TODO discuss let canister_id = if depth == 1 || (depth == 2 && raw) { - Principal::from_text(label).ok() + Principal::from_text(label).ok()? } else { - None + return None; }; - Some(Domain { - name, - canister_id, + Some(DomainLookup { + domain: domain.clone(), + canister_id: Some(canister_id), verify: !raw, - custom: false, }) } } impl ResolvesDomain for DomainResolver { - fn resolve(&self, host: &Fqdn) -> Option { + fn resolve(&self, host: &Fqdn) -> Option { // Try to resolve canister using different sources - self.resolve_alias(host) - .or_else(|| self.resolve_domain(host)) - .or_else(|| { - let custom = self.custom_domains.lookup_custom_domain(host)?; - Some(Domain { - name: host.to_owned(), - canister_id: Some(custom.canister_id), - verify: true, - custom: true, - }) - }) + self.resolve_domain(host) + .or_else(|| self.custom_domains.resolve(host)) } } @@ -310,194 +338,177 @@ mod test { .map(|x| CanisterAlias::from_str(x).unwrap()) .collect::>(); - let domains = vec![fqdn!("ic0.app"), fqdn!("icp0.io"), fqdn!("foo")]; + let domains_base = vec![fqdn!("ic0.app"), fqdn!("icp0.io")]; + let domains_api = vec![fqdn!("icp-api.io")]; let custom_domain_provider = TestCustomDomainProvider(CustomDomain { name: fqdn!("foo.baz"), canister_id: principal!(TEST_CANISTER_ID), }); + let custom_domain_storage = CustomDomainStorage::new(vec![Arc::new(custom_domain_provider)], Duration::ZERO); custom_domain_storage.refresh().await?; + let resolver = DomainResolver::new( - domains.clone(), + domains_base.clone(), + domains_api, aliases.clone(), Arc::new(custom_domain_storage), - )?; + ); // Check aliases - for d in &domains { + for d in &domains_base { // Ensure all aliases resolve with all domains for a in &aliases { assert_eq!( - resolver.resolve_alias(&fqdn!(&format!("{}.{d}", a.0))), - Some(Domain { - name: d.clone(), + resolver.resolve(&fqdn!(&format!("{}.{d}", a.0))), + Some(DomainLookup { + domain: Domain { + name: d.clone(), + custom: false, + http: true, + api: true, + }, canister_id: Some(a.1), verify: true, - custom: false, }) ); } - // Ensure that non-existant aliases do not resolve + // Ensure that missing aliases do not resolve assert_eq!( - resolver.resolve_alias(&FQDN::from_str(&format!("foo.{d}"))?), + resolver.resolve(&FQDN::from_str(&format!("foo.{d}"))?), None ); - assert_eq!( - resolver.resolve_alias(&FQDN::from_str(&format!("bar.{d}"))?), + resolver.resolve(&FQDN::from_str(&format!("bar.{d}"))?), None ); } - // Check domains - let id = principal!("aaaaa-aa"); + // Check resolving + let canister_id = principal!("aaaaa-aa"); + let domain_ic0_app = Domain { + name: fqdn!("ic0.app"), + http: true, + api: true, + custom: false, + }; + let domain_icp0_io = Domain { + name: fqdn!("icp0.io"), + http: true, + api: true, + custom: false, + }; + let domain_icp_api_io = Domain { + name: fqdn!("icp-api.io"), + http: false, + api: true, + custom: false, + }; + let domain_foo_baz = Domain { + name: fqdn!("foo.baz"), + http: true, + api: true, + custom: true, + }; - // No canister ID + // Base domain, no canister ID assert_eq!( - resolver.resolve_domain(&fqdn!("ic0.app")), - Some(Domain { - name: fqdn!("ic0.app"), + resolver.resolve(&fqdn!("ic0.app")), + Some(DomainLookup { + domain: domain_ic0_app.clone(), canister_id: None, verify: true, - custom: false, }) ); - // Some subdomain + // API domain assert_eq!( - resolver.resolve_domain(&fqdn!("raw.ic0.app")), - Some(Domain { - name: fqdn!("ic0.app"), + resolver.resolve(&fqdn!("icp-api.io")), + Some(DomainLookup { + domain: domain_icp_api_io.clone(), canister_id: None, verify: true, - custom: false, }) ); - // Normal + // API domain with canister shouldn't resolve + assert_eq!(resolver.resolve(&fqdn!("aaaaa-aa.icp-api.io")), None); + + // Raw subdomain but w/o canister + assert_eq!(resolver.resolve(&fqdn!("raw.ic0.app")), None); + + // Base domain with canister assert_eq!( - resolver.resolve_domain(&fqdn!("aaaaa-aa.ic0.app")), - Some(Domain { - name: fqdn!("ic0.app"), - canister_id: Some(id), + resolver.resolve(&fqdn!("aaaaa-aa.ic0.app")), + Some(DomainLookup { + domain: domain_ic0_app.clone(), + canister_id: Some(canister_id), verify: true, - custom: false, }) ); + + // Another one assert_eq!( - resolver.resolve_domain(&fqdn!("aaaaa-aa.icp0.io")), - Some(Domain { - name: fqdn!("icp0.io"), - canister_id: Some(id), + resolver.resolve(&fqdn!("aaaaa-aa.icp0.io")), + Some(DomainLookup { + domain: domain_icp0_io.clone(), + canister_id: Some(canister_id), verify: true, - custom: false, }) ); // Raw assert_eq!( - resolver.resolve_domain(&fqdn!("aaaaa-aa.raw.ic0.app")), - Some(Domain { - name: fqdn!("ic0.app"), - canister_id: Some(id), + resolver.resolve(&fqdn!("aaaaa-aa.raw.ic0.app")), + Some(DomainLookup { + domain: domain_ic0_app.clone(), + canister_id: Some(canister_id), verify: false, - custom: false, }) ); assert_eq!( - resolver.resolve_domain(&fqdn!("aaaaa-aa.raw.icp0.io")), - Some(Domain { - name: fqdn!("icp0.io"), - canister_id: Some(id), + resolver.resolve(&fqdn!("aaaaa-aa.raw.icp0.io")), + Some(DomainLookup { + domain: domain_icp0_io.clone(), + canister_id: Some(canister_id), verify: false, - custom: false, }) ); + // Malformed canister shouldn't resolve + assert_eq!(resolver.resolve(&fqdn!("aaaaa-aaa.icp0.io")), None); + // foo-- assert_eq!( - resolver.resolve_domain(&fqdn!("foo--aaaaa-aa.ic0.app")), - Some(Domain { - name: fqdn!("ic0.app"), - canister_id: Some(id), + resolver.resolve(&fqdn!("foo--aaaaa-aa.ic0.app")), + Some(DomainLookup { + domain: domain_ic0_app.clone(), + canister_id: Some(canister_id), verify: true, - custom: false, }) ); - assert_eq!( - resolver.resolve_domain(&fqdn!("foo--bar--aaaaa-aa.ic0.app")), - Some(Domain { - name: fqdn!("ic0.app"), - canister_id: Some(id), + resolver.resolve(&fqdn!("foo--bar--aaaaa-aa.ic0.app")), + Some(DomainLookup { + domain: domain_ic0_app.clone(), + canister_id: Some(canister_id), verify: true, - custom: false, }) ); // Nested subdomain should not match canister id (?) - assert_eq!( - resolver.resolve_domain(&fqdn!("aaaaa-aa.foo.ic0.app")), - Some(Domain { - name: fqdn!("ic0.app"), - canister_id: None, - verify: true, - custom: false, - }) - ); - assert_eq!( - resolver.resolve_domain(&fqdn!("aaaaa-aa.foo.icp0.io")), - Some(Domain { - name: fqdn!("icp0.io"), - canister_id: None, - verify: true, - custom: false, - }) - ); - - // Check the trait - // Resolve from alias - assert_eq!( - resolver.resolve(&fqdn!("nns.ic0.app")), - Some(Domain { - canister_id: Some(principal!("qoctq-giaaa-aaaaa-aaaea-cai")), - name: fqdn!("ic0.app"), - verify: true, - custom: false, - }) - ); - - // Resolve from hostname - assert_eq!( - resolver.resolve(&fqdn!("aaaaa-aa.ic0.app")), - Some(Domain { - name: fqdn!("ic0.app"), - canister_id: Some(id), - verify: true, - custom: false, - }) - ); - - assert_eq!( - resolver.resolve(&fqdn!("aaaaa-aa.raw.ic0.app")), - Some(Domain { - name: fqdn!("ic0.app"), - canister_id: Some(id), - verify: false, - custom: false, - }) - ); + assert_eq!(resolver.resolve(&fqdn!("aaaaa-aa.foo.ic0.app")), None); + assert_eq!(resolver.resolve(&fqdn!("aaaaa-aa.foo.icp0.io")), None); // Resolve custom domain assert_eq!( resolver.resolve(&fqdn!("foo.baz")), - Some(Domain { - name: fqdn!("foo.baz"), + Some(DomainLookup { + domain: domain_foo_baz.clone(), canister_id: Some(principal!(TEST_CANISTER_ID)), verify: true, - custom: true, }) ); diff --git a/src/routing/middleware/validate.rs b/src/routing/middleware/validate.rs index b935523..8c0a792 100644 --- a/src/routing/middleware/validate.rs +++ b/src/routing/middleware/validate.rs @@ -23,12 +23,12 @@ pub async fn middleware( }; // Resolve the domain - let domain = resolver + let lookup = resolver .resolve(&authority) .ok_or(ErrorCause::UnknownDomain)?; // Inject canister_id separately if it was resolved - if let Some(v) = domain.canister_id { + if let Some(v) = lookup.canister_id { request.extensions_mut().insert(CanisterId(v)); } @@ -36,7 +36,8 @@ pub async fn middleware( // TODO remove Arc? let ctx = Arc::new(RequestCtx { authority, - domain: domain.clone(), + domain: lookup.domain.clone(), + verify: lookup.verify, }); request.extensions_mut().insert(ctx.clone()); @@ -45,7 +46,7 @@ pub async fn middleware( // Inject the same into the response response.extensions_mut().insert(ctx); - if let Some(v) = domain.canister_id { + if let Some(v) = lookup.canister_id { response.extensions_mut().insert(CanisterId(v)); } diff --git a/src/routing/mod.rs b/src/routing/mod.rs index de46383..2fe9491 100644 --- a/src/routing/mod.rs +++ b/src/routing/mod.rs @@ -59,6 +59,7 @@ pub struct RequestCtx { // HTTP2 authority or HTTP1 Host header pub authority: FQDN, pub domain: Domain, + pub verify: bool, } impl RequestCtx { @@ -88,7 +89,6 @@ pub async fn redirect_to_https( pub fn setup_router( cli: &Cli, - domains: Vec, custom_domain_providers: Vec>, tasks: &mut TaskManager, http_client: Arc, @@ -102,11 +102,16 @@ pub fn setup_router( tasks.add("custom_domain_storage", custom_domain_storage.clone()); // Prepare domain resolver to resolve domains & infer canister_id from requests + let mut domains_base = cli.domain.domain.clone(); + domains_base.extend_from_slice(&cli.domain.domain_app); + domains_base.extend_from_slice(&cli.domain.domain_system); + let domain_resolver = Arc::new(DomainResolver::new( - domains, + domains_base, + cli.domain.domain_api.clone(), cli.domain.domain_canister_alias.clone(), custom_domain_storage, - )?) as Arc; + )) as Arc; // GeoIP let geoip_mw = cli diff --git a/src/tls/cert/storage.rs b/src/tls/cert/storage.rs index 39136a5..647093c 100644 --- a/src/tls/cert/storage.rs +++ b/src/tls/cert/storage.rs @@ -8,7 +8,7 @@ use fqdn::{Fqdn, FQDN}; use rustls::{server::ClientHello, sign::CertifiedKey}; use super::Cert; -use crate::{http::ACME_TLS_ALPN_NAME, tls::resolver}; +use crate::{http::ALPN_ACME, tls::resolver}; pub trait StoresCertificates: Send + Sync { fn store(&self, cert_list: Vec>) -> Result<(), Error>; @@ -94,7 +94,7 @@ impl resolver::ResolvesServerCert for StorageKey { // we don't break ACME challenge if ch .alpn() - .map(|mut x| x.all(|x| x == ACME_TLS_ALPN_NAME)) + .map(|mut x| x.all(|x| x == ALPN_ACME)) .unwrap_or(false) { return None; diff --git a/src/tls/mod.rs b/src/tls/mod.rs index a11dfd4..f79261f 100644 --- a/src/tls/mod.rs +++ b/src/tls/mod.rs @@ -22,7 +22,7 @@ use rustls::{ use crate::{ cli::Cli, - http::{dns::Resolves, Client, ACME_TLS_ALPN_NAME, ALPN_H1, ALPN_H2}, + http::{dns::Resolves, Client, ALPN_ACME, ALPN_H1, ALPN_H2}, routing::domain::ProvidesCustomDomains, tasks::TaskManager, tls::{ @@ -224,7 +224,7 @@ pub async fn setup( certificate_resolver, tls_session_storage, if cli.acme.acme_challenge == Some(Challenge::Alpn) { - vec![ACME_TLS_ALPN_NAME.to_vec()] + vec![ALPN_ACME.to_vec()] } else { vec![] },