Mengumpulkan log audit Azure DevOps
Ringkasan
Parser ini menangani log audit Azure DevOps dalam format JSON. Proses ini mengekstrak kolom dari struktur JSON bertingkat dan tingkat teratas, lalu memetakannya ke UDM. Logika bersyarat berdasarkan nilai kolom tertentu mengategorikan peristiwa dan memperkaya output dengan informasi keamanan yang relevan. Parser juga menangani pesan berformat non-JSON dengan mencoba mengekstrak payload JSON menggunakan pola grok.
Sebelum memulai
Pastikan Anda memiliki prasyarat berikut:
- Instance Google SecOps
- Organisasi Azure DevOps yang aktif
- Akses istimewa ke Organisasi Azure DevOps dan Azure
Menyiapkan feed
Ada dua titik entri berbeda untuk menyiapkan feed di platform Google SecOps:
- Setelan SIEM > Feed
- Hub Konten > Paket Konten
Menyiapkan feed dari Setelan SIEM > Feed
Untuk mengonfigurasi beberapa feed untuk berbagai jenis log dalam keluarga produk ini, lihat Mengonfigurasi feed menurut produk.
Untuk mengonfigurasi satu feed, ikuti langkah-langkah berikut:
- Buka Setelan SIEM > Feed.
- Klik Tambahkan Feed Baru.
- Di halaman berikutnya, klik Konfigurasi satu feed.
- Di kolom Feed name, masukkan nama feed (misalnya, Azure Devops Logs).
- Pilih Webhook sebagai Jenis sumber.
- Pilih Azure Devops Audit sebagai Log type.
- Klik Berikutnya.
- Opsional: Tentukan nilai untuk parameter input berikut:
- Pembatas pemisahan: Pembatas yang digunakan untuk memisahkan baris log, seperti
\n
. - Namespace aset: Namespace aset.
- Label penyerapan: Label yang diterapkan ke peristiwa dari feed ini.
- Pembatas pemisahan: Pembatas yang digunakan untuk memisahkan baris log, seperti
- Klik Berikutnya.
- Tinjau konfigurasi feed di layar Selesaikan, lalu klik Kirim.
- Klik Buat Kunci Rahasia untuk membuat kunci rahasia guna mengautentikasi feed ini.
- Salin dan simpan kunci rahasia. Anda tidak dapat melihat kunci rahasia ini lagi. Jika perlu, Anda dapat membuat ulang kunci rahasia baru, tetapi tindakan ini akan membuat kunci rahasia sebelumnya tidak berlaku.
- Di tab Detail, salin URL endpoint feed dari kolom Informasi Endpoint. Anda perlu menentukan URL endpoint ini di aplikasi klien Anda.
- Klik Selesai.
Menyiapkan feed dari Hub Konten
Tentukan nilai untuk kolom berikut:
- Pembatas pemisahan: Pembatas yang digunakan untuk memisahkan baris log, seperti
\n
.
Opsi lanjutan
- Nama Feed: Nilai yang telah diisi otomatis yang mengidentifikasi feed.
- Jenis Sumber: Metode yang digunakan untuk mengumpulkan log ke Google SecOps.
- Namespace aset: Namespace aset.
- Label penyerapan: Label yang diterapkan ke peristiwa dari feed ini.
- Klik Berikutnya.
- Tinjau konfigurasi feed di layar Selesaikan, lalu klik Kirim.
- Klik Buat Kunci Rahasia untuk membuat kunci rahasia guna mengautentikasi feed ini.
Membuat kunci API untuk feed webhook
Buka konsolGoogle Cloud > Kredensial.
Klik Create credentials, lalu pilih API key.
Batasi akses kunci API ke Google Security Operations API.
Tentukan URL endpoint
- Di aplikasi klien Anda, tentukan URL endpoint HTTPS yang disediakan di feed webhook.
Aktifkan autentikasi dengan menentukan kunci API dan kunci rahasia sebagai bagian dari header kustom dalam format berikut:
X-goog-api-key = API_KEY X-Webhook-Access-Key = SECRET
Rekomendasi: Tentukan kunci API sebagai header, bukan menentukannya di URL. Jika klien webhook Anda tidak mendukung header kustom, Anda dapat menentukan kunci API dan kunci rahasia menggunakan parameter kueri dalam format berikut:
ENDPOINT_URL?key=API_KEY&secret=SECRET
Ganti kode berikut:
ENDPOINT_URL
: URL endpoint feed.API_KEY
: Kunci API untuk mengautentikasi ke Google Security Operations.SECRET
: Kunci rahasia yang Anda buat untuk mengautentikasi feed.
Mengonfigurasi fitur Auditing di Azure DevOps
- Login ke organisasi Anda (
https://dev.azure.com/{yourorganization}
). - Pilih ikon roda gigi untuk Setelan organisasi.
- Pilih Kebijakan di bagian Keamanan.
- Geser tombol Log Peristiwa Audit ke AKTIF.
Mengonfigurasi Topik Event Grid di Azure
- Login ke Portal Azure.
- Telusuri dan akses Event Grid.
- Temukan Topik di bagian Peristiwa kustom.
- Klik + Create.
- Pilih Subscription dan Resource Group Anda. Berikan nama (misalnya,
DevopsAuditLog
) dan pilih region. Klik Tinjau dan buat. - Akses Topic baru, lalu salin Topic Endpoint URL.
- Buka Settings > Access Keys, lalu salin Key 1.
Mengonfigurasi Azure DevOps Log Stream ke Event Grid
- Login ke organisasi Anda (
https://dev.azure.com/{yourorganization}
). - Pilih ikon roda gigi untuk Setelan organisasi.
- Pilih Audit.
- Buka tab Streams, lalu pilih New stream > Event Grid.
- Masukkan endpoint topik dan kunci akses yang dibuat di Mengonfigurasi Topik Event Grid di Azure.
Mengonfigurasi Webhook di Azure DevOps untuk Google SecOps
- Di Portal Azure, telusuri dan akses Event Grid.
- Pilih Topic yang dibuat sebelumnya.
- Buka Entitas > Langganan Peristiwa.
- Klik + Event Subscription.
- Berikan nama deskriptif (misalnya, *
Google SecOps Integration
). - Pilih Web Hook, lalu klik Configure an endpoint.
- Konfigurasi endpoint:
- Endpoint pelanggan: Masukkan URL endpoint Google SecOps API.
- Di bagian HTTP headers, tambahkan header berikut:
- Header 1:
- Kunci:
X-goog-api-key
- Nilai: Kunci API yang Anda buat di bagian Membuat kunci API untuk feed webhook.
- Kunci:
- Header 2:
- Kunci:
X-Webhook-Access-Key
- Nilai: Kunci rahasia yang Anda buat di bagian Mengonfigurasi feed di Google SecOps untuk memproses log Azure DevOps.
- Kunci:
- Header 1:
- Tetapkan header Content-Type ke
application/json
.
- Klik Buat.
Tabel Pemetaan UDM
Kolom Log | Pemetaan UDM | Logika |
---|---|---|
ActivityId |
metadata.product_log_id |
Dipetakan langsung dari kolom Id dalam log mentah saat kolom records tidak ada, atau dari kolom ActivityId dalam objek data saat records ada. |
ActionId |
metadata.product_event_type |
Dipetakan langsung dari kolom ActionId dalam objek data . |
ActorCUID |
additional.fields |
Disertakan sebagai kolom tambahan dengan kunci "Actor CUID". |
ActorDisplayName |
principal.user.user_display_name |
Dipetakan langsung dari kolom ActorDisplayName jika bukan "Azure DevOps Service". Jika "Azure DevOps Service", layanan tersebut akan ditambahkan sebagai label ke principal.resource.attribute.labels . |
ActorUPN |
principal.user.email_addresses |
Dipetakan langsung dari kolom ActorUPN jika cocok dengan pola alamat email. |
ActorUserId |
principal.user.userid |
Dipetakan langsung dari kolom ActorUserId . |
Area |
target.application |
Digunakan untuk membuat kolom target.application dengan menambahkan "DevOps " ke nilai Area . |
AuthenticationMechanism |
extensions.auth.auth_details , security_result.rule_id |
Diuraikan untuk mengekstrak detail autentikasi dan ID aturan. Detail autentikasi dipetakan ke extensions.auth.auth_details . ID aturan yang diekstrak dipetakan ke security_result.rule_id . |
CategoryDisplayName |
security_result.action_details |
Dipetakan langsung ke security_result.action_details . |
City |
principal.location.city |
Dipetakan langsung dari kolom City . |
Conditions |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "Conditions". |
Country |
principal.location.country_or_region |
Dipetakan langsung dari kolom Country . |
Data.* |
Bervariasi | Kolom dalam objek Data dipetakan ke kolom UDM yang berbeda berdasarkan nama dan konteksnya. Lihat contoh spesifik di bawah. |
Data.AccessLevel |
target.resource.attribute.labels |
Ditambahkan sebagai label dengan kunci "AccessLevel". |
Data.AgentId |
target.resource.product_object_id |
Dipetakan ke target.resource.product_object_id jika PipelineId dan AuthorizationId tidak ada. |
Data.AgentName |
target.resource.name |
Dipetakan ke target.resource.name jika PipelineName , NamespaceName , dan DisplayName tidak ada. |
Data.AuthorizationId |
target.resource.product_object_id |
Dipetakan ke target.resource.product_object_id jika PipelineId tidak ada. |
Data.CallerProcedure |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "CallerProcedure". |
Data.CheckSuiteId |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "CheckSuiteId". |
Data.CheckSuiteStatus |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "CheckSuiteStatus". |
Data.ConnectionId |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "ConnectionId". |
Data.ConnectionName |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "ConnectionName". |
Data.ConnectionType |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "ConnectionType". |
Data.DefinitionId |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "DefinitionId". |
Data.DeploymentResult |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "DeploymentResult". |
Data.DisplayName |
target.resource.name |
Dipetakan ke target.resource.name jika PipelineName dan NamespaceName tidak ada. |
Data.EndpointIdList |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "EndpointIdList". |
Data.EnvironmentName |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "EnvironmentName". |
Data.Filter.continuationToken |
target.resource.attribute.labels |
Ditambahkan sebagai label dengan kunci "continuation_token". |
Data.Filter.endTime |
target.resource.attribute.labels |
Ditambahkan sebagai label dengan kunci "filter_end_time". |
Data.Filter.startTime |
target.resource.attribute.labels |
Ditambahkan sebagai label dengan kunci "filter_start_time". |
Data.FinishTime |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "FinishTime". |
Data.GroupId |
target.group.product_object_id |
Dipetakan langsung ke target.group.product_object_id saat Data.Updates.0.GroupId tidak ada. |
Data.GroupName |
target.group.group_display_name |
Dipetakan langsung ke target.group.group_display_name . |
Data.JobName |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "JobName". |
Data.MemberId |
target.user.userid |
Dipetakan langsung ke target.user.userid saat Data.Updates.0.MemberId tidak ada. |
Data.MemberDisplayName |
target.user.user_display_name |
Dipetakan langsung ke target.user.user_display_name . |
Data.NamespaceId |
target.resource.product_object_id |
Dipetakan ke target.resource.product_object_id jika PipelineId , AuthorizationId , dan AgentId tidak ada. |
Data.NamespaceName |
target.resource.name |
Dipetakan ke target.resource.name jika PipelineName tidak ada. |
Data.ownerDetails |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "OwnerDetails". |
Data.OwnerId |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "OwnerId". |
Data.PipelineId |
target.resource.product_object_id |
Dipetakan langsung ke target.resource.product_object_id . |
Data.PipelineName |
target.resource.name |
Dipetakan langsung ke target.resource.name . |
Data.PipelineRevision |
target.resource.attribute.labels |
Ditambahkan sebagai label dengan kunci "PipelineRevision". |
Data.PipelineScope |
target.resource.attribute.labels |
Ditambahkan sebagai label dengan kunci "PipelineScope". |
Data.PlanType |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "PlanType". |
Data.PreviousAccessLevel |
target.resource.attribute.labels |
Ditambahkan sebagai label dengan kunci "PreviousAccessLevel". |
Data.PublisherName |
target.resource.attribute.labels |
Ditambahkan sebagai label dengan kunci "PublisherName". |
Data.Reason |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "Reason". |
Data.ReleaseId |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "ReleaseId". |
Data.ReleaseName |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "ReleaseName". |
Data.RequesterId |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "RequesterId". |
Data.RetentionLeaseId |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "RetentionLeaseId". |
Data.RetentionOwnerId |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "RetentionOwnerId". |
Data.RunName |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "RunName". |
Data.Scopes |
target.resource.attribute.labels |
Ditambahkan sebagai label dengan kunci "Cakupan". |
Data.StageName |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "StageName". |
Data.StartTime |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "StartTime". |
Data.TargetUser |
target.user.userid |
Dipetakan langsung ke target.user.userid . |
Data.Timestamp |
metadata.event_timestamp |
Diuraikan dan dipetakan ke metadata.event_timestamp . |
Data.TokenType |
target.resource.attribute.labels |
Ditambahkan sebagai label dengan kunci "TokenType". |
Data.Updates.0.GroupId |
target.group.product_object_id |
Dipetakan langsung ke target.group.product_object_id . |
Data.Updates.0.MemberId |
target.user.userid |
Dipetakan langsung ke target.user.userid . |
Data.ValidFrom |
target.resource.attribute.labels |
Ditambahkan sebagai label dengan kunci "ValidFrom". |
Data.ValidTo |
target.resource.attribute.labels |
Ditambahkan sebagai label dengan kunci "ValidTo". |
DewPoint |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "DewPoint". |
Details |
metadata.description |
Dipetakan langsung ke metadata.description . |
Humidity |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "Humidity". |
Icon |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "Icon". |
Id |
metadata.product_log_id |
Dipetakan langsung ke metadata.product_log_id . |
IpAddress |
principal.ip |
Dipetakan langsung ke principal.ip . |
MoonPhase |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "MoonPhase". |
Moonrise |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "Moonrise". |
Moonset |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "Moonset". |
OperationName |
metadata.product_event_type |
Dipetakan langsung ke metadata.product_event_type . |
Precipitation |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "Precipitation". |
Pressure |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "Pressure". |
ProjectId |
target.resource_ancestors.product_object_id |
Digunakan untuk mengisi kolom product_object_id dalam target.resource_ancestors saat ancestor berjenis CLOUD_PROJECT . |
ProjectName |
target.resource_ancestors.name , target.resource.attribute.labels |
Digunakan untuk mengisi kolom name dalam target.resource_ancestors saat ancestor berjenis CLOUD_PROJECT . Juga ditambahkan sebagai label ke target.resource.attribute.labels dengan kunci "ProjectName". |
RoleLocation |
target.location.name |
Dipetakan langsung ke target.location.name . |
ScopeDisplayName |
target.resource_ancestors.name |
Digunakan untuk mengisi kolom name dalam target.resource_ancestors saat ancestor berjenis CLOUD_ORGANIZATION . |
ScopeId |
target.resource_ancestors.product_object_id |
Digunakan untuk mengisi kolom product_object_id dalam target.resource_ancestors saat ancestor berjenis CLOUD_ORGANIZATION . |
ScopeType |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "ScopeType". |
Sunrise |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "Sunrise". |
Sunset |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "Sunset". |
Temperature |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "Temperature". |
TenantId |
metadata.product_deployment_id , additional.fields |
Dipetakan langsung ke metadata.product_deployment_id . Juga ditambahkan sebagai kolom tambahan dengan kunci "TenantId". |
TimeGenerated |
metadata.event_timestamp |
Diuraikan dan dipetakan ke metadata.event_timestamp . |
UserAgent |
network.http.user_agent , network.http.parsed_user_agent |
Dipetakan langsung ke network.http.user_agent . Juga diuraikan dan dipetakan ke network.http.parsed_user_agent . |
UVIndex |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "UVIndex". |
Visibility |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "Visibility". |
WindDirection |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "WindDirection". |
WindSpeed |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "WindSpeed". |
_Internal_WorkspaceResourceId |
additional.fields |
Ditambahkan sebagai kolom tambahan dengan kunci "workspace_resource_id". |
T/A | metadata.event_type |
Ditentukan oleh logika berdasarkan OperationName dan kolom lainnya. Defaultnya adalah "GENERIC_EVENT" jika tidak ada jenis peristiwa tertentu yang cocok. Nilai yang mungkin mencakup "STATUS_SHUTDOWN", "RESOURCE_CREATION", "STATUS_UPDATE", "USER_RESOURCE_DELETION", "RESOURCE_READ", "RESOURCE_WRITTEN", "RESOURCE_DELETION", dan "GROUP_MODIFICATION". |
T/A | metadata.vendor_name |
Tetapkan ke "Microsoft". |
T/A | metadata.product_name |
Tetapkan ke "Azure DevOps". |
T/A | metadata.log_type |
Tetapkan ke "AZURE_DEVOPS". |
T/A | principal.user.account_type |
Tetapkan ke "SERVICE_ACCOUNT_TYPE" jika AuthenticationMechanism berisi "ServicePrincipal", atau tetapkan ke "CLOUD_ACCOUNT_TYPE". |
T/A | target.asset.attribute.cloud.environment |
Tetapkan ke MICROSOFT_AZURE . |
T/A | security_result.action |
Disetel ke "ALLOW" untuk operasi yang berhasil (Berhasil, Dibuat, Diubah, dieksekusi, diperbarui, dihapus) dan "BLOCK" untuk operasi yang gagal (Gagal, Waktu Habis). |
T/A | extensions.auth.mechanism |
Tetapkan ke "USERNAME_PASSWORD" jika summary adalah "UserAuthToken". |
T/A | target.resource.resource_type |
Disetel ke "SETTING" jika pipeline_id ada, "CREDENTIAL" jika authorization_id ada, "DEVICE" jika agent_id ada, atau "DATABASE" jika namespace_id ada. Jika tidak, nilai ini akan ditetapkan ke "STORAGE_BUCKET" dalam beberapa kasus berdasarkan operationName . |
T/A | target.resource.resource_subtype |
Ditetapkan ke "Pipeline" jika pipeline_id ada, "Token" jika authorization_id ada, "Agen" jika agent_id ada, atau "Namespace" jika namespace_id ada. |
Perlu bantuan lain? Dapatkan jawaban dari anggota Komunitas dan profesional Google SecOps.