Skip to content

Commit

Permalink
inbound: Support multiple authorization types
Browse files Browse the repository at this point in the history
The inbound policy module uses the label `saz_name` to indicate the
authorization resource being employed to allow/deny traffic. This
corresponds to the `ServerAuthorization` kubernetes resource (with the
`saz` shortname). This resource type is going to be deprecated in favor
of a new, more general, `AuthorizationPolicy` resource.

When this change is made in the control plane, the policy controller
will include a `kind` label on gRPC messages indicating whether the
resource type, or `default` if a default policy is in effect.

This change honors this new `kind` field and adds a dedicated label to
indicate the kind.

Server labels are changed from:

    srv_name="default:foo"
    srv_name="fah"

to:

    srv_kind="default",srv_name="foo"
    srv_kind="server",srv_name="fah"

Authorization labels are changed from:

    saz_name="default:bar"
    saz_name="bah"

to:

    authz_kind="default",authz_name="bar"
    authz_kind="serverauthorization",authz_name="bah"

Signed-off-by: Oliver Gould <ver@buoyant.io>
  • Loading branch information
olix0r committed Mar 24, 2022
1 parent f08371e commit 097fb1e
Show file tree
Hide file tree
Showing 15 changed files with 137 additions and 42 deletions.
22 changes: 12 additions & 10 deletions linkerd/app/core/src/metrics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,17 @@ pub struct InboundEndpointLabels {

/// A label referencing an inbound `Server` (i.e. for policy).
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct ServerLabel(pub Arc<str>);
pub struct ServerLabel {
pub kind: Arc<str>,
pub name: Arc<str>,
}

/// Labels referencing an inbound `ServerAuthorization.
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct AuthzLabels {
pub server: ServerLabel,
pub authz: Arc<str>,
pub kind: Arc<str>,
pub name: Arc<str>,
}

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
Expand Down Expand Up @@ -289,22 +293,20 @@ impl FmtLabels for InboundEndpointLabels {
}
}

impl fmt::Display for ServerLabel {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}

impl FmtLabels for ServerLabel {
fn fmt_labels(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "srv_name=\"{}\"", self.0)
write!(f, "srv_kind=\"{}\",srv_name=\"{}\"", self.kind, self.name)
}
}

impl FmtLabels for AuthzLabels {
fn fmt_labels(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.server.fmt_labels(f)?;
write!(f, ",saz_name=\"{}\"", self.authz)
write!(
f,
"authz_kind=\"{}\",authz_name=\"{}\"",
self.kind, self.name
)
}
}

