Skip to content

TLS for OpenFaaS

TLS for OpenFaaS

Transport Layer Security (TLS) is a cryptographic protocol that provides secure encryption on top of HTTP. It is required for any OpenFaaS gateway which is exposed to the Internet.

This guide explains how to obtain TLS certificates for the OpenFaaS Gateway running on Kubernetes. For faasd, see the instructions in the eBook.

  • Setup an Ingress Controller
  • Configure cert-manager to obtain a certificate from Let's Encrypt
  • Configure the an Ingress record for the OpenFaaS Gateway

Pre-requisites

  • A domain name under your control, and access to create A or CNAME records
  • A public IP address with NodePorts, a Load Balancer or a tunnel such as inlets
  • A Kubernetes cluster

Where you see example.com given in an example, replace that with your own domain name.

Make sure you can obtain public IP addresses

Managed Kubernetes services have a built-in LoadBalancer provisioner, which will provide a public IP address or CNAME for you, once you create a Service of type LoadBalancer.

If you're running self-managed Kubernetes, where each node has its own Public IP address, then you can configure your Ingress Controller to use a NodePort mapped to port 80 and 443 on the host.

If you are running on a local or private network, you can use inlets-operator instead, which provisions a VM and uses its public IP address over a websocket tunnel.

Set up an Ingress Controller

We recommend ingress-nginx for OpenFaaS, however any Ingress controller will work, or you can use Istio with separate instructions.

To install ingress-nginx, use either the Helm chart, or arkade:

$ arkade install ingress-nginx

See also: ingress-nginx installation

Install cert-manager

cert-manager is a Kubernetes operator maintained by the Cloud Native Computing Foundation (CNCF) which automates TLS certificate management.

To install cert-manager, use either the Helm chart, or arkade:

$ arkade install cert-manager

See also: cert-manager installation

Configure cert-manager

You'll need to create an Issuer or ClusterIssuer for your cert-manager installation. This will tell cert-manager which domain it is operating on, and how to register an account for you.

The below will create an Issuer that only operates in the openfaas namespace, with a HTTP01 challenge. Note the ingress class specified in the HTTP01 challenge, this should match the class of your Ingress controller. You can view ingress classes with kubectl get ingressclass.

export EMAIL="you@example.com"

cat > issuer.yaml <<EOF
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: letsencrypt-prod
  namespace: openfaas
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: $EMAIL
    privateKeySecretRef:
      name: letsencrypt
    solvers:
    - selector: {}
      http01:
        ingress:
          class: nginx
---
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: letsencrypt-staging
  namespace: openfaas
spec:
  acme:
    server: https://acme-staging-v02.api.letsencrypt.org/directory
    email: $EMAIL
    privateKeySecretRef:
      name: letsencrypt-staging
    solvers:
    - selector: {}
      http01:
        ingress:
          class: nginx
---

EOF

Apply the staging and production Issuers:

$ kubectl apply -f issuer.yaml

Create the required DNS records

You will need to create an A or CNAME record for your domain, pointing to the public IP address of your Ingress controller.

If you created the Ingress Controller with arkade, you'll see a new service in the default namespace called ingress-nginx-controller. You can find the public IP address with:

$ kubectl get svc -n default ingress-nginx-controller

NAME                       TYPE           CLUSTER-IP   EXTERNAL-IP     PORT(S)                      AGE
ingress-nginx-controller   LoadBalancer   10.43.87.4   18.136.136.18   80:31876/TCP,443:30108/TCP   28d

Take the IP address from the EXTERNAL-IP column and create an A record for your domain in your domain management software, or a CNAME record if you're using AWS EKS, and see a domain name in this field.

All users should create an entry for: gateway.example.com and then OpenFaaS dashboard users should create an additional record pointing at the same address for: dashboard.example.com.

Configure TLS for the OpenFaaS gateway

You can now configure the OpenFaaS gateway to use TLS by setting the following Helm values, you can save them in a file called tls.yaml:

export DOMAIN="gw.example.com"

cat > tls.yaml <<EOF
ingress:
  enabled: true
  ingressClassName: nginx
  annotations:
    cert-manager.io/issuer: letsencrypt-prod
  tls:
    - hosts:
        - $DOMAIN
      secretName: openfaas-gateway-cert
  hosts:
  - host: $DOMAIN
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: gateway
            port:
              number: 8080
EOF

If you're using something other than ingress-nginx, then change the ingressClassName field accordingly. Note that the kubernetes.io/ingress.class annotation is deprecated and should not be used.

The cert-manager.io/issuer annotation is used to pick between the staging and production Issuers for Let's Encrypt. If this is your first time working with cert-manager, you may want to use the staging issuer first to avoid running into rate limits if you have something misconfigured.

Now upgrade OpenFaaS via helm, use any custom values.yaml files that you have saved from a previous installation:

helm repo update && \
    helm upgrade --install openfaas openfaas/openfaas \
        --namespace openfaas \
        --values tls.yaml \
        --values values-custom.yaml

Configure TLS for the OpenFaaS dashboard

If you're using OpenFaaS Standard or OpenFaaS for Enterprises, you will probably want to create an additional Ingress record for the OpenFaaS dashboard.

Edit the previous example:

export DOMAIN="gw.example.com"
export DOMAIN_DASHBOARD="dashboard.example.com"

cat > tls.yaml <<EOF
ingress:
  enabled: true
  ingressClassName: nginx
  annotations:
    cert-manager.io/issuer: letsencrypt-prod
  tls:
    - hosts:
        - $DOMAIN
      secretName: openfaas-gateway-cert
    - hosts:
        - $DOMAIN_DASHBOARD
      secretName: openfaas-dashboard-cert
  hosts:
  - host: $DOMAIN
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: gateway
            port:
              number: 8080
  - host: $DOMAIN_DASHBOARD
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: dashboard
            port:
              number: 8080
EOF

As above, run the helm upgrade command to apply the changes.

Verifying the installation

First, check that the DNS records you created have taken effect. You can use nslookup or dig to check that the domain names resolve to the public address of your Ingress Controller's service.

$ nslookup gw.example.com

Next, verify that the Ingress records have the desired domains in the "HOSTS" field:

$ kubectl get ingress -n openfaas

Next, check that the certificates have been issued and that they're ready:

$ kubectl get certificates -n openfaas -o wide

If you're still encountering issues, you can check the logs of the cert-manager controller:

$ kubectl logs -n cert-manager deploy/cert-manager

Log into the OpenFaaS gateway using its new URL:

$ export OPENFAAS_URL=https://gw.example.com

$ PASSWORD=$(kubectl get secret -n openfaas basic-auth -o jsonpath="{.data.basic-auth-password}" | base64 --decode; echo)
$ echo -n $PASSWORD | faas-cli login --username admin --password-stdin

# List some functions:

$ faas-cli list

If you're using Identity and Access Management (IAM) for OpenFaaS, see the SSO instructions instead.