[management] fix a bug with missed extra dns labels for a new peer (#3798)

This commit is contained in:
Vlad 2025-05-14 17:50:21 +02:00 committed by GitHub
parent 2158461121
commit adf494e1ac
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 307 additions and 116 deletions

View File

@ -8,6 +8,8 @@ import (
const maxDomains = 32 const maxDomains = 32
var domainRegex = regexp.MustCompile(`^(?:\*\.)?(?:(?:xn--)?[a-zA-Z0-9_](?:[a-zA-Z0-9-_]{0,61}[a-zA-Z0-9])?\.)*(?:xn--)?[a-zA-Z0-9](?:[a-zA-Z0-9-_]{0,61}[a-zA-Z0-9])?$`)
// ValidateDomains checks if each domain in the list is valid and returns a punycode-encoded DomainList. // ValidateDomains checks if each domain in the list is valid and returns a punycode-encoded DomainList.
func ValidateDomains(domains []string) (List, error) { func ValidateDomains(domains []string) (List, error) {
if len(domains) == 0 { if len(domains) == 0 {
@ -17,8 +19,6 @@ func ValidateDomains(domains []string) (List, error) {
return nil, fmt.Errorf("domains list exceeds maximum allowed domains: %d", maxDomains) return nil, fmt.Errorf("domains list exceeds maximum allowed domains: %d", maxDomains)
} }
domainRegex := regexp.MustCompile(`^(?:\*\.)?(?:(?:xn--)?[a-zA-Z0-9_](?:[a-zA-Z0-9-_]{0,61}[a-zA-Z0-9])?\.)*(?:xn--)?[a-zA-Z0-9](?:[a-zA-Z0-9-_]{0,61}[a-zA-Z0-9])?$`)
var domainList List var domainList List
for _, d := range domains { for _, d := range domains {
@ -37,27 +37,20 @@ func ValidateDomains(domains []string) (List, error) {
return domainList, nil return domainList, nil
} }
// ValidateDomainsStrSlice checks if each domain in the list is valid // ValidateDomainsList checks if each domain in the list is valid
func ValidateDomainsStrSlice(domains []string) ([]string, error) { func ValidateDomainsList(domains []string) error {
if len(domains) == 0 { if len(domains) == 0 {
return nil, nil return nil
} }
if len(domains) > maxDomains { if len(domains) > maxDomains {
return nil, fmt.Errorf("domains list exceeds maximum allowed domains: %d", maxDomains) return fmt.Errorf("domains list exceeds maximum allowed domains: %d", maxDomains)
} }
domainRegex := regexp.MustCompile(`^(?:\*\.)?(?:(?:xn--)?[a-zA-Z0-9_](?:[a-zA-Z0-9-_]{0,61}[a-zA-Z0-9])?\.)*(?:xn--)?[a-zA-Z0-9](?:[a-zA-Z0-9-_]{0,61}[a-zA-Z0-9])?$`)
var domainList []string
for _, d := range domains { for _, d := range domains {
d := strings.ToLower(d) d := strings.ToLower(d)
if !domainRegex.MatchString(d) { if !domainRegex.MatchString(d) {
return domainList, fmt.Errorf("invalid domain format: %s", d) return fmt.Errorf("invalid domain format: %s", d)
} }
domainList = append(domainList, d)
} }
return domainList, nil return nil
} }

View File

@ -97,36 +97,30 @@ func TestValidateDomains(t *testing.T) {
} }
} }
// TestValidateDomainsStrSlice tests the ValidateDomainsStrSlice function. func TestValidateDomainsList(t *testing.T) {
func TestValidateDomainsStrSlice(t *testing.T) {
// Generate a slice of valid domains up to maxDomains
validDomains := make([]string, maxDomains) validDomains := make([]string, maxDomains)
for i := 0; i < maxDomains; i++ { for i := range maxDomains {
validDomains[i] = fmt.Sprintf("example%d.com", i) validDomains[i] = fmt.Sprintf("example%d.com", i)
} }
tests := []struct { tests := []struct {
name string name string
domains []string domains []string
expected []string
wantErr bool wantErr bool
}{ }{
{ {
name: "Empty list", name: "Empty list",
domains: nil, domains: nil,
expected: nil,
wantErr: false, wantErr: false,
}, },
{ {
name: "Single valid ASCII domain", name: "Single valid ASCII domain",
domains: []string{"sub.ex-ample.com"}, domains: []string{"sub.ex-ample.com"},
expected: []string{"sub.ex-ample.com"},
wantErr: false, wantErr: false,
}, },
{ {
name: "Underscores in labels", name: "Underscores in labels",
domains: []string{"_jabber._tcp.gmail.com"}, domains: []string{"_jabber._tcp.gmail.com"},
expected: []string{"_jabber._tcp.gmail.com"},
wantErr: false, wantErr: false,
}, },
{ {
@ -134,73 +128,58 @@ func TestValidateDomainsStrSlice(t *testing.T) {
// ValidateDomainsStrSlice will fail on non-ASCII domain chars. // ValidateDomainsStrSlice will fail on non-ASCII domain chars.
name: "Unicode domain fails (no punycode conversion)", name: "Unicode domain fails (no punycode conversion)",
domains: []string{"münchen.de"}, domains: []string{"münchen.de"},
expected: nil,
wantErr: true, wantErr: true,
}, },
{ {
name: "Invalid domain format - leading dash", name: "Invalid domain format - leading dash",
domains: []string{"-example.com"}, domains: []string{"-example.com"},
expected: nil,
wantErr: true, wantErr: true,
}, },
{ {
name: "Invalid domain format - trailing dash", name: "Invalid domain format - trailing dash",
domains: []string{"example-.com"}, domains: []string{"example-.com"},
expected: nil,
wantErr: true, wantErr: true,
}, },
{ {
// The function stops on the first invalid domain and returns an error,
// so only the first domain is definitely valid, but the second is invalid.
name: "Multiple domains with a valid one, then invalid", name: "Multiple domains with a valid one, then invalid",
domains: []string{"google.com", "invalid_domain.com-"}, domains: []string{"google.com", "invalid_domain.com-"},
expected: []string{"google.com"},
wantErr: true, wantErr: true,
}, },
{ {
name: "Valid wildcard domain", name: "Valid wildcard domain",
domains: []string{"*.example.com"}, domains: []string{"*.example.com"},
expected: []string{"*.example.com"},
wantErr: false, wantErr: false,
}, },
{ {
name: "Wildcard with leading dot - invalid", name: "Wildcard with leading dot - invalid",
domains: []string{".*.example.com"}, domains: []string{".*.example.com"},
expected: nil,
wantErr: true, wantErr: true,
}, },
{ {
name: "Invalid wildcard with multiple asterisks", name: "Invalid wildcard with multiple asterisks",
domains: []string{"a.*.example.com"}, domains: []string{"a.*.example.com"},
expected: nil,
wantErr: true, wantErr: true,
}, },
{ {
name: "Exactly maxDomains items (valid)", name: "Exactly maxDomains items (valid)",
domains: validDomains, domains: validDomains,
expected: validDomains,
wantErr: false, wantErr: false,
}, },
{ {
name: "Exceeds maxDomains items", name: "Exceeds maxDomains items",
domains: append(validDomains, "extra.com"), domains: append(validDomains, "extra.com"),
expected: nil,
wantErr: true, wantErr: true,
}, },
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
got, err := ValidateDomainsStrSlice(tt.domains) err := ValidateDomainsList(tt.domains)
// Check if we got an error where expected
if tt.wantErr { if tt.wantErr {
assert.Error(t, err) assert.Error(t, err)
} else { } else {
assert.NoError(t, err) assert.NoError(t, err)
} }
// Compare the returned domains to what we expect
assert.Equal(t, tt.expected, got)
}) })
} }
} }

