apache-superset のdashboard をログイン無しで見えるようにする

# はじめに
データ分析をやる上でオープンソースのBIツール環境が色々と公開されるようになってきて、筆者もお世話になっています。
BIツールにはいろいろとありますが、グラフの見た目・バリエーションと惰性（笑）が理由で、筆者はsuperset をよく使っています。

ただ、公開目的で作成した一部のdashboard をアカウント無しでアクセスできるようにする方法がイマイチわからず、半日以上嵌ってしまったので、その辺の顛末を書いておきます。

# superset のインストール

まずはvenv で仮想環境を構築して、apache-superset をインストールしていきます。
以下の環境で構築を進めています。

- さくらのVPS CentOS7
- python 3.6
- Superset 0.36.0
- Flask 1.1.2
- Werkzeug 1.0.1

以下を実行します。

```
python3 -m venv superset

source superset/bin/activate

pip install --upgrade pip
pip install mysqlclient
pip install apache-superset

cd superset

```
仮想環境名はひとまずsuperset としています。必要に応じて変更しましょう。

# ポートを開放する
superset に外部からアクセスしてもらうため、ポートを開放する必要があります。
筆者の場合はさくらのVPS でCentOS7 を使っているので、以下のようにしてポートを開放しています。

```
sudo firewall-cmd --list-all
sudo firewall-cmd --add-port=8088/tcp --permanent
sudo firewall-cmd --reload
```

ポートは8088を使用しするものとしています。

# 初期設定を行う
初期設定にはflask を使用しますが、その前に一つやっておかなければならないことがあります（実はここの順番が大事だったりします）。

まず、新たにsuperset_config.py というファイルをsuperset/bin 以下に作成し、以下の一行を追加してください。
（superset を実行するときにパスが通っている場所であればどこでも良いようです。）

```
PUBLIC_ROLE_LIKE_GAMMA = True
```

このsuperset_config.py ですが、もしこのファイルが存在していたら、
superset 環境にあるsupserset/config.py からimport され、
元々superset/config.py で定義されている状態変数をsuperset_config.py によって
上書きさせるような仕組みになっています。

さて、続いて、以下を実行してください。

```
export FLASK_APP=superset
export LC_ALL=en_US.utf-8
export LANG=en_US.utf-8

flask fab create-admin
superset db upgrade
superset init
```

flask を実行すると初期アカウントを求められますので、適宜入力していってください。
（なお、古いバージョンのsuperset だとflask ではなくfabmanager を使用していたようです。）

## superset を実行する

以下を実行します。

 superset run -h (サーバのIPアドレス) -p (ポート番号)

ポート番号は、事前に開放しておいたポート番号を指定しましょう。

デーモンとして起動する場合は下記の記事を参照してください（thanks for gomesuit様!）。

https://qiita.com/gomesuit/items/5bc51242b0b41571a1e9

## 公開用のアカウントを追加する

superset にログインしたら、Security -> List Users でユーザ一覧を表示します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143965/1c0428d1-b28b-d0b4-3726-11fac4ebce3e.png)

そして、+ アイコンをクリックしてユーザを追加していきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143965/43e9d5b2-5e4b-6bd0-89d7-9c301a55c925.png)

ユーザ登録画面にて、Is Active? にチェックを入れ、Role にPublic を追加しておきます。
（メアドは適当で。）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143965/8e25f419-76b3-d8c2-037f-948a0463667a.png)

## 公開用のdata source, chart, dashboard を追加する

公開しようとしているdashboard と、これに必要なchart, data source(Database, Table 共に) を追加していってください。
なお、data source のTable として、SQL-DB のTable を直接指定することもできますが、公開にするとすべての属性が見えてしまいます。中には見られたくない属性もあると思いますので、Table を直接指定せず、SQL Lab でクエリを記述して、data source のTable をExplore する方が良いかと思います。

ここでは、database というデータベースをもとに、SQL Lab でExplore されたdata source Table をtable.data_source として説明を続けます。
table.data_source からchart, dashboard を追加してください。

## Public ロールにdata source を関連付ける

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143965/a7d17d73-85c8-1fcc-9c6f-0671b6954487.png)

Sequrity -> List Roles と選択し、Public ロールのEdit record アイコンをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143965/c8a4e0df-745c-e179-0b78-69130135aaeb.png)

すると、Public にすでに関連付けられている権限が沢山でてきますので、ここに権限を追加します。
追加する権限は datasource access on [database].[table.data_source] です。データソースとして使用しているデータベースおよびテーブルに応じて権限が存在しているので、選択してPublic に権限を追加してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143965/cab71e9e-b3dd-9168-0cd4-391b1d319380.png)

これで、このデータソースに関連したchart 及びdashboard をログイン無しで閲覧することができるようになります。

# 編集後記
## 何にハマったのか？
この辺の設定の仕方については本家のreadme にもきちんと書いてはいるんです。
https://superset.incubator.apache.org/security.html?highlight=public#public

上記のリンクにこう書かれてます。

> Public
> It’s possible to allow logged out users to access some Superset features.
> 
> By setting PUBLIC_ROLE_LIKE_GAMMA = True in your superset_config.py, 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.

確かにそうなんですが、superset_config.py を書き換えてsuperset を再起動しても全然ログイン無しでのアクセスができない状況。

## どうやって解決につながったのか？

しばらく嵌りながら色々調べていくと、以下のような書き込みを発見。

https://github.com/apache/incubator-superset/issues/4393

mistercrunch さん曰く、

> did you run superset init ? Public should then be like Gamma, to which you can start adding tables / databases

これを見て、実は
superset init -> superset_config.py を編集 -> superset run を実行する、

という手順が実は間違ってるんじゃないかと疑い始め、

superset_config.py を編集 -> superset init -> superset run を実行する、

の順番で構築・起動をやり直したらうまくいきましたと…。

## 考察をつらつらと

今回のそもそもの趣旨はPublic ロールにGamma ロールの権限を継承させることなんですが、筆者はてっきりsuperset が内部的にこの継承処理をしているものだと勝手に思っていました。

この思い込みがまずかったようで、実際にはsuperset init を実行したときにsuperset_config.py が参照され、Public ロールの初期権限にGamma ロールの権限がそのままコピーされるのが正しいようです。

実際、外部からアクセスできる状態になると、Public ロールの権限が初期状態で以下のようになっていました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143965/2f6edfd2-b7ce-ff70-839e-5d8eda55a29a.png)

PUBLIC_ROLE_LIKE_GAMMA = True になっていないと、ここのPublic の権限欄が初期状態で空の状態になります。
もし、dashboard を公開しようとしていて嵌っているようでしたら、Public の権限欄を確認してみてください。