[{"content":" GÜNLÜK TEKNOLOJİ BÜLTENİ // 2026-10-15\nBu bülten, Canlı Teknoloji Radarı üzerinde toplanan 30+ otoriter kaynaktan derlenmiş; yapay zekâ, küresel teknoloji, donanım mimarileri, çekirdek ve güvenlik alanlarındaki en kritik gelişmeleri içerir.\n🐧 Kernel.org Canlı Takipçisi: Mainline: 7.3-rc7 | Stable: 7.2.11 | LTS: 6.18.57\n🤖 Yapay Zekâ, Büyük Dil Modelleri \u0026amp; Model Mimarileri How Third Moment Research runs 10,000 agents for 36+ hours (OpenAI Newsroom)\nWith GPT-6 Astra and GPT-6.1 Sol, Codex, and Daybreak for cybersecurity, this AI lab builds agents that focus for days and improve with use. Claude Code / AI Shows Potential For Reverse-Engineering Hardware For Linux Support (Phoronix Hardware)\nAI/LLMs like Claude Code are beginning to prove capable of helping to reverse engineer hardware for Linux support, especially when it comes to the tedious reverse engineering tasks\u0026hellip; Amp puts AI agents to work beyond code with OpenAI models (OpenAI Newsroom)\nSee how Amp pushes the frontier of what agents can do with GPT-6 Astra, Ultrafast, GPT-Live-1, and Sign in with ChatGPT. Run fast, private agents on-device with LFM2.5-24B-A2B (Hugging Face Blog)\nRun fast, private agents on-device with LFM2.5-24B-A2B ⚡ Küresel Teknoloji, Yazılım Mimarisi \u0026amp; Ekosistem Friends don’t let friends feed their data to AI agents (The Verge Tech)\nThere\u0026rsquo;s a growing trend in the consumer tech world: gadgets designed to spy on everything and everyone around you, regardless of whether or not anyone else actually consented to it. Turn one giant AI-generated pull request to a reviewable stack (GitHub Engineering)\nInstead of one huge, un-reviewable pull request, teach coding agents to decompose work into a clean, ordered stack with GitHub stacked pull requests. Instagram Modernized Its UI with an AI-Native Architecture, Cutting Token Costs by 33% (InfoQ Architecture)\nInstagram Direct migrated its Android UI from the legacy Android View system to Jetpack Compose, creating an AI-native UI codebase that is easier for AI coding agents to understand, modify, and maintain. AI agents are coming to Rivian’s cars (TechCrunch)\nWe\u0026rsquo;ll likely learn more about how this will work at the company\u0026rsquo;s upcoming \u0026ldquo;AI \u0026amp; Autonomy Day\u0026rdquo; event in December. 🖥️ Donanım, Çipler \u0026amp; Hesaplama Mimarisi Huawei Proposes Enabling CPU Boost By Default For ACPI CPPC Linux Driver (Phoronix Hardware)\nFor those using the generic ACPI Collaborative Processor Performance Control (CPPC) CPUFreq driver such as on a number of ARM64 Linux server platforms, if the CPUs support a \u0026ldquo;boost\u0026rdquo; mode it\u0026rsquo;s disabled by default. Intel’s Crescent Island AI Server GPU Gets a Name and Specs: Meet the Intel GPU D-Series (ServeTheHome · Tartışma)\nIntel today has unveiled its official performance specifications and branding for its upcoming \u0026ldquo;Crescent Island\u0026rdquo; data center AI inference cards. SPECviewperf 15.0.1 Linux Edition Released: Linux’s Key Graphics Benchmark Adds Arm Support (ServeTheHome · Tartışma)\nSPEC has released version 15.0.1 of SPECviewperf Linux Edition, bringing a slew of upgrades and official Arm support to Linux\u0026rsquo;s key workstation graphics benchmark suite. We are taking a look at those changes, and what performance is like on some modern systems 🚨 Kritik Güvenlik ve CVE Uyarıları [KRİTİK TEHDİT] Palo Alto Networks Patches PAN-OS Authenticated RCE Flaw Amid Active Exploitation Kaynak: The Hacker News | Skor: 10/10 Özet: Palo Alto Networks on Wednesday issued security updates for a high-severity flaw in PAN-OS software that has come under active exploitation. [CVE-2026-0322] Palo Alto Networks warns of PAN-OS RCE flaw exploited in attacks Kaynak: BleepingComputer | Skor: 10/10 Özet: Palo Alto Networks has released security updates for a high-severity PAN-OS RCE zero-day, tracked as CVE-2026-0322, that has been exploited in attacks targeting firewalls. [KRİTİK TEHDİT] Microsoft Patches Record 1,413 Flaws, Including Exploited Windows Shell Bug Kaynak: The Hacker News | Skor: 10/10 Özet: Microsoft on Tuesday shattered its own Patch Tuesday record by shipping patches for a whopping 1,413 vulnerabilities, including one that it said has come under active exploitation. [CVE-2026-39919] Ghostscript flaw lets hackers hijack servers via PDF uploads Kaynak: BleepingComputer | Skor: 10/10 Özet: A critical heap buffer overflow vulnerability (CVE-2026-39919) in the Ghostscript interpreter and rendering engine could allow remote code execution through specially crafted PDF files. 🐧 Linux Çekirdeği ve Sistem Mühendisliği Apple Contributes SSAF Driver To LLVM Clang For Source Code Transformations (Phoronix Hardware)\nApple compiler engineers have contributed to upstream LLVM/Clang today a Scalable Static Analysis Framework (SSAF) driver for whole-program based analysis and source-to-source code transformations\u0026hellip; Cloud Hypervisor 54 Released With Live Migration Improvements (Phoronix)\nCloud Hypervisor, the Rust-based Virtual Machine Monitor that began as an Intel open-source project and evolved into a multi-vendor Linux Foundation project, is out today with a sizable feature update\u0026hellip; Rustls 0.23.46 Released With Four Security Fixes (Phoronix)\nRustls as the modern TLS library written in the Rust programming language with an emphasis on memory safety is out today with its v0.23.46 release in order to ship four new security fixes\u0026hellip; 🛡️ Altyapı Güvenliği \u0026amp; Tehdit İstihbaratı Microsoft October 2026 Patch Tuesday fixes 1,411 flaws, 3 zero-days (BleepingComputer)\nToday is Microsoft\u0026rsquo;s October 2026 Patch Tuesday, with security updates addressing a record-breaking 1,411 flaws, including one actively exploited and two publicly disclosed zero-day vulnerabilities. Next.js Ships Out-of-Band Patch for Two Critical RCE Flaws in Caching and SVG Processing (The Hacker News)\nNext.js released an out-of-band security update on October 14 that fixes two critical flaws allowing unauthenticated remote code execution, along with a high-severity denial-of-service flaw. Drupal Patches Critical Field UI Flaw With Unauthenticated RCE Path via Contributed Modules (The Hacker News)\nDrupal core has a critical flaw in its Field UI module that could let an attacker run code on the site\u0026rsquo;s server, and fixes were shipped on October 14 in Drupal 11.4.10, 11.3.19, and 10.6.19. ☁️ Bulut, Depolama \u0026amp; Ağ Mimarileri ZCS Command Injection via SNMP Handlers Enables Unauthenticated Remote Code Execution (InfoQ)\nA critical remote command execution vulnerability in the Zimbra Collaboration Suite, identified as CVE-2026-73570, poses risks by allowing unauthorized access to mailbox data and credentials. Deploy with Void (Cloudflare Blog)\nIntroducing Void: an open-source SDK, CLI, and self-hosted platform for building full-stack Vite apps and deploying them to Cloudflare. Introducing Clef-omni with full multimodality, plus a faster Clef and a cheaper Clef-flash (Cloudflare Blog)\nWe are expanding the Clef decision model family with Clef-omni, natively processing audio, video, images, and text in a single pipeline. We’ve also lowered Clef-flash pricing and boosted Clef inference speeds by up to 2.0x. 🐙 Açık Kaynak Projeler ve Araçlar open-telemetry/opentelemetry-ebpf-instrumentation: Zero-code OpenTelemetry instrumentation powered by eBPF (GitHub Trending)\n[C ★593] Zero-code OpenTelemetry instrumentation powered by eBPF cilium/cilium: eBPF-based Networking, Security, and Observability (GitHub Trending)\n[Go ★25661] eBPF-based Networking, Security, and Observability projectcalico/calico: Cloud native networking and network security (GitHub Trending)\n[Go ★7393] Cloud native networking and network security 🌐 Mühendislik Topluluğu ve Tartışmalar LFM2.5-24B-A2B: Built for fast on-device agents (Hacker News: Best · Topluluk Tartışması)\nArticle URL: https://www.liquid.ai/blog/lfm2-5-24b-a2b Comments URL: https://news.ycombinator.com/item?id=50097369 Points: 268 # Comments: 71 AOSP Source Releases Are So Late Developers Disassemble Libraries to Report Bugs (Hacker News: Best · Topluluk Tartışması)\nArticle URL: https://github.com/android/ndk/issues/2260 Comments URL: https://news.ycombinator.com/item?id=50083130 Points: 302 # Comments: 142 Redesigning source control at Anthropic (Lobsters · Topluluk Tartışması)\nRedesigning source control at Anthropic 📡 Tüm canlı akışı ve anlık filtrelemeyi onurbaydas.com/radar sayfasından takip edebilir, kaynak listesini OPML formatında indirebilirsiniz.\n","permalink":"https://onurbaydas.com/posts/radar/2026-10-15-sistem-ve-guvenlik-radari/","summary":"Günün öne çıkan yapay zekâ modelleri, küresel teknoloji ve yazılım gelişmeleri, kritik güvenlik uyarıları, donanım inovasyonları ve açık kaynak sistem bülteni.","title":"Teknoloji, Yapay Zekâ ve Sistem Radarı: 15 Ekim 2026"},{"content":" OPERASYONEL RAPOR // 2026-10-14\nBu bülten, Canlı Sistem Radarı üzerinde toplanan 25+ otoriter kaynaktan derlenmiş; kural tabanlı puanlama ile filtrelenmiş günün en kritik gelişmelerini içerir.\n🐧 Kernel.org Canlı Takipçisi: Mainline: 7.3-rc7 | Stable: 7.2.10 | LTS: 6.18.56\n🚨 Kritik Güvenlik ve CVE Uyarıları [CVE-2026-39919] Ghostscript flaw lets hackers hijack servers via PDF uploads Kaynak: BleepingComputer | Skor: 10/10 Özet: A critical heap buffer overflow vulnerability (CVE-2026-39919) in the Ghostscript interpreter and rendering engine could allow remote code execution through specially crafted PDF files. [CVE-2026-73570] ZCS Command Injection via SNMP Handlers Enables Unauthenticated Remote Code Execution Kaynak: InfoQ | Skor: 10/10 Özet: A critical remote command execution vulnerability in the Zimbra Collaboration Suite, identified as CVE-2026-73570, poses risks by allowing unauthorized access to mailbox data and credentials. [KRİTİK TEHDİT] Microsoft Patches Record 1,413 Flaws, Including Exploited Windows Shell Bug Kaynak: The Hacker News | Skor: 10/10 Özet: Microsoft on Tuesday shattered its own Patch Tuesday record by shipping patches for a whopping 1,413 vulnerabilities, including one that it said has come under active exploitation. [KRİTİK TEHDİT] Microsoft October 2026 Patch Tuesday fixes 1,411 flaws, 3 zero-days Kaynak: BleepingComputer | Skor: 10/10 Özet: Today is Microsoft\u0026rsquo;s October 2026 Patch Tuesday, with security updates addressing a record-breaking 1,411 flaws, including one actively exploited and two publicly disclosed zero-day vulnerabilities. 🐧 Linux Çekirdeği, Donanım ve Sistem Cloud Hypervisor 54 Released With Live Migration Improvements (Phoronix)\nCloud Hypervisor, the Rust-based Virtual Machine Monitor that began as an Intel open-source project and evolved into a multi-vendor Linux Foundation project, is out today with a sizable feature update\u0026hellip; Rustls 0.23.46 Released With Four Security Fixes (Phoronix)\nRustls as the modern TLS library written in the Rust programming language with an emphasis on memory safety is out today with its v0.23.46 release in order to ship four new security fixes\u0026hellip; Mesa Expands NPU Capabilities With Support For YOLOX With PyTorch (Phoronix)\nWhile Mesa is predominantly used for GPU drivers, open-source developer Tomeu Vizoso continues advancing the capabilities of NPUs within the Mesa driver stack\u0026hellip; 🛡️ Altyapı Güvenliği \u0026amp; Tehdit İstihbaratı AI-Found Linux Kernel Flaw Gives Local Users Root, and Can Break a Guest Out to the Host (The Hacker News)\nA flaw in Linux\u0026rsquo;s vhost subsystem lets a local user read and write kernel memory at will and become root across nearly a decade of kernel versions. Researchers Used a Public OpenAI Model to Build a $250,000 Chrome Full-Chain Exploit in Six Days (The Hacker News)\nA team at security firm XBOW chained three then-unknown Google Chrome bugs into a single attack that runs code on a Windows computer when the user only loads a web page, the company said. Hirudo Android Trojan Uses Patched Banking Apps to Bypass Their Built-In Security Checks (The Hacker News)\nCybersecurity researchers have disclosed details of a new Android banking trojan called Hirudo that works by replacing legitimate banking apps with purpose-built patched versions designed to bypass security checks from inside the app itself, marking a new\u0026hellip; 🐙 Açık Kaynak Sistemler ve eBPF Repoları FootprintAI/Containarium: Open-source agent runtime — SSH-native isolation, eBPF egress policy,\u0026hellip; (GitHub Trending)\n[Go ★305] Open-source agent runtime — SSH-native isolation, eBPF egress policy, Kubernetes + LXC backends, GPU passthrough, MCP-native CLI open-telemetry/opentelemetry-ebpf-instrumentation: Zero-code OpenTelemetry instrumentation powered by eBPF (GitHub Trending)\n[C ★590] Zero-code OpenTelemetry instrumentation powered by eBPF cilium/tetragon: eBPF-based Security Observability and Runtime Enforcement (GitHub Trending)\n[C ★5073] eBPF-based Security Observability and Runtime Enforcement ⚙️ Depolama, Ağ ve Kurumsal Mimariler Intel’s Crescent Island AI Server GPU Gets a Name and Specs: Meet the Intel GPU D-Series (ServeTheHome)\nIntel today has unveiled its official performance specifications and branding for its upcoming \u0026ldquo;Crescent Island\u0026rdquo; data center AI inference cards. SPECviewperf 15.0.1 Linux Edition Released: Linux’s Key Graphics Benchmark Adds Arm Support (ServeTheHome)\nSPEC has released version 15.0.1 of SPECviewperf Linux Edition, bringing a slew of upgrades and official Arm support to Linux\u0026rsquo;s key workstation graphics benchmark suite. We are taking a look at those changes, and what performance is like on some modern systems AMD EPYC 8005 SKU List and Value Analysis: Mainstream Sorano’s Big Stride (ServeTheHome)\nFollowing the recent launch of AMD\u0026rsquo;s EPYC 8005 Sorano server CPUs, we are taking a look at the various SKU options among chips, and what configurations offer the best value for different needs ⚡ Yapay Zeka Altyapısı ve GPU Hesaplama The AI race: China\u0026rsquo;s open-weight models trail US closed models by just 7 months (r/LocalLLaMA · Tartışma)\nSource: whatmodel.sh , an open source AI leaderboard I built (and launched here yesterday). Every point comes from published benchmark results: 22,113 of them across 987 benchmarks, from 1,011 sources, each one linked to where it was published. Anthropic Executive Says Open-Source AI Models Are Higher Risk (r/LocalLLaMA · Tartışma)\nhttps://www.bloomberg.com/news/articles/2026-10-14/anthropic-executive-says-open-source-ai-models-are-higher-risk\u0026hellip; Someone is running Qwen 27B at ~20 tok/s on a jailbroken PS5\u0026rsquo;s GPU (r/LocalLLaMA · Tartışma)\nsubmitted by /u/LatentSpacer [link] [comments] 🌐 Mühendislik Topluluğu ve Tartışmalar AOSP Source Releases Are So Late Developers Disassemble Libraries to Report Bugs (Hacker News: Best · Topluluk Tartışması)\nArticle URL: https://github.com/android/ndk/issues/2260 Comments URL: https://news.ycombinator.com/item?id=50083130 Points: 302 # Comments: 142 Redesigning source control at Anthropic (Lobsters · Topluluk Tartışması)\nRedesigning source control at Anthropic US law enforcement and intel agency docs: since 2021, the FBI, DHS, and NYPD have viewed AI as both a facilitator of violent extremism and a target for attacks (The Guardian) (Techmeme)\nThe Guardian : US law enforcement and intel agency docs: since 2021, the FBI, DHS, and NYPD have viewed AI as both a facilitator of violent extremism and a target for attacks — From the FBI to local police departments, US authorities are increasingly warning\u0026hellip; 📡 Tüm canlı akışı ve anlık filtrelemeyi onurbaydas.online/radar sayfasından takip edebilir, kaynak listesini OPML formatında indirebilirsiniz.\n","permalink":"https://onurbaydas.com/posts/radar/2026-10-14-sistem-ve-guvenlik-radari/","summary":"Günün öne çıkan Linux çekirdeği güncellemeleri, kritik CVE/güvenlik analizleri, depolama mimarileri ve altyapı gelişmeleri.","title":"Sistem ve Güvenlik Radarı: 14 Ekim 2026"},{"content":"Giriş Paylaşımlı, çok kullanıcılı Linux iş istasyonlarında birkaç hafta içinde birkaç ayrı şey bozuldu. Kullanıcının NFS üzerindeki ev dizininde dosyalar nobody:nogroup olarak görünmeye başladı. Share\u0026rsquo;i sıkılaştırdıktan sonra kullanıcı, ls onu sahip olarak gösterdiği halde kendi ev dizinine yazamaz oldu. Yeni açılan bir kullanıcı dataset\u0026rsquo;i, kullanıcıya ait ve 700 izinli olması gerekirken root:root sahipliğinde ve 755 izinli çıktı. Bir kullanıcının Jupyter container\u0026rsquo;ı I have no name! istemiyle açıldı ve sudo çalışmadı.\nBunların çoğunun kök nedeni aynıydı. Aynı Active Directory kullanıcısının Linux istemcilerde bir UID\u0026rsquo;si, depolama sunucusunda başka bir UID\u0026rsquo;si vardı. İki taraf da kendi kurallarına göre doğru yapılandırılmıştı. Sonunda istemcilerin kullandığı tabanı hesaplayıp depolama sunucusunun ID aralığını aynı sayıdan başlattık. Erişimin çalışması için aynı yol üzerindeki iki eşlemenin daha, biri istemcide biri sunucuda, düzeltilmesi gerekti.\nBu yazı bir kullanıcının kimliğini oturum açmadan NFS üzerindeki bir dosyaya kadar takip ediyor. Uyuşmazlığın nerede sorun çıkardığını ve neden çoğu zaman gizli kaldığını gösteriyor. Sonunda çözümü, kendi kurulumunuz için bir kontrol listesini ve alternatifleri anlatıyor.\nKurulum Ortam dört parçadan oluşuyor:\nDomain controller: EXAMPLE.LOCAL realm\u0026rsquo;i için Samba tabanlı bir AD cihazı. Depolama: nas.example.local (192.0.2.10) adresinde, aynı domain\u0026rsquo;e bağlı TrueNAS SCALE. Her kullanıcının ayrı bir ZFS dataset\u0026rsquo;i var ve bunlar NFSv4 üzerinden yalnızca sec=krb5 ile paylaşılıyor. Her dataset\u0026rsquo;in sahibi kendi kullanıcısı, izni 0700. Sahibi tam yetkili, diğer herkesin yetkisi yok. İstemciler: SSSD ile domain\u0026rsquo;e bağlı Ubuntu iş istasyonları. pam_mount oturum açılırken kullanıcının dataset\u0026rsquo;ini bağlıyor, NFS\u0026rsquo;in Kerberos tarafını rpc.gssd yürütüyor. Docker: Kullanıcılar işlerini (Jupyter, eğitim işleri) container\u0026rsquo;larda çalıştırıyor. Kullanıcının NFS dizini container\u0026rsquo;a /workspace olarak bind mount ediliyor. İzolasyon hedefi basit: Docker devreye girse bile A kullanıcısı B kullanıcısının dataset\u0026rsquo;ini okuyamamalı.\nDiyagram, düzeltmeden önce her adımda hangi kimliğin geçerli olduğunu gösteriyor. UID\u0026rsquo;ler örnektir.\nflowchart TD A[\u0026#34;İstemcide oturum açma\u0026lt;br/\u0026gt;AD parolası\u0026#34;] --\u0026gt; B[\u0026#34;SSSD\u0026lt;br/\u0026gt;SID\u0026#39;den UID (ID mapping)\u0026lt;br/\u0026gt;alice = 1914801105\u0026#34;] B --\u0026gt; C[\u0026#34;SSSD krb5_child\u0026lt;br/\u0026gt;TGT: /tmp/krb5cc_1914801105\u0026#34;] C --\u0026gt; D[\u0026#34;pam_mount\u0026lt;br/\u0026gt;nas:/.../alice sec=krb5 bağlanır\u0026#34;] D --\u0026gt; E[\u0026#34;docker exec --user 1914801105\u0026lt;br/\u0026gt;container içindeki süreç\u0026#34;] E --\u0026gt; F[\u0026#34;Çekirdek NFS istemcisi\u0026lt;br/\u0026gt;çağıran UID = 1914801105\u0026#34;] F --\u0026gt; G[\u0026#34;rpc.gssd\u0026lt;br/\u0026gt;UID ile ccache bulur\u0026lt;br/\u0026gt;principal alice@EXAMPLE.LOCAL\u0026#34;] G --\u0026gt; H[\u0026#34;TrueNAS\u0026lt;br/\u0026gt;kendi idmap\u0026#39;iyle (RID) principal\u0026#39;dan UID\u0026lt;br/\u0026gt;alice = 100001106\u0026#34;] H --\u0026gt; I[\u0026#34;ZFS izin kontrolü\u0026lt;br/\u0026gt;sahip 100001106, izin 0700\u0026#34;] I --\u0026gt; J[\u0026#34;Yanıt: sahip isim olarak\u0026lt;br/\u0026gt;EXAMPLE\\\\alice@example.local\u0026#34;] J --\u0026gt; K[\u0026#34;İstemcide nfsidmap + SSSD\u0026lt;br/\u0026gt;isimden yerel UID 1914801105\u0026#34;] İstemcinin hesapladığı sayı sunucuya hiç ulaşmaz. Yalnızca doğru Kerberos biletini bulmak için kullanılır. Sunucu principal ile ve kendi sayısıyla çalışır, sahip bilgisi istemciye isim olarak geri döner. Her çeviri adımı çalıştığı sürece iki sayı hiç karşılaşmaz. Uyuşmazlığın bu kadar uzun süre gizli kalabilmesinin nedeni de budur.\nContainer\u0026rsquo;lar Neden Burada Root Olarak Çalışmamalı sec=sys kullanıldığında sunucu, istemcinin gönderdiği UID\u0026rsquo;ye güvenir. sec=krb5 kullanıldığında ise bir Kerberos principal\u0026rsquo;ına güvenir. İstemcinin yine de her istek için hangi principal\u0026rsquo;ı kullanacağına karar vermesi gerekir ve bunu isteği yapan sürecin UID\u0026rsquo;sine bakarak yapar.\nİstemci Kerberos kimliğini nasıl seçer rpc.gssd man sayfası bu aramayı anlatır. Kullanıcının kimlik bilgileri, adı kullanıcının UID\u0026rsquo;sinden üretilen bir dosyada durur. Bu dosya genellikle /tmp altındadır. Bizim istemcilerde SSSD bilet önbelleğini tam olarak bu biçimde bir isimle yazar:\n# /etc/sssd/sssd.conf (domain bölümü, kısaltılmış) ldap_id_mapping = True krb5_ccachedir = /tmp krb5_ccname_template = FILE:%d/krb5cc_%U krb5_renewable_lifetime = 7d krb5_renew_interval = 60m krb5_ccname_template içinde %U oturum açan kullanıcının UID\u0026rsquo;sidir, %d ise krb5_ccachedir değeridir (bkz. sssd-krb5(5)). Yenileme ayarları, uzun süren bir Jupyter oturumunun biletini yarı yolda kaybetmesini önler.\nContainer host\u0026rsquo;un çekirdeğini paylaşır. Container içindeki bir süreç /workspace\u0026lsquo;e eriştiğinde host\u0026rsquo;un NFS istemcisi o sürecin UID\u0026rsquo;sini görür ve rpc.gssd bilet önbelleğini o UID\u0026rsquo;ye göre arar. Yani NFS sunucusunun hangi Kerberos kimliğini göreceğini container\u0026rsquo;daki UID belirler.\nRoot ne elde eder rpc.gssd man sayfası root konusunda açıktır: varsayılan olarak, GSS kimlik doğrulaması gerektiren UID 0 erişimlerinde makinenin kendi kimlik bilgileri (machine credentials) kullanılır.\nBu nedenle container içindeki root süreci NAS\u0026rsquo;a kullanıcı olarak değil, makine hesabı olarak ulaşır. Makine hesabı hiçbir kullanıcı dataset\u0026rsquo;inin sahibi değildir ve hepsi 0700 izinlidir. Sonuçta container içindeki root, kullanıcının dosyalarına kullanıcının kendisinden daha az erişebilir. Bu güvenlik açısından iyidir, ama pratikte bazı şeyleri bozar. Root olarak çalışıp /workspace\u0026lsquo;e yazan her kurulum adımı başarısız olur.\nBizde sorun daha da erken başladı. Başlatıcı container\u0026rsquo;ları root olarak ve -w /workspace ile başlatıyordu. Share yalnızca Kerberos kabul eder hale gelince container hiç açılmaz oldu: çalışma ortamının /workspace\u0026lsquo;e yaptığı chdir root olarak çalıştı ve reddedildi. Çözüm, container\u0026rsquo;ı -w / ile başlatmak oldu. Böylece root NFS yoluna hiç dokunmuyor, /workspace\u0026lsquo;e yalnızca kullanıcı olarak çalışan exec\u0026rsquo;lerde geçiliyor.\nBaşlatıcı betiğimiz eskiden Jupyter dizinlerini root olarak oluşturup ardından chown -R ile kullanıcıya veriyordu. Kerberos ile bağlı bir dizinde bu adım çalışamaz. Bu adımı kullanıcı olarak çalışan bir mkdir ile değiştirdik:\n# Dizinleri KULLANICI olarak oluştur (NFS, sahibi kullanıcı) docker exec --user \u0026#34;$UID:$GID\u0026#34; \u0026#34;$name\u0026#34; bash -c \u0026#39; mkdir -p /workspace/.jupyter/runtime /workspace/.local/bin /workspace/.cache \u0026#39; Aynı durum host\u0026rsquo;ta da yaşandı. Zaten bağlı olan bir NFS yoluna chmod 0755 uygulayan bir playbook PermissionError: [Errno 1] Operation not permitted hatasıyla durdu. İzinler sunucuya aittir ve istemci onları değiştiremez.\nKullanıcı olarak çalışmak, root\u0026rsquo;u container içinde tutmak Başlatıcı artık her etkileşimli kabuğu ve Jupyter sürecini host\u0026rsquo;taki UID ve GID ile başlatıyor:\ndocker exec -it --user \u0026#34;$(id -u):$(id -g)\u0026#34; \u0026#34;$name\u0026#34; bash -lc \u0026#39;cd /workspace \u0026amp;\u0026amp; exec bash\u0026#39; Docker dokümanına göre --user seçeneğine sayısal bir UID verilebilir. Container içinde var olması gereken yalnızca kullanıcı adıdır. İmajın /etc/passwd dosyasında karşılığı olmayan sayısal bir UID de çalışır. I have no name! istemi de buradan gelir. Bash, geçerli UID\u0026rsquo;yi bir isme çeviremediğinde bu istemi gösterir. Kullanıcıyı sorgulayan araçlar da bozulur, sudo da bunlardan biridir.\nBu yüzden önce, imajın kullanıcıyı tanıması için ayrı bir root adımı çalışır:\ndocker exec --user 0 \u0026#34;$name\u0026#34; bash -c \u0026#34; grep -q \u0026#39;:x:$GID:\u0026#39; /etc/group || echo \u0026#39;$USER:x:$GID:\u0026#39; \u0026gt;\u0026gt; /etc/group id $UID \u0026gt;/dev/null 2\u0026gt;\u0026amp;1 || echo \u0026#39;$USER:x:$UID:$GID::/workspace:/bin/bash\u0026#39; \u0026gt;\u0026gt; /etc/passwd grep -q \u0026#39;^$USER:\u0026#39; /etc/shadow || echo \u0026#39;$USER:*:19999:0:99999:7:::\u0026#39; \u0026gt;\u0026gt; /etc/shadow command -v sudo \u0026gt;/dev/null || (apt-get update \u0026amp;\u0026amp; apt-get install -y sudo) echo \u0026#39;$USER ALL=(ALL) NOPASSWD:ALL\u0026#39; \u0026gt; /etc/sudoers.d/lab \u0026amp;\u0026amp; chmod 0440 /etc/sudoers.d/lab \u0026#34; Bu bloktaki her satır karşılaştığımız bir hatayı düzeltti:\nİlk sürüm useradd kullanıyordu. Bazı imajlarda bu komut yok, bu yüzden betik artık /etc/passwd ve /etc/group dosyalarına doğrudan yazıyor. Jupyter Docker Stacks tabanlı imajlar jovyan (UID 1000) kullanıcısıyla başlar. --user 0 olmadan kurulum adımı jovyan olarak çalıştı ve /etc/passwd dosyasına yazamadı. Sonuç I have no name! ve çalışmayan bir sudo oldu. passwd içinde olup shadow içinde olmayan bir kullanıcı, sudo\u0026lsquo;nun account validation failure hatası vermesine yol açar. Süresi dolmayan, parolası kilitli bir shadow satırı bunu çözer. sudo yalnızca container içinde çalışır, böylece kullanıcılar kendi ortamlarına apt install yapabilir. Bu root NAS\u0026rsquo;a makine hesabı olarak ulaştığı için başka bir kullanıcının dataset\u0026rsquo;ini okuyamaz. Docker daemon\u0026rsquo;una erişimin kendisi ayrı bir sorundur. Onu Docker authorization üzerine ayrı bir yazıda anlattım.\njovyan durumu farklı bir şekilde bozulur. Host\u0026rsquo;ta UID 1000 için bir bilet önbelleği yoktur, dolayısıyla rpc.gssd\u0026lsquo;nin sunabileceği bir kimlik yoktur. Doğru çalışan tek UID kullanıcının kendi UID\u0026rsquo;sidir.\nUID Uyuşmazlığı İki ID eşleme motoru, iki sayı Active Directory kullanıcıları UID ile değil SID ile tanır. AD kullanıcılarını gören her Linux sistemi bir SID\u0026rsquo;i sayıya çevirmek zorundadır ve bizim iki sistemimiz bunun için farklı motorlar kullanıyor.\nİstemcilerde SSSD. AD sağlayıcısında ldap_id_mapping varsayılan olarak açıktır. sssd-ad(5) man sayfasına göre sağlayıcı, UID ve GID değerlerini AD\u0026rsquo;deki objectSID alanından üretir. ID eşleme açıkken uidNumber ve gidNumber alanları yok sayılır. Varsayılan aralık 200.000\u0026rsquo;den 2.000.200.000\u0026rsquo;e kadar uzanır ve 200.000\u0026rsquo;lik dilimlere bölünür. Her domain, SID\u0026rsquo;inin hash\u0026rsquo;iyle seçilen bir dilime düşer. Bu yüzden ortaya çıkan UID\u0026rsquo;ler büyük ve rastgele görünen sayılardır.\nTrueNAS\u0026rsquo;ta winbind ve RID backend\u0026rsquo;i. TrueNAS AD\u0026rsquo;ye Samba üzerinden bağlanır. Dokümanına göre varsayılan olarak, kullanıcı ya da grup SID\u0026rsquo;inin RID bileşenine dayalı algoritmik bir yöntem kullanır. Varsayılan domain aralığı 100000001 ile 200000000 arasıdır. Bizim TrueNAS da bu varsayılanı kullanıyordu. Samba man sayfası formülü şöyle verir: ID = RID - BASE_RID + LOW_RANGE_ID.\nİki motor da deterministiktir, ama farklı tabanlardan başlarlar. RID\u0026rsquo;i 1105 olan bir kullanıcı için istemci 1914801105, TrueNAS ise 100001106 hesapladı. İkisi de yanlış değildi, ama aynı sayı değildiler. İki sayıyı ilk kez, istemcideki id çıktısını TrueNAS\u0026rsquo;ta kullanıcının dosyalarının sahibiyle karşılaştırdığımızda yan yana gördük.\nUyuşmazlık katman katman nerede vurur Örnek UID\u0026rsquo;ler düzeltmeden önceki değerlerdir.\nKatman Kimlik nereden gelir Örnek UID Uyuşmazlık burada ne yapar İstemci host SSSD, SID\u0026rsquo;den ID eşleme 1914801105 İstemci içinde tutarlıdır. id -u bu sayıyı verir, başlatıcı da onu container\u0026rsquo;a geçirir. Bu sayı TrueNAS\u0026rsquo;a bir gün sayı olarak gönderilirse yanlış hesabı ya da hiçbir hesabı göstermez. Container docker exec --user \u0026lt;host UID\u0026gt; 1914801105 passwd kaydı yoksa I have no name! çıkar ve sudo bozulur. Süreç root ya da jovyan olarak çalışırsa NFS istekleri kullanıcının kimliğini taşımaz. NFS isteği rpc.gssd /tmp/krb5cc_\u0026lt;UID\u0026gt; dosyasını bulur, principal ağa gider alice@EXAMPLE.LOCAL Sayı istemcide yalnızca bir arama anahtarıdır. Bilet önbelleği sürecin gerçekten çalıştığı UID ile adlandırıldığı sürece uyuşmazlık burada önemli değildir. TrueNAS dosya sistemi winbind idmap ile principal\u0026rsquo;dan UID, ZFS sahipliğiyle karşılaştırılır 100001106 Dataset\u0026rsquo;in sahibi bu sayı olmalıdır. Sahiplik yanlışsa kullanıcı kendi 0700 dataset\u0026rsquo;ine giremez. TrueNAS API filesystem.setperm Provisioning kodu ne gönderirse 100001106 (doğru) ya da 1914801105 (yanlış) İsimle yaptığımız çağrı uygulanmadı. Dataset root:root 755 kaldı: sahibi yazamadı, diğer kullanıcılar okuyabildi. İstemcinin UID\u0026rsquo;sini göndermek de aynı derecede yanlış olurdu. NFSv4 isim eşleme (idmapd) Sunucu EXAMPLE\\alice@example.local gönderir, istemci bunu NSS (SSSD) üzerinden çevirir istemci: 1914801105 İstemcinin NFSv4 domain\u0026rsquo;i uymazsa isim çevrilmez ve dosya nobody görünür. Uyarsa isim istemcinin kendi UID\u0026rsquo;sine çevrilir ve uyuşmazlık görünmez olur. Belirti 1: nobody:nogroup İstemci logları şu satırlarla doluydu:\nnfsidmap: libnfsidmap: Unable to determine the NFSv4 domain; Using \u0026#39;localdomain\u0026#39; as the NFSv4 domain ... nfsidmap: nss_getpwnam: name \u0026#39;EXAMPLE\\alice@example.local\u0026#39; does not map into domain \u0026#39;localdomain\u0026#39; nfsidmap: nss_name_to_gid: name \u0026#39;EXAMPLE\\domain users@example.local\u0026#39; does not map into domain \u0026#39;localdomain\u0026#39; NFSv4 dosya sahibini sayı olarak değil, kullanıcı@domain biçiminde bir dize olarak gönderir (nfsidmap(5)). İstemci yalnızca kendi NFSv4 domain\u0026rsquo;inden gelen isimleri kabul eder. idmapd.conf(5) bu domain\u0026rsquo;i, kullanıcı adı ile UID ve grup adı ile GID arasında tekil bir eşlemenin geçerli olduğu bir ad alanı olarak tanımlar. Domain ayarlı değilse istemci önce DNS\u0026rsquo;te _nfsv4idmapdomain kaydına, ardından DNS domain\u0026rsquo;ine bakar. Bizim iş istasyonlarımız iki yoldan da bir domain belirleyemedi, localdomain değerine düştü ve her dosyanın sahibi nobody oldu.\nÇözüm her istemcide tek bir satır ve önbelleğin temizlenmesiydi:\n# /etc/idmapd.conf [General] Domain = example.local sudo nfsidmap -c nfsidmap -c önbelleğe alınmış eşlemelerin tutulduğu keyring\u0026rsquo;i temizler. Man sayfası, eskimiş tek bir anahtarın bile sahipliğin nobody görünmesine yol açabileceği konusunda uyarır.\nBu düzeltmeden sonra sahiplik doğru göründü ve uyuşmazlık görünmez oldu: ls -l alice gösteriyordu, ls -ln 1914801105 gösteriyordu, TrueNAS ise 100001106 saklıyordu.\nBelirti 2: sahip doğru, yine de Permission denied Başlangıçta share tüm erişimi tek bir kullanıcıya eziyordu (mapall) ve bu, sahiplik sorunlarını gizliyordu. mapall\u0026lsquo;ı kaldırıp share\u0026rsquo;i yalnızca Kerberos kabul edecek şekilde değiştirdikten sonra izolasyon tek bir şeye bağlı kaldı: her dataset\u0026rsquo;in sahibi, TrueNAS\u0026rsquo;ın kullanıcının principal\u0026rsquo;ını eşlediği UID\u0026rsquo;nin tam olarak kendisi olmalıydı.\nBu değişiklikten sonraki ilk test şöyleydi:\n$ stat -c \u0026#39;%U %u\u0026#39; ~/nfs-home alice 1914801105 $ touch ~/nfs-home/_t touch: cannot touch \u0026#39;/home/alice/nfs-home/_t\u0026#39;: Permission denied İstemci sahibi doğru kullanıcıya çözdü, çünkü idmapd ismi çeviriyordu. Sunucu ise yazmayı yine reddetti. Aynı anda üç şey yanlıştı ve her biri tek başına erişimi engellemeye yetiyordu:\nSayılar farklıydı. TrueNAS dosyaları kendi UID\u0026rsquo;siyle saklıyordu ve istemciler bu UID\u0026rsquo;yi hiç kullanmıyordu. İstemci kullanıcının biletini sunmuyordu. Bilet önbelleğinin adında rastgele bir son ek vardı (/tmp/krb5cc_1914801105_XXXXXX) ve rpc.gssd onu bulamadı. Sunucu principal\u0026rsquo;ı nobody\u0026lsquo;ye eşliyordu. İlk ikisi düzeltildikten sonra bile kullanıcı ls: cannot open directory ...: Permission denied aldı. Teşhis için dizini kısa bir süre 777 yaptık ve dizin açıldı. Kullanıcı içeri sahip olarak değil, \u0026ldquo;diğerleri\u0026rdquo; izniyle giriyordu. TrueNAS\u0026rsquo;ta getent passwd 'EXAMPLE\\alice' çözülüyordu, ama domain\u0026rsquo;siz getent passwd alice boş dönüyordu. Çözüm bölümü üçünü de ele alıyor.\nBelirti 3: root:root 755 sahipliğinde yeni dataset Provisioning kodu izinleri isimle ayarlıyordu:\npayload = { \u0026#34;path\u0026#34;: mount_path, \u0026#34;uid\u0026#34;: None, \u0026#34;user\u0026#34;: \u0026#34;EXAMPLE\\\\alice\u0026#34;, \u0026#34;group\u0026#34;: \u0026#34;EXAMPLE\\\\domain users\u0026#34;, \u0026#34;mode\u0026#34;: \u0026#34;700\u0026#34;, \u0026#34;options\u0026#34;: {\u0026#34;recursive\u0026#34;: True, \u0026#34;traverse\u0026#34;: False}, } Bizim TrueNAS sürümümüzde bu çağrı reddedildi ve yeni dataset\u0026rsquo;ler root:root 755 olarak kaldı. Kimse fark etmedi, çünkü provisioning kodu hatayı yakalayıp \u0026ldquo;kritik değil\u0026rdquo; diye log\u0026rsquo;a yazdı ve devam etti. Eski dataset\u0026rsquo;ler yalnızca elle düzeltildikleri için doğru görünüyordu. Yalnızca Kerberos kabul eden bir share\u0026rsquo;de root:root 755 bir dataset, sahibinin kendi ev dizinine yazamaması ve kimliği doğrulanmış diğer her kullanıcının o dizini okuyabilmesi demektir. Daha yeni TrueNAS API dokümanları filesystem.setperm için user ve group isim alanlarını listeliyor, yani isimle yapılan çağrı sizin sürümünüzde farklı davranabilir. Sayısal ID kullanmak bu soruyu tamamen ortadan kaldırır.\nNeden sessiz kalıyor Uyuşmazlık hiçbir zaman UID\u0026rsquo;lerden bahseden bir hata üretmedi:\nHer sistem kendi kurallarına göre doğru çalışıyor ve her araç doğru ismi gösteriyor. Belirtiler farklı katmanlarda farklı isimler taşıyor: nobody, sahibi olduğunuz dosyada Permission denied, root:root 755, I have no name!. Kerberos sayıyı ağda gizliyor. Sayı ancak sınırı geçtiği yerde önem kazanıyor: bir izin API çağrısı, bir sec=sys mount\u0026rsquo;u, sayısal sahipliği koruyarak yapılan bir geri yükleme, istemciden yapılan bir chown. Uyuşmazlığı ancak iki sayıyı yan yana koyduğunuzda görürsünüz.\nÇözüm Çözüm üç parçadan oluştu. Önce her katmanın doğru kimliği taşımasını sağladık, sonra iki sayıyı eşitledik, en son da kullanıcıyı hâlâ nobody\u0026lsquo;ye çeviren iki eşlemeyi düzelttik.\n1. kısım: her adımda doğru kimlik Ağda isimler. Her istemcinin idmapd.conf dosyasına Domain = example.local yazılır ve nfsidmap -c çalıştırılır. Böylece TrueNAS\u0026rsquo;tan gelen sahip dizeleri SSSD üzerinden yerel kullanıcılara çevrilir. Erişim için principal\u0026rsquo;lar. Share yalnızca KRB5 kabul eder, mapall/maproot yoktur. İstemciler sec=krb5 ile bağlanır, rpc.gssd çalıştırır, bilet önbelleğini öngörülebilir bir yolda (/tmp/krb5cc_%U) tutar ve yeniler. Share yalnızca Kerberos kabul eder hale geldikten sonra bunların her biri en az bir kez bozuldu: pam_mount seçeneklerinde sec=krb5 yoktu, mount reddedildi. rpc-gssd her istemcide çalışmıyordu. Etkinleştirilmesi gerekir. rpc.gssd şu hatayı yazdı: ERROR: unable to resolve 192.0.2.10 to hostname: Name or service not known. Ters çözümleme olmadan sunucunun NFS servis principal\u0026rsquo;ını kuramaz ve mount başarısız olur. DNS\u0026rsquo;te bir PTR kaydı ya da /etc/hosts\u0026lsquo;a sunucunun FQDN\u0026rsquo;iyle bir satır bunu çözer. Bazı kullanıcılar ls: cannot access '/home/alice/nfs-home/': Key has expired aldı. SSSD KDC\u0026rsquo;ye ulaşamazken oturum açmışlardı. Geçerli bir biletleri yoktu ve onu yenileyen de olmadı. Yukarıda gösterilen yenileme ayarları bunu çözer, kullanıcının bir kez çıkış yapıp tekrar girmesi gerekir. Container içinde kullanıcının UID\u0026rsquo;si. /workspace\u0026lsquo;e dokunan her süreç --user \u0026lt;host UID\u0026gt;:\u0026lt;host GID\u0026gt; ile çalışır. Root işleri yalnızca container\u0026rsquo;ın kendi dosyalarına dokunan ayrı bir --user 0 exec\u0026rsquo;iyle yapılır. Sahiplik için sunucunun kendi çözümlemesi. Provisioning, TrueNAS\u0026rsquo;a kullanıcı için hangi UID\u0026rsquo;yi kullandığını sorar ve sahipliği sayısal olarak ayarlar: uid_resp = self._post(\u0026#34;/user/get_user_obj\u0026#34;, {\u0026#34;username\u0026#34;: username}) user_obj = uid_resp.json() or {} uid, gid = user_obj.get(\u0026#34;pw_uid\u0026#34;), user_obj.get(\u0026#34;pw_gid\u0026#34;) if not isinstance(uid, int) or not isinstance(gid, int): return {\u0026#34;success\u0026#34;: False, \u0026#34;message\u0026#34;: \u0026#34;could not resolve uid/gid\u0026#34;} payload = { \u0026#34;path\u0026#34;: mount_path, \u0026#34;mode\u0026#34;: \u0026#34;700\u0026#34;, \u0026#34;uid\u0026#34;: uid, \u0026#34;gid\u0026#34;: gid, \u0026#34;options\u0026#34;: {\u0026#34;recursive\u0026#34;: True, \u0026#34;traverse\u0026#34;: False}, } resp = self._post(\u0026#34;/filesystem/setperm\u0026#34;, payload) user.get_user_obj, bir kullanıcı için struct passwd alanlarını (pw_uid ve pw_gid dahil) döndürür ve Active Directory hesapları için de çalışır. TrueNAS API dokümanı filesystem.setperm içindeki uid ve gid alanlarını sayısal sahip kimlikleri olarak tanımlar. TrueNAS kullanıcıyı çözemezse provisioning durur ve root sahipliğinde bir dataset bırakmaz.\n2. kısım: TrueNAS aralığını taşıyarak UID\u0026rsquo;leri hizalamak İki motor da kullanıcının RID\u0026rsquo;ine sabit bir taban ekler. TrueNAS\u0026rsquo;ta bu taban range_low - BASE_RID, SSSD\u0026rsquo;de ise domain\u0026rsquo;in düştüğü dilimin başlangıcıdır. sssd-ad(5) sayfası ldap_idmap_range_size değerinin domain\u0026rsquo;deki en büyük RID\u0026rsquo;den küçük olmamasını şart koşar, yani her kullanıcı o tek dilime sığar. TrueNAS aralığını aynı tabandan başlatırsa sayılar eşitlenir.\nSSSD\u0026rsquo;nin tabanını, istemcideki UID\u0026rsquo;den RID\u0026rsquo;i çıkararak bulduk. Bunu bir kullanıcı ve iki grup için yaptık. Üçü de aynı sayıyı verdi, bu da istemcinin formülünün taban + RID olduğunu doğruladı:\nalice 1914801105 - 1105 = 1914800000 domain users 1914800513 - 513 = 1914800000 başka bir grup 1914801158 - 1158 = 1914800000 Sonra TrueNAS tarafını değiştirdik:\nDomain\u0026rsquo;in Active Directory idmap ayarlarında RID backend\u0026rsquo;i kalır. Range Low tabana, Range High taban artı SSSD dilim boyutuna (200.000) ayarlanır. RID backend\u0026rsquo;inin SSSD uyumluluk seçeneği kapalı kalır, çünkü aralık zaten hizalıdır. TrueNAS, directory service etkinken idmap değişikliğini kaydetmedi. Directory service\u0026rsquo;i devre dışı bırakın, kaydedin, sonra tekrar etkinleştirin. Etkinleştirmek TrueNAS\u0026rsquo;ın domain\u0026rsquo;e yeniden katılmasına yol açar. Katılım için kullanılan hesabın TrueNAS\u0026rsquo;ın bilgisayar nesnesine yazma yetkisi olmalıdır. Yoksa katılım LDB_MODIFY sırasında Insufficient access hatasıyla başarısız olur. Bu adımda KRB5KDC_ERR_PREAUTH_FAILED görürseniz neden yanlış parola, yanlış UPN biçimi ya da Kerberos\u0026rsquo;un izin verdiğinden büyük bir saat farkıdır. Doğrulama: TrueNAS\u0026rsquo;ta wbinfo -i 'EXAMPLE\\alice', istemcideki id -u alice ile aynı UID\u0026rsquo;yi göstermelidir. Mevcut verinin sahipliğini yeniden ayarlayın, çünkü TrueNAS\u0026rsquo;taki bütün AD UID\u0026rsquo;leri değişti. Örnek sayılarla:\nistemci (SSSD): alice RID 1105 -\u0026gt; 1914801105 TrueNAS önce: alice RID 1105 -\u0026gt; 100001106 (aralık 100000001-200000000) TrueNAS sonra: alice RID 1105 -\u0026gt; 1914801105 (aralık 1914800000-1915000000) Sahipliği yeniden ayarlamak isteğe bağlı bir adım değil. ZFS sahibi sayı olarak saklar, bu yüzden mevcut her dataset hâlâ eski TrueNAS UID\u0026rsquo;lerini gösteriyordu. TrueNAS\u0026rsquo;ın eski ve yeni formülü ikisi de taban + RID olduğu için kayma her hesapta aynıdır: 1914800000 - 100000001 = 1814799999. Önce özyinelemeli bir ZFS snapshot aldık, sonra eski aralıktaki her UID ve GID\u0026rsquo;ye bu kaymayı ekledik:\nzfs snapshot -r pool/users@before-idmap-fix OLD_LOW=100000001; OLD_HIGH=200000000; DELTA=1814799999 for U in $(find /mnt/pool/users -printf \u0026#39;%U\\n\u0026#39; | sort -un); do [ \u0026#34;$U\u0026#34; -ge \u0026#34;$OLD_LOW\u0026#34; ] \u0026amp;\u0026amp; [ \u0026#34;$U\u0026#34; -le \u0026#34;$OLD_HIGH\u0026#34; ] \u0026amp;\u0026amp; find /mnt/pool/users -uid \u0026#34;$U\u0026#34; -exec chown -h \u0026#34;$((U + DELTA))\u0026#34; {} + done # gruplar için aynı döngü: %G, -gid ve chgrp Burada iki ayrıntı önemli. Her kullanıcının ev dizini ayrı bir child dataset\u0026rsquo;ti, bu yüzden find -xdev kullanmamalı, yoksa ilk dataset sınırında durur. Küçük UID\u0026rsquo;li yerel hesaplar eski aralığın dışında kaldığı için döngü onlara dokunmaz.\nDeğişiklikten sonra kontrol ettiğimiz her kullanıcıda UID istemcide, container\u0026rsquo;da ve TrueNAS\u0026rsquo;ta aynıydı. ls -ln artık iki tarafta da aynı sayıyı gösteriyor. Bir sayı sınırı geçse bile doğru kişiyi gösteriyor.\n3. kısım: hâlâ nobody döndüren iki eşleme Sayıların hizalanması yetmedi. Belirti 2\u0026rsquo;deki kullanıcı iki nedenle hâlâ Permission denied alıyordu.\nİstemcide, rpc.gssd\u0026lsquo;nin bulabildiği bir bilet önbelleği. SSSD bileti rastgele son ekli bir isimle yazmıştı: /tmp/krb5cc_1914801105_XXXXXX. rpc.gssd bu dosyayı kullanmadı. krb5_ccname_template = FILE:%d/krb5cc_%U ayarı (yukarıda gösterildi) önbelleğe sabit bir isim verdi. Ayarı her istemciye dağıtıp SSSD\u0026rsquo;yi yeniden başlattık. Ardından klist /tmp/krb5cc_1914801105 gösterdi.\nTrueNAS\u0026rsquo;ta \u0026ldquo;Use Default Domain\u0026rdquo;. Bu ayar kapalıyken TrueNAS yalnızca domain önekli ismi (EXAMPLE\\alice) çözüyor, domain\u0026rsquo;siz alice boş dönüyordu. Gelen principal\u0026rsquo;lar nobody\u0026lsquo;ye düşüyordu. 777 testinde dizinin açılmasının nedeni buydu. Ayar açılınca domain\u0026rsquo;siz isim hizalanmış UID\u0026rsquo;ye çözüldü ve 0700 ev dizini sahibine açıldı.\nBu ayarı değiştirmenin de bir püf noktası vardı. TrueNAS, Kerberos kullanıcı kimlik bilgisi tutarken directory service\u0026rsquo;i devre dışı bırakmayı reddetti: Kerberos user credentials may not be stored for disabled directory services. Önce kimlik bilgisini TrueNAS makine hesabının Kerberos principal\u0026rsquo;ına (keytab\u0026rsquo;ına) çevirdik, sonra devre dışı bırakıp ayarı değiştirdik ve tekrar etkinleştirdik. Bu, sonraki yeniden katılımlardaki parola ve PREAUTH_FAILED sorunlarını da ortadan kaldırdı.\nEski eşlemeler iki tarafta da önbellekte durur, bu yüzden değişiklikten sonra onları temizledik:\n# TrueNAS net cache flush nfsidmap -c midclt call service.restart nfs # istemciler: yeniden mount edin ya da çıkış yapıp tekrar girin Bu yöntemin bazı sınırları var:\nSSSD\u0026rsquo;nin seçtiği dilime bağlıdır. Hepsi aynı dilime düşsün diye tüm istemciler aynı SSSD ID eşleme ayarlarını kullanmalıdır. Man sayfası, hash çakışmalarının dilimleri makineden makineye farklılaştırabileceği konusunda uyarır. Bu yüzden birden fazla istemcide kontrol edin. RID\u0026rsquo;i SSSD aralık boyutundan büyük olan kullanıcılar bu şemaya uymaz. Man sayfasına göre bu kullanıcılar için sorgular başarısız olur. TrueNAS dokümanı, domain aralığının yerel hesaplarla ya da güvenilen domain aralıklarıyla çakışmaması gerektiği ve idmap hatalarının izinleri yanlış kullanıcılara atayabileceği konusunda uyarır. Değişikliği bir bakım penceresinde yapın ve kullanıcılar oturum açmadan önce doğrulayın. Kendi Kurulumunuzu Nasıl Kontrol Edersiniz Bu komutları sorun yaşayan kullanıcı olarak çalıştırın ve sonuçları sistemler arasında karşılaştırın.\nİstemcide, kim olduğunuzu öğrenin:\nid # SSSD\u0026#39;nin hesapladığı UID ve GID getent passwd alice # aynısı, NSS üzerinden klist # principal ve bilet önbelleği yolu; krb5cc_\u0026lt;UID\u0026#39;niz\u0026gt; ile bitmeli klist bilet göstermiyorsa ya da önbellek adı id -u çıktısındaki UID\u0026rsquo;yi içermiyorsa, rpc.gssd bileti bulamaz. sssd.conf içindeki krb5_ccname_template ayarını kontrol edin.\nTrueNAS\u0026rsquo;ta, sunucunun sizi kim sandığını öğrenin (TrueNAS kabuğundan):\nid \u0026#39;EXAMPLE\\alice\u0026#39; midclt call user.get_user_obj \u0026#39;{\u0026#34;username\u0026#34;: \u0026#34;alice\u0026#34;}\u0026#39; pw_uid değerini istemcideki id -u çıktısıyla karşılaştırın. Farklıysa iki üç hesap için istemcideki UID\u0026rsquo;den RID\u0026rsquo;i çıkarın. Sonuç hepsinde aynıysa o sayı istemcinin tabanıdır ve yukarıdaki aralık değişikliği işe yarar.\nNFS mount\u0026rsquo;unu ve isim eşlemeyi kontrol edin:\nfindmnt -t nfs4 -o TARGET,SOURCE,OPTIONS # sec=krb5 ve vers=4.x olmalı nfsidmap -d # etkin NFSv4 domain\u0026#39;i; \u0026#34;localdomain\u0026#34; olmamalı grep -E \u0026#39;^\\s*Domain\u0026#39; /etc/idmapd.conf systemctl is-active rpc-gssd journalctl -t nfsidmap --since today # \u0026#34;does not map into domain\u0026#34; = yanlış domain Share yalnızca Kerberos kabul ediyorsa ve sahibi olduğunuz bir dizinde yine Permission denied alıyorsanız, sunucunun domain\u0026rsquo;siz kullanıcı adını nasıl gördüğüne bakın (TrueNAS\u0026rsquo;ta domain olmadan getent passwd alice). klist\u0026lsquo;in rastgele son eki olmayan bir önbellek gösterdiğini de kontrol edin. Daha fazla ayrıntı için rpc-gssd\u0026lsquo;yi durdurup erişimi tekrarlarken rpc.gssd -f -vvv komutunu ön planda çalıştırın.\nSahipliği iki yönden kontrol edin:\nls -l ~/nfs-home # isimler: alice görünmeli, asla nobody değil ls -ln ~/nfs-home # sayılar: hizalamadan sonra TrueNAS\u0026#39;takiyle aynı UID TrueNAS\u0026rsquo;ta ls -ln /mnt/pool/users/alice aynı UID\u0026rsquo;yi ve drwx------ iznini göstermelidir.\nContainer içinde:\ndocker exec --user \u0026#34;$(id -u):$(id -g)\u0026#34; mybox sh -c \u0026#39;id; whoami; ls -ln /workspace | head\u0026#39; id host\u0026rsquo;taki UID\u0026rsquo;yi, whoami bir hata değil bir isim göstermelidir. /workspace içindeki dosyalar da aynı UID\u0026rsquo;yi göstermelidir. Ardından aynı komutu --user 0 ile çalıştırıp /workspace\u0026lsquo;i listelemeyi deneyin. Makine hesabının dataset\u0026rsquo;e erişimi olmayan bir Kerberos mount\u0026rsquo;unda bu başarısız olmalıdır. Başarılı olursa share\u0026rsquo;in maproot ayarını ve dataset\u0026rsquo;in iznini kontrol edin.\nAlternatifler SSSD\u0026rsquo;yi POSIX attribute\u0026rsquo;larına geçirmek. Her kullanıcı için AD\u0026rsquo;de uidNumber/gidNumber saklanır, SSSD\u0026rsquo;de ldap_id_mapping = False yapılır ve TrueNAS\u0026rsquo;ta AD (RFC2307) idmap backend\u0026rsquo;i seçilir. İki taraf da herhangi bir dilim ya da aralıktan bağımsız olarak aynı saklanan sayıyı okur. Bedelleri:\nHer hesabın bu attribute\u0026rsquo;lara ihtiyacı vardır ve provisioning onları benzersiz ve kalıcı olarak atamak zorundadır. SSSD man sayfası, performans için bu attribute\u0026rsquo;ların Global Catalog\u0026rsquo;a da kopyalanmasını önerir. Man sayfası, ID eşleme ayarlarını değiştirmenin kullanıcı ve grup kimliklerini değiştireceği konusunda uyarır. Bu durumda istemcilerdeki her ev dizininin sahipliği yeniden ayarlanmalıdır. İki UID alanıyla yaşamak. Sayılar farklı bırakılır, Kerberos ve idmapd isimlerine güvenilir, sahiplik her zaman sunucunun kendi çözümlemesinden ayarlanır. Hiçbir şey taşınmaz, ama herkes istemcinin UID\u0026rsquo;sini asla sunucuya göndermemesi gerektiğini bilmelidir. Bu da sec=sys, NFSv3 ve sayısal sahipliği koruyan dikkatsiz yedeklemeleri dışarıda bırakır. Bir süre böyle çalıştık ve uyuşmazlık tam da bu yüzden gizli kaldı. (İstemcilerde SSSD yerine winbind kullanmak da iki tarafa aynı algoritmayı verir, ama kimlik altyapısını değiştirmeyi gerektirir.)\nUyguladığımız yaklaşım: TrueNAS RID aralığını taşımak. Tek bir sunucuda tek bir ayar değişir, AD\u0026rsquo;ye ve istemcilere dokunulmaz. Bedeli, mevcut dataset\u0026rsquo;lerin sahipliğinin bir kez yeniden ayarlanması, NAS\u0026rsquo;ın domain\u0026rsquo;e yeniden katılması ve SSSD\u0026rsquo;nin dilimine bağımlı kalmaktır. SSSD\u0026rsquo;nin ID eşleme ayarları değişirse ya da bir istemci farklı bir dilime düşerse uyuşmazlık geri gelir. Tek NAS\u0026rsquo;lı ve istemcileri aynı yapılandırılmış bir ortam için, her yerde kullanıcı başına tek UID elde etmenin en ucuz yolu buydu.\nSonuç NFSv4 ve Kerberos ile ağdaki kimlik bir principal ve bir isim dizesinden oluşur. Sayısal UID yalnızca her sistemin kendi içinde vardır. Bu yüzden istemcilerimiz ve NAS, görünürde hiçbir sorun olmadan her kullanıcının UID\u0026rsquo;si konusunda anlaşamıyordu. Sorunlar, bir sayının ya da ismin bir sınırı geçtiği yerlerde ortaya çıktı: localdomain değerine düşen bir idmapd domain\u0026rsquo;i, rpc.gssd\u0026lsquo;nin bulamadığı bir bilet önbelleği, domain\u0026rsquo;siz kullanıcı adını çözemeyen bir sunucu, sessizce başarısız olan bir izin çağrısı ve klavyenin başındaki kişi yerine root ya da imajın kendi kullanıcısı olarak çalışan container\u0026rsquo;lar.\nBu olaydan üç kural çıktı:\nKerberos NFS\u0026rsquo;e dokunan container süreçlerini kullanıcının host\u0026rsquo;taki UID\u0026rsquo;siyle çalıştırın, root işlerini container içinde tutun. Sunucudaki sahipliği, sunucunun kendi çözümlediği UID ile ayarlayın. İstemcideki id -u değerini sunucunun aynı kullanıcı için kullandığı UID ile karşılaştırın. Farklıysa istemcinin tabanını (UID eksi RID) hesaplayın, sunucunun RID aralığını o tabandan başlatın ve verinin sahipliğini yeniden ayarlayın. Kaynaklar rpc.gssd(8), bilet önbelleği araması ve UID 0 için makine kimlik bilgileri: https://man7.org/linux/man-pages/man8/rpc.gssd.8.html nfsidmap(5), NFSv4 kullanıcı@domain isimleri, -c, -d, nobody görünen eski anahtarlar: https://man7.org/linux/man-pages/man5/nfsidmap.5.html idmapd.conf(5), Domain ve varsayılan değeri: https://linux.die.net/man/5/idmapd.conf sssd-ad(5), ldap_id_mapping, ID aralıkları ve dilimler, ldap_idmap_range_size: https://man.archlinux.org/man/sssd-ad.5.en sssd-krb5(5), krb5_ccname_template, yenileme ayarları: https://man.archlinux.org/man/sssd-krb5.5.en Samba idmap_rid(8): https://www.samba.org/samba/docs/current/man-html/idmap_rid.8.html TrueNAS, Configuring Active Directory (idmap backend\u0026rsquo;leri ve uyarılar): https://www.truenas.com/docs/scale/credentials/directoryservices/configad/ TrueNAS, Directory Services Screens (Range Low/High, varsayılan aralıklar): https://www.truenas.com/docs/scale/credentials/directoryservices/directoryservicesscreens/ TrueNAS API, filesystem.setperm: https://api.truenas.com/v25.10/api_methods_filesystem.setperm.html TrueNAS API, user.get_user_obj: https://api.truenas.com/v25.10/api_methods_user.get_user_obj.html Docker, container çalıştırma (varsayılan kullanıcı, --user, sayısal UID\u0026rsquo;ler): https://docs.docker.com/engine/containers/run/ Docker CLI, docker container exec: https://docs.docker.com/reference/cli/docker/container/exec/ ","permalink":"https://onurbaydas.com/posts/nfs-uid-mismatch/","summary":"\u003ch2 id=\"giriş\"\u003eGiriş\u003c/h2\u003e\n\u003cp\u003ePaylaşımlı, çok kullanıcılı Linux iş istasyonlarında birkaç hafta içinde birkaç ayrı şey bozuldu. Kullanıcının NFS üzerindeki ev dizininde dosyalar \u003ccode\u003enobody:nogroup\u003c/code\u003e olarak görünmeye başladı. Share\u0026rsquo;i sıkılaştırdıktan sonra kullanıcı, \u003ccode\u003els\u003c/code\u003e onu sahip olarak gösterdiği halde kendi ev dizinine yazamaz oldu. Yeni açılan bir kullanıcı dataset\u0026rsquo;i, kullanıcıya ait ve \u003ccode\u003e700\u003c/code\u003e izinli olması gerekirken \u003ccode\u003eroot:root\u003c/code\u003e sahipliğinde ve \u003ccode\u003e755\u003c/code\u003e izinli çıktı. Bir kullanıcının Jupyter container\u0026rsquo;ı \u003ccode\u003eI have no name!\u003c/code\u003e istemiyle açıldı ve \u003ccode\u003esudo\u003c/code\u003e çalışmadı.\u003c/p\u003e","title":"Bir Kullanıcı, İki UID: Domain'e Bağlı TrueNAS'ta NFSv4, Kerberos ve Docker"},{"content":"English version: Docker Authorization with OPA\n1. Giriş Paylaşımlı, çok kullanıcılı Linux iş istasyonlarında Docker\u0026rsquo;ı kısıtlamak için opa-docker-authz kurdum. Rutin bir policy güncellemesinden sonra --privileged konteynerlerin sessizce çalıştığını fark ettim. Bu yazı, o olayın ve sonrasında kaynak kodda bulduklarımın özeti.\nDocker authorization plugin\u0026rsquo;leri, Docker daemon\u0026rsquo;una gelen her API isteğini işlenmeden önce bir policy\u0026rsquo;ye göre değerlendirmeyi sağlar. opa-docker-authz, bu mekanizmayı OPA (Open Policy Agent) ve Rego policy diliyle uygulayan bir plugin\u0026rsquo;dir.\nBu yazı şu konuları ele alıyor:\nDocker authorization plugin mekanizmasının çalışma şekli ve opa-docker-authz kurulumu. Örnek bir policy\u0026rsquo;nin neyi garanti ettiği, neyi etmediği. Dört tuzak: sessiz fail-open, policy güncelleme, Rego sözdizimi ve sürüm uyumu, policy\u0026rsquo;nin göremediği alanlar. Authorization plugin\u0026rsquo;inin tasarım gereği sağlayamadığı korumalar. Production için bir kontrol listesi. Fail-open, bir kontrol mekanizmasının hata durumunda isteği reddetmek yerine geçirmesi demektir. Yazının ana konusu, bu durumun hiçbir hata ya da uyarı üretmeden oluşabilmesi.\n2. Senaryo ve hedef Senaryo: çok kullanıcılı, paylaşımlı Linux iş istasyonları. Kullanıcıların Docker kullanması gerekiyor ama birbirlerinin verisine ve host\u0026rsquo;a erişmemeleri isteniyor.\nTemel gerilim şu: Docker daemon\u0026rsquo;u (dockerd) root olarak çalışır. Daemon, arka planda çalışan ve Docker API isteklerini işleyen servistir. Daemon\u0026rsquo;un socket\u0026rsquo;ine erişebilen biri, daemon\u0026rsquo;dan root yetkisiyle iş yapmasını isteyebilir. Docker\u0026rsquo;ın resmi dokümanı da docker grubunun kullanıcıya root düzeyinde yetki verdiğini belirtir. Bu senaryoda kullanıcıların socket\u0026rsquo;e erişimi var.\nHedef tek bir kural:\nHer kullanıcı yalnızca kendi workspace\u0026rsquo;ini (/home/\u0026lt;kullanıcı\u0026gt;/workspace) konteyner içinde /workspace yoluna bağlayabilsin. Başka bind mount yok, privileged konteyner yok, host namespace\u0026rsquo;leri yok. GPU erişimi serbest.\nBind mount, host\u0026rsquo;taki bir dizini konteynerin içine doğrudan bağlamaktır. Konteyner o dizini kendi dosya sistemi gibi görür. Konteyner root olarak çalışıyorsa dizindeki her şeyi okuyup yazabilir.\nBeklenen kullanım kabaca şöyle bir çağrıdır:\ndocker run -d \\ --gpus all \\ -v \u0026#34;/home/\u0026lt;kullanıcı\u0026gt;/workspace\u0026#34;:/workspace \\ \u0026#34;\u0026lt;imaj\u0026gt;\u0026#34; Kullanıcıların terminal erişimi olduğu için policy\u0026rsquo;nin yalnızca bu komutu değil, Docker API\u0026rsquo;sine gelebilecek her isteği hesaba katması gerekir.\nYazıdaki yaklaşım, root olarak çalışan standart dockerd\u0026rsquo;nin önüne bir authorization katmanı koymaktır. Rootless Docker ve userns-remap gibi alternatifler Bölüm 10\u0026rsquo;da ele alınıyor.\n3. Docker authorization plugin nasıl çalışır? Docker\u0026rsquo;ın varsayılan erişim modeli \u0026ldquo;ya hep ya hiç\u0026quot;tir. Daemon\u0026rsquo;a erişebilen her istemci her API çağrısını yapabilir. Authorization plugin\u0026rsquo;leri bu modele bir karar noktası ekler. Daemon, her API isteğini işlemeden önce yapılandırılmış plugin\u0026rsquo;lere izin verip vermediklerini sorar.\nİstek akışı:\nsequenceDiagram participant C as docker CLI / istemci participant D as dockerd (API sunucusu) participant M as Authz middleware participant P as opa-docker-authz plugin participant O as OPA (plugin içinde) participant H as API handler C-\u0026gt;\u0026gt;D: HTTP isteği (ör. POST /v1.xx/containers/create) D-\u0026gt;\u0026gt;M: isteği middleware\u0026#39;e ver alt zincir boş M-\u0026gt;\u0026gt;H: doğrudan ilet (kontrol yok) H--\u0026gt;\u0026gt;C: yanıt else zincirde plugin var M-\u0026gt;\u0026gt;P: AuthZReq (Method, URI, başlıklar, JSON gövde, User) P-\u0026gt;\u0026gt;P: policy dosyasını diskten oku P-\u0026gt;\u0026gt;O: input ile data.docker.authz.allow değerlendir O--\u0026gt;\u0026gt;P: true / false / undefined / hata P--\u0026gt;\u0026gt;M: Allow: true veya false + mesaj alt izin M-\u0026gt;\u0026gt;H: isteği işle H--\u0026gt;\u0026gt;C: yanıt else ret M--\u0026gt;\u0026gt;C: \u0026#34;authorization denied by plugin ...\u0026#34; end end Yazının geri kalanı için önemli ayrıntılar:\nZincir boşsa kontrol yoktur. Moby\u0026rsquo;nin pkg/authorization/middleware.go dosyasındaki WrapHandler, plugin listesi boşsa isteği doğrudan handler\u0026rsquo;a verir. Middleware\u0026rsquo;de \u0026ldquo;plugin olmalıydı ama yok\u0026rdquo; diye bir uyarı mekanizması yoktur. Bölüm 6\u0026rsquo;daki tuzağın temeli budur.\nMiddleware fail-closed çalışır. Docker\u0026rsquo;ın resmi dokümanına göre zincirdeki bir plugin\u0026rsquo;e ulaşılamazsa istek reddedilir. Docker, plugin yazarlarına da fail-closed davranmalarını önerir. Dolayısıyla \u0026ldquo;plugin çöktü, her şey açıldı\u0026rdquo; senaryosu middleware düzeyinde beklenmez. Risk, plugin\u0026rsquo;in zincirden hiçbir uyarı olmadan çıkarılmasıdır.\nKullanıcı kimliği çoğu kurulumda boştur. Plugin\u0026rsquo;e giden istekte User ve AuthenticationMethod alanları vardır. Moby kaynak koduna göre bu alanlar yalnızca istek TLS üzerinden geldiyse ve istemci bir client sertifikası sunduysa dolar. Kullanıcı adı sertifikanın CN alanından alınır. Unix socket üzerinden gelen isteklerde, yani yerel docker komutlarının neredeyse tamamında, iki alan da boş string\u0026rsquo;dir. Policy \u0026ldquo;bu isteği kim yaptı?\u0026rdquo; sorusunu cevaplayamaz. Bunun sonuçları Bölüm 10\u0026rsquo;da ele alınıyor.\nPlugin her şeyi görmez. Resmi dokümana göre:\nGövde plugin\u0026rsquo;e yalnızca JSON olarak iletilebildiğinde gönderilir. exec ve attach gibi hijack edilen bağlantılarda plugin yalnızca ilk HTTP isteğini görür. logs ve events gibi akan yanıtlarda yalnızca isteği görür. BuildKit\u0026rsquo;in kullandığı gRPC endpoint\u0026rsquo;i authorization\u0026rsquo;a tabi değildir. Image build\u0026rsquo;i authorization ile kısıtlamaya çalışan bir policy bu kanalı göremez. Endpoint, Docker API\u0026rsquo;sinde belirli bir işlemi yapan yoldur, örneğin /containers/create.\n4. Kurulum opa-docker-authz, Docker managed plugin olarak kurulabilen, içinde OPA gömülü bir authorization plugin\u0026rsquo;idir. Örneklerde openpolicyagent/opa-docker-authz-v2:0.9 etiketi kullanılıyor. Bu sürüm OPA 0.60 ile gelir. Sürüm konusu Bölüm 8\u0026rsquo;de ayrıca ele alınıyor.\nKurulum:\ndocker plugin install --alias opa-docker-authz \\ --grant-all-permissions \\ openpolicyagent/opa-docker-authz-v2:0.9 \\ opa-args=\u0026#34;-policy-file /opa/policies/authz.rego\u0026#34; Policy yolu dikkat gerektirir. Plugin\u0026rsquo;in yapılandırması host\u0026rsquo;taki /etc/docker dizinini plugin\u0026rsquo;in içinde /opa yoluna salt okunur olarak bağlar. Host\u0026rsquo;ta /etc/docker/policies/authz.rego konumundaki dosya, plugin\u0026rsquo;in içinden /opa/policies/authz.rego olarak görünür. opa-args içine host yolu değil, plugin içindeki yol yazılmalıdır. Yol yanlışsa plugin her isteğe izin verir (Bölüm 6).\nDosya ve dizin izinleri:\ninstall -d -m 0755 -o root -g root /etc/docker/policies install -m 0644 -o root -g root authz.rego /etc/docker/policies/authz.rego Plugin\u0026rsquo;i daemon\u0026rsquo;un yetkilendirme zincirine eklemek için daemon.json:\n{ \u0026#34;authorization-plugins\u0026#34;: [\u0026#34;opa-docker-authz\u0026#34;] } Mevcut bir daemon.json varsa bu anahtar diğer ayarlarla birleştirilmelidir. Sıra: önce plugin kurulur, sonra daemon.json güncellenir, sonra daemon\u0026rsquo;un yapılandırmayı yeniden okuması sağlanır. Bunun için servis yeniden başlatılabilir. systemctl reload docker de zinciri yeniden kurar ve çalışan konteynerleri durdurmaz (Bölüm 6).\n5. Policy: Satır satır Aşağıdaki policy OPA 0.60\u0026rsquo;ın klasik Rego sözdizimiyle yazılmıştır.\npackage docker.authz default allow = false allow { not is_container_create } allow { is_container_create; not deny } is_container_create { input.Method == \u0026#34;POST\u0026#34; endswith(split(input.Path, \u0026#34;?\u0026#34;)[0], \u0026#34;/containers/create\u0026#34;) } package docker.authz ve allow kuralı, plugin\u0026rsquo;in varsayılan olarak sorguladığı karar noktasıdır: data.docker.authz.allow.\ndefault allow = false güvenli bir varsayılandır. Hiçbir allow kuralı eşleşmezse karar ret olur.\nSonraki iki satır policy\u0026rsquo;nin mimarisini belirler:\nKonteyner oluşturma isteği değilse izin ver. Konteyner oluşturma isteğiyse ve hiçbir deny kuralı tetiklenmediyse izin ver. is_container_create, API sürüm önekini (/v1.47/ gibi) atlamak için endswith kullanır ve sorgu parametrelerini (?name=...) split ile ayırır.\nKesin yasaklar:\ndeny { input.Body.HostConfig.Privileged == true } deny { count(input.Body.HostConfig.CapAdd) \u0026gt; 0 } deny { input.Body.HostConfig.PidMode == \u0026#34;host\u0026#34; } deny { input.Body.HostConfig.NetworkMode == \u0026#34;host\u0026#34; } deny { input.Body.HostConfig.IpcMode == \u0026#34;host\u0026#34; } deny { input.Body.HostConfig.UTSMode == \u0026#34;host\u0026#34; } deny { startswith(input.Body.HostConfig.UsernsMode, \u0026#34;host\u0026#34;) } deny { count(input.Body.HostConfig.Devices) \u0026gt; 0 } deny { s := input.Body.HostConfig.SecurityOpt[_]; contains(s, \u0026#34;unconfined\u0026#34;) } deny { s := input.Body.HostConfig.SecurityOpt[_]; contains(s, \u0026#34;no-new-privileges:false\u0026#34;) } deny { s := input.Body.HostConfig.SecurityOpt[_]; contains(s, \u0026#34;no-new-privileges=false\u0026#34;) } Bu kurallar şunları yasaklar: --privileged, --cap-add, host\u0026rsquo;un PID/ağ/IPC/UTS namespace\u0026rsquo;lerini paylaşmak, user namespace\u0026rsquo;i kapatmak, --device ile cihaz geçirmek ve seccomp/AppArmor gibi korumaları unconfined yapmak. Her biri tek başına konteynerden host\u0026rsquo;a geçiş için yeterli olabilir.\nBind mount kuralı:\ndeny { b := input.Body.HostConfig.Binds[_]; not bind_ok(b) } deny { m := input.Body.HostConfig.Mounts[_]; m.Type == \u0026#34;bind\u0026#34;; not mount_ok(m) } bind_ok(b) { parts := split(b, \u0026#34;:\u0026#34;) parts[1] == \u0026#34;/workspace\u0026#34; seg := split(parts[0], \u0026#34;/\u0026#34;) count(seg) == 4 seg[1] == \u0026#34;home\u0026#34; seg[3] == \u0026#34;workspace\u0026#34; } mount_ok(m) { m.Target == \u0026#34;/workspace\u0026#34; seg := split(m.Source, \u0026#34;/\u0026#34;) count(seg) == 4 seg[1] == \u0026#34;home\u0026#34; seg[3] == \u0026#34;workspace\u0026#34; } Docker\u0026rsquo;da bind mount iki ayrı alandan gelebilir. -v kaynak:hedef sözdizimi HostConfig.Binds dizisine, --mount type=bind,... sözdizimi HostConfig.Mounts dizisine yazılır. Policy ikisini de kontrol eder.\nKaynak yol / ile bölündüğünde tam dört parça olmalıdır: \u0026quot;\u0026quot;, \u0026quot;home\u0026quot;, kullanıcı adı, \u0026quot;workspace\u0026quot;. Hedef /workspace olmalıdır. Böylece /home/\u0026lt;kullanıcı\u0026gt;/workspace/alt-dizin gibi daha derin yollar da reddedilir. Gerekçe: Docker bind kaynağındaki sembolik bağları (symlink) çözer. Bu kural eklenmeden önce canlı ortamda şu görüldü: workspace içine host\u0026rsquo;un köküne işaret eden bir symlink konup bu alt yol bağlandığında host\u0026rsquo;un dosyaları okunabiliyordu. Dört parça kuralı alt yol üzerinden gelen symlink\u0026rsquo;i kapatır. Workspace dizininin kendisinin symlink olması ayrı bir risktir (Bölüm 10).\nGaranti ettikleri (canlı daemon üzerinde doğrulandı): --privileged, --cap-add, host kökünü ya da /etc\u0026lsquo;yi bağlamak, alt yol symlink\u0026rsquo;i, Docker socket\u0026rsquo;ini konteynere bağlamak, --device, --ipc=host ve --mount type=bind ile workspace dışı bağlama reddedilir. Beklenen kullanım (workspace bind ve --gpus all) çalışır. Makine yeniden başlatıldığında plugin geri gelir ve kurallar uygulanmaya devam eder.\nGaranti etmedikleri Bölüm 9 ve 10\u0026rsquo;da. Bir kısmı policy\u0026rsquo;nin eksik yazılmasından, bir kısmı mekanizmanın kendisinden kaynaklanır. Ancak önce, policy doğru olsa bile korumanın tamamen kapanabildiği durum ele alınmalı.\n6. Tuzak 1: Sessiz fail-open Belirti Plugin docker plugin ls çıktısında etkin görünür, daemon.json içinde authorization-plugins tanımlıdır, policy dosyası doğrudur. Buna rağmen docker run --rm --privileged alpine true başarıyla çalışır. Host bind mount\u0026rsquo;ları da reddedilmez. Daemon log\u0026rsquo;unda hata ya da uyarı yoktur.\nBu durum şu komut çifti çalıştırıldıktan sonra oluşur:\ndocker plugin disable --force opa-docker-authz docker plugin enable opa-docker-authz Bu komut çifti, \u0026ldquo;plugin\u0026rsquo;i yeniden yükleyip yeni policy\u0026rsquo;yi okutmak\u0026rdquo; amacıyla sık kullanılan bir alışkanlıktır.\nMekanizma: plugin zincirden düşer Moby kaynak kodunda üç parça bu davranışı açıklar:\ndaemon/pkg/plugin/backend_linux.go içindeki Disable() fonksiyonu, authorization tipindeki bir plugin devre dışı bırakıldığında AuthzMiddleware.RemovePlugin(name) çağırır. Plugin dockerd\u0026rsquo;nin yetkilendirme zincirinden çıkarılır. Aynı dosyadaki Enable() fonksiyonunda plugin\u0026rsquo;i middleware\u0026rsquo;e geri ekleyen bir çağrı yoktur. Plugin etkinleşir, docker plugin ls onu etkin gösterir, ama plugin zincirde değildir. daemon/command/daemon.go içindeki config reload yolu authzMiddleware.SetPlugins(cfg.AuthorizationPlugins) çağırır. Zinciri daemon.json içindeki listeden yeniden kuran yer budur. systemctl reload docker daemon\u0026rsquo;a SIGHUP gönderir ve bu yolu tetikler. Zincir boşken middleware her isteği doğrudan handler\u0026rsquo;a verir (Bölüm 3). Sonuç olarak disable/enable sonrasında authorization sessizce kapalıdır. Daemon hata vermez, plugin etkin görünür, policy dosyası doğrudur, ama hiçbir istek plugin\u0026rsquo;e gitmez. Davranış güncel moby kaynağında da aynıdır.\nKısaca: docker plugin disable authorization\u0026rsquo;ı kapatır, docker plugin enable geri açmaz, systemctl reload docker açar.\nTarihçe: zincirden çıkarma neden var? Zincirden çıkarma bir hata değil, bir düzeltmedir. 2017\u0026rsquo;de açılan moby issue #31836, authorization plugin\u0026rsquo;i devre dışı bırakıldıktan sonra daemon\u0026rsquo;un istekleri hâlâ o plugin\u0026rsquo;e gönderdiğini bildirdi. Plugin artık yanıt vermediği için tüm API istekleri bloklanıyordu.\nDüzeltme olan commit 38de272bd4, Disable() fonksiyonuna authorization tipindeki plugin\u0026rsquo;i middleware zincirinden çıkaran kodu ekledi. Aynı commit Enable() tarafına plugin\u0026rsquo;i zincire geri ekleyen bir kod eklemedi. Bu ilk düzeltme zincirden çıkarmayı farklı bir kodla yapıyordu; aynı yıl moby #33655 (\u0026ldquo;Eliminate authz plugin disable race\u0026rdquo;) bu kodu bugünkü RemovePlugin fonksiyonuna taşıdı ve davranış aynı kaldı. Bu bölümdeki sessiz fail-open, o düzeltmenin bu asimetrisinden doğan bir yan etkidir.\nGözlenen davranış Canlı bir daemon üzerindeki test sonuçları kaynak koddaki mekanizmayla uyumludur:\nAdım --privileged testi Policy yazıldı + systemctl reload docker Reddedildi Policy değişti + disable / enable Çalıştı (fail-open) Dizin 755, dosya 644 yapıldı + disable / enable Çalıştı (fail-open) Plugin yeniden kuruldu (disable → rm → install) + systemctl reload docker Reddedildi Davranış güncel sürümde de aynıdır: Docker Engine 29.9.0 ve opa-docker-authz v0.9 ile disable/enable sonrası --privileged çalışır, systemctl reload docker sonrası reddedilir.\nSon adımda zinciri yeniden kuran, yeniden kurulum değil reload\u0026rsquo;dur. Yeniden kurulum da bir disable/enable döngüsü içerir ve kendi başına plugin\u0026rsquo;i zincire geri eklemez. Zincire geri ekleme SetPlugins ile, yani reload sırasında olur.\nDaemon journal\u0026rsquo;ında dikkat çekici bir kayıt var: plugin, kendisini devre dışı bırakan POST .../plugins/opa-docker-authz/disable?force=1 isteğine izin vermiş (result: true). Bu policy yalnızca konteyner oluşturmayı denetlediği için disable isteği de authorization\u0026rsquo;dan geçer ve izin alır. Bu kayıttan sonra test isteklerine ait karar kaydı yoktur: istekler artık plugin\u0026rsquo;e ulaşmaz.\nYaygın yanlış teşhis: dosya izinleri Bu belirti için sık başvurulan açıklama şudur: \u0026ldquo;Policy dosyası 644 değilse plugin dosyayı okuyamaz, boş policy ile çalışır ve her şeye izin verir.\u0026rdquo; Bu açıklama iki nedenle yanlıştır:\nYukarıdaki tabloda izinler 644 yapıldıktan sonra disable/enable ile koruma hâlâ kapalıdır. Düzelten adım reload\u0026rsquo;dur. opa-docker-authz policy dosyasını os.ReadFile ile okur. Okuma hatası (izin hatası dahil) olursa isteği reddeder. İzin sorunu fail-closed bir sonuç üretir. Karışıklığın olası kaynağı: resmi openpolicyagent/opa CLI imajı root olmayan bir kullanıcıyla çalışır. 600 izinli bir policy dosyası bu imajla opa check edilirse \u0026ldquo;permission denied\u0026rdquo; alınır. Bu, plugin\u0026rsquo;in davranışı hakkında bilgi vermez. 755/644 izinleri, ayrı çalıştırılan opa check gibi araçların dosyayı okuyabilmesi için önerilen bir hijyen kuralıdır, ama fail-open\u0026rsquo;ın nedeni değildir.\nPlugin\u0026rsquo;in açıkça fail-open olduğu durum Plugin\u0026rsquo;in kaynak kodunda gerçekten fail-open olan bir dal vardır. Policy dosyası okunmadan önce os.Stat ile kontrol edilir. Dosya yoksa plugin şu mesajı log\u0026rsquo;a yazıp isteğe izin verir:\nOPA policy file %s does not exist, failing open and allowing request Dolayısıyla opa-args içindeki yolda bir yazım hatası ya da /etc/docker → /opa dönüşümünün yanlış uygulanması korumayı tamamen kapatır. Bu durumda plugin log\u0026rsquo;unda bir iz kalır.\nKaynak koddan çıkan karar tablosu:\nDurum Plugin kararı Policy dosyası yok İzin (fail-open), log\u0026rsquo;a yazılır Dosya okunamıyor (ör. izin hatası) Ret Rego derleme ya da değerlendirme hatası Ret allow undefined Ret Plugin zincirde değil Plugin\u0026rsquo;e hiç sorulmaz, izin Tespit Plugin\u0026rsquo;in \u0026ldquo;etkin\u0026rdquo; görünmesi ya da dosya hash\u0026rsquo;inin doğru olması bu sorunu yakalamaz. Policy dosyasının hash\u0026rsquo;ini, dosya modunu ve docker plugin ls çıktısındaki etkin durumu toplayan bir drift kontrolü, fail-open sırasında da \u0026ldquo;doğru\u0026rdquo; sonuç verir. Zincirin gerçek durumu için docker info gibi yapılandırma çıktılarına da dayanılmamalıdır.\nGüvenilir kontrol davranış testidir. Normal bir kullanıcı hesabıyla:\ndocker run --rm --privileged alpine true Bu komut şu mesajla reddedilmelidir:\ndocker: Error response from daemon: authorization denied by plugin opa-docker-authz:latest: request rejected by administrative policy Komutun yalnızca başarısız olması yeterli değildir. İmaj çekilemediği ya da daemon\u0026rsquo;a ulaşılamadığı için de başarısız olabilir. Çıktıda authorization denied geçtiği kontrol edilmelidir. Bu testin düzenli çalışan sürümü Bölüm 11\u0026rsquo;de.\n7. Tuzak 2: Policy güncelleme Plugin, kaynak koduna göre policy dosyasını her istekte diskten okur. Önbellek yoktur. Dosya değiştiği anda bir sonraki istek yeni policy ile değerlendirilir. Policy güncellemesi için plugin\u0026rsquo;i yeniden yüklemeye gerek yoktur.\nAsıl risk, disable/enable komut çiftinin güncelleme otomasyonuna girmesidir. Policy değiştiğinde plugin\u0026rsquo;i disable/enable yapan, daemon.json değişmediği için reload yapmayan bir otomasyon, her çalıştığında dokunduğu makinelerde authorization\u0026rsquo;ı bir sonraki reload ya da yeniden başlatmaya kadar kapatır. Dokümanda doğru prosedür yazılı olsa bile otomasyon farklı bir şey yapıyorsa bu risk gözden kaçar.\nGüvenli policy güncellemesi:\nYeni policy\u0026rsquo;yi plugin\u0026rsquo;in kullandığı OPA sürümüyle derleyin (opa check) ve test girdileriyle değerlendirin (opa eval). Dosyayı yerine koyun. Plugin dosyayı her istekte okuduğu için yazma sırasında yarım bir dosya görülürse o istek derleme hatası yüzünden reddedilir. Bunu önlemek için yeni dosyayı aynı dizine geçici bir adla yazıp mv ile değiştirin. Plugin\u0026rsquo;e dokunmayın. --privileged testini çalıştırın. Plugin\u0026rsquo;in kendisi değiştiyse (sürüm yükseltme, yeniden kurulum) işlem bittikten sonra systemctl reload docker çalıştırın ve davranış testini tekrarlayın. Policy plugin API\u0026rsquo;sine yazmayı yasaklıyorsa (Bölüm 9), bu işlemlerden önce plugin\u0026rsquo;in zincirden daemon.json üzerinden çıkarılması gerekir.\nAuthorization\u0026rsquo;ı birden fazla makineye yaymak için bir desen: yedek al → reload → docker ps başarısızsa otomatik geri al → --privileged testi. Çalışan konteynerleri durdurmaz ve makinelerde paralel çalıştırılabilir.\n#!/usr/bin/env bash set -u cfg=/etc/docker/daemon.json bak=\u0026#34;$cfg.bak.$(date +%s)\u0026#34; cp -a \u0026#34;$cfg\u0026#34; \u0026#34;$bak\u0026#34; # authorization-plugins anahtarını mevcut ayarlarla birleştir jq \u0026#39;. + {\u0026#34;authorization-plugins\u0026#34;: [\u0026#34;opa-docker-authz\u0026#34;]}\u0026#39; \u0026#34;$bak\u0026#34; \u0026gt; \u0026#34;$cfg.new\u0026#34; \\ \u0026amp;\u0026amp; mv \u0026#34;$cfg.new\u0026#34; \u0026#34;$cfg\u0026#34; systemctl reload docker # Daemon sağlıklı değilse otomatik geri al if ! docker ps \u0026gt;/dev/null 2\u0026gt;\u0026amp;1; then cp -a \u0026#34;$bak\u0026#34; \u0026#34;$cfg\u0026#34; systemctl reload docker echo \u0026#34;ROLLBACK\u0026#34; exit 1 fi echo -n \u0026#34;ps=OK \u0026#34; # Davranış testi if docker run --rm --privileged alpine true 2\u0026gt;\u0026amp;1 | grep -q \u0026#34;authorization denied\u0026#34;; then echo \u0026#34;priv=DENIED\u0026#34; else echo \u0026#34;priv=OPEN\u0026#34; exit 2 fi Her makine ps=OK priv=DENIED raporlamadan dağıtım bitmiş sayılmamalı.\n8. Tuzak 3: Rego sözdizimi ve plugin sürümü Sürüm durumu OPA 1.0 ile Rego sözdizimi değişti. Kural gövdelerinden önce if, çok değerli kurallarda contains artık zorunludur. Bölüm 5\u0026rsquo;teki policy klasik (0.x) sözdizimiyle yazılmıştır.\nopa-docker-authz sürümleri:\nPlugin OPA Docker Hub\u0026rsquo;da managed plugin v0.9 0.60.0 Var (en yeni etiket) v0.10 1.3.0 Yok v0.11 1.21.1 Yok Proje bakımdadır ve yeni sürümler GitHub\u0026rsquo;da yayınlanır. Ancak docker plugin install ile Docker Hub\u0026rsquo;dan çekilebilen en yeni etiket 0.9\u0026rsquo;dur. 0.10 ve sonrası Docker Hub\u0026rsquo;da managed plugin olarak yayınlanmadığı için, bu sürümleri kullanmak plugin\u0026rsquo;i kaynak koddan derlemeyi gerektirir.\nSonuç: 0.9 için yazılmış klasik bir policy, plugin 0.10+ sürümüne yükseltildiğinde derlenmez. OPA 1.21.1 ile opa check:\nrego_parse_error: `if` keyword is required before rule body Plugin derleme hatasında isteği reddeder. Sonuç fail-closed\u0026rsquo;dır, ama docker ps dahil her istek reddedilir ve Docker kullanılamaz hâle gelir.\nKöprü: import rego.v1 İki sürümde de çalışan bir policy için import rego.v1 kullanılır. Bu import OPA 0.59.0\u0026rsquo;da eklendi. Policy OPA 1.x sözdizimine çevrilip başına bu satır konduğunda hem 0.60 hem 1.x onu derler.\npackage docker.authz import rego.v1 default allow := false allow if { is_container_create not deny } deny if input.Body.HostConfig.Privileged == true authz-hardened-v1.rego bu biçimdedir ve OPA 0.60.0 ile 1.21.1 üzerinde tüm test girdileriyle değerlendirildi. İki sürüm aynı kararları verir. Plugin yükseltmesinden önce policy\u0026rsquo;nin bu biçime çevrilmesi önerilir.\nRego tuzağı: hata \u0026ldquo;izin\u0026quot;e dönüşebilir OPA varsayılan olarak bir built-in fonksiyonun çalışma zamanı hatasını (örneğin geçersiz bir regex) hata olarak değil, undefined olarak ele alır. Plugin de OPA\u0026rsquo;yı StrictBuiltinErrors seçeneği olmadan çağırır.\nBir deny kuralı içinde built-in hata verirse kural undefined olur, yani tetiklenmez. not deny bu durumda true olur. Deny-list + not deny deseninde hata izin anlamına gelir.\nTest: bozuk bir regex içeren bir deny kuralıyla privileged girdi allow = true döndürür. Aynı değerlendirme --strict-builtin-errors ile çalıştırıldığında eval_builtin_error verir.\nÖnlemler:\nCI\u0026rsquo;da policy testlerini opa eval --strict-builtin-errors ile çalıştırın. deny kurallarında hata verebilecek built-in\u0026rsquo;lerden (regex, ayrıştırma fonksiyonları) mümkün olduğunca kaçının. Mümkünse deny-list yerine allow-list kullanın. Neyin yasak olduğunu değil, neyin izinli olduğunu tarif edin. Böylece undefined bir sonuç ret anlamına gelir. 9. Tuzak 4: Policy\u0026rsquo;nin göremedikleri Bölüm 5\u0026rsquo;teki policy ve sertleştirilmiş sürümü 19 test senaryosu üzerinde, hem opa eval ile hem canlı Docker daemon\u0026rsquo;u üzerinde test edildi.\nTest girdisi Orijinal Sertleştirilmiş Kendi workspace\u0026rsquo;i izin izin Başka kullanıcının workspace\u0026rsquo;i izin izin --privileged ret ret /etc bind ret ret Workspace alt yolu ret ret --mount type=bind ile kök dizin ret ret Driver seçenekli volume mount izin ret --volumes-from izin ret --gpus izin izin Gövdesiz create isteği izin ret Plugin devre dışı bırakma isteği izin ret Plugin listeleme (GET) izin izin Driver seçenekli volume create izin ret Sade volume create izin izin Gövdesiz volume create izin ret exec izin izin exec --privileged izin ret .. içeren yol izin ret --cap-add ret ret Canlı daemon testleri plugin v0.9 (OPA 0.60) ile yapıldı. opa eval ile yapılan değerlendirmede sertleştirilmiş sütun, klasik sözdizimli authz-hardened.rego için OPA 0.60\u0026rsquo;ta, authz-hardened-v1.rego için hem OPA 0.60 hem 1.21.1\u0026rsquo;de aynıdır. Başka kullanıcının workspace\u0026rsquo;i ve exec satırları Bölüm 10\u0026rsquo;un konusudur.\nSade volume create satırıyla ilgili bir tutarsızlık var. Adlandırılmış bir volume -v isim:/yol ile bağlandığında HostConfig.Binds\u0026lsquo;e düşer, /home/... biçimine uymadığı için bind kuralına takılır ve reddedilir. Aynı volume --mount type=volume ile bağlandığında driver yapılandırması olmadığı için izin alır. Sade volume\u0026rsquo;lar host dizini göstermediği için bu zararsızdır. -v ile de izin vermek isteyen bir policy, bind_ok\u0026lsquo;a adlandırılmış volume için ayrı bir dal eklemelidir.\nVolume tipindeki mount\u0026rsquo;lar Orijinal policy HostConfig.Mounts girdilerini yalnızca Type == \u0026quot;bind\u0026quot; ise kontrol eder. Docker\u0026rsquo;ın local volume driver\u0026rsquo;ı ise driver seçenekleriyle host\u0026rsquo;taki bir dizini gösteren bir volume oluşturmayı destekler. Böyle bir mount Type == \u0026quot;volume\u0026quot; olarak gelir ve bind kuralına girmez. Konteyner host\u0026rsquo;un keyfi bir dizinine erişebilir.\nDüzeltme: driver yapılandırması içeren volume mount\u0026rsquo;larını reddetmek.\ndeny { m := input.Body.HostConfig.Mounts[_]; m.Type == \u0026#34;volume\u0026#34;; m.VolumeOptions.DriverConfig } volume create seçenekleri Aynı sonuca, önce ayrı bir POST /volumes/create isteğiyle driver seçenekli bir volume oluşturup sonra onu bağlayarak da ulaşılabilir. Orijinal policy konteyner oluşturma dışındaki her endpoint\u0026rsquo;e izin verdiği için bu istek denetlenmez.\nDüzeltme: volume oluşturmayı ayrı bir karar noktası yapmak ve yalnızca driver seçeneği içermeyen istekleri kabul etmek. Seçeneksiz volume\u0026rsquo;lar serbest kalır.\nallow { is_volume_create; volume_ok } is_volume_create { input.Method == \u0026#34;POST\u0026#34; endswith(split(input.Path, \u0026#34;?\u0026#34;)[0], \u0026#34;/volumes/create\u0026#34;) } volume_ok { is_object(input.Body); count(object.get(input.Body, \u0026#34;DriverOpts\u0026#34;, {})) == 0 } Kural bilinçli olarak allow-list biçiminde. volume_deny { count(input.Body.DriverOpts) \u0026gt; 0 } gibi bir deny-list kuralı gövde gelmediğinde tetiklenmez ve istek geçer (aşağıda \u0026ldquo;Gövdesiz istek\u0026rdquo;). is_object kontrolü, gövdenin hiç gelmediği ya da null geldiği durumu da reddeder. Docker CLI volume create isteğinde gövdeyi her zaman gönderir ve seçenek yoksa DriverOpts boş bir nesnedir, bu yüzden normal kullanım etkilenmez.\n--volumes-from HostConfig.VolumesFrom, başka bir konteynerin tüm mount\u0026rsquo;larını devralmayı sağlar. Paylaşımlı bir makinede bu, başka bir kullanıcının workspace\u0026rsquo;i takılı konteynerinden o workspace\u0026rsquo;i devralmak demektir. Orijinal policy bu alana bakmaz.\ndeny { count(input.Body.HostConfig.VolumesFrom) \u0026gt; 0 } Yol normalizasyonu Policy yolu yalnızca / ile böler, çözümlemez. /home/../workspace dört parçaya bölünür ve kurala uyar. Bu örnek doğrudan hassas veriye erişim sağlamaz, ama policy\u0026rsquo;nin yolu metin olarak değerlendirdiğini gösterir. Sertleştirilmiş sürüm kullanıcı adı segmentinde boş değeri, . ve ..\u0026lsquo;yı reddeder:\nbind_ok(b) { parts := split(b, \u0026#34;:\u0026#34;) parts[1] == \u0026#34;/workspace\u0026#34; seg := split(parts[0], \u0026#34;/\u0026#34;) count(seg) == 4 seg[1] == \u0026#34;home\u0026#34; not {\u0026#34;\u0026#34;, \u0026#34;.\u0026#34;, \u0026#34;..\u0026#34;}[seg[2]] seg[3] == \u0026#34;workspace\u0026#34; } Plugin\u0026rsquo;in girdisinde symlink\u0026rsquo;leri çözülmüş yolu taşıması beklenen bir Resolved alanı vardır. Ancak managed plugin\u0026rsquo;de bu alan boş gelir. Plugin çözümlemeyi kendi dosya sisteminde yapar ve plugin\u0026rsquo;in içinde host\u0026rsquo;un /home dizini yoktur. Bu nedenle Resolved symlink savunması olarak kullanılamaz.\nGövdesiz istek Deny-list deseninin en sinsi kör noktası budur. Bütün deny kuralları input.Body.HostConfig altındaki alanlara bakar. Gövde plugin\u0026rsquo;e ulaşmazsa ya da plugin onu ayrıştıramazsa hiçbir deny kuralı tetiklenmez, not deny true olur ve istek geçer.\nPlugin\u0026rsquo;in gövdeyi her zaman ayrıştıracağı varsayılmamalıdır. Docker\u0026rsquo;ın dokümanı da gövdenin plugin\u0026rsquo;e her durumda iletilmediğini belirtir. Düzeltme tek satırdır:\ndeny { not input.Body.HostConfig } Bu kural, konteyner oluşturma isteğinde HostConfig yoksa isteği reddeder. Normal docker run her zaman HostConfig gönderdiği için meşru kullanımı etkilemez.\nBu kör nokta teorik değil. CVE-2024-41110\u0026rsquo;da, özel hazırlanmış bir API isteğiyle daemon isteği authorization plugin\u0026rsquo;ine gövdesiz iletebiliyordu. Gövdeye bakarak karar veren plugin\u0026rsquo;ler, normalde reddedecekleri bir isteğe izin verebiliyordu. Açık ilk olarak Ocak 2019\u0026rsquo;da Docker Engine v18.09.1\u0026rsquo;de düzeltilmişti. Düzeltme sonraki ana sürümlere taşınmadığı için regresyon olarak geri geldi. Advisory\u0026rsquo;ye göre etkilenen sürümler v19.03.15, v20.10.27, v23.0.14, v24.0.9, v25.0.5, v26.0.2, v26.1.4, v27.0.3, v27.1.0 ve her birinin dalındaki önceki sürümlerdir. Advisory yamalı sürümü yalnızca üç dal için verir: v23.0.14, v26.1.4 ve v27.1.0\u0026rsquo;dan sonraki sürümler. docker-ce için düzeltme v27.1.1\u0026rsquo;dedir. 19.03, 20.10, 24.0, 25.0, 26.0 ve 27.0 dalları için advisory yamalı sürüm vermez. Bu dallardan birindeyseniz yamalı bir sürüme yükseltin.\ndeny { not input.Body.HostConfig } kuralı tam bu durumu yakalar: gövdesiz bir create isteğinde HostConfig undefined olur ve istek reddedilir. Engine yamalı olsa bile kural savunma derinliği olarak kalmalıdır, çünkü policy\u0026rsquo;nin güvenliği engine\u0026rsquo;deki tek bir düzeltmeye bağlı olmamalı.\nAynı kör nokta, gövdeye bakan her deny-list kuralında vardır. Policy\u0026rsquo;ye konteyner oluşturma dışında bir karar noktası eklendiğinde (volume create, exec) o noktanın da gövdesiz isteği reddettiği ayrıca test edilmelidir.\nPlugin API\u0026rsquo;si Bölüm 6\u0026rsquo;daki journal kaydında plugin\u0026rsquo;i devre dışı bırakma isteği authorization\u0026rsquo;dan geçer ve izin alır. Bu, socket\u0026rsquo;e erişebilen her kullanıcının authorization\u0026rsquo;ın tamamını kapatabileceği anlamına gelir. Bölüm 6\u0026rsquo;daki mekanizmanın doğrudan sonucudur.\nDüzeltme: plugin API\u0026rsquo;sinde okuma dışındaki her işlemi reddetmek.\nallow { not is_container_create; not is_volume_create; not is_plugin_write } is_plugin_write { input.Method != \u0026#34;GET\u0026#34;; input.PathArr[1] == \u0026#34;plugins\u0026#34; } is_plugin_write { input.Method != \u0026#34;GET\u0026#34;; startswith(input.PathArr[1], \u0026#34;v\u0026#34;); input.PathArr[2] == \u0026#34;plugins\u0026#34; } İkinci kural sürüm önekli yolları (/v1.47/plugins/...) yakalar.\nOperasyonel sonuç: bu kural yöneticinin de socket üzerinden plugin\u0026rsquo;i devre dışı bırakmasını engeller. Plugin\u0026rsquo;i yükseltmek ya da yeniden kurmak için önce authorization-plugins anahtarı daemon.json\u0026lsquo;dan çıkarılıp reload yapılır, işlem bitince anahtar geri konur ve tekrar reload yapılır. Bu takas, Bölüm 7\u0026rsquo;deki tehlikeli disable/enable alışkanlığını da imkânsız hâle getirir.\nexec --privileged docker exec --privileged, çalışan bir konteynerde privileged bir süreç başlatır. Bu istek POST /containers/{id}/exec endpoint\u0026rsquo;ine gider ve gövdesinde Privileged: true alanı bulunur. Bölüm 5\u0026rsquo;teki policy yalnızca konteyner oluşturmayı denetlediği için bu istek serbesttir. Dolayısıyla create aşamasında reddedilen privileged yetki, exec aşamasında alınabilir.\nKimlik gerektirmeyen bu kısım policy ile kapatılabilir:\nallow { not is_container_create; not is_volume_create; not is_plugin_write; not is_exec_create } allow { is_exec_create; exec_ok } is_exec_create { input.Method == \u0026#34;POST\u0026#34; input.PathArr[count(input.PathArr) - 1] == \u0026#34;exec\u0026#34; } exec_ok { input.Body.Privileged == false } İlk satır, \u0026ldquo;Plugin API\u0026rsquo;si\u0026rdquo; başlığındaki genel allow kuralının yerini alır.\nKural bilinçli olarak allow-list biçiminde. Docker CLI exec isteğinde Privileged alanını her zaman gönderir, bu yüzden normal docker exec çalışmaya devam eder. Allow-list olduğu için gövdesiz ya da alanı eksik bir istek reddedilir.\nDeny-list ile yazılmış exec_deny { not input.Body } gibi bir kural bu işi yapmaz. Plugin gövdeyi ayrıştıramadığında input.Body alanı null gelebilir. null Rego\u0026rsquo;da tanımlı bir değerdir, false değildir, dolayısıyla not input.Body false olur. Gövdesiz bir privileged exec isteği böyle bir kuraldan geçer. Create tarafındaki deny { not input.Body.HostConfig } kuralı bu sorundan etkilenmez: null bir gövdenin HostConfig alanı undefined olur ve kural tetiklenir.\n--gpus ve DeviceRequests --gpus, HostConfig.Devices alanına değil HostConfig.DeviceRequests alanına yazılır. Devices kuralı GPU erişimini engellemez. Bu senaryoda GPU erişimi hedefin parçası olduğu için alan bilinçli olarak açık bırakıldı. GPU\u0026rsquo;yu kısıtlamak isteyen bir policy\u0026rsquo;nin DeviceRequests\u0026lsquo;i ayrıca ele alması gerekir.\nKontrol edilmeyen diğer alanlar CgroupnsMode, CgroupParent, Sysctls, Runtime ve PortBindings iki policy\u0026rsquo;de de kontrol edilmez. Bunlar daha düşük riskli kabul edildi. Deny-list yaklaşımının doğası gereği, Docker API\u0026rsquo;sine her yeni alan eklendiğinde liste gözden geçirilmelidir.\n10. Authorization plugin\u0026rsquo;inin veremedikleri Sertleştirilmiş tabloda iki satır hâlâ açıktır: başka kullanıcının workspace\u0026rsquo;i ve exec. exec --privileged policy ile kapatılabilir (Bölüm 9). Ama \u0026ldquo;kimin konteyneri?\u0026rdquo; sorusuna dayanan kısıtlar policy\u0026rsquo;yi iyileştirerek kapatılamaz.\nKimlik yok Unix socket üzerinden gelen isteklerde User alanı boştur (Bölüm 3). Policy /home/\u0026lt;kullanıcı\u0026gt;/workspace yolunun biçimini kontrol edebilir, ama isteği yapanın o \u0026lt;kullanıcı\u0026gt; olup olmadığını bilemez. Bir kullanıcı başka bir kullanıcının workspace\u0026rsquo;ini kendi konteynerine bağlayabilir.\nEv dizinlerinin 0700 izinli olması bunu durdurmaz. Dosyalara erişen, root olarak çalışan daemon\u0026rsquo;dur. Yerel diskteki dizinler için bu doğrudan okuma ve yazma erişimi demektir. Workspace\u0026rsquo;ler NFS üzerinden sec=krb5 ile bağlıysa, root daemon\u0026rsquo;un başka bir kullanıcının verisine erişip erişemeyeceği Kerberos kimlik eşlemesine bağlıdır.\nAynı nedenle bir risk daha vardır. Kullanıcı kendi ev dizininin sahibi olduğu için workspace dizinini silip yerine host\u0026rsquo;ta başka bir yeri gösteren bir symlink koyabilir. Yol biçimi policy\u0026rsquo;den geçer ve Docker bind kaynağındaki symlink\u0026rsquo;i çözdüğü için (Bölüm 5) symlink\u0026rsquo;in gösterdiği yer bağlanır. Workspace bir NFS mount noktasıysa silinemez. Mount yokken ya da workspace yerel bir dizinse bu mümkündür. Yol biçimine bakan bir policy bu riski kapatamaz.\nTLS client sertifikalarıyla kimlik taşımak teorik olarak mümkündür. Ancak bu, kullanıcıların yerel socket yerine TLS üzerinden ve kendi sertifikalarıyla bağlanmasını gerektirir. Paylaşımlı bir iş istasyonu için bu ayrı bir altyapı işidir.\nexec, commit, rm serbest Policy yalnızca konteyner oluşturmayı denetler. Kimlik olmadığı için \u0026ldquo;bu konteyner kimin?\u0026rdquo; sorusuna dayanan bir kural da yazılamaz. Bir kullanıcı:\nbaşka bir kullanıcının konteynerine root olarak exec ile girebilir, o konteyneri commit ile imaja çevirip dışarı alabilir, onu durdurabilir ya da silebilir. exec tamamen yasaklanabilir, ama bu durumda kullanıcılar kendi konteynerlerine de giremez. Sahiplik bilgisi olmadan seçici bir kural yazılamaz.\ndocker grubu root eşdeğeridir Docker\u0026rsquo;ın resmi dokümanına göre docker grubu kullanıcıya root düzeyinde yetki verir ve Docker daemon\u0026rsquo;unu yalnızca güvenilir kullanıcılar kontrol edebilmelidir. Authorization plugin\u0026rsquo;i bu gerçeği değiştirmez, yalnızca bazı yolları kapatır. Bu yolların listesi kolayca eksik kalabilir. Plugin, bir yönetici hatasıyla ya da policy yeterince sıkı değilse sıradan bir kullanıcının isteğiyle sessizce devreden çıkabilir.\nAuthorization tek başına bir güvenlik sınırı değil Riskleri iki kategoriye ayırmak işe yarar:\nTasarım gereği açıklar: Docker\u0026rsquo;ın meşru özellikleriyle host\u0026rsquo;a erişim (--privileged, host bind mount, volume driver seçenekleri gibi). Authorization policy\u0026rsquo;si bunları kapatmak için vardır. Runtime kaçış açıkları: runc ya da kernel\u0026rsquo;deki güvenlik hataları üzerinden konteynerden kaçış. Bunları hiçbir policy kapatmaz. Çare runc, Docker ve kernel\u0026rsquo;i güncel tutmaktır. Authorization plugin\u0026rsquo;i birinci kategoride işe yarayan bir katmandır. Ancak kimlik olmadığı, plugin zincirden düşebildiği ve deny-list eksik kalabildiği için, güvenilmeyen kullanıcılara karşı tek başına yeterli değildir.\nAlternatifler Rootless Docker: Daemon kullanıcının kendi yetkileriyle çalışır. Root eşdeğeri sorun büyük ölçüde ortadan kalkar. Podman: Daemon\u0026rsquo;suz, rootless çalışabilen bir alternatif. userns-remap: Konteynerdeki root\u0026rsquo;u host\u0026rsquo;ta yetkisiz bir UID aralığına eşler. Kullanıcı başına ayrı daemon: Her kullanıcının kendi socket\u0026rsquo;i ve izolasyonu olur. Kubernetes + admission control: Kimlik ve yetkilendirme API sunucusunda yerleşiktir. Policy (örneğin OPA Gatekeeper ile) kimliği bilen bir bağlamda yazılır. Root sahipli bir başlatıcı: Kullanıcılara Docker socket\u0026rsquo;i yerine, yalnızca izin verilen parametrelerle konteyner başlatan, root\u0026rsquo;a ait küçük bir araç verilir. Kimlik işletim sisteminden gelir. Her seçeneğin bir bedeli vardır. Rootless Docker mevcut bir kuruluma sonradan eklendiğinde uyum sorunları çıkarabilir. userns-remap, konteynerdeki root\u0026rsquo;u host\u0026rsquo;ta başka bir UID\u0026rsquo;ye eşlediği için kullanıcıların NFS\u0026rsquo;teki verilerine kendi kimlikleriyle erişmesini bozabilir. GPU erişimi de etkilenebilir. Kimlik gerektiren gereksinimler için root sahipli bir başlatıcı ya da kullanıcı başına ayrı daemon, authorization plugin\u0026rsquo;inden daha sağlam bir temel sunar.\n11. Production kontrol listesi Sürüm\nDocker Engine en az 29.3.1 olsun. Bu sürüm, AuthZ plugin\u0026rsquo;lerinin atlatılabildiği CVE-2026-34040\u0026rsquo;ı ve docker plugin install sırasında privilege doğrulamasının atlanabildiği CVE-2026-33997\u0026rsquo;yi yamalar. Daha eski bir sürümde kalmak zorundaysanız en azından CVE-2024-41110 için yamalı bir sürüm kullanın. Advisory yamalı sürümü yalnızca 23.0, 26.1 ve 27.1 dalları için verir: v23.0.14, v26.1.4 ve v27.1.0\u0026rsquo;dan sonraki sürümler (docker-ce v27.1.1). 19.03, 20.10, 24.0, 25.0, 26.0 ve 27.0 dalları için yamalı sürüm verilmez; bu dallardaysanız yamalı bir sürüme yükseltin (Bölüm 9). İzinler\nPolicy dizini 0755 root:root, dosyası 0644 root:root olsun. Fail-open\u0026rsquo;ın nedeni bu değildir. Ayrı çalıştırılan opa check gibi araçların dosyayı okuyabilmesi için önerilen bir hijyen kuralıdır. Policy yolunu plugin içindeki yola göre yazın (/etc/docker/... → /opa/...). Yol yanlışsa plugin açıkça fail-open olur. Davranış testi\nHer kurulumdan, her policy değişikliğinden ve her plugin işleminden sonra normal bir kullanıcıyla docker run --rm --privileged alpine true çalıştırın. Yalnızca çıkış kodunu değil, authorization denied mesajını kontrol edin. docker plugin ls, dosya hash\u0026rsquo;leri ve dosya modları zincirin durumunu göstermez. Bunlarla sınırlı bir drift kontrolü fail-open\u0026rsquo;ı yakalamaz. Periyodik test ve alarm\nDavranış testini düzenli aralıklarla çalıştırın ve reddedilmezse alarm üretin. Bölüm 6\u0026rsquo;daki durumu en erken yakalayacak kontrol budur: #!/usr/bin/env bash # Root olmayan, docker grubundaki bir servis hesabıyla çalıştırın. out=$(docker run --rm --privileged alpine true 2\u0026gt;\u0026amp;1) if ! grep -q \u0026#34;authorization denied\u0026#34; \u0026lt;\u0026lt;\u0026lt;\u0026#34;$out\u0026#34;; then logger -p auth.crit \u0026#34;docker-authz: privileged test NOT denied: ${out:-\u0026lt;başarılı\u0026gt;}\u0026#34; exit 1 fi Güncelleme prosedürü\nPolicy değişikliği için plugin\u0026rsquo;e dokunmayın. Dosyayı değiştirin, test edin. docker plugin disable/enable komutlarını policy güncellemesi için kullanmayın. Plugin işlemlerinden (yükseltme, yeniden kurulum) önce plugin\u0026rsquo;i daemon.json\u0026lsquo;dan çıkarıp reload yapın. İşlem bitince geri ekleyip tekrar reload yapın ve davranış testini tekrarlayın. Otomasyon betiklerini dokümandaki prosedürle karşılaştırın. Plugin API\u0026rsquo;sine yazma işlemlerini policy\u0026rsquo;de reddedin. Plugin sürümünü yükseltmeden önce policy\u0026rsquo;yi import rego.v1 biçimine çevirin ve hedef OPA sürümüyle opa check çalıştırın. Policy\nGövdesiz istekleri reddedin: deny { not input.Body.HostConfig }. Konteyner oluşturma dışındaki karar noktalarında (volume create, exec) allow-list kullanın ve gövdesiz istekle test edin. Mounts içindeki volume tipini, volume create seçeneklerini ve VolumesFrom\u0026lsquo;u kontrol edin. Yol segmentlerinde ., .. ve boş değeri reddedin. CI\u0026rsquo;da --strict-builtin-errors ile test edin. Yedekleme\n/var/lib/docker dizinini yedekten hariç tutmayın ya da plugin\u0026rsquo;i geri yükleme prosedürüne açıkça ekleyin. Plugin ikilisi orada durur. daemon.json plugin\u0026rsquo;i isterken plugin yoksa validateAuthzPlugins başarısız olur ve dockerd başlamaz. Sonuç fail-closed\u0026rsquo;dır: authorization açılmaz ama makinede Docker tamamen durur. Loglama\nPlugin\u0026rsquo;in karar log\u0026rsquo;larını merkezi bir yere gönderin. Plugin API\u0026rsquo;sine verilen izinler ve ardından kesilen karar log\u0026rsquo;ları, zincirden düşmenin ilk izleridir. failing open and allowing request mesajı için ayrı bir alarm kuralı tanımlayın. 12. Sonuç Bir güvenlik kontrolünün çalıştığını \u0026ldquo;etkin\u0026rdquo; görünmesinden değil, gerçekten engelleyip engellemediğini test ederek anlarsınız. Plugin etkin görünebilir, policy dosyası doğru ve izinler düzgün olabilir. Bunlara rağmen authorization zinciri boş olabilir. Tek satırlık bir docker run --privileged testi bu durumu bir saniyede gösterir. docker plugin disable authorization\u0026rsquo;ı kapatır, enable geri açmaz, systemctl reload docker açar.\nDocker authorization plugin\u0026rsquo;i, docker grubunun root eşdeğeri olduğu gerçeğini değiştirmez. Kimlik bilmeyen, yalnızca bazı endpoint\u0026rsquo;leri denetleyen ve sessizce devreden çıkabilen bir katmandır. Güvenilir kullanıcılar arasında kazaları önlemek için faydalıdır. Güvenilmeyen kullanıcıları ayırmak için rootless çalışma, kullanıcı başına izolasyon ya da kimliği bilen bir kontrol düzlemi gibi daha sağlam bir temel gerekir.\nBu olaydan sonra davranış testini periyodik olarak çalıştırıyorum. \u0026ldquo;Etkin görünmek\u0026rdquo; ile \u0026ldquo;çalışmak\u0026rdquo; arasındaki farkı test etmeden bilemezsiniz.\nGüncelleme (12 Ekim 2026) Bölüm 6\u0026rsquo;ya zincirden çıkarmanın tarihçesi, Bölüm 9\u0026rsquo;a CVE-2024-41110 ve Bölüm 11\u0026rsquo;e minimum Docker Engine sürümü eklendi.\n13. Kaynaklar Docker, Access authorization plugin: https://docs.docker.com/engine/extend/plugins_authorization/ Docker, Linux post-installation steps (docker grubu): https://docs.docker.com/engine/install/linux-postinstall/ Docker, Docker daemon attack surface: https://docs.docker.com/engine/security/#docker-daemon-attack-surface Docker, dockerd configuration reload behavior: https://docs.docker.com/reference/cli/dockerd/#configuration-reload-behavior moby, pkg/authorization/middleware.go: https://github.com/moby/moby/blob/b1bf272a8c767e2a21737fa0625844e9970c3dc2/pkg/authorization/middleware.go moby, daemon/pkg/plugin/backend_linux.go: https://github.com/moby/moby/blob/b1bf272a8c767e2a21737fa0625844e9970c3dc2/daemon/pkg/plugin/backend_linux.go moby, daemon/command/daemon.go: https://github.com/moby/moby/blob/b1bf272a8c767e2a21737fa0625844e9970c3dc2/daemon/command/daemon.go moby, issue #31836 (disable edilen authz plugin\u0026rsquo;in istekleri bloklaması): https://github.com/moby/moby/issues/31836 moby, commit 38de272bd4 (disable edilen authz plugin\u0026rsquo;i zincirden çıkarma): https://github.com/moby/moby/commit/38de272bd4 moby, PR #33655 (Eliminate authz plugin disable race): https://github.com/moby/moby/pull/33655 NVD, CVE-2024-41110: https://nvd.nist.gov/vuln/detail/CVE-2024-41110 moby, GHSA-v23v-6jw2-98fq (CVE-2024-41110 advisory): https://github.com/moby/moby/security/advisories/GHSA-v23v-6jw2-98fq NVD, CVE-2026-34040: https://nvd.nist.gov/vuln/detail/CVE-2026-34040 NVD, CVE-2026-33997: https://nvd.nist.gov/vuln/detail/CVE-2026-33997 opa-docker-authz, main.go: https://github.com/open-policy-agent/opa-docker-authz/blob/v0.9/main.go opa-docker-authz, sürümler: https://github.com/open-policy-agent/opa-docker-authz/releases opa-docker-authz v0.9, go.mod: https://github.com/open-policy-agent/opa-docker-authz/blob/v0.9/go.mod Docker Hub, openpolicyagent/opa-docker-authz-v2 etiketleri: https://hub.docker.com/r/openpolicyagent/opa-docker-authz-v2/tags OPA, v0 → v1 yükseltme rehberi: https://www.openpolicyagent.org/docs/v0-upgrade OPA, v0.59.0 sürüm notları (rego.v1 import\u0026rsquo;u): https://github.com/open-policy-agent/opa/releases/tag/v0.59.0 OPA, hatalar ve strict built-in errors: https://www.openpolicyagent.org/docs/errors ","permalink":"https://onurbaydas.com/posts/docker-authz-opa/","summary":"\u003cp\u003e\u003cem\u003eEnglish version: \u003ca href=\"/posts/docker-authz-opa-en/\"\u003eDocker Authorization with OPA\u003c/a\u003e\u003c/em\u003e\u003c/p\u003e\n\u003ch2 id=\"1-giriş\"\u003e1. Giriş\u003c/h2\u003e\n\u003cp\u003ePaylaşımlı, çok kullanıcılı Linux iş istasyonlarında Docker\u0026rsquo;ı kısıtlamak için \u003ccode\u003eopa-docker-authz\u003c/code\u003e kurdum. Rutin bir policy güncellemesinden sonra \u003ccode\u003e--privileged\u003c/code\u003e konteynerlerin sessizce çalıştığını fark ettim. Bu yazı, o olayın ve sonrasında kaynak kodda bulduklarımın özeti.\u003c/p\u003e\n\u003cp\u003eDocker authorization plugin\u0026rsquo;leri, Docker daemon\u0026rsquo;una gelen her API isteğini işlenmeden önce bir policy\u0026rsquo;ye göre değerlendirmeyi sağlar. \u003ccode\u003eopa-docker-authz\u003c/code\u003e, bu mekanizmayı OPA (Open Policy Agent) ve Rego policy diliyle uygulayan bir plugin\u0026rsquo;dir.\u003c/p\u003e\n\u003cp\u003eBu yazı şu konuları ele alıyor:\u003c/p\u003e","title":"OPA ile Docker Authorization: Sessiz Fail-Open ve Canlı Ortamdan Dersler"},{"content":"Ben Onur Baydaş, Türkiye\u0026rsquo;de çalışan bir sistem ve altyapı mühendisiyim. 2024\u0026rsquo;ten bu yana on-prem altyapı tasarlıyor, kuruyor, işletiyor ve sorun gideriyorum: yönetilen bir bulut servisine yaslanamadığınız, donanımdan depolamaya, kimlikten iş zamanlamaya kadar her katmanın sizin sorumluluğunuzda olduğu ortamlar.\nŞu an Çok kullanıcılı GPU altyapısında scheduling, partitioning ve izolasyon Virtualization ve software-defined storage cluster\u0026rsquo;larının işletimi Backup, monitoring ve high availability Canlı ortam deneyimlerinden Türkçe/İngilizce teknik yazılar Neler üzerinde çalışıyorum Virtualization ve storage: Cluster tabanlı virtualization, software-defined storage, hyperconverged infrastructure (HCI), enterprise NAS ve ZFS tabanlı depolama. GPU altyapısı: Yapay zekâ ve araştırma iş yükleri için GPU sunucuları ve cluster\u0026rsquo;ları, GPU partitioning ve virtual GPU, HPC job scheduling, stres testi ve driver/framework uyumluluğu. Çok kullanıcılı platformlar: Paylaşımlı Linux iş istasyonları: kullanıcı izolasyonu, kaynak yönetimi, container erişim kontrolü ve günlük operasyon. Container güvenliği: Paylaşımlı makinelerde container runtime\u0026rsquo;ı kısıtlamak, policy-as-code ile authorization ve cross-user izolasyon açıkları. Kimlik ve erişim: Directory services ve identity management, Kerberos ile kimlik doğrulama, network home directories, PAM entegrasyonu. Backup ve DR: Hyperconverged backup, deduplication backup appliance\u0026rsquo;ları, yedekleme izleme ve raporlama. High availability: Cluster resource management, block-level replication, active/passive servis failover. Observability: Metrics, centralized logging, alerting ve dashboard\u0026rsquo;lar; merkezi syslog toplama. Donanım ve yaşam döngüsü: Rack sunucu kurulumu, out-of-band management (BMC), RAID controller ve disk arızası analizi, vendor support süreçleri. Network ve security: Next-generation firewall yönetimi, segmentasyon, yönetim ağı tasarımı. Ne yazıyorum Canlı ortamda gerçekten karşılaştığım sorunları yazıyorum: sessiz hatalar, yanıltıcı dokümantasyon ve dokümanın söylemediğini kaynak kodun nasıl söylediği. Her yazı gerçek bir olaya dayanıyor, canlı sistemde test ediliyor ve kaynak linkleriyle destekleniyor.\nİletişim E-posta: onurbaydas@gmail.com GitHub: github.com/onurbaydas ","permalink":"https://onurbaydas.com/about/","summary":"\u003cp\u003eBen Onur Baydaş, Türkiye\u0026rsquo;de çalışan bir sistem ve altyapı mühendisiyim. 2024\u0026rsquo;ten bu\nyana on-prem altyapı tasarlıyor, kuruyor, işletiyor ve sorun gideriyorum: yönetilen\nbir bulut servisine yaslanamadığınız, donanımdan depolamaya, kimlikten iş zamanlamaya\nkadar her katmanın sizin sorumluluğunuzda olduğu ortamlar.\u003c/p\u003e\n\u003ch2 id=\"şu-an\"\u003eŞu an\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eÇok kullanıcılı GPU altyapısında scheduling, partitioning ve izolasyon\u003c/li\u003e\n\u003cli\u003eVirtualization ve software-defined storage cluster\u0026rsquo;larının işletimi\u003c/li\u003e\n\u003cli\u003eBackup, monitoring ve high availability\u003c/li\u003e\n\u003cli\u003eCanlı ortam deneyimlerinden Türkçe/İngilizce teknik yazılar\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"neler-üzerinde-çalışıyorum\"\u003eNeler üzerinde çalışıyorum\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eVirtualization ve storage:\u003c/strong\u003e Cluster tabanlı virtualization, software-defined\nstorage, hyperconverged infrastructure (HCI), enterprise NAS ve ZFS tabanlı depolama.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eGPU altyapısı:\u003c/strong\u003e Yapay zekâ ve araştırma iş yükleri için GPU sunucuları ve\ncluster\u0026rsquo;ları, GPU partitioning ve virtual GPU, HPC job scheduling, stres testi ve\ndriver/framework uyumluluğu.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eÇok kullanıcılı platformlar:\u003c/strong\u003e Paylaşımlı Linux iş istasyonları: kullanıcı\nizolasyonu, kaynak yönetimi, container erişim kontrolü ve günlük operasyon.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eContainer güvenliği:\u003c/strong\u003e Paylaşımlı makinelerde container runtime\u0026rsquo;ı kısıtlamak,\npolicy-as-code ile authorization ve cross-user izolasyon açıkları.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eKimlik ve erişim:\u003c/strong\u003e Directory services ve identity management, Kerberos ile kimlik\ndoğrulama, network home directories, PAM entegrasyonu.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eBackup ve DR:\u003c/strong\u003e Hyperconverged backup, deduplication backup appliance\u0026rsquo;ları,\nyedekleme izleme ve raporlama.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eHigh availability:\u003c/strong\u003e Cluster resource management, block-level replication,\nactive/passive servis failover.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eObservability:\u003c/strong\u003e Metrics, centralized logging, alerting ve dashboard\u0026rsquo;lar; merkezi\nsyslog toplama.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eDonanım ve yaşam döngüsü:\u003c/strong\u003e Rack sunucu kurulumu, out-of-band management (BMC),\nRAID controller ve disk arızası analizi, vendor support süreçleri.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eNetwork ve security:\u003c/strong\u003e Next-generation firewall yönetimi, segmentasyon, yönetim\nağı tasarımı.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"ne-yazıyorum\"\u003eNe yazıyorum\u003c/h2\u003e\n\u003cp\u003eCanlı ortamda gerçekten karşılaştığım sorunları yazıyorum: sessiz hatalar, yanıltıcı\ndokümantasyon ve dokümanın söylemediğini kaynak kodun nasıl söylediği. Her yazı\ngerçek bir olaya dayanıyor, canlı sistemde test ediliyor ve kaynak linkleriyle\ndestekleniyor.\u003c/p\u003e","title":"Hakkımda"},{"content":"","permalink":"https://onurbaydas.com/radar/","summary":"Canlı sistem ve güvenlik istihbaratı akışı.","title":"Sistem ve Güvenlik Radarı"}]