yeke.io · dokümanlar · guardrail
Guardrail politikaları
Bir işlemin ne zaman duracağını veya ek onay isteyeceğini politikalarla belirleyin. Bu rehber CEL koşullarını, etkileri, örnekleri ve politikaları üretime almadan önce test etmeyi anlatır.
Dosya modu (YEKE_POLICY_DIR) her katmanda çalışır. İmzalı paket
modu, çift onay alanı ve bakım penceresi Enterprise'dır ve bu sayfada ayrı bir bölümde
işaretlenmiştir.
Politika nedir, zincirde nerede koşar
Politikalar mevcut yetkileri daraltabilir veya ek kontrol isteyebilir. Kubernetes RBAC’in vermediği bir yetkiyi veremez.
YEKE'de her yazma tek bir zincirden geçer ve guardrail o zincirin bir halkasıdır. Sıra sabittir; politika dry-run'dan sonra koşar, yani apiserver'ın "uygulansaydı ne olurdu" cevabı elindeyken karar verir.
POST /operations → doğrulama → önceki hâl → koleksiyon genişletme → sınıflandırma → dry-run → guardrail → plan hash'i → onay kartı → apply
Bunun pratik sonucu, koşulunuzun elindeki bilgidir: object alanı dry-run'ın
döndürdüğü nesnedir (yoksa istek gövdesi), step.dryRun.changedPaths ise
gerçekten değişecek yolların listesidir. Politika bir tahmine değil, ölçülmüş bir sonuca
bakar.
Politikanın yapamadıkları
- Kubernetes RBAC'in yerine geçmez. İstek apiserver'a kullanıcının kendi kimliğiyle gider ve son kararı apiserver verir. Guardrail, RBAC'in verdiği yetkiyi genişletemez ve RBAC'in reddettiğini onaylayamaz — önüne kapı koyar, yerine geçmez.
allowya dabypassetkisi yoktur. Dört etki var (deny,require,warn,redact) ve hiçbiri gevşetmez. Guardrail yalnızca sıkılaştırır.- Yapısal onay tabanı politikadan bağımsızdır. Politika seti bomboş olsa bile her
yazma en az
standard,destructivesınıflanan her adım en azelevatedonay ister. "Onaysız yıkıcı işlem yok" iddiası politika hijyenine değil koda dayanır — bir politika bu tabanın altına inemez. - Politika hatası "serbest" demek değildir.
matchçalışma anında hata verirse o adımdenysayılır ve karttaPolitika hatasıolarak politikanınid'siyle görünür. Bedeli gerçektir: bozuk bir politika işlemleri durdurur — ama görünür şekilde durdurur.
Dosya modu ve alanlar
Dosya modunda politika değişikliklerini yüklemek için core’u yeniden başlatın.
YEKE_POLICY_DIR bir dizin gösterir; içindeki *.yaml ve
*.yml dosyaları açılışta, ad sırasına göre yüklenir. Bir dosya ya politika
belgesidir (üst düzey policies:) ya da bakım takvimidir (üst düzey
freezes:) — ikisi aynı dosyada bulunamaz, yükleyici reddeder. Ayrım
dosyanın adından değil üst düzey anahtardan yapılır: dosyayı yeniden adlandırmak içeriğini
değiştirmez.
# /etc/yeke/policies/10-uretim.yaml
policies:
- id: kurum.uretim-silme
description: "Üretim namespace'lerinde silme"
enabled: true
match: 'step.action == "delete" && step.target.namespace == "uretim"'
effect: require
level: elevated| Alan | Zorunlu | Ne yapar |
|---|---|---|
id | evet | Politikanın adı (1–128 karakter). Kartta ve denetim izinde görünür. Aynı
id iki kaynakta tanımlanırsa core açılmaz — hangisinin geçerli olduğu
belirsiz kalamaz. |
description | hayır | Serbest açıklama. messageCode ve message yoksa kartta
gerekçe olarak bu görünür; o da yoksa politikanın id'si görünür. |
enabled | hayır (true) |
false yazılan politika yine derlenir ama değerlendirmeye
girmez. Kapalı bir politikanın bozuk olduğunu açıldığı gün öğrenmek, hatayı en kötü
ana ertelemek olurdu. |
match | evet | CEL ifadesi (1–8192 karakter); bool dönmek zorunda. Derlenemezse core açılmaz. |
effect | evet | deny · require · warn ·
redact. Anlamları aşağıdaki tabloda. |
level | hayır | standard ya da elevated. Yalnız
effect: require ile yazılabilir; başka bir etkiyle yazılırsa core
açılmaz. Yazılmazsa standard. |
message | hayır | Eşleşmenin tek satırlık gerekçesi, operatörün kendi cümlesi (≤2048 karakter).
messageCode de yazılmışsa bu alan hiç okunmaz. |
messageCode | hayır | Gerekçenin kodu — kapalı küme (aşağıda). Kod kazanır, çünkü çevrilebilen odur: kartta kullanıcının kendi dilinde çıkar. |
flags | hayır | Sınıflandırmaya eklenecek bayraklar. irreversible bayrağını
yalnız politika atar; kart onu "geri alınamaz" olarak çizer. |
caveats | hayır | Kartta gösterilecek ek uyarılar — operatörün kendi cümleleri. Arayüz bunları "sunucudan geldi" etiketiyle çizer ve çevirmez. |
caveatCodes | hayır | Uyarının kodu — kapalı küme (aşağıda). Kartta kodlar önce, serbest metin sonra gelir. |
severity | hayır | Adımın yıkıcılık sınıfını yükseltir. Tek kabul edilen değer
destructive; mutating yazmak bir düşürme girişimidir ve
reddedilir. effect: redact ile yazılamaz. |
redactPaths | koşullu | Maskelenecek alan yolları. Yalnız effect: redact ile
yazılabilir ve orada zorunludur — boş liste de reddedilir. |
requireSecondApproval | hayır | Enterprise. true ise eşleşen plan ikinci bir onaycının rızasını
ister. Etkiden bağımsızdır: bir warn politikası da ikinci bir göz
isteyebilir. |
requiredApproverGroup | hayır | Enterprise. Onaycı kümesini bir gruba daraltır.
requireSecondApproval: true olmadan yazılamaz — istenmeyen bir onayı
daraltmak sessizce hiçbir şey yapmazdı. |
Tanımadığı anahtarı yutmaz, açılışta ölür
- Yazım hatası sessizce geçmez. Şema katıdır: yukarıdaki listede olmayan bir
anahtar (
levell,affect) reddedilir. Yutulsaydı operatör "yazdım ama çalışmıyor" ile baş başa kalırdı. - Bozuk bir politika core'u açmaz. Ayrıştırılamayan YAML, şemaya uymayan alan,
derlenemeyen
match, tekrar edenid— dördü de açılışı durdurur. Bozuk politikayı atlayıp devam etmek, operatörün yazdığını sandığı ama sistemin hiç yüklemediği bir kural üretirdi. YEKE_POLICY_DIRverilip okunamazsa da açılmaz. Dizin yoksa değişkeni hiç vermeyin: var sayıp okuyamamak, politikaların sessizce yüklenmemesi demektir.- Değişiklik = dosya + yeniden başlatma. Dosya modunda politika için bir yazma ucu yoktur; yürürlükteki set süreç ömrü boyunca sabittir. Yeniden başlatmadan yürürlüğe giren tek kaynak imzalı pakettir (aşağıda).
match yazımı — CEL bağlamı
Adlandırma Kubernetes'in ValidatingAdmissionPolicy
sözlüğünü izler: object ve oldObject orada ne demekse burada da
o demek.
İfade adım başına değerlendirilir — genişletilmiş her hedef ayrı görünür — ve bool
dönmek zorundadır. Bool olmayan bir sonuç (ör. yalnızca step.action yazmak)
hatadır, "doğru" sayılmaz.
| Değişken | İçerik |
|---|---|
op.source |
Planı kim kurdu: "ui" (arayüz), "nl" (sohbet),
"api" (doğrudan API çağıranı; kabuk da şemanın sözlüğünde bir API
çağıranıdır). |
op.identity.userop.identity.groups |
İsteğin apiserver'a gideceği Kubernetes kimliği ve grupları. |
op.cluster.idop.cluster.name |
Hedef cluster. |
op.cluster.execRecording |
Cluster'ın terminal kaydı için duruşu — lisanstan bağımsız. Yapılandırma denetimi için: "bu cluster kayıt için ayarlanmış mı". |
op.cluster.recordingActive |
Duruş ve session-recording lisansı usea izin
veriyor — bu oturumda kaydın gerçekten başlayıp başlamayacağı. Lisans
kaldırıldığında duruş true kalır ama bu alan false olur;
güvence isteyen kural bunu okumalı. |
op.revertOf |
Bu plan bir geri alma ise kaynak planın kimliği, değilse null. |
step.action |
create · update · patch ·
delete · stream. |
step.methodstep.path |
Adımın HTTP fiili ve apiserver yolu — startsWith,
contains, matches ile sınanabilir. |
step.target.schemaId |
Hedefin şema kimliği: grup varsa grup.tekil
(apps.deployment), çekirdek grupta yalnız tekil ad
(pod). |
step.target.groupstep.target.versionstep.target.kindstep.target.resource |
API grubu (çekirdek grup ""), sürüm, tip adı ve çoğul kaynak adı. |
step.target.namespaced |
Tip namespace kapsamlı mı (bool). |
step.target.namespacestep.target.namestep.target.subresource |
Hedefin namespace'i, adı ve subresource'u. Üçü de her zaman doludur;
yokluk "" ile temsil edilir, eksik anahtar olarak değil. |
step.classification.severity |
mutating ya da destructive. |
step.classification.flags |
Bayrak listesi: cluster-scoped, collection,
finalizers, owner-managed, orphan-delete,
dry-run-unsupported, irreversible, stream,
conflicting-declaration ve subresource:<ad>
biçiminde tipe özgü bayraklar. |
step.dryRun.status |
ok · failed · unsupported ·
skipped · not-applicable. |
step.dryRun.changedPaths |
Dry-run'ın ölçtüğü, gerçekten değişecek alan yollarının listesi. |
object |
Yeni hâl: dry-run sonucu, yoksa istek gövdesi. delete adımında
null. |
oldObject |
Canlı önceki hâl. create adımında null. |
İki farklı alan sınıfı — ve has() kuralı
op ve step altındaki her alan sözleşme alanıdır ve her
zaman doludur; doğrudan okuyabilirsiniz. Buna karşılık object ve
oldObject gerçek Kubernetes nesneleridir ve alanları eksik olabilir — eksik alan
okumak CEL'de hatadır, sessizce false değil. Hata da fail-closed tarafa
düşer, yani politikanız yanlışlıkla plan reddedebilir. Kural basit: object /
oldObject altına inen her yolu has() ile koruyun.
# yanlış — nesnede spec yoksa politika hata verir, adım deny olur match: 'object.spec.replicas == 0' # doğru — has() null kök üstünde de fırlatmaz, false döner match: 'has(object.spec) && has(object.spec.replicas) && object.spec.replicas == 0'
Desteklenen sözdizimi
Motorun semantiği her açılışta 54 ifadelik bir uyum korpusuyla sınanır; geçmezse core açılmaz. Aşağıdaki yapıların hepsi o korpusta doğrulanmıştır:
- Karşılaştırma ve mantık:
==,!=,&&,||,!, üçlü işleç (? :). Kısa devre çalışır (false && <hata>=false) ama hata yutulmaz:true && <hata>hatadır. in: hem liste üyeliği (step.target.resource in ["pods", "nodes"]) hem harita anahtarı ("kritik" in oldObject.metadata.labels).has(): alan var mı. Yok olan alandafalsedöner, hata vermez.- İndeksleme:
oldObject.metadata.labels["app"],step.classification.flags[0]. Dikkat: olmayan bir harita anahtarına ya da liste indeksine erişmek hatadır — indekslemeden önceinya dahas()ile sorun. - Metin fonksiyonları:
startsWith(),endsWith(),contains(),matches()(düzenli ifade). - Makrolar ve boyut:
exists(),all(),size(). nullkarşılaştırması:object == null,op.revertOf != null. Amanullbir kökün altına inmek (object.metadata.name) hatadır.- Tanınmayan her şey açık hata verir: bilinmeyen değişken, bilinmeyen alan,
bilinmeyen fonksiyon, bilinmeyen metot, sözdizimi hatası. Hiçbiri sessizce
false'a düşmez — korpusun asıl ölçtüğü şey budur.
Örnekler
Sekiz tam politika. Adlar kurumun kendi ad alanında
(kurum.); yerleşik setle çakışmaması için yeterli.
1) Üretim namespace'inde silme yükseltilmiş onay ister
policies:
- id: kurum.uretim-silme
description: "Üretim namespace'lerinde silme"
match: >
step.action == "delete" &&
step.target.namespace in ["uretim", "uretim-veri"]
effect: require
level: elevated
caveats:
- "Üretim namespace'i: değişiklik kaydını açmadan uygulamayın."İki namespace'te silme yapan her adım için kart elevated'a çıkar — kullanıcı
hedefin adını birebir yazmadan uygula düğmesi etkinleşmez. caveats satırı kartta
operatörün kendi cümlesi olarak, çevrilmeden görünür.
2) kube-system'e yazmak reddedilir
policies:
- id: kurum.sistem-namespace-yazma
description: "kube-system'e YEKE üzerinden yazılmaz"
match: >
step.action in ["create", "update", "patch", "delete"] &&
step.target.namespace == "kube-system"
effect: deny
message: "kube-system küme yönetiminin işidir; bu değişiklik YEKE'den geçmez."Bir adımda tek bir deny bütün planı düşürür; kart uygulanamaz hâlde
çizilir. Yerleşik builtin.system-namespace aynı hedefte yalnızca onayı
yükseltir — bu politika onu sıkılaştırır, çünkü guardrail'de birleşim daima en kısıtlayıcı
olanın lehinedir.
3) Replikayı sıfıra çekmek uyarı düşürür
policies:
- id: kurum.sifira-olcekleme-uyarisi
description: "Sıfıra ölçeklemede nöbetçiyi hatırlat"
match: >
has(object.spec) && has(object.spec.replicas) &&
object.spec.replicas == 0
effect: warn
message: "Sıfıra ölçekleme nöbet listesine duyurulmalı."warn onay seviyesine dokunmaz, kartta bir uyarı satırı ekler.
Kapsam notu: bu koşul yalnızca ana nesne üstünden yapılan ölçeklemeyi görür. Kanonik
yol (scale subresource'u) bir Scale nesnesi taşır ve orada sıfır
değeri gövdeden tamamen düşer — o dalı da yakalamak isteyen yerleşik
builtin.scale-to-zero'nun iki dallı koşuluna bakabilir. Sıfıra ölçekleme zaten
yerleşik olarak elevated onay istiyor; bu politika onun üstüne yalnızca kurumun
kendi cümlesini koyar.
4) Kendi tipinizdeki parola alanını maskeleyin
policies:
- id: kurum.veritabani-parola-maskesi
description: "Kendi veritabanı tipimizde parola alanları maskelenir"
match: >
step.target.group == "ornek.io" &&
step.target.resource == "veritabanlari"
effect: redact
redactPaths:
- "spec.baglanti.parola"
- "spec.baglanti.kullanicilar[].parola"
message: "Parola alanları plan yanıtında ve denetim izinde maskelenir."Yol biçimi noktayla iner, [] "bu dizinin her elemanı" demektir. Maske
değerin yerine anahtarlı bir işaret yazar: değer okunamaz ama iki kaydın aynı değeri taşıyıp
taşımadığı görülebilir — "bu alan değişti mi" sorusu maskeleme sonrasında da cevaplanabilir
kalır. Secret'ın data/stringData alanları zaten yerleşik olarak
maskelidir; bu örnek aynı korumayı kurumun kendi tipine taşır.
Koşulu fiil üstünden değil nesne üstünden yazın. Bir
redact politikasına step.action koymak, maskeyi tam da en gerekli
olduğu yerde düşürür: silmede istek gövdesi yoktur ve kullanıcının kartta gördüğü tek şey
canlı nesnenin tamamıdır.
5) Bir CRD grubundaki her yazma kart açar
policies:
- id: kurum.ornek-grubu-onay
description: "ornek.io grubundaki her yazma onay kartı açar"
match: 'step.target.group == "ornek.io"'
effect: require
messageCode: SYSTEM_NAMESPACElevel yazılmadığı için standard: tek kartlık onay, ad yazma yok.
Yapısal taban yine de altına inmez — aynı grupta bir delete gelirse kart zaten
elevated olur. messageCode kapalı kümeden seçilir ve kartta
kullanıcının dilinde çıkar; kümede size uyan bir kod yoksa message ile kendi
cümlenizi yazın.
6) Dry-run'ın değiştirdiği yola göre koşul
policies:
- id: kurum.replika-degisikligi
description: "Dry-run replika sayısını değiştiriyorsa yükseltilmiş onay"
match: >
step.dryRun.status == "ok" &&
"spec.replicas" in step.dryRun.changedPaths
effect: require
level: elevatedGuardrail dry-run'dan sonra koştuğu için changedPaths bir tahmin değil bir
ölçümdür: istek o alana dokunuyor görünse bile değer aynıysa yol listede olmaz.
status == "ok" koşulu bilinçli — dry-run koşmadıysa (unsupported,
skipped) liste boştur ve boş listeye bakan bir kural sessizce hiç
eşleşmezdi.
7) Etiketli nesnede silme reddedilir
policies:
- id: kurum.kritik-etiket-koruma
description: "kritik=evet etiketli nesne YEKE'den silinemez"
match: >
step.action == "delete" &&
has(oldObject.metadata) && has(oldObject.metadata.labels) &&
"kritik" in oldObject.metadata.labels &&
oldObject.metadata.labels["kritik"] == "evet"
effect: deny
message: "Bu nesne kritik etiketli; silme kaydı ayrı bir süreçten geçer."İki korumanın da neden gerektiğine dikkat: has() etiket haritasının varlığını,
in ise o haritada anahtarın varlığını sorar. İkincisi olmadan, etiketi olan ama
kritik anahtarı olmayan bir nesnede indeksleme hata verir ve adım fail-closed
deny olur — yani politika, kastetmediği nesneleri de durdururdu.
8) Kayıt kapalıyken üretimde terminal açılmasın
policies:
- id: kurum.uretimde-kayitsiz-terminal-yok
description: "Üretim cluster'larında kayıt kapalıyken terminal açılamaz"
match: >
step.action == "stream" &&
op.cluster.name.startsWith("uretim") &&
!op.cluster.recordingActive
effect: deny
message: "Bu cluster'da terminal oturumu ancak kaydı açıkken açılabilir."Bu, yerleşik kapalı şablon ops.recording-required'ın kendi ad alanına
kopyalanmış hâli. Koşul bilerek recordingActive okuyor, execRecording
değil: lisans düştüğünde cluster kaydının duruşu true kalır ama kayıt
başlamaz, yani duruşa bakan bir kural o kurulumda sessizce delinirdi.
Etkiler, seviyeler ve kodlar
Bir adıma birden fazla politika eşleşebilir. Sonuçlar birleştirilir; politika sırası korumayı zayıflatmaz.
| Etki | Ne olur |
|---|---|
deny |
Plan reddedilir. Bir adımda bir deny planın tamamını düşürür.
level yazılamaz. |
require |
Onay kartı açılır. level: standard tek onay;
level: elevated hedefin adının birebir yazılmasını ister —
yazılmadan uygula etkinleşmez. |
warn |
Kartta uyarı olarak görünür; onay seviyesine dokunmaz. Yeni bir kuralı sahada denemenin yolu. |
redact |
redactPathsteki alanların değerleri plan yanıtında ve
denetim izinde maskelenir. Bu politika kartın politika listesine hiç girmez
— mesajı tele çıkmaz, yalnızca YAML'ı okuyan operatör için durur. |
- Seviye birleşimi maksimumdur:
approvalLevel = max(eşleşenrequireseviyeleri, yapısal taban). Politika tabanı düşüremez. - Bayrak, uyarı ve sınıf yükseltmeleri birikir ve geri alınamaz: bir politika
adımı
destructive'e çektiyse başka bir politika onu geri indiremez. - Tek geçiş vardır. Bir politikanın eklediği bayrağa (ör.
irreversible) göre başka bir politikanın yeniden eşleşmesi için ikinci tur koşulmaz — sıranın sonucu etkilememesi garantisi buna bağlı. - Aynı etkiyi farklı mesajla veren iki politika ikisi birden listelenir. Kart hangi kuralın konuştuğunu gizlemez.
Yazabileceğiniz messageCode değerleri
Kapalı küme — ürünün kendi cümleleri, iki dilde çevrili:
IRREVERSIBLE_STORAGE · NAMESPACE_DELETE ·
CRD_DELETE · CLUSTER_SCOPED_DELETE ·
DRY_RUN_UNSUPPORTED · POD_EVICTION ·
SYSTEM_NAMESPACE · RBAC_BINDING_WRITE ·
SCALE_TO_ZERO · NL_STRICT · SHELL_STRICT
Yazabileceğiniz caveatCodes değerleri
REVERT_DELETES_CREATED · REVERT_RESTORES_PRIOR ·
REVERT_RECREATES_OBJECT · SUBRESOURCE_CREATE_NO_TARGET ·
FINALIZERS_PENDING · FINALIZERS_ON_DELETING ·
OWNER_MANAGED · ORPHAN_PROPAGATION ·
FINALIZERS_DRY_RUN · SEQUENCED_IN_PLAN ·
STORAGE_DATA_LOST · NAMESPACE_CASCADE ·
CRD_INSTANCES_DELETED · DRY_RUN_UNVERIFIED ·
EVICTION_DELETES_POD · RBAC_GRANTS_AUTHORITY ·
SCALE_TO_ZERO_OUTAGE
Kümede karşılığı olmayan bir uyarı için caveats ile kendi
cümlenizi yazın. Kod seçmek her zaman daha iyidir — kod çevrilir, serbest metin
çevrilmez.
Çift onay, bakım penceresi ve paket modu
Üçü de Enterprise. İlk ikisi politika verisinin içinde yaşar, üçüncüsü politikanın nereden geldiğini değiştirir.
Çift onay alanları
policies:
- id: kurum.cift-onay
description: "Üretimde Deployment değişikliği ikinci bir göz ister"
match: >
step.action in ["update", "patch"] &&
step.target.resource == "deployments" &&
step.target.namespace == "uretim"
effect: require
level: elevated
requireSecondApproval: true
requiredApproverGroup: "sre-onaycilar"- Uygun onaycı kimdir: plan sahibinden farklı, hesabı aktif ve o cluster'da bir kimlik kuralıyla kimliği olan herhangi bir kullanıcı. Politika bir grup verdiyse kullanıcının çözülmüş gruplarında o grubun da bulunması şarttır — grup, kimlik kuralının ürettiği gruplardır, ikinci bir grup kavramı açılmaz.
- Küme saklanmaz, her seferinde yeniden hesaplanır. Saklanan bir liste bayatlar: hesap pasifleşir, kimlik eşlemesi kalkar, grup daralır.
- İkinci onaycı yalnız rıza verir, planı yine sahibi uygular. Rıza planın güncel hash'ine bağlıdır; plan tazelenip hash değişince rıza düşer (kayıt silinmez, kapı saymaz) ve yeniden istenir.
- Varsayılan kapalıdır. Kural yazılmadıkça hiçbir plan ikinci onay istemez — bu, tek yöneticili bir kurulumun kilitlenmemesi için bilinçli bir seçim.
requiredApproverGrouptek başına yazılamaz. Daraltılacak bir onay yoksa daraltma sessizce hiçbir şey yapardı; yükleyici bunu açılışta reddeder.
Bakım penceresi — ayrı bir dosya
Takvim politika dosyasında değil, aynı dizindeki ayrı bir dosyada yaşar: üst düzey
anahtar freezes:. Aynı dosyada hem policies: hem
freezes: bulunması reddedilir — bir dosyanın ne olduğu, açıldığında belli
olmalı.
# /etc/yeke/policies/90-takvim.yaml freezes: - id: hafta-sonu description: "Hafta sonu değişiklik dondurması" timezone: Europe/Istanbul # ZORUNLU weekly: - { from: "Fri 17:00", to: "Mon 09:00" } dates: - { from: "2026-12-29T00:00:00", to: "2027-01-02T09:00:00" } scope: { clusters: ["*"] }
timezonezorunludur ve bir IANA bölge adıdır. "Cuma 17:00" kimin cuması sorusu bir kurumda gerçek bir sorudur; UTC varsaymak sessiz bir yanlış üretir ve belirtisi "pencere iki saat kaymış" gibi görünür.weeklybiçimi"Gün SS:DD"— üç harfli İngilizce gün kısaltması (Mon–Sun) ve 24 saatlik saat.datesyerel duvar saatidir (YYYY-AA-GGTSS:DD:SS), saat dilimi eki yazılmaz: pencerenin kenditimezone'uyla çelişebilecek ikinci bir zaman kaynağı açardı.weeklyvedatesikisi de boş bırakılabilir — hiç eşleşmeyen bir pencere, her zaman kapalı bir pencereden çok daha ucuzdur.scope.clusterspencerenin kapsadığı cluster'lardır;["*"]hepsi demektir. Pencere içindeki birapplyreddedilir, plan kaydı mutasyonsuz kalır — ayrıntısı Yönetişim sayfasında.- Pencere kimlikleri politika kimliklerinden ayrı bir ad alanıdır, ama kendi içinde benzersiz olmak zorundadır: iki pencere aynı adı taşırsa izde "hangi pencere reddetti" sorusunun cevabı belirsizleşirdi.
Paket modu — imzalı, anında yürürlükte
YEKE_POLICY_MODE=central verildiğinde politika seti dizinden değil imzalı bir
paketten gelir. Gövde signature alanı olmadan yazılır ve
version her yüklemede artmak zorundadır:
{
"version": 3,
"policies": [
{
"id": "kurum.uretim-silme",
"match": "step.action == \"delete\" && step.target.namespace == \"uretim\"",
"effect": "require",
"level": "elevated"
}
],
"freezes": [
{
"id": "hafta-sonu",
"timezone": "Europe/Istanbul",
"weekly": [{ "from": "Fri 17:00", "to": "Mon 09:00" }],
"scope": { "clusters": ["*"] }
}
]
}Alanlar dosya kipiyle birebir aynıdır — paket ve dosya aynı derleyiciden geçer, yani dosya modunda reddedilen bir politika pakette de reddedilir. İmzalama kurumun kendi private key'iyle yapılır:
pnpm --filter @yeke/core exec tsx tools/policy-package/sign.ts \ --private-key policy-private.pem \ --package paket.json \ --out paket-imzali.json
Şifreli bir PEM'de (ENCRYPTED PRIVATE KEY başlığı ya da eski
Proc-Type: 4,ENCRYPTED) passphrase YEKE_POLICY_KEY_PASSPHRASE ortam
değişkeninden ya da gizli girdiden okunur; düz PEM'de bu adım hiç sorulmaz.
İmzalı gövde PUT /api/policy/package ile, admin oturumuyla yüklenir;
ekrandan yüklemek için /admin/policy. Yükleme anında yürürlüğe girer, core
yeniden başlamaz — ama koşan bir planı etkilemez: plan kaydı sınıflandırıldığı politika
sürümünü taşır ve apply o sürümle koşar.
- İki mod aynı anda olmaz.
YEKE_POLICY_MODE=centralileYEKE_POLICY_DIRbirlikte verilirse core açık hatayla durur — iki kaynağı birleştirmek "aynıidli iki politika varsa hangisi kazanır" sorusunun sessiz bir cevabını üretirdi. - Bozuk imza ya da bayat sürüm yürürlükteki paketi düşürmez. Yükleme reddedilir,
önceki sürüm yürürlükte kalır. Aynı ya da küçük bir
versionda reddedilir. - Yerleşik set paket modunda de yüklüdür. Paket operatörün setidir, ürünün kendi politikalarının yerine geçmez.
Anahtar üretimi, yükleme ucunun tamamı ve lisans davranışı Yönetişim sayfasında.
Politikayı test
Önce uyarı üreten bir kuralla test edin. Sonuçları kontrol ettikten sonra engelleme veya ek onay etkisini etkinleştirin.
- Önce
warnile yazın. Yeni bir kuralıeffect: warnile sahaya alıp kartta gerçekten kastettiğiniz adımlarda çıktığını gördükten sonrarequireya dadeny'a çevirin. Yanlış yazılmış birdeny, doğru işlemleri de durdurur. - Planı kurun, kartı okuyun, uygulamayın. Arayüzden ya da
POST /api/clusters/:clusterId/operationsile bir plan kurun; kart eşleşen politikalarınid'lerini, mesajlarını, uyarılarını, onay seviyesini ve maskelenmiş alanları gösterir. Sonra planıPOST /api/clusters/:clusterId/operations/:opId/cancelile iptal edin — planı kurmak hiçbir şey uygulamaz, iptal iz bırakır. - Açılış günlüğü ne yüklendiğini sayar. Core açılırken uyum korpusunun geçtiğini
ve kaç politikanın etkin olduğunu adlarıyla birlikte yazar; bakım penceresi varsa onları
da bölgeleriyle listeler. Yazdığınız politikanın adını orada görmüyorsanız ya
enabled: false'tur ya da dosya hiç okunmamıştır.
[guardrail] CEL conformance corpus passed (54 expressions) [guardrail] 12 active policies loaded (2 files): builtin.irreversible-storage, … [guardrail] 1 change-freeze windows loaded: hafta-sonu (Europe/Istanbul)
Açılışı durduran hatalar
Hata mesajı her zaman politikanın adını ve geldiği dosyayı söyler; core dinlemeye hiç açılmaz.
Policy file is not valid YAML (/etc/yeke/policies/10-uretim.yaml): … Policy file does not match the schema (/etc/yeke/policies/10-uretim.yaml): policies.0.effect: Invalid enum value Policy id defined twice: 'kurum.uretim-silme' (/etc/yeke/policies/10-uretim.yaml and /etc/yeke/policies/20-ek.yaml). Which one is valid cannot remain ambiguous. Policy 'kurum.ornek' (…) could not be compiled: …
idçakışması iki dosya arasında da sayılır — ve yerleşik setle de. Bu yüzden kendi politikalarınıza bir ön ek verin.- Kapalı politika da derlenir.
enabled: falseyazılmış bozuk bir politika açılışı yine durdurur; hatayı açtığınız güne ertelemez. - Çalışma anı hatası açılışta görünmez. Derleme
match'in sözdizimini ve tipini sınar; eksik alan hatası ancak eşleşen bir plan kurulduğunda çıkar ve o adımdenyolur.has()disiplini bu yüzden önemli.
Yerleşik politikalar
On yedi kayıt, on dördü açık. Hepsi veri olarak gelir — motor hiçbir kaynak adı bilmez.
| Politika | Etki | Ne yapar |
|---|---|---|
builtin.irreversible-storage | require · elevated |
PersistentVolume ve PersistentVolumeClaim silme; irreversible
bayrağı ekler. |
builtin.namespace-delete | require · elevated |
Namespace silme — içindeki her şey cascade gider. |
builtin.crd-delete | require · elevated |
CustomResourceDefinition silme; o tipin tüm örnekleri birlikte silinir. |
builtin.cluster-scoped-delete | require · elevated |
Cluster kapsamlı bir nesnenin silinmesi. |
builtin.dry-run-unsupported | require · elevated |
Dry-run'ın koşamadığı işlem — doğrulanmamış bir değişiklik uygulanıyor. |
builtin.pod-eviction | require · elevated |
Eviction subresource'u; sınıfı destructive'e yükseltir, çünkü
create-only bir istek olmasına rağmen pod siler. |
builtin.system-namespace | require · elevated |
kube-system, kube-public,
kube-node-lease içinde yıkıcı işlem. |
builtin.rbac-binding-write | require · elevated |
RoleBinding / ClusterRoleBinding yazma — yetki dağıtan nesneler. YEKE'nin kendi "yetkiyi ver" düğmesi de bu kapıdan geçer. |
builtin.scale-to-zero | require · elevated |
Replika sayısının sıfıra indirilmesi; hem ana nesne hem scale
subresource'u dalını kapsar. |
builtin.node-cordon | warn |
Bir node'u cordon etmek (yeni pod yerleşimini kapatmak), cluster'da başka yerleşilebilir node varken. Onay istemez, uyarır. |
builtin.node-cordon-last-node | require · elevated |
Cluster'ın son yerleşilebilir node'unu cordon etmek; sınıfı
destructive'e yükseltir, çünkü yeni pod'lar hiçbir node'a
yerleşemez. |
builtin.node-cordon-topology-unknown | require · elevated |
Bir node'u cordon etmek, yerleşilebilir node sayısı okunamadığında — son node olup olmadığı bilinmediği için onay yükseltilir. |
builtin.redact-secrets | redact |
Secret'ın data ve stringData alanları — okumada da
yazmada da silmede de. |
builtin.redact-env-values | redact |
Ortam değişkeni değerleri, PodSpec'in dört yerleşiminde × üç container
listesinde. valueFrom bilerek kapsam dışı: içinde değer değil bir
referans vardır. |
ops.nl-strict | kapalı | Şablon. Açılırsa sohbetten gelen (op.source == "nl") her yazma
yükseltilmiş onay ister. |
ops.shell-strict | kapalı | Şablon. Açılırsa kabuktan gelen her yazma kendi onay kartını açar; oturum onayının yetkilendirdiği yazma yolu devre dışı kalır. |
ops.recording-required | kapalı | Şablon. Açılırsa op.cluster.recordingActive kapalıyken
stream adımını reddeder — kaydı başlamayacak bir terminal oturumu
açılamaz. |
Kapatılabilir mi
enabled alanı yerleşik dosyanın kendi içindedir ve o dosya imajla
gelir. YEKE_POLICY_DIR'den bir yerleşik politikayı kapatmak ya da ezmek
mümkün değildir: aynı id'yi ikinci bir kaynakta tanımlamak core'u açılışta
durdurur, ve yerleşik set paket modunda de yüklenir. Operatörün elindeki yol
eklemektir — guardrail sıkılaştırır, gevşetmez. Yukarıdaki üç şablonun
(ops.nl-strict, ops.shell-strict, ops.recording-required)
davranışını istiyorsanız aynı koşulu kendi ad alanınızda kendi politikanız olarak yazın.