AWS Well-Architected WAFR bezpieczeństwo niezawodność remediacja IAM KMS

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.

Jerzy Kopaczewski ·
Twój przegląd Well-Architected się zakończył. Raport zawiera listę elementów wysokiego ryzyka (HRI) - ale co teraz? Ten runbook pokrywa 10 najczęściej wykrywanych problemów WAFR i pokazuje, jak je naprawić krok po kroku. Każda naprawa zawiera komendę CLI lub konfigurację Terraform, którą możesz wdrożyć od razu.

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ę.