Sandor Molnar created KNOX-3557:
-----------------------------------

             Summary: K8sDestinationAudienceValidator: do not match aud entries 
that carry a resource path when the path header is not configured
                 Key: KNOX-3557
                 URL: https://issues.apache.org/jira/browse/KNOX-3557
             Project: Apache Knox
          Issue Type: Task
          Components: KnoxIDF
            Reporter: Sandor Molnar
            Assignee: Sandor Molnar
             Fix For: 3.1.0


h3. Problem

When {{request.audience.k8s.path.header.name}} is not configured, 
{{K8sDestinationAudienceValidator.matchesPath}} returns {{true}} for any 
resource path. So an {{aud}} entry that names a resource path matches every 
request to that destination service, although the entry asks for something 
narrower.

Because of how the two forms are parsed, Knox may then read an entry as naming 
a different service than its path suggests:
 * *DNS form.* With {{{}request.audience.k8s.dns.format.enabled=true{}}}, every 
entry is tried as the DNS form first, and the custom form is used only if that 
doesn't match. A host with one or two labels, or of the form 
{{{}<a>.<b>.svc[.<cluster-domain prefix>]{}}}, parses as a DNS name, and the 
path is never compared. {{[https://svc-a.ns-a.svc.cluster.local/ns-b/svc-b]}} 
therefore matches {{svc-a}} in {{{}ns-a{}}}.
 * *Custom form.* The first two path segments are the namespace and service. 
The rest is the resource path, which is also never compared. 
{{https://<cluster-domain>/ns-a/svc-a/ns-b/svc-b}} therefore matches {{svc-a}} 
in {{{}ns-a{}}}.

Some components check these values outside Knox. One example is an admission 
policy that authorizes delegation-policy {{resourcePolicy}} keys by their 
trailing {{{}/<namespace>/<service>{}}}. Such a component reads both entries 
above as targeting {{{}ns-b/svc-b{}}}, while Knox accepts them for 
{{{}ns-a/svc-a{}}}. Today it can only be safe by copying Knox's host-parsing 
rules.
h3. Proposal

When the path header is not configured, treat an {{aud}} entry whose resource 
path is not {{/}} as not matching, in both forms. Entries without a path don't 
change: they still mean the whole service. A DNS-form entry that doesn't match 
still falls back to the custom form, as it does today. There the host must be 
in {{{}request.audience.k8s.cluster-domains{}}}.

With this change, both examples above are rejected for {{{}svc-a{}}}. An 
external check then only needs an exact {{/<namespace>/<service>}} ending for 
the custom form, or an exact host for the DNS form.

*Compatibility:* deployments that configure no path header but mint audiences 
with a path would start failing. Either:
 * make this the default and say so in the release notes; or
 * keep today's behaviour behind an opt-out parameter.

h3. Tests
 * No path header configured:
 ** a DNS-form entry with a non-root path doesn't match;
 ** a custom-form entry with segments after {{/<namespace>/<service>}} doesn't 
match;
 ** entries without a path, in either form, still match.
 * No path header configured: a DNS-form entry with a path falls back to the 
custom form, and matches only if its host is in {{cluster-domains}} and its 
path is exactly {{{}/<namespace>/<service>{}}}.
 * Path header configured: behavior unchanged.



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

Reply via email to