Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ingress: Require the l5d-dst-override header #992

Merged
merged 4 commits into from
Apr 29, 2021
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
6 changes: 4 additions & 2 deletions linkerd/app/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,15 @@ pub fn is_discovery_rejected(err: &(dyn std::error::Error + 'static)) -> bool {
}
}

pub fn http_request_l5d_override_dst_addr<B>(req: &http::Request<B>) -> Result<Addr, addr::Error> {
pub fn http_request_l5d_override_dst_name_addr<B>(
req: &http::Request<B>,
) -> Result<NameAddr, addr::Error> {
proxy::http::authority_from_header(req, DST_OVERRIDE_HEADER)
.ok_or_else(|| {
tracing::trace!("{} not in request headers", DST_OVERRIDE_HEADER);
addr::Error::InvalidHost
})
.and_then(|a| Addr::from_authority_and_default_port(&a, DEFAULT_PORT))
.and_then(|a| NameAddr::from_authority_with_default_port(&a, DEFAULT_PORT))
}

pub fn http_request_authority_addr<B>(req: &http::Request<B>) -> Result<Addr, addr::Error> {
Expand Down
13 changes: 2 additions & 11 deletions linkerd/app/inbound/src/target.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
use indexmap::IndexMap;
use linkerd_app_core::{
classify, dst, http_request_authority_addr, http_request_host_addr,
http_request_l5d_override_dst_addr, metrics, profiles,
classify, dst, http_request_authority_addr, http_request_host_addr, metrics, profiles,
proxy::{http, tap},
stack_tracing,
svc::{self, Param},
tls,
transport::{self, addrs::*},
transport_header::TransportHeader,
Addr, Conditional, Error, CANONICAL_DST_HEADER, DST_OVERRIDE_HEADER,
Addr, Conditional, Error, CANONICAL_DST_HEADER,
};
use std::{convert::TryInto, net::SocketAddr, str::FromStr, sync::Arc};
use tracing::debug;
Expand Down Expand Up @@ -323,14 +322,6 @@ impl<A> svc::stack::RecognizeRoute<http::Request<A>> for RequestTarget {
})
})
})
.or_else(|| {
http_request_l5d_override_dst_addr(req)
.ok()
.map(|override_addr| {
debug!("using {}", DST_OVERRIDE_HEADER);
override_addr
})
})
.or_else(|| http_request_authority_addr(req).ok())
.or_else(|| http_request_host_addr(req).ok())
.unwrap_or_else(|| self.accept.tcp.target_addr.into());
Expand Down
37 changes: 16 additions & 21 deletions linkerd/app/outbound/src/ingress.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use crate::{http, stack_labels, tcp, trace_labels, Config, Outbound};
use linkerd_app_core::{
config::{ProxyConfig, ServerConfig},
detect, discovery_rejected, drain, errors, http_request_l5d_override_dst_addr, http_tracing,
io, profiles,
detect, discovery_rejected, drain, errors, http_request_l5d_override_dst_name_addr,
http_tracing, io, profiles,
proxy::api_resolve::Metadata,
svc::{self, stack::Param},
tls,
transport::{self, ClientAddr, OrigDstAddr, Remote, ServerAddr},
Addr, AddrMatch, Conditional, Error,
transport::{self, OrigDstAddr, Remote, ServerAddr},
AddrMatch, Conditional, Error, NameAddr,
};
use std::convert::TryFrom;
use thiserror::Error;
Expand All @@ -30,7 +30,7 @@ impl Outbound<()> {
Service = impl svc::Service<I, Response = (), Error = Error, Future = impl Send>,
>
where
T: Param<OrigDstAddr> + Param<Remote<ClientAddr>> + Clone + Send + Sync + 'static,
T: Param<OrigDstAddr> + Clone + Send + Sync + 'static,
I: io::AsyncRead + io::AsyncWrite + io::PeerAddr + std::fmt::Debug + Send + Unpin + 'static,
N: svc::NewService<tcp::Endpoint, Service = NSvc> + Clone + Send + Sync + 'static,
NSvc: svc::Service<io::PrefixedIo<transport::metrics::SensorIo<I>>, Response = ()>
Expand Down Expand Up @@ -156,7 +156,7 @@ struct AllowHttpProfile(AddrMatch);

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
struct Target {
dst: Addr,
dst: NameAddr,
version: http::Version,
}

Expand All @@ -169,8 +169,8 @@ impl svc::stack::Predicate<Target> for AllowHttpProfile {
type Request = profiles::LookupAddr;

fn check(&mut self, Target { dst, .. }: Target) -> Result<profiles::LookupAddr, Error> {
if self.0.matches(&dst) {
Ok(profiles::LookupAddr(dst))
if self.0.names().matches(dst.name()) {
Ok(profiles::LookupAddr(dst.into()))
} else {
Err(discovery_rejected().into())
}
Expand All @@ -185,14 +185,10 @@ impl TryFrom<(Option<profiles::Receiver>, Target)> for http::Logical {
(profile, Target { dst, version }): (Option<profiles::Receiver>, Target),
) -> Result<Self, Self::Error> {
let profile = profile.ok_or(ProfileRequired)?;
let logical_addr = profile.borrow().addr.clone().ok_or(ProfileRequired)?;

// XXX This is a hack to fix caching when an dst-override is set.
let orig_dst = if let Some(a) = dst.socket_addr() {
OrigDstAddr(a)
} else {
OrigDstAddr(([0, 0, 0, 0], dst.port()).into())
};
let logical_addr = profile.borrow().addr.clone().ok_or(ProfileRequired)?;
let orig_dst = OrigDstAddr(([0, 0, 0, 0], dst.port()).into());

Ok(Self {
orig_dst,
Expand All @@ -206,11 +202,7 @@ impl TryFrom<(Option<profiles::Receiver>, Target)> for http::Logical {
impl From<(tls::NoClientTls, Target)> for http::Endpoint {
fn from((reason, Target { dst, version }): (tls::NoClientTls, Target)) -> Self {
// XXX This is a hack to fix caching when an dst-override is set.
let addr = if let Some(a) = dst.socket_addr() {
Remote(ServerAddr(a))
} else {
Remote(ServerAddr(([0, 0, 0, 0], dst.port()).into()))
};
let addr = Remote(ServerAddr(([0, 0, 0, 0], dst.port()).into()));

Self {
addr,
Expand All @@ -234,8 +226,7 @@ impl<B> svc::stack::RecognizeRoute<http::Request<B>> for TargetPerRequest {
type Key = Target;

fn recognize(&self, req: &http::Request<B>) -> Result<Self::Key, Error> {
let dst =
http_request_l5d_override_dst_addr(req).unwrap_or_else(|_| self.0.orig_dst.0.into());
let dst = http_request_l5d_override_dst_name_addr(req).map_err(|_| DstOverrideRequired)?;
Ok(Target {
dst,
version: self.0.protocol,
Expand All @@ -248,3 +239,7 @@ impl<B> svc::stack::RecognizeRoute<http::Request<B>> for TargetPerRequest {
#[derive(Debug, Error)]
#[error("ingress routing requires a service profile")]
struct ProfileRequired;

#[derive(Debug, Error)]
#[error("ingress routing requires the l5d-dst-override header")]
struct DstOverrideRequired;
Comment on lines +244 to +245
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could maybe be worth having the error indicate whether the header was missing or malformed? but, that would take a somewhat larger change, so it's not a blocker.