API Key Authentication

This task provides instructions for configuring API Key Authentication. API Key Authentication verifies whether an incoming request includes a valid API key in the header, parameter, or cookie before routing the request to a backend service.

Envoy Gateway introduces a new CRD called SecurityPolicy that allows the user to configure Api Key authentication. This instantiated resource can be linked to a Gateway, HTTPRoute or GRPCRoute resource.

Prerequisites

Follow the steps below to install Envoy Gateway and the example manifest. Before proceeding, you should be able to query the example backend using HTTP.

Expand for instructions
  1. Install the Gateway API CRDs and Envoy Gateway using Helm:

    helm install eg oci://docker.io/envoyproxy/gateway-helm --version v1.3.0 -n envoy-gateway-system --create-namespace
    
  2. Install the GatewayClass, Gateway, HTTPRoute and example app:

    kubectl apply -f https://github.com/envoyproxy/gateway/releases/download/v1.3.0/quickstart.yaml -n default
    
  3. Verify Connectivity:

    You can also test the same functionality by sending traffic to the External IP. To get the external IP of the Envoy service, run:

    export GATEWAY_HOST=$(kubectl get gateway/eg -o jsonpath='{.status.addresses[0].value}')
    

    Note: In certain environments, the load balancer may be exposed using a hostname, instead of an IP address. If so, replace ip in the above command with hostname.

    Curl the example app through Envoy proxy:

    curl --verbose --header "Host: www.example.com" http://$GATEWAY_HOST/get
    

    Get the name of the Envoy service created by the example Gateway:

    export ENVOY_SERVICE=$(kubectl get svc -n envoy-gateway-system --selector=gateway.envoyproxy.io/owning-gateway-namespace=default,gateway envoyproxy.io/owning-gateway-name=eg -o jsonpath='{.items[0].metadata.name}')
    

    Port forward to the Envoy service:

    kubectl -n envoy-gateway-system port-forward service/${ENVOY_SERVICE} 8888:80 &
    

    Curl the example app through Envoy proxy:

    curl --verbose --header "Host: www.example.com" http://localhost:8888/get
    

Configuration

API Key must be stored in a kubernetes secret and referenced in the SecurityPolicy configuration. The secret is an Opaque secret, with each API key stored under a key corresponding to the client ID.

Create a API Key Secret

Create an Opaque Secret containing the client ID and its corresponding API key

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Secret
type: Opaque
metadata:
  name: apikey-secret
stringData:
  client1: supersecret
EOF

Save and apply the following resource to your cluster:

---
apiVersion: v1
kind: Secret
type: Opaque
metadata:
  name: apikey-secret
stringData:
  client1: supersecret

Create a SecurityPolicy

The below example defines a SecurityPolicy that authenticates requests against the client list in the kubernetes secret created in the previous step.

cat <<EOF | kubectl apply -f -
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
  name: apikey-auth-example
spec:
  targetRefs:
    - group: gateway.networking.k8s.io
      kind: HTTPRoute
      name: backend
  apiKeyAuth:
    credentialRefs:
    - group: ""
      kind: Secret
      name: apikey-secret
    extractFrom:
    - headers:
      - x-api-key
EOF

Save and apply the following resource to your cluster:

---
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
  name: apikey-auth-example
spec:
  targetRefs:
    - group: gateway.networking.k8s.io
      kind: HTTPRoute
      name: backend
  apiKeyAuth:
    credentialRefs:
    - group: ""
      kind: Secret
      name: apikey-secret
    extractFrom:
    - headers:
      - x-api-key

Verify the SecurityPolicy configuration:

kubectl get securitypolicy/apikey-auth-example -o yaml

Testing

Ensure the GATEWAY_HOST environment variable from the Quickstart is set. If not, follow the Quickstart instructions to set the variable.

echo $GATEWAY_HOST

Send a request to the backend service without x-api-key header:

curl -kv -H "Host: www.example.com" "http://${GATEWAY_HOST}/" 

You should see 401 Unauthorized in the response, indicating that the request is not allowed without providing valid API Key in x-api-key header.

* Connected to 127.0.0.1 (127.0.0.1) port 80
...
> GET / HTTP/2
> Host: www.example.com
> User-Agent: curl/8.7.1
> Accept: */*
...
< HTTP/2 401
< content-length: 58
< content-type: text/plain
< date: Sun, 19 Jan 2025 12:55:39 GMT
<

* Connection #0 to host 127.0.0.1 left intact
Client authentication failed.

Send a request to the backend service with x-api-key header:

curl -v -H "Host: www.example.com" -H 'x-api-key: supersecret' "http://${GATEWAY_HOST}/" 

The request should be allowed and you should see the response from the backend service.

Clean-Up

Follow the steps from the Quickstart to uninstall Envoy Gateway and the example manifest.

Delete the SecurityPolicy and the secret

kubectl delete securitypolicy/apikey-auth-example
kubectl delete secret/apikey-secret

Next Steps

Checkout the Developer Guide to get involved in the project.