Audyt bezpieczeństwa AWS: praktyczny checklist dla zespołów DevOps
Procedura audytu bezpieczeństwa środowiska AWS, od przeglądu IAM, przez konfigurację sieci, po szyfrowanie i monitoring. Gotowy checklist do cyklicznego stosowania.
Jeśli potrzebujesz zewnętrznego wsparcia w przeprowadzeniu audytu bezpieczeństwa chmury, sprawdź naszą usługę konsulting DevOps i bezpieczeństwo chmury.
Kiedy przeprowadzić audyt
- Przed migracją produkcji do nowego konta AWS
- Po incydencie bezpieczeństwa lub podejrzeniu naruszenia
- Cyklicznie co kwartał (minimum co pół roku)
- Przed audytem compliance (SOC2, ISO 27001, NIS2)
- Po znaczącej zmianie w infrastrukturze (nowy VPC, nowe konto w organizacji)
Narzędzia do automatyzacji
Zanim zaczniesz ręczny przegląd, uruchom skanery automatyczne:
# AWS Security Hub - natywne sprawdzenie zgodności
aws securityhub get-findings --filters '{"RecordState":[{"Value":"ACTIVE","Comparison":"EQUALS"}]}' \
--query 'Findings[?Severity.Label==`CRITICAL`].[Title,Resources[0].Id]' --output table
# Prowler - open-source audyt AWS (instalacja: pip install prowler)
prowler aws --severity critical high --output-formats json-ocsf html
# ScoutSuite - multi-cloud security auditing
scout aws --report-dir ./audit-$(date +%Y%m%d)
# AWS Trusted Advisor (wymaga Business/Enterprise support)
aws support describe-trusted-advisor-checks --language pl \
--query 'checks[?category==`security`].name'
Prowler pokrywa ponad 300 checklist z CIS AWS Benchmark, PCI-DSS i GDPR. Jeśli możesz uruchomić tylko jedno narzędzie, wybierz Prowler.
Checklist: IAM i dostęp
Root account
# Sprawdź czy root ma klucze API (powinien NIE mieć)
aws iam get-account-summary --query 'SummaryMap.AccountAccessKeysPresent'
# Wynik powinien być 0
# Sprawdź czy MFA jest włączone na root
aws iam get-account-summary --query 'SummaryMap.AccountMFAEnabled'
# Wynik powinien być 1
| Checkpoint | Status oczekiwany | Jak sprawdzić |
|---|---|---|
| Root account bez kluczy API | AccountAccessKeysPresent = 0 | aws iam get-account-summary |
| MFA na root account | AccountMFAEnabled = 1 | aws iam get-account-summary |
| Root account nieużywany >90 dni | Brak recent login | Credential Report |
| MFA na wszystkich użytkownikach IAM z konsolą | 100% pokrycie | aws iam generate-credential-report |
| Brak inline policies na użytkownikach | Wszystkie przez grupy/role | prowler aws -c iam_inline_policy_no_administrative_privileges |
| Rotacja kluczy API <90 dni | Brak starych kluczy | Credential Report kolumna access_key_last_rotated |
Polityki i role
# Znajdź użytkowników z AdministratorAccess
aws iam list-entities-for-policy \
--policy-arn arn:aws:iam::aws:policy/AdministratorAccess \
--query '[PolicyUsers[].UserName, PolicyGroups[].GroupName, PolicyRoles[].RoleName]'
# Znajdź polityki z wildcard (*) na actions i resources
aws iam list-policies --scope Local --query 'Policies[].Arn' --output text | \
xargs -I {} aws iam get-policy-version --policy-arn {} \
--version-id $(aws iam get-policy --policy-arn {} --query 'Policy.DefaultVersionId' --output text) \
--query 'PolicyVersion.Document'
# Nieużywane role (bez assume w ostatnich 90 dniach)
aws iam generate-service-last-accessed-details --arn arn:aws:iam::ACCOUNT_ID:role/ROLE_NAME
Checklist: Sieć i dostęp sieciowy
# Security Groups z otwartym 0.0.0.0/0 na portach innych niż 80/443
aws ec2 describe-security-groups \
--filters Name=ip-permission.cidr,Values='0.0.0.0/0' \
--query 'SecurityGroups[].{Name:GroupName,ID:GroupId,Rules:IpPermissions[?IpRanges[?CidrIp==`0.0.0.0/0`]].{Port:FromPort,Proto:IpProtocol}}' \
--output table
# Publiczne subnety bez NAT Gateway (potencjalny wektor ataku)
aws ec2 describe-route-tables --query 'RouteTables[].Routes[?GatewayId!=null && DestinationCidrBlock==`0.0.0.0/0`]'
# VPC Flow Logs - sprawdź czy są włączone na wszystkich VPC
aws ec2 describe-flow-logs --query 'FlowLogs[].{VPC:ResourceId,Status:FlowLogStatus,Dest:LogDestination}'
| Checkpoint | Oczekiwany stan |
|---|---|
| Brak SG z 0.0.0.0/0 na SSH (22) lub RDP (3389) | Zero wyników |
| VPC Flow Logs włączone na każdym VPC | 100% |
| Brak publicznych IP na instancjach baz danych | Zero wyników |
| NACLe blokują znane złośliwe zakresy IP | Skonfigurowane |
| Brak default VPC w użyciu w produkcji | Usunięte lub puste |
Checklist: Szyfrowanie i storage
# Buckety S3 bez szyfrowania default
aws s3api list-buckets --query 'Buckets[].Name' --output text | tr '\t' '\n' | while read bucket; do
enc=$(aws s3api get-bucket-encryption --bucket "$bucket" 2>&1)
if echo "$enc" | grep -q "ServerSideEncryptionConfigurationNotFoundError"; then
echo "BRAK SZYFROWANIA: $bucket"
fi
done
# Buckety S3 z publicznym dostępem
aws s3api list-buckets --query 'Buckets[].Name' --output text | tr '\t' '\n' | while read bucket; do
status=$(aws s3api get-public-access-block --bucket "$bucket" 2>&1)
if echo "$status" | grep -q "NoSuchPublicAccessBlockConfiguration"; then
echo "BRAK BLOKADY PUBLICZNEGO DOSTĘPU: $bucket"
fi
done
# Wolumeny EBS bez szyfrowania
aws ec2 describe-volumes --filters Name=encrypted,Values=false \
--query 'Volumes[].{ID:VolumeId,Size:Size,State:State}' --output table
# RDS bez szyfrowania at-rest
aws rds describe-db-instances \
--query 'DBInstances[?StorageEncrypted==`false`].{ID:DBInstanceIdentifier,Engine:Engine}' --output table
Checklist: Logging i monitoring
# CloudTrail - sprawdź czy jest aktywny i multi-region
aws cloudtrail describe-trails --query 'trailList[].{Name:Name,MultiRegion:IsMultiRegionTrail,Logging:HasCustomEventSelectors}'
aws cloudtrail get-trail-status --name default --query '{IsLogging:IsLogging,LatestDelivery:LatestDeliveryTime}'
# Config - czy AWS Config nagrywa
aws configservice describe-configuration-recorders \
--query 'ConfigurationRecorders[].{Name:name,Recording:recording}'
# GuardDuty - czy jest włączony
aws guardduty list-detectors --query 'DetectorIds'
# Alarmy na kluczowe zdarzenia (root login, zmiana IAM policy)
aws cloudwatch describe-alarms --alarm-name-prefix "Security-" \
--query 'MetricAlarms[].{Name:AlarmName,State:StateValue}'
| Checkpoint | Oczekiwany stan |
|---|---|
| CloudTrail aktywny, multi-region | IsLogging: true, Multi-region: true |
| CloudTrail logi w oddzielnym koncie (log archive) | Bucket w innym koncie |
| AWS Config nagrywający zmiany | Recording: true |
| GuardDuty włączony w każdym regionie | DetectorId w każdym regionie |
| Alarm na root login | Skonfigurowany i aktywny |
| Alarm na CreateUser/AttachPolicy | Skonfigurowany i aktywny |
Raportowanie wyników
Po uruchomieniu Prowler generujesz raport:
# Pełny raport z priorytetyzacją
prowler aws --severity critical high medium \
--output-formats html csv json-ocsf \
--output-directory ./audit-report-$(date +%Y%m%d)
# Porównanie z poprzednim audytem
prowler aws --severity critical high \
--output-formats csv \
| diff previous-audit.csv - > delta-findings.txt
Raport powinien zawierać:
- Krytyczne - naprawić w ciągu 24h (otwarte root klucze, publiczne bazy danych)
- Wysokie - naprawić w ciągu tygodnia (brak MFA, brak szyfrowania)
- Średnie - zaplanować na następny sprint (rotacja kluczy, unused roles)
Automatyzacja cyklicznego audytu
Zaplanuj audyt jako cykliczny pipeline (np. co tydzień w CI/CD):
# .github/workflows/security-audit.yml
name: Weekly AWS Security Audit
on:
schedule:
- cron: '0 6 * * 1' # Poniedziałek 6:00 UTC
jobs:
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Prowler
run: pip install prowler
- name: Run audit
run: prowler aws --severity critical high --output-formats json-ocsf html
env:
AWS_ACCESS_KEY_ID: $
AWS_SECRET_ACCESS_KEY: $
AWS_DEFAULT_REGION: eu-central-1
- name: Upload report
uses: actions/upload-artifact@v4
with:
name: security-audit-$
path: output/
Rola IAM do audytu powinna mieć politykę SecurityAudit managed policy + ViewOnlyAccess, żadnych uprawnień zapisu.
Następne kroki
- Napraw krytyczne findings natychmiast
- Wdrożenie AWS Config Rules do ciągłego monitorowania
- Rozważ AWS Organizations z SCP (Service Control Policies) jako guardrails
- Skonfiguruj Security Hub z automatycznym agregowaniem wyników
Jeśli potrzebujesz wsparcia w przeprowadzeniu audytu lub wdrożeniu automatyzacji bezpieczeństwa, skontaktuj się z nami.