Help us shape the future of Go! Take the 2026 Go Developer Survey

provision

package
v1.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 16, 2026 License: Apache-2.0 Imports: 12 Imported by: 0

Documentation

Overview

* Package provision, hedeflerde grup/kullanıcı/sudo durumunu kurar. * * ⚠️ PLAN İLE UYGULAMA AYRI — VE AYRILMALARI BU PAKETİN TEMEL KARARI. * Plan saf: gözlenen durum ile istenen durumu alıp adımları üretiyor, * hiçbir şeye bağlanmıyor ve tek başına ölçülebiliyor. Hatalar burada * yaşıyor: "zaten var mı", "hangi araç", "ne sırayla". Uygulama ince * bir katman ve gerçek makinede doğrulanıyor. * * ⚠️ BU PAKET HİÇBİR ŞEY SİLMİYOR. Silme ayrı ve yıkıcı bir yol; * yayılımın içine karıştırılsaydı, bir yapılandırma hatası "eksik" * diye okunup üretimde hesap kapatırdı.

Index

Constants

View Source
const JITGroup = "postern-jit"

* JITGroup, postern'in açtığı geçici hesapların üye olduğu grup. * * ⚠️ SİLMENİN ÖN KOŞULU BU ÜYELİK. Ada bakarak silmek, postern'den * önce var olan bir hesabı yok edebilirdi; göç 022'nin dersi * ("satır kararlı kimlikle anahtarlanır, adla değil") burada da * geçerli. Grup, "bu hesabı ben açtım" demenin makinedeki hâli.

View Source
const MinJITGID = 1000

* MinJITGID, bir geçici hesabın alınabileceği en küçük grup numarası. * * ⚠️ ALTINDAKİLER KORUNUYOR. Linux'ta 1000'in altı sistem gruplarıdır * (login.defs: SYS_GID_MAX 999, GID_MIN 1000): root, wheel/sudo, adm, * shadow, docker… Bunlardan birine üyelik, hiçbir sudo kuralı yazmadan * root'a giden bir yol — docker grubu root eşdeğeridir, shadow parola * özetlerini okutur. Geçici hesap yalnızca kullanıcı gruplarına * alınabilir; sınır kullanıcının kararı (2026-09-13).

Variables

View Source
var ErrUnconfirmed = errors.New("the target did not confirm whether the step ran")

* ErrUnconfirmed, hedefin adımın ÇALIŞIP ÇALIŞMADIĞINI bildirmediğini * söyler: kanal açılamadı, exec isteği reddedildi, kanal çıkış kodu * gelmeden kapandı, ya da bağlam komut koşarken doldu. * * ⚠️ NE "BAŞARISIZ" NE "ULAŞILAMADI" — VE ÜÇÜNCÜ SINIF OLMADAN İKİSİ DE * YALAN SÖYLÜYORDU. Bağlam sudoers kurulumunun ortasında dolarsa * postern kanalı kapatıyor ama OpenSSH pty'siz çocuğa sinyal * göndermiyor: `install` root olarak BİTİYOR. Bunu "ulaşılamadı, hiçbir * şey olmadı" diye raporlamak, kurulmuş bir sudo kuralını yok saymak; * "başarısız" diye raporlamak operatörü hedefin günlüklerine yollamak * olurdu. Doğru cümle "bilmiyoruz" ve rapor tam olarak onu söylüyor.

View Source
var ErrUnreachable = errors.New("target could not be reached")

* ErrUnreachable, makineye HİÇ ULAŞILAMADIĞINI söyler. * * ⚠️ "KOMUT DÜŞTÜ" İLE "MAKİNEYE ULAŞAMADIM" AYRI ŞEYLER — VE KARIŞTIKLARI * HÂLİ ÖLÇTÜK. Yayılım raporu "group.add failed" diyordu; gerçek ise * bağlantının hiç kurulamamasıydı. İkisi operatöre bambaşka şeyler * söylüyor: ilki "hedef reddetti, bak", ikincisi "makine kapalı, tekrar * dene". Hedefi, taşıma katmanının hatasıyla suçlamak bu projenin * reddettiği türden bir rapor.

Functions

func PrincipalsPath

