---
# System prepended metadata

title: Ratify CRD Multi-tenancy Support

---

# Background
Ratify is going to support multi-tenancy model in the next release. One major necessary refactoring is CRD scope.

Currently we have 4 CRDs with different scopes, including policy, store, verifier and certificateStore.

|CRD| scope |
|---|---|
|policy|cluster|
|store|cluster|
|verifier|cluster|
|certificateStore|namespaced|

Take Policy and CertificateStore as examples:
```yaml
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: policies.config.ratify.deislabs.io
spec:
  group: config.ratify.deislabs.io
  names:
    kind: Policy
    listKind: PolicyList
    plural: policies
    singular: policy
  scope: Cluster
```
```yaml
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: certificatestores.config.ratify.deislabs.io
spec:
  group: config.ratify.deislabs.io
  names:
    kind: CertificateStore
    listKind: CertificateStoreList
    plural: certificatestores
    singular: certificatestore
  scope: Namespaced
```

To support both namespaced and cluster-wide resources, we would have to create 2 CRDs for each resource, one is namespaced, and the other is cluster-wide.

For each resource, the name of 2 CRDs would be different in terms of the scope. Therefore, there are 3 options to make this change.

## 1. ClusterResource vs Resource
For cluster-wide resources, we would prefix CRD name with `Cluster`.
e.g.
- ClusterPolicy
- ClusterStore
- ClusterVerifier
- ClusterCertificateStore

And for namespaced resources, we would keep the original names like: Policy/Store/Verifier/CertificateStore

### Examples
Cluster-wide Policy:
```yaml
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: clusterpolicies.config.ratify.deislabs.io
spec:
  group: config.ratify.deislabs.io
  names:
    kind: ClusterPolicy
    listKind: ClusterPolicyList
    plural: clusterpolicies
    singular: clusterpolicy
  scope: Cluster
```
Namespaced Policy:
```yaml
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: policies.config.ratify.deislabs.io
spec:
  group: config.ratify.deislabs.io
  names:
    kind: Policy
    listKind: PolicyList
    plural: policies
    singular: policy
  scope: Namespaced
```

### Pros & Cons
#### Pros
- It's clear to customers to differentiate between cluster-wide and namespaced resources.
- It's the same as the way Kyverno handles ClusterPolicy/Policy.
- User Experience: it's convenient and clear for users to apply correspoding CRs per namespace(cluster).
#### Cons
- Current verifier/store/policy are cluster-wide resources, we have to update their scope to namespaced, which is a breaking change since spec.scope is immutable.


## 2. Resource vs NamespacedResource
For cluster-wide resources, we would keep the original names like: Policy/Store/Verifier/CertificateStore

For namespaced resources, names would be prefixed with `Namespaced`, e.g.
- NamespacedPolicy
- NamespacedStore
- NamespacedVerifier
- NamespacedCertificateStore

### Examples
Cluster-wide policy:
```yaml
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: policies.config.ratify.deislabs.io
spec:
  group: config.ratify.deislabs.io
  names:
    kind: Policy
    listKind: PolicyList
    plural: policies
    singular: policy
  scope: Cluster
```
Namespaced policy:
```yaml
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: namespacedpolicies.config.ratify.deislabs.io
spec:
  group: config.ratify.deislabs.io
  names:
    kind: NamespacedPolicy
    listKind: NamespacedPolicyList
    plural: namespacedpolicies
    singular: namespacedpolicy
  scope: Namespaced
```

### Pros & Cons
#### Pros
- It's relatively clear for customers to differentiate between cluster-wide and namespaced resources.
- Though it requires breaking change to certificateStore naming, it's less work and change than option 1.
#### Cons
- It's more more to name ClusterResource/Resource than Resource/NamespacedResource.
- It also requires breaking change to cetificateStore which is namespaced now.

## 3. Mixture of Option 1 and 2
The purpose of this option is to avoid breaking changes. The overall naming for each resource is below:
| Resource | Cluster-wide | Namespaced|
|---|---|---|
| Policy| Policy | NamespacedPolicy |
| Verifier | Verifier | NamespacedVerifier |
| Store | Store | NamespacedStore |
| CertificateStore | ClusterCertificateStore | CertificateStore |

This option have different naming approaches for 2 groups, one is policy/verifier/store, and the other is certStore.

#### Pros
- It avoids breaking change to CRD names. We don't need to update existing CRDs but just add new CRDs.
#### Cons
- User Experience: Resources have different name prefix in terms of the scope.

# Conclusion
Option 1 and 2 are the same under the hood except option 2 requires less breaking change.
And we need to consider user experience from 2 perspective:
1. Compatibility during upgrading Ratify with multi-tenancy support.
    - Breaking change in CRD means that users have to delete all existing CRDs before upgrading Ratify.
    - If customers are fine with this one-time operation, then option 1 would be best.
    - If this is not acceptable, then we can only adopt option 3.
2. User experience post upgrading Ratify.
    - This is on-going user experience for customers as they need to keep applying CRs.
    - To make it more convenient and clear for customers to apply CRs in terms of scopes, option 1 would be the best option.