データ分類を使用する

このトピックでは、Snowflakeでの 分類プロセス の使用例を示します。

このトピックの内容:

概要

データを分類する次の例は、スコープに基づいてさまざまなユースケースに対応しています。

初めて分類を使用する場合は、単一のテーブルの分類から始めてから、他の2つの例に進んでください。

共通テーブルおよびロール

このトピックの例では、以下に示すテーブルとカスタムロールを使用しています。

  • テーブル: 従業員に関するデータが含まれている my_db.my_schema.hr_data

  • ロール:

    • data_engineer: 分類プロセス を実行します。

    • policy_admin: マスキングポリシーで個人情報を保護します。

    • analyst: アクセスを制限する必要がある可能性のあるロールの例です。例では、このロールが存在することを前提としています。

    • データベースロール:

      • GOVERNANCE_ADMIN: 分類システムタグを割り当てます。

      • GOVERNANCE_VIEWER: タグとマスキングポリシーに関連するAccount Usageビューをクエリします。

  1. テーブルを作成します。

    CREATE OR REPLACE TABLE hr_data (
        age INTEGER,
        email_address VARCHAR,
        fname VARCHAR,
        lname VARCHAR
        );
    
    Copy
  2. テーブルをロードします(詳細表示なし)。

  3. カスタムロールを作成し、それらのロールに必要な権限を付与します。

  4. 分類プロセスを実行するには、 data_engineer ロールがテーブルにアクセスする必要があります。ロールをデータベースロールに切り替えることはできないため、この例では GOVERNANCE_ADMIN データベースロールを data_engineer ロールに付与することに注意してください。

    use role accountadmin;
    
    create role data_engineer;
    
    grant usage on database my_db to role data_engineer;
    
    grant usage on schema my_db.my_schema to role data_engineer;
    
    grant select, update on table my_db.my_schema.hr_data to role data_engineer;
    
    grant database role snowflake.governance_admin to role data_engineer;
    
    Copy
  5. policy_admin カスタムロールは、 PII データを含むすべての列にマスキングポリシーを割り当てる必要があります。

    use role accountadmin;
    create role policy_admin;
    grant apply masking policy on account to role policy_admin;
    grant database role snowflake.governance_viewer to role policy_admin;
    
    Copy

単一のテーブルを分類する

単一のテーブルの例は、3段階の分類プロセス(つまり、分析、確認、適用)を拡張して結果を適用し、 analyst カスタムロールからのテーブルアクセスを取り消します。

ステップ1: テーブル列を分類する

このステップでは、 data_engineer が分類プロセスを実行し、 policy_adminマスキングポリシー で列データを保護します。

  1. 分析: data_engineer カスタムロールを使用して EXTRACT_SEMANTIC_CATEGORIES 関数を呼び出し、 my_db.my_schema.hr_data という名前のテーブルの列を分類します。

    USE ROLE data_engineer;
    
    SELECT EXTRACT_SEMANTIC_CATEGORIES('my_db.my_schema.hr_data');
    
    Copy
  2. レビュー: データエンジニアが結果をレビューして、結果が意味を成すことを確認します。詳細については、 出力を解釈する をご参照ください。

  3. 適用: データエンジニアは、分類システムタグを列に割り当てます。

    データエンジニアには、自動割り当てと手動割り当ての2つのオプションがあります。

    システムタグを自動的に割り当てるには、 ASSOCIATE_SEMANTIC_CATEGORY_TAGS ストアドプロシージャを呼び出します。ノート:

    • テーブルの完全修飾名と最初のステップの関数は、ストアドプロシージャの引数です。

    • ストアドプロシージャは EXTRACT_SEMANTIC_CATEGORIES 関数を再実行します。最初のステップの結果を保持する場合は、ストアドプロシージャを呼び出す前に結果をテーブルに保存します。

      CALL ASSOCIATE_SEMANTIC_CATEGORY_TAGS(
         'my_db.my_schema.hr_data',
          EXTRACT_SEMANTIC_CATEGORIES('my_db.my_schema.hr_data')
      );
      
      Copy

      ストアドプロシージャが正常に実行されると、次のようなメッセージが返されます。 Applied tag semantic_category to <n> columns. Applied tag privacy_category to <n> columns.

    それ以外の、ストアドプロシージャが実行されない場合や、必要に応じて分類システムタグを手動で各列に割り当てることが決定された場合は、 ALTER TABLE ... ALTER COLUMN ステートメントを使用します。たとえば、いずれかのシステムタグを FNAME 列(つまり、名)に割り当てます。

    USE ROLE data_engineer;
    
    ALTER TABLE my_db.my_schema.hr_data
      MODIFY COLUMN fname
      SET TAG SNOWFLAKE.CORE.SEMANTIC_CATEGORY='NAME';
    
    Copy

    または

    ALTER TABLE my_db.my_schema.hr_data
      MODIFY COLUMN fname
      SET TAG SNOWFLAKE.CORE.PRIVACY_CATEGORY='IDENTIFIER';
    
    Copy

