DataOps nâng cao 28 — Tự động hoá quản trị: Policy-as-code

13 thg 7, 2026 2 lượt xem
#compliance
#governance
#data-engineering
#dataops
#policy-as-code

Quản trị không phải tài liệu, mà là code chạy trong pipeline

Ở nhiều tổ chức, "governance" là một thư mục SharePoint đầy chính sách PDF mà không ai đọc, cộng với một hội đồng phê duyệt họp hai tuần một lần để gác cổng thủ công. Kết quả có thể đoán trước: chính sách và thực tế lệch nhau, người làm data đi vòng cho kịp deadline, và khi thanh tra NHNN hỏi "bảng chứa CMND của khách hàng được mã hoá và giới hạn quyền như thế nào", câu trả lời là một cuộc rà soát thủ công kéo dài nhiều tuần.

Bài này lật ngược cách tiếp cận đó. Governance automation nghĩa là biến chính sách dữ liệu thành quy tắc máy kiểm được (machine-checkable rules), nhúng vào CI và nền tảng, để mỗi thay đổi được kiểm tự động, vi phạm bị chặn trước khi lên production, và mọi thứ đều có bằng chứng để giải trình. Trong ngân hàng, đây không phải xa xỉ mà là điều kiện sống còn: rủi ro rò rỉ PII, phạt tuân thủ và mất uy tín đều đắt hơn nhiều so với chi phí tự động hoá.

Bài kế thừa nền tảng self-service ở DataOps nâng cao 7 — Platform & self-service, quality/contract ở DataOps nâng cao 5 — Quality & contracts, và các chủ đề quản trị nền ở Governance — Tổng quan.

Compliance-as-code / Policy-as-code

Ý tưởng trung tâm: viết chính sách thành quy tắc executable, chạy trong CI/pipeline để chặn vi phạm thay vì phát hiện sau. Một chính sách "as-code" tốt phải: (1) diễn đạt được ý định nghiệp vụ, (2) máy kiểm được không mơ hồ, (3) chạy nhanh trong CI, (4) cho thông báo lỗi rõ ràng để người sửa được.

Vài chính sách điển hình cho một warehouse ngân hàng:

Chính sáchQuy tắc máy kiểmHành vi khi vi phạm
Mọi cột PII phải có tag và maskingmodel chứa cột nhạy cảm phải khai meta.pii: true + policy tagCI fail
Không bảng nào publickhông grant PUBLIC/allUsers trên schema/tableCI fail, block deploy
Model phải có owner, description, testmọi model có meta.owner, description, ≥1 testCI fail
Naming conventionstaging stg_, marts dim_/fct_, không tên viết tắt tuỳ ýCI warn/fail
Retention khai báomọi bảng có meta.retention_daysCI fail nếu thiếu
Không PII ở tầng public martcột pii: true không được materialize ở schema báo cáoCI fail

Công cụ

  • OPA / Rego (Open Policy Agent): engine policy tổng quát. Ta xuất metadata (dbt manifest.json, danh sách grants, mô tả hạ tầng dưới dạng JSON) rồi viết rule Rego đánh giá. Mạnh khi chính sách cắt ngang nhiều hệ (data + hạ tầng + CI).
  • dbt project evaluator: package dbt kiểm best-practice — model thiếu test/description, source không dùng, cấu trúc DAG sai tầng, model không có owner. Chạy như một phần của dbt build.
  • dbt-checkpoint: pre-commit hooks kiểm nhanh trên diff (model mới phải có description, có test, có tag) — bắt lỗi ngay lúc commit, trước cả CI.
  • Custom checks: script Python đọc manifest.json/catalog.json cho luật đặc thù NCB mà công cụ chuẩn không có (ví dụ: cột khớp danh mục PII nội bộ phải có masking policy tương ứng).

Ví dụ rule Rego chặn bảng public (minh hoạ, không phải block chạy được):

package datawarehouse.grants

# deny nếu có bất kỳ grant nào tới PUBLIC
deny[msg] {
    some g
    input.grants[g].grantee == "PUBLIC"
    msg := sprintf("Cấm grant PUBLIC trên %v", [input.grants[g].object])
}

# deny nếu bảng gắn pii=true nhưng thiếu masking policy
deny[msg] {
    some t
    input.tables[t].meta.pii == true
    not input.tables[t].masking_policy
    msg := sprintf("Bảng PII %v thiếu masking_policy", [input.tables[t].name])
}

