Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added multi-tenancy support. #3729

Closed
wants to merge 1 commit into from
Closed

Conversation

thakur00mayank
Copy link

Issue: #1089

To achieve multi-tenancy:

  1. set "ENABLE_MULTI_TENANCY = True" in superset_config file.
  2. add column tenant_id String(256) in the tables or views in which you want multi-tenancy.
  3. if you are adding the multi-tenancy in existing project then
    make sure that ab_user table have the column tenant_id else alter the table.
  4. if you want to enable multi-tenancy with CUSTOM_SECURITY_MANAGER,
    then your custom security manager class should be a subclass of MultiTenantSecurityManager class.

Added the documentation for multi-tenancy.

Fixed few typing errors. Also remove tenant_id from user view.
Fixes few test cases and role update api to support the custom user model.

Issue: apache#1089

To achieve multi-tenancy:
1. set "ENABLE_MULTI_TENANCY = True" in superset_config file.
2. add column tenant_id String(256) in the tables or views in which you want multi-tenancy.
3. if you are adding the multi-tenancy in existing project then
   make sure that ab_user table have the column tenant_id else alter the table.
4. if you want to enable multi-tenancy with CUSTOM_SECURITY_MANAGER,
   then your custom security manager class should be a subclass of MultiTenantSecurityManager class.

Added the documentation for multi-tenancy.

Fixed few typing errors. Also remove tenant_id from user view.
Fixes few test cases and role update api to support the custom user model.
@coveralls
Copy link

coveralls commented Oct 27, 2017

Coverage Status

Coverage decreased (-0.06%) to 71.21% when pulling 5a063f3 on Altizon:altizon into cbd0107 on apache:master.

@thakur00mayank
Copy link
Author

The coverage is decreased because multi-tenancy featured is used based on configuration. By default, multi-tenancy is not enabled, so test cases don't hit the newly added lines for multitenancy.
@xrmx and @mistercrunch can you please let me know whether this pull request is going to be accepted or I have to do some changes. Please suggest me the required changes if there is any.

@xrmx
Copy link
Contributor

xrmx commented Nov 3, 2017

How do you know it works without tests?

@thakur00mayank
Copy link
Author

I have tested it locally by setting "ENABLE_MULTI_TENANCY = True" in superset_config file and making slices from the datasource which have the tenant_id as one of its columns. If datasource does not have the column tenant_id, then tenant filter is not applied for slices made from this datasource.

@rahulsingh303
Copy link

I tried doing this , it doesn't work , anyone was able to do this successfully ? Idea is that , this should solve the issue of dynamic data level filtering on user login.

@thakur00mayank
Copy link
Author

For us, it is working. Can you please tell us what steps you have taken to achieve this(please mention whether you are doing it in the existing project or new one).

@rahulsingh303
Copy link

I used the file which you have changed to achieve this (init.py , security.py...etc) and used in my latest version of superset . All the views are broken with this error get_sqla_query() got an unexpected keyword argument 'form_data' . I believe somehow I need to download all the files from your commit tree , but am unable to do that . Is there a way to get all the files in your commit tree ?

@codigoscupom
Copy link

this was built on top of a deprecated endpoint (update_role).
#4041
See the commit on core.py
https://github.com/apache/incubator-superset/pull/3729/files#diff-ac978615a4f22c4fad4d01f39e1d4595

So, you would probably need to adapt it to the current superset version.

@thakur00mayank
Copy link
Author

Thanks, @neilsoncarlos for pointing out the new changes. I will soon do the required changes. and update the pull request.

@joaomg
Copy link

joaomg commented May 18, 2018

@thakur00mayank I'm interested in multi-tenancy, you need help on making the changes?

@codigoscupom
Copy link

codigoscupom commented Oct 24, 2018

if you follow the steps above you will end up with a:

