5 minute read

風音屋データエンジニアの濱田(@hrkhjp)です。

Snowflakeを運用していると、「SYSADMINACCOUNTADMIN ロールを使っているのに、なぜかテーブルを削除できない」といった状況に遭遇したことはありませんか?

これはSnowflake特有の権限モデルに起因するよくあるトラブルです。実は、Snowflakeには、「すべてのオブジェクトを無条件で削除することができる管理者権限」というのは存在しません。

本記事では、Snowflakeにおけるオブジェクトの DROP 操作に必要な権限である OWNERSHIP権限 と、ロール継承を活用したSnowflake推奨のベストプラクティスについて解説します。

Snowflakeには「DROP権限」が存在しない

多くのデータベースシステムでは、オブジェクトを削除するための権限が個別に存在します。テーブルに関しては、たとえばMySQLには DROP 権限がありますし、BigQueryには bigquery.tables.delete 権限があります。しかし、Snowflakeにはオブジェクトを DROP することを許可するための、特定の権限はありません。

そのため、以下のように ALL PRIVILEGES を付与したとしても、そのロールがオブジェクトを DROP できるようにはなりません。

-- テーブルへの全ての権限をMY_ROLEに付与するが...
GRANT ALL PRIVILEGES ON TABLE my_db.my_schema.my_table TO ROLE MY_ROLE;

-- これでもMY_ROLEはmy_tableをDROPできない!
USE ROLE MY_ROLE;
DROP TABLE my_db.my_schema.my_table;

ちなみに、この SQL で付与される権限にはテーブルの DELETE 権限が含まれますが、これはテーブルのレコード(中身)を削除するための権限であり、テーブル自体を削除することはできません。

ALL PRIVILEGES に DROP 権限が含まれないという点は、Snowflakeの権限管理を理解する上で最初の重要なポイントです。

オブジェクトをDROPできるのは「所有者」だけ

では、どうすればオブジェクトを DROP できるのでしょうか。答えはシンプルで、そのオブジェクトの OWNERSHIP (所有権) を持つロールだけが DROP できます。

OWNERSHIP は、オブジェクトが作成された際に、その操作を実行したロールに自動的に付与される特別な権限です。

このルールは非常に強力で、ACCOUNTADMINSYSADMIN といった管理者ロールも例外ではありません。 たとえ ACCOUNTADMIN であっても、自身が OWNERSHIP を持たないオブジェクトを直接 DROP することはできないのです。

OWNERSHIP権限は「委譲」しかできない

OWNERSHIP は、SELECT や INSERT のような一般的な権限とは異なり、他のロールに「付与」するのではなく、「委譲」することしかできません。これは GRANT OWNERSHIP コマンドで行います。

-- my_tableのOWNERSHIPをNEW_OWNER_ROLEに委譲する
GRANT OWNERSHIP ON TABLE my_db.my_schema.my_table TO ROLE NEW_OWNER_ROLE;

重要なのは、OWNERSHIP を委譲すると、元の所有者(ロール)はそのオブジェクトに対する所有権を失うという点です。つまり、あるオブジェクトの所有者は、常にただ一つのロールとなります。

ロール継承で「実質的な」共同管理を実現する

オブジェクトの所有者は常に単一のロールですが、権限の継承を活用することで、実質的に複数のロールがオブジェクトを管理できる状態を作ることが可能です。権限の継承は、GRANT ROLE によってロールを別のロールに付与することで実現できます。

たとえば、LOADER_ROLE が作成したテーブルがあるとします。

USE ROLE LOADER_ROLE;
CREATE TABLE my_db.my_schema.my_table (...);

ここで、LOADER_ROLE に OWNERSHIP を持たせたまま、MANAGER_ROLE にも OWNERSHIP を持たせたいとします。このようなケースでは、OWNERSHIP の委譲ではなく、権限の継承を行います。

-- LOADER_ROLEをMANAGER_ROLEに付与(継承させる)
USE ROLE ACCOUNTADMIN;
GRANT ROLE LOADER_ROLE TO ROLE MANAGER_ROLE;

これより、MANAGER_ROLELOADER_ROLE の権限を引き継ぐため、my_table に対する OWNERSHIP を間接的に持つことになり、DROP できるようになります。 また、LOADER_ROLE は依然としてOWNERSHIP権限を持っているため、自身でも DROP できます。

Snowflake推奨のベストプラクティス:SYSADMINへの権限集約

ここまでの仕組みを踏まえ、Snowflakeでは以下のようにロール階層を構築することをベストプラクティスとして推奨しています。

  • 目的別のカスタムロールを作成する
  • 作成したすべてのカスタムロールを SYSADMIN ロールに付与する

こうすることで、システム管理者である SYSADMIN は配下のカスタムロールが作成したすべてのオブジェクトの OWNERSHIP を間接的に保持することになります。これにより、「システム管理者なのに操作ができない」といったトラブルを防ぐことができ、データベース全体の管理が非常に容易になります。

また、最上位ロールである ACCOUNTADMINSYSADMIN の権限を継承するため、結果としてシステム全体のオブジェクトを統括できるようになります。なお、このときすべてのカスタムロールを SYSADMIN直接付与する必要はありません。カスタムロールが階層構造を持つ場合、それぞれの階層の最上位にあるカスタムロールだけを SYSADMIN に付与しましょう。

たとえば、先ほどのケースで考えると、LOADER_ROLESYSADMIN に付与せず、MANAGER_ROLE だけを付与すれば十分です。なぜなら、LOADER_ROLE の権限は MANAGER_ROLE を経由して間接的に SYSADMIN に権限が継承されるからです。

ロール階層

まとめ

今回は、Snowflakeにおける DROP 操作と OWNERSHIP 権限について解説しました。

  • Snowflakeには直接的な DROP 権限は存在せず、オブジェクトを DROP できるのは OWNERSHIP を持つロールだけです。
  • ACCOUNTADMINSYSADMIN もこのルールの例外ではありません。
  • OWNERSHIP は1つのロールにしか属さないが、ロールの付与(権限の継承)によって柔軟な管理が可能になります。
  • すべてのカスタムロールを SYSADMIN に継承させるのが、Snowflakeが推奨するベストプラクティスです。

この権限モデルは、一見すると少し複雑に感じるかもしれません。しかし、この仕組みを理解し、SYSADMIN への権限集約というベストプラクティスを徹底することで、「あのテーブル、誰が作ったか分からなくて消せない…」といった属人化によるトラブルを未然に防ぎ、堅牢で管理しやすいデータ基盤を構築できます。

Snowflakeを使いこなす上で、この権限モデルの理解は不可欠です。本記事が、皆さんのSnowflake運用の一助となれば幸いです。

参考リンク