Custom Auth

While Gloo provides an auth server that covers your OpenID Connect and Basic Auth use cases, it also allows your to use your own authetication server, to implement custom auth logic.

In this guide we will demonstrate your to create and configure gloo to use your own auth service. For simplicity we will use an http service. Though this guide will work (with minor adjuestments) also work with a gRPC server that implements the Envoy spec for an external authorization server.

Let’s get right to it!

Deploy Gloo and the petstore demo app

Install Gloo-enterprise (version v0.13.5 or above) and the petstore demo:

glooctl install gateway --license-key <YOUR KEY>
kubectl apply -f https://raw.githubusercontent.com/solo-io/gloo/master/example/petstore/petstore.yaml

Add a route and test that everything so far works:

glooctl add route --name default --namespace gloo-system --path-prefix / --dest-name default-petstore-8080 --dest-namespace gloo-system
URL=$(glooctl proxy url)
curl $URL/api/pets/
[{"id":1,"name":"Dog","status":"available"},{"id":2,"name":"Cat","status":"pending"}]

HTTP Authentication service intro

When using an HTTP auth service, the request will be forwarded to the authentication service. If the auth service returns 200 OK it is considered authorized. Otherwise the request is denied. You can fine tune which headers are sent to the the auth service, and wether or not the body is forwarded as well, by editting the extauth extension settings in the Gloo settings (see below for an example of the Gloo settings with the extension settings).

For reference, here’s the code for the auhtorization server used in this tutorial:

import http.server
import socketserver

class Server(http.server.SimpleHTTPRequestHandler):
    def do_GET(self):
        path = self.path
        print("path", path)
        if path.startswith("/api/pets/1"):
            self.send_response(200, 'OK')
        else:
            self.send_response(401, 'Not authorized')
        self.send_header('x-server', 'pythonauth')
        self.end_headers()

def serve_forever(port):
    socketserver.TCPServer(('', port), Server).serve_forever()

if __name__ == "__main__":
    serve_forever(8000)

As you can see, this service will allow requests to /api/pets/1 and will deny everything else.

You can easily change the sample auth server. When using minikube, download the Dockerfile and the server code and just run:

eval $(minikube docker-env)
docker build -t quay.io/solo-io/sample-auth .
kubectl delete pod -n gloo-system -l app=sample-auth

Deploy auth service

To add this service to your cluster, download the auth-service yaml and apply it:

kubectl apply -f auth-service.yaml

This file contains the deployment, service and upstream definitions.

Configure Gloo to use your server

Configure Gloo settings

Edit the gloo settings (kubectl edit settings -n gloo-system default) to point to your auth server. settings should look like this:

apiVersion: gloo.solo.io/v1
kind: Settings
metadata:
  name: default
  namespace: gloo-system
spec:
  bindAddr: 0.0.0.0:9977
  discoveryNamespace: gloo-system
  extensions:
    configs:
      extauth:
        extauthzServerRef:
          name: auth-server
          namespace: gloo-system
        httpService: {}
        requestBody:
          maxRequestBytes: 10240
        requestTimeout: 0.5s
      rate-limit:
        ratelimit_server_ref:
          name: rate-limit
          namespace: gloo-system
  kubernetesArtifactSource: {}
  kubernetesConfigSource: {}
  kubernetesSecretSource: {}
  refreshRate: 60s

When using a gRPC auth service, remove the httpService: {} line from the config above.

This configuration also sets other configuraiton parameters:

  • requestBody - When set to, the request body will also be sent to the auth service. with this configuration, a body up to 10KB will be buffered and sent to the auth-service. This is useful in use cases where the auth service needs to compute an HMAC on the body.
  • requestTimeout - A timeout for the auth service response. If the service takes longer to response, the request will be denied.

Configure the VirtualService

Edit the VirtualService (kubectl edit virtualservice -n gloo-system default), and mark it with custom auth to turn authentication on. The VirtualService should look like this:

apiVersion: gateway.solo.io/v1
kind: VirtualService
metadata:
  name: default
  namespace: gloo-system
spec:
  virtualHost:
    domains:
    - '*'
    virtualHostPlugins:
      extensions:
        configs:
          extauth:
            customAuth: {}
    routes:
    - matcher:
        prefix: /
      routeAction:
        single:
          upstream:
            name: default-petstore-8080
            namespace: gloo-system

To make it easy, if you have followed this guide verbatim, you can just download and apply this manifest to update both Settings and VirtualService.

Test

We are all set to test!

curl -w "%{http_code}\n"  $URL/api/pets/1
{"id":1,"name":"Dog","status":"available"}
200

curl -w "%{http_code}\n"  $URL/api/pets/2 
401

Conclusion

Gloo’s extendable architecture allows follows the ‘batties included but replacable’ approach. while you can use Gloo’s built in auth services for OpenID Connect and Basic Auth, you can also extend Gloo with your own custom auth logic.