-
Notifications
You must be signed in to change notification settings - Fork 271
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
linkerd_identity: split linkerd_identity::Id
into DNS and URI variants
#2538
Conversation
|| suffixes.iter().any(|s| s.contains(&id.to_str())) | ||
} | ||
}) => match id { | ||
id::Id::Uri(_) => identities.contains(&*id.to_str()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does that make sense for now ?
Codecov Report
Additional details and impacted files@@ Coverage Diff @@
## main #2538 +/- ##
==========================================
+ Coverage 67.61% 67.66% +0.05%
==========================================
Files 330 330
Lines 14781 14803 +22
==========================================
+ Hits 9994 10017 +23
+ Misses 4787 4786 -1
... and 2 files with indirect coverage changes Continue to review full report in Codecov by Sentry.
|
linkerd/identity/src/lib.rs
Outdated
pub struct Id(pub linkerd_dns_name::Name); | ||
pub enum Id { | ||
Dns(linkerd_dns_name::Name), | ||
Uri(http::Uri), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure about the suitability of http::Uri
to represent RFC 3986 URIs. The crate documentation makes no claims about satisfying the spec, and is designed to represent the HTTP-specific URI quirks.
I believe our primary options are:
We already have a dependency on the url crate:
:; cargo tree -i url --depth 1
url v2.3.0
├── linkerd-http-route v0.1.0 (/workspaces/linkerd2-proxy/linkerd/http-route)
└── trust-dns-proto v0.22.0
so this is probably a more appealing target.
Also, it provides an Url::as_str, so we can avoid allocating strings on each comparison.
linkerd/meshtls/verifier/src/lib.rs
Outdated
// Wildcards can perhaps be handled in a future path... | ||
return None; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm curious where this arises from. Is there a bug in the current name parsing? Is this not handled properly by the ID parser?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mentioned that this was already present but I do not see any other wildcard handling in the diff.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this was present in the rustls client id extraction code: https://github.com/linkerd/linkerd2-proxy/blob/f4f606555e9c671694f4f21009ba7affe0aaacad/linkerd/meshtls/rustls/src/server.rs#L143C21-L143C21
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems this has been there for a while. Do you remember the precise reason?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comes from cd04d7a#diff-6eab3f24cc45f109bf10a46bd6be573f28ebd28d826dd38ffb5a7cb1cca46bc7L135-L143 -- there used to be an explicit variant.
It made sense to document this case when it was an explicit enum case we had to handle, but I don't think it makes any sense to explicitly handle a "*" DNS name: A "*" dns name must not be parsed by Id::parse_dns_name(dns)
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Is it true that we don't actually enforce any requirements around spiffe:// IDs? This seems fine I just want to confirm that's the case.
- Given that, it seems beneficial to have a test that documents the behavior with, for instance, a http:// uri.
self.0.without_trailing_dot().fmt(f) | ||
match self { | ||
Self::Dns(dns) => dns.without_trailing_dot().fmt(f), | ||
Self::Uri(uri) => uri.fmt(f), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we test round-tripping an Id through a parser? like:
something like
let id: Id = "uri://host:1234/path".parse().unwrap();
assert_eq!(id, id.to_string().parse().unwrap());
pub fn parse_uri(s: &str) -> Result<Self, InvalidId> { | ||
http::Uri::try_from(s) | ||
.map(Self::Uri) | ||
.map_err(|e| InvalidId(e.into())) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
codecov says we never hit InvalidId. is that true? should we test passing a DNS name to parse_uri?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have added a test for that
It is true. I have added a test for that. |
Signed-off-by: Zahari Dichev <[email protected]>
Signed-off-by: Zahari Dichev <[email protected]>
Signed-off-by: Zahari Dichev <[email protected]>
Signed-off-by: Zahari Dichev <[email protected]>
692c9d6
to
0359465
Compare
Signed-off-by: Zahari Dichev <[email protected]>
# `trust-dns-proto`, depends on `idna` v0.2.3 while `url` depends on v0.5.0 | ||
{ name = "idna" }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I looked into this and (1) it appears that trust-dns has rebranded as hickory-dns, so we're going to have to be aware of that when we upgrade trust-dns; (2) and the latest version is on idna v0.4.
Normally, we'd follow up this PR with an upstream PR to update hickory-dns to idna 0.5 so that we can be sure to resolve this when we take the next hickory udpate.
These exceptions are fine temporarily, but each skip here means we're double-building dependencies. We try to keep this overhead manageable over time.
linkerd/app/inbound/Cargo.toml
Outdated
@@ -30,6 +30,7 @@ linkerd-meshtls-rustls = { path = "../../meshtls/rustls", optional = true } | |||
linkerd-proxy-client-policy = { path = "../../proxy/client-policy" } | |||
linkerd-tonic-watch = { path = "../../tonic-watch" } | |||
linkerd2-proxy-api = { version = "0.12", features = ["inbound"] } | |||
linkerd-identity = { path = "../../identity" } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This shouldn't be necessary: app-inbound and app-outbound pick up the vast majority of their dependencies via reexport from app-core:
linkerd2-proxy/linkerd/app/core/src/lib.rs
Lines 50 to 54 in 31b2aea
pub mod identity { | |
pub use linkerd_identity::*; | |
pub use linkerd_meshtls::*; | |
pub use linkerd_proxy_identity_client as client; | |
} |
tls::ConditionalClientTls::Some(tls::ClientTls::new( | ||
client_tls.server_id, | ||
client_tls.server_name, | ||
alpn, | ||
)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tioli
.map(move |mut client_tls| {
client_tls.alpn = if use_transport_header {
use linkerd_app_core::transport_header::PROTOCOL;
Some(tls::client::AlpnProtocols(vec![PROTOCOL.into()]))
} else {
None
};
tls::ConditionalClientTls::Some(client_tls)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
alternately -- we could add a ClientTls::with_alpn(self, alpn: Option<AlpnProtocols>) -> ClientTls
if you wanted to avoid the mut, so this would end up
.map(move |client_tls| {
tls::ConditionalClientTls::Some(client_tls.with_alpn(if use_transport_header {
use linkerd_app_core::transport_header::PROTOCOL;
Some(tls::client::AlpnProtocols(vec![PROTOCOL.into()]))
} else {
None
}))
@@ -59,8 +59,7 @@ impl<S> RequireIdentity<S> { | |||
#[inline] | |||
fn extract_id<B>(req: &mut http::Request<B>) -> Option<identity::Id> { | |||
let v = req.headers_mut().remove(HEADER_NAME)?; | |||
let n = v.to_str().ok()?.parse::<dns::Name>().ok()?; | |||
Some(n.into()) | |||
v.to_str().ok()?.parse::<identity::Id>().ok() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tioli -- the explicit annotation is no longer needed because we're not using an intermediate type.
v.to_str().ok()?.parse::<identity::Id>().ok() | |
v.to_str().ok()?.parse().ok() |
let alpn = if use_transport_header { | ||
use linkerd_app_core::transport_header::PROTOCOL; | ||
Some(tls::client::AlpnProtocols(vec![PROTOCOL.into()])) | ||
} else { | ||
None | ||
}; | ||
tls::ConditionalClientTls::Some(tls::ClientTls::new(server_id, alpn)) | ||
tls::ConditionalClientTls::Some(tls::ClientTls::new( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same suggestion as above could apply here
tls::ConditionalClientTls::Some(tls::ClientTls::new( | ||
client_tls.server_id, | ||
client_tls.server_name, | ||
alpn, | ||
)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and here
linkerd/tls/src/client.rs
Outdated
@@ -79,10 +79,9 @@ pub struct ConnectMeta<M> { | |||
|
|||
impl ClientTls { | |||
// XXX(ver) We'll have to change this when ServerIds are not necessarily DNS names. | |||
pub fn new(server_id: ServerId, alpn: Option<AlpnProtocols>) -> Self { | |||
let ServerId(linkerd_identity::Id(name)) = server_id.clone(); | |||
pub fn new(server_id: ServerId, server_name: ServerName, alpn: Option<AlpnProtocols>) -> Self { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suspect you could leave this unchanged -- avoiding having to specifiy None in many cases -- and explicitly set the alpn field only when an override is necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's nothing blocking merging this, though there are a few small cleanups/followups we should include.
@olix0r I will address the followups, and we can merge after |
Signed-off-by: Zahari Dichev <[email protected]>
eec7bb9
to
2defa19
Compare
This change culminates recent work to restructure the balancer to use a PoolQueue so that balancer changes may occur independently of request processing. This replaces independent discovery buffering so that the balancer task is responsible for polling discovery streams without independent buffering. Requests are buffered and processed as soon as the pool has available backends. Fail-fast circuit breaking is enforced on the balancer's queue so that requests can't get stuck in a queue indefinitely. In general, the new balancer is instrumented directly with metrics, and the relevant metric name prefix and labelset is provided by the stack. In addition to detailed queue metrics including request (in-queue) latency histograms, but also failfast states, discovery updates counts, and balancer endpoint pool sizes. --- * outbound: Move queues into the concrete stack (linkerd/linkerd2-proxy#2539) * metrics: Remove unused features (linkerd/linkerd2-proxy#2542) * Add the PoolQueue middleware (linkerd/linkerd2-proxy#2540) * ci: Fixup codecov config (linkerd/linkerd2-proxy#2545) * ci: Cancel prior runs (linkerd/linkerd2-proxy#2546) * ci: Skip ARM builds during non-release CI (linkerd/linkerd2-proxy#2547) * deps: Update tokio, tonic, and prost (linkerd/linkerd2-proxy#2544) * build(deps): bump tj-actions/changed-files from 40.2.0 to 40.2.1 (linkerd/linkerd2-proxy#2549) * metrics: Use prometheus-client for proxy_build_info (linkerd/linkerd2-proxy#2551) * balance: Add a p2c Pool implementation (linkerd/linkerd2-proxy#2541) * metrics: Export process metrics using prometheus-client (linkerd/linkerd2-proxy#2552) * linkerd_identity: split `linkerd_identity::Id` into DNS and URI variants (linkerd/linkerd2-proxy#2538) * outbound: Move HTTP balancer into its own module (linkerd/linkerd2-proxy#2554) * app: Setup prom registry for use in balancers (linkerd/linkerd2-proxy#2555) * vscode: Move workspace settings to devcontainer (linkerd/linkerd2-proxy#2557) * build(deps): bump tj-actions/changed-files from 40.2.1 to 40.2.2 (linkerd/linkerd2-proxy#2556) * balance: Instrument metrics in pool balancer (linkerd/linkerd2-proxy#2558) * Enable PoolQueue balancer (linkerd/linkerd2-proxy#2559) Signed-off-by: Oliver Gould <[email protected]>
This change culminates recent work to restructure the balancer to use a PoolQueue so that balancer changes may occur independently of request processing. This replaces independent discovery buffering so that the balancer task is responsible for polling discovery streams without independent buffering. Requests are buffered and processed as soon as the pool has available backends. Fail-fast circuit breaking is enforced on the balancer's queue so that requests can't get stuck in a queue indefinitely. In general, the new balancer is instrumented directly with metrics, and the relevant metric name prefix and labelset is provided by the stack. In addition to detailed queue metrics including request (in-queue) latency histograms, but also failfast states, discovery updates counts, and balancer endpoint pool sizes. --- * outbound: Move queues into the concrete stack (linkerd/linkerd2-proxy#2539) * metrics: Remove unused features (linkerd/linkerd2-proxy#2542) * Add the PoolQueue middleware (linkerd/linkerd2-proxy#2540) * ci: Fixup codecov config (linkerd/linkerd2-proxy#2545) * ci: Cancel prior runs (linkerd/linkerd2-proxy#2546) * ci: Skip ARM builds during non-release CI (linkerd/linkerd2-proxy#2547) * deps: Update tokio, tonic, and prost (linkerd/linkerd2-proxy#2544) * build(deps): bump tj-actions/changed-files from 40.2.0 to 40.2.1 (linkerd/linkerd2-proxy#2549) * metrics: Use prometheus-client for proxy_build_info (linkerd/linkerd2-proxy#2551) * balance: Add a p2c Pool implementation (linkerd/linkerd2-proxy#2541) * metrics: Export process metrics using prometheus-client (linkerd/linkerd2-proxy#2552) * linkerd_identity: split `linkerd_identity::Id` into DNS and URI variants (linkerd/linkerd2-proxy#2538) * outbound: Move HTTP balancer into its own module (linkerd/linkerd2-proxy#2554) * app: Setup prom registry for use in balancers (linkerd/linkerd2-proxy#2555) * vscode: Move workspace settings to devcontainer (linkerd/linkerd2-proxy#2557) * build(deps): bump tj-actions/changed-files from 40.2.1 to 40.2.2 (linkerd/linkerd2-proxy#2556) * balance: Instrument metrics in pool balancer (linkerd/linkerd2-proxy#2558) * Enable PoolQueue balancer (linkerd/linkerd2-proxy#2559) Signed-off-by: Oliver Gould <[email protected]>
Our
linkerd_identity::Id
type was capable of representingonly DNS-like SANs. In order to be able to perform SAN
verification on SPIFFE identities, in this PR we turn this
type into an enum that can represent either a DNS or URI ids.
Additionally the logic in `meshtls::verifier`` has been updated
to consider URI SANs as well.
Signed-off-by: Zahari Dichev [email protected]