diff --git a/docs/multi-tenancy.md b/docs/multi-tenancy.md new file mode 100644 index 000000000..993303f30 --- /dev/null +++ b/docs/multi-tenancy.md @@ -0,0 +1,111 @@ +# Multi Tenancy + +Fleet uses Kubernetes RBAC where possible. + +One addition on top of RBAC is the [`GitRepoRestriction`](namespaces#restricting-gitrepos) resource, which can be used to control GitRepo resources in a namespace. + +A multi-tenant fleet setup looks like this: + +* tenants don't share namespaces, each tenant has one or more namespaces on the + upstream cluster, where they can create GitRepo resources +* tenants can deploy cluster wide resources and are limited to a set of + namespaces on downstream clusters +* clusters are in a separate namespace + +## Example Tenant + +This would create a user 'fleetuser', who can only manage GitRepo resources in the 'project1' namespace. + + kubectl create serviceaccount fleetuser + kubectl create namespace project1 + kubectl create -n project1 role fleetuser --verb=get --verb=list --verb=create --verb=delete --resource=gitrepos.fleet.cattle.io + kubectl create -n project1 rolebinding fleetuser --serviceaccount=default:fleetuser --role=fleetuser + +If we want to give access to multiple namespaces, we can use a single cluster role with two role bindings: + + kubectl create clusterrole fleetuser --verb=get --verb=list --verb=create --verb=delete --resource=gitrepos.fleet.cattle.io + kubectl create -n project1 rolebinding fleetuser --serviceaccount=default:fleetuser --clusterrole=fleetuser + kubectl create -n project2 rolebinding fleetuser --serviceaccount=default:fleetuser --clusterrole=fleetuser + +This makes sure, tenants can't interfere with GitRepo resources from other tenants, since they don't have access to their namespaces. + +## Allow Access to Clusters + +This assumes all GitRepos created by 'fleetuser' have the `team: one` label. Different labels could be used, to select different cluster namespaces. + +In each of the user's namespaces, as an admin create a [`BundleNamespaceMapping`](./namespaces#cross-namespace-deployments). + + kind: BundleNamespaceMapping + apiVersion: fleet.cattle.io/v1alpha1 + metadata: + name: mapping + namespace: project1 + + # Bundles to match by label. + # The labels are defined in the fleet.yaml # labels field or from the + # GitRepo metadata.labels field + bundleSelector: + matchLabels: + team: one + # or target one repo + #fleet.cattle.io/repo-name: simpleapp + + # Namespaces containing clusters to match by label + namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: fleet-default + # or clusters in every namespace with a label + #workspace: prod + +The [`target` section](./gitrepo-targets) in the GitRepo resource can be used to deploy only to a subset of the matched clusters. + +## Restricting Access to Downstream Clusters + +Admins can further restrict tenants by creating a `GitRepoRestriction` in each of their namespaces. + + kind: GitRepoRestriction + apiVersion: fleet.cattle.io/v1alpha1 + metadata: + name: restriction + namespace: project1 + + allowedTargetNamespaces: + - project1simpleapp + +This will deny the creation of cluster wide resources, which may interfere with other tenants and limit th deployment to the 'project1simpleapp' namespace. + +## An Example GitRepo Resource + +A GitRepo resource create by a tenant, without admin access could look like this: + + kind: GitRepo + apiVersion: fleet.cattle.io/v1alpha1 + metadata: + name: simpleapp + namespace: project1 + labels: + team: one + + spec: + repo: https://github.com/rancher/fleet-examples + paths: + - bundle-diffs + + targetNamespace: project1simpleapp + + # do not match the upstream/local cluster, won't work + targets: + - name: dev + clusterSelector: + matchLabels: + env: dev + +This includes the `team: one` label and and the required `targetNamespace`. + +Together with the previous `BundleNamespaceMapping` it would target all clusters with a `env: dev` label in the 'fleet-default' namespace. + +:::note + +`BundleNamespaceMappings` do not work with local clusters, so make sure not to target them. + +::: diff --git a/docs/namespaces.md b/docs/namespaces.md index 84f4d172a..e93a5b46b 100644 --- a/docs/namespaces.md +++ b/docs/namespaces.md @@ -103,6 +103,15 @@ spec: allowedClientSecretNames: [] allowedRepoPatterns: [] allowedServiceAccounts: [] + allowedTargetNamespaces: [] defaultClientSecretName: "" defaultServiceAccount: "" ``` + +### AllowedTargetNamespaces + +This can be used to limit a deployment to a set of namespaces on a downstream cluster. +If an allowedTargetNamespaces restriction is present, all `GitRepos` must +specify a `targetNamespace` and the specified namespace must be in the allow +list. +This also prevents the creation of cluster wide resources. diff --git a/sidebars.js b/sidebars.js index d740de9eb..ac8a18473 100644 --- a/sidebars.js +++ b/sidebars.js @@ -26,6 +26,7 @@ module.exports = { ], }, 'namespaces', + 'multi-tenancy', ], }, { @@ -64,4 +65,4 @@ module.exports = { ], }, ], -}; \ No newline at end of file +};