github.com/argoproj/argo-cd/v3@v3.2.1/docs/proposals/003-applications-outside-argocd-namespace.md (about)

     1  ---
     2  title: Allow Application resources to exist in any namespace
     3  authors:
     4    - "@jannfis"
     5  sponsors:
     6    - TBD
     7  reviewers:
     8    - TBD
     9  approvers:
    10    - TBD
    11  
    12  creation-date: 2021-06-05
    13  last-updated: 2021-06-05
    14  ---
    15  
    16  # Allow Application resources to exist in any namespace
    17  
    18  Improve Argo CDs multi-tenancy model to allow Application CRs to be created
    19  and consumed from different namespaces than the control plane's namespace.
    20  
    21  Related issues:
    22  - https://github.com/argoproj/argo-cd/issues/3474
    23  
    24  ## Open Questions [optional]
    25  
    26  * The major open question is, how to name `Application`s in a scenario where
    27    the K8s resource's name isn't unique anymore.
    28  
    29  ## Summary
    30  
    31  The multi-tenancy model of Argo CD is currently of limited use in a purely
    32  declarative setup when full autonomy of the tenants is desired.
    33  This stems mainly from the fact that the multi-tenancy
    34  model is built around the premise that only a full administrative party has
    35  access to the Argo CD control plane namespace (usually `argocd`), and the
    36  multi-tenancy is enforced through the Argo CD API instead of Kubernetes.
    37  
    38  The Argo CD multi-tenancy model is centered around the `AppProject`, which
    39  is used to impose certain rules and limitations to the `Application` that
    40  is associated with the `AppProject`. These limitations e.g. include the
    41  target clusters and namespaces where an `Application` is allowed to sync to,
    42  what kind of resources are allowed to be synced by an `Application` and so
    43  forth.
    44  
    45  An `Application` is associated to an `AppProject` by referencing it in the
    46  `.spec.project` field of the `Application` resource. Argo CD has an internal
    47  RBAC model to control the `AppProject` that can be referenced from the
    48  `Application`, but only when created or modified through Argo CD's API
    49  layer.
    50  
    51  Whoever can create or modify `Application` resources in the control-plane
    52  namespace, can effectively circumvent any restrictions that should be
    53  imposed by the `AppProject`, simply by choosing another value for the
    54  `.spec.project` field. So naturally, access to the `argocd` namespace
    55  is considered equal to super user access within Argo CD RBAC model. This
    56  prevents a fully-declarative way in which every party could autonomously
    57  manage their applications using plain Kubernetes mechanisms (e.g. create,
    58  modify and delete applications through K8s API control plane) and also
    59  full GitOps-style management of `Application` resources in a multi-tenant
    60  setup.
    61  
    62  ## Motivation
    63  
    64  The main motivation behind this enhancement proposal is to allow organisations
    65  who wish to set-up Argo CD for multi-tenancy can enable their tenants to fully
    66  self-manage `Application` resources in a declarative way, including being
    67  synced from Git (e.g. via an _app of apps_ pattern).
    68  
    69  The owning party could also set-up a dedicated _app of apps_ pattern for their
    70  tenants, e.g.
    71  
    72  * Have one _management_ namespace per tenant
    73  
    74  * Provide a Git repository to the tenant for managing Argo CD `Application`
    75    resources
    76  
    77  * Create an appropriate `AppProject` per tenant that restricts source to above
    78    mentioned Git repository, restricts destination to above mentioned namespace
    79    and restricts allowed resources to be `Application`.
    80  
    81  * Create an appropriate `Application` in Argo CD, which uses above mentionend
    82    Git repository as source, and above mentioned Namespace as destination
    83  
    84  ### Goals
    85  
    86  * Allow reconciliation from Argo CD `Application` resources from any namespace
    87    in the cluster where the Argo CD control plane is installed to.
    88  
    89  * Allow declarative self-service management of `Application` resources from
    90    users without access to the Argo CD control plane's namespace (e.g. `argocd`)
    91  
    92  * Be as less intrusive as possible, while not introducing additional controllers
    93    or components.
    94  
    95  ### Non-Goals
    96  
    97  * Allow reconciliation from Argo CD `Application` resources that are created in
    98    remote clusters. We believe this would be possible with some adaptions, but
    99    for this initial proposal we only consider the control plane's cluster as a
   100    source for `Application` resources.
   101  
   102  * Allow users to create `AppProject` resources on their own. Since `AppProject`
   103    is used as central entity for enforcing governance and security, these should
   104    stay in the control of the cluster administrators.
   105  
   106  * Replace or modify Argo CD internal RBAC model
   107  
   108  ## Proposal
   109  
   110  We suggest to adapt the current mechanisms of reconciliation of `Application`
   111  resources to include resources within the control plane's cluster, but outside
   112  the control plane's namespace (e.g. `argocd`).
   113  
   114  We think the following changes would need to be performed so that this will
   115  become possible in a secure manner:
   116  
   117  * Adapt the `AppProject` spec to include a new field, e.g. `sourceNamespaces`.
   118    The values of this new field will define which applications will be allowed
   119    to associate to the `AppProject`. Consider the following example:
   120  
   121    ```yaml
   122    apiVersion: argoproj.io/v1alpha1
   123    kind: AppProject
   124    metadata:
   125      name: some-project
   126      namespace: argocd
   127    spec:
   128      sourceNamespaces:
   129      - foo-ns
   130      - bar-ns
   131    ```
   132  
   133    ```yaml
   134    apiVersion: argoproj.io/v1alpha1
   135    kind: Application
   136    metadata:
   137      name: some-app
   138      namespace: bar-ns
   139    spec:
   140      project: some-project
   141    ```
   142  
   143    ```yaml
   144    apiVersion: argoproj.io/v1alpha1
   145    kind: Application
   146    metadata:
   147      name: other-app
   148      namespace: other-ns
   149    spec:
   150      project: some-project
   151    ```
   152  
   153    would allow `Application` resources that are created in either namespace
   154    `foo-ns` or `bar-ns` to specify `some-project` in their `.spec.project`
   155    field to associate themselves to the `AppProject` named `some-project`.
   156    In the above example, the Application `some-app` would be allowed to associate
   157    to the AppProject `some-project`, but the Application `other-app` would be
   158    invalid.
   159  
   160    This method would allow to delegate certain namespaces where users have
   161    Kubernetes RBAC access to create `Application` resources.
   162  
   163  * `Applications` created in the control-plane's namespace (e.g. `argocd`) are
   164    allowed to associate with any project when created declaratively, as they
   165    are considered created by a super-user. So the following example would be
   166    allowed to associate itself to project `some-project`, even with the
   167    `argocd` namespace not being in the list of allowed `sourceNamespaces`:
   168  
   169    ```yaml
   170    apiVersion: argoproj.io/v1alpha1
   171    kind: Application
   172    metadata:
   173      name: superuser-app
   174      namespace: argocd
   175    spec:
   176      project: some-project
   177    ```
   178  
   179  * `Applications` created imperatively (e.g. through Argo CD API via UI or
   180    CLI) will keep being created in the control plane namespace, and Argo CD
   181    RBAC will still be applied to determine whether a user is allowed to
   182    create `Application` for given `AppProject`.
   183  
   184  If no `.spec.sourceNamespaces` is set to an `AppProject`, a default of the
   185  control plane's namespace (e.g. `argocd`) will be assumed, and the current
   186  behaviour would not be changed (only `Application` resources created in the
   187  `argocd` namespace would be allowed to associate with the `AppProject`).
   188  
   189  When the `argocd-application-controllers` discovers an `Application` to
   190  consider for reconciliation, it would make sure that the `Application` is
   191  valid by:
   192  
   193  * Looking up the `AppProject` from the value of `.spec.project` field in the
   194   `Application` resource
   195  
   196  * Matching the value of `.metadata.namespace` in the `Application` to a
   197    namespace found in `.spec.sourceNamespaces` in the referenced `AppProject`
   198    resource.
   199  
   200  * If there is a match, reconciliation would continue as normal with the
   201    association desired in the `Application`'s spec.
   202  
   203  * If there is no match, reconciliation would be aborted with a permission
   204    error.
   205  
   206  ### Use cases
   207  
   208  Add a list of detailed use cases this enhancement intends to take care of.
   209  
   210  #### Use case 1: Autonomous self-service of declarative configuration
   211  
   212  As a developer, I want to be able to create & manage an Argo CD `Application`
   213  in a declarative way, without sending a pull-request to the cluster admin's
   214  repository and possibly wait for their review, approval and merge. I want
   215  this process to be in full control of my DevOps team.
   216  
   217  As a cluster admin, I want to allow my users the self management of Argo CD
   218  `Application` resources without getting involved in the creation process,
   219  e.g. by reviewing & approving PRs into our admin namespace. I still want
   220  to be sure that users cannot circumvent any restrictions that our organisation
   221  wants to impose on these applications capabilities.
   222  
   223  #### Use case 2: App-of-apps pattern for my own applications
   224  
   225  As a developer, I want to have the ability to use app-of-apps for my own
   226  `Application` resources. For this, I will have to create `Application`
   227  manifests, but I'm currently not allowed to write to the `argocd` namespace.
   228  
   229  #### Use case 3: Easy onboarding of new applications and tenants
   230  
   231  As an administrator, I want to provide my tenants with a very easy way to
   232  create their applications from a simple commit to Git, without losing my
   233  ability to govern and restrict what goes into my cluster.  I want to set up
   234  an Argo CD application that reconciles my tenant's `Application` manifests to
   235  a fixed location (namespace) in my cluster, so that the tenant can just put
   236  their manifests into the Git repository and Argo CD will pick it up from
   237  there, without having to use complex tools such as Open Policy Agent to
   238  enforce what AppProjects my tenants are allowed to use.
   239  
   240  ### Implementation Details/Notes/Constraints [optional]
   241  
   242  #### Application names
   243  
   244  One major challenge to solve is the _uniqueness_ of `Application` names. As of
   245  now this is enforced by Kubernetes, since the `Application` name is also the
   246  name of the Kubernetes resource (e.g. value of `.metadata.name`). Because all
   247  `Application` resources must currently exist in the same namespace, Kubernetes
   248  already enforces a unique name for each `Application`.
   249  
   250  This imposes a major challenge when `Application` resources may exist in other
   251  namespaces, because it would be possible that two resources will have the same
   252  name.
   253  
   254  One way to mitigate this would be to decouple the application's name from the
   255  name of the `Application` resource by considering the name of the resource's
   256  namespace as part of the application name.
   257  
   258  E.g. consider the two following examples:
   259  
   260  ```yaml
   261  apiVersion: argoproj.io/v1alpha1
   262  kind: Application
   263  metadata:
   264    name: some-app
   265    namespace: foons
   266  spec:
   267    project: some-project
   268  ```
   269  
   270  and
   271  
   272  ```yaml
   273  apiVersion: argoproj.io/v1alpha1
   274  kind: Application
   275  metadata:
   276    name: some-app
   277    namespace: barns
   278  spec:
   279    project: some-project
   280  ```
   281  
   282  The _name_ of the first application would become `foons/some-app` and the _name_
   283  of the second application would become `barns/some-app`. This would have the
   284  advantage to instantly have a clue about _where_ the application is coming from,
   285  without having to resort to the Kubernetes API to inspect `.spec.namespace`
   286  field of the app. The notation may also use a hyphen (`-`) or underscore (`_`)
   287  instead of a slash (`/`) as a divider between the _source_ and the _name_, this
   288  is implementation detail.
   289  
   290  It is suggested to _not_ apply this naming convention to `Application` resources
   291  created in the control plane's namespace, as this may break backwards compat
   292  with existing RBAC rules. So, when considering the following example:
   293  
   294  ```yaml
   295  apiVersion: argoproj.io/v1alpha1
   296  kind: Application
   297  metadata:
   298    name: some-app
   299    namespace: argocd
   300  spec:
   301    project: some-project
   302  ```
   303  
   304  The name of the application would still be `some-app`, instead of
   305  `argocd/some-app`. This would allow us introducing the change without breaking
   306  the RBAC rules of existing installations, and it would be not as intrusive.
   307  Since for all other `Application` resources in external namespaces the name
   308  will be prefixed, collisions in names should not happen.
   309  
   310  We also considered the name of the `AppProject` instead the name of the
   311  `Application`'s namespace. However, since in this proposal an `AppProject`
   312  could allow resources from _multiple_ namespaces, and in each namespace an
   313  `Application` with the same name could co-exist, this wouldn't solve the
   314  uniqueness requirement.
   315  
   316  #### Length of application names
   317  
   318  When implementing above naming conventions, we may easily hit the length limit
   319  enforced by Kubernetes on label values. Since we currently rely on setting the
   320  `Application` name as a label on resources managed through the `Application`,
   321  we should have an alternative implemented first.
   322  
   323  There are already a few thoughts and suggestions on how to move away from
   324  storing the `Application` name as a value in the identifying label, but this
   325  would be a prerequisite before moving forward. As the demand for having more
   326  lengthy `Application` names than what is currently possible (due to the limit
   327  imposed by label's values), we feel that this should be implemented
   328  independently anyway.
   329  
   330  List of issues on GitHub tracker regarding the length of the application name:
   331  
   332  * https://github.com/argoproj/argo-cd/issues/5595
   333  
   334  ### Detailed examples
   335  
   336  ### Security Considerations
   337  
   338  We think that the security model of this proposal fits nicely within existing
   339  mechanisms of Argo CD (e.g. RBAC, `AppProject` constraints).
   340  
   341  However, on a bug in the implementation - e.g. the unwanted possibility for
   342  non-admin users to associate their `Application` resources to arbitrary or
   343  non-allowed `AppProject` resources - privilege escalation could occur.
   344  
   345  Good unit- and end-to-end tests need to be in place for this functionality
   346  to ensure we don't accidentally introduce a change that would allow any form
   347  of uncontrolled association between an `Application` and an `AppProject`.
   348  
   349  ### Risks and Mitigations
   350  
   351  #### Uncontrolled creation of a huge amount of Application resources
   352  
   353  A rogue party or process (e.g. malfunctioning CI) could create a tremendous
   354  amount of unwanted `Application` resources in an allowed source namespace,
   355  with a potential performance impact on the Argo CD installation. However, this
   356  is also true for a rogue party using the Argo CLI with appropriate Argo CD RBAC
   357  permissions to create applications or even with ApplicationSet.
   358  
   359  A possible mitigation to this would be to enforce an (optional) quota to the
   360  number of `Application` resources allowed to associate with any given
   361  `AppProject` resource.
   362  
   363  #### Third-party tools
   364  
   365  Most third-party tools will look for `Application` resources in a single
   366  namespace (the control plane's namespace - `argocd`) right now. These would
   367  have to adapted to scan for `Application` resources in the complete cluster,
   368  and might need updated RBAC permissions for this purpose.
   369  
   370  ### Upgrade / Downgrade Strategy
   371  
   372  Upgrading to a version implementing this proposal should be frictionless and
   373  wouldn't require administrators to perform any changes in the configuration
   374  to keep the current behaviour. `AppProject` resources without the new field
   375  `.spec.sourceNamespaces` being set will keep their behaviour, since they
   376  will allow `Application` resources in the control plane's namespace to be
   377  associated with the `AppProject`. Also, these `Applications` wouldn't be
   378  subject to a name change (e.g. the proposed `<namespace>-<appname>` name).
   379  
   380  Downgrading would not be easily possible once users start to make use of the
   381  feature and create `Applications` in other namespaces than the control plane's
   382  one. These applications would be simply ignored in a downgrade scenario, and
   383  effectively become unmanaged. The mitigation to this would be to take these
   384  `Application` resources and migrate them back to the control plane's namespace,
   385  but possibly would have to adapt application names for uniqueness as well,
   386  with consequences to RBAC rules.
   387  
   388  ## Drawbacks
   389  
   390  * Application names have to change considerably to stay _unique_
   391  
   392  * The Application CRs still need to reside on the control plane's cluster
   393  
   394  * Downgrade/rollback would not be easily possible
   395  
   396  ## Alternatives
   397  
   398  ### ApplicationSet
   399  
   400  One alternative is `ApplicationSet`, which automates the creation of
   401  `Application` resources using generators with user-controlled input.
   402  However, this does not solve creation of one-off `Applications` and is
   403  considerably more complex to setup and maintain.
   404  
   405  We do think that the proposed solution will nicely play together with the
   406  `ApplicationSet` mechanism, and also could be used in conjunction with it
   407  to provide better isolation of `Application` resources generated by
   408  `ApplicationSet`.
   409  
   410  ### AppSource CRD and controller
   411  
   412  Another recent proposal is the `AppSource` CRD and controller. We suggest this
   413  proposal as a direct alternative to the `AppSource` CRD, with the drawback
   414  that `Application` resources require to reside in the control plane's cluster
   415  instead of the ability being created on remote clusters as well.
   416  
   417  The `AppSource` proposal can be found here:
   418  https://github.com/argoproj/argo-cd/issues/6405