init
This commit is contained in:
commit
23c7133fa9
33 files changed
+2896
No files matched your search
@@ -0,0 +1,81 @@
|
||||
package sysadm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
// dropInPath is the sshd config snippet this tool owns. Modern OpenSSH
|
||||
// (Debian/Ubuntu/RHEL defaults) includes /etc/ssh/sshd_config.d/*.conf from
|
||||
// the main sshd_config automatically; DropInIncluded checks that assumption.
|
||||
const dropInPath = "/etc/ssh/sshd_config.d/50-ssh-access-tui.conf"
|
||||
|
||||
const dropInTemplate = `# Managed by ssh-access-tui. Do not edit by hand — re-run
|
||||
# "ssh-access-tui install" to regenerate this file.
|
||||
#
|
||||
# Baseline (defense-in-depth) restrictions for all jump/forward-only
|
||||
# accounts. The authoritative per-user host whitelist lives in each
|
||||
# account's authorized_keys "permitopen=" options, not here — this block
|
||||
# only backstops that in case a key's options were ever mis-set.
|
||||
Match Group ` + JumpGroup + `
|
||||
PermitTTY no
|
||||
X11Forwarding no
|
||||
AllowAgentForwarding no
|
||||
AllowStreamLocalForwarding no
|
||||
AllowTcpForwarding local
|
||||
PermitTunnel no
|
||||
Match all
|
||||
|
||||
# VERBOSE logging records which destination host:port each forwarded
|
||||
# channel was opened to — needed for the audit trail of "who connected
|
||||
# where", since plain port-forward sessions don't show up in ` + "`who`" + `.
|
||||
LogLevel VERBOSE
|
||||
`
|
||||
|
||||
// DropInIncluded reports whether the main sshd_config appears to include
|
||||
// the sshd_config.d drop-in directory. If not, the caller should tell the
|
||||
// admin to add "Include /etc/ssh/sshd_config.d/*.conf" manually.
|
||||
func DropInIncluded() bool {
|
||||
data, err := os.ReadFile("/etc/ssh/sshd_config")
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return contains(string(data), "sshd_config.d")
|
||||
}
|
||||
|
||||
// InstallSSHDConfig writes the managed drop-in, validates it with
|
||||
// `sshd -t`, and reloads the running sshd. It refuses to reload (leaving the
|
||||
// previous config live) if validation fails.
|
||||
func InstallSSHDConfig() error {
|
||||
if err := RequireRoot(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.WriteFile(dropInPath, []byte(dropInTemplate), 0o644); err != nil {
|
||||
return fmt.Errorf("write %s: %w", dropInPath, err)
|
||||
}
|
||||
if out, err := exec.Command("sshd", "-t").CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("sshd config now invalid, NOT reloaded — fix and rerun: %s", out)
|
||||
}
|
||||
if err := reloadSSHD(); err != nil {
|
||||
return fmt.Errorf("config valid but reload failed: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func reloadSSHD() error {
|
||||
// Service name differs across distros; try both, ignore first failure.
|
||||
if err := exec.Command("systemctl", "reload", "ssh").Run(); err == nil {
|
||||
return nil
|
||||
}
|
||||
return exec.Command("systemctl", "reload", "sshd").Run()
|
||||
}
|
||||
|
||||
func contains(s, substr string) bool {
|
||||
for i := 0; i+len(substr) <= len(s); i++ {
|
||||
if s[i:i+len(substr)] == substr {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
Reference in new issue
Block a user