Bahasa Kueri Kusto di Microsoft Sentinel

Bahasa Kueri Kusto adalah bahasa yang akan Anda gunakan untuk bekerja dengan dan memanipulasi data di Microsoft Azure Sentinel. Log yang Anda masukkan ke dalam ruang kerja Anda tidak bernilai banyak jika Anda tidak dapat menganalisisnya dan mendapatkan informasi penting yang tersembunyi di semua data itu. Bahasa Kueri Kusto tidak hanya memiliki kekuatan dan fleksibilitas untuk mendapatkan informasi tersebut, tetapi juga kesederhanaan untuk membantu Anda memulai dengan cepat. Jika Anda memiliki latar belakang dalam membuat skrip atau bekerja dengan database, banyak konten artikel ini akan terasa sangat akrab. Jika tidak, jangan khawatir, karena sifat intuitif bahasa akan dengan cepat memungkinkan Anda mulai menulis kueri sendiri dan meningkatkan nilai untuk organisasi Anda.

Artikel ini memperkenalkan dasar-dasar Bahasa Kusto Query, yang mencakup beberapa fungsi dan operator yang paling sering digunakan, yang harus menangani 75 hingga 80 persen kueri yang akan Anda tulis setiap hari. Saat Anda memerlukan lebih banyak kedalaman, atau untuk menjalankan kueri yang lebih lanjutan, Anda dapat memanfaatkan buku kerja KQL Tingkat Lanjut untuk Microsoft Azure Sentinel yang baru (lihat posting blog pengantar ini). Lihat juga dokumentasi Bahasa Kueri Kusto resmi serta berbagai kursus online (seperti Pluralsight).

Latar Belakang - Mengapa Bahasa Kueri Kusto?

Microsoft Azure Sentinel dibangun di atas layanan Azure Monitor dan menggunakan ruang kerja Analitik Log Azure Monitor untuk menyimpan semua datanya. Data ini mencakup hal-hal berikut:

  • data yang dicerna dari sumber eksternal ke dalam tabel yang telah ditentukan menggunakan konektor data Microsoft Azure Sentinel.
  • data yang dicerna dari sumber eksternal ke dalam tabel kustom yang ditentukan pengguna, menggunakan konektor data yang dibuat khusus serta beberapa jenis konektor diluar kotak.
  • data yang dibuat oleh Microsoft Azure Sentinel itu sendiri, yang dihasilkan dari analisis yang dibuat dan dilakukannya - misalnya, peringatan, insiden, dan informasi terkait UEBA.
  • data yang diunggah ke Microsoft Azure Sentinel untuk membantu deteksi dan analisis - misalnya, umpan intelijen ancaman dan daftar tonton.

Bahasa Kueri Kusto dikembangkan sebagai bagian dari layanan Azure Data Explorer, dan oleh karena itu dioptimalkan untuk mencari melalui penyimpanan data besar di lingkungan cloud. Terinspirasi oleh penjelajah bawah laut terkenal Jacques Cousteau (dan diucapkan sesuai "koo-STOH"), ini dirancang untuk membantu Anda menyelam jauh ke dalam lautan data dan menjelajahi harta karun mereka yang tersembunyi.

Bahasa Kueri Kusto juga digunakan di Azure Monitor (dan karenanya di Microsoft Azure Sentinel), termasuk beberapa fitur Azure Monitor tambahan, sehingga Anda dapat mengambil, memvisualisasikan, menganalisis, dan mengurai data di penyimpanan data Analitik Log. Di Microsoft Azure Sentinel, Anda menggunakan alat berdasarkan Bahasa Kueri Kusto setiap kali Anda memvisualisasikan dan menganalisis data dan mencari ancaman, baik dalam aturan dan buku kerja yang ada, atau dalam membangun sendiri.

Karena Bahasa Kueri Kusto adalah bagian dari hampir semua yang Anda lakukan di Microsoft Azure Sentinel, pemahaman yang jelas tentang cara kerjanya akan membantu Anda mendapatkan lebih banyak dari SIEM Anda.

Apa itu kueri?

Kueri Bahasa Kueri Kusto adalah permintaan baca-saja untuk memproses data dan mengembalikan hasil – tidak menulis data apa pun. Kueri beroperasi pada data yang diatur ke dalam hierarki database, tabel, dan kolom, mirip dengan SQL.

Permintaan dinyatakan dalam bahasa sederhana dan menggunakan model aliran data yang dirancang untuk membuat sintaks mudah dibaca, ditulis, dan diotomatisasi. Kita akan melihat ini secara rinci.

Kueri Bahasa Kueri Kusto terdiri dari pernyataan yang dipisahkan oleh titik koma. Ada banyak jenis pernyataan, tetapi hanya dua jenis yang banyak digunakan yang akan kita bahas di sini:

  • Pernyataan ekspresi tabular adalah apa yang biasanya kita maksud ketika kita berbicara tentang kueri - ini adalah isi sebenarnya dari kueri. Hal penting yang perlu diketahui tentang pernyataan ekspresi tabular adalah bahwa pernyataan tersebut menerima input tabel (tabel atau ekspresi tabel lainnya) dan menghasilkan output tabel. Setidaknya satu di antaranya diperlukan. Sebagian besar artikel ini akan membahas pernyataan semacam ini.

  • biarkan pernyataan memungkinkan Anda untuk membuat dan menentukan variabel dan konstanta di luar isi kueri, untuk keterbacaan dan fleksibilitas yang lebih mudah. Ini opsional dan tergantung pada kebutuhan khusus Anda. Kami akan membahas pernyataan semacam ini di akhir artikel.

