Streamlit appをrestricted caller’s rightsで動作させる場合にコンテナインスタンスが必須となる背景を考えた話

行レベルセキュリティに頼ったマルチテナントは、実装ミスによる認可破綻が起こりやすいので怖い。
RBAC・インフラレベルで認可する仕組みができれば、appは認可コードを一切かかずに、
Snowflakeに認可の安全性を移譲できる。

しかし、これまでStreamlit in SnowflakeではOwner’s rightsでしか動作せず、
実現ができなかった。6月1日に「Restricted caller’s rights」が一般提供(GA)され、
caller’s rightsで Streamlit を動作させられるようになった。
ただし、コンテナインスタンスが必須となる。
どういう仕組みで機能するのか気になったので調べてみた。

Restricted caller’s rightsが一般提供(GA)された

これまで、ストアドプロシージャ、SPCSサービス、Streamlit in SnowflakeアプリはOwner’s role、
すなわち、リソースの所有者の権限でしか動作させることができなかった。
2026年6月1日に「Restricted caller’s rights」がGAされたことで、
これらのリソースをCaller’s role、すなわち呼び出し元権限で動作させることが可能となった。

呼び出し元の権限次第で、Snowflake側のガバナンスが全く効かない、という世界線は存在せず、
「呼び出し元の権限」に対して「別のロールによる許可」で制限した権限でのみ、これらを実行できる。

混乱する代理人問題とCaller’s right

Caller’s rightで動作する、ということは、所有者が書いたコードを、閲覧者の権限で実行するということ。
閲覧者の強い権限により「閲覧するだけのつもりだったがDROPできてしまった」みたいなことになる。
これを混乱する代理人問題と言い、権限を持つ閲覧者が所有者のコードに意図せず権限を貸している。
アプリが悪意を持っていたりアホだったりした場合に被害が拡大する要因となる。

GRANT CallerとCaller’s rightの権限波及の仕組み

実行主体が所有者(Owner)から呼び出し元(Caller)に移るためSnowflake側の権限波及が大きく変わる。
管理者が別の管理者に MANAGE CALLER GRANTS することで、別の管理者は CALLER GRANTS できる。
別の管理者は CALLER USAGE, CALLER SELECT 等で「このアプリ(Owner’s role)が閲覧者の代理として
使って良い権限」をホワイトリスト形式で指定する。
結果、閲覧者がたまたま ACCOUNTADMIN でも 管理者はアプリが許可した対象へのSELECTしか
行使できない。つまり、閲覧者がDROPやALTERを持っていたとしてもアプリ経由では実行できない。
閲覧者の身元・ポリシー(行/列制御)は活かしつつアプリが行使できる権限の上限は管理者が固定する、
が実現できるようになる。

なぜウェアハウスランタイムではCaller’s right動作ができないのか

Restricted caller’s rights and Streamlit in Snowflake
公式によると、ウェアハウスランタイムではCaller’s right動作できない。

By default, all Streamlit in Snowflake apps run with the privileges of the owner, not the privileges of the caller. The Streamlit app developer can define whether a container-runtime app runs with owner’s rights or restricted caller’s rights. Restricted caller’s rights aren’t supported in warehouse runtimes. Restricted caller’s rights requires Streamlit version 1.53.1 or later.

以下が核心。Streamlit in SnowflakeアプリはSQLをOwner権限のストアドプロシージャ相当のサンドボックスで動く。だから、DESCRIBE/SHOW/LIST 制限などの「ストアドプロシージャ相当の制約」が付く。
Runtime environments for Streamlit apps

Warehouse runtimes provide an on-demand, personal instance of the Streamlit app for each viewer. When a viewer opens the app, a new instance of the app is created for that viewer. Each viewer has their own isolated environment, which increases user load times. While both runtimes execute SQL queries using the owner’s privileges, apps using warehouse runtimes are subject to similar restrictions as owner’s rights stored procedures. For more information, see Owner’s rights stored procedures.

ストアドプロシージャ準拠の権限モデルにはCaller’s rightが想定されていなかったため、
同じ理由でStreamlit in SnowflakeでもCaller’s rightができなかった。

Caller’s right の本質は、所有者とは別の閲覧者としてのセッションを張る、ということ。
これは、アプリプロセスが複数の認証コンテキスト(OwnerとCaller)を同時に保持・維持する必要がある。
ステートレスなアプリのホスティングでセッション変数が揮発する問題の解決に、
ウェアハウスにステートを持たせるという解決策をとらないのは、それは当たり前だし、
そういう用途なら、常時稼働でステートを持てるコンテナウェアハウスが適当だよ、ということかな。

ストアドプロシージャにおけるOwner’s right、Caller’s rightについては以下があたる。

まとめ

Streamlit in Snowflakeのクエリ実行は背後でストアドプロシージャが動作していることを理解した。
ストアドプロシージャはセキュリティのため、制限されたサンドボックスで動作している。
混乱する代理人問題の対応として、SnowflakeではCaller’s rightsによる動作を許可していない。
このモデルでは、Caller’s rights の入り込む余地がないか、既存の破壊的変更が必要となる。

そこで、常時稼働、ステートフルを前提としたコンテナインスタンスに Caller’s rights を
ホワイトリスト式で制限する「Restricted caller’s rights」が導入された。