← Semua materi
Security GuideCloud SecurityLanjutanBARU

Investigasi perubahan AWS Security Group dengan CloudTrail dan AWS CLI

Telusuri siapa yang menambah, mengubah, atau menghapus rule Security Group dengan CloudTrail Event History, AWS CLI, dan jq tanpa langsung melakukan rollback.

Tujuan latihan

Membangun timeline perubahan Security Group yang menghubungkan event API, identity/session, source, request parameters, hasil request, serta konfigurasi rule saat ini untuk menentukan respons yang tepat.

Persiapan

Akses read-only ke CloudTrail Event History dan EC2 DescribeSecurityGroups, AWS CLI v2, serta jq. Siapkan account, Region, security group ID, dan rentang waktu kejadian. Contoh output bersifat simulasi dan tidak berasal dari environment produksi.

Security Group berubah
CloudTrail Event History
Identity + requestParameters
Current state + keputusan

Masalah

Sebuah rule ingress terlihat terlalu terbuka atau berubah tanpa penjelasan. Current state hanya menunjukkan konfigurasi sekarang; ia tidak langsung menjawab siapa yang mengubahnya, lewat console/CLI/automation mana, kapan perubahan terjadi, apakah request berhasil, atau apakah rule sempat ditambahkan lalu dicabut. Investigasi perlu menggabungkan CloudTrail dengan kondisi Security Group saat ini.

Batas bukti CloudTrail Event History

Event History tersedia otomatis dan menyimpan management events selama 90 hari pada setiap AWS Region. Pencarian bersifat per account dan per Region, serta hanya menerima satu lookup attribute ditambah rentang waktu. Untuk retensi lebih panjang, pencarian multi-Region/multi-account, atau query banyak field, gunakan trail atau CloudTrail Lake yang memang sudah disiapkan. Jangan menyimpulkan 'tidak ada perubahan' sebelum account, Region, waktu, dan batas retensi diverifikasi.

1. Pastikan identity, account, dan Region pengujian

Mulai dengan kredensial read-only yang benar. get-caller-identity menunjukkan account dan ARN caller; configure get region membantu menemukan default lokal, tetapi investigasi tetap sebaiknya memakai --region secara eksplisit. Jangan menyalin access key atau token session ke catatan insiden.

aws sts get-caller-identity
aws configure get region

export AWS_REGION='ap-southeast-1'
export SG_ID='sg-0123456789abcdef0'

2. Tetapkan window waktu dalam UTC

CloudTrail eventTime menggunakan UTC. Ubah waktu laporan lokal ke UTC dan beri margin sebelum/sesudah kejadian agar event yang berdekatan tidak terlewat. Contoh berikut sengaja menggunakan timestamp eksplisit; ganti dengan window insiden Anda dan jangan melebihi batas 90 hari Event History.

export START_TIME='2026-10-03T16:30:00Z'
export END_TIME='2026-10-03T18:30:00Z'
printf 'region=%s\nsg=%s\nwindow=%s..%s\n' \
  "$AWS_REGION" "$SG_ID" "$START_TIME" "$END_TIME"

3. Ambil current state sebelum melakukan perubahan

Simpan konfigurasi Security Group saat ini sebagai bukti pembanding. Perintah ini read-only. Perhatikan GroupId, GroupName, VpcId, IpPermissions, IpPermissionsEgress, rule ID, protocol, port, CIDR, source Security Group, prefix list, dan description. Current state tidak membuktikan siapa yang membuat rule.

aws ec2 describe-security-groups \
  --group-ids "$SG_ID" \
  --region "$AWS_REGION" \
  --output json > current-security-group.json

jq '.SecurityGroups[0] | {
  GroupId, GroupName, VpcId,
  ingress: .IpPermissions,
  egress: .IpPermissionsEgress
}' current-security-group.json

4. Cari event perubahan ingress yang paling umum

AuthorizeSecurityGroupIngress menambah izin ingress, RevokeSecurityGroupIngress menghapusnya, sedangkan ModifySecurityGroupRules mengubah rule yang memiliki security-group-rule-id. Jalankan lookup satu event name pada satu waktu karena LookupEvents hanya menerima satu lookup attribute. Output dapat kosong bila Region atau window salah.

aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=EventName,AttributeValue=AuthorizeSecurityGroupIngress \
  --start-time "$START_TIME" \
  --end-time "$END_TIME" \
  --region "$AWS_REGION" \
  --output json > ct-authorize-ingress.json

5. Filter hasil ke Security Group target

CloudTrailEvent pada output lookup-events adalah JSON yang disimpan sebagai string. Gunakan fromjson sebelum membaca field di dalamnya. Filter berikut mencari SG_ID di event yang sudah dibatasi oleh nama event dan waktu; setelah kandidat ditemukan, requestParameters tetap harus diperiksa secara terstruktur.

