Trino 7 — Bảo mật & quản trị truy cập

13 thg 7, 2026 2 lượt xem
#security
#governance
#sql
#access-control
#trino

Trino 7 — Bảo mật & quản trị truy cập

Sáu bài trước đã dựng nên bức tranh kỹ thuật: Trino 1 — Tổng quan định vị Trino là query engine phân tán, Trino 2 — Kiến trúc mổ xẻ coordinator/worker, Trino 3 — ConnectorsTrino 4 — SQL liên hợp cho thấy sức mạnh JOIN xuyên nguồn, Trino 5 — LakehouseTrino 6 — Tuning lo phần hiệu năng. Bài này chạm vào điều quan trọng bậc nhất với ngân hàng: bảo mật.

Lý do đơn giản mà nghiêm trọng: Trino là một điểm truy cập TẬP TRUNG tới rất nhiều nguồn nhạy cảm. Trước khi có Trino, mỗi hệ (core banking Postgres, data lake, CRM MySQL) có tường lửa và phân quyền riêng, người dùng phải xin quyền từng nơi. Sau khi có Trino, một analyst chỉ cần một kết nối duy nhất là có tiềm năng chạm tới toàn bộ dữ liệu khách hàng — số tài khoản, số dư, giao dịch, thông tin định danh (PII). Nếu Trino không được khoá chặt, nó trở thành "chìa khoá vạn năng" mà kẻ tấn công thèm muốn nhất. Bảo mật Trino vì thế không phải tuỳ chọn — với ngân hàng, đó là điều kiện bắt buộc để đưa vào sản xuất.

Bảo mật Trino gồm bốn lớp xếp chồng, phải làm đủ cả bốn mới an toàn:

Lớp 1 — Xác thực: bạn LÀ AI? (Authentication)

Mặc định, Trino không bật xác thực — ai kết nối được tới cổng là chạy được câu, khai báo tên user tuỳ ý. Điều này chỉ chấp nhận cho môi trường thử nghiệm cô lập. Trong sản xuất, bắt buộc bật ít nhất một phương thức xác thực, và xác thực chỉ hoạt động khi HTTPS/TLS đã bật (Trino từ chối gửi mật khẩu qua HTTP trần).

Trino hỗ trợ nhiều phương thức, cấu hình qua http-server.authentication.type (có thể liệt kê nhiều loại, thử lần lượt):

Phương thứcCơ chếPhù hợp
PASSWORD (LDAP)User/mật khẩu, xác thực qua LDAP/Active DirectoryPhổ biến nhất ở doanh nghiệp — tái dùng AD của ngân hàng, quản lý tập trung
PASSWORD (file)User/mật khẩu băm trong file password.db (bcrypt)Số ít service account, môi trường nhỏ
OAUTH2 / JWTXác thực qua Identity Provider (Okta, Keycloak, Azure AD) trả tokenSSO hiện đại, tích hợp BI tool; JWT cho service-to-service
KERBEROSVé Kerberos (SPNEGO)Hệ sinh thái Hadoop/AD dùng Kerberos sẵn
CERTIFICATEChứng chỉ client TLS (mutual TLS)Kết nối máy-máy độ tin cậy cao, không mật khẩu

Trong bối cảnh NCB, mô hình điển hình là LDAP/AD làm nguồn danh tính cho người dùng (analyst đăng nhập bằng tài khoản domain của họ) kết hợp OAuth2 cho BI tool và certificate cho các job tự động. Quan trọng: xác thực chỉ trả lời "bạn là ai" — nó chưa nói bạn được làm gì, đó là việc của lớp phân quyền.

Lớp 2 — Mã hoá: TLS cho client và internal

Xác thực mà không mã hoá là vô nghĩa — kẻ nghe lén (man-in-the-middle) sẽ tóm được mật khẩu và dữ liệu. Trino cần TLS ở hai đường:

  • TLS client → coordinator (http-server.https.enabled=true): mã hoá toàn bộ giao tiếp giữa client (BI, notebook, JDBC) và coordinator — cả mật khẩu lẫn kết quả truy vấn (chứa PII) đều được mã hoá trên đường truyền. Đây là điều kiện tiên quyết để bật authentication.
  • TLS internal coordinator ↔ worker và worker ↔ worker (internal-communication.https.required=true): đây là điểm hay bị bỏ quên. Dữ liệu di chuyển giữa các node trong cụm khi shuffle/exchange cũng chứa dữ liệu khách hàng thô. Trong một trung tâm dữ liệu ngân hàng nhiều tenant, giao tiếp internal cũng phải mã hoá. Trino dùng một shared secret (internal-communication.shared-secret) để các node xác thực lẫn nhau, chống node giả mạo trà trộn vào cụm.