func PrincipalsPath(pattern, user string) (string, error)

* PrincipalsPath, sshd'nin AuthorizedPrincipalsFile desenini bir hesap * için yola çevirir. Boş desen → "" (dosya gerekmiyor). * * ⚠️ DESENDE %u ŞART. %u'suz bir desen tek bir PAYLAŞILAN dosya demek * ve ona yazmak makinedeki herkesin principal listesini ezmek olurdu. * %h (ev dizini) gibi öbür belirteçler desteklenmiyor: ev dizinini * varsaymak yerine reddetmek, yanlış yere dosya yazmaktan iyi. Sonuç * kabuk komutuna giriyor; yol karakter kontrolünden geçmek zorunda.

func PrincipalsPatternFor

func PrincipalsPatternFor(ctx context.Context, r Runner, user, fallback string) string

* PrincipalsPatternFor, AuthorizedPrincipalsFile deseninin HESABIN * BAĞLAMINDA etkin değerini okur. * * ⚠️ BAĞLAMSIZ OKUMA MATCH BLOKLARINI GÖRMÜYOR ve bu ölçüldü. Yetenek * sondası `sudo -n sshd -T` çalıştırıyor; o çıktı yalnızca genel * yapılandırmanın birleşimi. Demo hedefine * * Match User jitayse * AuthorizedPrincipalsFile /etc/ssh/jit_principals/%u * * eklenip iki okuma karşılaştırıldı: bağlamsız okuma * `/etc/ssh/auth_principals/%u`, `-C user=jitayse` ile okuma * `/etc/ssh/jit_principals/%u` dedi. Yani Match bloklu bir kurulumda * postern dosyayı sshd'nin BAKMADIĞI yere yazıyor; hak "uygulandı" * görünüyor ve kişi giremiyor. * * ⚠️ KOMUTA GİREN TEK DEĞİŞKEN, ŞEKLİ DOĞRULANMIŞ HESAP ADI. * CapabilityCommands bilerek sabit; oraya değişken koymak config'e * erişen herkese filoda komut çalıştırma yetkisi verirdi. Burası plan * katmanı: ad zaten `^[a-z_][a-z0-9_.-]{0,31}$` kümesinde (kabuk * metakarakteri yok) ve uymayan ad için komut hiç kurulmuyor, genel * değere düşülüyor. * * ⚠️ OKUNAMAZSA GENEL DEĞER. sshd'si olmayan, sudo'suz ya da yaşlı bir * hedefte bu okuma başarısız olabiliyor; o durumda bağlamsız değer * bugünkü davranışın aynısı. Sessiz değil: çağıran farkı raporluyor.

func SudoPath

func SudoPath(group string) string

SudoPath, bir grup için postern'in yazdığı dosyanın yolu. Dışa açık: hedefin durumunu okuyan taraf (Observed.PosternSudoers) aynı yolu kullanmazsa plan dosyayı hiç "var" görmez ve her koşuda yeniden yazar.

func UserSudoPath

func UserSudoPath(user string) string

UserSudoPath, bir hesap için postern'in yazdığı dosyanın yolu. Grup dosyalarından ayrı bir önek: "dba" adlı grup ile "dba" adlı hesabın kuralları aynı dosyaya düşmesin.

Types

type AccountFacts

type AccountFacts struct {
	Exists bool
	UID    int
	Home   string
	Groups []string
}

AccountFacts, sökme planının bir hesap hakkında bilmesi gerekenler.

func Account

func Account(ctx context.Context, r Runner, name string) (AccountFacts, error)

* Account, bir hesabın numarasını, evini ve gruplarını hedeften okur — * sökme planının varsayım değil ölçüm istediği üç şey. * * ⚠️ SİLMEDEN ÖNCE OKUNUYOR. Ad-UID eşlemesi userdel ile kayboluyor ve * kalan dosyaların raporu o numarayla aranıyor; sonradan sorulsa cevap * yok. Ev dizini de getent'ten: "/home/<ad>" varsaymak, farklı evi olan * bir hesapta karalama yolu kontrolünü yanlış yere baktırırdı.

func (AccountFacts) InJITGroup

func (a AccountFacts) InJITGroup() bool

