หมายเหตุ
การเข้าถึงหน้านี้ต้องได้รับการอนุญาต คุณสามารถลอง ลงชื่อเข้าใช้หรือเปลี่ยนไดเรกทอรีได้
การเข้าถึงหน้านี้ต้องได้รับการอนุญาต คุณสามารถลองเปลี่ยนไดเรกทอรีได้
บทความนี้อธิบายวิธีที่นักพัฒนากลไกจัดการของบริษัทอื่นสามารถรวมเข้ากับการรักษาความปลอดภัย OneLake เพื่อสอบถามข้อมูลจาก OneLake ในขณะที่บังคับใช้การรักษาความปลอดภัยระดับแถว (RLS) และการรักษาความปลอดภัยระดับคอลัมน์ (CLS) การผสานรวมใช้ โมเดลกลไกจัดการที่ได้รับอนุญาต ซึ่งกลไกจัดการของคุณจะอ่านข้อมูลโดยตรงจาก OneLake และบังคับใช้นโยบายความปลอดภัยในเลเยอร์การประมวลผลของตัวเอง
Note
คุณลักษณะนี้เป็นส่วนหนึ่งของรุ่นตัวอย่างและจัดทําขึ้นเพื่อวัตถุประสงค์ในการประเมินและการพัฒนาเท่านั้น ซึ่งอาจเปลี่ยนแปลงตามคําติชมและไม่แนะนําสําหรับการใช้งานด้านการผลิต
ภาพรวม
การรักษาความปลอดภัยของ OneLake กําหนดนโยบายการควบคุมการเข้าถึงแบบละเอียด รวมถึงการรักษาความปลอดภัยระดับตาราง ระดับแถว และระดับคอลัมน์ เพียงครั้งเดียวใน OneLake กลไกจัดการ Microsoft Fabric เช่น Spark และจุดสิ้นสุดการวิเคราะห์ SQL บังคับใช้นโยบายเหล่านี้ในเวลาคิวรี อย่างไรก็ตาม การรักษาความปลอดภัยของ OneLake รับประกันการบังคับใช้นโยบายการควบคุมการเข้าถึงแบบละเอียดโดยไม่คํานึงถึงวิธีการเข้าถึงข้อมูล ด้วยเหตุนี้ คําขอภายนอกที่ไม่ได้รับอนุญาตในการอ่านไฟล์จาก OneLake จึงถูกบล็อกเพื่อให้แน่ใจว่าข้อมูลจะไม่รั่วไหล
รุ่นเครื่องยนต์ที่ได้รับอนุญาตช่วยแก้ปัญหานี้ได้ คุณลงทะเบียนข้อมูลประจําตัวเฉพาะ (บริการหลักหรือข้อมูลประจําตัวที่มีการจัดการ) ที่มีการเข้าถึงการอ่านข้อมูลอย่างเต็มรูปแบบ และยังสามารถอ่านข้อมูลเมตาความปลอดภัยได้อีกด้วย กลไกจัดการของคุณใช้ข้อมูลประจําตัวนี้เพื่อ:
- อ่านไฟล์ข้อมูลดิบจาก OneLake
- ดึงข้อมูลนโยบายความปลอดภัยที่มีประสิทธิภาพสําหรับผู้ใช้ที่ระบุโดยการเรียกใช้ รับสิทธิ์การเข้าถึงสําหรับ API หลัก
- ใช้ตัวกรองแถวและคอลัมน์ที่ส่งคืนในเลเยอร์การดําเนินการคิวรีของตัวเอง
- ส่งคืนเฉพาะข้อมูลที่อนุญาตให้กับผู้ใช้ปลายทาง
วิธีการนี้ช่วยให้กลไกจัดการของคุณควบคุมการวางแผนการสืบค้นและการแคชได้อย่างเต็มที่ พร้อมทั้งรักษาการบังคับใช้ความปลอดภัยให้สอดคล้องกับสิ่งที่กลไกจัดการ Fabric มีให้ และทําให้การควบคุม การอนุญาต อยู่ในมือของผู้ใช้
ข้อกำหนดเบื้องต้น
ก่อนที่คุณจะเริ่มผสานการทํางาน โปรดตรวจสอบให้แน่ใจว่าคุณมีสิ่งต่อไปนี้:
- บริการหลักของ Microsoft Entra หรือข้อมูลประจําตัวที่มีการจัดการที่กลไกจัดการของคุณใช้เพื่อเข้าถึง OneLake รองรับเฉพาะข้อมูลประจําตัวของ Microsoft Entra เท่านั้น
- บทบาท สมาชิกพื้นที่ทํางาน (หรือสูงกว่า) สําหรับข้อมูลประจําตัวของกลไกจัดการในพื้นที่ทํางานเป้าหมาย สิ่งนี้จะให้สิทธิ์ที่จําเป็นแก่ข้อมูลประจําตัวในการอ่านไฟล์ข้อมูลและข้อมูลเมตาด้านความปลอดภัยจาก OneLake
- รายการ Fabric (เลคเฮาส์ ฐานข้อมูลมิเรอร์ หรือแค็ตตาล็อกมิเรอร์) ที่เปิดใช้งานการรักษาความปลอดภัย OneLake
- Security role ของ OneLake ที่ กําหนดค่า ในรายการด้วยนโยบาย RLS หรือ CLS ที่คุณต้องการบังคับใช้
- ข้อมูลประจําตัวของกลไกจัดการต้องมีสิทธิ์ เข้าถึงการอ่านแบบไม่จํากัด ไปยังตารางที่อ่าน หากนโยบาย RLS หรือ CLS ใช้กับข้อมูลประจําตัวของกลไกจัดการ API จะส่งคืนข้อผิดพลาด
สถาปัตยกรรม
ไดอะแกรมต่อไปนี้แสดงโฟลว์การอนุญาตระดับสูงสําหรับการรวมกลไกจัดการที่ได้รับอนุญาต
┌──────────────┐ ┌──────────────────┐ ┌───────────┐
│ End user │──1──▶│ 3rd-party engine │──2──▶│ OneLake │
│ (query) │ │(service principal)│◀──3──│ (data + │
│ │◀──6──│ │──4──▶│ security)│
└──────────────┘ └──────────────────┘ └───────────┘
- ผู้ใช้ปลายทางส่งแบบสอบถามไปยังกลไกจัดการของบุคคลที่สาม
- ข้อมูลประจําตัวของกลไกจัดการรับรองความถูกต้องกับ OneLake และอ่านไฟล์ข้อมูลดิบ (Delta parquet) โดยใช้ OneLake API
- OneLake ส่งคืนข้อมูลที่ร้องขอ
- กลไกจัดการจะ
principalAccessเรียก API โดยส่งผ่านรหัสออบเจ็กต์ Microsoft Entra ของผู้ใช้ปลายทาง เพื่อรับการเข้าถึงที่มีประสิทธิภาพของผู้ใช้ - กลไกจัดการจะใช้ตัวกรองการเข้าถึงที่ส่งคืน (การเข้าถึงตาราง, เพรดิเคต RLS, รายการคอลัมน์ CLS) กับข้อมูลในเลเยอร์การประมวลผลของตัวเอง
- กลไกจัดการส่งคืนเฉพาะผลลัพธ์ที่กรองและอนุญาตให้กับผู้ใช้ปลายทาง
ขั้นตอนที่ 1: ตั้งค่าข้อมูลประจําตัวของกลไกจัดการ
กลไกจัดการของคุณต้องการข้อมูลประจําตัวของ Microsoft Entra ที่ OneLake รู้จักและเชื่อถือ ข้อมูลประจําตัวนี้จะอ่านไฟล์ข้อมูลและข้อมูลเมตาด้านความปลอดภัยในนามของกลไกจัดการของคุณ
สร้างหรือระบุบริการหลักหรือข้อมูลประจําตัวที่มีการจัดการ ใน Microsoft Entra ID สําหรับกลไกจัดการของคุณ สําหรับข้อมูลเพิ่มเติม ดู แอปพลิเคชันและบริการหลักในรหัส Microsoft Entra
เพิ่มข้อมูลประจําตัวให้กับบทบาท สมาชิก พื้นที่ทํางาน ในพอร์ทัล Fabric ไปที่การตั้งค่าพื้นที่ทํางาน และเพิ่มบริการหลักไปยังบทบาท สมาชิก สิ่งนี้จะให้ข้อมูลประจําตัว:
- อ่านการเข้าถึงไฟล์ข้อมูลทั้งหมดใน OneLake สําหรับรายการในพื้นที่ทํางานนั้น
- เข้าถึงการอ่านเมตาดาต้าของบทบาทความปลอดภัย OneLake ผ่าน API กลไกจัดการที่ได้รับอนุญาต
สําหรับข้อมูลเพิ่มเติมเกี่ยวกับบทบาทพื้นที่ทํางาน โปรดดู บทบาทในพื้นที่ทํางาน
ตรวจสอบให้แน่ใจว่าข้อมูลประจําตัวมีการเข้าถึงที่ไม่จํากัด ข้อมูลประจําตัวของกลไกจัดการต้องมีสิทธิ์อ่านแบบเต็มรูปแบบในแต่ละตารางที่สืบค้น หาก Security role ของ OneLake ใช้ข้อจํากัด RLS หรือ CLS กับข้อมูลประจําตัวของกลไกจัดการ การอ่านข้อมูลและการเรียก API จะล้มเหลว แนวทางปฏิบัติที่ดีที่สุดคือไม่เพิ่มข้อมูลประจําตัวของกลไกจัดการไปยัง Security role ของ OneLake ใดๆ ที่มีข้อจํากัด RLS หรือ CLS
สำคัญ
คุณสามารถเพิกถอนการเข้าถึงของกลไกจัดการได้ตลอดเวลาโดยลบออกจากบทบาทพื้นที่ทํางาน การเพิกถอนการเข้าถึงจะมีผลภายในเวลาประมาณ 2 นาที
ขั้นตอนที่ 2: อ่านข้อมูลจาก OneLake
เมื่อกําหนดค่าข้อมูลประจําตัวของกลไกจัดการแล้ว กลไกจัดการของคุณสามารถอ่านไฟล์ข้อมูลได้โดยตรงจาก OneLake โดยใช้ API ที่เข้ากันได้กับ Azure Data Lake Storage (ADLS) Gen2 มาตรฐาน
ข้อมูล OneLake สามารถเข้าถึงได้ที่:
https://onelake.dfs.fabric.microsoft.com/{workspaceId}/{itemId}/Tables/{schema}/{tableName}/
กลไกจัดการของคุณรับรองความถูกต้องโดยใช้โทเค็นผู้ถือที่ได้รับผ่านโฟลว์ข้อมูลประจําตัวไคลเอ็นต์ Microsoft Entra OAuth 2.0 ใช้ขอบเขต https://storage.azure.com/.default ทรัพยากร OneLake เมื่อร้องขอโทเค็น
ตัวอย่าง: รับรองความถูกต้องและอ่านข้อมูล (Python)
from azure.identity import ClientSecretCredential
from azure.storage.filedatalake import DataLakeServiceClient
tenant_id = "<your-tenant-id>"
client_id = "<your-service-principal-client-id>"
client_secret = "<your-service-principal-secret>"
credential = ClientSecretCredential(tenant_id, client_id, client_secret)
service_client = DataLakeServiceClient(
account_url="https://onelake.dfs.fabric.microsoft.com",
credential=credential
)
# Access a specific item in a workspace
file_system_client = service_client.get_file_system_client("<workspace-id>")
directory_client = file_system_client.get_directory_client("<item-id>/Tables/dbo/Customers")
# List and read Delta parquet files
for path in directory_client.get_paths():
if path.name.endswith(".parquet"):
file_client = file_system_client.get_file_client(path.name)
downloaded = file_client.download_file()
data = downloaded.readall()
# Process the parquet data with your engine
สําหรับข้อมูลเพิ่มเติมเกี่ยวกับ OneLake API โปรดดู การเข้าถึง OneLake ด้วย API
ขั้นตอนที่ 3: ดึงข้อมูลการเข้าถึงที่มีประสิทธิภาพของผู้ใช้
หลังจากอ่านข้อมูลดิบแล้ว กลไกจัดการของคุณต้องกําหนดสิ่งที่ผู้ใช้ที่สืบค้นได้รับอนุญาตให้เห็น เรียกใช้ รับ สิทธิ์เข้าถึง API หลัก เพื่อรับสิทธิ์เข้าถึงรายการอย่างมีประสิทธิภาพของผู้ใช้
จุดสิ้นสุด API
GET https://onelake.dfs.fabric.microsoft.com/v1.0/workspaces/{workspaceId}/artifacts/{artifactId}/securityPolicy/principalAccess
เนื้อความของคําขอ
{
"aadObjectId": "<end-user-entra-object-id>",
"inputPath": "Tables",
"maxResults": 500 //optional, default is 500
}
| พารามิเตอร์ | ประเภท | จำเป็นต้องระบุ | คำอธิบาย |
|---|---|---|---|
| aadObjectId | สตริง | ใช่ | รหัสออบเจ็กต์ Microsoft Entra ของผู้ใช้ปลายทางที่คุณต้องการตรวจสอบการเข้าถึง |
| inputPath | สตริง | ใช่ | ไม่ว่าจะ Tables หรือ Files ส่งคืนสิทธิ์การเข้าถึงของผู้ใช้สําหรับส่วนที่ระบุของรายการ สําหรับกลไกการสืบค้นส่วนใหญ่ inputPath จะเป็นTables |
| ความต่อเนื่องโทเค็น | สตริง | ไม่ใช่ | ใช้เพื่อดึงผลลัพธ์ต่อเนื่องเมื่อชุดผลลัพธ์เกินmaxResults |
| maxResults | จำนวนเต็ม | ไม่ใช่ | รายการสูงสุดต่อหน้า ค่าเริ่มต้นคือ 500 |
การตอบสนองตัวอย่าง (RLS เท่านั้น)
{
"identityETag": "3fc4dc476ded773e4cf43936190bf20fa9480a077b25edc0b4bbe247112542f6",
"metadataETag": "\"eyJhciI6IlwiMHg4R...\"",
"value": [
{
"path": "Tables/dbo/Customers",
"access": ["Read"],
"rows": "SELECT * FROM [dbo].[Customers] WHERE [customerId] = '123'",
"effect": "Permit"
},
{
"path": "Tables/dbo/Employees",
"access": ["Read"],
"rows": "SELECT * FROM [dbo].[Employees] WHERE [address] = '123'",
"effect": "Permit"
},
{
"path": "Tables/dbo/EmployeeTerritories",
"access": ["Read"],
"effect": "Permit"
}
]
}
การตอบสนองตัวอย่าง (RLS และ CLS)
เมื่อมีการกําหนดค่าความปลอดภัยระดับคอลัมน์บนตาราง การตอบสนองจะรวมอาร์ columns เรย์ที่แสดงเฉพาะคอลัมน์ที่ผู้ใช้ได้รับอนุญาตให้เข้าถึง คอลัมน์ที่ไม่มีอยู่ในอาร์เรย์นี้จะถูกซ่อนจากผู้ใช้
{
"identityETag": "79372bc169b00882d9abec3d404032131e96bc406e15c6766514723021e153eb",
"metadataETag": "\"eyJhciI6IlwiMHg4R...\"",
"value": [
{
"path": "Tables/dbo/Customers",
"access": ["Read"],
"columns": [
{
"name": "address",
"columnEffect": "Permit",
"columnAction": ["Read"]
},
{
"name": "city",
"columnEffect": "Permit",
"columnAction": ["Read"]
},
{
"name": "contactTitle",
"columnEffect": "Permit",
"columnAction": ["Read"]
},
{
"name": "country",
"columnEffect": "Permit",
"columnAction": ["Read"]
},
{
"name": "fax",
"columnEffect": "Permit",
"columnAction": ["Read"]
},
{
"name": "phone",
"columnEffect": "Permit",
"columnAction": ["Read"]
},
{
"name": "postalCode",
"columnEffect": "Permit",
"columnAction": ["Read"]
},
{
"name": "region",
"columnEffect": "Permit",
"columnAction": ["Read"]
}
],
"rows": "SELECT * FROM [dbo].[Customers] WHERE [customerID] = 'ALFKI'",
"effect": "Permit"
},
{
"path": "Tables/dbo/Employees",
"access": ["Read"],
"rows": "SELECT * FROM [dbo].[Employees] WHERE [address] = '123'",
"effect": "Permit"
}
]
}
ทําความเข้าใจการตอบสนอง
การตอบสนองประกอบด้วยอาร์เรย์ของ PrincipalAccessEntry ออบเจ็กต์ โดยแต่ละรายการแสดงถึงตารางที่ผู้ใช้สามารถเข้าถึงได้ ตารางที่ไม่มีอยู่ในการตอบกลับจะไม่สามารถเข้าถึงได้โดยผู้ใช้
| ฟิลด์ | ประเภท | คำอธิบาย |
|---|---|---|
path |
สตริง | เส้นทางไปยังตารางที่ผู้ใช้สามารถเข้าถึงได้ เช่น Tables/dbo/Customers. |
access |
string[] | อาร์เรย์ของชนิดการเข้าถึงที่ได้รับ ขณะนี้รองรับเท่านั้นRead |
columns |
วัตถุ[] | อาร์เรย์ของออบเจ็กต์คอลัมน์ที่ผู้ใช้ได้รับอนุญาตให้เข้าถึง แต่ละออบเจ็กต์ประกอบด้วย name (ชื่อคอลัมน์), columnEffect (Permit) และ columnAction (["Read"]) หากไม่มีฟิลด์นี้ จะไม่ใช้ CLS และอนุญาตให้ใช้คอลัมน์ทั้งหมด หากมี ควรส่งคืน เฉพาะ คอลัมน์ที่ระบุไว้เท่านั้น |
rows |
สตริง | คําสั่ง T-SQL SELECT ที่แสดงถึงตัวกรองความปลอดภัยระดับแถว เฉพาะแถวที่ตรงกับเพรดิเคตนี้เท่านั้นที่ควรส่งคืนให้กับผู้ใช้ หากไม่มีฟิลด์นี้ จะไม่ใช้ RLS และอนุญาตให้ใช้แถวทั้งหมด |
effect |
สตริง | ประเภทเอฟเฟกต์ ปัจจุบัน เสมอPermit |
สำคัญ
ฟิลด์ประกอบด้วย rows นิพจน์ T-SQL ที่กลไกจัดการของคุณต้องแยกวิเคราะห์และนําไปใช้เป็นเพรดิเคตตัวกรอง นิพจน์ใช้ SELECT * FROM [schema].[table] WHERE ... รูปแบบ กลไกจัดการของคุณต้องแยก WHERE ส่วนคําสั่งและนําไปใช้กับข้อมูลที่ส่งคืน
ETags สําหรับการแคช
การตอบสนองประกอบด้วยค่า ETag สองค่าที่เปิดใช้งานการแคชที่มีประสิทธิภาพ:
-
identityETag: แสดงสถานะปัจจุบันของข้อมูลประจําตัวและการเป็นสมาชิกกลุ่มของผู้ใช้ แคชผลการเข้าถึงของผู้ใช้และนํากลับมาใช้ใหม่จนกว่า ETag นี้จะเปลี่ยนไป -
metadataETag: แสดงสถานะปัจจุบันของการกําหนดค่าความปลอดภัยของรายการ แคชข้อมูลเมตาของบทบาทและนํามาใช้ใหม่จนกว่า ETag นี้จะเปลี่ยนไป
ใช้ ETag เหล่านี้กับส่วนหัวของ If-None-Match คําขอเพื่อหลีกเลี่ยงการดึงข้อมูลที่ไม่เปลี่ยนแปลงอีกครั้ง สิ่งนี้ช่วยปรับปรุงประสิทธิภาพสําหรับแคชที่มีผู้ใช้หลายคน
ตัวอย่าง: ดึงข้อมูลการเข้าถึงที่มีประสิทธิภาพ (Python)
import requests
# Get a token for the OneLake DFS endpoint
token = credential.get_token("https://storage.azure.com/.default").token
workspace_id = "<workspace-id>"
artifact_id = "<artifact-id>"
user_object_id = "<end-user-entra-object-id>"
url = (
f"https://onelake.dfs.fabric.microsoft.com/v1.0/"
f"workspaces/{workspace_id}/artifacts/{artifact_id}/"
f"securityPolicy/principalAccess"
)
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json"
}
body = {
"aadObjectId": user_object_id,
"inputPath": "Tables"
}
response = requests.get(url, headers=headers, json=body)
access_data = response.json()
# The response contains the user's effective access
for entry in access_data["value"]:
print(f"Table: {entry['path']}, Access: {entry['access']}")
if "columns" in entry:
col_names = [col["name"] for col in entry["columns"]]
print(f" CLS permitted columns: {col_names}")
if "rows" in entry:
print(f" RLS filter: {entry['rows']}")
ขั้นตอนที่ 4: ใช้ตัวกรองความปลอดภัย
หลังจากดึงข้อมูลการเข้าถึงที่มีประสิทธิภาพของผู้ใช้แล้ว กลไกจัดการของคุณต้องใช้นโยบายความปลอดภัยกับข้อมูลก่อนที่จะส่งคืนผลลัพธ์ ขั้นตอนนี้มีความสําคัญ กลไกจัดการของคุณมีหน้าที่บังคับใช้นโยบายอย่างถูกต้อง
การกรองระดับตาราง
ส่งคืนข้อมูลจากตารางที่ปรากฏในการ principalAccess ตอบกลับเท่านั้น ถ้าตารางไม่อยู่ในรายการ แสดงว่าผู้ใช้จะไม่มีสิทธิ์เข้าถึงตารางนั้น และไม่ควรส่งคืนข้อมูล
# Build a set of accessible tables for the user
accessible_tables = {entry["path"] for entry in access_data["value"]}
# Before returning query results, verify the table is accessible
def is_table_accessible(table_path: str) -> bool:
return table_path in accessible_tables
การกรองความปลอดภัยระดับแถว
เมื่อ rows มีเขตข้อมูลอยู่ในรายการ Access กลไกจัดการของคุณต้องแยกวิเคราะห์เพรดิเคต T-SQL และนําไปใช้เป็นตัวกรองกับข้อมูลของตาราง
rowsค่าคือSELECTคําสั่งที่มีWHEREส่วนคําสั่งที่กําหนดแถวที่ผู้ใช้สามารถดูได้
สำคัญ
ถ้ากลไกจัดการของคุณไม่สามารถแยกวิเคราะห์คําสั่ง SQL การสืบค้นกับตารางที่มีคุณสมบัติที่ไม่ใช่ null rows ควรล้มเหลวโดยมีข้อผิดพลาดและไม่ส่งคืนข้อมูล สิ่งนี้ทําให้มั่นใจได้ว่าผู้ใช้จะได้รับสิทธิ์เข้าถึงเฉพาะสิ่งที่พวกเขาได้รับอนุญาตให้ดูเท่านั้น
ตัวอย่างเช่น ตัวกรอง RLS ต่อไปนี้:
SELECT * FROM [dbo].[Customers] WHERE [customerId] = '123' UNION SELECT * FROM [dbo].[Customers] WHERE [customerID] = 'ALFKI'
กลไกจัดการของคุณควรแยกเพรดิเคตและนําไปใช้เพื่อกรองข้อมูล:
import sqlparse
def extract_rls_predicates(rls_expression: str) -> list:
"""
Parse the RLS T-SQL expression and extract WHERE clause predicates.
The expression may contain UNION of multiple SELECT statements.
"""
predicates = []
statements = rls_expression.split(" UNION ")
for stmt in statements:
parsed = sqlparse.parse(stmt)[0]
where_seen = False
where_clause = []
for token in parsed.tokens:
if where_seen:
where_clause.append(str(token).strip())
if token.ttype is sqlparse.tokens.Keyword and token.value.upper() == "WHERE":
where_seen = True
if where_clause:
predicates.append(" ".join(where_clause))
return predicates
def apply_rls_filter(dataframe, access_entry: dict):
"""Apply RLS filtering to a dataframe based on the access entry."""
if "rows" not in access_entry:
return dataframe # No RLS, return all rows
predicates = extract_rls_predicates(access_entry["rows"])
# Combine predicates with OR (UNION semantic)
combined_filter = " OR ".join(f"({p})" for p in predicates)
return dataframe.filter(combined_filter)
สำคัญ
เมื่อ rows ไม่มีฟิลด์จากรายการการเข้าถึง จะไม่มีการนํา RLS ไปใช้กับตารางนั้น และควรส่งคืนแถวทั้งหมด เมื่อมีฟิลด์ กลไกจัดการของคุณต้องกรองข้อมูล การส่งกลับข้อมูลที่ไม่ได้กรองสําหรับตารางที่มี RLS ถือเป็นการละเมิดความปลอดภัย
การกรองความปลอดภัยระดับคอลัมน์
เมื่อมีการกําหนดค่า CLS บนตาราง การตอบสนองจะ principalAccess รวมอาร์ columns เรย์ที่แสดงรายการคอลัมน์ที่ผู้ใช้ได้รับอนุญาตให้เข้าถึงอย่างชัดเจน วัตถุคอลัมน์แต่ละรายการประกอบด้วย:
| ทรัพย์สิน | ประเภท | คำอธิบาย |
|---|---|---|
name |
สตริง | ชื่อคอลัมน์ (คํานึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่) |
columnEffect |
สตริง | เอฟเฟกต์ที่ใช้กับคอลัมน์ ปัจจุบัน เสมอPermit |
columnAction |
string[] | การดําเนินการที่อนุญาตในคอลัมน์ ขณะนี้รองรับเท่านั้นRead |
ถ้า columns ฟิลด์ ไม่มี อยู่ในรายการการเข้าถึง จะไม่มี CLS นําไปใช้ และคอลัมน์ทั้งหมดในตารางจะได้รับอนุญาต หากมีฟิลด์อยู่ เอ็นจิ้นของคุณต้องส่งคืนเฉพาะคอลัมน์ที่ระบุไว้เท่านั้นcolumns
def get_permitted_columns(access_entry: dict) -> list | None:
"""
Return the list of permitted column names for a table.
Returns None if no CLS applies (all columns are permitted).
"""
if "columns" not in access_entry:
return None # No CLS, all columns are permitted
return [
col["name"]
for col in access_entry["columns"]
if col.get("columnEffect") == "Permit"
and "Read" in col.get("columnAction", [])
]
def apply_cls_filter(dataframe, access_entry: dict):
"""Apply CLS filtering to a dataframe based on the access entry."""
permitted_columns = get_permitted_columns(access_entry)
if permitted_columns is None:
return dataframe # No CLS, return all columns
# Only keep columns that are in the permitted list
return dataframe.select(permitted_columns)
สำคัญ
เมื่อ columns ฟิลด์ไม่มีอยู่ในรายการการเข้าถึง จะไม่ใช้ CLS และควรส่งคืนคอลัมน์ทั้งหมด เมื่อมีฟิลด์ กลไกจัดการของคุณต้องส่งคืนเฉพาะคอลัมน์ที่ระบุไว้เท่านั้น การส่งกลับคอลัมน์ที่ซ่อนอยู่ถือเป็นการละเมิดความปลอดภัย
การจัดการตารางที่ไม่มีการเข้าถึง
หากผู้ใช้สอบถามตารางที่ไม่ปรากฏในการ principalAccess ตอบกลับ กลไกจัดการของคุณต้องปฏิเสธการเข้าถึง อย่าถอยกลับไปส่งคืนข้อมูลที่ไม่ได้กรอง
def query_table(table_path: str, user_access: dict):
"""Query a table with OneLake security enforcement."""
# Find the user's access entry for this table
entry = next(
(e for e in user_access["value"] if e["path"] == table_path),
None
)
if entry is None:
raise PermissionError(
f"Access denied: user doesn't have permission to access {table_path}"
)
# Read the data from OneLake
data = read_table_from_onelake(table_path)
# Apply column-level security
data = apply_cls_filter(data, entry)
# Apply row-level security
data = apply_rls_filter(data, entry)
return data
ขั้นตอนที่ 5: จัดการการแคชและการตรวจจับการเปลี่ยนแปลง
สําหรับการผสานรวมระดับการผลิต โดยเฉพาะกลไกจัดการที่มีแคชข้อมูลสําหรับผู้ใช้หลายคน คุณจําเป็นต้องจัดการกับการเปลี่ยนแปลงนโยบายความปลอดภัยและการเป็นสมาชิกกลุ่มผู้ใช้
ข้อมูลเมตาความปลอดภัยของแคช
ใช้ค่า identityETag และ metadataETag จากการ principalAccess ตอบกลับเพื่อกําหนดว่าเมื่อใดที่ข้อมูลความปลอดภัยที่แคชไว้เป็นข้อมูลเก่า:
-
identityETag: การเปลี่ยนแปลงเมื่อมีการอัพเดตการเป็นสมาชิกกลุ่มหรือพร็อพเพอร์ตี้ข้อมูลประจําตัวของผู้ใช้ แคชการเข้าถึงที่มีประสิทธิภาพของผู้ใช้ที่คีย์บน(userId, identityETag) -
metadataETag: การเปลี่ยนแปลงเมื่อมีการอัปเดตบทบาทความปลอดภัยหรือนโยบาย OneLake ในรายการ คําจํากัดความบทบาทแคชที่คีย์บน(artifactId, metadataETag)
การสํารวจความคิดเห็นสําหรับการเปลี่ยนแปลง
สํารวจ principalAccess API เป็นระยะเพื่อตรวจหาการเปลี่ยนแปลง ควรสํารวจ API ก่อนดําเนินการสืบค้นเพื่อให้แน่ใจว่าไม่มีอะไรเปลี่ยนแปลง แทนที่จะแสดงผลลัพธ์จากแคชโดยตรง ใช้ If-None-Match ส่วนหัวที่มีแบนด์วิดท์ที่ได้รับ ETag ก่อนหน้านี้เพื่อลดแบนด์วิดท์:
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json",
"If-None-Match": f'"{cached_etag}"'
}
response = requests.get(url, headers=headers, json=body)
if response.status_code == 304:
# Security hasn't changed, use cached data
pass
elif response.status_code == 200:
# Security has changed, update cache
new_access_data = response.json()
update_cache(user_id, new_access_data)
ข้อควรพิจารณาของเวลาแฝง
- การเปลี่ยนแปลงข้อกําหนดบทบาทความปลอดภัยของ OneLake ใช้เวลาประมาณ 5 นาที ในการเผยแพร่
- การเปลี่ยนแปลงการเป็นสมาชิกกลุ่มผู้ใช้ใน Microsoft Entra ID จะใช้เวลาประมาณ 1 ชั่วโมง จึงจะมีผลใน OneLake
- เอ็นจิ้น Fabric บางตัวมีเลเยอร์แคชของตัวเอง ดังนั้นอาจต้องใช้เวลาเพิ่มเติม
ออกแบบช่วงเวลาการสํารวจและแคช TTL ของคุณให้เหมาะสม วิธีการที่แนะนําคือการสํารวจความคิดเห็นทุกๆ 5 นาทีสําหรับการเปลี่ยนแปลงข้อมูลเมตาด้านความปลอดภัย และรีเฟรชการเข้าถึงเฉพาะผู้ใช้ในแต่ละคิวรีหรือในช่วงเวลาที่สั้นลง
ขั้นตอนที่ 6: จัดการการแบ่งหน้า
principalAccess API รองรับการแบ่งหน้าสําหรับรายการที่มีหลายตาราง เมื่อการตอบกลับมีรายการ maxResultsมากกว่า การตอบกลับจะมี continuationToken.
all_entries = []
continuation_token = None
while True:
body = {
"aadObjectId": user_object_id,
"inputPath": "Tables",
"maxResults": 500
}
if continuation_token:
body["continuationToken"] = continuation_token
response = requests.get(url, headers=headers, json=body)
data = response.json()
all_entries.extend(data["value"])
# Check for continuation token in response
continuation_token = data.get("continuationToken")
if not continuation_token:
break
การจัดการข้อผิดพลาด
จัดการสถานการณ์ข้อผิดพลาดต่อไปนี้ในการผสานการทํางาน
| สถานะ HTTP | รหัสข้อผิดพลาด | คำอธิบาย | การดําเนินการที่แนะนํา |
|---|---|---|---|
| 200 | - | Success. | ประมวลผลการตอบกลับ |
| 404 | รายการไม่พบ | ไม่มีพื้นที่ทํางานหรือรายการ หรือข้อมูลประจําตัวของกลไกจัดการไม่มีการเข้าถึง | ตรวจสอบรหัสพื้นที่ทํางานและรหัสสิ่งประดิษฐ์ ยืนยันข้อมูลประจําตัวของกลไกจัดการมีสิทธิ์เข้าถึงสมาชิกพื้นที่ทํางาน |
| 412 | เงื่อนไขเบื้องต้นล้มเหลว | ETag in If-Match ที่ระบุไม่ตรงกับ ETag ทรัพยากรปัจจุบัน |
ดึงทรัพยากรอีกครั้งโดยไม่มี If-Match ส่วนหัวเพื่อรับ ETag ล่าสุด |
| 429 | - | เกินขีดจํากัดอัตรา | รอตามระยะเวลาที่ระบุในส่วน Retry-After หัวก่อนที่จะลองอีกครั้ง |
แนวทางปฏิบัติที่ดีที่สุดด้านความปลอดภัย
ปฏิบัติตามแนวทางปฏิบัติแนะนําเหล่านี้เพื่อให้แน่ใจว่าการผสานการทํางานจะปลอดภัย
- ปกป้องข้อมูลประจําตัวของกลไกจัดการ บริการหลักได้ยกระดับการเข้าถึงข้อมูลใน OneLake จัดเก็บข้อมูลประจําตัวอย่างปลอดภัยโดยใช้บริการต่างๆ เช่น Azure Key Vault
- อย่าเปิดเผยข้อมูลดิบต่อผู้ใช้ปลายทาง ใช้ตัวกรองความปลอดภัยที่ส่งคืนโดย
principalAccessAPI เสมอก่อนที่จะส่งคืนข้อมูลใดๆ การข้ามการบังคับใช้ถือเป็นการละเมิดความปลอดภัย - ตรวจสอบเพรดิเคต RLS อย่างระมัดระวัง แยกวิเคราะห์และใช้เพรดิเคตส่วนคําสั่ง T-SQL
WHEREอย่างถูกต้อง การแยกวิเคราะห์ที่ไม่ถูกต้องอาจนําไปสู่การรั่วไหลของข้อมูล หากเกิดข้อผิดพลาดในการแยกวิเคราะห์หรือการแม็ปไวยากรณ์ที่ไม่แน่ใจ ให้คิวรีล้มเหลวด้วยข้อผิดพลาดในการแยกวิเคราะห์ RLS แทนที่จะแสดงผลลัพธ์บางส่วนหรือไม่ปลอดภัยแก่ผู้ใช้ - จัดการตารางที่หายไปเนื่องจากการเข้าถึงถูกปฏิเสธ หากไม่มีตารางในการตอบกลับ API แสดงว่าผู้ใช้ไม่มีสิทธิ์เข้าถึง ไม่ถอยกลับไปใช้ข้อมูลที่ไม่ได้กรอง ความปลอดภัยของ OneLake จะใช้การปฏิเสธตามค่าเริ่มต้นเสมอ
- การตรวจสอบการเข้าถึง บันทึกว่าผู้ใช้รายใดเข้าถึงตารางใดและนโยบายความปลอดภัยใดที่ใช้สําหรับการปฏิบัติตามข้อกําหนดและการแก้ไขปัญหา
- สํารวจความคิดเห็นเกี่ยวกับการเปลี่ยนแปลงด้านความปลอดภัย ใช้ ETags เพื่อตรวจหาการเปลี่ยนแปลงและรีเฟรชนโยบายที่แคชไว้ทันที
ข้อจำกัด
- API อยู่
principalAccessในช่วงแสดงตัวอย่างและอาจเปลี่ยนแปลงได้ตามความคิดเห็น -
ReadเฉพาะชนิดและPermitเอฟเฟกต์การเข้าถึงเท่านั้นที่ได้รับการสนับสนุนในปัจจุบัน - ข้อมูลประจําตัวของเอ็นจิ้นต้องมีการเข้าถึงระดับรูทที่ไม่จํากัด หาก RLS หรือ CLS ใช้กับข้อมูลประจําตัวของกลไกจัดการ การเรียกใช้ API จะล้มเหลว
- เพรดิเคต RLS ใช้ไวยากรณ์ T-SQL เอ็นจิ้นของคุณมีหน้าที่ในการแยกวิเคราะห์และใช้เพรดิเคตอย่างถูกต้อง
- การเปลี่ยนแปลงนโยบายความปลอดภัยใช้เวลาประมาณ 5 นาทีในการเผยแพร่ การเปลี่ยนแปลงการเป็นสมาชิกกลุ่มผู้ใช้ใช้เวลาประมาณ 1 ชั่วโมง