nabsul/kcert

Support for Istio Gateways

CmdrSharp opened this issue · 14 comments

Hi! First - thanks for a cool project!

Are there any plans to support watching Istio Gateway-objects rather than just Kubernetes ingresses?
The current implementation doesn't work well together with Istio unless you strictly use Ingress'es, which removes a fair bit of the feature-set that istio provides through its gateway abstraction.

https://istio.io/latest/docs/tasks/traffic-management/ingress/ingress-control/

I think this would be beyond the scope of KCert (the K is for Kubernetes :-D ). However, I've been thinking of using the KCert code as a base to make a more general certificate management service.

To work generally there would need to be an API/contract for the following actions:

  • Initiate certificate creation
  • Read/Store certificates
  • Receive and respond to http challenges

What would these actions look like in the case of Istio?

Istio is perfectly capable of reading normal Ingress objects. For cert-manager, you specify the ingress class on the Issuer like so:

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod-cluster
  namespace: istio-system
spec:
  acme:
    email: ops@deanpetrusek.cloud
    server: https://acme-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      name: letsencrypt-prod-cluster
    solvers:
    - http01:
        ingress:
          class: istio

This makes cert-manager create its ingress objects with a specific annotation like so:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: ingress
  annotations:
    kubernetes.io/ingress.class: istio
spec:
...

That's all there is to it, really. The difference on your end would just be the ability to scan for changes to the classic Istio gateway objects. They look like this:

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: gateway
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 443
      name: https
      protocol: HTTPS
    tls:
      mode: SIMPLE
      credentialName: ingress-cert
    hosts:
    - my.example.com

Ah, I understand now. This is why I'm not a fan of CRDs, and intentionally avoided creating any new ones with KCert :-D

Still, this should be possible. Let me think about how to best implement this; whether a one-off Istio-specific implemention makes sense, or if there's a way to make this part more generic.

The other challenge I will have is testing such a change. I'm not at all familiar with Istio, and I doubt I have time setup a test environment. I would need help for that part.

Understood! Happy to help testing or provide info when/if needed. Service meshes aren't uncommon so some basic support for the larger options isn't a bad goal, I think :)

Great! The information you provided above is a great start. One thing I think might be missing: How will KCert set up an http route to itself? That is needed for the http challenge to succeed.

Currently this is done by creating a temporary ingress, but I assume it will need to be done via this Gateway CRD now.

When istio is set up with support for classic ingress objects, no other resources are needed. In fact for this purpose it won't care about the Gateway object (since you've defined it in an ingress). The gateway object is the classic Istio CRD which most (I think) still use, so that's why it is what needs to be scanned for the hosts.

Without that support, you would create a VirtualService which defines routing. Not even cert-manager supports that model though, so I'm not sure it's reasonable to put it within scope here.

The gateway object is the classic Istio CRD which most (I think) still use, so that's why it is what needs to be scanned for the hosts.

Right, so this sounds to me like only watching Gateway objects isn't sufficient. We'll need to route http requests to /.well-known/acme-challenge to port 80 of KCert.

I believe that's done using normal HTTPRoute definitions for the gateway API.

https://istio.io/latest/docs/tasks/traffic-management/ingress/ingress-control/

I should elborate to make sure this is entirely clear;

  1. Istio supports normal ingress objects. At that point, it doesn't do much of its job as a service mesh - but for our case here, that's not relevant anyway. What is important is that it can direct traffic for the ACME Challenge. Apart from the annotation, I don't think you need to make any other changes. on that logic.
  2. Now when it comes to what objects to watch for changes; it can either be the Kubernetes Gateway objects, or Istio's own CRD (also called Gateway). For now, I believe most still use the latter (which we've discussed so far), since the support for native Gateway objects is still in beta.

KCert doesn't use Gateway objects at all (Kubernetes native or otherwise). It uses ingresses for everything right now.

Yeah, and that should work fine here too. The difference is strictly in what objects to watch.

Cool. I have a bit of a backlog of open source project issues. Hopefully I can get to this in the next couple of weeks.

Hi - I've been reading this thread with interest. did anything come of this in the end?

nabsul commented

Hi @fidoedidoe. This feature sounds interesting and useful, but I don't have the capacity to work on it. It would involve too much overhead for me since I've never used Istio.

I would be happy to accept and merge a pull request, as long as:

  • The feature is off by default and clearly doesn't change the old behavior
  • It would then be up to the contributor to test the feature and make sure it works