From 495169f49af5db3a53386011f2f4e4beace056bb Mon Sep 17 00:00:00 2001 From: lindner-tj Date: Thu, 4 Jul 2024 12:08:49 +0200 Subject: [PATCH 01/12] Added Keycloak part to configuring-superset.mdx using Flask-OIDC --- .../configuration/configuring-superset.mdx | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/docs/docs/configuration/configuring-superset.mdx b/docs/docs/configuration/configuring-superset.mdx index e21fe5d6dc727..eff8757477a2a 100644 --- a/docs/docs/configuration/configuring-superset.mdx +++ b/docs/docs/configuration/configuring-superset.mdx @@ -321,7 +321,103 @@ CUSTOM_SECURITY_MANAGER = CustomSsoSecurityManager } ] ``` +### Keycloak-Specific Configuration using Flask-OIDC +If you are using Keycloak as OpenID Connect 1.0 Provider, the above configuration based on [`Authlib`](https://authlib.org/) might not work. In this case using [`Flask-OIDC`](https://https://pypi.org/project/flask-oidc/) is a viable option. +Make sure the pip package [`Flask-OIDC`](https://https://pypi.org/project/flask-oidc/) is installed on the webserver. This was succesfully tested using version 2.2.0. + +For this to work, you need to create a new security manager in the same directory as `superset-config.py`, e.g. `keycloak_security_manager.py`: +```python +from flask_appbuilder.security.manager import AUTH_OID +from superset.security import SupersetSecurityManager +from flask_oidc import OpenIDConnect +from flask_appbuilder.security.views import AuthOIDView +from flask_login import login_user +from urllib.parse import quote +from flask_appbuilder.views import ModelView, SimpleFormView, expose +from flask import ( + redirect, + request, +) +import logging + +class OIDCSecurityManager(SupersetSecurityManager): + + def __init__(self, appbuilder): + super(OIDCSecurityManager, self).__init__(appbuilder) + if self.auth_type == AUTH_OID: + self.oid = OpenIDConnect(self.appbuilder.get_app) + self.authoidview = AuthOIDCView + +class AuthOIDCView(AuthOIDView): + + @expose('/login/', methods=['GET', 'POST']) + def login(self, flag=True): + sm = self.appbuilder.sm + oidc = sm.oid + + @self.appbuilder.sm.oid.require_login + def handle_login(): + user = sm.auth_user_oid(oidc.user_getfield('email')) + + if user is None: + info = oidc.user_getinfo(['preferred_username', 'given_name', 'family_name', 'email']) + user = sm.add_user(info.get('preferred_username'), info.get('given_name'), info.get('family_name'), + info.get('email'), sm.find_role('Gamma')) + + login_user(user, remember=False) + return redirect(self.appbuilder.get_url_for_index) + + return handle_login() + + @expose('/logout/', methods=['GET', 'POST']) + def logout(self): + oidc = self.appbuilder.sm.oid + + oidc.logout() + super(AuthOIDCView, self).logout() + redirect_url = request.url_root.strip('/') + self.appbuilder.get_url_for_login + + return redirect( + oidc.client_secrets.get('issuer') + '/protocol/openid-connect/logout?redirect_uri=' + quote(redirect_url)) +``` +Then, append `superset-config.py` accordingly: +```python +from keycloak_security_manager import OIDCSecurityManager +from flask_appbuilder.security.manager import AUTH_OID, AUTH_REMOTE_USER, AUTH_DB, AUTH_LDAP, AUTH_OAUTH +import os + +AUTH_TYPE = AUTH_OID +SECRET_KEY: 'SomethingNotEntirelySecret' +OIDC_CLIENT_SECRETS = '/path/to/client_secret.json' +OIDC_ID_TOKEN_COOKIE_SECURE = False +OIDC_OPENID_REALM: '' +OIDC_INTROSPECTION_AUTH_METHOD: 'client_secret_post' +CUSTOM_SECURITY_MANAGER = OIDCSecurityManager + +# 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' +``` +The client-specific OpenID information is contained in `client_secret.json`. Create this file in the same directory as `superset-config.py`: +```json +{ + "": { + "issuer": "https:///realms/", + "auth_uri": "https:///realms//protocol/openid-connect/auth", + "client_id": "https://", + "client_secret": "", + "redirect_uris": [ + "https:///oauth-authorized/" + ], + "userinfo_uri": "https:///realms//protocol/openid-connect/userinfo", + "token_uri": "https:///realms//protocol/openid-connect/token", + "token_introspection_uri": "https:///realms//protocol/openid-connect/token/introspect" + } +} +``` ## LDAP Authentication FAB supports authenticating user credentials against an LDAP server. From fd34bf156e973933e79ce6e6baf8d6130e72934a Mon Sep 17 00:00:00 2001 From: lindner-tj Date: Thu, 4 Jul 2024 12:10:46 +0200 Subject: [PATCH 02/12] typo fix --- docs/docs/configuration/configuring-superset.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/configuration/configuring-superset.mdx b/docs/docs/configuration/configuring-superset.mdx index eff8757477a2a..a6321d2213faf 100644 --- a/docs/docs/configuration/configuring-superset.mdx +++ b/docs/docs/configuration/configuring-superset.mdx @@ -337,7 +337,7 @@ from urllib.parse import quote from flask_appbuilder.views import ModelView, SimpleFormView, expose from flask import ( redirect, - request, + request ) import logging From a1f2645b2a0a30835b6847b2f4fd153c614e0456 Mon Sep 17 00:00:00 2001 From: lindner-tj Date: Wed, 10 Jul 2024 09:03:33 +0200 Subject: [PATCH 03/12] Update docs/docs/configuration/configuring-superset.mdx Co-authored-by: Sam Firke --- docs/docs/configuration/configuring-superset.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/configuration/configuring-superset.mdx b/docs/docs/configuration/configuring-superset.mdx index a6321d2213faf..2435f81251649 100644 --- a/docs/docs/configuration/configuring-superset.mdx +++ b/docs/docs/configuration/configuring-superset.mdx @@ -381,7 +381,7 @@ class AuthOIDCView(AuthOIDView): return redirect( oidc.client_secrets.get('issuer') + '/protocol/openid-connect/logout?redirect_uri=' + quote(redirect_url)) ``` -Then, append `superset-config.py` accordingly: +Then add to your `superset_config.py` file: ```python from keycloak_security_manager import OIDCSecurityManager from flask_appbuilder.security.manager import AUTH_OID, AUTH_REMOTE_USER, AUTH_DB, AUTH_LDAP, AUTH_OAUTH From 27c6b941666a9ffd859307fc3606836b1fae8d59 Mon Sep 17 00:00:00 2001 From: lindner-tj Date: Wed, 10 Jul 2024 09:04:35 +0200 Subject: [PATCH 04/12] Update docs/docs/configuration/configuring-superset.mdx Co-authored-by: Sam Firke --- docs/docs/configuration/configuring-superset.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/configuration/configuring-superset.mdx b/docs/docs/configuration/configuring-superset.mdx index 2435f81251649..a4f26aad9d116 100644 --- a/docs/docs/configuration/configuring-superset.mdx +++ b/docs/docs/configuration/configuring-superset.mdx @@ -326,7 +326,7 @@ If you are using Keycloak as OpenID Connect 1.0 Provider, the above configuratio Make sure the pip package [`Flask-OIDC`](https://https://pypi.org/project/flask-oidc/) is installed on the webserver. This was succesfully tested using version 2.2.0. -For this to work, you need to create a new security manager in the same directory as `superset-config.py`, e.g. `keycloak_security_manager.py`: +The following code defines a new security manager. Add it to a new file named `keycloak_security_manager.py`, placed in the same directory as your `superset_config.py` file. ```python from flask_appbuilder.security.manager import AUTH_OID from superset.security import SupersetSecurityManager From 6fd72f57a3cb95aa31411327fd0f3dd23517f8b7 Mon Sep 17 00:00:00 2001 From: lindner-tj Date: Wed, 10 Jul 2024 09:05:21 +0200 Subject: [PATCH 05/12] Update docs/docs/configuration/configuring-superset.mdx Co-authored-by: Sam Firke --- docs/docs/configuration/configuring-superset.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/configuration/configuring-superset.mdx b/docs/docs/configuration/configuring-superset.mdx index a4f26aad9d116..ecf37ded5014d 100644 --- a/docs/docs/configuration/configuring-superset.mdx +++ b/docs/docs/configuration/configuring-superset.mdx @@ -401,7 +401,7 @@ AUTH_USER_REGISTRATION = True # The default user self registration role AUTH_USER_REGISTRATION_ROLE = 'Public' ``` -The client-specific OpenID information is contained in `client_secret.json`. Create this file in the same directory as `superset-config.py`: +Store your client-specific OpenID information in a file called `client_secret.json`. Create this file in the same directory as `superset_config.py`: ```json { "": { From 6261e2b60a58d28328c1ea98096acbd63004ccdd Mon Sep 17 00:00:00 2001 From: lindner-tj Date: Thu, 11 Jul 2024 10:39:15 +0200 Subject: [PATCH 06/12] Update configuring-superset.mdx --- .../configuration/configuring-superset.mdx | 148 +++++++++--------- 1 file changed, 74 insertions(+), 74 deletions(-) diff --git a/docs/docs/configuration/configuring-superset.mdx b/docs/docs/configuration/configuring-superset.mdx index ecf37ded5014d..afc02521bf9af 100644 --- a/docs/docs/configuration/configuring-superset.mdx +++ b/docs/docs/configuration/configuring-superset.mdx @@ -328,72 +328,72 @@ Make sure the pip package [`Flask-OIDC`](https://https://pypi.org/project/flask- The following code defines a new security manager. Add it to a new file named `keycloak_security_manager.py`, placed in the same directory as your `superset_config.py` file. ```python -from flask_appbuilder.security.manager import AUTH_OID -from superset.security import SupersetSecurityManager -from flask_oidc import OpenIDConnect -from flask_appbuilder.security.views import AuthOIDView -from flask_login import login_user -from urllib.parse import quote -from flask_appbuilder.views import ModelView, SimpleFormView, expose +from flask_appbuilder.security.manager import AUTH_OID +from superset.security import SupersetSecurityManager +from flask_oidc import OpenIDConnect +from flask_appbuilder.security.views import AuthOIDView +from flask_login import login_user +from urllib.parse import quote +from flask_appbuilder.views import ModelView, SimpleFormView, expose from flask import ( - redirect, - request -) -import logging - -class OIDCSecurityManager(SupersetSecurityManager): - - def __init__(self, appbuilder): - super(OIDCSecurityManager, self).__init__(appbuilder) - if self.auth_type == AUTH_OID: - self.oid = OpenIDConnect(self.appbuilder.get_app) - self.authoidview = AuthOIDCView - -class AuthOIDCView(AuthOIDView): - - @expose('/login/', methods=['GET', 'POST']) - def login(self, flag=True): - sm = self.appbuilder.sm - oidc = sm.oid - - @self.appbuilder.sm.oid.require_login - def handle_login(): - user = sm.auth_user_oid(oidc.user_getfield('email')) - - if user is None: - info = oidc.user_getinfo(['preferred_username', 'given_name', 'family_name', 'email']) - user = sm.add_user(info.get('preferred_username'), info.get('given_name'), info.get('family_name'), - info.get('email'), sm.find_role('Gamma')) - - login_user(user, remember=False) - return redirect(self.appbuilder.get_url_for_index) - - return handle_login() - - @expose('/logout/', methods=['GET', 'POST']) - def logout(self): - oidc = self.appbuilder.sm.oid - - oidc.logout() - super(AuthOIDCView, self).logout() - redirect_url = request.url_root.strip('/') + self.appbuilder.get_url_for_login - - return redirect( + redirect, + request +) +import logging + +class OIDCSecurityManager(SupersetSecurityManager): + + def __init__(self, appbuilder): + super(OIDCSecurityManager, self).__init__(appbuilder) + if self.auth_type == AUTH_OID: + self.oid = OpenIDConnect(self.appbuilder.get_app) + self.authoidview = AuthOIDCView + +class AuthOIDCView(AuthOIDView): + + @expose('/login/', methods=['GET', 'POST']) + def login(self, flag=True): + sm = self.appbuilder.sm + oidc = sm.oid + + @self.appbuilder.sm.oid.require_login + def handle_login(): + user = sm.auth_user_oid(oidc.user_getfield('email')) + + if user is None: + info = oidc.user_getinfo(['preferred_username', 'given_name', 'family_name', 'email']) + user = sm.add_user(info.get('preferred_username'), info.get('given_name'), info.get('family_name'), + info.get('email'), sm.find_role('Gamma')) + + login_user(user, remember=False) + return redirect(self.appbuilder.get_url_for_index) + + return handle_login() + + @expose('/logout/', methods=['GET', 'POST']) + def logout(self): + oidc = self.appbuilder.sm.oid + + oidc.logout() + super(AuthOIDCView, self).logout() + redirect_url = request.url_root.strip('/') + self.appbuilder.get_url_for_login + + return redirect( oidc.client_secrets.get('issuer') + '/protocol/openid-connect/logout?redirect_uri=' + quote(redirect_url)) ``` Then add to your `superset_config.py` file: ```python -from keycloak_security_manager import OIDCSecurityManager -from flask_appbuilder.security.manager import AUTH_OID, AUTH_REMOTE_USER, AUTH_DB, AUTH_LDAP, AUTH_OAUTH -import os - -AUTH_TYPE = AUTH_OID -SECRET_KEY: 'SomethingNotEntirelySecret' -OIDC_CLIENT_SECRETS = '/path/to/client_secret.json' -OIDC_ID_TOKEN_COOKIE_SECURE = False -OIDC_OPENID_REALM: '' -OIDC_INTROSPECTION_AUTH_METHOD: 'client_secret_post' -CUSTOM_SECURITY_MANAGER = OIDCSecurityManager +from keycloak_security_manager import OIDCSecurityManager +from flask_appbuilder.security.manager import AUTH_OID, AUTH_REMOTE_USER, AUTH_DB, AUTH_LDAP, AUTH_OAUTH +import os + +AUTH_TYPE = AUTH_OID +SECRET_KEY: 'SomethingNotEntirelySecret' +OIDC_CLIENT_SECRETS = '/path/to/client_secret.json' +OIDC_ID_TOKEN_COOKIE_SECURE = False +OIDC_OPENID_REALM: '' +OIDC_INTROSPECTION_AUTH_METHOD: 'client_secret_post' +CUSTOM_SECURITY_MANAGER = OIDCSecurityManager # Will allow user self registration, allowing to create Flask users from Authorized User AUTH_USER_REGISTRATION = True @@ -403,19 +403,19 @@ AUTH_USER_REGISTRATION_ROLE = 'Public' ``` Store your client-specific OpenID information in a file called `client_secret.json`. Create this file in the same directory as `superset_config.py`: ```json -{ - "": { - "issuer": "https:///realms/", - "auth_uri": "https:///realms//protocol/openid-connect/auth", - "client_id": "https://", - "client_secret": "", - "redirect_uris": [ - "https:///oauth-authorized/" - ], - "userinfo_uri": "https:///realms//protocol/openid-connect/userinfo", - "token_uri": "https:///realms//protocol/openid-connect/token", - "token_introspection_uri": "https:///realms//protocol/openid-connect/token/introspect" - } +{ + "": { + "issuer": "https:///realms/", + "auth_uri": "https:///realms//protocol/openid-connect/auth", + "client_id": "https://", + "client_secret": "", + "redirect_uris": [ + "https:///oauth-authorized/" + ], + "userinfo_uri": "https:///realms//protocol/openid-connect/userinfo", + "token_uri": "https:///realms//protocol/openid-connect/token", + "token_introspection_uri": "https:///realms//protocol/openid-connect/token/introspect" + } } ``` ## LDAP Authentication From 2336e9e9b3938fb5a5ae74bbd70344b2a727bd98 Mon Sep 17 00:00:00 2001 From: lindner-tj Date: Thu, 11 Jul 2024 15:41:59 +0200 Subject: [PATCH 07/12] Added mention of Flask-OpenID as required dependency Answering the question of @kormpakis made me aware that I forgot to include this. --- docs/docs/configuration/configuring-superset.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/configuration/configuring-superset.mdx b/docs/docs/configuration/configuring-superset.mdx index afc02521bf9af..a433bdc02d7ee 100644 --- a/docs/docs/configuration/configuring-superset.mdx +++ b/docs/docs/configuration/configuring-superset.mdx @@ -324,7 +324,7 @@ CUSTOM_SECURITY_MANAGER = CustomSsoSecurityManager ### Keycloak-Specific Configuration using Flask-OIDC If you are using Keycloak as OpenID Connect 1.0 Provider, the above configuration based on [`Authlib`](https://authlib.org/) might not work. In this case using [`Flask-OIDC`](https://https://pypi.org/project/flask-oidc/) is a viable option. -Make sure the pip package [`Flask-OIDC`](https://https://pypi.org/project/flask-oidc/) is installed on the webserver. This was succesfully tested using version 2.2.0. +Make sure the pip package [`Flask-OIDC`](https://https://pypi.org/project/flask-oidc/) is installed on the webserver. This was succesfully tested using version 2.2.0. This package requires [`Flask-OpenID`](https://pypi.org/project/Flask-OpenID/) as a dependency. The following code defines a new security manager. Add it to a new file named `keycloak_security_manager.py`, placed in the same directory as your `superset_config.py` file. ```python From 9e5e644bea6176378089779c05975be3089ecf19 Mon Sep 17 00:00:00 2001 From: lindner-tj Date: Tue, 27 Aug 2024 10:07:53 +0200 Subject: [PATCH 08/12] Update networking-settings.mdx --- .../configuration/networking-settings.mdx | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/docs/docs/configuration/networking-settings.mdx b/docs/docs/configuration/networking-settings.mdx index 3993c8bfc46de..5b0a46121d6fe 100644 --- a/docs/docs/configuration/networking-settings.mdx +++ b/docs/docs/configuration/networking-settings.mdx @@ -1,3 +1,4 @@ + --- title: Network and Security Settings sidebar_position: 7 @@ -27,6 +28,59 @@ Note that Superset bundles [flask-talisman](https://pypi.org/project/talisman/) Self-descried as a small Flask extension that handles setting HTTP headers that can help protect against a few common web application security issues. + +## HTML Embedding of Dashboards and Charts + +There are two ways to embed a dashboard: Using the [SDK](https://www.npmjs.com/package/@superset-ui/embedded-sdk) or embedding a direct link. Note that in the latter case everybody who knows the link is able to access the dashboard. + +### Enabling Embedding via the SDK + +Clicking on `...` next to `EDIT DASHBOARD` on the top right of the dashboard's overview page should yield a drop-down menu including the entry "Embed dashboard". + +To enable this entry, add the following line to the `.env` file: + +```text +SUPERSET_FEATURE_EMBEDDED_SUPERSET=true +``` +### Embedding a Public Direct Link to a Dashboard + +This works by first changing the content security policy (CSP) of [flask-talisman](https://github.com/GoogleCloudPlatform/flask-talisman) to allow for certain domans to display Superset content. Then a dashbaord can be made publicly accessible, i.e. **bypassing any authentication mechanism**. Once made public, the dashboard's URL can be added to an iframe in another website's HTML Code. + +#### Changing flask-talisman CSP + +Add to superset_config.py the entire `TALISMAN_CONFIG` section from `config.py` and include a `frame-ancestors` section: +```python +TALISMAN_ENABLED = True +TALISMAN_CONFIG = { + "content_security_policy": { + ... + "frame-ancestors": ["*.my-domain.com", "*.another-domain.com"], + ... +``` +****This becomes active after fully restarting Superset. For Docker this means recreating the container.**** +#### Making a Dashboard Public +1. Add the `'DASHBOARD_RBAC': True` [Feature Flag](https://github.com/apache/superset/blob/master/RESOURCES/FEATURE_FLAGS.md) to `superset_config.py` +2. Add the `Public` role to your dashboard as described [here](https://superset.apache.org/docs/using-superset/creating-your-first-dashboard/#manage-access-to-dashboards) + +#### Embedding a Public Dashboard + +Now anybody can directly access the dashboard's URL. You can embed it in an iframe like so: + +```html + +``` +#### Embedding a Chart + +Can be done simply by going to a chart's overview page and then clicking at the top right on `...` > `Share` > `Embed code` + ## CSRF settings Similarly, [flask-wtf](https://flask-wtf.readthedocs.io/en/0.15.x/config/) is used manage From aff063e001075f19d5c9e1b71d5cdadc659986b8 Mon Sep 17 00:00:00 2001 From: lindner-tj Date: Tue, 27 Aug 2024 10:19:33 +0200 Subject: [PATCH 09/12] Update networking-settings.mdx --- docs/docs/configuration/networking-settings.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/docs/configuration/networking-settings.mdx b/docs/docs/configuration/networking-settings.mdx index 5b0a46121d6fe..0c0cf0615ef60 100644 --- a/docs/docs/configuration/networking-settings.mdx +++ b/docs/docs/configuration/networking-settings.mdx @@ -52,9 +52,9 @@ Add to superset_config.py the entire `TALISMAN_CONFIG` section from `config.py` ```python TALISMAN_ENABLED = True TALISMAN_CONFIG = { - "content_security_policy": { - ... - "frame-ancestors": ["*.my-domain.com", "*.another-domain.com"], + "content_security_policy": { + ... + "frame-ancestors": ["*.my-domain.com", "*.another-domain.com"], ... ``` ****This becomes active after fully restarting Superset. For Docker this means recreating the container.**** From 0bf0703ee76d8edd365d99e30f8904895e5ffaf0 Mon Sep 17 00:00:00 2001 From: lindner-tj Date: Tue, 27 Aug 2024 10:21:05 +0200 Subject: [PATCH 10/12] Update networking-settings.mdx --- docs/docs/configuration/networking-settings.mdx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/docs/configuration/networking-settings.mdx b/docs/docs/configuration/networking-settings.mdx index 0c0cf0615ef60..79c258b35820c 100644 --- a/docs/docs/configuration/networking-settings.mdx +++ b/docs/docs/configuration/networking-settings.mdx @@ -52,10 +52,10 @@ Add to superset_config.py the entire `TALISMAN_CONFIG` section from `config.py` ```python TALISMAN_ENABLED = True TALISMAN_CONFIG = { - "content_security_policy": { - ... - "frame-ancestors": ["*.my-domain.com", "*.another-domain.com"], - ... + "content_security_policy": { + ... + "frame-ancestors": ["*.my-domain.com", "*.another-domain.com"], + ... ``` ****This becomes active after fully restarting Superset. For Docker this means recreating the container.**** #### Making a Dashboard Public From 37e73e3687bd903f5e12a1f5b4650ba49dd74bbb Mon Sep 17 00:00:00 2001 From: lindner-tj Date: Thu, 29 Aug 2024 09:47:52 +0200 Subject: [PATCH 11/12] Apply suggestions from code review Co-authored-by: Sam Firke --- docs/docs/configuration/networking-settings.mdx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/docs/configuration/networking-settings.mdx b/docs/docs/configuration/networking-settings.mdx index 79c258b35820c..473daf092d48c 100644 --- a/docs/docs/configuration/networking-settings.mdx +++ b/docs/docs/configuration/networking-settings.mdx @@ -25,7 +25,7 @@ The following keys in `superset_config.py` can be specified to configure CORS: ## HTTP headers Note that Superset bundles [flask-talisman](https://pypi.org/project/talisman/) -Self-descried as a small Flask extension that handles setting HTTP headers that can help +Self-described as a small Flask extension that handles setting HTTP headers that can help protect against a few common web application security issues. @@ -44,11 +44,11 @@ SUPERSET_FEATURE_EMBEDDED_SUPERSET=true ``` ### Embedding a Public Direct Link to a Dashboard -This works by first changing the content security policy (CSP) of [flask-talisman](https://github.com/GoogleCloudPlatform/flask-talisman) to allow for certain domans to display Superset content. Then a dashbaord can be made publicly accessible, i.e. **bypassing any authentication mechanism**. Once made public, the dashboard's URL can be added to an iframe in another website's HTML Code. +This works by first changing the content security policy (CSP) of [flask-talisman](https://github.com/GoogleCloudPlatform/flask-talisman) to allow for certain domains to display Superset content. Then a dashboard can be made publicly accessible, i.e. **bypassing authentication**. Once made public, the dashboard's URL can be added to an iframe in another website's HTML Code. #### Changing flask-talisman CSP -Add to superset_config.py the entire `TALISMAN_CONFIG` section from `config.py` and include a `frame-ancestors` section: +Add to `superset_config.py` the entire `TALISMAN_CONFIG` section from `config.py` and include a `frame-ancestors` section: ```python TALISMAN_ENABLED = True TALISMAN_CONFIG = { @@ -57,7 +57,7 @@ TALISMAN_CONFIG = { "frame-ancestors": ["*.my-domain.com", "*.another-domain.com"], ... ``` -****This becomes active after fully restarting Superset. For Docker this means recreating the container.**** +Restart Superset for this configuration change to take effect. #### Making a Dashboard Public 1. Add the `'DASHBOARD_RBAC': True` [Feature Flag](https://github.com/apache/superset/blob/master/RESOURCES/FEATURE_FLAGS.md) to `superset_config.py` 2. Add the `Public` role to your dashboard as described [here](https://superset.apache.org/docs/using-superset/creating-your-first-dashboard/#manage-access-to-dashboards) @@ -79,7 +79,7 @@ Now anybody can directly access the dashboard's URL. You can embed it in an ifra ``` #### Embedding a Chart -Can be done simply by going to a chart's overview page and then clicking at the top right on `...` > `Share` > `Embed code` +A chart's embed code can be generated by going to a chart's edit view and then clicking at the top right on `...` > `Share` > `Embed code` ## CSRF settings From 5475f61f16f7f11772f406236b9e9a48174b3cd0 Mon Sep 17 00:00:00 2001 From: lindner-tj Date: Thu, 29 Aug 2024 10:06:57 +0200 Subject: [PATCH 12/12] moved SDK section --- .../configuration/networking-settings.mdx | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/docs/docs/configuration/networking-settings.mdx b/docs/docs/configuration/networking-settings.mdx index 473daf092d48c..611b44cf0abcb 100644 --- a/docs/docs/configuration/networking-settings.mdx +++ b/docs/docs/configuration/networking-settings.mdx @@ -33,18 +33,9 @@ protect against a few common web application security issues. There are two ways to embed a dashboard: Using the [SDK](https://www.npmjs.com/package/@superset-ui/embedded-sdk) or embedding a direct link. Note that in the latter case everybody who knows the link is able to access the dashboard. -### Enabling Embedding via the SDK - -Clicking on `...` next to `EDIT DASHBOARD` on the top right of the dashboard's overview page should yield a drop-down menu including the entry "Embed dashboard". - -To enable this entry, add the following line to the `.env` file: - -```text -SUPERSET_FEATURE_EMBEDDED_SUPERSET=true -``` ### Embedding a Public Direct Link to a Dashboard -This works by first changing the content security policy (CSP) of [flask-talisman](https://github.com/GoogleCloudPlatform/flask-talisman) to allow for certain domains to display Superset content. Then a dashboard can be made publicly accessible, i.e. **bypassing authentication**. Once made public, the dashboard's URL can be added to an iframe in another website's HTML Code. +This works by first changing the content security policy (CSP) of [flask-talisman](https://github.com/GoogleCloudPlatform/flask-talisman) to allow for certain domains to display Superset content. Then a dashboard can be made publicly accessible, i.e. **bypassing authentication**. Once made public, the dashboard's URL can be added to an iframe in another website's HTML code. #### Changing flask-talisman CSP @@ -58,7 +49,9 @@ TALISMAN_CONFIG = { ... ``` Restart Superset for this configuration change to take effect. + #### Making a Dashboard Public + 1. Add the `'DASHBOARD_RBAC': True` [Feature Flag](https://github.com/apache/superset/blob/master/RESOURCES/FEATURE_FLAGS.md) to `superset_config.py` 2. Add the `Public` role to your dashboard as described [here](https://superset.apache.org/docs/using-superset/creating-your-first-dashboard/#manage-access-to-dashboards) @@ -81,6 +74,16 @@ Now anybody can directly access the dashboard's URL. You can embed it in an ifra A chart's embed code can be generated by going to a chart's edit view and then clicking at the top right on `...` > `Share` > `Embed code` +### Enabling Embedding via the SDK + +Clicking on `...` next to `EDIT DASHBOARD` on the top right of the dashboard's overview page should yield a drop-down menu including the entry "Embed dashboard". + +To enable this entry, add the following line to the `.env` file: + +```text +SUPERSET_FEATURE_EMBEDDED_SUPERSET=true +``` + ## CSRF settings Similarly, [flask-wtf](https://flask-wtf.readthedocs.io/en/0.15.x/config/) is used manage