AWS KMS: Nên Dùng AWS Managed Key hay Customer Managed Key để Mã Hóa S3?

Bạn vừa được yêu cầu bật mã hóa cho S3 bucket chứa dữ liệu nhạy cảm. Console hiện ra ba lựa chọn: SSE-S3, SSE-KMS với AWS Managed Key, SSE-KMS với Customer Managed Key. Câu hỏi thực tế không phải là 'mã hóa có cần thiết không' mà là 'chọn loại key nào, và cái đó sẽ tốn bao nhiêu tiền mỗi tháng khi traffic tăng lên.'

TL;DR — AWS KMS Key Types cho S3

Tiêu chí AWS Managed Key (aws/s3) Customer Managed Key (CMK)
Ai quản lý key? AWS tự động quản lý Bạn tự tạo và quản lý
Phí lưu trữ key Miễn phí ~$1/tháng/key
Phí API call Miễn phí (không tính phí API) $0.03 / 10,000 requests
Key rotation Tự động hàng năm, không tắt được Tùy chọn, có thể bật/tắt
Key policy tùy chỉnh Không
Cross-account access Không hỗ trợ Có hỗ trợ
CloudTrail audit Có (limited) Có (đầy đủ)
Phù hợp cho Workload đơn giản, chi phí tối thiểu Compliance, multi-account, audit nghiêm ngặt

AWS KMS Hoạt Động Như Thế Nào với S3

Trước khi quyết định loại key, cần hiểu rõ cơ chế mã hóa thực sự xảy ra ở đâu. S3 không dùng KMS key trực tiếp để mã hóa từng byte dữ liệu — đó là envelope encryption.

sequenceDiagram participant Client participant S3 participant KMS Client->>S3: PUT object request S3->>KMS: GenerateDataKey (using KMS key) KMS-->>S3: Plaintext DEK + Encrypted DEK S3->>S3: Encrypt object with Plaintext DEK S3->>S3: Delete Plaintext DEK from memory S3->>S3: Store object + Encrypted DEK S3-->>Client: 200 OK Note over Client,KMS: GET flow Client->>S3: GET object request S3->>KMS: Decrypt (send Encrypted DEK) KMS-->>S3: Plaintext DEK S3->>S3: Decrypt object S3-->>Client: Plaintext object data
  1. GenerateDataKey: Khi S3 nhận PUT request, nó gọi KMS để tạo một data key mới (DEK). KMS trả về hai bản: plaintext DEK và encrypted DEK.
  2. Encrypt object: S3 dùng plaintext DEK để mã hóa object bằng AES-256. Sau đó xóa plaintext DEK khỏi memory.
  3. Store encrypted DEK: Encrypted DEK được lưu kèm với object metadata trong S3.
  4. Decrypt flow: Khi GET request đến, S3 gửi encrypted DEK lên KMS để giải mã, nhận lại plaintext DEK, dùng nó để giải mã object, rồi trả về data cho client.

Mỗi PUT và GET đều tạo ra ít nhất một KMS API call. Đây là lý do tại sao chi phí KMS tăng tuyến tính theo số lượng object operations — không phải theo dung lượng dữ liệu.

Envelope encryption giống như khóa két sắt bằng chìa khóa phụ, rồi cất chìa khóa phụ đó vào két sắt chính. Bạn chỉ cần bảo vệ két sắt chính (KMS key) — còn két sắt phụ (DEK) có thể nằm ngay cạnh dữ liệu mà không lo bị lộ.

AWS Managed Key — Miễn Phí Nhưng Có Giới Hạn

AWS Managed Key cho S3 có alias là aws/s3. AWS tạo key này tự động khi bạn bật SSE-KMS lần đầu, tự động rotate hàng năm, và bạn không trả bất kỳ khoản phí nào — không phí lưu trữ key, không phí API call.

Điều nhiều người không biết: bạn không thể xem hay chỉnh sửa key policy của AWS Managed Key. Điều này có nghĩa là bạn không thể giới hạn service nào được phép dùng key, không thể cấp cross-account access, và không thể tích hợp với các điều kiện IAM phức tạp. Nếu một IAM principal có quyền kms:Decrypts3:GetObject, họ có thể đọc object — bạn không có thêm lớp kiểm soát nào ở tầng key.

