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