完成数据库敏感信息的加密
This commit is contained in:
parent
11f2d8a1f4
commit
bceda9a95c
31
docs/faq.md
31
docs/faq.md
@ -108,7 +108,7 @@ Mar 5 20:00:16.923 [DEBU] 用户「admin」密码初始化为: next-terminal
|
|||||||
/ | \_/ __ \\ \/ /\ __\ | |_/ __ \_ __ \/ \| |/ \\__ \ | |
|
/ | \_/ __ \\ \/ /\ __\ | |_/ __ \_ __ \/ \| |/ \\__ \ | |
|
||||||
/ | \ ___/ > < | | | |\ ___/| | \/ Y Y \ | | \/ __ \| |__
|
/ | \ ___/ > < | | | |\ ___/| | \/ Y Y \ | | \/ __ \| |__
|
||||||
\____|__ /\___ >__/\_ \ |__| |____| \___ >__| |__|_| /__|___| (____ /____/
|
\____|__ /\___ >__/\_ \ |__| |____| \___ >__| |__|_| /__|___| (____ /____/
|
||||||
\/ \/ \/ \/ \/ \/ \/ v0.3.0
|
\/ \/ \/ \/ \/ \/ \/ v0.4.0
|
||||||
|
|
||||||
当前数据库模式为:mysql
|
当前数据库模式为:mysql
|
||||||
Mar 5 20:00:16.923 [DEBU] 用户「admin」已重置TOTP
|
Mar 5 20:00:16.923 [DEBU] 用户「admin」已重置TOTP
|
||||||
@ -117,3 +117,32 @@ Mar 5 20:00:16.923 [DEBU] 用户「admin」已重置TOTP
|
|||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>想要修改数据库敏感信息加密的key怎么办?</summary>
|
||||||
|
首先需要进入程序所在目录,使用docker安装的程序目录为:/usr/local/next-terminal
|
||||||
|
|
||||||
|
执行命令
|
||||||
|
|
||||||
|
```shell
|
||||||
|
./next-terminal --encryption-key 旧的加密key new-encryption-key 新的的加密key
|
||||||
|
```
|
||||||
|
|
||||||
|
成功之后会输出
|
||||||
|
|
||||||
|
``` shell
|
||||||
|
|
||||||
|
_______ __ ___________ .__ .__
|
||||||
|
\ \ ____ ___ ____/ |_ \__ ___/__________ _____ |__| ____ _____ | |
|
||||||
|
/ | \_/ __ \\ \/ /\ __\ | |_/ __ \_ __ \/ \| |/ \\__ \ | |
|
||||||
|
/ | \ ___/ > < | | | |\ ___/| | \/ Y Y \ | | \/ __ \| |__
|
||||||
|
\____|__ /\___ >__/\_ \ |__| |____| \___ >__| |__|_| /__|___| (____ /____/
|
||||||
|
\/ \/ \/ \/ \/ \/ \/ v0.4.0
|
||||||
|
|
||||||
|
当前数据库模式为:mysql
|
||||||
|
Mar 5 20:00:16.923 [DEBU] encryption key has being changed.
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
最后重新启动程序,并且把加密key修改为新的。
|
||||||
|
</details>
|
||||||
|
|
||||||
|
@ -104,6 +104,7 @@ docker run -d \
|
|||||||
| MYSQL_PASSWORD | `mysql`数据库密码 |
|
| MYSQL_PASSWORD | `mysql`数据库密码 |
|
||||||
| MYSQL_DATABASE | `mysql`数据库名称 |
|
| MYSQL_DATABASE | `mysql`数据库名称 |
|
||||||
| SERVER_ADDR | 服务器监听地址,默认`0.0.0.0:8088` |
|
| SERVER_ADDR | 服务器监听地址,默认`0.0.0.0:8088` |
|
||||||
|
| ENCRYPTION_KEY | 授权凭证和资产的密码,密钥等敏感信息加密的key,默认`next-terminal` |
|
||||||
|
|
||||||
## 其他
|
## 其他
|
||||||
|
|
||||||
|
@ -147,9 +147,12 @@ sqlite:
|
|||||||
file: 'next-terminal.db'
|
file: 'next-terminal.db'
|
||||||
server:
|
server:
|
||||||
addr: 0.0.0.0:8088
|
addr: 0.0.0.0:8088
|
||||||
# 当设置下面两个参数时会自动开启https模式
|
# 当设置下面两个参数时会自动开启https模式(前提是证书文件存在)
|
||||||
# cert: /root/next-terminal/cert.pem
|
# cert: /root/next-terminal/cert.pem
|
||||||
# key: /root/next-terminal/key.pem
|
# key: /root/next-terminal/key.pem
|
||||||
|
|
||||||
|
# 授权凭证和资产的密码,密钥等敏感信息加密的key,默认`next-terminal`
|
||||||
|
#encryption-key: next-terminal
|
||||||
```
|
```
|
||||||
|
|
||||||
启动
|
启动
|
||||||
|
14
main.go
14
main.go
@ -1,6 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/md5"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"next-terminal/pkg/config"
|
"next-terminal/pkg/config"
|
||||||
@ -12,7 +13,7 @@ import (
|
|||||||
"github.com/labstack/gommon/log"
|
"github.com/labstack/gommon/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
const Version = "v0.3.4"
|
const Version = "v0.4.0"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
err := Run()
|
err := Run()
|
||||||
@ -34,6 +35,12 @@ func Run() error {
|
|||||||
// 为了兼容之前调用global包的代码 后期预期会改为调用pgk/config
|
// 为了兼容之前调用global包的代码 后期预期会改为调用pgk/config
|
||||||
global.Config = config.GlobalCfg
|
global.Config = config.GlobalCfg
|
||||||
|
|
||||||
|
if global.Config.EncryptionKey == "" {
|
||||||
|
global.Config.EncryptionKey = "next-terminal"
|
||||||
|
}
|
||||||
|
md5Sum := fmt.Sprintf("%x", md5.Sum([]byte(global.Config.EncryptionKey)))
|
||||||
|
global.Config.EncryptionPassword = []byte(md5Sum)
|
||||||
|
|
||||||
global.Cache = api.SetupCache()
|
global.Cache = api.SetupCache()
|
||||||
db := api.SetupDB()
|
db := api.SetupDB()
|
||||||
e := api.SetupRoutes(db)
|
e := api.SetupRoutes(db)
|
||||||
@ -44,6 +51,11 @@ func Run() error {
|
|||||||
if global.Config.ResetTotp != "" {
|
if global.Config.ResetTotp != "" {
|
||||||
return api.ResetTotp(global.Config.ResetTotp)
|
return api.ResetTotp(global.Config.ResetTotp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if global.Config.NewEncryptionKey != "" {
|
||||||
|
return api.ChangeEncryptionKey(global.Config.EncryptionKey, global.Config.NewEncryptionKey)
|
||||||
|
}
|
||||||
|
|
||||||
sessionRepo := repository.NewSessionRepository(db)
|
sessionRepo := repository.NewSessionRepository(db)
|
||||||
propertyRepo := repository.NewPropertyRepository(db)
|
propertyRepo := repository.NewPropertyRepository(db)
|
||||||
ticker := task.NewTicker(sessionRepo, propertyRepo)
|
ticker := task.NewTicker(sessionRepo, propertyRepo)
|
||||||
|
@ -11,14 +11,17 @@ import (
|
|||||||
var GlobalCfg *Config
|
var GlobalCfg *Config
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Debug bool
|
Debug bool
|
||||||
Demo bool
|
Demo bool
|
||||||
DB string
|
DB string
|
||||||
Server *Server
|
Server *Server
|
||||||
Mysql *Mysql
|
Mysql *Mysql
|
||||||
Sqlite *Sqlite
|
Sqlite *Sqlite
|
||||||
ResetPassword string
|
ResetPassword string
|
||||||
ResetTotp string
|
ResetTotp string
|
||||||
|
EncryptionKey string
|
||||||
|
EncryptionPassword []byte
|
||||||
|
NewEncryptionKey string
|
||||||
}
|
}
|
||||||
|
|
||||||
type Mysql struct {
|
type Mysql struct {
|
||||||
@ -83,10 +86,12 @@ func SetupConfig() *Config {
|
|||||||
Cert: viper.GetString("server.cert"),
|
Cert: viper.GetString("server.cert"),
|
||||||
Key: viper.GetString("server.key"),
|
Key: viper.GetString("server.key"),
|
||||||
},
|
},
|
||||||
ResetPassword: viper.GetString("reset-password"),
|
ResetPassword: viper.GetString("reset-password"),
|
||||||
ResetTotp: viper.GetString("reset-totp"),
|
ResetTotp: viper.GetString("reset-totp"),
|
||||||
Debug: viper.GetBool("debug"),
|
Debug: viper.GetBool("debug"),
|
||||||
Demo: viper.GetBool("demo"),
|
Demo: viper.GetBool("demo"),
|
||||||
|
EncryptionKey: viper.GetString("encryption-key"),
|
||||||
|
NewEncryptionKey: viper.GetString("new-encryption-key"),
|
||||||
}
|
}
|
||||||
GlobalCfg = config
|
GlobalCfg = config
|
||||||
return config
|
return config
|
||||||
|
58
pkg/service/asset.go
Normal file
58
pkg/service/asset.go
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
|
||||||
|
"next-terminal/pkg/global"
|
||||||
|
"next-terminal/server/repository"
|
||||||
|
"next-terminal/server/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AssetService struct {
|
||||||
|
assetRepository *repository.AssetRepository
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAssetService(assetRepository *repository.AssetRepository) *AssetService {
|
||||||
|
return &AssetService{assetRepository: assetRepository}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r AssetService) Encrypt() error {
|
||||||
|
items, err := r.assetRepository.FindAll()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for i := range items {
|
||||||
|
item := items[i]
|
||||||
|
if item.Encrypted {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if item.Password != "" && item.Password != "-" {
|
||||||
|
encryptedCBC, err := utils.AesEncryptCBC([]byte(item.Password), global.Config.EncryptionPassword)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
item.Password = base64.StdEncoding.EncodeToString(encryptedCBC)
|
||||||
|
}
|
||||||
|
|
||||||
|
if item.PrivateKey != "" && item.PrivateKey != "-" {
|
||||||
|
encryptedCBC, err := utils.AesEncryptCBC([]byte(item.PrivateKey), global.Config.EncryptionPassword)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
item.PrivateKey = base64.StdEncoding.EncodeToString(encryptedCBC)
|
||||||
|
}
|
||||||
|
|
||||||
|
if item.Passphrase != "" && item.Passphrase != "-" {
|
||||||
|
encryptedCBC, err := utils.AesEncryptCBC([]byte(item.Passphrase), global.Config.EncryptionPassword)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
item.Passphrase = base64.StdEncoding.EncodeToString(encryptedCBC)
|
||||||
|
}
|
||||||
|
err = r.assetRepository.EncryptedById(true, item.Password, item.PrivateKey, item.Passphrase, item.ID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
58
pkg/service/credential.go
Normal file
58
pkg/service/credential.go
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
|
||||||
|
"next-terminal/pkg/global"
|
||||||
|
"next-terminal/server/repository"
|
||||||
|
"next-terminal/server/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CredentialService struct {
|
||||||
|
credentialRepository *repository.CredentialRepository
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCredentialService(credentialRepository *repository.CredentialRepository) *CredentialService {
|
||||||
|
return &CredentialService{credentialRepository: credentialRepository}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r CredentialService) Encrypt() error {
|
||||||
|
items, err := r.credentialRepository.FindAll()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for i := range items {
|
||||||
|
item := items[i]
|
||||||
|
if item.Encrypted {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if item.Password != "" && item.Password != "-" {
|
||||||
|
encryptedCBC, err := utils.AesEncryptCBC([]byte(item.Password), global.Config.EncryptionPassword)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
item.Password = base64.StdEncoding.EncodeToString(encryptedCBC)
|
||||||
|
}
|
||||||
|
|
||||||
|
if item.PrivateKey != "" && item.PrivateKey != "-" {
|
||||||
|
encryptedCBC, err := utils.AesEncryptCBC([]byte(item.PrivateKey), global.Config.EncryptionPassword)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
item.PrivateKey = base64.StdEncoding.EncodeToString(encryptedCBC)
|
||||||
|
}
|
||||||
|
|
||||||
|
if item.Passphrase != "" && item.Passphrase != "-" {
|
||||||
|
encryptedCBC, err := utils.AesEncryptCBC([]byte(item.Passphrase), global.Config.EncryptionPassword)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
item.Passphrase = base64.StdEncoding.EncodeToString(encryptedCBC)
|
||||||
|
}
|
||||||
|
err = r.credentialRepository.EncryptedById(true, item.Password, item.PrivateKey, item.Passphrase, item.ID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
@ -160,7 +160,7 @@ func (r ShellJob) Run() {
|
|||||||
|
|
||||||
msgChan := make(chan string)
|
msgChan := make(chan string)
|
||||||
for i := range assets {
|
for i := range assets {
|
||||||
asset, err := r.jobService.assetRepository.FindById(assets[i].ID)
|
asset, err := r.jobService.assetRepository.FindByIdAndDecrypt(assets[i].ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msgChan <- fmt.Sprintf("资产「%v」Shell执行失败,查询数据异常「%v」", assets[i].Name, err.Error())
|
msgChan <- fmt.Sprintf("资产「%v」Shell执行失败,查询数据异常「%v」", assets[i].Name, err.Error())
|
||||||
return
|
return
|
||||||
@ -176,7 +176,7 @@ func (r ShellJob) Run() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
if asset.AccountType == "credential" {
|
if asset.AccountType == "credential" {
|
||||||
credential, err := r.jobService.credentialRepository.FindById(asset.CredentialId)
|
credential, err := r.jobService.credentialRepository.FindByIdAndDecrypt(asset.CredentialId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msgChan <- fmt.Sprintf("资产「%v」Shell执行失败,查询授权凭证数据异常「%v」", assets[i].Name, err.Error())
|
msgChan <- fmt.Sprintf("资产「%v」Shell执行失败,查询授权凭证数据异常「%v」", assets[i].Name, err.Error())
|
||||||
return
|
return
|
||||||
|
@ -33,3 +33,7 @@ func (r SessionService) FixSessionState() error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r SessionService) EmptyPassword() error {
|
||||||
|
return r.sessionRepository.EmptyPassword()
|
||||||
|
}
|
||||||
|
@ -58,7 +58,7 @@ func (r UserService) InitUser() (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r UserService) FixedUserOnlineState() error {
|
func (r UserService) FixUserOnlineState() error {
|
||||||
// 修正用户登录状态
|
// 修正用户登录状态
|
||||||
onlineUsers, err := r.userRepository.FindOnlineUsers()
|
onlineUsers, err := r.userRepository.FindOnlineUsers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"next-terminal/pkg/constant"
|
"next-terminal/pkg/constant"
|
||||||
|
"next-terminal/pkg/global"
|
||||||
"next-terminal/server/model"
|
"next-terminal/server/model"
|
||||||
"next-terminal/server/utils"
|
"next-terminal/server/utils"
|
||||||
|
|
||||||
@ -199,6 +200,9 @@ func AssetUpdateEndpoint(c echo.Context) error {
|
|||||||
item.Description = "-"
|
item.Description = "-"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := assetRepository.Encrypt(&item, global.Config.EncryptionPassword); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if err := assetRepository.UpdateById(&item, id); err != nil {
|
if err := assetRepository.UpdateById(&item, id); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -264,7 +268,7 @@ func AssetGetEndpoint(c echo.Context) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var item model.Asset
|
var item model.Asset
|
||||||
if item, err = assetRepository.FindById(id); err != nil {
|
if item, err = assetRepository.FindByIdAndDecrypt(id); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
attributeMap, err := assetRepository.FindAssetAttrMapByAssetId(id)
|
attributeMap, err := assetRepository.FindAssetAttrMapByAssetId(id)
|
||||||
@ -289,9 +293,12 @@ func AssetTcpingEndpoint(c echo.Context) (err error) {
|
|||||||
|
|
||||||
active := utils.Tcping(item.IP, item.Port)
|
active := utils.Tcping(item.IP, item.Port)
|
||||||
|
|
||||||
if err := assetRepository.UpdateActiveById(active, item.ID); err != nil {
|
if item.Active != active {
|
||||||
return err
|
if err := assetRepository.UpdateActiveById(active, item.ID); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Success(c, active)
|
return Success(c, active)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/base64"
|
||||||
"errors"
|
"errors"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"next-terminal/pkg/constant"
|
"next-terminal/pkg/constant"
|
||||||
|
"next-terminal/pkg/global"
|
||||||
"next-terminal/server/model"
|
"next-terminal/server/model"
|
||||||
"next-terminal/server/utils"
|
"next-terminal/server/utils"
|
||||||
|
|
||||||
@ -32,27 +34,28 @@ func CredentialCreateEndpoint(c echo.Context) error {
|
|||||||
case constant.Custom:
|
case constant.Custom:
|
||||||
item.PrivateKey = "-"
|
item.PrivateKey = "-"
|
||||||
item.Passphrase = "-"
|
item.Passphrase = "-"
|
||||||
if len(item.Username) == 0 {
|
if item.Username == "" {
|
||||||
item.Username = "-"
|
item.Username = "-"
|
||||||
}
|
}
|
||||||
if len(item.Password) == 0 {
|
if item.Password == "" {
|
||||||
item.Password = "-"
|
item.Password = "-"
|
||||||
}
|
}
|
||||||
case constant.PrivateKey:
|
case constant.PrivateKey:
|
||||||
item.Password = "-"
|
item.Password = "-"
|
||||||
if len(item.Username) == 0 {
|
if item.Username == "" {
|
||||||
item.Username = "-"
|
item.Username = "-"
|
||||||
}
|
}
|
||||||
if len(item.PrivateKey) == 0 {
|
if item.PrivateKey == "" {
|
||||||
item.PrivateKey = "-"
|
item.PrivateKey = "-"
|
||||||
}
|
}
|
||||||
if len(item.Passphrase) == 0 {
|
if item.Passphrase == "" {
|
||||||
item.Passphrase = "-"
|
item.Passphrase = "-"
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return Fail(c, -1, "类型错误")
|
return Fail(c, -1, "类型错误")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
item.Encrypted = true
|
||||||
if err := credentialRepository.Create(&item); err != nil {
|
if err := credentialRepository.Create(&item); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -96,26 +99,48 @@ func CredentialUpdateEndpoint(c echo.Context) error {
|
|||||||
case constant.Custom:
|
case constant.Custom:
|
||||||
item.PrivateKey = "-"
|
item.PrivateKey = "-"
|
||||||
item.Passphrase = "-"
|
item.Passphrase = "-"
|
||||||
if len(item.Username) == 0 {
|
if item.Username == "" {
|
||||||
item.Username = "-"
|
item.Username = "-"
|
||||||
}
|
}
|
||||||
if len(item.Password) == 0 {
|
if item.Password == "" {
|
||||||
item.Password = "-"
|
item.Password = "-"
|
||||||
}
|
}
|
||||||
|
if item.Password != "-" {
|
||||||
|
encryptedCBC, err := utils.AesEncryptCBC([]byte(item.Password), global.Config.EncryptionPassword)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
item.Password = base64.StdEncoding.EncodeToString(encryptedCBC)
|
||||||
|
}
|
||||||
case constant.PrivateKey:
|
case constant.PrivateKey:
|
||||||
item.Password = "-"
|
item.Password = "-"
|
||||||
if len(item.Username) == 0 {
|
if item.Username == "" {
|
||||||
item.Username = "-"
|
item.Username = "-"
|
||||||
}
|
}
|
||||||
if len(item.PrivateKey) == 0 {
|
if item.PrivateKey == "" {
|
||||||
item.PrivateKey = "-"
|
item.PrivateKey = "-"
|
||||||
}
|
}
|
||||||
if len(item.Passphrase) == 0 {
|
if item.PrivateKey != "-" {
|
||||||
|
encryptedCBC, err := utils.AesEncryptCBC([]byte(item.PrivateKey), global.Config.EncryptionPassword)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
item.PrivateKey = base64.StdEncoding.EncodeToString(encryptedCBC)
|
||||||
|
}
|
||||||
|
if item.Passphrase == "" {
|
||||||
item.Passphrase = "-"
|
item.Passphrase = "-"
|
||||||
}
|
}
|
||||||
|
if item.Passphrase != "-" {
|
||||||
|
encryptedCBC, err := utils.AesEncryptCBC([]byte(item.Passphrase), global.Config.EncryptionPassword)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
item.Passphrase = base64.StdEncoding.EncodeToString(encryptedCBC)
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return Fail(c, -1, "类型错误")
|
return Fail(c, -1, "类型错误")
|
||||||
}
|
}
|
||||||
|
item.Encrypted = true
|
||||||
|
|
||||||
if err := credentialRepository.UpdateById(&item, id); err != nil {
|
if err := credentialRepository.UpdateById(&item, id); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -149,7 +174,7 @@ func CredentialGetEndpoint(c echo.Context) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
item, err := credentialRepository.FindById(id)
|
item, err := credentialRepository.FindByIdAndDecrypt(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/md5"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -45,6 +47,7 @@ var (
|
|||||||
sessionService *service.SessionService
|
sessionService *service.SessionService
|
||||||
mailService *service.MailService
|
mailService *service.MailService
|
||||||
numService *service.NumService
|
numService *service.NumService
|
||||||
|
assetService *service.AssetService
|
||||||
)
|
)
|
||||||
|
|
||||||
func SetupRoutes(db *gorm.DB) *echo.Echo {
|
func SetupRoutes(db *gorm.DB) *echo.Echo {
|
||||||
@ -54,6 +57,7 @@ func SetupRoutes(db *gorm.DB) *echo.Echo {
|
|||||||
|
|
||||||
if err := InitDBData(); err != nil {
|
if err := InitDBData(); err != nil {
|
||||||
log.WithError(err).Error("初始化数据异常")
|
log.WithError(err).Error("初始化数据异常")
|
||||||
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ReloadData(); err != nil {
|
if err := ReloadData(); err != nil {
|
||||||
@ -251,6 +255,7 @@ func InitService() {
|
|||||||
sessionService = service.NewSessionService(sessionRepository)
|
sessionService = service.NewSessionService(sessionRepository)
|
||||||
mailService = service.NewMailService(propertyRepository)
|
mailService = service.NewMailService(propertyRepository)
|
||||||
numService = service.NewNumService(numRepository)
|
numService = service.NewNumService(numRepository)
|
||||||
|
assetService = service.NewAssetService(assetRepository)
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitDBData() (err error) {
|
func InitDBData() (err error) {
|
||||||
@ -266,12 +271,18 @@ func InitDBData() (err error) {
|
|||||||
if err := jobService.InitJob(); err != nil {
|
if err := jobService.InitJob(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := userService.FixedUserOnlineState(); err != nil {
|
if err := userService.FixUserOnlineState(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := sessionService.FixSessionState(); err != nil {
|
if err := sessionService.FixSessionState(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := sessionService.EmptyPassword(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := assetService.Encrypt(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,6 +323,47 @@ func ResetTotp(username string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ChangeEncryptionKey(oldEncryptionKey, newEncryptionKey string) error {
|
||||||
|
|
||||||
|
oldPassword := []byte(fmt.Sprintf("%x", md5.Sum([]byte(oldEncryptionKey))))
|
||||||
|
newPassword := []byte(fmt.Sprintf("%x", md5.Sum([]byte(newEncryptionKey))))
|
||||||
|
|
||||||
|
credentials, err := credentialRepository.FindAll()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for i := range credentials {
|
||||||
|
credential := credentials[i]
|
||||||
|
if err := credentialRepository.Decrypt(&credential, oldPassword); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := credentialRepository.Encrypt(&credential, newPassword); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := credentialRepository.UpdateById(&credential, credential.ID); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assets, err := assetRepository.FindAll()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for i := range assets {
|
||||||
|
asset := assets[i]
|
||||||
|
if err := assetRepository.Decrypt(&asset, oldPassword); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := assetRepository.Encrypt(&asset, newPassword); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := assetRepository.UpdateById(&asset, asset.ID); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.Infof("encryption key has being changed.")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func SetupCache() *cache.Cache {
|
func SetupCache() *cache.Cache {
|
||||||
// 配置缓存器
|
// 配置缓存器
|
||||||
mCache := cache.New(5*time.Minute, 10*time.Minute)
|
mCache := cache.New(5*time.Minute, 10*time.Minute)
|
||||||
|
@ -137,6 +137,9 @@ func CloseSessionById(sessionId string, code int, reason string) {
|
|||||||
session.DisconnectedTime = utils.NowJsonTime()
|
session.DisconnectedTime = utils.NowJsonTime()
|
||||||
session.Code = code
|
session.Code = code
|
||||||
session.Message = reason
|
session.Message = reason
|
||||||
|
session.Password = "-"
|
||||||
|
session.PrivateKey = "-"
|
||||||
|
session.Passphrase = "-"
|
||||||
|
|
||||||
_ = sessionRepository.UpdateById(&session, sessionId)
|
_ = sessionRepository.UpdateById(&session, sessionId)
|
||||||
}
|
}
|
||||||
@ -359,7 +362,7 @@ type File struct {
|
|||||||
|
|
||||||
func SessionLsEndpoint(c echo.Context) error {
|
func SessionLsEndpoint(c echo.Context) error {
|
||||||
sessionId := c.Param("id")
|
sessionId := c.Param("id")
|
||||||
session, err := sessionRepository.FindById(sessionId)
|
session, err := sessionRepository.FindByIdAndDecrypt(sessionId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ func SSHEndpoint(c echo.Context) (err error) {
|
|||||||
cols, _ := strconv.Atoi(c.QueryParam("cols"))
|
cols, _ := strconv.Atoi(c.QueryParam("cols"))
|
||||||
rows, _ := strconv.Atoi(c.QueryParam("rows"))
|
rows, _ := strconv.Atoi(c.QueryParam("rows"))
|
||||||
|
|
||||||
session, err := sessionRepository.FindById(sessionId)
|
session, err := sessionRepository.FindByIdAndDecrypt(sessionId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := Message{
|
msg := Message{
|
||||||
Type: Closed,
|
Type: Closed,
|
||||||
|
@ -65,7 +65,7 @@ func TunEndpoint(c echo.Context) error {
|
|||||||
configuration.SetParameter("width", width)
|
configuration.SetParameter("width", width)
|
||||||
configuration.SetParameter("height", height)
|
configuration.SetParameter("height", height)
|
||||||
configuration.SetParameter("dpi", dpi)
|
configuration.SetParameter("dpi", dpi)
|
||||||
session, err = sessionRepository.FindById(sessionId)
|
session, err = sessionRepository.FindByIdAndDecrypt(sessionId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
CloseSessionById(sessionId, NotFoundSession, "会话不存在")
|
CloseSessionById(sessionId, NotFoundSession, "会话不存在")
|
||||||
return err
|
return err
|
||||||
|
@ -21,6 +21,7 @@ type Asset struct {
|
|||||||
Created utils.JsonTime `json:"created"`
|
Created utils.JsonTime `json:"created"`
|
||||||
Tags string `json:"tags"`
|
Tags string `json:"tags"`
|
||||||
Owner string `gorm:"index" json:"owner"`
|
Owner string `gorm:"index" json:"owner"`
|
||||||
|
Encrypted bool `json:"encrypted"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type AssetForPage struct {
|
type AssetForPage struct {
|
||||||
|
@ -14,6 +14,7 @@ type Credential struct {
|
|||||||
Passphrase string `json:"passphrase"`
|
Passphrase string `json:"passphrase"`
|
||||||
Created utils.JsonTime `json:"created"`
|
Created utils.JsonTime `json:"created"`
|
||||||
Owner string `gorm:"index" json:"owner"`
|
Owner string `gorm:"index" json:"owner"`
|
||||||
|
Encrypted bool `json:"encrypted"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Credential) TableName() string {
|
func (r *Credential) TableName() string {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package repository
|
package repository
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -145,7 +146,36 @@ func (r AssetRepository) Find(pageIndex, pageSize int, name, protocol, tags stri
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r AssetRepository) Encrypt(item *model.Asset, password []byte) error {
|
||||||
|
if item.Password != "" && item.Password != "-" {
|
||||||
|
encryptedCBC, err := utils.AesEncryptCBC([]byte(item.Password), password)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
item.Password = base64.StdEncoding.EncodeToString(encryptedCBC)
|
||||||
|
}
|
||||||
|
if item.PrivateKey != "" && item.PrivateKey != "-" {
|
||||||
|
encryptedCBC, err := utils.AesEncryptCBC([]byte(item.PrivateKey), password)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
item.PrivateKey = base64.StdEncoding.EncodeToString(encryptedCBC)
|
||||||
|
}
|
||||||
|
if item.Passphrase != "" && item.Passphrase != "-" {
|
||||||
|
encryptedCBC, err := utils.AesEncryptCBC([]byte(item.Passphrase), password)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
item.Passphrase = base64.StdEncoding.EncodeToString(encryptedCBC)
|
||||||
|
}
|
||||||
|
item.Encrypted = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (r AssetRepository) Create(o *model.Asset) (err error) {
|
func (r AssetRepository) Create(o *model.Asset) (err error) {
|
||||||
|
if err := r.Encrypt(o, global.Config.EncryptionPassword); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if err = r.DB.Create(o).Error; err != nil {
|
if err = r.DB.Create(o).Error; err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -157,8 +187,54 @@ func (r AssetRepository) FindById(id string) (o model.Asset, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r AssetRepository) Decrypt(item *model.Asset, password []byte) error {
|
||||||
|
if item.Encrypted {
|
||||||
|
if item.Password != "" && item.Password != "-" {
|
||||||
|
origData, err := base64.StdEncoding.DecodeString(item.Password)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
decryptedCBC, err := utils.AesDecryptCBC(origData, password)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
item.Password = string(decryptedCBC)
|
||||||
|
}
|
||||||
|
if item.PrivateKey != "" && item.PrivateKey != "-" {
|
||||||
|
origData, err := base64.StdEncoding.DecodeString(item.PrivateKey)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
decryptedCBC, err := utils.AesDecryptCBC(origData, password)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
item.PrivateKey = string(decryptedCBC)
|
||||||
|
}
|
||||||
|
if item.Passphrase != "" && item.Passphrase != "-" {
|
||||||
|
origData, err := base64.StdEncoding.DecodeString(item.Passphrase)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
decryptedCBC, err := utils.AesDecryptCBC(origData, password)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
item.Passphrase = string(decryptedCBC)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r AssetRepository) FindByIdAndDecrypt(id string) (o model.Asset, err error) {
|
||||||
|
err = r.DB.Where("id = ?", id).First(&o).Error
|
||||||
|
if err == nil {
|
||||||
|
err = r.Decrypt(&o, global.Config.EncryptionPassword)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func (r AssetRepository) UpdateById(o *model.Asset, id string) error {
|
func (r AssetRepository) UpdateById(o *model.Asset, id string) error {
|
||||||
o.ID = id
|
|
||||||
return r.DB.Updates(o).Error
|
return r.DB.Updates(o).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,6 +243,11 @@ func (r AssetRepository) UpdateActiveById(active bool, id string) error {
|
|||||||
return r.DB.Exec(sql, active, id).Error
|
return r.DB.Exec(sql, active, id).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r AssetRepository) EncryptedById(encrypted bool, password, privateKey, passphrase, id string) error {
|
||||||
|
sql := "update assets set encrypted = ?, password = ?,private_key = ?, passphrase = ? where id = ?"
|
||||||
|
return r.DB.Exec(sql, encrypted, password, privateKey, passphrase, id).Error
|
||||||
|
}
|
||||||
|
|
||||||
func (r AssetRepository) DeleteById(id string) error {
|
func (r AssetRepository) DeleteById(id string) error {
|
||||||
return r.DB.Where("id = ?", id).Delete(&model.Asset{}).Error
|
return r.DB.Where("id = ?", id).Delete(&model.Asset{}).Error
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
package repository
|
package repository
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
|
||||||
"next-terminal/pkg/constant"
|
"next-terminal/pkg/constant"
|
||||||
|
"next-terminal/pkg/global"
|
||||||
"next-terminal/server/model"
|
"next-terminal/server/model"
|
||||||
|
"next-terminal/server/utils"
|
||||||
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
@ -65,6 +69,9 @@ func (r CredentialRepository) Find(pageIndex, pageSize int, name, order, field s
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r CredentialRepository) Create(o *model.Credential) (err error) {
|
func (r CredentialRepository) Create(o *model.Credential) (err error) {
|
||||||
|
if err := r.Encrypt(o, global.Config.EncryptionPassword); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if err = r.DB.Create(o).Error; err != nil {
|
if err = r.DB.Create(o).Error; err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -76,6 +83,79 @@ func (r CredentialRepository) FindById(id string) (o model.Credential, err error
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r CredentialRepository) Encrypt(item *model.Credential, password []byte) error {
|
||||||
|
if item.Password != "-" {
|
||||||
|
encryptedCBC, err := utils.AesEncryptCBC([]byte(item.Password), password)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
item.Password = base64.StdEncoding.EncodeToString(encryptedCBC)
|
||||||
|
}
|
||||||
|
if item.PrivateKey != "-" {
|
||||||
|
encryptedCBC, err := utils.AesEncryptCBC([]byte(item.PrivateKey), password)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
item.PrivateKey = base64.StdEncoding.EncodeToString(encryptedCBC)
|
||||||
|
}
|
||||||
|
if item.Passphrase != "-" {
|
||||||
|
encryptedCBC, err := utils.AesEncryptCBC([]byte(item.Passphrase), password)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
item.Passphrase = base64.StdEncoding.EncodeToString(encryptedCBC)
|
||||||
|
}
|
||||||
|
item.Encrypted = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r CredentialRepository) Decrypt(item *model.Credential, password []byte) error {
|
||||||
|
if item.Encrypted {
|
||||||
|
if item.Password != "" && item.Password != "-" {
|
||||||
|
origData, err := base64.StdEncoding.DecodeString(item.Password)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
decryptedCBC, err := utils.AesDecryptCBC(origData, password)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
item.Password = string(decryptedCBC)
|
||||||
|
}
|
||||||
|
if item.PrivateKey != "" && item.PrivateKey != "-" {
|
||||||
|
origData, err := base64.StdEncoding.DecodeString(item.PrivateKey)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
decryptedCBC, err := utils.AesDecryptCBC(origData, password)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
item.PrivateKey = string(decryptedCBC)
|
||||||
|
}
|
||||||
|
if item.Passphrase != "" && item.Passphrase != "-" {
|
||||||
|
origData, err := base64.StdEncoding.DecodeString(item.Passphrase)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
decryptedCBC, err := utils.AesDecryptCBC(origData, password)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
item.Passphrase = string(decryptedCBC)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r CredentialRepository) FindByIdAndDecrypt(id string) (o model.Credential, err error) {
|
||||||
|
err = r.DB.Where("id = ?", id).First(&o).Error
|
||||||
|
if err == nil {
|
||||||
|
err = r.Decrypt(&o, global.Config.EncryptionPassword)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func (r CredentialRepository) UpdateById(o *model.Credential, id string) error {
|
func (r CredentialRepository) UpdateById(o *model.Credential, id string) error {
|
||||||
o.ID = id
|
o.ID = id
|
||||||
return r.DB.Updates(o).Error
|
return r.DB.Updates(o).Error
|
||||||
@ -107,3 +187,13 @@ func (r CredentialRepository) CountByUserId(userId string) (total int64, err err
|
|||||||
err = db.Find(&model.Credential{}).Count(&total).Error
|
err = db.Find(&model.Credential{}).Count(&total).Error
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r CredentialRepository) FindAll() (o []model.Credential, err error) {
|
||||||
|
err = r.DB.Find(&o).Error
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r CredentialRepository) EncryptedById(encrypted bool, password, privateKey, passphrase, id string) error {
|
||||||
|
sql := "update assets set encrypted = ?, password = ?,private_key = ?, passphrase = ? where id = ?"
|
||||||
|
return r.DB.Exec(sql, encrypted, password, privateKey, passphrase, id).Error
|
||||||
|
}
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
package repository
|
package repository
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/base64"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"next-terminal/pkg/constant"
|
"next-terminal/pkg/constant"
|
||||||
|
"next-terminal/pkg/global"
|
||||||
"next-terminal/server/model"
|
"next-terminal/server/model"
|
||||||
|
"next-terminal/server/utils"
|
||||||
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
@ -93,6 +96,51 @@ func (r SessionRepository) FindById(id string) (o model.Session, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r SessionRepository) FindByIdAndDecrypt(id string) (o model.Session, err error) {
|
||||||
|
err = r.DB.Where("id = ?", id).First(&o).Error
|
||||||
|
if err == nil {
|
||||||
|
err = r.Decrypt(&o)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r SessionRepository) Decrypt(item *model.Session) error {
|
||||||
|
if item.Password != "" && item.Password != "-" {
|
||||||
|
origData, err := base64.StdEncoding.DecodeString(item.Password)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
decryptedCBC, err := utils.AesDecryptCBC(origData, global.Config.EncryptionPassword)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
item.Password = string(decryptedCBC)
|
||||||
|
}
|
||||||
|
if item.PrivateKey != "" && item.PrivateKey != "-" {
|
||||||
|
origData, err := base64.StdEncoding.DecodeString(item.PrivateKey)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
decryptedCBC, err := utils.AesDecryptCBC(origData, global.Config.EncryptionPassword)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
item.PrivateKey = string(decryptedCBC)
|
||||||
|
}
|
||||||
|
if item.Passphrase != "" && item.Passphrase != "-" {
|
||||||
|
origData, err := base64.StdEncoding.DecodeString(item.Passphrase)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
decryptedCBC, err := utils.AesDecryptCBC(origData, global.Config.EncryptionPassword)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
item.Passphrase = string(decryptedCBC)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (r SessionRepository) FindByConnectionId(connectionId string) (o model.Session, err error) {
|
func (r SessionRepository) FindByConnectionId(connectionId string) (o model.Session, err error) {
|
||||||
err = r.DB.Where("connection_id = ?", connectionId).First(&o).Error
|
err = r.DB.Where("connection_id = ?", connectionId).First(&o).Error
|
||||||
return
|
return
|
||||||
@ -167,3 +215,8 @@ func (r SessionRepository) CountSessionByDay(day int) (results []D, err error) {
|
|||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r SessionRepository) EmptyPassword() error {
|
||||||
|
sql := "update sessions set password = '-',private_key = '-', passphrase = '-' where 1=1"
|
||||||
|
return r.DB.Exec(sql).Error
|
||||||
|
}
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
package utils_test
|
package utils_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/md5"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@ -51,3 +54,26 @@ func TestAesDecryptCBC(t *testing.T) {
|
|||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, "Hello Next Terminal", string(decryptCBC))
|
assert.Equal(t, "Hello Next Terminal", string(decryptCBC))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPbkdf2(t *testing.T) {
|
||||||
|
pbkdf2, err := utils.Pbkdf2("1234")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
println(hex.EncodeToString(pbkdf2))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAesEncryptCBCWithAnyKey(t *testing.T) {
|
||||||
|
origData := []byte("admin") // 待加密的数据
|
||||||
|
key := []byte(fmt.Sprintf("%x", md5.Sum([]byte("next-terminal")))) // 加密的密钥
|
||||||
|
encryptedCBC, err := utils.AesEncryptCBC(origData, key)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "3qwawlPxghyiLS5hdr/p0g==", base64.StdEncoding.EncodeToString(encryptedCBC))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAesDecryptCBCWithAnyKey(t *testing.T) {
|
||||||
|
origData, err := base64.StdEncoding.DecodeString("3qwawlPxghyiLS5hdr/p0g==") // 待解密的数据
|
||||||
|
assert.NoError(t, err)
|
||||||
|
key := []byte(fmt.Sprintf("%x", md5.Sum([]byte("next-terminal")))) // 加密的密钥
|
||||||
|
decryptCBC, err := utils.AesDecryptCBC(origData, key)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "admin", string(decryptCBC))
|
||||||
|
}
|
||||||
|
@ -5,6 +5,8 @@ import (
|
|||||||
"crypto/aes"
|
"crypto/aes"
|
||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/sha256"
|
||||||
"database/sql/driver"
|
"database/sql/driver"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -19,6 +21,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/pbkdf2"
|
||||||
|
|
||||||
"github.com/gofrs/uuid"
|
"github.com/gofrs/uuid"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
@ -239,6 +243,7 @@ func PKCS5UnPadding(origData []byte) []byte {
|
|||||||
return origData[:(length - unPadding)]
|
return origData[:(length - unPadding)]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AesEncryptCBC /*
|
||||||
func AesEncryptCBC(origData, key []byte) ([]byte, error) {
|
func AesEncryptCBC(origData, key []byte) ([]byte, error) {
|
||||||
block, err := aes.NewCipher(key)
|
block, err := aes.NewCipher(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -266,3 +271,15 @@ func AesDecryptCBC(encrypted, key []byte) ([]byte, error) {
|
|||||||
origData = PKCS5UnPadding(origData)
|
origData = PKCS5UnPadding(origData)
|
||||||
return origData, nil
|
return origData, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Pbkdf2(password string) ([]byte, error) {
|
||||||
|
//生成随机盐
|
||||||
|
salt := make([]byte, 32)
|
||||||
|
_, err := rand.Read(salt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
//生成密文
|
||||||
|
dk := pbkdf2.Key([]byte(password), salt, 1, 32, sha256.New)
|
||||||
|
return dk, nil
|
||||||
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "next-terminal",
|
"name": "next-terminal",
|
||||||
"version": "0.3.4",
|
"version": "0.4.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ant-design/icons": "^4.3.0",
|
"@ant-design/icons": "^4.3.0",
|
||||||
|
@ -355,10 +355,10 @@ class Asset extends Component {
|
|||||||
window.open(`#/access?assetId=${id}&assetName=${name}&protocol=${protocol}`);
|
window.open(`#/access?assetId=${id}&assetName=${name}&protocol=${protocol}`);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
message.warn('您访问的资产未在线,请确认网络状态。', 10);
|
message.warn({content: '您访问的资产未在线,请确认网络状态。', key: id, duration: 10});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
message.error('操作失败 :( ' + result.message, 10);
|
message.error({content: result.message, key: id, duration: 10});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user