แชร์ผ่าน


รวมกลไกจัดการของบุคคลที่สามกับการรักษาความปลอดภัย OneLake (พรีวิว)

บทความนี้อธิบายวิธีที่นักพัฒนากลไกจัดการของบริษัทอื่นสามารถรวมเข้ากับการรักษาความปลอดภัย OneLake เพื่อสอบถามข้อมูลจาก OneLake ในขณะที่บังคับใช้การรักษาความปลอดภัยระดับแถว (RLS) และการรักษาความปลอดภัยระดับคอลัมน์ (CLS) การผสานรวมใช้ โมเดลกลไกจัดการที่ได้รับอนุญาต ซึ่งกลไกจัดการของคุณจะอ่านข้อมูลโดยตรงจาก OneLake และบังคับใช้นโยบายความปลอดภัยในเลเยอร์การประมวลผลของตัวเอง

Note

คุณลักษณะนี้เป็นส่วนหนึ่งของรุ่นตัวอย่างและจัดทําขึ้นเพื่อวัตถุประสงค์ในการประเมินและการพัฒนาเท่านั้น ซึ่งอาจเปลี่ยนแปลงตามคําติชมและไม่แนะนําสําหรับการใช้งานด้านการผลิต

ภาพรวม

การรักษาความปลอดภัยของ OneLake กําหนดนโยบายการควบคุมการเข้าถึงแบบละเอียด รวมถึงการรักษาความปลอดภัยระดับตาราง ระดับแถว และระดับคอลัมน์ เพียงครั้งเดียวใน OneLake กลไกจัดการ Microsoft Fabric เช่น Spark และจุดสิ้นสุดการวิเคราะห์ SQL บังคับใช้นโยบายเหล่านี้ในเวลาคิวรี อย่างไรก็ตาม การรักษาความปลอดภัยของ OneLake รับประกันการบังคับใช้นโยบายการควบคุมการเข้าถึงแบบละเอียดโดยไม่คํานึงถึงวิธีการเข้าถึงข้อมูล ด้วยเหตุนี้ คําขอภายนอกที่ไม่ได้รับอนุญาตในการอ่านไฟล์จาก OneLake จึงถูกบล็อกเพื่อให้แน่ใจว่าข้อมูลจะไม่รั่วไหล

รุ่นเครื่องยนต์ที่ได้รับอนุญาตช่วยแก้ปัญหานี้ได้ คุณลงทะเบียนข้อมูลประจําตัวเฉพาะ (บริการหลักหรือข้อมูลประจําตัวที่มีการจัดการ) ที่มีการเข้าถึงการอ่านข้อมูลอย่างเต็มรูปแบบ และยังสามารถอ่านข้อมูลเมตาความปลอดภัยได้อีกด้วย กลไกจัดการของคุณใช้ข้อมูลประจําตัวนี้เพื่อ:

  1. อ่านไฟล์ข้อมูลดิบจาก OneLake
  2. ดึงข้อมูลนโยบายความปลอดภัยที่มีประสิทธิภาพสําหรับผู้ใช้ที่ระบุโดยการเรียกใช้ รับสิทธิ์การเข้าถึงสําหรับ API หลัก
  3. ใช้ตัวกรองแถวและคอลัมน์ที่ส่งคืนในเลเยอร์การดําเนินการคิวรีของตัวเอง
  4. ส่งคืนเฉพาะข้อมูลที่อนุญาตให้กับผู้ใช้ปลายทาง

วิธีการนี้ช่วยให้กลไกจัดการของคุณควบคุมการวางแผนการสืบค้นและการแคชได้อย่างเต็มที่ พร้อมทั้งรักษาการบังคับใช้ความปลอดภัยให้สอดคล้องกับสิ่งที่กลไกจัดการ 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)│
└──────────────┘       └──────────────────┘       └───────────┘
  1. ผู้ใช้ปลายทางส่งแบบสอบถามไปยังกลไกจัดการของบุคคลที่สาม
  2. ข้อมูลประจําตัวของกลไกจัดการรับรองความถูกต้องกับ OneLake และอ่านไฟล์ข้อมูลดิบ (Delta parquet) โดยใช้ OneLake API
  3. OneLake ส่งคืนข้อมูลที่ร้องขอ
  4. กลไกจัดการจะ principalAccess เรียก API โดยส่งผ่านรหัสออบเจ็กต์ Microsoft Entra ของผู้ใช้ปลายทาง เพื่อรับการเข้าถึงที่มีประสิทธิภาพของผู้ใช้
  5. กลไกจัดการจะใช้ตัวกรองการเข้าถึงที่ส่งคืน (การเข้าถึงตาราง, เพรดิเคต RLS, รายการคอลัมน์ CLS) กับข้อมูลในเลเยอร์การประมวลผลของตัวเอง
  6. กลไกจัดการส่งคืนเฉพาะผลลัพธ์ที่กรองและอนุญาตให้กับผู้ใช้ปลายทาง

ขั้นตอนที่ 1: ตั้งค่าข้อมูลประจําตัวของกลไกจัดการ

