Loading onboard/onboard.go +20 −0 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ import ( "encoding/base64" "errors" "fmt" "log/syslog" "os" "strings" "time" Loading @@ -20,9 +21,27 @@ import ( "golang.org/x/crypto/ssh" ) // logAuthFailure logs a shibboleth failure to the auth syslog facility // so that tools like CrowdSec can rate-limit abusive IPs. func logAuthFailure(clientIP, fingerprint string) { sl, err := syslog.New(syslog.LOG_AUTHPRIV|syslog.LOG_WARNING, "bulletin") if err != nil { return } defer sl.Close() _ = sl.Warning(fmt.Sprintf("Failed shibboleth from %s (key %s)", clientIP, fingerprint)) } // Run executes the onboarding flow. fingerprint is the SHA256 // fingerprint of the connecting key. pubkeyStr is "type:base64". func Run(fingerprint, pubkeyStr string) int { // Parse client IP from SSH_CONNECTION for auth logging. clientIP := "unknown" if conn := os.Getenv("SSH_CONNECTION"); conn != "" { if parts := strings.Fields(conn); len(parts) >= 1 { clientIP = parts[0] } } // Open DB. store, err := storage.Open() if err != nil { Loading Loading @@ -61,6 +80,7 @@ func Run(fingerprint, pubkeyStr string) int { // Rate limit: increasing delay on wrong answers. delay := time.Duration(i+1) * 2 * time.Second time.Sleep(delay) logAuthFailure(clientIP, fingerprint) fmt.Println("Incorrect answer. Access denied.") return 1 } Loading security/sandbox_linux.go +16 −0 Original line number Diff line number Diff line Loading @@ -61,6 +61,20 @@ func InitSandbox() error { } } // Syslog socket paths (varies by distro/init system). potentialSyslogSockets := []string{ "/dev/log", // traditional / symlink on systemd "/run/systemd/journal/dev-log", // systemd journal socket "/var/run/syslog", // macOS / some BSDs "/var/run/log", // FreeBSD } var syslogSockets []string for _, s := range potentialSyslogSockets { if _, err := os.Stat(s); err == nil { syslogSockets = append(syslogSockets, s) } } err := landlock.V5.BestEffort().Restrict( // BULLETIN data directory (DB, WAL, SHM files). landlock.RWDirs(bulldir), Loading @@ -86,6 +100,8 @@ func InitSandbox() error { // TLS: CA certificate bundles and directory for HTTPS verification. landlock.ROFiles(caFiles...), landlock.RODirs(caDirs...), // Syslog socket for auth event logging (onboarding failures). landlock.RWFiles(syslogSockets...), ) if err != nil { return fmt.Errorf("failed to apply landlock sandbox: %w", err) Loading security/sandbox_openbsd.go +3 −1 Original line number Diff line number Diff line Loading @@ -50,6 +50,8 @@ func InitSandbox() error { {"/etc/hosts", "r"}, // TLS: CA certificate bundle for HTTPS verification. {"/etc/ssl/cert.pem", "r"}, // Syslog socket for auth event logging (onboarding failures). {"/dev/log", "rw"}, } for _, u := range unveils { Loading @@ -74,7 +76,7 @@ func InitSandbox() error { // tty - terminal operations (editor, REPL) // inet - outbound network (SSH FETCH from forges) // dns - DNS resolution (for SSH FETCH) if err := unix.PledgePromises("stdio rpath wpath cpath flock tty inet dns"); err != nil { if err := unix.PledgePromises("stdio rpath wpath cpath flock tty inet dns unix"); err != nil { return fmt.Errorf("pledge: %w", err) } Loading Loading
onboard/onboard.go +20 −0 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ import ( "encoding/base64" "errors" "fmt" "log/syslog" "os" "strings" "time" Loading @@ -20,9 +21,27 @@ import ( "golang.org/x/crypto/ssh" ) // logAuthFailure logs a shibboleth failure to the auth syslog facility // so that tools like CrowdSec can rate-limit abusive IPs. func logAuthFailure(clientIP, fingerprint string) { sl, err := syslog.New(syslog.LOG_AUTHPRIV|syslog.LOG_WARNING, "bulletin") if err != nil { return } defer sl.Close() _ = sl.Warning(fmt.Sprintf("Failed shibboleth from %s (key %s)", clientIP, fingerprint)) } // Run executes the onboarding flow. fingerprint is the SHA256 // fingerprint of the connecting key. pubkeyStr is "type:base64". func Run(fingerprint, pubkeyStr string) int { // Parse client IP from SSH_CONNECTION for auth logging. clientIP := "unknown" if conn := os.Getenv("SSH_CONNECTION"); conn != "" { if parts := strings.Fields(conn); len(parts) >= 1 { clientIP = parts[0] } } // Open DB. store, err := storage.Open() if err != nil { Loading Loading @@ -61,6 +80,7 @@ func Run(fingerprint, pubkeyStr string) int { // Rate limit: increasing delay on wrong answers. delay := time.Duration(i+1) * 2 * time.Second time.Sleep(delay) logAuthFailure(clientIP, fingerprint) fmt.Println("Incorrect answer. Access denied.") return 1 } Loading
security/sandbox_linux.go +16 −0 Original line number Diff line number Diff line Loading @@ -61,6 +61,20 @@ func InitSandbox() error { } } // Syslog socket paths (varies by distro/init system). potentialSyslogSockets := []string{ "/dev/log", // traditional / symlink on systemd "/run/systemd/journal/dev-log", // systemd journal socket "/var/run/syslog", // macOS / some BSDs "/var/run/log", // FreeBSD } var syslogSockets []string for _, s := range potentialSyslogSockets { if _, err := os.Stat(s); err == nil { syslogSockets = append(syslogSockets, s) } } err := landlock.V5.BestEffort().Restrict( // BULLETIN data directory (DB, WAL, SHM files). landlock.RWDirs(bulldir), Loading @@ -86,6 +100,8 @@ func InitSandbox() error { // TLS: CA certificate bundles and directory for HTTPS verification. landlock.ROFiles(caFiles...), landlock.RODirs(caDirs...), // Syslog socket for auth event logging (onboarding failures). landlock.RWFiles(syslogSockets...), ) if err != nil { return fmt.Errorf("failed to apply landlock sandbox: %w", err) Loading
security/sandbox_openbsd.go +3 −1 Original line number Diff line number Diff line Loading @@ -50,6 +50,8 @@ func InitSandbox() error { {"/etc/hosts", "r"}, // TLS: CA certificate bundle for HTTPS verification. {"/etc/ssl/cert.pem", "r"}, // Syslog socket for auth event logging (onboarding failures). {"/dev/log", "rw"}, } for _, u := range unveils { Loading @@ -74,7 +76,7 @@ func InitSandbox() error { // tty - terminal operations (editor, REPL) // inet - outbound network (SSH FETCH from forges) // dns - DNS resolution (for SSH FETCH) if err := unix.PledgePromises("stdio rpath wpath cpath flock tty inet dns"); err != nil { if err := unix.PledgePromises("stdio rpath wpath cpath flock tty inet dns unix"); err != nil { return fmt.Errorf("pledge: %w", err) } Loading