Product Management
Đăng nhập
ESC

Nhập từ khóa để tìm kiếm

↑↓ Di chuyển
Enter Mở
ESC Đóng

Bài 52 — Encryption — At-rest & In-transit

Đã đọc 0/15 mục · còn khoảng 12 phút
Cách chúng tôi ghi nhận

Một mục được tính là đã đọc khi nó nằm giữa màn hình đủ lâu so với độ dài của nó (bảng và sơ đồ tính một nửa), bạn vẫn đang cuộn hoặc bấm phím, và bạn đã thấy tới cuối mục. Lướt nhanh hoặc để tab mở không được tính. Chúng tôi chỉ lưu thời gian đọc từng mục — không lưu gì khác.

Mở đầu — vì sao bài này quan trọng

Hãy tưởng tượng bạn là người phụ trách hạ tầng cho một ví điện tử tại Việt Nam. Một buổi sáng, đội vận hành phát hiện một ổ đĩa (disk) bị tháo nhầm khỏi trung tâm dữ liệu trong lúc thay phần cứng, và không ai chắc chắn nó đã đi đâu. Nếu toàn bộ dữ liệu số dư, số CMND/CCCD, lịch sử giao dịch trên ổ đĩa đó nằm ở dạng plaintext (văn bản thô, đọc được trực tiếp), thì đó là một thảm họa — không chỉ về mặt kỹ thuật mà cả về pháp lý và uy tín. Nhưng nếu dữ liệu đã được encrypt at-rest (mã hóa khi lưu trữ), thì kẻ cầm ổ đĩa chỉ nhìn thấy một mớ byte vô nghĩa, vì khóa giải mã (decryption key) không nằm trên ổ đĩa đó.

Encryption — mã hóa — là lớp phòng thủ cuối cùng khi mọi lớp khác đã thất bại. Firewall có thể bị vượt qua, IAM policy có thể bị cấu hình sai, nhưng nếu dữ liệu được mã hóa đúng cách thì kẻ tấn công có lấy được file cũng không đọc được nội dung. Trong bài này, chúng ta tập trung vào hai trạng thái mã hóa quan trọng nhất trong cloud: encryption at-rest (mã hóa dữ liệu khi nằm yên trên storage) và encryption in-transit (mã hóa dữ liệu khi đang di chuyển trên mạng). Đây cũng là hai yêu cầu gần như bắt buộc trong mọi khung tuân thủ như PCI-DSS, ISO 27001, và Nghị định 13/2023 về bảo vệ dữ liệu cá nhân của Việt Nam.

Mục tiêu của bài không phải để bạn trở thành nhà mật mã học, mà để bạn hiểu cơ chế hoạt động, biết bật đúng cấu hình trên các dịch vụ cloud phổ biến, và tránh những sai lầm khiến "đã mã hóa nhưng vẫn không an toàn".

Khái niệm cốt lõi

Ba trạng thái của dữ liệu

Dữ liệu tồn tại ở ba trạng thái, và mỗi trạng thái cần một cách bảo vệ riêng:

  • At-rest — dữ liệu nằm yên trên đĩa: file trên S3, block trên EBS, row trong database, snapshot backup.
  • In-transit — dữ liệu đang truyền qua mạng: request từ trình duyệt tới server, giữa hai microservice, giữa app và database.
  • In-use — dữ liệu đang được xử lý trong RAM/CPU. Đây là mảng khó nhất (confidential computing), nằm ngoài phạm vi bài này.
Bài 52 xoáy vào hai trạng thái đầu, vì đó là nơi 99% khối lượng công việc thực tế của một kỹ sư cloud nằm ở đó.

Symmetric vs Asymmetric — hai loại mã hóa

Symmetric encryption (mã hóa đối xứng): dùng cùng một khóa để mã hóa và giải mã. Thuật toán phổ biến là AES-256. Ưu điểm: rất nhanh, phù hợp mã hóa khối dữ liệu lớn. Đây là thứ dùng cho at-rest.

