Overview and What You Will Learn
Encryption and secrets are the layer most teams get wrong first, and the layer attackers go after first. This topic covers the full defense stack AWS gives you for protecting data and detecting threats:
- AWS KMS — how encryption keys actually work in AWS, and the difference between AWS Owned, AWS Managed, and Customer Managed Keys
- SSM Parameter Store vs Secrets Manager — which one to use for config values vs credentials that need to rotate
- CloudHSM — dedicated hardware key management for strict compliance requirements
- ACM — free, auto-renewing TLS certificates and where they can (and can't) be attached
- WAF and Shield — Layer 7 application firewalling and DDoS protection
- GuardDuty, Inspector, and Macie — the three AWS threat-detection services and when each one fires
By the end you'll be able to pick the right encryption/secrets service for a given workload, wire up certificate and DDoS protection correctly, and know what each detection service actually catches versus what it doesn't.
Why This Matters in Production
In January 2025, a ransomware group called Codefinger started targeting AWS accounts directly — not through malware, but by abusing a legitimate S3 feature. Using stolen or leaked AWS credentials, the attackers re-encrypted victims' S3 objects with SSE-C (server-side encryption with a customer-supplied key), generating that key themselves and never handing it to AWS. Because S3 stores only verification material for an SSE-C key, not the key itself, once the attacker held the only working copy, recovery was impossible without paying for it. They then set the encrypted files to auto-delete within seven days to pressure victims into paying.
No AWS vulnerability was exploited — the entire attack relied on obtaining valid account credentials and using AWS's own encryption feature against the account owner. It's a clean example of why "we use encryption" means nothing on its own: who controls the key is the actual security boundary. AWS's response was structural — as of April 2026, SSE-C is now disabled by default on new general-purpose S3 buckets and a set of existing ones, though it can still be explicitly re-enabled, so knowing this history matters even if you never touch SSE-C directly.
This is exactly the mindset this topic builds: KMS, Secrets Manager, WAF, Shield, and GuardDuty aren't a checklist to enable once — they're a set of decisions about who can hold, use, and rotate the keys that protect your data, and how fast you'd notice if that control slipped.
AWS KMS — Key Management Service
KMS is the encryption backbone almost every other AWS service quietly depends on. Every encrypted S3 object, every encrypted EBS volume, every encrypted RDS database, and every secret in Secrets Manager ultimately depends on a KMS key. If you understand KMS, most of AWS's "encryption at rest" story falls into place; if a KMS key is misconfigured or compromised, that same dependency chain becomes the attacker's shortcut.
What KMS actually manages:
KMS does not store your data.KMS creates, stores, and controls the cryptographic KEYSthat other services (S3, EBS, RDS, Secrets Manager, SSM...)use to encrypt and decrypt YOUR data.Key types in KMS:
| Key type | Who manages it | Can you see/rotate the policy? | Typical use |
|---|---|---|---|
| AWS Owned Key | AWS, fully internal | No — invisible to you | Default encryption AWS applies behind the scenes on some services |
AWS Managed Key (e.g. aws/s3, aws/secretsmanager) |
AWS, but scoped to your account | View only, AWS handles rotation | Free, zero-setup encryption for a specific service |
| Customer Managed Key (CMK) | You | Full control — key policy, rotation, cross-account sharing | Anything needing cross-account access, custom key policies, or an audit trail you control |
Rememberthe deciding question is almost always "do I need to share this key across accounts, or control its policy myself?" If yes → Customer Managed Key. If no, and you just want encryption on by default → the AWS Managed Key is free and sufficient. Secrets Manager itself recommends the AWS managed key
aws/secretsmanagerfor most cases since there's no cost to using it, and reserves a customer managed key for when you need cross-account access or a custom key policy.
Encryption models KMS supports:
KMS supports symmetric, asymmetric, and envelope encryption models. In practice on AWS you'll mostly interact with symmetric CMKs (used by S3, EBS, Secrets Manager, SSM SecureString) and envelope encryption (a data key encrypts your actual data, and that data key is itself encrypted by your KMS key — this is what happens under the hood every time you enable SSE-KMS on S3).
Key rotation:
Enable automatic annual rotation on every Customer Managed Key you create. Rotation doesn't re-encrypt existing data — KMS keeps old key material available to decrypt anything encrypted under it, while new encryption operations use the fresh key material. This limits how much is exposed if a key is ever compromised, without breaking anything already encrypted.
A real, current attack path to know — Codefinger and SSE-C:
The Codefinger campaign above is the reason security teams now explicitly call out SSE-C as a risk. The fix is to restrict SSE-C usage via IAM policy so it can't be used unless explicitly required, keep encryption keys centralized in KMS instead, and use Service Control Policies to limit which users and applications can perform cryptographic operations at all. Since Codefinger, many organizations have restricted or blocked SSE-C entirely — if your account doesn't have a deliberate reason to use SSE-C, don't leave it available.
## Deny SSE-C uploads at the bucket policy level## (attach to any bucket that has no legitimate SSE-C use case){ "Version": "2012-10-17", "Statement": [{ "Sid": "DenySSECUploads", "Effect": "Deny", "Principal": "*", "Action": "s3:PutObject", "Resource": "arn:aws:s3:::YOUR-BUCKET/*", "Condition": { "StringLike": { "s3:x-amz-server-side-encryption-customer-algorithm": "*" } } }]}Securityif you ever see a KMS key scheduled for deletion that you didn't schedule, or S3 objects suddenly encrypted with an algorithm your team doesn't use, treat it as an active incident, not a configuration drift — both are consistent with a credential-compromise ransomware pattern, not an accident.
AWS SSM Parameter Store
SSM Parameter Store is the free, simple option for storing configuration values and secrets as key-value pairs, part of AWS Systems Manager.
Parameter types:
String → plaintext, e.g. a feature flag or a hostnameStringList → comma-separated plaintext listSecureString → encrypted with KMS (AWS managed key by default, or your own CMK)Standard vs Advanced tier:
| Standard | Advanced | |
|---|---|---|
| Cost | Free | Paid, per parameter |
| Max parameters per account | 10,000 | Higher limit |
| Max value size | 4 KB | 8 KB |
| Parameter policies (expiration/notification) | No | Yes |
Parameter policies (Advanced tier only) let you attach expiration and notification behavior directly to a parameter:
// ExpirationNotification — EventBridge alert 15 days before expiry{"Type":"ExpirationNotification","Attributes":{"Before":"15","Unit":"Days"}} // NoChangeNotification — alert if parameter not updated in 20 days{"Type":"NoChangeNotification","Attributes":{"After":"20","Unit":"Days"}}AWS Secrets Manager
A newer service specifically built for storing and rotating secrets — database credentials, API keys, OAuth tokens. The key difference from SSM Parameter Store is built-in automatic rotation.
Force rotation every X days — password changes automatically on scheduleAuto-generates new secrets using a Lambda function — no manual effortDeep RDS integration — when secret rotates, Secrets Manager updates the DB password tooAlways encrypted with KMS — no option to store plaintext Without rotation: a stolen DB password works foreverWith rotation: the stolen password stops working in X days Day 1: password = "abc123"Day 30: Secrets Manager auto-rotates Lambda generates new secret → updates RDS → stores new secret password = "xyz789"Day 60: auto-rotates againYour app always fetches the latest password from Secrets Manager. It never breaks because it never stores the password itself.
Multi-Region Secrets:
Replicate secrets across multiple AWS regions. Replica stays in sync with primary automatically. If primary region fails, promote replica to standalone secret.
SSM Parameter Store vs Secrets Manager:
| SSM Parameter Store | Secrets Manager | |
|---|---|---|
| Cost | Free (standard) | Paid |
| Auto rotation | No | Yes — built-in with Lambda |
| RDS integration | No | Yes — syncs DB password on rotation |
| Encryption | Optional (KMS) | Always (KMS) |
| Best for | Config values, feature flags, simple secrets | DB passwords and API keys needing rotation |
RememberThe decision between SSM Parameter Store and Secrets Manager comes down to one question: does this secret need automatic rotation? If yes, use Secrets Manager. If no, SSM Parameter Store is free and sufficient.
CloudHSM — Dedicated Hardware Key Management
KMS is a software-managed service. CloudHSM provisions dedicated encryption hardware for you — an HSM (Hardware Security Module). You manage your own encryption keys entirely.
KMS: AWS manages the software for encryptionCloudHSM: AWS provides dedicated hardware, you manage keysKey facts:
Single-tenant hardware — not shared with other AWS customersFIPS 140-2 Level 3 — higher than KMS Level 2Tamper-resistant deviceNo free tierMust use CloudHSM Client Software to interactCloudHSM vs KMS:
| Feature | AWS KMS | AWS CloudHSM |
|---|---|---|
| Tenancy | Multi-tenant | Single-tenant dedicated hardware |
| FIPS standard | Level 2 | Level 3 |
| Key types | AWS Owned, AWS Managed, CMK | Customer Managed only |
| Free tier | Yes | No |
| Access control | AWS IAM | You create users and manage permissions |
Use CloudHSM when: FIPS 140-2 Level 3 compliance is required, your organisation needs to own and manage all key material with zero AWS involvement, regulatory requirements mandate dedicated hardware.
AWS Certificate Manager (ACM)
ACM provisions, manages, and auto-renews TLS certificates for HTTPS. Public certificates are free.
Where ACM certificates can be used:
Elastic Load Balancers (CLB, ALB, NLB)CloudFront DistributionsAPIs on API GatewayCommon MistakeACM certificates cannot be used directly with EC2 instances. The certificate cannot be extracted from ACM and installed manually. Use ACM only with the supported services above.
DNS Validation (preferred):
Route 53 integration adds CNAME record automaticallyCertificate auto-renews without any action neededWorks even if the domain is not in Route 53Import your own certificate:
ACM does not auto-renew imported certificatesTwo alerting mechanisms to prevent expiry surprises: EventBridge fires daily starting 45 days before expiry → wire to Lambda/SNS AWS Config rule acm-certificate-expiration-check → flags as non-compliantEdge-Optimized API Gateway certificate rule:
Edge-Optimized endpoint → TLS certificate must be in us-east-1Regional endpoint → TLS certificate must be in same region as APIRememberEdge-Optimized API Gateway uses CloudFront under the hood. All CloudFront certificates must be in us-east-1 globally. If your certificate is in ap-south-1 and your API is Edge-Optimized, it will not work.
AWS WAF — Web Application Firewall
WAF protects web applications from attacks at Layer 7 (HTTP/HTTPS). It evaluates each request against rules you define — allow, block, or count.
Where WAF can be attached:
Application Load BalancerAPI GatewayCloudFrontAppSync GraphQL APICognito User PoolWAF cannot attach to NLB — NLB operates at Layer 4, WAF requires Layer 7.
Web ACL rule types:
IP-based rules → allow or block specific IPs or CIDR ranges (up to 10,000 IPs per set)Request rules → inspect headers, body, query strings for SQL injection and XSSGeo Match rules → block or allow traffic from specific countriesSize Constraint → block requests with unusually large payloadsRate-Based rules → limit requests per IP per time window (DDoS and brute-force protection)Fixed IP with WAF + ALB:
ALB does not have a static IP — its IPs can change. When clients or firewalls need to whitelist a fixed IP, use Global Accelerator in front of ALB.
User → Global Accelerator (fixed Anycast IP) → ALB (with WAF WebACL) → EC2WAF Web ACL must be in the same region as the ALB. Global Accelerator provides the fixed IP.
AWS Shield — DDoS Protection
Shield Standard (free, automatic):
Automatically enabled for all AWS customersProtects against Layer 3 and Layer 4 attacksSYN floods, UDP floods, reflection attacksAlways on, no configuration requiredShield Advanced ($3,000/month per organisation):
Advanced DDoS mitigation for large-scale attacksProtects EC2, ELB, CloudFront, Global Accelerator, Route 5324/7 access to AWS DDoS Response Team (DRT) during active attacksCost protection — AWS may credit scaling costs caused by a DDoS eventAutomatically creates and deploys WAF rules during active Layer 7 attacksWhen Shield Advanced is worth it:
Your application generates significant revenue and downtime is catastrophicYou have SLA commitments to customers with financial penaltiesYou need DRT support during an active attack — Standard gives you no access to AWS expertsYou need cost protection for auto-scaling triggered by attack trafficThreat Detection — GuardDuty, Inspector, Macie
Amazon GuardDuty — runtime threat detection:
Monitors your account continuously using ML and threat intelligence. One click to enable. No agents.
Data sources GuardDuty analyses: CloudTrail Logs → unusual API calls, privilege escalation attempts VPC Flow Logs → unusual traffic patterns, known malicious IPs DNS Logs → instances connecting to suspicious domains What it detects: Compromised EC2 (communicating with command-and-control servers) Unauthorized API calls from unusual locations Data exfiltration attempts Cryptocurrency mining (dedicated finding type) Credential theft and usage from unexpected locationsGuardDuty generates findings. Connect findings to EventBridge to trigger SNS alerts or Lambda automated responses. GuardDuty detects — it does not block.
## Enable GuardDuty in ap-south-1aws guardduty create-detector \ --enable \ --region ap-south-1 ## List findingsaws guardduty list-findings \ --detector-id DETECTOR-ID \ --region ap-south-1Amazon Inspector — vulnerability scanning:
Automated security assessments for EC2, container images in ECR, and Lambda functions.
For EC2: Uses SSM Agent to collect OS and package data Compares against CVE databases Checks network reachability for unintended internet exposure For containers: Scans ECR images automatically when pushed Continuous scanning when base image CVEs are disclosed For Lambda: Checks function code and dependencies when deployedInspector performs continuous scanning — re-scans automatically when changes happen. Every finding gets a risk score for prioritisation. Findings go to EventBridge and Security Hub.
GuardDuty vs Inspector:
GuardDuty = "Something suspicious is happening right now" (active threat detection)Inspector = "This system has a weakness that could be exploited" (vulnerability scanning)Amazon Macie — sensitive data classification:
Discovers, classifies, and protects sensitive data in S3. Uses ML and pattern matching to find PII, financial data, and confidential business information.
S3 Buckets → Macie scans content → finds sensitive patterns (credit card numbers, email addresses, government IDs, Aadhaar numbers) ↓Generates findings ↓Sends to Amazon EventBridge ↓Trigger Lambda or SNS for automated responseReal example at an Indian fintech: a developer accidentally uploads a file containing customer KYC data to an S3 bucket. Macie detects PAN card and Aadhaar number patterns, generates an alert, fires an EventBridge event, and Lambda restricts bucket access automatically.
Hands-on Lab — KMS, Secrets Manager, and GuardDuty
Step 1 — Create a Customer Managed KMS Key
## Create CMK in ap-south-1aws kms create-key \ --description "Key for production secrets and snapshots" \ --region ap-south-1 ## Create a memorable aliasaws kms create-alias \ --alias-name alias/devops-prod-key \ --target-key-id KEY-ID-FROM-ABOVE \ --region ap-south-1Step 2 — Create a secret in Secrets Manager
## Store RDS database credentials as a JSON secretaws secretsmanager create-secret \ --name "prod/devops-app/rds-mysql" \ --description "RDS MySQL credentials for production app" \ --secret-string '{"username":"admin","password":"Str0ng@DBPass#2024"}' \ --kms-key-id alias/devops-prod-key \ --region ap-south-1Step 3 — Retrieve the secret from application code
## Retrieve full secret valueaws secretsmanager get-secret-value \ --secret-id "prod/devops-app/rds-mysql" \ --region ap-south-1 ## Extract just the secret stringaws secretsmanager get-secret-value \ --secret-id "prod/devops-app/rds-mysql" \ --query SecretString \ --output text \ --region ap-south-1## Returns: {"username":"admin","password":"Str0ng@DBPass#2024"}Step 4 — Store config values in SSM Parameter Store
## Plaintext config value (no encryption needed)aws ssm put-parameter \ --name "/devops-app/prod/db-host" \ --value "devops-prod-db.abc123.ap-south-1.rds.amazonaws.com" \ --type String \ --region ap-south-1 ## Encrypted sensitive value using our CMKaws ssm put-parameter \ --name "/devops-app/prod/api-key" \ --value "sk_live_abc123xyz789" \ --type SecureString \ --key-id alias/devops-prod-key \ --region ap-south-1 ## Retrieve encrypted parameter (SSM decrypts via KMS automatically)aws ssm get-parameter \ --name "/devops-app/prod/api-key" \ --with-decryption \ --region ap-south-1 ## Retrieve all parameters for an app path in one callaws ssm get-parameters-by-path \ --path "/devops-app/prod/" \ --with-decryption \ --region ap-south-1Step 5 — Enable GuardDuty
## Enable GuardDuty (one click, no agents)aws guardduty create-detector \ --enable \ --finding-publishing-frequency FIFTEEN_MINUTES \ --region ap-south-1## Note the DetectorId from output ## List detectorsaws guardduty list-detectors --region ap-south-1 ## List findings (initially empty on new account)aws guardduty list-findings \ --detector-id DETECTOR-ID \ --region ap-south-1Step 6 — Cleanup
## Delete secret (7-day recovery window by default)aws secretsmanager delete-secret \ --secret-id "prod/devops-app/rds-mysql" \ --force-delete-without-recovery \ --region ap-south-1 ## Delete SSM parametersaws ssm delete-parameters \ --names "/devops-app/prod/db-host" "/devops-app/prod/api-key" \ --region ap-south-1 ## Disable GuardDutyaws guardduty delete-detector \ --detector-id DETECTOR-ID \ --region ap-south-1 ## Schedule KMS key deletion (minimum 7 day waiting period)aws kms schedule-key-deletion \ --key-id alias/devops-prod-key \ --pending-window-in-days 7 \ --region ap-south-1Production Best Practices and Common Pitfalls
- Enable GuardDuty in every AWS account and every region from day one — it is one click and the cost is minimal compared to the cost of a breach
- Use Secrets Manager for any credential that needs rotation — SSM Parameter Store has no built-in rotation
- Enable KMS key rotation on all Customer Managed Keys — rotating keys limits the exposure window if a key is ever compromised
- Use KMS CMKs for cross-account encrypted snapshot sharing — AWS Managed Keys cannot be shared
- Never put API keys or database passwords in Lambda environment variables — use Secrets Manager and retrieve at initialisation
- Set up ACM expiry alerts with EventBridge on day one for imported certificates — ACM does not auto-renew imported certs
- Use WAF rate-based rules on all public-facing APIs — basic DDoS and brute-force protection at minimal cost
- Enable Macie on buckets containing PII or financial data — the first data classification run often finds data in places teams did not expect
- Restrict or deny SSE-C on S3 buckets unless you have a specific, documented reason to use it — this closes the exact path the Codefinger ransomware campaign used
Quick Reference and Troubleshooting Commands
| Task | Command |
|---|---|
| Create KMS key | aws kms create-key --description "description" --region ap-south-1 |
| Create key alias | aws kms create-alias --alias-name alias/my-key --target-key-id <key-id> |
| Create secret | aws secretsmanager create-secret --name <name> --secret-string '{"key":"value"}' |
| Get secret value | aws secretsmanager get-secret-value --secret-id <name> --query SecretString --output text |
| Store SSM parameter | aws ssm put-parameter --name /path/param --value "value" --type SecureString |
| Get SSM parameter | aws ssm get-parameter --name /path/param --with-decryption |
| Enable GuardDuty | aws guardduty create-detector --enable --region ap-south-1 |
| List GuardDuty findings | aws guardduty list-findings --detector-id <id> --region ap-south-1 |
| List KMS keys | aws kms list-keys --region ap-south-1 |
| List ACM certificates | aws acm list-certificates --region ap-south-1 |
Common problems and fixes:
| Problem | Likely cause | Fix |
|---|---|---|
| KMS throttling on S3 downloads | SSE-KMS at high request rate hitting KMS quota | Request KMS quota increase or switch to SSE-S3 |
| Cannot share encrypted snapshot cross-account | Encrypted with AWS Managed Key | Re-encrypt with a Customer Managed Key that you can share via key policy |
| Secrets Manager rotation failing | Rotation Lambda has no network access to RDS | Deploy Lambda in same VPC as RDS with correct Security Groups |
| ACM certificate not renewing | Domain validation CNAME was deleted | Re-add the validation CNAME record in Route 53 |
| GuardDuty finding not triggering alert | EventBridge rule not configured | Create EventBridge rule on GuardDuty finding events → SNS |
Common MistakeUsing SSM Parameter Store Standard tier for database passwords that need rotation. SSM has no built-in rotation. You would need to write your own rotation Lambda, schedule it, update RDS manually, and store the new value. Secrets Manager handles all of this natively. Use Secrets Manager for any credential that must rotate automatically.
SecurityGuardDuty generates findings but does not block anything. It detects — your response infrastructure must block. Wire GuardDuty findings to EventBridge → Lambda that automatically adds the offending IP to a WAF IP block list or a NACL deny rule. Detection without automated response is incomplete security.
TipRun Macie on all S3 buckets at least once after initial setup. Teams are consistently surprised by what Macie finds — developer test data containing real customer records, legacy files with unmasked payment information, backup files with credentials. The first scan is almost always the most valuable.