Dynamische data-masking in dbt

Door Atzmon Ben Binyamin op Jan 10, 2023 1:30:00 PM

<span id="hs_cos_wrapper_name" class="hs_cos_wrapper hs_cos_wrapper_meta_field hs_cos_wrapper_type_text" style="" data-hs-cos-general-type="meta_field" data-hs-cos-type="text" >Dynamische data-masking in dbt</span>

Dynamische gegevensafscherming is een Snowflake-beveiligingsfunctie op kolomniveau die afschermingsbeleidslijnen gebruikt om selectief gegevens af te schermen in tabel- en weergavekolommen tijdens het uitvoeren van een query. Momenteel ondersteunt Snowflake Dynamic Data Masking op tabellen en weergaven.

dbt is een ontwikkelraamwerk bovenop Snowflake waarmee ik modulaire SQL-datapijplijnen kan bouwen en code kan implementeren met behulp van dev/prod-omgevingen. Het maakt Git versiebeheer, documentatie en nog veel meer mogelijk. Bekijk de dbt documentatie voor meer informatie!

Onlangs heb ik geëxperimenteerd met een dbt package genaamd dbt_snow_mask om Dynamic Data Masking te implementeren in snowflake door alleen dbt te gebruiken.

Laten we het wiel niet opnieuw uitvinden...

Een van de voordelen van het gebruik van dbt is het robuuste pakket-ecosysteem. Een dbt package is extra Jinja en SQL code die kan worden toegevoegd aan een project, voor extra functionaliteit. Het is zo eenvoudig als het importeren van een pakket in python.

Eén zo'n pakket is dbt_snow_mask, dat macro's bevat die in ons hele project kunnen worden gebruikt. Het pakket zal ons helpen om Dynamic Data Masking toe te passen met behulp van dbt meta. Het pakket gebruikt dbt_utils als een afhankelijkheid, dus zorg ervoor dat je deze ook toevoegt.

Het toevoegen van het pakket aan ons project is vrij eenvoudig en we doen dit door de 'package info' in ons packages.yml bestand te plakken:

packages: - package: dbt-labs/dbt_utils versie: 1.0.0 - package: entechlog/dbt_snow_mask versie: 0.2.3

Voer dbt deps uit om de pakketten te installeren.

Dynamische gegevensafscherming: Maskingbeleid maken

Onder de macromap heb ik de map snow-mask-ddl gemaakt met een sql-bestand dat een macro bevat:

De naam van het maskeerbeleid dat door deze macro wordt gemaakt, is ..<masking_policy_name>. In mijn voorbeeld hebben we <masking_policy_name> als temp. De Jinja-beschrijving aan het begin is nodig voor de specificatie van het dynamische databaseschema.

Een 'meta' config toevoegen aan onze modellen

Laten we een meta config toevoegen aan het modellen gerelateerde .yml bestand om te definiëren op welke kolommen het maskeerbeleid dat we hebben gemaakt zal worden toegepast. We voegen deze toe aan jaffle_shop.yml, waar we onze jaffle_shop staging configuraties centraliseren. We voegen het ook toe aan onze core.yml, waar we onze marts/core configuraties centraliseren.

Ik heb de metaconfiguratie toegevoegd onder de rechterkolom voor het model waarop ik de maskering wil toepassen. Hier hebben we onder stg_customers de meta config toegevoegd aan de kolommen first_name en last_name.

Een voorbeeld van een jaffle_shop.yml bestand dat ik in een project heb:

version: 2 sources: - name: jaffle_shop description: sources for jaffle_shop database: raw schema: jaffle_shop #loader: <string> #loaded_at_field: <column_name> #meta: {<dictionary>} #tags: [<string>] tabellen: 
      - name: customers - name: orders loaded_at_field: _batched_at freshness: warn_after: {count: 12, period: hour}models: - name: stg_customers description: Staged customer data from jaffle_shop app columns: - name: customer_id description: Primary key for customers tests: - unique - not_null - name: first_name meta: masking_policy: temp - name: last_name meta: masking_policy: temp - name: stg_orders description: Staged order data from jaffle_shop app columns: - name: order_id description: Primary key for orders tests: - unique - not_null - name: status description: '' tests: - accepted_values: values: ['shipped', 'completed', 'return_pending', 'returned', 'placed'] - name: customer_id tests: - relationships: to: ref('stg_customers') field: customer_id

Een voorbeeld van core.yml bestand, waar we de meta config first_name en last_name kolommen in dim_customers toevoegen.

versie: 2modellen: - naam: dim_customers kolommen: - naam: customer_id beschrijving: Primary key for customers tests: - unique - not_null - name: first_name meta: masking_policy: temp - name: last_name meta: masking_policy: temp - name: first_order_date - name: most_recent_order_date - name: number_of_orders - name: lifetime_value - name: fct_orders description: Staged order data from jaffle_shop app columns: - name: order_id description: Primary key for orders tests: - unique - not_null - name: customer_id #description: - name: order_date - name: amount

Dynamische data-afscherming toepassen

Om onze gemaakte macro toe te passen, willen we pre_hook en post_hook instellen in onze dbt_project.yml configuratie en ons maskeerbeleid maken en toepassen wanneer dbt wordt uitgevoerd. Laten we eens kijken naar de models sectie in onze dbt_project.yml:

models: jaffle_shop: # alle modellen moeten 'unique' en 'not_null' tests hebben +required_tests: {"unique.*|not_null": 2} staging: +materialized: view marts: core: +materialized: table pre-hook: 
      -Post-hook: 
      -

Als alternatief kunnen we een config toevoegen aan elk specifiek model:

Of met behulp van de opdrachtregel:

dbt run-operation create_masking_policy --args '{"resource_type": "models"}'

Instellingen zijn nu compleet!

Laten we alles bouwen met dbt build, en onze maskering op sneeuwvlok controleren.

Sneeuwvlok

Na het aanmaken van een nieuwe rol rep1 met de juiste rechten en machtigingen, zijn we klaar om onze data-afscherming te controleren. Ter herinnering: we verwachten dat de gegevens voor iedereen worden gemaskeerd, behalve voor de rol SYSADMIN:

CASE WHEN CURRENT_ROLE() IN ('SYSADMIN') THEN val ELSE '***********'END

Laten we overschakelen naar SYSADMIN en de gevoelige tabellen controleren:

use role SYSADMIN;select * from stg_customers;select * from dim_customers;

Beide tabellen zijn niet gemaskeerd, zoals verwacht.

Dezelfde tabellen controleren, deze keer met de rol rep1:

use role rep1;select * from stg_customers;select * from dim_customers;

We zijn klaar! Alle tabellen gedragen zich zoals verwacht.