ステップ2: テーブル列を保護する

このステップでは、 my_db.my_schema.hr_data テーブルのいくつかの列に PRIVACY_CATEGORY = 'IDENTIFIER' タグが割り当てられており、これらの列をマスキングポリシーで保護する必要があることを前提としています。

これらの列を保護するには、

  1. policy_admin ロールを使用して、 IDENTIFIER プライバシータグが適用されている列を検索します。

    USE ROLE policy_admin;
    
    SELECT * FROM SNOWFLAKE.ACCOUNT_USAGE.TAG_REFERENCES
      WHERE TAG_NAME = 'PRIVACY_CATEGORY'
      AND TAG_VALUE = 'IDENTIFIER';
    
    Copy

    TAG_REFERENCES ビューの遅延は、最大120分間です。より早く結果が必要で、分類タグをクエリする列の名前がわかっている場合は、代わりに TAG_REFERENCES または TAG_REFERENCES_ALL_COLUMNS テーブル関数を使用できます。

  2. policy_admin ロールを使用して、適切な列にマスキングポリシーを適用します。たとえば、次のステートメントは identifier_mask マスキングポリシーを fname 列に適用します。

    ALTER TABLE my_db.my_schema.hr_data
      MODIFY COLUMN fname
      SET MASKING POLICY governance.policies.identifier_mask;
    
    Copy

ステップ3: システムタグを使用してアクセス権を取り消す

最後に、セキュリティ管理者(つまり、 SECURITYADMIN ロールを持つユーザー)は、

  • TAG_REFERENCES ビューをクエリして、 IDENTIFIER プライバシータグ値を持つすべての列を検索します。

  • 列に PRIVACY_CATEGORY = 'IDENTIFIER' タグが設定されているテーブルに対する analyst カスタムロールの SELECT 権限を取り消します。

ちなみに

これらのタスクを実行するために SECURITYADMIN システムロールを使用する必要はありません。必要な権限が割り当てられている任意のカスタムロールを使用できます。

USE ROLE SECURITYADMIN;

SELECT * FROM SNOWFLAKE.ACCOUNT_USAGE.TAG_REFERENCES
    WHERE TAG_NAME = 'PRIVACY_CATEGORY'
    AND TAG_VALUE= 'IDENTIFIER';

REVOKE SELECT ON TABLE my_db.my_schema.hr_data FROM ROLE analyst;
Copy

スキーマ内にあるすべてのテーブルを分類する

この例は、2つのユーザー定義のストアドプロシージャを使用して、スキーマ内にあるすべてのテーブルを分類する方法を示しています。

  • classify_schema: スキーマ内のすべてのテーブルをリストし、分類結果を格納するテーブルを作成してから、分類タグを各テーブルから抽出して結果テーブルに格納します。

  • associate_tag_batch: classify_schema ストアドプロシージャの結果を使用して、分類システムタグをスキーマ内のすべてのテーブル列に自動的に割り当て、各テーブルに割り当てられたタグの数を返します。

重要

classify_schema という名前のストアドプロシージャは、結果を格納する仮テーブルを作成します。仮テーブルは、このストアドプロシージャを呼び出すユーザーのユーザーセッションの期間中、存在します。ユーザーセッションが期限切れになると、Snowflakeは仮テーブルをドロップするため、ユーザーはストアドプロシージャを再度呼び出して、仮テーブルを再作成する必要があります。

仮テーブルを保持する必要がある場合は、 sqlText コマンドから temp キーワードを削除してテーブルを作成します。

