User Authentication

Overview

Hydrolix authentication provides a centralized authentication system for your cluster. It works for all externally-available endpoints. It is enabled by default and covers:

  • Ingest API
  • Query API (including Clickhouse and HTTP)
  • Web UI
  • Miscellaneous services such as the transform validator, version, prometheus, and acme endpoints

Hydrolix ensures that one of these conditions is true for each request, or it denies access:

  • The request includes a valid 24-hour Bearer token
  • The endpoint is the /login API method
  • In the case of the Web UI, the user is logged in

Users may be added, deleted, and managed using the Web UI or Config API.

πŸ“˜

If you're upgrading from Hydrolix version 4.2 or earlier, set unified_auth: false in your hydrolixconfig.yaml file to re-enable the older, non-unified methods of authentication.

Using Authentication

Web UI

Visit your Hydrolix cluster's IP address via a web browser and you will be directed to the login page if you aren't already logged in.

API and Other Endpoints

In this mechanism, the Bearer token is provided to the endpoint rather than a username and password. This token is valid for 24 hours, and can be thought of as a session token. This token authorizes access without the extra risk of sending rarely-changing usernames and passwords over the network for every request.

To retrieve the bearer token, use the login API endpoint. For example, using curl:

curl --request POST \
     --url https://hostname.company.net/config/v1/login \
     --header 'Accept: application/json' \
     --header 'Content-Type: application/json' \
     --data '
{
     "username": "[email protected]",
     "password": "secret"
}
'

The login API will return the following output:

{
  "uuid": "1111-2222-3333-4444-5555",
  "email": "[email protected]",
  "orgs": [
    {
      "uuid": "aaaa-bbbb-cccc-dddd",
      "name": "Hydrolix",
      "type": "singletenant"
    }
  ],
  "groups": [
    "org.asdf.Hydrolix.admin"
  ],
  "auth_token": {
    "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJXbzNLa21MbnhDNzVyaHVJQXR0RHhxak9LTlh4bURvWU5pTkVyeExueHhRIn0.eyJleHAiOjE2NjA0MDE4NjQsImlhdCI6MTY2MDMxNTQ2NCwianRpIjoiYmUzOTllMmItZjhkNC00MjY2LWI3OTYtZDdjN2NhZDhkNGU1IiwiaXNzIjoiaHR0cDovL2tleWNsb2FrOjgwODAvYXV0aC9yZWFsbXMvaHlkcm9saXgtdXNlcnMiLCJhdWQiOlsiY29uZmlnLWFwaSIsImFjY291bnQiXSwic3ViIjoiODM0NTc4M2YtYjE3Yi00ZTdhLTk3MDAtOTA5MzAxNmIyNWFmIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoiY29uZmlnLWFwaSIsInNlc3Npb25fc3RhdGUiOiJiZjY0ZTkwMy1iNmZjLTQ0NWEtYWU4Yi0wZDM1NzI1OGZkZGEiLCJhY3IiOiIxIiwiYWxsb3dlZC1vcmlnaW5zIjpbImh0dHA6Ly9sb2NhbGhvc3Q6MzAwMSJdLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsiZGVmYXVsdC1yb2xlcy1oeWRyb2xpeC11c2VycyIsIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6ImVtYWlsIGNvbmZpZy1hcGktc2VydmljZSBwcm9maWxlIiwic2lkIjoiYmY2NGU5MDMtYjZmYy00NDVhLWFlOGItMGQzNTcyNThmZGRhIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsInByZWZlcnJlZF91c2VybmFtZSI6InNlcnZpY2VzQGh5ZHJvbGl4LmlvIiwiZW1haWwiOiJzZXJ2aWNlc0BoeWRyb2xpeC5pbyJ9.hR9Cv52CYVlG_FoSoGxvKjWXJXSWxxBMQJKP7EMbVxfpOZmQNmfaBPuBMO7NbGM12a7VPo8V_SQqxneJHPX4sxOiZ1DPePU1QPTrhh41-FkvyD6lQ9FEnAQGZFLFp0VKYiNbMIYnnM1dyfQAARwwcNq7wWQ_kZmzAz9QZMbdvtKzmGnlhsZkirBkz7aWQcnyuJQPcg6CZPa4p9nsP7qcLqMGY_b88v_VnBO13qM4u20NFvo2h8pef_tgtFupvZiUDMDjIFI_UTij6PLNJZFBYwmrxIMNrmJshtGIbMfRMFHKMVe6l7ruzwxCj-asdfasdfasdf",
    "expires_in": 86400,
    "token_type": "Bearer"
  }
}

