Data Engineer Associate — 第 13 章
この章で学ぶこと
この章に出てくる用語
Unity Catalog で `GRANT SELECT ON TABLE main.sales.orders TO `analysts`` を実行したのに、そのグループの利用者がクエリを投げると `PERMISSION_DENIED` で失敗する。原因は権限の種類ではなく、権限の連鎖を組み立てていないことにあります。
メタストアの下にカタログ、スキーマ、テーブルが並ぶ三段構造そのものは深追いしません。押さえるのは「三段のどこに何を GRANT すると、どこまで効くか」です。
権限操作の構文は 3 つだけです。付与は `GRANT privilege_types ON securable_object TO principal`、取り消しは `REVOKE privilege_types ON securable_object FROM principal`、確認は `SHOW GRANTS [principal] ON securable_type securable_name` です。付与が `TO`、取り消しが `FROM` の違いが引っかけに使われます。
GRANT SELECT ON TABLE main.sales.orders TO `analysts`;
REVOKE MODIFY ON TABLE main.sales.orders FROM `analysts`;
SHOW GRANTS `analysts` ON TABLE main.sales.orders;選択肢には存在しない構文が並びます。`SHOW PERMISSIONS`、`LIST GRANTS FOR`、`DESCRIBE PRIVILEGES`、`CREATE ROLE`、`GRANT OWNERSHIP`、`ALTER TABLE ... ADD READER` はいずれも Databricks SQL にありません。`INFORMATION_SCHEMA` も読み取り専用で、`INSERT` による権限変更はできません。
プリンシパルはユーザー・グループ・サービスプリンシパルの 3 種類です。ユーザーはメールアドレス、サービスプリンシパルはアプリケーション ID で指定し、特殊文字を含む名前はバッククォートで囲みます。クラスタ ID やジョブ ID は指定できません。
GRANT と REVOKE は加減算モデルです。`GRANT SELECT, MODIFY` のあとに `REVOKE MODIFY` を実行すれば SELECT だけが残ります。REVOKE が外すのは書いた権限だけで、別の権限にも、別のプリンシパルにも、別のオブジェクトにも連鎖しません。`REVOKE ALL PRIVILEGES ON SCHEMA sales_db.sales` を実行しても、親カタログに付けた `USE CATALOG` はそのまま残ります。付与されていない権限を REVOKE してもエラーにはならず成功します。GRANT に有効期限はなく、期間限定のアクセスは期間終了後に REVOKE するジョブで実現します。
古い問題文やスクリプトでは `GRANT USAGE ON CATALOG sales_db TO `data_analyst`` も見かけます。`USAGE` はレガシーの Hive メタストア用テーブルアクセス制御にあった権限で、それ自体は操作を許さず、スキーマのオブジェクトを触るための追加要件として働きました。Unity Catalog での正式名が `USE CATALOG` と `USE SCHEMA` です。捏造構文だと早合点しないでください。
| 権限 | 許すこと |
|---|---|
| SELECT | テーブル・ビューの読み取り |
| MODIFY | INSERT / UPDATE / DELETE / MERGE の書き込み |
| CREATE TABLE | スキーマ配下へのテーブル作成 |
| EXECUTE | SQL UDF の呼び出し |
| READ VOLUME | ボリューム内のファイル読み取り |
| BROWSE | データを読ませずメタデータを閲覧させる |
| APPLY TAG | タグの追加・編集 |
| USE CATALOG / USE SCHEMA | 子オブジェクトへ到達する通行許可 |
| MANAGE | 権限付与・所有権移譲・名前変更・削除 |
読み取り専用の要件に `ALL PRIVILEGES` が過剰なのは、MODIFY まで付くためです。
子オブジェクトへ到達するには親の通行許可が要ります。カタログには `USE CATALOG`、スキーマには `USE SCHEMA` が必要で、この 2 つはデータへのアクセス権を一切与えません。逆に、どちらかが欠けるとテーブルに SELECT を持っていても親階層をたどれず失敗します。冒頭の `PERMISSION_DENIED` の正体はたいていこれです。
| やりたいこと | 必要な権限の組み合わせ |
|---|---|
| テーブルを SELECT する | カタログの USE CATALOG + スキーマの USE SCHEMA + テーブルの SELECT |
| マネージドテーブルを作る | USE CATALOG + USE SCHEMA + スキーマの CREATE TABLE |
| 外部テーブルを作る | 上記に加えて外部ロケーションの CREATE EXTERNAL TABLE |
| SQL UDF を呼び出す | USE CATALOG + USE SCHEMA + 関数の EXECUTE |
| テーブルに GRANT する | 所有者または MANAGE + 親の USE CATALOG / USE SCHEMA |
権限を配るための権限も連鎖の対象です。GRANT と REVOKE を実行できるのはそのオブジェクトの所有者、親カタログや親スキーマの所有者、そのオブジェクトに MANAGE を持つ利用者、メタストア管理者の 4 者で、いずれも親コンテナの利用権限が要ります。アカウント管理者である必要はなく、SELECT と MODIFY はデータ操作の権限であって権限管理の権限ではありません。
例外は `BROWSE` です。オブジェクトを発見しメタデータを閲覧してアクセス申請を行う権限で、`USE CATALOG` も `SELECT` も与えずに探索だけを許可します。中身は見せずにテーブルの存在だけ見せたい要件はこれで解きます。
親コンテナに付けた権限は現在および将来の子オブジェクトに継承されます。`GRANT SELECT ON SCHEMA main.sales TO `alice`` と書けば、後から作られるテーブルやビューにも SELECT が及びます。逆方向はなく、テーブルへの GRANT が親スキーマやカタログへ広がることはありません。
例外が 2 つあります。1 つ目はメタストアで、ここに付与した権限は配下のカタログにもテーブルにも継承されません。カタログに SELECT を付ければ配下のテーブルを読めるのとは扱いが違います。2 つ目は所有権で、カタログの所有者でも配下に他人が作ったテーブルの所有者にはなりません。ただし所有者は子オブジェクトを管理できます。
`MANAGE` は所有者に近い操作をまとめて許可する権限です。所有者との差は「データ操作権が自動で付くかどうか」です。
| 比較軸 | MANAGE 権限 | 所有者 (OWNER) |
|---|---|---|
| 権限の付与・取り消し | できる | できる |
| 所有権の移譲・名前変更・削除 | できる | できる |
| SELECT や MODIFY の自動付与 | 付かない (自分自身へ付与は可能) | 所有者として操作できる |
| 設定方法 | GRANT MANAGE ON ... TO ... | ALTER ... OWNER TO ... |
| ALL PRIVILEGES に含まれるか | 含まれない | 該当なし |
`ALL PRIVILEGES` は対象に適用できる権限をまとめて付与しますが、`MANAGE`・`EXTERNAL USE SCHEMA`・`EXTERNAL USE LOCATION` の 3 つは含みません。所有権の移譲は `ALTER <securable-type> <name> OWNER TO <principal>` で行い、実行できるのは GRANT と同じ 4 者です。所有者にはグループも指定できます。`GRANT OWNERSHIP` ではありません。
カタログ層には別に押さえる点が 2 つあります。`DROP CATALOG` と `ALTER CATALOG ... OWNER TO` はカタログの所有者かメタストア管理者だけの操作です。スキーマ作成は `CREATE SCHEMA` を持つ人なら誰でもでき、テーブルへの GRANT も所有者か MANAGE でできますが、カタログの削除と所有者変更は降りてきません。新しいカタログを作れるのはメタストアレベルで CREATE CATALOG を付与された利用者かメタストア管理者だけです。一般ユーザーの `CREATE CATALOG sales` が権限エラーになるのは設計どおりで、名前の衝突や言語設定が原因ではありません。
`DENY privilege_types ON securable_object TO principal` という構文は Databricks SQL に実在します。GRANT と同じく `TO` を使う点に注意してください。しかしこの機能はUnity Catalog ではサポートされず、レガシーの `hive_metastore` 配下にのみ適用されます。UC で「見せない」を実現する手段は REVOKE と、次節以降の行フィルタ・列マスク・ABAC ポリシーです。
拒否は明示・暗黙を問わず付与より優先され、スキーマへの拒否は配下の全オブジェクトへ、カタログへの拒否は配下の全スキーマへ暗黙的に及びます。解除は GRANT による上書きではなく同じ権限を REVOKE することで行い、`UNDENY` は存在しません。
確認 — 穴あけ 3 問
0 / 3
空欄を押すと選択肢が出ます。間違えても減点はありません。
Unity Catalog でテーブルを SELECT するには、テーブルの SELECT とカタログの USE CATALOG に加えて、スキーマの が必要です。
ALL PRIVILEGES には EXTERNAL USE SCHEMA、EXTERNAL USE LOCATION、そして が含まれません。
DENY ステートメントは Unity Catalog では未サポートで、 カタログとその配下オブジェクトにのみ適用できます。
GRANT で解けるのは「このテーブルを見せるか、見せないか」までです。ところが現場の要件はもっと細かく、「営業担当には自分の担当地域の行だけ見せたい」「マイナンバーの列は人事だけ生の値、他部署は伏字」という形で来ます。部門ごとにテーブルやビューを複製すれば実現できますが、部門が 12 で対象テーブルが 40 枚なら 480 本になり、列が 1 つ増えるたびに全部を直すことになります。この困りごとに対する Unity Catalog の答えが行フィルタ (Row Filter) と列マスク (Column Mask) です。
この 2 つが登場する前は、動的ビュー (Dynamic View) と呼ばれるパターンが使われていました。`CREATE VIEW` の定義の中に `CASE WHEN is_account_group_member('HR') THEN ssn ELSE '***-**-****' END` のような式や `WHERE current_user() = owner` のような条件を直接書き、ビュー側で可視範囲を分岐させる方法です。今も動きますが、守っている対象がビューなので、基礎テーブルへの直接アクセスを塞ぎ続ける運用が付いて回ります。行フィルタと列マスクは、この制御をテーブル本体へ移すための機能です。
行フィルタの実体は Unity Catalog に永続化されたSQL UDF です。戻り値の型は `BOOLEAN` でなければならず、`TRUE` を返した行だけがクエリ結果に残ります。`FALSE` はもちろん、`NULL` を返した行も除外される点が重要です。参照する列に NULL が混ざると意図せず行が消えるため、NULL を考慮した実装が要ります。ノートブックのセルで定義した一時 UDF や Hive Metastore の Java UDF は使えません。
CREATE FUNCTION main.sec.filter_region(region STRING)
RETURNS BOOLEAN
RETURN IF(is_account_group_member('admin'), true, region = 'US');
ALTER TABLE main.sales.orders SET ROW FILTER main.sec.filter_region ON (region);
ALTER TABLE main.sales.orders DROP ROW FILTER;テーブル作成と同時に付ける場合は `CREATE TABLE employees(emp_name STRING, dept STRING) WITH ROW FILTER filter_emps ON (dept)` のように `WITH ROW FILTER <関数> ON (<列>)` を書きます。`ON (...)` には関数のパラメータに対応する列名のほか、STRING・数値・BOOLEAN・INTERVAL・NULL といった定数リテラルも渡せます。任意の SQL 式や他テーブルの列は渡せません。解除はテーブル単位の `ALTER TABLE t DROP ROW FILTER` で、列名は指定しません。行フィルタは 1 テーブルにつき 1 つだけです。
列マスクも SQL UDF ですが、戻り値の要件が違います。戻り型はマスク対象列の型にキャスト可能である必要があり、BOOLEAN 固定でも STRING 固定でもありません。数値列を数値のままマスクすることもできます。マスク対象の列は関数の第 1 引数へ自動的に対応づけられ、2 つ目以降の引数は `USING COLUMNS` で渡します。
CREATE FUNCTION main.sec.mask_ssn(ssn STRING)
RETURNS STRING
RETURN CASE WHEN is_account_group_member('HR') THEN ssn ELSE '***-**-****' END;
CREATE TABLE main.hr.persons (name STRING, ssn STRING MASK main.sec.mask_ssn);
ALTER TABLE main.hr.persons ALTER COLUMN ssn SET MASK main.sec.mask_ssn;
ALTER TABLE main.hr.addr ALTER COLUMN address SET MASK main.sec.mask_pii USING COLUMNS (region);
ALTER TABLE main.hr.persons ALTER COLUMN ssn DROP MASK;作成時は列定義の直後に `MASK <関数名>` を書きます。`MASKED BY` は他製品の構文で Databricks には存在せず、テーブル単位の `WITH MASK` や `SET MASK ... ON (...)` もありません。解除は必ず列を指定した `ALTER TABLE t ALTER COLUMN c DROP MASK` で行い、テーブル単位で一括解除する構文はありません。1 つの列に付けられるマスクは 1 つだけで、条件を組み合わせたい場合は `USING COLUMNS` で追加の列を渡し、1 つの関数の中で分岐します。
| 比較軸 | 行フィルタ | 列マスク |
|---|---|---|
| 制御するもの | どの行を見せるか | 列の値をどう変換して見せるか |
| UDF の戻り型 | BOOLEAN 固定 (TRUE の行だけ残る) | 対象列の型にキャスト可能な型 |
| 作成時の構文 | WITH ROW FILTER fn ON (col) | col STRING MASK fn |
| 既存への適用 | ALTER TABLE t SET ROW FILTER fn ON (col) | ALTER TABLE t ALTER COLUMN c SET MASK fn |
| 追加引数の渡し方 | ON (列 または 定数リテラル) | USING COLUMNS (列 または 定数リテラル) |
| 解除 | ALTER TABLE t DROP ROW FILTER | ALTER TABLE t ALTER COLUMN c DROP MASK |
| 設定できる数 | 1 テーブルにつき 1 つ | 1 列につき 1 つ (複数列に併用可) |
偽の構文も型が決まっています。`CREATE ROW POLICY` は PostgreSQL や Snowflake の書き方です。`GRANT ROW FILTER` や `GRANT MASK` という権限種別も存在せず、行フィルタと列マスクは権限ではなくテーブルの属性です。`ADD CONSTRAINT` に寄せた書き方も誤りで、CHECK 制約とは別の機構です。
両者は同じテーブルに併用できます。評価順は行フィルタで行を絞ってから、残った行に列マスクを適用する順です。しかも適用のタイミングはデータソースから行が取得された直後で、述語・集計・並べ替えはすべてその後に評価されます。したがって `SELECT count(*)` でさえフィルタ通過後の行だけを数え、実行するユーザーによって返る値が変わります。
関数の中で誰が実行しているかを判定するには、専用の組み込み関数を使います。`is_account_group_member('HR')` はセッションユーザーがアカウントレベルのそのグループに所属していれば TRUE を返し、`current_user()` と `session_user()` は実行者の ID を返します。`current_database()` のようなセッション情報はユーザー属性ではないため使えません。管理者に全行を見せたい行フィルタは `RETURN IF(is_account_group_member('admin'), true, region = 'US')` と書きます。ここを `AND` でつなぐと、管理者ですら US 以外の行を見られなくなります。
フィルタやマスクを割り当てるには、関数への `EXECUTE`、関数のスキーマへの `USE SCHEMA`、親カタログへの `USE CATALOG` が必要です。加えて、既存テーブルへ設定・解除する場合はテーブルの所有者であるか、MANAGE と SELECT の両方を持つ必要があります。新規テーブルとして作る場合はスキーマの `CREATE TABLE`、列を追加するなどスキーマ変更を伴う文ではさらに `MODIFY` が要ります。列単位の `GRANT MASK` のような権限は存在しません。
| コンピュートの種類 | 行フィルタ / 列マスクを使う要件 |
|---|---|
| SQL ウェアハウス | そのまま利用できる |
| 標準アクセスモード | Databricks Runtime 12.2 LTS 以上 |
| 専用アクセスモード | 15.4 LTS 以上で読み取り (書き込みは 16.3 以上) |
| DBR 12.2 LTS 未満 | 非対応。安全側に倒れてデータが返らない |
| パーティション列にポリシーがある表への DELETE / UPDATE / MERGE | 17.2 以上 |
12.2 LTS 未満のクラスタから読んだときに全行が返ってしまうことはありません。古いランタイムでポリシーを回避して生データを読む抜け道はない、と覚えてください。
ポリシーはビューそのものには適用できません。ただし基礎テーブルに付いたポリシーはビュー経由のアクセスでもセッションユーザーの ID で評価されるため、ビューを挟んで回避することはできません。同様に、クラウドストレージのパスを直接指定するファイルアクセスも非サポートで、テーブル名を通さない抜け道は塞がれています。
運用で最も壊しやすいのは関数の削除順序です。テーブルに割り当てられたままの UDF を先に `DROP FUNCTION` すると、そのテーブルはアクセス不能な状態になります。必ず `ALTER TABLE ... ALTER COLUMN ... DROP MASK` または `ALTER TABLE ... DROP ROW FILTER` でポリシーを外してから関数を削除します。順序はどちらでもよい、という選択肢は誤りです。
もう 1 つの落とし穴がマテリアライズドビューとストリーミングテーブルです。これらではポリシーがパイプラインの実行 ID (run-as) で評価されます。その ID がフィルタやマスクの対象に含まれていると、マスク済みの値がそのまま実体化されて恒久的に残ります。パイプライン用のサービスプリンシパルは、次節の `EXCEPT` で除外しておくのが定石です。
確認 — 穴あけ 3 問
0 / 3
空欄を押すと選択肢が出ます。間違えても減点はありません。
行フィルタに使う SQL UDF の戻り値の型は でなければならず、FALSE を返した行と NULL を返した行が除外されます。
既存テーブルの列にマスクを設定する構文は ALTER TABLE t ALTER COLUMN ssn mask_ssn です。
手動で設定した行フィルタ・列マスクを標準アクセスモードで使うには、Databricks Runtime 以上が必要です。
前節の `ALTER TABLE` による手動適用には 2 つの弱点があります。1 つは、テーブルが増えるたびに人手で付け直す必要があり、翌週に作られたテーブルには何も効かないこと。もう 1 つは、テーブル所有者が自分で外せてしまい、統制する側とされる側が同じ人になることです。これを解くのがABAC (属性ベースアクセス制御) です。テーブルを名指しする代わりに「pii タグが付いた列」という属性でポリシーを書き、カタログやスキーマに 1 度貼れば配下へ自動的に効かせます。
ABAC の条件に使える属性は、アカウントレベルで定義され付与権限が制御されたガバナンスタグに限られます。誰でも自由に付けられる通常のタグでは動きません。Delta の `TBLPROPERTIES` もタグとは別の仕組みで、条件には使えません。タグの変更がポリシー評価に反映されるまでには数分かかります。
CREATE [OR REPLACE] POLICY policy_name
ON { CATALOG c | SCHEMA s | TABLE t }
[COMMENT description]
{ ROW FILTER fn | COLUMN MASK fn }
TO principal [, ...]
[EXCEPT principal [, ...]]
FOR TABLES
[WHEN condition]
[MATCH COLUMNS condition [AS alias] [, ...]]
ON COLUMN alias -- COLUMN MASK では必須
[USING COLUMNS (arg [, ...])]紐づけ先はカタログ・スキーマ・テーブルの 3 つで、メタストアやワークスペースには付けられません。角括弧の付き方そのものが正誤判定になります。`TO` と `FOR TABLES` は省略できない必須句で、`ON COLUMN` は列マスクでは必須・行フィルタでは書きません。任意なのは `COMMENT`・`EXCEPT`・`WHEN`・`MATCH COLUMNS`・`USING COLUMNS` です。`WHEN` を省略すると条件は TRUE 扱いになり、配下の全テーブルが対象になります。
`TO` にはポリシーを適用するプリンシパル、`EXCEPT` には適用から免除するプリンシパルを書きます。管理者や ETL 用サービスプリンシパルを `EXCEPT` に入れ、マスクなしで処理させる設計が定番です。前節で触れたパイプラインの run-as も、ここで除外します。
`MATCH COLUMNS` は対象列を特定して `AS` で別名を付ける句で、条件には 2 つの関数を使います。`has_tag('pii')` はタグのキーが付いているかだけを見て値は問わず、`has_tag_value('pii', 'ssn')` はキーと値の組で絞り込みます。pii が付いた列を一律に伏せるなら前者、pii の値が ssn の列だけを狙うなら後者です。条件は AND / OR / NOT で組み合わせられます。列マスクではさらに `ON COLUMN <別名>` で、一致した列のうちどれにマスクを掛けるかを指定し、行フィルタでは `USING COLUMNS` で別名を UDF の引数として渡します。
CREATE POLICY mask_pii ON CATALOG prod
COLUMN MASK prod.governance.mask_value
TO `account users` EXCEPT `etl_service_principal`
FOR TABLES
MATCH COLUMNS has_tag_value('pii', 'ssn') AS ssn
ON COLUMN ssn;管理系の構文も 3 つ覚えます。一覧は `SHOW [EFFECTIVE] POLICIES ON { CATALOG | SCHEMA | TABLE } <名前>`、詳細は `DESCRIBE POLICY <名前> ON ...`、削除は `DROP POLICY <名前> ON ...` です。作成・編集・削除・参照のすべてに、対象セキュラブルの所有権または MANAGE 権限が必要で、加えてポリシーが使う UDF への EXECUTE が要ります。テーブルへの SELECT だけでは触れませんし、メタストア管理者に限定されているわけでもありません。
この一点が ABAC の職務分離を成立させています。ポリシーはカタログやスキーマの管理者が貼るため、配下のテーブル所有者は自分のテーブルに掛かったマスクを上書きも解除もできません。手動適用ではテーブル所有者が自分で `DROP MASK` できてしまうのと対照的です。
| 項目 | 上限 |
|---|---|
| メタストアあたりのポリシー数 | 10,000 |
| カタログまたはスキーマあたり | 100 |
| テーブルあたり | 50 |
| 1 ポリシーの TO と EXCEPT の合計プリンシパル数 | 20 |
| MATCH COLUMNS の列条件数 | 3 |
実行環境の要件は手動適用とは別物です。ABAC ポリシーにはサーバーレスコンピュート、または Databricks Runtime 16.4 以上の標準/専用コンピュートが必要で、専用の場合はきめ細かなアクセス制御によるフィルタリングを有効にします。手動適用の 12.2 LTS とは数字が違う点が狙われます。
競合の扱いも重要です。あるユーザーと 1 つのテーブルに対して実行時に解決される行フィルタは 1 つ、1 つの列に解決される列マスクも 1 つでなければなりません。複数の異なるものが該当すると、AND で合成されることも作成順で優先されることもなく、アクセスが拒否されます。`TO` と `EXCEPT` で範囲を切り分け、重ならないよう設計します。ビューに直接適用できないこと、タイムトラベルとクローンが使えないことは手動適用と同じです。
| 比較軸 | ABAC ポリシー | 手動の ALTER TABLE 適用 |
|---|---|---|
| 付ける場所 | カタログ / スキーマ / テーブル | テーブル (と列) |
| 新規テーブルへの追随 | タグが付けば自動で効く | 効かない。都度設定が必要 |
| 管理する人 | 上位のガバナンス管理者 | テーブル所有者 |
| 所有者による解除 | できない (職務分離が成立) | できる |
| 向く場面 | 多数テーブルへの一貫適用 | テーブル固有のロジック |
| コンピュート要件 | サーバーレスまたは DBR 16.4 以上 | SQL ウェアハウスまたは DBR 12.2 LTS 以上 |
確認 — 穴あけ 3 問
0 / 3
空欄を押すと選択肢が出ます。間違えても減点はありません。
ABAC ポリシーの TO 句と EXCEPT 句に指定できるプリンシパルは、1 ポリシーあたり合計 までです。
ABAC ポリシーの作成・編集・削除・参照には、対象セキュラブルの所有権または 権限が必要です。
ABAC ポリシーを使うには、サーバーレスコンピュートまたは Databricks Runtime 以上のコンピュートが必要です。
ここまでの GRANT もポリシーも、宛先となる ID が正しく揃っていて初めて機能します。権限も行フィルタも正しく書いたのに効かない、という最後の落とし穴はアクセス制御の外側にあります。誰に配るか (アイデンティティ)、資格情報をどこに置くか (シークレット)、外へ出る通信をどう絞るか (ネットワーク) の 3 点を片付けます。
Databricks のグループには 2 種類あります。アカウントコンソールで管理されるアカウントグループと、ワークスペース内で作られたレガシーのワークスペースローカルグループです。Unity Catalog のデータ権限を付与できるのはアカウントグループだけで、ワークスペースローカルグループには付与できず、他ワークスペースへの割り当てもアカウントレベルのロール付与もできません。GRANT がうまくいかないときは、グループ名の特殊文字やメンバー数ではなく、まずグループの種別を疑ってください。ワークスペースローカルグループが自動でアカウントグループへ昇格することもありません。
アカウント内の全ユーザーとサービスプリンシパルを含む `account users` というシステムグループが自動で用意されており、ABAC ポリシーの `TO` に指定する宛先としてよく使われます。ここへ広い権限を与えると事実上の全員公開になる点には注意します。前節で見た `is_account_group_member()` がアカウントレベルの所属だけを判定するのも、この設計に対応しています。
外部 API のキーや DB のパスワードをノートブックへ平文で書くと、UC の GRANT が一切効かない場所に機密が露出します。正しい置き場がシークレットスコープです。取得は `dbutils.secrets.get(scope="prod", key="api_key")` の 1 行で、取得した値は表示時に `[REDACTED]` に置き換えられます。`dbutils.fs.head` で読む経路や `spark.conf.get` で読む API は存在しません。
スコープ名はワークスペース内で一意で、英数字・ダッシュ・アンダースコア・`@`・ピリオドが使え、最大 128 文字、大文字小文字は区別されません。アクセス制御は `READ` / `WRITE` / `MANAGE` の 3 段階です。値を Databricks 側に保存するスコープと、Azure Key Vault の内容を読み出すスコープがありますが、取得コードはどちらも同じ `dbutils.secrets.get` です。
サーバーレスコンピュートは Databricks 側の基盤で動くため、顧客 VPC のセキュリティグループでは制御できません。公式の手段は 2 つです。1 つはServerless Egress Control で、許可したドメイン (FQDN) 宛だけにアウトバウンドを限定します。もう 1 つがNCC (Network Connectivity Configuration) で、こちらの中核用途はサーバーレスの送信元 IP を安定させることです。接続元 IP を allowlist で絞っている Snowflake などの外部サービスへ接続するとき、この固定化がないと通してもらえません。
NCC はアカウント管理者がアカウントコンソールで作るリージョン単位のオブジェクトで、プライベートエンドポイントを束ねる役割も持ち、ワークスペースへアタッチして使います。宛先を絞るのが Egress Control、出口に固定の名札を付けるのが NCC、と役割で分けて覚えます。サーバーレスは全エグレスを遮断していて外部 API を呼べない、という説明は誤りです。
この 3 つは、いずれも「テーブルに GRANT を書く」だけでは塞げない穴に対応しています。アカウントグループを整えなければ権限の宛先が定まらず、シークレットスコープを使わなければ資格情報が UC の外に漏れ、外向き通信を絞らなければ許可された利用者がデータを外部へ持ち出せます。アクセス制御は、この 3 層が揃って初めて意図どおりに働きます。
確認 — 穴あけ 3 問
0 / 3
空欄を押すと選択肢が出ます。間違えても減点はありません。
Unity Catalog のデータ権限を付与できるのは グループで、ワークスペースローカルグループには付与できません。
シークレットスコープ名は最大 文字で、大文字小文字は区別されません。
サーバーレスの送信元 IP を安定させ、IP allowlist を持つ外部サービスへ接続できるようにするのは です。
この章のまとめ
この端末にだけ保存されます(登録不要)
この章の根拠
最終確認 2026-08-09 / 対応バージョン DEA 2026-05-04 改訂版
コース全体