diff --git a/helm/argo-stack/overlays/ingress-authz-overlay/README.md b/helm/argo-stack/overlays/ingress-authz-overlay/README.md index d07fe2c1..85f90f4d 100644 --- a/helm/argo-stack/overlays/ingress-authz-overlay/README.md +++ b/helm/argo-stack/overlays/ingress-authz-overlay/README.md @@ -64,6 +64,27 @@ See the [User Guide](docs/authz-ingress-user-guide.md) for architecture diagrams - NGINX Ingress Controller - cert-manager (for TLS) - **must be installed before deploying this overlay** +### TLS Certificate Ownership + +When using cert-manager's ingress-shim, only **one** ingress resource can "own" a Certificate. +This overlay uses a `primary: true` flag on routes to designate which ingress should have the +`cert-manager.io/cluster-issuer` annotation. + +By default, the `workflows` route is set as primary. Other ingresses reference the same TLS +secret but without the cluster-issuer annotation, avoiding the "certificate resource is not +owned by this object" error. + +To change the primary route: + +```yaml +ingressAuthzOverlay: + routes: + workflows: + primary: false # Remove primary from workflows + applications: + primary: true # Make applications the primary +``` + ### Installing cert-manager If you see `no matches for kind "ClusterIssuer"`, cert-manager is not installed: diff --git a/helm/argo-stack/overlays/ingress-authz-overlay/docs/authz-ingress-user-guide.md b/helm/argo-stack/overlays/ingress-authz-overlay/docs/authz-ingress-user-guide.md index 4e57dbe7..e5e919ba 100644 --- a/helm/argo-stack/overlays/ingress-authz-overlay/docs/authz-ingress-user-guide.md +++ b/helm/argo-stack/overlays/ingress-authz-overlay/docs/authz-ingress-user-guide.md @@ -193,6 +193,41 @@ Common issues: - **ACME Registration Failed**: Check your email address is valid and you can reach Let's Encrypt's API - **Secret Not Found in Expected Namespace**: The secret is created in the cert-manager namespace, not your application namespace +### TLS Certificate Ownership + +When using multiple ingress resources with the same TLS secret and cert-manager's ingress-shim, you may encounter an error: + +``` +certificate resource is not owned by this object. refusing to update non-owned certificate resource +``` + +This happens because **cert-manager only allows one Ingress to own a Certificate**. When multiple ingresses have the `cert-manager.io/cluster-issuer` annotation pointing to the same certificate, a conflict occurs. + +**Solution**: This overlay uses a `primary: true` flag on routes. Only the primary route's Ingress gets the `cert-manager.io/cluster-issuer` annotation. Other ingresses reference the TLS secret but don't trigger certificate creation. + +```yaml +ingressAuthzOverlay: + routes: + workflows: + enabled: true + primary: true # Only this route has cert-manager.io/cluster-issuer annotation + # ... + applications: + enabled: true + # primary: false (default) - uses the TLS secret but doesn't trigger cert creation +``` + +By default, the `workflows` route is primary. To change: + +```yaml +ingressAuthzOverlay: + routes: + workflows: + primary: false + api: + primary: true # Move certificate ownership to /api route +``` + ### Configuration Options | Setting | Description | Default | diff --git a/helm/argo-stack/overlays/ingress-authz-overlay/templates/ingress-authz.yaml b/helm/argo-stack/overlays/ingress-authz-overlay/templates/ingress-authz.yaml index 6f81fae3..a056aef2 100644 --- a/helm/argo-stack/overlays/ingress-authz-overlay/templates/ingress-authz.yaml +++ b/helm/argo-stack/overlays/ingress-authz-overlay/templates/ingress-authz.yaml @@ -3,6 +3,11 @@ Ingress resources for each route in the ingress-authz-overlay. Each route creates a separate Ingress resource in its respective namespace, all sharing the same host and TLS configuration. All routes are protected by the authz-adapter via NGINX external auth. + +NOTE: Only the route with primary: true should have the cert-manager.io/cluster-issuer +annotation. Other routes just reference the TLS secret without the annotation to avoid +cert-manager ownership conflicts. If no route has primary: true, no ingress will have +the cluster-issuer annotation (the Certificate must be created manually or by another means). */}} {{- if .Values.ingressAuthzOverlay.enabled }} {{- $root := . }} @@ -25,8 +30,8 @@ metadata: meta.helm.sh/release-namespace: {{ $root.Release.Namespace }} # NGINX external auth annotations {{- include "ingress-authz-overlay.authAnnotations" $root | nindent 4 }} - {{- if $config.tls.enabled }} - # Let's Encrypt / cert-manager integration + {{- if and $config.tls.enabled $route.primary }} + # Let's Encrypt / cert-manager integration (only on primary route to avoid ownership conflicts) cert-manager.io/cluster-issuer: {{ $config.tls.clusterIssuer | quote }} {{- end }} {{- if $route.useRegex }} diff --git a/helm/argo-stack/overlays/ingress-authz-overlay/values.yaml b/helm/argo-stack/overlays/ingress-authz-overlay/values.yaml index ed3b71a4..301e2056 100644 --- a/helm/argo-stack/overlays/ingress-authz-overlay/values.yaml +++ b/helm/argo-stack/overlays/ingress-authz-overlay/values.yaml @@ -87,10 +87,17 @@ ingressAuthzOverlay: # Each route creates a separate Ingress resource in the specified namespace. # All routes share the same host and TLS configuration. # All routes are protected by the authz-adapter via NGINX external auth. + # + # IMPORTANT: Only ONE route should have the cert-manager.io/cluster-issuer annotation + # to avoid "certificate resource is not owned by this object" errors. + # Set `primary: true` on exactly one route to designate it as the certificate owner. routes: - # Argo Workflows UI + # Argo Workflows UI (primary route - manages TLS certificate) workflows: enabled: true + # Set primary: true to designate this route as the certificate owner + # Only the primary route gets the cert-manager.io/cluster-issuer annotation + primary: true namespace: argo-stack service: argo-stack-argo-workflows-server port: 2746