-
Notifications
You must be signed in to change notification settings - Fork 34
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement sshs config generator from known_hosts files
- Loading branch information
1 parent
f882b24
commit 46ee11e
Showing
2 changed files
with
169 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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" | ||
|
@@ -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") | ||
} |