Mastering Certificate Challenges with Ease
By Amrutha Paladugu
Author LinkedIn: https://www.linkedin.com/in/amrutha-paladugu/
Introduction:
Kong Hybrid mode represents a groundbreaking approach to API management, merging the control plane (CP) and data plane (DP) capabilities. This mode offers many benefits that empower organizations to achieve enhanced control, security, and performance in their API ecosystem. In this article, we’ll delve into a real-world scenario showcasing the capabilities of Kong Hybrid mode. Specifically, we’ll explore the deployment of Kong Hybrid across Google Kubernetes Engine (GKE) and an On-Premise Kubernetes cluster. We will focus on achieving secure communication, certificate management, workload deployment, and external access. Join us as we navigate this journey through a hybrid API management deployment.
Kong Hybrid architecture with one DP on the cloud and one DP on-premise.
Understanding Certificates:
Mutual Transport Layer Security (mTLS) plays a vital role in Kong’s security features by facilitating secure communication between services. When operating in hybrid mode, the authentication process relies on an mTLS handshake to ensure that communication between CP and DP nodes remains secure, requiring the presentation of certificates. Kong manages certificate key pairs in two distinct modes: Shared and PKI.
In the Shared mode (the default setting), Kong CLI generates a certificate/key pair, and copies of this pair are then distributed across nodes. CP and DP nodes share and utilize this certificate/key pair.
On the other hand, in the PKI mode, certificates signed by a central certificate authority (CA) are provided. Kong performs validation on both ends by verifying if they originate from the same CA. This approach effectively mitigates the risks associated with the transportation of private keys and provides increased security. If one of the DP nodes is compromised, an attacker won’t be able to affect other nodes in the Kong cluster.
In this article, we will use PKI mode and generate three different cert/key pairs for CP and the 2 DPs. All three pairs need to be signed by the same CA discussed above.
Additionally, we will provision a Let’s Encrypt certificate for DP1’s public-facing endpoint and verify encrypted traffic.
Certificate generation:
Step1: Generate CA cert using OpenSSL:
openssl genrsa -out ca.key 4096 openssl req -x509 -new -nodes -key ca.key -sha256 -days 365 -out ca.crt
Step2: Generate private key and CSR(certificate signing request) for CP and DPs
openssl req -new -newkey rsa:2048 -nodes -keyout cp-tls.key -out cp-tls.csr -subj "/CN=*.kong.example.com" openssl req -new -newkey rsa:2048 -nodes -keyout dp1-tls.key -out dp1-tls.csr -subj "/CN=*.kong.example.com" openssl req -new -newkey rsa:2048 -nodes -keyout dp2-tls.key -out dp2-tls.csr -subj "/CN=*.127.0.0.1.nip.io"
The CN (Common Name) here would be your wildcard domain.
Step3: Use CA from Step1 to sign the generated CSRs from Step2
openssl x509 -req -in cp-tls.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out cp-tls.crt -days 365 openssl x509 -req -in dp1-tls.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out dp1-tls.crt -days 365 openssl x509 -req -in dp2-tls.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out dp2-tls.crt -days 365
Step4: Create bundle certs:
cat cp-tls.crt ca.crt > cp-tls-bundle.crt cat dp1-tls.crt ca.crt > dp1-tls-bundle.crt cat dp2-tls.crt ca.crt > dp2-tls-bundle.crt
Note: Save these certificates in an accessible directory (certs) for the CP and the DPs.
Install CP and DP1 on GKE:
Connect to a GKE cluster and use the next set of commands to install CP and DP1.
Create ns, Create secrets, update helm repo:
sudo snap install helm - classic helm repo add kong https://charts.konghq.com helm repo update kubectl create namespace kong-cp kubectl create namespace kong-dp1
Create secrets for Kong Enterprise license, Session Config, Admin password, and Postgresql password:
kubectl create secret generic kong-enterprise-license -n kong-cp \ - from-file=license=license.json \ - dry-run=client -o yaml | kubectl apply -f - kubectl create secret generic kong-session-config -n kong-cp \ - from-literal=portal_session_conf='{"storage":"kong","secret":"super_secret_salt_string","cookie_name":"portal_session","cookie_samesite":"off","cookie_secure":false, "cookie_domain": ".example.com"}' \ - from-literal=admin_gui_session_conf='{"cookie_name":"admin_session","cookie_samesite":"off","secret":"super_secret_salt_string","cookie_secure":false,"storage":"kong", "cookie_domain": ".example.com"}' kubectl create secret generic kong-manager-password -n kong-cp \ - from-literal=password=password kubectl create secret generic kong-cp-postgresql -n kong-cp \ - from-literal=host="enterprise-postgresql.kong.svc.cluster.local" \ - from-literal=password=password
Note: If you don’t have access to an Enterprise license, you can still go ahead and try the installation but will not be able to access the Admin GUI.
Now, create Kubernetes Secrets for the cluster cert and CA cert for ns kong-cp.
kubectl create secret tls kong-cluster-cert -n kong-cp \ - cert=./certs/cp-tls-bundle.crt \ - key=./certs/cp-tls.key kubectl create secret generic kong-ca-cert -n kong-cp \ - from-file=ca.crt=./certs/ca.crt
We use Helm to install the CP and DPs and use custom values.yaml files.
Update the values-cp.yaml with the below values:
image: repository: kong/kong-gateway tag: "3.4" secretVolumes: - kong-cluster-cert - kong-ca-cert env: role: control_plane cluster_mtls: pki cluster_ca_cert: /etc/secrets/kong-ca-cert/ca.crt cluster_cert: /etc/secrets/kong-cluster-cert/tls.crt cluster_cert_key: /etc/secrets/kong-cluster-cert/tls.key nginx_http_ssl_protocols: TLSv1.2 admin_gui_ssl_cert: /etc/secrets/kong-cluster-cert/tls.crt admin_gui_ssl_cert_key: /etc/secrets/kong-cluster-cert/tls.key admin_ssl_cert: /etc/secrets/kong-cluster-cert/tls.crt admin_ssl_cert_key: /etc/secrets/kong-cluster-cert/tls.key portal_gui_ssl_cert: /etc/secrets/kong-cluster-cert/tls.crt portal_gui_ssl_cert_key: /etc/secrets/kong-cluster-cert/tls.key portal_api_ssl_cert: /etc/secrets/kong-cluster-cert/tls.crt portal_api_ssl_cert_key: /etc/secrets/kong-cluster-cert/tls.key lua_ssl_verify_depth: 3 admin_api_uri: https://admin.kong.example.com admin_gui_url: https://manager.kong.example.com portal_auth: basic-auth portal_api_url: https://portal-api.kong.example.com portal_gui_url: https://portal-dev.kong.example.com portal_gui_host: portal-dev.kong.example.com portal_gui_protocol: https database: postgres pg_host: kong-cp-postgresql pg_database: kong pg_user: postgres pg_schema: kong pg_password: valueFrom: secretKeyRef: name: kong-cp-postgresql key: password portal_session_conf: valueFrom: secretKeyRef: name: kong-session-config key: portal_session_conf user: kong password: valueFrom: secretKeyRef: name: kong-manager-password key: password admin: enabled: true type: ClusterIP annotations: konghq.com/protocol: https labels: {} http: enabled: false tls: enabled: true servicePort: 443 containerPort: 8444 parameters: - http2 ingress: annotations: konghq.com/https-redirect-status-code: "301" nginx.ingress.kubernetes.io/backend-protocol: HTTPS enabled: true ingressClassName: kong-dev hostname: admin.kong.example.com path: / tls: kong-cluster-cert manager: enabled: true type: ClusterIP annotations: konghq.com/protocol: https labels: {} http: enabled: false tls: enabled: true servicePort: 443 containerPort: 8445 parameters: - http2 ingress: annotations: konghq.com/https-redirect-status-code: "301" nginx.ingress.kubernetes.io/backend-protocol: HTTPS enabled: true ingressClassName: kong-dev hostname: manager.kong.example.com path: / tls: kong-cluster-cert cluster: enabled: true type: LoadBalancer annotations: {} http: enabled: false tls: enabled: true servicePort: 443 containerPort: 8005 ingress: annotations: konghq.com/https-redirect-status-code: "301" nginx.ingress.kubernetes.io/backend-protocol: HTTPS enabled: true ingressClassName: kong-dev hostname: cp.kong.example.com path: / tls: kong-cluster-cert clustertelemetry: enabled: true type: LoadBalancer http: enabled: false tls: enabled: true servicePort: 443 containerPort: 8006 ingress: annotations: konghq.com/https-redirect-status-code: "301" nginx.ingress.kubernetes.io/backend-protocol: HTTPS enabled: true ingressClassName: kong-dev hostname: tel.kong.example.com path: / tls: kong-cluster-cert proxy: enabled: false ingressController: enabled: true ingressClass: kong-dev resources: limits: cpu: 200m memory: 256Mi requests: cpu: 100m memory: 128Mi installCRDs: false env: publish_service: kong-dp/kong-dp-kong-proxy kong_admin_token: valueFrom: secretKeyRef: name: kong-manager-password key: password enterprise: enabled: true license_secret: kong-enterprise-license # CHANGEME vitals: enabled: false rbac: enabled: true session_conf_secret: kong-session-config admin_api_auth: basic-auth portal: enabled: true smtp: enabled: false portal: enabled: true type: ClusterIP annotations: konghq.com/protocol: https labels: {} http: enabled: false tls: enabled: true servicePort: 443 containerPort: 8446 ingress: annotations: konghq.com/https-redirect-status-code: "301" nginx.ingress.kubernetes.io/backend-protocol: HTTPS enabled: true ingressClassName: kong-dev hostname: portal-dev.kong.example.com path: / tls: kong-cluster-cert portalapi: enabled: true type: ClusterIP annotations: konghq.com/protocol: https labels: {} http: enabled: false tls: enabled: true servicePort: 443 containerPort: 8447 ingress: annotations: konghq.com/https-redirect-status-code: "301" nginx.ingress.kubernetes.io/backend-protocol: HTTPS enabled: true ingressClassName: kong-dev hostname: portal-api.kong.example.com path: / tls: kong-cluster-cert postgresql: enabled: true auth: database: kong username: postgres existingSecret: kong-cp-postgresql secretKeys: adminPasswordKey: password
Let’s try and understand the above values file:
The secrets we created, kong-cluster-cert and kong-ca-cert are mounted as volumes for the SSL certificates and are accessed at the specified path, for example:
cluster_ca_cert: /etc/secrets/kong-ca-cert/ca.crt
The environment variables are for configuring Kong and its components. They control settings related to SSL/TLS, database connections, authentication, and more. Also, they specify the role as “control_plane” and enable cluster mutual TLS (mTLS) using the PKI method. The admin API and GUI URLs, authentication methods, and other configuration parameters are also defined using the env variables.
Admin, Manager, Portal, Portal API, and PostgreSQL:
- These sections configure various components of Kong. All these components are enabled for the CP and would be disabled in the DP values yaml. Their type ( ClusterIP), TLS, and Ingress settings are also defined, including annotations, hostnames, paths, and TLS certificates for these components.
- PostgreSQL settings specify authentication details for connecting to the PostgreSQL database used by Kong.
- Enterprise-related settings include the license secret, RBAC configuration, SMTP, and vitals.
Proxy and Ingress Controller:
- The proxy section specifies whether the Kong proxy is enabled. For CP values, this would be disabled as the DP does all the proxying.
- Ingress Controller settings define the resources and environment variables for the Kong Ingress Controller.
Cluster and Cluster Telemetry:
- Cluster and cluster telemetry are essential for Kong Gateway’s Control Plane (CP) and Data Plane (DP) connection. DP instances connect to the CP through the CP cluster, which provides redundancy, load balancing, and configuration synchronization.
- Cluster telemetry plays a crucial role in monitoring the health of both CP and DP components, ensuring they can work together effectively and respond to changes and issues in real time. This setup provides a reliable and resilient CP-DP connection in Kong Gateway deployments.
Install the CP:
helm upgrade - install kong-cp kong/kong - namespace kong-cp -f values-cp.yaml
Once the CP is installed, verify that all pods are running and the Cluster and Clusterterlemetry services’ external LoadBalancer IPs are ready.
To install DP in the same cluster, follow the steps below and create license and certificate secrets for DP1.
kubectl create secret generic kong-enterprise-license -n kong-dp1 \ --from-file=license=license.json \ --dry-run=client -o yaml | kubectl apply -f - kubectl create secret tls kong-cluster-cert -n kong-dp1 \ - cert=./certs/dp1-tls-bundle.crt \ - key=./certs/dp1-tls.key kubectl create secret generic kong-ca-cert -n kong-dp1 \ - from-file=ca.crt=./certs/ca.crt
To encrypt the oneway traffic to the public-facing end point of DP1, we use Let’s Encrypt CA. Use the below link to generate one for the domain you use.
SSL Certificate Generator: Free letsencrypt SSL in minutes:
A free SSL Certificate Generator. No login is required. Secure your site with a letsencrypt certificate. Includes a…
punchsalad.com
Create a secret for this cert in the kong-dp1 namespace:
kubectl create secret tls kong-tls-cert -n kong-dp1 \ - cert=./letsencrypt/ca.crt \ - key=./letsencrypt/ca.key Create a values-dp1.yaml file with the below values: image: repository: kong/kong-gateway tag: "3.4" secretVolumes: - kong-cluster-cert - kong-ca-cert - kong-tls-cert env: role: data_plane database: "off" status_listen: 0.0.0.0:8100 cluster_control_plane: cp.kong.example.com:443 cluster_telemetry_endpoint: tel.kong.example.com:443 cluster_mtls: pki cluster_server_name: cp.kong.example.com cluster_telemetry_server_name: tel.kong.example.com lua_ssl_verify_depth: 3 cluster_ca_cert: /etc/secrets/kong-ca-cert/ca.crt lua_ssl_trusted_certificate: /etc/secrets/kong-cluster-cert/tls.crt cluster_cert: /etc/secrets/kong-cluster-cert/tls.crt cluster_cert_key: /etc/secrets/kong-cluster-cert/tls.key ssl_cert: /etc/secrets/kong-tls-cert/tls.crt ssl_cert_key: /etc/secrets/kong-tls-cert/tls.key ingressController: enabled: false enterprise: enabled: true license_secret: kong-enterprise-license vitals: enabled: false portal: enabled: false rbac: enabled: false admin: enabled: false manager: enabled: false portal: enabled: false portalapi: enabled: false proxy: enabled: true type: LoadBalancer annotations: {} tls: enabled: true servicePort: 443 containerPort: 8443 parameters: - http2 # stream: {} ingress: enabled: true
Please take note of the key differences here from the earlier values-cp yaml. All the Manager, Admin, Portal, Portalapi, and IngressController sections are disabled, while the Proxy section is enabled as type LoadBalancer. As explained earlier, ensuring the correct configuration of cluster and cluster telemetry endpoints is crucial.
Another point worth mentioning is the secret volume for the Let’s Encrypt certificate:kong-tls-cert. This is accessed through the below variables:
ssl_cert: /etc/secrets/kong-tls-cert/tls.crt
ssl_cert_key: /etc/secrets/kong-tls-cert/tls.key
Install DP1:
helm upgrade --install kong-dp1 kong/kong --namespace kong-dp1 -f values-dp1.yaml
Note the LoadBalancer IPs for the Cluster and Clustertelemetry service in the CP and the Proxy service in the DP. Map these values to the domain you intend to use. In our scenario, it would be as follows:
cp.kong.example.com - - - - - - - > 34.136.32.39 cp-tel.kong.example.com - - - - >34.68.58.255 *.kong.example.com - - - - - - - - >34.132.64.159
You should now be able to access Kong Manager (in case you are using an Enterprise license) at manager.kong.example.com, but the browser won’t recognize the OpenSSL CA, and hence it will appear as NotSecure as shown in the below image.
Access Admi GUI and view certificate (Not Secure- openSSL)
Deploy a sample application:
Let’s deploy a sample nodeJS application in the same GKE cluster in the default namespace, try accessing it through the DP endpoint, and see if the Let’s Encrypt certificate is served.
kubectl create deploy --image debianmaster/nodejs-welcome welcome kubectl expose deployment welcome --type=LoadBalancer --name=welcome --port=8080 --target-port=8080
Deploying a sample nodeJS ‘welcome’ application
Add a service and a route to this application through the Kong manager.
Now, the workload can be accessed through dp1.kong.example.com/welcome. Click on the lock icon🔒present right before the URL and view the certificate. You will notice that the Let’s Encrypt certificate is being served, as shown in the below image.
Access the workload through the DP endpoint and verify the Let’s Encrypt cert.
Install DP2 on local K3s:\
Connect to a local K3s (lightweight Kubernetes) cluster and install the following command set to install DP2.
Create namespace for DP2
kubectl create ns kong-dp2
Create secrets for enterprise licenses and certificates:
kubectl create secret generic kong-enterprise-license - from-file=license=./license.json -n kong-dp2 - dry-run=client -o yaml | kubectl apply -f - kubectl create secret tls kong-cluster-cert -n kong-dp2 \ - cert=./certs/dp2-tls-bundle.crt \ - key=./certs/dp2-tls.key kubectl create secret generic kong-ca-cert -n kong-dp2 \ - from-file=ca.crt=./certs/ca.crt
Create a values-dp2.yaml file with the below values:
image: repository: kong/kong-gateway tag: "3.4" secretVolumes: - kong-cluster-cert - kong-ca-cert env: role: data_plane cluster_control_plane: cp.kong.example.com:443 cluster_telemetry_endpoint: tel.kong.example.com:443 lua_ssl_trusted_certificate: /etc/secrets/kong-cluster-cert/tls.crt cluster_mtls: pki cluster_server_name: cp.kong.example.com cluster_telemetry_server_name: tel.kong.example.com cluster_ca_cert: /etc/secrets/kong-ca-cert/ca.crt cluster_cert: /etc/secrets/kong-cluster-cert/tls.crt cluster_cert_key: /etc/secrets/kong-cluster-cert/tls.key database: "off" audit_log: "on" headers: "off" anonymous_reports: "off" untrusted_lua: "off" enterprise: enabled: true license_secret: kong-enterprise-license vitals: enabled: false portal: enabled: false rbac: enabled: false admin: enabled: false manager: enabled: false portal: enabled: false portalapi: enabled: false ingressController: enabled: false proxy: enabled: true type: LoadBalancer annotations: { konghq.com/protocol: "https" } tls: enabled: true servicePort: 443 containerPort: 8443 parameters: - http2 ingress: enabled: true Install DP2 helm upgrade - install kong-dp2 kong/kong - namespace kong-dp2 -f values-dp2.yaml
Deploy a sample application in the K3s cluster:
Let’s deploy a sample nodeJS application in the same K3s cluster in the default namespace and try to access it through the DP2 endpoint and verify.
kubectl create deploy --image debianmaster/nodejs-welcome hello kubectl expose deployment hello --type=LoadBalancer --name=hello --port=8080 --target-port=8080
Verify deployment of nodeJS ‘hello’ application.
Add a service and a route to this application through the Kong manager.
Now the workload can be accessed through dp2.127.0.0.1.nip.io/hello
Throughout this article, we embarked on a journey to uncover the transformative power of Kong Hybrid mode within API management. By harmonizing the control plane (CP) and data plane (DP), Kong Hybrid empowers organizations to balance control, security, and performance seamlessly. Through a real-world scenario, we showcased the deployment of Kong Hybrid across Google Kubernetes Engine (GKE) and an On-Premise Kubernetes cluster.
We navigated the intricate landscape of certificate management, emphasizing the pivotal role of Mutual Transport Layer Security (mTLS) and certificates in fortifying Kong’s security architecture. By embracing PKI mode, we ensured secure communication and mitigated the risks inherent in key transportation.
By following our straightforward, step-by-step instructions, we achieved successful deployments of Kong CP and DP1 within the GKE cluster, followed by Kong DP2 in an On-Premise K3s cluster. We highlighted the deployment of sample applications, demonstrated access through DP endpoints, and verified Let’s Encrypt certificates, reinforcing the foundation of a robust and secure API ecosystem.
As we wrap up this journey, remember the importance of resource cleanup to prevent lingering costs. The world of Kong Hybrid mode introduces a revolutionary approach that bridges the gap between Cloud and On-Premise, enabling the creation of APIs that transcend traditional confines. With mastery of this approach, you’ll confidently and innovatively navigate the dynamic realm of modern API management.
For more details visit: [https://zelarsoft.com/kong-consulting-and-licensing/]
Top comments (0)