QueryProxy
Doküman menüsü

Sorun giderme

queryproxy:doctor ile başlayın, her kontrolü okuyun ve operatörlerin en sık karşılaştığı hataları giderin; takılan taleplerden TLS ve secret sorunlarına.

Güncelleme:

Doctor ile başlayın. Kurulumu okur ve loglarda kazı yapmadan önce neyin yanlış olduğunu söyler.

docker exec queryproxy php artisan queryproxy:doctor

Docker olmadan, uygulama dizininde php artisan queryproxy:doctor çalıştırın.

Doctor çıktısını okuma

Komut, her biri bir durum taşıyan kontrollerden oluşan bir tablo basar:

Durum Anlamı
ok Kontrol geçti
warn Dikkat edilmesi gereken bir şey var; çalıştırma yine de 0 ile çıkar
fail Kurulumu bozan ya da tehlikeye atan bir sorun; çalıştırma 1 ile çıkar
skip Kontrol uygulanmıyor (hiçbir SIEM sink’i açık değil, cache ya da kuyruk kontrolün okuyabileceği türde değil, vb.)

Seçenekler:

  • --strict uyarıların da 1 ile çıkmasını sağlar. Deploy pipeline’ında kullanın.
  • --full-audit tüm denetim zincirini dolaşır. Onsuz doctor en yeni kayıtları ve zincirin başını kontrol eder; bu daha hızlıdır.
  • --json betikler için {"ok": …, "strict": …, "checks": […]} basar.

Doctor yalnızca okur. Kurulumda hiçbir şeyi değiştirmez.

Her kontrol ne anlama gelir

Kontrol ok değilse şunu yapın
app_environment fail: APP_ENV=production iken APP_DEBUG açık. warn: başka bir ortamda açık. APP_DEBUG’ı kapatın
app_key fail: anahtar eksik ya da bozuk ya da geçerli ama saklanan kimlik bilgilerinin şifresini çözemiyor; yani anahtar değişmiş. Eski anahtarı geri getirin ya da APP_PREVIOUS_KEYS içine yazın
app_key_location warn: APP_KEY dosyası SQLite veritabanıyla aynı volume’de. APP_KEY ya da APP_KEY_FILE’ı volume’ün dışından verin
database fail: uygulama veritabanına ulaşılamıyor ya da bekleyen migration’lar var. php artisan migrate --force çalıştırın
queue_timing fail: kuyruğun retry_after değeri işçi timeout’undan büyük değil; bu yüzden uzun bir sorgu ikinci kez başlatılır. retry_after’ı yükseltin ya da QUERYPROXY_EXECUTION_TIMEOUT’u düşürün
worker warn: işler çalıştırma timeout’u artı bir dakikadan uzun süre beklemiş; çalışan bir kuyruk işçisi yok gibi. php artisan queue:work --queue=queries,default başlatın. fail: kuyruk tablosu yok, php artisan migrate --force çalıştırın. skip: yalnızca database kuyruğunu ölçer
scheduler warn: heartbeat yok ya da eski. php artisan schedule:work başlatın. Başlatmanın hemen ardından bir dakika bekleyin
failed_jobs warn: işler başarısız oldu. php artisan queue:failed ile inceleyin; başarısız SIEM teslimleri de buraya düşer
storage_permissions fail: storage/ altındaki bir yol, QueryProxy’yi çalıştıran kullanıcı tarafından yazılamıyor
result_disk fail: QUERYPROXY_RESULT_DISK’in adını verdiği disk yok ya da herkese açık. Özel bir disk kullanın
trusted_proxies fail: TRUSTED_PROXIES * ya da başka bir hepsini-kapsar değer (**, 0.0.0.0/0, ::/0). Vekilin IP’lerini ya da CIDR’larını yazın. 10.0.0.0/8 gibi geniş ama geçerli bir aralık geçer; bu yüzden ağınızın izin verdiği kadar dar tutun
sqlite_allowed_dir warn: SQLite bağlantıları var ve QUERYPROXY_SQLITE_ALLOWED_DIR boş ya da var olmayan bir dizine işaret ediyor. SQLite bağlantısı ve ayar yoksa kontrol ok olur
masking_coverage warn: bir takımın etkin maskeleme kuralı yok, dolayısıyla sonuçları maskelenmiyor. Maskeleme sayfasında varsayılan kuralları kurun
tls_enforcement warn: bazı bağlantılar TLS istemiyor (bkz. TLS hataları). Onları düzenleyip TLS’i zorunlu kılın
tls_files fail: saklanan bir PEM’in şifresi çözülemiyor, genellikle anahtar değiştiği için. warn: storage/app/tls altındaki dosyaların izinleri yanlış
secret_files fail: bir *_FILE değişkeni okunamıyor, boş ya da düz karşılığıyla birlikte ayarlanmış
metrics warn: token 24 karakterden kısa ya da QUERYPROXY_METRICS_ALLOWED_IPS IP adresi ya da CIDR aralığı olmayan bir girdi içeriyor (asla eşleşmez). fail: token’ın _FILE’ı okunamıyor. skip: /metrics kapalı
siem_sinks fail: yapılandırılmış bir sink kullanılmayacak, dolayısıyla denetim olayları dışa aktarılmıyor. warn: düz http:// üzerinde bir webhook ya da UDP üzerinden syslog (şifresiz ve onaysız); --strict bunları çalıştırmanın başarısızlığına çevirir
audit_chain fail: zincir kopuk ya da kayıtlar kaldırılmış. php artisan audit:verify çalıştırın

