Skip to content

Keycloak with Grafana

Overview

This system provides distributors access to their specific device metrics through:

  1. MQTT device telemetry
  2. Telegraf processing with fleet-based routing
  3. InfluxDB fleet-specific buckets
  4. Grafana with dynamic bucket selection

Detailed Data Flow

Diagram

flowchart LR
    MQTT[MQTT Broker] --> Telegraf
    Telegraf --> InfluxDB
    Keycloak[Keycloak] --> Grafana
    Grafana --> ClientMS[Client Microservice]
    ClientMS --> Grafana
    Grafana --> InfluxDB
    InfluxDB --- Bucket1[fleet_123]
    InfluxDB --- Bucket2[fleet_456]
    InfluxDB --- Bucket3[...]
    Telegraf -.-> InfluxDB
    Grafana -.-> InfluxDB

Component Details

  1. MQTT Topics Structure:

    dt/V01/GPRSV2/{fleetId}/VCUA/{OEMID}
    
  2. Telegraf Configuration:

[[inputs.mqtt_consumer]]
  servers = ["tcp://mqtt.example.com:1883"]
  topics = ["#"]
  data_format = "json"

[[processors.regex]]
  namepass = ["mqtt_consumer"]
  [[processors.regex.tags]]
    key = "topic"
    pattern = 'fleet/(?P<fleet_id>[^/]+)/device/(?P<device_id>[^/]+)/.*'
    replacement = "${fleet_id}"

[[outputs.influxdb_v2]]
  urls = ["http://influxdb:8086"]
  token = "$INFLUX_TOKEN"
  organization = "omvivoltaic"
  bucket = "fleet_${tag.fleet_id}"
  1. Grafana Configuration:
[auth.generic_oauth]enabled = true
name = Keycloak
client_id = grafana
client_secret = <secret>
auth_url = https://keycloak/auth/realms/omvivoltaic_dev/protocol/openid-connect/auth
token_url = https://keycloak/auth/realms/omvivoltaic_dev/protocol/openid-connect/token
api_url = https://keycloak/auth/realms/omvivoltaic_dev/protocol/openid-connect/userinfo
  1. Grafana Dashboard Setup:
    • Variables:
      • ${fleetId} (from external API call)
      • ${deviceId} (filter dropdown)
    • Data source queries:

      flux

      from(bucket: "fleet_${fleetId}")
        |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
        |> filter(fn: (r) => r["deviceId"] == "${deviceId}")
      
      1. Data Collection Path:

        Devices → MQTT (fleet/{fleetId}/device/{deviceId})
                → Telegraf (extracts fleetId/deviceId)
                → InfluxDB (writes to fleet_{fleetId} bucket)
        
      2. Visualization Path:

        User → Grafana (login via Keycloak)
             → Calls Client Microservice (gets fleetId)
             → Queries InfluxDB (fleet_{fleetId} bucket)
             → Renders dashboard (filterable by deviceId)
        

Access Control Implementation

  1. On Grafana login:
    • Keycloak provides user email/username
    • Grafana calls Client Microservice API with user identity
    • Returns corresponding fleetId
    • All queries automatically scoped to fleet_{fleetId} bucket
  2. Device Filtering:
    • Dashboard loads available devices for the fleet
    • User selects specific device to view metrics
    • All visualizations update with device-filtered data

Grafana Configuration Setup

Group-to-Role Mapping

The Grafana authentication configuration includes the following group mappings:

yaml
# Grafana Configuration (grafana.ini or environment variables)
[auth.jwt]
enabled = true
header_name = X-JWT-Assertion
email_claim = email
username_claim = preferred_username
groups_claim = groups

# Role mapping based on groups
role_attribute_path = contains(groups[*], 'SUPER-ADMIN') && 'grafanaAdmin' || contains(groups[*], 'DISTRIBUTOR') && 'Viewer' || 'Viewer'

Role Definitions

grafanaAdmin Role:

  • Complete administrative access
  • Dashboard creation and editing
  • Data source management
  • User and team management
  • System configuration access

Viewer Role:

  • Read-only dashboard access
  • View existing dashboards and panels
  • No editing or administrative capabilities
  • Limited to viewing assigned dashboards

Permission Hierarchy

  1. SUPER-ADMIN GroupgrafanaAdmin Role
    • Highest level access
    • Full system control
  2. DISTRIBUTOR GroupViewer Role
    • Limited read-only access
    • Restricted to viewing capabilities

Implementation Details

Keycloak Configuration

  1. Group Creation: Two primary groups created in Keycloak:
    • SUPER-ADMIN
    • DISTRIBUTOR
  2. Token Mapping: Groups are automatically included in JWT tokens through Keycloak's group mapper configuration
  3. User Registration: Backend system automatically assigns users to appropriate groups during user creation process

Grafana Integration

  • Grafana receives JWT tokens containing group information
  • Group membership determines user permissions and dashboard access
  • Token validation ensures secure authentication flow

Grafana Role Mapping Configuration

The Grafana configuration maps Keycloak groups to Grafana roles as follows:

Group to Role Mapping:

  • SUPER-ADMIN group → grafanaAdmin role
    • Full administrative privileges in Grafana
    • Complete access to all dashboards, data sources, and system settings
    • User management capabilities
  • DISTRIBUTOR group → Viewer role
    • Read-only access to dashboards
    • Limited permissions for viewing data
    • No administrative or editing capabilities

Configuration Details:

  • Groups are extracted from the JWT token's groups field
  • Role assignment is automatic based on group membership
  • Users inherit permissions based on their assigned Grafana role
  • If a user belongs to multiple groups, the highest privilege level applies

Security Considerations

Token Security

  • Tokens include expiration timestamps to prevent unauthorized long-term access
  • Issuer validation ensures tokens originate from trusted Keycloak instance
  • Audience validation confirms tokens are intended for Grafana usage

Group-Based Access Control

  • Group membership provides fine-grained permission control
  • Multiple group assignments allow for flexible permission structures
  • User-specific groups enable individual access customization

Troubleshooting

Common Issues

  1. Missing Groups in Token
    • Verify group assignment in Keycloak
    • Check group mapper configuration
    • Confirm user is properly assigned to groups
  2. Token Validation Errors
    • Verify issuer URL matches Keycloak configuration
    • Check audience parameter matches Grafana client ID
    • Ensure token hasn't expired
  3. Permission Denied in Grafana
    • Confirm group-to-permission mapping in Grafana
    • Verify user's groups match required permissions
    • Check Grafana role mapping configuration
    • Ensure SUPER-ADMIN users have grafanaAdmin role
    • Verify DISTRIBUTOR users have Viewer role assigned
  4. Incorrect Role Assignment
    • Verify group names match exactly (SUPER-ADMIN, DISTRIBUTOR)
    • Check Grafana's group-to-role mapping configuration
    • Confirm JWT token contains correct groups array

Future Enhancements

Potential Improvements

  • Additional granular groups for specific feature access
  • Dynamic group assignment based on user attributes
  • Integration with external authorization systems
  • Audit logging for group-based access events