feat(client): add authorized WireGuard device enrollment and desktop connection
This commit is contained in:
1 parent
d2f1f5040e
commit
6dd3c7dd45
25 files changed
+3274
-131
No files matched your search
@@ -0,0 +1,84 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"vpn-platform/backend/internal/model"
|
||||
"vpn-platform/backend/internal/store"
|
||||
)
|
||||
|
||||
func TestClientSessionCannotExpandToSameNameOtherLine(t *testing.T) {
|
||||
if err := store.Init(t.TempDir()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
hashA, _ := bcrypt.GenerateFromPassword([]byte("password-a"), bcrypt.MinCost)
|
||||
hashB, _ := bcrypt.GenerateFromPassword([]byte("password-b"), bcrypt.MinCost)
|
||||
lineA := model.Tunnel{Name: "A", Protocol: "wireguard"}
|
||||
lineB := model.Tunnel{Name: "B", Protocol: "wireguard"}
|
||||
store.DB.Create(&lineA)
|
||||
store.DB.Create(&lineB)
|
||||
uA := model.VPNUser{TunnelID: lineA.ID, Username: "same", Password: string(hashA), Enabled: true, Source: "local"}
|
||||
uB := model.VPNUser{TunnelID: lineB.ID, Username: "same", Password: string(hashB), Enabled: true, Source: "local"}
|
||||
store.DB.Create(&uA)
|
||||
store.DB.Create(&uB)
|
||||
passed, _, err := authorizedLines("same", "password-a", "")
|
||||
if err != nil || len(passed) != 1 || passed[0].ID != uA.ID {
|
||||
t.Fatalf("错误的授权记录: %+v, %v", passed, err)
|
||||
}
|
||||
token, _, err := issueClientToken("same", "laptop", "linux", passed)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var session model.ClientSession
|
||||
if err := store.DB.Where("token_hash = ?", clientTokenHash(token)).First(&session).Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
granted := currentGrantedUsers(&session)
|
||||
if _, _, err := clientAuthorizedTunnel(granted, lineB.ID); err == nil {
|
||||
t.Fatal("错误密码的同名线路不得获得授权")
|
||||
}
|
||||
if _, _, err := clientAuthorizedTunnel(granted, lineA.ID); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
store.DB.Model(&uA).Update("password", string(hashB))
|
||||
if got := currentGrantedUsers(&session); len(got) != 0 {
|
||||
t.Fatalf("修改密码后旧授权必须失效: %+v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAllocateClientAddressSkipsUsedAndBoundaries(t *testing.T) {
|
||||
used := map[string]bool{
|
||||
"10.8.0.1": true, // 服务端自身
|
||||
"10.8.0.2": true, // 已占用 Peer
|
||||
}
|
||||
addr, err := allocateClientAddress("10.8.0.1/24", used)
|
||||
if err != nil {
|
||||
t.Fatalf("allocate: %v", err)
|
||||
}
|
||||
if addr != "10.8.0.3/32" {
|
||||
t.Fatalf("应分配第一个空闲地址 10.8.0.3/32,得到 %s", addr)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAllocateClientAddressSmallSubnet(t *testing.T) {
|
||||
// /30 只有 2 个可用主机位,均被占用时必须报错而不是返回网络/广播地址
|
||||
used := map[string]bool{"10.8.0.1": true, "10.8.0.2": true}
|
||||
if _, err := allocateClientAddress("10.8.0.1/30", used); err == nil {
|
||||
t.Fatal("地址耗尽时必须报错")
|
||||
}
|
||||
if _, err := allocateClientAddress("10.8.0.1/31", map[string]bool{}); err == nil {
|
||||
t.Fatal("/31 无可用主机位,必须报错")
|
||||
}
|
||||
if _, err := allocateClientAddress("fd00::1/64", map[string]bool{}); err == nil {
|
||||
t.Fatal("IPv6 网段暂不支持自动分配,必须明确报错")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAllocateClientAddressExhausted(t *testing.T) {
|
||||
used := map[string]bool{"192.168.1.1": true, "192.168.1.2": true, "192.168.1.3": true,
|
||||
"192.168.1.4": true, "192.168.1.5": true, "192.168.1.6": true}
|
||||
if _, err := allocateClientAddress("192.168.1.1/29", used); err == nil {
|
||||
t.Fatal("/29 全部占用时必须报错")
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user