Talepler

Bir talep queued kalıyor

Olasılık sırasına göre üç neden:

  1. İşçi yok. Doctor’ın worker kontrolü uyarır. İşçiyi başlatın ya da konteynerde QUERYPROXY_RUN_WORKER=true ayarlayın.
  2. Her bağlantı slot’u meşgul. Bir bağlantıda aynı anda en fazla QUERYPROXY_CONNECTION_SLOTS talep (varsayılan 2) çalışır; geri kalanlar bekler ve kendiliğinden başlar. Denetim günlüğü reason=connection_slots_busy ile request.execution_deferred gösterir ve queryproxy_slot_deferred_requests_total metriği bunu sayar. Hedef veritabanı daha fazlasını kaldırabiliyorsa ayarı yükseltin ya da 0 yapın.
  3. İşçi yanlış kuyruğu dinliyor. queries ve default kuyruklarına hizmet etmelidir: --queue=queries,default.

Bir okuma “tried to change data” ile başarısız oluyor

Mesaj şöyledir: This statement tried to change data, but read requests run in a read-only database session. Submit it as a write request if the change is intended. Veritabanı, salt okunur oturum içindeki bir yazmayı reddetti. PostgreSQL’de buna SELECT … FOR UPDATE ve FOR SHARE da dahildir. İfadeyi yazma olarak gönderin ya da kilit ifadesini kaldırın.

Veritabanı bağlantıyı düşürdükten sonra bir okuma başarısız oluyor

Bir ifade başladıktan sonra QueryProxy yeniden bağlanmaz; bu yüzden kısa bir ağ kopması çalıştırmayı başarısız kılar. Talebi yeniden gönderin.

MySQL’de bir yazma çalıştırma timeout’unu aşıyor

Veritabanı tarafı statement timeout’u MySQL’de yalnızca SELECT’e ulaşır (MAX_EXECUTION_TIME); bu yüzden uzun bir MySQL yazması veritabanı tarafından kesilmez. İş QUERYPROXY_EXECUTION_TIMEOUT dolunca biter ve talep başarısız olur; yazma yine de sunucuda çalışmış olabilir. Daha erken iptal etmek için Stop query kullanın.

“Stop query”, sorgunun sinyallenemediğini söylüyor

