1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SnowflakeのSPCS(Snowpark Container Services)でApache Supersetを動かしてみたメモ書き

1
Posted at

SupersetをSPCSでうごかしたい

記事探したけどなかった。

SPCS

Snowflakeの中でコンテナ動かせるサービス。
以下のが基礎がわかりやすい。基本的に何でも動きます。
https://speakerdeck.com/__allllllllez__/jin-ri-karashi-merareru-spcsnokihon

Apache Superset

OSSのBIツールです。ちょい大変だけどPythonで設定したらなんでもできます。SSOだってi18nだってできます。

割と前からあって、継続的に開発されていて現役です。Redashとは違います。
https://superset.apache.org

Snowflakeにも昔からつながります。
https://dev.classmethod.jp/articles/try-connect-to-snowflake-with-apache-superset/

直近だとこんな記事あった
https://qiita.com/suu_dev/items/82fec21aab7196014aeb

で、Snowflakeはとてもいいんですが、ダッシュボードがもうちょーっと充実していると嬉しいので安価にたてれるSupersetをSPCSでやると、ユーザー権限とかもいい感じにできるのでいい感じになるのではということです。

ポイント

Supersetの設定

Supersetは立てるときにsuperset_config.pyにPythonコードで設定を書くというストロングスタイルです。なので、なんでもカスタマイズ可能です。i18nもデフォルト対応してるのにsuperset_config.pyに書く必要があるというありさま。

ユーザー

SPCSのなかのサービスではリクエストに Sf-Context-Current-User ヘッダーを付与されるので、これをSuperset側でみてやって、ユーザーがこれってみることができます。これやってやるとSSOも不要です。

Superset 側は AUTH_REMOTE_USERsuperset/config/superset_config.py)で、WSGI 環境変数 REMOTE_USER を見てログインする感じの実装してやればいいです。

以下の感じのコードを書いて


class SnowflakeRemoteUserMiddleware:
    """Copy Sf-Context-Current-User into REMOTE_USER with optional mapping."""

    def __init__(self, app: Callable[[dict[str, Any], Callable], Any]):
        self.app = app
        self.map = json.loads(os.getenv("SF_SUPERSET_USER_MAP", "{}"))
        self.default_policy = os.getenv("SF_USER_UNMAPPED_POLICY", "create")
        self.fallback_user = os.getenv("SF_FAKE_REMOTE_USER")

    def __call__(self, environ: dict[str, Any], start_response: Callable):
        sf_user = environ.get("HTTP_SF_CONTEXT_CURRENT_USER") or self.fallback_user
        if sf_user:
            mapped = self._resolve_user(sf_user)
            if mapped is None:
                start_response("403 Forbidden", [("Content-Type", "text/plain")])
                return [b"Superset access denied: user mapping missing"]
            environ["REMOTE_USER"] = mapped
        return self.app(environ, start_response)

    def _resolve_user(self, sf_user: str) -> str | None:
        key = sf_user.upper()
        if key in self.map:
            return self.map[key]
        policy = self.default_policy.lower()
        if policy == "deny":
            return None
        normalize = os.getenv("SF_USERNAME_NORMALIZER", "lower")
        if normalize == "identity":
            return sf_user
        return sf_user.lower()

ADDITIONAL_MIDDLEWARE = [SnowflakeRemoteUserMiddleware]とかやってサービス立ち上げると

image.png

からの

image.png

みたいにSuperset側での認証不要でSnowflakeのユーザーでそのままSupersetのユーザーとすることができます。おんなじ感じでロールもなんかできるはずです(未)

その辺は適当に動く状態にしたgithubのレポジトリがあるのでそっち参照でよろしくおねがいします。

Snowflakeへの接続

Supersetではデータベースへは内部でsqlalchemy使って接続文字列をGUIで組み立てて接続する仕組みになっています。
データベース接続設定のできるロールを持つユーザーでデータベースへ接続ってやるとでてきます。

image.png

デフォルトだとSnowflakeコネクタははいってないので最初に設定でコネクタはrequirements.txtに書いておく必要があります。

で、SPCS特有の問題なんですが、SPCSの中からSnowflakeのデータベースにつなぐのに、ネットワーク設定が必要です。普通にやると。なので、External Access IntegrationをAccount Adminとかで作ってやって、自分のSnowflake宛のインターネット接続を許可してやる必要があります。なお、同じノリで任意の外部サービスにつなぐこともできます。

とはいえ折角Snowflakeの中に閉じているので中からアクセスしたいです。SPCSの中からSnowflakeのデータベースを叩くにはSPCS が注入する OAuth トークン(/snowflake/session/token)で 同一アカウントへ“内側”接続する方式を使います。

Supersetでは設定だけじゃなくてデータベース接続エンジンなんかもオーバーライドできるのでSPCSのトークンがあったらオーバーライドしてアカウントとかの設定を無視してヘッダーからトークンとってきてつなぐみたいなSnowflakeエンジンを書いてオーバーライドしてやると、EAIしなくても接続可能です。

なんか一応できました。

かなり無茶苦茶で洗練もされてませんが、こんな感じ

sqlalchemyにはじかれるのでダミーのアカウントとかを記載したデータベース接続を作ってやって

image.png

データセット登録画面からちゃんとデータベースがみえています
image.png

で、超適当だけど、こんな感じのダッシュボードも簡単にできてしまいます。
image.png

細かい使い方とかは他の記事見てくださいな。

その他

PostgresでメタデータのデータベースもってるのでPostgressをいまはSPCSでまとめて立ててるけど、Postgres Snowflakeに逃がせるはずで、たぶんだいぶはかどるはず。

まとめ

  • SnowflakeのSPCSのなかでSupersetを動かしてみたよ
  • SPCSのユーザーヘッダーとか使ってログインとかできるよ
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?