Documentation
¶
Overview ¶
Package config defines postern's YAML configuration schema and loading.
SÖZLEŞME (S3): config yalnızca ALTYAPI taşır — dinleme adresi, anahtar yolları, veritabanı ve kayıt dizini. Kimlik ve yetki verisi (kullanıcı, rol, hedef) burada YAŞAMAZ: tek kaynağı veritabanıdır ve yalnızca yetkili kanallardan (bastion hostundaki postern CLI; ileride OIDC'li API) değiştirilir. YAML'a kullanıcı yazmak diye bir şey yoktur.
Index ¶
- Constants
- type ArchiveConfig
- type AuthConfig
- type CAConfig
- type Config
- type DatabaseConfig
- type HTTPConfig
- type ListenConfig
- func (c ListenConfig) HandshakeTimeoutOrDefault() time.Duration
- func (c ListenConfig) MaxAuthTriesOrDefault() int
- func (c ListenConfig) MaxChannelsOrDefault() int
- func (c ListenConfig) MaxConnsOrDefault() int
- func (c ListenConfig) MaxConnsPerIPOrDefault() int
- func (c ListenConfig) MaxPendingLoginsOrDefault() int
- type OIDCConfig
- type RecordingConfig
- type SessionConfig
- type ShutdownConfig
- type SyncConfig
- func (c SyncConfig) GraceOrDefault() time.Duration
- func (c SyncConfig) IntervalOrDefault() time.Duration
- func (c SyncConfig) MaxRevokePerRunOrDefault() int
- func (c SyncConfig) MaxUnknownFractionOrDefault() float64
- func (c SyncConfig) MaxZeroFractionOrDefault() float64
- func (c SyncConfig) MinZeroFloorOrDefault() int
- func (c SyncConfig) TimeoutOrDefault() time.Duration
- type TargetProbeConfig
Constants ¶
const DatabaseDSNEnv = "POSTERN_DATABASE_DSN"
DatabaseDSNEnv, database.dsn'i geçersiz kılan ortam değişkeni.
Ayrı bir değişken olmasının sebebi işlemsel: bağlantı dizesi parola taşır ve config dosyaları sürüm kontrolüne, yedeklere, hata ayıklama paketlerine girer.
const DefaultRecordingMinFree = 1 << 30
DefaultRecordingMinFree, MinFree boş bırakıldığında geçerli olan.
1 GiB: birkaç uzun oturumu rahat karşılayacak ve operatöre yer açması için zaman bırakacak kadar; boş bir diskte kimseyi rahatsız etmeyecek kadar küçük.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ArchiveConfig ¶
type ArchiveConfig struct {
// Endpoint boşsa arşivleme kapalı ve hiçbir şey değişmiyor.
Endpoint string `yaml:"endpoint"`
Bucket string `yaml:"bucket"`
Region string `yaml:"region"`
// Prefix, nesne anahtarının önüne eklenen yol ("postern/uretim").
Prefix string `yaml:"prefix"`
// CAFile, şirket içi bir depo kendi kökünü kullanıyorsa.
//
// ⚠️ insecure_skip_verify YOK ve olmayacak: doğrulanmamış bir TLS
// bağlantısına oturum kayıtlarını yazmak, denetim izini araya
// girene teslim etmenin en sessiz yolu.
CAFile string `yaml:"ca_file"`
AccessKeyID string `yaml:"access_key_id"`
/*
* SecretKeyFile, gizli anahtarı TAŞIYAN DOSYANIN YOLU.
*
* ⚠️ SIRRIN KENDİSİ CONFIG'E YAZILMIYOR. Aynı gerekçe
* POSTERN_DATABASE_DSN'de de geçerli: config dosyası kopyalanıyor,
* yedekleniyor, hata raporuna yapıştırılıyor. Dosya yolu vermek,
* sırrı 0600 bir dosyada ve süreçle aynı sahiplikte tutmayı
* mümkün kılıyor.
*
* POSTERN_ARCHIVE_SECRET_KEY ortam değişkeni bunu geçersiz kılıyor
* (systemd EnvironmentFile ile kullanmak için).
*/
SecretKeyFile string `yaml:"secret_key_file"`
/*
* ServerSideEncryption, x-amz-server-side-encryption değeri.
* BOŞ = başlık gönderilmiyor ve VARSAYILAN BU.
*
* ⚠️ ÖLÇÜLDÜ: koşulsuz "AES256" göndermek, KMS yapılandırılmamış
* bir MinIO'da 501 NotImplemented veriyor — yani şirket içi
* kurulumların çoğunda hiçbir kayıt yüklenemezdi. Üstelik
* bastion'ı ele geçiren yükleme kimliğini de ele geçirdiği için
* bu başlığın O saldırgana karşı bir faydası yok. Doğru yer
* kovanın kendi varsayılanı.
*/
ServerSideEncryption string `yaml:"server_side_encryption"`
// Interval, tarama sıklığı. Boş = 1 dakika.
Interval time.Duration `yaml:"interval"`
// Timeout, tek bir yükleme isteğinin üst sınırı. Boş = 30 saniye.
Timeout time.Duration `yaml:"timeout"`
}
* ArchiveConfig, kayıtların S3 uyumlu bir depoya yüklenmesi. * * ⚠️ NEDEN VAR: denetim izi bugüne kadar yalnızca denetlenen makinede * duruyordu. Bastion'ı ele geçiren kayıtları da ele geçiriyor. * * ⚠️ YÜKLEME OTURUM YOLUNDA DEĞİL. Kayıt önce yerele yazılıyor; * yükleme ayrı bir döngüde, sonradan. Bu yüzden nesne deposunun * kesintisi bastion'ın kesintisi DEĞİL — bedeli, yüklenemeyen * kayıtların budanamaması ve diskin dolabilmesi (bkz. MinFree).
func (ArchiveConfig) Enabled ¶
func (a ArchiveConfig) Enabled() bool
Enabled, arşivlemenin açık olup olmadığı.
func (ArchiveConfig) SecretAccessKey ¶
func (a ArchiveConfig) SecretAccessKey() (string, error)
* SecretAccessKey, gizli anahtarı çözer. * * ⚠️ ORTAM DEĞİŞKENİ DOSYAYI GEÇERSİZ KILIYOR, tersi değil: systemd * EnvironmentFile ile çalışan bir kurulumun config'i değiştirmesi * gerekmesin. * * ⚠️ DOSYA İZNİ KONTROL EDİLİYOR. CA ve mühür anahtarları için bu * kontrol var; yükleme sırrı için olmaması, grup okunabilir bir * dosyanın sessizce kabul edilmesi demekti.
type AuthConfig ¶
type AuthConfig struct {
/*
* PublicKeyLogin, kullanıcıların kendi anahtarlarıyla girmesine
* izin verir. Yazılmazsa AÇIK.
*
* NEDEN KAPATILABİLİR: iki bacak var ve karıştırılıyor. Kullanıcının
* anahtarı GELEN bacakta, "postern'e kim olduğunu kanıtlama" işi;
* sertifika GİDEN bacakta, "hedefe bu kullanıcı adına açabilirim"
* işi. Tamamen SSO ile çalışan bir kurumda gelen bacaktaki anahtar
* kapısı hiç kullanılmıyor ama açık duruyor — ve o kapı IdP'ye
* BAKMIYOR. Kullanılmayan bir kapıyı kapatmak, saldırı yüzeyini
* kullanıldığı kadarına indirir.
*
* ⚠️ Kapatıldığında PublicKeyCallback HİÇ KURULMUYOR: sunucu
* publickey yöntemini teklif bile etmiyor. Kabul edip reddetmek,
* istemcinin deneme hakkını yakması ve duruşun dışarıdan
* görünmemesi demekti.
*/
PublicKeyLogin *bool `yaml:"public_key_login"`
}
* AuthConfig, bastion'a girişin kabul edilen yolları. * * ⚠️ Sıfır değeri "anahtar girişi AÇIK" olmalı — bu yüzden alan * `PublicKeyLogin *bool`, düz bool değil. Düz bool olsaydı yapılandırma * dosyasında satırı olmayan her mevcut kurulum, yükseltmeden sonra * anahtarla giremez hale gelirdi: sessizce herkesi kapı dışında * bırakan bir varsayılan.
func (AuthConfig) PublicKeyLoginEnabled ¶
func (a AuthConfig) PublicKeyLoginEnabled() bool
PublicKeyLoginEnabled, yazılmamış alan için varsayılan (açık).
type CAConfig ¶
type CAConfig struct {
KeyFile string `yaml:"key_file"`
}
CAConfig, sertifika otoritesi.
key_file, `postern ca init` ile üretilen özel anahtar. serve her oturumda bununla sertifika kesecek; ca.Load izin kontrolünü kendisi yapıyor.
type Config ¶
type Config struct {
Listen ListenConfig `yaml:"listen"`
HostKey string `yaml:"host_key"` // path to the bastion's own host private key
CA CAConfig `yaml:"ca"`
Database DatabaseConfig `yaml:"database"`
Session SessionConfig `yaml:"session"`
Sync SyncConfig `yaml:"sync"`
// Auth, bastion'ın KABUL ETTİĞİ giriş yolları.
Auth AuthConfig `yaml:"auth"`
// TargetProbe, hedefe bağlanıldığında makineyi TANIMA denemesi.
// VARSAYILAN KAPALI — bkz. TargetProbeConfig.
TargetProbe TargetProbeConfig `yaml:"target_probe"`
// SecretKeyFile, veritabanındaki şifreli ayarları açan ana anahtar
// (`postern secret init` üretir). Boş bırakılabilir: o zaman şifreli
// ayar okunamaz/yazılamaz ama bastion'ın geri kalanı çalışır.
//
// ⚠️ Bu dosya veritabanıyla AYNI yerde durmamalı: ikisi birlikte
// sızarsa şifrelemenin tek faydası (yedek/kopya senaryosu) kaybolur.
SecretKeyFile string `yaml:"secret_key_file"`
Recording RecordingConfig `yaml:"recording"`
// HTTP ve OIDC birlikte OOB girişini açar (S3.3). İkisi de boş
// bırakılabilir: o zaman bastion yalnızca public key kabul eder —
// mevcut kurulumlar hiçbir şey değiştirmeden çalışmaya devam eder.
HTTP HTTPConfig `yaml:"http"`
OIDC OIDCConfig `yaml:"oidc"`
// Shutdown, SIGTERM alındığında açık oturumlara ne olacağı.
Shutdown ShutdownConfig `yaml:"shutdown"`
}
func (*Config) OIDCEnabled ¶
OIDCEnabled, tarayıcı üzerinden OIDC girişinin yapılandırıldığı. Kimlik sağlayıcı ARTIK tek giriş yolu değil; adı da onu söylüyor.
func (Config) SSHEndpoint ¶
* SSHEndpoint, kullanıcıya GÖSTERİLECEK ssh adresi. * * ⚠️ NEDEN VAR: panel "ssh kullanıcı:hedef@bastion" komutunu * kopyalatıyor ve <bastion> yerine gerçek bir adres yazması gerekiyor. * Yer tutucu bırakmak, kopyalanan komutu yapıştırıldığı anda bozuk * yapardı; dinleme adresini olduğu gibi vermek ise ":2222" ya da * "0.0.0.0:2222" gibi dışarıda anlamsız bir şey verirdi. * * Sıra: açıkça yazılmış listen.external_addr; yoksa host'u * http.external_url'den (operatörün ZATEN beyan ettiği dış kimlik), * portu listen.addr'dan. * * Çözülemezse boş host dönüyor ve panel kopyalama seçeneğini hiç * göstermiyor — çalışmayacak bir komut vermektense hiç vermemek.
func (*Config) Validate ¶
Validate checks the config for missing fields and nonexistent files. It reports the first problem found; the error message names the offending field or path.
func (*Config) WebEnabled ¶
* WebEnabled, HTTP yüzeyinin (panel + yönetim API'si) yapılandırıldığı. * * ⚠️ OIDC'DEN AYRI. Eskiden tek bir yüklem vardı ve o da düpedüz * "issuer_url dolu mu" demekti; bütün HTTP yüzeyi onun içinde * kuruluyordu. Sonucu: dizini olan ama kimlik sağlayıcısı OLMAYAN bir * kurum postern'i panelsiz çalıştırmak zorundaydı — yani ürünün * yönetilebilir hâli bir Keycloak kurmaya bağlıydı. * * Bu ayrımın kazara bir port açmadığını doğrulamak gerekiyordu: * http.addr ile oidc.* bugün HEP-YA-HİÇ doğrulanıyor, dolayısıyla * "http.addr dolu, OIDC boş" bir yapılandırma zaten geçersizdi. Yeni * dinleyici ancak operatör bunu bilerek yazarsa açılıyor.
type DatabaseConfig ¶
type DatabaseConfig struct {
// DSN, PostgreSQL bağlantı dizesi. İki biçim de kabul edilir:
//
// postgres://postern:parola@db.local:5432/postern?sslmode=verify-full
// host=db.local user=postern dbname=postern sslmode=verify-full
//
// sslmode yazılmamışsa store.Open "verify-full" varsayar. libpq'nun
// varsayılanı olan "prefer" TLS kurulamazsa düz metne SESSİZCE
// düşer; bir bastion'ın kimlik verisi için bu kabul edilemez.
//
// ⚠️ Bu dize PAROLA taşır. Config dosyasına yazmak yerine
// POSTERN_DATABASE_DSN ortam değişkenini kullanmak tercih edilir —
// dolu olduğunda buradaki değerin yerine geçer. Şemadaki diğer
// sırların aksine bu, veritabanının KENDİSİNE ulaşmak için gerekli
// olduğundan settings tablosuna konulamıyor.
DSN string `yaml:"dsn"`
}
DatabaseConfig, kalıcı durumun tutulduğu PostgreSQL bağlantısı.
S3'ten itibaren kullanıcılar, roller, hedefler ve oturum denetim kaydı burada. Yönetimi paket doc'undaki sözleşmeye tabi: CLI ya da API, config değil.
type HTTPConfig ¶
type HTTPConfig struct {
// Addr, dinlenecek adres (":8088" gibi).
Addr string `yaml:"addr"`
// ExternalURL, KULLANICININ tarayıcısından erişilen kök
// ("https://bastion.warewave.io:8088" gibi). Login linkleri ve OIDC
// redirect_url bununla kurulur — Addr'dan türetilemez: bastion NAT/
// proxy arkasında olabilir, ":8088" dış dünyada bir anlam taşımaz.
ExternalURL string `yaml:"external_url"`
// TrustedProxies, X-Forwarded-For'una güvenilecek kaynak adresler
// ("10.0.0.0/8", "127.0.0.1"). BOŞ = başlık hiç okunmuyor.
//
// ⚠️ TLS için ters vekil ŞART koştuğumuz hâlde bu alan yoktu ve
// sonucu ölçüldü: vekil arkasında bütün istemciler tek adrese
// çöküyor, parola tahmini gecikmesi hesap bazına iniyor ve
// kimliği doğrulanmamış biri "admin" hesabını beş dakikada bir
// istekle panelden süresiz kilitleyebiliyordu. Ayrıntı ve ölçüm
// httpapi/trustedproxy.go'da.
//
// ⚠️ YALNIZCA GERÇEKTEN ÖNÜNDEKİ VEKİLİ YAZ. Buraya geniş bir
// aralık yazmak, o aralıktaki herkese kendi hız sınırı anahtarını
// VE denetim satırına yazılacak adresi seçtirmek olur.
//
// ⚠️ ARTIK BİR DENETİM AYARI DA. Panel terminali oturumu açarken
// kaynak adresi buradan çözüyor; ayarlanmadığında sessions.src_ip'ye
// vekilin adresi yazılıyor ve "bu kabuk nereden açıldı" sorusu
// panelden açılan her oturum için aynı cevabı veriyor.
TrustedProxies []string `yaml:"trusted_proxies"`
// TerminalEnabled, tarayıcıdaki web terminalini açar. VARSAYILAN
// KAPALI ve bu bilinçli bir güvenlik kararı: web terminali, SPA'daki
// herhangi bir XSS'i hedef makinede komut çalıştırma yetkisine
// çevirir. Bugün aynı XSS yalnızca API'yi kullanabilir — sınırlı bir
// zarar. Terminale ihtiyacı olmayan kurulum o yüzeyi hiç taşımasın;
// kod var diye kapı açık olmak zorunda değil.
//
// Açan kurulum için şartlar: HTTPS (external_url https), sıkı CSP
// (securityHeaders zaten kuruyor) ve WS upgrade'inde Origin kontrolü.
TerminalEnabled bool `yaml:"terminal_enabled"`
}
HTTPConfig, tarayıcıya bakan uçların dinleyicisi.
type ListenConfig ¶
type ListenConfig struct {
Addr string `yaml:"addr"` // e.g. ":2222"
/*
* ExternalAddr, KULLANICININ ssh ile bağlandığı adres
* ("bastion.warewave.io:2222" gibi).
*
* ⚠️ Addr'dan TÜRETİLEMEZ — http.external_url'in var olma
* gerekçesinin aynısı: ":2222" dış dünyada bir şey ifade etmiyor,
* "0.0.0.0" hiç etmiyor, ve bastion NAT ya da yük dengeleyici
* arkasında olabilir.
*
* Yazılmazsa panel şunu türetiyor: host'u http.external_url'den,
* portu Addr'dan. Kurulumların çoğunda doğru olan bu; olmadığı yerde
* burası yazılır. Bu değer yalnızca panelin GÖSTERDİĞİ komutu
* etkiliyor — hiçbir erişim kararına girmiyor.
*/
ExternalAddr string `yaml:"external_addr"`
// MaxConns, eşzamanlı SSH bağlantısı üst sınırı (varsayılan 256).
MaxConns int `yaml:"max_conns"`
// MaxConnsPerIP, tek kaynaktan eşzamanlı bağlantı (varsayılan 8).
//
// ⚠️ L4 yük dengeleyici ya da TCP vekil ARKASINDA kapatılmalı (-1):
// orada bütün kullanıcılar dengeleyicinin IP'siyle görünür ve bu
// sınır 9. kullanıcıda kesintiye döner. postern PROXY protokolü
// konuşmuyor.
MaxConnsPerIP int `yaml:"max_conns_per_ip"`
// HandshakeTimeout, kimlik doğrulanana kadar tanınan süre
// (varsayılan 30s).
//
// Kapattığı açık somut: SSH sürüm satırı bayt bayt okunuyor, yani
// saatte bir bayt gönderen bir istemci kimliğini hiç doğrulamadan
// bir goroutine ve bir dosya tanıtıcısı tutabiliyordu.
//
// Tarayıcı girişi (OOB) bu süreden UZUN sürer ve süre onay
// beklenirken ayrıca uzatılır — bkz. internal/sshd/limits.go.
// Yani buraya oobTimeout'tan kısa bir değer yazmak girişi bozmaz.
HandshakeTimeout time.Duration `yaml:"handshake_timeout"`
// MaxAuthTries, bağlantı başına kimlik doğrulama denemesi
// (varsayılan 4; x/crypto'nun kendi varsayılanı 6).
//
// ⚠️ Çok düşürmeyin: OpenSSH doğru anahtarı bulana kadar ajandaki
// TÜM anahtarları sırayla sunar, yani 5 anahtarı olan bir geliştirici
// 4'te "too many authentication failures" alır. Çözüm istemci
// tarafında IdentitiesOnly=yes.
MaxAuthTries int `yaml:"max_auth_tries"`
// MaxChannelsPerConn, bağlantı başına eşzamanlı oturum kanalı
// (varsayılan 10).
//
// Bu kümedeki TEK kimlik doğrulama SONRASI sınır: her kanal bir
// hedef bağlantısı, bir .cast dosyası ve bir denetim satırı demek.
MaxChannelsPerConn int `yaml:"max_channels_per_conn"`
// MaxPendingLogins, aynı anda onay bekleyen tarayıcı girişi
// (varsayılan 32).
MaxPendingLogins int `yaml:"max_pending_logins"`
}
func (ListenConfig) HandshakeTimeoutOrDefault ¶
func (c ListenConfig) HandshakeTimeoutOrDefault() time.Duration
func (ListenConfig) MaxAuthTriesOrDefault ¶
func (c ListenConfig) MaxAuthTriesOrDefault() int
func (ListenConfig) MaxChannelsOrDefault ¶
func (c ListenConfig) MaxChannelsOrDefault() int
func (ListenConfig) MaxConnsOrDefault ¶
func (c ListenConfig) MaxConnsOrDefault() int
func (ListenConfig) MaxConnsPerIPOrDefault ¶
func (c ListenConfig) MaxConnsPerIPOrDefault() int
func (ListenConfig) MaxPendingLoginsOrDefault ¶
func (c ListenConfig) MaxPendingLoginsOrDefault() int
type OIDCConfig ¶
type OIDCConfig struct {
IssuerURL string `yaml:"issuer_url"`
ClientID string `yaml:"client_id"`
// ClientSecret public client'ta boş — PKCE onun yerini tutuyor.
ClientSecret string `yaml:"client_secret"`
}
OIDCConfig, kimlik sağlayıcısı. auth.OIDCConfig'e birebir taşınır.
type RecordingConfig ¶
type RecordingConfig struct {
Dir string `yaml:"dir"` // session recordings root
// RecordInput defaults to false on purpose: keystrokes include
// passwords. See docs/history/postern-PLAN.md S1.7, design note 4.
RecordInput bool `yaml:"record_input"`
/*
* Retain, kayıtların saklanma süresi ("90d", "2160h").
*
* ⚠️ VARSAYILAN "HİÇ SİLME" ve bu bilinçli. Budama denetim kanıtı
* silmek demek; ayarı yazmayan bir kurulumda postern'in kendi
* başına kanıt silmesi, sakladığı şeyin ne olduğunu anlamamak
* olurdu. Operatör süreyi SÖYLEYENE kadar hiçbir şey silinmiyor.
*
* Sınırsız büyümenin cevabı bu ayar DEĞİL: cevabı MinFree, ve o
* varsayılan olarak açık.
*/
Retain string `yaml:"retain"`
/*
* MinFree, yeni oturum açmayı reddetmeye başladığımız boş alan
* ("2GiB"). Boş bırakılırsa varsayılan kullanılıyor; "0" kapatıyor.
*
* ⚠️ VARSAYILAN AÇIK, ve gerekçesi dolu diskin bugün ne yaptığı:
* postern kayıt tutamayınca oturumu reddediyor (denetim öncelikli
* politika, doğru karar) ama proxy AÇIK oturumları da kapatıyor.
* Yani disk dolduğunda yalnızca yeni girişler durmuyor, çalışan
* işler de kesiliyor.
*
* Eşik aynı reddi DAHA ERKEN veriyor: yeni oturum reddediliyor,
* çalışanlar yaşamaya devam ediyor ve operatörün yer açmak için
* zamanı oluyor. "Reddetmeye başlamak" bir kayıp değil; kayıp,
* onu diskin kendisinin haber vermesini beklemek.
*/
MinFree string `yaml:"min_free"`
// Archive, kayıtların nesne deposuna kopyalanması. Boş = kapalı.
Archive ArchiveConfig `yaml:"archive"`
}
func (RecordingConfig) MinFreeBytes ¶
func (r RecordingConfig) MinFreeBytes() (uint64, error)
* MinFreeBytes, eşiği bayta çevirir. * * "2GiB", "500MiB", "1073741824" kabul ediliyor. Boş bırakmak * VARSAYILANI seçiyor; açıkça "0" yazmak KAPATIYOR — ikisi ayrı * niyetler ve aynı değere düşmemeleri gerekiyor.
func (RecordingConfig) RetainDuration ¶
func (r RecordingConfig) RetainDuration() (time.Duration, error)
* RetainDuration, kayıt saklama süresini çözer. * * ⚠️ ÇÖZÜLEMEYEN DEĞER HATA, "varsayılana dön" DEĞİL. "90gun" yazan * operatör, sessizce "hiç silme"ye düşerse diskinin neden dolduğunu * anlamaz; tersi daha kötü olurdu — yanlış çözülen bir süre, olması * gerekenden fazlasını siler.
type SessionConfig ¶
type SessionConfig struct {
// AcceptEnv, kullanıcıdan hedefe geçmesine izin verilen ortam
// değişkeni adları. Sondaki * joker: "LC_*" tüm LC_ ile
// başlayanları kapsar.
//
// Yazılmazsa varsayılan LANG ve LC_* (OpenSSH'ın yaygın AcceptEnv
// yapılandırmasıyla aynı). BOŞ LİSTE yazmak "hiçbiri" demek —
// "yazmamak" ile "boş yazmak" farklı şeyler.
//
// ⚠️ Buraya PATH, LD_PRELOAD, BASH_ENV gibi bir ad eklemek hedefte
// NE ÇALIŞACAĞINI kullanıcının eline verir. Whitelist'in var olma
// sebebi tam olarak bu.
AcceptEnv []string `yaml:"accept_env"`
// IdleTimeout, iki yönde de hiç bayt akmayan oturumun kapatılma
// süresi. VARSAYILAN KAPALI (0).
//
// Kapalı olması bilinçli: "boşta" tanımı bayt akışıdır, tuş vuruşu
// değil. Bir saat süren `make -j` çıktı üretmediği anda ölmemeli.
// Makul görünen bir varsayılan koymak, o derlemeyi ortasından kesmek
// demek olurdu.
//
// ÖLÜ EŞE KARŞI DEĞİL: TCP keepalive onu zaten ~2,5 dakikada fark
// ediyor. Bunun gerekçesi denetim — üretim makinesinde unutulmuş
// root kabuğu.
IdleTimeout time.Duration `yaml:"idle_timeout"`
/*
* SFTP, `subsystem sftp` kanalını açar. VARSAYILAN KAPALI.
*
* ⚠️ Kapalı olması bilinçli. Bu kanal uzun süre HİÇ yoktu ve
* gerekçesi ölçülmüştü: transfer terminal kaydına ham ikili olarak
* düşüyor, "kim hangi dosyayı aldı" cevapsız kalıyordu. Artık
* dosya seviyesinde denetleniyor (internal/sftpaudit) — ama
* varsayılan açık gelseydi, yükseltme yapan bir operatör hiçbir
* şey yapmadan yeni bir veri ÇIKIŞ yolu kazanırdı. Yeni bir çıkış
* yolu, açıkça istenerek açılır.
*
* Açıkken her dosya olayı session_files tablosuna yazılıyor;
* yazılamıyorsa oturum kapanıyor.
*/
SFTP bool `yaml:"sftp"`
// MaxLifetime, oturumun mutlak ömrü. VARSAYILAN KAPALI (0).
//
// Gerekçesi somut: süreli rol atamaları (AssignRole expiresAt)
// oturum ORTASINDA yeniden denetlenmiyor. Süresi dolmadan bir dakika
// önce açılan bir oturum, bugün kendi yetkisinden sonsuza kadar uzun
// yaşıyor.
MaxLifetime time.Duration `yaml:"max_lifetime"`
}
SessionConfig, oturum kanalının davranış sınırları.
type ShutdownConfig ¶
type ShutdownConfig struct {
/*
* DrainTimeout, açık oturumların kendiliğinden bitmesi için
* beklenen süre. Dolduğunda oturumlar SEBEBİYLE kapatılıyor:
* kullanıcı "bastion kapanıyor" cümlesini görüyor, kayıt düzgün
* kapanıyor ve arşiv kuyruğuna giriyor.
*
* ⚠️ SINIRSIZ BEKLEME SEÇENEĞİ YOK ve bu bilinçli: tek bir uzun
* oturum yeniden başlatmayı süresiz bloklardı, init sistemi de
* sonunda SIGKILL gönderip başladığımız yere — yarım kayıtlara —
* geri dönerdi. Beklemenin bir sonu olmalı ve sonu biz
* söylemeliyiz.
*/
DrainTimeout time.Duration `yaml:"drain_timeout"`
}
* ShutdownConfig, kapanışın açık oturumlara davranışı. * * ⚠️ NEDEN VAR: Serve, ctx iptal edilince dinleyiciyi kapatıp HEMEN * dönüyordu ve bağlantıları taşıyan goroutine'leri bekleyen hiçbir şey * yoktu. Süreç ölürken herkesin oturumu ortasından kopuyor, kayıtları * yarım kapanıyor ve — Close hiç çalışmadığı için — arşiv kuyruğuna * hiç girmiyorlardı. Yani bir yeniden başlatma, o an bağlı olan * herkesin kaydını hem yarım hem yüklenemez bırakıyordu.
func (ShutdownConfig) DrainTimeoutOrDefault ¶
func (c ShutdownConfig) DrainTimeoutOrDefault() time.Duration
DrainTimeoutOrDefault, yazılmamışsa 30 saniye.
systemd'nin varsayılan TimeoutStopSec'i 90 saniye; 30 saniye hem kullanıcının cümleyi görüp çıkmasına yetiyor hem de init sisteminin sabrının epey altında kalıyor.
type SyncConfig ¶
type SyncConfig struct {
Enabled bool `yaml:"enabled"`
// Interval, koşular arası süre (varsayılan 15m).
Interval time.Duration `yaml:"interval"`
// Grace, kullanıcı dizinde bulunamadıktan sonra iptal için beklenen
// süre (varsayılan 1h). Kısa bir çoğaltma gecikmesi ya da bakım
// penceresi yetkileri silmesin diye.
Grace time.Duration `yaml:"grace"`
// Timeout, tek bir koşunun üst sınırı (varsayılan 5m).
Timeout time.Duration `yaml:"timeout"`
// --- patlama yarıçapı tavanları ---
//
// MaxZeroFraction ve MinZeroFloor BİRLİKTE aşılmalı: küçük
// kurumlarda oran tek kişiyle aşılır, büyüklerinde taban tek başına
// anlamsız kalır.
MaxZeroFraction float64 `yaml:"max_zero_fraction"` // varsayılan 0.10
MinZeroFloor int `yaml:"min_zero_floor"` // varsayılan 3
MaxUnknownFraction float64 `yaml:"max_unknown_fraction"` // varsayılan 0.25
MaxRevokePerRun int `yaml:"max_revoke_per_run"` // varsayılan 25
// DryRun, kararları hesaplar ve raporlar ama HİÇBİR ŞEY YAZMAZ.
// Açmadan önce bir süre bununla koşturmak doğru yol.
DryRun bool `yaml:"dry_run"`
}
SyncConfig, periyodik dizin senkronizasyonu.
⚠️ VARSAYILAN KAPALI. Açıldığında bu döngü OTOMATİK OLARAK YETKİ İPTAL EDER; yanlış yapılandırılmış bir dizin ya da fark edilmeyen bir kesinti, kimsenin giremediği bir bastion demek.
Tavanlar neden config'te, settings tablosunda değil: bunlar kimlik verisi değil, otomatik toplu iptalin ÜST SINIRI. Onu yükseltebilmek için host'a erişmek gerekmeli — admin bayrağının yalnızca CLI'dan verilebilmesiyle aynı gerekçe. (LDAP'ın BAĞLANTI ayarları settings tablosunda kalıyor; panelden düzenlenmesi gereken onlar.)
func (SyncConfig) GraceOrDefault ¶
func (c SyncConfig) GraceOrDefault() time.Duration
func (SyncConfig) IntervalOrDefault ¶
func (c SyncConfig) IntervalOrDefault() time.Duration
func (SyncConfig) MaxRevokePerRunOrDefault ¶
func (c SyncConfig) MaxRevokePerRunOrDefault() int
func (SyncConfig) MaxUnknownFractionOrDefault ¶
func (c SyncConfig) MaxUnknownFractionOrDefault() float64
func (SyncConfig) MaxZeroFractionOrDefault ¶
func (c SyncConfig) MaxZeroFractionOrDefault() float64
func (SyncConfig) MinZeroFloorOrDefault ¶
func (c SyncConfig) MinZeroFloorOrDefault() int
func (SyncConfig) TimeoutOrDefault ¶
func (c SyncConfig) TimeoutOrDefault() time.Duration
type TargetProbeConfig ¶
type TargetProbeConfig struct {
// Enabled, tanımayı açar. Varsayılan false.
Enabled bool `yaml:"enabled"`
// Refresh, aynı hedefin ne kadar sonra yeniden sorulacağı.
// Yazılmazsa 24 saat. Her oturumda sormak, hedefin günlüklerini
// postern'in gürültüsüyle doldururdu.
Refresh time.Duration `yaml:"refresh"`
// Timeout, tanıma komutlarının tamamı için üst sınır.
// Yazılmazsa 5 saniye.
//
// ⚠️ Kısa olması ŞART: tanıma kullanıcının oturumuyla aynı TCP
// bağlantısını paylaşıyor ve asılı bir komut o bağlantıyı meşgul
// eder. Oturumun kendisi hiçbir koşulda tanımayı BEKLEMEZ.
Timeout time.Duration `yaml:"timeout"`
}
* TargetProbeConfig, hedefte KOMUT ÇALIŞTIRARAK yapılan tanıma. * * ⚠️ VARSAYILAN KAPALI VE ÖYLE KALMALI. Kapalıyken postern hedefte * kullanıcının oturumu dışında hiçbir şey çalıştırmaz; hedef hakkında * bildiği her şey el sıkışmadan gelir (SSH afişi, anahtar türü, süre). * Bu, bir bastion'ın taşıyabileceği en dar yetki ve birçok kurumun * denetim politikası tam olarak bunu şart koşuyor. * * Açıldığında ne değişir, açıkça: * * 1. postern, kullanıcının AÇTIĞI BAĞLANTI üzerinde ek bir exec kanalı * açar ve sabit birkaç okuma komutu çalıştırır. Komutlar hedefin * kendi günlüklerinde O KULLANICININ adına görünür — kullanıcının * yazmadığı komutlar, kullanıcının hesabında. * 2. Bu yüzden her koşu admin_log'a yazılır: kimin bağlantısında, * hangi hedefte, ne çalıştırıldı. * * ⚠️ KOMUT LİSTESİ YAPILANDIRILAMAZ ve bu kasıtlı. Operatörün komut * yazabildiği bir alan, config dosyasına erişebilen herkese denetim * altındaki HER MAKİNEDE uzaktan komut çalıştırma yetkisi verirdi — * yani bastion'ı tam da engellemek için var olduğu şeye çevirirdi. * Çalışanlar upstream.ProbeCommands içinde, salt okunur ve sabit.
func (TargetProbeConfig) RefreshOrDefault ¶
func (c TargetProbeConfig) RefreshOrDefault() time.Duration
RefreshOrDefault, yazılmamış Refresh için varsayılan.
func (TargetProbeConfig) TimeoutOrDefault ¶
func (c TargetProbeConfig) TimeoutOrDefault() time.Duration
TimeoutOrDefault, yazılmamış Timeout için varsayılan.