|
| 1 | +# NPEP-122: Tenancy API |
| 2 | + |
| 3 | +* Issue: [#122](https://github.com/kubernetes-sigs/network-policy-api/issues/122) |
| 4 | +* Status: Provisional |
| 5 | + |
| 6 | +## TLDR |
| 7 | + |
| 8 | +Tenancy definition and the API (SameLabels/NotSameLabels) is confusing and ambiguous as of now. |
| 9 | +We want to rethink the tenancy use cases and the API to keep it simple and easy to understand, but |
| 10 | +flexible enough to cover all defined use cases. |
| 11 | + |
| 12 | +## Goals |
| 13 | + |
| 14 | +- Clarify tenancy use cases. |
| 15 | +- Provide a complete definition of a tenant in respect to ANP. |
| 16 | +- Avoid unneeded tenancy configs that only exist because of ANP use cases. |
| 17 | + |
| 18 | +## Non-Goals |
| 19 | + |
| 20 | +- Define new use cases for tenancy (as opposed to clarify the ones we considered initially, but didn't explain well enough) |
| 21 | +- Define user stories for multiple tenancy policies in the same cluster. |
| 22 | + |
| 23 | +## Introduction |
| 24 | + |
| 25 | +The KEP doesn’t say a whole lot about tenants… |
| 26 | + |
| 27 | +From the Goals: |
| 28 | + |
| 29 | + As a cluster administrator, I want to have the option to enforce in-cluster network level access controls that |
| 30 | + facilitate network multi-tenancy and strict network level isolation between multiple teams and tenants sharing |
| 31 | + a cluster via use of namespaces or groupings of namespaces per tenant. |
| 32 | + |
| 33 | + Example: I would like to define two tenants in my cluster, one composed of the pods in foo-ns-1 and foo-ns-2 |
| 34 | + and the other with pods in bar-ns-1, where inter-tenant traffic is denied. |
| 35 | + |
| 36 | +From the User Stories: |
| 37 | + |
| 38 | + Story 4: Create and Isolate multiple tenants in a cluster |
| 39 | + |
| 40 | + As a cluster admin, I want to build tenants in my cluster that are isolated from each other by default. |
| 41 | + Tenancy may be modeled as 1:1, where 1 tenant is mapped to a single Namespace, or 1:n, where a single tenant |
| 42 | + may own more than 1 Namespace. |
| 43 | + |
| 44 | +Elsewhere: |
| 45 | + |
| 46 | + AdminNetworkPolicy Pass rules allows an admin to delegate security posture for certain traffic to the Namespace |
| 47 | + owners by overriding any lower precedence Allow or Deny rules. For example, intra-tenant traffic management can be |
| 48 | + delegated to tenant admins explicitly with the use of Pass rules. |
| 49 | + |
| 50 | +So really, the only solidly-agreed-upon use case is that you should be able to create enforced isolation |
| 51 | +between particular sets of namespaces. |
| 52 | + |
| 53 | +### Clarifying user stories |
| 54 | + |
| 55 | +#### Story 4.1: Create and Isolate multiple tenants in a cluster by default, overridable isolation |
| 56 | + |
| 57 | +Here is the existing tenancy related user story from our website: |
| 58 | + |
| 59 | + As a cluster admin, I want to build tenants in my cluster that are isolated from each other by default. |
| 60 | + Tenancy may be modeled as 1:1, where 1 tenant is mapped to a single Namespace, or 1:n, where a single tenant |
| 61 | + may own more than 1 Namespace. |
| 62 | + |
| 63 | +The wording used here has led to much confusion. Specifically, the "by default" part actually means this policy should |
| 64 | +be at the BANP priority, and solves the "Engineering org vs Marketing org" use case where you want to keep orgs |
| 65 | +from accidentally interfering with each other. By default, cross-tenant traffic should be dropped. |
| 66 | +However, namespace owners can override this behavior by applying their own policies as needed. |
| 67 | + |
| 68 | +In reality, the CR attached to this story defines strict tenancy, which should be a separate use case (see next section). |
| 69 | + |
| 70 | +To make the use case more obvious we can add some details to it like the following |
| 71 | + |
| 72 | + As a cluster admin, I want to build tenants for different departments (e.g. Engineering vs Marketing) |
| 73 | + in my cluster that are isolated from each other by default. |
| 74 | + By default, cross-tenant traffic is dropped. However, namespace owners can override this behavior by applying |
| 75 | + their own policies as needed. |
| 76 | + Tenancy may be modeled as 1:1, where 1 tenant is mapped to a single Namespace, or 1:n, where a single tenant |
| 77 | + may own more than 1 Namespace. |
| 78 | + |
| 79 | +#### Story 4.2: Create and Isolate multiple tenants in a cluster, strict isolation |
| 80 | + |
| 81 | +Strict tenancy is the "Coke vs Pepsi" sort of thing where you want each tenant to feel like it has its own cluster, |
| 82 | +and be totally independent of the other tenants. We can write it down like this |
| 83 | + |
| 84 | + As a cluster admin, I want to build tenants for different organizations (e.g. Coke vs Pepsi) |
| 85 | + in my cluster that are isolated from each other, where this isolation |
| 86 | + can't be overridden by namespace owners. This policy should make every tenant completely independent and isolated |
| 87 | + from other tenants. Tenancy may be modeled as 1:1, where 1 tenant is mapped to a single Namespace, or 1:n, where a single tenant |
| 88 | + may own more than 1 Namespace. |
| 89 | + |
| 90 | +#### Story 4.3: Allow internal connections for tenants |
| 91 | + |
| 92 | + As a cluster admin, I want to build tenants in my cluster and always allow connections inside one tenant. |
| 93 | + At the same time I want to setup an overridable deny-all policy to protect namespaces by default. |
| 94 | + This policy should make sure internal connectivity for a tenant is always allowed, in case there are |
| 95 | + lower-priority deny rules. |
| 96 | + |
| 97 | +#### Story 4.4: Tenants interaction with (B)ANP |
| 98 | + |
| 99 | + As a cluster admin, I want to be able to setup policies with higher and lower priority than tenancy policy. |
| 100 | + I want to deny inter-tenant connections, but I want to allow ingress traffic from the monitoring namespace |
| 101 | + to all namespaces. Therefore, I need "allow from monitoring" rule to have higher priority than "deny from |
| 102 | + other tenants". |
| 103 | + I want to setup "deny all" BANP to protect cluster workloads, but I want to allow internal connections |
| 104 | + within tenant. Therefore, I need "allow from same tenant" rule to have higher priority than "deny all" BANP. |
| 105 | + |
| 106 | +#### What I couldn't figure out user stories for |
| 107 | + |
| 108 | +- Skip action |
| 109 | +- Ports *[]AdminNetworkPolicyPort |
| 110 | + |
| 111 | +### Existing API |
| 112 | + |
| 113 | +AdminNetworkPolicy has the “SameLabels” and “NotSameLabels” fields to support the use cases involving tenancy. For example: |
| 114 | + |
| 115 | +**Use case** |
| 116 | + |
| 117 | +Traffic should be disallowed by default between namespaces owned by different users (defined by labels i.e `user=foo` or `user=bar`). |
| 118 | + |
| 119 | +**Policy** |
| 120 | +``` |
| 121 | +kind: BaselineAdminNetworkPolicy |
| 122 | +apiVersion: policy.networking.k8s.io/v1alpha1 |
| 123 | +metadata: |
| 124 | + name: user-based-tenancy |
| 125 | +spec: |
| 126 | + subject: |
| 127 | + namespaces: |
| 128 | + matchExpressions: |
| 129 | + - key: user |
| 130 | + operator: Exists |
| 131 | + ingress: |
| 132 | + - action: Deny |
| 133 | + from: |
| 134 | + - namespaces: |
| 135 | + notSameLabels: |
| 136 | + - user |
| 137 | +``` |
| 138 | + |
| 139 | +**Meaning** |
| 140 | + |
| 141 | +In namespaces that have a “user” label, by default, deny ingress from namespaces that have a different “user” label. |
| 142 | + |
| 143 | +There are several major problems with this implementation of tenancy as it pertains to the user stories. |
| 144 | + |
| 145 | +First, There is no explicit definition of "tenancy" anywhere. The administrator has an idea of |
| 146 | +"tenants are defined by the user label", but that's only true because this particular ANP happens to include that |
| 147 | +particular rule, and there's no way to find the ANP(s) that defines tenancy if you don't already know what they are. |
| 148 | + |
| 149 | +Second, the SameLabels/NotSameLabels selectors behave really differently from other peers, causing multiple underlying |
| 150 | +rules to be created, and the syntax doesn't make that obvious. |
| 151 | + |
| 152 | +Third, the syntax is very general purpose / powerful. ANP has subjects and peers, which are different, |
| 153 | +and currently Tenancy is defined on the peers side. Tenancy by itself has the same subject and peer, |
| 154 | +at least for the existing use cases, and having separate selectors for subject and peer allows for more |
| 155 | +configurations than needed. |
| 156 | + |
| 157 | +Fourth, the ANP subject allows using pod selectors, while tenancy use cases only need namespace selectors. |
| 158 | + |
| 159 | +## API |
| 160 | + |
| 161 | +TBD |
| 162 | + |
| 163 | +## Conformance Details |
| 164 | + |
| 165 | +TBD |
| 166 | +<!--- |
| 167 | +(This section describes the names to be used for the feature or |
| 168 | +features in conformance tests and profiles. |
| 169 | +
|
| 170 | +These should be `CamelCase` names that specify the feature as |
| 171 | +precisely as possible, and are particularly important for |
| 172 | +Extended features, since they may be surfaced to users.) |
| 173 | +--> |
| 174 | + |
| 175 | +## Alternatives |
| 176 | + |
| 177 | +Other alternatives were mentioned https://docs.google.com/document/d/113xBe7VMK7hMYdIdB9gobp7JwVkWQLnqdMPNkamfaK8/edit, |
| 178 | +but none of them cover all the Goals defined in this NPEP. |
| 179 | + |
| 180 | +There are 2 main problems with leaving Tenancy as a (B)ANP peer: |
| 181 | +1. tenancy is only based on namespace labels, but (B)ANP subject allows using pod selector too |
| 182 | +2. tenancy definition is less obvious, since it is a part of the peers list. Usually peer rules are the same for |
| 183 | +all (B)ANP subject pods, but for tenancy that is not true. |
| 184 | +3. There are actually more that 2 problems, mainly about allowing much more configurations for tenancy than we have |
| 185 | +user stories for, but it is covered in the previous sections :) |
| 186 | + |
| 187 | +Therefore, creating a new object seems like a more clear way to implement Tenancy. |
| 188 | + |
| 189 | +## References |
| 190 | + |
| 191 | +- https://docs.google.com/document/d/113xBe7VMK7hMYdIdB9gobp7JwVkWQLnqdMPNkamfaK8 |
0 commit comments