Ví dụ khai báo policy trong dbt (minh hoạ) — model được coi là "đủ điều kiện governance" nhờ metadata bắt buộc:

# models/marts/customer/dim_customer.yml (minh hoạ)
models:
  - name: dim_customer
    description: "Dimension khách hàng, khoá theo customer_id"
    meta:
      owner: "team-huy-dong@ncb"
      pii: true
      retention_days: 3650
      classification: "restricted"
    columns:
      - name: national_id
        meta: { pii: true, policy_tag: "PII.NATIONAL_ID" }
        tests: [not_null]
    tests:
      - dbt_utils.expression_is_true:
          expression: "national_id is null or masked = true"

Ví dụ cấu hình dbt_project.yml cho dbt project evaluator (minh hoạ) — bật kiểm owner và test coverage:

vars:
  dbt_project_evaluator:
    documentation_coverage_target: 95
    test_coverage_target: 90
    models_without_owner_severity: error

Metadata-driven governance: phân loại & gắn tag tự động

Con người không thể gắn tag tay cho hàng nghìn cột — và sẽ quên. Cách bền vững là quét cột tự động để phát hiện dữ liệu nhạy cảm rồi gắn tag, sau đó để tag lan truyền theo lineage.

Phân loại tự động: một scanner định kỳ quét tên cột + mẫu dữ liệu mẫu, so với danh mục PII (regex cho số CMND/CCCD 9–12 số, số điện thoại 0[0-9]{9}, email, số thẻ). Cột khớp được đề xuất tag pii, classification. Với ngân hàng nên để scanner đề xuất và người phê duyệt hàng loạt, tránh false positive gắn nhầm cột account_balance là PII.

Tag lan truyền theo lineage: nếu stg_customers.national_id là PII, mọi cột phái sinh trực tiếp từ nó trong dim_customer, mart_kyc cũng được đánh dấu PII tự động. Đây là chỗ lineage sinh từ dbt (column-level lineage) trả cổ tức: policy không phải khai lại ở từng tầng, mà chảy theo dữ liệu.

Access control theo tag (tag-based access): quyền không gắn vào từng bảng thủ công mà gắn vào tag. "Ai được đọc cột tag PII.NATIONAL_ID" định nghĩa một lần; mọi cột mang tag đó tự động thừa hưởng luật. Thêm cột PII mới → tự động được bảo vệ, không cần nhớ cấp/thu quyền.

Governance ở ranh giới: data contract

Nơi dễ mất kiểm soát nhất là ranh giới giữa các domain: một domain đổi schema, domain hạ nguồn vỡ; hoặc PII rò sang một data product không được phép nhận. Data contract biến giao diện dữ liệu thành hợp đồng máy kiểm được: schema, kiểu, ràng buộc chất lượng, và phân loại nhạy cảm của từng trường.

Contract cho phép nhúng governance ngay tại điểm trao đổi: contract khai national_idPII.restricted, thì CI của bên tiêu thụ có thể từ chối nếu data product của họ là tầng public. Chi tiết cơ chế contract ở DataOps nâng cao 5 — Quality & contracts; ở quy mô nhiều domain, mô hình phân quyền governance liên bang (federated) xem DataOps nâng cao 14 — Data Mesh at scale.

Chính sách truy cập là code: grants, masking, RLS

Cấp quyền bằng tay qua UI là nguồn lỗi kinh điển: cấp rồi quên thu, cấp nhầm role, không ai biết ai có quyền gì. Grants-as-code đưa toàn bộ ma trận quyền vào Git, review qua PR, áp qua CI — đúng tinh thần Governance — Access control.

# access/roles.yml (minh hoạ)
roles:
  analyst_huy_dong:
    read: [marts.dim_customer, marts.fct_deposit]
    masked_columns: [dim_customer.national_id, dim_customer.phone]
  compliance_officer:
    read: [marts.*]
    unmasked_columns: [dim_customer.national_id]  # có mục đích KYC hợp pháp
  • Masking as code: cột PII định nghĩa masking policy trong code; role thường thấy dữ liệu che (***), chỉ role có mục đích hợp pháp (KYC, điều tra gian lận) mới thấy rõ. Áp bằng migration versioned, không sửa tay trên warehouse.
  • RLS (Row-Level Security) as code: giới hạn dòng theo vai trò — ví dụ chi nhánh chỉ thấy khách của chi nhánh mình. Luật RLS là code, được test tự động.

Toàn bộ được kiểm bởi policy-as-code: một rule Rego xác minh không có role nào đọc được cột PII mà không có masking, không role nào ngoài whitelist unmask được national_id.

