···141141 string addr = 1;
142142 // weight of this backend, if load-balancing
143143 optional uint64 weight = 2;
144144+145145+ // skip verifying certificates on tls backends
146146+ //
147147+ // useful if your backend certs are self-signed,
148148+ // or for some reason not valid for the backend itself.
149149+ //
150150+ // generally prefer to use `ca_path` instead.
151151+ bool skip_verifying_certs = 3;
152152+153153+ // path to the CA file used to verify the backend's certs, on tls backends
154154+ //
155155+ // useful if the backend is using self-signed certs
156156+ optional string ca_path = 4;
144157}
145158146159// a unix domain socket backend
+34-11
src/gateway.rs
···1010use http::{HeaderName, HeaderValue};
1111use pingora::lb::selection::consistent::KetamaHashing;
1212use pingora::prelude::*;
1313+use pingora::protocols::tls::CaType;
1314use url::Url;
14151516use crate::gateway::oidc::{InProgressAuth, SESSION_COOKIE_NAME, UserInfo};
···618619 StatusCode::SERVICE_UNAVAILABLE,
619620 ))?;
620621621621- let needs_tls = backend
622622+ let backend_data = backend
622623 .ext
623624 .get::<BackendData>()
624624- .map(|d| d.tls)
625625- .unwrap_or(true);
625625+ .cloned() // just some bools and an arc, it's fine
626626+ .unwrap_or_default();
626627627627- Ok(Box::new(HttpPeer::new(
628628- backend,
629629- needs_tls,
630630- backends.sni_name.to_string(),
631631- )))
628628+ let peer = match backend_data {
629629+ BackendData::HttpOnly => HttpPeer::new(backend, false, backends.sni_name.to_string()),
630630+ BackendData::Tls {
631631+ skip_verifying_cert,
632632+ ca,
633633+ } => {
634634+ let mut peer = HttpPeer::new(backend, true, backends.sni_name.to_string());
635635+ peer.options.verify_cert = !skip_verifying_cert;
636636+ peer.options.ca = ca;
637637+ peer
638638+ }
639639+ };
640640+ Ok(Box::new(peer))
632641 }
633642634643 async fn response_filter(
···663672///
664673/// for use in [`AuthGateway::upstream_peer`]
665674#[derive(Clone)]
666666-pub struct BackendData {
667667- /// does the backend want tls
668668- pub tls: bool,
675675+pub enum BackendData {
676676+ HttpOnly,
677677+ Tls {
678678+ /// should skip we verifying the cert (useful if the certs are selfsigned and we don't want to
679679+ /// have them loaded)
680680+ skip_verifying_cert: bool,
681681+ /// custom ca to use to verify backend certs
682682+ ca: Option<Arc<CaType>>,
683683+ },
684684+}
685685+impl Default for BackendData {
686686+ fn default() -> Self {
687687+ Self::Tls {
688688+ skip_verifying_cert: false,
689689+ ca: None,
690690+ }
691691+ }
669692}
+21-4
src/main.rs
···55use pingora::lb::selection::consistent::KetamaHashing;
66use pingora::listeners::tls::{BundleCert, CertAndKey, TlsSettings};
77use pingora::prelude::*;
88+use pingora::utils::tls::CertKey;
89910use self::gateway::{AuthGateway, BackendData, DomainInfo, oidc};
1011···3435 .iter()
3536 .map(|backend| {
3637 let mut ext = lb::Extensions::new();
3737- ext.insert(BackendData { tls: true });
3838+ let ca = backend.ca_path.as_ref().map(|path| {
3939+ // yikes pingora does not make this easy to construct
4040+ CertKey::new(
4141+ vec![std::fs::read(path).expect("unable to read ca path")],
4242+ vec![],
4343+ )
4444+ .into_certs()
4545+ });
4646+ ext.insert(BackendData::Tls {
4747+ skip_verifying_cert: backend.skip_verifying_certs,
4848+ ca,
4949+ });
3850 let mut backend = Backend::new_with_weight(
3951 &backend.addr,
4052 backend.weight.map(|w| w as usize).unwrap_or(1),
···4557 })
4658 .chain(domain.http.iter().map(|backend| {
4759 let mut ext = lb::Extensions::new();
4848- ext.insert(BackendData { tls: false });
6060+ ext.insert(BackendData::HttpOnly);
4961 let mut backend = Backend::new_with_weight(
5062 &backend.addr,
5163 backend.weight.map(|w| w as usize).unwrap_or(1),
···5668 }))
5769 .chain(domain.uds.iter().map(|backend| {
5870 let mut ext = lb::Extensions::new();
5959- ext.insert(BackendData { tls: false });
7171+ ext.insert(BackendData::HttpOnly);
6072 Ok(Backend {
6173 addr: SocketAddr::Unix(
6274 std::os::unix::net::SocketAddr::from_pathname(&backend.path)
···7688 balancer: svc.task(),
7789 tls_mode: config::format::domain::TlsMode::try_from(domain.tls_mode)
7890 .context("invalid tls mode")?,
7979- sni_name: name.clone(),
9191+ sni_name: domain
9292+ .tls
9393+ .as_ref()
9494+ .and_then(|d| d.sni.as_ref())
9595+ .unwrap_or(name)
9696+ .clone(),
8097 oidc: domain
8198 .oidc_auth
8299 .clone()