mirror of https://github.com/apache/superset.git
402 lines
18 KiB
Plaintext
402 lines
18 KiB
Plaintext
---
|
||
title: Configuring Superset
|
||
hide_title: true
|
||
sidebar_position: 1
|
||
version: 1
|
||
---
|
||
|
||
# Configuring Superset
|
||
|
||
## superset_config.py
|
||
|
||
Superset exposes hundreds of configurable parameters through its
|
||
[config.py module](https://github.com/apache/superset/blob/master/superset/config.py). The
|
||
variables and objects exposed act as a public interface of the bulk of what you may want
|
||
to configure, alter and interface with. In this python module, you'll find all these
|
||
parameters, sensible defaults, as well as rich documentation in the form of comments
|
||
|
||
To configure your application, you need to create you own configuration module, which
|
||
will allow you to override few or many of these parameters. Instead of altering the core module,
|
||
You'll want to define your own module (typically a file named `superset_config.py`.
|
||
Add this file to your `PYTHONPATH` or create an environment variable
|
||
`SUPERSET_CONFIG_PATH` specifying the full path of the `superset_config.py`.
|
||
|
||
For example, if deploying on Superset directly on a Linux-based system where your
|
||
`superset_config.py` is under `/app` directory, you can run:
|
||
|
||
```bash
|
||
export SUPERSET_CONFIG_PATH=/app/superset_config.py
|
||
```
|
||
|
||
If you are using your own custom Dockerfile with official Superset image as base image,
|
||
then you can add your overrides as shown below:
|
||
|
||
```bash
|
||
COPY --chown=superset superset_config.py /app/
|
||
ENV SUPERSET_CONFIG_PATH /app/superset_config.py
|
||
```
|
||
|
||
Docker compose deployments handle application configuration differently using specific conventions..
|
||
Refer to the [docker-compose tips & configuration](/docs/installation/docker-compose#docker-compose-tips--configuration)
|
||
for details.
|
||
|
||
The following is an example of just a few of the parameters you can set in your `superset_config.py` file:
|
||
|
||
```
|
||
# Superset specific config
|
||
ROW_LIMIT = 5000
|
||
|
||
# Flask App Builder configuration
|
||
# Your App secret key will be used for securely signing the session cookie
|
||
# and encrypting sensitive information on the database
|
||
# Make sure you are changing this key for your deployment with a strong key.
|
||
# Alternatively you can set it with `SUPERSET_SECRET_KEY` environment variable.
|
||
# You MUST set this for production environments or the server will refuse
|
||
# to start and you will see an error in the logs accordingly.
|
||
SECRET_KEY = 'YOUR_OWN_RANDOM_GENERATED_SECRET_KEY'
|
||
|
||
# The SQLAlchemy connection string to your database backend
|
||
# This connection defines the path to the database that stores your
|
||
# superset metadata (slices, connections, tables, dashboards, ...).
|
||
# Note that the connection information to connect to the datasources
|
||
# you want to explore are managed directly in the web UI
|
||
# The check_same_thread=false property ensures the sqlite client does not attempt
|
||
# to enforce single-threaded access, which may be problematic in some edge cases
|
||
SQLALCHEMY_DATABASE_URI = 'sqlite:////path/to/superset.db?check_same_thread=false'
|
||
|
||
# Flask-WTF flag for CSRF
|
||
WTF_CSRF_ENABLED = True
|
||
# Add endpoints that need to be exempt from CSRF protection
|
||
WTF_CSRF_EXEMPT_LIST = []
|
||
# A CSRF token that expires in 1 year
|
||
WTF_CSRF_TIME_LIMIT = 60 * 60 * 24 * 365
|
||
|
||
# Set this API key to enable Mapbox visualizations
|
||
MAPBOX_API_KEY = ''
|
||
```
|
||
|
||
:::tip
|
||
Note that it is typical to copy and paste [only] the portions of the
|
||
core [superset/config.py](https://github.com/apache/superset/blob/master/superset/config.py) that
|
||
you want to alter, along with the related comments into your own `superset_config.py` file.
|
||
:::
|
||
|
||
All the parameters and default values defined
|
||
in [superset/config.py](https://github.com/apache/superset/blob/master/superset/config.py)
|
||
can be altered in your local `superset_config.py`. Administrators will want to read through the file
|
||
to understand what can be configured locally as well as the default values in place.
|
||
|
||
Since `superset_config.py` acts as a Flask configuration module, it can be used to alter the
|
||
settings Flask itself, as well as Flask extensions that Superset bundles like
|
||
`flask-wtf`, `flask-caching`, `flask-migrate`,
|
||
and `flask-appbuilder`. Each one of these extensions offers intricate configurability.
|
||
Flask App Builder, the web framework used by Superset, also offers many
|
||
configuration settings. Please consult the
|
||
[Flask App Builder Documentation](https://flask-appbuilder.readthedocs.org/en/latest/config.html)
|
||
for more information on how to configure it.
|
||
|
||
You'll want to change:
|
||
|
||
- `SECRET_KEY`: to a long random string
|
||
- `SQLALCHEMY_DATABASE_URI`: that by default points to sqlite database located at
|
||
~/.superset/superset.db
|
||
|
||
```
|
||
WTF_CSRF_EXEMPT_LIST = [‘’]
|
||
```
|
||
|
||
## Specifying a SECRET_KEY
|
||
|
||
### Adding an initial SECRET_KEY
|
||
|
||
Superset requires a user-specified SECRET_KEY to start up. This requirement was [added in version 2.1.0 to force secure configurations](https://preset.io/blog/superset-security-update-default-secret_key-vulnerability/). Add a strong SECRET_KEY to your `superset_config.py` file like:
|
||
|
||
```python
|
||
SECRET_KEY = 'YOUR_OWN_RANDOM_GENERATED_SECRET_KEY'
|
||
```
|
||
|
||
You can generate a strong secure key with `openssl rand -base64 42`.
|
||
|
||
:::caution Use a strong secret key
|
||
This key will be used for securely signing session cookies and encrypting sensitive information stored in Superset's application metadata database.
|
||
Your deployment must use a complex, unique key.
|
||
:::
|
||
|
||
### Rotating to a newer SECRET_KEY
|
||
|
||
If you wish to change your existing SECRET_KEY, add the existing SECRET_KEY to your `superset_config.py` file as
|
||
`PREVIOUS_SECRET_KEY = `and provide your new key as `SECRET_KEY =`. You can find your current SECRET_KEY with these
|
||
commands - if running Superset with Docker, execute from within the Superset application container:
|
||
|
||
```python
|
||
superset shell
|
||
from flask import current_app; print(current_app.config["SECRET_KEY"])
|
||
```
|
||
|
||
Save your `superset_config.py` with these values and then run `superset re-encrypt-secrets`.
|
||
|
||
## Setting up a production metadata database
|
||
|
||
Superset needs a database to store the information it manages, like the definitions of
|
||
charts, dashboards, and many other things.
|
||
|
||
By default, Superset is configured to use [SQLite](https://www.sqlite.org/),
|
||
a self-contained, single-file database that offers a simple and fast way to get started
|
||
(without requiring any installation). However, for production environments,
|
||
using SQLite is highly discouraged due to security, scalability, and data integrity reasons.
|
||
It's important to use only the supported database engines and consider using a different
|
||
database engine on a separate host or container.
|
||
|
||
Superset supports the following database engines/versions:
|
||
|
||
| Database Engine | Supported Versions |
|
||
| ----------------------------------------- | ---------------------------------- |
|
||
| [PostgreSQL](https://www.postgresql.org/) | 10.X, 11.X, 12.X, 13.X, 14.X, 15.X |
|
||
| [MySQL](https://www.mysql.com/) | 5.7, 8.X |
|
||
|
||
Use the following database drivers and connection strings:
|
||
|
||
| Database | PyPI package | Connection String |
|
||
| ----------------------------------------- | ------------------------- | ---------------------------------------------------------------------- |
|
||
| [PostgreSQL](https://www.postgresql.org/) | `pip install psycopg2` | `postgresql://<UserName>:<DBPassword>@<Database Host>/<Database Name>` |
|
||
| [MySQL](https://www.mysql.com/) | `pip install mysqlclient` | `mysql://<UserName>:<DBPassword>@<Database Host>/<Database Name>` |
|
||
|
||
:::tip
|
||
Properly setting up metadata store is beyond the scope of this documentation. We recommend
|
||
using a hosted managed service such as [Amazon RDS](https://aws.amazon.com/rds/) or
|
||
[Google Cloud Databases](https://cloud.google.com/products/databases?hl=en) to handle
|
||
service and supporting infrastructure and backup strategy.
|
||
:::
|
||
|
||
To configure Superset metastore set `SQLALCHEMY_DATABASE_URI` config key on `superset_config`
|
||
to the appropriate connection string.
|
||
|
||
## Running on a WSGI HTTP Server
|
||
|
||
While you can run Superset on NGINX or Apache, we recommend using Gunicorn in async mode. This
|
||
enables impressive concurrency even and is fairly easy to install and configure. Please refer to the
|
||
documentation of your preferred technology to set up this Flask WSGI application in a way that works
|
||
well in your environment. Here’s an async setup known to work well in production:
|
||
|
||
```
|
||
-w 10 \
|
||
-k gevent \
|
||
--worker-connections 1000 \
|
||
--timeout 120 \
|
||
-b 0.0.0.0:6666 \
|
||
--limit-request-line 0 \
|
||
--limit-request-field_size 0 \
|
||
--statsd-host localhost:8125 \
|
||
"superset.app:create_app()"
|
||
```
|
||
|
||
Refer to the [Gunicorn documentation](https://docs.gunicorn.org/en/stable/design.html) for more
|
||
information. _Note that the development web server (`superset run` or `flask run`) is not intended
|
||
for production use._
|
||
|
||
If you're not using Gunicorn, you may want to disable the use of `flask-compress` by setting
|
||
`COMPRESS_REGISTER = False` in your `superset_config.py`.
|
||
|
||
Currently, Google BigQuery python sdk is not compatible with `gevent`, due to some dynamic monkeypatching on python core library by `gevent`.
|
||
So, when you use `BigQuery` datasource on Superset, you have to use `gunicorn` worker type except `gevent`.
|
||
|
||
## HTTPS Configuration
|
||
|
||
You can configure HTTPS upstream via a load balancer or a reverse proxy (such as nginx) and do SSL/TLS Offloading before traffic reaches the Superset application. In this setup, local traffic from a Celery worker taking a snapshot of a chart for Alerts & Reports can access Superset at a `http://` URL, from behind the ingress point.
|
||
You can also configure [SSL in Gunicorn](https://docs.gunicorn.org/en/stable/settings.html#ssl) (the Python webserver) if you are using an official Superset Docker image.
|
||
|
||
## Configuration Behind a Load Balancer
|
||
|
||
If you are running superset behind a load balancer or reverse proxy (e.g. NGINX or ELB on AWS), you
|
||
may need to utilize a healthcheck endpoint so that your load balancer knows if your superset
|
||
instance is running. This is provided at `/health` which will return a 200 response containing “OK”
|
||
if the webserver is running.
|
||
|
||
If the load balancer is inserting `X-Forwarded-For/X-Forwarded-Proto` headers, you should set
|
||
`ENABLE_PROXY_FIX = True` in the superset config file (`superset_config.py`) to extract and use the
|
||
headers.
|
||
|
||
In case the reverse proxy is used for providing SSL encryption, an explicit definition of the
|
||
`X-Forwarded-Proto` may be required. For the Apache webserver this can be set as follows:
|
||
|
||
```
|
||
RequestHeader set X-Forwarded-Proto "https"
|
||
```
|
||
|
||
## Custom OAuth2 Configuration
|
||
|
||
Superset is built on Flask-AppBuilder (FAB), which supports many providers out of the box
|
||
(GitHub, Twitter, LinkedIn, Google, Azure, etc). Beyond those, Superset can be configured to connect
|
||
with other OAuth2 Authorization Server implementations that support “code” authorization.
|
||
|
||
Make sure the pip package [`Authlib`](https://authlib.org/) is installed on the webserver.
|
||
|
||
First, configure authorization in Superset `superset_config.py`.
|
||
|
||
```python
|
||
from flask_appbuilder.security.manager import AUTH_OAUTH
|
||
|
||
# Set the authentication type to OAuth
|
||
AUTH_TYPE = AUTH_OAUTH
|
||
|
||
OAUTH_PROVIDERS = [
|
||
{ 'name':'egaSSO',
|
||
'token_key':'access_token', # Name of the token in the response of access_token_url
|
||
'icon':'fa-address-card', # Icon for the provider
|
||
'remote_app': {
|
||
'client_id':'myClientId', # Client Id (Identify Superset application)
|
||
'client_secret':'MySecret', # Secret for this Client Id (Identify Superset application)
|
||
'client_kwargs':{
|
||
'scope': 'read' # Scope for the Authorization
|
||
},
|
||
'access_token_method':'POST', # HTTP Method to call access_token_url
|
||
'access_token_params':{ # Additional parameters for calls to access_token_url
|
||
'client_id':'myClientId'
|
||
},
|
||
'jwks_uri':'https://myAuthorizationServe/adfs/discovery/keys', # may be required to generate token
|
||
'access_token_headers':{ # Additional headers for calls to access_token_url
|
||
'Authorization': 'Basic Base64EncodedClientIdAndSecret'
|
||
},
|
||
'api_base_url':'https://myAuthorizationServer/oauth2AuthorizationServer/',
|
||
'access_token_url':'https://myAuthorizationServer/oauth2AuthorizationServer/token',
|
||
'authorize_url':'https://myAuthorizationServer/oauth2AuthorizationServer/authorize'
|
||
}
|
||
}
|
||
]
|
||
|
||
# Will allow user self registration, allowing to create Flask users from Authorized User
|
||
AUTH_USER_REGISTRATION = True
|
||
|
||
# The default user self registration role
|
||
AUTH_USER_REGISTRATION_ROLE = "Public"
|
||
```
|
||
|
||
Then, create a `CustomSsoSecurityManager` that extends `SupersetSecurityManager` and overrides
|
||
`oauth_user_info`:
|
||
|
||
```python
|
||
import logging
|
||
from superset.security import SupersetSecurityManager
|
||
|
||
class CustomSsoSecurityManager(SupersetSecurityManager):
|
||
|
||
def oauth_user_info(self, provider, response=None):
|
||
logging.debug("Oauth2 provider: {0}.".format(provider))
|
||
if provider == 'egaSSO':
|
||
# As example, this line request a GET to base_url + '/' + userDetails with Bearer Authentication,
|
||
# and expects that authorization server checks the token, and response with user details
|
||
me = self.appbuilder.sm.oauth_remotes[provider].get('userDetails').data
|
||
logging.debug("user_data: {0}".format(me))
|
||
return { 'name' : me['name'], 'email' : me['email'], 'id' : me['user_name'], 'username' : me['user_name'], 'first_name':'', 'last_name':''}
|
||
...
|
||
```
|
||
|
||
This file must be located at the same directory than `superset_config.py` with the name
|
||
`custom_sso_security_manager.py`. Finally, add the following 2 lines to `superset_config.py`:
|
||
|
||
```
|
||
from custom_sso_security_manager import CustomSsoSecurityManager
|
||
CUSTOM_SECURITY_MANAGER = CustomSsoSecurityManager
|
||
```
|
||
|
||
**Notes**
|
||
|
||
- The redirect URL will be `https://<superset-webserver>/oauth-authorized/<provider-name>`
|
||
When configuring an OAuth2 authorization provider if needed. For instance, the redirect URL will
|
||
be `https://<superset-webserver>/oauth-authorized/egaSSO` for the above configuration.
|
||
|
||
- If an OAuth2 authorization server supports OpenID Connect 1.0, you could configure its configuration
|
||
document URL only without providing `api_base_url`, `access_token_url`, `authorize_url` and other
|
||
required options like user info endpoint, jwks uri etc. For instance:
|
||
```python
|
||
OAUTH_PROVIDERS = [
|
||
{ 'name':'egaSSO',
|
||
'token_key':'access_token', # Name of the token in the response of access_token_url
|
||
'icon':'fa-address-card', # Icon for the provider
|
||
'remote_app': {
|
||
'client_id':'myClientId', # Client Id (Identify Superset application)
|
||
'client_secret':'MySecret', # Secret for this Client Id (Identify Superset application)
|
||
'server_metadata_url': 'https://myAuthorizationServer/.well-known/openid-configuration'
|
||
}
|
||
}
|
||
]
|
||
```
|
||
|
||
## LDAP Authentication
|
||
|
||
FAB supports authenticating user credentials against an LDAP server.
|
||
To use LDAP you must install the [python-ldap](https://www.python-ldap.org/en/latest/installing.html) package.
|
||
See [FAB's LDAP documentation](https://flask-appbuilder.readthedocs.io/en/latest/security.html#authentication-ldap)
|
||
for details.
|
||
|
||
## Mapping LDAP or OAUTH groups to Superset roles
|
||
|
||
AUTH_ROLES_MAPPING in Flask-AppBuilder is a dictionary that maps from LDAP/OAUTH group names to FAB roles.
|
||
It is used to assign roles to users who authenticate using LDAP or OAuth.
|
||
|
||
### Mapping OAUTH groups to Superset roles
|
||
|
||
The following `AUTH_ROLES_MAPPING` dictionary would map the OAUTH group "superset_users" to the Superset roles "Gamma" as well as "Alpha", and the OAUTH group "superset_admins" to the Superset role "Admin".
|
||
|
||
```python
|
||
AUTH_ROLES_MAPPING = {
|
||
"superset_users": ["Gamma","Alpha"],
|
||
"superset_admins": ["Admin"],
|
||
}
|
||
```
|
||
### Mapping LDAP groups to Superset roles
|
||
|
||
The following `AUTH_ROLES_MAPPING` dictionary would map the LDAP DN "cn=superset_users,ou=groups,dc=example,dc=com" to the Superset roles "Gamma" as well as "Alpha", and the LDAP DN "cn=superset_admins,ou=groups,dc=example,dc=com" to the Superset role "Admin".
|
||
|
||
```python
|
||
AUTH_ROLES_MAPPING = {
|
||
"cn=superset_users,ou=groups,dc=example,dc=com": ["Gamma","Alpha"],
|
||
"cn=superset_admins,ou=groups,dc=example,dc=com": ["Admin"],
|
||
}
|
||
```
|
||
Note: This requires `AUTH_LDAP_SEARCH` to be set. For more details, please see the [FAB Security documentation](https://flask-appbuilder.readthedocs.io/en/latest/security.html).
|
||
|
||
### Syncing roles at login
|
||
|
||
You can also use the `AUTH_ROLES_SYNC_AT_LOGIN` configuration variable to control how often Flask-AppBuilder syncs the user's roles with the LDAP/OAUTH groups. If `AUTH_ROLES_SYNC_AT_LOGIN` is set to True, Flask-AppBuilder will sync the user's roles each time they log in. If `AUTH_ROLES_SYNC_AT_LOGIN` is set to False, Flask-AppBuilder will only sync the user's roles when they first register.
|
||
|
||
## Flask app Configuration Hook
|
||
|
||
`FLASK_APP_MUTATOR` is a configuration function that can be provided in your environment, receives
|
||
the app object and can alter it in any way. For example, add `FLASK_APP_MUTATOR` into your
|
||
`superset_config.py` to setup session cookie expiration time to 24 hours:
|
||
|
||
```python
|
||
from flask import session
|
||
from flask import Flask
|
||
|
||
|
||
def make_session_permanent():
|
||
'''
|
||
Enable maxAge for the cookie 'session'
|
||
'''
|
||
session.permanent = True
|
||
|
||
# Set up max age of session to 24 hours
|
||
PERMANENT_SESSION_LIFETIME = timedelta(hours=24)
|
||
def FLASK_APP_MUTATOR(app: Flask) -> None:
|
||
app.before_request_funcs.setdefault(None, []).append(make_session_permanent)
|
||
```
|
||
|
||
## Feature Flags
|
||
|
||
To support a diverse set of users, Superset has some features that are not enabled by default. For
|
||
example, some users have stronger security restrictions, while some others may not. So Superset
|
||
allow users to enable or disable some features by config. For feature owners, you can add optional
|
||
functionalities in Superset, but will be only affected by a subset of users.
|
||
|
||
You can enable or disable features with flag from `superset_config.py`:
|
||
|
||
```python
|
||
FEATURE_FLAGS = {
|
||
'PRESTO_EXPAND_DATA': False,
|
||
}
|
||
```
|
||
|
||
A current list of feature flags can be found in [RESOURCES/FEATURE_FLAGS.md](https://github.com/apache/superset/blob/master/RESOURCES/FEATURE_FLAGS.md).
|