File "C:\dev\superset\lib\site-packages\superset_init_.py", line 19, in
from superset.multi_tenant import MultiTenantSecurityManager
File "C:\dev\superset\lib\site-packages\superset\multi_tenant.py", line 8, in
....
"Can't place table_args on an inherited class "
sqlalchemy.exc.ArgumentError: Can't place table_args on an inherited class with no table.

Did anyone else try to implement this?

Copy link
Member

@mistercrunch mistercrunch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need a database migration that adds tenant_id to all relevant tables (happy to discuss if you disagree). We probably want to do this using a MultiTenantModelMixin simple class that adds the field and perhaps a is_user_tenant method and/or other utility method. There may be a way to force a filter based on tenant_id in the query method (call super and force-apply a tenant_id filter in the SQLAlchemy method itself).

I think it's good for the database structure to be homogenous across all Superset installs as opposed to creating columns manually / conditionally. Personally I'd rather have an unused tenant_id column than conditions around whether the column exists or not.

I think this solution is incomplete where we'll need a new TenantAdmin role that allows tenants to manage their own rights limited their scope. I think there might also be a need to not expose the Superset database itself in SQL Lab itself. Sounds like we need to de-couple the examples database connection from the main database itself.

from flask_appbuilder import Model
from flask_appbuilder.security.views import UserDBModelView
from flask_babel import lazy_gettext

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIT: our linter / PEP8 likes 2 empty lines before method and class definition. To lint locally, run flake8 superset/ from the root of the repo

# This will add multi tenant support in user model
class MultiTenantSecurityManager(SecurityManager):
user_model = MultiTenantUser
userdbmodelview = MultiTenantUserDBModelView
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIT: missing return char

@mistercrunch
Copy link
Member

Disregard the comment about overriding query, that's a method of SQLAlchemy's session object, not the Model object. There must be a Model method that we can override though where we can force a predicate (filter) on tenant_id when in multi-tenant mode.

@kristw kristw added the inactive Inactive for >= 30 days label Jan 23, 2019
@stale stale bot closed this Apr 10, 2019
@ksaagariconic
Copy link
Contributor

Hello there, is there a reason that this feature has not been merged to master or is there someone else working on refactoring and making this better? Just keen to know, so that we can work on it and contribute from our end if any one has a use case. Alternatively, keen on not reinventing the wheel if someone has found a workaround for this. Thanks!

@yonatanpc
Copy link

Hello there, is there a reason that this feature has not been merged to master or is there someone else working on refactoring and making this better? Just keen to know, so that we can work on it and contribute from our end if any one has a use case. Alternatively, keen on not reinventing the wheel if someone has found a workaround for this. Thanks!

Same here, we are reviewing Superset and multi-tenancy is a must have for us.. Thanks in advance.

@holdenrehg
Copy link

I'm interested in a multi-tenant setup as well.

Happy to help if there are details on what work is remaining here.

@thewoodenshoe
Copy link

Any updates on this, I'm interested in this as well.

@mistercrunch
Copy link
Member

We don't think this is the right approach, and it turns out making Superset multitenant with strong security/isolation guarantees isn't easy. This would require a SIP (Superset Improvement Proposal) with a detailed plan.

Also to be discussed is whether we'd want to do schema-level multitenancy or row-level. Row-level seems like the right approach, but would have to be baked deeply in the app. That's hard to do as an afterthought, and especially given the fact that FAB is not tenant aware. Making FAB tenant-aware may be part of the solution.

@mohammedhassant
Copy link

if you follow the steps above you will end up with a:

File "C:\dev\superset\lib\site-packages\superset_init_.py", line 19, in
from superset.multi_tenant import MultiTenantSecurityManager
File "C:\dev\superset\lib\site-packages\superset\multi_tenant.py", line 8, in
....
"Can't place table_args on an inherited class "
sqlalchemy.exc.ArgumentError: Can't place table_args on an inherited class with no table.

I get the same, is anyone find the solution for this error

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
inactive Inactive for >= 30 days
Projects
None yet
Development

Successfully merging this pull request may close these issues.