Apache Superset —Thoughts on custom authentication, running as Docker, having public dashboards and behind Nginx
In many projects, data visualization is an important need. But the project has many other micro-services. So integrating superset with other services becomes critical in getting superset as one of the service co-existing with others.
In this article, we will see few of my thoughts on :
- Having custom authentication layer for Superset
- Running superset as docker and few helper scripts
- Issues that I faced running Superset behind an NGINX reverse proxy
- Exposing public dashboards and few tips on this area
- Superset base url issue and patch fix
To be frank, the documentation of Superset is very limited on this front. Right from authentication integration, we need to spend a lot of time in figuring out ourselves. I searched a lot and where ever I go (google, stackoverflow, superset github issues, flask appbuilder github issues) many ask questions on customizing the authentication layer. Hope this article will save some one else time.
Custom Authentication — Problem statement
- Superset is based on flask-appbuilder, which also provides the authentication layer. Flask appbuilder provides authentication methods
- Sometimes none of the authentication methods suites our needs. This is where Flask appbuilder’s support for custom security and custom authentication comes handy
- Let’s say we have a micro services architecture and Superset plays a role in visualizing the data. But there is another micro service which takes care of user management
Solution
- Let’s implement a custom security and authentication layer
- I am using superset docker image. But the core concept remains the same for superset run directly on the host system
Solution source code
- Source code for a standalone superset with custom authentication
- Source code for a django demo application integrated with superset
Approach
- Run superset docker with the following superset_config.py and security.py placed in a config directory
docker run --detach --name superset -p "8088:8088" -v $(pwd)/config:/etc/superset -v $(pwd)/data:/var/lib/superset amancevice/superset:0.25.6
- Notice, in superset_config.py, we try to initialize CUSTOM_SECURITY_MANAGER with our own implemention.
- A sample security manager is shown below
Redirect users directly to target page (like a specific dashboard)
Many times, it is useful to redirect the users to some specific dashboard. If login can be taken care of by above flow, it would be nice to take them directly where we want them to be.
http://localhost:8088/login?username=admin&redirect=/superset/dashboard/world_health/#The above url will auto login as admin and take the user directly into the world_health dashboard
Next steps
- The flow that we discussed is to demonstrate the possibility of a custom security layer and how to get it working.
- If we pass username param in request it will bypass the login and take the user inside.
- We need to make the authentication more stringent. On top of the above flow, based on the ecosystem, we could use a JWT token or other means in the CustomSecurity layer.
Superset users still remains in Superset
- This approach doesn’t eradicate superset’s user management, authorization flow (roles) etc.,
- It embraces flask appbuilder’s user management
- When creating a user in our application, we need to call REST API exposed by flask to create equivalent user with same username in superset
- Also assign the roles in superset with REST API programmatically.
- This way superset manages it’s own internal flows as it is and other micro services can integrate easily with superset
- This also give lot of flexibility on controlling which dashboards should be visible to which user etc., inline with superset’s way of role management
Overriding Superset html templates
At times, changing superset’s UI (html template) becomes a need. It is little tricky to narrow down this, since out of the box, Superset doesn’t support it, to my knowledge.
One way to achieve it is by finding the path of superset templates directory and mounting our changes as volume
- In the above example, we override the navbar.html inside superset with our own content
- the path to superset, while we used the above docker image, happened to be
/usr/local/lib/python3.5/dist-package/superset/templates/...
Ensure this is the path in your case.
Public dashboards
This is not meant for production. It’s for experiments or while doing a proof of concept.
#superset_config.py
PUBLIC_ROLE_LIKE_GAMMA = True
After this, we need to re-run the init user (if already run)
> docker-compose exec superset superset-init
Dashboards & charts can be embedded without superset header (Nav bar etc) by adding standalone=true
parameter to the url, like this :
http://localhost:9000/superset/dashboard/world_health/?standalone=true
We need to grant database source permissions to public role for the data to be visible.
Problems running behind NGINX
After spending too much time to find a way to make Superset work behind NGINX, found:
- Superset uses muliple static file references (/static/…/…js & css) without taking base url conventions
- Superset will only work when it is loaded in a root path (
/
) - Superset supports
url_for
way of configuring baseUrl. But this is implemented well only on the backend python layer. It is not well implemented on frontend (Javascript) layer. There are areas where they do things like the following which breaks:
// Builds a dataTable from a flask appbuilder api endpoint
let url = '/' + modelView.toLowerCase() + '/api/read';
Detailed Github issue discussion on this topic:
CORS Issue
If we try to embed superset dashboard into another application, we might face CORS issue. For quick experiments., we could use following Chrome extension —
This article describes other ways of solving CORS issue —
Superset base url issue
Andrey Mikhailov — responded to this article with a patch. I believe, it might be useful to others. While trying to implement custom authentication with JWT, he ran into issues with custom path e.g. /analytics/
. His patched superset is available here — https://github.com/andrey-mikhailov/superset-custom-path. Thanks Andrey Mikhailov