curl "$PROXY_IP/echo" \
--no-progress-meter --fail-with-body
You should see the following response:
No required TLS certificate was sent
Create a Secret containing a CA Certificate and pass the ID of the certificate to an mTLS plugin configuration.
If you don’t have a Konnect account, you can get started quickly with our onboarding wizard.
Set the personal access token as an environment variable:
export KONNECT_TOKEN='YOUR KONNECT TOKEN'
Install the Gateway API CRDs before installing Kong Ingress Controller.
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.3.0/standard-install.yaml
Create a Gateway and GatewayClass instance to use.
echo "
apiVersion: v1
kind: Namespace
metadata:
name: kong
---
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: kong
annotations:
konghq.com/gatewayclass-unmanaged: 'true'
spec:
controllerName: konghq.com/kic-gateway-controller
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: kong
spec:
gatewayClassName: kong
listeners:
- name: proxy
port: 80
protocol: HTTP
allowedRoutes:
namespaces:
from: All
" | kubectl apply -n kong -f -
Use the Konnect API to create a new CLUSTER_TYPE_K8S_INGRESS_CONTROLLER Control Plane:
CONTROL_PLANE_DETAILS=$(curl -X POST "https://us.api.konghq.com/v2/control-planes" \
--no-progress-meter --fail-with-body \
-H "Authorization: Bearer $KONNECT_TOKEN" \
--json '{
"name": "My KIC CP",
"cluster_type": "CLUSTER_TYPE_K8S_INGRESS_CONTROLLER"
}'
)
We’ll need the id and telemetry_endpoint for the values.yaml file later. Save them as environment variables:
CONTROL_PLANE_ID=$(echo $CONTROL_PLANE_DETAILS | jq -r .id)
CONTROL_PLANE_TELEMETRY=$(echo $CONTROL_PLANE_DETAILS | jq -r '.config.telemetry_endpoint | sub("https://";"")')
Kong Ingress Controller talks to Konnect over a connected secured with TLS certificates.
Generate a new certificate using openssl:
openssl req -new -x509 -nodes -newkey rsa:2048 -subj "/CN=kongdp/C=US" -keyout ./tls.key -out ./tls.crt
The certificate needs to be a single line string to send it to the Konnect API with curl. Use awk to format the certificate:
export CERT=$(awk 'NF {sub(/\r/, ""); printf "%s\\n",$0;}' tls.crt);
Next, upload the certificate to Konnect:
curl -X POST "https://us.api.konghq.com/v2/control-planes/$CONTROL_PLANE_ID/dp-client-certificates" \
--no-progress-meter --fail-with-body \
-H "Authorization: Bearer $KONNECT_TOKEN" \
--json '{
"cert": "'$CERT'"
}'
Finally, store the certificate in a Kubernetes secret so that Kong Ingress Controller can read it:
kubectl create namespace kong -o yaml --dry-run=client | kubectl apply -f -
kubectl create secret tls konnect-client-tls -n kong --cert=./tls.crt --key=./tls.key
Add the Kong Helm charts:
helm repo add kong https://charts.konghq.com
helm repo update
Create a values.yaml file:
cat <<EOF > values.yaml
controller:
ingressController:
image:
tag: "3.5"
env:
feature_gates: "FillIDs=true"
konnect:
license:
enabled: true
enabled: true
controlPlaneID: "$CONTROL_PLANE_ID"
tlsClientCertSecretName: konnect-client-tls
apiHostname: "us.kic.api.konghq.com"
gateway:
image:
repository: kong/kong-gateway
tag: "3.13"
env:
konnect_mode: 'on'
vitals: "off"
cluster_mtls: pki
cluster_telemetry_endpoint: "$CONTROL_PLANE_TELEMETRY:443"
cluster_telemetry_server_name: "$CONTROL_PLANE_TELEMETRY"
cluster_cert: /etc/secrets/konnect-client-tls/tls.crt
cluster_cert_key: /etc/secrets/konnect-client-tls/tls.key
lua_ssl_trusted_certificate: system
proxy_access_log: "off"
dns_stale_ttl: "3600"
secretVolumes:
- konnect-client-tls
EOF
Install Kong Ingress Controller using Helm:
helm install kong kong/ingress -n kong --create-namespace --values ./values.yaml
Set $PROXY_IP as an environment variable for future commands:
export PROXY_IP=$(kubectl get svc --namespace kong kong-gateway-proxy -o jsonpath='{range .status.loadBalancer.ingress[0]}{@.ip}{@.hostname}{end}')
echo $PROXY_IP
Add the Kong Helm charts:
helm repo add kong https://charts.konghq.com
helm repo update
Create a file named license.json containing your Kong Gateway Enterprise license and store it in a Kubernetes secret:
kubectl create namespace kong --dry-run=client -o yaml | kubectl apply -f -
kubectl create secret generic kong-enterprise-license --from-file=license=./license.json -n kong
Create a values.yaml file:
cat <<EOF > values.yaml
gateway:
image:
repository: kong/kong-gateway
tag: "3.13"
env:
LICENSE_DATA:
valueFrom:
secretKeyRef:
name: kong-enterprise-license
key: license
EOF
Install Kong Ingress Controller using Helm:
helm install kong kong/ingress -n kong --create-namespace --values ./values.yaml
Set $PROXY_IP as an environment variable for future commands:
export PROXY_IP=$(kubectl get svc --namespace kong kong-gateway-proxy -o jsonpath='{range .status.loadBalancer.ingress[0]}{@.ip}{@.hostname}{end}')
echo $PROXY_IP
This how-to requires some Kubernetes services to be available in your cluster. These services will be used by the resources created in this how-to.
kubectl apply -f https://developer.konghq.com/manifests/kic/echo-service.yaml -n kong
This how-to also requires 1 pre-configured route:
Mutual TLS (mTLS) is a way to secure connectivity using certificates. Kong Gateway can look for a certificate in incoming requests and reject the request if the public key presented does not match the private key stored in Kong Gateway.
To use the mtls-auth plugin you need a CA certificate. If you don’t have one, generate a new certificate using openssl:
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -sha256 -days 365 -nodes \
-subj "/C=US/ST=California/L=San Francisco/O=Kong/OU=Org/CN=www.example.com"
CA Certificates in Kong Gateway are provisioned by creating a Secret or ConfigMap resource in Kubernetes.
Resources holding CA certificates must have the following properties:
konghq.com/ca-cert: "true" label appliedcert or ca.crt data property which contains a valid CA certificate in PEM formatkubernetes.io/ingress.class annotation whose value matches the value of the controller’s --ingress-class argument. By default, that value is kong.id data property which contains a random UUIDEach CA Certificate that you create needs a unique ID. Any random UUID should suffice here, and it doesn’t have a security implication. You can use uuidgen (Linux, macOS) or New-Guid (Windows) to generate an ID.
CERT_ID=$(uuidgen | tr "[:upper:]" "[:lower:]")
kubectl create secret -n kong generic my-ca-cert --from-literal=id=$CERT_ID --from-file=cert=./cert.pem
kubectl label secret -n kong my-ca-cert 'konghq.com/ca-cert=true'
kubectl annotate secret -n kong my-ca-cert 'kubernetes.io/ingress.class=kong'
The mtls-auth plugin requires a CA Certificate ID that will be used to validate the Certificate in the incoming request. In this example we disable revocation checks, but you should enable checks in a production setting.
echo "
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: mtls-auth
namespace: kong
annotations:
kubernetes.io/ingress.class: kong
config:
ca_certificates:
- '$CERT_ID'
skip_consumer_lookup: true
revocation_check_mode: SKIP
plugin: mtls-auth
" | kubectl apply -f -
Next, apply the KongPlugin resource by annotating the service resource:
kubectl annotate -n kong service echo konghq.com/plugins=mtls-auth
At this point, Kong Gateway will reject requests that do not contain a client certificate.
Send a request to check Kong Gateway prompts for a client certificate:
curl "$PROXY_IP/echo" \
--no-progress-meter --fail-with-body
You should see the following response:
No required TLS certificate was sent
curl "$PROXY_IP/echo" \
--no-progress-meter --fail-with-body
You should see the following response:
No required TLS certificate was sent
As you can see, Kong Gateway is restricting the request because it doesn’t have the necessary authentication information.
Two things to note here:
-k is used because Kong Gateway is set up to serve a self-signed certificate by default. For full mutual authentication in production use cases, you must configure Kong Gateway to serve a Certificate that is signed by a trusted CA.$PROXY_IP might contain a port that points to http port of Kong Gateway. In others, it might contain a DNS name instead of an IP address. If needed, update the command to send an https request to the https port of Kong Gateway or the load balancer in front of it.Use the key and Certificate to authenticate against Kong Gateway and use the Service:
curl -k --key key.pem --cert cert.pem "https://$PROXY_IP/echo" \
--no-progress-meter --fail-with-body
curl -k --key key.pem --cert cert.pem "https://$PROXY_IP/echo" \
--no-progress-meter --fail-with-body
The results should look like this:
HTTP/2 200
content-type: text/plain; charset=UTF-8
server: echoserver
x-kong-upstream-latency: 1
x-kong-proxy-latency: 1
via: kong/x.y.z
kubectl delete -n kong -f https://developer.konghq.com/manifests/kic/echo-service.yaml
helm uninstall kong -n kong