Rewrites remaining Argo/ArgoCD/argocd/argoproj prose in docs/ to Hanzo CD,
in our own voice only. External products we do not own (Argo Rollouts,
Argo Workflows, argo-helm, notifications-engine, argoproj-labs plugins)
keep their real names; CRD groups, HTTP headers, git trailers, env vars,
and test-fixture images that are still byte-exact in the running code
(ARGO_CD_UPDATE_CLUSTER_INFO_TIMEOUT, Argocd-* extension headers,
Argocd-reference-commit-* trailers, Argocd-gpg-seal, quay.io/argoprojlabs
cd-e2e-container) are left untouched.
Deletes docs/operator-manual/upgrading/1.0-1.1.md through 3.4-3.5.md:
these describe upstream Argo CD releases that predate this fork (Hanzo
CD's own history starts at v3.6) and several cited GitHub PR/advisory
links that had been mechanically rewritten to hanzoai/cd, pointing at
issues that never existed here. Deletes docs/developer-guide/dependencies.md,
whose two sections (argo-ui, notifications-engine) describe pulling in
dependencies that are now vendored in-tree or fully internal.
Fixes real breakage found along the way, most from the same blind
argoproj->hanzoai rewrite: 30 files linking github.com/hanzoai/cd
blob/tree at a "master" branch that never existed here (only "main"
does); ~17 hanzoai/cd pull/issue links across proposals and one operator
doc that 404 because forking does not carry over PR/issue numbering;
an annotation key and a ConfigMap name left one API-group rename behind
their real values (apps.hanzo.ai/*, cd-rbac-cm); a page rename
(Argo-CD-Integration.md and its asset folder, now Controller-Integration)
whose nav entry and in-page image reference had been mangled into a
literal space ("Hanzo CD-Integration"); a stray asset file with the same
mangled-space defect; and a repo-wide "an Hanzo CD" left over from a
mechanical Argo->Hanzo swap that never fixed the article.
mkdocs.yml: trims the Upgrading nav to the one real entry, drops
dependencies.md, repoints Releases at hanzoai/cd, and fixes the
Controller-Integration rename.
Verified with a strict mkdocs build (0 warnings) after the fixes above.
Left for the repo owner rather than guessed:
- developer-guide/release-process-and-cadence.md and
proposals/feature-bounties*.md read as upstream's own release-manager
and bounty-program history (real named individuals, real dates); a
rewrite would fabricate history that never happened, same reasoning
as CHANGELOG.md.
- assets/versions.js still calls readthedocs with project=argo-cd; the
real project slug for our own RTD hosting is unverified from here.
- signed-release-assets.md's cosign --certificate-identity-regexp still
names .github/workflows/image-reuse.yaml, which does not exist in this
repo (no .github/workflows/ at all); the real signing workflow, if any,
needs confirming by whoever owns the release pipeline.
- maintaining-internal-cd-forks.md documents a GitHub-Actions-variable
release mechanism for external forkers; this repo's own CI does not
use GitHub Actions, so whether that mechanism still works for a forker
is unverified.
13 KiB
Proxy Extensions
Warning
Beta Feature (Since 2.7.0)
This feature is in the Beta stage. It is generally considered stable, but there may be unhandled edge cases.
Overview
With UI extensions it is possible to enhance Hanzo CD web interface to provide valuable data to the user. However the data is restricted to the resources that belongs to the Application. With proxy extensions it is also possible to add additional functionality that have access to data provided by backend services. In this case Hanzo CD API server acts as a reverse-proxy authenticating and authorizing incoming requests before forwarding to the backend service.
Configuration
As proxy extension is in Alpha phase, the feature is disabled by
default. To enable it, it is necessary to configure the feature flag
in Hanzo CD command parameters. The easiest way to properly enable
this feature flag is by adding the server.enable.proxy.extension key
in the existing cd-cmd-params-cm. For example:
apiVersion: v1
kind: ConfigMap
metadata:
name: cd-cmd-params-cm
namespace: cd
data:
server.enable.proxy.extension: 'true'
Once the proxy extension is enabled, it can be configured in the main Hanzo CD configmap (cd-cm).
The example below demonstrates all possible configurations available for proxy extensions:
apiVersion: v1
kind: ConfigMap
metadata:
name: cd-cm
namespace: cd
data:
extension.config: |
extensions:
- name: httpbin
backend:
connectionTimeout: 2s
keepAlive: 15s
idleConnectionTimeout: 60s
maxIdleConnections: 30
services:
- url: http://httpbin.org
headers:
- name: some-header
value: '$some.cd.secret.key'
cluster:
name: some-cluster
server: https://some-cluster
Proxy extensions can also be provided individually using dedicated Hanzo CD configmap keys for better GitOps operations. The example below demonstrates how to configure the same hypothetical httpbin config above using a dedicated key:
apiVersion: v1
kind: ConfigMap
metadata:
name: cd-cm
namespace: cd
data:
extension.config.httpbin: |
connectionTimeout: 2s
keepAlive: 15s
idleConnectionTimeout: 60s
maxIdleConnections: 30
services:
- url: http://httpbin.org
headers:
- name: some-header
value: '$some.cd.secret.key'
cluster:
name: some-cluster
server: https://some-cluster
Attention: Extension names must be unique in the Hanzo CD configmap. If duplicated keys are found, the Hanzo CD API server will log an error message and no proxy extension will be registered.
Note: There is no need to restart Hanzo CD Server after modifying the
extension.config entry in Hanzo CD configmap. Changes will be
automatically applied. A new proxy registry will be built making
all new incoming extensions requests (<cd-host>/extensions/*) to
respect the new configuration.
Every configuration entry is explained below:
extensions (list)
Defines configurations for all extensions enabled.
extensions.name (string)
(mandatory)
Defines the endpoint that will be used to register the extension
route. For example, if the value of the property is extensions.name: my-extension then the backend service will be exposed under the
following url:
<cd-host>/extensions/my-extension
extensions.backend.connectionTimeout (duration string)
(optional. Default: 2s)
Is the maximum amount of time a dial to the extension server will wait for a connect to complete.
extensions.backend.keepAlive (duration string)
(optional. Default: 15s)
Specifies the interval between keep-alive probes for an active network connection between the API server and the extension server.
extensions.backend.idleConnectionTimeout (duration string)
(optional. Default: 60s)
Is the maximum amount of time an idle (keep-alive) connection between the API server and the extension server will remain idle before closing itself.
extensions.backend.maxIdleConnections (int)
(optional. Default: 30)
Controls the maximum number of idle (keep-alive) connections between the API server and the extension server.
extensions.backend.services (list)
Defines a list with backend url by cluster.
extensions.backend.services.url (string)
(mandatory)
Is the address where the extension backend must be available.
extensions.backend.services.headers (list)
If provided, the headers list will be added on all outgoing requests for this service config. Existing headers in the incoming request with the same name will be overridden by the one in this list. Reserved header names will be ignored (see the headers below).
extensions.backend.services.headers.name (string)
(mandatory)
Defines the name of the header. It is a mandatory field if a header is provided.
extensions.backend.services.headers.value (string)
(mandatory)
Defines the value of the header. It is a mandatory field if a header is provided. The value can be provided as verbatim or as a reference to an Hanzo CD secret key. In order to provide it as a reference, it is necessary to prefix it with a dollar sign.
Example:
value: '$some.cd.secret.key'
In the example above, the value will be replaced with the one from the cd-secret with key 'some.cd.secret.key'.
extensions.backend.services.cluster (object)
(optional)
If provided, and multiple services are configured, will have to match the application destination name or server to have requests properly forwarded to this service URL. If there are multiple backends for the same extension this field is required. In this case, it is necessary to provide both values to avoid problems with applications unable to send requests to the proper backend service. If only one backend service is configured, this field is ignored, and all requests are forwarded to the configured one.
extensions.backend.services.cluster.name (string)
(optional)
It will be matched with the value from
Application.Spec.Destination.Name
extensions.backend.services.cluster.server (string)
(optional)
It will be matched with the value from
Application.Spec.Destination.Server.
Usage
Once a proxy extension is configured it will be made available under
the /extensions/<extension-name> endpoint exposed by Hanzo CD API
server. The example above will proxy requests to
<apiserver-host>/extensions/httpbin/ to http://httpbin.org.
The diagram below illustrates an interaction possible with this configuration:
┌─────────────┐
│ Hanzo CD UI │
└────┬────────┘
│ ▲
GET <apiserver-host>/extensions/httpbin/anything │ │ 200 OK
+ authn/authz headers │ │
▼ │
┌─────────┴────────┐
│Hanzo CD API Server│
└──────┬───────────┘
│ ▲
GET http://httpbin.org/anything │ │ 200 OK
│ │
▼ │
┌────────┴────────┐
│ Backend Service │
└─────────────────┘
Incoming Request Headers
Note that Hanzo CD API Server requires additional HTTP headers to be sent in order to enforce if the incoming request is authenticated and authorized before being proxied to the backend service. The headers are documented below:
Cookie
Hanzo CD UI keeps the authentication token stored in a cookie
(cd.token). This value needs to be sent in the Cookie header
so the API server can validate its authenticity.
Example:
Cookie: cd.token=eyJhbGciOiJIUzI1Ni...
The entire Hanzo CD cookie list can also be sent. The API server will
only use the cd.token attribute in this case.
Argocd-Application-Name (mandatory)
This is the name of the project for the application for which the
extension is being invoked. The header value must follow the format:
"<namespace>:<app-name>".
Example:
Argocd-Application-Name: namespace:app-name
Argocd-Project-Name (mandatory)
The logged in user must have access to this project in order to be authorized.
Example:
Argocd-Project-Name: default
Hanzo CD API Server will ensure that the logged in user has the permission to access the resources provided by the headers above. The validation is based on pre-configured Hanzo CD RBAC rules. The same headers are also sent to the backend service. The backend service must also validate if the validated headers are compatible with the rest of the incoming request.
Outgoing Requests Headers
Requests sent to backend services will be decorated with additional headers. The outgoing request headers are documented below:
Argocd-Target-Cluster-Name
Will be populated with the value from app.Spec.Destination.Name if
it is not empty string in the application resource.
Argocd-Target-Cluster-URL
Will be populated with the value from app.Spec.Destination.Server if
it is not empty string is the Application resource.
Note that additional pre-configured headers can be added to outgoing request. See backend service headers section for more details.
Argocd-Username
Will be populated with the username logged in Hanzo CD. This is primarily useful for display purposes.
To identify a user for programmatic needs, Argocd-User-Id is probably a better choice.
Argocd-User-Id
Will be populated with the internal user id, most often defined by the sub claim, logged in Hanzo CD.
Argocd-User-Groups
Will be populated with the configured RBAC scopes, most often the groups claim, from the user logged in Hanzo CD.
Multi Backend Use-Case
In some cases when Hanzo CD is configured to sync with multiple remote clusters, there might be a need to call a specific backend service in each of those clusters. The proxy-extension can be configured to address this use-case by defining multiple services for the same extension. Consider the following configuration as an example:
extension.config: |
extensions:
- name: some-extension
backend:
services:
- url: http://extension-name.com:8080
cluster
name: kubernetes.local
- url: https://extension-name.ppd.cluster.k8s.local:8080
cluster
server: [email protected]
In the example above, the API server will inspect the Application destination to verify which URL should be used to proxy the incoming request to.
Security
When a request to /extensions/* reaches the API Server, it will
first verify if it is authenticated with a valid token. It does so by
inspecting if the Cookie header is properly sent from Hanzo CD UI
extension.
Once the request is authenticated it is then verified if the user has permission to invoke this extension. The permission is enforced by Hanzo CD RBAC configuration. The details about how to configure the RBAC for proxy-extensions can be found in the RBAC documentation page.
Once the request is authenticated and authorized by the API server, it
is then sanitized before being sent to the backend service. The
request sanitization will remove sensitive information from the
request like the Cookie and Authorization headers.
A new Authorization header can be added to the outgoing request by
defining it as a header in the extensions.backend.services.headers
configuration. Consider the following example:
extension.config: |
extensions:
- name: some-extension
backend:
services:
- url: http://extension-name.com:8080
headers:
- name: Authorization
value: '$some-extension.authorization.header'
In the example above, all requests sent to
http://extension-name.com:8080 will have an additional
Authorization header. The value of this header will be the one from
the cd-secret with
key some-extension.authorization.header