Skip to content

Commit e9eaedc

Browse files
authored
policy: Add support for cluster-scoped default policies (#1210)
The policy controller supports the default policies `cluster-authenticated` and `cluster-unauthenticated` but the proxy would error if configured with these policies. In order to use a single policy annotation honored by both the policy controller and proxy, this change adds support for a new configuration, `LINKERD2_POLICY_CLUSTER_NETWORKS`, that allows the proxy to enforce cluster-scoped defaults. When this configuration is not specified, the cluster-scoped defaults are not supported. This default will apply to all ports that are not documented in the pod's spec (i.e. ports not in the `LINKERD2_PROXY_INBOUND_PORTS` configuration). This change also updates policy labeling to track server and authz labels independently so that keys may overlap, as is required by linkerd/linkerd2#6722
1 parent 214106b commit e9eaedc

File tree

7 files changed

+186
-98
lines changed

7 files changed

+186
-98
lines changed

linkerd/app/inbound/src/detect.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -380,11 +380,12 @@ mod tests {
380380
protocol: Protocol::Detect {
381381
timeout: std::time::Duration::from_secs(10),
382382
},
383-
labels: None.into_iter().collect(),
384383
tls: tls::ConditionalServerTls::Some(tls::ServerTls::Established {
385384
client_id: Some(client_id()),
386385
negotiated_protocol: None,
387386
}),
387+
server_labels: None.into_iter().collect(),
388+
authz_labels: None.into_iter().collect(),
388389
},
389390
};
390391

@@ -412,11 +413,12 @@ mod tests {
412413
protocol: Protocol::Detect {
413414
timeout: std::time::Duration::from_secs(10),
414415
},
415-
labels: None.into_iter().collect(),
416416
tls: tls::ConditionalServerTls::Some(tls::ServerTls::Established {
417417
client_id: Some(client_id()),
418418
negotiated_protocol: None,
419419
}),
420+
server_labels: None.into_iter().collect(),
421+
authz_labels: None.into_iter().collect(),
420422
},
421423
};
422424

@@ -442,11 +444,12 @@ mod tests {
442444
orig_dst_addr: orig_dst_addr(),
443445
permit: Permitted {
444446
protocol: Protocol::Http1,
445-
labels: None.into_iter().collect(),
446447
tls: tls::ConditionalServerTls::Some(tls::ServerTls::Established {
447448
client_id: Some(client_id()),
448449
negotiated_protocol: None,
449450
}),
451+
server_labels: None.into_iter().collect(),
452+
authz_labels: None.into_iter().collect(),
450453
},
451454
};
452455

@@ -472,11 +475,12 @@ mod tests {
472475
orig_dst_addr: orig_dst_addr(),
473476
permit: Permitted {
474477
protocol: Protocol::Http1,
475-
labels: None.into_iter().collect(),
476478
tls: tls::ConditionalServerTls::Some(tls::ServerTls::Established {
477479
client_id: Some(client_id()),
478480
negotiated_protocol: None,
479481
}),
482+
server_labels: None.into_iter().collect(),
483+
authz_labels: None.into_iter().collect(),
480484
},
481485
};
482486

@@ -502,11 +506,12 @@ mod tests {
502506
orig_dst_addr: orig_dst_addr(),
503507
permit: Permitted {
504508
protocol: Protocol::Http2,
505-
labels: None.into_iter().collect(),
506509
tls: tls::ConditionalServerTls::Some(tls::ServerTls::Established {
507510
client_id: Some(client_id()),
508511
negotiated_protocol: None,
509512
}),
513+
server_labels: None.into_iter().collect(),
514+
authz_labels: None.into_iter().collect(),
510515
},
511516
};
512517

Lines changed: 73 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,88 @@
1-
use linkerd_app_core::{Ipv4Net, Ipv6Net};
2-
use linkerd_server_policy::{Authentication, Authorization, Protocol, ServerPolicy, Suffix};
1+
use linkerd_app_core::{IpNet, Ipv4Net, Ipv6Net};
2+
use linkerd_server_policy::{
3+
Authentication, Authorization, Labels, Protocol, ServerPolicy, Suffix,
4+
};
35
use std::time::Duration;
46

57
pub fn all_authenticated(timeout: Duration) -> ServerPolicy {
6-
ServerPolicy {
7-
protocol: Protocol::Detect { timeout },
8-
authorizations: vec![Authorization {
9-
networks: vec![Ipv4Net::default().into(), Ipv6Net::default().into()],
10-
authentication: Authentication::TlsAuthenticated {
11-
identities: Default::default(),
12-
suffixes: vec![Suffix::from(vec![])],
13-
},
14-
labels: Some(("authz".to_string(), "_all-authenticated".to_string()))
15-
.into_iter()
16-
.collect(),
17-
}],
18-
labels: Some(("server".to_string(), "_default".to_string()))
19-
.into_iter()
20-
.collect(),
21-
}
8+
mk(
9+
"default:all-authenticated",
10+
all_nets(),
11+
authenticated(),
12+
timeout,
13+
)
2214
}
2315