InJITGroup, hesabın postern tarafından açıldığının kanıtı.

type Desired

type Desired struct {
	Groups []Group
	Users  []User
	/*
	 * PrincipalsFile, hedefin sshd'sinin AuthorizedPrincipalsFile deseni
	 * (upstream.ManageCapabilities.PrincipalsFile). Boş değilse geçici
	 * hesabın dosyası yazılıyor; boşsa sshd giriş adını sertifikanın
	 * principal'ında arıyor ve dosya gerekmiyor.
	 */
	PrincipalsFile string
}

Desired, bir hedefte olması istenen durum.

type Group

type Group struct {
	Name string

	// Sudo, gruba yazılacak kural. Komutu yoksa sudo dosyası hiç
	// yazılmıyor — "sudosuz grup" geçerli bir istek.
	Sudo sudoers.Rule
}

Group, hedefte bulunması istenen grup ve onun sudo kuralı.

type GroupFacts

type GroupFacts struct {
	Exists    bool
	GID       int
	Members   []string
	PrimaryOf []string
}

* GroupFacts, bir grubun hedefteki kullanımı: üyeleri ve birincil grubu o * olan hesaplar. Geri alma "boş mu" sorusunu bununla cevaplıyor.

func GroupUsage

func GroupUsage(ctx context.Context, r Runner, name string) (GroupFacts, error)

* GroupUsage, bir grubun üyelerini ve birincil grubu o olan hesapları okur. * * ⚠️ İKİSİ DE OKUNUYOR. /etc/group'taki üye listesi birincil grubu * göstermiyor: `useradd -g dba veli` ile açılan hesap dba'nın üyesi * görünmez ama grubu siler silmez o hesap sahipsiz bir GID'e düşer.

func (GroupFacts) UsedByOthers

func (f GroupFacts) UsedByOthers(except string) bool

UsedByOthers, except dışında birinin grubu kullanıp kullanmadığı.

type GroupInfo

type GroupInfo struct {
	Name    string   `json:"name"`
	GID     int      `json:"gid"`
	Members []string `json:"members"`
}

GroupInfo, hedefteki bir grubun adı, numarası ve üyeleri.

func Groups

func Groups(ctx context.Context, r Runner) ([]GroupInfo, error)

* Groups, hedefin bütün gruplarını okur — panelin "hangi gruba alayım" * seçicisi için. Observe'un aksine envanterin tamamı isteniyor; seçici * ancak listeyi görerek seçebilir. `getent group` sudo istemiyor ve NSS * üzerinden dizin gruplarını da veriyor.

func (GroupInfo) Protected

func (g GroupInfo) Protected() bool

Protected, grubun geçici hesaplara kapalı olup olmadığı.

type Observed

type Observed struct {
	Groups map[string]bool
	// GIDs, var olan grupların numaraları — sistem grubu ayrımı için.
	GIDs map[string]int
	// Users, hesabın üye olduğu gruplar.
	Users map[string][]string
	// PosternSudoers, postern'in yazdığı sudo dosyalarının içeriği.
	PosternSudoers map[string]string
	// Principals, geçici hesapların principals dosyalarının içeriği (yol → içerik).
	Principals map[string]string
}

Observed, hedefte ŞU AN olan durum.

func Observe

func Observe(ctx context.Context, r Runner, d Desired) (Observed, error)

* Observe, istenen durumun ilgilendirdiği her şeyi hedeften okur: gruplar * var mı, hesaplar hangi gruplarda, postern'in sudo dosyalarında ne var. * * ⚠️ YALNIZCA SORULANI OKUYOR. Makinenin bütün grup ve hesap listesini * çekmek daha kolay olurdu ama hedefin envanterini bastion'a taşımak * demekti; plan neyi değiştirecekse yalnızca onu soruyor.

type Outcome

type Outcome string

Outcome, tek bir adımın sonucu.

const (
	OutcomeDone Outcome = "done"
	OutcomeFail Outcome = "failed"
	// OutcomeUnreachable, makineye ulaşılamadı: hedefin suçu değil.
	OutcomeUnreachable Outcome = "unreachable"
	// OutcomeUnconfirmed, adım gitti ama hedef koşup koşmadığını
	// bildirmedi — makinede olmuş da olabilir (bkz. ErrUnconfirmed).
	OutcomeUnconfirmed Outcome = "not confirmed"
	// OutcomeSkipped, önceki bir adım düştüğü için HİÇ DENENMEDİ.
	OutcomeSkipped Outcome = "not attempted"
)