# Kiểm tra AWS Managed Keys hiện có trong account
aws kms list-keys \
  --region us-east-1

# Xem chi tiết một key cụ thể (thay KEY_ID bằng ID thực)
aws kms describe-key \
  --key-id alias/aws/s3 \
  --region us-east-1

Output của lệnh trên sẽ cho thấy KeyManager: AWS — đây là dấu hiệu phân biệt với CMK có KeyManager: CUSTOMER.

Customer Managed Key — Kiểm Soát Đầy Đủ, Có Chi Phí

CMK là key bạn tự tạo trong KMS. Bạn viết key policy, quyết định ai được dùng key, bật hay tắt key rotation, và có thể disable hoặc schedule deletion cho key. Đây là lựa chọn bắt buộc khi có yêu cầu compliance như PCI-DSS, HIPAA, hoặc khi cần audit trail chi tiết từng API call.

Tạo CMK cho S3

# Tạo symmetric CMK
aws kms create-key \
  --description "CMK for S3 bucket production-data" \
  --key-usage ENCRYPT_DECRYPT \
  --region us-east-1

# Tạo alias dễ nhớ
aws kms create-alias \
  --alias-name alias/s3-production-data \
  --target-key-id <KEY_ID_FROM_ABOVE> \
  --region us-east-1

# Bật automatic key rotation
aws kms enable-key-rotation \
  --key-id alias/s3-production-data \
  --region us-east-1

Key Policy tối thiểu cho S3 CMK

🔽 Click để xem Key Policy JSON
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Enable IAM User Permissions",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::123456789012:root"
      },
      "Action": "kms:*",
      "Resource": "*"
    },
    {
      "Sid": "Allow S3 service to use the key",
      "Effect": "Allow",
      "Principal": {
        "Service": "s3.amazonaws.com"
      },
      "Action": [
        "kms:GenerateDataKey",
        "kms:Decrypt"
      ],
      "Resource": "*"
    },
    {
      "Sid": "Allow specific IAM role to decrypt",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::123456789012:role/DataAccessRole"
      },
      "Action": [
        "kms:Decrypt",
        "kms:GenerateDataKey"
      ],
      "Resource": "*"
    }
  ]
}

Key policy là tầng kiểm soát đầu tiên — ngay cả khi IAM policy cho phép, nếu key policy không grant quyền, KMS sẽ từ chối. Đây là điểm khác biệt quan trọng so với AWS Managed Key.

Cấu Hình S3 Bucket Encryption với KMS

graph TD A["Chọn loại KMS Key"] --> B{"Yêu cầu?"}; B -->|"Đơn giản, không compliance"| C["AWS Managed Key
(alias: aws/s3)"]; B -->|"Compliance / Cross-account"| D["Customer Managed Key"]; C --> E["put-bucket-encryption
SSEAlgorithm: aws:kms"]; D --> F["Tạo CMK + Key Policy"]; F --> G["put-bucket-encryption
KMSMasterKeyID: CMK ARN"]; E --> H["BucketKeyEnabled: true"]; G --> H; H --> I["Encryption Active"];

Bật SSE-KMS với AWS Managed Key

aws s3api put-bucket-encryption \
  --bucket my-production-bucket \
  --server-side-encryption-configuration '{
    "Rules": [{
      "ApplyServerSideEncryptionByDefault": {
        "SSEAlgorithm": "aws:kms"
      },
      "BucketKeyEnabled": true
    }]
  }'

Bật SSE-KMS với Customer Managed Key

aws s3api put-bucket-encryption \
  --bucket my-production-bucket \
  --server-side-encryption-configuration '{
    "Rules": [{
      "ApplyServerSideEncryptionByDefault": {
        "SSEAlgorithm": "aws:kms",
        "KMSMasterKeyID": "arn:aws:kms:us-east-1:123456789012:key/YOUR-KEY-ID"
      },
      "BucketKeyEnabled": true
    }]
  }'

Lưu ý tham số BucketKeyEnabled: true trong cả hai trường hợp. Đây là chi tiết quan trọng ảnh hưởng trực tiếp đến chi phí — phần tiếp theo sẽ giải thích tại sao.

Chi Phí KMS Thực Tế — S3 Bucket Key là Yếu Tố Quyết Định

