github.com/argoproj/argo-cd/v2@v2.10.5/docs/proposals/proxy-extensions.md (about) 1 --- 2 title: Reverse Proxy Extensions 3 4 authors: 5 - "@leoluz" 6 7 sponsors: 8 - TBD 9 10 reviewers: 11 - TBD 12 13 approvers: 14 - TBD 15 16 creation-date: 2022-07-23 17 18 --- 19 20 # Reverse-Proxy Extensions support for Argo CD 21 22 Enable UI extensions to use a backend service. 23 24 * [Summary](#summary) 25 * [Motivation](#motivation) 26 * [Goals](#goals) 27 * [Non-Goals](#non-goals) 28 * [Proposal](#proposal) 29 * [Use cases](#use-cases) 30 * [Security Considerations](#security-considerations) 31 * [Risks and Mitigations](#risks-and-mitigations) 32 * [Upgrade / Downgrade](#upgrade--downgrade) 33 * [Drawbacks](#drawbacks) 34 * [Open Questions](#open-questions) 35 36 --- 37 38 ## Summary 39 40 Argo CD currently supports the creation of [UI extensions][1] allowing 41 developers to define the visual content of the "more" tab inside 42 a specific resource. Developers are able to access the resource state to 43 build the UI. However, currently it isn't possible to use a backend 44 service to provide additional functionality to extensions. This proposal 45 defines a new reverse proxy feature in Argo CD, allowing developers to 46 create a backend service that can be used in UI extensions. Extensions 47 backend code will live outside Argo CD main repository. 48 49 ## Motivation 50 51 The initiative to implement the anomaly detection capability in Argo CD 52 highlighted the need to improve the existing UI extensions feature. The 53 new capability will required the UI to have access to data that isn't 54 available as part of Application's owned resources. It is necessary to 55 access an API defined by the extension's development team so the proper 56 information can be displayed. 57 58 ## Goals 59 60 The following goals are desired but not necessarily all must be 61 implemented in a given Argo CD release: 62 63 #### [G-1] Argo CD (API Server) must have low performance impact when running extensions 64 65 Argo CD API server is a critical component as it serves all APIs used by 66 the CLI as well as the UI. The Argo CD team has no controll over what is 67 going to be executed in extension's backend service. Thus it is important 68 that the reverse proxy implementation to cause the lowest possible impact 69 in the API server while processing high latency requests. 70 71 Possible solutions: 72 - Implement a rate limit layer to protect Argo CD API server 73 - Implement configurable different types of timeouts (idle connection, 74 duration, etc) between Argo CD API server and backend services. 75 - Implement the reverse proxy as a separate server/pod (needs discussion). 76 77 ---- 78 79 #### [G-2] Argo CD admins should be able to define rbacs to define which users can invoke specific extensions 80 81 Argo CD Admins must be able to define which extensions are allowed to be 82 executed by the logged in user. This should be fine grained by Argo CD 83 project like the current rbac implementation. 84 85 ---- 86 87 #### [G-3] Argo CD deployment should be independent from backend services 88 89 Extension developers should be able to deploy their backend services 90 independently from Argo CD. An extension can evolve their internal API and 91 deploying a new version shouldn't require Argo CD to be updated or 92 restarted. 93 94 ---- 95 96 #### [G-4] Enhance the current Extensions framework to configure backend services 97 98 *Not in the first release* 99 100 [Argo CD extensions][2] is an `argoproj-labs` project that supports loading 101 extensions in runtime. Currently the project is implementing a controller 102 that defines and reconciles the custom resource `ArgoCDExtension`. This 103 CRD should be enhanced to provide the ability to define backend services 104 that will be used by the extension. Once configured UI can send requests 105 to API server in a specific endpoint. API server will act as a reverse 106 proxy receiving the request from the UI and routing to the appropriate 107 backend service. 108 109 Example: 110 ```yaml 111 apiVersion: argoproj.io/v1alpha1 112 kind: ArgoCDExtension 113 metadata: 114 name: my-cool-extention 115 finalizers: 116 - extensions-finalizer.argocd.argoproj.io 117 spec: 118 sources: 119 - git: 120 url: https://github.com/some-org/my-cool-extension.git 121 backend: 122 serviceName: some-backend-svc 123 endpoint: /some-backend 124 ``` 125 126 **Note**: While this is a nice-to-have, it won't be part of the first proxy 127 extension version. This would need to be considered if Argo CD extensions 128 eventually get traction. 129 130 ---- 131 132 #### [G-5] Setup multiple backend services for the same extension 133 134 In case of one Argo CD instance managing applications in multiple clusters, it 135 will be necessary to configure backend service URLs per cluster for the same 136 extension. This should be an optional configuration. If only one URL is 137 configured, that one should be used for all clusters. 138 139 ---- 140 141 #### [G-6] Provide safe communication channel between Argo CD API server and extension backend 142 143 Argo CD API server should provide configuration for establishing a safe communication 144 channel with the extension backend. This can be achieved similarly to how Kubernetes 145 API Server does to [authenticate with aggregated servers][5] by using certificates. 146 147 ## Non-Goals 148 149 It isn't in the scope of this proposal to specify commands in the Argo CD 150 CLI. This proposal covers the reverse-proxy extension spec that will be 151 used by Argo CD UI. 152 153 ## Proposal 154 155 ### Use cases 156 157 The following use cases should be implemented for the conclusion of this 158 proposal: 159 160 #### [UC-1]: As an Argo CD admin, I want to configure a backend services so it can be used by my UI extension 161 162 Define a new section in the Argo CD configmap ([argocd-cm.yaml][4]) 163 allowing admins to register and configure new extensions. All enabled 164 extensions backend will be available to be invoked by the Argo CD UI under 165 the following API base path: 166 167 `<argocd-host>/api/v1/extensions/<extension-name>` 168 169 With the configuration below, the expected behavior is explained in the 170 following examples: 171 172 ```yaml 173 extension.config: | 174 extensions: 175 - name: some-extension 176 enabled: true 177 backend: 178 idleConnTimeout: 10s 179 services: 180 - url: http://extension-name.com:8080 181 ``` 182 183 - **Example 1**: 184 185 Argo CD API server acts as a reverse-proxy forwarding http requests as 186 follows: 187 188 ``` 189 ┌────────────┐ 190 │ Argo CD UI │ 191 └──────┬─────┘ 192 │ 193 │ GET http://argo.com/api/v1/extensions/some-extension 194 │ 195 ▼ 196 ┌──────────────────┐ 197 │Argo CD API Server│ 198 └────────┬─────────┘ 199 │ 200 │ GET http://extension-name.com:8080 201 │ 202 ▼ 203 ┌───────────────┐ 204 │Backend Service│ 205 └───────────────┘ 206 ``` 207 208 - **Example 2**: 209 210 If a backend provides an API under the `/apiv1/metrics` endpoint, Argo CD 211 should be able to invoke it such as: 212 213 ``` 214 ┌────────────┐ 215 │ Argo CD UI │ 216 └──────┬─────┘ 217 │ 218 │ GET http://argo.com/api/v1/extensions/some-extension/apiv1/metrics/123 219 │ 220 ▼ 221 ┌──────────────────┐ 222 │Argo CD API Server│ 223 └────────┬─────────┘ 224 │ 225 │ GET http://extension-name.com:8080/apiv1/metrics/123 226 │ 227 ▼ 228 ┌───────────────┐ 229 │Backend Service│ 230 └───────────────┘ 231 ``` 232 233 - **Example 3**: 234 235 In this use-case we have one Argo CD instance connected with different 236 clusters. There is a requirement defining that every extension instance 237 needs to be deployed in each of the target clusters. To address this 238 use-case there is a need to configure multiple backend URLs for the 239 same extension (one for each cluster). For doing so, the following 240 configuration should be possible: 241 242 ```yaml 243 extension.config: | 244 extensions: 245 - name: some-extension 246 enabled: true 247 backend: 248 idleConnTimeout: 10s 249 services: 250 - url: http://extension-name.com:8080 251 clusterName: kubernetes.local 252 - url: https://extension-name.ppd.cluster.k8s.local:8080 253 clusterName: admins@ppd.cluster.k8s.local 254 ``` 255 256 Note that there is an URL configuration per cluster name. The cluster 257 name is extracted from the Argo CD cluster secret and must match the 258 field `data.name`. In this case the UI must send the header 259 `Argocd-Application-Name` with the full qualified application name 260 (`<namespace>/<application-name>`). 261 262 Example: 263 264 `Argocd-Application-Name: preprod/some-application` 265 266 With this information, API Server can check in which cluster it should 267 get the backend URL from. This will be done by inspecting the 268 Application destination configuration to find the proper cluster name. 269 270 The diagram below shows how Argo CD UI could send the request with 271 the additional header to get the proxy forwarding it to the proper 272 cluster: 273 274 ``` 275 ┌────────────┐ 276 │ Argo CD UI │ 277 └──────┬─────┘ 278 │ 279 │ GET http://argo.com/api/v1/extensions/some-extension 280 │ HEADER: "Argocd-Application-Name: default/ppd-application" 281 │ 282 ▼ 283 ┌──────────────────┐ 284 │Argo CD API Server│ 285 └────────┬─────────┘ 286 │ 287 │ GET https://extension-name.ppd.cluster.k8s.local:8080 288 │ 289 ▼ 290 ┌───────────────┐ 291 │Backend Service│ 292 └───────────────┘ 293 ``` 294 295 ##### Considerations 296 297 - The `idleConnTimeout` can be used to avoid accumulating too many 298 goroutines waiting slow for extensions. In this case a proper timeout 299 error (408) should be returned to the browser. 300 - Scheme, http verb and request body are forwarded as it is 301 received by the API server to the backend service. 302 - Headers will be filtered and not forwarded as it is received in Argo CD 303 API server. Sensitive headers will be removed (e.g. `Cookie`). 304 - A new header is added in the forwared request (`X-Forwarded-Host`) to 305 allow ssl redirection. 306 - This proposal doesn't specify how backends should implement authz or 307 authn. This topic could be discussed as a future enhancement to the 308 proxy extension feature in Argo CD. 309 310 ---- 311 312 #### [UC-2]: As an Argo CD admin, I want to define extensions rbacs so access permissions can be enforced 313 314 Extend Argo CD rbac registering a new `ResourceType` for extensions in the 315 [policy configuration][3]. The current policy permission configuration is 316 defined as: 317 318 ``` 319 p, <subject>, <resource>, <action>, <object>, <access> 320 ``` 321 322 With a new resource type for extensions, admins will be able to configure 323 access rights per extension per project. 324 325 * **Basic config suggestion:** 326 327 This is the basic suggestion where admins will be able to define permissions 328 per project and per extension. In this case namespace specific permissions 329 isn't covered. 330 331 The `object` field must contain the project name and the extension name in 332 the format `<project>/<extension>` 333 334 - *Example 1*: 335 336 ``` 337 p, role:allow-extensions, extensions, *, some-project/some-extension, allow 338 ``` 339 340 In the example 1, a permission is configured to allowing the subject 341 `role:allow-extensions`, for the resource type `extensions`, for all (`*`) 342 actions, in the project `some-project`, for the extension name 343 `some-extension`. 344 345 346 - *Example 2*: 347 348 ``` 349 p, role:allow-extensions, extensions, *, */some-extension, allow 350 ``` 351 352 In the example 2, the permission is similar to the example 1 with the 353 difference that the extension `some-extension` will be allowed for all 354 projects. 355 356 - *Example 3*: 357 358 ``` 359 p, role:allow-extensions, extensions, *, */*, allow 360 ``` 361 362 In the example 3, the subject `role:allow-extensions` is allowed to 363 execute extensions in all projects. 364 365 * **Advanced config suggestions:** 366 367 With advanced RBAC configuration suggestions, admins will be able to define 368 permissions per project, per namespace and per extension. 369 370 There are 3 main approaches to achieve this type of RBAC configuration: 371 372 1. `<object>` has addional section for namespace: 373 ``` 374 p, dev, extensions, *, some-project/some-namespace/some-extension, allow 375 ``` 376 377 2. `<action>` has 2 sections for extension name and namespace: 378 ``` 379 p, dev, extensions, some-extension/some-namespace, some-project/some-application, allow 380 ``` 381 382 3. `<resource>` has 2 sections for extension type and extension name: 383 ``` 384 p, dev, extensions/some-extension, *, some-project/some-application, allow 385 ``` 386 387 Reference: [Original discussion][6] 388 389 The final RBAC format must be defined and properly documented during implementation. 390 391 ### Security Considerations 392 393 - Argo CD API Server must apply **authn** and **authz** for all incoming 394 extensions requests 395 - Argo CD must authorize requests coming from UI and check that the 396 authenticated user has access to invoke a specific URL belonging to an 397 extension 398 399 ### Risks and Mitigations 400 401 ### Upgrade / Downgrade 402 403 ## Drawbacks 404 405 - Slight increase in Argo CD code base complexity. 406 - Increased security risk. 407 - Impact of extensions on overall Argo CD performance (mitigated by rate limiting + idle conn timeout). 408 409 ## Open Questions 410 411 1. What are the possible actions that can be provided to extensions RBAC? 412 A. This proposal does not define additional RBAC actions for extensions. 413 Currently the only possible value is `*` which will allow admins to enable 414 or disable certain extensions per project. If there is a new requirement 415 to support additional actions for extensions to limit just specific HTTP 416 verbs for example, an enhancement can be created to extend this 417 functionality. If this requirement becomes necessary, it won't be a 418 breaking change as it will be more restrictive. 419 420 [1]: https://argo-cd.readthedocs.io/en/stable/developer-guide/ui-extensions/ 421 [2]: https://github.com/argoproj-labs/argocd-extensions 422 [3]: https://github.com/argoproj/argo-cd/blob/a23bfc3acaa464cbdeafdbbe66d05a121d5d1fb3/server/rbacpolicy/rbacpolicy.go#L17-L25 423 [4]: https://argo-cd.readthedocs.io/en/stable/operator-manual/argocd-cm.yaml 424 [5]: https://kubernetes.io/docs/tasks/extend-kubernetes/configure-aggregation-layer/#authentication-flow 425 [6]: https://github.com/argoproj/argo-cd/pull/10435#discussion_r986941880