Mengumpulkan log Snipe-IT

Didukung di:

Dokumen ini menjelaskan cara menyerap log Snipe-IT ke Google Security Operations menggunakan Google Cloud Storage. Snipe-IT adalah sistem pengelolaan aset IT open source yang melacak hardware, lisensi software, aksesori, bahan habis pakai, dan aset IT lainnya selama siklus prosesnya.

Sebelum memulai

Pastikan Anda memiliki prasyarat berikut:

  • Instance Google SecOps
  • Project GCP dengan Cloud Storage API diaktifkan
  • Izin untuk membuat dan mengelola bucket GCS
  • Izin untuk mengelola kebijakan IAM di bucket GCS
  • Izin untuk membuat fungsi Cloud Run, topik Pub/Sub, dan tugas Cloud Scheduler
  • Akses istimewa ke tenant Snipe-IT

Kumpulkan prasyarat Snipe-IT (token API dan URL dasar)

  1. Login ke Snipe-IT.
  2. Buka menu pengguna Anda (avatar kanan atas) dan klik Manage API keys.
  3. Klik Create New Token:
    • Nama/Label: Masukkan label deskriptif (misalnya, Google SecOps export).
  4. Klik Generate.
  5. Salin token API (hanya akan ditampilkan satu kali). Simpan dengan aman.
  6. Tentukan URL dasar API Anda, biasanya: https://<your-domain>/api/v1
    • Contoh: https://snipeit.example.com/api/v1

Buat bucket Google Cloud Storage

  1. Buka Konsol Google Cloud.
  2. Pilih project Anda atau buat project baru.
  3. Di menu navigasi, buka Cloud Storage > Buckets.
  4. Klik Create bucket.
  5. Berikan detail konfigurasi berikut:

    Setelan Nilai
    Beri nama bucket Anda Masukkan nama yang unik secara global (misalnya, snipe-it-logs)
    Location type Pilih berdasarkan kebutuhan Anda (Region, Dual-region, Multi-region)
    Location Pilih lokasi (misalnya, us-central1)
    Kelas penyimpanan Standar (direkomendasikan untuk log yang sering diakses)
    Kontrol akses Seragam (direkomendasikan)
    Alat perlindungan Opsional: Aktifkan pembuatan versi objek atau kebijakan retensi
  6. Klik Create.

Buat akun layanan untuk fungsi Cloud Run

Cloud Run Function memerlukan akun layanan dengan izin untuk menulis ke bucket GCS.

Membuat akun layanan

  1. Di Konsol GCP, buka IAM & Admin > Service Accounts.
  2. Klik Create Service Account.
  3. Berikan detail konfigurasi berikut:
    • Nama akun layanan: Masukkan snipeit-assets-to-gcs-sa.
    • Deskripsi akun layanan: Masukkan Service account for Cloud Run function to collect Snipe-IT logs.
  4. Klik Create and Continue.
  5. Di bagian Grant this service account access to project:
    1. Klik Pilih peran.
    2. Telusuri dan pilih Storage Object Admin.
    3. Klik + Add another role.
    4. Telusuri dan pilih Cloud Run Invoker.
    5. Klik + Add another role.
    6. Telusuri dan pilih Cloud Functions Invoker.
  6. Klik Lanjutkan.
  7. Klik Done.

Peran ini diperlukan untuk:

  • Storage Object Admin: Menulis log ke bucket GCS dan mengelola file status
  • Cloud Run Invoker: Izinkan Pub/Sub memanggil fungsi
  • Cloud Functions Invoker: Mengizinkan pemanggilan fungsi

Memberikan izin IAM pada bucket GCS

Beri akun layanan izin tulis di bucket GCS:

  1. Buka Cloud Storage > Buckets.
  2. Klik nama bucket Anda.
  3. Buka tab Izin.
  4. Klik Grant access.
  5. Berikan detail konfigurasi berikut:
    • Tambahkan prinsipal: Masukkan email akun layanan (misalnya, snipeit-assets-to-gcs-sa@PROJECT_ID.iam.gserviceaccount.com).
    • Tetapkan peran: Pilih Storage Object Admin.
  6. Klik Simpan.

Membuat topik Pub/Sub

Buat topik Pub/Sub yang akan dipublikasikan oleh Cloud Scheduler dan akan dilanggan oleh fungsi Cloud Run.

  1. Di Konsol GCP, buka Pub/Sub > Topics.
  2. Klik Create topic.
  3. Berikan detail konfigurasi berikut:
    • ID Topik: Masukkan snipeit-assets-trigger.
    • Biarkan setelan lainnya sesuai default.
  4. Klik Create.

