Skip to content

Commit 106f25a

Browse files
author
Naadir Jeewa
committed
Provide more prescriptive guidance on multi-tenancy
Signed-off-by: Naadir Jeewa <[email protected]>
1 parent 6750716 commit 106f25a

File tree

1 file changed

+107
-2
lines changed

1 file changed

+107
-2
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Multi tenancy
22

3-
Multi tenancy in Cluster API defines the capability of an infrastructure provider to manage different credentials, each
4-
one of them corresponding to an infrastructure tenant.
3+
Multi tenancy in Cluster API defines the capability of an infrastructure provider to manage
4+
different credentials, each one of them corresponding to an infrastructure tenant.
55

66
## Contract
77

@@ -11,3 +11,108 @@ In order to support multi tenancy, the following rule applies:
1111
- Providers SHOULD deploy and run any kind of webhook (validation, admission, conversion)
1212
following Cluster API codebase best practices for the same release.
1313
- Providers MUST create and publish a `{type}-component.yaml` accordingly.
14+
- Providers MUST use the field of name `identityRef` to reference the multi-tenancy CR in the
15+
`InfraCluster` CR.
16+
- Providers MUST implement `identityRef` must be of the following type:
17+
18+
```go
19+
type ProviderIdentityReference struct {
20+
// Kind of the identity.
21+
// +kubebuilder:validation:Enum=<Supported provider types>
22+
Kind string
23+
// Name of the identity.
24+
// +kubebuilder:validation:MinLength=1
25+
Name string
26+
}
27+
```
28+
29+
- A Namespace field MUST never be added to the ProviderIdentityReference type to avoid crossing
30+
namespace boundaries.
31+
32+
- Where identity types use private key material, CRs MUST implement a `secretRef` on their spec of
33+
type string and only read secrets from the same namespace as the CR for namespaced scope resources
34+
OR the controller namespace for cluster-scoped resources.
35+
36+
- Providers MAY support `Secret` as a top-level
37+
supported identity type, but only from the same namespace as the owning CR.
38+
39+
- Providers MAY support the use of `identityRef` in other low-level resources, such as Load
40+
Balancers.
41+
42+
## Supported RBAC Models
43+
44+
Providers MAY support any combination of cluster-scoped or namespace-scoped CRs as follows:
45+
46+
### Cluster-scoped global resources for delegated access
47+
48+
In a common use for multi-tenancy, a cloud admin will want to set up a range of identities, and then
49+
delegate them to individual teams. This is best done using global resources to prevent repetition.
50+
51+
#### Cluster-scoped Contract
52+
53+
- Cluster scoped resources MUST be named with `<Provider>Cluster<Type>Identity`. Examples:
54+
- `FabrikamClusterRoleIdentity`
55+
- `FabrikamClusterStaticIdentity`
56+
57+
- Where identity types use private key material, CRs MUST
58+
implement a `secretRef` on their spec of type string and
59+
only read secrets from the controller namespace.
60+
61+
- Cluster scoped resources MUST be delegated using a
62+
label selector, present on the spec as:
63+
64+
```go
65+
type InfraClusterIdentity struct {
66+
// AllowedNamespaces is used to identify which namespaces are allowed to use the identity from.
67+
// Namespaces can be selected either using an array of namespaces or with label selector.
68+
// An empty allowedNamespaces object indicates that clusters can use this identity from any
69+
// namespace.
70+
// If this object is nil, no namespaces will be allowed (default behaviour, if this field is not
71+
// provided).
72+
// A namespace should be either in the NamespaceList or match with Selector to use the identity.
73+
//
74+
// +optional
75+
AllowedNamespaces *AllowedNamespaces `json:"allowedNamespaces"`
76+
}
77+
78+
type AllowedNamespaces struct {
79+
// AllowedNamespaces is a selector of namespaces that clusters can use this Identity from.
80+
// This is a standard Kubernetes LabelSelector, a label query over a set of resources.
81+
// The result of matchLabels and matchExpressions are ANDed.
82+
//
83+
// An empty selector indicates that resources cannot use this identity from any namespace if
84+
// NamespaceList is not supplied.
85+
// +optional
86+
Selector metav1.LabelSelector `json:"selector"`
87+
}
88+
```
89+
- Providers MAY support an additional `NamespaceList` string
90+
slice in the `AllowedNamespaces` struct.
91+
92+
- Providers MUST treat nil for `AllowedNamespaces` as matching zero namespaces.
93+
- Providers MUST treat `{}` as matching *all* namespaces.
94+
- Providers SHOULD mark `NamespaceList` as deprecated from v1alpha4
95+
96+
When Cluster API no longer supports Kubernetes versions older than Kubernetes v1.21, when the
97+
NamespaceDefaultLabelName [feature gate] transitioned to Beta, then:
98+
99+
- Providers MUST remove the `NamespaceList` field.
100+
- Conversion webhooks in MUST perform the following:
101+
- Translate the NamespaceList into the following match expression:
102+
- `kubernetes.io/metadata.name in (<comma-separated list of namespaces from <NamespaceList>)`
103+
104+
### Namespaced scoped resources
105+
106+
Namespaced scoped resources are useful most particularly when you want to allow developers to
107+
provision clusters on their own accounts, but may not be suitable for every use case.
108+
109+
#### Namespace-scoped contract
110+
111+
- Namespace scoped resources MUST be named `<Provider><Type>Identity`, e.g.:
112+
- `ContosoCloudRoleIdentity`
113+
- `ContosoCloudStaticIdentity`
114+
- Where identity types use private key material, CRs MUST
115+
implement a `secretRef` on their spec of type string and
116+
only read secrets from the same namespace as the CR.
117+
118+
[feature gate]: https://kubernetes.io/docs/reference/command-line-tools-reference/feature-gates/

0 commit comments

Comments
 (0)