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

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