Asymmetric encryption (mã hóa bất đối xứng): dùng cặp khóa public/private. Chậm hơn nhiều, nên chủ yếu dùng để trao đổi khóa và ký số (như trong quá trình bắt tay TLS). Đây là nền tảng của in-transit.

Envelope encryption — trái tim của at-rest trên cloud

Đây là khái niệm quan trọng nhất bạn cần nắm. Cloud không mã hóa terabyte dữ liệu bằng một khóa duy nhất, vì như vậy vừa chậm vừa nguy hiểm khi phải xoay (rotate) khóa. Thay vào đó họ dùng envelope encryption (mã hóa kiểu phong bì):

  • Một khóa gốc KMS key / CMK (Customer Master Key, nay gọi là KMS key trên AWS) được lưu an toàn trong KMS (Key Management Service) và không bao giờ rời khỏi module HSM.
  • Với mỗi khối dữ liệu, hệ thống sinh một DEK (Data Encryption Key) ngẫu nhiên để mã hóa dữ liệu thật.
  • DEK này lại được mã hóa bằng KMS key, tạo ra một encrypted DEK lưu cạnh dữ liệu.
  • Khi cần đọc, hệ thống gửi encrypted DEK cho KMS để giải mã ra plaintext DEK, dùng nó giải mã dữ liệu, rồi xóa DEK khỏi bộ nhớ.
Nhờ đó, muốn xoay khóa gốc bạn chỉ cần mã hóa lại các DEK (nhỏ), không phải mã hóa lại toàn bộ dữ liệu (khổng lồ). Và quyền truy cập dữ liệu thực chất được kiểm soát bởi quyền gọi KMS để giải mã DEK — đây là lý do IAM và KMS luôn đi đôi với nhau.

Encryption at-rest trên các dịch vụ AWS

Trên AWS, hầu hết dịch vụ storage đã hỗ trợ mã hóa at-rest:

  • S3: có SSE-S3 (khóa do AWS quản lý hoàn toàn), SSE-KMS (dùng KMS key của bạn, có audit log qua CloudTrail), và SSE-C (bạn tự cung cấp khóa). Từ đầu 2023, S3 mã hóa mặc định mọi object mới bằng SSE-S3.
  • EBS: bật một checkbox là toàn bộ volume và snapshot được mã hóa AES-256. Có thể bật "encryption by default" ở cấp region.
  • RDS: mã hóa storage, backup, read replica và snapshot. Lưu ý: phải bật lúc tạo instance — không thể bật cho một RDS đang chạy mà chưa mã hóa (phải tạo snapshot, copy sang bản mã hóa, rồi restore).
  • DynamoDB: mã hóa at-rest mặc định, không tắt được.
Về loại khóa: bạn có thể dùng AWS managed key (miễn phí, AWS tự xoay hằng năm, nhưng bạn không kiểm soát policy) hoặc customer managed key (bạn tạo trong KMS, tự đặt key policy, tự bật rotation, kiểm soát ai được dùng — trả phí khoảng 1 USD/khóa/tháng cộng phí theo lượt gọi API). Với dữ liệu nhạy cảm cần audit và tách quyền, hãy dùng customer managed key.

Encryption in-transit — TLS là mặc định

In-transit gần như đồng nghĩa với TLS (Transport Layer Security, kế nhiệm của SSL). Khi client kết nối HTTPS, hai bên thực hiện TLS handshake: server trình chứng chỉ (certificate), client xác thực chứng chỉ, hai bên thỏa thuận một session key đối xứng, và từ đó mọi dữ liệu được mã hóa. Bạn nên yêu cầu tối thiểu TLS 1.2, ưu tiên TLS 1.3 (nhanh hơn, an toàn hơn).

