kargo icon indicating copy to clipboard operation
kargo copied to clipboard

Support cross-project credentials (Public/Private/Protected Projects)

Open jessesuen opened this issue 2 years ago • 4 comments

Proposed Feature

Currently, Kargo credentials are stored as secrets within each Kargo project namespace. This is good to enable self-service and provide strong tenancy guarantees.

Currently, these credentials are not shareable so the same credentials currently have to be repeated into many namespaces (similar to imagePullSecrets). However, in soft tenancy scenarios, a common use case is for a Kargo admin to configure git or image credentials globally, and allow those credentials to be used by multiple projects. Alternatively, even a non-Kargo admin who manages many projects, might want to reference a single Secret across many of their projects.

NOTE: the git credentials might be quite privileged credentials since they have read + write privileges to perform gitops commits, open pull requests, etc...

Motivation

Although Kargo is being designed first to support hard tenancy (using namespaces as a unit of isolation) which enables self-service, we should make it convenient for organizations that allow for softer tenancy, with shared, more powerful credentials to be used across projects.

Suggested Implementation

  1. The git/image credential Secret can be defined once (e.g. either in kargo namespace or someplace else) and used by many projects.
  2. The owner of the Secret can define rules on which projects might have access to the Secret. This may also have wildcards
  3. We should support multiple repos for which the secret might be valid for. e.g. (https://github.com/my-org/*)

Related: https://github.com/akuity/kargo/pull/1041

EDIT (2/14/24): we now have global credentials namespace feature, so this request is being repurposed for solving the remaining cross-project credential sharing.

jessesuen avatar Oct 30 '23 21:10 jessesuen

Few workarounds to this issue:

  1. Use something like Kyverno to can propagate a secret to many Namespaces (e.g. to all Namespaces with kargo.akuity.io/project: "true")
  2. If using external secrets, use something like ClusterExternalSecret to propagate the secret to all kargo.akuity.io/project: "true" Namespaces

jessesuen avatar Oct 30 '23 21:10 jessesuen

In https://github.com/akuity/kargo/pull/1041, the attempted approach was to look to the kargo namespace for globally configured credentials. In my view, global credentials are a specialized case of a more general feature to support credential sharing across two or more projects. If we solve credential sharing among two projects, we will have solved the global use case.

I think we have the following two personas/use cases:

  1. kargo admin who wants global credentials to be shared across all projects
  2. kargo projects owner who manages 2+ projects and wants to share credentials between them

The access model I'm currently thinking that can balance the personas is:

  • Repo credentials are still created in a namespace (it might be kargo, or another namespace)
  • A kargo admin can choose to configure "search paths" of namespaces for which to find credentials (similar to shell PATH env var) at the global level. When set at a global level, the search paths will apply to all projects. Global search paths are naturally opt-in by virtue of setting the system-wide search path to something.
  • In the future, projects will also gain the ability to set their own search paths as well (probably using the Project CRD). This will allow an end user who controls two kargo project namespaces, to share credentials amongst their two projects without involving a kargo admin.
  • The trust relationship would need be bi-directional. Even though a project might set/prefer a search path, it doesn't necessarily mean it automatically has access. I'd like to explore ways where we could leverage kubernetes RBAC and maybe subject access reviews to determine whether or not a credential can be shared with a project.

jessesuen avatar Oct 31 '23 16:10 jessesuen

We now have global credential namespaces. So we have already solved for the globally shared credential use case.

Repurposing this issue for the idea of allowing Projects to share between other Projects, without it being global.

jessesuen avatar Feb 14 '24 23:02 jessesuen

Adding some details here from a convo @jessesuen and I had offline. One idea we were toying with was, to make an analogy to access modifiers in OO programming languages, a project could conceivably be "public, protected, or private." Some OO languages, like C++, permit classes to declare "friends--" other classes that have visibility into protected attributes. Semantics similar to these could allow individual projects to express their level of willingness to share things such as credentials or service accounts with no other projects, some other projects, or all other projects. We certainly do not have to use the same access modifiers as C++. With some careful thought, I am sure we can agree on more appropriate terminology, but the analogy is a useful one for advancing this discussion.

krancour avatar Feb 15 '24 14:02 krancour