กลไกจัดการของคุณต้องการข้อมูลประจําตัวของ Microsoft Entra ที่ OneLake รู้จักและเชื่อถือ ข้อมูลประจําตัวนี้จะอ่านไฟล์ข้อมูลและข้อมูลเมตาด้านความปลอดภัยในนามของกลไกจัดการของคุณ

  1. สร้างหรือระบุบริการหลักหรือข้อมูลประจําตัวที่มีการจัดการ ใน Microsoft Entra ID สําหรับกลไกจัดการของคุณ สําหรับข้อมูลเพิ่มเติม ดู แอปพลิเคชันและบริการหลักในรหัส Microsoft Entra

  2. เพิ่มข้อมูลประจําตัวให้กับบทบาท สมาชิก พื้นที่ทํางาน ในพอร์ทัล Fabric ไปที่การตั้งค่าพื้นที่ทํางาน และเพิ่มบริการหลักไปยังบทบาท สมาชิก สิ่งนี้จะให้ข้อมูลประจําตัว:

    • อ่านการเข้าถึงไฟล์ข้อมูลทั้งหมดใน OneLake สําหรับรายการในพื้นที่ทํางานนั้น
    • เข้าถึงการอ่านเมตาดาต้าของบทบาทความปลอดภัย OneLake ผ่าน API กลไกจัดการที่ได้รับอนุญาต

    สําหรับข้อมูลเพิ่มเติมเกี่ยวกับบทบาทพื้นที่ทํางาน โปรดดู บทบาทในพื้นที่ทํางาน

  3. ตรวจสอบให้แน่ใจว่าข้อมูลประจําตัวมีการเข้าถึงที่ไม่จํากัด ข้อมูลประจําตัวของกลไกจัดการต้องมีสิทธิ์อ่านแบบเต็มรูปแบบในแต่ละตารางที่สืบค้น หาก 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
  • อย่าเปิดเผยข้อมูลดิบต่อผู้ใช้ปลายทาง ใช้ตัวกรองความปลอดภัยที่ส่งคืนโดย principalAccess API เสมอก่อนที่จะส่งคืนข้อมูลใดๆ การข้ามการบังคับใช้ถือเป็นการละเมิดความปลอดภัย
  • ตรวจสอบเพรดิเคต RLS อย่างระมัดระวัง แยกวิเคราะห์และใช้เพรดิเคตส่วนคําสั่ง T-SQL WHERE อย่างถูกต้อง การแยกวิเคราะห์ที่ไม่ถูกต้องอาจนําไปสู่การรั่วไหลของข้อมูล หากเกิดข้อผิดพลาดในการแยกวิเคราะห์หรือการแม็ปไวยากรณ์ที่ไม่แน่ใจ ให้คิวรีล้มเหลวด้วยข้อผิดพลาดในการแยกวิเคราะห์ RLS แทนที่จะแสดงผลลัพธ์บางส่วนหรือไม่ปลอดภัยแก่ผู้ใช้
  • จัดการตารางที่หายไปเนื่องจากการเข้าถึงถูกปฏิเสธ หากไม่มีตารางในการตอบกลับ API แสดงว่าผู้ใช้ไม่มีสิทธิ์เข้าถึง ไม่ถอยกลับไปใช้ข้อมูลที่ไม่ได้กรอง ความปลอดภัยของ OneLake จะใช้การปฏิเสธตามค่าเริ่มต้นเสมอ
  • การตรวจสอบการเข้าถึง บันทึกว่าผู้ใช้รายใดเข้าถึงตารางใดและนโยบายความปลอดภัยใดที่ใช้สําหรับการปฏิบัติตามข้อกําหนดและการแก้ไขปัญหา
  • สํารวจความคิดเห็นเกี่ยวกับการเปลี่ยนแปลงด้านความปลอดภัย ใช้ ETags เพื่อตรวจหาการเปลี่ยนแปลงและรีเฟรชนโยบายที่แคชไว้ทันที

ข้อจำกัด

  • API อยู่ principalAccess ในช่วงแสดงตัวอย่างและอาจเปลี่ยนแปลงได้ตามความคิดเห็น
  • ReadเฉพาะชนิดและPermitเอฟเฟกต์การเข้าถึงเท่านั้นที่ได้รับการสนับสนุนในปัจจุบัน
  • ข้อมูลประจําตัวของเอ็นจิ้นต้องมีการเข้าถึงระดับรูทที่ไม่จํากัด หาก RLS หรือ CLS ใช้กับข้อมูลประจําตัวของกลไกจัดการ การเรียกใช้ API จะล้มเหลว
  • เพรดิเคต RLS ใช้ไวยากรณ์ T-SQL เอ็นจิ้นของคุณมีหน้าที่ในการแยกวิเคราะห์และใช้เพรดิเคตอย่างถูกต้อง
  • การเปลี่ยนแปลงนโยบายความปลอดภัยใช้เวลาประมาณ 5 นาทีในการเผยแพร่ การเปลี่ยนแปลงการเป็นสมาชิกกลุ่มผู้ใช้ใช้เวลาประมาณ 1 ชั่วโมง