Grafana users synced from a YAML file

Make Grafana automatically synchronize user roles from YAML file

Oct 18, 2022 by Mikolaj Gasior



Intro

Grafana is a great tool for monitoring and observability. In one of the projects we had it configured with SSO with GitHub and we had this problem where user role kept getting downgraded, like from Admin back to Viewer. Also, at the time of writing this post, synchronization with teams in GitHub was available only in Enterprise version.

Hence, we made a quick hack (that lasts until now). Grafana stores data in SQLite, and user roles are saved in it. Therefore, we came up with an idea that roles such as Editor and Admin will be stored in a YAML file and that a simple application will keep such configuration in sync with what’s in the database.

Note that, in our case there wasn’t that much changes once the initial setup went on production.

See Sample YAML. To get things in sync, the application loops through the entries in the YAML configuration file and runs an SQL query similar to then one blow.

UPDATE org_user SET role = ? WHERE user_id IN (SELECT id FROM user WHERE login=?);

Source code

You can find sidecar source code on GitHub. All the necessary documentation on how to build it and add it is there as well.

Sample YAML

Check out sample configuration file.

version: "1"
database: /path/to/grafana.db
dry_run: no
run_once: no
sleep: 10
orgs:
  - id: 1
    admins:
      - login: admin1
    editors:
      - login: editor1
      - login: editor2
    viewers:
      - login: viewer1
      - login: viewer2

Dry-running

There are few more bits to that. We wanted a dry-run mode, an option to run the app just once and exit (instead of running as a deamon, in a sidecar), being able to set delay between each iteration of the loop and, finally, an option to set the application to not crash when YAML configuration is invalid. Latter one is useful when, like in our case, the YAML file is provided by ConfigMap. When it’s invalid, a sidecar should not crash because it might crash whole grafana pod.

Deployment

Grafana was deployed in Kubernetes cluster with Helm chart, so an additional sidecar was just added on an existing grafana pod.

Helm chart modification

Few lines have to be added to the Helm chart’s values file to get the whole thing working. See below example.

extraConfigmapMounts:
  - name: sc-users
    configMap: grafana-sc-users
    mountPath: /etc/grafana/provisioning/sc-users
    subPath: ''

extraContainers: |-
  - name: grafana-sc-users
    image: YOUR-DOCKER-REGISTRY/IMAGE-HERE:IMAGE-TAG
    imagePullPolicy: Always
    args:
      - "start"
      - "-i"
      - "-c"
      - "/etc/grafana/provisioning/sc-users/users.yaml"
    volumeMounts:
      - mountPath: /etc/grafana/provisioning/sc-users
        name: sc-users
      - mountPath: /var/lib/grafana
        name: storage