How to exposed ArgoCD using ingress and cert-manager with the Helm Chart?

744 Views Asked by At

Problem

I have a problem while exposing ArgoCD with ingress when I trying to enable TLS. With my current config, a secret argocd-server-tls is well generated with a valid certificate. but I got an error 500, Internal Server Error while trying to resolve the ingress. All ArgoCD logs are OK, I can see that my TLS configuration are well loaded from the argocd-server-tls secret "msg="Loading TLS configuration from secret argocd/argocd-server-tls" (log from argocd-server).

I can find an error log on the trafik logs:

msg="'500 Internal Server Error' caused by: tls: failed to verify certificate: x509: cannot validate certificate for <ARGOCD_SERVER_POD_IP> because it doesn't contain any IP SANs"

Is someone encountered the same issue ?

Context

  • ArgoCD: v2.9.1
  • Helm chart: 5.51.6
  • Cert-manager: v.1.13.2
  • Traefik: 25.0.0

I'm using a cert-manager clusterIssuer to get a certificate. It working well with other service on the same cluster.

Config

Here is my ArgoCD Helm values file:

values.yaml

server:
  ingress:
    enabled: true
    annotations:
      ingress.kubernetes.io/ssl-redirect: true
      ingress.kubernetes.io/proxy-body-size: 0
      traefik.ingress.kubernetes.io/router.entrypoints: websecure
      cert-manager.io/cluster-issuer: My-cluster-issuer
    ingressClassName: traefik
    hosts:
      - myargocddomain.com
    tls:
      - hosts:
          - myargocddomain.com
        secretName: argocd-server-tls
    # -- Uses `server.service.servicePortHttps` instead `server.service.servicePortHttp`
    https: true

What I tried ?

I have seen on the ArgoCD Helm Chart that a certificate section could be set:

values.yaml

## Server
#
server:
  certificate:
    # -- Deploy a Certificate resource (requires cert-manager)
    enabled: true
    # -- The name of the Secret that will be automatically created and managed by this Certificate resource
    secretName: argocd-server-tls
    # -- Certificate primary domain (commonName)
    domain: myargocddomain.com
    # -- Certificate Subject Alternate Names (SANs)
    additionalHosts: []
    # Certificate issuer
    ## Ref: https://cert-manager.io/docs/concepts/issuer
    issuer:
      # -- Certificate issuer group. Set if using an external issuer. Eg. `cert-manager.io`
      group: "cert-manager.io"
      # -- Certificate issuer kind. Either `Issuer` or `ClusterIssuer`
      kind: "ClusterIssuer"
      # -- Certificate issuer name. Eg. `letsencrypt`
      name: "My-cluster-issuer"

  ingress:
      enabled: true
      annotations:
        ingress.kubernetes.io/ssl-redirect: true
        ingress.kubernetes.io/proxy-body-size: 0
        traefik.ingress.kubernetes.io/router.entrypoints: websecure
        cert-manager.io/cluster-issuer: My-cluster-issuer
      ingressClassName: traefik
      hosts:
        - myargocddomain.com
      tls:
      - hosts:
          - myargocddomain.com
        secretName: argocd-server-tls
    # -- Uses `server.service.servicePortHttps` instead `server.service.servicePortHttp`
    https: true

The problem with this configuration is that two certificate are created, targeting the same secret "argocd-server-tls", so one has Ready: False with this message Secret was issued for "argocd-server-tls". If this message is not transient, you might have two conflicting Certificates pointing to the same secret.

Then I tried to set server.certificate.secretName=toto for testing, here is another problem. Still two certificate created, the one that come with the Ingress and the one from the certificate configuration. The one from the ingress still created properly but doesn't work (Internal Server Error...) and the other one are not ready with message Issuing certificate as Secret does not exist.

1

There are 1 best solutions below

0
On

I Finally got it ! It was a problem of TLS termination. In the current configuration bellow, I was trying to terminate TLS at ArgoCD level. But what I wanted to do is to secure traffic outside of the cluster (I haven't yet implement any solution to encrypt internal traffic).

So what I needed to do was to encrypt traffic from outside (client) to my Load Balancer and then enabled insecure traffic from the Load Balancer to ArgoCD server.

                                  |
                 WWW              |             Internal
 ________                   ______|_______                     ________
|        |                 |              |                   |        |
| Client |======(TLS)=====>| LoadBalancer |======(clear)=====>| ArgoCD |
|________|                 |______________|                   |________|

Here is the final configuration:

values.yaml

configs:
  cm:
    url: "https://<MY_DOMAIN>"
  params:
    server.insecure: "true"


server:
  certificate:
    # -- Deploy a Certificate resource (requires cert-manager)
    enabled: true
    # -- The name of the Secret that will be automatically created and managed by this Certificate resource
    secretName: argocd-server-tls
    # -- Certificate primary domain (commonName)
    domain: <MY_DOMAIN>
    # Certificate issuer
    ## Ref: https://cert-manager.io/docs/concepts/issuer
    issuer:
      # -- Certificate issuer group. Set if using an external issuer. Eg. `cert-manager.io`
      group: "cert-manager.io"
      # -- Certificate issuer kind. Either `Issuer` or `ClusterIssuer`
      kind: "ClusterIssuer"
      # -- Certificate issuer name. Eg. `letsencrypt`
      name: "<ISSUER_NAME>"

  ingress:
    enabled: true
    annotations:
      traefik.ingress.kubernetes.io/router.entrypoints: websecure
    ingressClassName: traefik
    hosts:
      - <MY_DOMAIN>
    tls:
      - hosts:
          - <MY_DOMAIN>
        secretName: argocd-server-tls
    # -- Uses `server.service.servicePortHttps` instead `server.service.servicePortHttp`
    https: false

Here ArgoCD run in insecure mode, but using SSL cert for outside traffic !

About my thee issue that was trying to generate two secret, that was because I was reference the CertManager issuer two times: Once on the server.certificate bloc and once on the server.ingress. That result on two certificate requests, I just removed the one from server.ingress.