Talep cancelled olarak işaretlenir, ancak veritabanı iptal sinyalini almamıştır ve ifade timeout’unda sona erer. Düğme yalnızca veritabanı oturumu bilinen çalışan bir talep için görünür, SQLite için görünmez. Bağlantının kullanıcısının ihtiyaç duyduğu yetkileri kontrol edin:

  • PostgreSQL: aynı kullanıcı ya da pg_signal_backend rolü.
  • MySQL ve MariaDB: aynı kullanıcı ya da CONNECTION_ADMIN. Yalnızca ifade iptal edilir.
  • SQL Server: VIEW SERVER STATE (onsuz çalıştırmanın oturumu kontrol bağlantısına görünmez) ve ALTER ANY CONNECTION (KILL buna ihtiyaç duyar). SQL Server’da Stop oturumu sonlandırır ve açık bir transaction sunucuda geri alınır.

Chat’teki SQL önizlemesi “SQL hidden” diyor

İfade güvenle redakte edilemedi, bu yüzden önizleme gösterilmiyor. QUERYPROXY_CHAT_INCLUDE_SQL=none önizlemeyi her yerde gizler; full ifadeyi gönderildiği gibi gösterir.

TLS hataları

v0.3.0’da oluşturulan bir bağlantı TLS ister ve sunucu sunmuyorsa başarısız olur. Bağlantı testi sonucunu okuyun: TLS durumunu gösterir.

Belirti Neden ve çözüm
PostgreSQL: server does not support SSL, but SSL was required Sunucuda TLS yok. Sunucuda etkinleştirin. Yalnızca tamamen güvendiğiniz bir ağda, düz metne izin veren prefer ya da disable seçeneğini bağlantının SSL modunda seçin
MySQL veya MariaDB: bağlantı handshake’ten hemen sonra kapanıyor (hata 2006) Sunucu TLS sunmuyor. Sunucuda etkinleştirin
PostgreSQL verify-full ya da MySQL “Verify the server certificate” başarısız oluyor Sunucu sertifikası yapıştırdığınız CA’ya zincirlenmiyor ya da adı host’la eşleşmiyor. Doğru CA PEM’ini yapıştırın; verify-full için host sertifikayla eşleşmelidir
SQL Server: sertifika hatası Sunucu sertifikası güvenilen bir CA’dan değil. CA’yı QueryProxy host’una kurun ya da self-signed bir sertifika için TrustServerCertificate’i bilerek açın
SQL Server: pdo_sqlsrv eksik diyen RuntimeException TLS zorunlu bir SQL Server bağlantısı pdo_sqlsrv eklentisine ihtiyaç duyar. Onsuz Laravel şifresiz bir dblib bağlantısına düşerdi; bu yüzden QueryProxy bağlanmayı reddeder

Yükseltmeden önceki bağlantılar eski davranışını korur; tls_enforcement onları listeler.

Chat

Bir Slack ya da Teams düğmesi “has expired” diyor

this button has expired. Use the button in the newer message mesajı, talep hâlâ pending iken o kartın 24 saatlik action token’ının bittiği anlamına gelir. Talepler süresi dolup düşmez; talebi QueryProxy’de açın ya da yeni token’lı bir kart gönderen hatırlatmayı bekleyin (bkz. QUERYPROXY_PENDING_REMIND_AFTER).

Teams hiçbir şey almıyor ya da flow boş alanlar okuyor

Önce webhook host’unu kontrol edin. *.powerplatform.com ve *.logic.azure.com bir Adaptive Card alır; eski connector URL’leri (*.webhook.office.com ve allowlist’e eklediyseniz outlook.office.com) MessageCard alır. Bir Workflows URL’sinden eski MessageCard alanlarını okuyan özel bir flow boş değerler alır. Bkz. Teams entegrasyonu. Allowlist dışındaki bir host reddedilir; onu QUERYPROXY_CHAT_WEBHOOK_ALLOWED_HOSTS ile genişletin.

Slack Approve bir web formuna bağlantıyla yanıt veriyor

O tıklama bir admin override olurdu ve override’lar her kanalda yazılı bir gerekçe ister. Hiçbir şey onaylanmadı; bağlantıyı açın ve gerekçeyi doldurun.

İzleme ve dışa aktarım

