Skip to content

Commit a2a6503

Browse files
authored
fix: Refactor terminal connection logic (#10283)
Refs #9617
1 parent 9c22005 commit a2a6503

File tree

20 files changed

+327
-39
lines changed

20 files changed

+327
-39
lines changed

agent/app/api/v2/setting.go

Lines changed: 50 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
package v2
22

33
import (
4+
"encoding/base64"
45
"encoding/json"
5-
"os"
6-
"os/user"
7-
"path"
86

97
"github.com/1Panel-dev/1Panel/agent/app/api/v2/helper"
108
"github.com/1Panel-dev/1Panel/agent/app/dto"
9+
"github.com/1Panel-dev/1Panel/agent/app/model"
1110
"github.com/1Panel-dev/1Panel/agent/global"
1211
"github.com/1Panel-dev/1Panel/agent/utils/ssh"
1312
"github.com/gin-gonic/gin"
@@ -71,6 +70,35 @@ func (b *BaseApi) LoadBaseDir(c *gin.Context) {
7170
helper.SuccessWithData(c, global.Dir.DataDir)
7271
}
7372

73+
// @Tags System Setting
74+
// @Summary Load local conn
75+
// @Success 200 {object} dto.SSHConnData
76+
// @Security ApiKeyAuth
77+
// @Security Timestamp
78+
// @Router /settings/ssh [get]
79+
func (b *BaseApi) LoadLocalConn(c *gin.Context) {
80+
connInfoInDB, err := settingService.GetSSHInfo()
81+
if err != nil {
82+
helper.InternalServer(c, err)
83+
return
84+
}
85+
var data dto.SSHConnData
86+
if err := json.Unmarshal([]byte(connInfoInDB), &data); err != nil {
87+
helper.InternalServer(c, err)
88+
return
89+
}
90+
if len(data.Password) != 0 {
91+
data.Password = base64.StdEncoding.EncodeToString([]byte(data.Password))
92+
}
93+
if len(data.PrivateKey) != 0 {
94+
data.PrivateKey = base64.StdEncoding.EncodeToString([]byte(data.PrivateKey))
95+
}
96+
if len(data.PassPhrase) != 0 {
97+
data.PassPhrase = base64.StdEncoding.EncodeToString([]byte(data.PassPhrase))
98+
}
99+
helper.SuccessWithData(c, data)
100+
}
101+
74102
func (b *BaseApi) CheckLocalConn(c *gin.Context) {
75103
_, err := loadLocalConn()
76104
helper.SuccessWithData(c, err == nil)
@@ -87,6 +115,7 @@ func (b *BaseApi) CheckLocalConnByInfo(c *gin.Context) {
87115
if err := helper.CheckBindAndValidate(&req, c); err != nil {
88116
return
89117
}
118+
90119
helper.SuccessWithData(c, settingService.TestConnByInfo(req))
91120
}
92121

@@ -96,51 +125,41 @@ func (b *BaseApi) CheckLocalConnByInfo(c *gin.Context) {
96125
// @Security ApiKeyAuth
97126
// @Security Timestamp
98127
// @Router /settings/ssh [post]
99-
func (b *BaseApi) SaveLocalConnInfo(c *gin.Context) {
128+
func (b *BaseApi) SaveLocalConn(c *gin.Context) {
100129
var req dto.SSHConnData
101130
if err := helper.CheckBindAndValidate(&req, c); err != nil {
102131
return
103132
}
104-
helper.SuccessWithData(c, settingService.SaveConnInfo(req))
105-
}
106-
107-
func loadLocalConn() (*ssh.SSHClient, error) {
108-
itemPath := ""
109-
currentInfo, _ := user.Current()
110-
if len(currentInfo.HomeDir) == 0 {
111-
itemPath = "/root/.ssh/id_ed25519_1panel"
112-
} else {
113-
itemPath = path.Join(currentInfo.HomeDir, ".ssh/id_ed25519_1panel")
114-
}
115-
if _, err := os.Stat(itemPath); err != nil {
116-
_ = sshService.CreateRootCert(dto.CreateRootCert{EncryptionMode: "ed25519", Name: "id_ed25519_1panel", Description: "1Panel Terminal"})
117-
}
118133

119-
privateKey, _ := os.ReadFile(itemPath)
120-
connWithKey := ssh.ConnInfo{
121-
Addr: "127.0.0.1",
122-
User: "root",
123-
Port: 22,
124-
AuthMode: "key",
125-
PrivateKey: privateKey,
126-
}
127-
client, err := ssh.NewClient(connWithKey)
128-
if err == nil {
129-
return client, nil
134+
if err := settingService.SaveConnInfo(req); err != nil {
135+
helper.InternalServer(c, err)
136+
return
130137
}
138+
helper.Success(c)
139+
}
131140

141+
func loadLocalConn() (*ssh.SSHClient, error) {
132142
connInfoInDB, err := settingService.GetSSHInfo()
133143
if err != nil {
134144
return nil, err
135145
}
136146
if len(connInfoInDB) == 0 {
137147
return nil, errors.New("no such ssh conn info in db!")
138148
}
139-
var connInDB ssh.ConnInfo
149+
var connInDB model.LocalConnInfo
140150
if err := json.Unmarshal([]byte(connInfoInDB), &connInDB); err != nil {
141151
return nil, err
142152
}
143-
return ssh.NewClient(connInDB)
153+
sshInfo := ssh.ConnInfo{
154+
Addr: connInDB.Addr,
155+
Port: int(connInDB.Port),
156+
User: connInDB.User,
157+
AuthMode: connInDB.AuthMode,
158+
Password: connInDB.Password,
159+
PrivateKey: []byte(connInDB.PrivateKey),
160+
PassPhrase: []byte(connInDB.PassPhrase),
161+
}
162+
return ssh.NewClient(sshInfo)
144163
}
145164

146165
// @Tags System Setting

agent/app/model/setting.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,13 @@ type NodeInfo struct {
1515
ServerCrt string `json:"serverCrt"`
1616
ServerKey string `json:"serverKey"`
1717
}
18+
19+
type LocalConnInfo struct {
20+
Addr string `json:"addr"`
21+
Port uint `json:"port"`
22+
User string `json:"user"`
23+
AuthMode string `json:"authMode"`
24+
Password string `json:"password"`
25+
PrivateKey string `json:"privateKey"`
26+
PassPhrase string `json:"passPhrase"`
27+
}

agent/app/service/setting.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,13 @@ func (u *SettingService) GetSettingByKey(key string) string {
143143
case "SystemIP":
144144
value, _ := settingRepo.GetValueByKey(key)
145145
return value
146+
case "LocalSSHConn":
147+
value, _ := settingRepo.GetValueByKey(key)
148+
if len(value) == 0 {
149+
return ""
150+
}
151+
itemStr, _ := encrypt.StringDecryptWithBase64(value)
152+
return itemStr
146153
default:
147154
return ""
148155
}

agent/init/migration/migrate.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ func InitAgentDB() {
3939
migrations.UpdateWebsiteSSL,
4040
migrations.AddQuickJump,
4141
migrations.UpdateMcpServerAddType,
42+
migrations.InitLocalSSHConn,
4243
})
4344
if err := m.Migrate(); err != nil {
4445
global.LOG.Error(err)

agent/init/migration/migrations/init.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,23 @@
11
package migrations
22

33
import (
4+
"encoding/json"
45
"fmt"
6+
"os"
7+
"os/user"
58
"path"
69
"time"
710

11+
"github.com/1Panel-dev/1Panel/agent/app/dto"
812
"github.com/1Panel-dev/1Panel/agent/app/dto/request"
913
"github.com/1Panel-dev/1Panel/agent/app/model"
1014
"github.com/1Panel-dev/1Panel/agent/app/service"
1115
"github.com/1Panel-dev/1Panel/agent/constant"
1216
"github.com/1Panel-dev/1Panel/agent/global"
1317
"github.com/1Panel-dev/1Panel/agent/utils/common"
18+
"github.com/1Panel-dev/1Panel/agent/utils/copier"
1419
"github.com/1Panel-dev/1Panel/agent/utils/encrypt"
20+
"github.com/1Panel-dev/1Panel/agent/utils/ssh"
1521
"github.com/1Panel-dev/1Panel/agent/utils/xpack"
1622

1723
"github.com/go-gormigrate/gormigrate/v2"
@@ -510,3 +516,40 @@ var UpdateMcpServerAddType = &gormigrate.Migration{
510516
return nil
511517
},
512518
}
519+
520+
var InitLocalSSHConn = &gormigrate.Migration{
521+
ID: "20250905-init-local-ssh",
522+
Migrate: func(tx *gorm.DB) error {
523+
itemPath := ""
524+
currentInfo, _ := user.Current()
525+
if len(currentInfo.HomeDir) == 0 {
526+
itemPath = "/root/.ssh/id_ed25519_1panel"
527+
} else {
528+
itemPath = path.Join(currentInfo.HomeDir, ".ssh/id_ed25519_1panel")
529+
}
530+
if _, err := os.Stat(itemPath); err != nil {
531+
_ = service.NewISSHService().CreateRootCert(dto.CreateRootCert{EncryptionMode: "ed25519", Name: "id_ed25519_1panel", Description: "1Panel Terminal"})
532+
}
533+
privateKey, _ := os.ReadFile(itemPath)
534+
connWithKey := ssh.ConnInfo{
535+
Addr: "127.0.0.1",
536+
User: "root",
537+
Port: 22,
538+
AuthMode: "key",
539+
PrivateKey: privateKey,
540+
}
541+
if _, err := ssh.NewClient(connWithKey); err != nil {
542+
return nil
543+
}
544+
var conn model.LocalConnInfo
545+
_ = copier.Copy(&conn, &connWithKey)
546+
conn.PrivateKey = string(privateKey)
547+
conn.PassPhrase = ""
548+
localConn, _ := json.Marshal(&conn)
549+
connAfterEncrypt, _ := encrypt.StringEncrypt(string(localConn))
550+
if err := tx.Model(&model.Setting{}).Where("key = ?", "LocalSSHConn").Updates(map[string]interface{}{"value": connAfterEncrypt}).Error; err != nil {
551+
return err
552+
}
553+
return nil
554+
},
555+
}

agent/router/ro_setting.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ func (s *SettingRouter) InitRouter(Router *gin.RouterGroup) {
2929
settingRouter.GET("/basedir", baseApi.LoadBaseDir)
3030

3131
settingRouter.POST("/ssh/check", baseApi.CheckLocalConn)
32-
settingRouter.POST("/ssh", baseApi.SaveLocalConnInfo)
32+
settingRouter.GET("/ssh/conn", baseApi.LoadLocalConn)
33+
settingRouter.POST("/ssh", baseApi.SaveLocalConn)
3334
settingRouter.POST("/ssh/check/info", baseApi.CheckLocalConnByInfo)
3435
}
3536
}

frontend/src/api/interface/host.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export namespace Host {
4747
user: string;
4848
authMode: string;
4949
privateKey: string;
50+
passPhrase: string;
5051
password: string;
5152
}
5253
export interface GroupChange {

frontend/src/api/modules/terminal.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ export const deleteHost = (params: { ids: number[] }) => {
6060
};
6161

6262
// agent
63+
export const loadLocalConn = () => {
64+
return http.get<Host.HostConnTest>(`/settings/ssh/conn`);
65+
};
6366
export const testLocalConn = () => {
6467
return http.post<boolean>(`/settings/ssh/check`);
6568
};

frontend/src/lang/modules/en.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1165,6 +1165,8 @@ const message = {
11651165
},
11661166
terminal: {
11671167
local: 'Local',
1168+
defaultConn: 'Default Connection',
1169+
defaultConnHelper: 'Whether to connect to the host by default after opening the terminal',
11681170
localHelper: 'The `local` name is used only for system local identification',
11691171
connLocalErr: 'Unable to automatically authenticate, please fill in the local server login information.',
11701172
testConn: 'Test connection',

frontend/src/lang/modules/ja.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1126,6 +1126,8 @@ const message = {
11261126
},
11271127
terminal: {
11281128
local: 'ローカル',
1129+
defaultConn: 'デフォルト接続',
1130+
defaultConnHelper: 'ターミナルを開いた後にデフォルトでホストに接続するかどうか',
11291131
localHelper: 'ローカル名はシステムのローカル識別にのみ使用されます。',
11301132
connLocalErr: '自動的に認証できない場合は、ローカルサーバーのログイン情報を入力してください。',
11311133
testConn: 'テスト接続',

0 commit comments

Comments
 (0)