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