Security (Bảo mật)Security
Part of the Cloud knowledge base — AWS deep dive. Complements DevOps Roadmap.
Tổng quan
Bảo mật trên AWS không phải một dịch vụ mà là một tư thế nhiều lớp: identity (IAM, có trang riêng), bảo vệ dữ liệu (KMS, encryption khắp nơi), quản lý secret (Secrets Manager, Parameter Store), phát hiện mối đe dọa (GuardDuty, Security Hub, Inspector, Macie, Detective), phòng thủ mạng và ứng dụng (WAF, Shield, Security Groups, PrivateLink), và certificate (ACM). Nguyên tắc thống nhất là shared responsibility model: AWS bảo vệ phần cloud (phần cứng, hypervisor, nội bộ dịch vụ được quản lý), và bạn bảo vệ những gì bạn đặt vào trong cloud (dữ liệu, cấu hình, identity, và mức độ phơi bày mạng). Gần như mọi vụ vi phạm trên AWS là misconfiguration phía khách hàng, không phải lỗi của AWS.
Với một DevOps engineer, mục tiêu thực tế là phòng thủ theo chiều sâu với các phần nhàm chán được tự động hóa. Encrypt mọi thứ khi lưu trữ và khi truyền tải theo mặc định. Đừng bao giờ để secret chạm vào source control. Giả định rằng phát hiện là một pipeline, không phải một người ngồi canh màn hình — các finding từ GuardDuty chảy vào Security Hub, kích hoạt automation EventBridge, và chỉ page một người khi thực sự cần một quyết định của con người. Và coi cấu hình bảo mật như code (Config rules, guardrail IaC) để một tư thế đúng là mặc định và drift được bắt tự động.
Trade-off chính là bảo mật vs. ma sát. Các hệ thống bị khóa hoàn hảo mà chặn developer sẽ bị lách qua, và chính các cách lách đó là lỗ hổng. Kỹ năng là làm cho con đường an toàn trở thành con đường dễ: encryption KMS “tự động xảy ra” trên một bucket, secret rotate mà không ai để ý, WAF rule chặn tấn công mà không phá traffic hợp lệ. Trang này bao quát các building block của AWS và các thực hành làm cho secure-by-default trở thành mặc định ít ma sát.
Kiến thức nền tảng
Shared responsibility model, cụ thể
| Lớp | Ai bảo vệ |
|---|---|
| Data center vật lý, phần cứng | AWS |
| Hypervisor, host OS, nội bộ dịch vụ được quản lý | AWS |
| Guest OS, patching (trên EC2) | Bạn |
| Cấu hình mạng (SG/NACL/routes), firewall | Bạn |
| IAM, identity, key policy | Bạn |
| Code ứng dụng, phân loại dữ liệu | Bạn |
| Lựa chọn encryption (at rest / in transit) | Bạn (AWS cung cấp công cụ) |
Ranh giới phân chia dịch chuyển khi bạn leo lên bậc thang dịch vụ được quản lý: với Lambda hay Fargate, AWS patch OS; với EC2, bạn làm. Biết chính xác ranh giới nằm ở đâu cho mỗi dịch vụ bạn dùng là kỹ năng bảo mật đầu tiên.
Encryption: at rest vs. in transit
- At rest — dữ liệu trên đĩa (EBS, S3, RDS, DynamoDB, EFS) được encrypt với key quản lý bởi KMS. Hầu hết dịch vụ cho encryption một-checkbox; lựa chọn là key nào (AWS-owned, AWS-managed, hoặc CMK của bạn).
- In transit — dữ liệu trên đường truyền được encrypt bằng TLS. Terminate TLS tại load balancer / API Gateway / CloudFront với một certificate ACM, và ưu tiên TLS cho cả các hop nội bộ (encryption in-transit của RDS/Redis, VPC endpoint).
Mặc định hiện đại là encrypt mọi thứ, mọi nơi, vì chi phí biên gần bằng không và mặt trái của một snapshot chưa encrypt hoặc một endpoint HTTP là thảm họa.
KMS trong một bức tranh
AWS Key Management Service (KMS) là dịch vụ được quản lý để tạo và kiểm soát khóa mã hóa, được hậu thuẫn bởi các hardware security module (HSM) đạt chuẩn FIPS 140. Khóa KMS không bao giờ rời HSM ở dạng chưa mã hóa. Bạn hiếm khi encrypt dữ liệu lớn bằng KMS trực tiếp (có giới hạn 4 KB); thay vào đó KMS cho phép envelope encryption.
Khái niệm chính
Các loại khóa KMS
| Loại khóa | Ai tạo/kiểm soát policy | Rotation | Chi phí | Dùng khi |
|---|---|---|---|---|
| AWS-owned | AWS, dùng chung nhiều account, vô hình với bạn | AWS | Miễn phí | Bạn chỉ cần “được encrypt” và không quan tâm key |
AWS-managed (aws/s3, aws/rds) | AWS, per-service, per-account | Tự động, hàng năm | Miễn phí (tính phí usage) | Encryption dịch vụ mặc định, không cần policy tùy chỉnh |
| Customer-managed (CMK) | Bạn — toàn quyền kiểm soát key policy | Tùy chọn tự động (hàng năm) hoặc on-demand | ~$1/tháng + usage | Bạn cần kiểm soát key-policy, chia sẻ cross-account, rotation tùy chỉnh, hoặc audit chi tiết |
Chọn CMK bất cứ khi nào bạn cần (a) viết một key policy kiểm soát ai được dùng/quản trị key, (b) chia sẻ encryption qua các account, (c) áp đặt nhịp rotation của riêng bạn, hoặc (d) có CloudTrail visibility per-key cho compliance. Ngược lại, AWS-managed key miễn phí và ổn.
Envelope encryption
KMS không encrypt gigabyte dữ liệu của bạn trực tiếp. Thay vào đó:
- Ứng dụng của bạn (hoặc dịch vụ AWS) yêu cầu KMS một data key qua
GenerateDataKey. - KMS trả data key hai lần: một ở dạng plaintext (dùng ngay để encrypt dữ liệu cục bộ bằng AES-256) và một đã được encrypt dưới CMK (khóa “bọc”).
- Bạn lưu data key đã encrypt cạnh ciphertext và loại bỏ khóa plaintext khỏi memory.
- Để decrypt, bạn gửi khóa bọc lại cho KMS
Decrypt, nhận lại data key plaintext, decrypt dữ liệu, và loại bỏ khóa lần nữa.
Cách này hiệu quả (crypto khối lượng lớn là AES cục bộ, chỉ khóa nhỏ round-trip tới KMS), có thể audit (mỗi Decrypt là một event CloudTrail), và có thể thu hồi (disable CMK và mọi dữ liệu encrypt dưới nó lập tức không truy cập được). Mỗi checkbox “encrypt với KMS” ở cấp dịch vụ đang làm chính xác điều này bên dưới.
KMS key policy
Khác với IAM policy (gắn vào một principal), một key policy là resource policy gắn vào chính key, và nó là access control chính cho một CMK — một IAM policy đơn thuần không thể cấp quyền trừ khi key policy cho phép. Một key policy tối thiểu, đúng đắn tách biệt administrator (quản lý key, không được dùng nó để decrypt) khỏi user (encrypt/decrypt, không được xóa key).
Ví dụ thực tế — key policy CMK least-privilege:
{
"Version": "2012-10-17",
"Id": "checkout-key-policy",
"Statement": [
{
"Sid": "RootAccountFullControl",
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::111122223333:root" },
"Action": "kms:*",
"Resource": "*"
},
{
"Sid": "KeyAdmins",
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::111122223333:role/kms-admin" },
"Action": [
"kms:Create*", "kms:Describe*", "kms:Enable*", "kms:List*",
"kms:Put*", "kms:Update*", "kms:Revoke*", "kms:Disable*",
"kms:Get*", "kms:Delete*", "kms:ScheduleKeyDeletion", "kms:CancelKeyDeletion"
],
"Resource": "*"
},
{
"Sid": "KeyUsers",
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::111122223333:role/checkout-service" },
"Action": [ "kms:Encrypt", "kms:Decrypt", "kms:ReEncrypt*", "kms:GenerateDataKey*", "kms:DescribeKey" ],
"Resource": "*",
"Condition": {
"StringEquals": { "kms:ViaService": "secretsmanager.us-east-1.amazonaws.com" }
}
}
]
}
Sự tách biệt quan trọng: role kms-admin có thể rotate và disable key nhưng không decrypt được dữ liệu, và role checkout-service có thể decrypt nhưng không xóa được key — nên không một principal bị xâm nhập nào là thảm họa toàn diện. Điều kiện kms:ViaService còn hạn chế service role chỉ dùng key qua Secrets Manager, không trực tiếp. Giữ statement root để bạn không bao giờ tự khóa mình ra ngoài (mất admin cuối cùng của một CMK mà không có root access là không thể khôi phục).
Secrets Manager vs. SSM Parameter Store
Cả hai lưu cấu hình và secret được encrypt với KMS, nhưng nhắm đến nhu cầu khác nhau.
| Đặc điểm | Secrets Manager | SSM Parameter Store |
|---|---|---|
| Mục đích chính | Secret có vòng đời | Config + secret (SecureString) |
| Rotation tự động | Có, tích hợp sẵn (Lambda-driven, native cho RDS/Redshift/DocumentDB) | Không (tự làm) |
| Replication cross-account / cross-region | Có, native | Chỉ Advanced tier, giới hạn |
| Chi phí | ~$0.40/secret/tháng + API call | Standard tier miễn phí; Advanced tier tính phí |
| Giới hạn kích thước | 64 KB | 4 KB (standard), 8 KB (advanced) |
| Versioning / staging label | Có (AWSCURRENT/AWSPREVIOUS) | Có (lịch sử version) |
| Tốt nhất cho | Credential DB, API key cần rotate | Config app, feature flag, secret không rotate với ngân sách eo hẹp |
Quy tắc ngón tay cái: nếu nó cần rotation tự động (credential database, API key bên thứ ba) hoặc chia sẻ cross-account, dùng Secrets Manager. Nếu là config thuần hoặc một secret tĩnh và bạn muốn zero chi phí, dùng Parameter Store SecureString. Nhiều đội dùng cả hai: Parameter Store cho phần lớn config, Secrets Manager cho một nhúm credential cần rotate.
Ví dụ thực tế — lấy secret trong code (Python, boto3):
import boto3, json
def get_db_credentials():
client = boto3.client("secretsmanager")
resp = client.get_secret_value(SecretId="prod/checkout/db")
secret = json.loads(resp["SecretString"])
return secret["username"], secret["password"]
# Từ CLI (ví dụ trong một bước CI):
# aws secretsmanager get-secret-value \
# --secret-id prod/checkout/db \
# --query SecretString --output text | jq -r .password
Thuộc tính then chốt: credential không bao giờ nằm trong code, image, hay file env commit vào git — app lấy nó lúc runtime bằng IAM role của mình, và rotation xảy ra trong suốt vì app luôn đọc AWSCURRENT. Cache kết quả trong memory để tránh dội API, và để rotation Lambda hoán đổi giá trị sau label.
Bộ dịch vụ phát hiện mối đe dọa
AWS cung cấp một tập dịch vụ phát hiện bổ trợ lẫn nhau; hãy nghĩ về chúng như các cảm biến cấp dữ liệu cho một bảng điều khiển trung tâm.
| Dịch vụ | Phát hiện | Nguồn dữ liệu | Ẩn dụ |
|---|---|---|---|
| GuardDuty | Mối đe dọa & bất thường (đào crypto, rò rỉ credential, IP độc hại, lời gọi API bất thường) | CloudTrail, VPC Flow Logs, DNS logs, EKS audit logs, S3, malware scan | IDS thông minh |
| Inspector | Lỗ hổng phần mềm & phơi bày mạng ngoài ý muốn (CVE trong EC2, ECR image, Lambda) | Quét agentless/agent | Vulnerability scanner |
| Macie | Dữ liệu nhạy cảm (PII, credential) trong S3 | Phân loại nội dung bằng ML | Data-loss-prevention scanner |
| Detective | Nguyên nhân gốc của một finding — trực quan hóa và correlate hoạt động theo thời gian | Đồ thị GuardDuty + logs | Điều tra viên forensic |
| Security Hub | Không tự phát hiện gì — tổng hợp finding từ tất cả cái trên + kiểm tra compliance (CIS, PCI, FSBP) | Mọi dịch vụ bảo mật | Dashboard trung tâm / SIEM-lite |
Luồng công việc dự kiến: GuardDuty/Inspector/Macie tạo finding → Security Hub tổng hợp và chấm điểm chúng và chạy các standard compliance → EventBridge route các finding nghiêm trọng đến phản ứng tự động hoặc một ticket → Detective giúp bạn điều tra những cái cần con người. Bật chúng khắp org qua một tài khoản delegated administrator để một member account mới được bảo vệ từ ngày đầu. Riêng GuardDuty có tỷ lệ signal-to-noise cao và nên được coi là baseline mặc-định-bật.
WAF & Shield
- AWS WAF — một web application firewall cho HTTP(S), gắn vào CloudFront, ALB, API Gateway, hoặc AppSync. Bạn soạn các rule thành một web ACL: managed rule group (do AWS/vendor cung cấp cho OWASP Top 10, bad bot, input xấu đã biết), rate-based rule (throttle một IP), và custom match rule (block/allow theo header, URI, geo, IP set). Nó phòng thủ SQLi, XSS, và flood tầng 7.
- AWS Shield Standard — miễn phí, bảo vệ tự động chống DDoS tầng 3/4 thông thường (SYN flood, reflection attack) cho mọi khách hàng AWS.
- AWS Shield Advanced — trả phí, thêm bảo vệ cho DDoS lớn/tinh vi, truy cập 24/7 Shield Response Team, cost-protection khi scale trong lúc tấn công, và tích hợp WAF chặt hơn. Đáng giá cho app internet-facing quan trọng về doanh thu.
ACM: certificate
AWS Certificate Manager (ACM) cấp phát, quản lý, và tự động gia hạn certificate TLS miễn phí, khi dùng với các dịch vụ tích hợp (CloudFront, ALB/NLB, API Gateway). Bạn request một cert public, chứng minh sở hữu domain (DNS validation là tốt nhất — một CNAME tự gia hạn), và gắn nó vào listener. ACM xử lý gia hạn để certificate không bao giờ hết hạn âm thầm — sự cố 2 giờ sáng kinh điển. Lưu ý cert cho CloudFront phải nằm ở us-east-1. Với cert private/nội bộ, ACM Private CA phát một cây certificate private. Cert public của ACM không thể export (private key ở lại trong AWS) — với TLS terminate ở EC2 hay on-prem bạn dùng ACM Private CA hoặc mang cert của riêng bạn.
Tóm tắt bảo mật mạng
Phân lớp từ vành đai vào trong (chi tiết đầy đủ ở trang Networking):
- Security Groups — firewall stateful, allow-only ở cấp instance/ENI. Traffic trả về được tự động cho phép. Tham chiếu SG khác làm source cho tiering sạch (web-SG được phép tới app-SG).
- Network ACLs — stateless, cấp subnet, có cả rule allow và deny. Đánh giá theo thứ tự. Hữu ích cho block subnet-wide thô (ví dụ deny một CIDR xấu) mà SG không thể diễn đạt.
- PrivateLink / VPC endpoints — tới các dịch vụ AWS (S3, DynamoDB, hoặc một dịch vụ partner/SaaS) qua đường mạng AWS private thay vì internet công cộng. Gateway endpoint (S3, DynamoDB) miễn phí; Interface endpoint (hầu hết dịch vụ khác) là ENI trong subnet của bạn, tính phí theo giờ + per-GB, và giữ traffic hoàn toàn khỏi internet — quan trọng cho compliance và cho private subnet không có NAT.
Kết hợp chúng: SG cho các allow-list thông thường, NACL cho guard subnet thô, và PrivateLink để loại bỏ phơi bày internet cho traffic service-to-service và service-to-AWS-API.
Best Practices
- Encrypt mọi thứ at rest theo mặc định, dùng CMK nơi cần kiểm soát. Bật default encryption trên S3, EBS, RDS, DynamoDB. Lý do: chi phí biên gần bằng không, và một snapshot hay bucket chưa encrypt là một vụ vi phạm lên trang nhất; CMK thêm audit per-key và thu hồi cho dữ liệu nhạy cảm.
- Áp đặt TLS in transit và terminate với ACM. Redirect HTTP→HTTPS, dùng cert ACM với DNS tự gia hạn, bật encryption in-transit cho RDS/Redis. Lý do: plaintext trên đường truyền dễ bị nghe lén, và ACM tự gia hạn loại bỏ sự cố certificate hết hạn kinh điển.
- Tách key administrator khỏi key user trong key policy. Lý do: một key admin không decrypt được và một app không xóa key được nghĩa là không một principal bị xâm nhập đơn lẻ nào là thảm họa toàn diện.
- Bật rotation khóa KMS và giữ statement root. Bật rotation hàng năm (hoặc on-demand); đừng bao giờ xóa root access khỏi một CMK. Lý do: rotation giới hạn blast radius của một key bị lộ; mất administrator cuối cùng của một CMK là không thể khôi phục.
- Đừng bao giờ lưu secret trong code, image, file env, hay Terraform state trong git. Lấy từ Secrets Manager / Parameter Store lúc runtime qua IAM role. Lý do: secret đã commit rò rỉ mãi mãi trong lịch sử git và là một vector vi phạm hàng đầu; lấy lúc runtime giữ chúng khỏi mọi artifact.
- Dùng rotation của Secrets Manager cho credential database và bên thứ ba. Lý do: credential tĩnh dài hạn là secret bị đánh cắp nhiều nhất; rotation tự động thu ngắn thời gian hữu dụng của bất kỳ vụ lộ nào xuống còn vài giờ.
- Ưu tiên Parameter Store SecureString cho config không rotate để tiết kiệm chi phí. Lý do: standard tier miễn phí; trả phí per-secret của Secrets Manager cho feature flag tĩnh là lãng phí — dành nó cho những thứ thực sự cần rotate.
- Bật GuardDuty khắp org với một delegated administrator. Lý do: nó signal cao, công sức thấp, và tự phủ các account mới; một account bị xâm nhập không có GuardDuty là một vụ vi phạm âm thầm chờ xảy ra.
- Tổng hợp finding trong Security Hub và tự động hóa phản ứng qua EventBridge. Lý do: con người không thể canh năm console phát hiện riêng lẻ; chấm điểm trung tâm cộng ngăn chặn tự động (cô lập SG, disable key) biến phát hiện thành phản ứng nhanh.
- Quét image và instance với Inspector; chặn khi có CVE nghiêm trọng trong CI. Lý do: container thừa hưởng mọi lỗ hổng trong base layer; gate deploy trên finding của Inspector ngăn image known-exploitable chạm production.
- Đặt WAF trước app internet-facing với AWS managed rule group + rate limit. Lý do: managed rule phủ OWASP Top 10 và bad bot với gần như không bảo trì; rate-based rule làm cùn credential-stuffing và flood tầng 7.
- Dùng PrivateLink/VPC endpoint cho traffic AWS API và dịch vụ nội bộ. Lý do: giữ traffic khỏi internet công cộng giảm bề mặt tấn công, thỏa mãn yêu cầu data-residency, và cho private subnet tới S3/DynamoDB mà không cần NAT gateway tốn kém.
- Tham chiếu security group làm source thay vì CIDR cho các tier nội bộ. Lý do: rule SG-to-SG vẫn đúng khi IP thay đổi và mã hóa ý định (“web tier được phép tới app tier”) thay vì các danh sách IP dễ vỡ.
- Bật Macie trên các bucket có thể chứa PII. Lý do: khám phá dữ liệu nhạy cảm tự động bắt PII rơi vào sai bucket trước khi nó thành một sự cố compliance, điều mà review thủ công không bao giờ scale được.
- Áp đặt guardrail encryption và phơi bày bằng AWS Config rule. Triển khai managed rule (
s3-bucket-server-side-encryption-enabled,encrypted-volumes,restricted-ssh) với auto-remediation. Lý do: phòng-ngừa-cộng-phát-hiện giữ tư thế đúng tự động thay vì dựa vào con người không bao giờ misconfigure. - Áp least privilege cho KMS qua
kms:ViaServicevà grant condition. Lý do: hạn chế một key chỉ dùng được qua đúng dịch vụ dự kiến (ví dụ Secrets Manager) ngăn một role bị xâm nhập decrypt dữ liệu qua các đường không lường trước.
Tài liệu tham khảo
- AWS Shared Responsibility Model
- AWS KMS Developer Guide
- KMS envelope encryption
- KMS key policies
- AWS Secrets Manager User Guide
- SSM Parameter Store
- Amazon GuardDuty User Guide
- AWS Security Hub User Guide
- Amazon Inspector User Guide
- Amazon Macie User Guide
- Amazon Detective User Guide
- AWS WAF Developer Guide
- AWS Shield Developer Guide
- AWS Certificate Manager User Guide
- AWS PrivateLink
- AWS Well-Architected — Security Pillar
Part of the Cloud knowledge base — AWS deep dive. Complements DevOps Roadmap.
Overview
Security on AWS is not one service but a layered posture: identity (IAM, covered in its own page), data protection (KMS, encryption everywhere), secrets management (Secrets Manager, Parameter Store), threat detection (GuardDuty, Security Hub, Inspector, Macie, Detective), network and application defense (WAF, Shield, Security Groups, PrivateLink), and certificates (ACM). The unifying principle is the shared responsibility model: AWS secures the cloud (hardware, hypervisor, managed-service internals), and you secure what you put in the cloud (your data, configurations, identities, and network exposure). Nearly every breach on AWS is a customer-side misconfiguration, not an AWS failure.
For a DevOps engineer the practical goal is defense in depth with the boring parts automated. Encrypt everything at rest and in transit by default. Never let a secret touch source control. Assume detection is a pipeline, not a person watching a screen — findings from GuardDuty flow into Security Hub, trigger EventBridge automation, and page someone only when a human decision is genuinely needed. And treat security configuration as code (Config rules, IaC guardrails) so that a correct posture is the default and drift is caught automatically.
The governing trade-off is security vs. friction. Perfectly locked-down systems that block developers get worked around, and the workarounds are the vulnerability. The craft is making the secure path the easy path: KMS encryption that “just happens” on a bucket, secrets that rotate without anyone noticing, WAF rules that block attacks without breaking legitimate traffic. This page covers the AWS building blocks and the practices that make secure-by-default the low-friction default.
Fundamentals
The shared responsibility model, concretely
| Layer | Who secures it |
|---|---|
| Physical data centers, hardware | AWS |
| Hypervisor, host OS, managed-service internals | AWS |
| Guest OS, patching (on EC2) | You |
| Network config (SG/NACL/routes), firewall | You |
| IAM, identities, key policies | You |
| Application code, data classification | You |
| Encryption choices (at rest / in transit) | You (AWS provides the tools) |
The dividing line moves as you go up the managed-service ladder: with Lambda or Fargate, AWS patches the OS; with EC2, you do. Knowing exactly where the line sits for each service you use is the first security skill.
Encryption: at rest vs. in transit
- At rest — data on disk (EBS, S3, RDS, DynamoDB, EFS) encrypted with keys managed by KMS. Most services offer one-checkbox encryption; the choice is which key (AWS-owned, AWS-managed, or your customer-managed CMK).
- In transit — data on the wire encrypted with TLS. Terminate TLS at the load balancer / API Gateway / CloudFront with an ACM certificate, and prefer TLS for internal hops too (RDS/Redis in-transit encryption, VPC endpoints).
The modern default is encrypt everything, everywhere, because the marginal cost is near zero and the downside of an unencrypted snapshot or an HTTP endpoint is catastrophic.
KMS in one picture
AWS Key Management Service (KMS) is a managed service for creating and controlling encryption keys, backed by FIPS 140-validated hardware security modules (HSMs). KMS keys never leave the HSM unencrypted. You rarely encrypt large data with KMS directly (there is a 4 KB limit); instead KMS enables envelope encryption.
Key Concepts
KMS key types
| Key type | Who creates/controls policy | Rotation | Cost | Use when |
|---|---|---|---|---|
| AWS-owned | AWS, shared across accounts, invisible to you | AWS | Free | You just want “encrypted” and don’t care about the key |
AWS-managed (aws/s3, aws/rds) | AWS, per-service, per-account | Auto, yearly | Free (usage billed) | Default service encryption, no custom policy needed |
| Customer-managed (CMK) | You — full key policy control | Optional auto (yearly) or on-demand | ~$1/mo + usage | You need key-policy control, cross-account sharing, custom rotation, or audit granularity |
Choose a CMK whenever you need to (a) write a key policy controlling who can use/administer the key, (b) share encryption across accounts, (c) enforce your own rotation cadence, or (d) get per-key CloudTrail visibility for compliance. Otherwise AWS-managed keys are free and fine.
Envelope encryption
KMS does not encrypt your gigabytes directly. Instead:
- Your application (or the AWS service) asks KMS for a data key via
GenerateDataKey. - KMS returns the data key twice: once in plaintext (used immediately to encrypt your data locally with AES-256) and once encrypted under the CMK (the “wrapped” key).
- You store the encrypted data key alongside the ciphertext and discard the plaintext key from memory.
- To decrypt, you send the wrapped key back to KMS
Decrypt, get the plaintext data key, decrypt your data, and discard the key again.
This is efficient (bulk crypto is local AES, only the tiny key round-trips to KMS), auditable (every Decrypt is a CloudTrail event), and revocable (disable the CMK and all data encrypted under it becomes inaccessible instantly). Every service-level “encrypt with KMS” checkbox is doing exactly this under the hood.
KMS key policies
Unlike IAM policies (attached to a principal), a key policy is a resource policy attached to the key itself, and it is the primary access control for a CMK — an IAM policy alone cannot grant access unless the key policy allows it. A minimal, correct key policy separates administrators (manage the key, cannot use it to decrypt) from users (encrypt/decrypt, cannot delete the key).
Worked example — a least-privilege CMK policy:
{
"Version": "2012-10-17",
"Id": "checkout-key-policy",
"Statement": [
{
"Sid": "RootAccountFullControl",
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::111122223333:root" },
"Action": "kms:*",
"Resource": "*"
},
{
"Sid": "KeyAdmins",
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::111122223333:role/kms-admin" },
"Action": [
"kms:Create*", "kms:Describe*", "kms:Enable*", "kms:List*",
"kms:Put*", "kms:Update*", "kms:Revoke*", "kms:Disable*",
"kms:Get*", "kms:Delete*", "kms:ScheduleKeyDeletion", "kms:CancelKeyDeletion"
],
"Resource": "*"
},
{
"Sid": "KeyUsers",
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::111122223333:role/checkout-service" },
"Action": [ "kms:Encrypt", "kms:Decrypt", "kms:ReEncrypt*", "kms:GenerateDataKey*", "kms:DescribeKey" ],
"Resource": "*",
"Condition": {
"StringEquals": { "kms:ViaService": "secretsmanager.us-east-1.amazonaws.com" }
}
}
]
}
The separation matters: the kms-admin role can rotate and disable the key but cannot decrypt data, and the checkout-service role can decrypt but cannot delete the key — so neither a compromised admin nor a compromised app is fully catastrophic. The kms:ViaService condition further restricts the service role to use the key only through Secrets Manager, not directly. Keep the root statement so you never lock yourself out (losing the last admin of a CMK with no root access is unrecoverable).
Secrets Manager vs. SSM Parameter Store
Both store configuration and secrets encrypted with KMS, but they target different needs.
| Feature | Secrets Manager | SSM Parameter Store |
|---|---|---|
| Primary purpose | Secrets with lifecycle | Config + secrets (SecureString) |
| Automatic rotation | Yes, built-in (Lambda-driven, native for RDS/Redshift/DocumentDB) | No (DIY) |
| Cross-account / cross-region replication | Yes, native | Advanced tier only, limited |
| Cost | ~$0.40/secret/mo + API calls | Standard tier free; Advanced tier billed |
| Size limit | 64 KB | 4 KB (standard), 8 KB (advanced) |
| Versioning / staging labels | Yes (AWSCURRENT/AWSPREVIOUS) | Yes (version history) |
| Best for | DB creds, API keys needing rotation | App config, feature flags, non-rotating secrets on a budget |
Rule of thumb: if it needs automatic rotation (database credentials, third-party API keys) or cross-account sharing, use Secrets Manager. If it’s plain config or a static secret and you want zero cost, use Parameter Store SecureString. Many teams use both: Parameter Store for the bulk of config, Secrets Manager for the handful of rotating credentials.
Worked example — retrieving a secret in code (Python, boto3):
import boto3, json
def get_db_credentials():
client = boto3.client("secretsmanager")
resp = client.get_secret_value(SecretId="prod/checkout/db")
secret = json.loads(resp["SecretString"])
return secret["username"], secret["password"]
# From the CLI (e.g. in a CI step):
# aws secretsmanager get-secret-value \
# --secret-id prod/checkout/db \
# --query SecretString --output text | jq -r .password
The critical property: the credential is never in the code, the image, or an env file committed to git — the app fetches it at runtime using its IAM role, and rotation happens transparently because the app always reads AWSCURRENT. Cache the result in memory to avoid hammering the API, and let the rotation Lambda swap the value behind the label.
Threat detection stack
AWS provides a set of complementary detection services; think of them as sensors feeding a central pane.
| Service | Detects | Data source | Analogy |
|---|---|---|---|
| GuardDuty | Threats & anomalies (crypto-mining, credential exfiltration, malicious IPs, unusual API calls) | CloudTrail, VPC Flow Logs, DNS logs, EKS audit logs, S3, malware scan | Intelligent IDS |
| Inspector | Software vulnerabilities & unintended network exposure (CVEs in EC2, ECR images, Lambda) | Agentless/agent scanning | Vulnerability scanner |
| Macie | Sensitive data (PII, credentials) in S3 | ML content classification | Data-loss-prevention scanner |
| Detective | Root cause of a finding — visualizes and correlates activity over time | GuardDuty + logs graph | Forensic investigator |
| Security Hub | Nothing itself — aggregates findings from all the above + compliance checks (CIS, PCI, FSBP) | All security services | Central dashboard / SIEM-lite |
The intended workflow: GuardDuty/Inspector/Macie generate findings → Security Hub aggregates and scores them and runs compliance standards → EventBridge routes critical findings to automated response or a ticket → Detective helps you investigate the ones that need a human. Enable them org-wide via a delegated administrator account so a new member account is protected from day one. GuardDuty in particular is high signal-to-noise and should be considered a default-on baseline.
WAF & Shield
- AWS WAF — a web application firewall for HTTP(S), attached to CloudFront, ALB, API Gateway, or AppSync. You compose rules into a web ACL: managed rule groups (AWS/vendor-supplied for OWASP Top 10, bad bots, known-bad inputs), rate-based rules (throttle an IP), and custom match rules (block/allow by header, URI, geo, IP set). It defends against SQLi, XSS, and layer-7 floods.
- AWS Shield Standard — free, automatic protection against common layer-3/4 DDoS (SYN floods, reflection attacks) for all AWS customers.
- AWS Shield Advanced — paid, adds protection for larger/sophisticated DDoS, 24/7 access to the Shield Response Team, cost-protection for scaling during an attack, and tighter WAF integration. Worth it for internet-facing revenue-critical apps.
ACM: certificates
AWS Certificate Manager (ACM) provisions, manages, and auto-renews TLS certificates for free, when used with integrated services (CloudFront, ALB/NLB, API Gateway). You request a public cert, prove domain ownership (DNS validation is best — a CNAME that renews automatically), and attach it to your listener. ACM handles renewal so certificates never expire silently — the classic 2 a.m. outage. Note certs for CloudFront must live in us-east-1. For private/internal certs, ACM Private CA issues a private certificate hierarchy. ACM public certs cannot be exported (the private key stays in AWS) — for EC2-terminated or on-prem TLS you either use ACM Private CA or bring your own cert.
Network security recap
Layered from the perimeter inward (full detail in the Networking page):
- Security Groups — stateful, instance/ENI-level allow-only firewalls. Return traffic is automatically allowed. Reference other SGs as sources for clean tiering (web-SG allowed to reach app-SG).
- Network ACLs — stateless, subnet-level allow and deny rules. Evaluated in order. Useful for coarse subnet-wide blocks (e.g. deny a bad CIDR) that SGs cannot express.
- PrivateLink / VPC endpoints — reach AWS services (S3, DynamoDB, or a partner/SaaS service) over private AWS network paths instead of the public internet. Gateway endpoints (S3, DynamoDB) are free; Interface endpoints (most other services) are ENIs in your subnets, billed hourly + per-GB, and keep traffic off the internet entirely — important for compliance and for private subnets with no NAT.
Combine them: SGs for the common allow-lists, NACLs for coarse subnet guards, and PrivateLink to eliminate internet exposure for service-to-service and service-to-AWS-API traffic.
Best Practices
- Encrypt everything at rest by default, using CMKs where control matters. Enable default encryption on S3, EBS, RDS, DynamoDB. Rationale: the marginal cost is near zero, and a single unencrypted snapshot or bucket is a headline breach; CMKs add per-key auditing and revocation for sensitive data.
- Enforce TLS in transit and terminate with ACM. Redirect HTTP→HTTPS, use ACM certs with DNS auto-renewal, enable in-transit encryption for RDS/Redis. Rationale: plaintext on the wire is trivially sniffable, and ACM auto-renewal removes the classic expired-certificate outage.
- Separate KMS key administrators from key users in the key policy. Rationale: a key admin who cannot decrypt and an app that cannot delete the key mean no single compromised principal is fully catastrophic.
- Enable KMS key rotation and keep the root statement. Turn on annual (or on-demand) rotation; never remove
rootaccess from a CMK. Rationale: rotation limits the blast radius of a leaked key; losing the last administrator of a CMK is unrecoverable. - Never store secrets in code, images, env files, or Terraform state in git. Fetch from Secrets Manager / Parameter Store at runtime via IAM roles. Rationale: committed secrets leak forever in git history and are a top breach vector; runtime retrieval keeps them out of every artifact.
- Use Secrets Manager rotation for database and third-party credentials. Rationale: static long-lived credentials are the most-stolen secret; automatic rotation shrinks the useful lifetime of any leak to hours.
- Prefer Parameter Store SecureString for non-rotating config to save cost. Rationale: the standard tier is free; paying Secrets Manager’s per-secret fee for static feature flags is waste — reserve it for things that truly need rotation.
- Turn GuardDuty on org-wide with a delegated administrator. Rationale: it is high signal, low effort, and auto-covers new accounts; a compromised account with no GuardDuty is a silent breach waiting to happen.
- Aggregate findings in Security Hub and automate response via EventBridge. Rationale: humans cannot watch five separate detection consoles; central scoring plus automated containment (isolate SG, disable key) turns detection into fast response.
- Scan images and instances with Inspector; block on critical CVEs in CI. Rationale: containers inherit every vulnerability in their base layer; gating deploys on Inspector findings stops known-exploitable images from reaching production.
- Put WAF in front of internet-facing apps with AWS managed rule groups + rate limits. Rationale: managed rules cover the OWASP Top 10 and bad bots with near-zero maintenance; rate-based rules blunt credential-stuffing and layer-7 floods.
- Use PrivateLink/VPC endpoints for AWS API and internal service traffic. Rationale: keeping traffic off the public internet reduces attack surface, satisfies data-residency requirements, and lets private subnets reach S3/DynamoDB without a costly NAT gateway.
- Reference security groups as sources instead of CIDR ranges for internal tiers. Rationale: SG-to-SG rules stay correct as IPs change and encode intent (“web tier may reach app tier”) rather than brittle IP lists.
- Enable Macie on buckets that may hold PII. Rationale: automated sensitive-data discovery catches PII landing in the wrong bucket before it becomes a compliance incident, which manual review never scales to.
- Enforce encryption and exposure guardrails with AWS Config rules. Deploy managed rules (
s3-bucket-server-side-encryption-enabled,encrypted-volumes,restricted-ssh) with auto-remediation. Rationale: prevention-plus-detection keeps posture correct automatically instead of relying on humans to never misconfigure. - Apply least privilege to KMS via
kms:ViaServiceand grant conditions. Rationale: restricting a key to be usable only through the intended service (e.g. Secrets Manager) prevents a compromised role from decrypting data through unexpected paths.
References
- AWS Shared Responsibility Model
- AWS KMS Developer Guide
- KMS envelope encryption
- KMS key policies
- AWS Secrets Manager User Guide
- SSM Parameter Store
- Amazon GuardDuty User Guide
- AWS Security Hub User Guide
- Amazon Inspector User Guide
- Amazon Macie User Guide
- Amazon Detective User Guide
- AWS WAF Developer Guide
- AWS Shield Developer Guide
- AWS Certificate Manager User Guide
- AWS PrivateLink
- AWS Well-Architected — Security Pillar