Nguyên tắc: không có dữ liệu ngân hàng nào được đi trên dây ở dạng plaintext, dù là ra client hay giữa các worker.

Lớp 3 — Phân quyền: bạn được LÀM GÌ? (Authorization)

Đây là trái tim của quản trị truy cập. Sau khi biết "bạn là ai", Trino hỏi tiếp: user này được đọc/ghi những catalog/schema/table/column nào? Cơ chế là system access control (SAC) — một plugin quyết định cho phép hay từ chối từng thao tác. Trino cung cấp/tích hợp mấy lựa chọn:

File-based access control

Đơn giản, không cần hệ thống ngoài: định nghĩa rule dưới dạng JSON trong một file, cấp/từ chối theo user, group, catalog, schema, table (khớp bằng regex). Ví dụ ý tưởng (minh hoạ, không phải cấu hình chạy được):

{
  "catalogs": [
    { "user": "analyst_.*", "catalog": "core", "allow": "read-only" },
    { "user": "analyst_.*", "catalog": "lake", "allow": "read-only" },
    { "user": "etl_svc",    "catalog": "lake", "allow": "all" }
  ],
  "schemas": [
    { "user": "analyst_.*", "catalog": "core", "schema": "public", "owner": false }
  ]
}

Ưu điểm: nhẹ, minh bạch, versioned trong Git. Nhược: khó co giãn cho hàng trăm rule, không có UI cho nghiệp vụ, sửa rule thường phải reload. Hợp cụm nhỏ hoặc làm lớp phòng thủ cơ bản.

Tích hợp Apache Ranger / OPA / Privacera

Với quy mô ngân hàng, phân quyền thường tập trung tại một hệ quản trị bên ngoài thay vì rải trong file:

  • Apache Ranger: chuẩn de-facto trong hệ sinh thái Hadoop. Có UI quản trị policy theo role, hỗ trợ column maskingrow filtering ngay trong policy, và ghi audit tích hợp. Trino gọi Ranger plugin để hỏi quyền mỗi thao tác. Rất hợp khi ngân hàng đã dùng Ranger cho Hive/HDFS — dùng chung một bộ policy.
  • OPA (Open Policy Agent): engine policy đa dụng viết bằng ngôn ngữ Rego; Trino gửi context (user, thao tác, đối tượng) và OPA trả allow/deny. Linh hoạt cực cao, hợp team thích "policy as code" và muốn thống nhất chính sách xuyên nhiều hệ (không chỉ Trino).
  • Privacera / Immuta / Collibra: nền tảng data governance thương mại, quản lý policy, masking, discovery PII và audit theo hướng tuân thủ, có tích hợp Trino sẵn.

Điểm chung: phân quyền được ngoại hoá và tập trung, để đội governance quản lý policy một chỗ, áp cho nhiều engine — thay vì mỗi người config một kiểu. Kết nối với Governance & Access Control để đồng bộ mô hình role/entitlement toàn tổ chức.

Phân quyền của Trino kiểm soát theo cấp bậc phân cấp: catalog → schema → table → column, cộng các thao tác (SELECT, INSERT, DELETE, CREATE, DROP, SET SESSION…). Một analyst có thể được đọc core.public.customers nhưng bị cấm core.public.employees, hoặc chỉ đọc được vài cột nhất định của customers.

Lớp 3b — Column masking & Row filtering: che PII, lọc theo vai trò