Membuat fungsi Cloud Run untuk mengumpulkan log

Fungsi Cloud Run dipicu oleh pesan Pub/Sub dari Cloud Scheduler untuk mengambil aset hardware dari Snipe-IT API dan menuliskannya ke GCS.

  1. Di Konsol GCP, buka Cloud Run.
  2. Klik Create service.
  3. Pilih Function (gunakan editor inline untuk membuat fungsi).
  4. Di bagian Konfigurasi, berikan detail konfigurasi berikut:

    Setelan Nilai
    Nama layanan snipeit-assets-to-gcs
    Region Pilih region yang cocok dengan bucket GCS Anda (misalnya, us-central1)
    Runtime Pilih Python 3.12 atau yang lebih baru
  5. Di bagian Pemicu (opsional):

    1. Klik + Tambahkan pemicu.
    2. Pilih Cloud Pub/Sub.
    3. Di Select a Cloud Pub/Sub topic, pilih topik (snipeit-assets-trigger).
    4. Klik Simpan.
  6. Di bagian Authentication:

    1. Pilih Wajibkan autentikasi.
    2. Periksa Identity and Access Management (IAM).
  7. Scroll ke bawah dan luaskan Containers, Networking, Security.

  8. Buka tab Security:

    • Akun layanan: Pilih akun layanan (snipeit-assets-to-gcs-sa).
  9. Buka tab Containers:

    1. Klik Variables & Secrets.
    2. Klik + Tambahkan variabel untuk setiap variabel lingkungan:
    Nama Variabel Nilai Contoh
    GCS_BUCKET snipe-it-logs
    GCS_PREFIX snipeit/assets
    SNIPE_BASE_URL https://snipeit.example.com/api/v1
    SNIPE_API_TOKEN your-api-token
    PAGE_SIZE 500
    MAX_PAGES 200
  10. Scroll ke bawah di tab Variables & Secrets ke Requests:

    • Waktu tunggu permintaan: Masukkan 600 detik (10 menit).
  11. Buka tab Setelan di Penampung:

    • Di bagian Referensi:
      • Memori: Pilih 512 MiB atau lebih tinggi.
      • CPU: Pilih 1.
    • Klik Done.
  12. Scroll ke Lingkungan eksekusi:

    • Pilih Default (direkomendasikan).
  13. Di bagian Penskalaan revisi:

    • Minimum number of instances: Masukkan 0.
    • Maximum number of instances: Masukkan 100 (atau sesuaikan berdasarkan perkiraan beban).
  14. Klik Create.

  15. Tunggu hingga layanan dibuat (1-2 menit).

  16. Setelah layanan dibuat, editor kode inline akan terbuka secara otomatis.

