Azeem Haider
Azeem Haider

Reputation: 313

Enabling SSL on GKE endpoints not working correctly

I created API on GKE using cloud endpoints. It is working fine without Https You can try it here API without Https

I followed the instructions which mention here Enabling SSL for cloud endpoint after setup everything which is mention in this page I'm able to access my endpoints with Https but with a warning.

Your connection is not private - Back to Safety (Chrome)

Check it here API with Https

Can you please let me know what I'm missing

Update

I'm using Google-managed SSL certificates for cloud endpoints in GKE.
I followed the steps which are mention in this doc but not able to successfully add SSL Certificate.

When I go in my cloud console I see

Some backend services are in UNKNOWN state

Here are my development yaml's

deployment.yaml

apiVersion: v1
kind: Service
metadata:
  name: quran-grpc
spec:
  ports:
  - port: 81
    targetPort: 9000
    protocol: TCP
    name: rpc
  - port: 80
    targetPort: 8080
    protocol: TCP
    name: http
  - port: 443
    protocol: TCP
    name: https
  selector:
    app: quran-grpc
  type: LoadBalancer
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: quran-grpc
spec:
  replicas: 1
  selector:
    matchLabels:
      app: quran-grpc
  template:
    metadata:
      labels:
        app: quran-grpc
    spec:
      volumes:
        - name: nginx-ssl
          secret:
            secretName: nginx-ssl
      containers:
      - name: esp
        image: gcr.io/endpoints-release/endpoints-runtime:1
        args: [
          "--http_port=8080",
          "--ssl_port=443",
          "--http2_port=9000",
          "--backend=grpc://127.0.0.1:50051",
          "--service=quran.endpoints.utopian-button-227405.cloud.goog",
          "--rollout_strategy=managed",
        ]
        ports:
          - containerPort: 9000
          - containerPort: 8080
          - containerPort: 443
        volumeMounts:
          - mountPath: /etc/nginx/ssl
            name: nginx-ssl
            readOnly: true
      - name: python-grpc-quran
        image: gcr.io/utopian-button-227405/python-grpc-quran:5.0
        ports:
          - containerPort: 50051

ssl-cert.yaml

apiVersion: networking.gke.io/v1beta1
kind: ManagedCertificate
metadata:
  name: quran-ssl
spec:
  domains:
    - quran.endpoints.utopian-button-227405.cloud.goog
---
apiVersion: v1
kind: Service
metadata:
  name: quran-ingress-svc
spec:
  selector:
    name: quran-ingress-svc
  type: NodePort
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: quran-ingress
  annotations:
    kubernetes.io/ingress.global-static-ip-name: 34.71.56.199
    networking.gke.io/managed-certificates: quran-ssl
spec:
  backend:
    serviceName: quran-ingress-svc
    servicePort: 80

Can you please let me know what I'm doing wrong.

Upvotes: 2

Views: 2903

Answers (1)

Mr.KoopaKiller
Mr.KoopaKiller

Reputation: 4002

Your SSL configuration is working fine, and the reason you are receiving this error is because you are using a self-signed certificate.

A self-signed certificate is a certificate that is not signed by a certificate authority (CA). These certificates are easy to make and do not cost money. However, they do not provide all of the security properties that certificates signed by a CA aim to provide. For instance, when a website owner uses a self-signed certificate to provide HTTPS services, people who visit that website will see a warning in their browser.

To solve this issue you should buy a valid certificate from a trusted CA, or use Let's Encrypt that will give a certificated valid for 90 days, and after this period you can renew this certificate.

If you decide to buy a SSL certificate, you can follow the document you describe to create a Kubernetes secret and use in your ingress, simple as that.

But if you don't want to buy a certificate, you could install cert-manager in your cluster, it will help you to generate valid certificates using Let's Encrypt.

Here is an example of how to use cert-manager + Let's Encrypt solution to generate valid SSL certificates:

Using cert-manager with Let's Encrypt

cert-manager builds on top of Kubernetes, introducing certificate authorities and certificates as first-class resource types in the Kubernetes API. This makes it possible to provide 'certificates as a service' to developers working within your Kubernetes cluster.

Let's Encrypt is a non-profit certificate authority run by Internet Security Research Group that provides X.509 certificates for Transport Layer Security encryption at no charge. The certificate is valid for 90 days, during which renewal can take place at any time. I'm supossing you already have NGINX ingress installed and working.

Pre-requisites: - NGINX Ingress installed and working - HELM 3.0 installed and working

cert-manager install

Note: When running on GKE (Google Kubernetes Engine), you may encounter a ‘permission denied’ error when creating some of these resources. This is a nuance of the way GKE handles RBAC and IAM permissions, and as such you should ‘elevate’ your own privileges to that of a ‘cluster-admin’ before running the above command. If you have already run the above command, you should run them again after elevating your permissions:

Follow the official docs to install, or just use HELM 3.0 with the followe command:

$ kubectl create namespace cert-manager
$ helm repo add jetstack https://charts.jetstack.io
$ helm repo update
$ kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v0.14.1/cert-manager-legacy.crds.yaml

Create CLusterIssuer for Let's Encrypt: Save the content below in a new file called letsencrypt-production.yaml:

Note: Replace <EMAIL-ADDRESS> with your valid email.

apiVersion: certmanager.k8s.io/v1alpha1
kind: ClusterIssuer
metadata:
  labels:
    name: letsencrypt-prod
  name: letsencrypt-prod
spec:
  acme:
    email: <EMAIL-ADDRESS>
    http01: {}
    privateKeySecretRef:
      name: letsencrypt-prod
    server: 'https://acme-v02.api.letsencrypt.org/directory'

Apply the configuration with:

kubectl apply -f letsencrypt-production.yaml

Install cert-manager with Let's Encrypt as a default CA:

helm install cert-manager \
--namespace cert-manager --version v0.8.1 jetstack/cert-manager \
--set ingressShim.defaultIssuerName=letsencrypt-prod \
--set ingressShim.defaultIssuerKind=ClusterIssuer
Verify the installation:
$ kubectl get pods --namespace cert-manager

NAME                                       READY   STATUS    RESTARTS   AGE
cert-manager-5c6866597-zw7kh               1/1     Running   0          2m
cert-manager-cainjector-577f6d9fd7-tr77l   1/1     Running   0          2m
cert-manager-webhook-787858fcdb-nlzsq      1/1     Running   0          2m

Using cert-manager

Apply this annotation in you ingress spec:

cert-manager.io/cluster-issuer: "letsencrypt-prod"

After apply cert-manager will generate the tls certificate fot the domain configured in Host: like this:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-app
  namespace: default
  annotations:
    kubernetes.io/ingress.class: nginx
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
  rules:
  - host: myapp.domain.com
    http:
      paths:
      - path: "/"
        backend:
          serviceName: my-app
          servicePort: 80

Upvotes: 1

Related Questions