We have earlier seen how to set up SSO with any identity system that you may have in your organization here: Customizing Superset For Turbo Forms: Single Sign On (SSO) and how we achieved multi-tenancy with Superset. In this concluding part, we will look at auto-provisioning “tenants” or customers and putting it all together.
Note: Unlike the other blogs, this is more technical and requires basic Python coding skills.
Recall that for multi-tenancy we leverage Superset Row Level Security, Dashboard Role-Based Access (RBAC), and custom roles to provide access to databases and dashboards for specific tenants. More specifically we need to create tenant (customer) specific roles and provide access to the required databases and dashboards so that the users who are auto-provisioned via the SSO process (refer to the 2nd blog) can be attached to these roles.
The interface requirement is that when a new tenant is provisioned in TurboApps we need to also provide the roles in Superset with the appropriate access rights. So how do we go about doing this?
We need to create a Python / Flask API class. Refer to the Flask ApBuider documentation for more details. Some snippets to help find your way are provided below. The steps are
- Create the schema (data to be passed to the API)
- Create the API
- Setup the restrictions
- Run superset inits to generate the required permissions for the roles
Schema: For the provisioning API that TurboApps requires only the tenant id and if it’s a shared database instance or a dedicated instance.
Read Part 1: Selecting An Analytics Solution For Turbo Forms
The schema defines a company (tenant id) and if the DB instance is dedicated or shared. This input will be used in the API definition.
API: Let’s now define the provisioning API.
So quite a few things happening here:
- API class TurboAppsApi extends BaseApi and defines the endpoint provision company
- Accepts provision_schema as input
- Protects the API so that only specified roles who have this permission are allowed to execute it
- Required modules like Database, RowLevelSecurityFilter, Dashboard, etc are imported
- Retrieve the companyid from the passed arguments
- The subsequent code has not been provided for the sake of simplicity. The other activities are basically to:
a. Check if the tenant already exists
b. Create the roles for Admin, Manager, and User
c. Provide access to the required databases for the roles
d. Create the RLS
e. Attach the RLS to the roles
7. A good way to develop your specific need is to look at the Superset API docs and Github code to understand the APIs available and ways to utilize them.
Now that we have the API we need to “glue” it to the Superset app in a way that upgrades to Superset don’t break it.
Also Read: Unvired Mobile Platform: Database Connector
Create the module file: Create the __init__.py module file and add the similar content as below.
We are in effect defining a custom initializer for the FlaskApp. We make sure the default initialization happens by invoking super() and then adding the imported TurboAppsApi to the AppBulder. The custom API will now get included in the Superset app. There is however the last step still to glue the initialization class.
superset_config.py to the rescue: Remember that we configured a lot of stuff in our custom superset_config.py and configured our CUSTOM_SECURITY_MANAGER for the SSO. Open that up and add the following to it:
- To ensure that upgrades do not affect the custom code, I have placed the code in a module called Unvired in the superset config folder. Hence the path_to_superset_config is appended to the sys path.
- Then we import the TurboAppInitializer and set the APP_INITIALIZER to it
That’s it, not run superset init, and then start it up and hit the endpoint to get it all going.
Putting it all together:
- Place the superset_config.py file with the required settings in a folder.
- Configure the environment to point to the superset_config.py file
- Create the required module in the same folder and the required python code.
- Run superset inits to create the required permission for the custom API module
- Integrate the call into your system for auto-provisioning
Hopefully, this gives the right hints to setting up Superset according to your custom needs. Feel free to reach out to me via https://unvired.com/contact if you need any additional information. Thanks for reading and do provide your feedback via the same link.