Skip to content

Commit

Permalink
Implement sshs config generator from known_hosts files
Browse files Browse the repository at this point in the history
  • Loading branch information
quantumsheep committed Feb 9, 2022
1 parent f882b24 commit 46ee11e
Show file tree
Hide file tree
Showing 2 changed files with 169 additions and 19 deletions.
148 changes: 148 additions & 0 deletions cmd/generate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
package cmd

import (
"fmt"
"log"
"os"
"regexp"
"strings"

"github.com/mitchellh/go-homedir"
"github.com/quantumsheep/sshconfig"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

var generateCmd = &cobra.Command{
Use: "generate",
Short: "Generate a ssh configuration from different sources",
Version: rootCmd.Version,
Run: runGenerate,
}

func init() {
flags := generateCmd.Flags()
flags.Bool("known-hosts", false, "Generate from known_hosts file")
flags.String("known-hosts-file", "~/.ssh/known_hosts", "Path of known_hosts file")

viper.SetDefault("author", "quantumsheep <[email protected]>")
viper.SetDefault("license", "MIT")
}

func runGenerate(cmd *cobra.Command, args []string) {
flags := cmd.Flags()

knownHosts := false

if enabled, e := flags.GetBool("known-hosts"); e == nil {
knownHosts = enabled
}

if !knownHosts {
cmd.Help()
os.Exit(0)
}

configs := make([]*KnownHostConfig, 0)

if knownHosts {
knownHostsFile := "~/.ssh/known_hosts"

if str, e := flags.GetString("known-hosts-file"); e == nil && str != "" {
knownHostsFile = str
}

knownHostsFile, e := homedir.Expand(knownHostsFile)
if e != nil {
log.Fatal(e)
}

// open file
bytes, e := os.ReadFile(knownHostsFile)
if e != nil {
log.Fatal(e)
}

data := string(bytes)
rx := regexp.MustCompile(`^((\[(?P<HostWithPort>.*?)\]:(?P<Port>\d+))|((?P<DomainName>.*?),(?P<IP>.*?))|(?P<Host>.*?))[ ]`)

lines := strings.Split(data, "\n")
for _, line := range lines {
if line == "" {
continue
}

config := NewKnownHostConfig()

matches := rx.FindStringSubmatch(line)

if host := matches[rx.SubexpIndex("HostWithPort")]; host != "" {
config.Host = host
config.HostName = host
config.Port = matches[rx.SubexpIndex("Port")]
} else if host := matches[rx.SubexpIndex("DomainName")]; host != "" {
config.Host = host
config.HostName = matches[rx.SubexpIndex("IP")]
} else if host := matches[rx.SubexpIndex("Host")]; host != "" {
config.Host = host
config.HostName = host
}

configs = append(configs, config)
}
}

config := strings.Join(KnownHostConfigStrings(KnownHostConfigUniques(configs)), "\n\n")
fmt.Println(config)
}

type KnownHostConfig struct {
*sshconfig.SSHHost

Host string
Port string
}

func NewKnownHostConfig() *KnownHostConfig {
return &KnownHostConfig{
SSHHost: &sshconfig.SSHHost{},
Port: "22",
}
}

func (c *KnownHostConfig) String() string {
return "Host " + c.Host +
"\n\tHostname " + c.HostName +
"\n\tPort " + c.Port
}

func KnownHostConfigStrings(configs []*KnownHostConfig) []string {
list := make([]string, 0)

for _, item := range configs {
list = append(list, item.String())
}

return list
}

func KnownHostConfigUniques(configs []*KnownHostConfig) []*KnownHostConfig {
list := make([]*KnownHostConfig, 0)

for _, item := range configs {
found := false

for _, item2 := range list {
if item.Host == item2.Host && item.HostName == item2.HostName && item.Port == item2.Port {
found = true
break
}
}

if !found {
list = append(list, item)
}
}

return list
}
40 changes: 21 additions & 19 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,29 @@ var rootCmd = &cobra.Command{
Use: "sshs",
Short: "ssh clients manager",
Version: Version,
Run: run,
Run: runRoot,
}

func run(cmd *cobra.Command, args []string) {
func init() {
flags := rootCmd.Flags()
flags.StringP("search", "s", "", "Host search filter")
flags.StringP("config", "c", "~/.ssh/config", "SSH config file")
flags.BoolP("proxy", "p", false, "Display full ProxyCommand")

viper.SetDefault("author", "quantumsheep <[email protected]>")
viper.SetDefault("license", "MIT")

rootCmd.AddCommand(generateCmd)
}

func Execute() {
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}

func runRoot(cmd *cobra.Command, args []string) {
flags := cmd.Flags()

sshConfigPath := "~/.ssh/config"
Expand Down Expand Up @@ -266,20 +285,3 @@ func run(cmd *cobra.Command, args []string) {
ui.Render(grid)
}
}

func Execute() {
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}

func init() {
flags := rootCmd.PersistentFlags()
flags.StringP("search", "s", "", "Host search filter")
flags.StringP("config", "c", "~/.ssh/config", "SSH config file")
flags.BoolP("proxy", "p", false, "Display full ProxyCommand")

viper.SetDefault("author", "quantumsheep <[email protected]>")
viper.SetDefault("license", "MIT")
}

0 comments on commit 46ee11e

Please sign in to comment.