πŸ‘

Pretty JSON

Note that the output from the above command can be made much more human-readable by piping it through a JSON utility such as jq.

Include the auth_token.access_token field value in your HTTP requests to authenticate with the token. Use a header named authorization with the value Bearer <TOKEN>:

curl --request POST \
  --url https://hostname.company.net/query/ \
  --header 'authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJXbzNLa21MbnhDNzVyaHVJQXR0RHhxak9LTlh4bURvWU5pTkVyeExueHhRIn0.eyJleHAiOjE2NjA0MDE4NjQsImlhdCI6MTY2MDMxNTQ2NCwianRpIjoiYmUzOTllMmItZjhkNC00MjY2LWI3OTYtZDdjN2NhZDhkNGU1IiwiaXNzIjoiaHR0cDovL2tleWNsb2FrOjgwODAvYXV0aC9yZWFsbXMvaHlkcm9saXgtdXNlcnMiLCJhdWQiOlsiY29uZmlnLWFwaSIsImFjY291bnQiXSwic3ViIjoiODM0NTc4M2YtYjE3Yi00ZTdhLTk3MDAtOTA5MzAxNmIyNWFmIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoiY29uZmlnLWFwaSIsInNlc3Npb25fc3RhdGUiOiJiZjY0ZTkwMy1iNmZjLTQ0NWEtYWU4Yi0wZDM1NzI1OGZkZGEiLCJhY3IiOiIxIiwiYWxsb3dlZC1vcmlnaW5zIjpbImh0dHA6Ly9sb2NhbGhvc3Q6MzAwMSJdLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsiZGVmYXVsdC1yb2xlcy1oeWRyb2xpeC11c2VycyIsIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6ImVtYWlsIGNvbmZpZy1hcGktc2VydmljZSBwcm9maWxlIiwic2lkIjoiYmY2NGU5MDMtYjZmYy00NDVhLWFlOGItMGQzNTcyNThmZGRhIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsInByZWZlcnJlZF91c2VybmFtZSI6InNlcnZpY2VzQGh5ZHJvbGl4LmlvIiwiZW1haWwiOiJzZXJ2aWNlc0BoeWRyb2xpeC5pbyJ9.hR9Cv52CYVlG_FoSoGxvKjWXJXSWxxBMQJKP7EMbVxfpOZmQNmfaBPuBMO7NbGM12a7VPo8V_SQqxneJHPX4sxOiZ1DPePU1QPTrhh41-FkvyD6lQ9FEnAQGZFLFp0VKYiNbMIYnnM1dyfQAARwwcNq7wWQ_kZmzAz9QZMbdvtKzmGnlhsZkirBkz7aWQcnyuJQPcg6CZPa4p9nsP7qcLqMGY_b88v_VnBO13qM4u20NFvo2h8pef_tgtFupvZiUDMDjIFI_UTij6PLNJZFBYwmrxIMNrmJshtGIbMfRMFHKMVe6l7ruzwxCj-asdfasdfasdf' \
  --data 'SELECT column FROM table'
{
    "error": "std::exception. Code: 1001, type: h::db::AclError, e.what() = <AclError invalid user token provided (Hydrolix v3.48.5 - Turbine aceb91e6)>, Stack trace (when copying this message, always include the lines below):\n\n (version 22.12.1.1)",
    "query": "select count() from hydro.logs"
}

🚧

Token Prefix

Don't forget the prefix Bearer.

Reporting

You can see reports of usage, including valid and invalid requests per token, in your Hydrolix cluster's Prometheus reporting.