github.com/argoproj/argo-cd/v3@v3.2.1/docs/developer-guide/extensions/proxy-extensions.md (about)

     1  # Proxy Extensions
     2  
     3  !!! warning "Beta Feature (Since 2.7.0)"
     4  
     5      This feature is in the [Beta](https://github.com/argoproj/argoproj/blob/main/community/feature-status.md#beta) stage.
     6      It is generally considered stable, but there may be unhandled edge cases.
     7  
     8  ## Overview
     9  
    10  With UI extensions it is possible to enhance Argo CD web interface to
    11  provide valuable data to the user. However the data is restricted to
    12  the resources that belongs to the Application. With proxy extensions
    13  it is also possible to add additional functionality that have access
    14  to data provided by backend services. In this case Argo CD API server
    15  acts as a reverse-proxy authenticating and authorizing incoming
    16  requests before forwarding to the backend service.
    17  
    18  ## Configuration
    19  
    20  As proxy extension is in [Alpha][1] phase, the feature is disabled by
    21  default. To enable it, it is necessary to configure the feature flag
    22  in Argo CD command parameters. The easiest way to properly enable
    23  this feature flag is by adding the `server.enable.proxy.extension` key
    24  in the existing `argocd-cmd-params-cm`. For example:
    25  
    26  ```yaml
    27  apiVersion: v1
    28  kind: ConfigMap
    29  metadata:
    30    name: argocd-cmd-params-cm
    31    namespace: argocd
    32  data:
    33    server.enable.proxy.extension: 'true'
    34  ```
    35  
    36  Once the proxy extension is enabled, it can be configured in the main
    37  Argo CD configmap ([argocd-cm][2]).
    38  
    39  The example below demonstrates all possible configurations available
    40  for proxy extensions:
    41  
    42  ```yaml
    43  apiVersion: v1
    44  kind: ConfigMap
    45  metadata:
    46    name: argocd-cm
    47    namespace: argocd
    48  data:
    49    extension.config: |
    50      extensions:
    51      - name: httpbin
    52        backend:
    53          connectionTimeout: 2s
    54          keepAlive: 15s
    55          idleConnectionTimeout: 60s
    56          maxIdleConnections: 30
    57          services:
    58          - url: http://httpbin.org
    59            headers:
    60            - name: some-header
    61              value: '$some.argocd.secret.key'
    62            cluster:
    63              name: some-cluster
    64              server: https://some-cluster
    65  ```
    66  
    67  Proxy extensions can also be provided individually using dedicated
    68  Argo CD configmap keys for better GitOps operations. The example below
    69  demonstrates how to configure the same hypothetical httpbin config
    70  above using a dedicated key:
    71  
    72  ```yaml
    73  apiVersion: v1
    74  kind: ConfigMap
    75  metadata:
    76    name: argocd-cm
    77    namespace: argocd
    78  data:
    79    extension.config.httpbin: |
    80      connectionTimeout: 2s
    81      keepAlive: 15s
    82      idleConnectionTimeout: 60s
    83      maxIdleConnections: 30
    84      services:
    85      - url: http://httpbin.org
    86        headers:
    87        - name: some-header
    88          value: '$some.argocd.secret.key'
    89        cluster:
    90          name: some-cluster
    91          server: https://some-cluster
    92  ```
    93  
    94  Attention: Extension names must be unique in the Argo CD configmap. If
    95  duplicated keys are found, the Argo CD API server will log an error
    96  message and no proxy extension will be registered.
    97  
    98  Note: There is no need to restart Argo CD Server after modifying the
    99  `extension.config` entry in Argo CD configmap. Changes will be
   100  automatically applied. A new proxy registry will be built making
   101  all new incoming extensions requests (`<argocd-host>/extensions/*`) to
   102  respect the new configuration.
   103  
   104  Every configuration entry is explained below:
   105  
   106  #### `extensions` (_list_)
   107  
   108  Defines configurations for all extensions enabled.
   109  
   110  #### `extensions.name` (_string_)
   111  
   112  (mandatory)
   113  
   114  Defines the endpoint that will be used to register the extension
   115  route. For example, if the value of the property is `extensions.name:
   116  my-extension` then the backend service will be exposed under the
   117  following url:
   118  
   119      <argocd-host>/extensions/my-extension
   120  
   121  #### `extensions.backend.connectionTimeout` (_duration string_)
   122  
   123  (optional. Default: 2s)
   124  
   125  Is the maximum amount of time a dial to the extension server will wait
   126  for a connect to complete.
   127  
   128  #### `extensions.backend.keepAlive` (_duration string_)
   129  
   130  (optional. Default: 15s)
   131  
   132  Specifies the interval between keep-alive probes for an active network
   133  connection between the API server and the extension server.
   134  
   135  #### `extensions.backend.idleConnectionTimeout` (_duration string_)
   136  
   137  (optional. Default: 60s)
   138  
   139  Is the maximum amount of time an idle (keep-alive) connection between
   140  the API server and the extension server will remain idle before
   141  closing itself.
   142  
   143  #### `extensions.backend.maxIdleConnections` (_int_)
   144  
   145  (optional. Default: 30)
   146  
   147  Controls the maximum number of idle (keep-alive) connections between
   148  the API server and the extension server.
   149  
   150  #### `extensions.backend.services` (_list_)
   151  
   152  Defines a list with backend url by cluster.
   153  
   154  #### `extensions.backend.services.url` (_string_)
   155  
   156  (mandatory)
   157  
   158  Is the address where the extension backend must be available.
   159  
   160  #### `extensions.backend.services.headers` (_list_)
   161  
   162  If provided, the headers list will be added on all outgoing requests
   163  for this service config. Existing headers in the incoming request with
   164  the same name will be overridden by the one in this list. Reserved header
   165  names will be ignored (see the [headers](#incoming-request-headers) below).
   166  
   167  #### `extensions.backend.services.headers.name` (_string_)
   168  
   169  (mandatory)
   170  
   171  Defines the name of the header. It is a mandatory field if a header is
   172  provided.
   173  
   174  #### `extensions.backend.services.headers.value` (_string_)
   175  
   176  (mandatory)
   177  
   178  Defines the value of the header. It is a mandatory field if a header is
   179  provided. The value can be provided as verbatim or as a reference to an
   180  Argo CD secret key. In order to provide it as a reference, it is
   181  necessary to prefix it with a dollar sign.
   182  
   183  Example:
   184  
   185      value: '$some.argocd.secret.key'
   186  
   187  In the example above, the value will be replaced with the one from
   188  the argocd-secret with key 'some.argocd.secret.key'.
   189  
   190  #### `extensions.backend.services.cluster` (_object_)
   191  
   192  (optional)
   193  
   194  If provided, and multiple services are configured, will have to match
   195  the application destination name or server to have requests properly
   196  forwarded to this service URL. If there are multiple backends for the
   197  same extension this field is required. In this case, it is necessary
   198  to provide both values to avoid problems with applications unable to
   199  send requests to the proper backend service. If only one backend
   200  service is configured, this field is ignored, and all requests are
   201  forwarded to the configured one.
   202  
   203  #### `extensions.backend.services.cluster.name` (_string_)
   204  
   205  (optional)
   206  
   207  It will be matched with the value from
   208  `Application.Spec.Destination.Name`
   209  
   210  #### `extensions.backend.services.cluster.server` (_string_)
   211  
   212  (optional)
   213  
   214  It will be matched with the value from
   215  `Application.Spec.Destination.Server`.
   216  
   217  ## Usage
   218  
   219  Once a proxy extension is configured it will be made available under
   220  the `/extensions/<extension-name>` endpoint exposed by Argo CD API
   221  server. The example above will proxy requests to
   222  `<apiserver-host>/extensions/httpbin/` to `http://httpbin.org`.
   223  
   224  The diagram below illustrates an interaction possible with this
   225  configuration:
   226  
   227  ```
   228                                                ┌─────────────┐
   229                                                │ Argo CD UI  │
   230                                                └────┬────────┘
   231                                                     │  ▲
   232    GET <apiserver-host>/extensions/httpbin/anything │  │ 200 OK
   233              + authn/authz headers                  │  │
   234                                                     ▼  │
   235                                              ┌─────────┴────────┐
   236                                              │Argo CD API Server│
   237                                              └──────┬───────────┘
   238                                                     │  ▲
   239                     GET http://httpbin.org/anything │  │ 200 OK
   240                                                     │  │
   241                                                     ▼  │
   242                                               ┌────────┴────────┐
   243                                               │ Backend Service │
   244                                               └─────────────────┘
   245  ```
   246  
   247  ### Incoming Request Headers
   248  
   249  Note that Argo CD API Server requires additional HTTP headers to be
   250  sent in order to enforce if the incoming request is authenticated and
   251  authorized before being proxied to the backend service. The headers
   252  are documented below:
   253  
   254  #### `Cookie`
   255  
   256  Argo CD UI keeps the authentication token stored in a cookie
   257  (`argocd.token`). This value needs to be sent in the `Cookie` header
   258  so the API server can validate its authenticity.
   259  
   260  Example:
   261  
   262      Cookie: argocd.token=eyJhbGciOiJIUzI1Ni...
   263  
   264  The entire Argo CD cookie list can also be sent. The API server will
   265  only use the `argocd.token` attribute in this case.
   266  
   267  #### `Argocd-Application-Name` (mandatory)
   268  
   269  This is the name of the project for the application for which the
   270  extension is being invoked. The header value must follow the format:
   271  `"<namespace>:<app-name>"`.
   272  
   273  Example:
   274  
   275      Argocd-Application-Name: namespace:app-name
   276  
   277  #### `Argocd-Project-Name` (mandatory)
   278  
   279  The logged in user must have access to this project in order to be
   280  authorized.
   281  
   282  Example:
   283  
   284      Argocd-Project-Name: default
   285  
   286  Argo CD API Server will ensure that the logged in user has the
   287  permission to access the resources provided by the headers above. The
   288  validation is based on pre-configured [Argo CD RBAC rules][3]. The
   289  same headers are also sent to the backend service. The backend service
   290  must also validate if the validated headers are compatible with the
   291  rest of the incoming request.
   292  
   293  ### Outgoing Requests Headers
   294  
   295  Requests sent to backend services will be decorated with additional
   296  headers. The outgoing request headers are documented below:
   297  
   298  #### `Argocd-Target-Cluster-Name`
   299  
   300  Will be populated with the value from `app.Spec.Destination.Name` if
   301  it is not empty string in the application resource.
   302  
   303  #### `Argocd-Target-Cluster-URL`
   304  
   305  Will be populated with the value from `app.Spec.Destination.Server` if
   306  it is not empty string is the Application resource.
   307  
   308  Note that additional pre-configured headers can be added to outgoing
   309  request. See [backend service headers](#extensionsbackendservicesheaders-list)
   310  section for more details.
   311  
   312  #### `Argocd-Username`
   313  
   314  Will be populated with the username logged in Argo CD. This is primarily useful for display purposes. 
   315  To identify a user for programmatic needs, `Argocd-User-Id` is probably a better choice.
   316  
   317  #### `Argocd-User-Id`
   318  
   319  Will be populated with the internal user id, most often defined by the `sub` claim, logged in Argo CD.
   320  
   321  #### `Argocd-User-Groups`
   322  
   323  Will be populated with the configured RBAC scopes, most often the `groups` claim, from the user logged in Argo CD.
   324  
   325  ### Multi Backend Use-Case
   326  
   327  In some cases when Argo CD is configured to sync with multiple remote
   328  clusters, there might be a need to call a specific backend service in
   329  each of those clusters. The proxy-extension can be configured to
   330  address this use-case by defining multiple services for the same
   331  extension. Consider the following configuration as an example:
   332  
   333  ```yaml
   334  extension.config: |
   335    extensions:
   336    - name: some-extension
   337      backend:
   338        services:
   339        - url: http://extension-name.com:8080
   340          cluster
   341            name: kubernetes.local
   342        - url: https://extension-name.ppd.cluster.k8s.local:8080
   343          cluster
   344            server: user@ppd.cluster.k8s.local
   345  ```
   346  
   347  In the example above, the API server will inspect the Application
   348  destination to verify which URL should be used to proxy the incoming
   349  request to.
   350  
   351  ## Security
   352  
   353  When a request to `/extensions/*` reaches the API Server, it will
   354  first verify if it is authenticated with a valid token. It does so by
   355  inspecting if the `Cookie` header is properly sent from Argo CD UI
   356  extension.
   357  
   358  Once the request is authenticated it is then verified if the
   359  user has permission to invoke this extension. The permission is
   360  enforced by Argo CD RBAC configuration. The details about how to
   361  configure the RBAC for proxy-extensions can be found in the [RBAC
   362  documentation][3] page.
   363  
   364  Once the request is authenticated and authorized by the API server, it
   365  is then sanitized before being sent to the backend service. The
   366  request sanitization will remove sensitive information from the
   367  request like the `Cookie` and `Authorization` headers.
   368  
   369  A new `Authorization` header can be added to the outgoing request by
   370  defining it as a header in the `extensions.backend.services.headers`
   371  configuration. Consider the following example:
   372  
   373  ```yaml
   374  extension.config: |
   375    extensions:
   376    - name: some-extension
   377      backend:
   378        services:
   379        - url: http://extension-name.com:8080
   380          headers:
   381          - name: Authorization
   382            value: '$some-extension.authorization.header'
   383  ```
   384  
   385  In the example above, all requests sent to
   386  `http://extension-name.com:8080` will have an additional
   387  `Authorization` header. The value of this header will be the one from
   388  the [argocd-secret](../../operator-manual/argocd-secret-yaml.md) with
   389  key `some-extension.authorization.header`
   390  
   391  [1]: https://github.com/argoproj/argoproj/blob/master/community/feature-status.md
   392  [2]: https://argo-cd.readthedocs.io/en/stable/operator-manual/argocd-cm.yaml
   393  [3]: ../../operator-manual/rbac.md#the-extensions-resource