jq --arg sg "$SG_ID" '
  [.Events[]
   | .CloudTrailEvent |= fromjson
   | select(.CloudTrailEvent | tostring | contains($sg))]
' ct-authorize-ingress.json > ct-authorize-ingress-target.json

jq 'length' ct-authorize-ingress-target.json

Contoh ringkasan kandidat (simulasi)

Output berikut hanya menunjukkan bentuk evidence yang diharapkan. absence of errorCode perlu dibaca bersama requestParameters dan current state; jangan menyalin nilai contoh sebagai fakta lingkungan Anda.

{
  "eventTime": "2026-10-03T17:12:41Z",
  "eventName": "AuthorizeSecurityGroupIngress",
  "identityType": "AssumedRole",
  "principalArn": "arn:aws:sts::123456789012:assumed-role/NetworkAdmin/session-example",
  "sourceIPAddress": "198.51.100.24",
  "groupId": "sg-0123456789abcdef0",
  "errorCode": null
}

6. Ekstrak field inti tanpa membuang raw event

Simpan file raw sebagai evidence lalu buat ringkasan terpisah. Field penting mencakup eventID, waktu, action, Region, identity, session issuer/source identity bila ada, source IP, user agent, requestParameters, responseElements, errorCode, dan errorMessage. requestParameters menjelaskan apa yang diminta; error fields membantu membedakan perubahan berhasil dari percobaan gagal.

jq '[.[] | .CloudTrailEvent | {
  eventTime,
  eventID,
  eventName,
  awsRegion,
  identity: {
    type: .userIdentity.type,
    arn: .userIdentity.arn,
    principalId: .userIdentity.principalId,
    sessionIssuer: .userIdentity.sessionContext.sessionIssuer.arn,
    sourceIdentity: .userIdentity.sessionContext.sourceIdentity,
    mfaAuthenticated: .userIdentity.sessionContext.attributes.mfaAuthenticated
  },
  sourceIPAddress,
  userAgent,
  requestParameters,
  responseElements,
  errorCode,
  errorMessage
}]' ct-authorize-ingress-target.json > timeline-authorize-ingress.json

7. Kumpulkan semua jenis perubahan rule secara terkendali

Satu rule dapat berubah melalui beberapa API. Loop berikut mengambil event ingress, egress, description, dan modify. Jeda satu detik menjaga request tetap jauh di bawah batas LookupEvents dua request per detik per account per Region. Nama file hanya berasal dari daftar tetap, bukan input bebas.

mkdir -p cloudtrail-sg-events

event_names=(
  AuthorizeSecurityGroupIngress
  RevokeSecurityGroupIngress
  ModifySecurityGroupRules
  UpdateSecurityGroupRuleDescriptionsIngress
  AuthorizeSecurityGroupEgress
  RevokeSecurityGroupEgress
  UpdateSecurityGroupRuleDescriptionsEgress
)

for event_name in "${event_names[@]}"; do
  aws cloudtrail lookup-events \
    --lookup-attributes "AttributeKey=EventName,AttributeValue=$event_name" \
    --start-time "$START_TIME" \
    --end-time "$END_TIME" \
    --region "$AWS_REGION" \
    --output json > "cloudtrail-sg-events/$event_name.json" || exit 1
  sleep 1
done

8. Gabungkan kandidat menjadi timeline kronologis

Gunakan jq -s untuk membaca semua file sebagai satu array, decode CloudTrailEvent, filter SG target, lalu urutkan berdasarkan eventTime. Timeline ascending memperlihatkan urutan add, modify, dan revoke. Simpan eventID agar setiap ringkasan dapat ditelusuri kembali ke raw event.

jq -s --arg sg "$SG_ID" '
  [.[].Events[]
   | .CloudTrailEvent |= fromjson
   | select(.CloudTrailEvent | tostring | contains($sg))
   | .CloudTrailEvent
   | {
       eventTime, eventID, eventName, awsRegion,
       identityType: .userIdentity.type,
       principalArn: .userIdentity.arn,
       sessionIssuer: .userIdentity.sessionContext.sessionIssuer.arn,
       sourceIdentity: .userIdentity.sessionContext.sourceIdentity,
       sourceIPAddress, userAgent,
       requestParameters, responseElements,
       errorCode, errorMessage
     }]
  | sort_by(.eventTime)
' cloudtrail-sg-events/*.json > security-group-timeline.json

jq '.[] | {eventTime,eventName,principalArn,sourceIPAddress,errorCode}' \
  security-group-timeline.json

9. Baca identity dan session dengan hati-hati

IAMUser menunjukkan kredensial user, sedangkan AssumedRole menunjukkan temporary credentials dan biasanya membutuhkan pemeriksaan sessionIssuer, session name pada ARN/principalId, sourceIdentity bila organisasi mengisinya, dan bukti dari identity provider. IdentityCenterUser dapat membawa onBehalfOf. Role ARN bukan otomatis nama manusia; korelasikan dengan IAM Identity Center, STS, pipeline, atau change ticket yang relevan.