Audit & lineage tự động phục vụ giải trình

Governance không dừng ở "chặn được vi phạm" — phải chứng minh được ta kiểm soát. Ba thứ cần tự động:

  • Audit log truy cập: ai đọc bảng nào, khi nào, cột nào (đặc biệt cột PII). Log tập trung, bất biến, giữ theo retention.
  • Lineage tự động: sinh từ dbt (không khai tay), trả lời "dữ liệu này từ đâu, chảy đi đâu" — cần khi báo cáo sự cố rò rỉ hoặc chứng minh phạm vi ảnh hưởng.
  • Change history: mọi thay đổi policy/grant/schema là commit Git — ai đổi, khi nào, được ai duyệt.

Khi thanh tra hỏi "cột CMND được bảo vệ ra sao", câu trả lời là: policy-as-code này (link commit), grants-as-code này, audit log 12 tháng này, lineage này — thay vì một cuộc rà soát thủ công. Chi tiết catalog/lineage/audit xem Governance — Tổng quan.

Nhúng tuân thủ NĐ13/NHNN vào pipeline

Nghị định 13/2023/NĐ-CP về bảo vệ dữ liệu cá nhân và các quy định NHNN đặt ra nghĩa vụ về consent (đồng ý), mục đích xử lý, retention (lưu trữ), quyền xoá. Governance automation nhúng các nghĩa vụ này thành kiểm tra tự động (chi tiết pháp lý ở Governance — Privacy & compliance):

  • Consent & mục đích: mỗi bảng PII khai purpose (mục đích thu thập); pipeline nào dùng dữ liệu ngoài mục đích đã khai → CI cảnh báo. Bản ghi thiếu consent flag không được đưa vào mart marketing.
  • Retention: mọi bảng PII bắt buộc khai retention_days; một job tự động phát hiện/che/xoá bản ghi quá hạn; policy-as-code fail nếu bảng thiếu khai báo.
  • Quyền xoá (right to erasure): có quy trình xoá/che theo customer_id chảy qua mọi hệ (nhờ lineage), và test tự động xác nhận sau khi xử lý không còn dấu vết ở tầng phân tích.

SQL: một CHECK governance tự động

Dưới đây là một check governance có thể chạy trực tiếp trên sandbox: quét bảng customers phát hiện giá trị giống PII (số điện thoại / CMND) lọt vào cột full_name — dấu hiệu dữ liệu bẩn hoặc phân loại sai cần cảnh báo. Loại check này chạy định kỳ trong pipeline như một data-quality/governance gate.

-- ▶ Chạy được
SELECT id, full_name, created_at
FROM customers
WHERE full_name ~ '[0-9]{9,12}'
   OR full_name ~ '0[0-9]{9}'
ORDER BY created_at DESC;

Câu trên trả về các bản ghi khách hàng mà trường tên chứa chuỗi số dài giống CMND/CCCD (9–12 số) hoặc số điện thoại di động (0 + 9 số) — những giá trị đáng lẽ không được nằm ở cột tên. Trong CI, biến thể của nó có thể chạy dưới dạng test dbt: nếu COUNT(*) > 0 thì fail và chặn deploy.

Governance by default trên nền tảng self-service

Cách bền vững nhất không phải kiểm ở cuối, mà làm cho con đường dễ nhất cũng là con đường tuân thủ. Golden path ở DataOps nâng cao 7 — Platform & self-service đã nhúng sẵn: template dbt có macro mã hoá PII, cấu hình mặc định gắn owner/retention, CI mặc định chạy policy-as-code, mọi model tự đăng ký catalog.

Khi domain dùng golden path, họ tuân thủ mà không phải cố gắng. Policy-as-code khi đó không phải rào cản khó chịu mà là lưới an toàn — bắt trường hợp domain đi lệch đường. Đây cũng là góc DevSecOps của dữ liệu, tương đồng công cụ ở Security — DevSecOps tooling.

Đo lường & cân bằng kiểm soát với tốc độ

Governance tự động phải đo được, nếu không sẽ trôi:

Chỉ sốÝ nghĩaMục tiêu
% model có ownerTrách nhiệm rõ ràng100%
% cột PII đã gắn tagPhủ phân loại> 95%
% model có test + descriptionChất lượng + tài liệu> 90%
Số vi phạm bị CI chặn/thángLưới an toàn hoạt độngTheo dõi xu hướng
Số bảng public ngoài ý muốnRò rỉ tiềm tàng0
Thời gian policy check trong CIKhông làm chậm dev< 2 phút

