Skip to content

Commit f82fb55

Browse files
committed
allow ssh config extension
1 parent 685fd26 commit f82fb55

File tree

4 files changed

+67
-18
lines changed

4 files changed

+67
-18
lines changed

README.md

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ Or download the binaries directly (choose your os/arch):
2424

2525
```
2626
# download the binaries from the release
27-
wget https://github.com/noboruma/s1h/releases/download/v0.3.3/s1h_Darwin_arm64.tar.gz
28-
wget https://github.com/noboruma/s1h/releases/download/v0.3.3/s1h_Darwin_x86_64.tar.gz
29-
wget https://github.com/noboruma/s1h/releases/download/v0.3.3/s1h_Linux_arm64.tar.gz
30-
wget https://github.com/noboruma/s1h/releases/download/v0.3.3/s1h_Linux_x86_64.tar.gz
31-
wget https://github.com/noboruma/s1h/releases/download/v0.3.3/s1h_Windows_arm64.zip
32-
wget https://github.com/noboruma/s1h/releases/download/v0.3.3/s1h_Windows_x86_64.zip
27+
wget https://github.com/noboruma/s1h/releases/download/v0.4.0/s1h_Darwin_arm64.tar.gz
28+
wget https://github.com/noboruma/s1h/releases/download/v0.4.0/s1h_Darwin_x86_64.tar.gz
29+
wget https://github.com/noboruma/s1h/releases/download/v0.4.0/s1h_Linux_arm64.tar.gz
30+
wget https://github.com/noboruma/s1h/releases/download/v0.4.0/s1h_Linux_x86_64.tar.gz
31+
wget https://github.com/noboruma/s1h/releases/download/v0.4.0/s1h_Windows_arm64.zip
32+
wget https://github.com/noboruma/s1h/releases/download/v0.4.0/s1h_Windows_x86_64.zip
3333
3434
tar xvf chosen.tar.gz
3535
```
@@ -122,6 +122,11 @@ Enter password for <host>: <terminal input>
122122
This updates the stored credentials for the specified ssh host.
123123
`s1h` comes with other password operations: `reveal` and `delete`.
124124

125+
It is also possible to extend SSH config and add completely new entries or override existing hosts by passing a hostname, such as:
126+
```sh
127+
s1h upsert -host=<host> [-password=<password>] -hostname=toto.io [-user=root] [-port=22]
128+
```
129+
125130
#### Example:
126131