type Report

type Report struct {
	Results []Result
}

* Report, bir hedefteki koşunun tamamı. * * ⚠️ "KAÇ TANE YAPILDI" YETMİYOR, "KAÇ TANE DENENMEDİ" DE GEREKİYOR. * Yarıda kalmış bir koşuda kalan adımları saymamak, makinenin ne * durumda olduğunu okuyamamak demek — ve bu paketin reddettiği tek şey * yarım uygulanmış makine.

func Apply

func Apply(ctx context.Context, r Runner, steps []Step) Report

* Apply, adımları sırayla çalıştırır ve İLK HATADA DURUR. * * ⚠️ DEVAM ETMEK, YARIM UYGULAMANIN KENDİSİ. Örnekler soyut değil: * doğrulama adımı düşmüşken kurulum adımını koşturmak, geçersiz bir * sudoers dosyasını yerine koyar ve o makinede herkesin sudo'sunu * götürür — postern'in kendi hesabı dahil, yani makine kendini * onaramaz. Grup açılamamışken kullanıcıyı o gruba eklemek de hata * verir, ama daha kötüsü: hata mesajı asıl sebebi değil sonucu * gösterir. * * ⚠️ DENENMEYEN ADIMLAR DA RAPORA GİRİYOR. Operatör makinenin hangi * noktada kaldığını görmeli; eksik bir liste, "geri kalanı yapıldı * mı" sorusunu cevapsız bırakır.

func (Report) Done

func (r Report) Done() int

func (Report) Failed

func (r Report) Failed() int

func (Report) FirstError

func (r Report) FirstError() error

FirstError, koşuyu durduran hata.

func (Report) OK

func (r Report) OK() bool

OK, koşunun tamamının uygulandığı — ve UYGULANDIĞININ BİLİNDİĞİ.

func (Report) Skipped

func (r Report) Skipped() int

func (Report) Summary

func (r Report) Summary() string

Summary, panelde ve denetim satırında görünecek cümle.

func (Report) Unconfirmed

func (r Report) Unconfirmed() int

func (Report) Unreachable

func (r Report) Unreachable() int

type Result

type Result struct {
	Step    Step
	Outcome Outcome
	// Output, hedefin çıktısı — denetim satırına giren şey.
	Output string
	Err    error
}

Result, bir adımın sonucu ve hedefin söyledikleri.

type Revoke

type Revoke struct {
	User string
	Mode RevokeMode

	// Home, hesabın ev dizini (getent'ten okunuyor).
	Home string

	/*
	 * Scratch, ev dizini dışında silinecek YOLLAR — operatörün
	 * önceden bildirdikleri.
	 *
	 * ⚠️ "KULLANICIYA AİT HER ŞEYİ SİL" DEĞİL. `find / -uid N -delete`
	 * bir üretim makinesini bir kez mahveder: yanlış UID, paylaşılan
	 * dizinde bırakılmış bir dosya, ya da bir editörün sahipliğini
	 * değiştirdiği sistem dosyası. Kapsam bildirilmiş yollarla
	 * sınırlı; dışarıda kalanlar SİLİNMİYOR, raporlanıyor.
	 */
	Scratch []string

	/*
	 * UID, hesabın numarası — SİLMEDEN ÖNCE okunuyor.
	 *
	 * ⚠️ RAPOR ADI DEĞİL NUMARAYI KULLANIYOR — ÖLÇÜLDÜ. Adla arama
	 * `userdel`den sonra çalışmıyor: ad artık çözülmüyor, find hata
	 * veriyor ve rapor SESSİZCE BOŞ dönüyor. Yani kalan dosyaları
	 * gösteren şey, tam da işe yarayacağı anda hiçbir şey göstermiyordu.
	 */
	UID int

	// InJITGroup, hesabın postern tarafından açıldığının kanıtı.
	InJITGroup bool

	// SudoFiles, bu hesap için yazılmış postern sudo dosyaları.
	SudoFiles []string
	// PrincipalsFile, hesabın principals dosyası (PrincipalsPath ile
	// çözülmüş); boşsa dosya yok.
	PrincipalsFile string
	/*
	 * DeleteGroups, hesapla birlikte silinecek gruplar — çağıranın
	 * "postern açtı ve başka kimse kullanmıyor" diye ÖLÇTÜĞÜ gruplar
	 * (GroupUsage). Plan bunu yeniden ölçmüyor; hesap silindikten sonra
	 * groupdel'e veriyor. Yalnızca silme kipinde.
	 */
	DeleteGroups []string
}