Nguyên tắc cân bằng cốt lõi: không gác cổng thủ công. Hội đồng phê duyệt họp hai tuần một lần giết tốc độ và không thực sự an toàn hơn — con người rà tay bỏ sót nhiều hơn máy. Thay vào đó: chính sách rõ ràng thành code, kiểm tự động tức thì trong CI, chỉ những ngoại lệ hiếm (đi lệch golden path) mới cần con người xem. Đây là cách vừa nhanh vừa kiểm soát chặt — đúng tinh thần DataOps áp cho quản trị.

Use case thực tế

NCB xây một data product mart_kyc phục vụ đội tuân thủ, chứa national_id, phone, full_name của khách hàng. Trước đây quy trình là: đội huy động tự dựng bảng, mở ticket nhờ platform cấp quyền, và mỗi quý một cuộc rà soát thủ công kiểm PII — mất trung bình 3 tuần/data product và vẫn sót lỗi (một lần national_id lọt sang mart marketing không mã hoá).

Sau khi áp governance automation:

  1. Ngày 1 — Analyst tạo model từ golden path. dbt-checkpoint (pre-commit) chặn ngay commit vì model thiếu descriptionowner; sửa trong 2 phút.
  2. CI trên PR — dbt project evaluator + custom check chạy 90 giây: phát hiện national_id là PII (khớp danh mục) nhưng thiếu masking policy → chặn PR với thông báo rõ. Analyst thêm meta: { pii: true, policy_tag: "PII.NATIONAL_ID" }; masking tự áp qua tag.
  3. Rego check — xác minh không grant PUBLIC, chỉ role compliance_officer unmask được national_id. Grants-as-code merge qua PR, áp tự động.
  4. Sau merge — Lineage tự sinh; tag PII lan truyền; audit log bật. Retention 3650 ngày khai trong meta, job xoá quá hạn tự chạy.

Kết quả sau 6 tháng: time-to-first-pipeline giảm từ ~3 tuần xuống < 1 ngày; 0 bảng public ngoài ý muốn; 98% model có owner + tag; 47 vi phạm bị CI chặn trước production (trước đây sẽ lọt và phát hiện muộn). Khi NHNN thanh tra bảo vệ dữ liệu cá nhân, đội cung cấp policy-as-code, grants-as-code, audit log và lineage trong 1 ngày thay vì nhiều tuần rà tay.

Ghi nhớ

  • Governance là code chạy trong CI/nền tảng, không phải tài liệu tĩnh hay hội đồng gác cổng thủ công.
  • Policy-as-code: viết chính sách (PII có tag/masking, không bảng public, model có owner/test, naming, retention) thành rule máy kiểm được — OPA/Rego, dbt project evaluator, dbt-checkpoint, custom check — chặn vi phạm trong CI.
  • Metadata-driven: quét cột phân loại PII tự động, tag lan truyền theo lineage, access control gắn theo tag (thêm cột PII mới tự được bảo vệ).
  • Grants/masking/RLS as code: ma trận quyền trong Git, review qua PR, áp qua migration — không sửa tay trên warehouse.
  • Audit + lineage tự động để giải trình ai/gì/khi nào; nhúng kiểm tra NĐ13/NHNN (consent, mục đích, retention, quyền xoá).
  • Governance by default trên golden path: con đường dễ nhất cũng tuân thủ sẵn; policy-as-code là lưới an toàn cho trường hợp đi lệch.
  • Đo lường (% owner/tag/test, số vi phạm bị chặn, số bảng public) và cân bằng: tự động thay cho gác cổng thủ công — vừa nhanh vừa kiểm soát chặt.

Bài viết liên quan

CSV/JSON/Parquet/Avro, lưu trữ theo hàng vs cột, nén, và OLTP vs OLAP.

13 thg 7, 2026 8

Data Engineering là gì, vai trò trong vòng đời dữ liệu, và bức tranh hệ sinh thái công cụ.

13 thg 7, 2026 5

Vì sao xử lý phân tán, mô hình Spark (RDD/DataFrame), lazy evaluation, shuffle và tối ưu.

13 thg 7, 2026 5

Đảm bảo chất lượng & minh bạch dữ liệu bằng dbt: data tests dựng sẵn (unique, not_null, relationships, accepted_values), singular test, unit test, và tài liệu tự sinh kèm lineage graph.

13 thg 7, 2026 5