10. Tafsirkan sourceIPAddress dan userAgent

sourceIPAddress dapat berupa alamat client, alamat/proxy perusahaan, atau nama service ketika request berasal dari AWS service. userAgent membantu membedakan console, AWS CLI, SDK, Terraform/provider, atau service—tetapi bukan bukti tunggal pelaku. NAT, VPN, proxy, dan automation membuat satu IP atau user agent dapat dipakai banyak sesi.

11. Bedakan request berhasil dan gagal

Event dengan errorCode/errorMessage menunjukkan API call gagal dan tidak boleh dianggap sebagai perubahan yang diterapkan. Ketika error field tidak ada, periksa requestParameters, responseElements bila tersedia, event yang terjadi setelahnya, dan current state. Jangan mengandalkan responseElements saja karena bentuk respons berbeda antar-API dan versi.

12. Cocokkan parameter rule secara exact

Bandingkan protocol, fromPort, toPort, CIDR IPv4/IPv6, referenced group, prefix list, description, serta securityGroupRuleId bila tersedia. CIDR 0.0.0.0/0 dan ::/0 berarti sumber mana pun untuk address family tersebut, tetapi risikonya tetap bergantung pada protocol/port, route, public exposure, dan kontrol lain. Jangan menyebut rule identik hanya karena port-nya sama.

13. Verifikasi kemungkinan automation atau infrastructure as code

Jika userAgent/session mengarah ke Terraform, CloudFormation, CI/CD, Lambda, atau service role, cari execution/deployment yang cocok dengan eventTime dan eventID. Perubahan manual dapat ditimpa ulang oleh desired state automation. Respons yang benar mungkin memperbaiki repository/template lalu melakukan deployment terkontrol, bukan mengedit rule berulang kali di console.

14. Bangun evidence package yang aman

Simpan command, account ID, Region, UTC window, SG ID, raw lookup output, timeline hasil parsing, dan current state. Redact data yang tidak perlu sebelum dibagikan: account ID, public IP, user ARN, session name, request metadata, dan resource identifiers dapat sensitif. Jangan mengedit raw evidence; buat salinan redacted dan catat hash bila prosedur organisasi memerlukannya.

sha256sum \
  current-security-group.json \
  security-group-timeline.json \
  cloudtrail-sg-events/*.json > evidence.sha256

sha256sum --check evidence.sha256

Decision path

Jika tidak ada event, validasi account, Region, UTC window, nama API, dan batas 90 hari; lanjutkan ke trail/CloudTrail Lake bila retensi atau scope Event History tidak cukup. Jika event memiliki errorCode, perlakukan sebagai percobaan gagal dan cari event sukses lain. Jika event sukses tetapi rule sudah tidak ada, cari modify/revoke setelahnya. Jika rule masih ada dan tidak terotorisasi, dokumentasikan evidence, nilai exposure, koordinasikan containment melalui change/incident process, dan perbaiki sumber automation bila ada. Jika actor adalah assumed role, identifikasi session atau identity provider sebelum menamai individu.

Kesalahan umum

Jangan mencari hanya di Region default, menganggap waktu lokal sebagai UTC, memakai hanya satu event name, atau menyimpulkan pelaku dari role name/source IP saja. Jangan menganggap event gagal sebagai perubahan sukses. Jangan melakukan rollback sebelum mengetahui dependency, karena rule dapat mendukung load balancer, health check, peering, atau jalur operasional lain. Jangan memakai --no-verify-ssl dan jangan menaruh credential pada command, file artikel, atau ticket.

Checklist verifikasi

Konfirmasi account dan Region; gunakan UTC window dengan margin; pastikan usia event kurang dari 90 hari; ambil current state; cari authorize, revoke, modify, description, ingress, dan egress; simpan raw event; decode CloudTrailEvent; validasi eventID, actor/session, source, request, error, serta urutan waktu; cocokkan rule exact; periksa automation/change ticket; redaksi evidence; dan tentukan containment hanya melalui proses yang disetujui.

Pelajaran

Investigasi Security Group yang kuat tidak berhenti pada 'siapa mengubah'. Hasil yang dapat ditindaklanjuti menghubungkan identity dan session, API action, parameter rule, status keberhasilan, timeline perubahan berikutnya, current state, serta sumber automation. Dengan alur ini, rollback dan perbaikan dapat dilakukan berdasarkan evidence, bukan asumsi.

Referensi resmi

AWS CloudTrail — Working with Event history ↗AWS CLI — cloudtrail lookup-events ↗AWS CloudTrail — Record contents ↗AWS CloudTrail — userIdentity element ↗Amazon VPC — Security group rules ↗
Lihat semua materi →