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
5 changes: 3 additions & 2 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2587,8 +2587,9 @@ dependencies = [

[[package]]
name = "linkerd2-proxy-api"
version = "0.14.0"
source = "git+https://github.com/linkerd/linkerd2-proxy-api.git?branch=main#6c316cc41a3a0e194a70f22b5698ec21ce245e99"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4682c00263191a5bfa4fbe64f6d80b22ff2b49aaa294da5aac062f5abc6eb9e"
dependencies = [
"h2",
"http",
Expand Down
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -91,5 +91,5 @@ debug = 1
lto = true

[workspace.dependencies]
#linkerd2-proxy-api = "0.14.0"
linkerd2-proxy-api = { git = "https://github.com/linkerd/linkerd2-proxy-api.git", branch = "main" }
linkerd2-proxy-api = "0.15.0"
# linkerd2-proxy-api = { git = "https://github.com/linkerd/linkerd2-proxy-api.git", branch = "main" }
4 changes: 2 additions & 2 deletions linkerd/app/integration/src/policy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,18 +162,18 @@ pub fn outbound_default_opaque_route(dst: impl ToString) -> outbound::OpaqueRout
metadata: Some(api::meta::Metadata {
kind: Some(api::meta::metadata::Kind::Default("default".to_string())),
}),
error: None,
rules: vec![outbound::opaque_route::Rule {
backends: Some(opaque_route::Distribution {
kind: Some(distribution::Kind::FirstAvailable(
distribution::FirstAvailable {
backends: vec![opaque_route::RouteBackend {
backend: Some(backend(dst)),
invalid: None,
filters: Vec::new(),
}],
},
)),
}),
filters: Vec::new(),
}],
}
}
Expand Down
4 changes: 2 additions & 2 deletions linkerd/app/outbound/src/opaq/logical/route/filters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ where
let filters: &[opaq::Filter] = &t.param();
if let Some(filter) = filters.iter().next() {
match filter {
opaq::Filter::ForbiddenRoute => {
opaq::Filter::Forbidden => {
return Err(errors::TCPForbiddenRoute.into());
}

opaq::Filter::InvalidBackend(message) => {
opaq::Filter::Invalid(message) => {
return Err(errors::TCPInvalidBackend(message.clone()).into());
}

Expand Down
4 changes: 2 additions & 2 deletions linkerd/app/outbound/src/tls/logical/route/filters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ where
let filters: &[tls::Filter] = &t.param();
if let Some(filter) = filters.iter().next() {
match filter {
tls::Filter::ForbiddenRoute => {
tls::Filter::Forbidden => {
return Err(errors::TLSForbiddenRoute.into());
}

tls::Filter::InvalidBackend(message) => {
tls::Filter::Invalid(message) => {
return Err(errors::TLSInvalidBackend(message.clone()).into());
Comment on lines -13 to 18
Copy link
Member Author

Choose a reason for hiding this comment

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

We can change the name of these error types to be more generic if we want to. We currently return Invalid only if backends are invalid and Forbidden only if a route is forbidden, so this seems fine as it is for now 🤷

}

Expand Down
73 changes: 35 additions & 38 deletions linkerd/proxy/client-policy/src/opaq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ pub struct NonIoErrors;

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum Filter {
ForbiddenRoute,
InvalidBackend(std::sync::Arc<str>),
Forbidden,
Invalid(std::sync::Arc<str>),
InternalError(&'static str),
}

Expand All @@ -31,15 +31,11 @@ pub(crate) mod proto {
use super::*;
use crate::{
proto::{BackendSet, InvalidBackend, InvalidDistribution, InvalidMeta},
Backend, Meta, RouteBackend, RouteDistribution,
Meta, RouteBackend, RouteDistribution,
};
use linkerd2_proxy_api::outbound::{self, opaque_route};

use once_cell::sync::Lazy;
use std::sync::Arc;

pub(crate) static NO_FILTERS: Lazy<Arc<[Filter]>> = Lazy::new(|| Arc::new([]));

#[derive(Debug, thiserror::Error)]
pub enum InvalidOpaqueRoute {
#[error("invalid route metadata: {0}")]
Expand All @@ -48,6 +44,9 @@ pub(crate) mod proto {
#[error("invalid distribution: {0}")]
Distribution(#[from] InvalidDistribution),

#[error("invalid filter: {0}")]
Filter(#[from] InvalidFilter),

/// Note: this restriction may be removed in the future, if a way of
/// actually matching rules for opaque routes is added.
#[error("an opaque route must have exactly one rule, but {0} were provided")]
Expand All @@ -65,6 +64,15 @@ pub(crate) mod proto {
Missing(&'static str),
}

#[derive(Debug, thiserror::Error)]
pub enum InvalidFilter {
#[error("invalid route error kind: {0}")]
InvalidRouteErrorKind(i32),

#[error("missing filter kind")]
Missing,
}

pub(crate) fn fill_route_backends(rts: Option<&Route>, set: &mut BackendSet) {
if let Some(Route { policy, .. }) = rts {
policy.distribution.fill_backends(set);
Expand All @@ -84,11 +92,7 @@ pub(crate) mod proto {
}

fn try_route(
outbound::OpaqueRoute {
metadata,
rules,
error,
}: outbound::OpaqueRoute,
outbound::OpaqueRoute { metadata, rules }: outbound::OpaqueRoute,
) -> Result<Route, InvalidOpaqueRoute> {
let meta = Arc::new(
metadata
Expand All @@ -104,23 +108,22 @@ pub(crate) mod proto {
}

let rule = rules.first().cloned().expect("already checked");
let policy = try_rule(&meta, rule, error)?;
let policy = try_rule(&meta, rule)?;
Ok(Route { policy })
}

fn try_rule(
meta: &Arc<Meta>,
opaque_route::Rule { backends }: opaque_route::Rule,
route_error: Option<opaque_route::RouteError>,
opaque_route::Rule { backends, filters }: opaque_route::Rule,
) -> Result<Policy, InvalidOpaqueRoute> {
let distribution = backends
.ok_or(InvalidOpaqueRoute::Missing("distribution"))?
.try_into()?;

let filters = match route_error {
Some(e) => Arc::new([e.into()]),
None => NO_FILTERS.clone(),
};
let filters = filters
.into_iter()
.map(Filter::try_from)
.collect::<Result<Arc<[_]>, _>>()?;

Ok(Policy {
meta: meta.clone(),
Expand Down Expand Up @@ -175,30 +178,24 @@ pub(crate) mod proto {
impl TryFrom<opaque_route::RouteBackend> for RouteBackend<Filter> {
type Error = InvalidBackend;
fn try_from(
opaque_route::RouteBackend { backend, invalid }: opaque_route::RouteBackend,
) -> Result<Self, Self::Error> {
opaque_route::RouteBackend { backend, filters }: opaque_route::RouteBackend,
) -> Result<RouteBackend<Filter>, InvalidBackend> {
let backend = backend.ok_or(InvalidBackend::Missing("backend"))?;

let backend = Backend::try_from(backend)?;

let filters = match invalid {
Some(invalid) => Arc::new([invalid.into()]),
None => NO_FILTERS.clone(),
};

Ok(RouteBackend { filters, backend })
RouteBackend::try_from_proto(backend, filters)
}
}

impl From<opaque_route::RouteError> for Filter {
fn from(_: opaque_route::RouteError) -> Self {
Self::ForbiddenRoute
}
}
impl TryFrom<opaque_route::Filter> for Filter {
type Error = InvalidFilter;

fn try_from(filter: opaque_route::Filter) -> Result<Self, Self::Error> {
use linkerd2_proxy_api::opaque_route::Invalid;
use opaque_route::filter::Kind;

impl From<opaque_route::route_backend::Invalid> for Filter {
fn from(ib: opaque_route::route_backend::Invalid) -> Self {
Self::InvalidBackend(ib.message.into())
match filter.kind.ok_or(InvalidFilter::Missing)? {
Kind::Invalid(Invalid { message }) => Ok(Filter::Invalid(message.into())),
Kind::Forbidden(_) => Ok(Filter::Forbidden),
}
}
}
}
68 changes: 34 additions & 34 deletions linkerd/proxy/client-policy/src/tls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ pub struct Tls {

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum Filter {
ForbiddenRoute,
InvalidBackend(Arc<str>),
Forbidden,
Invalid(Arc<str>),
InternalError(&'static str),
}

Expand Down Expand Up @@ -42,16 +42,12 @@ pub(crate) mod proto {
use super::*;
use crate::{
proto::{BackendSet, InvalidBackend, InvalidDistribution, InvalidMeta},
Backend, Meta, RouteBackend, RouteDistribution,
Meta, RouteBackend, RouteDistribution,
};
use linkerd2_proxy_api::outbound::{self, tls_route};
use linkerd_tls_route::sni::proto::InvalidSniMatch;

use once_cell::sync::Lazy;
use std::sync::Arc;

pub(crate) static NO_FILTERS: Lazy<Arc<[Filter]>> = Lazy::new(|| Arc::new([]));

#[derive(Debug, thiserror::Error)]
pub enum InvalidTlsRoute {
#[error("invalid sni match: {0}")]
Expand All @@ -63,6 +59,9 @@ pub(crate) mod proto {
#[error("invalid distribution: {0}")]
Distribution(#[from] InvalidDistribution),

#[error("invalid filter: {0}")]
Filter(#[from] InvalidFilter),

/// Note: this restriction may be removed in the future, if a way of
/// actually matching rules for TLS routes is added.
#[error("a TLS route must have exactly one rule, but {0} were provided")]
Expand All @@ -75,6 +74,15 @@ pub(crate) mod proto {
Missing(&'static str),
}

#[derive(Debug, thiserror::Error)]
pub enum InvalidFilter {
#[error("invalid route error kind: {0}")]
InvalidRouteErrorKind(i32),

#[error("missing filter kind")]
Missing,
}

impl TryFrom<outbound::proxy_protocol::Tls> for Tls {
type Error = InvalidTlsRoute;
fn try_from(proto: outbound::proxy_protocol::Tls) -> Result<Self, Self::Error> {
Expand All @@ -101,7 +109,6 @@ pub(crate) mod proto {
rules,
snis,
metadata,
error,
} = proto;
let meta = Arc::new(
metadata
Expand All @@ -123,7 +130,7 @@ pub(crate) mod proto {

let policy = rules
.into_iter()
.map(|rule| try_rule(&meta, rule, error.clone()))
.map(|rule| try_rule(&meta, rule))
.next()
.ok_or(InvalidTlsRoute::OnlyOneRule(0))??;

Expand All @@ -132,17 +139,16 @@ pub(crate) mod proto {

fn try_rule(
meta: &Arc<Meta>,
tls_route::Rule { backends }: tls_route::Rule,
route_error: Option<tls_route::RouteError>,
tls_route::Rule { backends, filters }: tls_route::Rule,
) -> Result<Policy, InvalidTlsRoute> {
let distribution = backends
.ok_or(InvalidTlsRoute::Missing("distribution"))?
.try_into()?;

let filters = match route_error {
Some(e) => Arc::new([e.into()]),
None => NO_FILTERS.clone(),
};
let filters = filters
.into_iter()
.map(Filter::try_from)
.collect::<Result<Arc<[_]>, _>>()?;

Ok(Policy {
meta: meta.clone(),
Expand Down Expand Up @@ -197,30 +203,24 @@ pub(crate) mod proto {
impl TryFrom<tls_route::RouteBackend> for RouteBackend<Filter> {
type Error = InvalidBackend;
fn try_from(
tls_route::RouteBackend { backend, invalid }: tls_route::RouteBackend,
) -> Result<Self, Self::Error> {
tls_route::RouteBackend { backend, filters }: tls_route::RouteBackend,
) -> Result<RouteBackend<Filter>, InvalidBackend> {
let backend = backend.ok_or(InvalidBackend::Missing("backend"))?;

let backend = Backend::try_from(backend)?;

let filters = match invalid {
Some(invalid) => Arc::new([invalid.into()]),
None => NO_FILTERS.clone(),
};

Ok(RouteBackend { filters, backend })
RouteBackend::try_from_proto(backend, filters)
}
}

impl From<tls_route::RouteError> for Filter {
fn from(_: tls_route::RouteError) -> Self {
Self::ForbiddenRoute
}
}
impl TryFrom<tls_route::Filter> for Filter {
type Error = InvalidFilter;

fn try_from(filter: tls_route::Filter) -> Result<Self, Self::Error> {
use linkerd2_proxy_api::opaque_route::Invalid;
use tls_route::filter::Kind;

impl From<tls_route::route_backend::Invalid> for Filter {
fn from(ib: tls_route::route_backend::Invalid) -> Self {
Self::InvalidBackend(ib.message.into())
match filter.kind.ok_or(InvalidFilter::Missing)? {
Kind::Invalid(Invalid { message }) => Ok(Filter::Invalid(message.into())),
Kind::Forbidden(_) => Ok(Filter::Forbidden),
}
}
}
}
Loading