Skip to content

Commit 3db1728

Browse files
authored
outbound: Strip endpoint identity when disabled (#862)
When the proxy's identity is disabled, we may still mark outbound endpoints as having a peer identity (even though a TLS connection is never established. This change modifies the outbound HTTP and TCP endpoint stacks to optionally strip server identities before metrics are recorded.
1 parent f388bc2 commit 3db1728

File tree

9 files changed

+46
-51
lines changed

9 files changed

+46
-51
lines changed

linkerd/app/integration/src/tests/discovery.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -386,8 +386,7 @@ mod http2 {
386386
metrics::metric("tcp_close_total")
387387
.label("peer", "dst")
388388
.label("direction", "outbound")
389-
.label("tls", "no_identity")
390-
.label("no_tls_reason", "not_provided_by_service_discovery")
389+
.label("tls", "disabled")
391390
.label(
392391
"authority",
393392
format_args!("disco.test.svc.cluster.local:{}", port),

linkerd/app/integration/src/tests/telemetry.rs

Lines changed: 11 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,7 @@ async fn metrics_endpoint_outbound_request_count() {
158158
let srv_port = proxy.outbound_server.as_ref().unwrap().addr.port();
159159
metrics::labels()
160160
.label("direction", "outbound")
161-
.label("tls", "no_identity")
162-
.label("no_tls_reason", "not_provided_by_service_discovery")
161+
.label("tls", "disabled")
163162
.label(
164163
"authority",
165164
format_args!("tele.test.svc.cluster.local:{}", srv_port),
@@ -319,13 +318,9 @@ mod response_classification {
319318
#[tokio::test]
320319
async fn outbound_http() {
321320
let fixture = async { Fixture::outbound_with_server(make_test_server().await).await };
322-
test_http(
323-
fixture,
324-
"outbound",
325-
"no_identity",
326-
Some("not_provided_by_service_discovery"),
327-
|proxy| Some(proxy.outbound_server.as_ref().unwrap().addr.port()),
328-
)
321+
test_http(fixture, "outbound", "disabled", None, |proxy| {
322+
Some(proxy.outbound_server.as_ref().unwrap().addr.port())
323+
})
329324
.await
330325
}
331326
}
@@ -1135,8 +1130,7 @@ mod transport {
11351130
format_args!("tele.test.svc.cluster.local:{}", port),
11361131
)
11371132
.label("direction", "outbound")
1138-
.label("tls", "no_identity")
1139-
.label("no_tls_reason", "not_provided_by_service_discovery")
1133+
.label("tls", "disabled")
11401134
})
11411135
.await;
11421136
}
@@ -1170,8 +1164,7 @@ mod transport {
11701164
metrics::labels()
11711165
.label("authority", proxy.outbound_server.as_ref().unwrap().addr)
11721166
.label("direction", "outbound")
1173-
.label("tls", "no_identity")
1174-
.label("no_tls_reason", "not_provided_by_service_discovery")
1167+
.label("tls", "disabled")
11751168
})
11761169
.await;
11771170
}
@@ -1214,8 +1207,7 @@ mod transport {
12141207
metrics::metric("tcp_close_total")
12151208
.label("peer", "dst")
12161209
.label("direction", "inbound")
1217-
.label("tls", "no_identity")
1218-
.label("no_tls_reason", "not_provided_by_service_discovery")
1210+
.label("tls", "disabled")
12191211
.label("errno", "EXFULL")
12201212
.value(1u64)
12211213
.assert_in(&metrics)
@@ -1256,8 +1248,7 @@ mod transport {
12561248
metrics::metric("tcp_close_total")
12571249
.label("peer", "dst")
12581250
.label("direction", "outbound")
1259-
.label("tls", "no_identity")
1260-
.label("no_tls_reason", "not_provided_by_service_discovery")
1251+
.label("tls", "disabled")
12611252
.label("errno", "EXFULL")
12621253
.value(1u64)
12631254
.assert_in(&metrics)
@@ -1379,8 +1370,7 @@ mod transport {
13791370
let mut dst_count = metrics::metric("tcp_connection_duration_count")
13801371
.label("peer", "dst")
13811372
.label("direction", "outbound")
1382-
.label("tls", "no_identity")
1383-
.label("no_tls_reason", "not_provided_by_service_discovery")
1373+
.label("tls", "disabled")
13841374
.label("errno", "")
13851375
.value(1u64);
13861376

@@ -1416,8 +1406,7 @@ mod transport {
14161406
|proxy| {
14171407
metrics::labels()
14181408
.label("direction", "outbound")
1419-
.label("tls", "no_identity")
1420-
.label("no_tls_reason", "not_provided_by_service_discovery")
1409+
.label("tls", "disabled")
14211410
.label("authority", proxy.outbound_server.as_ref().unwrap().addr)
14221411
},
14231412
)
@@ -1435,8 +1424,7 @@ mod transport {
14351424
|proxy| {
14361425
metrics::labels()
14371426
.label("direction", "outbound")
1438-
.label("tls", "no_identity")
1439-
.label("no_tls_reason", "not_provided_by_service_discovery")
1427+
.label("tls", "disabled")
14401428
.label("authority", proxy.outbound_server.as_ref().unwrap().addr)
14411429
},
14421430
)

linkerd/app/outbound/src/http/endpoint.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@ use linkerd_app_core::{
99
proxy::{http, tap},
1010
reconnect,
1111
spans::SpanConverter,
12-
svc, Error, TraceContext, CANONICAL_DST_HEADER, L5D_REQUIRE_ID,
12+
svc, tls, Error, TraceContext, CANONICAL_DST_HEADER, L5D_REQUIRE_ID,
1313
};
1414
use tokio::{io, sync::mpsc};
1515
use tracing::debug_span;
1616

1717
pub fn stack<B, C>(
1818
config: &ConnectConfig,
19+
local_id: Option<&tls::LocalId>,
1920
tcp_connect: C,
2021
tap: tap::Registry,
2122
metrics: metrics::Proxy,
@@ -36,6 +37,7 @@ where
3637
C::Response: io::AsyncRead + io::AsyncWrite + Send + Unpin,
3738
C::Future: Send + Unpin,
3839
{
40+
let identity_disabled = local_id.is_none();
3941
svc::stack(tcp_connect)
4042
// Initiates an HTTP client on the underlying transport. Prior-knowledge HTTP/2
4143
// is typically used (i.e. when communicating with other proxies); though
@@ -67,5 +69,12 @@ where
6769
.push_on_response(http::BoxResponse::layer())
6870
.check_new::<Endpoint>()
6971
.instrument(|e: &Endpoint| debug_span!("endpoint", peer.addr = %e.addr))
72+
.push_map_target(move |e: Endpoint| {
73+
if identity_disabled {
74+
e.identity_disabled()
75+
} else {
76+
e
77+
}
78+
})
7079
.into_inner()
7180
}

linkerd/app/outbound/src/http/tests.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ where
8989
&cfg.proxy,
9090
super::endpoint::stack(
9191
&cfg.proxy.connect,
92+
None,
9293
connect,
9394
tap,
9495
metrics.outbound.clone(),
@@ -403,8 +404,7 @@ async fn active_stacks_dont_idle_out() {
403404
let body = body.take().expect("service only called once in this test");
404405
Response::new(body)
405406
})
406-
.http2()
407-
.expect_identity(id.clone());
407+
.http2();
408408

409409
let connect = support::connect().endpoint_fn_boxed(ep1, server.run());
410410
let profiles = profile::resolver().profile(

linkerd/app/outbound/src/target.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,12 @@ impl<P> Endpoint<P> {
224224
pub fn from_accept(reason: tls::NoServerId) -> impl (Fn(Accept<P>) -> Self) + Clone {
225225
move |accept| Self::from_logical(reason)(Logical::from((None, accept)))
226226
}
227+
228+
/// Marks identity as disabled.
229+
pub fn identity_disabled(mut self) -> Self {
230+
self.identity = Conditional::None(tls::NoServerId::Disabled);
231+
self
232+
}
227233
}
228234

229235
impl<P> Into<SocketAddr> for Endpoint<P> {

linkerd/app/outbound/src/tcp/connect.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ pub fn stack<P>(
1919
Error = Error,
2020
Future = impl Send,
2121
> + Clone {
22+
let identity_disabled = local_identity.is_none();
2223
svc::stack(ConnectTcp::new(config.keepalive))
2324
// Initiates mTLS if the target is configured with identity.
2425
.push(tls::Client::layer(local_identity))
@@ -30,6 +31,13 @@ pub fn stack<P>(
3031
.push_timeout(config.timeout)
3132
.push(svc::stack::BoxFuture::layer())
3233
.push(metrics.transport.layer_connect())
34+
.push_map_target(move |e: Endpoint<P>| {
35+
if identity_disabled {
36+
e.identity_disabled()
37+
} else {
38+
e
39+
}
40+
})
3341
.push_request_filter(PreventLoop { port: server_port })
3442
.into_inner()
3543
}

linkerd/app/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ impl Config {
150150
&outbound.proxy,
151151
outbound::http::endpoint::stack(
152152
&outbound.proxy.connect,
153+
local_identity.as_ref().map(|l| l.id()),
153154
outbound::tcp::connect::stack(
154155
&outbound.proxy.connect,
155156
outbound_addr.port(),

linkerd/app/test/src/http_util.rs

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::app_core::{identity as id, io::BoxedIo, tls, Conditional, Error};
1+
use crate::app_core::{io::BoxedIo, tls, Error};
22
use hyper::{body::HttpBody, Body, Request, Response};
33
use std::{
44
fmt,
@@ -8,7 +8,6 @@ use tracing::Instrument;
88

99
pub struct Server {
1010
settings: hyper::server::conn::Http,
11-
expected_id: Option<tls::ConditionalServerId>,
1211
f: HandleFuture,
1312
}
1413

@@ -18,7 +17,6 @@ impl Default for Server {
1817
fn default() -> Self {
1918
Self {
2019
settings: hyper::server::conn::Http::new(),
21-
expected_id: None,
2220
f: Box::new(|_| {
2321
Ok(Response::builder()
2422
.status(http::status::StatusCode::NOT_FOUND)
@@ -53,16 +51,6 @@ impl Server {
5351
self
5452
}
5553

56-
pub fn expect_identity(mut self, id: impl Into<id::Name>) -> Self {
57-
self.expected_id = Some(Conditional::Some(tls::ServerId(id.into())));
58-
self
59-
}
60-
61-
pub fn no_identity(mut self, reason: tls::NoServerId) -> Self {
62-
self.expected_id = Some(Conditional::None(reason));
63-
self
64-
}
65-
6654
pub fn new(mut f: impl (FnMut(Request<Body>) -> Response<Body>) + Send + 'static) -> Self {
6755
Self {
6856
f: Box::new(move |req| Ok::<_, Error>(f(req))),
@@ -75,19 +63,11 @@ impl Server {
7563
E: std::fmt::Debug,
7664
for<'e> &'e E: Into<tls::ConditionalServerId>,
7765
{
78-
let Self {
79-
f,
80-
settings,
81-
expected_id,
82-
} = self;
66+
let Self { f, settings } = self;
8367
let f = Arc::new(Mutex::new(f));
8468
move |endpoint| {
8569
let span = tracing::debug_span!("server::run", ?endpoint);
8670
let _e = span.enter();
87-
if let Some(expected_id) = expected_id.as_ref() {
88-
let server_id: tls::ConditionalServerId = (&endpoint).into();
89-
assert_eq!(&server_id, expected_id);
90-
}
9171
let f = f.clone();
9272
let (client_io, server_io) = crate::io::duplex(4096);
9373
let svc = hyper::service::service_fn(move |request: Request<Body>| {

linkerd/proxy/identity/src/certify.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,10 @@ impl LocalCrtKey {
192192
crate::metrics::Report::new(self.crt_key.clone(), self.refreshes.clone())
193193
}
194194

195+
pub fn id(&self) -> &id::LocalId {
196+
&self.id
197+
}
198+
195199
pub fn name(&self) -> &id::Name {
196200
self.id.as_ref()
197201
}
@@ -209,7 +213,7 @@ impl Into<tls::client::Config> for &'_ LocalCrtKey {
209213

210214
impl Into<id::LocalId> for &'_ LocalCrtKey {
211215
fn into(self) -> id::LocalId {
212-
id::LocalId(self.name().clone())
216+
self.id().clone()
213217
}
214218
}
215219

0 commit comments

Comments
 (0)