diff --git a/docs/book/src/developer/architecture/controllers/multi-tenancy.md b/docs/book/src/developer/architecture/controllers/multi-tenancy.md index 9c57e6b8c41d..bed85bfb0667 100644 --- a/docs/book/src/developer/architecture/controllers/multi-tenancy.md +++ b/docs/book/src/developer/architecture/controllers/multi-tenancy.md @@ -1,7 +1,7 @@ # Multi tenancy -Multi tenancy in Cluster API defines the capability of an infrastructure provider to manage different credentials, each -one of them corresponding to an infrastructure tenant. +Multi tenancy in Cluster API defines the capability of an infrastructure provider to manage +different credentials, each one of them corresponding to an infrastructure tenant. ## Contract @@ -11,3 +11,108 @@ In order to support multi tenancy, the following rule applies: - Providers SHOULD deploy and run any kind of webhook (validation, admission, conversion) following Cluster API codebase best practices for the same release. - Providers MUST create and publish a `{type}-component.yaml` accordingly. +- Providers MUST use the field of name `identityRef` to reference the multi-tenancy CR in the + `InfraCluster` CR. +- Providers MUST implement `identityRef` must be of the following type: + + ```go + type ProviderIdentityReference struct { + // Kind of the identity. + // +kubebuilder:validation:Enum= + Kind string + // Name of the identity. + // +kubebuilder:validation:MinLength=1 + Name string + } + ``` + +- A Namespace field MUST never be added to the ProviderIdentityReference type to avoid crossing + namespace boundaries. + +- Where identity types use private key material, CRs MUST implement a `secretRef` on their spec of + type string and only read secrets from the same namespace as the CR for namespaced scope resources + OR the controller namespace for cluster-scoped resources. + +- Providers MAY support `Secret` as a top-level + supported identity type, but only from the same namespace as the owning CR. + +- Providers MAY support the use of `identityRef` in other low-level resources, such as Load + Balancers. + +## Supported RBAC Models + +Providers MAY support any combination of cluster-scoped or namespace-scoped CRs as follows: + +### Cluster-scoped global resources for delegated access + +In a common use for multi-tenancy, a cloud admin will want to set up a range of identities, and then +delegate them to individual teams. This is best done using global resources to prevent repetition. + +#### Cluster-scoped Contract + +- Cluster scoped resources MUST be named with `ClusterIdentity`. Examples: + - `FabrikamClusterRoleIdentity` + - `FabrikamClusterStaticIdentity` + +- Where identity types use private key material, CRs MUST + implement a `secretRef` on their spec of type string and + only read secrets from the controller namespace. + +- Cluster scoped resources MUST be delegated using a + label selector, present on the spec as: + +```go +type InfraClusterIdentity struct { + // AllowedNamespaces is used to identify which namespaces are allowed to use the identity from. + // Namespaces can be selected either using an array of namespaces or with label selector. + // An empty allowedNamespaces object indicates that clusters can use this identity from any + // namespace. + // If this object is nil, no namespaces will be allowed (default behaviour, if this field is not + // provided). + // A namespace should be either in the NamespaceList or match with Selector to use the identity. + // + // +optional +AllowedNamespaces *AllowedNamespaces `json:"allowedNamespaces"` +} + +type AllowedNamespaces struct { + // AllowedNamespaces is a selector of namespaces that clusters can use this Identity from. + // This is a standard Kubernetes LabelSelector, a label query over a set of resources. + // The result of matchLabels and matchExpressions are ANDed. + // + // An empty selector indicates that resources cannot use this identity from any namespace if + // NamespaceList is not supplied. + // +optional + Selector metav1.LabelSelector `json:"selector"` +} +``` +- Providers MAY support an additional `NamespaceList` string + slice in the `AllowedNamespaces` struct. + +- Providers MUST treat nil for `AllowedNamespaces` as matching zero namespaces. +- Providers MUST treat `{}` as matching *all* namespaces. +- Providers SHOULD mark `NamespaceList` as deprecated from v1alpha4 + +When Cluster API no longer supports Kubernetes versions older than Kubernetes v1.21, when the +NamespaceDefaultLabelName [feature gate] transitioned to Beta, then: + + - Providers MUST remove the `NamespaceList` field. + - Conversion webhooks in MUST perform the following: + - Translate the NamespaceList into the following match expression: + - `kubernetes.io/metadata.name in ()` + +### Namespaced scoped resources + +Namespaced scoped resources are useful most particularly when you want to allow developers to +provision clusters on their own accounts, but may not be suitable for every use case. + +#### Namespace-scoped contract + +- Namespace scoped resources MUST be named `Identity`, e.g.: + - `ContosoCloudRoleIdentity` + - `ContosoCloudStaticIdentity` +- Where identity types use private key material, CRs MUST + implement a `secretRef` on their spec of type string and + only read secrets from the same namespace as the CR. + +[feature gate]: https://kubernetes.io/docs/reference/command-line-tools-reference/feature-gates/