Custom Auth server

The custom auth feature was introduced with Gloo Gateway, release 0.20.7, and Gloo Gateway Enterprise, release 0.13.5. If you are using an earlier version, this tutorial will not work.

Gloo Gateway Enterprise ships with an external auth server that implements a wide array of authentication and authorization models. Even though these features are not available in the open source version of Gloo Gateway, you can deploy your own service and configure Gloo Gateway to use it to secure your Virtual Services.

In this guide we will see how to create such a custom external auth service. For simplicity, we will implement an HTTP service. With minor adjustments, you should be able to use the contents of this guide to deploy a gRPC server that implements the Envoy spec for an external authorization server.

Setup

This guide assumes that you have deployed Gloo to the gloo-system namespace and that the glooctl command line utility is installed on your machine. glooctl provides several convenient functions to view, manipulate, and debug Gloo resources; in particular, it is worth mentioning the following command, which we will use each time we need to retrieve the URL of the Gloo Gateway that is running inside your cluster:

glooctl proxy url

Let’s start by creating the sample petstore application:

kubectl apply -f https://raw.githubusercontent.com/solo-io/gloo/v1.14.x/example/petstore/petstore.yaml

We can now add a route to the sample application by running the following command:


kubectl apply -f - <<EOF
apiVersion: gateway.solo.io/v1
kind: VirtualService
metadata:
  name: default
  namespace: gloo-system
spec:
  virtualHost:
    domains:
    - '*'
    routes:
    - matchers:
      - prefix: /
      routeAction:
        single:
          upstream:
            name: default-petstore-8080
            namespace: gloo-system
EOF

glooctl add route --name default --namespace gloo-system --path-prefix / --dest-name default-petstore-8080 --dest-namespace gloo-system

Let’s verify that everything so far works by querying the virtual service.

curl $(glooctl proxy url)/api/pets/

You should see the following output:

[{"id":1,"name":"Dog","status":"available"},{"id":2,"name":"Cat","status":"pending"}]

Creating a simple HTTP Authentication service

When a request matches a route that defines an extauth configuration, Gloo Gateway will forward the request to the external auth service. If the HTTP service returns a 200 OK response, the request will be considered authorized and sent to its original destination. Otherwise the request will be denied. You can fine tune which headers are sent to the the auth service, and whether or not the body is forwarded as well, by editing the extauth settings in the Gloo Gateway settings (see the example below).

For reference, here’s the code for the authorization 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.

Deploy auth service

To deploy this service to your cluster, copy the content of this file to a file named auth-service.yaml and apply it:

kubectl apply --filename auth-service.yaml

This file contains the deployment, service and upstream definitions.

When running in minikube you can easily update this sample auth service. Just download the Dockerfile and the server.py file to a local directory, apply your changes to the server code, and run the following commands:

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

Configure Gloo Gateway to use your server

Configure Gloo Gateway settings

To use our custom auth server, we need to edit the Gloo Gateway Settings resource. Run the following command to edit the settings:

kubectl --namespace gloo-system edit settings default

We need to add the following extauth attribute:

apiVersion: gloo.solo.io/v1
kind: Settings
metadata:
  name: default
  namespace: gloo-system
spec:
  discoveryNamespace: gloo-system
  gateway:
    validation:
      alwaysAccept: true
      proxyValidationServerAddr: gloo:9988
  gloo:
    xdsBindAddr: 0.0.0.0:9977
  kubernetesArtifactSource: {}
  kubernetesConfigSource: {}
  kubernetesSecretSource: {}
  refreshRate: 60s
  extauth:
   extauthzServerRef:
     name: auth-server
     namespace: gloo-system
   httpService: {}
   requestBody:
     maxRequestBytes: 10240
   requestTimeout: 0.5s

More details about the httpService object are available here . For example, if you want to copy some of the original request headers to the request that gets sent to the custom auth server, you would need to configure the extauth attribute in the following way:

apiVersion: gloo.solo.io/v1
kind: Settings
metadata:
  name: default
  namespace: gloo-system
spec:
  discoveryNamespace: gloo-system
  gateway:
    validation:
      alwaysAccept: true
      proxyValidationServerAddr: gloo:9988
  gloo:
    xdsBindAddr: 0.0.0.0:9977
  kubernetesArtifactSource: {}
  kubernetesConfigSource: {}
  kubernetesSecretSource: {}
  refreshRate: 60s
  extauth:
   extauthzServerRef:
     name: auth-server
     namespace: gloo-system
   httpService:
     request:
       allowedHeaders:
       - "X-foo"
   requestBody:
     maxRequestBytes: 10240
   requestTimeout: 0.5s

When using a gRPC auth service, remove the httpService attribute from the configuration above.

This configuration also sets other configuration parameters:

Securing the Virtual Service

Edit the VirtualService and mark it with custom auth to turn authentication on:

kubectl apply -f - <<EOF
apiVersion: gateway.solo.io/v1
kind: VirtualService
metadata:
  name: default
  namespace: gloo-system
spec:
  virtualHost:
    domains:
    - '*'
    options:
      extauth:
        customAuth: {}
    routes:
    - matchers:
      - prefix: /
      routeAction:
        single:
          upstream:
            name: default-petstore-8080
            namespace: gloo-system
EOF

If you have followed this guide verbatim, you can just download and apply this manifest to update both the Settings and the Virtual Service.

Test

Let’s verify that our configuration has been accepted by Gloo Gateway. Requests to /api/pets/1 should be allowed:

curl --write-out "%{http_code}\n" $(glooctl proxy url)/api/pets/1
{"id":1,"name":"Dog","status":"available"}
200

Any request with a path that is not /api/pets/1 should be denied.

curl --write-out "%{http_code}\n" $(glooctl proxy url)/api/pets/2
401

Conclusion

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