mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2024-11-27 20:49:03 +08:00
feat: 主机增加记住密码,支持带密码私钥连接 (#570)
This commit is contained in:
parent
a5fd55e90e
commit
0ddbdfeac9
@ -245,11 +245,13 @@ func (b *BaseApi) UpdateHost(c *gin.Context) {
|
||||
upMap["port"] = req.Port
|
||||
upMap["user"] = req.User
|
||||
upMap["auth_mode"] = req.AuthMode
|
||||
upMap["remember_password"] = req.RememberPassword
|
||||
if len(req.Password) != 0 {
|
||||
upMap["password"] = req.Password
|
||||
}
|
||||
if len(req.PrivateKey) != 0 {
|
||||
upMap["private_key"] = req.PrivateKey
|
||||
upMap["pass_phrase"] = req.PassPhrase
|
||||
}
|
||||
upMap["description"] = req.Description
|
||||
if err := hostService.Update(req.ID, upMap); err != nil {
|
||||
|
@ -44,6 +44,9 @@ func (b *BaseApi) WsSsh(c *gin.Context) {
|
||||
var connInfo ssh.ConnInfo
|
||||
_ = copier.Copy(&connInfo, &host)
|
||||
connInfo.PrivateKey = []byte(host.PrivateKey)
|
||||
if len(host.PassPhrase) != 0 {
|
||||
connInfo.PassPhrase = []byte(host.PassPhrase)
|
||||
}
|
||||
|
||||
wsConn, err := upGrader.Upgrade(c.Writer, c.Request, nil)
|
||||
if err != nil {
|
||||
|
@ -5,15 +5,17 @@ import (
|
||||
)
|
||||
|
||||
type HostOperate struct {
|
||||
ID uint `json:"id"`
|
||||
GroupID uint `json:"groupID"`
|
||||
Name string `json:"name"`
|
||||
Addr string `json:"addr" validate:"required"`
|
||||
Port uint `json:"port" validate:"required,number,max=65535,min=1"`
|
||||
User string `json:"user" validate:"required"`
|
||||
AuthMode string `json:"authMode" validate:"oneof=password key"`
|
||||
PrivateKey string `json:"privateKey"`
|
||||
Password string `json:"password"`
|
||||
ID uint `json:"id"`
|
||||
GroupID uint `json:"groupID"`
|
||||
Name string `json:"name"`
|
||||
Addr string `json:"addr" validate:"required"`
|
||||
Port uint `json:"port" validate:"required,number,max=65535,min=1"`
|
||||
User string `json:"user" validate:"required"`
|
||||
AuthMode string `json:"authMode" validate:"oneof=password key"`
|
||||
Password string `json:"password"`
|
||||
PrivateKey string `json:"privateKey"`
|
||||
PassPhrase string `json:"passPhrase"`
|
||||
RememberPassword bool `json:"rememberPassword"`
|
||||
|
||||
Description string `json:"description"`
|
||||
}
|
||||
@ -23,8 +25,9 @@ type HostConnTest struct {
|
||||
Port uint `json:"port" validate:"required,number,max=65535,min=1"`
|
||||
User string `json:"user" validate:"required"`
|
||||
AuthMode string `json:"authMode" validate:"oneof=password key"`
|
||||
PrivateKey string `json:"privateKey"`
|
||||
Password string `json:"password"`
|
||||
PrivateKey string `json:"privateKey"`
|
||||
PassPhrase string `json:"passPhrase"`
|
||||
}
|
||||
|
||||
type SearchHostWithPage struct {
|
||||
@ -43,15 +46,19 @@ type ChangeHostGroup struct {
|
||||
}
|
||||
|
||||
type HostInfo struct {
|
||||
ID uint `json:"id"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
GroupID uint `json:"groupID"`
|
||||
GroupBelong string `json:"groupBelong"`
|
||||
Name string `json:"name"`
|
||||
Addr string `json:"addr"`
|
||||
Port uint `json:"port"`
|
||||
User string `json:"user"`
|
||||
AuthMode string `json:"authMode"`
|
||||
ID uint `json:"id"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
GroupID uint `json:"groupID"`
|
||||
GroupBelong string `json:"groupBelong"`
|
||||
Name string `json:"name"`
|
||||
Addr string `json:"addr"`
|
||||
Port uint `json:"port"`
|
||||
User string `json:"user"`
|
||||
AuthMode string `json:"authMode"`
|
||||
Password string `json:"password"`
|
||||
PrivateKey string `json:"privateKey"`
|
||||
PassPhrase string `json:"passPhrase"`
|
||||
RememberPassword bool `json:"rememberPassword"`
|
||||
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
@ -2,14 +2,17 @@ package model
|
||||
|
||||
type Host struct {
|
||||
BaseModel
|
||||
GroupID uint `gorm:"type:decimal;not null" json:"group_id"`
|
||||
Name string `gorm:"type:varchar(64);not null" json:"name"`
|
||||
Addr string `gorm:"type:varchar(16);not null" json:"addr"`
|
||||
Port int `gorm:"type:decimal;not null" json:"port"`
|
||||
User string `gorm:"type:varchar(64);not null" json:"user"`
|
||||
AuthMode string `gorm:"type:varchar(16);not null" json:"authMode"`
|
||||
Password string `gorm:"type:varchar(64)" json:"password"`
|
||||
PrivateKey string `gorm:"type:varchar(256)" json:"privateKey"`
|
||||
|
||||
GroupID uint `gorm:"type:decimal;not null" json:"group_id"`
|
||||
Name string `gorm:"type:varchar(64);not null" json:"name"`
|
||||
Addr string `gorm:"type:varchar(16);not null" json:"addr"`
|
||||
Port int `gorm:"type:decimal;not null" json:"port"`
|
||||
User string `gorm:"type:varchar(64);not null" json:"user"`
|
||||
AuthMode string `gorm:"type:varchar(16);not null" json:"authMode"`
|
||||
Password string `gorm:"type:varchar(64)" json:"password"`
|
||||
PrivateKey string `gorm:"type:varchar(256)" json:"privateKey"`
|
||||
PassPhrase string `gorm:"type:varchar(256)" json:"passPhrase"`
|
||||
RememberPassword bool `json:"rememberPassword"`
|
||||
|
||||
Description string `gorm:"type:varchar(256)" json:"description"`
|
||||
}
|
||||
|
@ -52,11 +52,15 @@ func (u *HostService) TestByInfo(req dto.HostConnTest) bool {
|
||||
req.Password = host.Password
|
||||
req.AuthMode = host.AuthMode
|
||||
req.PrivateKey = host.PrivateKey
|
||||
req.PassPhrase = host.PassPhrase
|
||||
}
|
||||
|
||||
var connInfo ssh.ConnInfo
|
||||
_ = copier.Copy(&connInfo, &req)
|
||||
connInfo.PrivateKey = []byte(req.PrivateKey)
|
||||
if len(req.PassPhrase) != 0 {
|
||||
connInfo.PassPhrase = []byte(req.PassPhrase)
|
||||
}
|
||||
client, err := connInfo.NewClient()
|
||||
if err != nil {
|
||||
return false
|
||||
@ -85,6 +89,10 @@ func (u *HostService) TestLocalConn(id uint) bool {
|
||||
if err := copier.Copy(&connInfo, &host); err != nil {
|
||||
return false
|
||||
}
|
||||
connInfo.PrivateKey = []byte(host.PrivateKey)
|
||||
if len(host.PassPhrase) != 0 {
|
||||
connInfo.PassPhrase = []byte(host.PassPhrase)
|
||||
}
|
||||
client, err := connInfo.NewClient()
|
||||
if err != nil {
|
||||
return false
|
||||
@ -115,6 +123,11 @@ func (u *HostService) SearchWithPage(search dto.SearchHostWithPage) (int64, inte
|
||||
}
|
||||
group, _ := groupRepo.Get(commonRepo.WithByID(host.GroupID))
|
||||
item.GroupBelong = group.Name
|
||||
if !item.RememberPassword {
|
||||
item.Password = ""
|
||||
item.PrivateKey = ""
|
||||
item.PassPhrase = ""
|
||||
}
|
||||
dtoHosts = append(dtoHosts, item)
|
||||
}
|
||||
return total, dtoHosts, err
|
||||
@ -182,6 +195,8 @@ func (u *HostService) Create(req dto.HostOperate) (*dto.HostInfo, error) {
|
||||
upMap["auth_mode"] = req.AuthMode
|
||||
upMap["password"] = req.Password
|
||||
upMap["private_key"] = req.PrivateKey
|
||||
upMap["pass_phrase"] = req.PassPhrase
|
||||
upMap["remember_password"] = req.RememberPassword
|
||||
upMap["description"] = req.Description
|
||||
if err := hostRepo.Update(sameHostID, upMap); err != nil {
|
||||
return nil, err
|
||||
|
@ -23,6 +23,7 @@ func Init() {
|
||||
migrations.AddDefaultGroup,
|
||||
migrations.AddTableRuntime,
|
||||
migrations.UpdateTableApp,
|
||||
migrations.UpdateTableHost,
|
||||
})
|
||||
if err := m.Migrate(); err != nil {
|
||||
global.LOG.Error(err)
|
||||
|
@ -264,3 +264,13 @@ var UpdateTableApp = &gormigrate.Migration{
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var UpdateTableHost = &gormigrate.Migration{
|
||||
ID: "20230410-update-table-host",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
if err := tx.AutoMigrate(&model.Host{}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
@ -127,20 +127,8 @@ func (w *wsBufferWriter) Write(p []byte) (int, error) {
|
||||
}
|
||||
|
||||
func makePrivateKeySigner(privateKey []byte, passPhrase []byte) (gossh.Signer, error) {
|
||||
var signer gossh.Signer
|
||||
if passPhrase != nil {
|
||||
s, err := gossh.ParsePrivateKeyWithPassphrase(privateKey, passPhrase)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error parsing SSH key: '%v'", err)
|
||||
}
|
||||
signer = s
|
||||
} else {
|
||||
s, err := gossh.ParsePrivateKey(privateKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error parsing SSH key: '%v'", err)
|
||||
}
|
||||
signer = s
|
||||
if len(passPhrase) != 0 {
|
||||
return gossh.ParsePrivateKeyWithPassphrase(privateKey, passPhrase)
|
||||
}
|
||||
|
||||
return signer, nil
|
||||
return gossh.ParsePrivateKey(privateKey)
|
||||
}
|
||||
|
@ -18,6 +18,10 @@ export namespace Host {
|
||||
port: number;
|
||||
user: string;
|
||||
authMode: string;
|
||||
password: string;
|
||||
privateKey: string;
|
||||
passPhrase: string;
|
||||
rememberPassword: boolean;
|
||||
description: string;
|
||||
}
|
||||
export interface HostOperate {
|
||||
@ -28,8 +32,10 @@ export namespace Host {
|
||||
port: number;
|
||||
user: string;
|
||||
authMode: string;
|
||||
privateKey: string;
|
||||
password: string;
|
||||
privateKey: string;
|
||||
passPhrase: string;
|
||||
rememberPassword: boolean;
|
||||
|
||||
description: string;
|
||||
}
|
||||
|
@ -674,10 +674,12 @@ const message = {
|
||||
port: 'Port',
|
||||
user: 'Username',
|
||||
authMode: 'Auth Mode',
|
||||
passwordMode: 'password',
|
||||
passwordMode: 'Password',
|
||||
rememberPassword: 'Remember password',
|
||||
keyMode: 'PrivateKey',
|
||||
password: 'Password',
|
||||
key: 'Private Key',
|
||||
key: 'Private key',
|
||||
keyPassword: 'Private key password',
|
||||
emptyTerminal: 'No terminal is currently connected',
|
||||
},
|
||||
logs: {
|
||||
|
@ -673,10 +673,12 @@ const message = {
|
||||
port: '端口',
|
||||
user: '用户名',
|
||||
authMode: '认证方式',
|
||||
passwordMode: '密码输入',
|
||||
keyMode: '密钥输入',
|
||||
passwordMode: '密码认证',
|
||||
rememberPassword: '记住密码',
|
||||
keyMode: '私钥认证',
|
||||
password: '密码',
|
||||
key: '密钥',
|
||||
key: '私钥',
|
||||
keyPassword: '私钥密码',
|
||||
emptyTerminal: '暂无终端连接',
|
||||
},
|
||||
logs: {
|
||||
|
@ -36,7 +36,22 @@
|
||||
>
|
||||
<el-input clearable type="textarea" v-model="dialogData.rowData!.privateKey" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('terminal.port')" prop="port">
|
||||
<el-form-item
|
||||
:label="$t('terminal.keyPassword')"
|
||||
v-if="dialogData.rowData!.authMode === 'key'"
|
||||
prop="passPhrase"
|
||||
>
|
||||
<el-input
|
||||
type="password"
|
||||
show-password
|
||||
clearable
|
||||
v-model="dialogData.rowData!.passPhrase"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-checkbox clearable v-model.number="dialogData.rowData!.rememberPassword">
|
||||
{{ $t('terminal.rememberPassword') }}
|
||||
</el-checkbox>
|
||||
<el-form-item style="margin-top: 10px" :label="$t('terminal.port')" prop="port">
|
||||
<el-input clearable v-model.number="dialogData.rowData!.port" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('commons.table.group')" prop="groupID">
|
||||
|
@ -40,7 +40,17 @@
|
||||
<el-form-item :label="$t('terminal.key')" v-if="hostInfo.authMode === 'key'" prop="privateKey">
|
||||
<el-input clearable type="textarea" v-model="hostInfo.privateKey" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('terminal.port')" prop="port">
|
||||
<el-form-item
|
||||
:label="$t('terminal.keyPassword')"
|
||||
v-if="hostInfo.authMode === 'key'"
|
||||
prop="passPhrase"
|
||||
>
|
||||
<el-input type="password" show-password clearable v-model="hostInfo.passPhrase" />
|
||||
</el-form-item>
|
||||
<el-checkbox clearable v-model.number="hostInfo.rememberPassword">
|
||||
{{ $t('terminal.rememberPassword') }}
|
||||
</el-checkbox>
|
||||
<el-form-item style="margin-top: 10px" :label="$t('terminal.port')" prop="port">
|
||||
<el-input clearable v-model.number="hostInfo.port" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('commons.table.title')" prop="name">
|
||||
@ -91,6 +101,8 @@ let hostInfo = reactive<Host.HostOperate>({
|
||||
authMode: 'password',
|
||||
password: '',
|
||||
privateKey: '',
|
||||
passPhrase: '',
|
||||
rememberPassword: false,
|
||||
description: '',
|
||||
});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user