View File

@ -556,6 +556,10 @@ func (am *DefaultAccountManager) AddPeer(ctx context.Context, setupKey, userID s
return fmt.Errorf("failed to get free IP: %w", err) return fmt.Errorf("failed to get free IP: %w", err)
} }
if err := domain.ValidateDomainsList(peer.ExtraDNSLabels); err != nil {
return status.Errorf(status.InvalidArgument, "invalid extra DNS labels: %v", err)
}
registrationTime := time.Now().UTC() registrationTime := time.Now().UTC()
newPeer = &nbpeer.Peer{ newPeer = &nbpeer.Peer{
ID: xid.New().String(), ID: xid.New().String(),
@ -771,6 +775,7 @@ func (am *DefaultAccountManager) handlePeerLoginNotFound(ctx context.Context, lo
Meta: login.Meta, Meta: login.Meta,
SSHKey: login.SSHKey, SSHKey: login.SSHKey,
Location: nbpeer.Location{ConnectionIP: login.ConnectionIP}, Location: nbpeer.Location{ConnectionIP: login.ConnectionIP},
ExtraDNSLabels: login.ExtraDNSLabels,
} }
return am.AddPeer(ctx, login.SetupKey, login.UserID, newPeer) return am.AddPeer(ctx, login.SetupKey, login.UserID, newPeer)
@ -875,16 +880,6 @@ func (am *DefaultAccountManager) LoginPeer(ctx context.Context, login types.Peer
return status.Errorf(status.PreconditionFailed, "couldn't login peer: setup key doesn't allow extra DNS labels") return status.Errorf(status.PreconditionFailed, "couldn't login peer: setup key doesn't allow extra DNS labels")
} }
extraLabels, err := domain.ValidateDomainsStrSlice(login.ExtraDNSLabels)
if err != nil {
return status.Errorf(status.InvalidArgument, "invalid extra DNS labels: %v", err)
}
if !slices.Equal(peer.ExtraDNSLabels, extraLabels) {
peer.ExtraDNSLabels = extraLabels
shouldStorePeer = true
}
if shouldStorePeer { if shouldStorePeer {
if err = transaction.SavePeer(ctx, store.LockingStrengthUpdate, accountID, peer); err != nil { if err = transaction.SavePeer(ctx, store.LockingStrengthUpdate, accountID, peer); err != nil {
return err return err

View File

@ -10,6 +10,7 @@ import (
"net/netip" "net/netip"
"os" "os"
"runtime" "runtime"
"strings"
"testing" "testing"
"time" "time"
@ -1290,15 +1291,21 @@ func Test_RegisterPeerByUser(t *testing.T) {
Status: &nbpeer.PeerStatus{Connected: false, LastSeen: time.Now()}, Status: &nbpeer.PeerStatus{Connected: false, LastSeen: time.Now()},
SSHEnabled: false, SSHEnabled: false,
LastLogin: util.ToPtr(time.Now()), LastLogin: util.ToPtr(time.Now()),
ExtraDNSLabels: []string{
"extraLabel1",
"extraLabel2",
},
} }
addedPeer, _, _, err := am.AddPeer(context.Background(), "", existingUserID, newPeer) addedPeer, _, _, err := am.AddPeer(context.Background(), "", existingUserID, newPeer)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, newPeer.ExtraDNSLabels, addedPeer.ExtraDNSLabels)
peer, err := s.GetPeerByPeerPubKey(context.Background(), store.LockingStrengthShare, addedPeer.Key) peer, err := s.GetPeerByPeerPubKey(context.Background(), store.LockingStrengthShare, addedPeer.Key)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, peer.AccountID, existingAccountID) assert.Equal(t, peer.AccountID, existingAccountID)
assert.Equal(t, peer.UserID, existingUserID) assert.Equal(t, peer.UserID, existingUserID)
assert.Equal(t, newPeer.ExtraDNSLabels, peer.ExtraDNSLabels)
account, err := s.GetAccount(context.Background(), existingAccountID) account, err := s.GetAccount(context.Background(), existingAccountID)
require.NoError(t, err) require.NoError(t, err)
@ -1339,15 +1346,12 @@ func Test_RegisterPeerBySetupKey(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
existingAccountID := "bf1c8084-ba50-4ce7-9439-34653001fc3b" existingAccountID := "bf1c8084-ba50-4ce7-9439-34653001fc3b"
existingSetupKeyID := "A2C8E62B-38F5-4553-B31E-DD66C696CEBB"
_, err = s.GetAccount(context.Background(), existingAccountID) _, err = s.GetAccount(context.Background(), existingAccountID)
require.NoError(t, err) require.NoError(t, err)
newPeer := &nbpeer.Peer{ newPeerTemplate := &nbpeer.Peer{
ID: xid.New().String(),
AccountID: existingAccountID, AccountID: existingAccountID,
Key: "newPeerKey",
UserID: "", UserID: "",
IP: net.IP{123, 123, 123, 123}, IP: net.IP{123, 123, 123, 123},
Meta: nbpeer.PeerSystemMeta{ Meta: nbpeer.PeerSystemMeta{
@ -1358,31 +1362,96 @@ func Test_RegisterPeerBySetupKey(t *testing.T) {
DNSLabel: "newPeer.test", DNSLabel: "newPeer.test",
Status: &nbpeer.PeerStatus{Connected: false, LastSeen: time.Now()}, Status: &nbpeer.PeerStatus{Connected: false, LastSeen: time.Now()},
SSHEnabled: false, SSHEnabled: false,
ExtraDNSLabels: []string{
"extraLabel1",
"extraLabel2",
},
} }
addedPeer, _, _, err := am.AddPeer(context.Background(), existingSetupKeyID, "", newPeer) testCases := []struct {
name string
existingSetupKeyID string
expectedGroupIDsInAccount []string
expectAddPeerError bool
expectedErrorMsgSubstring string
}{
{
name: "Successful registration with setup key allowing extra DNS labels",
existingSetupKeyID: "A2C8E62B-38F5-4553-B31E-DD66C696CEBD",
expectAddPeerError: false,
expectedGroupIDsInAccount: []string{"cfefqs706sqkneg59g2g", "cfefqs706sqkneg59g4g"},
},
{
name: "Failed registration with setup key not allowing extra DNS labels",
existingSetupKeyID: "A2C8E62B-38F5-4553-B31E-DD66C696CEBB",
expectAddPeerError: true,
expectedErrorMsgSubstring: "setup key doesn't allow extra DNS labels",
},
{
name: "Absent setup key",
existingSetupKeyID: "AAAAAAAA-38F5-4553-B31E-DD66C696CEBB",
expectAddPeerError: true,
expectedErrorMsgSubstring: "failed adding new peer: account not found",
},
}
require.NoError(t, err) for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
currentPeer := &nbpeer.Peer{
ID: xid.New().String(),
AccountID: newPeerTemplate.AccountID,
Key: "newPeerKey_" + xid.New().String(),
UserID: newPeerTemplate.UserID,
IP: newPeerTemplate.IP,
Meta: newPeerTemplate.Meta,
Name: newPeerTemplate.Name,
DNSLabel: newPeerTemplate.DNSLabel,
Status: &nbpeer.PeerStatus{Connected: false, LastSeen: time.Now()},
SSHEnabled: newPeerTemplate.SSHEnabled,
ExtraDNSLabels: newPeerTemplate.ExtraDNSLabels,
}
peer, err := s.GetPeerByPeerPubKey(context.Background(), store.LockingStrengthShare, newPeer.Key) addedPeer, _, _, err := am.AddPeer(context.Background(), tc.existingSetupKeyID, "", currentPeer)
require.NoError(t, err)
assert.Equal(t, peer.AccountID, existingAccountID) if tc.expectAddPeerError {
require.Error(t, err, "Expected an error when adding peer with setup key: %s", tc.existingSetupKeyID)
assert.Contains(t, err.Error(), tc.expectedErrorMsgSubstring, "Error message mismatch")
return
}
require.NoError(t, err, "Expected no error when adding peer with setup key: %s", tc.existingSetupKeyID)
assert.NotNil(t, addedPeer, "addedPeer should not be nil on success")
assert.Equal(t, currentPeer.ExtraDNSLabels, addedPeer.ExtraDNSLabels, "ExtraDNSLabels mismatch")
peerFromStore, err := s.GetPeerByPeerPubKey(context.Background(), store.LockingStrengthShare, currentPeer.Key)
require.NoError(t, err, "Failed to get peer by pub key: %s", currentPeer.Key)
assert.Equal(t, existingAccountID, peerFromStore.AccountID, "AccountID mismatch for peer from store")
assert.Equal(t, currentPeer.ExtraDNSLabels, peerFromStore.ExtraDNSLabels, "ExtraDNSLabels mismatch for peer from store")
assert.Equal(t, addedPeer.ID, peerFromStore.ID, "Peer ID mismatch between addedPeer and peerFromStore")
account, err := s.GetAccount(context.Background(), existingAccountID) account, err := s.GetAccount(context.Background(), existingAccountID)
require.NoError(t, err) require.NoError(t, err, "Failed to get account: %s", existingAccountID)
assert.Contains(t, account.Peers, addedPeer.ID) assert.Contains(t, account.Peers, addedPeer.ID, "Peer ID not found in account.Peers")
assert.Contains(t, account.Groups["cfefqs706sqkneg59g2g"].Peers, addedPeer.ID)
assert.Contains(t, account.Groups["cfefqs706sqkneg59g4g"].Peers, addedPeer.ID)
assert.Equal(t, uint64(1), account.Network.Serial) for _, groupID := range tc.expectedGroupIDsInAccount {
require.NotNil(t, account.Groups[groupID], "Group %s not found in account", groupID)
assert.Contains(t, account.Groups[groupID].Peers, addedPeer.ID, "Peer ID %s not found in group %s", addedPeer.ID, groupID)
}
lastUsed, err := time.Parse("2006-01-02T15:04:05Z", "0001-01-01T00:00:00Z") assert.Equal(t, uint64(1), account.Network.Serial, "Network.Serial mismatch; this assumes specific initial state or increment logic.")
assert.NoError(t, err)
hashedKey := sha256.Sum256([]byte(existingSetupKeyID)) hashedKey := sha256.Sum256([]byte(tc.existingSetupKeyID))
encodedHashedKey := b64.StdEncoding.EncodeToString(hashedKey[:]) encodedHashedKey := b64.StdEncoding.EncodeToString(hashedKey[:])
assert.NotEqual(t, lastUsed, account.SetupKeys[encodedHashedKey].LastUsed)
assert.Equal(t, 1, account.SetupKeys[encodedHashedKey].UsedTimes) setupKeyData, ok := account.SetupKeys[encodedHashedKey]
require.True(t, ok, "Setup key data not found in account.SetupKeys for key ID %s (encoded: %s)", tc.existingSetupKeyID, encodedHashedKey)
var zeroTime time.Time
assert.NotEqual(t, zeroTime, setupKeyData.LastUsed, "Setup key LastUsed time should have been updated and not be zero.")
assert.Equal(t, 1, setupKeyData.UsedTimes, "Setup key UsedTimes should be 1 after first use.")
})
}
} }
@ -1456,6 +1525,160 @@ func Test_RegisterPeerRollbackOnFailure(t *testing.T) {
assert.Equal(t, 0, account.SetupKeys[encodedHashedKey].UsedTimes) assert.Equal(t, 0, account.SetupKeys[encodedHashedKey].UsedTimes)
} }
func Test_LoginPeer(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("The SQLite store is not properly supported by Windows yet")
}
s, cleanup, err := store.NewTestStoreFromSQL(context.Background(), "testdata/extended-store.sql", t.TempDir())
if err != nil {
t.Fatal(err)
}
defer cleanup()
eventStore := &activity.InMemoryEventStore{}
metrics, err := telemetry.NewDefaultAppMetrics(context.Background())
assert.NoError(t, err)
ctrl := gomock.NewController(t)
t.Cleanup(ctrl.Finish)
settingsMockManager := settings.NewMockManager(ctrl)
permissionsManager := permissions.NewManager(s)
am, err := BuildManager(context.Background(), s, NewPeersUpdateManager(nil), nil, "", "netbird.cloud", eventStore, nil, false, MocIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager)
assert.NoError(t, err)
existingAccountID := "bf1c8084-ba50-4ce7-9439-34653001fc3b"
_, err = s.GetAccount(context.Background(), existingAccountID)
require.NoError(t, err, "Failed to get existing account, check testdata/extended-store.sql. Account ID: %s", existingAccountID)
baseMeta := nbpeer.PeerSystemMeta{
Hostname: "loginPeerHost",
GoOS: "linux",
}
newPeerTemplate := &nbpeer.Peer{
AccountID: existingAccountID,
UserID: "",
IP: net.IP{123, 123, 123, 123},
Meta: nbpeer.PeerSystemMeta{
Hostname: "newPeer",
GoOS: "linux",
},
Name: "newPeerName",
DNSLabel: "newPeer.test",
Status: &nbpeer.PeerStatus{Connected: false, LastSeen: time.Now()},
SSHEnabled: false,
ExtraDNSLabels: []string{
"extraLabel1",
"extraLabel2",
},
}
testCases := []struct {
name string
setupKey string
wireGuardPubKey string
expectExtraDNSLabelsMismatch bool
extraDNSLabels []string
expectLoginError bool
expectedErrorMsgSubstring string
}{
{
name: "Successful login with setup key",
setupKey: "A2C8E62B-38F5-4553-B31E-DD66C696CEBD",
expectLoginError: false,
},
{
name: "Successful login with setup key with DNS labels mismatch",
setupKey: "A2C8E62B-38F5-4553-B31E-DD66C696CEBD",
expectExtraDNSLabelsMismatch: true,
extraDNSLabels: []string{"anotherLabel1", "anotherLabel2"},
expectLoginError: false,
},
{
name: "Failed login with setup key not allowing extra DNS labels",
setupKey: "A2C8E62B-38F5-4553-B31E-DD66C696CEBB",
expectExtraDNSLabelsMismatch: true,
extraDNSLabels: []string{"anotherLabel1", "anotherLabel2"},
expectLoginError: true,
expectedErrorMsgSubstring: "setup key doesn't allow extra DNS labels",
},
}
for _, tc := range testCases {
currentWireGuardPubKey := "testPubKey_" + xid.New().String()
t.Run(tc.name, func(t *testing.T) {
upperKey := strings.ToUpper(tc.setupKey)
hashedKey := sha256.Sum256([]byte(upperKey))
encodedHashedKey := b64.StdEncoding.EncodeToString(hashedKey[:])
sk, err := s.GetSetupKeyBySecret(context.Background(), store.LockingStrengthUpdate, encodedHashedKey)
require.NoError(t, err, "Failed to get setup key %s from storage", tc.setupKey)
currentPeer := &nbpeer.Peer{
ID: xid.New().String(),
AccountID: newPeerTemplate.AccountID,
Key: currentWireGuardPubKey,
UserID: newPeerTemplate.UserID,
IP: newPeerTemplate.IP,
Meta: newPeerTemplate.Meta,
Name: newPeerTemplate.Name,
DNSLabel: newPeerTemplate.DNSLabel,
Status: &nbpeer.PeerStatus{Connected: false, LastSeen: time.Now()},
SSHEnabled: newPeerTemplate.SSHEnabled,
}
// add peer manually to bypass creation during login stage
if sk.AllowExtraDNSLabels {
currentPeer.ExtraDNSLabels = newPeerTemplate.ExtraDNSLabels
}
_, _, _, err = am.AddPeer(context.Background(), tc.setupKey, "", currentPeer)
require.NoError(t, err, "Expected no error when adding peer with setup key: %s", tc.setupKey)
loginInput := types.PeerLogin{
WireGuardPubKey: currentWireGuardPubKey,
SSHKey: "test-ssh-key",
Meta: baseMeta,
UserID: "",
SetupKey: tc.setupKey,
ConnectionIP: net.ParseIP("192.0.2.100"),
}
if tc.expectExtraDNSLabelsMismatch {
loginInput.ExtraDNSLabels = tc.extraDNSLabels
}
loggedinPeer, networkMap, postureChecks, loginErr := am.LoginPeer(context.Background(), loginInput)
if tc.expectLoginError {
require.Error(t, loginErr, "Expected an error during LoginPeer with setup key: %s", tc.setupKey)
assert.Contains(t, loginErr.Error(), tc.expectedErrorMsgSubstring, "Error message mismatch")
assert.Nil(t, loggedinPeer, "LoggedinPeer should be nil on error")
assert.Nil(t, networkMap, "NetworkMap should be nil on error")
assert.Nil(t, postureChecks, "PostureChecks should be empty or nil on error")
return
}
require.NoError(t, loginErr, "Expected no error during LoginPeer with setup key: %s", tc.setupKey)
assert.NotNil(t, loggedinPeer, "loggedinPeer should not be nil on success")
if tc.expectExtraDNSLabelsMismatch {
assert.NotEqual(t, tc.extraDNSLabels, loggedinPeer.ExtraDNSLabels, "ExtraDNSLabels should not match on loggedinPeer")
assert.Equal(t, currentPeer.ExtraDNSLabels, loggedinPeer.ExtraDNSLabels, "ExtraDNSLabels mismatch on loggedinPeer")
} else {
assert.Equal(t, currentPeer.ExtraDNSLabels, loggedinPeer.ExtraDNSLabels, "ExtraDNSLabels mismatch on loggedinPeer")
}
assert.NotNil(t, networkMap, "networkMap should not be nil on success")
assert.Equal(t, existingAccountID, loggedinPeer.AccountID, "AccountID mismatch for logged peer")
peerFromStore, err := s.GetPeerByPeerPubKey(context.Background(), store.LockingStrengthShare, loginInput.WireGuardPubKey)
require.NoError(t, err, "Failed to get peer by pub key: %s", loginInput.WireGuardPubKey)
assert.Equal(t, existingAccountID, peerFromStore.AccountID, "AccountID mismatch for peer from store")
assert.Equal(t, loggedinPeer.ID, peerFromStore.ID, "Peer ID mismatch between loggedinPeer and peerFromStore")
})
}
}
func TestPeerAccountPeersUpdate(t *testing.T) { func TestPeerAccountPeersUpdate(t *testing.T) {
manager, account, peer1, peer2, peer3 := setupNetworkMapTest(t) manager, account, peer1, peer2, peer3 := setupNetworkMapTest(t)

View File

@ -1,5 +1,5 @@
CREATE TABLE `accounts` (`id` text,`created_by` text,`created_at` datetime,`domain` text,`domain_category` text,`is_domain_primary_account` numeric,`network_identifier` text,`network_net` text,`network_dns` text,`network_serial` integer,`dns_settings_disabled_management_groups` text,`settings_peer_login_expiration_enabled` numeric,`settings_peer_login_expiration` integer,`settings_regular_users_view_blocked` numeric,`settings_groups_propagation_enabled` numeric,`settings_jwt_groups_enabled` numeric,`settings_jwt_groups_claim_name` text,`settings_jwt_allow_groups` text,`settings_extra_peer_approval_enabled` numeric,`settings_extra_integrated_validator_groups` text,PRIMARY KEY (`id`)); CREATE TABLE `accounts` (`id` text,`created_by` text,`created_at` datetime,`domain` text,`domain_category` text,`is_domain_primary_account` numeric,`network_identifier` text,`network_net` text,`network_dns` text,`network_serial` integer,`dns_settings_disabled_management_groups` text,`settings_peer_login_expiration_enabled` numeric,`settings_peer_login_expiration` integer,`settings_regular_users_view_blocked` numeric,`settings_groups_propagation_enabled` numeric,`settings_jwt_groups_enabled` numeric,`settings_jwt_groups_claim_name` text,`settings_jwt_allow_groups` text,`settings_extra_peer_approval_enabled` numeric,`settings_extra_integrated_validator_groups` text,PRIMARY KEY (`id`));
CREATE TABLE `setup_keys` (`id` text,`account_id` text,`key` text,`name` text,`type` text,`created_at` datetime,`expires_at` datetime,`updated_at` datetime,`revoked` numeric,`used_times` integer,`last_used` datetime DEFAULT NULL,`auto_groups` text,`usage_limit` integer,`ephemeral` numeric,PRIMARY KEY (`id`),CONSTRAINT `fk_accounts_setup_keys_g` FOREIGN KEY (`account_id`) REFERENCES `accounts`(`id`)); CREATE TABLE `setup_keys` (`id` text,`account_id` text,`key` text,`name` text,`type` text,`created_at` datetime,`expires_at` datetime,`updated_at` datetime,`revoked` numeric,`used_times` integer,`last_used` datetime DEFAULT NULL,`auto_groups` text,`usage_limit` integer,`ephemeral` numeric,`allow_extra_dns_labels` numeric,PRIMARY KEY (`id`),CONSTRAINT `fk_accounts_setup_keys_g` FOREIGN KEY (`account_id`) REFERENCES `accounts`(`id`));
CREATE TABLE `peers` (`id` text,`account_id` text,`key` text,`setup_key` text,`ip` text,`meta_hostname` text,`meta_go_os` text,`meta_kernel` text,`meta_core` text,`meta_platform` text,`meta_os` text,`meta_os_version` text,`meta_wt_version` text,`meta_ui_version` text,`meta_kernel_version` text,`meta_network_addresses` text,`meta_system_serial_number` text,`meta_system_product_name` text,`meta_system_manufacturer` text,`meta_environment` text,`meta_files` text,`name` text,`dns_label` text,`peer_status_last_seen` datetime,`peer_status_connected` numeric,`peer_status_login_expired` numeric,`peer_status_requires_approval` numeric,`user_id` text,`ssh_key` text,`ssh_enabled` numeric,`login_expiration_enabled` numeric,`last_login` datetime,`created_at` datetime,`ephemeral` numeric,`location_connection_ip` text,`location_country_code` text,`location_city_name` text,`location_geo_name_id` integer,PRIMARY KEY (`id`),CONSTRAINT `fk_accounts_peers_g` FOREIGN KEY (`account_id`) REFERENCES `accounts`(`id`)); CREATE TABLE `peers` (`id` text,`account_id` text,`key` text,`setup_key` text,`ip` text,`meta_hostname` text,`meta_go_os` text,`meta_kernel` text,`meta_core` text,`meta_platform` text,`meta_os` text,`meta_os_version` text,`meta_wt_version` text,`meta_ui_version` text,`meta_kernel_version` text,`meta_network_addresses` text,`meta_system_serial_number` text,`meta_system_product_name` text,`meta_system_manufacturer` text,`meta_environment` text,`meta_files` text,`name` text,`dns_label` text,`peer_status_last_seen` datetime,`peer_status_connected` numeric,`peer_status_login_expired` numeric,`peer_status_requires_approval` numeric,`user_id` text,`ssh_key` text,`ssh_enabled` numeric,`login_expiration_enabled` numeric,`last_login` datetime,`created_at` datetime,`ephemeral` numeric,`location_connection_ip` text,`location_country_code` text,`location_city_name` text,`location_geo_name_id` integer,PRIMARY KEY (`id`),CONSTRAINT `fk_accounts_peers_g` FOREIGN KEY (`account_id`) REFERENCES `accounts`(`id`));
CREATE TABLE `users` (`id` text,`account_id` text,`role` text,`is_service_user` numeric,`non_deletable` numeric,`service_user_name` text,`auto_groups` text,`blocked` numeric,`last_login` datetime DEFAULT NULL,`created_at` datetime,`issued` text DEFAULT "api",`integration_ref_id` integer,`integration_ref_integration_type` text,PRIMARY KEY (`id`),CONSTRAINT `fk_accounts_users_g` FOREIGN KEY (`account_id`) REFERENCES `accounts`(`id`)); CREATE TABLE `users` (`id` text,`account_id` text,`role` text,`is_service_user` numeric,`non_deletable` numeric,`service_user_name` text,`auto_groups` text,`blocked` numeric,`last_login` datetime DEFAULT NULL,`created_at` datetime,`issued` text DEFAULT "api",`integration_ref_id` integer,`integration_ref_integration_type` text,PRIMARY KEY (`id`),CONSTRAINT `fk_accounts_users_g` FOREIGN KEY (`account_id`) REFERENCES `accounts`(`id`));
CREATE TABLE `personal_access_tokens` (`id` text,`user_id` text,`name` text,`hashed_token` text,`expiration_date` datetime,`created_by` text,`created_at` datetime,`last_used` datetime,PRIMARY KEY (`id`),CONSTRAINT `fk_users_pa_ts_g` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`)); CREATE TABLE `personal_access_tokens` (`id` text,`user_id` text,`name` text,`hashed_token` text,`expiration_date` datetime,`created_by` text,`created_at` datetime,`last_used` datetime,PRIMARY KEY (`id`),CONSTRAINT `fk_users_pa_ts_g` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`));
@ -26,8 +26,9 @@ CREATE INDEX `idx_name_server_groups_account_id` ON `name_server_groups`(`accoun
CREATE INDEX `idx_posture_checks_account_id` ON `posture_checks`(`account_id`); CREATE INDEX `idx_posture_checks_account_id` ON `posture_checks`(`account_id`);
INSERT INTO accounts VALUES('bf1c8084-ba50-4ce7-9439-34653001fc3b','edafee4e-63fb-11ec-90d6-0242ac120003','2024-10-02 16:01:38.210000+02:00','test.com','private',1,'af1c8024-ha40-4ce2-9418-34653101fc3c','{"IP":"100.64.0.0","Mask":"//8AAA=="}','',0,'[]',0,86400000000000,0,0,0,'',NULL,NULL,NULL); INSERT INTO accounts VALUES('bf1c8084-ba50-4ce7-9439-34653001fc3b','edafee4e-63fb-11ec-90d6-0242ac120003','2024-10-02 16:01:38.210000+02:00','test.com','private',1,'af1c8024-ha40-4ce2-9418-34653101fc3c','{"IP":"100.64.0.0","Mask":"//8AAA=="}','',0,'[]',0,86400000000000,0,0,0,'',NULL,NULL,NULL);
INSERT INTO setup_keys VALUES('A2C8E62B-38F5-4553-B31E-DD66C696CEBB','bf1c8084-ba50-4ce7-9439-34653001fc3b','A2C8E62B-38F5-4553-B31E-DD66C696CEBB','Default key','reusable','2021-08-19 20:46:20.005936822+02:00','2321-09-18 20:46:20.005936822+02:00','2021-08-19 20:46:20.005936822+02:00',0,0,NULL,'["cfefqs706sqkneg59g2g"]',0,0); INSERT INTO setup_keys VALUES('A2C8E62B-38F5-4553-B31E-DD66C696CEBB','bf1c8084-ba50-4ce7-9439-34653001fc3b','A2C8E62B-38F5-4553-B31E-DD66C696CEBB','Default key','reusable','2021-08-19 20:46:20.005936822+02:00','2321-09-18 20:46:20.005936822+02:00','2021-08-19 20:46:20.005936822+02:00',0,0,NULL,'["cfefqs706sqkneg59g2g"]',0,0,0);
INSERT INTO setup_keys VALUES('A2C8E62B-38F5-4553-B31E-DD66C696CEBC','bf1c8084-ba50-4ce7-9439-34653001fc3b','A2C8E62B-38F5-4553-B31E-DD66C696CEBC','Faulty key with non existing group','reusable','2021-08-19 20:46:20.005936822+02:00','2321-09-18 20:46:20.005936822+02:00','2021-08-19 20:46:20.005936822+02:00',0,0,NULL,'["abcd"]',0,0); INSERT INTO setup_keys VALUES('A2C8E62B-38F5-4553-B31E-DD66C696CEBD','bf1c8084-ba50-4ce7-9439-34653001fc3b','A2C8E62B-38F5-4553-B31E-DD66C696CEBD','Default key with extra DNS labels','reusable','2021-08-19 20:46:20.005936822+02:00','2321-09-18 20:46:20.005936822+02:00','2021-08-19 20:46:20.005936822+02:00',0,0,NULL,'["cfefqs706sqkneg59g2g"]',0,0,1);
INSERT INTO setup_keys VALUES('A2C8E62B-38F5-4553-B31E-DD66C696CEBC','bf1c8084-ba50-4ce7-9439-34653001fc3b','A2C8E62B-38F5-4553-B31E-DD66C696CEBC','Faulty key with non existing group','reusable','2021-08-19 20:46:20.005936822+02:00','2321-09-18 20:46:20.005936822+02:00','2021-08-19 20:46:20.005936822+02:00',0,0,NULL,'["abcd"]',0,0,0);
INSERT INTO users VALUES('edafee4e-63fb-11ec-90d6-0242ac120003','bf1c8084-ba50-4ce7-9439-34653001fc3b','admin',0,0,'','["cfefqs706sqkneg59g3g"]',0,NULL,'2024-10-02 16:01:38.210678+02:00','api',0,''); INSERT INTO users VALUES('edafee4e-63fb-11ec-90d6-0242ac120003','bf1c8084-ba50-4ce7-9439-34653001fc3b','admin',0,0,'','["cfefqs706sqkneg59g3g"]',0,NULL,'2024-10-02 16:01:38.210678+02:00','api',0,'');
INSERT INTO users VALUES('f4f6d672-63fb-11ec-90d6-0242ac120003','bf1c8084-ba50-4ce7-9439-34653001fc3b','user',0,0,'','[]',0,NULL,'2024-10-02 16:01:38.210678+02:00','api',0,''); INSERT INTO users VALUES('f4f6d672-63fb-11ec-90d6-0242ac120003','bf1c8084-ba50-4ce7-9439-34653001fc3b','user',0,0,'','[]',0,NULL,'2024-10-02 16:01:38.210678+02:00','api',0,'');
INSERT INTO personal_access_tokens VALUES('9dj38s35-63fb-11ec-90d6-0242ac120003','f4f6d672-63fb-11ec-90d6-0242ac120003','','SoMeHaShEdToKeN','2023-02-27 00:00:00+00:00','user','2023-01-01 00:00:00+00:00','2023-02-01 00:00:00+00:00'); INSERT INTO personal_access_tokens VALUES('9dj38s35-63fb-11ec-90d6-0242ac120003','f4f6d672-63fb-11ec-90d6-0242ac120003','','SoMeHaShEdToKeN','2023-02-27 00:00:00+00:00','user','2023-01-01 00:00:00+00:00','2023-02-01 00:00:00+00:00');