... Go back to home

How to use JWT Auth for Grafana Iframe + Python REST API

#grafana #jwt #python #rest-api
2024-08-16
  1. Generate RS256 key pair using openssl

    a. Run the following commands in terminal, make sure openssl is installed

    1openssl genpkey -algorithm RSA -out private.key
    2openssl rsa -pubout -in private.key -out public.key
    

    b. These commands will generate 2 files, private.key and public.key

    1├── private.key
    2└── public.key
    
  2. Convert the contents of public.key file to JSON format using https://russelldavies.github.io/jwk-creator/

    a. Copy the contents of public.key into the PEM encoded key field

    b. Fill in the Key ID with grafana

    c. Leave the Public Key Use and Algorithm fields empty

    d. Click the Convert button

  3. Create a jwks.json file

    a. Create a new file named jwks.json and fill it with the following JSON

    1{
    2    "keys": []
    3}
    

    b. Copy the JWK result from https://russelldavies.github.io/jwk-creator/ into the keys array in the jwks.json file. For example:

     1{
     2    "keys": [
     3        {
     4            "kty": "RSA",
     5            "n": "mCE7VaNgkjT0EyiMhyybdOfMaMWbdGyFhmWr-2e4cHY3oVxsLpdT9rcqPUtpGUI9KpRB-V8fcJj8W8YxpTLEFdca-wDP3Vgdyq76-tNYLicMCuvqQD-2PIHDgzPvGBdbj7SZLKs9v8XUfyJ5MhdeSsQVHczgun34h7BfMPhW_qZwd7mXmXB0NHNRVUSYEpBJFmnp6i6CAF5hIRCCxaFZLdzArWg1WXADDJqTC_nVlKMZkpOLTFP5JqtOrWKJGn-uYINyJ0HreXMSehknCZNh1-S7-J8LG--YL2E4JtwkdbbSA-iyuQYRJUT9WezrS-kQSXypntrC-aAH0YOFj9lw8Q",
     6            "e": "AQAB",
     7            "kid": "grafana"
     8        }
     9    ]
    10}
    

    c. Save the jwks.json file

  4. Mount jwks.json to /etc/grafana/jwks.json in the Grafana container

  5. Configure Grafana in the grafana.ini file in the Grafana container

     1[security]
     2allow_embedding = true
     3...
     4
     5[auth.jwt]
     6enabled = true
     7url_login = true
     8header_name = X-JWT-Assertion
     9email_claim = sub
    10username_claim = user
    11jwk_set_file = /etc/grafana/jwks.json
    
  6. Restart the Grafana container

  7. To access Grafana using JWT, an auth_token needs to be generated first.

     1import jwt
     2import datetime
     3
     4payload = {
     5    "exp": int((datetime.datetime.now() + datetime.timedelta(hours=50)).timestamp()), # token expiration time (unix timestamp)
     6    'sub': 'admin@gmail.com', # grafana user email
     7    'user': 'admin', # grafana username
     8}
     9
    10token = jwt.encode(payload, SECRET_KEY, algorithm='RS256', headers={
    11    'kid': 'grafana' # use the same key_id (kid) as in jwks.json
    12})
    13
    14token = token.decode('utf-8')
    15
    16print(f'auth_token: {token}')
    
     1from flask_restx import Resource
     2from flask import render_template_string
     3
     4class ApiClass(Resource):
     5    def get(self):
     6        iframe = 'http://localhost:3000/d-solo/a5919b27-0868-44a0-9f4e-28fad226288f/new-dashboard?orgId=1&panelId=1&auth_token=' + token
     7
     8        template = f"""
     9        <iframe
    10            frameborder="0"
    11            noresize="noresize"
    12            style="position: absolute; background: transparent; width: 100%; height: 100%"
    13            src="{ iframe }"
    14            frameborder="0"
    15        ></iframe>
    16        """
    17
    18        return Response(render_template_string(template), mimetype='text/html')