Menambahkan kode fungsi

  1. Masukkan main di Function entry point
  2. Di editor kode inline, buat dua file:

    • File pertama: main.py:

          import functions_framework
          from google.cloud import storage
          import json
          import os
          import urllib3
          from datetime import datetime, timezone
          import urllib.parse
      
          # Initialize HTTP client
          http = urllib3.PoolManager()
      
          # Initialize Storage client
          storage_client = storage.Client()
      
          @functions_framework.cloud_event
          def main(cloud_event):
              """
              Cloud Run function triggered by Pub/Sub to fetch hardware assets from Snipe-IT API and write to GCS.
      
              Args:
                  cloud_event: CloudEvent object containing Pub/Sub message
              """
      
              # Get environment variables
              bucket_name = os.environ.get('GCS_BUCKET')
              prefix = os.environ.get('GCS_PREFIX', 'snipeit/assets')
              base_url = os.environ.get('SNIPE_BASE_URL', '').rstrip('/')
              token = os.environ.get('SNIPE_API_TOKEN')
              page_size = int(os.environ.get('PAGE_SIZE', '500'))
              max_pages = int(os.environ.get('MAX_PAGES', '200'))
      
              if not all([bucket_name, base_url, token]):
                  print('Error: Missing required environment variables')
                  return
      
              try:
                  # Get GCS bucket
                  bucket = storage_client.bucket(bucket_name)
      
                  # Fetch and write pages
                  ts = datetime.now(timezone.utc)
                  offset = 0
                  page = 0
                  total = 0
      
                  headers = {
                      'Authorization': f'Bearer {token}',
                      'Accept': 'application/json',
                      'Content-Type': 'application/json'
                  }
      
                  while page < max_pages:
                      # Fetch page from Snipe-IT API
                      params = {
                          'limit': page_size,
                          'offset': offset,
                          'sort': 'id',
                          'order': 'asc'
                      }
                      qs = urllib.parse.urlencode(params)
                      url = f"{base_url}/hardware?{qs}"
      
                      print(f'Fetching page {page} from {url}')
      
                      response = http.request('GET', url, headers=headers, timeout=60.0)
      
                      if response.status != 200:
                          print(f'Error: API returned status {response.status}')
                          break
      
                      data = json.loads(response.data.decode('utf-8'))
      
                      # Get rows from response (Snipe-IT uses 'rows' field)
                      rows = data.get('rows', [])
                      total_available = data.get('total', 0)
      
                      # Write page to GCS
                      blob_name = f"{prefix}/{ts.strftime('%Y/%m/%d')}/snipeit-hardware-{page:05d}.json"
                      blob = bucket.blob(blob_name)
                      body = json.dumps(data, separators=(',', ':')).encode('utf-8')
                      blob.upload_from_string(body, content_type='application/json')
      
                      print(f'Wrote page {page} with {len(rows)} rows to {blob_name}')
      
                      total += len(rows)
      
                      # Check if we've reached the end
                      # Snipe-IT returns empty rows array when no more data
                      if len(rows) == 0:
                          print(f'No more results (empty rows array)')
                          break
      
                      # Also check if we've fetched all available records
                      if offset + len(rows) >= total_available:
                          print(f'Reached end of data (offset {offset + len(rows)} >= total {total_available})')
                          break
      
                      page += 1
                      offset += page_size
      
                  print(f'Successfully processed {page + 1} pages with {total} total objects')
      
              except Exception as e:
                  print(f'Error processing logs: {str(e)}')
                  raise
          ```
      
    • File kedua: requirements.txt:

      functions-framework==3.*
      google-cloud-storage==2.*
      urllib3>=2.0.0
      
  3. Klik Deploy untuk menyimpan dan men-deploy fungsi.

  4. Tunggu hingga deployment selesai (2-3 menit).

Buat tugas Cloud Scheduler

Cloud Scheduler memublikasikan pesan ke topik Pub/Sub secara berkala, yang memicu fungsi Cloud Run.

  1. Di Konsol GCP, buka Cloud Scheduler.
  2. Klik Create Job.
  3. Berikan detail konfigurasi berikut:

    Setelan Nilai
    Nama snipeit-assets-to-gcs-hourly
    Region Pilih region yang sama dengan fungsi Cloud Run
    Frekuensi 0 * * * * (setiap jam, tepat pada waktunya)
    Zona Waktu Pilih zona waktu (UTC direkomendasikan)
    Jenis target Pub/Sub
    Topik Pilih topik (snipeit-assets-trigger)
    Isi pesan {} (objek JSON kosong)
  4. Klik Create.

Opsi frekuensi jadwal

  • Pilih frekuensi berdasarkan volume log dan persyaratan latensi:

    Frekuensi Ekspresi Cron Kasus Penggunaan
    Setiap 5 menit */5 * * * * Volume tinggi, latensi rendah
    Setiap 15 menit */15 * * * * Volume sedang
    Setiap jam 0 * * * * Standar (direkomendasikan)
    Setiap 6 jam 0 */6 * * * Volume rendah, pemrosesan batch
    Harian 0 0 * * * Pengumpulan data historis

Menguji tugas penjadwal

  1. Di konsol Cloud Scheduler, temukan tugas Anda.
  2. Klik Jalankan paksa untuk memicu secara manual.
  3. Tunggu beberapa detik, lalu buka Cloud Run > Services > snipeit-assets-to-gcs > Logs.
  4. Pastikan fungsi berhasil dieksekusi.
  5. Periksa bucket GCS untuk mengonfirmasi bahwa log telah ditulis.

Mengambil akun layanan Google SecOps

Google SecOps menggunakan akun layanan unik untuk membaca data dari bucket GCS Anda. Anda harus memberi akun layanan ini akses ke bucket Anda.

Dapatkan email akun layanan

  1. Buka Setelan SIEM > Feed.
  2. Klik Tambahkan Feed Baru.
  3. Klik Konfigurasi satu feed.
  4. Di kolom Nama feed, masukkan nama untuk feed (misalnya, Snipe-IT logs).
  5. Pilih Google Cloud Storage V2 sebagai Source type.
  6. Pilih Snipe-IT sebagai Jenis log.
  7. Klik Get Service Account. Email akun layanan yang unik akan ditampilkan, misalnya:

    chronicle-12345678@chronicle-gcp-prod.iam.gserviceaccount.com
    
  8. Salin alamat email ini untuk digunakan di langkah berikutnya.

Memberikan izin IAM ke akun layanan Google SecOps

Akun layanan Google SecOps memerlukan peran Storage Object Viewer di bucket GCS Anda.

  1. Buka Cloud Storage > Buckets.
  2. Klik nama bucket Anda.
  3. Buka tab Izin.
  4. Klik Grant access.
  5. Berikan detail konfigurasi berikut:
    • Add principals: Tempel email akun layanan Google SecOps.
    • Tetapkan peran: Pilih Storage Object Viewer.
  6. Klik Simpan.

Mengonfigurasi feed di Google SecOps untuk menyerap log Snipe-IT

  1. Buka Setelan SIEM > Feed.
  2. Klik Tambahkan Feed Baru.
  3. Klik Konfigurasi satu feed.
  4. Di kolom Nama feed, masukkan nama untuk feed (misalnya, Snipe-IT logs).
  5. Pilih Google Cloud Storage V2 sebagai Source type.
  6. Pilih Snipe-IT sebagai Jenis log.
  7. Klik Berikutnya.
  8. Tentukan nilai untuk parameter input berikut:

    • URL bucket penyimpanan: Masukkan URI bucket GCS dengan jalur awalan:

      gs://snipe-it-logs/snipeit/assets/
      
      • Ganti:

        • snipe-it-logs: Nama bucket GCS Anda.
        • snipeit/assets: Jalur folder/awalan tempat log disimpan.
    • Opsi penghapusan sumber: Pilih opsi penghapusan sesuai preferensi Anda:

      • Jangan pernah: Tidak pernah menghapus file apa pun setelah transfer (direkomendasikan untuk pengujian).
      • Hapus file yang ditransfer: Menghapus file setelah transfer berhasil.
      • Hapus file yang ditransfer dan direktori kosong: Menghapus file dan direktori kosong setelah transfer berhasil.

    • Usia File Maksimum: Menyertakan file yang diubah dalam beberapa hari terakhir. Defaultnya adalah 180 hari.

    • Namespace aset: Namespace aset.

    • Label penyerapan: Label yang akan diterapkan ke peristiwa dari feed ini.

  9. Klik Berikutnya.

  10. Tinjau konfigurasi feed baru Anda di layar Selesaikan, lalu klik Kirim.

Tabel pemetaan UDM

Kolom log Pemetaan UDM Logika
created_at.datetime entity.asset.attribute.creation_time Diuraikan sebagai UNIX_MS
age entity.asset.attribute.labels.value Dipetakan secara langsung
alt_barcode entity.asset.attribute.labels.value Dipetakan secara langsung
asset_eol_date entity.asset.attribute.labels.value Dipetakan secara langsung
asset_tag entity.asset.attribute.labels.value Dipetakan secara langsung
asset_type_value entity.asset.attribute.labels.value Dipetakan secara langsung
assets_classification_value entity.asset.attribute.labels.value Dipetakan secara langsung
category.id entity.asset.attribute.labels.value Dipetakan secara langsung
custom_fields.RAM.value entity.asset.attribute.labels.value Dipetakan secara langsung
custom_fields.SSD.value entity.asset.attribute.labels.value Dipetakan secara langsung
last_update_time.formatted entity.asset.attribute.labels.value Dipetakan secara langsung
manufacturer.id entity.asset.attribute.labels.value Dipetakan secara langsung
model_id entity.asset.attribute.labels.value Dipetakan secara langsung
model_number entity.asset.attribute.labels.value Dipetakan secara langsung
updated_at.datetime entity.asset.attribute.last_update_time Diuraikan sebagai UNIX_MS
category.name entity.asset.category Dipetakan secara langsung
custom_fields.Processor.value entity.asset.hardware.cpu_model Dipetakan secara langsung
manufacturer.name entity.asset.hardware.manufacturer Dipetakan secara langsung
model.name entity.asset.hardware.model Dipetakan secara langsung
serial entity.asset.hardware.serial_number Dipetakan secara langsung
name entity.asset.hostname Dipetakan secara langsung
location.name entity.asset.location.name Dipetakan secara langsung
id entity.asset.product_object_id Dipetakan secara langsung
custom_fields.Owner.value entity.labels.value Dipetakan secara langsung
deleted_at entity.labels.value Dipetakan secara langsung
eol entity.labels.value Dipetakan secara langsung
expected_checkin entity.labels.value Dipetakan secara langsung
image entity.labels.value Dipetakan secara langsung
last_audit_date entity.labels.value Dipetakan secara langsung
next_audit_date.date entity.labels.value Dipetakan secara langsung
notes entity.labels.value Dipetakan secara langsung
order_number entity.labels.value Dipetakan secara langsung
purchase_cost entity.labels.value Dipetakan secara langsung
purchase_date.date entity.labels.value Dipetakan secara langsung
purchase_date.formatted entity.labels.value Dipetakan secara langsung
qr entity.labels.value Dipetakan secara langsung
requestable entity.labels.value Dipetakan secara langsung
requests_counter entity.labels.value Dipetakan secara langsung
rtd_location.id entity.labels.value Dipetakan secara langsung
status_label.id entity.labels.value Dipetakan secara langsung
status_label.status_meta entity.labels.value Dipetakan secara langsung
status_label.status_type entity.labels.value Dipetakan secara langsung
supplier.id entity.labels.value Dipetakan secara langsung
supplier.name entity.labels.value Dipetakan secara langsung
updated_at.formatted entity.labels.value Dipetakan secara langsung
warranty_expires.date entity.labels.value Dipetakan secara langsung
warranty_expires.formatted entity.labels.value Dipetakan secara langsung
warranty_months entity.labels.value Dipetakan secara langsung
assigned_to.username entity.user.attribute.labels.value Dipetakan secara langsung
available_actions.checkin entity.user.attribute.labels.value Dipetakan secara langsung
available_actions.checkout entity.user.attribute.labels.value Dipetakan secara langsung
available_actions.clone entity.user.attribute.labels.value Dipetakan secara langsung
available_actions.delete entity.user.attribute.labels.value Dipetakan secara langsung
available_actions.restore entity.user.attribute.labels.value Dipetakan secara langsung
available_actions.update entity.user.attribute.labels.value Dipetakan secara langsung
checkin_counter entity.user.attribute.labels.value Dipetakan secara langsung
checkout_counter entity.user.attribute.labels.value Dipetakan secara langsung
company.id entity.user.attribute.labels.value Dipetakan secara langsung
created_by.id entity.user.attribute.labels.value Dipetakan secara langsung
created_by.name entity.user.attribute.labels.value Dipetakan secara langsung
last_checkin.datetime entity.user.attribute.labels.value Dipetakan secara langsung
last_checkin.formatted entity.user.attribute.labels.value Dipetakan secara langsung
last_checkout.formatted entity.user.attribute.labels.value Dipetakan secara langsung
assigned_to.type entity.user.attribute.roles.name Dipetakan secara langsung
company.name entity.user.company_name Dipetakan secara langsung
assigned_to_email entity.user.email_addresses Digabung
assigned_to.employee_number entity.user.employee_id Dipetakan secara langsung
assigned_to.first_name entity.user.first_name Dipetakan secara langsung
last_checkout.datetime entity.user.last_login_time Diuraikan sebagai UNIX_MS
assigned_to.last_name entity.user.last_name Dipetakan secara langsung
assigned_to.name entity.user.user_display_name Dipetakan secara langsung
assigned_to.id entity.user.userid Dipetakan secara langsung
has_asset metadata.entity_type Dipetakan: true → ASSET
has_user metadata.entity_type Dipetakan: true → USER
has_asset metadata.product_name Dipetakan: true → CMDB
has_user metadata.product_name Dipetakan: true → CMDB
has_asset metadata.vendor_name Dipetakan: true → Snipe-IT
has_user metadata.vendor_name Dipetakan: true → Snipe-IT
T/A entity.asset.attribute.labels.key Konstanta: model_id
T/A entity.asset.platform_software.platform Konstanta: WINDOWS
T/A entity.labels.key Konstanta: purchase_date
T/A entity.user.attribute.labels.key Konstanta: checkout
T/A metadata.entity_type Konstanta: ASSET
T/A metadata.product_name Konstanta: CMDB
T/A metadata.vendor_name Konstanta: Snipe-IT

Log Perubahan

Melihat Log Perubahan untuk parser ini

Perlu bantuan lain? Dapatkan jawaban dari anggota Komunitas dan profesional Google SecOps.