From adf494e1ac45a642d6be5113b39d98b62843aa89 Mon Sep 17 00:00:00 2001 From: Vlad <4941176+crn4@users.noreply.github.com> Date: Wed, 14 May 2025 17:50:21 +0200 Subject: [PATCH] [management] fix a bug with missed extra dns labels for a new peer (#3798) --- management/domain/validate.go | 23 +- management/domain/validate_test.go | 105 +++---- management/server/peer.go | 23 +- management/server/peer_test.go | 265 ++++++++++++++++-- management/server/testdata/extended-store.sql | 7 +- 5 files changed, 307 insertions(+), 116 deletions(-) diff --git a/management/domain/validate.go b/management/domain/validate.go index a42aebe6f..bf2af7116 100644 --- a/management/domain/validate.go +++ b/management/domain/validate.go @@ -8,6 +8,8 @@ import ( 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. func ValidateDomains(domains []string) (List, error) { 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) } - 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 for _, d := range domains { @@ -37,27 +37,20 @@ func ValidateDomains(domains []string) (List, error) { return domainList, nil } -// ValidateDomainsStrSlice checks if each domain in the list is valid -func ValidateDomainsStrSlice(domains []string) ([]string, error) { +// ValidateDomainsList checks if each domain in the list is valid +func ValidateDomainsList(domains []string) error { if len(domains) == 0 { - return nil, nil + return nil } 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 { d := strings.ToLower(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 } diff --git a/management/domain/validate_test.go b/management/domain/validate_test.go index c9c042d9d..30efcd9a9 100644 --- a/management/domain/validate_test.go +++ b/management/domain/validate_test.go @@ -97,110 +97,89 @@ func TestValidateDomains(t *testing.T) { } } -// TestValidateDomainsStrSlice tests the ValidateDomainsStrSlice function. -func TestValidateDomainsStrSlice(t *testing.T) { - // Generate a slice of valid domains up to maxDomains +func TestValidateDomainsList(t *testing.T) { validDomains := make([]string, maxDomains) - for i := 0; i < maxDomains; i++ { + for i := range maxDomains { validDomains[i] = fmt.Sprintf("example%d.com", i) } tests := []struct { - name string - domains []string - expected []string - wantErr bool + name string + domains []string + wantErr bool }{ { - name: "Empty list", - domains: nil, - expected: nil, - wantErr: false, + name: "Empty list", + domains: nil, + wantErr: false, }, { - name: "Single valid ASCII domain", - domains: []string{"sub.ex-ample.com"}, - expected: []string{"sub.ex-ample.com"}, - wantErr: false, + name: "Single valid ASCII domain", + domains: []string{"sub.ex-ample.com"}, + wantErr: false, }, { - name: "Underscores in labels", - domains: []string{"_jabber._tcp.gmail.com"}, - expected: []string{"_jabber._tcp.gmail.com"}, - wantErr: false, + name: "Underscores in labels", + domains: []string{"_jabber._tcp.gmail.com"}, + wantErr: false, }, { // Unlike ValidateDomains (which converts to punycode), // ValidateDomainsStrSlice will fail on non-ASCII domain chars. - name: "Unicode domain fails (no punycode conversion)", - domains: []string{"münchen.de"}, - expected: nil, - wantErr: true, + name: "Unicode domain fails (no punycode conversion)", + domains: []string{"münchen.de"}, + wantErr: true, }, { - name: "Invalid domain format - leading dash", - domains: []string{"-example.com"}, - expected: nil, - wantErr: true, + name: "Invalid domain format - leading dash", + domains: []string{"-example.com"}, + wantErr: true, }, { - name: "Invalid domain format - trailing dash", - domains: []string{"example-.com"}, - expected: nil, - wantErr: true, + name: "Invalid domain format - trailing dash", + domains: []string{"example-.com"}, + 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", - domains: []string{"google.com", "invalid_domain.com-"}, - expected: []string{"google.com"}, - wantErr: true, + name: "Multiple domains with a valid one, then invalid", + domains: []string{"google.com", "invalid_domain.com-"}, + wantErr: true, }, { - name: "Valid wildcard domain", - domains: []string{"*.example.com"}, - expected: []string{"*.example.com"}, - wantErr: false, + name: "Valid wildcard domain", + domains: []string{"*.example.com"}, + wantErr: false, }, { - name: "Wildcard with leading dot - invalid", - domains: []string{".*.example.com"}, - expected: nil, - wantErr: true, + name: "Wildcard with leading dot - invalid", + domains: []string{".*.example.com"}, + wantErr: true, }, { - name: "Invalid wildcard with multiple asterisks", - domains: []string{"a.*.example.com"}, - expected: nil, - wantErr: true, + name: "Invalid wildcard with multiple asterisks", + domains: []string{"a.*.example.com"}, + wantErr: true, }, { - name: "Exactly maxDomains items (valid)", - domains: validDomains, - expected: validDomains, - wantErr: false, + name: "Exactly maxDomains items (valid)", + domains: validDomains, + wantErr: false, }, { - name: "Exceeds maxDomains items", - domains: append(validDomains, "extra.com"), - expected: nil, - wantErr: true, + name: "Exceeds maxDomains items", + domains: append(validDomains, "extra.com"), + wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := ValidateDomainsStrSlice(tt.domains) - // Check if we got an error where expected + err := ValidateDomainsList(tt.domains) if tt.wantErr { assert.Error(t, err) } else { assert.NoError(t, err) } - - // Compare the returned domains to what we expect - assert.Equal(t, tt.expected, got) }) } } diff --git a/management/server/peer.go b/management/server/peer.go index 9ff80442e..8bc6cdb05 100644 --- a/management/server/peer.go +++ b/management/server/peer.go @@ -556,6 +556,10 @@ func (am *DefaultAccountManager) AddPeer(ctx context.Context, setupKey, userID s 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() newPeer = &nbpeer.Peer{ ID: xid.New().String(), @@ -767,10 +771,11 @@ func (am *DefaultAccountManager) handlePeerLoginNotFound(ctx context.Context, lo // we couldn't find this peer by its public key which can mean that peer hasn't been registered yet. // Try registering it. newPeer := &nbpeer.Peer{ - Key: login.WireGuardPubKey, - Meta: login.Meta, - SSHKey: login.SSHKey, - Location: nbpeer.Location{ConnectionIP: login.ConnectionIP}, + Key: login.WireGuardPubKey, + Meta: login.Meta, + SSHKey: login.SSHKey, + Location: nbpeer.Location{ConnectionIP: login.ConnectionIP}, + ExtraDNSLabels: login.ExtraDNSLabels, } 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") } - 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 err = transaction.SavePeer(ctx, store.LockingStrengthUpdate, accountID, peer); err != nil { return err diff --git a/management/server/peer_test.go b/management/server/peer_test.go index 406c3e49e..9c1de0659 100644 --- a/management/server/peer_test.go +++ b/management/server/peer_test.go @@ -10,6 +10,7 @@ import ( "net/netip" "os" "runtime" + "strings" "testing" "time" @@ -1290,15 +1291,21 @@ func Test_RegisterPeerByUser(t *testing.T) { Status: &nbpeer.PeerStatus{Connected: false, LastSeen: time.Now()}, SSHEnabled: false, LastLogin: util.ToPtr(time.Now()), + ExtraDNSLabels: []string{ + "extraLabel1", + "extraLabel2", + }, } addedPeer, _, _, err := am.AddPeer(context.Background(), "", existingUserID, newPeer) require.NoError(t, err) + assert.Equal(t, newPeer.ExtraDNSLabels, addedPeer.ExtraDNSLabels) peer, err := s.GetPeerByPeerPubKey(context.Background(), store.LockingStrengthShare, addedPeer.Key) require.NoError(t, err) assert.Equal(t, peer.AccountID, existingAccountID) assert.Equal(t, peer.UserID, existingUserID) + assert.Equal(t, newPeer.ExtraDNSLabels, peer.ExtraDNSLabels) account, err := s.GetAccount(context.Background(), existingAccountID) require.NoError(t, err) @@ -1339,15 +1346,12 @@ func Test_RegisterPeerBySetupKey(t *testing.T) { assert.NoError(t, err) existingAccountID := "bf1c8084-ba50-4ce7-9439-34653001fc3b" - existingSetupKeyID := "A2C8E62B-38F5-4553-B31E-DD66C696CEBB" _, err = s.GetAccount(context.Background(), existingAccountID) require.NoError(t, err) - newPeer := &nbpeer.Peer{ - ID: xid.New().String(), + newPeerTemplate := &nbpeer.Peer{ AccountID: existingAccountID, - Key: "newPeerKey", UserID: "", IP: net.IP{123, 123, 123, 123}, Meta: nbpeer.PeerSystemMeta{ @@ -1358,31 +1362,96 @@ func Test_RegisterPeerBySetupKey(t *testing.T) { DNSLabel: "newPeer.test", Status: &nbpeer.PeerStatus{Connected: false, LastSeen: time.Now()}, 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) - require.NoError(t, err) - assert.Equal(t, peer.AccountID, existingAccountID) + addedPeer, _, _, err := am.AddPeer(context.Background(), tc.existingSetupKeyID, "", currentPeer) - account, err := s.GetAccount(context.Background(), existingAccountID) - require.NoError(t, err) - assert.Contains(t, account.Peers, addedPeer.ID) - assert.Contains(t, account.Groups["cfefqs706sqkneg59g2g"].Peers, addedPeer.ID) - assert.Contains(t, account.Groups["cfefqs706sqkneg59g4g"].Peers, addedPeer.ID) + 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 + } - assert.Equal(t, uint64(1), account.Network.Serial) + 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") - lastUsed, err := time.Parse("2006-01-02T15:04:05Z", "0001-01-01T00:00:00Z") - assert.NoError(t, err) + 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") - hashedKey := sha256.Sum256([]byte(existingSetupKeyID)) - encodedHashedKey := b64.StdEncoding.EncodeToString(hashedKey[:]) - assert.NotEqual(t, lastUsed, account.SetupKeys[encodedHashedKey].LastUsed) - assert.Equal(t, 1, account.SetupKeys[encodedHashedKey].UsedTimes) + account, err := s.GetAccount(context.Background(), existingAccountID) + require.NoError(t, err, "Failed to get account: %s", existingAccountID) + assert.Contains(t, account.Peers, addedPeer.ID, "Peer ID not found in account.Peers") + + 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) + } + + assert.Equal(t, uint64(1), account.Network.Serial, "Network.Serial mismatch; this assumes specific initial state or increment logic.") + + hashedKey := sha256.Sum256([]byte(tc.existingSetupKeyID)) + encodedHashedKey := b64.StdEncoding.EncodeToString(hashedKey[:]) + + 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) } +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) { manager, account, peer1, peer2, peer3 := setupNetworkMapTest(t) diff --git a/management/server/testdata/extended-store.sql b/management/server/testdata/extended-store.sql index 7900dabf5..324bf6293 100644 --- a/management/server/testdata/extended-store.sql +++ b/management/server/testdata/extended-store.sql @@ -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 `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 `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`)); @@ -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`); 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-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-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-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('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');