Keycloak with Grafana¶
Overview¶
This system provides distributors access to their specific device metrics through:
- MQTT device telemetry
- Telegraf processing with fleet-based routing
- InfluxDB fleet-specific buckets
- 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¶
-
MQTT Topics Structure:
dt/V01/GPRSV2/{fleetId}/VCUA/{OEMID} -
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}"
- 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
- 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}")-
Data Collection Path:
Devices → MQTT (fleet/{fleetId}/device/{deviceId}) → Telegraf (extracts fleetId/deviceId) → InfluxDB (writes to fleet_{fleetId} bucket) -
Visualization Path:
User → Grafana (login via Keycloak) → Calls Client Microservice (gets fleetId) → Queries InfluxDB (fleet_{fleetId} bucket) → Renders dashboard (filterable by deviceId)
-
- Variables:
Access Control Implementation¶
- 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
- 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¶
- SUPER-ADMIN Group → grafanaAdmin Role
- Highest level access
- Full system control
- DISTRIBUTOR Group → Viewer Role
- Limited read-only access
- Restricted to viewing capabilities
Implementation Details¶
Keycloak Configuration¶
- Group Creation: Two primary groups created in Keycloak:
SUPER-ADMINDISTRIBUTOR
- Token Mapping: Groups are automatically included in JWT tokens through Keycloak's group mapper configuration
- 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-ADMINgroup →grafanaAdminrole- Full administrative privileges in Grafana
- Complete access to all dashboards, data sources, and system settings
- User management capabilities
DISTRIBUTORgroup →Viewerrole- 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
groupsfield - 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¶
- Missing Groups in Token
- Verify group assignment in Keycloak
- Check group mapper configuration
- Confirm user is properly assigned to groups
- Token Validation Errors
- Verify issuer URL matches Keycloak configuration
- Check audience parameter matches Grafana client ID
- Ensure token hasn't expired
- 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-ADMINusers havegrafanaAdminrole - Verify
DISTRIBUTORusers haveViewerrole assigned
- 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
- Verify group names match exactly (
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