/metrics 404, 401 ya da 400 yanıtı veriyor

  • 404: kapalı. QUERYPROXY_METRICS_TOKEN ya da QUERYPROXY_METRICS_ALLOWED_IPS ayarlayın.
  • 401: yanlış token ya da istemci adresi allowlist’te değil. Bir ters vekilin arkasında, TRUSTED_PROXIES ayarlamadığınız sürece adres vekilin adresidir.
  • 400: scrape’in Host başlığı APP_URL’in host’u değil ve TRUSTED_HOSTS içinde de değil. Scrape yapılandırmasında Host başlığını ayarlayın ya da adı listeye ekleyin.

Bkz. İzleme.

SIEM olayları ulaşmıyor

  1. Doctor’ı çalıştırın; siem_sinks kullanılmayacak bir sink’i adıyla söyler (16 karakterlik secret’ı olmayan bir webhook asla imzasız gönderilmez).
  2. SIEM kuyruğu için bir işçi çalıştırın. Varsayılan, hazır işçinin hizmet verdiği default’tur; özel bir QUERYPROXY_SIEM_QUEUE kendi işçisine ihtiyaç duyar.
  3. php artisan queue:failed’e bakın. Yeniden deneme hakkını tüketen bir teslim oraya düşer.

Teslim en az bir kez yapılır, bu yüzden alıcılar id üzerinden tekilleştirme yapmalıdır.

Secret’lar ve açılış

Konteyner “Both X and X_FILE are set” ile çıkıyor

İkisinden yalnızca birini tanımlayın. null, (null) ya da (empty) olarak ayarlanmış düz bir değişken ayarlanmamış sayılır. Mesaj değişkenin ve yolun adını verir, değeri asla vermez.

Konteyner “X_FILE points at … which is not a readable file” ile çıkıyor

Secret’ı o yola bağlayın ve konteynerin çalıştığı kullanıcının okuyabileceği şekilde yapın. Boş dosya da reddedilir. Sondaki satır sonları kırpılır; başka hiçbir şey kırpılmaz.

Yeniden başlatmadan sonra saklanan kimlik bilgileri okunamıyor

APP_KEY değişti. Özgün anahtarı geri getirin ya da APP_PREVIOUS_KEYS içine yazın. Bkz. Yedekleme ve geri yükleme.

Dosyadan okunan bir secret yine de yapılandırma cache’inde görünüyor

php artisan config:cache, dosyalardan okunan secret’lar dahil her yapılandırma değerini bootstrap/cache/config.php içine düz metin olarak yazar. Cache her zaman böyle çalışmıştır ve *_FILE’ın amacını kısmen boşa çıkarır. Image her açılışta yapılandırmayı yeniden cache’ler. O yolu diğer kullanıcılara kapalı tutun ve paylaşılan image’ların ve yedeklerin dışında bırakın.

Yükseltme ve veritabanı

Migration 1419 hatasıyla başarısız oluyor

MySQL ya da MariaDB denetim trigger’larını oluşturmayı reddetti. Migration kullanıcısı TRIGGER yetkisine ve binary logging açıksa SUPER ya da log_bin_trust_function_creators=1 değerine ihtiyaç duyar. Bkz. Yükseltme.

audit:verify bir kopukluk bildiriyor

audit:verify ilk bozuk kaydı ve nedenini söyler: hash taşımayan, kendinden öncekine bağlanmayan, hash’iyle eşleşmeyen bir kayıt; zinciri başlatmayan bir ilk kayıt; yazılan kayıt sayısından farklı bir uzunluk ya da kaydedilmiş olandan farklı bir zincir başı. Harekete geçmeden önce zinciri SIEM kopyanızla karşılaştırın; bkz. Denetim zinciri ve SIEM dışa aktarımı.

Bir MySQL talebi sql_mode mesajıyla reddediliyor

Hedef oturumun sql_mode değeri, guard’ın farklı okuduğu NO_BACKSLASH_ESCAPES ya da ANSI_QUOTES içeriyor. Bkz. Yapılandırma.

Sonraki adımlar

Gezinmek için ok tuşları, açmak için Enter.