Настройка Superset
Общие сведения
Интеграция обеспечивает SSO между Inspark IoT и Superset Apache по протоколу OAuth, и проксирование всех запросов к superset в web-приложение платформы.
Необходимо выполнить две настроки:
- Настроить конфигурационный файл nginx, который используется в платформе для обслуживания http запросов.
- Выполнить настройки в в файл superset_config.py ПО superset платформы.
- Выполнить интеграционные настройки в платформе InsparkIoT
- Настроить специальную роль InsparkRole в аналитическом приложении superset
- Создать базу с именем superset_<имя инстанса> руками, позже туда будет подключаться модуль Superset
Инфо
В платформе используется модифицированный клон superset apache. Для корректной работы аналитического модуля нужно использовать экземпляр ПО от компании Inspark
Настройка nginx
В конфигурацию сервера nginx необходимо внести дополнительные настройки:
location @dwh {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_pass http://<dns имя сервера superset>:<порт доступа по HTTP(S)>;
}
location ~ ^/(tableschemaview|sqllab|tabstateview|static|superset|api|login|oauth-authorized|csstemplateasyncmodelview|dashboardasync|rowlevelsecurityfiltersmodelview|dashboard|chart|tablemodelview|databaseview|csvtodatabaseview|columnartodatabaseview|savedqueryview|users|roles|datasource) {
try_files $uri @dwh;
}
порт доступа по HTTP задается, если используется нестандартный порт 80(443).
Порт superset по умолчанию: 8083
Настройка интеграции ПО superset
На стороне Superset необходимо внести изменения в файл superset_config.py. В зависимости от варианта развертывания (docker либо Kubernites), настройки вносятся немного по разному.
Настройка superset_config.py в Kubernites
Ниже приведены настройки для helm Kubernites, который доступен по адресу https://github.com/apache/superset/tree/master/helm
В стандартном helm superset внести следующие изменения в секцию bootstrapScript
bootstrapScript: |
#!/bin/bash
rm -rf /var/lib/apt/lists/* && \
pip install \
jmespath==1.0.1 \
Authlib==1.1.0 \
psycopg2-binary==2.9.1 \
clickhouse-connect>=0.4.1 \
redis==3.5.3 && \
if [ ! -f ~/bootstrap ]; then echo "Running Superset with uid {{ .Values.runAsUser }}" > ~/bootstrap; fi
pip install apache-superset[cors]
В секции подключаются дополнительные python-библиотеки Authlib и jmespath (иногда не устанавливается автоматически) и подключается CORS
С 4 версии superset ОБЯЗАТЕЛЬНО устанавливать SECRET_KEY, дефолтный не допускается. Для этого необходимо внести изменения в следующую секцию:
extraSecretEnv:
SUPERSET_SECRET_KEY: 'QfV0d5aEpFJAOX87nu3ZDUuZbnNiBLO7JSoBQeANfFic4//rB9ojknUF'
Этот ключ для примера, он используется в большинстве инстансов в кластере, можно оставить его.
После установки нового ключа (например, при обновлении до 4 версии необходимо его указать, а в старой версии стоял ключ по-умолчанию), необходимо указать предыдущий ключ, который вы можете посмотреть в конфигурации суперсета (pythonpath/superset_config). Для этого добавьте строчку
PREVIOUS_SECRET_KEY = 'ваш старый ключ'.
При этом старая база данных будет настроена на предыдущий ключ и для ее использования, необходимо зайти в под суперсета, указать в конфигурации новый и старый ключи и прописать команду superset re-encrypt-secrets
Внести следующие изменения в секцию configOverrides
configOverrides:
enable_proxy: |
FEATURE_FLAGS = {
"ALERT_REPORTS": True,
"ENABLE_TEMPLATE_PROCESSING": True,
"ENABLE_TEMPLATE_REMOVE_FILTERS": True,
"DASHBOARD_CROSS_FILTERS": True,
"ALLOW_FULL_CSV_EXPORT": True,
"GENERIC_CHART_AXES": True,
"HTML_SANITIZATION": False,
"DASHBOARD_RBAC": True
}
Далее подключить настройки OAuth. Показан пример подключения 2-х Компаний, где
<имя Instance1>
- строка, любое имя, например site1<secret_Ins1>
- строка, любая достаточно большая последовательность символов<dns имя Instance1>
- dns имя или TCP/IP адрес инстанса, например site1.inspark.ru
аналогично для Instance 2.
Примечание
Важно обратить внимание на строчку AUTH_USER_REGISTRATION_ROLE_JMESPATH = "starts_with(username, 'root\xA9') && 'Admin' || 'InsparkRole'"
В ней задается специальная роль в superset, которая называется InsparkRole, и права для которой следует назначить как показано ниже по тексту.
enable_oauth: |
from flask_appbuilder.security.manager import AUTH_OAUTH
AUTH_TYPE = AUTH_OAUTH
OAUTH_PROVIDERS = [
{ 'name':'<имя Instance1>',
'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':'<имя Instance1>', # Client Id (Identify Superset application)
'client_secret':'<secret_Ins1>', # 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':'<имя Instance1>'
},
'access_token_headers':{ # Additional headers for calls to access_token_url
'Authorization': 'Basic Base64EncodedClientIdAndSecret'
},
'api_base_url':'http://<dns имя Instance1>/sem-restservices/oauth2/',
'access_token_url':'http://<dns имя Instance1>/sem-restservices/oauth2/token',
'authorize_url':'http://<dns имя Instance1>/sem-restservices/oauth2/authorize'
}
},
{ 'name':'<имя Instance2>',
'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':'<имя Instance2>', # Client Id (Identify Superset application)
'client_secret':'<secret_Ins1>', # 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':'<имя Instance2>'
},
'access_token_headers':{ # Additional headers for calls to access_token_url
'Authorization': 'Basic Base64EncodedClientIdAndSecret'
},
'api_base_url':'http://<dns имя Instance2>/sem-restservices/oauth2/',
'access_token_url':'http://<dns имя Instance2>/sem-restservices/oauth2/token',
'authorize_url':'http://<dns имя Instance2>/sem-restservices/oauth2/authorize'
}
}
]
AUTH_USER_REGISTRATION = True
AUTH_USER_REGISTRATION_ROLE_JMESPATH = "starts_with(username, 'root\xA9') && 'Admin' || 'InsparkRole'"
CSRF_ENABLED = True
ENABLE_PROXY_FIX = True
PREFERRED_URL_SCHEME = 'https'
APP_NAME = "Analytic"
LOGO_TOOLTIP = "Inspark"
BABEL_DEFAULT_LOCALE = "ru"
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))
me = self.appbuilder.sm.oauth_remotes[provider].get('userinfo')
logging.info("'userinfo: {0}".format(me))
data = me.json()
logging.info("me.json() %s", data)
return { 'name' : data['user_name'], 'email' : data['email'], 'id' : data['user_name'], 'username' : data['user_name'], 'first_name': data['first_name'], 'last_name': data['last_name']}
CUSTOM_SECURITY_MANAGER = CustomSsoSecurityManager
Обязательно следует указать корректные настройки клиента и его секрета в superset_config.py, одни и те же настройки на разных суперсетах использовать не разрешается:
'client_id':'<имя Instance1>' 'client_secret':'<secret_Ins1>'
Здесь client_id уникально идентифицирует инстанс Superset, который с ним работает. В случае если инстансов Superset более одного - они должны иметь разные client_id.
Здесь client_secret является секретным кодом клиента, для обеспечения большего уровня безопасности, на этапе выдаче токена авторизации Inspark проверяет этот код.
Указываем дополнительные настройки кеширования данных в секции celery_conf
.
celery_conf: |
from celery.schedules import crontab
class CeleryConfig(object):
BROKER_URL = f"redis://{env('REDIS_HOST')}:{env('REDIS_PORT')}/0"
CELERY_IMPORTS = ('superset.sql_lab', )
CELERY_RESULT_BACKEND = f"redis://{env('REDIS_HOST')}:{env('REDIS_PORT')}/0"
CELERY_ANNOTATIONS = {'tasks.add': {'rate_limit': '10/s'}}
CELERY_IMPORTS = ('superset.sql_lab', "superset.tasks", "superset.tasks.thumbnails", )
CELERY_ANNOTATIONS = {
'sql_lab.get_sql_results': {
'rate_limit': '100/s',
},
'email_reports.send': {
'rate_limit': '1/s',
'time_limit': 600,
'soft_time_limit': 600,
'ignore_result': True,
},
}
CELERYBEAT_SCHEDULE = {
'reports.scheduler': {
'task': 'reports.scheduler',
'schedule': crontab(minute='*', hour='*'),
},
'reports.prune_log': {
'task': 'reports.prune_log',
'schedule': crontab(minute=0, hour=0),
},
'cache-warmup-hourly': {
'task': 'cache-warmup',
'schedule': crontab(minute='*/30', hour='*'),
'kwargs': {
'strategy_name': 'top_n_dashboards',
'top_n': 10,
'since': '7 days ago',
},
}
}
CELERY_CONFIG = CeleryConfig
Настройка superset_config.py на выделенном сервере
Для docker развертывания изменяется только файл superset_config.py
, подробную информация как это делать см. https://github.com/apache/superset/tree/master/docker#readme.
Порядок действий:
- Устанавливаем Superset Apache
git clone https://github.com/apache/superset.git
cd superset
- Добавляем зависимость для библиотеки Authlib
echo Authlib > ./docker/requirements-local.txt
- В файл конфигурации
superset_config.py
добавляем настройки OAuth2 авторизации.
# openssl rand -base64 42
SECRET_KEY = 'DBADfOo270l3WG3FAzGGxr1bqWqdQh+YibKe+UnP5iSn1NIvloZ1OI0L'
from flask_appbuilder.security.manager import AUTH_OAUTH
AUTH_TYPE = AUTH_OAUTH
OAUTH_PROVIDERS = [
{ 'name':'semnext',
'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':'inspark-superset', # Client Id (Identify Superset application)
'client_secret':'K08wI5oRMsXSn6eBaEtX6WSYphhiLNIL', # 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':'inspark-superset'
},
'access_token_headers':{ # Additional headers for calls to access_token_url
'Authorization': 'Basic Base64EncodedClientIdAndSecret'
},
'api_base_url':'http://<instanse Inspark>/sem-restservices/oauth2/',
'access_token_url':'http://<instanse Inspark>/sem-restservices/oauth2/token',
'authorize_url':'http://<instanse Inspark>/sem-restservices/oauth2/authorize'
}
}
]
AUTH_USER_REGISTRATION = True
AUTH_USER_REGISTRATION_ROLE_JMESPATH = "starts_with(username, 'root\xA9') && 'Admin' || 'InsparkRole'"
from custom_sso_security_manager import CustomSsoSecurityManager
CUSTOM_SECURITY_MANAGER = CustomSsoSecurityManager
Затем создаем файл с настройками получения данных пользователя на сервере авторизации. Создаем файл custom_sso_security_manager.py
в той же директории где расположен основной файл настроек.
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 == 'semnext':
me = self.appbuilder.sm.oauth_remotes[provider].get('userinfo')
logging.info("'userinfo: {0}".format(me))
data = me.json()
logging.info("me.json() %s", data)
return { 'name' : data['user_name'], 'email' : data['email'], 'id' : data['user_name'], 'username' : data['user_name'], 'first_name': data['first_name'], 'last_name': data['last_name']}
- Запускаем Superset
docker-compose -f docker-compose-non-dev.yml up -d
Настройка платформы InsparkIoT
Настройка интеграции по OAuth протоколу описана в разделе (см. раздел Настройка OAuth протокола).
Данные для автризации указываются в application.yml модуля sem-restservices. Например:
auth:
# таймаут сеансов пользователей, минут
sessionTimeout: 1440
oauth2:
# секретный код, который сэм подписывает JWT токены в формате Base64
# ! это SECRET_KEY, указаный при настройке superset !
jwtSecretKeyBase64: DBADfOo270l3WG3FAzGGxr1bqWqdQh+YibKe+UnP5iSn1NIvloZ1OI0L
# url на форму авторизации, форма должна принимать параметр ?client_id= с идентификатором OAuth клиента,
# и в случаи успешной авторизации вернуть его в GET запросе oauth2/authorize,
# по умолчанию используется форма ../#!/login?client_id=
loginUrl: /#!/login
# описание клиентов (список)
client:
-
# идентификатор клиента, для Superset представляющую аналитическую систему Semnext
# должен соответствовать названию и идентификатору клиента в файле superset_config.py
# OAUTH_PROVIDERS = [
# 'name':<>
# ...
# 'remote_app': {
# 'client_id':<>, # Client Id (Identify Superset application)
id: inspark-superset
# секретный ключ клиента
secret: K08wI5oRMsXSn6eBaEtX6WSYphhiLNIL
# url клиента (url инстанса, к которому подключается superset = свой)
url: http://10.3.2.103
# устанавливается только для Superset который является аналитической подсистемой Semnext
analytic: true
Для варианта Kubernites
В текущей версии helm values.yml
можно задать настройки только для одного подключения. Для этого необходимо задать две переменные в `values.yml':
global:
environment:
#url инстанса, к которому подключается superset
superset_host: "http://proxy-semona.<namespace>"
superset_id: "имя Instance1"
Переменной superset_host
присваивается значение с учетом настройки Nginx (см. выше).
Настройка роли InsparkRole
Выполнить вход пользователем root в Личный кабинет платформы InsparkIoT, выбрать в меню Отчеты и Аналитика пункт Аналитика.
В разделе должен прогрузится список дашбордов аналитического модуля. Кликнуть на любой дашборд, войти в аналитический модуль.
Если нет дашбордов (еще не созданы), введите ссылку :https://<host>/superset/welcome
, где
host - имя инстанса платформы.
Далее, войдите в список Ролей superset и скопируйте роль Gamma, назовите ее InsparkRole.
В роли InsparkRole оставьте права на доступ к меню Dashboards, Chart. Удалите все права с can write ..
.
Подключение сервиса DWH
Для открытия Компании возможности использовать сервисы аналитики, необходимо:
- Авторизуйтесь в платформе как суперпользователь.
- В меню выберите пункт Настройка ETL -> Управление выгрузкой.
- Кликните на компанию
- На форме отметьте
Выгрузка в DWH
- В поле Интервалы выгрузки поставьте глубину выгрузки от текущей даты в количестве месяцев.