Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eb2eb004ed | ||
|
|
c3e5b18b8c |
@@ -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**.
|
||||
206
rfcs/0003-multi-tenancy-mode/README.md
Normal file
206
rfcs/0003-multi-tenancy-mode/README.md
Normal 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**.
|
||||
Reference in New Issue
Block a user