Đây là phần nghiệp vụ ngân hàng quan tâm nhất, và Trino (qua SAC như Ranger/OPA hoặc column mask policy) hỗ trợ tận cấp cột và dòng:

  • Column-level security & data masking: một cột nhạy cảm (số CMND/CCCD, số tài khoản, số dư) có thể bị che (mask) hoặc từ chối tuỳ vai trò người xem. Analyst marketing thấy account_no dạng ******1234, còn cán bộ kiểm soát rủi ro thấy đầy đủ. Masking thực hiện bằng cách áp một biểu thức (VD regexp_replace, băm, hoặc trả NULL) lên cột trước khi kết quả rời engine.
  • Row-level security (RLS) / row filtering: chỉ trả những dòng người dùng được phép. Ví dụ kinh điển: nhân viên chi nhánh Hà Nội chỉ thấy khách hàng thuộc chi nhánh Hà Nội — engine tự chèn một điều kiện lọc (VD WHERE city = 'Hà Nội') vào mọi truy vấn của họ, dù họ viết SELECT *. Người dùng không thể "lách" vì filter áp ở tầng engine, không phải ở câu SQL họ gõ.

Điểm mạnh: masking và filtering là transparent — analyst viết câu SQL bình thường, engine tự áp policy. Họ không cần biết (và không thể tắt) lớp bảo vệ. Đây là cách ngân hàng vừa mở dữ liệu cho phân tích rộng, vừa giữ least exposure với PII.

SQL "▶ Chạy được" — minh hoạ masking & row filtering bằng SELECT

Trong Trino, masking/filtering do policy engine áp tự động (analyst không tự viết). Nhưng để bạn thấy bản chất phép biến đổi, câu SELECT sau minh hoạ đúng logic đó bằng biểu thức thuần, và chạy được trên sandbox PostgreSQL: che account_no bằng regexp_replace (chỉ lộ 4 số cuối), và lọc dòng theo city để mô phỏng RLS "chỉ thấy khách chi nhánh Hà Nội":

-- ▶ Chạy được
SELECT
    c.full_name,
    c.city,
    a.currency,
    regexp_replace(a.account_no, '.(?=.{4})', '*', 'g') AS account_no_masked,
    ROUND(a.balance::numeric, 2)                        AS balance
FROM accounts a
JOIN customers c ON a.customer_id = c.id
WHERE c.city = 'Hà Nội'          -- mô phỏng row filter theo chi nhánh (RLS)
ORDER BY a.balance DESC;

Ở đây regexp_replace(...) thay mọi ký tự trừ 4 ký tự cuối bằng * — chính là column masking cho account_no; còn WHERE c.city = 'Hà Nội' mô phỏng row filter mà policy engine sẽ tự chèn cho user thuộc chi nhánh đó. Trên Trino thật, cả hai được áp bởi Ranger/OPA policy trước khi kết quả rời engine, người dùng không thấy và không sửa được điều kiện này.

Kế thừa & ánh xạ quyền tới nguồn: least privilege cho connector

Đây là hiểu lầm nguy hiểm nhất về bảo mật Trino, cần tách bạch hai lớp quyền hoàn toàn khác nhau:

  1. Quyền của người dùng tại Trino (phân quyền lớp 3 ở trên): analyst an.nguyen được đọc gì trong Trino.
  2. Quyền của tài khoản mà connector dùng để nối vào nguồn: mỗi catalog cấu hình một connection string + credential để Trino đăng nhập vào nguồn (VD user trino_ro nối vào Postgres core).

Vấn đề: connector thường nối vào nguồn bằng một tài khoản kỹ thuật dùng chung cho mọi truy vấn — nguồn không biết câu này thực chất do analyst nào chạy. Nghĩa là quyền thực tế chạm được dữ liệu = quyền của tài khoản connector, không phải quyền của người dùng cuối tại nguồn. Nếu bạn cấp cho trino_ro quyền đọc toàn bộ DB core, thì bất kỳ ai vượt qua được lớp phân quyền Trino cũng đọc được toàn bộ đó.

Nguyên tắc bắt buộc — least privilege cho tài khoản connector:

  • Tài khoản connector chỉ nên có quyền tối thiểu cần thiết, và với các nguồn OLTP sản xuất, hầu như luôn là CHỈ ĐỌC (read-only). Trino không cần ghi vào core banking — cấm luôn quyền write để một câu DELETE/UPDATE lọt qua cũng vô hại.
  • Giới hạn tài khoản connector chỉ thấy các schema/table cần thiết, không cấp toàn quyền DB.
  • Với connector hỗ trợ impersonation/pass-through (VD Kerberos xuống HDFS, hoặc user impersonation ở một số JDBC), nên dùng để nguồn biết danh tính người dùng thật và áp quyền của nguồn — nhưng không phải connector nào cũng hỗ trợ, nên đừng phụ thuộc.
  • Không hardcode credential trong file catalog dạng plaintext — dùng cơ chế secret bên dưới.

