Superset is a great application, although it has usage limitations in my company, as it doesn’t allow to set row-level security for the users. Regional users should see the data of their region only, in my case; others must have access to several regions or to all of them. We have 82 regions, so it’s pointless and excessive to make dashboard or data source for each of them.
I have been thinking about this problem for a very long time. I have set reverse proxy OpenResty (Nginx+LUA) before Superset eventually. Now I can intercept users’ requests and check region filters set. It’s not difficult to write the procedure, that will check whether the user have the access to that region or not, if not he will be redirected to the web page saying «The access is denied». The problem is that I need to know from which user the request was sent. Is there any opportunity to configure Superset in such a way so that Gunicorn will send in the http header the user’s name to OpenRestry?
And I’d like to know how Superset community that experienced this problem have solved it.
We have a similar use case using Druid. We did consider the Proxy route where we would modify the Druid query with a extension. However, we are currently testing passing into Superset as part of authentication/authorization specific user-defined variables (analogous to your "Region"). These can be defined in a custom superset-config.py. Once passed, the idea would be to eedit or extend the base Views to force a filter clause. In our case the Druid issued query would have a FILTER applied so the user would see his/her relevant "records". This is the general idea but something we are trying since Druid expects the application layer to define this. I do agree this is something that would be great if it were standard.
@ahsanshah good day! Thank you for your answer, but could you specify what do you mean saying “specific user-defined variables”. Can you show how you did it? Where can I find such an example?
Your idea with View is very interesting, but how can I see which user sent the query to set the relevant filter? Do you create View for each Region (in my case)? If so this variant doesn’t suit me unfortunately.
I will solve the problem with the use of Proxy or View easily but I don’t know how to get the user login, that sent the query?
So much of this depends on how you are directing your users to Superset from the external context (e.g. LDAP, SAML, etc). The idea would be on the login (from an external context) you would set a specific USER "Session" value, for example "Region" and that would be defined in some data store outside of Superset. This would then be a variable you can use in viz.py. By doing this, upon login a user would have a set of "session variables" which can then be used with a customized "Gamma" role in Flask App Builder. You would then "restrict"outbound queries to filter per the logic you need. E.g user A belonging to Region X would default all outbound queries to have that condition in the payload. As i mentioned, this is an approach we are evaluating but I recommend you work with your team on how users are defined in your organization and how they may be planning to integrate.
I’ve found the way how to change http-header, for this purpose you need to add in config.py:
from flask import session
class CustomHeaderMiddleware(object):
def __init__(self, app):
self.app = app
def __call__(self, environ, start_response):
def custom_start_response(status, headers, exc_info=None):
if "user_id" in session:
headers.append(('user_id, session["user_id"]))
else:
headers.append(('user_id', '0'))
return start_response(status, headers, exc_info)
return self.app(environ, custom_start_response)
ADDITIONAL_MIDDLEWARE = [CustomHeaderMiddleware,]
I'm thinking that the proper way to for row-level-security is to introduce a new model ForcedPredicate that would be attached to datasources and roles (many to many).
Then at query time somehow add this filter(s) to the query if its associated with one of the user's roles.
Agree with this @mistercrunch, right now I think people are working around these via various hacks (Security/Roles or Reverse Proxy, etc). A common framework would indeed allow a more cross-department or data sensitive use cases.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. For admin, please label this issue .pinned to prevent stale bot from closing the issue.
This is still an issue and should be .pinned or else have a more specific issue spun off
Most helpful comment
Agree with this @mistercrunch, right now I think people are working around these via various hacks (Security/Roles or Reverse Proxy, etc). A common framework would indeed allow a more cross-department or data sensitive use cases.