Trên cloud, in-transit thể hiện ở nhiều tầng: chứng chỉ trên Load Balancer/CloudFront (thường cấp miễn phí qua ACM — AWS Certificate Manager), kết nối mã hóa tới RDS (bật cờ rds.force_ssl), và cả encryption in-transit nội bộ giữa các node trong cluster (ví dụ giữa các broker Kafka, giữa app và ElastiCache Redis).

Tình huống thực tế

Tình huống 1 — Sàn thương mại điện tử và yêu cầu PCI-DSS

Một sàn TMĐT quy mô trung bình tại TP.HCM, tạm gọi là ShopViet, xử lý khoảng 40.000 đơn/ngày và lưu thông tin thẻ được token hóa. Khi làm audit PCI-DSS để tích hợp cổng thanh toán, auditor phát hiện hai lỗ hổng: (1) database RDS PostgreSQL lưu dữ liệu khách hàng nhưng không bật encryption at-rest, và (2) kết nối giữa backend và RDS đang dùng plaintext trong VPC vì "đằng nào cũng là mạng nội bộ".

Đội kỹ thuật xử lý như sau. Với at-rest: vì không thể bật mã hóa trực tiếp lên RDS đang chạy, họ tạo một snapshot, dùng thao tác copy-snapshot với tùy chọn mã hóa bằng customer managed key, rồi restore ra instance mới trong cửa sổ bảo trì ban đêm — downtime khoảng 25 phút. Với in-transit: họ bật tham số rds.force_ssl=1 và cập nhật connection string của ứng dụng để dùng sslmode=verify-full kèm CA certificate của AWS.

Bài học rút ra: "Mạng nội bộ nên an toàn" là một giả định nguy hiểm — mô hình zero-trust đòi hỏi mã hóa ngay cả bên trong VPC, vì một EC2 bị chiếm quyền có thể sniff traffic nội bộ. Và hãy bật encryption ngay từ ngày đầu tạo RDS, vì bật sau tốn công gấp nhiều lần.

Tình huống 2 — Fintech và bài toán kiểm soát khóa

Một công ty fintech cho vay tiêu dùng, tạm gọi CreditNow, muốn dùng AWS managed key cho nhanh. Nhưng bộ phận tuân thủ yêu cầu: phải chứng minh được ai đã truy cập dữ liệu KYC (Know Your Customer) và khi nào, đồng thời phải có khả năng "khóa cứng" toàn bộ dữ liệu ngay lập tức nếu phát hiện xâm nhập.

AWS managed key không đáp ứng được, vì bạn không kiểm soát key policy và không thấy chi tiết mọi lượt Decrypt. Họ chuyển sang customer managed key trong KMS, viết key policy chỉ cho phép đúng role của service KYC được gọi kms:Decrypt, và bật CloudTrail để log mọi lượt gọi KMS. Nhờ đó, khi mô phỏng sự cố, họ chỉ cần vô hiệu hóa (disable) KMS key — ngay lập tức toàn bộ S3 object, EBS volume, RDS phụ thuộc khóa đó trở nên không giải mã được, tạo thành một "kill switch" tức thời.

Bài học rút ra: Ai kiểm soát khóa, người đó kiểm soát dữ liệu. Với dữ liệu tài chính và cá nhân nhạy cảm, customer managed key không phải là chi phí thừa mà là công cụ vận hành và ứng phó sự cố. Chi phí vài USD/tháng cho khóa là không đáng kể so với giá trị của khả năng audit và kill switch.

Tình huống 3 — Startup và cái bẫy "TLS ở edge nhưng plaintext ở trong"

Một startup SaaS về quản lý bán hàng đặt CloudFront trước ứng dụng, cấu hình HTTPS đẹp đẽ ở edge với chứng chỉ ACM. Người dùng nhìn thấy ổ khóa xanh, ai cũng yên tâm. Nhưng khi rà soát kiến trúc, họ phát hiện: từ CloudFront về origin (ALB) đang dùng HTTP, và từ ALB tới các EC2 backend cũng là HTTP. Nghĩa là dữ liệu chỉ được mã hóa ở đoạn từ trình duyệt tới CloudFront, còn phần lớn hành trình bên trong AWS lại là plaintext.

