Skip to content

RBAC How-to: Traefik Configuration

This page describes the steps to grant a user access to the Grafana UI and permission to ingest data to a specific table. These permissions are enforced by Traefik when the enable_traefik_authorization tunable is true.

Prerequisites⚓︎

This example assumes you have set the $HDX_HOSTNAME to the hostname of your Hydrolix cluster, for example: hostname.hydrolix.live.

Log in to the API⚓︎

Get the bearer token, which is good for the next 24 hours, to authenticate future API calls. This command assumes you've set the $HDX_HOSTNAME, $HDX_USER, and $HDX_PASSWORD environment variables:

1
2
3
4
5
6
7
8
export HDX_TOKEN=$(
  curl -v -X POST -H "Content-Type: application/json" \
  https://$HDX_HOSTNAME/config/v1/login/ \
  -d "{
    \"username\":\"$HDX_USER\",
    \"password\":\"$HDX_PASSWORD\"  
  }" | jq -r ".auth_token.access_token"
)

List orgs and projects from the API⚓︎

List the Hydrolix installation's organizations with the following command:

1
2
3
4
curl -X GET -H "Content-Type: application/json" \
   -H "Authorization: Bearer $HDX_TOKEN" \
   https://$HDX_HOSTNAME/config/v1/orgs \
   | jq -r ".results.[] | [.uuid,.name] | @tsv"

From the output, find the organization's UUID you want to use and assign that to an environment variable $HDX_ORG.

Similarly, use this command to list the projects available to the organization:

1
2
3
4
curl -X GET -H "Content-Type: application/json" \
   -H "Authorization: Bearer $HDX_TOKEN" \
   https://$HDX_HOSTNAME/config/v1/orgs/$HDX_ORG/projects \
   | jq -r ".results.[] | [.uuid,.name] | @tsv"

From the output, find the project you want to use and assign its UUID to an environment variable called $HDX_PROJECT.

List tables in project⚓︎

From the previous steps, the $HDX_HOSTNAME, $HDX_TOKEN, $HDX_ORG, and $HDX_PROJECT environment variables should be set.

You will also need the UUID of the target table. List the tables in your project with the following command:

1
2
3
4
curl -X GET -H "Content-Type: application/json" \
  -H "Authorization: Bearer $HDX_TOKEN" \
  https://$HDX_HOSTNAME/config/v1/orgs/$HDX_ORG/projects/$HDX_PROJECT/tables/ \
  | jq -r ".results.[] | [.uuid,.name] | @tsv"
1
2
3
df67fce7-4553-437f-a9fc-820ace745ec7    my_table
6b2a344f-bfd5-4dbf-af82-1a9fa8b3dd38    another_very_nice_table
...

From the output, find the table you want to grant ingest access to and assign its UUID to an environment variable called $HDX_TABLE.

Create the role⚓︎

This example creates a role called grafana_and_ingest with two policies. The first policy grants global access to the Grafana UI using the view_grafana permission. The second policy grants the ingest_table permission scoped to the table.

curl -X POST -H "Content-Type: application/json" \
  -H "Authorization: Bearer $HDX_TOKEN" \
  https://$HDX_HOSTNAME/config/v1/roles \
  -d @- <<EOF | jq
{
  "name": "grafana_and_ingest",
  "policies": [
    {
      "permissions": ["view_grafana"],
      "scope_name": "global"
    },
    {
      "permissions": ["ingest_table"],
      "scope_type": "table",
      "scope_id": "$HDX_TABLE"
    }
  ]
}
EOF
{
  "id": 6,
  "name": "grafana_and_ingest",
  "policies": [
    {
      "permissions": [
        "ingest_table"
      ],
      "scope_type": "table",
      "scope_id": "df67fce7-4553-437f-a9fc-820ace745ec7",
      "scope_name": "my_table",
      "scope_deployment_id": null
    },
    {
      "permissions": [
        "view_grafana"
      ],
      "scope_name": "global",
      "scope_deployment_id": null
    }
  ]
}

Get a user's UUID⚓︎

List the users in your cluster to find the UUID of the user you want to assign the role to:

1
2
3
4
curl -X GET -H "Content-Type: application/json" \
  -H "Authorization: Bearer $HDX_TOKEN" \
  https://$HDX_HOSTNAME/config/v1/users/ \
  | jq -r ".results[] | [.uuid,.email] | @tsv"
1
2
3
5452c5ba-95e4-4395-b436-7144cc58cbdf    user@domain.tld
7dd5be9b-f758-4412-a092-13ece9d65c07    ceo@domain.tld
...

From the output, find the user you want and assign their UUID to an environment variable called $HDX_USER.

Assign the role to a user⚓︎

Assign the grafana_and_ingest role to the user:

1
2
3
4
5
6
7
8
curl -X POST -H "Content-Type: application/json" \
  -H "Authorization: Bearer $HDX_TOKEN" \
  https://$HDX_HOSTNAME/config/v1/users/$HDX_USER/add_roles/ \
  -d '{
  "roles": [
    "grafana_and_ingest"
  ]
}'
{"success":true,"message":"1 roles added to user user@domain.tld"}

Enable Traefik route authorization⚓︎

Set the enable_traefik_authorization tunable to true in the Hydrolix configuration spec:

spec:
  enable_traefik_authorization: true

Once active, Traefik enforces permission checks on ingest and service endpoints for all authenticated users.

What this user can and can't do⚓︎

With the grafana_and_ingest role and Traefik authorization enabled, the user can:

  • view_grafana: Access to the Grafana UI at https://$HDX_HOSTNAME/grafana.
  • ingest_table: Ingest data to the specified table using the HTTP Stream API.

The same user can't:

  • Access Kibana, Prometheus, Superset, or the version endpoint. These require the corresponding view_kibana, view_prometheus, view_superset, and view_version permissions. Traefik returns 403 Forbidden.
  • Ingest data to any other table. The ingest_table permission is scoped to a single table. Requests targeting other tables return 403 Forbidden.

Verify a user's permissions⚓︎

To confirm which permissions are assigned to an authenticated user, send a request to the /config/v1/users/current/ endpoint:

1
2
3
curl -X GET \
  -H "Authorization: Bearer $HDX_TOKEN" \
  https://$HDX_HOSTNAME/config/v1/users/current/ | jq
{
  "uuid": "5452c5ba-95e4-4395-b436-7144cc58cbdf",
  "email": "user@domain.tld",
  "orgs": [
    {
      "uuid": "e88fd2ff-be6b-408b-8e57-0056cb37f279",
      "name": "Hydrolix",
      "type": "singletenant",
      "cloud": "aws",
      "kubernetes": true
    }
  ],
  "is_superuser": false,
  "roles": [
    {
      "id": 6,
      "name": "grafana_and_ingest",
      "policies": [
        {
          "permissions": [
            "view_grafana"
          ],
          "scope_name": "global",
          "scope_deployment_id": null
        },
        {
          "permissions": [
            "ingest_table"
          ],
          "scope_type": "table",
          "scope_id": "df67fce7-4553-437f-a9fc-820ace745ec7",
          "scope_name": "my_table",
          "scope_deployment_id": null
        }
      ]
    }
  ],
  "audit": false,
  "emailVerified": true,
  "enabled": true,
  "is_service_account": false,
  "name": "user@domain.tld"
}