Basic Auth

This feature is available in Gloo Gateway Enterprise only. If you are using the open source version of Gloo, these instructions do not work.

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 a Virtual Service 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 Virtual Services using Basic Authentication, you first need to provide Gloo 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 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 Gateway will return a 401 response to the downstream client.

Be sure to check the external auth configuration overview for detailed information about how authentication is configured on Virtual Services.

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 a Static Upstream that routes to a website; we will send requests to it during this tutorial.



apiVersion: gloo.solo.io/v1
kind: Upstream
metadata:
  name: json-upstream
  namespace: gloo-system
spec:
  static:
    hosts:
      - addr: jsonplaceholder.typicode.com
        port: 80

glooctl create upstream static --static-hosts jsonplaceholder.typicode.com:80 --name json-upstream

Creating a Virtual Service

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

Apply the following virtual service:

apiVersion: gateway.solo.io/v1
kind: VirtualService
metadata:
  name: auth-tutorial
  namespace: gloo-system
spec:
  virtualHost:
    domains:
      - 'foo'
    routes:
      - matchers:
        - prefix: /
        routeAction:
          single:
            upstream:
              name: json-upstream
              namespace: gloo-system
        options:
          autoHostRewrite: true

Let’s send a request that matches the above route to the gateway proxy and make sure it works:

curl -H "Host: foo" $(glooctl proxy url)/posts/1

The above command should produce the following output:

{
  "userId": 1,
  "id": 1,
  "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
  "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
}

Securing the Virtual Service

The auth configuration format shown on this page was introduced with Gloo Enterprise, release 0.20.1. If you are using an earlier version, please refer to this page to see which configuration formats are supported by each version.

As we just saw, we were able to reach the upstream without having to provide any credentials. This is because by default Gloo Gateway allows any request on routes that do not specify authentication configuration. Let’s change this behavior. We will update the Virtual Service so that only requests by the user user with password password are allowed. Gloo Gateway 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 CRD with our Basic Authentication configuration:

kubectl apply -f - <<EOF
apiVersion: enterprise.gloo.solo.io/v1
kind: AuthConfig
metadata:
  name: basic-auth
  namespace: gloo-system
spec:
  configs:
  - basicAuth:
      apr:
        users:
          user:
            salt: "TYiryv0/"
            hashedPassword: "8BvzLUO9IfGPGGsPnAgSu1"
EOF

Once the AuthConfig has been created, we can use it to secure our Virtual Service:

kubectl apply -f - <<EOF
apiVersion: gateway.solo.io/v1
kind: VirtualService
metadata:
  name: auth-tutorial
  namespace: gloo-system
spec:
  virtualHost:
    domains:
      - 'foo'
    routes:
      - matchers:
        - prefix: /
        routeAction:
          single:
            upstream:
              name: json-upstream
              namespace: gloo-system
        options:
          autoHostRewrite: true      
    options:
      extauth:
        configRef:
          name: basic-auth
          namespace: gloo-system
EOF

In the above example we have added the configuration to the Virtual Host. Each route belonging to a Virtual Host will inherit its AuthConfig, unless it overwrites or disables it.

Testing denied requests

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

curl -v -H "Host: foo" $(glooctl proxy url)/posts/1

You will see that the response now contains a 401 Unauthorized code, indicating that Gloo Gateway 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

This outputs dXNlcjpwYXNzd29yZA==. Let’s include the header with this value in our request:

curl -H "Authorization: basic dXNlcjpwYXNzd29yZA==" -H "Host: foo" $(glooctl proxy url)/posts/1

We are now able to reach the upstream again!

{
  "userId": 1,
  "id": 1,
  "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
  "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
}

Logging

If Gloo Gateway is running on kubernetes, the extauth server logs can be viewed with:

kubectl logs -n gloo-system deploy/extauth -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"

Extended configuration

The auth configuration format that is shown on this page was introduced with Gloo Gateway Enterprise release 1.16.0. To find the configuration format for an earlier version, see Configuration format history.

An extended configuration is available that allows use of the SHA1 hashing algorithm instead of APR.

The following configuration defines a list of users, and the salt and hashed password that they need to use to authenticate successfully. It uses APR encryption to store the credentials for the same user that was used in the previous example.

apiVersion: enterprise.gloo.solo.io/v1
kind: AuthConfig
metadata:
  name: basic-auth
  namespace: gloo-system
spec:
  configs:
  - basicAuth:
      encryption:
        apr: {}
      userList:
        users:
          user:
            salt: "TYiryv0/"
            hashedPassword: "8BvzLUO9IfGPGGsPnAgSu1"

You can change the encryption algorithm for the hashed password to SHA1 as shown in the following example. In this example, the username and salt remain the same and the hashedPassword needs to be recalculated and updated.

apiVersion: enterprise.gloo.solo.io/v1
kind: AuthConfig
metadata:
  name: basic-auth
  namespace: gloo-system
spec:
  configs:
  - basicAuth:
      encryption:
        sha1: {}
      userList:
        users:
          user:
            salt: "TYiryv0/"
            hashedPassword: "010eb058a59f4ac5ba05639b0263cf91b4345fd6"

The same curls should work with this config as the hashing algorithm only affects the hashed password stored on the server side.

curl -H "Authorization: basic dXNlcjpwYXNzd29yZA==" -H "Host: foo" $(glooctl proxy url)/posts/1

The hashed password is case-insensitive as the alphabetic characters represent hexadecimal digits.

When using the extended configuration, the proxy-authorization header is also supported.

curl -H "Proxy- Authorization: basic dXNlcjpwYXNzd29yZA==" -H "Host: foo" $(glooctl proxy url)/posts/1

Summary

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

Cleanup the resources by running:

kubectl delete ac -n gloo-system basic-auth
kubectl delete vs -n gloo-system auth-tutorial
kubectl delete upstream -n gloo-system json-upstream