Họ khắc phục bằng cách đặt Origin Protocol Policy của CloudFront thành "HTTPS Only", gắn chứng chỉ lên ALB, và bật HTTPS cho target group tới backend. Chi phí thêm gần như bằng không vì ACM miễn phí, chỉ tốn chút CPU cho việc mã hóa.

Bài học rút ra: "Có HTTPS" không đồng nghĩa với "mã hóa end-to-end". Hãy vẽ ra sơ đồ luồng dữ liệu và kiểm tra từng chặng (hop) một; một mắt xích plaintext làm hỏng cả chuỗi.

Hướng dẫn từng bước

Dưới đây là quy trình thực tế để đảm bảo encryption at-rest và in-transit cho một workload điển hình trên AWS.

Bước 1 — Kiểm kê dữ liệu và phân loại. Liệt kê mọi nơi lưu dữ liệu (S3, EBS, RDS, DynamoDB, backup) và mọi luồng mạng. Đánh dấu dữ liệu nào nhạy cảm (PII, tài chính, KYC) — đây là nơi bắt buộc dùng customer managed key.

Bước 2 — Tạo customer managed key trong KMS. Vào KMS, tạo một symmetric key, đặt key policy tối thiểu (chỉ role cần thiết được Encrypt/Decrypt/GenerateDataKey), và bật automatic key rotation (AWS sẽ tự xoay hằng năm).

Bước 3 — Bật encryption at-rest. Với S3: đặt bucket policy từ chối upload không mã hóa và bật default encryption SSE-KMS. Với EBS: bật "encryption by default" cấp region. Với RDS mới: tick encryption và chọn KMS key lúc tạo. Với RDS đang chạy chưa mã hóa: snapshot → copy có mã hóa → restore.

Bước 4 — Bật encryption in-transit. Cấp chứng chỉ qua ACM, gắn lên CloudFront/ALB, ép redirect HTTP sang HTTPS, đặt policy tối thiểu TLS 1.2. Bật SSL bắt buộc cho RDS (rds.force_ssl) và cho ElastiCache (transit-encryption-enabled).

Bước 5 — Kiểm chứng từng chặng. Dùng openssl s_client -connect ten-mien:443 để xem phiên bản TLS và chứng chỉ. Kiểm tra origin của CloudFront có phải HTTPS Only. Chạy aws s3api get-bucket-encryption để xác nhận bucket đã bật mã hóa.

Bước 6 — Bật audit. Bật CloudTrail để log mọi lượt gọi KMS, đặt cảnh báo khi có kms:Decrypt bất thường về tần suất hoặc nguồn gọi.

Lỗi thường gặp & mẹo

  • Nhầm "đã bật mã hóa" với "an toàn". Nếu ai cũng có quyền gọi KMS để giải mã, thì mã hóa gần như vô nghĩa. Mã hóa chỉ mạnh khi quyền dùng khóa được siết chặt bằng IAM và key policy.
  • Quên mã hóa backup và snapshot. Rất nhiều đội mã hóa database production nhưng để lộ snapshot/backup ở dạng plaintext. Kẻ tấn công luôn nhắm vào backup vì đó là "bản sao đầy đủ, ít ai canh gác".
  • Chỉ mã hóa ở edge. Như tình huống 3 — hãy đảm bảo mọi hop nội bộ cũng dùng TLS nếu dữ liệu nhạy cảm.
  • Dùng TLS phiên bản cũ. TLS 1.0/1.1 đã bị coi là không an toàn. Ép tối thiểu TLS 1.2.
  • Xóa/vô hiệu KMS key mà không kiểm tra phụ thuộc. Vô hiệu một khóa đang được S3/EBS/RDS dùng sẽ khiến dữ liệu không đọc được — hữu ích khi làm kill switch có chủ đích, nhưng thảm họa nếu làm nhầm. Luôn kiểm tra các resource phụ thuộc trước.
  • Mẹo — dùng key policy + IAM condition. Bạn có thể thêm điều kiện như kms:ViaService để khóa chỉ được dùng thông qua đúng dịch vụ (ví dụ chỉ S3 mới được dùng), chặn việc lạm dụng khóa qua đường khác.
  • Mẹo — bật rotation ngay từ đầu. Bật automatic rotation cho customer managed key ngay khi tạo; nó minh bạch với ứng dụng và giúp bạn qua audit dễ dàng.
  • Mẹo — dùng bucket policy để cưỡng chế. Với S3, một bucket policy Deny khi header x-amz-server-side-encryption vắng mặt sẽ đảm bảo không object nào lọt vào ở dạng plaintext.