Đây là phần mà nhiều engineer bị bất ngờ khi nhận hóa đơn AWS tháng đầu tiên sau khi bật KMS.

Mô hình chi phí CMK

Với Customer Managed Key, chi phí gồm hai phần:

  • Phí lưu trữ key: Khoảng $1/tháng cho mỗi CMK bạn tạo.
  • Phí API requests: Khoảng $0.03 cho mỗi 10,000 requests. Mỗi S3 PUT và GET đều tạo ra KMS API call.

Pricing và limits thay đổi theo thời gian — luôn kiểm tra trang AWS KMS Pricing chính thức.

AWS Managed Key không có phí API

Theo tài liệu giá chính thức của AWS KMS, AWS Managed Keys không phát sinh phí lưu trữ key và không phát sinh phí cho API calls. Đây là điểm khác biệt quan trọng so với CMK khi tính toán chi phí cho workload có lượng S3 operations lớn.

S3 Bucket Key — Tính năng giảm chi phí cho CMK

Khi BucketKeyEnabled: true, S3 tạo ra một bucket-level data key được cache tạm thời. Thay vì gọi KMS cho mỗi object operation, S3 dùng bucket key này để tạo DEK locally — chỉ gọi KMS định kỳ để refresh bucket key. Theo AWS documentation, tính năng này có thể giảm đáng kể số lượng KMS API calls từ S3.

graph LR subgraph Without_BucketKey ["Không có Bucket Key"] A1["PUT obj-1"] --> K1["KMS API call"] A2["PUT obj-2"] --> K2["KMS API call"] A3["GET obj-1"] --> K3["KMS API call"] A4["GET obj-2"] --> K4["KMS API call"] end subgraph With_BucketKey ["Có Bucket Key (BucketKeyEnabled: true)"] B1["PUT obj-1"] --> BK["Bucket Key
(cached)"] B2["PUT obj-2"] --> BK B3["GET obj-1"] --> BK B4["GET obj-2"] --> BK BK -->|"Periodic refresh only"| KMS_BK["KMS API call"] end

Bucket Key chỉ có tác dụng với CMK vì AWS Managed Key đã miễn phí API calls. Tuy nhiên, bật Bucket Key cho cả hai trường hợp là thực hành tốt — nó không gây hại và giúp giảm chi phí nếu sau này bạn migrate sang CMK.

Symptom → Misdiagnosis → Root Cause: Hóa Đơn KMS Tăng Đột Biến

Một tình huống thực tế: team bật SSE-KMS với CMK cho S3 bucket chứa thumbnail images. Cuối tháng, hóa đơn KMS tăng vài trăm đô so với dự kiến. Nhìn vào CloudWatch, số lượng KMS requests lên đến hàng triệu.

Misdiagnosis đầu tiên: Nghĩ rằng có process nào đó đang loop và đọc/ghi S3 liên tục. Team dành nửa ngày trace application logs.

Root cause thực sự: BucketKeyEnabled không được bật khi tạo bucket encryption configuration. Mỗi thumbnail GET request — và service này phục vụ hàng triệu requests/ngày — đều tạo ra một KMS Decrypt call riêng biệt.

# Kiểm tra trạng thái Bucket Key hiện tại
aws s3api get-bucket-encryption \
  --bucket my-production-bucket \
  --region us-east-1

Nếu output không có BucketKeyEnabled: true, đó là vấn đề. Fix bằng cách chạy lại lệnh put-bucket-encryption với BucketKeyEnabled: true như đã trình bày ở trên.

Sau khi bật Bucket Key, số KMS requests giảm mạnh. Đây là loại behavioral interaction giữa hai settings mà không đọc kỹ documentation sẽ không nhận ra — S3 bucket encryption config và KMS pricing model là hai tài liệu riêng biệt, nhưng chúng ảnh hưởng lẫn nhau trực tiếp.

Decision Guide — Chọn Loại Key Nào

graph TD Start(["Cần mã hóa S3 bucket"]) --> Q1{"Có yêu cầu
compliance không?"}; Q1 -->|"Không"| Q2{"Cần cross-account
access?"}; Q1 -->|"Có (PCI, HIPAA...)"| CMK["Dùng CMK"]; Q2 -->|"Không"| Q3{"Cần custom
key policy?"}; Q2 -->|"Có"| CMK; Q3 -->|"Không"| AMK["Dùng AWS Managed Key
(Miễn phí)"]; Q3 -->|"Có"| CMK; CMK --> BK1["Bật BucketKeyEnabled: true"]; AMK --> BK2["Bật BucketKeyEnabled: true"]; BK1 --> Done(["Hoàn tất"]); BK2 --> Done;

Nguyên tắc thực tế: nếu bạn không có yêu cầu compliance cụ thể, không cần cross-account access, và không cần custom key policy — AWS Managed Key là lựa chọn hợp lý với chi phí bằng không. CMK chỉ thực sự cần thiết khi bạn cần kiểm soát tầng key policy hoặc có audit requirement nghiêm ngặt.

IAM Permissions Cần Thiết

Khi dùng CMK, IAM principal cần quyền trên cả S3 lẫn KMS. Thiếu một trong hai sẽ gây lỗi AccessDenied — và error message không phải lúc nào cũng chỉ rõ tầng nào bị từ chối.

🔽 Click để xem IAM Policy cho S3 + KMS CMK access
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "S3BucketAccess",
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject"
      ],
      "Resource": "arn:aws:s3:::my-production-bucket/*"
    },
    {
      "Sid": "KMSCMKAccess",
      "Effect": "Allow",
      "Action": [
        "kms:Decrypt",
        "kms:GenerateDataKey"
      ],
      "Resource": "arn:aws:kms:us-east-1:123456789012:key/YOUR-KEY-ID"
    }
  ]
}

