Skip to content

Commit c482c53

Browse files
authored
grpc-xds: add virtual-host domain matching (#2871)
## Motivation Ref: #2754 For gRFC A74 XdsDependencyManager, to resolve the channel's virtual host, we'll need to run string matching per Envoy `StringMatcher` spec. ## Solution To reduce the size of the upcoming A74 PR, I'm sending this `StringMatcher` PR first. The implementation mostly follows the design we used in `tonic-xds`, with these highlights: 1. Since the same string matching logic is shared between the virtual host selection and A29 SAN matching for mTLS, we extracted a common `StringMatcher` validated resource type and a pure `matcher` module. 2. Used the Rust idiomatic "new type" pattern for `DomainMatchScore` and `SafeRegex`: the former encapsulate the match ordering semantics, and the latter to reject empty regex pattern and conform to the "only match the entire input" Envoy spec.
1 parent 3aec51b commit c482c53

13 files changed

Lines changed: 1368 additions & 193 deletions

File tree

‎grpc-xds/build.rs‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@
3737
//! instead of colliding.
3838
3939
use std::collections::BTreeMap;
40-
use std::path::{Path, PathBuf};
40+
use std::path::Path;
41+
use std::path::PathBuf;
4142

4243
fn main() {
4344
let manifest = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap());

‎grpc-xds/rustfmt.toml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
imports_granularity = "Item"

‎grpc-xds/src/lib.rs‎

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,23 +38,26 @@
3838
unused,
3939
clippy::all
4040
)]
41-
pub(crate) mod generated {
41+
mod generated {
4242
include!(concat!(env!("OUT_DIR"), "/generated/mod.rs"));
4343
}
4444

4545
/// Validated xDS resource types (LDS/RDS/CDS/EDS), each implementing
4646
/// `xds_client::Resource` so they can be deserialized, named, and validated
4747
/// per their respective gRFCs (A27 core resource types, A28 route matching,
4848
/// A37 aggregate clusters).
49-
pub(crate) mod resource;
49+
mod resource;
50+
51+
/// Pure routing utilities.
52+
mod routing;
5053

5154
/// xDS load balancing policies (gRFC A31 and friends), plus
5255
/// [`load_balancing::register`] to install them in the gRPC LB registry.
5356
mod load_balancing;
5457

5558
/// [`xds_config::XdsConfig`]: the atomic xDS configuration snapshot assembled
5659
/// from a channel's Listener/RouteConfiguration/Cluster/Endpoints resources.
57-
pub(crate) mod xds_config;
60+
mod xds_config;
5861

5962
#[cfg(test)]
6063
mod tests {
@@ -66,10 +69,10 @@ mod tests {
6669
//! `generated` module is `pub(crate)` — doctests compile as an external
6770
//! crate and can only reach the public API.
6871
69-
use crate::generated::envoy::config::{
70-
cluster::v3::Cluster, endpoint::v3::ClusterLoadAssignment, listener::v3::Listener,
71-
route::v3::RouteConfiguration,
72-
};
72+
use crate::generated::envoy::config::cluster::v3::Cluster;
73+
use crate::generated::envoy::config::endpoint::v3::ClusterLoadAssignment;
74+
use crate::generated::envoy::config::listener::v3::Listener;
75+
use crate::generated::envoy::config::route::v3::RouteConfiguration;
7376

7477
/// Encodes then decodes a message. `serialize` / `parse` are methods of the
7578
/// `protobuf::Message` trait (in scope via the `M: protobuf::Message` bound).

‎grpc-xds/src/resource/cluster.rs‎

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,13 @@
2525
//! Validated Cluster resource (CDS).
2626
2727
use protobuf::Parse;
28+
use xds_client::Error;
29+
use xds_client::Resource;
2830
use xds_client::resource::TypeUrl;
29-
use xds_client::{Error, Resource};
3031

32+
use crate::generated::envoy::config::cluster::v3::Cluster;
33+
use crate::generated::envoy::config::cluster::v3::cluster::ClusterDiscoveryTypeOneof;
3134
use crate::generated::envoy::config::cluster::v3::cluster::DiscoveryType;
32-
use crate::generated::envoy::config::cluster::v3::{Cluster, cluster::ClusterDiscoveryTypeOneof};
3335
use crate::generated::envoy::extensions::clusters::aggregate::v3::ClusterConfig as AggregateClusterConfig;
3436

3537
/// Extension name and `typed_config` type for gRFC A37 aggregate clusters.
@@ -262,15 +264,16 @@ fn validate_aggregate_discovery(
262264
#[cfg(test)]
263265
mod tests {
264266
use super::*;
265-
use crate::generated::envoy::config::cluster::v3::cluster::{
266-
CustomClusterType, EdsClusterConfig,
267-
};
268-
use crate::generated::envoy::config::core::v3::{
269-
Address, AggregatedConfigSource, ConfigSource, SocketAddress,
270-
};
271-
use crate::generated::envoy::config::endpoint::v3::{
272-
ClusterLoadAssignment, Endpoint, LbEndpoint, LocalityLbEndpoints,
273-
};
267+
use crate::generated::envoy::config::cluster::v3::cluster::CustomClusterType;
268+
use crate::generated::envoy::config::cluster::v3::cluster::EdsClusterConfig;
269+
use crate::generated::envoy::config::core::v3::Address;
270+
use crate::generated::envoy::config::core::v3::AggregatedConfigSource;
271+
use crate::generated::envoy::config::core::v3::ConfigSource;
272+
use crate::generated::envoy::config::core::v3::SocketAddress;
273+
use crate::generated::envoy::config::endpoint::v3::ClusterLoadAssignment;
274+
use crate::generated::envoy::config::endpoint::v3::Endpoint;
275+
use crate::generated::envoy::config::endpoint::v3::LbEndpoint;
276+
use crate::generated::envoy::config::endpoint::v3::LocalityLbEndpoints;
274277
use protobuf::Serialize;
275278
use protobuf_well_known_types::Any;
276279

‎grpc-xds/src/resource/endpoint.rs‎

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,17 @@
2424

2525
//! Validated ClusterLoadAssignment resource (EDS).
2626
27-
use std::collections::{HashMap, HashSet};
27+
use std::collections::HashMap;
28+
use std::collections::HashSet;
2829

2930
use protobuf::Parse;
31+
use xds_client::Error;
32+
use xds_client::Resource;
3033
use xds_client::resource::TypeUrl;
31-
use xds_client::{Error, Resource};
3234

3335
use crate::generated::envoy::config::core::v3::HealthStatus as EnvoyHealthStatus;
34-
use crate::generated::envoy::config::endpoint::v3::{
35-
ClusterLoadAssignment, lb_endpoint::HostIdentifierOneof,
36-
};
36+
use crate::generated::envoy::config::endpoint::v3::ClusterLoadAssignment;
37+
use crate::generated::envoy::config::endpoint::v3::lb_endpoint::HostIdentifierOneof;
3738

3839
/// Validated ClusterLoadAssignment (EDS resource).
3940
#[derive(Debug, Clone)]
@@ -315,12 +316,12 @@ impl EndpointsResource {
315316
#[cfg(test)]
316317
mod tests {
317318
use super::*;
318-
use crate::generated::envoy::config::core::v3::{
319-
Address, Locality as EnvoyLocality, SocketAddress,
320-
};
321-
use crate::generated::envoy::config::endpoint::v3::{
322-
Endpoint, LbEndpoint as EnvoyLbEndpoint, LocalityLbEndpoints as EnvoyLocalityLbEndpoints,
323-
};
319+
use crate::generated::envoy::config::core::v3::Address;
320+
use crate::generated::envoy::config::core::v3::Locality as EnvoyLocality;
321+
use crate::generated::envoy::config::core::v3::SocketAddress;
322+
use crate::generated::envoy::config::endpoint::v3::Endpoint;
323+
use crate::generated::envoy::config::endpoint::v3::LbEndpoint as EnvoyLbEndpoint;
324+
use crate::generated::envoy::config::endpoint::v3::LocalityLbEndpoints as EnvoyLocalityLbEndpoints;
324325
use protobuf::Serialize;
325326
use protobuf_well_known_types::UInt32Value;
326327

‎grpc-xds/src/resource/listener.rs‎

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@ use std::sync::Arc;
2828

2929
use protobuf::Parse;
3030
use protobuf_well_known_types::Any;
31+
use xds_client::Error;
32+
use xds_client::Resource;
3133
use xds_client::resource::TypeUrl;
32-
use xds_client::{Error, Resource};
3334

3435
use super::route::RouteConfigResource;
3536
use crate::generated::envoy::config::listener::v3::Listener;
@@ -161,13 +162,15 @@ impl ListenerResource {
161162
#[cfg(test)]
162163
mod tests {
163164
use super::*;
164-
use crate::generated::envoy::config::core::v3::{
165-
AggregatedConfigSource, ConfigSource, SelfConfigSource,
166-
};
165+
use crate::generated::envoy::config::core::v3::AggregatedConfigSource;
166+
use crate::generated::envoy::config::core::v3::ConfigSource;
167+
use crate::generated::envoy::config::core::v3::SelfConfigSource;
167168
use crate::generated::envoy::config::listener::v3::ApiListener;
168-
use crate::generated::envoy::config::route::v3::{
169-
Route, RouteAction, RouteConfiguration, RouteMatch, VirtualHost,
170-
};
169+
use crate::generated::envoy::config::route::v3::Route;
170+
use crate::generated::envoy::config::route::v3::RouteAction;
171+
use crate::generated::envoy::config::route::v3::RouteConfiguration;
172+
use crate::generated::envoy::config::route::v3::RouteMatch;
173+
use crate::generated::envoy::config::route::v3::VirtualHost;
171174
use crate::generated::envoy::extensions::filters::network::http_connection_manager::v3::Rds;
172175
use protobuf::Serialize;
173176

‎grpc-xds/src/resource/mod.rs‎

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,28 @@ mod cluster;
3636
mod endpoint;
3737
mod listener;
3838
mod route;
39+
mod safe_regex;
40+
mod string_matcher;
3941

40-
pub(crate) use cluster::{ClusterDiscovery, ClusterResource};
41-
pub(crate) use endpoint::{
42-
EndpointAddress, EndpointsResource, HealthStatus, LbEndpoint, Locality, LocalityLbEndpoints,
43-
};
44-
pub(crate) use listener::{ListenerResource, RouteSource};
45-
pub(crate) use route::{
46-
HeaderMatchSpecifier, HeaderMatcher, PathSpecifier, Route, RouteAction, RouteConfigResource,
47-
RouteMatch, StringMatcher, VirtualHost, WeightedCluster,
48-
};
42+
pub(crate) use cluster::ClusterDiscovery;
43+
pub(crate) use cluster::ClusterResource;
44+
pub(crate) use endpoint::EndpointAddress;
45+
pub(crate) use endpoint::EndpointsResource;
46+
pub(crate) use endpoint::HealthStatus;
47+
pub(crate) use endpoint::LbEndpoint;
48+
pub(crate) use endpoint::Locality;
49+
pub(crate) use endpoint::LocalityLbEndpoints;
50+
pub(crate) use listener::ListenerResource;
51+
pub(crate) use listener::RouteSource;
52+
pub(crate) use route::DomainMatcher;
53+
pub(crate) use route::HeaderMatchSpecifier;
54+
pub(crate) use route::HeaderMatcher;
55+
pub(crate) use route::PathSpecifier;
56+
pub(crate) use route::Route;
57+
pub(crate) use route::RouteAction;
58+
pub(crate) use route::RouteConfigResource;
59+
pub(crate) use route::RouteMatch;
60+
pub(crate) use route::VirtualHost;
61+
pub(crate) use route::WeightedCluster;
62+
pub(crate) use safe_regex::SafeRegex;
63+
pub(crate) use string_matcher::StringMatcher;

0 commit comments

Comments
 (0)