Expand Down
7 changes: 5 additions & 2 deletions linkerd/app/core/src/transport/labels.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,14 +194,17 @@ mod tests {
negotiated_protocol: None,
}),
([192, 0, 2, 4], 40000).into(),
PolicyServerLabel("testserver".into()),
PolicyServerLabel {
kind: "server".into(),
name: "testserver".into(),
},
);
assert_eq!(
labels.to_string(),
"direction=\"inbound\",peer=\"src\",\
target_addr=\"192.0.2.4:40000\",target_ip=\"192.0.2.4\",target_port=\"40000\",\
tls=\"true\",client_id=\"foo.id.example.com\",\
srv_name=\"testserver\""
srv_kind=\"server\",srv_name=\"testserver\""
);
}
}
2 changes: 2 additions & 0 deletions linkerd/app/inbound/src/accept.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,10 @@ mod tests {
authorizations: vec![Authorization {
authentication: Authentication::Unauthenticated,
networks: vec![Default::default()],
kind: "serverauthorization".into(),
name: "testsaz".into(),
}],
kind: "server".into(),
name: "testsrv".into(),
},
None,
Expand Down
2 changes: 2 additions & 0 deletions linkerd/app/inbound/src/detect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -469,8 +469,10 @@ mod tests {
authorizations: vec![Authorization {
authentication: Authentication::Unauthenticated,
networks: vec![client_addr().ip().into()],
kind: "serverathorizationu".into(),
name: "testsaz".into(),
}],
kind: "server".into(),
name: "testsrv".into(),
},
);
Expand Down
1 change: 1 addition & 0 deletions linkerd/app/inbound/src/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ pub mod fuzz {
authorizations: vec![policy::Authorization {
authentication: policy::Authentication::Unauthenticated,
networks: vec![std::net::IpAddr::from([192, 0, 2, 3]).into()],
kind: "server".into(),
name: "testsaz".into(),
}],
name: "testsrv".into(),
Expand Down
12 changes: 10 additions & 2 deletions linkerd/app/inbound/src/http/router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,8 +253,16 @@ where
{
fn from((permit, t): (policy::Permit, T)) -> Self {
let labels = vec![
("srv_name".to_string(), permit.labels.server.to_string()),
("saz_name".to_string(), permit.labels.authz.to_string()),
(
"srv_kind".to_string(),
permit.labels.server.kind.to_string(),
),
(
"srv_name".to_string(),
permit.labels.server.name.to_string(),
),
("authz_kind".to_string(), permit.labels.kind.to_string()),
("authz_name".to_string(), permit.labels.name.to_string()),
];

Self {
Expand Down
7 changes: 6 additions & 1 deletion linkerd/app/inbound/src/http/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -610,8 +610,10 @@ impl svc::Param<policy::AllowPolicy> for Target {
authorizations: vec![policy::Authorization {
authentication: policy::Authentication::Unauthenticated,
networks: vec![std::net::IpAddr::from([192, 0, 2, 3]).into()],
kind: "serverauthorization".into(),
name: "testsaz".into(),
}],
kind: "server".into(),
name: "testsrv".into(),
},
);
Expand All @@ -621,7 +623,10 @@ impl svc::Param<policy::AllowPolicy> for Target {

impl svc::Param<policy::ServerLabel> for Target {
fn param(&self) -> policy::ServerLabel {
policy::ServerLabel("testsrv".into())
policy::ServerLabel {
kind: "server".into(),
name: "testsrv".into(),
}
}
}

Expand Down
17 changes: 13 additions & 4 deletions linkerd/app/inbound/src/policy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ impl From<DefaultPolicy> for ServerPolicy {
DefaultPolicy::Deny => ServerPolicy {
protocol: Protocol::Opaque,
authorizations: vec![],
name: "default:deny".into(),
kind: "default".into(),
name: "deny".into(),
},
}
}
Expand Down Expand Up @@ -101,7 +102,11 @@ impl AllowPolicy {

#[inline]
pub fn server_label(&self) -> ServerLabel {
ServerLabel(self.server.borrow().name.clone())
let s = self.server.borrow();
ServerLabel {
kind: s.kind.clone(),
name: s.name.clone(),
}
}

async fn changed(&mut self) {
Expand Down Expand Up @@ -169,8 +174,12 @@ impl Permit {
dst,
protocol: server.protocol,
labels: AuthzLabels {
server: ServerLabel(server.name.clone()),
authz: authz.name.clone(),
kind: authz.kind.clone(),
name: authz.name.clone(),
server: ServerLabel {
kind: server.kind.clone(),
name: server.name.clone(),
},
},
}
}
Expand Down
2 changes: 1 addition & 1 deletion linkerd/app/inbound/src/policy/authorize/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ where
}
Err(e) => {
tracing::info!(
server = %self.policy.server_label(),
server = %format_args!("{}:{}", self.policy.server_label().kind, self.policy.server_label().name),
tls = ?self.tls,
client = %self.client_addr,
"Request denied",
Expand Down
8 changes: 6 additions & 2 deletions linkerd/app/inbound/src/policy/authorize/tcp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,11 @@ where
})
}
Err(deny) => {
tracing::info!(server = %policy.server_label(), ?tls, %client, "Connection denied");
tracing::info!(
server = %format_args!("{}:{}", policy.server_label().kind, policy.server_label().name),
?tls, %client,
"Connection denied"
);
self.metrics.deny(&policy, tls);
AuthorizeTcp::Unauthorized(Unauthorized { deny })
}
Expand Down Expand Up @@ -150,7 +154,7 @@ where
_ = policy.changed() => {
if let Err(denied) = policy.check_authorized(client, &tls) {
tracing::info!(
server = %policy.server_label(),
server = %policy.server_label().name,
?tls,
%client,
"Connection terminated due to policy change",
Expand Down
2 changes: 2 additions & 0 deletions linkerd/app/inbound/src/policy/defaults.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,10 @@ fn mk(
authorizations: vec![Authorization {
networks: nets.into_iter().map(Into::into).collect(),
authentication,
kind: "default".into(),
name: name.into(),
}],
kind: "default".into(),
name: name.into(),
}
}
53 changes: 41 additions & 12 deletions linkerd/app/inbound/src/policy/discover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@ fn to_policy(proto: api::Server) -> Result<ServerPolicy> {
};

let loopback = Authorization {
name: "default:localhost".into(),
kind: "default".into(),
name: "localhost".into(),
authentication: Authentication::Unauthenticated,
networks: vec![
Network {
Expand Down Expand Up @@ -176,32 +177,60 @@ fn to_policy(proto: api::Server) -> Result<ServerPolicy> {
authn => return Err(format!("no authentication provided: {:?}", authn).into()),
};

let name = labels
.get("name")
.ok_or("authorization missing 'name' label")?
.clone()
.into();
let (kind, name) = {
let name = labels
.get("name")
.ok_or("authorization missing 'name' label")?
.clone();

let mut parts = name.splitn(2, ':');
match (parts.next().unwrap(), parts.next()) {
(kind, Some(name)) => (kind.into(), name.into()),
(name, None) => {
let kind = labels
.get("kind")
.cloned()
.unwrap_or_else(|| "serverauthorization".to_string());
(kind.into(), name.into())
}
}
};

Ok(Authorization {
networks,
authentication: authn,
kind,
name,
})
},
)
.chain(Some(Ok(loopback)))
.collect::<Result<Vec<_>>>()?;

let name = proto
.labels
.get("name")
.ok_or("server missing 'name' label")?
.clone()
.into();
let (kind, name) = {
let name = proto
.labels
.get("name")
.ok_or("server missing 'name' label")?
.clone();
let mut parts = name.splitn(2, ':');
match (parts.next().unwrap(), parts.next()) {
(kind, Some(name)) => (kind.into(), name.into()),
(name, None) => {
let kind = proto
.labels
.get("kind")
.cloned()
.unwrap_or_else(|| "server".to_string());
(kind.into(), name.into())
}
}
};

Ok(ServerPolicy {
protocol,
authorizations,
kind,
name,
})
}
Expand Down
Loading

0 comments on commit 097fb1e

Please sign in to comment.