Revoke, geri alınacak hak.

type RevokeMode

type RevokeMode string

RevokeMode, hakkın nasıl geri alınacağı.

const (
	/*
	 * ModeLock, kalıcı hesaplar için: hesap kilitleniyor, süreçleri
	 * kesiliyor, ama SİLİNMİYOR.
	 *
	 * ⚠️ SİLMEMEK BİR EKSİKLİK DEĞİL, KARAR. Silinen hesabın UID'si
	 * yeniden kullanılabiliyor; sonraki hesap aynı numarayı alırsa
	 * öncekinin bıraktığı bütün dosyaların sahibi oluyor. Kalıcı
	 * hesap, dosya sahipliğinin çıpası — "bunu kim bıraktı"
	 * sorusunun altı ay sonraki tek cevabı.
	 */
	ModeLock RevokeMode = "lock"

	/*
	 * ModeDelete, JIT hesapları için: hesap ve dosyaları siliniyor.
	 *
	 * ⚠️ YALNIZCA POSTERN'İN AÇTIĞI HESAPLARDA. JIT hesabının o
	 * makinede kalıcı bir işi yok; ama aynı ada sahip, postern'den
	 * önce var olan bir hesabı silmek başka bir şey olurdu.
	 */
	ModeDelete RevokeMode = "delete"
)

type Runner

type Runner interface {
	// Exec, komutu çalıştırır; stdin boş değilse girdi olarak verir.
	Exec(ctx context.Context, command, stdin string) (string, error)
}

* Runner, hedefte tek bir komut çalıştırabilen şey. * * ⚠️ ARAYÜZ, SSH'A BAĞLI DEĞİL. Uygulamanın kararları — nerede durulacak, * ne kaydedilecek — bir bağlantı kurmadan ölçülebilmeli; yoksa "ilk * hatada dur" gibi bir kuralın testi, gerçek bir makineye ve gerçek bir * arızaya bağlı olurdu.

type SSHRunner

type SSHRunner struct {
	// contains filtered or unexported fields
}

* SSHRunner, açık bir yönetim bağlantısı üzerinde adımları çalıştırır. * * ⚠️ BAĞLANTI ADIM BAŞINA DEĞİL, KOŞU BAŞINA. Her adım için yeniden * bağlanmak, hedefin günlüğüne bir yayılım koşusu başına onlarca root * girişi yazardı — makinenin sahibi için okunamaz bir iz.

func Connect

func Connect(ctx context.Context, t model.Target, authority *ca.CA, actor, reason string) (*SSHRunner, error)

* Connect, hedefe yönetim hesabıyla bağlanır ve bir Runner döner. * * actor ve reason hedefin kendi sshd günlüğüne düşen KeyID'ye giriyor * (bkz. upstream.DialManagement). * * ⚠️ HATA upstream'İN SINIFIYLA, ErrUnreachable'A SARILMADAN DÖNÜYOR — * VE İLK HÂLİ SARIYORDU. Sarmak, reddedilen bir sertifikayı ve değişmiş * bir host anahtarını da "ulaşılamadı" kovasına atıyordu: panelde "hedef * sertifikayı reddetti" cümlesinin hemen altında ham metin "target could * not be reached:" diye başlıyor, iki satır birbirini çürütüyordu. Daha * önemlisi yanlış iş söylüyordu: ulaşılamayan makinede beklemek işe * yarar, CA'ya güvenmeyen makinede asla. upstream/hostkey.go bu * düzleştirmeyi ölçüp ayrı sınıflar koymuştu. Bağlantı kurulamadıysa * ortada bir Apply raporu yok; çağıran upstream.ErrRefused, * ErrHostKeyMismatch, ErrHandshake ve ErrUnreachable'a bakarak karar * veriyor.