2416
pub fn all_unauthenticated(timeout: Duration) -> ServerPolicy {
25-
ServerPolicy {
26-
protocol: Protocol::Detect { timeout },
27-
authorizations: vec![Authorization {
28-
networks: vec![Ipv4Net::default().into(), Ipv6Net::default().into()],
29-
authentication: Authentication::Unauthenticated,
30-
labels: Some(("authz".to_string(), "_all-unauthenticated".to_string()))
31-
.into_iter()
32-
.collect(),
33-
}],
34-
labels: Some(("server".to_string(), "_default".to_string()))
35-
.into_iter()
36-
.collect(),
37-
}
17+
mk(
18+
"default:all-unauthenticated",
19+
all_nets(),
20+
Authentication::Unauthenticated,
21+
timeout,
22+
)
23+
}
24+
25+
pub fn cluster_authenticated(
26+
nets: impl IntoIterator<Item = IpNet>,
27+
timeout: Duration,
28+
) -> ServerPolicy {
29+
mk(
30+
"default:cluster-authenticated",
31+
nets,
32+
authenticated(),
33+
timeout,
34+
)
35+
}
36+
37+
pub fn cluster_unauthenticated(
38+
nets: impl IntoIterator<Item = IpNet>,
39+
timeout: Duration,
40+
) -> ServerPolicy {
41+
mk(
42+
"default:cluster-unauthenticated",
43+
nets,
44+
Authentication::Unauthenticated,
45+
timeout,
46+
)
3847
}
3948

4049
pub fn all_mtls_unauthenticated(timeout: Duration) -> ServerPolicy {
50+
mk(
51+
"default:all-tls-unauthenticated",
52+
all_nets(),
53+
Authentication::TlsUnauthenticated,
54+
timeout,
55+
)
56+
}
57+
58+
fn all_nets() -> impl Iterator<Item = IpNet> {
59+
vec![Ipv4Net::default().into(), Ipv6Net::default().into()].into_iter()
60+
}
61+
62+
fn authenticated() -> Authentication {
63+
Authentication::TlsAuthenticated {
64+
identities: Default::default(),
65+
suffixes: vec![Suffix::from(vec![])],
66+
}
67+
}
68+
69+
fn mk(
70+
name: &str,
71+
nets: impl IntoIterator<Item = IpNet>,
72+
authentication: Authentication,
73+
timeout: Duration,
74+
) -> ServerPolicy {
75+
let labels = Some(("name".to_string(), name.to_string()))
76+
.into_iter()
77+
.collect::<Labels>();
78+
4179
ServerPolicy {
4280
protocol: Protocol::Detect { timeout },
4381
authorizations: vec![Authorization {
44-
networks: vec![Ipv4Net::default().into(), Ipv6Net::default().into()],
45-
authentication: Authentication::TlsUnauthenticated,
46-
labels: Some(("authz".to_string(), "_all-unauthenticated-tls".to_string()))
47-
.into_iter()
48-
.collect(),
82+
networks: nets.into_iter().map(Into::into).collect(),
83+
authentication,
84+
labels: labels.clone(),
4985
}],
50-
labels: Some(("server".to_string(), "_default".to_string()))
51-
.into_iter()
52-
.collect(),
86+
labels,
5387
}
5488
}

linkerd/app/inbound/src/policy/discover.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ fn to_policy(proto: api::Server) -> Result<ServerPolicy> {
162162
Ok(Authorization {
163163
networks,
164164
authentication: authn,
165-
labels,
165+
labels: labels.into_iter().collect(),
166166
})
167167
},
168168
)
@@ -171,7 +171,7 @@ fn to_policy(proto: api::Server) -> Result<ServerPolicy> {
171171
Ok(ServerPolicy {
172172
protocol,
173173
authorizations,
174-
labels: proto.labels,
174+
labels: proto.labels.into_iter().collect(),
175175
})
176176
}
177177

linkerd/app/inbound/src/policy/mod.rs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@ use linkerd_app_core::{
1212
transport::{ClientAddr, OrigDstAddr, Remote},
1313
Result,
1414
};
15-
pub use linkerd_server_policy::{Authentication, Authorization, Protocol, ServerPolicy, Suffix};
16-
use std::{collections::BTreeMap, sync::Arc};
15+
pub use linkerd_server_policy::{
16+
Authentication, Authorization, Labels, Protocol, ServerPolicy, Suffix,
17+
};
18+
use std::sync::Arc;
1719
use thiserror::Error;
1820

1921
pub(crate) trait CheckPolicy {
@@ -38,8 +40,8 @@ pub(crate) struct Permitted {
3840
pub protocol: Protocol,
3941
pub tls: tls::ConditionalServerTls,
4042

41-
// We want predictable ordering of labels, so we use a BTreeMap.
42-
pub labels: BTreeMap<String, String>,
43+
pub server_labels: Labels,
44+
pub authz_labels: Labels,
4345
}
4446

4547
#[derive(Clone, Debug, Error)]
@@ -52,7 +54,9 @@ pub(crate) struct DeniedUnauthorized {
5254
client_addr: Remote<ClientAddr>,
5355
dst_addr: OrigDstAddr,
5456
tls: tls::ConditionalServerTls,
57+
labels: Labels,
5558
}
59+
5660
// === impl DefaultPolicy ===
5761

5862
impl From<ServerPolicy> for DefaultPolicy {
@@ -123,6 +127,7 @@ impl AllowPolicy {
123127
client_addr,
124128
dst_addr: self.dst,
125129
tls,
130+
labels: self.server.labels.clone(),
126131
})
127132
}
128133
}
@@ -131,12 +136,10 @@ impl AllowPolicy {
131136

132137
impl Permitted {
133138
fn new(server: &ServerPolicy, authz: &Authorization, tls: tls::ConditionalServerTls) -> Self {
134-
let mut labels = BTreeMap::new();
135-
labels.extend(server.labels.clone());
136-
labels.extend(authz.labels.clone());
137139
Self {
138140
protocol: server.protocol,
139-
labels,
141+
server_labels: server.labels.clone(),
142+
authz_labels: authz.labels.clone(),
140143
tls,
141144
}
142145
}

0 commit comments

Comments
 (0)