Skip to content

Commit 384aa21

Browse files
authored
Split cryptographic dependencies into a dedicated crate (#1307)
The `ring`/`rustls`/`webpki` crates provide the cryptographic primitives that we use for the proxy's mTLS functionality. But there's a desire to support other cryptographic implementations (i.e. openssl/boringssl), especially for FIPS 140-2. This change introduces a new crate, `linkerd-tls-rustls`, into which all types that depend on `ring`/`rustls`/`webpki` are moved. Specifically, `Key`, `Crt`, and `CrtKey` are moved from `linkerd-identity` into `rustls`. The `linkerd-tls` crate becomes generic over its TLS implementation by using a `NewService` to build client connectors and a `Service` to terminate server-side TLS connections.
1 parent 66f2f03 commit 384aa21

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+970
-704
lines changed

Cargo.lock

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,7 @@ dependencies = [
689689
"linkerd-stack-tracing",
690690
"linkerd-system",
691691
"linkerd-tls",
692+
"linkerd-tls-rustls",
692693
"linkerd-trace-context",
693694
"linkerd-tracing",
694695
"linkerd-transport-header",
@@ -991,12 +992,6 @@ name = "linkerd-identity"
991992
version = "0.1.0"
992993
dependencies = [
993994
"linkerd-dns-name",
994-
"ring",
995-
"thiserror",
996-
"tokio-rustls",
997-
"tracing",
998-
"untrusted",
999-
"webpki",
1000995
]
1001996

1002997
[[package]]
@@ -1009,7 +1004,6 @@ dependencies = [
10091004
"linkerd-errno",
10101005
"pin-project",
10111006
"tokio",
1012-
"tokio-rustls",
10131007
"tokio-test",
10141008
"tokio-util",
10151009
]
@@ -1152,6 +1146,7 @@ dependencies = [
11521146
"linkerd-metrics",
11531147
"linkerd-stack",
11541148
"linkerd-tls",
1149+
"linkerd-tls-rustls",
11551150
"linkerd2-proxy-api",
11561151
"pin-project",
11571152
"thiserror",
@@ -1189,6 +1184,7 @@ dependencies = [
11891184
"linkerd-proxy-transport",
11901185
"linkerd-stack",
11911186
"linkerd-tls",
1187+
"linkerd-tls-rustls",
11921188
"linkerd2-proxy-api",
11931189
"parking_lot",
11941190
"pin-project",
@@ -1364,13 +1360,29 @@ dependencies = [
13641360
"linkerd-io",
13651361
"linkerd-proxy-transport",
13661362
"linkerd-stack",
1363+
"linkerd-tls-rustls",
13671364
"linkerd-tracing",
1365+
"pin-project",
13681366
"thiserror",
13691367
"tokio",
1370-
"tokio-rustls",
13711368
"tower",
13721369
"tracing",
13731370
"untrusted",
1371+
]
1372+
1373+
[[package]]
1374+
name = "linkerd-tls-rustls"
1375+
version = "0.1.0"
1376+
dependencies = [
1377+
"futures",
1378+
"linkerd-identity",
1379+
"linkerd-io",
1380+
"linkerd-stack",
1381+
"linkerd-tls",
1382+
"ring",
1383+
"thiserror",
1384+
"tokio-rustls",
1385+
"tracing",
13741386
"webpki",
13751387
]
13761388

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ members = [
5353
"linkerd/system",
5454
"linkerd/tonic-watch",
5555
"linkerd/tls",
56+
"linkerd/tls/rustls",
5657
"linkerd/tracing",
5758
"linkerd/transport-header",
5859
"linkerd/transport-metrics",

linkerd/app/admin/src/stack.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ use linkerd_app_core::{
22
classify,
33
config::ServerConfig,
44
detect, drain, errors,
5+
identity::LocalCrtKey,
56
metrics::{self, FmtMetrics},
6-
proxy::{http, identity::LocalCrtKey},
7+
proxy::http,
78
serve,
89
svc::{self, ExtractParam, InsertParam, Param},
910
tls, trace,

linkerd/app/core/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ linkerd-tracing = { path = "../../tracing" }
5858
linkerd-transport-header = { path = "../../transport-header" }
5959
linkerd-transport-metrics = { path = "../../transport-metrics" }
6060
linkerd-tls = { path = "../../tls" }
61+
linkerd-tls-rustls = { path = "../../tls/rustls" }
6162
linkerd-trace-context = { path = "../../trace-context" }
6263
regex = "1.5.4"
6364
serde_json = "1"

linkerd/app/core/src/control.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ impl Config {
5454
> + Clone,
5555
>
5656
where
57-
L: Clone + svc::Param<tls::client::Config> + Send + Sync + 'static,
57+
L: svc::NewService<tls::ClientTls, Service = linkerd_tls_rustls::Connect>,
58+
L: Clone + Send + Sync + 'static,
5859
{
5960
let addr = self.addr;
6061

linkerd/app/core/src/lib.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,14 @@ pub use linkerd_dns;
2020
pub use linkerd_error::{is_error, Error, Infallible, Recover, Result};
2121
pub use linkerd_exp_backoff as exp_backoff;
2222
pub use linkerd_http_metrics as http_metrics;
23-
pub use linkerd_identity as identity;
2423
pub use linkerd_io as io;
2524
pub use linkerd_opencensus as opencensus;
25+
pub use linkerd_proxy_identity as identity;
2626
pub use linkerd_service_profiles as profiles;
2727
pub use linkerd_stack_metrics as stack_metrics;
2828
pub use linkerd_stack_tracing as stack_tracing;
2929
pub use linkerd_tls as tls;
30+
pub use linkerd_tls_rustls as rustls;
3031
pub use linkerd_tracing as trace;
3132
pub use linkerd_transport_header as transport_header;
3233

@@ -56,7 +57,7 @@ const DEFAULT_PORT: u16 = 80;
5657

5758
#[derive(Clone, Debug)]
5859
pub struct ProxyRuntime {
59-
pub identity: proxy::identity::LocalCrtKey,
60+
pub identity: identity::LocalCrtKey,
6061
pub metrics: metrics::Proxy,
6162
pub tap: proxy::tap::Registry,
6263
pub span_sink: http_tracing::OpenCensusSink,

linkerd/app/core/src/proxy/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ pub use linkerd_proxy_core as core;
55
pub use linkerd_proxy_discover as discover;
66
pub use linkerd_proxy_dns_resolve as dns_resolve;
77
pub use linkerd_proxy_http as http;
8-
pub use linkerd_proxy_identity as identity;
98
pub use linkerd_proxy_resolve as resolve;
109
pub use linkerd_proxy_tap as tap;
1110
pub use linkerd_proxy_tcp as tcp;

linkerd/app/inbound/fuzz/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@ cargo-fuzz = true
1111

1212
[target.'cfg(fuzzing)'.dependencies]
1313
arbitrary = { version = "1", features = ["derive"] }
14-
libfuzzer-sys = { version = "0.4.2", features = ["arbitrary-derive"] }
15-
tokio = { version = "1", features = ["full"] }
1614
hyper = { version = "0.14.9", features = ["http1", "http2"] }
1715
http = "0.2"
16+
libfuzzer-sys = { version = "0.4.2", features = ["arbitrary-derive"] }
1817
linkerd-app-core = { path = "../../core" }
1918
linkerd-app-inbound = { path = ".." }
2019
linkerd-app-test = { path = "../../test" }
2120
linkerd-proxy-identity = { path = "../../../proxy/identity", features = ["test-util"] }
2221
linkerd-tracing = { path = "../../../tracing", features = ["ansi"] }
22+
tokio = { version = "1", features = ["full"] }
2323
tracing = "0.1"
2424

2525
# Prevent this from interfering with workspaces

linkerd/app/inbound/src/detect.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ use crate::{
44
};
55
use linkerd_app_core::{
66
detect, identity, io,
7-
proxy::{http, identity::LocalCrtKey},
8-
svc, tls,
7+
proxy::http,
8+
rustls, svc, tls,
99
transport::{
1010
self,
1111
addrs::{ClientAddr, OrigDstAddr, Remote},
@@ -50,9 +50,11 @@ struct ConfigureHttpDetect;
5050
#[derive(Clone)]
5151
struct TlsParams {
5252
timeout: tls::server::Timeout,
53-
identity: LocalCrtKey,
53+
identity: identity::LocalCrtKey,
5454
}
5555

56+
type TlsIo<I> = tls::server::Io<rustls::ServerIo<tls::server::DetectIo<I>>, I>;
57+
5658
// === impl Inbound ===
5759

5860
impl<N> Inbound<N> {
@@ -92,7 +94,7 @@ impl<N> Inbound<N> {
9294
I: Debug + Send + Sync + Unpin + 'static,
9395
N: svc::NewService<Tls, Service = NSvc>,
9496
N: Clone + Send + Sync + Unpin + 'static,
95-
NSvc: svc::Service<tls::server::Io<I>, Response = ()>,
97+
NSvc: svc::Service<TlsIo<I>, Response = ()>,
9698
NSvc: Send + Unpin + 'static,
9799
NSvc::Error: Into<Error>,
98100
NSvc::Future: Send,
@@ -135,10 +137,12 @@ impl<N> Inbound<N> {
135137
.push_on_service(svc::MapTargetLayer::new(io::BoxedIo::new))
136138
.into_inner(),
137139
)
138-
.push(tls::NewDetectTls::<LocalCrtKey, _, _>::layer(TlsParams {
139-
timeout: tls::server::Timeout(detect_timeout),
140-
identity: rt.identity.clone(),
141-
}))
140+
.push(tls::NewDetectTls::<identity::LocalCrtKey, _, _>::layer(
141+
TlsParams {
142+
timeout: tls::server::Timeout(detect_timeout),
143+
identity: rt.identity.clone(),
144+
},
145+
))
142146
.push_switch(
143147
// If this port's policy indicates that authentication is not required and
144148
// detection should be skipped, use the TCP stack directly.
@@ -425,9 +429,9 @@ impl<T> svc::ExtractParam<tls::server::Timeout, T> for TlsParams {
425429
}
426430
}
427431

428-
impl<T> svc::ExtractParam<LocalCrtKey, T> for TlsParams {
432+
impl<T> svc::ExtractParam<identity::LocalCrtKey, T> for TlsParams {
429433
#[inline]
430-
fn extract_param(&self, _: &T) -> LocalCrtKey {
434+
fn extract_param(&self, _: &T) -> identity::LocalCrtKey {
431435
self.identity.clone()
432436
}
433437
}

linkerd/app/inbound/src/direct.rs

Lines changed: 41 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
use crate::{policy, Inbound};
22
use linkerd_app_core::{
3-
io,
4-
proxy::identity::LocalCrtKey,
3+
identity::LocalCrtKey,
4+
io, rustls,
55
svc::{self, ExtractParam, InsertParam, Param},
66
tls,
77
transport::{self, metrics::SensorIo, ClientAddr, OrigDstAddr, Remote, ServerAddr},
88
transport_header::{self, NewTransportHeaderServer, SessionProtocol, TransportHeader},
99
Conditional, Error, NameAddr, Result,
1010
};
11-
use std::{convert::TryFrom, fmt::Debug};
11+
use std::{convert::TryFrom, fmt::Debug, task};
1212
use thiserror::Error;
1313
use tracing::{debug_span, info_span};
1414

@@ -52,8 +52,9 @@ pub struct ClientInfo {
5252
pub local_addr: OrigDstAddr,
5353
}
5454

55-
type FwdIo<I> = SensorIo<io::PrefixedIo<tls::server::Io<I>>>;
56-
pub type GatewayIo<I> = io::EitherIo<FwdIo<I>, SensorIo<tls::server::Io<I>>>;
55+
type TlsIo<I> = tls::server::Io<rustls::ServerIo<tls::server::DetectIo<I>>, I>;
56+
type FwdIo<I> = SensorIo<io::PrefixedIo<TlsIo<I>>>;
57+
pub type GatewayIo<I> = io::EitherIo<FwdIo<I>, SensorIo<TlsIo<I>>>;
5758

5859
#[derive(Clone)]
5960
struct TlsParams {
@@ -102,7 +103,6 @@ impl<N> Inbound<N> {
102103
rt.metrics.proxy.transport.clone(),
103104
))
104105
.instrument(|_: &_| debug_span!("opaque"))
105-
.check_new_service::<Local, _>()
106106
// When the transport header is present, it may be used for either local TCP
107107
// forwarding, or we may be processing an HTTP gateway connection. HTTP gateway
108108
// connections that have a transport header must provide a target name as a part of
@@ -129,8 +129,13 @@ impl<N> Inbound<N> {
129129
negotiated_protocol: client.alpn,
130130
},
131131
);
132-
let permit = allow.check_authorized(client.client_addr, &tls)?;
133-
Ok(svc::Either::A(Local { addr: Remote(ServerAddr(addr)), permit, client_id: client.client_id, }))
132+
let permit =
133+
allow.check_authorized(client.client_addr, &tls)?;
134+
Ok(svc::Either::A(Local {
135+
addr: Remote(ServerAddr(addr)),
136+
permit,
137+
client_id: client.client_id,
138+
}))
134139
}
135140
TransportHeader {
136141
port,
@@ -167,30 +172,27 @@ impl<N> Inbound<N> {
167172
.instrument(
168173
|g: &GatewayTransportHeader| info_span!("gateway", dst = %g.target),
169174
)
170-
.check_new_service::<GatewayTransportHeader, io::PrefixedIo<tls::server::Io<I>>>()
171175
.into_inner(),
172176
)
173177
// Use ALPN to determine whether a transport header should be read.
174178
.push(NewTransportHeaderServer::layer(detect_timeout))
175-
.push_request_filter(
176-
|client: ClientInfo| -> Result<_> {
177-
if client.header_negotiated() {
178-
Ok(client)
179-
} else {
180-
Err(RefusedNoTarget.into())
181-
}
182-
},
183-
)
184-
.check_new_service::<ClientInfo, tls::server::Io<I>>()
179+
.push_request_filter(|client: ClientInfo| -> Result<_> {
180+
if client.header_negotiated() {
181+
Ok(client)
182+
} else {
183+
Err(RefusedNoTarget.into())
184+
}
185+
})
185186
// Build a ClientInfo target for each accepted connection. Refuse the
186187
// connection if it doesn't include an mTLS identity.
187188
.push_request_filter(ClientInfo::try_from)
188189
.push(svc::ArcNewService::layer())
189-
.push(tls::NewDetectTls::<WithTransportHeaderAlpn, _, _>::layer(TlsParams {
190-
timeout: tls::server::Timeout(detect_timeout),
191-
identity: WithTransportHeaderAlpn(rt.identity.clone()),
192-
}))
193-
.check_new_service::<T, I>()
190+
.push(tls::NewDetectTls::<WithTransportHeaderAlpn, _, _>::layer(
191+
TlsParams {
192+
timeout: tls::server::Timeout(detect_timeout),
193+
identity: WithTransportHeaderAlpn(rt.identity.clone()),
194+
},
195+
))
194196
.push_on_service(svc::BoxService::layer())
195197
.push(svc::ArcNewService::layer())
196198
})
@@ -293,8 +295,20 @@ impl Param<tls::ConditionalServerTls> for GatewayTransportHeader {
293295

294296
// === impl WithTransportHeaderAlpn ===
295297

296-
impl svc::Param<tls::server::Config> for WithTransportHeaderAlpn {
297-
fn param(&self) -> tls::server::Config {
298+
impl<I> svc::Service<I> for WithTransportHeaderAlpn
299+
where
300+
I: io::AsyncRead + io::AsyncWrite + Send + Unpin,
301+
{
302+
type Response = (tls::ServerTls, rustls::ServerIo<I>);
303+
type Error = io::Error;
304+
type Future = rustls::TerminateFuture<I>;
305+
306+
#[inline]
307+
fn poll_ready(&mut self, _: &mut task::Context<'_>) -> task::Poll<Result<(), io::Error>> {
308+
task::Poll::Ready(Ok(()))
309+
}
310+
311+
fn call(&mut self, io: I) -> Self::Future {
298312
// Copy the underlying TLS config and set an ALPN value.
299313
//
300314
// TODO: Avoid cloning the server config for every connection. It would
@@ -304,7 +318,7 @@ impl svc::Param<tls::server::Config> for WithTransportHeaderAlpn {
304318
config
305319
.alpn_protocols
306320
.push(transport_header::PROTOCOL.into());
307-
config.into()
321+
rustls::terminate(config.into(), io)
308322
}
309323
}
310324

0 commit comments

Comments
 (0)