---
title: "Snowflake Horizon Catalogとは？外部エンジン連携とガバナンス設定SQL【2026年11月】"
url: "https://www.issoh.co.jp/tech/details/2717/"
published: 2024-06-21
updated: 2026-11-01
categories: ["データ分析・BI"]
publisher: "株式会社一創"
---

# Snowflake Horizon Catalogとは？外部エンジン連携とガバナンス設定SQL【2026年11月】

Snowflake Horizon Catalogは、Snowflakeの内外にあるデータを対象にしたカタログ兼ガバナンス層です。2026年に入って役割が大きく変わりました。2月にApache Sparkなどの外部エンジンからSnowflake管理のApache Icebergテーブルを読めるようになり、5月には書き込みも一般提供（GA）に入りました。9月にはAIエージェントの権限に上限をかけるRestricted Session ScopeがGAになり、10月にはSnowflake外のBIツールやデータベースのメタデータを集めるHorizon Contextがプレビューで始まっています。

この記事では、2026年に提供範囲が広がった外部エンジン連携とAIエージェント統制を中心に、公式ドキュメントとリリースノートで確かめた構文だけを使って、外部エンジンの接続手順、外部エンジンへのポリシー適用、Horizon Context、品質・分類・アクセス制御、Open Catalogとの違いを実装できる粒度で整理します。

## まとめ：Horizon Catalogの要点（2026年11月時点）

