Skip to content

Commit 4a59ecd

Browse files
LeeEircbaijiangjie
authored andcommitted
perf: 增加校验认证header
1 parent 801304e commit 4a59ecd

File tree

3 files changed

+143
-1
lines changed

3 files changed

+143
-1
lines changed

pkg/auth/ssh.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"strings"
66

77
"github.com/gliderlabs/ssh"
8+
"github.com/jumpserver/koko/pkg/config"
89
gossh "golang.org/x/crypto/ssh"
910

1011
"github.com/jumpserver/koko/pkg/jms-sdk-go/model"
@@ -36,12 +37,15 @@ func SSHPasswordAndPublicKeyAuth(jmsService *service.JMService) SSHAuthFunc {
3637
userAuthClient, ok := ctx.Value(ContextKeyClient).(*UserAuthClient)
3738
if !ok {
3839
newClient := jmsService.CloneClient()
39-
40+
var accessKey model.AccessKey
41+
conf := config.GetConf()
42+
_ = accessKey.LoadFromFile(conf.AccessKeyFilePath)
4043
userClient := service.NewUserClient(
4144
service.UserClientUsername(username),
4245
service.UserClientRemoteAddr(remoteAddr),
4346
service.UserClientLoginType("T"),
4447
service.UserClientHttpClient(&newClient),
48+
service.UserClientSvcSignKey(accessKey),
4549
)
4650
userAuthClient = &UserAuthClient{
4751
UserClient: userClient,

pkg/jms-sdk-go/service/user_client.go

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
package service
22

33
import (
4+
"bytes"
5+
"crypto/aes"
6+
"encoding/base64"
7+
"fmt"
8+
"strconv"
9+
"strings"
10+
"time"
11+
412
"github.com/jumpserver/koko/pkg/jms-sdk-go/httplib"
513
"github.com/jumpserver/koko/pkg/jms-sdk-go/model"
614
)
@@ -33,6 +41,10 @@ func (u *UserClient) SetOption(setters ...UserClientOption) {
3341
}
3442
}
3543

44+
const (
45+
svcHeader = "X-JMS-SVC"
46+
)
47+
3648
func (u *UserClient) GetAPIToken() (resp AuthResponse, err error) {
3749
data := map[string]string{
3850
"username": u.Opts.Username,
@@ -41,6 +53,15 @@ func (u *UserClient) GetAPIToken() (resp AuthResponse, err error) {
4153
"remote_addr": u.Opts.RemoteAddr,
4254
"login_type": u.Opts.LoginType,
4355
}
56+
ak := u.Opts.signKey
57+
// 移除 Secret 中的 "-", 保证长度为 32
58+
secretKey := strings.ReplaceAll(ak.Secret, "-", "")
59+
encryptKey, err := GenerateEncryptKey(secretKey)
60+
if err != nil {
61+
return resp, err
62+
}
63+
signKey := fmt.Sprintf("%s:%s", ak.ID, encryptKey)
64+
u.client.SetHeader(svcHeader, fmt.Sprintf("Sign %s", signKey))
4465
_, err = u.client.Post(UserTokenAuthURL, data, &resp)
4566
return
4667
}
@@ -129,11 +150,70 @@ func UserClientHttpClient(con *httplib.Client) UserClientOption {
129150
}
130151
}
131152

153+
func UserClientSvcSignKey(key model.AccessKey) UserClientOption {
154+
return func(args *UserClientOptions) {
155+
args.signKey = key
156+
}
157+
}
158+
159+
func GenerateEncryptKey(key string) (string, error) {
160+
seconds := time.Now().Unix()
161+
value := strconv.FormatUint(uint64(seconds), 10)
162+
return EncryptECB(value, key)
163+
}
164+
132165
type UserClientOptions struct {
133166
Username string
134167
Password string
135168
PublicKey string
136169
RemoteAddr string
137170
LoginType string
138171
client *httplib.Client
172+
173+
signKey model.AccessKey
174+
}
175+
176+
func EncryptECB(plaintext string, key string) (string, error) {
177+
block, err := aes.NewCipher([]byte(key))
178+
if err != nil {
179+
return "", err
180+
}
181+
newPlaintext := make([]byte, 0, len(plaintext))
182+
newPlaintext = append(newPlaintext, []byte(plaintext)...)
183+
if len(newPlaintext)%aes.BlockSize != 0 {
184+
padding := aes.BlockSize - len(plaintext)%aes.BlockSize
185+
newPlaintext = append(newPlaintext, bytes.Repeat([]byte{byte(0x00)}, padding)...)
186+
}
187+
188+
ciphertext := make([]byte, len(newPlaintext))
189+
for i := 0; i < len(newPlaintext); i += aes.BlockSize {
190+
block.Encrypt(ciphertext[i:i+aes.BlockSize], newPlaintext[i:i+aes.BlockSize])
191+
}
192+
ret := base64.StdEncoding.EncodeToString(ciphertext)
193+
return ret, nil
194+
}
195+
196+
func DecryptECB(ciphertext string, key string) (string, error) {
197+
ret, err := base64.StdEncoding.DecodeString(ciphertext)
198+
if err != nil {
199+
return "", err
200+
}
201+
block, err := aes.NewCipher([]byte(key))
202+
if err != nil {
203+
return "", err
204+
}
205+
206+
if len(ret)%aes.BlockSize != 0 {
207+
return "", fmt.Errorf("ciphertext is not a multiple of the block size")
208+
}
209+
plaintext := make([]byte, len(ret))
210+
for i := 0; i < len(ret); i += aes.BlockSize {
211+
block.Decrypt(plaintext[i:i+aes.BlockSize], ret[i:i+aes.BlockSize])
212+
}
213+
214+
// 移除 Zero 填充
215+
for len(plaintext) > 0 && plaintext[len(plaintext)-1] == 0x00 {
216+
plaintext = plaintext[:len(plaintext)-1]
217+
}
218+
return string(plaintext), nil
139219
}

pkg/utils/aes_test.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
package utils
22

33
import (
4+
"bytes"
5+
"crypto/aes"
6+
"encoding/base64"
7+
"fmt"
48
"testing"
59
)
610

@@ -23,3 +27,57 @@ func TestDecrypt(t *testing.T) {
2327
}
2428

2529
}
30+
31+
func TestEncrypt(t *testing.T) {
32+
secret := "4bd477efa46d4acea8016af7b332589d"
33+
src := "abc"
34+
ret, err := encryptECB([]byte(src), []byte(secret))
35+
if err != nil {
36+
t.Fatal(err)
37+
}
38+
39+
t.Log(base64.StdEncoding.EncodeToString(ret))
40+
41+
}
42+
43+
func encryptECB(plaintext []byte, key []byte) ([]byte, error) {
44+
block, err := aes.NewCipher(key)
45+
if err != nil {
46+
return nil, err
47+
}
48+
49+
if len(plaintext)%aes.BlockSize != 0 {
50+
padding := aes.BlockSize - len(plaintext)%aes.BlockSize
51+
plaintext = append(plaintext, bytes.Repeat([]byte{byte(0x00)}, padding)...)
52+
}
53+
54+
ciphertext := make([]byte, len(plaintext))
55+
for i := 0; i < len(plaintext); i += aes.BlockSize {
56+
block.Encrypt(ciphertext[i:i+aes.BlockSize], plaintext[i:i+aes.BlockSize])
57+
}
58+
59+
return ciphertext, nil
60+
}
61+
62+
func decryptECB(ciphertext []byte, key []byte) ([]byte, error) {
63+
block, err := aes.NewCipher(key)
64+
if err != nil {
65+
return nil, err
66+
}
67+
68+
if len(ciphertext)%aes.BlockSize != 0 {
69+
return nil, fmt.Errorf("ciphertext is not a multiple of the block size")
70+
}
71+
72+
plaintext := make([]byte, len(ciphertext))
73+
for i := 0; i < len(ciphertext); i += aes.BlockSize {
74+
block.Decrypt(plaintext[i:i+aes.BlockSize], ciphertext[i:i+aes.BlockSize])
75+
}
76+
77+
// 移除 Zero 填充
78+
for len(plaintext) > 0 && plaintext[len(plaintext)-1] == 0x00 {
79+
plaintext = plaintext[:len(plaintext)-1]
80+
}
81+
82+
return plaintext, nil
83+
}

0 commit comments

Comments
 (0)