Basic Auth

This feature is available with a Gloo Mesh Gateway license only.

In certain cases - such as during testing or when releasing a new API to a small number of known users - it may be convenient to secure gateway routes using Basic Authentication. With this simple authentication mechanism the encoded user credentials are sent along with the request in a standard header.

To secure your routes using basic authentication, you first need to provide Gloo Mesh Gateway with a set of known users and their passwords. You can then use this information to decide who is allowed to access which routes. If a request matches a route on which basic authentication is configured, Gloo Mesh Gateway will verify the credentials in the standard Authorization header before sending the request to its destination. If the user associated with the credentials is not explicitly allowed to access that route, Gloo Mesh Gateway will return a 401 response to the downstream client.

Setup

First, we need to install Gloo Mesh Enterprise (minimum version 1.1) with extauth enabled. Please refer to the corresponding installation guide for details.

This guide makes use of the Bookinfo sample application. You can install the application by following the steps in the Bookinfo deployment section.

Creating a Virtual Gateway

Now let's configure Gloo Mesh Gateway to route requests to the destination we just created. To do that, we define a simple Virtual Gateway to match all requests that:

Apply the following virtual gateway and auth config:

apiVersion: networking.enterprise.mesh.gloo.solo.io/v1beta1
kind: VirtualGateway
metadata:
  labels:
    app: bookinfo-policies
    app.kubernetes.io/name: bookinfo-policies
  name: test-inlined-gateway
  namespace: bookinfo
spec:
  connectionHandlers:
    - http:
        routeConfig:
          - virtualHost:
              domains:
                - www.example.com
              routes:
                - matchers:
                    - uri:
                        prefix: /ratings
                  name: ratings
                  options: {}
                  routeAction:
                    destinations:
                      - kubeService:
                          clusterName: mgmt-cluster
                          name: ratings
                          namespace: bookinfo
  ingressGatewaySelectors:
    - destinationSelectors:
        - kubeServiceMatcher:
            clusters:
              - mgmt-cluster
            labels:
              istio: ingressgateway-ns
            namespaces:
              - istio-system
      portName: http2

Let's send a request that matches the above route to the Gloo Mesh gateway and make sure it works:

curl -v $(BOOKINFO_INGRESS_GATEWAY_URL)/ratings/1 -H "Host: www.example.com"

The above command should produce the following output:

{"id":1,"ratings":{"Reviewer1":5,"Reviewer2":4}}

Securing the Route

As we just saw, we were able to reach the destination without having to provide any credentials. This is because by default Gloo Mesh Gateway allows any request on routes that do not specify authentication configuration. Let's change this behavior. We will update the Virtual Gateway so that only requests by the user user with password password are allowed. Gloo Mesh expects password to be hashed and salted using the APR1 format. Passwords in this format follow this pattern:

$apr1$SALT$HASHED_PASSWORD

To generate such a password you can use the htpasswd utility:

htpasswd -nbm user password

Running the above command returns a string like user:$apr1$TYiryv0/$8BvzLUO9IfGPGGsPnAgSu1, where:

Now that we have a password in the required format, let's go ahead and create an AuthConfig CR and update our virtual gateway to reference the auth config:

apiVersion: networking.enterprise.mesh.gloo.solo.io/v1beta1
kind: VirtualGateway
metadata:
  labels:
    app: bookinfo-policies
    app.kubernetes.io/name: bookinfo-policies
  name: test-inlined-gateway
  namespace: bookinfo
spec:
  connectionHandlers:
    - http:
        routeConfig:
          - virtualHost:
              domains:
                - www.example.com
              routes:
                - matchers:
                    - uri:
                        prefix: /ratings
                  name: ratings
                  options:
                    extauth:
                      configRef:
                        name: basic-auth
                        namespace: bookinfo
                  routeAction:
                    destinations:
                      - kubeService:
                          clusterName: mgmt-cluster
                          name: ratings
                          namespace: bookinfo
  ingressGatewaySelectors:
    - destinationSelectors:
        - kubeServiceMatcher:
            clusters:
              - mgmt-cluster
            labels:
              istio: ingressgateway-ns
            namespaces:
              - istio-system
      portName: http2
---
apiVersion: enterprise.gloo.solo.io/v1
kind: AuthConfig
metadata:
  labels:
    app: bookinfo-policies
    app.kubernetes.io/name: bookinfo-policies
  name: basic-auth
  namespace: bookinfo
spec:
  configs:
    - basicAuth:
        apr:
          users:
            user:
              hashedPassword: 8BvzLUO9IfGPGGsPnAgSu1
              salt: TYiryv0/

Testing denied requests

Let's try and resend the same request we sent earlier:

curl -v $(BOOKINFO_INGRESS_GATEWAY_URL)/ratings/1 -H "Host: www.example.com"

You will see that the response now contains a 401 Unauthorized code, indicating that Gloo Mesh denied the request.

> GET /posts/1 HTTP/1.1
> Host: foo
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 401 Unauthorized
< www-authenticate: Basic realm=""
< date: Mon, 07 Oct 2019 13:36:58 GMT
< server: envoy
< content-length: 0

Testing authenticated requests

For a request to be allowed, it must now include the user credentials inside the expected header, which has the following format:

Authorization: basic <base64_encoded_credentials>

To encode the credentials, just run:

echo -n "user:password" | base64

For our example, this outputs dXNlcjpwYXNzd29yZA==. Let's include the header with this value in our request:

curl -v $(BOOKINFO_INGRESS_GATEWAY_URL)/ratings/1 -H "Host: www.example.com" -H "Authorization: basic dXNlcjpwYXNzd29yZA=="

We are now able to reach the ratings service again!

{"id":1,"ratings":{"Reviewer1":5,"Reviewer2":4}}

Logging

The ext-auth-service logs can be viewed with:

kubectl logs -n gloo-mesh deploy/ext-auth-service -c ext-auth-service -f

If the auth config has been received successfully, you should see the log line:

"logger":"extauth","caller":"runner/run.go:179","msg":"got new config"

Summary

In this tutorial, we installed Gloo Mesh Gateway and created an unauthenticated Virtual Gateway that routes requests to our ratings service. We then created a Basic Authentication AuthConfig object and used it to secure our Virtual Gateway. We first showed how unauthenticated requests fail with a 401 Unauthorized response, and then showed how to send authenticated requests successfully to the destination.

Cleanup the resources by running:

kubectl delete ac -n bookinfo basic-auth
kubectl delete vg -n bookinfo test-inlined-gateway