AWS Well-Architected Review - naprawa 10 najczęstszych HRI krok po kroku
Naprawa 10 najczęstszych problemów wysokiego ryzyka (HRI) z AWS Well-Architected Review. Krok po kroku: IAM root access, szyfrowanie, backup, Multi-AZ, monitoring, logging - z komendami CLI i Terraform.
Po zakończeniu przeglądu WAFR kluczowe jest szybkie wdrożenie napraw, aby zakwalifikować się do 10% zniżki AWS na powiązane zasoby. Każda naprawa poniżej odpowiada konkretnemu pytaniu w narzędziu Well-Architected Tool i po wdrożeniu pozwala zmienić status z HRI na „rozwiązane”.
Jeśli nie przeszedłeś jeszcze przeglądu, sprawdź nasz przewodnik przygotowania do WAFR lub usługę Well-Architected Review.
1. Konto root bez MFA i z aktywnymi kluczami API
| Filar: Bezpieczeństwo | Pytanie WA: SEC 1 - How do you securely manage credentials? |
Problem: Konto root AWS ma aktywne klucze dostępu lub brak włączonego MFA. Root ma nieodwołalne uprawnienia do wszystkiego w koncie.
Naprawa:
# Sprawdź status MFA na koncie root
aws iam get-account-summary --query 'SummaryMap.AccountMFAEnabled'
# Jeśli zwraca 0 - MFA nie jest włączone
# Sprawdź czy root ma aktywne klucze API
aws iam get-account-summary --query 'SummaryMap.AccountAccessKeysPresent'
# Jeśli zwraca 1 - klucze istnieją i muszą zostać usunięte
# Usuń klucze root (wymaga zalogowania jako root w konsoli)
# Console → IAM → Security credentials → Delete access keys
# Włącz MFA (hardware key preferowany, TOTP akceptowalny)
# Console → IAM → Security credentials → Assign MFA device
Walidacja:
aws iam get-account-summary \
--query '{MFA: SummaryMap.AccountMFAEnabled, AccessKeys: SummaryMap.AccountAccessKeysPresent}'
# Oczekiwane: {"MFA": 1, "AccessKeys": 0}
2. Brak szyfrowania danych w spoczynku (EBS, S3, RDS)
| Filar: Bezpieczeństwo | Pytanie WA: SEC 8 - How do you protect your data at rest? |
Problem: Wolumeny EBS, bucket S3 lub bazy RDS bez szyfrowania. Dane w czystym tekście na dyskach AWS.
Naprawa (prewencyjna - wymuszenie na nowych zasobach):
# Włącz domyślne szyfrowanie EBS dla regionu
aws ec2 enable-ebs-encryption-by-default --region eu-central-1
# Sprawdź status
aws ec2 get-ebs-encryption-by-default --region eu-central-1
# Oczekiwane: "EbsEncryptionByDefault": true
Wymuszenie szyfrowania S3 (Terraform):
# Polityka bucket wymuszająca szyfrowanie
resource "aws_s3_bucket_server_side_encryption_configuration" "enforce" {
bucket = aws_s3_bucket.main.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "aws:kms"
kms_master_key_id = aws_kms_key.s3.arn
}
bucket_key_enabled = true
}
}
Istniejące nieszyfrowane wolumeny EBS:
# Znajdź nieszyfrowane wolumeny
aws ec2 describe-volumes \
--filters Name=encrypted,Values=false \
--query 'Volumes[].{Id:VolumeId, Size:Size, State:State, Attached:Attachments[0].InstanceId}' \
--output table
# Szyfrowanie wymaga utworzenia snapshot → szyfrowanej kopii → nowego wolumenu
# Dla wolumenów podpiętych do instancji: wymaga planowanego okna przestoju
3. Brak automatycznych kopii zapasowych lub niesprawdzony proces odtwarzania
| Filar: Niezawodność | Pytanie WA: REL 9 - How do you back up data? |
Problem: Brak automatycznych backupów, lub backupy istnieją ale nigdy nie były testowane.
Naprawa (AWS Backup - centralny backup):
# Terraform: plan backup dla RDS, EBS, DynamoDB
resource "aws_backup_plan" "daily" {
name = "daily-backup-plan"
rule {
rule_name = "daily-retention-35"
target_vault_name = aws_backup_vault.main.name
schedule = "cron(0 3 * * ? *)" # codziennie o 03:00 UTC
lifecycle {
delete_after = 35 # retencja 35 dni
}
copy_action {
destination_vault_arn = aws_backup_vault.dr_region.arn
lifecycle {
delete_after = 7 # kopia DR: 7 dni
}
}
}
}
resource "aws_backup_selection" "production" {
name = "production-resources"
plan_id = aws_backup_plan.daily.id
iam_role_arn = aws_iam_role.backup.arn
selection_tag {
type = "STRINGEQUALS"
key = "environment"
value = "production"
}
}
Walidacja (test odtwarzania):
# Uruchom testowe odtworzenie z ostatniego backup
aws backup start-restore-job \
--recovery-point-arn arn:aws:ec2:eu-central-1:123456789012:snapshot/snap-xxx \
--iam-role-arn arn:aws:iam::123456789012:role/BackupRestoreRole \
--metadata '{"availabilityZone":"eu-central-1a","encrypted":"true"}' \
--resource-type EBS
# Sprawdź status
aws backup describe-restore-job --restore-job-id <job-id>
4. Brak rotacji kluczy KMS
| Filar: Bezpieczeństwo | Pytanie WA: SEC 8 - How do you protect your data at rest? |
Problem: Klucze KMS customer-managed bez włączonej automatycznej rotacji.
Naprawa:
# Znajdź klucze bez rotacji
for key_id in $(aws kms list-keys --query 'Keys[].KeyId' --output text); do
rotation=$(aws kms get-key-rotation-status --key-id $key_id --query 'KeyRotationEnabled' --output text 2>/dev/null)
if [ "$rotation" = "False" ]; then
alias=$(aws kms list-aliases --key-id $key_id --query 'Aliases[0].AliasName' --output text)
echo "BRAK ROTACJI: $key_id ($alias)"
fi
done
# Włącz rotację dla każdego klucza
aws kms enable-key-rotation --key-id <key-id>
Terraform:
resource "aws_kms_key" "main" {
description = "Main encryption key"
enable_key_rotation = true # rotacja co 365 dni (automatycznie)
policy = data.aws_iam_policy_document.kms.json
}
Walidacja:
aws kms get-key-rotation-status --key-id <key-id>
# Oczekiwane: "KeyRotationEnabled": true
5. Brak Multi-AZ dla produkcyjnych baz danych
| Filar: Niezawodność | Pytanie WA: REL 11 - How do you design your workload to withstand component failures? |
Problem: Baza produkcyjna RDS/Aurora bez Multi-AZ. Awaria jednej strefy dostępności oznacza niedostępność bazy (15-30 minut na odtworzenie z snapshot).
Naprawa:
# Sprawdź które bazy nie mają Multi-AZ
aws rds describe-db-instances \
--query 'DBInstances[?MultiAZ==`false`].{Id:DBInstanceIdentifier, Engine:Engine, Class:DBInstanceClass}' \
--output table
# Włącz Multi-AZ (powoduje krótki przestój ~30s podczas failover setup)
aws rds modify-db-instance \
--db-instance-identifier production-db \
--multi-az \
--apply-immediately
Uwaga: Włączenie Multi-AZ podwaja koszt instancji. Dla środowisk dev/staging to zazwyczaj nieuzasadnione. Stosuj selektywnie - tylko produkcja.
6. Security Groups z regułami 0.0.0.0/0 na portach niewebowych
| Filar: Bezpieczeństwo | Pytanie WA: SEC 5 - How do you protect your network resources? |
Problem: Security Groups z otwartym dostępem z internetu na porty SSH (22), RDP (3389), bazy danych (3306, 5432) lub inne porty niewebowe.
Naprawa:
# Znajdź Security Groups z regułami 0.0.0.0/0 na portach != 80/443
aws ec2 describe-security-groups \
--filters Name=ip-permission.cidr,Values=0.0.0.0/0 \
--query 'SecurityGroups[].{GroupId:GroupId, Name:GroupName, Rules:IpPermissions[?IpRanges[?CidrIp==`0.0.0.0/0`] && FromPort!=`80` && FromPort!=`443`]}' \
--output json | jq '.[] | select(.Rules | length > 0)'
# Usuń regułę otwierającą SSH z internetu
aws ec2 revoke-security-group-ingress \
--group-id sg-xxx \
--protocol tcp \
--port 22 \
--cidr 0.0.0.0/0
Alternatywa dla dostępu SSH: AWS Systems Manager Session Manager (zero otwartych portów):
# Dostęp do instancji bez SSH
aws ssm start-session --target i-xxx
7. Brak centralnego logowania (CloudTrail wyłączony lub niemonitorowany)
| Filar: Bezpieczeństwo | Pytanie WA: SEC 4 - How do you detect and investigate security events? |
Problem: CloudTrail nie jest aktywny we wszystkich regionach, lub logi trafiają do bucket bez alertów.
Naprawa (Terraform):
resource "aws_cloudtrail" "org_trail" {
name = "organization-trail"
s3_bucket_name = aws_s3_bucket.cloudtrail.id
is_organization_trail = true
is_multi_region_trail = true
include_global_service_events = true
enable_log_file_validation = true
cloud_watch_logs_group_arn = "${aws_cloudwatch_log_group.trail.arn}:*"
cloud_watch_logs_role_arn = aws_iam_role.cloudtrail_cloudwatch.arn
event_selector {
read_write_type = "All"
include_management_events = true
}
}
# Alert na logowanie jako root
resource "aws_cloudwatch_metric_filter" "root_login" {
name = "root-console-login"
pattern = "{ $.userIdentity.type = \"Root\" && $.eventType = \"AwsConsoleSignIn\" }"
log_group_name = aws_cloudwatch_log_group.trail.name
metric_transformation {
name = "RootLoginCount"
namespace = "SecurityMetrics"
value = "1"
}
}
8. Brak tagowania zasobów (brak alokacji kosztów)
| Filar: Optymalizacja kosztów | Pytanie WA: COST 2 - How do you govern usage? |
Problem: >30% zasobów bez tagów. Brak możliwości przypisania kosztów do zespołów lub usług.
Naprawa (SCP wymuszający tagi):
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "RequireTagsOnEC2",
"Effect": "Deny",
"Action": ["ec2:RunInstances"],
"Resource": ["arn:aws:ec2:*:*:instance/*", "arn:aws:ec2:*:*:volume/*"],
"Condition": {
"Null": {
"aws:RequestTag/team": "true",
"aws:RequestTag/environment": "true",
"aws:RequestTag/service": "true"
}
}
}
]
}
Tagowanie istniejących zasobów (bulk):
# Oznacz wszystkie instancje EC2 w danym VPC
for instance_id in $(aws ec2 describe-instances \
--filters Name=vpc-id,Values=vpc-xxx \
--query 'Reservations[].Instances[].InstanceId' --output text); do
aws ec2 create-tags --resources $instance_id \
--tags Key=team,Value=platform Key=environment,Value=production
done
9. Brak monitorowania limitów usług AWS (Service Quotas)
| Filar: Niezawodność | Pytanie WA: REL 1 - How do you manage service quotas and constraints? |
Problem: Brak monitoringu zbliżania się do limitów AWS (np. max VPC, max EC2 instances, max EBS volumes). Workload rośnie i nagle przestaje się skalować.
Naprawa:
# Sprawdź wykorzystanie kluczowych limitów
aws service-quotas list-service-quotas --service-code ec2 \
--query 'Quotas[?UsageMetric!=null].{Name:QuotaName, Value:Value, Usage:UsageMetric}' \
--output table
# Włącz Trusted Advisor check na limity (wymaga Business+ support)
aws support describe-trusted-advisor-checks \
--language en \
--query 'checks[?category==`service_limits`].{Name:name, Id:id}' \
--output table
Alert CloudWatch na limity (Terraform):
resource "aws_cloudwatch_metric_alarm" "ec2_limit" {
alarm_name = "ec2-instance-limit-80pct"
comparison_operator = "GreaterThanThreshold"
evaluation_periods = 1
metric_name = "ResourceCount"
namespace = "AWS/TrustedAdvisor"
period = 86400
statistic = "Maximum"
threshold = 80 # alert na 80% limitu
alarm_actions = [aws_sns_topic.alerts.arn]
}
10. Brak planu odtwarzania po awarii (DR) lub niesprawdzony plan
| Filar: Niezawodność | Pytanie WA: REL 13 - How do you plan for disaster recovery? |
Problem: Brak udokumentowanego planu DR, lub plan istnieje ale nigdy nie był testowany.
Minimalne wymagania DR:
# Sprawdź replikację cross-region dla krytycznych danych
# S3: Cross-Region Replication
aws s3api get-bucket-replication --bucket production-data \
--query 'ReplicationConfiguration.Rules[].{Status:Status, Destination:Destination.Bucket}'
# RDS: Read Replica w drugim regionie (dla Aurora: Global Database)
aws rds describe-db-instances \
--query 'DBInstances[?ReadReplicaSourceDBInstanceIdentifier!=null].{Id:DBInstanceIdentifier, Source:ReadReplicaSourceDBInstanceIdentifier, Region:AvailabilityZone}'
Dokumentacja DR (minimum):
| Element | Wartość | Ostatni test |
|---|---|---|
| RTO (docelowy czas przywrócenia) | 4h | 2026-03-15 |
| RPO (dopuszczalna utrata danych) | 1h | 2026-03-15 |
| Region DR | eu-west-1 | - |
| Proces przełączenia | Dokumentacja w Confluence | Nietestowany |
| Odpowiedzialny | On-call SRE | - |
Kluczowa zasada: Plan DR, który nie był testowany, nie jest planem - jest życzeniem. Testuj failover co kwartał, minimum co pół roku.
Po naprawie: zamknięcie pętli w AWS WA Tool
Po wdrożeniu każdej naprawy:
# 1. Zaloguj się do AWS Well-Architected Tool
# 2. Otwórz odpowiedni workload
# 3. Znajdź pytanie powiązane z naprawą
# 4. Zmień odpowiedź z "High Risk" na "No Risk" lub "Medium Risk"
# 5. Dodaj notatkę opisującą co zostało naprawione i kiedy
# Po zamknięciu partii napraw - utwórz milestone
aws wellarchitected create-milestone \
--workload-id <workload-id> \
--milestone-name "Remediacja Q3 2026 - batch 1"
Milestone dokumentuje stan „przed” i „po”, jest widoczny dla AWS i stanowi podstawę do kwalifikacji na 10% zniżki na naprawione zasoby.
Potrzebujesz wsparcia w naprawie wykrytych problemów? Sprawdź naszą usługę Well-Architected Review - przeprowadzamy zarówno przegląd, jak i naprawę.