func (*SSHRunner) Close

func (r *SSHRunner) Close() error

Close, yönetim bağlantısını kapatır.

func (*SSHRunner) Conn

func (r *SSHRunner) Conn() *upstream.Conn

Conn, yeteneği ölçmek gibi plan dışı okumalar için bağlantının kendisi.

func (*SSHRunner) Exec

func (r *SSHRunner) Exec(ctx context.Context, command, stdin string) (string, error)

* Exec, tek bir adımı çalıştırır ve STDOUT'u döner. * * ⚠️ "KOMUT DÜŞTÜ" İLE "MAKİNEYE ULAŞAMADIM" AYRIMI BURADA TAHMİN DEĞİL. * `ssh` ikilisiyle koşarken elimizde yalnızca çıkış kodu vardı ve 255'i * sezgiyle yorumluyorduk — uzak komutun kendisi de 255 dönebilir. * Protokol seviyesinde belirsizlik yok: CommandError, hedefin komutu * çalıştırıp bir kod bildirdiği anlamına geliyor; öbür her şey * cevapsızlık. * * Hata sebebi (stderr) CommandError'ın metninde duruyor ve Apply onu * Result.Err olarak kaydediyor; stdout'a karıştırılmıyor, çünkü stdout * VERİ olarak da okunuyor (bkz. upstream.Conn.Exec).

type Step

type Step struct {
	Kind StepKind

	/*
	 * Command, hedefte AYNEN çalıştırılacak komut — sudo dahil.
	 *
	 * ⚠️ SUDO PLANDA, UYGULAYICIDA DEĞİL. Plan operatöre gösterilen
	 * şey; "ne çalışacak" sorusunun cevabı burada eksiksiz durmalı.
	 * Uygulayıcı komutu değiştirirse, onaylanan ile koşan farklı olur.
	 */
	Command string
	// Content, varsa komutun stdin'ine verilecek metin.
	Content string
	// Why, panelde ve denetim satırında görünen cümle.
	Why string
	// Subject, adımın üzerinde çalıştığı ad (grup ya da hesap) — rapordan
	// "hangi grubu açtık" diye geri okunabilsin diye; komut metnini
	// ayrıştırmak kırılgan olurdu.
	Subject string
}

* Step, hedefte çalıştırılacak tek bir iş. * * ⚠️ DEĞİŞKEN İÇERİK Command'A GİRMİYOR. sudoers metni Content'te * duruyor ve hedefe STDIN ile gidiyor; komut satırı sabit kalıyor. * Aksi hâlde bir grup adı ya da kural metni hedefin kabuğuna * yorumlanacak biçimde ulaşırdı — ve bu paket root yetkisiyle * çalışıyor.

func GroupDeleteSteps

func GroupDeleteSteps(caps upstream.ManageCapabilities, groups []string) ([]Step, error)

* GroupDeleteSteps, postern'in açtığı ve artık boş olan grupları silen * adımlar. Adlar buraya gelmeden ölçülmüş olmalı (GroupUsage); burada * yalnızca ad biçimi ve postern-jit koruması var — kanıt grubu hiçbir * koşulda silinmiyor, başka geçici hesaplar ona bağlı.

func Plan

func Plan(caps upstream.ManageCapabilities, d Desired, o Observed) ([]Step, error)

* Plan, gözlenen durumdan istenen duruma giden adımları üretir. * * ⚠️ YÖNETİLEMEYEN HEDEFE HİÇ ADIM ÜRETİLMİYOR. Yarısı uygulanmış bir * makine, hiç dokunulmamış olandan kötü: panel yeşil görünür ve kimse * bakmaz. Eksikler yoklamada zaten adlandırılmış durumda.

func PrincipalRemoveStep

func PrincipalRemoveStep(path, user string) (Step, error)

