sshkeeper/internal/ssh/configgen.go

101 lines
2.3 KiB
Go

package ssh
import (
"fmt"
"os"
"strings"
"time"
"github.com/mirivlad/sshkeeper/internal/model"
)
// GenerateConfig creates OpenSSH config content from server profiles
func GenerateConfig(servers []*model.Server) (string, error) {
var sb strings.Builder
sb.WriteString("# Generated by sshkeeper. Do not edit manually.\n")
sb.WriteString(fmt.Sprintf("# Generated at: %s\n\n", time.Now().Format(time.RFC3339)))
for _, s := range servers {
sb.WriteString(fmt.Sprintf("Host %s\n", s.Alias))
sb.WriteString(fmt.Sprintf(" HostName %s\n", s.Host))
if s.Port != 22 {
sb.WriteString(fmt.Sprintf(" Port %d\n", s.Port))
}
if s.User != "" {
sb.WriteString(fmt.Sprintf(" User %s\n", s.User))
}
if s.IdentityFile != "" && s.AuthMethod != model.AuthPassword {
sb.WriteString(fmt.Sprintf(" IdentityFile %s\n", s.IdentityFile))
}
if s.ProxyJump != "" {
sb.WriteString(fmt.Sprintf(" ProxyJump %s\n", s.ProxyJump))
}
sb.WriteString("\n")
}
return sb.String(), nil
}
// WriteConfig writes the generated config to ~/.ssh/config.d/sshkeeper.conf
func WriteConfig(servers []*model.Server) error {
home, err := os.UserHomeDir()
if err != nil {
return err
}
configD := home + "/.ssh/config.d"
if err := os.MkdirAll(configD, 0700); err != nil {
return err
}
content, err := GenerateConfig(servers)
if err != nil {
return err
}
configFile := configD + "/sshkeeper.conf"
tmpFile := configFile + ".tmp"
if err := os.WriteFile(tmpFile, []byte(content), 0600); err != nil {
return err
}
return os.Rename(tmpFile, configFile)
}
// InstallInclude adds "Include ~/.ssh/config.d/*.conf" to ~/.ssh/config
func InstallInclude() error {
home, err := os.UserHomeDir()
if err != nil {
return err
}
sshDir := home + "/.ssh"
configD := sshDir + "/config.d"
mainConfig := sshDir + "/config"
if err := os.MkdirAll(configD, 0700); err != nil {
return err
}
includeLine := "Include ~/.ssh/config.d/*.conf"
// Check if already included
if data, err := os.ReadFile(mainConfig); err == nil {
if strings.Contains(string(data), "Include ~/.ssh/config.d") {
return nil
}
}
// Prepend include line
f, err := os.OpenFile(mainConfig, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600)
if err != nil {
return err
}
defer f.Close()
_, err = f.WriteString("\n" + includeLine + "\n")
return err
}