Với AWS Managed Key, IAM principal vẫn cần quyền KMS tương tự — nhưng resource có thể là "Resource": "*" vì bạn không biết ARN chính xác của AWS Managed Key trước khi nó được tạo.

Kiểm Tra và Monitoring KMS Usage

# Xem KMS API call metrics qua CloudTrail
aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=EventSource,AttributeValue=kms.amazonaws.com \
  --start-time 2024-01-01T00:00:00Z \
  --end-time 2024-01-02T00:00:00Z \
  --region us-east-1

# Liệt kê tất cả CMK trong region
aws kms list-keys \
  --region us-east-1

# Xem key rotation status của CMK
aws kms get-key-rotation-status \
  --key-id alias/s3-production-data \
  --region us-east-1

CloudTrail log đầy đủ KMS API calls chỉ có với CMK. Với AWS Managed Key, CloudTrail vẫn ghi nhưng mức độ chi tiết có thể khác nhau tùy context.

Wrap-up: Hiểu AWS KMS để Chọn Đúng Key cho S3

Quyết định giữa AWS Managed Key và Customer Managed Key khi mã hóa S3 không phải là câu hỏi kỹ thuật thuần túy — nó là câu hỏi về trade-off giữa chi phí, kiểm soát, và yêu cầu compliance. AWS Managed Key phù hợp cho phần lớn workload thông thường với chi phí bằng không. CMK cần thiết khi bạn cần kiểm soát key policy, cross-account access, hoặc audit trail chi tiết theo yêu cầu compliance.

Bất kể chọn loại key nào, luôn bật BucketKeyEnabled: true trong S3 encryption configuration — đặc biệt quan trọng với CMK để tránh chi phí KMS API không mong muốn.

Bước tiếp theo: Xem AWS KMS Developer GuideKMS Pricing page để cập nhật thông tin chi phí mới nhất trước khi triển khai production.

Glossary — Thuật Ngữ Chính

Thuật ngữ Giải thích
CMK (Customer Managed Key) KMS key do người dùng tạo và quản lý, có thể tùy chỉnh key policy và rotation schedule.
AWS Managed Key KMS key do AWS tạo và quản lý tự động cho từng service, không tính phí lưu trữ và API.
Envelope Encryption Kỹ thuật mã hóa dữ liệu bằng DEK, sau đó mã hóa DEK bằng KMS key — tránh truyền dữ liệu lớn qua KMS.
DEK (Data Encryption Key) Key tạm thời dùng để mã hóa dữ liệu thực tế, được tạo bởi KMS và lưu dưới dạng encrypted cùng object.
S3 Bucket Key Tính năng S3 cache bucket-level key để giảm số lượng KMS API calls, từ đó giảm chi phí với CMK.

Related Posts

Nhận xét