Allow setting ssh connection key file, fix connection ui
This commit is contained in:
@@ -115,6 +115,7 @@ func parseSshInfo(c *gin.Context) *shared.SSHInfo {
|
|||||||
Port: c.Request.FormValue("ssh_port"),
|
Port: c.Request.FormValue("ssh_port"),
|
||||||
User: c.Request.FormValue("ssh_user"),
|
User: c.Request.FormValue("ssh_user"),
|
||||||
Password: c.Request.FormValue("ssh_password"),
|
Password: c.Request.FormValue("ssh_password"),
|
||||||
|
Key: c.Request.FormValue("ssh_key"),
|
||||||
}
|
}
|
||||||
|
|
||||||
if info.Port == "" {
|
if info.Port == "" {
|
||||||
|
|||||||
@@ -14,14 +14,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Bookmark struct {
|
type Bookmark struct {
|
||||||
Url string `json:"url"` // Postgres connection URL
|
Url string `json:"url"` // Postgres connection URL
|
||||||
Host string `json:"host"` // Server hostname
|
Host string `json:"host"` // Server hostname
|
||||||
Port int `json:"port"` // Server port
|
Port int `json:"port"` // Server port
|
||||||
User string `json:"user"` // Database user
|
User string `json:"user"` // Database user
|
||||||
Password string `json:"password"` // User password
|
Password string `json:"password"` // User password
|
||||||
Database string `json:"database"` // Database name
|
Database string `json:"database"` // Database name
|
||||||
Ssl string `json:"ssl"` // Connection SSL mode
|
Ssl string `json:"ssl"` // Connection SSL mode
|
||||||
Ssh shared.SSHInfo `json:"ssh"` // SSH tunnel config
|
Ssh *shared.SSHInfo `json:"ssh"` // SSH tunnel config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b Bookmark) SSHInfoIsEmpty() bool {
|
func (b Bookmark) SSHInfoIsEmpty() bool {
|
||||||
@@ -71,6 +71,10 @@ func readServerConfig(path string) (Bookmark, error) {
|
|||||||
bookmark.Ssl = "disable"
|
bookmark.Ssl = "disable"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if bookmark.Ssh != nil && bookmark.Ssh.Port == "" {
|
||||||
|
bookmark.Ssh.Port = "22"
|
||||||
|
}
|
||||||
|
|
||||||
return bookmark, err
|
return bookmark, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -95,12 +95,12 @@ func Test_GetBookmark(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_Bookmark_SSHInfoIsEmpty(t *testing.T) {
|
func Test_Bookmark_SSHInfoIsEmpty(t *testing.T) {
|
||||||
emptySSH := shared.SSHInfo{
|
emptySSH := &shared.SSHInfo{
|
||||||
Host: "",
|
Host: "",
|
||||||
Port: "",
|
Port: "",
|
||||||
User: "",
|
User: "",
|
||||||
}
|
}
|
||||||
populatedSSH := shared.SSHInfo{
|
populatedSSH := &shared.SSHInfo{
|
||||||
Host: "localhost",
|
Host: "localhost",
|
||||||
Port: "8080",
|
Port: "8080",
|
||||||
User: "postgres",
|
User: "postgres",
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ func initClientUsingBookmark(bookmarkPath, bookmarkName string) (*client.Client,
|
|||||||
|
|
||||||
var ssh *shared.SSHInfo
|
var ssh *shared.SSHInfo
|
||||||
if !bookmark.SSHInfoIsEmpty() {
|
if !bookmark.SSHInfoIsEmpty() {
|
||||||
ssh = &bookmark.Ssh
|
ssh = bookmark.Ssh
|
||||||
}
|
}
|
||||||
|
|
||||||
return client.NewFromUrl(connStr, ssh)
|
return client.NewFromUrl(connStr, ssh)
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"golang.org/x/crypto/ssh"
|
"golang.org/x/crypto/ssh"
|
||||||
|
|
||||||
@@ -36,6 +37,14 @@ func privateKeyPath() string {
|
|||||||
return os.Getenv("HOME") + "/.ssh/id_rsa"
|
return os.Getenv("HOME") + "/.ssh/id_rsa"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func expandKeyPath(path string) string {
|
||||||
|
home := os.Getenv("HOME")
|
||||||
|
if home == "" {
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
return strings.Replace(path, "~", home, 1)
|
||||||
|
}
|
||||||
|
|
||||||
func fileExists(path string) bool {
|
func fileExists(path string) bool {
|
||||||
_, err := os.Stat(path)
|
_, err := os.Stat(path)
|
||||||
return err == nil
|
return err == nil
|
||||||
@@ -53,7 +62,14 @@ func parsePrivateKey(keyPath string) (ssh.Signer, error) {
|
|||||||
func makeConfig(info *shared.SSHInfo) (*ssh.ClientConfig, error) {
|
func makeConfig(info *shared.SSHInfo) (*ssh.ClientConfig, error) {
|
||||||
methods := []ssh.AuthMethod{}
|
methods := []ssh.AuthMethod{}
|
||||||
|
|
||||||
keyPath := privateKeyPath()
|
// Try to use user-provided key, fallback to system default key
|
||||||
|
keyPath := info.Key
|
||||||
|
if keyPath == "" {
|
||||||
|
keyPath = privateKeyPath()
|
||||||
|
} else {
|
||||||
|
keyPath = expandKeyPath(keyPath)
|
||||||
|
}
|
||||||
|
|
||||||
if fileExists(keyPath) {
|
if fileExists(keyPath) {
|
||||||
key, err := parsePrivateKey(keyPath)
|
key, err := parsePrivateKey(keyPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -65,7 +81,13 @@ func makeConfig(info *shared.SSHInfo) (*ssh.ClientConfig, error) {
|
|||||||
|
|
||||||
methods = append(methods, ssh.Password(info.Password))
|
methods = append(methods, ssh.Password(info.Password))
|
||||||
|
|
||||||
return &ssh.ClientConfig{User: info.User, Auth: methods}, nil
|
cfg := &ssh.ClientConfig{
|
||||||
|
User: info.User,
|
||||||
|
Auth: methods,
|
||||||
|
Timeout: time.Second * 10,
|
||||||
|
}
|
||||||
|
|
||||||
|
return cfg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tunnel *Tunnel) sshEndpoint() string {
|
func (tunnel *Tunnel) sshEndpoint() string {
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -563,6 +563,10 @@
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.connection-settings form .no-left-padding {
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.connection-scheme-group {
|
.connection-scheme-group {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -147,9 +147,12 @@
|
|||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-sm-3 control-label">Host</label>
|
<label class="col-sm-3 control-label">Host</label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-7">
|
||||||
<input type="text" id="pg_host" class="form-control" />
|
<input type="text" id="pg_host" class="form-control" />
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-sm-2 no-left-padding">
|
||||||
|
<input type="text" id="pg_port" class="form-control" placeholder="5432" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
@@ -174,14 +177,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-sm-3 control-label">Port</label>
|
<label class="col-sm-3 control-label">SSL Mode</label>
|
||||||
<div class="col-sm-9">
|
|
||||||
<input type="text" id="pg_port" class="form-control" placeholder="5432" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="col-sm-3 control-label">SSL</label>
|
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<select class="form-control" id="connection_ssl">
|
<select class="form-control" id="connection_ssl">
|
||||||
<option value="disable">disable</option>
|
<option value="disable">disable</option>
|
||||||
@@ -193,11 +189,16 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="connection-ssh-group">
|
<div class="connection-ssh-group">
|
||||||
|
<hr/>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-sm-3 control-label">SSH Host</label>
|
<label class="col-sm-3 control-label">SSH Host</label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-7">
|
||||||
<input type="text" id="ssh_host" class="form-control" />
|
<input type="text" id="ssh_host" class="form-control" />
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-sm-2 no-left-padding">
|
||||||
|
<input type="text" id="ssh_port" class="form-control" placeholder="22" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
@@ -215,9 +216,9 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-sm-3 control-label">SSH Port</label>
|
<label class="col-sm-3 control-label">SSH Key</label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input type="text" id="ssh_port" class="form-control" placeholder="optional" />
|
<input type="text" id="ssh_key" class="form-control" placeholder="optional" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1149,6 +1149,7 @@ $(document).ready(function() {
|
|||||||
$("#ssh_port").val(item.ssh.port);
|
$("#ssh_port").val(item.ssh.port);
|
||||||
$("#ssh_user").val(item.ssh.user);
|
$("#ssh_user").val(item.ssh.user);
|
||||||
$("#ssh_password").val(item.ssh.password);
|
$("#ssh_password").val(item.ssh.password);
|
||||||
|
$("#ssh_key").val(item.ssh.key);
|
||||||
$("#connection_ssh").click();
|
$("#connection_ssh").click();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -1156,6 +1157,7 @@ $(document).ready(function() {
|
|||||||
$("#ssh_port").val("");
|
$("#ssh_port").val("");
|
||||||
$("#ssh_user").val("");
|
$("#ssh_user").val("");
|
||||||
$("#ssh_password").val("");
|
$("#ssh_password").val("");
|
||||||
|
$("#ssh_key").val("");
|
||||||
$(".connection-ssh-group").hide();
|
$(".connection-ssh-group").hide();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -1178,6 +1180,7 @@ $(document).ready(function() {
|
|||||||
params["ssh_port"] = $("#ssh_port").val();
|
params["ssh_port"] = $("#ssh_port").val();
|
||||||
params["ssh_user"] = $("#ssh_user").val();
|
params["ssh_user"] = $("#ssh_user").val();
|
||||||
params["ssh_password"] = $("#ssh_password").val();
|
params["ssh_password"] = $("#ssh_password").val();
|
||||||
|
params["ssh_key"] = $("#ssh_key").val();
|
||||||
}
|
}
|
||||||
|
|
||||||
$("#connection_error").hide();
|
$("#connection_error").hide();
|
||||||
|
|||||||
Reference in New Issue
Block a user