Skip to content

Commit

Permalink
split tls id and sni name
Browse files Browse the repository at this point in the history
Signed-off-by: Zahari Dichev <zaharidichev@gmail.com>
  • Loading branch information
zaharidichev committed Nov 6, 2023
1 parent cbf226e commit 0db79a9
Show file tree
Hide file tree
Showing 40 changed files with 385 additions and 180 deletions.
2 changes: 1 addition & 1 deletion linkerd/app/admin/src/stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ struct NonHttpClient(Remote<ClientAddr>);

#[derive(Debug, Error)]
#[error("Unexpected TLS connection to {} from {}", self.0, self.1)]
struct UnexpectedSni(tls::ServerId, Remote<ClientAddr>);
struct UnexpectedSni(tls::ServerName, Remote<ClientAddr>);

#[derive(Clone, Debug)]
struct Tcp {
Expand Down
2 changes: 1 addition & 1 deletion linkerd/app/gateway/src/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ impl Gateway {
.push_map_target(Target::discard_parent)
// Add headers to prevent loops.
.push(NewHttpGateway::layer(identity::LocalId(
self.inbound.identity().name().clone(),
self.inbound.identity().tls_name().clone(),
)))
.push_on_service(svc::LoadShed::layer())
.lift_new()
Expand Down
4 changes: 2 additions & 2 deletions linkerd/app/inbound/src/detect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -396,8 +396,8 @@ impl svc::Param<http::normalize_uri::DefaultAuthority> for Http {
}
}

impl svc::Param<Option<identity::Name>> for Http {
fn param(&self) -> Option<identity::Name> {
impl svc::Param<Option<identity::TlsName>> for Http {
fn param(&self) -> Option<identity::TlsName> {
self.tls
.status
.value()
Expand Down
3 changes: 2 additions & 1 deletion linkerd/app/outbound/src/http/concrete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -374,9 +374,10 @@ impl<T> svc::Param<tls::ConditionalClientTls> for Endpoint<T> {
self.metadata
.identity()
.cloned()
.map(move |server_id| {
.map(move |(server_id, server_name)| {
tls::ConditionalClientTls::Some(tls::ClientTls {
server_id,
server_name,
alpn: if use_transport_header {
use linkerd_app_core::transport_header::PROTOCOL;
Some(tls::client::AlpnProtocols(vec![PROTOCOL.into()]))
Expand Down
2 changes: 1 addition & 1 deletion linkerd/app/outbound/src/http/require_id_header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ type ResponseFuture<F, T, E> =

impl<S> RequireIdentity<S> {
#[inline]
fn extract_id<B>(req: &mut http::Request<B>) -> Option<identity::Name> {
fn extract_id<B>(req: &mut http::Request<B>) -> Option<identity::TlsName> {
let v = req.headers_mut().remove(HEADER_NAME)?;
v.to_str().ok()?.parse().ok()
}
Expand Down
3 changes: 2 additions & 1 deletion linkerd/app/outbound/src/opaq/concrete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,9 +283,10 @@ impl<T> svc::Param<tls::ConditionalClientTls> for Endpoint<T> {
self.metadata
.identity()
.cloned()
.map(move |server_id| {
.map(move |(server_id, server_name)| {
tls::ConditionalClientTls::Some(tls::ClientTls {
server_id,
server_name,
alpn: if use_transport_header {
use linkerd_app_core::transport_header::PROTOCOL;
Some(tls::client::AlpnProtocols(vec![PROTOCOL.into()]))
Expand Down
37 changes: 22 additions & 15 deletions linkerd/app/outbound/src/tcp/tagged_transport.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,17 +154,18 @@ mod test {
struct Endpoint {
port_override: Option<u16>,
authority: Option<http::uri::Authority>,
server_id: Option<tls::ServerId>,
identity: Option<(tls::ServerId, tls::ServerName)>,
proto: Option<SessionProtocol>,
}

impl svc::Param<tls::ConditionalClientTls> for Endpoint {
fn param(&self) -> tls::ConditionalClientTls {
self.server_id
self.identity
.clone()
.map(|server_id| {
.map(|(server_id, server_name)| {
tls::ConditionalClientTls::Some(tls::ClientTls {
server_id,
server_name,
alpn: Some(tls::client::AlpnProtocols(vec![
transport_header::PROTOCOL.into()
])),
Expand Down Expand Up @@ -261,8 +262,9 @@ mod test {

let e = Endpoint {
port_override: Some(4143),
server_id: Some(tls::ServerId(
identity::Name::from_str("server.id").unwrap(),
identity: Some((
tls::ServerId(identity::TlsName::from_str("server.id").unwrap()),
tls::ServerName(identity::Name::from_str("server.id").unwrap()),
)),
authority: None,
proto: None,
Expand All @@ -285,8 +287,9 @@ mod test {

let e = Endpoint {
port_override: Some(4143),
server_id: Some(tls::ServerId(
identity::Name::from_str("server.id").unwrap(),
identity: Some((
tls::ServerId(identity::TlsName::from_str("server.id").unwrap()),
tls::ServerName(identity::Name::from_str("server.id").unwrap()),
)),
authority: Some(http::uri::Authority::from_str("foo.bar.example.com:5555").unwrap()),
proto: None,
Expand All @@ -309,8 +312,9 @@ mod test {

let e = Endpoint {
port_override: Some(4143),
server_id: Some(tls::ServerId(
identity::Name::from_str("server.id").unwrap(),
identity: Some((
tls::ServerId(identity::TlsName::from_str("server.id").unwrap()),
tls::ServerName(identity::Name::from_str("server.id").unwrap()),
)),
authority: None,
proto: None,
Expand All @@ -333,8 +337,9 @@ mod test {

let e = Endpoint {
port_override: Some(4143),
server_id: Some(tls::ServerId(
identity::Name::from_str("server.id").unwrap(),
identity: Some((
tls::ServerId(identity::TlsName::from_str("server.id").unwrap()),
tls::ServerName(identity::Name::from_str("server.id").unwrap()),
)),
authority: None,
proto: Some(SessionProtocol::Http1),
Expand All @@ -357,8 +362,9 @@ mod test {

let e = Endpoint {
port_override: Some(4143),
server_id: Some(tls::ServerId(
identity::Name::from_str("server.id").unwrap(),
identity: Some((
tls::ServerId(identity::TlsName::from_str("server.id").unwrap()),
tls::ServerName(identity::Name::from_str("server.id").unwrap()),
)),
authority: Some(http::uri::Authority::from_str("foo.bar.example.com:5555").unwrap()),
proto: Some(SessionProtocol::Http1),
Expand All @@ -381,8 +387,9 @@ mod test {

let e = Endpoint {
port_override: Some(4143),
server_id: Some(tls::ServerId(
identity::Name::from_str("server.id").unwrap(),
identity: Some((
tls::ServerId(identity::TlsName::from_str("server.id").unwrap()),
tls::ServerName(identity::Name::from_str("server.id").unwrap()),
)),
authority: None,
proto: Some(SessionProtocol::Http1),
Expand Down
67 changes: 54 additions & 13 deletions linkerd/app/src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ pub const ENV_IDENTITY_DISABLED: &str = "LINKERD2_PROXY_IDENTITY_DISABLED";
pub const ENV_IDENTITY_DIR: &str = "LINKERD2_PROXY_IDENTITY_DIR";
pub const ENV_IDENTITY_TRUST_ANCHORS: &str = "LINKERD2_PROXY_IDENTITY_TRUST_ANCHORS";
pub const ENV_IDENTITY_IDENTITY_LOCAL_NAME: &str = "LINKERD2_PROXY_IDENTITY_LOCAL_NAME";
pub const ENV_IDENTITY_IDENTITY_LOCAL_SERVER_NAME: &str = "LINKERD2_PROXY_IDENTITY_SERVER_NAME";
pub const ENV_IDENTITY_TOKEN_FILE: &str = "LINKERD2_PROXY_IDENTITY_TOKEN_FILE";
pub const ENV_IDENTITY_MIN_REFRESH: &str = "LINKERD2_PROXY_IDENTITY_MIN_REFRESH";
pub const ENV_IDENTITY_MAX_REFRESH: &str = "LINKERD2_PROXY_IDENTITY_MAX_REFRESH";
Expand Down Expand Up @@ -982,13 +983,20 @@ fn parse_port_range_set(s: &str) -> Result<RangeInclusiveSet<u16>, ParseError> {
Ok(set)
}

pub(super) fn parse_identity(s: &str) -> Result<identity::Name, ParseError> {
identity::Name::from_str(s).map_err(|identity::InvalidName| {
pub(super) fn parse_identity(s: &str) -> Result<identity::TlsName, ParseError> {
identity::TlsName::from_str(s).map_err(|identity::InvalidName| {
error!("Not a valid identity name: {}", s);
ParseError::NameError
})
}

pub(super) fn parse_name(s: &str) -> Result<identity::Name, ParseError> {
identity::Name::from_str(s).map_err(|identity::InvalidName| {
error!("Not a valid DNS name: {}", s);
ParseError::NameError
})
}

pub(super) fn parse<T, Parse>(
strings: &dyn Strings,
name: &str,
Expand Down Expand Up @@ -1131,15 +1139,25 @@ pub fn parse_control_addr<S: Strings>(
) -> Result<Option<ControlAddr>, EnvError> {
let a = parse(strings, &format!("{}_ADDR", base), parse_addr)?;
let n = parse(strings, &format!("{}_NAME", base), parse_identity)?;
match (a, n) {
(None, None) => Ok(None),
(Some(ref addr), _) if addr.is_loopback() => Ok(Some(ControlAddr {
let sn = parse(strings, &format!("{}_SERVER_NAME", base), parse_name).or(parse(
strings,
&format!("{}_NAME", base),
parse_name,
))?;

match (a, n, sn) {
(None, None, None) => Ok(None),
(Some(ref addr), _, _) if addr.is_loopback() => Ok(Some(ControlAddr {
addr: addr.clone(),
identity: Conditional::None(tls::NoClientTls::Loopback),
})),
(Some(addr), Some(name)) => Ok(Some(ControlAddr {
(Some(addr), Some(tls_name), Some(server_name)) => Ok(Some(ControlAddr {
addr,
identity: Conditional::Some(tls::ServerId(name).into()),
identity: Conditional::Some(tls::ClientTls {
server_id: tls::ServerId(tls_name),
server_name: tls::ServerName(server_name),
alpn: None,
}),
})),
_ => {
error!("{}_ADDR and {}_NAME must be specified together", base, base);
Expand All @@ -1165,7 +1183,15 @@ pub fn parse_identity_config<S: Strings>(
ParseError::InvalidTokenSource
})
});
let li = parse(strings, ENV_IDENTITY_IDENTITY_LOCAL_NAME, parse_identity);
let tls_name = parse(strings, ENV_IDENTITY_IDENTITY_LOCAL_NAME, parse_identity);

let server_name = match strings.get(ENV_IDENTITY_IDENTITY_LOCAL_SERVER_NAME)? {
Some(ref sn) => parse_name(sn)
.map(Some)
.map_err(|_| EnvError::InvalidEnvVar),
None => parse(strings, ENV_IDENTITY_IDENTITY_LOCAL_NAME, parse_name),
};

let min_refresh = parse(strings, ENV_IDENTITY_MIN_REFRESH, parse_duration);
let max_refresh = parse(strings, ENV_IDENTITY_MAX_REFRESH, parse_duration);

Expand All @@ -1181,12 +1207,22 @@ pub fn parse_identity_config<S: Strings>(
return Err(EnvError::InvalidEnvVar);
}

match (control?, ta?, dir?, li?, tok?, min_refresh?, max_refresh?) {
match (
control?,
ta?,
dir?,
tls_name?,
server_name?,
tok?,
min_refresh?,
max_refresh?,
) {
(
Some(control),
Some(trust_anchors_pem),
Some(dir),
Some(local_name),
Some(tls_name),
Some(server_name),
Some(token),
min_refresh,
max_refresh,
Expand Down Expand Up @@ -1235,21 +1271,26 @@ pub fn parse_identity_config<S: Strings>(
max_refresh: max_refresh.unwrap_or(DEFAULT_IDENTITY_MAX_REFRESH),
};
let docs = identity::Documents {
id: identity::LocalId(local_name),
name: identity::LocalName(server_name),
tls_name: identity::LocalId(tls_name),
trust_anchors_pem,
key_pkcs8: key?,
csr_der: csr?,
};
Ok((control, certify, docs))
}
(addr, trust_anchors, end_entity_dir, local_id, token, _minr, _maxr) => {
(addr, trust_anchors, end_entity_dir, tls_name, server_name, token, _minr, _maxr) => {
let s = format!("{0}_ADDR and {0}_NAME", ENV_IDENTITY_SVC_BASE);
let svc_env: &str = s.as_str();
for (unset, name) in &[
(addr.is_none(), svc_env),
(trust_anchors.is_none(), ENV_IDENTITY_TRUST_ANCHORS),
(end_entity_dir.is_none(), ENV_IDENTITY_DIR),
(local_id.is_none(), ENV_IDENTITY_IDENTITY_LOCAL_NAME),
(tls_name.is_none(), ENV_IDENTITY_IDENTITY_LOCAL_NAME),
(
server_name.is_none(),
ENV_IDENTITY_IDENTITY_LOCAL_SERVER_NAME,
),
(token.is_none(), ENV_IDENTITY_TOKEN_FILE),
] {
if *unset {
Expand Down
15 changes: 9 additions & 6 deletions linkerd/app/src/identity.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
pub use linkerd_app_core::identity::{
client::{certify, TokenSource},
InvalidName, LocalId, Name,
InvalidName, LocalId, LocalName, Name, TlsName,
};
use linkerd_app_core::{
control, dns,
Expand All @@ -25,7 +25,8 @@ pub struct Config {

#[derive(Clone)]
pub struct Documents {
pub id: LocalId,
pub name: LocalName,
pub tls_name: LocalId,
pub trust_anchors_pem: String,
pub key_pkcs8: Vec<u8>,
pub csr_der: Vec<u8>,
Expand Down Expand Up @@ -56,7 +57,8 @@ struct NotifyReady {
impl Config {
pub fn build(self, dns: dns::Resolver, client_metrics: ClientMetrics) -> Result<Identity> {
let (store, receiver) = Mode::default().watch(
(*self.documents.id).clone(),
(*self.documents.name).clone(),
(*self.documents.tls_name).clone(),
&self.documents.trust_anchors_pem,
&self.documents.key_pkcs8,
&self.documents.csr_der,
Expand Down Expand Up @@ -93,8 +95,8 @@ impl Config {

impl Credentials for NotifyReady {
#[inline]
fn dns_name(&self) -> &Name {
self.store.dns_name()
fn tls_name(&self) -> &TlsName {
self.store.tls_name()
}

#[inline]
Expand All @@ -119,7 +121,8 @@ impl Credentials for NotifyReady {
impl std::fmt::Debug for Documents {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Documents")
.field("id", &self.id)
.field("name", &self.name)
.field("tls_name", &self.tls_name)
.field("trust_anchors_pem", &self.trust_anchors_pem)
.finish()
}
Expand Down
6 changes: 3 additions & 3 deletions linkerd/app/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,8 +311,8 @@ impl App {
&self.dst
}

pub fn local_identity(&self) -> identity::Name {
self.identity.receiver().name().clone()
pub fn local_identity(&self) -> identity::TlsName {
self.identity.receiver().tls_name().clone()
}

pub fn identity_addr(&self) -> ControlAddr {
Expand Down Expand Up @@ -364,7 +364,7 @@ impl App {

// Kick off the identity so that the process can become ready.
let local = identity.receiver();
let local_id = local.name().clone();
let local_id = local.tls_name().clone();
let ready = identity.ready();
tokio::spawn(
identity
Expand Down
2 changes: 1 addition & 1 deletion linkerd/http-access-log/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ pub struct NewAccessLog<N> {
pub struct AccessLogContext<S> {
inner: S,
client_addr: SocketAddr,
client_id: Option<identity::Name>,
client_id: Option<identity::TlsName>,
}

struct ResponseFutureInner {
Expand Down
6 changes: 3 additions & 3 deletions linkerd/identity/src/credentials.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use crate::Name;
use crate::TlsName;
use linkerd_error::Result;
use std::{ops::Deref, time::SystemTime};

/// Publishes certificates to be used by TLS implementations.
pub trait Credentials {
/// Get the authoritative DNS-like name used in the certificate.
fn dns_name(&self) -> &Name;
/// Get the tls name used in the certificate's SAN.
fn tls_name(&self) -> &TlsName;

/// Generate a CSR to to be sent to the identity service.
fn gen_certificate_signing_request(&mut self) -> DerX509;
Expand Down
3 changes: 3 additions & 0 deletions linkerd/identity/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@
mod credentials;
mod local;
mod name;
mod tls_name;

pub use self::{
credentials::{Credentials, DerX509},
local::LocalId,
local::LocalName,
name::Name,
tls_name::TlsName,
};
pub use linkerd_dns_name::InvalidName;
Loading

0 comments on commit 0db79a9

Please sign in to comment.