1
0
mirror of synced 2026-03-01 11:16:56 +00:00

Compare commits

..

2 Commits

Author SHA1 Message Date
Stefan Prodan
eb2eb004ed Update RFC to reflect Flux v0.26 multi-tenant capabilities
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-02-03 11:04:58 +02:00
Stefan Prodan
c3e5b18b8c [RFC-0003] Flux Multi-Tenancy Mode
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2022-02-03 11:04:53 +02:00
2 changed files with 206 additions and 181 deletions

View File

@@ -1,181 +0,0 @@
# RFC-0002 Access control for source references
**Status:** provisional
**Creation date:** 2021-11-16
**Last update:** 2022-02-03
## Summary
Cross-namespace references to Flux sources should be subject to
Access Control Lists (ACLs) as defined by the owner of a particular source.
Similar to [Kubernetes Network Policies](https://kubernetes.io/docs/concepts/services-networking/network-policies/),
Flux ACLs define policies for restricting the access to the source artifact server based on the
caller's namespace.
## Motivation
As of [version 0.26](https://github.com/fluxcd/flux2/releases/tag/v0.26.0) (Feb 2022),
Flux allows for `Kustomizations`, `HelmReleases` and `ImageUpdateAutomations` to reference sources in different namespaces.
On multi-tenant clusters, platform admins can disable this behaviour with the `--no-cross-namespace-refs` flag
as described in the [multi-tenancy lockdown documentation](https://fluxcd.io/docs/installation/#multi-tenancy-lockdown).
This proposal tries to solve the "cross-namespace references side-step namespace isolation" issue (explained in
[RFC-0001](https://github.com/fluxcd/flux2/tree/main/rfcs/0001-authorization#cross-namespace-references-side-step-namespace-isolation))
for when platform admins want to allow tenants to share sources.
### Goals
- Allow source owners to choose which sources are shared and with which namespaces.
- Allow cluster admins to enforce source ACLs.
### Non-Goals
- Enforce source ACLs by default.
## Proposal
Extend the current Image Policy/Repository ACL implementation to all the others Flux resources
as described in [flux2#1704](https://github.com/fluxcd/flux2/issues/1704).
When a Flux resource (`Kustomization`, `HelmRelease` or `ImageUpdateAutomation`)
refers to a source (`GitRepository`, `HelmRepository` or `Bucket`) in a different namespace,
access is granted based on the source ACL.
The ACL check is performed only if `--enable-source-acl` flag is set to `true` for the following controllers:
- kustomize-controller
- helm-controller
- image-automation-controller
### User Stories
#### Story 1
> As a cluster admin, I want to share Helm Repositories approved by the platform team with all tenants.
If the owner of a Flux `HelmRepository` wants to grant access to the repository for all namespaces in a cluster,
an empty `matchLabels` can be used:
```yaml
apiVersion: source.toolkit.fluxcd.io/v1beta1
kind: HelmRepository
metadata:
name: bitnami
namespace: flux-system
spec:
url: https://charts.bitnami.com/bitnami
accessFrom:
namespaceSelectors:
- matchLabels: {}
```
If the `accessFrom` field is not present and `--enable-source-acl` is set to `true`,
means that a source can't be accessed from any other namespace but the one where it currently resides.
#### Story 2
> As a tenant, I want to share my app repository with another tenant
> so that they can deploy the application in their own namespace.
If `dev-team1` wants to grant read access to their repository to `dev-team2`,
a `matchLabels` that selects the namespace owned by `dev-team2` can be used:
```yaml
apiVersion: source.toolkit.fluxcd.io/v1beta1
kind: GitRepository
metadata:
name: app1
namespace: dev-team1
spec:
url: ssh://git@github.com/<org>/app1-deploy
secretRef:
name: app1-ro-ssh-key
accessFrom:
namespaceSelectors:
- matchLabels:
kubernetes.io/metadata.name: dev-team2
```
#### Story 3
> As a cluster admin, I want to let tenants configure image automation in their namespaces by
> referring to a Git repository managed by the platform team.
If the owner of a Flux `GitRepository` wants to grant write access to `ImageUpdateAutomations` in a different namespace,
a `matchLabels` that selects the image automation namespace can be used:
```yaml
apiVersion: source.toolkit.fluxcd.io/v1beta1
kind: GitRepository
metadata:
name: cluster-config
namespace: flux-system
spec:
url: ssh://git@github.com/<org>/cluster-config
secretRef:
name: read-write-ssh-key
accessFrom:
namespaceSelectors:
- matchLabels:
kubernetes.io/metadata.name: dev-team1
```
The `dev-team1` can refer to the `cluster-config` repository in their image automation config:
```yaml
apiVersion: image.toolkit.fluxcd.io/v1beta1
kind: ImageUpdateAutomation
metadata:
name: app1
namespace: dev-team1
spec:
sourceRef:
kind: GitRepository
name: cluster-config
namespace: flux-system
```
### Alternatives
#### Admission controllers
An alternative solution to source ACLs is to use an admission controller such as Kyverno or OPA Gatekeeper
and allow/disallow cross-namespace access to specific source.
The current proposal offers the same feature but without the need to manage yet another controller to guard
sources.
#### Kubernetes RBAC
Another alternative is to rely on impersonation and create a `ClusterRoleBinding` per named source and tenant account
as described in [fluxcd/flux2#582](https://github.com/fluxcd/flux2/pull/582).
The current proposal is more flexible than RBAC and implies less work for Flux users. ALCs act more like
Kubernetes Network Policies where access is defined based on labels, with RBAC every time a namespace is added,
the platform admins have to create new RBAC rules to target that namespace.
#### Source reflection CRD
Yet another alternative is to introduce a new API kind `SourceReflection` as described in
[fluxcd/flux2#582-821027543](https://github.com/fluxcd/flux2/pull/582#issuecomment-821027543).
The current proposal allows the owner to define the access control list on the source object, instead
of creating objects in namespaces where it has no control over.
#### Remove cross-namespace refs
An alternative is to simply remove cross-namespace references from the Flux API.
This would break with current behavior, and users would have to make substantial changes to their
repository structure and workflow. In cases where e.g. a resource is common (across many namespaces),
this would mean the source-controller would use way more memory and network bandwidth that grows with
each namespace that uses the same Git or Helm repository due to the requirement of having to duplicate
"common" resources.
## Implementation History
- ACL support for allowing cross-namespace access to `ImageRepositories` was first released in flux2 **v0.23.0**.
- Disabling cross-namespace access to sources was first released in flux2 **v0.26.0**.

View File

@@ -0,0 +1,206 @@
# RFC-0003 Flux Multi-Tenancy Mode
**Status:** provisional
**Creation date:** 2021-11-16
**Last update:** 2022-02-03
## Summary
For multi-tenant environments, we want to offer an easy way of configuring Flux to enforce tenant isolation
(as defined by the Soft Multi-Tenancy model from RFC-0001).
When running in the multi-tenant mode, Flux will lock down access to sources (as defined by RFC-0002),
and will use the tenant service account instead of defaulting to `cluster-admin`.
From an end-user perspective, the multi-tenancy mode means that:
- Platform admins have to create a Kubernetes service account and RBAC in each namespace where
Flux performs source-to-cluster reconciliation on behalf of tenants.
By default, Flux will have no permissions to reconcile the tenants sources onto clusters.
- Source owners have to specify with which tenants they wish to share their sources.
By default, nothing is shared between tenants.
## Motivation
As of [version 0.26](https://github.com/fluxcd/flux2/releases/tag/v0.26.0) (Feb 2022),
configuring Flux for soft multi-tenancy requires platform admins to:
- Deny cross-namespace access to Flux custom resources by setting the `--no-cross-namespace-refs` flag.
- Enforce impersonation by setting a default service account with the `--default-service-account` flag.
Instead of using a Kustomize patch to lock down Flux as descried in the
[multi-tenancy lockdown documentation](https://fluxcd.io/docs/installation/#multi-tenancy-lockdown),
we could extend `flux install` and `flux bootstrap` and offer a flag to configure Flux with multi-tenancy enforcements.
### Goals
- Enforce service account impersonation for source-to-cluster reconciliation.
- Enforce ACLs for cross-namespace access to sources.
### Non-Goals
- Enforce tenant's workload isolation with network policies and pod security standards as described
[here](https://kubernetes.io/blog/2021/04/15/three-tenancy-models-for-kubernetes/#security-considerations).
## Proposal
### User Stories
#### Story 1
> As a platform admin, I want to install Flux with lowest privilege/permission level possible.
#### Story 2
> As a platform admin, I want to give tenants full control over their assigned namespaces.
> So that tenants could use their own repositories and manager the app delivery with Flux.
#### Story 3
> As a platform admin, I want to prevent tenants from changing the cluster-wide configuration.
> If a tenant adds to their repository a cluster-scoped resource such as a namespace or cluster role,
> Flux should reject the change and notify the tenant that this operation is not allowed.
### Multi-tenant Bootstrap
When bootstrapping Flux, platform admins should have the option to lock down Flux for multi-tenant environments e.g.:
```shell
flux bootstrap --security-profile=multi-tenant
```
The security profile flag accepts two values: `single-tenant` and `multi-tenant`.
Platform admins may switch between the two modes at any time, either by rerunning bootstrap
or by patching the Flux manifests in Git.
The `multi-tenant` profile is just a shortcut to setting the following container args in the Flux deployment manifests:
```yaml
containers:
- name: manager
args:
- --default-service-account=flux
- --enable-source-acl=true
```
And for disabling cross-namespace references when using the notification API:
```yaml
kind: Deployment
metadata:
name: notification-controller
spec:
template:
spec:
containers:
- name: manager
args:
- --no-cross-namespace-refs=true
```
When running in the `multi-tenant` mode, Flux behaves differently:
- The source-to-cluster reconciliation no longer runs under the service account of
the Flux controllers. The controller service account, is only used to impersonate
the service account specified in the Flux custom resources (`Kustomizations`, `HelmReleases`).
- When no service account name is specified in a Flux custom resource,
a default will be used e.g. `system:serviceaccount:<tenant-namespace>:flux`.
- When a Flux custom resource (`Kustomizations`, `HelmReleases`, `ImagePolicies`, `ImageUpdateAutomations`)
refers to a source in a different namespace, access is granted based the source access control list.
If no ACL is defined for a source, cross-namespace access is denied.
- When a Flux notification (`Alerts`, `Receivers`)
refers to a resource in a different namespace, access is denied.
### Tenants Onboarding
When onboarding tenants, platform admins should have the option to assign namespaces, set
permissions and register the tenants repositories onto clusters in a declarative manner.
The Flux CLI offers an easy way of generating all the Kubernetes manifests needed to onboard tenants:
- `flux create tenant` command generates namespaces, service accounts and Kubernetes RBAC
with restricted access to the cluster resources, given tenants access only to their namespaces.
- `flux create secret git` command generates SSH keys used by Flux to clone the tenants repositories.
- `flux create source git` command generates the configuration that tells Flux which repositories belong to tenants.
- `flux create kustomization` command generates the configuration that tells Flux how to reconcile the manifests found in the tenants repositories.
All the above commands have an `--export` flag for generating the Kubernetes resources in YAML format.
The platform admins should place the generated manifests in the repository that defines the cluster(s) desired state.
Here is an example of the generated manifests:
```yaml
---
apiVersion: v1
kind: Namespace
metadata:
name: tenant1
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: flux
namespace: tenant1
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: flux
namespace: tenant1
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: flux
namespace: tenant1
---
apiVersion: source.toolkit.fluxcd.io/v1beta1
kind: GitRepository
metadata:
name: tenant1
namespace: tenant1
spec:
interval: 5m0s
ref:
branch: main
secretRef:
name: tenant1-git-auth
url: ssh://git@github.com/org/tenant1
---
apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
kind: Kustomization
metadata:
name: tenant1
namespace: tenant1
spec:
interval: 10m0s
path: ./
prune: true
serviceAccountName: flux
sourceRef:
kind: GitRepository
name: tenant1
```
Note that the [cluster-admin](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles)
role is used in a `RoleBinding`, this only gives full control over every resource in the role binding's namespace.
Once the tenants repositories are registered on the cluster(s), the tenants can configure their app delivery
in Git using Kubernetes namespace-scoped resources such as `Deployments`, `Services`, Flagger `Canaries`,
Flux `Kustomizations`, `HelmReleases`, `ImageUpdateAutomations`, `Alerts`, `Receivers`, etc.
## Alternatives
Instead of introducing the security profile flag to `flux bootstrap`,
we could document how to patch each controller deployment with Kustomize as described in the
[multi-tenancy lockdown documentation](https://fluxcd.io/docs/installation/#multi-tenancy-lockdown).
Having an easy way of locking down Flux with a single flag, make users aware of the security implications
and improves the user experience.
## Implementation History
- Disabling cross-namespace access and providing a default service account was first released in flux2 **v0.26.0**.