詳細については、 CREATE TABLE コマンドにある TEMP[ORARY] オプションをご参照ください。

  1. classify_schema という名前の最初のプロシージャを作成します。

    create or replace procedure classify_schema(schema_name string, result_table string)
    returns object language JavaScript
    as $$
    // 1
    const table_names = snowflake.execute({
      sqlText: `show terse tables in schema identifier(?)`,
      binds: [SCHEMA_NAME],
    });
    
    // helper function for quoted table names
    function quote(name) {
      return '"'+ name.replace(/"/g,'""') + '"';
    }
    
    // create table to store results in. if it already exists, we will add to it rather than overwrite
    snowflake.execute({
        sqlText: `create temp table if not exists identifier(?) (table_name string, result variant)`,
        binds: [RESULT_TABLE],
    })
    // loop through tables
    while (table_names.next()) {
      let name = table_names.getColumnValue('name');
      // add schema to table name
      name = SCHEMA_NAME + "." + quote(name);
      // insert qualified table name and result into result table
      const results = snowflake.execute({
        sqlText: `insert into identifier(?) select ?, extract_semantic_categories(?)`,
        binds: [RESULT_TABLE, name, name],
      });
    }
    // return the number of tables classified
    return {tables_classified: table_names.getRowCount()};
    $$;
    
    Copy
  2. associate_tag_batch という名前の2番目のプロシージャを作成します。

    create or replace procedure associate_tag_batch(result_table string)
    returns Object language JavaScript
    as $$
    // get table names and classification results to loop through
    const tags_to_apply = snowflake.execute({
      sqlText: `select table_name, result from identifier(?)`,
      binds: [RESULT_TABLE],
    });
    
    const out = {};
    while (tags_to_apply.next()) {
      // get table name
      const name = tags_to_apply.getColumnValue('TABLE_NAME');
      // get classification result
      const classification_results = tags_to_apply.getColumnValue('RESULT');
      // call associate semantic category tags with table name and classification result
      const results = snowflake.execute({
        sqlText: `call associate_semantic_category_tags(?, parse_json(?))`,
        binds: [name, JSON.stringify(classification_results)],
      });
      results.next();
      out[name] = results.getColumnValue(1).split('\n');
    }
    // return number of tags applied per table
    return out;
    $$;
    
    Copy
  3. 分類するスキーマの名前と、各テーブルの EXTRACT_SEMANTIC_CATEGORY の結果を引数として保持する仮テーブルの名前を使用して、 classify_schema ストアドプロシージャを呼び出します。

    call classify_schema('my_db.my_schema','my_temporary_classification_table');
    
    Copy
  4. 仮テーブルの結果を確認し、必要に応じて変更します。詳細については、 出力を解釈する をご参照ください。

  5. 結果が十分な場合は、 associate_tag_batch ストアドプロシージャを呼び出して、分類システムタグをテーブル列に割り当てます。

    call associate_tag_batch('my_temporary_classification_table');
    
    Copy

データベース内にあるすべてのテーブルを分類する

この例は、2つのストアドプロシージャを使用して、データベース内にあるすべてのテーブルを分類する方法を示しています。

  • classify_database: データベース内のスキーマごとにスキーマ内のすべてのテーブルを分類し、分類されたテーブルの数とスキーマの数を返します。

  • associate_tag_batch: スキーマ内にあるすべてのテーブルを分類する (このトピック内)で定義されているものと同じ操作を実行します。

  1. classify_database ストアドプロシージャを作成します。

    create or replace procedure classify_database(database_name string, result_table string)
    returns Object language JavaScript
    as $$
    // get list of schemas in database
    const schema_names = snowflake.execute({
      sqlText: `show terse schemas in database identifier(?)`,
      binds: [DATABASE_NAME],
    });
    
    // helper function for quoted schema names
    function quote(name) {
      return '"'+ name.replace(/"/g,'""') + '"';
    }
    
    // counter for tables. will use result from classify_schema to increment
    let table_count = 0
    while (schema_names.next()) {
      let name = schema_names.getColumnValue('name');
      // skip the information schema
      if (name == "INFORMATION_SCHEMA") {
        continue;
      }
      // add database name to schema
      name = DATABASE_NAME + "." + quote(name);
      // call classify_schema on each schema. This will loop over tables in schema
      const results = snowflake.execute({
        sqlText: `call classify_schema(?, ?)`,
        binds: [name, RESULT_TABLE],
      });
      results.next();
      // increment total number of tables by the number of tables in the schema
      table_count += results.getColumnValue(1).tables_classified ;
    }
    
    return {
        tables_classified: table_count,
        // subtract one from number of schemas because we skip the information schema
        schemas_classified: schema_names.getRowCount() - 1,
    };
    $$;
    
    Copy
  2. 分類するデータベースの名前と仮テーブルの名前を使用して classify_database ストアドプロシージャを呼び出し、データベースの各スキーマに結果を保存します。

    call classify_database('my_db','my_temporary_classification_table');
    
    Copy
  3. 各スキーマに移動して、仮テーブルを確認し、必要に応じて修正します。

  4. 結果が十分な場合は、 スキーマに対して associate_tag_batch ストアドプロシージャを1回呼び出し、そのスキーマのテーブルにタグを適用します。たとえば、データベースに3つのスキーマが含まれている場合は、ストアドプロシージャを3回呼び出します。

    call associate_tag_batch('my_temporary_classification_table');
    
    Copy