Mengumpulkan log Proxy OAuth2
Dokumen ini menjelaskan cara menyerap log OAuth2 Proxy ke Google Security Operations menggunakan Google Cloud Storage V2.
OAuth2 Proxy adalah reverse proxy CNCF Sandbox yang menyediakan autentikasi menggunakan penyedia OAuth2/OIDC (Google, GitHub, Keycloak, Azure AD, dan lainnya) untuk memvalidasi akun berdasarkan email, domain, atau grup. Layanan ini menghasilkan log autentikasi (keberhasilan/kegagalan login), log permintaan (permintaan HTTP yang di-proxy dengan identitas pengguna), dan log aplikasi standar. Karena OAuth2 Proxy berjalan sebagai container di Kubernetes dan menulis semua log ke stdout, pengumpul log native Kubernetes (Fluentd) digunakan untuk meneruskan log ke bucket GCS untuk penyerapan Google SecOps.
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
- Cluster Kubernetes yang sedang berjalan dengan OAuth2 Proxy yang di-deploy (melalui diagram Helm atau deployment manual)
- Akses
kubectlke cluster Kubernetes dengan izin untuk membuat DaemonSet, ConfigMap, Secret, dan Namespace - Kunci JSON akun layanan GCP dengan izin
storage.objects.createdi bucket GCS target
Membuat bucket Google Cloud Storage
- Buka Konsol Google Cloud.
- Pilih project Anda atau buat project baru.
- Di menu navigasi, buka Cloud Storage > Buckets.
- Klik Create bucket.
Berikan detail konfigurasi berikut:
Setelan Nilai Beri nama bucket Anda Masukkan nama yang unik secara global (misalnya, oauth2-proxy-logs-bucket)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) Access control Seragam (direkomendasikan) Alat perlindungan Opsional: Aktifkan pembuatan versi objek atau kebijakan retensi Klik Create.
Mengonfigurasi logging Proxy OAuth2
OAuth2 Proxy menulis tiga jenis log ke stdout: log standar, log autentikasi, dan log permintaan. Ketiganya diaktifkan secara default. Untuk memastikan log berisi detail yang relevan dengan keamanan secara maksimal, konfigurasi OAuth2 Proxy dengan tanda logging berikut.
Opsi 1: Mengonfigurasi melalui nilai diagram Helm
Jika OAuth2 Proxy di-deploy menggunakan Helm chart resmi, tambahkan kode berikut ke file
values.yamlAnda:config: configFile: |- standard_logging = true auth_logging = true request_logging = true silence_ping_logging = true standard_logging_format = "[{{.Timestamp}}] [{{.File}}] {{.Message}}" auth_logging_format = "{{.Client}} - {{.RequestID}} - {{.Username}} [{{.Timestamp}}] [{{.Status}}] {{.Message}}" request_logging_format = "{{.Client}} - {{.RequestID}} - {{.Username}} [{{.Timestamp}}] {{.Host}} {{.RequestMethod}} {{.Upstream}} {{.RequestURI}} {{.Protocol}} {{.UserAgent}} {{.StatusCode}} {{.ResponseSize}} {{.RequestDuration}}"Terapkan nilai Helm yang diperbarui:
helm upgrade oauth2-proxy oauth2-proxy/oauth2-proxy -f values.yaml -n <your-namespace>
Opsi 2: Mengonfigurasi melalui tanda command line
Jika OAuth2 Proxy di-deploy menggunakan manifes Deployment Kubernetes, tambahkan argumen berikut ke spesifikasi container:
args: - --standard-logging=true - --auth-logging=true - --request-logging=true - --silence-ping-logging=true
Opsi 3: Mengonfigurasi melalui variabel lingkungan
Tetapkan variabel lingkungan berikut di container OAuth2 Proxy:
env: - name: OAUTH2_PROXY_STANDARD_LOGGING value: "true" - name: OAUTH2_PROXY_AUTH_LOGGING value: "true" - name: OAUTH2_PROXY_REQUEST_LOGGING value: "true" - name: OAUTH2_PROXY_SILENCE_PING_LOGGING value: "true"
Memverifikasi logging Proxy OAuth2
Setelah menerapkan konfigurasi, verifikasi bahwa OAuth2 Proxy menghasilkan log:
kubectl logs -l app=oauth2-proxy -n <your-namespace> --tail=20Output-nya mencakup baris yang mirip dengan berikut ini:
10.0.0.1 - abc123 - user@example.com [2024/01/15 10:30:00] [AuthSuccess] Authenticated via OAuth2 10.0.0.1 - abc123 - user@example.com [2024/01/15 10:30:01] example.com GET 10.0.0.5:8080 "/dashboard" HTTP/1.1 "Mozilla/5.0" 200 1234 0.005
Buat akun layanan GCP untuk Fluentd
Fluentd memerlukan akun layanan GCP dengan akses tulis ke bucket GCS.
- Di GCP Console, buka IAM & Admin > Service Accounts.
- Klik Create Service Account.
- Berikan detail konfigurasi berikut:
- Nama akun layanan: Masukkan
fluentd-gcs-writer - Deskripsi akun layanan: Masukkan
Service account for Fluentd to write OAuth2 Proxy logs to GCS
- Nama akun layanan: Masukkan
- Klik Create and Continue.
- Di bagian Berikan akun layanan ini akses ke project:
- Klik Pilih peran.
- Telusuri dan pilih Storage Object Admin.
- Klik Lanjutkan.
- Klik Done.
Membuat dan mendownload kunci akun layanan
- Di daftar Service Accounts, klik akun layanan
fluentd-gcs-writer. - Buka tab Kunci.
- Klik Tambahkan Kunci > Buat kunci baru.
- Pilih JSON sebagai jenis kunci.
- Klik Create.
- Simpan file kunci JSON yang didownload dengan aman. File ini akan digunakan pada langkah berikutnya.
Buat secret Kubernetes untuk kunci akun layanan
Buat secret Kubernetes yang berisi kunci akun layanan GCP di namespace tempat Fluentd akan di-deploy:
kubectl create namespace logging kubectl create secret generic fluentd-gcs-key \ --from-file=service-account-key.json=<path-to-downloaded-key>.json \ -n logging
Men-deploy DaemonSet Fluentd untuk mengumpulkan log Proxy OAuth2
Deploy Fluentd sebagai DaemonSet di cluster Kubernetes untuk mengumpulkan log container dari pod OAuth2 Proxy dan meneruskannya ke bucket GCS.
Buat ConfigMap Fluentd
Buat file bernama
fluentd-configmap.yamldengan konten berikut:apiVersion: v1 kind: ConfigMap metadata: name: fluentd-gcs-config namespace: logging data: fluent.conf: | <source> @type tail read_from_head true tag kubernetes.* path /var/log/containers/*oauth2-proxy*.log pos_file /var/log/fluentd-oauth2-proxy.log.pos <parse> @type regexp expression /^(?<time>[^ ]+) (?<stream>stdout|stderr) [^ ]* (?<log>.*)$/ time_format %Y-%m-%dT%H:%M:%S.%N%z </parse> </source> <filter kubernetes.**> @type kubernetes_metadata @id filter_kube_metadata </filter> <match kubernetes.**> @type gcs project YOUR_GCP_PROJECT_ID keyfile /etc/secrets/service-account-key.json bucket oauth2-proxy-logs-bucket path oauth2-proxy-logs/%Y/%m/%d/ object_key_format %{path}%{time_slice}_%{hostname}_%{index}.%{file_extension} <buffer tag,time> @type file path /var/log/fluentd/gcs timekey 300 timekey_wait 60 timekey_use_utc true chunk_limit_size 10MB </buffer> <format> @type json </format> </match>
Ganti nilai berikut:
YOUR_GCP_PROJECT_ID: Project ID GCP Anda (misalnya,my-project-123456)oauth2-proxy-logs-bucket: Nama bucket GCS yang dibuat sebelumnyaTerapkan ConfigMap:
kubectl apply -f fluentd-configmap.yaml
Buat DaemonSet Fluentd
Buat file bernama
fluentd-daemonset.yamldengan konten berikut:apiVersion: apps/v1 kind: DaemonSet metadata: name: fluentd-gcs namespace: logging labels: k8s-app: fluentd-gcs spec: selector: matchLabels: k8s-app: fluentd-gcs template: metadata: labels: k8s-app: fluentd-gcs spec: tolerations: - key: node-role.kubernetes.io/control-plane effect: NoSchedule - key: node-role.kubernetes.io/master effect: NoSchedule containers: - name: fluentd-gcs image: fluent/fluentd-kubernetes-daemonset:v1-debian-gcs resources: limits: memory: 512Mi requests: cpu: 100m memory: 200Mi volumeMounts: - name: fluentd-gcs-config-volume mountPath: /fluentd/etc/fluent.conf subPath: fluent.conf readOnly: true - name: fluentd-gcs-secrets-volume mountPath: /etc/secrets/service-account-key.json subPath: service-account-key.json readOnly: true - name: varlog mountPath: /var/log - name: dockercontainerlogdirectory mountPath: /var/log/pods readOnly: true - name: fluentd-buffer mountPath: /var/log/fluentd terminationGracePeriodSeconds: 30 volumes: - name: fluentd-gcs-config-volume configMap: name: fluentd-gcs-config - name: fluentd-gcs-secrets-volume secret: secretName: fluentd-gcs-key - name: varlog hostPath: path: /var/log - name: dockercontainerlogdirectory hostPath: path: /var/log/pods - name: fluentd-buffer emptyDir: {}Terapkan DaemonSet:
kubectl apply -f fluentd-daemonset.yaml
Memverifikasi deployment Fluentd
Pastikan pod Fluentd berjalan di setiap node:
kubectl get pods -n logging -l k8s-app=fluentd-gcsPeriksa log Fluentd untuk penulisan GCS yang berhasil:
kubectl logs -l k8s-app=fluentd-gcs -n logging --tail=20Pastikan file log muncul di bucket GCS:
- Buka Cloud Storage > Buckets di GCP Console.
- Klik bucket (misalnya,
oauth2-proxy-logs-bucket). - Buka folder
oauth2-proxy-logs/. - Pastikan file
.jsonada dengan stempel waktu terbaru.
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
- Buka Setelan SIEM > Feed.
- Klik Tambahkan Feed Baru.
- Klik Konfigurasi satu feed.
- Di kolom Nama feed, masukkan nama untuk feed (misalnya,
OAuth2 Proxy Logs). - Pilih Google Cloud Storage V2 sebagai Source type.
- Pilih Kubernetes Auth Proxy sebagai Jenis log.
Klik Get Service Account. Email akun layanan yang unik akan ditampilkan, misalnya:
chronicle-12345678@chronicle-gcp-prod.iam.gserviceaccount.comSalin alamat email ini untuk digunakan di langkah berikutnya.
Klik Berikutnya.
Tentukan nilai untuk parameter input berikut:
URL bucket penyimpanan: Masukkan URI bucket GCS dengan jalur awalan:
gs://oauth2-proxy-logs-bucket/oauth2-proxy-logs/Ganti
oauth2-proxy-logs-bucketdengan nama bucket GCS Anda.
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
Klik Berikutnya.
Tinjau konfigurasi feed baru Anda di layar Selesaikan, lalu klik Kirim.
Memberikan izin IAM ke akun layanan Google SecOps
Akun layanan Google SecOps memerlukan peran Storage Object Viewer di bucket GCS Anda.
- Buka Cloud Storage > Buckets.
- Klik nama bucket Anda (misalnya,
oauth2-proxy-logs-bucket). - Buka tab Izin.
- Klik Grant access.
- Berikan detail konfigurasi berikut:
- Add principals: Tempel email akun layanan Google SecOps (misalnya,
chronicle-12345678@chronicle-gcp-prod.iam.gserviceaccount.com) - Tetapkan peran: Pilih Storage Object Viewer
- Add principals: Tempel email akun layanan Google SecOps (misalnya,
- Klik Simpan.
Referensi log OAuth2 Proxy
Tabel berikut menjelaskan kolom log yang dihasilkan oleh OAuth2 Proxy dan relevansi keamanannya:
Kolom log autentikasi
| Kolom | Contoh | Deskripsi |
|---|---|---|
| Klien | 10.0.0.1 |
Alamat IP klien/jarak jauh (menggunakan header X-Real-IP jika --reverse-proxy=true) |
| RequestID | 00010203-0405-4607-8809-0a0b0c0d0e0f |
ID permintaan dari header X-Request-Id (UUID acak jika kosong) |
| Nama pengguna | user@example.com |
Email atau nama pengguna permintaan autentikasi |
| Stempel waktu | 2024/01/15 10:30:00 |
Tanggal dan waktu peristiwa autentikasi |
| Status | AuthSuccess |
Hasil autentikasi: AuthSuccess, AuthFailure, atau AuthError |
| Pesan | Authenticated via OAuth2 |
Detail upaya autentikasi |
Kolom log permintaan
| Kolom | Contoh | Deskripsi |
|---|---|---|
| Klien | 10.0.0.1 |
Alamat IP klien/jarak jauh |
| RequestID | 00010203-0405-4607-8809-0a0b0c0d0e0f |
ID Permintaan |
| Nama pengguna | user@example.com |
Email pengguna yang diautentikasi |
| Stempel waktu | 2024/01/15 10:30:01 |
Tanggal dan waktu permintaan |
| Host | app.example.com |
Nilai header Host |
| RequestMethod | GET |
Metode permintaan HTTP |
| Upstream | 10.0.0.5:8080 |
Server upstream yang menangani permintaan |
| RequestURI | /dashboard |
Jalur URI permintaan |
| Protokol | HTTP/1.1 |
Protokol permintaan |
| UserAgent | Mozilla/5.0 |
String agen pengguna lengkap |
| StatusCode | 200 |
Kode status respons HTTP |
| ResponseSize | 1234 |
Ukuran respons dalam byte |
| RequestDuration | 0.005 |
Waktu pemrosesan permintaan dalam detik |
Tabel pemetaan UDM
| Kolom Log | Pemetaan UDM | Logika |
|---|---|---|
| tentang | tentang | Informasi tentang acara |
| http_req_id_field | additional.fields | Kolom tambahan yang tidak tercakup dalam skema UDM standar |
| http_req_path_field | additional.fields | |
| k8s_pod_app_field | additional.fields | |
| k8s_pod_template_hash_field | additional.fields | |
| k8s_pod_tls_mode_field | additional.fields | |
| k8s_pod_canonical_revision_field | additional.fields | |
| k8s_pod_canonical_name_field | additional.fields | |
| pod_name | additional.fields | |
| cntnr_name | additional.fields | |
| destination_canonical_revision | additional.fields | |
| requested_server | additional.fields | |
| nodename_label | additional.fields | |
| componentName_label | additional.fields | |
| componentVersion_label | additional.fields | |
| azureResourceID_label | additional.fields | |
| producer_label | additional.fields | |
| first_label | additional.fields | |
| last_label | additional.fields | |
| meta_name | additional.fields | |
| resource_version_label | additional.fields | |
| request_apiVersion | additional.fields | |
| request_kind_label | additional.fields | |
| request_type_label | additional.fields | |
| response_apiVersion | additional.fields | |
| response_kind_label | additional.fields | |
| response_type_label | additional.fields | |
| jsonPayload.message | metadata.description | Deskripsi peristiwa |
| event_type | metadata.event_type | Jenis acara |
| labels.request_id | metadata.product_log_id | ID log khusus produk |
| insertId | metadata.product_log_id | |
| jsonPayload.chartVersion | metadata.product_version | Versi produk |
| httpRequest.protocol | network.application_protocol | Protokol aplikasi yang digunakan dalam koneksi jaringan |
| network.direction | network.direction | Arah traffic jaringan |
| httpRequest.requestMethod | network.http.method | Metode HTTP |
| http_method | network.http.method | |
| httpRequest.status | network.http.response_code | Kode respons HTTP |
| httpRequest.userAgent | network.http.user_agent | Agen pengguna HTTP |
| requestMetadata.callerSuppliedUserAgent | network.http.user_agent | |
| labels.protocol | network.ip_protocol | Protokol IP |
| httpRequest.responseSize | network.received_bytes | Jumlah byte yang diterima |
| labels.total_received_bytes | network.received_bytes | |
| httpRequest.requestSize | network.sent_bytes | Jumlah byte yang dikirim |
| labels.total_sent_bytes | network.sent_bytes | |
| jsonPayload.session | network.session_id | ID sesi |
| labels.service_authentication_policy | network.tls.cipher | Cipher suite TLS |
| utama | utama | Entitas utama yang terlibat dalam peristiwa |
| principal_hostname | principal.hostname | Nama host utama |
| prin_userid | principal.user.userid | ID pengguna prinsipal |
| security_result | security_result | Hasil evaluasi keamanan |
| target | target | Entitas target yang terlibat dalam acara |
| target_hostname | target.hostname | Nama host target |
| resource_sub_type | target.resource.resource_subtype | Subjenis resource target |
| target_userid | target.user.userid | ID pengguna target |
| metadata.product_name | metadata.product_name | Nama produk |
| metadata.vendor_name | metadata.vendor_name | Nama vendor |
Log Perubahan
Melihat Log Perubahan untuk parser ini
Perlu bantuan lain? Dapatkan jawaban dari anggota Komunitas dan profesional Google SecOps.