Na pozadí brány firewall ochrany osobních údajů dat
Poznámka:
Úrovně ochrany osobních údajů jsou v tocích dat Power Platform momentálně nedostupné, ale produktový tým pracuje na povolení této funkce.
Pokud jste Power Query používali nějakou dobu, pravděpodobně jste to zaznamenali. Když se náhle zobrazí chyba, že žádné množství online vyhledávání, úpravy dotazů nebo bashing pomocí klávesnice se může napravit. Chyba podobná:
Formula.Firewall: Query 'Query1' (step 'Source') references other queries or steps, so it may not directly access a data source. Please rebuild this data combination.
Nebo možná:
Formula.Firewall: Query 'Query1' (step 'Source') is accessing data sources that have privacy levels which cannot be used together. Please rebuild this data combination.
Tyto Formula.Firewall
chyby jsou výsledkem brány firewall ochrany osobních údajů dat Power Query (označované také jako brána firewall), která se někdy může zdát, že existuje výhradně pro frustrování datových analytiků po celém světě. Věřte tomu nebo ne, ale brána firewall slouží k důležitému účelu. V tomto článku se podíváme pod pokličku, abychom lépe pochopili, jak to funguje. S lepším porozuměním vám snad budete moct v budoucnu lépe diagnostikovat a opravovat chyby brány firewall.
Co je to?
Účel brány firewall ochrany osobních údajů dat je jednoduchý: Existuje, aby Power Query zabránil neúmyslnému úniku dat mezi zdroji.
Proč je to potřeba? Určitě byste mohli vytvořit nějaký M, který by předal hodnotu SQL datovému kanálu OData. To by ale bylo záměrné úniky dat. Autor mashupu by (nebo alespoň měl) vědět, že to dělá. Proč je potřeba zajistit ochranu před neúmyslným únikem dat?
Odpověď? Skládací.
Skládací?
Skládání je termín, který odkazuje na převod výrazů v jazyce M (například filtry, přejmenování, spojení atd.) na operace s nezpracovaným zdrojem dat (například SQL, OData atd.). Obrovská část výkonu Power Query pochází ze skutečnosti, že PQ dokáže převést operace, které uživatel provádí prostřednictvím svého uživatelského rozhraní, na složité jazyky SQL nebo jiného back-endového zdroje dat, aniž by uživatel musel znát uvedené jazyky. Uživatelé získají výhodu výkonu nativních operací zdroje dat s jednoduchým použitím uživatelského rozhraní, ve kterém lze všechny zdroje dat transformovat pomocí společné sady příkazů.
V rámci posouvání může PQ někdy určit, že nejúčinnější způsob, jak spustit danou mashup, je vzít data z jednoho zdroje a předat je do jiného. Pokud například připojujete malý soubor CSV k obrovské tabulce SQL, pravděpodobně nechcete, aby PQ přečetl soubor CSV, přečetl celou tabulku SQL a pak je spojte na místním počítači. Pravděpodobně chcete, aby PQ vložil data CSV do příkazu SQL a požádal databázi SQL, aby provedl spojení.
To je způsob, jakým může dojít k neúmyslnému úniku dat.
Představte si, že jste se připojili k datům SQL, která zahrnovala čísla sociálního pojištění zaměstnanců s výsledky externího datového kanálu OData, a najednou jste zjistili, že se čísla sociálního zabezpečení z SQL odesílala do služby OData. Špatná zpráva, že?
Toto je druh scénáře, kterému má brána firewall zabránit.
Jak to funguje?
Brána firewall existuje, aby se zabránilo neúmyslnému odesílání dat z jednoho zdroje do jiného zdroje. Je to dost jednoduché.
Jak to tedy dosahuje tohoto poslání?
Provede to tak, že vaše dotazy M rozdělí na něco, co se nazývá oddíly, a pak vynucuje následující pravidlo:
- Oddíl může buď přistupovat k kompatibilním zdrojům dat, nebo odkazovat na jiné oddíly, ale ne na oba oddíly.
Jednoduché... ale matoucí. Co je oddíl? Co dělá dva zdroje dat "kompatibilní"? A proč by se brána firewall měla starat, pokud oddíl chce získat přístup ke zdroji dat a odkazovat na oddíl?
Pojďme to rozdělit a podívat se na výše uvedené pravidlo najednou.
Co je oddíl?
Na nejzásadnější úrovni je oddíl pouze kolekce jednoho nebo více kroků dotazu. Nejpodrobnější možný oddíl (alespoň v aktuální implementaci) je jediný krok. Největší oddíly můžou někdy zahrnovat více dotazů. (Další informace o tomto postupu najdete později.)
Pokud kroky neznáte, můžete je zobrazit na pravé straně okna Editor Power Query po výběru dotazu v podokně Použitý postup. Kroky udržují přehled o všem, co jste udělali pro transformaci dat do konečného tvaru.
Oddíly, které odkazují na jiné oddíly
Když se dotaz vyhodnotí pomocí brány firewall, brána firewall rozdělí dotaz a všechny jeho závislosti na oddíly (to znamená skupiny kroků). Kdykoli jeden oddíl odkazuje na něco v jiném oddílu, firewall nahradí odkaz voláním speciální funkce volanou Value.Firewall
. Jinými slovy brána firewall neumožňuje přímý přístup k oddílům. Všechny odkazy se upraví tak, aby procházely bránou firewall. Bránu firewall si můžete představit jako vrátného. Oddíl, který odkazuje na jiný oddíl, musí k tomu získat oprávnění brány firewall a brána firewall určuje, jestli budou odkazovaná data povolená do oddílu.
Všechno se může zdát docela abstraktní, takže se podívejme na příklad.
Předpokládejme, že máte dotaz s názvem Zaměstnanci, který načítá některá data z databáze SQL. Předpokládejme, že máte také jiný dotaz (EmployeesReference), který jednoduše odkazuje na zaměstnance.
shared Employees = let
Source = Sql.Database(…),
EmployeesTable = …
in
EmployeesTable;
shared EmployeesReference = let
Source = Employees
in
Source;
Tyto dotazy se nakonec rozdělí do dvou oddílů: jeden pro dotaz Zaměstnanci a druhý pro dotaz EmployeesReference (který bude odkazovat na oddíl Zaměstnanci). Při vyhodnocování se zapnutou bránou firewall se tyto dotazy přepíší takto:
shared Employees = let
Source = Sql.Database(…),
EmployeesTable = …
in
EmployeesTable;
shared EmployeesReference = let
Source = Value.Firewall("Section1/Employees")
in
Source;
Všimněte si, že jednoduchý odkaz na dotaz Zaměstnanci byl nahrazen voláním Value.Firewall
, který je zadán úplný název dotazu Zaměstnanci.
Když se vyhodnocuje EmployeesReference, brána firewall zachytí volání Value.Firewall("Section1/Employees")
, které teď má šanci určit, jestli (a jak) se požadovaná data přetékají do oddílu EmployeesReference. Může provádět libovolný počet věcí: zamítnout požadavek, ukládat požadovaná data do vyrovnávací paměti (což brání dalšímu posouvání do původního zdroje dat), atd.
Takto brána firewall udržuje kontrolu nad tokem dat mezi oddíly.
Oddíly, které přímo přistupují ke zdrojům dat
Řekněme, že definujete dotaz Query1 jedním krokem (všimněte si, že tento jednokrokový dotaz odpovídá jednomu oddílu brány firewall) a že tento jediný krok přistupuje ke dvěma zdrojům dat: k tabulce databáze SQL a souboru CSV. Jak se s tím brána firewall zabývá, protože neexistuje žádný odkaz na oddíly, a proto není potřeba ho zachytávat Value.Firewall
? Pojďme se podívat na dříve uvedené pravidlo:
- Oddíl může buď přistupovat k kompatibilním zdrojům dat, nebo odkazovat na jiné oddíly, ale ne na oba oddíly.
Aby bylo možné spustit dotaz na jeden oddíl, ale dva zdroje dat, musí být jeho dva zdroje dat kompatibilní. Jinými slovy, musí být v pořádku, aby se data mezi nimi sdílela obousměrně. To znamená, že úrovně ochrany osobních údajů obou zdrojů musí být veřejné nebo obě organizační, protože jde o jediné dvě kombinace, které umožňují sdílení v obou směrech. Pokud jsou oba zdroje označené jako soukromé nebo jeden je označený jako veřejný a jeden je označený jako organizační, nebo jsou označené pomocí některé jiné kombinace úrovní ochrany osobních údajů, pak obousměrné sdílení není povolené a proto není bezpečné, aby se oba vyhodnocovaly ve stejném oddílu. To by znamenalo, že by mohlo dojít k nebezpečnému úniku dat (kvůli posouvání) a brána firewall by neměla způsob, jak tomu zabránit.
Co se stane, když se pokusíte získat přístup k nekompatibilním zdrojům dat ve stejném oddílu?
Formula.Firewall: Query 'Query1' (step 'Source') is accessing data sources that have privacy levels which cannot be used together. Please rebuild this data combination.
Doufejme, že teď lépe rozumíte jedné z chybových zpráv uvedených na začátku tohoto článku.
Všimněte si, že tento požadavek na kompatibilitu platí pouze v rámci daného oddílu. Pokud oddíl odkazuje na jiné oddíly, zdroje dat z odkazovaných oddílů nemusí být vzájemně kompatibilní. Je to proto, že brána firewall může ukládat data do vyrovnávací paměti, což zabrání dalšímu posouvání proti původnímu zdroji dat. Data se načtou do paměti a budou považována za ta, která pocházejí odjinud.
Proč ne?
Řekněme, že definujete dotaz jedním krokem (který bude znovu odpovídat jednomu oddílu), který přistupuje ke dvěma dalším dotazům (tedy dvěma dalšími oddíly). Co kdybyste chtěli v jednom kroku získat přímý přístup k databázi SQL? Proč nemůže oddíl odkazovat na jiné oddíly a získat přímý přístup k kompatibilním zdrojům dat?
Jak jste viděli dříve, když jeden oddíl odkazuje na jiný oddíl, brána firewall funguje jako vrátný pro všechna data proudící do oddílu. Aby to bylo možné, musí mít možnost řídit, jaká data jsou povolená. Pokud existují zdroje dat, ke které se přistupuje v rámci oddílu a data proudí z jiných oddílů, ztratí schopnost být vrátným, protože tok dat může dojít k úniku do jednoho z interně přístupných zdrojů dat, aniž by o tom věděl. Brána firewall proto brání oddílu, který přistupuje k jiným oddílům, aby mohl přímo přistupovat k jakýmkoli zdrojům dat.
Co se stane, když se oddíl pokusí odkazovat na jiné oddíly a také přímo přistupovat ke zdrojům dat?
Formula.Firewall: Query 'Query1' (step 'Source') references other queries or steps, so it may not directly access a data source. Please rebuild this data combination.
Teď snad lépe pochopíte další chybovou zprávu uvedenou na začátku tohoto článku.
Podrobné oddíly
Jak můžete pravděpodobně odhadnout z výše uvedených informací, způsob dělení dotazů skončí neuvěřitelně důležité. Pokud máte nějaké kroky, které odkazují na jiné dotazy a další kroky, které přistupují ke zdrojům dat, teď snad zjistíte, že vykreslení hranic oddílů na určitých místech způsobí chyby brány firewall, zatímco jejich kreslení na jiných místech umožní, aby váš dotaz běžel úplně správně.
Jak se tedy přesně rozdělí dotazy?
Tato část je pravděpodobně nejdůležitější pro pochopení, proč se zobrazují chyby brány firewall a jak je vyřešit (kde je to možné).
Tady je souhrnný přehled logiky dělení.
- Počáteční dělení
- Vytvoří oddíl pro každý krok v každém dotazu.
- Statická fáze
- Tato fáze nezávisí na výsledcích vyhodnocení. Místo toho spoléhá na to, jak jsou dotazy strukturované.
- Oříznutí parametrů
- Oříznou oddíly založené na parametrech, to znamená jakýkoli oddíl, který:
- Neodkazuje na žádné jiné oddíly.
- Neobsahuje žádné vyvolání funkce.
- Není cyklické (to znamená, že se neodkazuje na sebe)
- Všimněte si, že "odebrání" oddílu efektivně zahrnuje do jakéhokoli jiného oddílu, na který odkazují.
- Oříznutí oddílů parametrů umožňuje, aby odkazy na parametry používané ve voláních funkce zdroje dat (například
Web.Contents(myUrl)
) fungovaly, a ne vyvolání chyb "Oddíl nemůže odkazovat na zdroje dat a další kroky".
- Oříznou oddíly založené na parametrech, to znamená jakýkoli oddíl, který:
- Seskupování (statické)
- Oddíly se sloučí v pořadí závislostí směrem dolů. Ve výsledných sloučených oddílech budou tyto oddíly oddělené:
- Oddíly v různých dotazech
- Oddíly, které neodkazují na jiné oddíly (a mají tak povolený přístup ke zdroji dat)
- Oddíly, které odkazují na jiné oddíly (a proto nemají přístup ke zdroji dat)
- Oddíly se sloučí v pořadí závislostí směrem dolů. Ve výsledných sloučených oddílech budou tyto oddíly oddělené:
- Oříznutí parametrů
- Tato fáze nezávisí na výsledcích vyhodnocení. Místo toho spoléhá na to, jak jsou dotazy strukturované.
- Dynamická fáze
- Tato fáze závisí na výsledcích vyhodnocení, včetně informací o zdrojích dat, ke které přistupují různé oddíly.
- Oříznutí
- Oříznou oddíly, které splňují všechny následující požadavky:
- Nemá přístup k žádným zdrojům dat.
- Neodkazuje na žádné oddíly, které přistupují ke zdrojům dat.
- Není cyklické
- Oříznou oddíly, které splňují všechny následující požadavky:
- Seskupování (dynamické)
- Teď, když byly oříznuty nepotřebné oddíly, zkuste vytvořit zdrojové oddíly, které jsou co největší. To se provádí sloučením oddílů pomocí stejných pravidel popsaných ve fázi statického seskupení výše.
Co to všechno znamená?
Pojďme si projít příklad, abychom si ukázali, jak funguje složitá logika uvedená výše.
Tady je ukázkový scénář. Je to poměrně jednoduché sloučení textového souboru (Kontakty) s databází SQL (Zaměstnanci), kde sql server je parametr (DbServer).
Tři dotazy
Tady je kód M pro tři dotazy použité v tomto příkladu.
shared DbServer = "MySqlServer" meta [IsParameterQuery=true, Type="Text", IsParameterQueryRequired=true];
shared Contacts = let
Source = Csv.Document(File.Contents("C:\contacts.txt"),[Delimiter=" ", Columns=15, Encoding=1252, QuoteStyle=QuoteStyle.None]),
#"Promoted Headers" = Table.PromoteHeaders(Source, [PromoteAllScalars=true]),
#"Changed Type" = Table.TransformColumnTypes(#"Promoted Headers",{{"ContactID", Int64.Type}, {"NameStyle", type logical}, {"Title", type text}, {"FirstName", type text}, {"MiddleName", type text}, {"LastName", type text}, {"Suffix", type text}, {"EmailAddress", type text}, {"EmailPromotion", Int64.Type}, {"Phone", type text}, {"PasswordHash", type text}, {"PasswordSalt", type text}, {"AdditionalContactInfo", type text}, {"rowguid", type text}, {"ModifiedDate", type datetime}})
in
#"Changed Type";
shared Employees = let
Source = Sql.Databases(DbServer),
AdventureWorks = Source{[Name="AdventureWorks"]}[Data],
HumanResources_Employee = AdventureWorks{[Schema="HumanResources",Item="Employee"]}[Data],
#"Removed Columns" = Table.RemoveColumns(HumanResources_Employee,{"HumanResources.Employee(EmployeeID)", "HumanResources.Employee(ManagerID)", "HumanResources.EmployeeAddress", "HumanResources.EmployeeDepartmentHistory", "HumanResources.EmployeePayHistory", "HumanResources.JobCandidate", "Person.Contact", "Purchasing.PurchaseOrderHeader", "Sales.SalesPerson"}),
#"Merged Queries" = Table.NestedJoin(#"Removed Columns",{"ContactID"},Contacts,{"ContactID"},"Contacts",JoinKind.LeftOuter),
#"Expanded Contacts" = Table.ExpandTableColumn(#"Merged Queries", "Contacts", {"EmailAddress"}, {"EmailAddress"})
in
#"Expanded Contacts";
Tady je zobrazení na vyšší úrovni zobrazující závislosti.
Pojďme na oddíl
Pojďme se trochu přiblížit a zahrnout kroky na obrázku a začít procházet logikou dělení. Tady je diagram tří dotazů zobrazující počáteční oddíly brány firewall zeleně. Všimněte si, že každý krok začíná ve vlastním oddílu.
Dále ořízíme oddíly parametrů. DbServer se tedy implicitně zahrne do zdrojového oddílu.
Teď provedeme statické seskupení. Tím se udržuje oddělení mezi oddíly v samostatných dotazech (všimněte si například, že poslední dva kroky zaměstnanců se seskupí podle kroků kontaktů) a mezi oddíly, které odkazují na jiné oddíly (například poslední dva kroky zaměstnanců) a mezi oddíly, které se neskupují (například první tři kroky zaměstnanců).
Teď vstoupíme do dynamické fáze. V této fázi se vyhodnotí výše uvedené statické oddíly. Oddíly, které nemají přístup k žádným zdrojům dat, se oříznou. Oddíly se pak seskupí a vytvoří zdrojové oddíly, které jsou co největší. V tomto ukázkovém scénáři ale všechny zbývající oddíly přistupují ke zdrojům dat a není možné provádět žádné další seskupení. Oddíly v naší ukázce se proto během této fáze nezmění.
Pojďme předstírat
Pro ilustraci si ale pojďme prohlédnout, co by se stalo, když by dotaz Kontakty, nikoli z textového souboru, byl pevně zakódovaný v jazyce M (možná prostřednictvím dialogového okna Zadat data ).
V tomto případě by dotaz Kontakty neměl přístup k žádným zdrojům dat. Proto by se ořízla během první části dynamické fáze.
Když oddíl Kontakty odeberete, poslední dva kroky zaměstnanců už neodkazují na žádné oddíly s výjimkou oddílu, který obsahuje první tři kroky zaměstnanců. Proto by se dva oddíly seskupily.
Výsledný oddíl by vypadal takto.
Příklad: Předávání dat z jednoho zdroje dat do jiného
Dobře, dost abstraktní vysvětlení. Pojďme se podívat na běžný scénář, ve kterém se pravděpodobně setkáte s chybou brány firewall a postupem, jak ji vyřešit.
Představte si, že chcete vyhledat název společnosti ze služby Northwind OData a pak pomocí názvu společnosti provést vyhledávání Bingem.
Nejprve vytvoříte dotaz společnosti , který načte název společnosti.
let
Source = OData.Feed("https://services.odata.org/V4/Northwind/Northwind.svc/", null, [Implementation="2.0"]),
Customers_table = Source{[Name="Customers",Signature="table"]}[Data],
CHOPS = Customers_table{[CustomerID="CHOPS"]}[CompanyName]
in
CHOPS
Dále vytvoříte vyhledávací dotaz, který odkazuje na společnost a předá ho Bingu.
let
Source = Text.FromBinary(Web.Contents("https://www.bing.com/search?q=" & Company))
in
Source
V tuto chvíli narazíte na potíže. Při vyhodnocování hledání dojde k chybě brány firewall.
Formula.Firewall: Query 'Search' (step 'Source') references other queries or steps, so it may not directly access a data source. Please rebuild this data combination.
Důvodem je to, že zdrojový krok hledání odkazuje na zdroj dat (bing.com) a odkazuje také na jiný dotaz nebo oddíl (společnost). Porušuje výše uvedené pravidlo (oddíl může přistupovat ke kompatibilním zdrojům dat nebo odkazovat na jiné oddíly, ale ne obojí).
Co dělat? Jednou z možností je úplně zakázat bránu firewall (prostřednictvím možnosti Ochrana osobních údajů s popiskem Ignorovat úrovně ochrany osobních údajů a potenciálně zvýšit výkon). Ale co když chcete bránu firewall nechat povolenou?
Pokud chcete tuto chybu vyřešit bez zakázání brány firewall, můžete zkombinovat společnost a hledat do jednoho dotazu, například takto:
let
Source = OData.Feed("https://services.odata.org/V4/Northwind/Northwind.svc/", null, [Implementation="2.0"]),
Customers_table = Source{[Name="Customers",Signature="table"]}[Data],
CHOPS = Customers_table{[CustomerID="CHOPS"]}[CompanyName],
Search = Text.FromBinary(Web.Contents("https://www.bing.com/search?q=" & CHOPS))
in
Search
Všechno se teď děje uvnitř jednoho oddílu. Za předpokladu, že úrovně ochrany osobních údajů pro oba zdroje dat jsou kompatibilní, brána firewall by teď měla být šťastná a už se nezobrazí chyba.
To je zalomení.
I když je na tomto tématu toho možné říci mnohem víc, tento úvodní článek už je dost dlouhý. Doufejme, že vám to pomůže lépe porozumět bráně firewall a pomůže vám pochopit a opravit chyby brány firewall, když na ně v budoucnu narazíte.