Horizon Catalogは、仮想ウェアハウスやストレージを担うSnowflake本体とは別レイヤーの「カタログ兼ガバナンス層」です。[公式ドキュメント](https://docs.snowflake.com/en/user-guide/snowflake-horizon)は「the agentic catalog for all your data, whether it is inside or outside of Snowflake」と定義しており、Snowflakeの外にあるデータとエンジンを対象に含めます。

| 領域             | 代表機能                     | 実装の起点                             | 提供段階・条件               |
| -------------- | ------------------------ | --------------------------------- | --------------------- |
| 外部エンジン連携       | Horizon IRC              | /polaris/api/catalog              | 読み書きGA・全エディション        |
| 外部エンジンへのポリシー適用 | Scan Plan API            | Iceberg 1.11以上                    | プレビュー・Enterprise以上    |
| 外部カタログ同期       | カタログリンクドデータベース           | CREATE DATABASE … LINKED\_CATALOG | GA（2025年10月）          |
| AIコンテキスト       | Horizon Context          | メタデータコネクタ                         | プレビュー（2026年10月）       |
| 検出             | Universal Search         | Snowsight                         | メタデータのみ検索             |
| 系統             | リネージ                     | SNOWFLAKE.CORE.GET\_LINEAGE       | Enterprise以上          |
| 品質             | データメトリック関数               | ADD DATA METRIC FUNCTION          | Enterprise以上・サーバーレス課金 |
| 機密データ          | 自動分類                     | CLASSIFICATION\_PROFILE           | Enterprise以上・サーバーレス課金 |
| 保護             | マスキング／行アクセス              | SET MASKING POLICY                | Enterprise以上          |
| エージェント統制       | Restricted Session Scope | セッションポリシー                         | GA（2026年9月）           |
| セキュリティ点検       | Trust Center             | TRUST\_CENTER\_ADMIN              | リーダーアカウント非対応          |

導入判断で先に決めるべき点は3つあります。Icebergの相互運用を新規に始めるならOpen Catalogではなく**Horizon Catalog側で組む**こと（Open Catalogは未利用の組織からの新規申込を受け付けていません）。外部エンジンから読ませるテーブルにマスキングや行アクセスを効かせたいならEnterprise Edition以上が前提になること。そして外部エンジンからのAPI呼び出しは2026年後半から課金が始まる予定であることです。

## Horizon Catalogの定義とSnowflake本体との境界

### 呼称が「Snowflake Horizon」から変わった経緯

2024年の[公式ブログ](https://www.snowflake.com/en/blog/announcing-new-innovations-for-snowflake-horizon/)までは「Snowflake Horizon」と呼ばれ、コンプライアンス・セキュリティ・プライバシー・相互運用性・アクセスの5領域の機能を束ねる名前でした。現在の公式資料は「Horizon Catalog」に揃っています。2025年11月4日の[プレスリリース](https://www.snowflake.com/en/news/press-releases/snowflake-delivers-the-enterprise-lakehouse-with-enhanced-open--data-access-and-flexibility-for-agentic-ai/)は、Horizon Catalogを「the universal AI catalog that provides context and governance for AI across all data」と呼び、Apache PolarisとApache Iceberg REST CatalogのオープンなAPIをHorizon Catalogへ直接組み込むと発表しました。

ドキュメントの構成もこれに合わせて変わり、行アクセスポリシーやマスキングポリシーの解説はHorizon Catalogを親階層とするページ群に置かれています。旧称で書かれた資料はCatalog付きの現行名に読み替え、対象がSnowflake外部のデータとエンジン、AIエージェントの振る舞いまで広がっている点を前提に読んでください。

### Snowflake基盤機能とHorizon Catalogの役割分担

ロールベースのアクセス制御（GRANT／REVOKE）はSnowflakeの基盤機能で、Horizon Catalogが追加したものではありません。Horizon Catalogの価値は、その基盤の上でタグ・分類・ポリシーを一貫して適用し、どのデータが機密でどこから来たかを追跡できる状態にする点にあります。「Horizonを導入する」という表現も実態に合いません。Snowflakeアカウントに最初から含まれる機能群で、外部エンジン向けのIceberg REST APIも全エディションで使えます。費用が変わるのは、Enterprise Edition以上を要する機能と、サーバーレスで動く処理の使用量です。

## 外部エンジンからIcebergテーブルを読み書きする手順

Horizon CatalogにはApache Polarisが組み込まれ、IcebergのREST API（公式の呼称はHorizon Iceberg REST Catalog API、以下Horizon IRC）を公開しています。[公式の対応表](https://docs.snowflake.com/en/user-guide/tables-iceberg-access-using-external-query-engine-snowflake-horizon)にはApache Spark・Trino・Apache Flink・DuckDB・PyIceberg・Dremio・StarRocks・Apache Dorisが並び、Snowflakeのユーザー・ロール・ポリシーをそのまま使ってテーブルを読み書きできます。提供段階はリリースノート上で次のように進みました。

| 日付         | 内容                                     | 段階 |
| ---------- | -------------------------------------- | -- |
| 2025-10-17 | 外部Iceberg RESTカタログと同期するカタログリンクドデータベース  | GA |
| 2026-02-06 | Snowflake管理Icebergテーブルを外部エンジンから読み取り    | GA |
| 2026-05-26 | 同テーブルへの外部エンジンからの書き込み（v2・v3）、WIF／OIDC認証 | GA |
| 2026-10-29 | 外部管理Icebergテーブルを同じエンドポイントで読み書き         | GA |

2026年10月29日の[リリースノート](https://docs.snowflake.com/en/release-notes/2026/other/2026-10-29-externally-managed-iceberg-tables-horizon-irc-ga)には、Snowflakeのデータ保護ポリシーが付いた外部管理テーブルへのアクセスはプレビューのままだと書かれています。ポリシー付きの外部管理テーブルを本番で外部エンジンへ開放するのは、GAを待ってからにするのが安全です。

### 外部エンジン用サービスユーザーとPATの準備

外部エンジン用には、人のユーザーではなくサービスユーザーを作り、読ませたいテーブルだけに権限を付けたロールを割り当てます。読み取りに必要なのはテーブルのSELECTと、親データベース・スキーマのUSAGEです。PATはROLE\_RESTRICTIONで利用ロールを1つに固定できます。既定ではサービスユーザーによる発行・利用にネットワークポリシーが必要です。Horizon IRCはユーザー単位のネットワークポリシーに非対応のため、接続元を許可するアカウント単位のポリシーが適用されていることを先に確認します。

```
CREATE OR REPLACE ROLE data_engineer;
GRANT USAGE ON DATABASE iceberg_test_db TO ROLE data_engineer;
GRANT USAGE ON SCHEMA iceberg_test_db.public TO ROLE data_engineer;
GRANT SELECT ON TABLE iceberg_test_db.public.test_table TO ROLE data_engineer;

CREATE OR REPLACE USER horizon_rest_srv_account_user TYPE=SERVICE DEFAULT_ROLE=data_engineer;
GRANT ROLE data_engineer TO USER horizon_rest_srv_account_user;

ALTER USER IF EXISTS HORIZON_REST_SRV_ACCOUNT_USER
ADD PAT HORIZON_REST_SRV_ACCOUNT_USER_PAT
  DAYS_TO_EXPIRY = 7
  ROLE_RESTRICTION = 'DATA_ENGINEER'
  COMMENT = 'HORIZON REST API PAT FOR SERVICE ACCOUNT';
```

書き込みもさせる場合、DMLにはテーブルのSELECT・UPDATE・TRUNCATE・INSERT・DELETEの5権限が**すべて**必要です。INSERTだけ付けても追記できません。もう1つの落とし穴が外部ボリュームの権限で、テーブルのOWNERSHIPを持つロールが外部ボリュームのUSAGEを失うと、vended credentials（カタログが払い出す一時的なストレージ認証情報）を要求する読み書きはすべて失敗します。PAT以外の認証はExternal OAuth、キーペア（JWTの既定の有効期間は1時間）、WIF／OIDCから選べます。

### 疎通確認とSparkの接続設定

接続先は`https://<account_identifier>.snowflakecomputing.com/polaris/api/catalog`です。アカウント識別子は`<組織名>-<アカウント名>`の形式で、`SELECT CURRENT_ORGANIZATION_NAME() || '-' || CURRENT_ACCOUNT_NAME();`で取得できます。まずPATをアクセストークンに交換し、カタログの設定を取得できるか確かめます。

```
curl -i --fail -X POST "https://<account_identifier>.snowflakecomputing.com/polaris/api/catalog/v1/oauth/tokens" \
 --header 'Content-Type: application/x-www-form-urlencoded' \
 --data-urlencode 'grant_type=client_credentials' \
 --data-urlencode 'scope=session:role:DATA_ENGINEER' \
 --data-urlencode 'client_secret=<PAT_token>'

curl -i --fail -X GET "https://<account_identifier>.snowflakecomputing.com/polaris/api/catalog/v1/config?warehouse=ICEBERG_TEST_DB" \
 -H "Authorization: Bearer <access_token>" \
 -H "Content-Type: application/json"
```

引用符なしで作ったデータベース名は、小文字で作っていても**大文字**で指定します。ここで得たアクセストークンは疎通確認専用で、Sparkの設定にはPATそのものを渡します。公式のPySpark例から要点を抜き出すと次のとおりです。

```
from pyspark.sql import SparkSession

CATALOG = "ICEBERG_TEST_DB"
spark = (
    SparkSession.builder
    .config("spark.jars.packages",
            "org.apache.iceberg:iceberg-spark-runtime-3.5_2.12:1.9.1,"
            "org.apache.iceberg:iceberg-aws-bundle:1.9.1")
    .config("spark.sql.extensions", "org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions")
    .config("spark.sql.defaultCatalog", CATALOG)
    .config(f"spark.sql.catalog.{CATALOG}", "org.apache.iceberg.spark.SparkCatalog")
    .config(f"spark.sql.catalog.{CATALOG}.type", "rest")
    .config(f"spark.sql.catalog.{CATALOG}.uri", "https://<account_identifier>.snowflakecomputing.com/polaris/api/catalog")
    .config(f"spark.sql.catalog.{CATALOG}.warehouse", CATALOG)
    .config(f"spark.sql.catalog.{CATALOG}.credential", "<PAT_token>")
    .config(f"spark.sql.catalog.{CATALOG}.scope", "session:role:DATA_ENGINEER")
    .config(f"spark.sql.catalog.{CATALOG}.client.region", "<region>")
    .config(f"spark.sql.catalog.{CATALOG}.header.X-Iceberg-Access-Delegation", "vended-credentials")
    .config("spark.sql.iceberg.vectorization.enabled", "false")
    .getOrCreate()
)
spark.sql("show namespaces").show()
```

`.warehouse`に渡すのはSnowflakeの**仮想ウェアハウス名ではなくデータベース名**です。データがAzure Storageにある場合は`iceberg-aws-bundle`を`iceberg-azure-bundle`に差し替えます。

### Horizon IRCの課金と操作上の制約

公式ドキュメントの課金節は、Horizon IRCを全エディションで利用可能とし、APIリクエストを100万コールあたり0.5クレジットのCloud Servicesとして課金すると記載しています。リージョンをまたぐデータアクセスには通常の転送料金がかかります。ただし同じ節に「Billing for this feature is scheduled to begin in second half of 2026, subject to change.」とあり、開始時期は確定していません。ストリーミング処理のように細かいコミットを大量に投げる構成は、呼び出し回数を先に見積もってください。

設計に効く制約は次のとおりです。

- 外部エンジンからのCREATE TABLE AS SELECT（CTAS）は未対応。ETLは CREATE TABLE と INSERT に分けて書く
- CREATE TABLEでベースロケーションを指定できず、Snowflakeがパスを決める
- イコールティ削除、Icebergのタグ・ブランチ作成、スナップショットへのロールバック、v2からv3への昇格は不可
- ユーザー単位のネットワークポリシーは非対応。AWS以外のS3互換ストレージも未対応
- S3のSSE-KMSで暗号化している場合、外部ボリュームの`KMS_KEY_ID`にキーの完全なARNを設定するか、IAMロールに`kms:DescribeKey`を許可しないと、認証情報の払い出しは成功してもデータの読み書きで失敗する

Sparkで書いた既存のETLをそのまま向ければ動く、という前提で移行計画を立てるべきではありません。CTASとイコールティ削除の有無を先に棚卸しし、該当するジョブだけは書き換えるか、Snowflake側で処理する構成にしてください。

## 外部エンジンにもマスキングと行アクセスを効かせる設定

Snowflakeで定義したマスキングポリシーや行アクセスポリシーは、外部エンジンから読ませるときにも適用できます。[公式ドキュメント](https://docs.snowflake.com/en/user-guide/tables-iceberg-query-using-external-query-engine-snowflake-horizon-enforce-access-policies)が示す方法は2つです。

| 観点      | Snowflake Connector for Spark | IRC Scan Plan API     |
| ------- | ----------------------------- | --------------------- |
| 対応エンジン  | Apache Sparkのみ                | Scan Plan API対応の全エンジン |
| 仕組み     | JDBCでSnowflake経由で実行           | カタログがフィルタ済みのスキャン計画を返す |
| クライアント側 | コネクタの導入が必要                    | Iceberg SDK 1.11以上    |

Scan Plan APIはプレビューで、Enterprise Edition以上が条件です。利用時はポリシーの評価・適用にSnowflakeの計算資源を消費し、一時ストレージや条件に応じたリージョン間転送の費用も発生します。適用できるのはマスキングポリシー、行アクセスポリシー、タグベースのマスキング、タグベースの行アクセスの4種類だけで、集計ポリシーや投影ポリシーなどほかのポリシーは対象外です。Scan Plan APIでは、カタログ自身がポリシーを評価して許可された範囲のデータだけをエンジンに渡すため、外部エンジンがポリシーを正しく守るかどうかを信用する必要がありません。Sparkでは`iceberg-spark-runtime`と`iceberg-aws-bundle`を1.11.0に更新します。加えて、ポリシーを定義し、接続ロールに対象テーブルの権限と外部ボリュームのUSAGE権限を付与する必要があります。フィルタ済みの中間データは利用者側の外部ボリュームに置かれ、作成から24時間で削除されるため、24時間を超えるクエリは失敗することがあります。ストレージへ直接アクセスできる利用者にはポリシーが効かない点と、ポリシー内の`CURRENT_STATEMENT()`が評価されない点も公式の注意事項に挙がっています。

見落としやすいのが書き込みです。オープンソースのScan Plan APIはポリシー付きテーブルへの書き込みをHTTP 403で拒否します。Horizon Catalogはこれを拡張していますが、[書き込みを通すのはポリシー本体が決まった型の条件で書かれている場合だけ](https://docs.snowflake.com/en/user-guide/tables-iceberg-enforce-access-policies-scan-plan-api)です。マスキングなら`CURRENT_ROLE()`がロールの一覧に含まれるか、`CURRENT_ACCOUNT()`がアカウントの一覧に含まれるか、`CURRENT_USER()`がリテラルのユーザー名と一致するか、などです。行アクセスなら`IS_ROLE_IN_SESSION('ANALYST_ROLE')`のようなリテラル指定か、マッピングテーブルへの`EXISTS`です。これ以外の書き方では403になる可能性があります。外部エンジンが書き込むテーブルには、条件をこの型に収めたポリシーを別に用意するのが確実です。

## Horizon Contextで集めるメタデータと業務定義

Horizon Contextは、Horizon Catalogの中にある「統制されたコンテキスト層」です。Snowflake内のオブジェクトに加え、BIツールやほかのデータベースのメタデータを集め、業務上の意味を付けて、人・BIツール・AIエージェントが同じ定義を参照できるようにします。2026年10月12日の[リリースノート](https://docs.snowflake.com/en/release-notes/2026/other/2026-10-12-horizon-context-preview)でプレビューが始まり、Power BI・Tableau・dbt・Databricks・BigQuery・SQL Server・Oracle・PostgreSQLを含む18のソースへのメタデータコネクタが用意されました。提供範囲はAWSとAzureの商用リージョンで、Google Cloudのリージョンは含まれていません。

公式ドキュメントは、集めるコンテキストを4つの層に分けています。

| 層  | 答える問い           | 例                   |
| -- | --------------- | ------------------- |
| 構造 | 何があり、どうつながっているか | テーブル、列、ダッシュボード、リネージ |
| 運用 | 今どういう状態か        | クエリ履歴、鮮度、品質指標       |
| 意味 | 何を意味するか         | セマンティックビューの指標と関係    |
| 行動 | 誰がどう使っているか      | 利用頻度、クエリパターン、下流の利用者 |

業務定義の置き場はセマンティックビューで、その編集環境であるSemantic Studioは2026年9月30日にGAになりました。Snowflake外のパイプラインのリネージは、Apache AirflowなどのOpenLineage発行元からSnowflakeのRESTエンドポイントへイベントを送れば、Snowflake内のリネージと同じグラフに統合されます。同じプレビューで追加されたAPPLY COMMENT権限を使うと、データスチュワードにMODIFYやOWNERSHIPを渡さずに説明文だけを編集させられます。メタデータを見る権限とデータを読む権限は別管理なので、カタログの閲覧者をデータの利用者と同じロールにまとめない設計にしてください。

### Universal Searchが探せる範囲

カタログの入口はSnowsightのUniversal Searchです。アカウント内のオブジェクトに加え、Snowflake Marketplaceのデータ製品、公式ドキュメント、Community Knowledge Baseの記事を横断し、表記ゆれや自然言語の問いかけにも結果を返します。ただし[公式ドキュメント](https://docs.snowflake.com/en/user-guide/ui-snowsight-universal-search)は「Universal Search searches only the object metadata, not the contents of your database objects.」と明記しています。検索されるのはオブジェクトと列の名前・コメント・タグで、格納された値は対象外です。コメントが空でも名前やタグが検索語に合えばヒットしますが、意味で探す問いかけに当てるにはコメントが手がかりになります。結果は実行中のロールと二次ロールの権限で変わります。

### Cortexによるテーブル説明の自動生成

コメントを人手で埋める負担を下げるのが、Cortexによる説明の自動生成です。ストアドプロシージャを呼ぶと、テーブルと列の説明文がJSONで返ります。

```
CALL AI_GENERATE_TABLE_DESC(
  'mydb.sch1.hr_data',
  {
    'describe_columns': true,
    'use_table_data': false
  });
```

`use_table_data`をtrueにするとサンプルデータも参照します。機微なデータを含むテーブルではfalseのまま、列名とデータ型から生成させてください。呼び出しには対象テーブルのSELECT権限と`SNOWFLAKE.CORTEX_USER`データベースロールが必要で、5,000列を超えるオブジェクトでは列の説明を生成できません。この呼び出しはコメントを書き込まない点に注意が必要です。公式ドキュメントは「The generated description is not retained by Snowflake until it is saved by the user.」としており、`ALTER TABLE t1 SET COMMENT = 'ai generated description';`のように別途保存するまでUniversal Searchの検索対象になりません。

## 依存関係とリネージをSQLで追う方法

ビューやテーブルの参照関係は、ACCOUNT\_USAGEスキーマのOBJECT\_DEPENDENCIESビューで確認します。

```
SELECT referenced_database,
       referenced_object_name,
       referencing_object_name,
       dependency_type
FROM snowflake.account_usage.object_dependencies
WHERE referenced_object_name = 'MY_TABLE';
```

このビューは最大3時間遅れて反映されます。またCTAS・INSERT・MERGEのようにデータをコピーする操作では依存関係の行が作られません。そのデータの流れを追うのがリネージで、テーブル関数`SNOWFLAKE.CORE.GET_LINEAGE`からSQLで取得できます（Enterprise Edition以上）。

```
SELECT distance,
       source_object_name,
       target_object_name
FROM TABLE(SNOWFLAKE.CORE.GET_LINEAGE('my_database.sch.table_a', 'TABLE', 'DOWNSTREAM'));
```

第2引数にはCOLUMNやTABLEなどのオブジェクトドメインを、第3引数にはUPSTREAMかDOWNSTREAMを渡します。たどる段数の`max_distance`は既定値・最大値ともに5で、出力が1,000万行を超えると通知なしに切り詰められます。5段より深い系統を調べるときは、途中のオブジェクトを起点に呼び直してください。参照関係はOBJECT\_DEPENDENCIES、データの流れはGET\_LINEAGE、誰がいつ触ったかはACCESS\_HISTORYビュー、と役割を分けて引くと迷いません。

## データ品質モニタリングの設定手順

### システムDMFの割り当てとスケジュール

データ品質は、データメトリック関数（DMF）をテーブルに紐づけて測ります。NULL件数や重複件数などの指標は`SNOWFLAKE.CORE`スキーマにシステムDMFとして用意されています。Enterprise Edition以上の機能で、スケジュール実行されたDMFの計算はサーバーレスの使用量として課金されます。

```
ALTER TABLE hr.tables.empl_info SET
  DATA_METRIC_SCHEDULE = 'USING CRON 0 8 * * MON,TUE,WED,THU,FRI UTC';

ALTER TABLE hr.tables.empl_info
  ADD DATA METRIC FUNCTION SNOWFLAKE.CORE.NULL_COUNT
    ON (email);
```

スケジュールは`'5 MINUTE'`のような分単位、上のようなCRON式、テーブルを変更するDMLを契機に動く`'TRIGGER_ON_CHANGES'`から選べます。日次バッチで入るテーブルに分単位のチェックをかけると、その回数分だけサーバーレスの費用がかかります。ロード完了直後を狙ったCRON式か、TRIGGER\_ON\_CHANGESに寄せてください。

### DMFのEXPECTATIONによる合否判定と結果の確認

測るだけでなく合否を判定したい場合は、EXPECTATION句を付けます。式がFALSEになるとexpectation violationとして報告されます。

```
CREATE OR REPLACE TABLE orders (
  order_id    NUMBER,
  customer_id NUMBER
)
WITH DATA METRIC FUNCTION SNOWFLAKE.CORE.NULL_COUNT
  ON (customer_id)
  EXPECTATION no_null_customers ( VALUE = 0 ),
     SNOWFLAKE.CORE.DUPLICATE_COUNT
  ON (order_id)
  EXPECTATION no_duplicate_orders ( VALUE = 0 );
```

実行結果はイベントテーブルに蓄積され、DATA\_QUALITY\_MONITORING\_RESULTSビューまたは同名のテーブル関数から参照します。参照経路ごとにアクセス制御の要件が違うため、監視ダッシュボードを作る前に、閲覧させたい相手がどの経路で読めるかを決めておいてください。

## 機密データの分類とアクセス制御

### 分類プロファイルによる自動分類

機密データの自動分類は、分類プロファイルを作ってデータベースやスキーマに割り当てる流れです。次の例はNAMEとNATIONAL\_IDENTIFIERだけを分類対象とし、それ以外のカテゴリは分類しません。Enterprise Edition以上の機能です。

```
CREATE OR REPLACE SNOWFLAKE.DATA_PRIVACY.CLASSIFICATION_PROFILE
  governance_db.classify_sch.my_profile(
    {
      'minimum_object_age_for_classification_days': 0,
      'snowflake_semantic_categories':
        [
          {'category': 'NAME'},
          {'category': 'NATIONAL_IDENTIFIER'}
        ]
    });

ALTER DATABASE my_db
  SET CLASSIFICATION_PROFILE = 'governance_db.classify_sch.my_profile';
```

プロファイルにはタグマップを含められ、該当した列へ「Highly Confidential」などのタグ値を自動で付けられます。分類はサーバーレスのクレジットを消費し、ACCOUNT\_USAGE.METERING\_HISTORYでservice\_typeが’SENSITIVE\_DATA\_CLASSIFICATION’の行として計上されます。プロファイルでAIモードを有効にすると、計算資源とは別にLLMのトークン料金がかかります。プロファイルの作成にはSNOWFLAKE.CLASSIFICATION\_ADMINと対象スキーマのCREATE SNOWFLAKE.DATA\_PRIVACY.CLASSIFICATION\_PROFILE、および親データベース・スキーマのUSAGEが必要です。割り当てにはプロファイルのOWNERSHIPまたはPRIVACY\_USERインスタンスロール、適切な範囲のEXECUTE AUTO CLASSIFICATION、およびアカウントに対するAPPLY TAG権限が必要です。

### マスキングポリシーと行アクセスポリシー

列単位で見せ方を変えるのがマスキングポリシー、行単位で見せる範囲を絞るのが行アクセスポリシーです。どちらもEnterprise Edition以上で、ポリシーを作ってから対象へ適用します。

```
CREATE MASKING POLICY employee_ssn_mask AS (val string) RETURNS string ->
  CASE
    WHEN CURRENT_ROLE() IN ('PAYROLL') THEN val
    ELSE '******'
  END;

ALTER TABLE IF EXISTS user_info MODIFY COLUMN ssn_number
  SET MASKING POLICY employee_ssn_mask;

CREATE OR REPLACE ROW ACCESS POLICY rap_it
AS (empl_id varchar) RETURNS BOOLEAN ->
  'IT_ADMIN' = current_role();

ALTER TABLE t1 ADD ROW ACCESS POLICY rap_it ON (empl_id);
```

別のポリシーへ差し替えるときは、UNSETとSETの2文に分けるとその間だけ列が無防備になります。`ALTER TABLE t1 MODIFY COLUMN c1 SET MASKING POLICY p2 FORCE;`のようにFORCEで一度に置き換えてください。どのオブジェクトにポリシーが当たっているかは、INFORMATION\_SCHEMA.POLICY\_REFERENCESテーブル関数で棚卸しできます。

### AIエージェント経由の閲覧を止める条件分岐

エージェントがSnowflake内で動く前提が加わり、「人が自分の権限で見るのは許すが、エージェントの実行コンテキストからは見せない」という制御が必要になりました。マスキングポリシーの本体で[IS\_AGENT\_ACTIVATED](https://docs.snowflake.com/en/sql-reference/functions/is%5Fagent%5Factivated)を評価すると、この判定を書けます。

```
CREATE OR REPLACE MASKING POLICY email_agent_mask AS (val STRING) RETURNS STRING ->
  CASE
    WHEN SYS_CONTEXT('SNOWFLAKE$CURRENT', 'IS_AGENT_ACTIVATED')::BOOLEAN = TRUE THEN '********'
    WHEN CURRENT_ROLE() IN ('ANALYST') THEN val
    ELSE '********'
  END;
```

この関数がTRUEを返すのは、Cortex Agents・Snowflake CoCo・CoWorkなどSnowflake側のエージェントが実行している場合と、管理型MCPサーバー経由の接続、SERVICE\_AGENTユーザー（2026年7月23日GA）のセッション、`IS_AGENTIC = TRUE`を設定したOAuth連携のセッションなどです。裏を返すと、**通常のユーザーにPATやキーペアで接続させた自作エージェントは「人」と判定されます**。自作エージェントにも適用するには、SERVICE\_AGENTユーザー、IS\_AGENTIC = TRUEを設定したOAuth連携、管理型MCPサーバー経由の接続など、エージェントとして識別される方式を使います。なお2026\_06の動作変更バンドルを有効にしたアカウントでは戻り値がVARCHARからBOOLEANに変わるため、上の例のように`::BOOLEAN`で比較しておくとどちらでも動きます。

### Restricted Session Scopeによるエージェント権限の制限

ユーザーの代理で動くエージェントは、既定ではそのユーザーの全権限を引き継ぎます。業務に必要な権限とエージェントに渡したくない権限が同じロールに同居する以上、ロールを絞るだけでは足りません。Restricted Session Scope（RSS）は、エージェントが動いている間だけ実効権限に上限をかける仕組みで、管理者がセッションポリシーで適用する方式が[2026年9月3日にGA](https://docs.snowflake.com/en/release-notes/2026/other/2026-09-03-restricted-session-scope)になりました。RBACと積集合を取るため、ユーザーが持たない権限を与えることはありません。

```
CREATE RESTRICTED SESSION SCOPE mydb.governance.agent_scope AS $$
privilege_scopes:
  allowed_privileges:
    - privileges: [data read, program usage]
      account: [all]
    - privileges: [data write]
      databases: [SANDBOX_DB, USER$]
role_scopes:
  blocked_roles: [ACCOUNTADMIN, SYSADMIN, SECURITYADMIN]
  allow_role_switching: true
$$;

CREATE SESSION POLICY mydb.governance.agent_policy
  AGENT_RESTRICTED_SESSION_SCOPE = 'MYDB.GOVERNANCE.AGENT_SCOPE';

ALTER ACCOUNT SET SESSION POLICY mydb.governance.agent_policy;
```

この例は、本番データは読み取りのみ、書き込みはサンドボックスと各ユーザーの個人データベースだけに限り、列挙した管理者ロールの使用を禁じます。ただし、許可されたプライマリロールが継承している権限まではblocked\_rolesで除去されません。ユーザー単位のセッションポリシーがある場合はそちらだけが使われ、アカウント単位のポリシーとは合成されません。RSSで「どこまで触れるか」を絞り、マスキングで「見える値」を絞る、という二段で組むのが公式の想定です。

## Trust Centerによるセキュリティ態勢の点検

Trust Centerは、Snowflakeアカウントをスキャナの推奨事項に照らして評価し、リスクがあれば発見事項（finding）を作る仕組みです。発見事項が空の場合も、対象スキャナが有効で、実行済みであり、表示フィルタで結果を除外していないことを確認します。空の一覧だけで、アカウント全体に問題がないとは判断できません。

```
USE ROLE ACCOUNTADMIN;

CREATE ROLE trust_center_admin_role;
GRANT APPLICATION ROLE SNOWFLAKE.TRUST_CENTER_ADMIN TO ROLE trust_center_admin_role;

CREATE ROLE trust_center_viewer_role;
GRANT APPLICATION ROLE SNOWFLAKE.TRUST_CENTER_VIEWER TO ROLE trust_center_viewer_role;

GRANT ROLE trust_center_admin_role TO USER example_admin_user;
```

スキャナはSecurity Essentials・CIS Benchmarks・Threat Intelligence・AI Security・Data Securityの5パッケージに分かれています。外部・内部ステージへの異常なデータ書き出しを検知するData Securityは2026年10月26日にGAになりました。Security Essentialsの既定の定期スキャンは無料ですが、ほかのスキャンや追加のオンデマンド実行はサーバーレスの計算料金がかかります。全パッケージを毎日回す設定にする前に、まずSecurity Essentialsの発見事項を潰すところから始めるのが費用対効果の高い順番です。発見事項はSNOWFLAKE.ACCOUNT\_USAGE.TRUST\_CENTER\_FINDINGSビューからSQLで取得でき、リーダーアカウントは対象外です。

## Horizon Catalog・Open Catalog・Apache Polarisの違い

名前が似た3つは、提供形態と新規に選べるかどうかで分かれます。

| 観点     | Horizon Catalog   | Snowflake Open Catalog | Apache Polaris |
| ------ | ----------------- | ---------------------- | -------------- |
| 提供形態   | Snowflakeアカウントの機能 | Polarisのマネージドサービス      | OSS（自前で運用）     |
| 新規利用   | 全アカウントで可          | 未作成の組織は申込不可            | 可              |
| 外部エンジン | Horizon IRC       | Iceberg REST           | Iceberg REST   |
| ポリシー   | Snowflakeのポリシーを適用 | カタログ独自のRBAC            | カタログ独自のRBAC    |

Open Catalogは、旧称のPolaris Catalogで覚えている方も多いIceberg RESTカタログです。[Open Catalogの概要ページ](https://docs.snowflake.com/en/user-guide/opencatalog/overview)は「New customers should use Snowflake Horizon Catalog for Apache Iceberg™ tables and multi-engine interoperability with Iceberg.」と案内し、「Customers who haven’t previously created a Snowflake Open Catalog account can’t sign up for their first Open Catalog account.」と記しています。既存の利用者は継続でき、追加アカウントも作れますが、これから設計する構成でOpen Catalogを前提に置くのは避けてください。Polarisを自前で運用する場合の構成は[Apache Polarisとは？IcebergカタログのRBACとDocker導入手順【1.8.0対応】](/tech/details/9631/)で扱っています。

AWS GlueやDatabricks Unity Catalogなど既存の外部カタログは、カタログリンクドデータベースでHorizon Catalogと同期させます。Snowflakeは既定で30秒ごとにリモートカタログを確認し、名前空間とテーブルを自動で登録します。

```
CREATE DATABASE my_linked_db
  LINKED_CATALOG = (
    CATALOG = 'my_catalog_int'
  );

SELECT SYSTEM$CATALOG_LINK_STATUS('my_linked_db');
```

リモートカタログ側のユーザーやロールのアクセス制御は同期されないため、Snowflake側で改めてGRANTを設計する必要があります。逆方向、つまりUnity CatalogからHorizon Catalogのテーブルを参照する連携は、公式の対応表で「Not announced」のままです（2026年11月時点）。Databricks側から見た権限モデルは[Unity Catalogとは？3レベル名前空間と権限継承・移行判断を実装視点で解説【2026年版】](/tech/details/16134/)を参照してください。

## 現行Snowflakeに存在しない構文と正しい代替

Horizonの日本語解説には、実行するとエラーになるSQLを載せたものが流通しています。頻出する誤りや混同しやすい説明を、公式ドキュメントの実在構文と対にして整理します。

| 実在しない記述                        | 正しい手段                                      |
| ------------------------------ | ------------------------------------------ |
| SHOW OBJECT DEPENDENCIES       | ACCOUNT\_USAGE.OBJECT\_DEPENDENCIESを検索     |
| 列定義の ENCRYPTED 属性              | 保存データは既定で暗号化                               |
| CREATE MONITORING RULE         | ADD DATA METRIC FUNCTION                   |
| CREATE SEARCH INDEX            | ADD SEARCH OPTIMIZATION／Cortex Search      |
| TRUST\_CENTER.POLICIES への問い合わせ | ACCOUNT\_USAGE.TRUST\_CENTER\_FINDINGSを検索  |
| information\_schema.lineage    | SNOWFLAKE.CORE.GET\_LINEAGE                |
| SET DATA CLASSIFICATION        | CLASSIFICATION\_PROFILEの割り当て               |
| CREATE DATABASE … CLONE を複製と説明 | CREATE REPLICATION GROUP（クローンは同一アカウント内の複製） |

特に最後の行は実害が大きい誤りです。ゼロコピークローンはリージョン間の複製ではないため、クローンを前提に事業継続計画を書くとリージョン障害時に復旧できません。出典が示されていないSQLは、公式ドキュメントで構文を引いてから使ってください。

## よくある質問

### Snowflake HorizonとHorizon Catalogは別物ですか？

別製品ではありません。2024年ごろまで「Snowflake Horizon」と呼ばれていた機能群を、現在の公式資料はHorizon Catalogと呼んでいます。対象はSnowflake内のガバナンス機能から、外部エンジンが読み書きするIcebergテーブルやAIエージェントの統制まで広がっています。

### Horizon Catalogは追加費用がかかりますか？

個別に購入する製品ではなく、Snowflakeアカウントの機能群です。リネージ、データ品質モニタリング、自動分類、マスキング・行アクセスポリシーはEnterprise Edition以上が条件で、品質モニタリングと自動分類はサーバーレスのクレジットを消費します。外部エンジン向けのHorizon IRCは全エディションで使え、100万コールあたり0.5クレジットの課金が2026年後半から始まる予定です。

### SparkやTrinoからSnowflakeのIcebergテーブルを読み書きできますか？

できます。Snowflake管理のIcebergテーブルは2026年2月に読み取り、5月に書き込みがGAになり、外部管理テーブルも10月29日にGAになりました。接続先は`/polaris/api/catalog`のエンドポイントで、PATなどで認証し、Snowflakeのロールの権限がそのまま適用されます。外部エンジンからのCTASやイコールティ削除は使えません。

### Polaris Catalogは今も使えますか？

Polaris Catalogはマネージドサービスとして提供される際にSnowflake Open Catalogという名称になりました。既存の利用者は継続して使えますが、Open Catalogアカウントを作ったことがない組織は新規に申し込めません。これから始めるならHorizon Catalog側でIcebergの相互運用を組む前提で設計してください。

### Horizon Contextとは何ですか？

Horizon Catalogの中で、メタデータを集めて業務上の意味を付け、人とAIエージェントに同じ定義を渡すためのコンテキスト層です。2026年10月12日にプレビューが始まり、Power BI・Tableau・dbt・Databricks・BigQueryなど18のソースからメタデータを集めるコネクタが使えます。提供はAWSとAzureの商用リージョンに限られます。

## 関連記事

- [Apache Polarisとは？IcebergカタログのRBACとDocker導入手順【1.8.0対応】](/tech/details/9631/)
- [オープンテーブルフォーマットとは？Iceberg・Delta Lake・Hudiの違いと選び方を実装視点で解説【2026年版】](/tech/details/13784/)
- [Unity Catalogとは？3レベル名前空間と権限継承・移行判断を実装視点で解説【2026年版】](/tech/details/16134/)
- [Snowflake Cortex Agentsとは？CREATE AGENT・REST API・権限とコストの実装手順【2026年10月】](/tech/details/9609/)
- [Snowflake Cortex AIとは？読み方・機能一覧・料金と日本リージョンで使えるモデル](/tech/details/5958/)

---

出典: [Snowflake Horizon Catalogとは？外部エンジン連携とガバナンス設定SQL【2026年11月】](<https://www.issoh.co.jp/tech/details/2717/>)（株式会社一創）