127132
```

cmd/s1h/main.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,13 @@ func main() {
3939
key, credsFile := loadOrStoreLocalEncryptedFile()
4040
switch os.Args[1] {
4141
case "upsert":
42-
var host, password string
42+
var host, password, hostname, user, port string
4343
updateCmd := flag.NewFlagSet("upsert", flag.ExitOnError)
4444
updateCmd.StringVar(&host, "host", "", "The host to update")
4545
updateCmd.StringVar(&password, "password", "", "The password to set for the host (optional)")
46+
updateCmd.StringVar(&hostname, "hostname", "", "The hostname/endpoint to set for the host (optional)")
47+
updateCmd.StringVar(&user, "user", "root", "The user to use for the host (optional)")
48+
updateCmd.StringVar(&port, "port", "22", "The port to use for the host (optional)")
4649
err := updateCmd.Parse(os.Args[2:])
4750
if err != nil {
4851
fmt.Println("Error upading credentials:", err.Error())
@@ -62,7 +65,7 @@ func main() {
6265
password = string(bytePassword)
6366
}
6467

65-
err = credentials.UpsertCredential(credsFile, host, password, key)
68+
err = credentials.UpsertCredential(credsFile, host, hostname, user, port, password, key)
6669
if err != nil {
6770
fmt.Println("Error updating credentials:", err)
6871
os.Exit(1)
@@ -103,7 +106,7 @@ func main() {
103106
fmt.Println("Please provide the hostname to reveal.")
104107
os.Exit(1)
105108
}
106-
pass, err := credentials.RevealCredential(credsFile, host, key)
109+
pass, err := credentials.RevealCredentialPassword(credsFile, host, key)
107110
if err != nil {
108111
fmt.Println("Error retrieving credential:", err.Error())
109112
os.Exit(1)
@@ -179,7 +182,7 @@ func loadConfigs() []ssh.SSHConfig {
179182
if err != nil {
180183
log.Fatalf("Error loading creds: %v\n", err)
181184
}
182-
config.PopulateCredentialsToConfig(creds, configs)
185+
configs = config.PopulateCredentialsToConfig(creds, configs)
183186
}
184187
return configs
185188
}

internal/config/ssh.go

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,35 @@ import (
55
"github.com/noboruma/s1h/internal/ssh"
66
)
77

8-
func PopulateCredentialsToConfig(creds credentials.Credentials, configs []ssh.SSHConfig) {
8+
func PopulateCredentialsToConfig(creds credentials.Credentials, configs []ssh.SSHConfig) []ssh.SSHConfig {
9+
processed := map[string]struct{}{}
910
for i, cfg := range configs {
10-
cfg.Password = creds.Entries[cfg.Host]
11+
cred := creds.Entries[cfg.Host]
12+
cfg.Password = cred.Password
13+
if cred.Hostname != "" { // Replace outdated data
14+
cfg.HostName = cred.Hostname
15+
cfg.User = cred.User
16+
cfg.Port = cred.Port
17+
}
1118
configs[i] = cfg
19+
processed[cfg.Host] = struct{}{}
1220
}
21+
// Add non existing entries
22+
for k, added := range creds.Entries {
23+
if added.Hostname == "" {
24+
continue
25+
}
26+
if _, has := processed[k]; has {
27+
continue
28+
}
29+
configs = append(configs, ssh.SSHConfig{
30+
Host: k,
31+
User: added.User,
32+
Port: added.Port,
33+
HostName: added.Hostname,
34+
IdentityFile: "",
35+
Password: added.Password,
36+
})
37+
}
38+
return configs
1339
}

internal/credentials/encrypt.go

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,15 @@ import (
1111
"os"
1212
)
1313

14+
type Entry struct {
15+
Password string `json:"password"`
16+
Hostname string `json:"hostname"`
17+
User string `json:"user"`
18+
Port string `json:"port"`
19+
}
20+
1421
type Credentials struct {
15-
Entries map[string]string `json:"credentials"`
22+
Entries map[string]Entry `json:"credentials"`
1623
}
1724

1825
func GenerateMasterKey() ([]byte, error) {
@@ -128,17 +135,25 @@ func saveCredentials(filename string, creds Credentials, key []byte) error {
128135
return nil
129136
}
130137

131-
func UpsertCredential(filename string, host string, password string, key []byte) error {
138+
func UpsertCredential(filename string, host, hostname, user, port string, password string, key []byte) error {
132139
creds, err := LoadCredentials(filename, key)
133140
if err != nil && !os.IsNotExist(err) {
134141
return err
135142
}
136143

137144
if creds.Entries == nil {
138-
creds.Entries = make(map[string]string)
145+
creds.Entries = make(map[string]Entry)
139146
}
140147

141-
creds.Entries[host] = password
148+
entry := Entry{
149+
Password: password,
150+
}
151+
if hostname != "" {
152+
entry.Hostname = hostname
153+
entry.User = user
154+
entry.Port = port
155+
}
156+
creds.Entries[host] = entry
142157

143158
return saveCredentials(filename, creds, key)
144159
}
@@ -154,7 +169,7 @@ func RemoveCredential(filename string, host string, key []byte) error {
154169
return saveCredentials(filename, creds, key)
155170
}
156171

157-
func RevealCredential(filename string, host string, key []byte) (string, error) {
172+
func RevealCredentialPassword(filename string, host string, key []byte) (string, error) {
158173
creds, err := LoadCredentials(filename, key)
159174
if err != nil {
160175
return "", err
@@ -165,5 +180,5 @@ func RevealCredential(filename string, host string, key []byte) (string, error)
165180
return "", fmt.Errorf("no entry for %s", host)
166181
}
167182

168-
return cred, nil
183+
return cred.Password, nil
169184
}

0 commit comments

Comments
 (0)