Tóm lại: phân quyền tại Trino và least privilege tại connector là hai hàng phòng thủ độc lập, phải làm cả hai. Trino không tự động "kế thừa" quyền chi tiết của người dùng xuống nguồn.

Lớp 4 — Audit & event logging: ai truy vấn gì

Với ngân hàng, ghi lại ai đã truy vấn dữ liệu gì, khi nào, từ đâu không phải tuỳ chọn mà là yêu cầu tuân thủ (compliance) — thanh tra, kiểm toán nội bộ, và điều tra sự cố đều cần nhật ký này. Trino cung cấp Event Listener: một plugin nhận sự kiện cho mỗi truy vấn với đầy đủ metadata:

  • User, nguồn (source), thời điểm bắt đầu/kết thúc.
  • Toàn văn câu SQL đã chạy.
  • Các table/column được truy cập (rất quan trọng để biết ai chạm PII).
  • Trạng thái (thành công/lỗi), thời gian, lượng dữ liệu quét, và cả câu bị từ chối vì thiếu quyền (dấu hiệu dò quét).

Event listener thường được cấu hình đẩy log vào Kafka/Elasticsearch/DB để tập trung phân tích. Ranger cũng tự ghi audit truy cập. Với dữ liệu khách hàng nhạy cảm, đội governance cần giám sát chủ động: cảnh báo khi có người quét bảng PII bất thường, khi số câu bị từ chối tăng vọt, hoặc khi một tài khoản truy cập ngoài giờ. Không có audit thì mọi lớp trên đều "mù" khi cần điều tra. Xem thêm góc quan sát vận hành ở Trino 8 — Triển khai & vận hành.

Resource groups: cô lập & chống lạm dụng

Bảo mật không chỉ là chống truy cập trái phép mà còn là chống một người dùng làm sập cụm (dù vô tình hay cố ý). Resource groups chia tài nguyên (bộ nhớ, số truy vấn đồng thời, CPU) theo nhóm người dùng/nguồn:

  • Nhóm analyst_adhoc bị giới hạn bộ nhớ và số câu đồng thời → một câu tham lam không nuốt hết RAM cụm, không làm nghẽn các job ưu tiên.
  • Nhóm etldashboard có hạn ngạch riêng, không giẫm chân nhau.
  • Đây là hàng rào chống lạm dụng và DoS nội bộ: một câu CROSS JOIN bất cẩn hay một vòng lặp gọi API dồn dập bị chặn ở mức nhóm, không hạ cả hệ thống.

Resource groups vừa là công cụ hiệu năng vừa là công cụ an ninh khả dụng (availability) — giữ cụm ổn định cho mọi tenant.

Secret cho catalog config: không hardcode

