Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] Access control for cross-namespace source refs #2092

Closed
wants to merge 4 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
181 changes: 181 additions & 0 deletions rfcs/0002-source-acl/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
# 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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will maintain backwards compatibility as far as I understand. Let's be explicit about that here, too: This RFC doesn't introduce backwards-incompatible changes.


## 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`)
stefanprodan marked this conversation as resolved.
Show resolved Hide resolved
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
makkes marked this conversation as resolved.
Show resolved Hide resolved

### User Stories

#### Story 1
stefanprodan marked this conversation as resolved.
Show resolved Hide resolved

> 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://[email protected]/<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,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be good to lay out the list of possible access... If as a user I grant access to another namespace, depending on the running controllers on that NS I might re-consider.

Copy link
Member Author

@stefanprodan stefanprodan Nov 24, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The level of access to the underlying Git repository depends on how you've configured the SSH key or token, if it has write access to just read. ImageUpdateAutomations need write access to patch image tags, while a HelmRelease or Kustomization needs only read access.

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://[email protected]/<org>/cluster-config
secretRef:
name: read-write-ssh-key
accessFrom:
namespaceSelectors:
- matchLabels:
kubernetes.io/metadata.name: dev-team1
Comment on lines +120 to +123
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This pattern is very flexible for resource discovery and I can easily understand the benefits of using it in this use case. The main challenge I can think of using this as part of flux's authorisation model in addition to the built-in RBAC is that a cluster admin who is unaware of flux's inner workings may be blindsided by this behaviour, leading to less secure flux deployments.

Given that RBAC will stop being the single source of truth from an authorisation perspective, it may be useful to also provide a sub-command on flux to allow admins to inspect effective permissions across a cluster.

```

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
stefanprodan marked this conversation as resolved.
Show resolved Hide resolved

#### 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**.