Bài tập thực hành

  • Thiết lập S3 mã hóa cưỡng chế. Tạo một customer managed key trong KMS, tạo một S3 bucket, cấu hình default encryption SSE-KMS, và viết bucket policy từ chối mọi upload không mã hóa. Thử upload một file không kèm header mã hóa và xác nhận nó bị chặn.
  • Mã hóa một RDS đang chạy (mô phỏng). Với một RDS test chưa mã hóa: tạo snapshot, copy-snapshot có bật encryption, restore ra instance mới. Ghi lại thời gian downtime ước tính và viết một runbook ngắn cho thao tác này.
  • Kiểm chứng in-transit end-to-end. Với một trang web đặt sau CloudFront + ALB, dùng openssl s_client để xác nhận phiên bản TLS ở edge, rồi kiểm tra Origin Protocol Policy và giao thức tới backend. Vẽ sơ đồ luồng và đánh dấu chặng nào đã mã hóa, chặng nào chưa.
  • Thiết kế kill switch. Viết một đoạn mô tả (không cần triển khai thật): nếu phát hiện xâm nhập, làm sao vô hiệu hóa một KMS key để "khóa cứng" toàn bộ dữ liệu, những dịch vụ nào sẽ bị ảnh hưởng, và cần làm gì để khôi phục.

Tóm tắt

Encryption là lớp phòng thủ cuối cùng, hoạt động ngay cả khi mọi lớp khác đã sụp đổ. Chúng ta đã đi qua hai trạng thái quan trọng nhất: at-rest (dữ liệu nằm yên trên storage) và in-transit (dữ liệu di chuyển trên mạng). Với at-rest, cơ chế cốt lõi là envelope encryption: dữ liệu được mã hóa bằng DEK, DEK được mã hóa bằng KMS key — nhờ đó việc xoay khóa và kiểm soát truy cập trở nên khả thi ở quy mô lớn. Hầu hết dịch vụ AWS (S3, EBS, RDS, DynamoDB) đều hỗ trợ bật mã hóa dễ dàng, với lựa chọn giữa AWS managed key (nhanh, miễn phí) và customer managed key (kiểm soát, audit, kill switch).

Với in-transit, TLS 1.2 trở lên là tiêu chuẩn, và bài học lớn nhất là phải mã hóa từng chặng chứ không chỉ ở edge. Ba tình huống thực tế — ShopViet, CreditNow, và startup SaaS — cho thấy các sai lầm phổ biến: bỏ qua mã hóa nội bộ VPC, dùng khóa không kiểm soát được, và ngộ nhận "có HTTPS là đủ". Nguyên tắc vàng để ghi nhớ: ai kiểm soát khóa, người đó kiểm soát dữ liệu — vì vậy hãy đầu tư vào quản lý khóa (KMS + IAM) nghiêm túc như đầu tư vào chính việc mã hóa.

Học xong bài này rồi? Tạo tài khoản miễn phí để lưu lại — lần sau vào là biết ngay đang dở ở đâu, và học hết khóa thì có chứng chỉ. Lưu tiến độ của tôi