* RemoveSudoFilesPlan, yalnızca postern'in yazdığı sudo dosyalarını * kaldıran adımlar — hesabı OLMAYAN bir hak için. * * ⚠️ NEDEN AYRI: sökme planı hesabın UID'sini ve üyeliğini istiyor, çünkü * silme kararı onlara bağlı. Hesap çoktan gitmişse (yedek süre, elle * silme, önceki yarım deneme) geride yalnızca sudo dosyası kalmış * olabilir ve o dosya hesap yeniden açıldığı gün yeniden yetki verir. * Yol kontrolü sökme planınınkinin aynısı.

* PrincipalRemoveStep, hesabın principals dosyasını kaldıran adım. * * ⚠️ YOL HESABIN ADIYLA BİTMEK ZORUNDA. Silinen şey `rm -f` ile gidiyor; * desenden gelen yol bir başka hesabın (ya da paylaşılan bir dosyanın) * yolu olsaydı, geri alma başka birinin girişini kapatırdı.

func RemoveSudoFilesPlan

func RemoveSudoFilesPlan(files []string) ([]Step, error)

func RevokePlan

func RevokePlan(caps upstream.ManageCapabilities, r Revoke) ([]Step, error)

* RevokePlan, hakkı geri alan adımları üretir. * * ⚠️ SIRA: SUDO, SÜREÇLER, SONRA HESAP. Kuralı önce almak, süreçler * ölene kadar geçen sürede yeni bir yükseltmeyi engelliyor. Süreçleri * hesaptan ÖNCE öldürmek ise zorunlu: hesap silindiğinde ad-UID eşlemesi * kayboluyor ve süreçler sahipsiz bir numarayla koşmaya devam ediyor.

type StepKind

type StepKind string

StepKind, adımın türü.

const (
	StepGroupAdd    StepKind = "group.add"
	StepUserAdd     StepKind = "user.add"
	StepUserGroup   StepKind = "user.group"
	StepSudoStage   StepKind = "sudo.stage"
	StepSudoCheck   StepKind = "sudo.check"
	StepSudoInstall StepKind = "sudo.install"
	StepPrincipal   StepKind = "principal.write"
	StepUserUnlock  StepKind = "user.unlock"
)
const (
	StepSudoRemove      StepKind = "sudo.remove"
	StepPrincipalRemove StepKind = "principal.remove"
	StepKill            StepKind = "user.kill"
	StepLock            StepKind = "user.lock"
	StepUserDel         StepKind = "user.delete"
	StepGroupDel        StepKind = "group.delete"
	StepScratchDel      StepKind = "scratch.delete"
	StepReportOwned     StepKind = "files.report"
)

type User

type User struct {
	Name   string
	Groups []string

	/*
	 * JIT true ise hesap GEÇİCİ: postern açıyor, süresi dolunca siliyor.
	 *
	 * ⚠️ ÜYELİK KANIT: JIT hesabı postern-jit grubuna giriyor ve sökme
	 * planı YALNIZCA o gruptaki hesabı siliyor. Bu üyeliği kuran tek yer
	 * burası; kurulmasaydı hiçbir hesap silinemez, ya da daha kötüsü,
	 * kanıt elle verilirdi (canlı test bir süre öyle yapıyordu).
	 */
	JIT bool

	/*
	 * ExpiresAt, JIT hesabının süresi — hedefe `useradd -e` ile de
	 * yazılıyor.
	 *
	 * ⚠️ YEDEK, ASIL MEKANİZMA DEĞİL. Sökmeyi postern yapıyor; bu tarih,
	 * postern ölürse ya da hedefe ulaşamazsa hesabın sonsuza dek açık
	 * kalmaması için. Gün çözünürlüğünde ve süre bitiminden SONRAKİ güne
	 * yuvarlanıyor: yedeğin asıl süreden önce vurması, geçerli bir hakkı
	 * ortasından kesmek olurdu.
	 */
	ExpiresAt time.Time

	/*
	 * Sudo, yalnızca bu hesaba yazılacak kural (grup kuralından ayrı).
	 * nil ise kullanıcı dosyası yazılmıyor. Dosya postern-user-<ad>
	 * adıyla gidiyor ve sökme planı onu adıyla kaldırıyor.
	 */
	Sudo *sudoers.Rule
}

User, hedefte bulunması istenen hesap.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL