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.
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
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.
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 kombinasisort
dantake
.Jika Anda perlu mengurutkan lebih dari satu bidang (seperti pada contoh terakhir di atas),
top
tidak dapat melakukannya, jadi Anda harus menggunakansort
dantake
.
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
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
.
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
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.
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 project
Anda, seperti yang ditunjukkan dalam contoh ini:
Perf
| project ObjectName, CounterValue, CounterName
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.
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
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.