Skip to content

Commit

Permalink
Provide more prescriptive guidance on multi-tenancy
Browse files Browse the repository at this point in the history
Signed-off-by: Naadir Jeewa <jeewan@vmware.com>
  • Loading branch information
randomvariable committed Apr 22, 2021
1 parent 6750716 commit 106f25a
Showing 1 changed file with 107 additions and 2 deletions.
109 changes: 107 additions & 2 deletions docs/book/src/developer/architecture/controllers/multi-tenancy.md
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -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=<Supported provider types>
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 `<Provider>Cluster<Type>Identity`. 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 (<comma-separated list of namespaces from <NamespaceList>)`

### 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 `<Provider><Type>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/

0 comments on commit 106f25a

Please sign in to comment.