Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New resource: GKE Managed Certificate #446

Closed
brendanator opened this issue May 19, 2019 · 10 comments
Closed

New resource: GKE Managed Certificate #446

brendanator opened this issue May 19, 2019 · 10 comments

Comments

@brendanator
Copy link

Affected Resource(s)

Please list the resources as a list, for example:

  • kubernetes_ingress

Expected Behaviour

Now the ingress resource is available it is nice and easy to setup ingress to load balance a backend service over http. Ideally it would only be available over https.

According to https://cloud.google.com/kubernetes-engine/docs/how-to/managed-certs a managed certificate is easy to create

apiVersion: networking.gke.io/v1beta1
kind: ManagedCertificate
metadata:
  name: example-certificate
spec:
  domains:
    - example.com

and using a certificate created this way with terraform ingress works correctly.

As this resource is not available I tried using google_compute_managed_ssl_certificate

resource "google_compute_managed_ssl_certificate" "example_certificate" {
  provider = "google-beta"

  name = "example-certificate"

  managed {
    domains = ["example.com."]
  }
}

but this never provisions and ingress doesn't switch over to https.

In both cases the ingress looks like this

resource "kubernetes_ingress" "example" {
  metadata {
    name = "example"

    annotations {
      "kubernetes.io/ingress.allow-http"       = "false"
      "networking.gke.io/managed-certificates" = "example-certificate"
    }
  }

  spec {
    rule {
      host = "example.com"

      http {
        path {
          backend {
            service_name = "example"
            service_port = 80
          }
        }
      }
    }
  }
}

Is there any scope in this provider to cloud specific extensions? If not, are there any suggestions as to how to provision this with terraform?

@sarneaud
Copy link

Try making sure the ingress is dependent on the cert in Terraform by interpolating the example-certificate. That way the ingress should be created after the cert.

GKE's ingress integration is a PITA when it comes to correctly reflecting config updates, but it should work cleanly if the cert exists first. I can confirm that the ingress works with certs that are created directly with gcloud and not with ManagedCertificate.

@caquino
Copy link

caquino commented May 27, 2019

I've been trying to achieve the same, but for some reason the certificate is never attached to my load balancer resource and it stays on FAILED_NOT_VISIBLE.

Did any of you succeed without the ManagedCertificate resource? should the annotation for pre-shared certificate should be used instead?

For me the certificate only managed to be provisioned when I switched to the pre-shared annotation, but the load balancer accepts connections on 443 without negotiating SSL, which is really weird.

@brendanator
Copy link
Author

I can confirm that I tried @sarneaud's suggestion and it didn't work. I get FAILED_NOT_VISIBLE like you @caquino

In the end I did this but it's a bit of a messy solution

resource "null_resource" "example_cert" {
  provisioner "local-exec" {
    command = <<EOT
kubectl create -f - -- <<EOF
apiVersion: networking.gke.io/v1beta1
kind: ManagedCertificate
metadata:
  name: example-certificate
spec:
  domains:
    - example.com
EOF
EOT
  }
}

@caquino
Copy link

caquino commented May 29, 2019

@brendanator I managed to get it working with the following solution:
First by creating a certificate:

resource "google_compute_managed_ssl_certificate" "default" {
  provider = "google-beta"

  name = "${var.name}-${var.environment}-ssl"

  managed {
    domains = ["www.${var.domain_name}"]
  }
}

The service should be created with type NodePort:

resource "kubernetes_service" "proxy_svc" {
  metadata {
    namespace = "default"
    name      = kubernetes_deployment.proxy_dep.metadata.0.name
  }

  spec {
    type             = "NodePort"
    session_affinity = "ClientIP"

    port {
      name        = "http"
      protocol    = "TCP"
      port        = 80
      target_port = 80
    }

    selector = {
      app = kubernetes_deployment.proxy_dep.metadata.0.labels.app
    }
  }
  depends_on = ["google_container_cluster.cluster"]
}

And the ingress configuration:

resource "kubernetes_ingress" "default" {
  metadata {
    name = "${var.name}-${var.environment}-ingress"

    annotations = {
      "ingress.gcp.kubernetes.io/pre-shared-cert"   = google_compute_managed_ssl_certificate.default.name
      "kubernetes.io/ingress.global-static-ip-name" = google_compute_global_address.address.name
    }
  }

  spec {
    rule {
      http {
        path {
          backend {
            service_name = kubernetes_service.proxy_svc.metadata.0.name
            service_port = 80
          }
        }
      }
    }
  }
}

The trick was to use ingress.gcp.kubernetes.io/pre-shared-cert instead of networking.gke.io/managed-certificates

Hope it helps

@brendanator
Copy link
Author

Thanks @caquino, I can confirm that using "ingress.gcp.kubernetes.io/pre-shared-cert" works

For anyone else doing this, I had to wait about 15 minutes for the cert to provision and another few minutes for ingress to start using it

@orkenstein
Copy link

I'd still like to have ManagedCertificate resource available in kubernetes provider.

@orkenstein
Copy link

@caquino thanks for you post. How to force load balancer to use HTTPS in that case? In my setup it still goes over HTTP all the time.

@marcmarcet-sage
Copy link

I agree with @orkenstein that the solution to this should be a ManagedCertificate resource for kubernetes.

@essjayhch
Copy link

essjayhch commented Oct 4, 2019

The problem is that from what I can tell, by interacting with this from the kubectl side as well as the terraform google_compute_managed_ssl_certificate is that when an ingress is created, it will only provision an HTTP target proxy for the load balancer that is configured. The only way that the HTTPS target proxy, which is where the certificate gets terminated on, is by way of ManagedCertificate resources for these specific instances. This is probably a side effect of the way that certificates are a prerequisite of provisioning the proxy in the first place.

@griffinator76
Copy link

Not sure why this issue has been closed? It would simplify deploying secured apps on GKE using this custom K8s resource instead of the workaround described above if there was an associated Terraform resource:
https://github.com/GoogleCloudPlatform/gke-managed-certs
https://cloud.google.com/kubernetes-engine/docs/how-to/managed-certs

@ghost ghost locked and limited conversation to collaborators Apr 21, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants