Skip to content

Commit c69a58d

Browse files
authored
Merge pull request #3010 from actiontech/support_ssh_key
support generate, store and get ssh key
2 parents 85cf6e5 + 9fbe96a commit c69a58d

File tree

7 files changed

+293
-6
lines changed

7 files changed

+293
-6
lines changed

sqle/api/app.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,8 @@ func StartApi(net *gracenet.Net, exitChan chan struct{}, config *config.SqleOpti
492492
v1Router.GET("/configurations/drivers", v1.GetDrivers)
493493
v2Router.GET("/configurations/drivers", v2.GetDrivers)
494494
v1Router.GET("/configurations/workflows/schedule/default_option", v1.GetScheduledTaskDefaultOptionV1)
495+
v1Router.GET("/configurations/ssh_key", v1.GetSSHPublicKey, sqleMiddleware.ViewGlobalAllowed())
496+
v1Router.POST("/configurations/ssh_key", v1.GenSSHKey, sqleMiddleware.OpGlobalAllowed())
495497

496498
// audit plan
497499
v1Router.GET("/audit_plan_metas", v1.GetAuditPlanMetas)

sqle/api/controller/v1/configuration.go

Lines changed: 97 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
11
package v1
22

33
import (
4+
"crypto/rsa"
5+
"fmt"
6+
"net/http"
7+
"strconv"
8+
49
"github.com/actiontech/sqle/sqle/utils"
510
"github.com/go-git/go-git/v5/plumbing"
611
"github.com/go-git/go-git/v5/plumbing/storer"
7-
"net/http"
8-
"strconv"
912

1013
"github.com/actiontech/sqle/sqle/api/controller"
1114
"github.com/actiontech/sqle/sqle/driver"
1215

1316
"github.com/actiontech/sqle/sqle/model"
1417

1518
"github.com/labstack/echo/v4"
19+
"golang.org/x/crypto/ssh"
1620
)
1721

1822
type GetDingTalkConfigurationResV1 struct {
@@ -538,3 +542,94 @@ type ScheduledTaskDefaultOptionV1Rsp struct {
538542
func GetScheduledTaskDefaultOptionV1(c echo.Context) error {
539543
return getScheduledTaskDefaultOptionV1(c)
540544
}
545+
546+
type SSHPublicKeyInfoV1Rsp struct {
547+
controller.BaseRes
548+
Data SSHPublicKeyInfo `json:"data"`
549+
}
550+
551+
type SSHPublicKeyInfo struct {
552+
PublicKey string `json:"public_key"`
553+
}
554+
555+
// GetSSHPublicKey
556+
// @Summary 获取SSH公钥
557+
// @Description get ssh public key
558+
// @Tags configuration
559+
// @Id getSSHPublicKey
560+
// @Security ApiKeyAuth
561+
// @Success 200 {object} v1.SSHPublicKeyInfo
562+
// @Router /v1/configurations/ssh_key [get]
563+
func GetSSHPublicKey(c echo.Context) error {
564+
storage := model.GetStorage()
565+
systemVariables, exists, err := storage.GetSystemVariableByKey(model.SystemVariableSSHPrimaryKey)
566+
if err != nil {
567+
c.Logger().Errorf("failed to get ssh public key: %v", err)
568+
return controller.JSONBaseErrorReq(c, err)
569+
}
570+
privateKey, err := ssh.ParseRawPrivateKey([]byte(systemVariables.Value))
571+
if err != nil {
572+
c.Logger().Errorf("failed to parse SSH private key: %v", err)
573+
return controller.JSONBaseErrorReq(c, err)
574+
}
575+
rsaPrivateKey, ok := privateKey.(*rsa.PrivateKey)
576+
if !ok {
577+
return controller.JSONBaseErrorReq(c, fmt.Errorf("private key is not an RSA key"))
578+
}
579+
publicKeyStr, err := utils.GeneratePublicKeyFromPrivateKey(rsaPrivateKey)
580+
if err != nil {
581+
return controller.JSONBaseErrorReq(c, err)
582+
}
583+
584+
return c.JSON(http.StatusOK,
585+
SSHPublicKeyInfoV1Rsp{
586+
Data: SSHPublicKeyInfo{
587+
PublicKey: func() string {
588+
if !exists {
589+
return ""
590+
}
591+
return publicKeyStr
592+
}(),
593+
},
594+
})
595+
}
596+
597+
// GenSSHKey
598+
// @Summary 生成SSH密钥对
599+
// @Description gen ssh key
600+
// @Tags configuration
601+
// @Id genSSHPublicKey
602+
// @Security ApiKeyAuth
603+
// @Success 200 {object} controller.BaseRes
604+
// @Router /v1/configurations/ssh_key [post]
605+
func GenSSHKey(c echo.Context) error {
606+
storage := model.GetStorage()
607+
_, exists, err := storage.GetSystemVariableByKey(model.SystemVariableSSHPrimaryKey)
608+
if err != nil {
609+
return controller.JSONBaseErrorReq(c, err)
610+
}
611+
612+
// 如果已存在密钥,则不重新生成
613+
if exists {
614+
return controller.JSONBaseErrorReq(c, nil)
615+
}
616+
617+
// 生成新的SSH密钥对
618+
primaryKey, _, err := utils.GenerateSSHKeyPair()
619+
if err != nil {
620+
return controller.JSONBaseErrorReq(c, err)
621+
}
622+
623+
// 保存密钥到系统变量
624+
err = storage.PathSaveSystemVariables([]model.SystemVariable{
625+
{
626+
Key: model.SystemVariableSSHPrimaryKey,
627+
Value: primaryKey,
628+
},
629+
})
630+
if err != nil {
631+
return controller.JSONBaseErrorReq(c, err)
632+
}
633+
634+
return controller.JSONBaseErrorReq(c, nil)
635+
}

sqle/docs/docs.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,50 @@ var doc = `{
628628
}
629629
}
630630
},
631+
"/v1/configurations/ssh_key": {
632+
"get": {
633+
"security": [
634+
{
635+
"ApiKeyAuth": []
636+
}
637+
],
638+
"description": "get ssh public key",
639+
"tags": [
640+
"configuration"
641+
],
642+
"summary": "获取SSH公钥",
643+
"operationId": "getSSHPublicKey",
644+
"responses": {
645+
"200": {
646+
"description": "OK",
647+
"schema": {
648+
"$ref": "#/definitions/v1.SSHPublicKeyInfo"
649+
}
650+
}
651+
}
652+
},
653+
"post": {
654+
"security": [
655+
{
656+
"ApiKeyAuth": []
657+
}
658+
],
659+
"description": "gen ssh key",
660+
"tags": [
661+
"configuration"
662+
],
663+
"summary": "生成SSH密钥对",
664+
"operationId": "genSSHPublicKey",
665+
"responses": {
666+
"200": {
667+
"description": "OK",
668+
"schema": {
669+
"$ref": "#/definitions/controller.BaseRes"
670+
}
671+
}
672+
}
673+
}
674+
},
631675
"/v1/configurations/system_variables": {
632676
"get": {
633677
"security": [
@@ -18189,6 +18233,14 @@ var doc = `{
1818918233
}
1819018234
}
1819118235
},
18236+
"v1.SSHPublicKeyInfo": {
18237+
"type": "object",
18238+
"properties": {
18239+
"public_key": {
18240+
"type": "string"
18241+
}
18242+
}
18243+
},
1819218244
"v1.ScheduleTaskDefaultOption": {
1819318245
"type": "object",
1819418246
"properties": {

sqle/docs/swagger.json

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,50 @@
612612
}
613613
}
614614
},
615+
"/v1/configurations/ssh_key": {
616+
"get": {
617+
"security": [
618+
{
619+
"ApiKeyAuth": []
620+
}
621+
],
622+
"description": "get ssh public key",
623+
"tags": [
624+
"configuration"
625+
],
626+
"summary": "获取SSH公钥",
627+
"operationId": "getSSHPublicKey",
628+
"responses": {
629+
"200": {
630+
"description": "OK",
631+
"schema": {
632+
"$ref": "#/definitions/v1.SSHPublicKeyInfo"
633+
}
634+
}
635+
}
636+
},
637+
"post": {
638+
"security": [
639+
{
640+
"ApiKeyAuth": []
641+
}
642+
],
643+
"description": "gen ssh key",
644+
"tags": [
645+
"configuration"
646+
],
647+
"summary": "生成SSH密钥对",
648+
"operationId": "genSSHPublicKey",
649+
"responses": {
650+
"200": {
651+
"description": "OK",
652+
"schema": {
653+
"$ref": "#/definitions/controller.BaseRes"
654+
}
655+
}
656+
}
657+
}
658+
},
615659
"/v1/configurations/system_variables": {
616660
"get": {
617661
"security": [
@@ -18173,6 +18217,14 @@
1817318217
}
1817418218
}
1817518219
},
18220+
"v1.SSHPublicKeyInfo": {
18221+
"type": "object",
18222+
"properties": {
18223+
"public_key": {
18224+
"type": "string"
18225+
}
18226+
}
18227+
},
1817618228
"v1.ScheduleTaskDefaultOption": {
1817718229
"type": "object",
1817818230
"properties": {

sqle/docs/swagger.yaml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4202,6 +4202,11 @@ definitions:
42024202
sql_statement:
42034203
type: string
42044204
type: object
4205+
v1.SSHPublicKeyInfo:
4206+
properties:
4207+
public_key:
4208+
type: string
4209+
type: object
42054210
v1.ScheduleTaskDefaultOption:
42064211
properties:
42074212
default_selector:
@@ -6951,6 +6956,33 @@ paths:
69516956
summary: 获取生成 sqle license需要的的信息
69526957
tags:
69536958
- configuration
6959+
/v1/configurations/ssh_key:
6960+
get:
6961+
description: get ssh public key
6962+
operationId: getSSHPublicKey
6963+
responses:
6964+
"200":
6965+
description: OK
6966+
schema:
6967+
$ref: '#/definitions/v1.SSHPublicKeyInfo'
6968+
security:
6969+
- ApiKeyAuth: []
6970+
summary: 获取SSH公钥
6971+
tags:
6972+
- configuration
6973+
post:
6974+
description: gen ssh key
6975+
operationId: genSSHPublicKey
6976+
responses:
6977+
"200":
6978+
description: OK
6979+
schema:
6980+
$ref: '#/definitions/controller.BaseRes'
6981+
security:
6982+
- ApiKeyAuth: []
6983+
summary: 生成SSH密钥对
6984+
tags:
6985+
- configuration
69546986
/v1/configurations/system_variables:
69556987
get:
69566988
description: get system variables

sqle/model/configuration.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ const (
1818
SystemVariableSqleUrl = "system_variable_sqle_url"
1919
SystemVariableOperationRecordExpiredHours = "system_variable_operation_record_expired_hours"
2020
SystemVariableCbOperationLogsExpiredHours = "system_variable_cb_operation_logs_expired_hours"
21+
SystemVariableSSHPrimaryKey = "system_variable_ssh_primary_key"
2122
)
2223

2324
const (
@@ -28,7 +29,7 @@ const (
2829
// SystemVariable store misc K-V.
2930
type SystemVariable struct {
3031
Key string `gorm:"primary_key"`
31-
Value string `gorm:"not null;type:varchar(255)"`
32+
Value string `gorm:"not null;type:text"`
3233
}
3334

3435
func (s *Storage) PathSaveSystemVariables(systemVariables []SystemVariable) error {
@@ -77,6 +78,23 @@ func (s *Storage) GetAllSystemVariables() (map[string]SystemVariable, error) {
7778
return sysVariables, nil
7879
}
7980

81+
// GetSystemVariableByKey retrieves a system variable by its key.
82+
// Returns the system variable, a boolean indicating if it was found, and any error that occurred.
83+
func (s *Storage) GetSystemVariableByKey(key string) (SystemVariable, bool, error) {
84+
var systemVariable SystemVariable
85+
86+
err := s.db.Where("`key` = ?", key).First(&systemVariable).Error
87+
88+
if err == gorm.ErrRecordNotFound {
89+
return systemVariable, false, nil
90+
}
91+
if err != nil {
92+
return systemVariable, false, errors.New(errors.ConnectStorageError, err)
93+
}
94+
95+
return systemVariable, true, nil
96+
}
97+
8098
func (s *Storage) GetSqleUrl() (string, error) {
8199
sys, err := s.GetAllSystemVariables()
82100
if err != nil {

0 commit comments

Comments
 (0)