Динамическая маскировка снежинки маскирует базовую таблицу: производные таблицы не маскируются, а представления становятся пустыми?

У меня есть необработанная таблица, в которой есть вариантный столбец данных json. Есть несколько обычных представлений (не материализованных представлений), а таблицы создаются с использованием событий json из исходной таблицы.

После применения политики маскирования с использованием UDF к столбцу вариантов необработанной таблицы, когда роль bi_analyst, я обнаружил две проблемы:

  1. Таблицы, полученные из базовой таблицы, не маскируются bi_analyst роль;
  2. Представления, полученные с использованием базовой таблицы, становятся пустыми с bi_analyst роль;

Кто-нибудь знает, почему это произошло? дозировать эту функцию динамического маскирования, не поддерживающую представления в базовой таблице?

Что я хотел бы сделать, так это замаскировать базовые данные, и все таблицы и представления, исходящие из них, также замаскированы с указанной ролью. С этими таблицами легко работать, так как я могу просто применить к ним политику маскирования.

Однако я понятия не имею о взглядах. Как я могу по-прежнему получать доступ к представлениям с ролью, которая должна видеть данные, но не конфиденциальные столбцы?

UDF - это:

-- JavaScript UDF to mask pii data --
use role ACCOUNTADMIN;

CREATE OR REPLACE FUNCTION full_address_masking(V variant)
  RETURNS variant
  LANGUAGE JAVASCRIPT
  AS
  $$
    if ("detail" in V) {
        if ("latitude" in V.detail) {
            V.detail.latitude = "******";
        }
        if ("longitude" in V.detail) {
            V.detail.longitude = "******";
        }
        if ("customerAddress" in V.detail) {
            V.detail.customerAddress = "******";
        }
    }

    return V;
  $$;

Политика маскирования:

-- Create a masking policy using JavaScript UDF --
create or replace masking policy json_address_mask as (val variant) returns variant ->
    CASE
      WHEN current_role() IN ('ACCOUNTADMIN') THEN val
      WHEN current_role() IN ('BI_ANALYST') THEN full_address_masking(val)
    ELSE full_address_masking(val)
    END;

Команда sql для установки политики маскирования для необработанных данных:

-- Set masking policy --
use role ACCOUNTADMIN;
alter table DB.PUBLIC.RAW_DATA 
    modify column EVERYTHING 
    set masking policy json_address_mask;

Политика маскирования применяется к столбцу вариантов. EVERYTHING, какая структура данных выглядит:

  {
      "detail": {
        "customAddress": "******",
        "id": 1,
        "latitude": "******",
        "longitude": "******"
      },
      "source": "AAA"
    }

Производная таблица:

create or replace table DB.SCHEMA_A.TABLE_A
as 
select * from DB.PUBLIC.RAW_DATA 
where everything:source='AAA';

grant select on table DB.schema_A.table_A to role bi_analyst;

Вид:

create or replace  view DB.SCHEMA_A.VIEW_A  as ( 
select
everything:account::string as account,
everything:detail:latitude::float as detail_latitude,
everything:detail:longitude::float as detail_longitude,
from
DB.PUBLIC.RAW_DATA
where
everything:source::string = 'AAA'

grant select on view DB.SCHEMA_A.VIEW_A to role bi_analyst;

В результате RAW_DATA замаскирован, TABLE_A совсем не замаскирован, VIEW_A получает 0 строк, возвращаемых при запросе данных с BI_ANALYST роль.

2 ответа

№1 - Когда вы создаете таблицу из таблицы, в которой есть замаскированные данные, вы получите данные, к которым у роли, создающей новую таблицу, есть доступ в замаскированной таблице. Итак, в вашем примере TABLE_A имеет немаскированные данные, потому что они были созданы ролью, которая имеет к ним доступ. Политика маскирования не применяется к новой таблице автоматически.

№2 - Что касается №2, я считаю, что ваша единственная проблема заключается в том, что JSON в вашем примере сформирован неправильно, поэтому вы получаете значения NULL. Когда я исправил этот json следующим образом, он отлично работает с той же функцией и политикой маскирования, которые вы опубликовали:

{
"detail":{
"latitude": 132034034.00,
"longitude": 12393438583732,
"id": 1,
"customAddress" : "XXX Road, XXX city, UK"
},
"source": "AAA"
}

Замаскированный результат:

{
  "detail": {
    "customAddress": "XXX Road, XXX city, UK",
    "id": 1,
    "latitude": "******",
    "longitude": "******"
  },
  "source": "AAA"
}

Проблема с таблицами, которые не были замаскированы, хорошо объясняется @Mike в своем ответе. Решением может быть просто создание производных таблиц с использованием роли, которая ограничена политикой маскирования.

Проблема представлений связана с типом замаскированного значения "******", которое является строковым типом, в то время как фактический тип полей latitude а также longitudeплавают. При создании представления я все еще использовалlatitude а также longitude поля для плавающего типа:

create or replace  view DB.SCHEMA_A.VIEW_A  as ( 
select
everything:account::string as account,
everything:detail:latitude::float as detail_latitude,
everything:detail:longitude::float as detail_longitude,
from
DB.PUBLIC.RAW_DATA
where
everything:source::string = 'AAA'

Есть скрытая ошибка приведения "******" к плаванию, но снежинка по-прежнему создает вид. Но когда я запрашиваю данные сBI_ANALYST роль, он возвращает 0 строк.

Таким образом, обходной путь - преобразование этих полей в вариантный тип:

create or replace  view DB.SCHEMA_A.VIEW_A  as ( 
select
everything:account::string as account,
everything:detail:latitude::variant as detail_latitude,
everything:detail:longitude::variant as detail_longitude,
from
DB.PUBLIC.RAW_DATA
where
everything:source::string = 'AAA'

Что не идеально, потому что полностью изменилось определение представления, ни одна из ролей не может получить фактический тип данных с плавающей запятой / числом, даже включая accountadmin

Другие вопросы по тегам