| --- |
| title: Security Configurations |
| sidebar_position: 1 |
| --- |
| |
| Authentication and authorization in Superset is handled by Flask AppBuilder (FAB), an application development framework |
| built on top of Flask. FAB provides authentication, user management, permissions and roles. |
| Please read its [Security documentation](https://flask-appbuilder.readthedocs.io/en/latest/security.html). |
| |
| ### Provided Roles |
| |
| Superset ships with a set of roles that are handled by Superset itself. You can assume |
| that these roles will stay up-to-date as Superset evolves (and as you update Superset versions). |
| |
| Even though **Admin** users have the ability, we don't recommend altering the |
| permissions associated with each role (e.g. by removing or adding permissions to them). The permissions |
| associated with each role will be re-synchronized to their original values when you run |
| the **superset init** command (often done between Superset versions). |
| |
| A table with the permissions for these roles can be found at [/RESOURCES/STANDARD_ROLES.md](https://github.com/apache/superset/blob/master/RESOURCES/STANDARD_ROLES.md). |
| |
| ### Admin |
| |
| Admins have all possible rights, including granting or revoking rights from other |
| users and altering other people’s slices and dashboards. |
| |
| ### Alpha |
| |
| Alpha users have access to all data sources, but they cannot grant or revoke access |
| from other users. They are also limited to altering the objects that they own. Alpha users can add and alter data sources. |
| |
| ### Gamma |
| |
| Gamma users have limited access. They can only consume data coming from data sources |
| they have been given access to through another complementary role. They only have access to |
| view the slices and dashboards made from data sources that they have access to. Currently Gamma |
| users are not able to alter or add data sources. We assume that they are mostly content consumers, though they can create slices and dashboards. |
| |
| Also note that when Gamma users look at the dashboards and slices list view, they will |
| only see the objects that they have access to. |
| |
| ### sql_lab |
| |
| The **sql_lab** role grants access to SQL Lab. Note that while **Admin** users have access |
| to all databases by default, both **Alpha** and **Gamma** users need to be given access on a per database basis. |
| |
| ### Public |
| |
| To allow logged-out users to access some Superset features, you can use the `PUBLIC_ROLE_LIKE` config setting and assign it to another role whose permissions you want passed to this role. |
| |
| For example, by setting `PUBLIC_ROLE_LIKE = "Gamma"` in your `superset_config.py` file, you grant |
| public role the same set of permissions as for the **Gamma** role. This is useful if one |
| wants to enable anonymous users to view dashboards. Explicit grant on specific datasets is |
| still required, meaning that you need to edit the **Public** role and add the public data sources to the role manually. |
| |
| ### Managing Data Source Access for Gamma Roles |
| |
| Here’s how to provide users access to only specific datasets. First make sure the users with |
| limited access have [only] the Gamma role assigned to them. Second, create a new role (Menu -> Security -> List Roles) and click the + sign. |
| |
| This new window allows you to give this new role a name, attribute it to users and select the |
| tables in the **Permissions** dropdown. To select the data sources you want to associate with this role, simply click on the dropdown and use the typeahead to search for your table names. |
| |
| You can then confirm with users assigned to the **Gamma** role that they see the |
| objects (dashboards and slices) associated with the tables you just extended them. |
| |
| ### SQL Execution Security Considerations |
| |
| Apache Superset includes features designed to provide safeguards when interacting with connected databases, such as the `DISALLOWED_SQL_FUNCTIONS` configuration setting. This aims to prevent the execution of potentially harmful database functions or system variables directly from Superset interfaces like SQL Lab. |
| |
| However, it is crucial to understand the following: |
| |
| **Superset is Not a Database Firewall**: Superset's built-in checks, like `DISALLOWED_SQL_FUNCTIONS`, provide a layer of protection but cannot guarantee complete security against all database-level threats or advanced bypass techniques (like specific comment injection methods). They should be viewed as a supplement to, not a replacement for, robust database security. |
| |
| **Configuration is Key**: The effectiveness of Superset's safeguards heavily depends on proper configuration by the Superset administrator. This includes maintaining the `DISALLOWED_SQL_FUNCTIONS` list, carefully managing feature flags (like `ENABLE_TEMPLATE_PROCESSING`), and configuring other security settings appropriately. |
| |
| **Database Security is Paramount**: The ultimate responsibility for securing database access, controlling permissions, and preventing unauthorized function execution lies with the database administrators (DBAs) and security teams managing the underlying database instance. |
| |
| **Recommended Database Practices**: We strongly recommend implementing security best practices at the database level, including: |
| * **Least Privilege**: Connecting Superset using dedicated database user accounts with the minimum permissions required for Superset's operation (typically read-only access to necessary schemas/tables). |
| * **Database Roles & Permissions**: Utilizing database-native roles and permissions to restrict access to sensitive functions, system variables (like `@@hostname`), schemas, or tables. |
| * **Network Security**: Employing network-level controls like database firewalls or proxies to restrict connections. |
| * **Auditing**: Enabling database-level auditing to monitor executed queries and access patterns. |
| |
| By combining Superset's configurable safeguards with strong database-level security practices, you can achieve a more robust and layered security posture. |
| |
| ### REST API for user & role management |
| |
| Flask-AppBuilder supports a REST API for user CRUD, |
| but this feature is in beta and is not enabled by default in Superset. |
| To enable this feature, set the following in your Superset configuration: |
| |
| ```python |
| FAB_ADD_SECURITY_API = True |
| ``` |
| |
| Once configured, the documentation for additional "Security" endpoints will be visible in Swagger for you to explore. |
| |
| ### Customizing Permissions |
| |
| The permissions exposed by FAB are very granular and allow for a great level of |
| customization. FAB creates many permissions automatically for each model that is |
| created (can_add, can_delete, can_show, can_edit, …) as well as for each view. |
| On top of that, Superset can expose more granular permissions like **all_datasource_access**. |
| |
| **We do not recommend altering the 3 base roles as there are a set of assumptions that |
| Superset is built upon**. It is possible though for you to create your own roles, and union them to existing ones. |
| |
| ### Permissions |
| |
| Roles are composed of a set of permissions, and Superset has many categories of |
| permissions. Here are the different categories of permissions: |
| |
| - Model & Action: models are entities like Dashboard, Slice, or User. Each model has |
| a fixed set of permissions, like **can_edit**, **can_show**, **can_delete**, **can_list**, **can_add**, |
| and so on. For example, you can allow a user to delete dashboards by adding **can_delete** on |
| Dashboard entity to a role and granting this user that role. |
| - Views: views are individual web pages, like the Explore view or the SQL Lab view. |
| When granted to a user, they will see that view in its menu items, and be able to load that page. |
| - Data source: For each data source, a permission is created. If the user does not have the |
| `all_datasource_access permission` granted, the user will only be able to see Slices or explore the data sources that are granted to them |
| - Database: Granting access to a database allows for the user to access all |
| data sources within that database, and will enable the user to query that |
| database in SQL Lab, provided that the SQL Lab specific permission have been granted to the user |
| |
| ### Restricting Access to a Subset of Data Sources |
| |
| We recommend giving a user the **Gamma** role plus any other roles that would add |
| access to specific data sources. We recommend that you create individual roles for |
| each access profile. For example, the users on the Finance team might have access to a set of |
| databases and data sources; these permissions can be consolidated in a single role. |
| Users with this profile then need to be assigned the **Gamma** role as a foundation to |
| the models and views they can access, and that Finance role that is a collection of permissions to data objects. |
| |
| A user can have multiple roles associated with them. For example, an executive on the Finance |
| team could be granted **Gamma**, **Finance**, and the **Executive** roles. The **Executive** |
| role could provide access to a set of data sources and dashboards made available only to executives. |
| In the **Dashboards** view, a user can only see the ones they have access to |
| based on the roles and permissions that were attributed. |
| |
| ### Row Level Security |
| |
| Using Row Level Security filters (under the **Security** menu) you can create filters |
| that are assigned to a particular table, as well as a set of roles. |
| If you want members of the Finance team to only have access to |
| rows where `department = "finance"`, you could: |
| |
| - Create a Row Level Security filter with that clause (`department = "finance"`) |
| - Then assign the clause to the **Finance** role and the table it applies to |
| |
| The **clause** field, which can contain arbitrary text, is then added to the generated |
| SQL statement’s WHERE clause. So you could even do something like create a filter |
| for the last 30 days and apply it to a specific role, with a clause |
| like `date_field > DATE_SUB(NOW(), INTERVAL 30 DAY)`. It can also support |
| multiple conditions: `client_id = 6` AND `advertiser="foo"`, etc. |
| |
| All relevant Row level security filters will be combined together (under the hood, |
| the different SQL clauses are combined using AND statements). This means it's |
| possible to create a situation where two roles conflict in such a way as to limit a table subset to empty. |
| |
| For example, the filters `client_id=4` and `client_id=5`, applied to a role, |
| will result in users of that role having `client_id=4` AND `client_id=5` |
| added to their query, which can never be true. |
| |
| ### User Sessions |
| |
| Superset uses [Flask](https://pypi.org/project/Flask/) |
| and [Flask-Login](https://pypi.org/project/Flask-Login/) for user session management. |
| |
| Session cookies are used to maintain session info and user state between requests, |
| although they do not contain personal user information they serve the purpose of identifying |
| a user session on the server side. |
| The session cookie is encrypted with the application `SECRET_KEY` and cannot be read by the client. |
| So it's very important to keep the `SECRET_KEY` secret and set to a secure unique complex random value. |
| |
| Flask and Flask-Login offer a number of configuration options to control session behavior. |
| |
| - Relevant Flask settings: |
| |
| `SESSION_COOKIE_HTTPONLY`: (default: `False`): Controls if cookies should be set with the `HttpOnly` flag. |
| |
| `SESSION_COOKIE_SECURE`: (default: `False`) Browsers will only send cookies with requests over |
| HTTPS if the cookie is marked “secure”. The application must be served over HTTPS for this to make sense. |
| |
| `SESSION_COOKIE_SAMESITE`: (default: "Lax") Prevents the browser from sending this cookie along with cross-site requests. |
| |
| `PERMANENT_SESSION_LIFETIME`: (default: "31 days") The lifetime of a permanent session as a `datetime.timedelta` object. |
| |
| #### Switching to server side sessions |
| |
| Server side sessions offer benefits over client side sessions on security and performance. |
| By enabling server side sessions, the session data is stored server side and only a session ID |
| is sent to the client. When a user logs in, a session is created server side and the session ID |
| is sent to the client in a cookie. The client will send the session ID with each request and the |
| server will use it to retrieve the session data. |
| On logout, the session is destroyed server side and the session cookie is deleted on the client side. |
| This reduces the risk for replay attacks and session hijacking. |
| |
| Superset uses [Flask-Session](https://flask-session.readthedocs.io/en/latest/) to manage server side sessions. |
| To enable this extension you have to set: |
| |
| ``` python |
| SESSION_SERVER_SIDE = True |
| ``` |
| |
| Flask-Session offers multiple backend session interfaces for Flask, here's an example for Redis: |
| |
| ``` python |
| from redis import Redis |
| |
| SESSION_TYPE = "redis" |
| SESSION_REDIS = Redis(host="redis", port=6379, db=0) |
| # sign the session cookie sid |
| SESSION_USE_SIGNER = True |
| ``` |
| |
| ### Content Security Policy (CSP) |
| |
| Superset uses the [Talisman](https://pypi.org/project/flask-talisman/) extension to enable implementation of a |
| [Content Security Policy (CSP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP), an added |
| layer of security that helps to detect and mitigate certain types of attacks, including |
| Cross-Site Scripting (XSS) and data injection attacks. |
| |
| A CSP makes it possible for server administrators to reduce or eliminate the vectors by which XSS can |
| occur by specifying the domains that the browser should consider to be valid sources of executable scripts. |
| A CSP-compatible browser will then only execute scripts loaded in source files received from those allowed domains, |
| ignoring all other scripts (including inline scripts and event-handling HTML attributes). |
| |
| A policy is described using a series of policy directives, each of which describes the policy for |
| a certain resource type or policy area. You can check possible directives |
| [here](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy). |
| |
| It's extremely important to correctly configure a Content Security Policy when deploying Superset to |
| prevent many types of attacks. Superset provides two variables in `config.py` for deploying a CSP: |
| |
| - `TALISMAN_ENABLED` defaults to `True`; set this to `False` in order to disable CSP |
| - `TALISMAN_CONFIG` holds the actual the policy definition (*see example below*) as well as any |
| other arguments to be passed to Talisman. |
| |
| When running in production mode, Superset will check at startup for the presence |
| of a CSP. If one is not found, it will issue a warning with the security risks. For environments |
| where CSP policies are defined outside of Superset using other software, administrators can disable |
| this warning using the `CONTENT_SECURITY_POLICY_WARNING` key in `config.py`. |
| |
| #### CSP Requirements |
| |
| - Superset needs the `style-src unsafe-inline` CSP directive in order to operate. |
| |
| ``` |
| style-src 'self' 'unsafe-inline' |
| ``` |
| |
| - Only scripts marked with a [nonce](https://content-security-policy.com/nonce/) can be loaded and executed. |
| Nonce is a random string automatically generated by Talisman on each page load. |
| You can get current nonce value by calling jinja macro `csp_nonce()`. |
| |
| ```html |
| <script nonce="{{ csp_nonce() }}"> |
| /* my script */ |
| </script> |
| ``` |
| |
| - Some dashboards load images using data URIs and require `data:` in their `img-src` |
| |
| ``` |
| img-src 'self' data: |
| ``` |
| |
| - MapBox charts use workers and need to connect to MapBox servers in addition to the Superset origin |
| |
| ``` |
| worker-src 'self' blob: |
| connect-src 'self' https://api.mapbox.com https://events.mapbox.com |
| ``` |
| |
| - Cartodiagram charts request map data (image and json) from external resources that can be edited by users, |
| and therefore either require a list of allowed domains to request from or a wildcard (`'*'`) for `img-src` and `connect-src`. |
| |
| - Other CSP directives default to `'self'` to limit content to the same origin as the Superset server. |
| |
| In order to adjust provided CSP configuration to your needs, follow the instructions and examples provided in |
| [Content Security Policy Reference](https://content-security-policy.com/) |
| |
| #### Other Talisman security considerations |
| |
| Setting `TALISMAN_ENABLED = True` will invoke Talisman's protection with its default arguments, |
| of which `content_security_policy` is only one. Those can be found in the |
| [Talisman documentation](https://pypi.org/project/flask-talisman/) under *Options*. |
| These generally improve security, but administrators should be aware of their existence. |
| |
| In particular, the option of `force_https = True` (`False` by default) may break Superset's Alerts & Reports |
| if workers are configured to access charts via a `WEBDRIVER_BASEURL` beginning |
| with `http://`. As long as a Superset deployment enforces https upstream, e.g., |
| through a load balancer or application gateway, it should be acceptable to keep this |
| option disabled. Otherwise, you may want to enable `force_https` like this: |
| |
| ```python |
| TALISMAN_CONFIG = { |
| "force_https": True, |
| "content_security_policy": { ... |
| ``` |
| |
| #### Configuring Talisman in Superset |
| |
| Talisman settings in Superset can be modified using superset_config.py. If you need to adjust security policies, you can override the default configuration. |
| |
| Example: Overriding Talisman Configuration in superset_config.py for loading images form s3 or other external sources. |
| |
| ```python |
| TALISMAN_CONFIG = { |
| "content_security_policy": { |
| "base-uri": ["'self'"], |
| "default-src": ["'self'"], |
| "img-src": [ |
| "'self'", |
| "blob:", |
| "data:", |
| "https://apachesuperset.gateway.scarf.sh", |
| "https://static.scarf.sh/", |
| # "https://cdn.brandfolder.io", # Uncomment when SLACK_ENABLE_AVATARS is True # noqa: E501 |
| "ows.terrestris.de", |
| "aws.s3.com", # Add Your Bucket or external data source |
| ], |
| "worker-src": ["'self'", "blob:"], |
| "connect-src": [ |
| "'self'", |
| "https://api.mapbox.com", |
| "https://events.mapbox.com", |
| ], |
| "object-src": "'none'", |
| "style-src": [ |
| "'self'", |
| "'unsafe-inline'", |
| ], |
| "script-src": ["'self'", "'strict-dynamic'"], |
| }, |
| "content_security_policy_nonce_in": ["script-src"], |
| "force_https": False, |
| "session_cookie_secure": False, |
| } |
| ``` |
| |
| For more information on setting up Talisman, please refer to |
| https://superset.apache.org/docs/configuration/networking-settings/#changing-flask-talisman-csp. |
| |
| ### Reporting Security Vulnerabilities |
| |
| Apache Software Foundation takes a rigorous standpoint in annihilating the security issues in its |
| software projects. Apache Superset is highly sensitive and forthcoming to issues pertaining to its |
| features and functionality. |
| |
| If you have apprehensions regarding Superset security or you discover vulnerability or potential |
| threat, don’t hesitate to get in touch with the Apache Security Team by dropping a mail at |
| security@apache.org. In the mail, specify the project name Superset with the description of the |
| issue or potential threat. You are also urged to recommend the way to reproduce and replicate the |
| issue. The security team and the Superset community will get back to you after assessing and |
| analysing the findings. |
| |
| PLEASE PAY ATTENTION to report the security issue on the security email before disclosing it on |
| public domain. The ASF Security Team maintains a page with the description of how vulnerabilities |
| and potential threats are handled, check [their web page](https://apache.org/security/committers.html) |
| for more details. |