Mỗi catalog cần credential nối vào nguồn (mật khẩu Postgres, access key S3…). Tuyệt đối không để plaintext trong file catalog/*.properties — file này dễ bị đọc, dễ lọt vào Git, dễ lộ qua backup. Cách đúng:

  • Dùng cơ chế secret của Trino hoặc tham chiếu biến môi trường (${ENV:PG_PASSWORD}) để credential không nằm trực tiếp trong file.
  • Tích hợp kho bí mật (HashiCorp Vault, cloud secret manager) để cấp phát và xoay vòng (rotate) credential định kỳ.
  • Phân quyền file hệ thống chặt (chỉ user chạy Trino đọc được), mã hoá đĩa nơi lưu config.

Một credential connector bị lộ = kẻ tấn công nối thẳng vào nguồn, bỏ qua toàn bộ Trino. Đây là mắt xích thường bị xem nhẹ nhưng hậu quả nặng nhất.

Use case thực tế

Bối cảnh (NCB): Khối Phân tích muốn mở cụm Trino cho ~120 analyst tự truy vấn dữ liệu khách hàng (bảng customers, accounts, transactions từ core Postgres + lake). Yêu cầu tuân thủ: analyst marketing không được thấy số tài khoản đầy đủ và số CCCD, chỉ được thấy khách thuộc chi nhánh mình phụ trách, và mọi truy cập PII phải được ghi log để kiểm toán.

Thiết kế bảo mật triển khai:

  1. Xác thực + TLS: bật HTTPS cho coordinator, xác thực qua LDAP/AD — analyst đăng nhập bằng tài khoản domain; BI tool dùng OAuth2 qua Keycloak. Bật TLS internal + shared secret cho giao tiếp worker.
  2. Phân quyền qua Apache Ranger: định nghĩa role mkt_analyst, risk_officer, etl_svc. Role mkt_analyst được SELECT trên core.public.customers/accounts nhưng bị cấm employees.
  3. Column masking: policy Ranger che account_nonational_id cho mkt_analyst (chỉ lộ 4 số cuối), risk_officer thấy đầy đủ — logic đúng như câu regexp_replace minh hoạ ở trên.
  4. Row filtering: policy chèn WHERE branch = <chi nhánh của user> tự động cho mọi câu của mkt_analyst — họ viết SELECT * cũng chỉ ra khách chi nhánh mình.
  5. Least privilege connector: tài khoản trino_ro nối vào Postgres core được cấp chỉ đọc trên đúng schema cần, không có quyền write; credential lấy từ Vault, không hardcode.
  6. Audit: Event Listener đẩy toàn bộ query log (user, SQL, bảng/cột chạm, kết quả) vào Elasticsearch; dashboard cảnh báo khi có người quét bảng PII bất thường hoặc số câu bị từ chối tăng đột biến.
  7. Resource groups: nhóm analyst_adhoc giới hạn RAM/đồng thời để một câu tham lam không làm nghẽn job ETL đêm.

Kết quả: 120 analyst tự phục vụ truy vấn trên một cụm, nhưng mỗi người chỉ thấy đúng phần dữ liệu được phép, PII bị che theo vai trò, và mọi truy cập đều để lại dấu vết kiểm toán. Trino trở thành cửa ngõ dữ liệu an toàn và tuân thủ, thay vì chìa khoá vạn năng rủi ro.

Ghi nhớ

  • Trino là điểm truy cập tập trung tới nhiều nguồn nhạy cảm → bảo mật là điều kiện bắt buộc để lên sản xuất, không phải tuỳ chọn.
  • Bốn lớp phải làm đủ cả: (1) TLS mã hoá client + internal, (2) authentication, (3) authorization, (4) audit.
  • Xác thực (bạn là ai): password/LDAP, OAuth2/JWT, Kerberos, certificate — mặc định Trino KHÔNG bật; xác thực chỉ chạy khi đã có HTTPS.
  • TLS hai đường: client→coordinator và internal coordinator↔worker (điểm hay quên) + shared secret chống node giả mạo.
  • Phân quyền qua system access control: file-based (nhỏ, versioned) hoặc tập trung qua Ranger/OPA/Privacera; kiểm soát theo catalog→schema→table→column.
  • Column masking che cột nhạy cảm theo vai trò; row filtering (RLS) chỉ trả dòng được phép (VD theo chi nhánh) — áp ở tầng engine, người dùng không lách được.
  • Least privilege cho tài khoản connector: quyền tại Trino ≠ quyền connector nối vào nguồn; connector nên chỉ đọc với OLTP sản xuất, credential không hardcode (dùng secret/Vault).
  • Audit / event logging ghi ai truy vấn gì — bắt buộc cho tuân thủ, phục vụ giám sát PII và điều tra sự cố.
  • Resource groups cô lập tài nguyên, chống lạm dụng/DoS nội bộ; secret cho catalog tránh lộ credential.

Bài viết liên quan

Cách index hoạt động (B-Tree), đọc EXPLAIN, seq scan vs index scan và mẫu tối ưu truy vấn.

13 thg 7, 2026 4

Khoá, ràng buộc, quan hệ và chuẩn hoá 1NF/2NF/3NF — thiết kế lược đồ đúng từ đầu.

13 thg 7, 2026 4

Kết nhiều bảng đúng cách: các loại JOIN, bẫy thường gặp và phép hợp tập.

13 thg 7, 2026 3

Truy vấn lồng, CTE (WITH), CTE đệ quy và hàm cửa sổ — vũ khí cho phân tích nâng cao.

13 thg 7, 2026 3