Documentation
¶
Index ¶
- Constants
- Variables
- func CleanSearchPath(p string) string
- func ValidateLabel(key, value string) error
- type AdminHolder
- type AdminLogEntry
- type ArchiveBacklogReport
- type ArchivePending
- type ArchiveState
- type Credential
- type DirectoryAccount
- type DiscoveredMachine
- type DiscoveryRun
- type DiscoverySource
- type FileQuery
- type FileTouch
- type GroupMapping
- type JITGrant
- type LocalCredentialHolder
- type PendingUser
- type ProvisionRequest
- type PublicKey
- type PurgeResult
- type PurgedAccount
- type RoleSudo
- type SessionFile
- type SessionStart
- type SettingView
- type StaleAccount
- type Store
- func (s *Store) AccountID(ctx context.Context, username string) (string, error)
- func (s *Store) AccountState(ctx context.Context, username string) (state string, confirmed time.Time, err error)
- func (s *Store) ActiveJITGrantsForUser(ctx context.Context, username string) ([]JITGrant, error)
- func (s *Store) AddGroupMapping(ctx context.Context, externalGroup, roleName, actor string) error
- func (s *Store) AddLocalCredential(ctx context.Context, username, verifier, by string) error
- func (s *Store) AddPublicKey(ctx context.Context, username string, keyBlob []byte, comment string) error
- func (s *Store) AddSessionFiles(ctx context.Context, sessionID string, files []SessionFile) error
- func (s *Store) AddWebAuthnCredential(ctx context.Context, username string, c WebAuthnCredential) error
- func (s *Store) AdminLog(ctx context.Context, limit int) ([]AdminLogEntry, error)
- func (s *Store) AdminVia(ctx context.Context, username string) (string, error)
- func (s *Store) Admins(ctx context.Context) ([]AdminHolder, error)
- func (s *Store) AllTargetFacts(ctx context.Context) (map[string]model.TargetFacts, error)
- func (s *Store) AllowIdentityBind(ctx context.Context, username string, at time.Time) error
- func (s *Store) ApplyAdminGroup(ctx context.Context, members []string) (granted, revoked []string, err error)
- func (s *Store) ApprovePending(ctx context.Context, id, osUser, by string) (PendingUser, error)
- func (s *Store) ArchiveBacklog(ctx context.Context) (b ArchiveBacklogReport, err error)
- func (s *Store) ArchiveStateOf(ctx context.Context, sessionID string) (ArchiveState, bool, error)
- func (s *Store) ArchivedIDs(ctx context.Context, ids []string) (map[string]bool, error)
- func (s *Store) AssignRole(ctx context.Context, username, roleName string, expiresAt time.Time) error
- func (s *Store) BeginTOTP(ctx context.Context, username, secret string) error
- func (s *Store) BindDirIdentity(ctx context.Context, username, subject string) error
- func (s *Store) BindIdPSubject(ctx context.Context, username, issuer, subject string) error
- func (s *Store) ClaimArchives(ctx context.Context, limit int, now time.Time, ...) ([]ArchivePending, error)
- func (s *Store) ClaimByVerifiedEmail(ctx context.Context, email, issuer, subject string, adminGroupMember bool) (model.User, error)
- func (s *Store) ClaimDiscoverySource(ctx context.Context, id string, now, dueBefore time.Time) (bool, error)
- func (s *Store) ClearTOTPFailures(ctx context.Context, username string) (int, error)
- func (s *Store) Close() error
- func (s *Store) CloseOrphanSessions(ctx context.Context, at time.Time) (closed, queued int64, err error)
- func (s *Store) ConfirmAccount(ctx context.Context, username string, at time.Time) error
- func (s *Store) ConfirmTOTP(ctx context.Context, username string, step int64) error
- func (s *Store) CreateDiscoverySource(ctx context.Context, d DiscoverySource, secret string) (string, error)
- func (s *Store) CreateFromDirectory(ctx context.Context, acc DirectoryAccount) (model.User, error)
- func (s *Store) CreateJITGrant(ctx context.Context, g JITGrant) (string, error)
- func (s *Store) CreateRole(ctx context.Context, name string) (string, error)
- func (s *Store) CreateTarget(ctx context.Context, t model.Target) (string, error)
- func (s *Store) CreateUser(ctx context.Context, username, email, osUser string) (string, error)
- func (s *Store) DeleteDiscoverySource(ctx context.Context, id string) (string, error)
- func (s *Store) DeleteRole(ctx context.Context, name string) error
- func (s *Store) DeleteRolePath(ctx context.Context, roleName, prefix string) error
- func (s *Store) DeleteRoleSudo(ctx context.Context, role string) error
- func (s *Store) DeleteSetting(ctx context.Context, key string) error
- func (s *Store) DeleteTarget(ctx context.Context, name string) error
- func (s *Store) DeleteTargetLabel(ctx context.Context, targetName, key, actor, via string) error
- func (s *Store) DeleteUser(ctx context.Context, username string) error
- func (s *Store) DeleteWebAuthnCredential(ctx context.Context, username, id string) error
- func (s *Store) DirSubjectOf(ctx context.Context, username string) (string, error)
- func (s *Store) DisableTOTP(ctx context.Context, username string) error
- func (s *Store) DiscoveredMachine(ctx context.Context, sourceID, ref string) (DiscoveredMachine, error)
- func (s *Store) DiscoveredMachines(ctx context.Context, sourceID string) ([]DiscoveredMachine, error)
- func (s *Store) DiscoveryRuns(ctx context.Context, sourceID string, limit int) ([]DiscoveryRun, error)
- func (s *Store) DiscoverySource(ctx context.Context, id string) (DiscoverySource, error)
- func (s *Store) DiscoverySourceSecret(ctx context.Context, id string) (string, error)
- func (s *Store) DiscoverySources(ctx context.Context) ([]DiscoverySource, error)
- func (s *Store) DueJITGrants(ctx context.Context, now time.Time) ([]JITGrant, error)
- func (s *Store) EndSession(ctx context.Context, id string, endedAt time.Time) error
- func (s *Store) ExpireJITGrant(ctx context.Context, id string, now time.Time) error
- func (s *Store) FailedRevokes(ctx context.Context) ([]JITGrant, error)
- func (s *Store) FileHistory(ctx context.Context, q FileQuery) ([]FileTouch, error)
- func (s *Store) FinishDiscoveryRun(ctx context.Context, r DiscoveryRun) error
- func (s *Store) FinishSyncRun(ctx context.Context, run SyncRun) error
- func (s *Store) FirstKeyAdded(ctx context.Context, username string) (bool, error)
- func (s *Store) ForgetPending(ctx context.Context, id string) error
- func (s *Store) GrantTarget(ctx context.Context, roleName, targetName string) error
- func (s *Store) GroupMappings(ctx context.Context) ([]GroupMapping, error)
- func (s *Store) HasIdPIdentity(ctx context.Context, username string) (bool, error)
- func (s *Store) JITGrant(ctx context.Context, id string) (JITGrant, error)
- func (s *Store) JITGrants(ctx context.Context, limit int) ([]JITGrant, error)
- func (s *Store) JITGrantsForTarget(ctx context.Context, target string, limit int) ([]JITGrant, error)
- func (s *Store) LatestDiscoveryRuns(ctx context.Context) (map[string]DiscoveryRun, error)
- func (s *Store) LinkDiscoveredMachine(ctx context.Context, sourceID, ref, targetID string) error
- func (s *Store) ListPending(ctx context.Context) ([]PendingUser, error)
- func (s *Store) LocalCredential(ctx context.Context, username string) (Credential, error)
- func (s *Store) LocalCredentialHolders(ctx context.Context) ([]LocalCredentialHolder, error)
- func (s *Store) LogAdmin(ctx context.Context, e AdminLogEntry) error
- func (s *Store) MarkArchiveFailed(ctx context.Context, sessionID, reason string, permanent bool, at time.Time) error
- func (s *Store) MarkArchived(ctx context.Context, sessionID, bucket, key, sha string, size int64, ...) error
- func (s *Store) MarkDirectoryMissing(ctx context.Context, username string, at time.Time) error
- func (s *Store) MarkDirectorySeen(ctx context.Context, username string, at time.Time) error
- func (s *Store) MarkDiscoveredMachineMissing(ctx context.Context, sourceID, ref string, now time.Time) error
- func (s *Store) MarkFirstKeyAdded(ctx context.Context, username string, at time.Time) error
- func (s *Store) MarkJITGrantApplied(ctx context.Context, id string, ok bool, report string, now time.Time) error
- func (s *Store) MarkJITGrantRevokeFailed(ctx context.Context, id, reason string, next time.Time) error
- func (s *Store) MarkJITGrantRevoked(ctx context.Context, id, report string, now time.Time) error
- func (s *Store) MarkSFTPJournal(ctx context.Context, id string, j model.SFTPJournal) error
- func (s *Store) Migrate(ctx context.Context) error
- func (s *Store) OpenSessions(ctx context.Context) ([]model.Session, error)
- func (s *Store) PendingByID(ctx context.Context, id string) (PendingUser, error)
- func (s *Store) PendingMigrations(ctx context.Context) (int, error)
- func (s *Store) Ping(ctx context.Context) error
- func (s *Store) ProvisionUser(ctx context.Context, req ProvisionRequest) (model.User, error)
- func (s *Store) PublicKeyCounts(ctx context.Context) (map[string]int, error)
- func (s *Store) PublicKeys(ctx context.Context, username string) ([]PublicKey, error)
- func (s *Store) PurgeAccount(ctx context.Context, username string, at time.Time) (PurgeResult, error)
- func (s *Store) PurgedAccounts(ctx context.Context) ([]PurgedAccount, error)
- func (s *Store) QueueArchive(ctx context.Context, sessionID string) error
- func (s *Store) RecordPending(ctx context.Context, p PendingUser) (string, error)
- func (s *Store) RecordTargetError(ctx context.Context, targetName, reason string) error
- func (s *Store) RecordTargetProbe(ctx context.Context, targetName string, p model.TargetProbe) error
- func (s *Store) RecordTargetProbeAttempt(ctx context.Context, targetName string, at time.Time) error
- func (s *Store) RecordTargetSeen(ctx context.Context, targetName string, f model.TargetFacts) error
- func (s *Store) RecordUnmappedGroups(ctx context.Context, groups []string) error
- func (s *Store) RefuseIfDeleted(ctx context.Context, username string) error
- func (s *Store) RefuseIfDeletedByID(ctx context.Context, id string) error
- func (s *Store) RejectPending(ctx context.Context, id, reason, by string) error
- func (s *Store) RemoveGroupMapping(ctx context.Context, externalGroup, roleName string) error
- func (s *Store) RemoveLocalCredential(ctx context.Context, username string) error
- func (s *Store) RemovePublicKey(ctx context.Context, username string, keyBlob []byte) error
- func (s *Store) ReplaceLocalCredential(ctx context.Context, username, verifier, by string) (replaced bool, err error)
- func (s *Store) ResetWebAuthn(ctx context.Context, username string) (int, error)
- func (s *Store) RevokeRole(ctx context.Context, username, roleName string) error
- func (s *Store) RevokeTarget(ctx context.Context, roleName, targetName string) error
- func (s *Store) RoleGrantSource(ctx context.Context, username, roleName string) (source string, found bool, err error)
- func (s *Store) RolePaths(ctx context.Context, roleName string) ([]model.PathRule, error)
- func (s *Store) RoleSudoRule(ctx context.Context, role string) (RoleSudo, error)
- func (s *Store) RoleSudoRules(ctx context.Context) (map[string]RoleSudo, error)
- func (s *Store) Roles(ctx context.Context) ([]model.Role, error)
- func (s *Store) RolesForGroups(ctx context.Context, groups []string) (roles, unmapped []string, err error)
- func (s *Store) Rollback(ctx context.Context) error
- func (s *Store) SaveDiscoveredMachine(ctx context.Context, m DiscoveredMachine) error
- func (s *Store) SchemaVersion(ctx context.Context) (int, error)
- func (s *Store) SecretsAvailable() bool
- func (s *Store) SeenGroupNames(ctx context.Context) ([]string, error)
- func (s *Store) Session(ctx context.Context, id string) (model.Session, error)
- func (s *Store) SessionFiles(ctx context.Context, sessionID string) ([]SessionFile, error)
- func (s *Store) Sessions(ctx context.Context, username string, limit int) ([]model.Session, error)
- func (s *Store) SetAccountState(ctx context.Context, username, state string) error
- func (s *Store) SetChosenPassword(ctx context.Context, username, verifier string, at time.Time) error
- func (s *Store) SetDiscoveredMachineIgnored(ctx context.Context, sourceID, ref string, ignored bool) (string, bool, error)
- func (s *Store) SetGroupAdmin(ctx context.Context, username string, admin bool) error
- func (s *Store) SetJITGrantCreatedGroups(ctx context.Context, id string, groups []string) error
- func (s *Store) SetRecordingChain(ctx context.Context, id, head string, links int64) error
- func (s *Store) SetRecordingPathForTest(ctx context.Context, sessionID, path string) error
- func (s *Store) SetRolePath(ctx context.Context, roleName, prefix string, allow, canWrite bool) error
- func (s *Store) SetRoleSudo(ctx context.Context, role string, rule sudoers.Rule, actor string) error
- func (s *Store) SetSearchTimeoutForTest(d time.Duration)
- func (s *Store) SetSetting(ctx context.Context, key, value string, encrypt bool, actor string) error
- func (s *Store) SetTargetLabel(ctx context.Context, targetName, key, value, actor, via string) error
- func (s *Store) SetUserAdmin(ctx context.Context, username string, admin bool) error
- func (s *Store) SetUserEmail(ctx context.Context, username, email string) error
- func (s *Store) SetUserOSUser(ctx context.Context, username, osUser string) error
- func (s *Store) SetUserSSOOnly(ctx context.Context, username string, ssoOnly bool) error
- func (s *Store) SetWebAuthnOnly(ctx context.Context, username string, only bool) error
- func (s *Store) Setting(ctx context.Context, key string) (string, error)
- func (s *Store) Settings(ctx context.Context) ([]SettingView, error)
- func (s *Store) SourceAccountCount(ctx context.Context) (int, error)
- func (s *Store) StaleAccounts(ctx context.Context, olderThan time.Time, state string) ([]StaleAccount, error)
- func (s *Store) StartDiscoveryRun(ctx context.Context, r DiscoveryRun) (int64, error)
- func (s *Store) StartSession(ctx context.Context, rec SessionStart) error
- func (s *Store) StartSyncRun(ctx context.Context, source, trigger string, dryRun bool) (int64, error)
- func (s *Store) SyncCandidates(ctx context.Context) ([]SyncCandidate, error)
- func (s *Store) SyncRoles(ctx context.Context, username string, roleNames []string) error
- func (s *Store) SyncRuns(ctx context.Context, limit int) ([]SyncRun, error)
- func (s *Store) TOTP(ctx context.Context, username string) (TOTPCredential, error)
- func (s *Store) TOTPEnrolled(ctx context.Context, username string) (bool, error)
- func (s *Store) TOTPFailure(ctx context.Context, username string, max int, lockFor time.Duration) (TOTPLock, error)
- func (s *Store) TOTPLockState(ctx context.Context, username string) (TOTPLock, error)
- func (s *Store) Target(ctx context.Context, name string) (model.Target, error)
- func (s *Store) TargetFacts(ctx context.Context, targetName string) (model.TargetFacts, error)
- func (s *Store) TargetKeys(ctx context.Context) ([]TargetKey, error)
- func (s *Store) TargetLabels(ctx context.Context, targetName string) (map[string]string, error)
- func (s *Store) Targets(ctx context.Context) ([]model.Target, error)
- func (s *Store) TouchDiscoverySource(ctx context.Context, id string, now time.Time) error
- func (s *Store) TouchLocalCredential(ctx context.Context, username string, at time.Time) error
- func (s *Store) TouchWebAuthnCredential(ctx context.Context, id string, signCount uint32, flags byte) error
- func (s *Store) TryLockSync(ctx context.Context) (release func(), acquired bool, err error)
- func (s *Store) UnbindDirIdentity(ctx context.Context, username string) error
- func (s *Store) UnlockTOTP(ctx context.Context, username string) error
- func (s *Store) UnmappedGroups(ctx context.Context) ([]UnmappedGroup, error)
- func (s *Store) UpdateDiscoverySource(ctx context.Context, d DiscoverySource, secret string) error
- func (s *Store) UseSecretBox(box *secret.Box)
- func (s *Store) UseTOTPStep(ctx context.Context, username string, step int64) error
- func (s *Store) User(ctx context.Context, username string) (model.User, error)
- func (s *Store) UserByDirSubject(ctx context.Context, subject string) (model.User, error)
- func (s *Store) UserByEmail(ctx context.Context, email string) (model.User, error)
- func (s *Store) UserByIdPSubject(ctx context.Context, issuer, subject string) (model.User, error)
- func (s *Store) UserByNameFold(ctx context.Context, name string) (string, error)
- func (s *Store) UserByPublicKey(ctx context.Context, keyBlob []byte) (model.User, error)
- func (s *Store) UserIdentity(ctx context.Context, username string) (string, error)
- func (s *Store) UserProfile(ctx context.Context, username string) (UserProfile, error)
- func (s *Store) Users(ctx context.Context) ([]model.User, error)
- func (s *Store) WebAuthnCredentials(ctx context.Context, username string) ([]WebAuthnCredential, error)
- func (s *Store) WebAuthnOnly(ctx context.Context, username string) (bool, error)
- type SyncCandidate
- type SyncRun
- type TOTPCredential
- type TOTPLock
- type TargetKey
- type UnmappedGroup
- type UserProfile
- type WebAuthnCredential
Constants ¶
const ( StateActive = "active" StateInactive = "inactive" StateDeleted = "deleted" )
Hesap durumları.
const ( DiscoveryRunning = "running" DiscoveryOK = "ok" DiscoveryFailed = "failed" )
Keşif koşusunun sonuçları.
const ( PendingWaiting = "waiting" PendingRejected = "rejected" )
Pending durumları.
const ( FileHistoryDefaultLimit = 200 FileHistoryMaxLimit = 1000 )
FileHistoryDefaultLimit / FileHistoryMaxLimit, geçmiş sorgusunun sınırları.
⚠️ DIŞARI AÇIKLAR çünkü kesilmiş bir listeyi "hepsi bu" diye göstermemek çağıranın işi: HTTP ucu, kaç satır istediğini bilmeden sonucun kırpılıp kırpılmadığını söyleyemez. Sınırı burada tutup orada bir kez daha yazsaydık, ikisi sessizce ayrışabilirdi.
Variables ¶
var ( // ErrNotFound, aranan kaydın olmadığını söyler. ErrNotFound = errors.New("store: not found") // ErrConflict, benzersizlik kısıtının ihlal edildiğini söyler // (aynı adla ikinci bir kullanıcı, rol, hedef...). ErrConflict = errors.New("store: already exists") // ErrInvalid: değerin kendisi kabul edilebilir değil — çağıranın // yeniden denemesi değil, DÜZELTMESİ gerekiyor. ErrConflict'ten // ayrı, çünkü "zaten var" ile "böyle olamaz" farklı cevaplar // gerektiriyor (409'a karşı 400). ErrInvalid = errors.New("store: invalid value") // ErrAccessDenied: kimlik geçerli ama postern'de karşılığı yok — // JIT sağlamada hiçbir grup role eşleşmediğinde. ErrAccessDenied = errors.New("store: access denied") // ErrIdentityConflict: kullanıcı adı var olan bir hesapla eşleşiyor // ama o hesap BAŞKA bir IdP kimliğine bağlı. // // ErrAccessDenied'dan AYRI TUTULUYOR çünkü ikisi operatöre bambaşka // şeyler söyler. "Grup eşlenmemiş" bir yapılandırma eksiğidir; bu // ise kullanıcı adı geri dönüşümü ya da hesap devralma denemesidir // — incelenmesi gereken bir olay. Tek bir sentinel altında // toplandığında giriş reddi "no mapped groups" diye loglanıyordu ve // olayı araştıran yönetici, düzeltmeyecek bir eşlemeyi düzeltmeye // gönderiliyordu. // // İstemciye giden yanıt İKİSİNDE DE aynı: ayrım yalnızca logda. ErrIdentityConflict = errors.New("store: identity conflict") /* * ErrAdminBindRefused: adı eşleşen bir YÖNETİCİ hesabını, ilk kez * görülen bir kimliğe bağlama denemesi. * * ErrIdentityConflict'ten AYRI, çünkü operatörün yapacağı şey * farklı: orada bir devralma denemesi var ve incelenmeli; burada * meşru bir yönetici de olabilir ve yolu açık — yöneticiliği * geçici olarak kaldırıp bağlaması yeterli. Aynı sentinel altında * toplansaydı, ikisi de "incelenecek olay" diye loglanır ve * gerçekten incelenmesi gereken seyrek olay gürültüye karışırdı. */ ErrAdminBindRefused = errors.New("store: administrator account cannot be claimed by username") /* * ErrAccountNotProvisioned: kimlik doğrulandı, postern hesabı yok ve * hesapların kendiliğinden açılması KAPALI. * * ⚠️ ErrAccessDenied'dan AYRI, çünkü çağıranın yapacağı şey farklı: * orada kapı kapanıyor, burada kişi onay kuyruğuna yazılıyor ve * bunu ekranda görüyor. Tek sentinel altında toplansalardı kuyruk * hiç dolmazdı. */ ErrAccountNotProvisioned = errors.New("store: account does not exist and auto-create is off") /* * ErrAdminPasswordRefused: yönetici hesabına kullanıcı parolası * konmak istendi. * * ⚠️ KURALI VERİTABANI TUTUYOR (göç 026), bu sentinel yalnızca onun * reddini konuşulabilir bir hataya çeviriyor. Burada bir `if` * yazmıyoruz: kural bir kez, kaçınılmaz olduğu yerde duruyor. * * Neden kural: acil durum kapısı tahmin edilebilir bir değere * bağlanamaz. Yönetici hesabının kimlik bilgisi makine üretimi * kalmak zorunda — postern'in "her şey bozulduğunda içeri girilir" * iddiası tam olarak buna dayanıyor. */ ErrAdminPasswordRefused = errors.New("store: an administrator account cannot hold a password") )
var ErrCredentialExists = errors.New("store: account already has a local credential")
ErrCredentialExists, hesabın zaten bir yerel kimlik bilgisi olduğunu söyler.
var ErrTooSlow = errors.New("store: search took too long and was stopped")
ErrTooSlow, arama sunucu tarafı zaman sınırına takıldı.
ErrInvalid DEĞİL: istek biçimsel olarak geçerliydi. Çağıranın söylemesi gereken şey "isteğin hatalı" değil, "bu arama fazla geniş".
Functions ¶
func CleanSearchPath ¶
* CleanSearchPath, ağaç aramasında kullanılacak yolu normalleştirir. * * ⚠️ DIŞARI AÇIK ÇÜNKÜ UÇ, ARANANI YANKILIYOR. Panel sonuçta * "under /etc/" yazıp sorgunun "/etc" ile çalıştığını gizleseydi, * denetçi neyin arandığını yanlış bilirdi — ve "moved here" rozetini * çizen istemci karşılaştırması da normalleştirilmemiş yola bakıp * kayardı. * * Sondaki eğik çizgiler atılıyor; hepsi eğik çizgiyse kök dizin.
func ValidateLabel ¶
ValidateLabel, anahtar/değer çiftini denetler.
DIŞA AÇIK, çünkü hedef yaratma yolu etiketleri hedefi AÇMADAN ÖNCE doğrulamak zorunda: önce açıp sonra etiketi reddetmek, yarısı uygulanmış bir istek bırakırdı.
Types ¶
type AdminHolder ¶
type AdminHolder struct {
Username string `json:"username"`
// Via: "cli", "group" ya da boş. Boş olan, admin_via sütunu
// eklenmeden önce yönetici yapılmış eski bir kayıttır (017 göçü
// mevcutları 'cli' sayıyor, yani pratikte boş kalmaması gerekir).
Via string `json:"via"`
}
AdminHolder, yönetici bayrağını taşıyan kişi ve bayrağın KAYNAĞI.
Kaynağı da taşıması şart: panel "kim yönetici" sorusuna cevap verirken "bunu kim verdi" sorusunu da cevaplamak zorunda. Aksi hâlde grup üzerinden gelen yetki ile acil durum için elle açılmış hesap ekranda ayırt edilemez ve operatör, kaldıramayacağı bir yetkiyi kaldırabileceğini sanır.
type AdminLogEntry ¶
type AdminLogEntry struct {
At time.Time
Actor string // web: oturum sahibi; cli: işletim sistemi kullanıcısı
Via string // "web" | "cli"
Action string // makine-okur: "user.create", "role.grant" ...
Entity string // etkilenen varlık adı
Details string
}
AdminLogEntry, tek bir yönetici işleminin kaydı.
type ArchiveBacklogReport ¶
type ArchiveBacklogReport struct {
Pending int
Oldest time.Time
Failing int
/*
* Lost, dosyası KAYIP olduğu için hiç yüklenemeyecek kayıtların
* sayısı (session_archives.permanent).
*
* ⚠️ Pending'DEN AYRI. Bunları "bekliyor" saymak, hiç bitmeyecek
* bir kuyruk ve sönmeyen bir "disk dolacak" alarmı demekti — oysa
* bu satırlar için yapılacak bir şey yok, yalnızca GÖRÜLMELERİ
* gerekiyor. "Kayıp" ile "bekliyor" operatöre bambaşka şey söyler.
*/
Lost int
}
* ArchiveBacklogReport, yükleme kuyruğunun durumu. * * ⚠️ Failing AYRI SAYILIYOR. "Bekleyen 40" ile "bekleyen 40, 40'ı da * üst üste başarısız" farklı iki durum: birincisi yükleyicinin geride * kalması, ikincisi hiç ilerlemediği. Arşivleyici hatanın kalıcı mı * geçici mi olduğunu zaten hesaplıyordu ama sonucu yalnızca log * cümlesini seçmek için kullanıyordu — operatörün baktığı ekranda bu * ayrım hiç görünmüyordu. * * Eşik ÜÇ: bir geçici kesinti bir iki denemeyi düşürür; üç üst üste * başarısızlık artık "bir şeyi düzeltmen gerekiyor" demektir.
type ArchivePending ¶
type ArchivePending struct {
SessionID string
RecordingPath string
StartedAt time.Time
Attempts int
// Chain ve Links, kaydın zincir başı (göç 034). Yükleyici bunları
// nesnenin üstverisine yazıyor, böylece baş kayıtla AYNI nesnede ve
// aynı saklama süresine tabi duruyor.
//
// Boş olabilir: göç öncesi kapanmış ya da çökme sonrası süpürülmüş
// oturumların zinciri yok. O hâlde üstveri de yazılmıyor — boş bir
// başı yüklemek, doğrulanamayan bir kaydı doğrulanmış göstermenin
// yolu olurdu.
Chain string
Links int64
}
ArchivePending, yüklenmeyi bekleyen bir kayıt.
type ArchiveState ¶
type ArchiveState struct {
Archived bool
ArchivedAt time.Time
Bucket string
ObjectKey string
SHA256 string
SizeBytes int64
Attempts int
LastError string
}
ArchiveState, bir oturumun arşiv durumu.
type Credential ¶
type Credential struct {
Verifier string
// Chosen: değeri KULLANICI seçti (parola). Değilse makine üretimi
// sır (015'in dünyası, acil durum kapısı).
Chosen bool
// MustChange: bir sonraki girişte değiştirilmek zorunda.
MustChange bool
}
* Credential, hesabın yerel kimlik bilgisi. Yoksa ErrNotFound. * * ⚠️ ARTIK DÜZ BİR DİZE DEĞİL. Eskiden yalnızca doğrulayıcı dönüyordu * ve doğruydu: tek bir kimlik bilgisi türü vardı. İki tür olduğu an * çağıranın HANGİ türle karşılaştığını bilmesi şart — yanlış doğrulama * yolunu seçmek, ya kullanıcıyı dışarıda bırakır ya da biçim kontrolünü * atlar. Türü çağıranın tahmin etmesine bırakmak yerine tek sorguda * veriyoruz.
type DirectoryAccount ¶
DirectoryAccount, dizinden kendiliğinden açılacak hesabın girdisi.
type DiscoveredMachine ¶ added in v1.2.0
type DiscoveredMachine struct {
SourceID string
// Source, kaynağın adı (okurken birleştiriliyor).
Source string
Ref string
Name string
Host string
Tags []string
Running bool
Role string
Tagged bool
HostKey string
Problem string
TargetID string
// Target ve TargetHostKey, bağlı hedefin adı ve SABİTLENMİŞ anahtarı
// (okurken birleştiriliyor; yazılmıyor).
Target string
TargetHostKey string
Ignored bool
FirstSeen time.Time
LastSeen time.Time
MissingSince time.Time
}
DiscoveredMachine, bir kaynağın bildirdiği makinenin son hâli.
type DiscoveryRun ¶ added in v1.2.0
type DiscoveryRun struct {
ID int64 `json:"id"`
SourceID string `json:"source_id"`
Trigger string `json:"trigger"`
Actor string `json:"actor"`
StartedAt time.Time `json:"started_at"`
FinishedAt time.Time `json:"finished_at,omitzero"`
Outcome string `json:"outcome"`
Reason string `json:"reason,omitempty"`
Seen int `json:"seen"`
NewMachines int `json:"new_machines"`
Missing int `json:"missing"`
KeyChanged int `json:"key_changed"`
Unreachable int `json:"unreachable"`
}
DiscoveryRun, bir kaynağın tek koşusu.
type DiscoverySource ¶ added in v1.2.0
type DiscoverySource struct {
ID string `json:"id"`
Name string `json:"name"`
Kind string `json:"kind"`
URL string `json:"url"`
Username string `json:"username"`
// SecretSet: kaynağın sırrı kayıtlı mı. Sırrın kendisi burada YOK.
SecretSet bool `json:"secret_set"`
CAPEM string `json:"ca_pem"`
Insecure bool `json:"insecure"`
Node string `json:"node"`
TagKey string `json:"tag_key"`
NamePattern string `json:"name_pattern"`
Port int `json:"port"`
IntervalSeconds int `json:"interval_seconds"`
Enabled bool `json:"enabled"`
CreatedBy string `json:"created_by"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
LastRunAt time.Time `json:"last_run_at,omitzero"`
}
DiscoverySource, panelden kaydedilen bir keşif kaynağı.
type FileQuery ¶
type FileQuery struct {
// Path, aranan yol. Under false ise TAM eşleşme.
Path string
/*
* Under: Path bir DİZİN, altındaki her şey aransın.
*
* ⚠️ SORUŞTURMANIN EN SIK SORDUĞU BU. "/etc altında ne oldu"
* sorusunu tam eşleşmeyle sormak imkânsız; her dosyayı tek tek
* bilmek gerekirdi.
*/
Under bool
// User / Target, olayın oturumundan süzme.
//
// ⚠️ Path'siz de anlamlılar: "ayse ne aldı" ve "web01'de ne oldu"
// soruşturmanın ikinci ve üçüncü sorusu.
User string
Target string
Limit int
}
* FileQuery, dosya geçmişi aramasının ölçütleri. * * ⚠️ EN AZ BİRİ DOLU OLMALI. Üçü birden boşken "her şeyi göster" * demek, sorulmamış bir soruya dolu bir ekranla cevap vermek olurdu — * bu ekranın kaçındığı şeyin ta kendisi.
type FileTouch ¶
type FileTouch struct {
SessionFile
/*
* Birleştirme LEFT JOIN, dolayısıyla bu alanlar boş kalabilir.
*
* ⚠️ BUGÜN BOŞ KALAMIYORLAR: 027'deki yabancı anahtar
* (ON DELETE RESTRICT) oturum satırının silinmesini engelliyor,
* yani her dosya olayının oturumu yerinde. LEFT JOIN yine de
* seçildi çünkü bedeli sıfır ve kısıt bir gün gevşetilirse doğru
* davranışı zaten yapıyor: olayın kendisi kanıt, yanındaki
* üstveriyi okuyamamak onu gizlemenin gerekçesi değil. Panel de
* bu ihtimale göre çiziyor (boş kullanıcıyı satırı yutarak değil,
* işaretleyerek gösteriyor).
*/
User string `json:"user"`
Target string `json:"target"`
OSUser string `json:"os_user"`
SrcIP string `json:"src_ip"`
}
* FileTouch, bir dosya olayı ve onu YAPAN oturumun kimliği. * * ⚠️ OTURUM KİMLİĞİ TEK BAŞINA CEVAP DEĞİL. "/etc/shadow'u kim aldı" * sorusunun cevabı bir UUID değil, bir kişidir; olayları çıplak * session_id'lerle döndürmek, denetçiyi her satır için ayrı bir * sorguya mecbur bırakırdı.
type GroupMapping ¶
GroupMapping, bir dış grubun hangi role karşılık geldiği.
type JITGrant ¶ added in v1.2.0
type JITGrant struct {
ID string `json:"id"`
Username string `json:"username"`
Target string `json:"target"`
OSUser string `json:"os_user"`
Groups []string `json:"groups"`
// Sudo, yalnızca bu hesaba yazılan kural; nil ise yok.
Sudo *sudoers.Rule `json:"sudo,omitempty"`
GrantedBy string `json:"granted_by"`
GrantedAt time.Time `json:"granted_at"`
ExpiresAt time.Time `json:"expires_at"`
// AppliedAt sıfırsa hak hedefe TAM olarak uygulanamadı; rapor sebebi
// söylüyor ve süpürücü kalan ne varsa toplayacak.
AppliedAt time.Time `json:"applied_at,omitzero"`
ApplyReport string `json:"apply_report,omitempty"`
RevokedAt time.Time `json:"revoked_at,omitzero"`
RevokeReport string `json:"revoke_report,omitempty"`
/*
* CreatedGroups, postern'in BU hak için açtığı gruplar. Geri almada
* boş kalanlar silinebiliyor; önceden var olan grup buraya girmiyor
* ve hiç silinmiyor — "postern açtıysa siler" (hesaptaki kanıtın
* grup için karşılığı).
*/
CreatedGroups []string `json:"created_groups"`
// CleanupGroups, geri almada boş kalan açılmış grupları silme izni.
CleanupGroups bool `json:"cleanup_groups"`
/*
* RevokeError, son geri alma denemesinin neden bitmediği; NextAttempt,
* süpürücünün bir daha ne zaman deneyeceği. Sıfırdan farklı bir deneme
* sayısıyla boş bir hata "şu an deneniyor" demek değil — her deneme
* ya revoked_at ya revoke_error yazıyor.
*/
RevokeError string `json:"revoke_error,omitempty"`
RevokeAttempts int `json:"revoke_attempts"`
NextAttempt time.Time `json:"next_attempt,omitzero"`
}
JITGrant, bir hedefte süreli açılmış hesap.
type LocalCredentialHolder ¶
type LocalCredentialHolder struct {
Username string
IsAdmin bool
CreatedAt time.Time
CreatedBy string
LastUsedAt time.Time
// Chosen: değeri kullanıcı seçti (parola), makine üretmedi.
Chosen bool
// MustChange: ilk girişte değiştirilmek zorunda, yani henüz
// kullanılmamış bir "veren de biliyor" değeri.
MustChange bool
/*
* ⚠️ State BURADA OLMAK ZORUNDA.
*
* Ölçülen tutarsızlık: iki ayrı kilitlenme koruması (panelde
* canSwitchTo, CLI'da settings set) "yerel kimlik bilgisi olan bir
* yönetici var" gördüğünde paneli kapatmaya izin veriyor. Ama
* locallogin.go silinmiş hesabı REDDEDİYOR. Yani silinmiş bir
* yönetici, iki korumayı da tatmin edip kimsenin giremediği bir
* panel bırakabiliyordu. Durumu taşımayan bir liste, o soruyu
* cevaplayamaz.
*/
State string
}
LocalCredentialHolder, yerel kimlik bilgisi olan bir hesabın özeti.
type PendingUser ¶
type PendingUser struct {
ID string `json:"id"`
Subject string `json:"subject"`
Source string `json:"source"`
// ⚠️ Username, Email ve SeenGroups YALNIZCA GÖSTERİM. Hiçbir karar
// bunlara bakmıyor: üçü de kaynakta değişebiliyor.
Username string `json:"username"`
Email string `json:"email"`
SeenGroups []string `json:"seen_groups"`
State string `json:"state"`
FirstSeen time.Time `json:"first_seen"`
LastSeen time.Time `json:"last_seen"`
DecidedBy string `json:"decided_by,omitempty"`
DecidedAt time.Time `json:"decided_at,omitzero"`
Reason string `json:"reason,omitempty"`
}
PendingUser, onay bekleyen (ya da reddedilmiş) bir kimlik.
type ProvisionRequest ¶
type ProvisionRequest struct {
// Username, IdP'nin verdiği kullanıcı adı — aynı zamanda hedeflerdeki
// hesap adı olacak (os_user). Kurumsal ortamda "isim.soyisim".
Username string
Email string
// Groups, IdP'nin bildirdiği ham grup adları.
Groups []string
/*
* GroupsResolved, grupların GERÇEKTEN öğrenilip öğrenilmediği.
*
* ⚠️ SIFIR DEĞERİ false VE BU KASITLI. false iken SSO rollerine
* HİÇ DOKUNULMAZ. Alanı doldurmayı unutan bir çağrı yolu, rolleri
* TAZELEMEMİŞ olur — rolleri SİLMİŞ değil. İki yanlıştan geri
* dönülebilir olanı bu.
*
* Neden gerekti: kaynak "kullanıcıyı bulamadım" dediğinde de boş
* bir grup listesi geliyordu ve buradaki kod onu "hiçbir gruba üye
* değil" diye okuyup bütün SSO rollerini siliyordu. Giriş yolunda
* ne bekleme süresi ne tavan var; senkronizasyon döngüsündeki
* korumaların hiçbiri burada çalışmıyor.
*/
GroupsResolved bool
// Issuer ve Subject, IdP kimliğinin KALICI anahtarı (OIDC "iss" ve
// "sub"). Username DEĞİL bunlar eşleştirme anahtarıdır: username
// birçok sağlayıcıda değiştirilebilir ve geri dönüştürülebilir.
// Boş bırakılırsa eşleştirme yapılamaz ve ProvisionUser reddeder.
Issuer string
Subject string
/*
* AdminGroupMember, GELEN KİMLİĞİN kendisinin yönetici grubunda
* olduğu.
*
* ⚠️ Adı bir yöneticiyle eşleşen hesabı devralmanın önündeki kapıyı
* bu açıyor — ve açması doğru: yönetici grubunda olan kişi zaten
* yöneticidir, başka bir yönetici hesabını almakla YENİ bir yetki
* kazanmaz. Kapatsaydık, dizin grubundan yönetici olan herkes
* yükseltmeden sonra kendi hesabına giremezdi.
*
* ⚠️ Çağıran bunu YALNIZCA grupları gerçekten çözülmüşken true
* yapmalı. Sıfır değeri false ve bu kasıtlı: alanı doldurmayı
* unutan bir yol, kapıyı AÇMIŞ değil KAPATMIŞ olur.
*/
AdminGroupMember bool
/*
* AutoCreate, hesabın KENDİLİĞİNDEN açılabileceği.
*
* ⚠️ Sıfır değeri false ve bu kasıtlı: alanı doldurmayı unutan bir
* çağrı yolu hesap AÇMAZ, açar değil. İki yanlıştan geri
* dönülebilir olanı bu.
*
* Kapalıyken kullanıcı ErrAccountNotProvisioned alıyor ve çağıran
* onu onay kuyruğuna yazıyor — kapıda bırakmıyor.
*/
AutoCreate bool
}
ProvisionRequest, JIT sağlama için kimlik sağlayıcıdan gelen bilgi.
type PurgeResult ¶
PurgeResult, purge'ün neyi serbest bıraktığı.
type PurgedAccount ¶
PurgedAccount, purge edilmiş bir kaydın izi.
type RoleSudo ¶ added in v1.2.0
type RoleSudo struct {
Role string `json:"role"`
Rule sudoers.Rule `json:"rule"`
UpdatedBy string `json:"updated_by"`
UpdatedAt time.Time `json:"updated_at"`
}
RoleSudo, bir rolün sudo kuralı ve onu en son kimin yazdığı.
type SessionFile ¶
type SessionFile struct {
ID string `json:"id"`
SessionID string `json:"session_id"`
At time.Time `json:"at"`
Op string `json:"op"`
Path string `json:"path"`
NewPath string `json:"new_path,omitempty"`
Flags string `json:"flags,omitempty"`
Read int64 `json:"read"`
Wrote int64 `json:"wrote"`
OK bool `json:"ok"`
Detail string `json:"detail,omitempty"`
/*
* InRecording, bu olayın oturum KAYDINA da yazıldığı ve kaydın
* mühür satırında sayıldığı.
*
* ⚠️ NEDEN SATIRIN ÜSTÜNDE TAŞINIYOR. Mühürdeki sayı ile buradaki
* satır sayısını karşılaştıran kontrol (verify.JournalOf), hangi
* satırın mühürde sayıldığını BİLMEK zorunda: bu tabloya kanal
* düzeyindeki ret defteri de yazıyor (proxy/lifecycle.go) ve o
* satırların kayıtta karşılığı yok. Ayrımı `op` dizgesinden tahmin
* etmek, x11 isteği reddedilmiş her SFTP oturumunu yanlış alarma
* çevirirdi — ikisi de "denied." önekini kullanıyor.
*/
InRecording bool `json:"in_recording"`
}
SessionFile, bir oturumda gerçekleşen tek bir dosya olayı.
type SessionStart ¶
type SettingView ¶
type SettingView struct {
Key string
Value string // şifreliyse maskeli
Secret bool
UpdatedAt time.Time
UpdatedBy string
}
SettingView, listeleme için ayar görünümü.
type StaleAccount ¶
type StaleAccount struct {
Username string
State string
Confirmed time.Time
SSOOnly bool
DirBound bool
ManualRoles int
}
StaleAccount, süresi dolmuş bir hesabın özeti.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
func (*Store) AccountID ¶
* AccountID, adı verilen hesabın kimliğini (users.id) döner. * * ⚠️ Panel oturumu bu KİMLİĞE bağlanıyor, ada değil. Ad yeniden * kullanılabiliyor (purge onu serbest bırakıyor); kimlik kalıcı. Oturum * ada bağlı kalırsa, adı devralan yeni kişiye çözülüyor.
func (*Store) AccountState ¶
func (s *Store) AccountState(ctx context.Context, username string) (state string, confirmed time.Time, err error)
AccountState, hesabın durumu ve son doğrulanma anı.
func (*Store) ActiveJITGrantsForUser ¶ added in v1.2.0
ActiveJITGrantsForUser, kişinin hâlâ açık hakları — silme öncesi bakılan liste.
func (*Store) AddGroupMapping ¶
AddGroupMapping, dış grubu role bağlar. Rol yoksa ErrNotFound; aynı eşleme ikinci kez eklenirse ErrConflict.
func (*Store) AddLocalCredential ¶
* AddLocalCredential, hesaba yerel kimlik bilgisi bağlar. * * ⚠️ ÜSTÜNE YAZMAZ. Var olan bir kimlik bilgisini sessizce * değiştirmek, komutu ikinci kez çalıştıran operatörün ELİNDEKİ sırrı * geçersiz kılardı — üstelik o an ekranda yeni bir sır gördüğü için * bunu fark etmeden. Daha kötüsü: kurulumun tek yöneticisinin kimlik * bilgisini, yazma yetkisi olan herkes böylece döndürebilirdi. * Değiştirmek istiyorsa açık bir komut kullanır.
func (*Store) AddPublicKey ¶
func (*Store) AddSessionFiles ¶
* AddSessionFiles, bir grup olayı TEK transaction'da yazar. * * ⚠️ Toplu yazım şart: rsync gibi bir istemci binlerce küçük dosyaya * dokunur ve olay başına ayrı gidiş-dönüş, denetimi transferin hız * sınırı hâline getirirdi. Denetimi yavaşlatmak, onu kapatma isteği * doğurur. * * Ya hepsi yazılır ya hiçbiri: yarım yazılmış bir grup, "dosya açıldı * ama hiç kapanmadı" gibi görünen uydurma bir denetim satırı bırakırdı.
func (*Store) AddWebAuthnCredential ¶ added in v1.2.0
func (s *Store) AddWebAuthnCredential(ctx context.Context, username string, c WebAuthnCredential) error
AddWebAuthnCredential, doğrulanmış bir anahtarı hesaba bağlar.
func (*Store) AdminVia ¶
AdminVia, yönetici yetkisinin kaynağını döner: "cli", "group" ya da boş (yönetici değil).
func (*Store) Admins ¶
func (s *Store) Admins(ctx context.Context) ([]AdminHolder, error)
Admins, yönetici bayrağı taşıyan herkesi kaynağıyla döner.
func (*Store) AllTargetFacts ¶
AllTargetFacts, hedef adı → gözlemler.
TEK SORGU: hedef başına ayrı sorgu, ana ekranı çizerken kullanıcının erişebildiği her hedef için bir gidiş dönüş demekti (N+1). Etiketlerde aynı gerekçeyle allTargetLabels var.
func (*Store) AllowIdentityBind ¶
AllowIdentityBind, bir yönetici hesabının SIRADAKİ kimlik bağlamasına izin verir. Tek kullanımlık.
func (*Store) ApplyAdminGroup ¶
func (s *Store) ApplyAdminGroup(ctx context.Context, members []string) (granted, revoked []string, err error)
* ApplyAdminGroup, grup üzerinden yönetici kümesini TEK İŞLEMDE eşitler. * * ⚠️ NEDEN "bir sonraki girişte" DEĞİL, ŞİMDİ: * * Yetki eskiden yalnızca kişi giriş yaptığında güncelleniyordu. Bu, * yönetici grubu DEĞİŞTİĞİNDE sessiz bir sızıntı bırakıyor: eski gruptan * gelen kişi bir daha hiç giriş yapmasa da yönetici KALIYOR. "Grubu * değiştirdim" ile "yetki değişti" arasındaki fark, kimsenin bakmadığı * bir yerde süresiz açık duruyordu. * * Ayrıca onay ekranını dürüst yapan şey bu: ekran "bu kişiler yönetici * oluyor" diyorsa, kaydettikten sonra gerçekten öyle olmalı — "herkes * bir dahaki girişinde" değil. * * members'ın DB'de karşılığı olmayanları ATLANIR (hata değil): dizinde * var ama postern'e hiç girmemiş kişinin hesabı yok. İlk girişinde * applyGroupAdmin onu zaten yakalar. * * CLI'ın verdiği yöneticiliğe DOKUNMAZ — ne verirken ne alırken.
func (*Store) ApprovePending ¶
* ApprovePending, hesabı AÇAR ve kimliği bağlar. * * ⚠️ ROL VERMİYOR. Roller kişinin bir sonraki girişinde CANLI kaynaktan * çözülüyor; kuyruktaki grup listesi onay ekranında ne görüldüğünü * gösteriyor, bir yetki kaydı değil. Bayat bir fotoğrafa göre rol * yazmak, yetkiyi geçmişe bağlamak olurdu. * * Hesap ve bağ AYNI transaction'da: arada kalan bir hata, kimliği * bağlanmamış bir hesap bırakır ve o hesap sonra ADLA devralınabilir * hâle gelirdi.
func (*Store) ArchiveBacklog ¶
func (s *Store) ArchiveBacklog(ctx context.Context) (b ArchiveBacklogReport, err error)
ArchiveBacklog, bekleyen kayıt sayısı ve EN ESKİSİNİN yaşı.
⚠️ YAŞ, SAYIDAN DAHA ÖNEMLİ. Ölmüş bir yükleyicinin belirtisi "sayı artıyor" değil, "en eskisi yaşlanıyor": sabit bir sayı da hiçbir şeyin ilerlemediği anlamına gelebilir.
func (*Store) ArchiveStateOf ¶
ArchiveStateOf, panelin gösterdiği durum.
func (*Store) ArchivedIDs ¶
* ArchivedIDs, verilen oturumlardan HANGİLERİNİN doğrulanmış şekilde * arşivlendiğini döner. * * ⚠️ BUDAYICININ KAPISI BU ve varsayılan REDDETME: dönen kümede * OLMAYAN her kimlik "silme" demek. Sorgu hata verirse çağıran koşuyu * iptal ediyor — hiçbir şey silmeden. "Çözemedim" ile "güvende" aynı * şey değil ve burada karıştırmanın bedeli kanıtın yok olması.
func (*Store) AssignRole ¶
func (s *Store) AssignRole(ctx context.Context, username, roleName string, expiresAt time.Time) error
AssignRole, kullanıcıya ELLE rol verir (source='manual').
expiresAt sıfır ise süresiz. Zaten verilmiş bir rolü tekrar vermek hata değil — ama artık tam olarak no-op da değil: expires_at GÜNCELLENİR, çünkü "bu yetkiyi uzat" doğal bir istek ve ayrı bir komut gerektirmesi için sebep yok.
Kullanıcı ya da rol yoksa ErrNotFound.
func (*Store) BeginTOTP ¶
* BeginTOTP, kayıt başlatır (ya da BAŞTAN başlatır). * * ⚠️ Doğrulanmış bir kaydın üzerine YAZMIYOR. Yazsaydı, oturumu çalınan * bir hesapta saldırgan kaydı sıfırlayıp kendi telefonunu bağlar ve * ikinci faktör sessizce el değiştirirdi. Doğrulanmış kaydı değiştirmek * ancak önce onu kapatmakla (DisableTOTP, kod ister) mümkün.
func (*Store) BindDirIdentity ¶
* BindDirIdentity, bir postern hesabını bir dizin kimliğine bağlar. * * ⚠️ YALNIZCA HENÜZ BAĞLI DEĞİLSE (`dir_subject IS NULL`). Var olan bir * bağı sessizce değiştirmek, tam olarak önlenmeye çalışılan devralmayı * geri getirirdi — 011'in BindIdPSubject'teki aynı kuralı. * * Zaten başka bir kimliğe bağlıysa ErrConflict; başka bir HESAP o * kimliği tutuyorsa benzersiz indeks ihlali yine ErrConflict'e çevrilir. * İki durum da "buradan devam etme" demek.
func (*Store) BindIdPSubject ¶
BindIdPSubject, bir postern hesabını bir IdP kimliğine bağlar.
SADECE HENÜZ BAĞLI DEĞİLSE: WHERE koşulu idp_subject IS NULL. Var olan bir bağı sessizce değiştirmek, tam olarak önlemeye çalıştığımız devralmayı geri getirirdi. Zaten bağlıysa ErrConflict.
func (*Store) ClaimArchives ¶
func (s *Store) ClaimArchives(ctx context.Context, limit int, now time.Time, claimTimeout, retryAfter time.Duration) ([]ArchivePending, error)
* ClaimArchives, yüklenecek işleri üstlenir. * * ⚠️ ÜSTLENME ZAMAN AŞIMIYLA SERBEST KALIYOR, temizlikle değil. * Öldürülen bir süreç hiçbir şey temizleyemez; claimed_at'i eski olan * satırı yeniden üstlenilebilir saymak, yeniden başlatmadan sonra işin * kendiliğinden devam etmesinin tek yolu. * * ⚠️ GERİ ÇEKİLME last_attempt_at ÜZERİNDEN: az önce denenmiş ve * başarısız olmuş bir satırı hemen yeniden almak, kesinti sırasında * depoyu ve log'u boğardı. * * ⚠️ GERİ ÇEKİLME ÜSTEL — VE SABİTTİ. Her başarısız satır her turda * yeniden alınıyordu; arşivleyici hatanın kalıcı mı geçici mi olduğunu * HESAPLIYOR (objstore.ErrTransient) ama sonucu yalnızca log cümlesini * seçmek için kullanıyordu. Yanlış yazılmış bir kova adı ya da * reddedilen bir imza, düzeltilene kadar her turda yeniden denenip * log'u dolduruyordu — ve içindeki gerçek, geçici arızayı görünmez * yapıyordu. * * attempts ile katlanıyor, altıncıda duruyor: retryAfter=1dk ile * 1, 2, 4, 8, 16, 32, 64 dakika. Kalıcı olarak "vazgeçildi" diye * işaretlemiyoruz ve bu bilinçli — operatör kovayı düzelttiğinde * yeni bir komut çalıştırmak zorunda kalmasın; sıra kendiliğinden * ilerlesin.
func (*Store) ClaimByVerifiedEmail ¶
func (s *Store) ClaimByVerifiedEmail(ctx context.Context, email, issuer, subject string, adminGroupMember bool) (model.User, error)
* ClaimByVerifiedEmail, giriş yollarının E-POSTA dalı için: hesabı * bulur ve aynı kapıdan geçirir. * * ⚠️ ProvisionUser KULLANILAMAZ, çünkü o gruplar çözülemediğinde * REDDEDİYOR — ve haklı: yeni bir hesap açıp açmamaya karar verecek * bilgi yok. Ama burada hesap ZATEN VAR; verilecek karar "bu kimlik bu * hesabı alabilir mi", ve o karar gruplara bağlı değil.
func (*Store) ClaimDiscoverySource ¶ added in v1.2.0
func (s *Store) ClaimDiscoverySource(ctx context.Context, id string, now, dueBefore time.Time) (bool, error)
* ClaimDiscoverySource, zamanı gelmiş kaynağın koşusunu SAHİPLENİR: * last_run_at ancak hâlâ dueBefore'dan eskiyse ilerliyor. İki bastion * aynı veritabanını paylaşıyorsa aynı dakikada ikisi birden koşturmasın.
func (*Store) ClearTOTPFailures ¶ added in v1.2.0
* ClearTOTPFailures, sayacı sıfırlar ve ÖNCEKİ değeri döndürür. * * ⚠️ ÖNCEKİ DEĞER DÖNMEK ZORUNDA. Kullanıcıya "son girişinizden bu yana N * başarısız deneme oldu" diyebilmemizin tek yolu bu; ayrı bir okuma * yapsaydık araya giren bir deneme sayıyı değiştirebilirdi ve kullanıcıya * yanlış bir sayı gösterirdik.
func (*Store) CloseOrphanSessions ¶
func (s *Store) CloseOrphanSessions(ctx context.Context, at time.Time) (closed, queued int64, err error)
* CloseOrphanSessions, açılışta sahipsiz kalmış oturum satırlarını kapatır. * * ⚠️ ÖLÇÜLEN ARIZA: postern SIGKILL alırsa (çökme, güç kesintisi, * `kill -9`) açık oturumların ended_at'i SONSUZA DEK NULL kalıyor. * Ölçüldü: bir oturum açıkken süreç öldürülüp yeniden başlatıldıktan * sonra satır hâlâ açıktı. Panel onu süresiz "çalışıyor" gösteriyor. * Kesme düğmesi bunu pasif bir görüntü hatasından aktif bir yalana * çeviriyordu: yönetici var olmayan bir oturumu kesmeye çalışırdı. * * ⚠️ YENİ BAŞLAYAN SÜREÇ HİÇBİR OTURUMA SAHİP DEĞİLDİR — kuralın * dayandığı tek önerme bu ve TEK DÜĞÜM varsayımıyla geçerli. İkinci bir * postern aynı veritabanına bağlıysa bu çağrı ONUN canlı oturumlarını * kapatır. 1.0 tek düğüm olduğu için kabul ediliyor; belgelerde * "bilinen sınırlar" altında yazılı. * * ⚠️ SATIR SİLİNMİYOR, KAPATILIYOR. Denetim izi kalmalı: "ne zaman * bittiğini bilmiyoruz" ile "hiç olmadı" ayrı şeyler. ended_at * açılış anı — gerçek bitişten sonra, yani süre OLDUĞUNDAN UZUN * görünebilir; bu yüzden çağıran kaç satır kapandığını LOG'A yazmalı.
func (*Store) ConfirmAccount ¶
* ConfirmAccount, kaynağın bu kişiyi ŞU AN doğruladığını kaydeder. * * ⚠️ HER BAŞARILI GİRİŞTE çağrılmalı — OIDC, dizin, hepsi. Zaman * temelli iptalin tek girdisi bu damga; koyulmayan bir kapı, o kapıdan * girenleri yavaş yavaş pasifleştirirdi. * * ⚠️ VE HESABI GERİ AKTİF EDİYOR. Pasifleşme "kaynak bunu bir süredir * doğrulamadı" demek; kaynak yeniden doğruladığı anda sebep ortadan * kalkıyor. Elle müdahale gerektirseydi, tatilden dönen herkes * yöneticiye başvururdu. * * 'deleted' hesap KENDİLİĞİNDEN geri gelmiyor: orada bir insan kararı * var (ya da uzun bir sessizlik) ve onu bir girişin sessizce bozması * doğru olmaz.
func (*Store) ConfirmTOTP ¶
* ConfirmTOTP, kaydı DOĞRULANMIŞ işaretler. * * Yalnızca doğrulanmamış bir kayıt onaylanabilir: ikinci bir onay * çağrısı, kullanılmış bir adımı geri açmamalı.
func (*Store) CreateDiscoverySource ¶ added in v1.2.0
func (s *Store) CreateDiscoverySource(ctx context.Context, d DiscoverySource, secret string) (string, error)
CreateDiscoverySource, kaynağı sırrı mühürlenmiş olarak yazar.
func (*Store) CreateFromDirectory ¶
* CreateFromDirectory, dizin kimliğinden hesap açar ve BAĞLAR. * * ⚠️ ROL EŞLEMESİ KAPIDA. Hiçbir grup bir role eşleşmiyorsa hesap * AÇILMIYOR (ErrAccessDenied). Bu, OIDC yolundaki ProvisionUser'ın * aynı sözleşmesi: "IdP'de hesabın olması postern'de hesabın olması * demek değil" kuralının otomatik açılıştaki karşılığı. Onsuz users * tablosu, hiçbir yere erişemeyen kayıtlarla dizinin kopyasına * dönüşürdü. * * ⚠️ Hesap ve bağ AYNI transaction'da: bağlanmamış bir hesap, adla * devralınabilir bir hesaptır.
func (*Store) CreateJITGrant ¶ added in v1.2.0
* CreateJITGrant, hakkı UYGULAMADAN ÖNCE yazar ve kimliğini döner. * * ⚠️ ÖNCE SATIR, SONRA MAKİNE. Uygulama ortasında süreç ölürse hedefte * yarım bir hesap kalır; satır yoksa süpürücünün onu bulacağı bir şey de * yoktur. applied_at boş bir satır "hedefte ne olduğu bilinmiyor" demek * ve süresi dolmuş sayılıyor.
func (*Store) CreateRole ¶
func (*Store) CreateTarget ¶
func (*Store) CreateUser ¶
func (*Store) DeleteDiscoverySource ¶ added in v1.2.0
DeleteDiscoverySource, kaynağı siler ve adını döner. Koşuları ve makine satırları onunla gidiyor; hedefler KALIYOR.
func (*Store) DeleteRole ¶
DeleteRole: rolün bağları (user_roles, role_targets) CASCADE ile gider; sessions rolü referanslamadığı için 787 bu yoldan çıkmaz — kontrol yine de duruyor, şema yarın değişirse sessizce yanlış hataya düşmeyelim.
func (*Store) DeleteRolePath ¶ added in v1.2.0
DeleteRolePath, bir yol kuralını kaldırır.
func (*Store) DeleteRoleSudo ¶ added in v1.2.0
* DeleteRoleSudo, rolün kuralını siler. * * ⚠️ HEDEFTEKİ DOSYA BUNUNLA GİTMİYOR. Kural postern'de siliniyor; * makinelerdeki /etc/sudoers.d/postern-<rol> dosyası postern o hedefe bir * daha dokunana kadar duruyor. Sessiz kalmıyoruz: çağıran bunu operatöre * söylüyor, çünkü "sildim" demek yetkinin kalktığı anlamına gelmiyor.
func (*Store) DeleteSetting ¶
Setting, tek bir ayarı döner; şifreliyse çözer. Yoksa ErrNotFound.
Anahtar yapılandırılmamışken şifreli bir ayara dokunmak AÇIK hata verir: boş string dönmek sırrı silinmiş gibi gösterir ve LDAP'ın parolasız bağlanmaya çalışmasına yol açardı. DeleteSetting, bir ayarı siler. Yoksa ErrNotFound.
Sır düşürmek için var: LDAP adresi değişince saklanan bind parolası düşürülüyor (bkz. httpapi.adminSetSetting). Değeri boşa çekmek yerine SATIRI silmek gerekiyor — boş bir değer "ayarlanmış ama boş" demek ve LoadConfig onu farklı yorumluyor.
func (*Store) DeleteTarget ¶
DeleteTarget, hedefi ve rol bağlarını (CASCADE) kaldırır. Yoksa ErrNotFound; oturum kaydı varsa ErrConflict — denetim kaydı olan varlık silinmez, bu bir kısıt değil özellik (ayrıntı: isFKRestrict).
func (*Store) DeleteTargetLabel ¶
DeleteTargetLabel, etiketi kaldırır. Yoksa ErrNotFound.
func (*Store) DeleteUser ¶
DeleteUser: kullanıcıyı, bağlarını ve anahtarlarını kaldırır. Oturum kaydı olan kullanıcı için ErrConflict. Erişimi kesmenin doğru yolu zaten silmek değil: anahtarlarını ve rollerini almak — kayıt kalır, kapı kapanır.
func (*Store) DeleteWebAuthnCredential ¶ added in v1.2.0
* DeleteWebAuthnCredential, bir anahtarı hesaptan kaldırır. * * ⚠️ SON ANAHTAR SİLİNİRKEN "yalnızca anahtar" KİLİDİ DE AÇILIYOR. * Aksi hâlde hesap, kabul edeceği hiçbir faktörü olmayan bir duruma * düşerdi: kod kapalı, anahtar yok. O durumdan çıkmanın tek yolu * yönetici olurdu ve kullanıcı bunu kendi eliyle, tek tıkla yapardı.
func (*Store) DirSubjectOf ¶
DirSubjectOf, hesabın bağlı olduğu dizin kimliğini döner; bağlı değilse boş dize.
func (*Store) DisableTOTP ¶
DisableTOTP, ikinci faktörü kaldırır.
func (*Store) DiscoveredMachine ¶ added in v1.2.0
func (s *Store) DiscoveredMachine(ctx context.Context, sourceID, ref string) (DiscoveredMachine, error)
DiscoveredMachine, tek makine.
func (*Store) DiscoveredMachines ¶ added in v1.2.0
func (s *Store) DiscoveredMachines(ctx context.Context, sourceID string) ([]DiscoveredMachine, error)
DiscoveredMachines, bulunan makineler; sourceID boşsa bütün kaynaklar.
func (*Store) DiscoveryRuns ¶ added in v1.2.0
func (s *Store) DiscoveryRuns(ctx context.Context, sourceID string, limit int) ([]DiscoveryRun, error)
DiscoveryRuns, kaynağın koşuları, en yeni önce.
func (*Store) DiscoverySource ¶ added in v1.2.0
DiscoverySource, tek kaynak.
func (*Store) DiscoverySourceSecret ¶ added in v1.2.0
DiscoverySourceSecret, kaynağın sırrını AÇIK olarak döner — yalnızca koşunun hipervizöre bağlanması için.
func (*Store) DiscoverySources ¶ added in v1.2.0
func (s *Store) DiscoverySources(ctx context.Context) ([]DiscoverySource, error)
DiscoverySources, kaynaklar ada göre sıralı.
func (*Store) DueJITGrants ¶ added in v1.2.0
* DueJITGrants, süresi dolmuş, geri alınmamış ve yeniden deneme zamanı * gelmiş hakları döner — süpürücünün her turda sorduğu soru.
func (*Store) EndSession ¶
func (*Store) ExpireJITGrant ¶ added in v1.2.0
ExpireJITGrant, hakkı ŞİMDİ süresi dolmuş sayar: elle geri alma bunu yazıp geri alma yolunu çağırıyor, böylece elle ve otomatik geri alma aynı koddan geçiyor.
func (*Store) FailedRevokes ¶ added in v1.3.0
* FailedRevokes, geri alınamamış haklar — süresi dolmuş ama hedefteki * hesabı hâlâ duran kayıtlar. * * ⚠️ SINIRSIZ VE KENDİ SORGUSU, JITGrants'ın SÜZÜLMÜŞ HÂLİ DEĞİL. Liste * en yeniden eskiye sıralı ve sınırlı; geri alması aylardır düşen bir * hak, üstüne binen yeni haklarla o sınırın altına kayar ve tam da en * çok bakılması gereken kayıt görünmez olurdu. Sayı zaten küçük: burada * bir satır olması, bir makinede fazladan bir hesap durması demek.
func (*Store) FileHistory ¶
* FileHistory, ölçütlere uyan dosya olaylarını en yeniden eskiye döner. * * Soruşturmanın sorusu bu: "/etc/shadow'u kim aldı". Oturumdan dosyaya * bakan bir arayüz bu soruyu cevaplayamaz — soruşturma dosyayı bilir, * oturumu bilmez. * * ⚠️ HEDEF YOLA DA BAKIYOR. Bir dosya bir yere rename ile gelmiş * olabilir ve o satırda aranan yol `path`te değil `new_path`te durur. * Yalnızca `path`e bakan bir arama, "/tmp/exfil buraya nereden geldi" * sorusuna "hiç dokunulmamış" cevabını verirdi — dosyayı oraya taşıyan * satır elimizdeyken. * * ⚠️ BOŞ ÖLÇÜT REDDEDİLİYOR — VE SEBEBİ ÖLÇÜLDÜ. Yalnızca yol * korumasını kaldırıp denedik: sorgu boş bir yol için BOŞ LİSTE * dönüyor (`new_path <> ”` koşulu, satırların çoğundaki boş * new_path'in eşleşmesini engelliyor). Yani tehlike rastgele bir liste * değil, boş bir liste: hiç sorulmamış bir soru "bu dosyaya * dokunulmamış" diye cevaplanmış görünürdü. * * ⚠️ ZAMAN SINIRLI ÇALIŞIYOR (searchtimeout.go). Ölçütler dışarıdan * geliyor ve havuzu SSH girişleri paylaşıyor.
func (*Store) FinishDiscoveryRun ¶ added in v1.2.0
func (s *Store) FinishDiscoveryRun(ctx context.Context, r DiscoveryRun) error
FinishDiscoveryRun, koşu satırını sonucuyla kapatır.
func (*Store) FinishSyncRun ¶
FinishSyncRun, koşuyu sonuçlandırır.
Satır 'failed' olarak AÇILIYOR ve burada güncelleniyor: süreç ortasında ölürse kayıt "başarılı" değil "başarısız" kalır — sessizce başarılı görünen bir yarım koşu, olmayan bir senkronizasyona güvenilmesi demek olurdu.
func (*Store) FirstKeyAdded ¶
* FirstKeyAdded, hesabın ilk anahtarını EKLEMİŞ olup olmadığı. * * ⚠️ SAYIYA DEĞİL DAMGAYA BAKIYOR. "Şu an anahtarı var mı" diye sorsaydık * sil-ve-ekle kuralı tamamen atlardı: oturumu ele geçiren kişi mevcut * anahtarı siler, sayaç sıfırlanır, yeni anahtarı bedavaya ekler. Damga * bir kez konuyor ve bir daha kalkmıyor.
func (*Store) ForgetPending ¶
ForgetPending, satırı tamamen siler — reddi geri almanın yolu.
Var olması şart: yanlışlıkla reddedilen biri, aksi hâlde bir daha hiç başvuramazdı.
func (*Store) GrantTarget ¶
func (*Store) GroupMappings ¶
func (s *Store) GroupMappings(ctx context.Context) ([]GroupMapping, error)
GroupMappings, tüm eşlemeleri grup adına göre sıralı döner.
func (*Store) HasIdPIdentity ¶
HasIdPIdentity, hesabın bir OIDC kimliğine bağlı olup olmadığı.
hasIdPIdentity'nin dışa açık eşi: sihirbaz "bu yönetici kaynağı çevirince kendini kilitler mi" sorusunu buradan soruyor.
func (*Store) JITGrants ¶ added in v1.2.0
JITGrants, bütün hedeflerdeki hakları yeniden eskiye döner — panelin geçici erişim sekmesi "kimin nerede açık hesabı var" sorusunu tek ekranda cevaplıyor.
func (*Store) JITGrantsForTarget ¶ added in v1.2.0
func (s *Store) JITGrantsForTarget(ctx context.Context, target string, limit int) ([]JITGrant, error)
JITGrantsForTarget, bir hedefin haklarını yeniden eskiye döner.
func (*Store) LatestDiscoveryRuns ¶ added in v1.2.0
LatestDiscoveryRuns, her kaynağın son koşusu.
func (*Store) LinkDiscoveredMachine ¶ added in v1.2.0
LinkDiscoveredMachine, makineyi kaydedildiği hedefe bağlar.
func (*Store) ListPending ¶
func (s *Store) ListPending(ctx context.Context) ([]PendingUser, error)
ListPending, kuyruğu döner (bekleyenler önce, en yeni başta).
func (*Store) LocalCredential ¶
LocalCredential, hesabın kimlik bilgisini döner. Yoksa ErrNotFound.
func (*Store) LocalCredentialHolders ¶
func (s *Store) LocalCredentialHolders(ctx context.Context) ([]LocalCredentialHolder, error)
* LocalCredentialHolders, yerel kimlik bilgisi olan hesapları döner. * * ⚠️ GÖRÜNÜRLÜK BİR GÜVENLİK ÖZELLİĞİ. Bu hesaplar bir acil durum * kapısı ve kullanılmayan bir acil durum kapısı unutulmuş bir kapıdır. * Operatörün "kimlerde var, en son ne zaman kullanıldı" sorusunu * veritabanına girmeden cevaplayabilmesi gerekiyor.
func (*Store) LogAdmin ¶
func (s *Store) LogAdmin(ctx context.Context, e AdminLogEntry) error
LogAdmin, bir yönetici işlemini deftere yazar (sıfır At damgalanır).
Çağıran, işlemi BAŞARIYLA bitirdikten sonra çağırır — başarısız denemeler HTTP log'unda zaten var; defter, "ne değişti"nin kaydı.
func (*Store) MarkArchiveFailed ¶
func (s *Store) MarkArchiveFailed(ctx context.Context, sessionID, reason string, permanent bool, at time.Time) error
MarkArchiveFailed, denemeyi ve sebebini kaydeder.
archived_at'e DOKUNMUYOR: bir kez doğrulanmış kayıt, sonradan gelen bir hata yüzünden "güvende değil"e dönmemeli.
⚠️ permanent: bu kayıt hiç yüklenemeyecek (ör. dosyası yok). true ise satır candidate kümesinden çıkıyor; yoksa her turda yeniden claim edilip kuyruğu ve "disk dolacak" alarmını sonsuza dek meşgul ederdi.
func (*Store) MarkArchived ¶
func (s *Store) MarkArchived(ctx context.Context, sessionID, bucket, key, sha string, size int64, at time.Time) error
* MarkArchived, yüklemenin DOĞRULANDIĞINI kaydeder. * * ⚠️ SIRA: yükle → deponun kendisine sor → BURAYA yaz → budayıcıya * silme izni doğ. Bu satır atıldığı andan itibaren kayıt yerelden * silinebilir hâle geliyor, dolayısıyla "gönderdim" ile "orada" * arasındaki farkı burada kapatmak zorundayız.
func (*Store) MarkDirectoryMissing ¶
MarkDirectoryMissing, kullanıcının bulunamadığını kaydeder.
COALESCE: kayıp saati YALNIZCA henüz kurulmamışsa kuruluyor. Her koşuda üzerine yazmak, grace penceresini gerçek bir saat olmaktan çıkarıp hiç dolmayan bir sayaca çevirirdi.
func (*Store) MarkDirectorySeen ¶
MarkDirectorySeen, kullanıcının dizinde bulunduğunu kaydeder ve kayıp saatini SIFIRLAR.
func (*Store) MarkDiscoveredMachineMissing ¶ added in v1.2.0
func (s *Store) MarkDiscoveredMachineMissing(ctx context.Context, sourceID, ref string, now time.Time) error
MarkDiscoveredMachineMissing, kaynağın artık bildirmediği makineyi işaretler; satır ve hedef kalıyor.
func (*Store) MarkFirstKeyAdded ¶
MarkFirstKeyAdded, damgayı koyar. Zaten varsa DOKUNMAZ — ilk anahtarın anı, sonradan eklenenlerle kaymamalı.
func (*Store) MarkJITGrantApplied ¶ added in v1.2.0
func (s *Store) MarkJITGrantApplied(ctx context.Context, id string, ok bool, report string, now time.Time) error
* MarkJITGrantApplied, uygulamanın sonucunu yazar. * * ⚠️ TAM UYGULANAMAYAN HAK HEMEN DÜŞÜYOR: expires_at şu ana çekiliyor, * süpürücü yarım kalanı ilk turunda toplayacak. Yarım bir hesabı istenen * süre boyunca makinede bırakmak, kimsenin onaylamadığı bir erişim * bırakmak olurdu.
func (*Store) MarkJITGrantRevokeFailed ¶ added in v1.2.0
func (s *Store) MarkJITGrantRevokeFailed(ctx context.Context, id, reason string, next time.Time) error
* MarkJITGrantRevokeFailed, geri almanın bitmediğini ve bir sonraki * denemeyi yazar. * * ⚠️ HATA SİLİNMİYOR, ÜSTÜNE YAZILIYOR. Panel "geri alma X'ten beri * başarısız" diyebilmeli; başarısız denemeyi sessizce ertelemek, süresi * dolmuş bir root hesabını kimsenin görmediği bir yerde açık bırakırdı.
func (*Store) MarkJITGrantRevoked ¶ added in v1.2.0
MarkJITGrantRevoked, hesabın hedeften gittiğini yazar.
func (*Store) MarkSFTPJournal ¶ added in v1.2.0
* MarkSFTPJournal, oturum kapanırken defterin durumunu yazar. * * ⚠️ SetRecordingChain'DEN AYRI, VE AYNI GEREKÇEYLE. Zincir başı gibi * bu da yalnızca broker'ın Run'ı döndükten sonra bilinebiliyor; ikisini * EndSession'a katmak, çökme sonrası süpürmenin (CloseOrphanSessions) * elinde olmayan bir sayıyı yazmasını gerektirirdi. O yolda mühür * sayısı YOK ve olmaması doğru: kaydı kapatan süreç ölmüş, kaç olay * saydığını kimse bilmiyor. * * ⚠️ BAŞARISIZLIĞI OTURUMU DÜŞÜRMÜYOR — oturum zaten bitti. Yazılamayan * bir işaret o oturumun defterini DOĞRULANAMAZ yapar (Measured false), * ama var olan hiçbir satırı bozmaz. Çağıran hatayı Error olarak * log'luyor: sessiz kalmak, kontrolün neden çalışmadığını sonradan * anlaşılamaz kılardı.
func (*Store) OpenSessions ¶
* OpenSessions, bitişi kaydedilmemiş bütün oturumları döner. * * ⚠️ AYRI BİR SORGU, Sessions(...200) ÜZERİNDE SÜZGEÇ DEĞİL. * * ÖLÇÜLEN ARIZA: panel "Active sessions" kartını en yeni 200 satırı * çekip istemcide `!ended_at` diye süzerek kuruyordu (Overview.tsx:158, * admin.go:739). Sabahtan beri açık duran bir oturumun üstüne 200 yeni * oturum bindiğinde, o oturum karttan tamamen düşüyor: yönetici onu * göremiyor, dolayısıyla kesemiyor da. Açık oturumları saymak için * geçmişin ilk 200 satırına bakmak, yanlış soruyu sormaktı. * * ⚠️ SINIRSIZ DEĞİL. Açık oturum sayısı bağlantı sınırlarıyla zaten * bağlı (listen.max_conns), ama uzlaştırılmamış hayalet satırlar * birikebiliyor (bkz. CloseOrphanSessions). Tavan, panelin bir kazayla * bütün tabloyu çekmesini engelliyor.
func (*Store) PendingByID ¶
PendingByID, tek satır.
func (*Store) PendingMigrations ¶
func (*Store) Ping ¶
Ping, veritabanına ulaşılabildiğini doğrular.
⚠️ Sağlık ucu için var ve BAŞKA HİÇBİR ŞEY YAPMIYOR: bir sorgu çalıştırmak, kimlik istemeyen bir uçtan tetiklenebilen iş demekti.
func (*Store) ProvisionUser ¶
ProvisionUser, IdP kimliğinden kullanıcıyı oluşturur/günceller ve SSO rollerini senkronize eder. Dönen değer yetkileriyle birlikte kullanıcıdır.
SÖZLEŞME: hiçbir grup role eşleşmiyorsa kullanıcı OLUŞTURULMAZ ve ErrAccessDenied döner. "IdP'de hesabın olması postern'de hesabın olması demek değil" kuralının JIT çağındaki hâli — sadece "elle ekle" yerine "grubunu eşle" oldu. Yan faydası: users tablosu IdP'nin tüm dizinine dönüşmez, yalnızca gerçekten erişimi olanları içerir.
Var olan kullanıcı için: eşleşme kalmadıysa kullanıcı SİLİNMEZ (denetim kaydı ona bağlı) ama SSO rolleri temizlenir — erişim biter, iz kalır.
func (*Store) PublicKeyCounts ¶
* PublicKeyCounts, kullanıcı adı → anahtar sayısı. * * ⚠️ TEK SORGU, KULLANICI BAŞINA BİR SORGU DEĞİL. * * Liste bu sayıyı eskiden satır başına PublicKeys() çağırarak * topluyordu: 200 kullanıcılı bir kurulumda tek bir sayfa açılışı 201 * sorgu demekti ve dönen anahtarların BLOB'ları da okunup atılıyordu — * ekranda görünen tek şey bir sayıyken. * * Sayı ekranda kalmak zorunda: "kim hiç bağlanamıyor" sorusunun cevabı * bu ve onu göstermeyen bir liste, yöneticiyi her kullanıcıyı tek tek * açmaya gönderiyordu. * * Adı serbest bırakılmış satırlar dışarıda: onları Users() da * göstermiyor ve aynı ürünün iki farklı cevabı olmamalı.
func (*Store) PublicKeys ¶
func (*Store) PurgeAccount ¶
func (s *Store) PurgeAccount(ctx context.Context, username string, at time.Time) (PurgeResult, error)
* PurgeAccount, kullanıcı ADINI ve diğer tanımlayıcıları serbest * bırakır — SATIRI SİLMEDEN. * * ⚠️ SATIR NEDEN KALIYOR: denetim kaydı ve oturum kayıtları kullanıcı * adını METİN olarak saklıyor. Satır yok olursa geçmişteki * "ayse.yilmaz" satırlarının kime ait olduğu cevapsız kalır — ve aynı * adı alan yeni kişiyle karışır. Kalan satır, "o ad şu tarihte * boşaltıldı" sorusunun cevabı. * * ⚠️ YALNIZCA 'deleted' HESAPLAR. Purge yaşam döngüsünün son adımı, bir * kısayol değil: aktif bir hesabın adını serbest bırakmak, o kişi hâlâ * kullanıyorken kimliğini elinden almak olurdu. * * Serbest bırakılanlar: kullanıcı adı, e-posta, iki kimlik bağı, * anahtarlar ve roller. Hepsi benzersizlik taşıyor ya da erişim * veriyor; biri kalırsa geri dönen kişi kendi hesabını açamaz.
func (*Store) PurgedAccounts ¶
func (s *Store) PurgedAccounts(ctx context.Context) ([]PurgedAccount, error)
* PurgedAccounts, purge edilmiş kayıtları döner. * * ⚠️ Bu liste denetimin bir parçası: geçmişteki bir kullanıcı adının * kime ait olduğu sorusu ancak "o ad şu tarihte boşaltıldı" bilgisiyle * cevaplanabiliyor. Satırların silinmemesinin sebebi de bu.
func (*Store) QueueArchive ¶
* QueueArchive, oturum için bekleyen bir arşiv satırı açar. * * Oturum kapanışında çağrılıyor. İkinci çağrı zararsız: satır zaten * varsa dokunulmuyor — özellikle archived_at'e, çünkü onu silmek * yüklenmiş bir kaydı yeniden bekleyene çevirirdi.
func (*Store) RecordPending ¶
* RecordPending, bir başvuruyu kaydeder ve GÜNCEL durumu döner. * * ⚠️ RED YAPIŞKAN. Reddedilmiş bir kimlik yeniden giriş denediğinde * satır 'waiting'e DÖNMÜYOR; yalnızca last_seen ilerliyor. Dönseydi, * reddedilen kişi tekrar tekrar deneyerek kuyruğu doldurur ve * yöneticiyi aynı kararı vermeye zorlardı. * * ⚠️ Ad DEĞİŞSE de aynı satır: anahtar kimlik. Adla anahtarlanan bir * kuyrukta reddedilen kişi dizinde adını değiştirip yeniden * başvurabilirdi.
func (*Store) RecordTargetError ¶
RecordTargetError, başarısız bir bağlantı denemesini işaretler.
func (*Store) RecordTargetProbe ¶
func (s *Store) RecordTargetProbe(ctx context.Context, targetName string, p model.TargetProbe) error
* RecordTargetProbe, hedefte KOMUT ÇALIŞTIRILARAK öğrenilenleri yazar. * * ⚠️ Yalnızca target_probe.enabled ile çağrılır. probed_at ayrı bir * damga: last_seen_at "bağlandık" demek, probed_at "makineye dokunduk" * demek ve ikisi aynı şey değil.
func (*Store) RecordTargetProbeAttempt ¶
func (s *Store) RecordTargetProbeAttempt(ctx context.Context, targetName string, at time.Time) error
* RecordTargetProbeAttempt, hedefe DOKUNULDUĞUNU kaydeder — ne * öğrenildiğini değil. * * ⚠️ NEDEN VAR: probed_at yalnızca BAŞARILI yoklamada yazılıyordu, oysa * target_probe.refresh kapısı ona bakıyor. Yani cevap üretmeyen bir * yoklama kapıyı hiç kapatmıyor ve HER KANALDA yeniden koşuyordu: * ölçüldü, tek bağlantıda beş kanal = beş yoklama ve (denetim satırı * denemeye taşındıktan sonra) beş defter satırı, oysa başarılı yoklamada * beş kanal = bir satır. * * Bedeli üç yerde: hedefin günlüğüne kullanıcının adına tekrar tekrar * komut düşüyor, denetim defteri aynı cümleyle şişiyor, ve refresh * ayarı söylediği şeyi yapmıyor. * * ⚠️ SEMANTİK DOĞRU: "ProbedAt sıfırsa hedefe hiç dokunulmadı" diyor * (model.TargetFacts) — cevapsız kalan bir yoklama da DOKUNUYOR: exec * kanalı açılıyor ve komutlar çalışıyor. Zaten denetlenmesinin sebebi * bu. Facts'e dokunulmuyor: öğrenilmemiş bir şey yazılmış gibi * görünmesin.
func (*Store) RecordTargetSeen ¶
RecordTargetSeen, başarılı bir bağlantıdan sonra öğrenilenleri yazar.
⚠️ ÇAĞIRAN BU HATAYI OTURUMA YANSITMAMALI. Burası bir gözlem kaydı; yazılamaması can sıkıcıdır ama kullanıcının oturumunu düşürmek için sebep değil. Denetim kaydı (sessions, admin_log) başka bir şey ve onun yazılamaması oturumu düşürür — ayrım kasıtlı.
func (*Store) RecordUnmappedGroups ¶
RecordUnmappedGroups, eşlenmemiş grupları teşhis tablosuna işler.
Hata döndürmez: bu bir teşhis kaydı, girişi düşürmesi için sebep yok. Sorun çıkarsa çağıran loglar.
func (*Store) RefuseIfDeleted ¶
* RefuseIfDeleted, silinmiş bir hesabın giriş yapmasını engeller. * * ⚠️ 'inactive' BURADA REDDEDİLMİYOR ve bu tasarımın kendisi: * pasifleşme "kaynak bir süredir doğrulamadı" demek ve BAŞARILI GİRİŞİN * kendisi o doğrulama. Reddetseydik, geri dönüş yolu bir yöneticiden * geçerdi ve tatilden dönen herkes kuyruğa girerdi. * * 'deleted' farklı: orada uzun bir sessizlik ya da bir insan kararı var * ve onu bir girişin sessizce bozması, "silindi" demenin anlamını yok * ederdi.
func (*Store) RefuseIfDeletedByID ¶
* RefuseIfDeletedByID, RefuseIfDeleted'in KİMLİK ile çalışan hâli. * * ⚠️ NEDEN AD DEĞİL KİMLİK: purge, adı serbest bırakıp satırı * 'purged:<id>' + deleted yapıyor. Ada bakan bir kontrol, ad yeniden * yaratıldığında YENİ satıra çözülüp nil döner — ölçülen sızıntı buydu * (CLI purge ayrı süreç, bellekteki oturumu düşüremiyor). Kimliğe bakan * kontrol, oturumun bağlı olduğu satırı görüyor: purge sonrası o satır * deleted, yani ret KALICI. * * Kimlik hiç yoksa (satır gerçekten silinmiş) ErrNotFound.
func (*Store) RejectPending ¶
* RejectPending, başvuruyu reddeder ve SATIRI BIRAKIR. * * ⚠️ Silinmiyor: silinseydi aynı kişi bir sonraki girişinde yeniden * 'waiting' olarak belirir ve red hiçbir şey ifade etmezdi. Sebep de * saklanıyor — aynı kararı ikinci kez veren yönetici, ilkinin niye * verildiğini görmeli.
func (*Store) RemoveGroupMapping ¶
RemoveGroupMapping, eşlemeyi kaldırır. Yoksa ErrNotFound.
⚠️ Bu, kullanıcıların rollerini ANINDA değiştirmez: mevcut SSO atamaları bir sonraki girişte yenilenir. Yetkiyi hemen kesmek gerekiyorsa rolü ya da kullanıcının erişimini ayrıca ele almak gerekir.
func (*Store) RemoveLocalCredential ¶
RemoveLocalCredential, kimlik bilgisini siler. Hesap kalır.
func (*Store) RemovePublicKey ¶
RemovePublicKey, anahtarı kullanıcıdan kaldırır. Kullanıcı yoksa ya da anahtar BU kullanıcıya ait değilse ErrNotFound — başka birinin anahtarını "benimkiymiş gibi" silmek sessizce başarılı OLMAMALI. keyBlob ham bayt; base64 çevrimi içeride, AddPublicKey ile simetrik.
func (*Store) ReplaceLocalCredential ¶
func (s *Store) ReplaceLocalCredential(ctx context.Context, username, verifier, by string) (replaced bool, err error)
* ReplaceLocalCredential, panelden verilen kimlik bilgisi. Var olanın * ÜSTÜNE YAZAR ve yalnızca YÖNETİCİ OLMAYAN hesaplar için çalışır. * * ⚠️ AddLocalCredential'IN ÜSTÜNE YAZMAMA KURALI KALDIRILMADI, YALNIZCA * BURADA GEÇERLİ DEĞİL — ve iki fonksiyonun ayrı durmasının sebebi tam * olarak bu. Oradaki kural şunu koruyordu: yazma yetkisi olan biri, * kurulumun tek yöneticisinin kimlik bilgisini sessizce döndüremesin. * Aşağıdaki `is_admin = FALSE` koşulu o korumayı aynen sürdürüyor — * yöneticiye bu yoldan dokunulamıyor, hiç. * * Üstüne yazmak burada ise ZORUNLU: "kullanıcı parolasını unuttu" * panelden çözülemezse, panelden sır verme özelliğinin var olma sebebi * — yöneticiyi host kabuğuna göndermemek — ilk gerçek olayda çöker. * * ⚠️ KOŞUL SQL'İN İÇİNDE, ÇAĞIRANDA DEĞİL. Çağıranın `if u.Admin` * yazması unutulabilir; buradaki WHERE unutulamaz. Üstüne bir de göç * 026'nın bileşik yabancı anahtarı var: holder_is_admin uydurulamıyor. * * Dönen değer: var olan bir kimlik bilgisinin üstüne mi yazıldı. * Denetim kaydı için — "verildi" ile "değiştirildi" farklı olaylar.
func (*Store) ResetWebAuthn ¶ added in v1.2.0
* ResetWebAuthn, hesabın bütün anahtarlarını siler ve kodu yeniden * kabul eder hâle getirir — yöneticinin acil çıkış yolu. * * ⚠️ TEK İŞLEMDE. İkisi ayrı olsaydı, aradaki bir hata hesabı tam da * kurtarmaya çalıştığımız duruma sokardı: anahtar yok, kod kapalı.
func (*Store) RevokeRole ¶
RevokeRole, kullanıcıdan rolü geri alır. Kullanıcı ya da rol yoksa ErrNotFound; bağ zaten yoksa SESSİZ no-op (AssignRole'un aynası).
func (*Store) RevokeTarget ¶
RevokeTarget, rolden hedef erişimini geri alır. GrantTarget'ın aynası.
func (*Store) RoleGrantSource ¶
func (s *Store) RoleGrantSource(ctx context.Context, username, roleName string) (source string, found bool, err error)
* RoleGrantSource, bir atamanın NEREDEN geldiğini söyler: "manual" ya * da "sso". found=false, böyle bir atama yok demek. * * ⚠️ NEDEN GEREKLİ: AssignRole'un ON CONFLICT dalı source'u koşulsuz * 'manual' yapıyor, SyncRoles ise yalnızca source='sso' satırlarını * siliyor. Yani dizinden gelen bir rolü elle "yeniden vermek", o rolü * senkronizasyonun erişemeyeceği bir yere taşıyor: kişi gruptan * çıkarıldığında rol ÜZERİNDE KALIYOR ve hiçbir otomatik yol onu geri * alamıyor. Bu okuma olmadan çağıran, sessizce kalıcı yetki üretiyor. * * Kimseyi engellemek için değil, SÖYLEYEBİLMEK için var.
func (*Store) RoleSudoRule ¶ added in v1.2.0
RoleSudoRule, rolün kuralı. Kural yoksa ErrNotFound.
func (*Store) RoleSudoRules ¶ added in v1.2.0
* RoleSudoRules, bütün rollerin kuralları, rol adıyla anahtarlı. * * Hak verme akışı bunu TEK sorguyla alıyor: kişinin seçtiği grupların * hangileri rol ve hangilerinin kuralı var, hepsi tek okumada.
func (*Store) Roles ¶
Roles, tüm rolleri hedefleriyle, ada göre sıralı döner; hedefsiz rol boş Targets ile gelir.
func (*Store) RolesForGroups ¶
func (s *Store) RolesForGroups(ctx context.Context, groups []string) (roles, unmapped []string, err error)
RolesForGroups, verilen dış grup adlarının karşılığı rolleri ve eşleşmeyen grupları döner.
Eşleşmeyenler çağırana veriliyor ki kaydedebilsin (RecordUnmappedGroups) ve yönetici neyi eşlemediğini görebilsin.
func (*Store) SaveDiscoveredMachine ¶ added in v1.2.0
func (s *Store) SaveDiscoveredMachine(ctx context.Context, m DiscoveredMachine) error
* SaveDiscoveredMachine, koşunun gördüğü hâli yazar. * * ⚠️ İKİ ALAN KOŞUNUN DEĞİL İNSANIN: ignored hiç güncellenmiyor ve * target_id yalnızca DOLDURULABİLİYOR, boşaltılamıyor. Koşu satırı * okuduktan sonra bir yönetici makineyi kaydedip ya da yok sayıp * koşu yazarken eski hâli geri koysaydı, verilen karar sessizce * silinirdi. Bağ yalnızca hedef silindiğinde kopuyor (ON DELETE SET NULL).
func (*Store) SecretsAvailable ¶ added in v1.2.0
SecretsAvailable, sır mühürleyen anahtar yüklü mü. Yoksa kaynak kaydedilemez; panel bunu formu açmadan söylüyor.
func (*Store) SeenGroupNames ¶
* SeenGroupNames, postern'in BUGÜNE KADAR gördüğü grup adları. * * İki kaynaktan: kullanıcılara gerçekten atanmış SSO rollerinin * eşlemeleri, ve eşlenmemiş grup teşhis tablosu. İkisi birlikte, * "bu ad hiç geldi mi" sorusunun elimizdeki en iyi cevabı. * * ⚠️ Kesin bir liste DEĞİL ve öyle sunulmamalı: bir kaynağa "hangi * gruplar var" diye genel olarak sorulamıyor (OIDC claim'i * listelenemez). Bu yüzden çağıran bunu bir teşhis olarak kullanıyor, * bir iddia olarak değil.
func (*Store) Session ¶
Session, tek bir oturumu kimlik ADLARIYLA döner. Yoksa ErrNotFound.
Sessions'ın sorgusunun WHERE s.id = $1 hâli; NULL/zaman çevrimleri de birebir aynı desen.
func (*Store) SessionFiles ¶
SessionFiles, bir oturumun dosya olaylarını zaman sırasıyla döner.
func (*Store) SetAccountState ¶
* SetAccountState, durumu elle değiştirir (panel/CLI). * * ⚠️ 'deleted'ten 'active'e dönüş SERBEST: yanlışlıkla silinmiş bir * hesabın geri gelememesi, tek tıkla kalıcı bir kayıp demekti. Fiziki * silme zaten yok.
func (*Store) SetChosenPassword ¶
func (s *Store) SetChosenPassword(ctx context.Context, username, verifier string, at time.Time) error
* SetChosenPassword, kullanıcının SEÇTİĞİ parolayı yazar. * * ⚠️ AddLocalCredential'DAN AYRI. O, üstüne yazmayı REDDEDİYOR ve bu * kasıtlı (bkz. oradaki not): var olan bir sırrı sessizce döndürmek, * elindeki değerle çalışan operatörü dışarıda bırakırdı. Burada tam * tersi isteniyor — amaç zaten üstüne yazmak. İki niyeti tek fonksiyona * bayrakla toplamak, o korumayı bir gün yanlışlıkla açık bırakırdı. * * ⚠️ YÖNETİCİ KONTROLÜ BURADA YOK. Kasıtlı: kuralı veritabanı tutuyor * (göç 026'daki CHECK). Buraya bir `if` yazmak, kuralın ikinci bir * kopyası olurdu ve iki kopyadan biri er ya da geç geride kalır. * Yönetici hesabında bu çağrı 23514 ile düşüyor ve çağıran onu * ErrAdminPasswordRefused olarak görüyor.
func (*Store) SetDiscoveredMachineIgnored ¶ added in v1.2.0
func (s *Store) SetDiscoveredMachineIgnored(ctx context.Context, sourceID, ref string, ignored bool) (string, bool, error)
SetDiscoveredMachineIgnored, yok sayma bayrağını çevirir; değiştiyse makinenin adını döner.
func (*Store) SetGroupAdmin ¶
* SetGroupAdmin, dizin GRUBUNDAN gelen yönetici yetkisini uygular. * * ⚠️ CLI'IN VERDİĞİNE DOKUNMAZ. WHERE koşulundaki * `admin_via IS DISTINCT FROM 'cli'` bunun için: acil durum diye elle * açılmış bir yöneticinin, dizinde o grubu görülmediği için sessizce * yetkisini kaybetmesi, tam olarak kaçınılması gereken şey — ve * kaybettiği an, onu geri verecek kişinin de kapısı kapanmış olurdu. * * Rol modelindeki source='sso' / 'manual' ayrımının aynısı: her * mekanizma yalnızca KENDİ verdiğini geri alabiliyor.
func (*Store) SetJITGrantCreatedGroups ¶ added in v1.2.0
SetJITGrantCreatedGroups, hak uygulanırken postern'in AÇTIĞI grupları kaydeder; geri alma yalnızca bunları silmeyi düşünür.
func (*Store) SetRecordingChain ¶ added in v1.2.0
* SetRecordingChain, kaydın zincir başını ve halka sayısını yazar. * * ⚠️ EndSession'DAN AYRI, VE BU BİLİNÇLİ. EndSession oturumu defterden * düşüren yol ve çökme sonrası süpürme (CloseOrphanSessions) da onu * kullanıyor — orada elde bir zincir YOK, çünkü kaydı kapatan süreç * ölmüş. İkisini birleştirmek, zinciri olmayan her kapanışta ya boş baş * yazmayı ya da imzayı yalanlamayı gerektirirdi. * * ⚠️ BAŞARISIZLIĞI OTURUMU DÜŞÜRMÜYOR. Oturum bitti; yazılamayan bir * zincir başı, o kaydı DOĞRULANAMAZ yapar ama var olan hiçbir şeyi * bozmaz. Çağıran hatayı log'luyor ve kapanışa devam ediyor: burada * hata döndürüp kapanışı yarıda bırakmak, denetim satırını "running" * bırakmak olurdu ki o gerçek bir kayıp.
func (*Store) SetRecordingPathForTest ¶
* SetRecordingPathForTest, kayıt yolunu doğrudan değiştirir. * * ⚠️ YALNIZCA TESTLER İÇİN. Üretimde bu sütunu yazan tek yer * StartSession; keyfi bir yol yazabilen bir API, veritabanına * ulaşan birine dosya okuma/yükleme yetkisi vermek olurdu. Test, * arşivleyicinin tam da o saldırıyı reddettiğini ölçüyor.
func (*Store) SetRolePath ¶ added in v1.2.0
func (s *Store) SetRolePath(ctx context.Context, roleName, prefix string, allow, canWrite bool) error
* SetRolePath, bir role yol kuralı ekler ya da var olanı günceller. * * ⚠️ ÖNEK MUTLAK OLMALI. Göreli bir kuralın neye göre olduğunu bilemeyiz — * istemcinin çalışma dizini hedefte, bizde değil — ve politika da göreli * yolları zaten reddediyor. Kabul etseydik hiçbir zaman eşleşmeyen bir * kural yazdırırdık: yönetici koruma koyduğunu sanır, koymamış olurdu. * * Şemada da CHECK var; buradaki kontrol hatayı ANLAŞILIR kılmak için, * kısıtın yerine geçmek için değil.
func (*Store) SetRoleSudo ¶ added in v1.2.0
func (s *Store) SetRoleSudo(ctx context.Context, role string, rule sudoers.Rule, actor string) error
* SetRoleSudo, rolün kuralını yazar (varsa değiştirir). * * ⚠️ KAÇIŞ RİSKİ VERİTABANINDA BEKLEMİYOR. sudoers.Validate'in kaçış * bulduğu bir kural (vim, less, find -exec ...) onaylanmadıkça * YAZILMIYOR — render anında reddedilmesini beklemek, kuralı kaydedip * hedefe gitme anında patlayan bir bomba bırakmak olurdu. Onaylanan kural * onay bayrağıyla birlikte duruyor ki denetim satırı da ekran da bunun * bir karar olduğunu söyleyebilsin.
func (*Store) SetSearchTimeoutForTest ¶
* SetSearchTimeoutForTest, sunucu tarafı sınırı kısaltır. * * ⚠️ YALNIZCA TESTLER İÇİN. Sınırın gerçekten UYGULANDIĞINI ölçmenin * tek yolu onu aşan bir sorgu çalıştırmak; 5 saniyelik varsayılanla o * test her CI koşusuna beş saniye eklerdi ve büyük ihtimalle hiç * yazılmazdı. Ölçülmeyen bir koruma, olmayan bir korumadır.
func (*Store) SetSetting ¶
func (s *Store) SetSetting(ctx context.Context, key, value string, encrypt bool, actor string) error
SetSetting, ayarı yazar. encrypt=true ise değer mühürlenerek saklanır.
encrypt=true iken anahtar yoksa REDDEDİLİR — düz metin yazıp "şifreledim" sanmak bu paketin bütün amacını sessizce boşa çıkarır.
func (*Store) SetTargetLabel ¶
func (s *Store) SetTargetLabel(ctx context.Context, targetName, key, value, actor, via string) error
SetTargetLabel, etiketi ekler ya da değerini değiştirir.
Denetim satırı BURADA yazılıyor, çağıranda değil: etiket hedefin nasıl bulunacağını belirliyor ve "prod" etiketini bir makineden alıp başkasına takan kişinin izi kalmalı.
func (*Store) SetUserAdmin ¶
SetUserAdmin, uygulama yönetim yetkisini verir ya da alır. Kullanıcı yoksa ErrNotFound.
func (*Store) SetUserEmail ¶
SetUserEmail, kullanıcının e-postasını değiştirir; boş string adresi SİLER (NULL). Kullanıcı yoksa ErrNotFound; adres başka bir kullanıcıda kayıtlıysa ErrConflict (users.email UNIQUE — OIDC eşleşmesi tekil kalmalı).
"user add"in reddettiği örtük değişikliğin AÇIK hâli: yönetici ne yaptığını komutun adıyla söylüyor.
func (*Store) SetUserOSUser ¶
SetUserOSUser, kullanıcının hedeflerdeki hesabını değiştirir. Boş değer şemadaki CHECK'e takılır; kullanıcı yoksa ErrNotFound.
⚠️ Bu, bir sonraki oturumdan itibaren kesilecek SERTİFİKALARIN principal'ını değiştirir — geçmiş denetim kayıtlarına dokunmaz (sessions.os_user o günkü kararı saklar; sebebi şemada yazıyor).
func (*Store) SetUserSSOOnly ¶
SetUserSSOOnly, kullanıcının yalnızca kimlik sağlayıcı üzerinden girebilmesini açar/kapatır. Kullanıcı yoksa ErrNotFound.
func (*Store) SetWebAuthnOnly ¶ added in v1.2.0
* SetWebAuthnOnly, hesabın kodu kabul edip etmeyeceğini belirler. * * ⚠️ ANAHTARSIZ AÇILAMIYOR. Açılsaydı hesabın kabul ettiği hiçbir ikinci * faktör kalmazdı ve kullanıcı kendini kilitlerdi — bu projede kurtarma * kodu bilerek yok, yani çıkış yolu yalnızca yönetici olurdu.
func (*Store) Settings ¶
func (s *Store) Settings(ctx context.Context) ([]SettingView, error)
Settings, ada göre sıralı ayar listesi döner — ŞİFRELİ DEĞERLER MASKELENMİŞ olarak.
⚠️ Bu fonksiyonun çıktısı admin API'sine gidiyor: şifreli bir ayarın değeri ASLA dönmez, maskelenir. Sır yazılır ama okunmaz.
func (*Store) SourceAccountCount ¶
SourceAccountCount, kaynaktan gelen toplam hesap sayısı — patlama yarıçapı oranının paydası.
func (*Store) StaleAccounts ¶
func (s *Store) StaleAccounts(ctx context.Context, olderThan time.Time, state string) ([]StaleAccount, error)
* StaleAccounts, kaynağın BELİRLİ BİR SÜREDİR doğrulamadığı hesapları * döner. * * ⚠️ KAPSAM: yalnızca kaynaktan gelen hesaplar (sso_only ya da dizine * bağlı). Yerel hesaplar DIŞARIDA ve bu kapsam daraltması özelliğin * otomasyon için güvenli olmasının tek sebebi: CI ve servis hesapları * yerel açılıyor, hiçbir kaynağa sorulamıyor ve "doğrulanmamış olmaları" * normal. Onları da kapsayan bir sayaç, her otomasyonu süre dolunca * keserdi.
func (*Store) StartDiscoveryRun ¶ added in v1.2.0
StartDiscoveryRun, koşu satırını açar.
func (*Store) StartSession ¶
func (s *Store) StartSession(ctx context.Context, rec SessionStart) error
func (*Store) StartSyncRun ¶
func (s *Store) StartSyncRun(ctx context.Context, source, trigger string, dryRun bool) (int64, error)
StartSyncRun, koşuyu açar ve id'sini döner.
func (*Store) SyncCandidates ¶
func (s *Store) SyncCandidates(ctx context.Context) ([]SyncCandidate, error)
SyncCandidates, senkronizasyona TABİ kullanıcıları döner.
- ⚠️ KAPSAM: sso_only OLANLAR ARTI DİZİNE BAĞLI OLANLAR. *
- Eskiden yalnızca sso_only = TRUE idi ve bu, freshen'da düzeltilen
- hatanın buradaki eşiydi: yetkisi dizinden gelen bir kullanıcı
- (dir_subject dolu, sso_only false) HİÇ senkronize edilmiyordu. Yani
- dizinden silinen kişi, bir daha hiç giriş yapmadığı sürece rollerini
- süresiz koruyordu — ve döngünün var olma sebebi tam olarak o kişiydi. *
- ⚠️ Servis hesapları (otomasyon, CI) HÂLÂ DIŞARIDA ve genişletme bunu
- bozmuyor: onların ne sso_only'si var ne dizin kimliği. Dizinde
- "bulunamamaları" normal ve döngünün onlara dokunmaması şart (göç 008
- tam olarak bu ayrım için).
func (*Store) SyncRoles ¶
SyncRoles, kullanıcının SSO kaynaklı rollerini IdP'nin söylediğiyle DEĞİŞTİRİR. Elle atanmış roller (source='manual') etkilenmez.
Her SSO girişinde çağrılır: gruptan çıkarılan kullanıcı yetkisini o an kaybeder, yeni gruba eklenen o an kazanır.
func (*Store) TOTPEnrolled ¶ added in v1.1.0
* TOTPEnrolled, hesabın DOĞRULANMIŞ bir ikinci faktörü var mı, onu söyler. * * ⚠️ SIRRA DOKUNMUYOR — ve bu bilinçli, iki sebeple. Birincisi bu soru her * istekte soruluyor (requireSession); sırrı her seferinde açmak, kapıya * gereksiz bir AES çözme maliyeti bindirirdi. İkincisi ve önemlisi: sır * anahtarı yoksa TOTP() hata veriyor, ve o hata bu kapıdan geçseydi * anahtarını kaybetmiş bir kurulumda panel BÜTÜNÜYLE kapanırdı — kimsenin * ikinci faktörü kaybolmadığı hâlde. Kapının sorusu "kayıt var mı", "sır * okunabiliyor mu" değil. * * Doğrulanmamış kayıt SAYILMIYOR: QR'ı hiç okutmamış birinin telefonunda * karşılığı olmayan bir kayıt, ikinci faktör değildir.
func (*Store) TOTPFailure ¶ added in v1.2.0
func (s *Store) TOTPFailure(ctx context.Context, username string, max int, lockFor time.Duration) (TOTPLock, error)
* TOTPFailure, bir başarısız denemeyi sayar ve gerekiyorsa kilitler. * * ⚠️ SAYMA VE KİLİTLEME TEK İFADEDE. İki adıma bölseydik (oku, sonra yaz) * aynı anda gelen denemeler aynı sayıyı okuyup aynı değeri yazardı: eşik * hiç geçilmeyebilir ve kilit hiç kurulmayabilirdi. Saldırganın * yapabileceği en kolay şey paralel denemek. * * max <= 0 ise kilit kurulmuyor, yalnızca sayılıyor: operatör kilidi * kapatabilmeli ve kapattığında sayacı da kaybetmemeli.
func (*Store) TOTPLockState ¶ added in v1.2.0
* TOTPLockState, sayaç ve kilidi okur. * * Doğrulayıcısı olmayan hesap ErrNotFound veriyor: kilit, doğrulayıcıya * ait bir şey.
func (*Store) TargetFacts ¶
TargetFacts, tek bir hedefin gözlemleri. Hiç bağlanılmamışsa sıfır değer döner — ErrNotFound DEĞİL: "henüz bağlanılmadı" bir hata değil, hedefin geçerli bir hâli.
func (*Store) TargetKeys ¶ added in v1.2.0
TargetKeys, bütün hedeflerin kimliği, adı ve sabitlenmiş anahtarı.
func (*Store) TargetLabels ¶
TargetLabels, tek bir hedefin etiketleri.
func (*Store) TouchDiscoverySource ¶ added in v1.2.0
TouchDiscoverySource, elle başlatılan koşunun zamanını yazar ki zamanlayıcı hemen ardından aynı kaynağı bir daha koşturmasın.
func (*Store) TouchLocalCredential ¶
TouchLocalCredential, son kullanım anını damgalar.
Hatası girişi DÜŞÜRMEZ: çağıran loglar. Kullanım damgası bir teşhis bilgisi ve onun yazılamaması, kimliği doğrulanmış bir kullanıcıyı dışarıda bırakmak için sebep değil.
func (*Store) TouchWebAuthnCredential ¶ added in v1.2.0
func (s *Store) TouchWebAuthnCredential(ctx context.Context, id string, signCount uint32, flags byte, ) error
* TouchWebAuthnCredential, başarılı bir girişten sonra sayacı, bayrakları * ve son kullanım anını yazar. * * ⚠️ SAYAÇ GERİ GİTMİYOR. Doğrulayıcı sayacı artırmıyorsa (bazı platform * anahtarları hep 0 gönderiyor) yazdığımız değer 0 kalıyor; kontrolü * yapan taraf bunu bilerek atlıyor (bkz. httpapi/webauthn.go). Burada * küçülen bir sayıyı yazmak, klon sezgisini sessizce kapatırdı. * * ⚠️ BAYRAKLAR SAYAÇTAN FARKLI: OLDUĞU GİBİ YAZILIYOR. "Yedeklenmiş" * bayrağı iki yöne de gidebiliyor (anahtar buluta senkronlanır ya da * senkrondan çıkar) ve şartname kaydın her başarılı imzadan sonra * güncellenmesini istiyor. Buraya yalnızca DOĞRULANMIŞ bir imzadan gelen * değer giriyor; çağıran onu kütüphanenin döndürdüğü kayıttan alıyor.
func (*Store) TryLockSync ¶
TryLockSync, senkronizasyon kilidini DENEYEREK alır.
İki postern süreci aynı veritabanına bakıyorsa ikisi de senkronize eder ve patlama yarıçapı sayaçlarını BAĞIMSIZ hesaplar — yani tavanlar ikiye bölünmüş olur ve ikisi birden geçebilir.
pg_try_advisory_lock BEKLEMEZ: alamadıysa bu koşu atlanır. Beklemek, zamanlayıcı tikleri kuyruğa dizmek demek olurdu.
⚠️ Kilit SABİTLENMİŞ bir bağlantıda tutuluyor: havuzdan alınan bir bağlantı koşunun ortasında geri verilebilir ve kilit sessizce düşerdi.
func (*Store) UnbindDirIdentity ¶
UnbindDirIdentity, bağı koparır.
⚠️ Kurtarma yolu ve var olması ŞART: dizinde silinip yeniden açılan bir kişi YENİ bir kimlik alır (ölçüldü) ve eski bağ onu kendi hesabından kilitler. Bunu çözecek bir komut olmazsa tek çıkış veritabanına elle girmek olurdu.
func (*Store) UnlockTOTP ¶ added in v1.2.0
* UnlockTOTP, kilidi yönetici eliyle kaldırır ve sayacı sıfırlar. * * ⚠️ SAYAÇ DA SIFIRLANIYOR. Yalnızca kilidi açmak, kullanıcının bir sonraki * hatasında anında yeniden kilitlenmesi demekti — yönetici müdahalesi * neredeyse hiçbir şey değiştirmezdi.
func (*Store) UnmappedGroups ¶
func (s *Store) UnmappedGroups(ctx context.Context) ([]UnmappedGroup, error)
UnmappedGroups, eşlenmemiş grupları en çok görülenden aza doğru döner.
func (*Store) UpdateDiscoverySource ¶ added in v1.2.0
* UpdateDiscoverySource, kaynağı günceller. secret boşsa kayıtlı sır * KALIR: panel sırrı hiç görmediği için "değiştirmedim" ile "sildim"i * ayırmanın tek yolu bu. Tür değişmiyor — makine kimlikleri türe özgü.
func (*Store) UseSecretBox ¶
UseSecretBox, şifreli ayarları açıp mühürleyecek anahtarı bağlar.
Store bunsuz da çalışır: şifresiz ayarlar okunur/yazılır, şifreli olana dokunulduğunda hata verilir. CLI'ın çoğu komutu sır gerektirmiyor ve anahtar dosyası olmadan da çalışabilmeli.
func (*Store) UseTOTPStep ¶
* UseTOTPStep, bir adımı TÜKETİR ve daha önce kullanılmışsa reddeder. * * ⚠️ TEK BİR İFADEDE KARŞILAŞTIR-VE-YAZ. Önce okuyup sonra yazan bir * uygulama, aynı kodla gönderilen İKİ eşzamanlı isteğin ikisini de * geçirirdi: her ikisi de eski değeri okur, her ikisi de kabul eder. * Tekrar korumasının bütün anlamı tam olarak o yarışı kapatmak. * * `last_step < $2` aynı zamanda pencere içindeki DAHA ESKİ adımları da * kapatıyor: adım N kullanıldıysa, hâlâ geçerli olan N-1 kodu da ölür.
func (*Store) UserByDirSubject ¶
UserByDirSubject, dizin kimliğine bağlı kullanıcıyı döner. Bağlı hesap yoksa ErrNotFound.
func (*Store) UserByEmail ¶
func (*Store) UserByIdPSubject ¶
UserByIdPSubject, (issuer, subject) çiftine bağlı kullanıcıyı döner.
func (*Store) UserByNameFold ¶
* UserByNameFold, adı HARF DUYARSIZ arar ve bulunan gerçek adı döner. * * ⚠️ KULLANICI ADLARI 019'DAN BERİ HARF DUYARSIZ BENZERSİZ. Eski yorum * bunun tersini söylüyordu ("Ops ile ops iki ayrı hesap olabilir") ve * o artık yanlış: göç 019 lower(username) üzerinde tekil bir indeks * kurdu, tam da bir harf farkıyla ikinci bir yönetici ve ikinci bir * canlı sır yaratılmasını önlemek için. * * Bu fonksiyon o tekilliğin okuma tarafı: bootstrap, adı ne yazımla * yazılmış olursa olsun tek hesabı bulmalı. * * lower() indeksi VAR (019) ve users.username ciColumns'ta — sorgu bir * tablo taraması yapmıyor. Eski yorum "indeks yok" diyordu; o da yanlış.
func (*Store) UserByPublicKey ¶
func (*Store) UserIdentity ¶ added in v1.2.0
* UserIdentity, hesabın KARARLI kimliği. * * ⚠️ WebAuthn kaydı bu değere bağlanıyor, kullanıcı adına DEĞİL. Ad * yeniden kullanılabiliyor (user purge); anahtarın bağlandığı şey ad * olsaydı, silinip yeniden açılan bir hesap eski sahibinin * doğrulayıcısındaki kaydı devralırdı.
func (*Store) UserProfile ¶
UserProfile, detay alanlarını TEK sorguda döner.
func (*Store) Users ¶
Users, tüm kullanıcıları rolleriyle birlikte, ada göre sıralı döner.
User'ın sorgusunun WHERE'siz hâli; gruplama iki seviyeli — önce kullanıcıya, sonra role. Desen User'dakiyle aynı, yalnızca indeks map'leri kullanıcı boyutu kazanıyor.
Hiç kullanıcı yoksa boş dilim, hata değil.
func (*Store) WebAuthnCredentials ¶ added in v1.2.0
func (s *Store) WebAuthnCredentials(ctx context.Context, username string) ([]WebAuthnCredential, error)
WebAuthnCredentials, hesabın anahtarlarını en eskiden yeniye döner.
type SyncCandidate ¶
type SyncCandidate struct {
Username string
Email string
// MissingSince sıfırsa kullanıcı en son bakıldığında dizinde vardı.
MissingSince time.Time
SSORoles int
ManualRoles int
/*
* DirSubject, hesabın bağlı olduğu KARARLI dizin kimliği; bağlı
* değilse boş.
*
* ⚠️ Döngü, varsa BUNUNLA aramalı. Adla arama, dizinde yeniden
* adlandırılan kişiyi SİLİNMİŞ kişiden ayırt edemiyor — ikisi de
* PresenceAbsent döner ve döngü ikincisini rol iptaline çevirir.
* Yani İK'nın bir soyadı güncellemesi, kimsenin fark etmediği bir
* yerde erişim kaybına dönüşüyordu.
*/
DirSubject string
}
SyncCandidate, senkronizasyonun bakacağı bir kullanıcı.
type SyncRun ¶
type SyncRun struct {
ID int64
StartedAt time.Time
FinishedAt time.Time
Source string
Trigger string
Outcome string
Reason string
Considered int
Present int
Absent int
Unknown int
Revoked int
RolesChanged int
DryRun bool
}
SyncRun, bir senkronizasyon koşusunun kaydı.
type TOTPCredential ¶
type TOTPCredential struct {
// ⚠️ Secret JSON'a ÇIKMIYOR. Bu değer kod üretmeye yeter; bir
// listeleme ucundan sızması, ikinci faktörü ikinci faktör olmaktan
// çıkarır. Yalnızca kayıt akışında, bir kez gösteriliyor.
Secret string `json:"-"`
Confirmed bool `json:"confirmed"`
ConfirmedAt time.Time `json:"confirmed_at,omitzero"`
CreatedAt time.Time `json:"created_at"`
LastUsedAt time.Time `json:"last_used_at,omitzero"`
}
TOTPCredential, bir hesabın ikinci faktörü.
type TOTPLock ¶ added in v1.2.0
* TOTPLock, bir hesabın kod denemelerinin durumu. * * ⚠️ Failures, SON BAŞARILI GİRİŞTEN BU YANAKİ hatalar. Kümülatif değil: * kullanıcıya "son girişinizden beri N deneme" diye gösterilebilmesi için * başarıda sıfırlanıyor. Kümülatif bir sayı zamanla anlamsız büyür ve * "bugün bir şey oldu mu" sorusunu cevaplayamaz.
type TargetKey ¶ added in v1.2.0
type TargetKey struct {
ID, Name, HostKey string
}
TargetKey, keşfin bir makineyi kayıtlı hedefle eşleştirmek için baktığı üç alan.
type UnmappedGroup ¶
UnmappedGroup, teşhis listesindeki bir kayıt.
type UserProfile ¶
type UserProfile struct {
Email string
// AdminVia: "cli", "group" ya da boş. Yöneticiliğin KAYNAĞI, çünkü
// panelin kaldırabildiği ile kaldıramadığı ayrı şeyler.
AdminVia string
State string
Confirmed time.Time
// Purged: adı serbest bırakılmış. Satır yalnızca denetim kaydının
// okunabilir kalması için duruyor.
Purged bool
// HasCredential false ise aşağıdaki alanlar anlamsız: hesabın
// postern'de doğrulanabilir bir değeri yok, kimliği başka yerden
// geliyor.
HasCredential bool
CredChosen bool
CredMustChange bool
CredCreatedAt time.Time
CredCreatedBy string
CredLastUsed time.Time
}
* UserProfile, kullanıcı DETAY ekranının ihtiyacı. * * ⚠️ NEDEN AYRI BİR SORGU: model.User bilerek dar tutuldu — yetki * kararlarının ihtiyacı olan alanları taşıyor ve SSH kapısında her * oturumda okunuyor. E-posta, hesap durumu ve kimlik bilgisi meta * verisi orada hiçbir kararı etkilemiyor; oraya eklemek, hiç * kullanılmayan alanları en sıcak yoldan geçirmek olurdu. * * Buradaki alanların ortak yanı hepsinin bir TEŞHİS sorusuna cevap * vermesi: "neden giremiyor", "yöneticiliği nereden geliyor", "bu * hesabın nasıl bir giriş bilgisi var".
type WebAuthnCredential ¶ added in v1.2.0
type WebAuthnCredential struct {
// ID, ham kimlik bilgisi kimliğinin base64url hâli.
ID string `json:"id"`
PublicKey []byte `json:"-"`
AAGUID []byte `json:"-"`
// SignCount, doğrulayıcının bildirdiği son sayaç.
SignCount uint32 `json:"-"`
/*
* Flags, doğrulayıcının bildirdiği bayrakların ham sekizlisi
* (UP/UV/BE/BS...). FlagsKnown, satırın bayraklar saklanmaya
* başlamadan önce (göç 040 öncesi) yazılıp yazılmadığını söylüyor.
*
* ⚠️ BUNU SAKLAMAMAK GİRİŞİ TAMAMEN KIRIYORDU — ÖLÇÜLDÜ.
* Şartname "yedeklenebilir" bayrağının hiç değişmemesini istiyor ve
* kütüphane her imzada kayıttakiyle karşılaştırıyor. Saklamayınca
* karşılaştırma sıfır değere düşüyor, Touch ID ve senkron olan her
* passkey (BE=1) "bu güvenlik anahtarı kabul edilmedi" alıyordu.
*
* ⚠️ "BİLİNMİYOR" İLE "HEPSİ KAPALI" AYRI. Sütun bu yüzden NULL
* kabul ediyor: ikisini aynı saymak, eski satırları da tam olarak
* yukarıdaki hataya düşürürdü.
*/
Flags byte `json:"-"`
FlagsKnown bool `json:"-"`
// Name, kişinin verdiği ad: kayıp anahtarı silecek olan buna bakıyor.
Name string `json:"name"`
CreatedAt time.Time `json:"created_at"`
LastUsedAt time.Time `json:"last_used_at,omitzero"`
}
* WebAuthnCredential, bir hesaba kayıtlı tek bir güvenlik anahtarı. * * ⚠️ TOTPCredential'DAN FARKI TEK CÜMLEDE: burada gizli bir şey yok. * TOTP sırrı paylaşılan bir sır ve JSON'a çıkmıyor (bkz. totp.go); * PublicKey ise çalınsa bile imza üretmiyor. Bu yüzden mühürlenmiyor, * ve mühürlenmemesi bir eksiklik değil — gereksiz yere mühürlemek * okuyana "bu değer gizli" diye yanlış bir şey öğretirdi.