Demo lingkungan

Anda dapat mempraktikkan pernyataan Bahasa Kueri Kusto - termasuk yang ada di artikel ini - di demo lingkungan Analitik Log di portal Microsoft Azure. Tidak ada biaya untuk menggunakan lingkungan latihan ini, tetapi Anda memerlukan akun Azure untuk mengaksesnya.

Menjelajahi demo lingkungan. Seperti Analitik Log di lingkungan produksi Anda, ini dapat digunakan dalam beberapa cara:

  • Pilih tabel tempat untuk membuat kueri. Dari tab Tabel default (ditampilkan dalam kotak merah di kiri atas), pilih tabel dari daftar tabel yang dikelompokkan berdasarkan topik (ditampilkan di kiri bawah). Perluas topik untuk melihat tabel individual, dan Anda dapat memperluas lebih lanjut setiap tabel untuk melihat semua bidangnya (kolom). Mengklik dua kali pada tabel atau nama bidang akan menempatkannya pada titik kursor di jendela kueri. Ketik sisa kueri Anda mengikuti nama tabel, seperti yang diarahkan di bawah ini.

  • Temukan kueri yang ada untuk mempelajari atau memodifikasi. Pilih tab Kueri (ditampilkan dalam persegi panjang merah di kiri atas) untuk melihat daftar kueri yang tersedia di luar kotak. Atau, pilih Kueri dari bilah bar tombol di kanan atas. Anda dapat menjelajahi kueri yang disertakan dengan Microsoft Sentinel diluar kotak. Mengklik dua kali kueri akan menempatkan seluruh kueri di jendela kueri pada titik kursor.

    Shows the Log Analytics demo environment.

Seperti di lingkungan demo ini, Anda dapat mengkueri dan memfilter data di halaman Log Microsoft Azure Sentinel. Anda dapat memilih tabel dan menelusuri paling detail untuk melihat kolom. Anda dapat mengubah kolom default yang ditampilkan menggunakan pemilih Kolom, dan Anda dapat mengatur rentang waktu default untuk kueri. Jika rentang waktu ditentukan secara eksplisit dalam kueri, filter waktu tidak akan tersedia (berwarna abu-abu).

Struktur kueri

Tempat yang baik untuk mulai belajar Bahasa Kueri Kusto adalah dengan memahami struktur query secara keseluruhan. Hal pertama yang akan Anda perhatikan ketika melihat kueri Kusto adalah penggunaan simbol pipa (|). Struktur kueri Kusto dimulai dengan mendapatkan data Anda dari sumber data dan kemudian meneruskan data melalui "alur", dan setiap langkah menyediakan beberapa tingkat pemrosesan dan kemudian meneruskan data ke langkah berikutnya. Di akhir alur, Anda akan mendapatkan hasil akhir Anda. Akibatnya, ini adalah alur kami:

Get Data | Filter | Summarize | Sort | Select

Konsep meneruskan data ke bawah alur ini membuat struktur yang sangat intuitif, karena mudah untuk membuat gambaran mental data Anda di setiap langkah.

Untuk mengilustrasikan hal ini, mari kita lihat kueri berikut, yang melihat log masuk Microsoft Entra. Saat Anda membaca setiap baris, Anda dapat melihat kata kunci yang menunjukkan apa yang terjadi pada data. Kami telah menyertakan tahap yang relevan dalam alur sebagai komentar di setiap baris.

Catatan

Anda dapat menambahkan komentar ke baris apa pun dalam kueri dengan mendahuluinya dengan garis miring ganda (//).

SigninLogs                              // Get data
| evaluate bag_unpack(LocationDetails)  // Ignore this line for now; we'll come back to it at the end.
| where RiskLevelDuringSignIn == 'none' // Filter
   and TimeGenerated >= ago(7d)         // Filter
| summarize Count = count() by city     // Summarize
| sort by Count desc                    // Sort
| take 5                                // Select

Karena output dari setiap langkah berfungsi sebagai input untuk langkah berikutnya, urutan langkah dapat menentukan hasil kueri dan memengaruhi performanya. Sangat penting bahwa Anda memesan langkah-langkah sesuai dengan apa yang ingin Anda dapatkan dari kueri.

Tip

  • Aturan praktis yang baik adalah memfilter data Anda lebih awal, jadi Anda hanya meneruskan data yang relevan ke alur. Ini akan sangat meningkatkan performa dan memastikan bahwa Anda tidak secara tidak sengaja memasukkan data yang tidak relevan dalam langkah ringkasan.
  • Artikel ini akan menunjukkan beberapa praktik terbaik lainnya yang perlu diingat. Untuk daftar yang lebih lengkap, lihat praktik terbaik kueri.

Semoga Anda sekarang memiliki apresiasi untuk keseluruhan struktur kueri di Bahasa Kueri Kusto. Sekarang mari kita lihat operator kueri yang sebenarnya, yang digunakan untuk membuat kueri.

Jenis data

Sebelum kita masuk ke operator kueri, mari kita lihat sekilas jenis data. Seperti dalam kebanyakan bahasa, jenis data menentukan perhitungan dan manipulasi apa yang dapat dijalankan terhadap suatu nilai. Misalnya, jika Anda memiliki nilai yang jenis string, Anda tidak akan dapat melakukan perhitungan aritmatika terhadapnya.

Di Bahasa Kueri Kusto, sebagian besar jenis data mengikuti konvensi standar dan memiliki nama yang mungkin pernah Anda lihat sebelumnya. Tabel berikut menunjukkan daftar lengkap:

Tabel jenis data

Jenis Nama tambahan Jenis .NET yang setara
bool Boolean System.Boolean
datetime Date System.DateTime
dynamic System.Object
guid uuid, uniqueid System.Guid
int System.Int32
long System.Int64
real Double System.Double
string System.String
timespan Time System.TimeSpan
decimal System.Data.SqlTypes.SqlDecimal

Meskipun sebagian besar jenis data adalah standar, Anda mungkin kurang terbiasa dengan jenis seperti dinamis, rentang waktu, dan guid.

Dinamis memiliki struktur yang sangat mirip dengan JSON, tetapi dengan satu perbedaan utama: Dapat menyimpan jenis data spesifik Bahasa Kueri Kusto yang tidak dapat dilakukan JSON tradisional, seperti nilai dinamis bersarang, atau rentang waktu. Berikut adalah contoh jenis dinamis:

{
"countryOrRegion":"US",
"geoCoordinates": {
"longitude":-122.12094116210936,
"latitude":47.68050003051758
},
"state":"Washington",
"city":"Redmond"
}

Rentang waktu adalah jenis data yang mengacu pada ukuran waktu seperti jam, hari, atau detik. Jangan membingungkan rentang waktu dengan tanggalwaktu, yang mengevaluasi ke tanggal dan waktu aktual, bukan ukuran waktu. Tabel berikut menunjukkan daftar akhiran rentang waktu.

Akhiran Rentang waktu

Function Deskripsi
D days
H hours
M menit
S seconds
Ms milliseconds
Microsecond mikrodetik
Tick nanodetik

Guid adalah jenis data yang mewakili 128-bit, pengenal unik global, yang mengikuti format standar [8]-[4]-[4]-[4]-[12], di mana setiap [angka] mewakili jumlah karakter dan setiap karakter dapat rentang dari 0-9 atau a-f.

Catatan

Bahasa Kueri Kusto memiliki operator tabular dan skalar. Sepanjang sisa artikel ini, jika Anda hanya melihat kata "operator", Anda dapat menganggap itu berarti operator tabel, kecuali dinyatakan lain.

Mendapatkan, membatasi, menyortir, dan memfilter data

Kosakata inti Bahasa Kueri Kusto - fondasi yang memungkinkan Anda menyelesaikan sebagian besar tugas Anda - adalah kumpulan operator untuk memfilter, menyortir, dan memilih data Anda. Sisa tugas yang perlu Anda lakukan akan mengharuskan Anda untuk memperluas pengetahuan Anda tentang bahasa tersebut untuk memenuhi kebutuhan Anda yang lebih maju. Mari kita perluas sedikit pada beberapa perintah yang kita gunakan dalam contoh di atas dan lihat take, sort, dan where.

Untuk masing-masing operator ini, kami akan memeriksa penggunaannya dalam contoh SigninLogs kami sebelumnya, dan mempelajari tip yang berguna atau praktik terbaik.

Mendapatkan data

Baris pertama dari setiap kueri dasar menentukan tabel mana yang ingin Anda kerjakan. Dalam kasus Microsoft Azure Sentinel, ini kemungkinan akan menjadi nama jenis log di ruang kerja Anda, seperti SigninLogs, SecurityAlert, atau CommonSecurityLog. Contohnya:

SigninLogs

Perhatikan bahwa dalam Bahasa Kueri Kusto, nama log peka huruf besar/kecil, sehingga SigninLogs dan signinLogs akan ditafsirkan secara berbeda. Berhati-hatilah saat memilih nama untuk log khusus Anda, sehingga mudah dikenali dan tidak terlalu mirip dengan log lain.

Membatasi data: ambil / batas

Operator ambil (dan operator batas yang sama) digunakan untuk membatasi hasil Anda dengan hanya mengembalikan sejumlah baris tertentu. Ini diikuti oleh bilangan bulat yang menentukan jumlah baris yang akan dikembalikan. Biasanya, ini digunakan di akhir kueri setelah Anda menentukan urutan sortir, dan dalam kasus seperti itu akan mengembalikan jumlah baris yang diberikan di bagian atas urutan yang disortir.

Menggunakan take kueri lebih awal dapat berguna untuk menguji kueri, saat Anda tidak ingin mengembalikan himpunan data besar. Namun, jika Anda menempatkan operasi take sebelum operasi sort apa pun, take akan mengembalikan baris yang dipilih secara acak - dan mungkin kumpulan baris yang berbeda setiap kali kueri dijalankan. Berikut adalah contoh menggunakan ambil:

SigninLogs
      | take 5

Screenshot of results of take operator.

Tip

Saat mengerjakan kueri baru di mana Anda mungkin tidak tahu akan seperti apa kueri itu, akan berguna untuk meletakkan pernyataan take di awal untuk membatasi himpunan data Anda secara artifisial untuk pemrosesan dan eksperimen yang lebih cepat. Setelah Anda puas dengan kueri lengkap, Anda dapat menghapus langkah take awal.

Menyortir data: sortir / urutan

Operator sortir (dan operator urutan yang sama) digunakan untuk mengurutkan data Anda dengan kolom tertentu. Dalam contoh berikut, kami memesan hasilnya oleh TimeGenerated dan mengatur arah urutan untuk turun dengan parameter desc, menempatkan nilai tertinggi terlebih dahulu; untuk urutan naik kami akan menggunakan ASC.

Catatan

Arah default untuk pengurutan adalah menurun, jadi secara teknis Anda hanya perlu menentukan apakah Anda ingin mengurutkan dalam urutan menaik. Namun, menentukan arah pengurutan dalam hal apa pun akan membuat kueri Anda lebih mudah dibaca.

SigninLogs
| sort by TimeGenerated desc
| take 5

Seperti yang kami sebutkan, kami menempatkan operator sort sebelum operator take. Kita perlu mengurutkan terlebih dahulu untuk memastikan kita mendapatkan lima baris yang sesuai.

Screenshot of results of sort operator, with take limit.

Atas

Operator teratas memungkinkan kami untuk menggabungkan operasi sort dan take menjadi satu operator:

SigninLogs
| top 5 by TimeGenerated desc

Dalam kasus di mana dua atau lebih baris memiliki nilai yang sama di kolom yang Anda urutkan, Anda bisa menambahkan lebih banyak kolom untuk diurutkan. Tambahkan kolom pengurutan ekstra dalam daftar yang dipisahkan koma, yang terletak setelah kolom pengurutan pertama, tetapi sebelum kata kunci urutan sortir. Contohnya:

SigninLogs
| sort by TimeGenerated, Identity desc
| take 5

Sekarang, jika TimeGenerated sama antara beberapa baris, maka akan mencoba mengurutkan berdasarkan nilai di kolom Identitas.

Catatan

Kapan harus menggunakan sort dan take, dan kapan harus menggunakan top

  • Jika Anda hanya menyortir pada satu bidang, gunakan top, karena memberikan performa yang lebih baik daripada kombinasi sort dan take.

  • Jika Anda perlu mengurutkan lebih dari satu bidang (seperti pada contoh terakhir di atas), top tidak dapat melakukannya, jadi Anda harus menggunakan sort dan take.

Memfilter data: tempat

Operator tempat yang bisa dibilang operator yang paling penting, karena ini adalah kunci untuk memastikan Anda hanya bekerja dengan subset data yang relevan dengan skenario Anda. Anda harus melakukan yang terbaik untuk memfilter data Anda sedini mungkin dalam kueri karena hal itu akan meningkatkan performa kueri dengan mengurangi jumlah data yang perlu diproses di langkah berikutnya; itu juga memastikan bahwa Anda hanya melakukan perhitungan pada data yang diinginkan. Lihat contoh ini:

SigninLogs
| where TimeGenerated >= ago(7d)
| sort by TimeGenerated, Identity desc
| take 5

Operator where menentukan variabel, operator perbandingan (skalar), dan nilai. Dalam kasus kami, kami menggunakan >=untuk menunjukkan bahwa nilai di kolom TimeGenerated harus lebih besar dari (yaitu, lebih lambat dari) atau sama dengan tujuh hari yang lalu.

Ada dua jenis operator perbandingan dalam Bahasa Kueri Kusto: untai dan numerik. Tabel berikut menunjukkan daftar lengkap operator numerik:

Operator numerik

Operator Deskripsi
+ Tambahan
- Pengurangan
* Perkalian
/ Divisi
% Modulo
< Kurang dari
> Lebih dari
== Sama dengan
!= Tidak sama dengan
<= Kurang dari atau sama dengan
>= Lebih dari atau sama dengan
in Sama dengan salah satu elemen
!in Tidak sama dengan satu pun elemen

Daftar operator untai adalah daftar yang lebih panjang karena memiliki permutasi untuk sensitivitas huruf besar-kecil, lokasi substring, awalan, akhiran, dan banyak lagi. Operator == adalah operator numerik dan untai, yang berarti dapat digunakan untuk angka dan teks. Misalnya, kedua pernyataan berikut akan valid jika pernyataan:

  • | where ResultType == 0
  • | where Category == 'SignInLogs'

Tip

Praktik Terbaik: Dalam kebanyakan kasus, Anda mungkin ingin memfilter data Anda dengan lebih dari satu kolom, atau memfilter kolom yang sama dengan lebih dari satu cara. Dalam instans ini, ada dua praktik terbaik yang harus Anda ingat.

Anda dapat menggabungkan beberapa pernyataan where menjadi satu langkah dengan menggunakan kata kunci dan. Contohnya:

SigninLogs
| where Resource == ResourceGroup
    and TimeGenerated >= ago(7d)

Ketika Anda memiliki beberapa filter yang digabungkan ke dalam satu pernyataan where menggunakan kata kunci dan, seperti di atas, Anda akan mendapatkan performa yang lebih baik dengan menempatkan filter yang hanya mereferensikan satu kolom terlebih dahulu. Jadi, cara yang lebih baik untuk menulis kueri di atas adalah:

SigninLogs
| where TimeGenerated >= ago(7d)
    and Resource == ResourceGroup

Dalam contoh ini, filter pertama menyebutkan satu kolom (TimeGenerated), sedangkan yang kedua mereferensikan dua kolom (Sumber daya dan ResourceGroup).

Meringkas data

Ringkasan adalah salah satu operator tabular terpenting di Bahasa Kueri Kusto, tetapi juga merupakan salah satu operator yang lebih kompleks untuk dipelajari jika Anda baru mengenal bahasa kueri secara umum. Tugas summarize adalah mengambil tabel data dan mengeluarkan tabel baru yang diagregasi oleh satu atau lebih kolom.

Struktur pernyataan ringkasan

Struktur dasar dari sebuah pernyataan summarize adalah sebagai berikut:

| summarize <aggregation> by <column>

Misalnya, berikut ini akan mengembalikan jumlah baris untuk setiap nilai CounterName dalam tabel Perf:

Perf
| summarize count() by CounterName

Screenshot of results of summarize operator with count aggregation.

Karena output summarize dari adalah tabel baru, kolom apa pun yang tidak ditentukan secara eksplisit dalam pernyataan summarize akan tidak diturunkan dari alur. Untuk mengilustrasikan konsep ini, pertimbangkan contoh ini:

Perf
| project ObjectName, CounterValue, CounterName
| summarize count() by CounterName
| sort by ObjectName asc

Pada baris kedua, kami menentukan bahwa kami hanya peduli dengan ObjectName, CounterValue, dan CounterName kolom. Kami kemudian meringkas untuk mendapatkan jumlah baris oleh CounterName dan akhirnya, kami mencoba mengurutkan data dalam urutan menaik berdasarkan kolom ObjectName. Sayangnya, kueri ini akan gagal dengan kesalahan (menunjukkan bahwa ObjectName tidak diketahui) karena ketika kami meringkas, kami hanya menyertakan kolom Count dan CounterName di tabel baru kami. Untuk menghindari kesalahan ini, kita cukup menambahkan ObjectName ke akhir langkah summarize kita, seperti ini:

Perf
| project ObjectName, CounterValue , CounterName
| summarize count() by CounterName, ObjectName
| sort by ObjectName asc

Cara membaca baris summarize di kepala Anda adalah : "ringkas jumlah baris oleh CounterName, dan kelompokkan dengan ObjectName". Anda dapat terus menambahkan kolom, dipisahkan oleh koma, ke akhir pernyataan summarize.

Screenshot of results of summarize operator with two arguments.

Berdasarkan contoh sebelumnya, jika kita ingin mengagregasi beberapa kolom secara bersamaan, kita dapat mencapainya dengan menambahkan agregasi ke operator summarize, dipisahkan oleh koma. Pada contoh di bawah ini, kami tidak hanya mendapatkan hitungan semua baris tetapi juga sejumlah nilai di kolom CounterValue di semua baris (yang cocok dengan filter apa pun dalam kueri):

Perf
| project ObjectName, CounterValue , CounterName
| summarize count(), sum(CounterValue) by CounterName, ObjectName
| sort by ObjectName asc

Screenshot of results of summarize operator with multiple aggregations.

Mengganti nama kolom yang diagregasi

Ini sepertinya saat yang tepat untuk berbicara tentang nama kolom untuk kolom yang diagregasi ini. Pada awal bagian ini, kami mengatakan operator summarize mengambil tabel data dan menghasilkan tabel baru, dan hanya kolom yang Anda tentukan dalam pernyataan summarize yang akan terus turun ke bawah alur. Oleh karena itu, jika Anda menjalankan contoh di atas, kolom yang dihasilkan untuk agregasi kami akan count_ dan sum_CounterValue.

Mesin Kusto akan secara otomatis membuat nama kolom tanpa kami harus eksplisit, tetapi sering kali, Anda akan menemukan bahwa Anda lebih suka kolom baru Anda memiliki nama yang lebih ramah. Anda dapat dengan mudah mengganti nama kolom Anda dalam pernyataan summarize dengan menentukan nama baru, diikuti oleh = dan agregasi, seperti:

Perf
| project ObjectName, CounterValue , CounterName
| summarize Count = count(), CounterSum = sum(CounterValue) by CounterName, ObjectName
| sort by ObjectName asc

Sekarang, kolom kami yang dirangkum akan diberi nama Count dan CounterSum.

Screenshot of friendly column names for aggregations.

Ada lebih banyak hal untuk operator summarize daripada yang dapat kami bahas di sini, tetapi Anda harus menginvestasikan waktu untuk mempelajarinya karena ini adalah komponen kunci untuk analisis data apa pun yang Anda rencanakan untuk dilakukan pada data Microsoft Azure Sentinel Anda.

Referensi agregasi

Banyak fungsi agregasi, tetapi beberapa yang paling umum digunakan adalah sum(), count(), dan avg(). Berikut daftar sebagian (lihat daftar lengkap):

Fungsi agregasi

Function Deskripsi
arg_max() Mengembalikan satu atau beberapa ekspresi saat argumen dimaksimalkan
arg_min() Mengembalikan satu atau beberapa ekspresi saat argumen dikecilkan
avg() Mengembalikan nilai rata-rata di seluruh grup
buildschema() Mengembalikan skema minimal yang menerima semua nilai input dinamis
count() Mengembalikan jumlah grup
countif() Mengembalikan jumlah dengan predikat grup
dcount() Mengembalikan perkiraan jumlah elemen grup yang berbeda
make_bag() Mengembalikan tas properti nilai dinamis dalam grup
make_list() Mengembalikan daftar semua nilai dalam grup
make_set() Mengembalikan set nilai yang berbeda dalam grup
max() Mengembalikan nilai maksimum di seluruh grup
min() Mengembalikan nilai minimum di seluruh grup
percentiles() Mengembalikan perkiraan persentil grup
stdev() Mengembalikan simpangan baku di seluruh grup
sum() Mengembalikan jumlah elemen dalam grup
take_any() Mengembalikan nilai acak yang tidak kosong untuk grup
variance() Mengembalikan varian di seluruh grup

Memilih: menambahkan dan menghapus kolom

Saat Anda mulai bekerja lebih banyak dengan kueri, Anda mungkin menemukan bahwa Anda memiliki lebih banyak informasi daripada yang Anda butuhkan pada subjek Anda (yaitu, terlalu banyak kolom di tabel Anda). Atau Anda mungkin memerlukan lebih banyak informasi daripada yang Anda miliki (yaitu, Anda perlu menambahkan kolom baru yang akan berisi hasil analisis kolom lain). Mari kita lihat beberapa operator kunci untuk manipulasi kolom.

Proyek dan proyek-jauh

Proyek kira-kira setara dengan pernyataan pilih banyak bahasa. Ini memungkinkan Anda untuk memilih kolom mana yang akan disimpan. Urutan kolom yang dikembalikan akan cocok dengan urutan kolom yang Anda cantumkan dalam pernyataan projectAnda, seperti yang ditunjukkan dalam contoh ini:

Perf
| project ObjectName, CounterValue, CounterName

Screenshot of results of project operator.

Seperti yang dapat Anda bayangkan, ketika Anda bekerja dengan kumpulan data yang sangat luas, Anda mungkin memiliki banyak kolom yang ingin Anda pertahankan, dan menentukan semuanya berdasarkan nama akan membutuhkan banyak pengetikan. Untuk kasus-kasus tersebut, Anda memiliki proyek jauh, yang memungkinkan Anda menentukan kolom mana yang akan dihapus, daripada yang mana yang harus disimpan, seperti itu:

Perf
| project-away MG, _ResourceId, Type

Tip

Ini dapat berguna untuk digunakan di dua lokasi project dalam kueri Anda, di awal dan lagi di akhir. Menggunakan project di awal kueri Anda dapat membantu meningkatkan performa dengan menghapus sebagian besar data yang tidak perlu Anda sampaikan ke alur. Menggunakannya lagi di akhir memungkinkan Anda menyingkirkan kolom apa pun yang mungkin telah dibuat pada langkah sebelumnya dan tidak diperlukan dalam hasil akhir Anda.

Perpanjang

Perpanjang digunakan untuk membuat kolom terhitung baru. Ini bisa berguna saat Anda ingin melakukan perhitungan terhadap kolom yang ada dan melihat output untuk setiap baris. Mari kita lihat contoh sederhana di mana kita menghitung kolom baru yang disebut Kbytes, yang dapat kita hitung dengan mengalikan nilai MB (di kolom Kuantitas yang ada) dengan 1.024.

Usage
| where QuantityUnit == 'MBytes'
| extend KBytes = Quantity * 1024
| project ResourceUri, MBytes=Quantity, KBytes

Pada baris terakhir dalam pernyataan project kami, kami mengganti nama kolom Kuantitas menjadi Mbytes, sehingga kami dapat dengan mudah mengetahui pelajaran ukuran mana yang relevan dengan setiap kolom.

Screenshot of results of extend operator.

Perlu dicatat bahwa extend juga bekerja dengan kolom terhitung. Misalnya, kita dapat menambahkan satu kolom lagi yang disebut Byte yang terhitung dari Kbytes:

Usage
| where QuantityUnit == 'MBytes'
| extend KBytes = Quantity * 1024
| extend Bytes = KBytes * 1024
| project ResourceUri, MBytes=Quantity, KBytes, Bytes

Screenshot of results of two extend operators.

Bergabung dengan tabel

Sebagian besar pekerjaan Anda di Microsoft Azure Sentinel dapat dilakukan dengan menggunakan satu jenis log, tetapi ada kalanya Anda ingin menghubungkan data bersama-sama atau melakukan pencarian terhadap kumpulan data lainnya. Seperti kebanyakan bahasa kueri, Bahasa Kueri Kusto menawarkan beberapa operator yang digunakan untuk melakukan berbagai jenis gabungan. Pada bagian ini, kita akan melihat operator yang paling banyak digunakan, union dan join.

union

Union hanya mengambil dua atau lebih tabel dan mengembalikan semua baris. Contohnya:

OfficeActivity
| union SecurityEvent

Ini akan mengembalikan semua baris dari tabel OfficeActivity dan SecurityEvent. Union menawarkan beberapa parameter yang dapat digunakan untuk menyesuaikan bagaimana serikat pekerja berperilaku. Dua yang paling berguna adalah dengan sumber dan jenis:

OfficeActivity
| union withsource = SourceTable kind = inner SecurityEvent

Parameter dengan sumber memungkinkan Anda menentukan nama kolom baru yang nilainya di baris tertentu akan menjadi nama tabel dari mana baris itu berasal. Pada contoh di atas, kami menamai kolom SourceTable, dan tergantung pada baris, nilainya adalah OfficeActivity atau SecurityEvent.

Parameter lain yang kami tentukan adalah jenis, yang memiliki dua opsi: dalam atau luar. Pada contoh di atas, kami menentukan dalam, yang berarti satu-satunya kolom yang akan disimpan selama penyatuan adalah kolom yang ada di kedua tabel. Atau, jika kita telah menentukan luar (yang merupakan nilai default), maka semua kolom dari kedua tabel akan dikembalikan.

Gabungkan

Gabungan bekerja mirip dengan union, kecuali alih-alih bergabung dengan tabel untuk membuat tabel baru, kami bergabung dengan baris untuk membuat tabel baru. Seperti kebanyakan bahasa database, ada beberapa jenis gabungan yang dapat Anda lakukan. Sintaks umum untuk join adalah:

T1
| join kind = <join type>
(
               T2
) on $left.<T1Column> == $right.<T2Column>

Setelah operator join, kami menentukan jenis gabungan yang ingin kami lakukan diikuti dengan tanda kurung terbuka. Di dalam tanda kurung adalah tempat Anda menentukan tabel yang ingin Anda gabungkan, serta pernyataan kueri lainnya di tabel yang ingin Anda tambahkan. Setelah tanda kurung penutupan, kami menggunakan kata kunci on diikuti oleh kiri kolom (kata kunci $left.< columnName> ) dan kanan ($right.< columnName>) kami dipisahkan dengan operator ==. Berikut adalah contoh gabungan dalam:

OfficeActivity
| where TimeGenerated >= ago(1d)
    and LogonUserSid != ''
| join kind = inner (
    SecurityEvent
    | where TimeGenerated >= ago(1d)
        and SubjectUserSid != ''
) on $left.LogonUserSid == $right.SubjectUserSid

Catatan

Jika kedua tabel memiliki nama yang sama untuk kolom tempat Anda melakukan gabungan, Anda tidak perlu menggunakan $left dan $right; sebagai gantinya, Anda bisa menentukan nama kolom. Menggunakan $left dan $right, bagaimanapun, lebih eksplisit dan umumnya dianggap sebagai praktik yang baik.

Untuk referensi Anda, tabel berikut menunjukkan daftar jenis gabungan yang tersedia.

Jenis-jenis Gabungan

Jenis gabungan Deskripsi
inner Mengembalikan satu untuk setiap kombinasi baris yang cocok dari kedua tabel.
innerunique Mengembalikan baris dari tabel kiri dengan nilai berbeda di bidang tertaut yang memiliki kecocokan di tabel kanan.
Ini adalah jenis gabungan default yang tidak ditentukan.
leftsemi Mengembalikan semua baris dari tabel kiri yang memiliki kecocokan di tabel kanan.
Hanya kolom dari tabel kiri yang akan dikembalikan.
rightsemi Mengembalikan semua baris dari tabel kanan yang memiliki kecocokan di tabel kiri.
Hanya kolom dari tabel kanan yang akan dikembalikan.
leftanti/
leftantisemi
Mengembalikan semua baris dari tabel kiri yang memiliki kecocokan di tabel kanan.
Hanya kolom dari tabel kiri yang akan dikembalikan.
rightanti/
rightantisemi
Mengembalikan semua baris dari tabel kanan yang memiliki kecocokan di tabel kiri.
Hanya kolom dari tabel kanan yang akan dikembalikan.
leftouter Mengembalikan semua baris dari tabel kiri. Untuk baris yang tidak memiliki kecocokan dalam tabel kanan, nilai sel akan null.
rightouter Mengembalikan semua baris dari tabel kanan. Untuk baris yang tidak memiliki kecocokan dalam tabel kiri, nilai sel akan null.
fullouter Mengembalikan semua baris dari tabel kiri dan kanan, cocok atau tidak.
Nilai yang tak cocok akan null.

Tip

Ini adalah praktik terbaik untuk memiliki tabel terkecil Anda di sebelah kiri. Dalam beberapa kasus, mengikuti aturan ini dapat memberi Anda keuntungan performa yang besar, tergantung pada jenis gabungan yang Anda lakukan dan ukuran tabel.

Evaluasi

Anda mungkin ingat kembali bahwa pada contoh pertama, kami melihat operator evaluasi di salah satu baris. Operator evaluate kurang umum digunakan daripada yang telah kami sentuh sebelumnya. Namun, mengetahui cara operator evaluate bekerja sepadan dengan waktu Anda. Sekali lagi, inilah kueri pertama itu, di mana Anda akan melihat evaluate di baris kedua.

SigninLogs
| evaluate bag_unpack(LocationDetails)
| where RiskLevelDuringSignIn == 'none'
   and TimeGenerated >= ago(7d)
| summarize Count = count() by city
| sort by Count desc
| take 5

Operator ini memungkinkan Anda untuk memanggil plugin yang tersedia (pada dasarnya fungsi bawaan). Banyak dari plugin ini difokuskan pada ilmu data, seperti autocluster, diffpatterns, dan sequence_detect, memungkinkan Anda untuk melakukan analisis tingkat lanjut dan menemukan anomali statistik dan garis luar.

Plugin yang digunakan dalam contoh di atas disebut bag_unpack, dan membuatnya sangat mudah untuk mengambil gugus data dinamis dan mengonversinya menjadi kolom. Ingat, data dinamis adalah jenis data yang terlihat sangat mirip dengan JSON, seperti yang ditunjukkan dalam contoh ini:

{
"countryOrRegion":"US",
"geoCoordinates": {
"longitude":-122.12094116210936,
"latitude":47.68050003051758
},
"state":"Washington",
"city":"Redmond"
}

Dalam hal ini, kami ingin meringkas data berdasarkan kota, tetapi kota berisi sebagai properti di dalam kolom LocationDetails. Untuk menggunakan properti kota dalam kueri kami, pertama-tama kami harus mengonversinya menjadi kolom menggunakan bag_unpack.

Kembali ke langkah alur asli kami, kami melihat ini:

Get Data | Filter | Summarize | Sort | Select

Sekarang setelah kami mempertimbangkan operator evaluate, kami dapat melihat bahwa itu mewakili tahap baru dalam alur, yang sekarang terlihat seperti ini:

Get Data | Parse | Filter | Summarize | Sort | Select

Ada banyak contoh operator dan fungsi lain yang dapat digunakan untuk mengurai sumber data ke dalam format yang lebih mudah dibaca dan dimanipulasi. Anda dapat mempelajarinya - dan sisa Bahasa Kueri Kusto - dalam dokumentasi lengkap dan di buku kerja.

Let pernyataan

Sekarang setelah kami membahas banyak operator utama dan jenis data, mari kita selesaikan dengan pernyataan let, yang merupakan cara yang bagus untuk membuat kueri Anda lebih mudah dibaca, diedit, dan dipelihara.

Let Anda membuat dan mengatur variabel, atau menetapkan nama ke ekspresi. Ekspresi ini bisa menjadi nilai tunggal, tetapi bisa juga seluruh kueri. Berikut contoh sederhananya:

let aWeekAgo = ago(7d);
SigninLogs
| where TimeGenerated >= aWeekAgo

Di sini, kami menentukan nama aWeekAgo dan mengaturnya agar sama dengan output fungsi rentang waktu, yang mengembalikan nilai tanggalwaktu. Kami kemudian mengakhiri pernyataan let dengan titik koma. Sekarang kami memiliki variabel baru yang disebut aWeekAgo yang dapat digunakan di mana saja dalam kueri kami.

Seperti yang baru saja kami sebutkan, Anda dapat menggunakan pernyataan let untuk mengambil seluruh kueri dan memberi nama hasilnya. Karena hasil kueri, sebagai ekspresi tabular, dapat digunakan sebagai input kueri, Anda dapat memperlakukan hasil bernama ini sebagai tabel untuk tujuan menjalankan kueri lain di atasnya. Berikut adalah sedikit modifikasi pada contoh sebelumnya:

let aWeekAgo = ago(7d);
let getSignins = SigninLogs
| where TimeGenerated >= aWeekAgo;
getSignins

Dalam hal ini, kami membuat pernyataan let kedua, di mana kami membungkus seluruh kueri kami menjadi variabel baru yang disebut getSignins. Sama seperti sebelumnya, kami mengakhiri pernyataan let kedua dengan titik koma. Kemudian kita memanggil variabel pada baris terakhir, yang akan menjalankan kueri. Perhatikan bahwa kami dapat menggunakan aWeekAgo di pernyataan let kedua. Ini karena kami menentukannya pada baris sebelumnya; jika kita menukar pernyataan let sehingga getSignins datang lebih dulu, kita akan mendapatkan kesalahan.

Sekarang kita dapat menggunakan getSignins sebagai dasar kueri lain (di jendela yang sama):

let aWeekAgo = ago(7d);
let getSignins = SigninLogs
| where TimeGenerated >= aWeekAgo;
getSignins
| where level >= 3
| project IPAddress, UserDisplayName, Level

Pernyataan Let memberi Anda lebih banyak kekuatan dan fleksibilitas dalam membantu mengatur pertanyaan Anda. Let dapat menentukan nilai skalar dan tabular serta membuat fungsi yang ditentukan pengguna. Mereka benar-benar berguna saat Anda mengatur kueri yang lebih kompleks yang mungkin melakukan banyak gabungan.

Langkah berikutnya

Meskipun artikel ini baru saja menggores permukaan, Anda sekarang memiliki dasar yang diperlukan, dan kami telah membahas bagian-bagian yang paling sering Anda gunakan untuk menyelesaikan pekerjaan Anda di Microsoft Azure Sentinel.

Buku kerja KQL Tingkat Lanjut untuk Microsoft Azure Sentinel

Manfaatkan buku kerja Bahasa Kueri Kusto tepat di Microsoft Azure Sentinel itu sendiri - buku kerja KQL Tingkat Lanjut untuk Microsoft Azure Sentinel. Ini memberi Anda bantuan langkah demi langkah dan contoh untuk banyak situasi yang mungkin Anda temui selama operasi keamanan sehari-hari Anda, dan juga mengarahkan Anda ke banyak hal yang sudah jadi, contoh diluar kotak aturan analitik, buku kerja, aturan berburu, dan elemen lainnya yang menggunakan kueri Kusto. Luncurkan buku kerja ini dari bilah Buku Kerja di Microsoft Azure Sentinel.

Buku kerja Kerangka kerja KQL Tingkat Lanjut - Memberdayakan Anda untuk menjadi ahli KQL adalah posting blog luar biasa yang menunjukkan kepada Anda cara menggunakan buku kerja ini.

Sumber daya lainnya

Lihat kumpulan sumber belajar, pelatihan, dan keterampilan ini untuk memperluas dan memperdalam pengetahuan Anda tentang Bahasa Kueri Kusto.