mirror of
https://github.com/netbirdio/netbird.git
synced 2025-05-12 20:25:27 +02:00
Adding DNS settings for accounts (#655)
Allow users to set groups in which the DNS management is disabled Added API, activity store, and network map sync test
This commit is contained in:
parent
2bc3d88af3
commit
12ae2e93fc
@ -89,6 +89,8 @@ type AccountManager interface {
|
|||||||
ListNameServerGroups(accountID string) ([]*nbdns.NameServerGroup, error)
|
ListNameServerGroups(accountID string) ([]*nbdns.NameServerGroup, error)
|
||||||
GetDNSDomain() string
|
GetDNSDomain() string
|
||||||
GetEvents(accountID, userID string) ([]*activity.Event, error)
|
GetEvents(accountID, userID string) ([]*activity.Event, error)
|
||||||
|
GetDNSSettings(accountID string, userID string) (*DNSSettings, error)
|
||||||
|
SaveDNSSettings(accountID string, userID string, dnsSettingsToSave *DNSSettings) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type DefaultAccountManager struct {
|
type DefaultAccountManager struct {
|
||||||
@ -129,6 +131,7 @@ type Account struct {
|
|||||||
Rules map[string]*Rule
|
Rules map[string]*Rule
|
||||||
Routes map[string]*route.Route
|
Routes map[string]*route.Route
|
||||||
NameServerGroups map[string]*nbdns.NameServerGroup
|
NameServerGroups map[string]*nbdns.NameServerGroup
|
||||||
|
DNSSettings *DNSSettings
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserInfo struct {
|
type UserInfo struct {
|
||||||
@ -339,6 +342,21 @@ func (a *Account) getUserGroups(userID string) ([]string, error) {
|
|||||||
return user.AutoGroups, nil
|
return user.AutoGroups, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *Account) getPeerDNSManagementStatus(peerID string) bool {
|
||||||
|
peerGroups := a.getPeerGroups(peerID)
|
||||||
|
enabled := true
|
||||||
|
if a.DNSSettings != nil {
|
||||||
|
for _, groupID := range a.DNSSettings.DisabledManagementGroups {
|
||||||
|
_, found := peerGroups[groupID]
|
||||||
|
if found {
|
||||||
|
enabled = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return enabled
|
||||||
|
}
|
||||||
|
|
||||||
func (a *Account) getPeerGroups(peerID string) lookupMap {
|
func (a *Account) getPeerGroups(peerID string) lookupMap {
|
||||||
groupList := make(lookupMap)
|
groupList := make(lookupMap)
|
||||||
for groupID, group := range a.Groups {
|
for groupID, group := range a.Groups {
|
||||||
@ -415,6 +433,11 @@ func (a *Account) Copy() *Account {
|
|||||||
nsGroups[id] = nsGroup.Copy()
|
nsGroups[id] = nsGroup.Copy()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var dnsSettings *DNSSettings
|
||||||
|
if a.DNSSettings != nil {
|
||||||
|
dnsSettings = a.DNSSettings
|
||||||
|
}
|
||||||
|
|
||||||
return &Account{
|
return &Account{
|
||||||
Id: a.Id,
|
Id: a.Id,
|
||||||
CreatedBy: a.CreatedBy,
|
CreatedBy: a.CreatedBy,
|
||||||
@ -429,6 +452,7 @@ func (a *Account) Copy() *Account {
|
|||||||
Rules: rules,
|
Rules: rules,
|
||||||
Routes: routes,
|
Routes: routes,
|
||||||
NameServerGroups: nsGroups,
|
NameServerGroups: nsGroups,
|
||||||
|
DNSSettings: dnsSettings,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1042,6 +1066,9 @@ func newAccountWithId(accountId, userId, domain string) *Account {
|
|||||||
routes := make(map[string]*route.Route)
|
routes := make(map[string]*route.Route)
|
||||||
nameServersGroups := make(map[string]*nbdns.NameServerGroup)
|
nameServersGroups := make(map[string]*nbdns.NameServerGroup)
|
||||||
users[userId] = NewAdminUser(userId)
|
users[userId] = NewAdminUser(userId)
|
||||||
|
dnsSettings := &DNSSettings{
|
||||||
|
DisabledManagementGroups: make([]string, 0),
|
||||||
|
}
|
||||||
log.Debugf("created new account %s with setup key %s", accountId, defaultKey.Key)
|
log.Debugf("created new account %s with setup key %s", accountId, defaultKey.Key)
|
||||||
|
|
||||||
acc := &Account{
|
acc := &Account{
|
||||||
@ -1054,6 +1081,7 @@ func newAccountWithId(accountId, userId, domain string) *Account {
|
|||||||
Domain: domain,
|
Domain: domain,
|
||||||
Routes: routes,
|
Routes: routes,
|
||||||
NameServerGroups: nameServersGroups,
|
NameServerGroups: nameServersGroups,
|
||||||
|
DNSSettings: dnsSettings,
|
||||||
}
|
}
|
||||||
|
|
||||||
addAllGroup(acc)
|
addAllGroup(acc)
|
||||||
|
@ -1276,6 +1276,7 @@ func TestAccount_Copy(t *testing.T) {
|
|||||||
ID: "nsGroup1",
|
ID: "nsGroup1",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
DNSSettings: &DNSSettings{},
|
||||||
}
|
}
|
||||||
err := hasNilField(account)
|
err := hasNilField(account)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -45,6 +45,10 @@ const (
|
|||||||
GroupAddedToSetupKey
|
GroupAddedToSetupKey
|
||||||
// GroupRemovedFromSetupKey indicates that a user removed a group from a setup key
|
// GroupRemovedFromSetupKey indicates that a user removed a group from a setup key
|
||||||
GroupRemovedFromSetupKey
|
GroupRemovedFromSetupKey
|
||||||
|
// GroupAddedToDisabledManagementGroups indicates that a user added a group to the DNS setting Disabled management groups
|
||||||
|
GroupAddedToDisabledManagementGroups
|
||||||
|
// GroupRemovedFromDisabledManagementGroups indicates that a user removed a group from the DNS setting Disabled management groups
|
||||||
|
GroupRemovedFromDisabledManagementGroups
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -92,6 +96,10 @@ const (
|
|||||||
GroupAddedToSetupKeyMessage string = "Group added to setup key"
|
GroupAddedToSetupKeyMessage string = "Group added to setup key"
|
||||||
// GroupRemovedFromSetupKeyMessage is a human-readable text message of the GroupRemovedFromSetupKey activity
|
// GroupRemovedFromSetupKeyMessage is a human-readable text message of the GroupRemovedFromSetupKey activity
|
||||||
GroupRemovedFromSetupKeyMessage string = "Group removed from user setup key"
|
GroupRemovedFromSetupKeyMessage string = "Group removed from user setup key"
|
||||||
|
// GroupAddedToDisabledManagementGroupsMessage is a human-readable text message of the GroupAddedToDisabledManagementGroups activity
|
||||||
|
GroupAddedToDisabledManagementGroupsMessage
|
||||||
|
// GroupRemovedFromDisabledManagementGroupsMessage is a human-readable text message of the GroupRemovedFromDisabledManagementGroups activity
|
||||||
|
GroupRemovedFromDisabledManagementGroupsMessage
|
||||||
)
|
)
|
||||||
|
|
||||||
// Activity that triggered an Event
|
// Activity that triggered an Event
|
||||||
@ -144,6 +152,10 @@ func (a Activity) Message() string {
|
|||||||
return GroupAddedToSetupKeyMessage
|
return GroupAddedToSetupKeyMessage
|
||||||
case GroupRemovedFromSetupKey:
|
case GroupRemovedFromSetupKey:
|
||||||
return GroupRemovedFromSetupKeyMessage
|
return GroupRemovedFromSetupKeyMessage
|
||||||
|
case GroupAddedToDisabledManagementGroups:
|
||||||
|
return GroupAddedToDisabledManagementGroupsMessage
|
||||||
|
case GroupRemovedFromDisabledManagementGroups:
|
||||||
|
return GroupRemovedFromDisabledManagementGroupsMessage
|
||||||
default:
|
default:
|
||||||
return "UNKNOWN_ACTIVITY"
|
return "UNKNOWN_ACTIVITY"
|
||||||
}
|
}
|
||||||
@ -196,6 +208,10 @@ func (a Activity) StringCode() string {
|
|||||||
return "setupkey.group.add"
|
return "setupkey.group.add"
|
||||||
case GroupRemovedFromSetupKey:
|
case GroupRemovedFromSetupKey:
|
||||||
return "setupkey.group.delete"
|
return "setupkey.group.delete"
|
||||||
|
case GroupAddedToDisabledManagementGroups:
|
||||||
|
return "dns.setting.disabled.management.group.add"
|
||||||
|
case GroupRemovedFromDisabledManagementGroups:
|
||||||
|
return "dns.setting.disabled.management.group.delete"
|
||||||
default:
|
default:
|
||||||
return "UNKNOWN_ACTIVITY"
|
return "UNKNOWN_ACTIVITY"
|
||||||
}
|
}
|
||||||
|
@ -5,13 +5,123 @@ import (
|
|||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
nbdns "github.com/netbirdio/netbird/dns"
|
nbdns "github.com/netbirdio/netbird/dns"
|
||||||
"github.com/netbirdio/netbird/management/proto"
|
"github.com/netbirdio/netbird/management/proto"
|
||||||
|
"github.com/netbirdio/netbird/management/server/activity"
|
||||||
|
"github.com/netbirdio/netbird/management/server/status"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const defaultTTL = 300
|
||||||
|
|
||||||
type lookupMap map[string]struct{}
|
type lookupMap map[string]struct{}
|
||||||
|
|
||||||
const defaultTTL = 300
|
// DNSSettings defines dns settings at the account level
|
||||||
|
type DNSSettings struct {
|
||||||
|
// DisabledManagementGroups groups whose DNS management is disabled
|
||||||
|
DisabledManagementGroups []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy returns a copy of the DNS settings
|
||||||
|
func (d *DNSSettings) Copy() *DNSSettings {
|
||||||
|
settings := &DNSSettings{
|
||||||
|
DisabledManagementGroups: make([]string, 0),
|
||||||
|
}
|
||||||
|
|
||||||
|
if d == nil {
|
||||||
|
return settings
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.DisabledManagementGroups != nil && len(d.DisabledManagementGroups) > 0 {
|
||||||
|
settings.DisabledManagementGroups = d.DisabledManagementGroups[:]
|
||||||
|
}
|
||||||
|
|
||||||
|
return settings
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDNSSettings validates a user role and returns the DNS settings for the provided account ID
|
||||||
|
func (am *DefaultAccountManager) GetDNSSettings(accountID string, userID string) (*DNSSettings, error) {
|
||||||
|
unlock := am.Store.AcquireAccountLock(accountID)
|
||||||
|
defer unlock()
|
||||||
|
|
||||||
|
account, err := am.Store.GetAccount(accountID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
user, err := account.FindUser(userID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !user.IsAdmin() {
|
||||||
|
return nil, status.Errorf(status.PermissionDenied, "only admins are allowed to view DNS settings")
|
||||||
|
}
|
||||||
|
|
||||||
|
if account.DNSSettings == nil {
|
||||||
|
return &DNSSettings{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return account.DNSSettings.Copy(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SaveDNSSettings validates a user role and updates the account's DNS settings
|
||||||
|
func (am *DefaultAccountManager) SaveDNSSettings(accountID string, userID string, dnsSettingsToSave *DNSSettings) error {
|
||||||
|
unlock := am.Store.AcquireAccountLock(accountID)
|
||||||
|
defer unlock()
|
||||||
|
|
||||||
|
account, err := am.Store.GetAccount(accountID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
user, err := account.FindUser(userID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !user.IsAdmin() {
|
||||||
|
return status.Errorf(status.PermissionDenied, "only admins are allowed to update DNS settings")
|
||||||
|
}
|
||||||
|
|
||||||
|
if dnsSettingsToSave == nil {
|
||||||
|
return status.Errorf(status.InvalidArgument, "the dns settings provided are nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = validateGroups(dnsSettingsToSave.DisabledManagementGroups, account.Groups)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
oldSettings := &DNSSettings{}
|
||||||
|
if account.DNSSettings != nil {
|
||||||
|
oldSettings = account.DNSSettings.Copy()
|
||||||
|
}
|
||||||
|
|
||||||
|
account.DNSSettings = dnsSettingsToSave.Copy()
|
||||||
|
|
||||||
|
account.Network.IncSerial()
|
||||||
|
if err = am.Store.SaveAccount(account); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
addedGroups := difference(dnsSettingsToSave.DisabledManagementGroups, oldSettings.DisabledManagementGroups)
|
||||||
|
for _, id := range addedGroups {
|
||||||
|
group := account.GetGroup(id)
|
||||||
|
meta := map[string]any{"group": group.Name, "group_id": group.ID}
|
||||||
|
am.storeEvent(userID, accountID, accountID, activity.GroupAddedToDisabledManagementGroups, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
removedGroups := difference(oldSettings.DisabledManagementGroups, dnsSettingsToSave.DisabledManagementGroups)
|
||||||
|
for _, id := range removedGroups {
|
||||||
|
group := account.GetGroup(id)
|
||||||
|
meta := map[string]any{"group": group.Name, "group_id": group.ID}
|
||||||
|
am.storeEvent(userID, accountID, accountID, activity.GroupRemovedFromDisabledManagementGroups, meta)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return am.updateAccountPeers(account)
|
||||||
|
}
|
||||||
|
|
||||||
func toProtocolDNSConfig(update nbdns.Config) *proto.DNSConfig {
|
func toProtocolDNSConfig(update nbdns.Config) *proto.DNSConfig {
|
||||||
protoUpdate := &proto.DNSConfig{ServiceEnable: update.ServiceEnable}
|
protoUpdate := &proto.DNSConfig{ServiceEnable: update.ServiceEnable}
|
||||||
|
266
management/server/dns_test.go
Normal file
266
management/server/dns_test.go
Normal file
@ -0,0 +1,266 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/netbirdio/netbird/management/server/activity"
|
||||||
|
"github.com/netbirdio/netbird/management/server/status"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
dnsGroup1ID = "group1"
|
||||||
|
dnsGroup2ID = "group2"
|
||||||
|
dnsPeer1Key = "BhRPtynAAYRDy08+q4HTMsos8fs4plTP4NOSh7C1ry8="
|
||||||
|
dnsPeer2Key = "/yF0+vCfv+mRR5k0dca0TrGdO/oiNeAI58gToZm5NyI="
|
||||||
|
dnsAccountID = "testingAcc"
|
||||||
|
dnsAdminUserID = "testingAdminUser"
|
||||||
|
dnsRegularUserID = "testingRegularUser"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetDNSSettings(t *testing.T) {
|
||||||
|
am, err := createDNSManager(t)
|
||||||
|
if err != nil {
|
||||||
|
t.Error("failed to create account manager")
|
||||||
|
}
|
||||||
|
|
||||||
|
account, err := initTestDNSAccount(t, am)
|
||||||
|
if err != nil {
|
||||||
|
t.Error("failed to init testing account")
|
||||||
|
}
|
||||||
|
|
||||||
|
dnsSettings, err := am.GetDNSSettings(account.Id, dnsAdminUserID)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Got an error when trying to retrieve the DNS settings with an admin user, err: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if dnsSettings == nil {
|
||||||
|
t.Fatal("DNS settings for new accounts shouldn't return nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
account.DNSSettings = &DNSSettings{
|
||||||
|
DisabledManagementGroups: []string{group1ID},
|
||||||
|
}
|
||||||
|
|
||||||
|
err = am.Store.SaveAccount(account)
|
||||||
|
if err != nil {
|
||||||
|
t.Error("failed to save testing account with new DNS settings")
|
||||||
|
}
|
||||||
|
|
||||||
|
dnsSettings, err = am.GetDNSSettings(account.Id, dnsAdminUserID)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Got an error when trying to retrieve the DNS settings with an admin user, err: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(dnsSettings.DisabledManagementGroups) != 1 {
|
||||||
|
t.Errorf("DNS settings should have one disabled mgmt group, groups: %s", dnsSettings.DisabledManagementGroups)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = am.GetDNSSettings(account.Id, dnsRegularUserID)
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("An error should be returned when getting the DNS settings with a regular user")
|
||||||
|
}
|
||||||
|
|
||||||
|
s, ok := status.FromError(err)
|
||||||
|
if !ok && s.Type() != status.PermissionDenied {
|
||||||
|
t.Errorf("returned error should be Permission Denied, got err: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSaveDNSSettings(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
userID string
|
||||||
|
inputSettings *DNSSettings
|
||||||
|
shouldFail bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Saving As Admin Should Be OK",
|
||||||
|
userID: dnsAdminUserID,
|
||||||
|
inputSettings: &DNSSettings{
|
||||||
|
DisabledManagementGroups: []string{dnsGroup1ID},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Should Not Update Settings As Regular User",
|
||||||
|
userID: dnsRegularUserID,
|
||||||
|
inputSettings: &DNSSettings{
|
||||||
|
DisabledManagementGroups: []string{dnsGroup1ID},
|
||||||
|
},
|
||||||
|
shouldFail: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Should Not Update Settings If Input is Nil",
|
||||||
|
userID: dnsAdminUserID,
|
||||||
|
inputSettings: nil,
|
||||||
|
shouldFail: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Should Not Update Settings If Group Is Invalid",
|
||||||
|
userID: dnsAdminUserID,
|
||||||
|
inputSettings: &DNSSettings{
|
||||||
|
DisabledManagementGroups: []string{"non-existing-group"},
|
||||||
|
},
|
||||||
|
shouldFail: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
t.Run(testCase.name, func(t *testing.T) {
|
||||||
|
am, err := createDNSManager(t)
|
||||||
|
if err != nil {
|
||||||
|
t.Error("failed to create account manager")
|
||||||
|
}
|
||||||
|
|
||||||
|
account, err := initTestDNSAccount(t, am)
|
||||||
|
if err != nil {
|
||||||
|
t.Error("failed to init testing account")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = am.SaveDNSSettings(account.Id, testCase.userID, testCase.inputSettings)
|
||||||
|
if err != nil {
|
||||||
|
if testCase.shouldFail {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
updatedAccount, err := am.Store.GetAccount(account.Id)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("should be able to retrieve updated account, got err: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
require.ElementsMatchf(t, testCase.inputSettings.DisabledManagementGroups, updatedAccount.DNSSettings.DisabledManagementGroups,
|
||||||
|
"resulting DNS settings should match input")
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetNetworkMap_DNSConfigSync(t *testing.T) {
|
||||||
|
|
||||||
|
am, err := createDNSManager(t)
|
||||||
|
if err != nil {
|
||||||
|
t.Error("failed to create account manager")
|
||||||
|
}
|
||||||
|
|
||||||
|
account, err := initTestDNSAccount(t, am)
|
||||||
|
if err != nil {
|
||||||
|
t.Error("failed to init testing account")
|
||||||
|
}
|
||||||
|
|
||||||
|
newAccountDNSConfig, err := am.GetNetworkMap(dnsPeer1Key)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, newAccountDNSConfig.DNSConfig.CustomZones, 1, "default DNS config should have one custom zone for peers")
|
||||||
|
require.True(t, newAccountDNSConfig.DNSConfig.ServiceEnable, "default DNS config should have local DNS service enabled")
|
||||||
|
|
||||||
|
dnsSettings := account.DNSSettings.Copy()
|
||||||
|
dnsSettings.DisabledManagementGroups = append(dnsSettings.DisabledManagementGroups, dnsGroup1ID)
|
||||||
|
account.DNSSettings = dnsSettings
|
||||||
|
err = am.Store.SaveAccount(account)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
updatedAccountDNSConfig, err := am.GetNetworkMap(dnsPeer1Key)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, updatedAccountDNSConfig.DNSConfig.CustomZones, 0, "updated DNS config should have no custom zone when peer belongs to a disabled group")
|
||||||
|
require.False(t, updatedAccountDNSConfig.DNSConfig.ServiceEnable, "updated DNS config should have local DNS service disabled when peer belongs to a disabled group")
|
||||||
|
|
||||||
|
peer2AccountDNSConfig, err := am.GetNetworkMap(dnsPeer2Key)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, peer2AccountDNSConfig.DNSConfig.CustomZones, 1, "DNS config should have one custom zone for peers not in the disabled group")
|
||||||
|
require.True(t, peer2AccountDNSConfig.DNSConfig.ServiceEnable, "DNS config should have DNS service enabled for peers not in the disabled group")
|
||||||
|
}
|
||||||
|
|
||||||
|
func createDNSManager(t *testing.T) (*DefaultAccountManager, error) {
|
||||||
|
store, err := createDNSStore(t)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
eventStore := &activity.InMemoryEventStore{}
|
||||||
|
return BuildManager(store, NewPeersUpdateManager(), nil, "", "netbird.test", eventStore)
|
||||||
|
}
|
||||||
|
|
||||||
|
func createDNSStore(t *testing.T) (Store, error) {
|
||||||
|
dataDir := t.TempDir()
|
||||||
|
store, err := NewFileStore(dataDir)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return store, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func initTestDNSAccount(t *testing.T, am *DefaultAccountManager) (*Account, error) {
|
||||||
|
peer1 := &Peer{
|
||||||
|
Key: dnsPeer1Key,
|
||||||
|
Name: "test-host1@netbird.io",
|
||||||
|
Meta: PeerSystemMeta{
|
||||||
|
Hostname: "test-host1@netbird.io",
|
||||||
|
GoOS: "linux",
|
||||||
|
Kernel: "Linux",
|
||||||
|
Core: "21.04",
|
||||||
|
Platform: "x86_64",
|
||||||
|
OS: "Ubuntu",
|
||||||
|
WtVersion: "development",
|
||||||
|
UIVersion: "development",
|
||||||
|
},
|
||||||
|
DNSLabel: dnsPeer1Key,
|
||||||
|
}
|
||||||
|
peer2 := &Peer{
|
||||||
|
Key: dnsPeer2Key,
|
||||||
|
Name: "test-host2@netbird.io",
|
||||||
|
Meta: PeerSystemMeta{
|
||||||
|
Hostname: "test-host2@netbird.io",
|
||||||
|
GoOS: "linux",
|
||||||
|
Kernel: "Linux",
|
||||||
|
Core: "21.04",
|
||||||
|
Platform: "x86_64",
|
||||||
|
OS: "Ubuntu",
|
||||||
|
WtVersion: "development",
|
||||||
|
UIVersion: "development",
|
||||||
|
},
|
||||||
|
DNSLabel: dnsPeer2Key,
|
||||||
|
}
|
||||||
|
|
||||||
|
domain := "example.com"
|
||||||
|
|
||||||
|
account := newAccountWithId(dnsAccountID, dnsAdminUserID, domain)
|
||||||
|
|
||||||
|
account.Users[dnsRegularUserID] = &User{
|
||||||
|
Id: dnsRegularUserID,
|
||||||
|
Role: UserRoleUser,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := am.Store.SaveAccount(account)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
newGroup1 := &Group{
|
||||||
|
ID: dnsGroup1ID,
|
||||||
|
Peers: []string{peer1.Key},
|
||||||
|
Name: dnsGroup1ID,
|
||||||
|
}
|
||||||
|
|
||||||
|
newGroup2 := &Group{
|
||||||
|
ID: dnsGroup2ID,
|
||||||
|
Name: dnsGroup2ID,
|
||||||
|
}
|
||||||
|
|
||||||
|
account.Groups[newGroup1.ID] = newGroup1
|
||||||
|
account.Groups[newGroup2.ID] = newGroup2
|
||||||
|
|
||||||
|
err = am.Store.SaveAccount(account)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = am.AddPeer("", dnsAdminUserID, peer1)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, err = am.AddPeer("", dnsAdminUserID, peer2)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return account, nil
|
||||||
|
}
|
@ -3,6 +3,8 @@ package server
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/netbirdio/netbird/management/server/activity"
|
"github.com/netbirdio/netbird/management/server/activity"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetEvents returns a list of activity events of an account
|
// GetEvents returns a list of activity events of an account
|
||||||
@ -31,3 +33,17 @@ func (am *DefaultAccountManager) GetEvents(accountID, userID string) ([]*activit
|
|||||||
|
|
||||||
return filtered, nil
|
return filtered, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (am *DefaultAccountManager) storeEvent(initiatorID, targetID, accountID string, activityID activity.Activity, meta map[string]any) {
|
||||||
|
_, err := am.eventStore.Save(&activity.Event{
|
||||||
|
Timestamp: time.Now(),
|
||||||
|
Activity: activityID,
|
||||||
|
InitiatorID: initiatorID,
|
||||||
|
TargetID: targetID,
|
||||||
|
AccountID: accountID,
|
||||||
|
Meta: meta,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("received an error while storing an activity event, error: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -503,6 +503,16 @@ components:
|
|||||||
enum: [ "name", "description", "enabled", "groups", "nameservers", "primary", "domains" ]
|
enum: [ "name", "description", "enabled", "groups", "nameservers", "primary", "domains" ]
|
||||||
required:
|
required:
|
||||||
- path
|
- path
|
||||||
|
DNSSettings:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
disabled_management_groups:
|
||||||
|
description: Groups whose DNS management is disabled
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- disabled_management_groups
|
||||||
Event:
|
Event:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
@ -522,10 +532,10 @@ components:
|
|||||||
enum: [ "user.peer.delete", "user.join", "user.invite", "user.peer.add", "user.group.add", "user.group.delete",
|
enum: [ "user.peer.delete", "user.join", "user.invite", "user.peer.add", "user.group.add", "user.group.delete",
|
||||||
"user.role.update",
|
"user.role.update",
|
||||||
"setupkey.peer.add", "setupkey.add", "setupkey.update", "setupkey.revoke", "setupkey.overuse",
|
"setupkey.peer.add", "setupkey.add", "setupkey.update", "setupkey.revoke", "setupkey.overuse",
|
||||||
"setupkey.group.delete", "setupkey.group.add"
|
"setupkey.group.delete", "setupkey.group.add",
|
||||||
"rule.add", "rule.delete", "rule.update",
|
"rule.add", "rule.delete", "rule.update",
|
||||||
"group.add", "group.update",
|
"group.add", "group.update", "dns.setting.disabled.management.group.add",
|
||||||
"account.create",
|
"account.create", "dns.setting.disabled.management.group.delete"
|
||||||
]
|
]
|
||||||
initiator_id:
|
initiator_id:
|
||||||
description: The ID of the initiator of the event. E.g., an ID of a user that triggered the event.
|
description: The ID of the initiator of the event. E.g., an ID of a user that triggered the event.
|
||||||
@ -1619,6 +1629,55 @@ paths:
|
|||||||
"$ref": "#/components/responses/forbidden"
|
"$ref": "#/components/responses/forbidden"
|
||||||
'500':
|
'500':
|
||||||
"$ref": "#/components/responses/internal_error"
|
"$ref": "#/components/responses/internal_error"
|
||||||
|
|
||||||
|
/api/dns/settings:
|
||||||
|
get:
|
||||||
|
summary: Returns a DNS settings object
|
||||||
|
tags: [ DNS ]
|
||||||
|
security:
|
||||||
|
- BearerAuth: [ ]
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: A JSON Object of DNS Setting
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/DNSSettings'
|
||||||
|
'400':
|
||||||
|
"$ref": "#/components/responses/bad_request"
|
||||||
|
'401':
|
||||||
|
"$ref": "#/components/responses/requires_authentication"
|
||||||
|
'403':
|
||||||
|
"$ref": "#/components/responses/forbidden"
|
||||||
|
'500':
|
||||||
|
"$ref": "#/components/responses/internal_error"
|
||||||
|
put:
|
||||||
|
summary: Updates a DNS settings object
|
||||||
|
tags: [ DNS ]
|
||||||
|
security:
|
||||||
|
- BearerAuth: [ ]
|
||||||
|
requestBody:
|
||||||
|
description: A DNS settings object
|
||||||
|
content:
|
||||||
|
'application/json':
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/DNSSettings'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: A JSON Object of DNS Setting
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/DNSSettings'
|
||||||
|
'400':
|
||||||
|
"$ref": "#/components/responses/bad_request"
|
||||||
|
'401':
|
||||||
|
"$ref": "#/components/responses/requires_authentication"
|
||||||
|
'403':
|
||||||
|
"$ref": "#/components/responses/forbidden"
|
||||||
|
'500':
|
||||||
|
"$ref": "#/components/responses/internal_error"
|
||||||
/api/events:
|
/api/events:
|
||||||
get:
|
get:
|
||||||
summary: Returns a list of all events
|
summary: Returns a list of all events
|
||||||
|
@ -14,12 +14,16 @@ const (
|
|||||||
// Defines values for EventActivityCode.
|
// Defines values for EventActivityCode.
|
||||||
const (
|
const (
|
||||||
EventActivityCodeAccountCreate EventActivityCode = "account.create"
|
EventActivityCodeAccountCreate EventActivityCode = "account.create"
|
||||||
|
EventActivityCodeDnsSettingDisabledManagementGroupAdd EventActivityCode = "dns.setting.disabled.management.group.add"
|
||||||
|
EventActivityCodeDnsSettingDisabledManagementGroupDelete EventActivityCode = "dns.setting.disabled.management.group.delete"
|
||||||
EventActivityCodeGroupAdd EventActivityCode = "group.add"
|
EventActivityCodeGroupAdd EventActivityCode = "group.add"
|
||||||
EventActivityCodeGroupUpdate EventActivityCode = "group.update"
|
EventActivityCodeGroupUpdate EventActivityCode = "group.update"
|
||||||
EventActivityCodeRuleAdd EventActivityCode = "rule.add"
|
EventActivityCodeRuleAdd EventActivityCode = "rule.add"
|
||||||
EventActivityCodeRuleDelete EventActivityCode = "rule.delete"
|
EventActivityCodeRuleDelete EventActivityCode = "rule.delete"
|
||||||
EventActivityCodeRuleUpdate EventActivityCode = "rule.update"
|
EventActivityCodeRuleUpdate EventActivityCode = "rule.update"
|
||||||
EventActivityCodeSetupkeyAdd EventActivityCode = "setupkey.add"
|
EventActivityCodeSetupkeyAdd EventActivityCode = "setupkey.add"
|
||||||
|
EventActivityCodeSetupkeyGroupAdd EventActivityCode = "setupkey.group.add"
|
||||||
|
EventActivityCodeSetupkeyGroupDelete EventActivityCode = "setupkey.group.delete"
|
||||||
EventActivityCodeSetupkeyOveruse EventActivityCode = "setupkey.overuse"
|
EventActivityCodeSetupkeyOveruse EventActivityCode = "setupkey.overuse"
|
||||||
EventActivityCodeSetupkeyPeerAdd EventActivityCode = "setupkey.peer.add"
|
EventActivityCodeSetupkeyPeerAdd EventActivityCode = "setupkey.peer.add"
|
||||||
EventActivityCodeSetupkeyRevoke EventActivityCode = "setupkey.revoke"
|
EventActivityCodeSetupkeyRevoke EventActivityCode = "setupkey.revoke"
|
||||||
@ -119,6 +123,12 @@ const (
|
|||||||
UserStatusInvited UserStatus = "invited"
|
UserStatusInvited UserStatus = "invited"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// DNSSettings defines model for DNSSettings.
|
||||||
|
type DNSSettings struct {
|
||||||
|
// DisabledManagementGroups Groups whose DNS management is disabled
|
||||||
|
DisabledManagementGroups []string `json:"disabled_management_groups"`
|
||||||
|
}
|
||||||
|
|
||||||
// Event defines model for Event.
|
// Event defines model for Event.
|
||||||
type Event struct {
|
type Event struct {
|
||||||
// Activity The activity that occurred during the event
|
// Activity The activity that occurred during the event
|
||||||
@ -657,6 +667,9 @@ type PatchApiDnsNameserversIdJSONRequestBody = PatchApiDnsNameserversIdJSONBody
|
|||||||
// PutApiDnsNameserversIdJSONRequestBody defines body for PutApiDnsNameserversId for application/json ContentType.
|
// PutApiDnsNameserversIdJSONRequestBody defines body for PutApiDnsNameserversId for application/json ContentType.
|
||||||
type PutApiDnsNameserversIdJSONRequestBody = NameserverGroupRequest
|
type PutApiDnsNameserversIdJSONRequestBody = NameserverGroupRequest
|
||||||
|
|
||||||
|
// PutApiDnsSettingsJSONRequestBody defines body for PutApiDnsSettings for application/json ContentType.
|
||||||
|
type PutApiDnsSettingsJSONRequestBody = DNSSettings
|
||||||
|
|
||||||
// PostApiGroupsJSONRequestBody defines body for PostApiGroups for application/json ContentType.
|
// PostApiGroupsJSONRequestBody defines body for PostApiGroups for application/json ContentType.
|
||||||
type PostApiGroupsJSONRequestBody PostApiGroupsJSONBody
|
type PostApiGroupsJSONRequestBody PostApiGroupsJSONBody
|
||||||
|
|
||||||
|
83
management/server/http/dns_settings.go
Normal file
83
management/server/http/dns_settings.go
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
package http
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/netbirdio/netbird/management/server"
|
||||||
|
"github.com/netbirdio/netbird/management/server/http/api"
|
||||||
|
"github.com/netbirdio/netbird/management/server/http/util"
|
||||||
|
"github.com/netbirdio/netbird/management/server/jwtclaims"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DNSSettings is a handler that returns the DNS settings of the account
|
||||||
|
type DNSSettings struct {
|
||||||
|
jwtExtractor jwtclaims.ClaimsExtractor
|
||||||
|
accountManager server.AccountManager
|
||||||
|
authAudience string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDNSSettings returns a new instance of DNSSettings handler
|
||||||
|
func NewDNSSettings(accountManager server.AccountManager, authAudience string) *DNSSettings {
|
||||||
|
return &DNSSettings{
|
||||||
|
accountManager: accountManager,
|
||||||
|
authAudience: authAudience,
|
||||||
|
jwtExtractor: *jwtclaims.NewClaimsExtractor(nil),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDNSSettings returns the DNS settings for the account
|
||||||
|
func (h *DNSSettings) GetDNSSettings(w http.ResponseWriter, r *http.Request) {
|
||||||
|
claims := h.jwtExtractor.ExtractClaimsFromRequestContext(r, h.authAudience)
|
||||||
|
account, user, err := h.accountManager.GetAccountFromToken(claims)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
http.Redirect(w, r, "/", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
dnsSettings, err := h.accountManager.GetDNSSettings(account.Id, user.Id)
|
||||||
|
if err != nil {
|
||||||
|
util.WriteError(err, w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
apiDNSSettings := &api.DNSSettings{
|
||||||
|
DisabledManagementGroups: dnsSettings.DisabledManagementGroups,
|
||||||
|
}
|
||||||
|
|
||||||
|
util.WriteJSONObject(w, apiDNSSettings)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateDNSSettings handles update to DNS settings of an account
|
||||||
|
func (h *DNSSettings) UpdateDNSSettings(w http.ResponseWriter, r *http.Request) {
|
||||||
|
claims := h.jwtExtractor.ExtractClaimsFromRequestContext(r, h.authAudience)
|
||||||
|
account, user, err := h.accountManager.GetAccountFromToken(claims)
|
||||||
|
if err != nil {
|
||||||
|
util.WriteError(err, w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var req api.PutApiDnsSettingsJSONRequestBody
|
||||||
|
err = json.NewDecoder(r.Body).Decode(&req)
|
||||||
|
if err != nil {
|
||||||
|
util.WriteErrorResponse("couldn't parse JSON request", http.StatusBadRequest, w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
updateDNSSettings := &server.DNSSettings{
|
||||||
|
DisabledManagementGroups: req.DisabledManagementGroups,
|
||||||
|
}
|
||||||
|
|
||||||
|
err = h.accountManager.SaveDNSSettings(account.Id, user.Id, updateDNSSettings)
|
||||||
|
if err != nil {
|
||||||
|
util.WriteError(err, w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := api.DNSSettings{
|
||||||
|
DisabledManagementGroups: updateDNSSettings.DisabledManagementGroups,
|
||||||
|
}
|
||||||
|
|
||||||
|
util.WriteJSONObject(w, &resp)
|
||||||
|
}
|
149
management/server/http/dns_settings_test.go
Normal file
149
management/server/http/dns_settings_test.go
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
package http
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/netbirdio/netbird/management/server/http/api"
|
||||||
|
"github.com/netbirdio/netbird/management/server/status"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/gorilla/mux"
|
||||||
|
"github.com/netbirdio/netbird/management/server"
|
||||||
|
"github.com/netbirdio/netbird/management/server/jwtclaims"
|
||||||
|
"github.com/netbirdio/netbird/management/server/mock_server"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
testDNSSettingsAccountID = "test_id"
|
||||||
|
testDNSSettingsExistingGroup = "test_group"
|
||||||
|
testDNSSettingsUserID = "test_user"
|
||||||
|
)
|
||||||
|
|
||||||
|
var baseExistingDNSSettings = &server.DNSSettings{
|
||||||
|
DisabledManagementGroups: []string{testDNSSettingsExistingGroup},
|
||||||
|
}
|
||||||
|
|
||||||
|
var testingDNSSettingsAccount = &server.Account{
|
||||||
|
Id: testDNSSettingsAccountID,
|
||||||
|
Domain: "hotmail.com",
|
||||||
|
Users: map[string]*server.User{
|
||||||
|
testDNSSettingsUserID: server.NewAdminUser("test_user"),
|
||||||
|
},
|
||||||
|
DNSSettings: baseExistingDNSSettings,
|
||||||
|
}
|
||||||
|
|
||||||
|
func initDNSSettingsTestData() *DNSSettings {
|
||||||
|
return &DNSSettings{
|
||||||
|
accountManager: &mock_server.MockAccountManager{
|
||||||
|
GetDNSSettingsFunc: func(accountID string, userID string) (*server.DNSSettings, error) {
|
||||||
|
return testingDNSSettingsAccount.DNSSettings, nil
|
||||||
|
},
|
||||||
|
SaveDNSSettingsFunc: func(accountID string, userID string, dnsSettingsToSave *server.DNSSettings) error {
|
||||||
|
if dnsSettingsToSave != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return status.Errorf(status.InvalidArgument, "the dns settings provided are nil")
|
||||||
|
},
|
||||||
|
GetAccountFromTokenFunc: func(_ jwtclaims.AuthorizationClaims) (*server.Account, *server.User, error) {
|
||||||
|
return testingDNSSettingsAccount, testingDNSSettingsAccount.Users[testDNSSettingsUserID], nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
authAudience: "",
|
||||||
|
jwtExtractor: jwtclaims.ClaimsExtractor{
|
||||||
|
ExtractClaimsFromRequestContext: func(r *http.Request, authAudiance string) jwtclaims.AuthorizationClaims {
|
||||||
|
return jwtclaims.AuthorizationClaims{
|
||||||
|
UserId: "test_user",
|
||||||
|
Domain: "hotmail.com",
|
||||||
|
AccountId: testDNSSettingsAccountID,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDNSSettingsHandlers(t *testing.T) {
|
||||||
|
tt := []struct {
|
||||||
|
name string
|
||||||
|
expectedStatus int
|
||||||
|
expectedBody bool
|
||||||
|
expectedDNSSettings *api.DNSSettings
|
||||||
|
requestType string
|
||||||
|
requestPath string
|
||||||
|
requestBody io.Reader
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Get DNS Settings",
|
||||||
|
requestType: http.MethodGet,
|
||||||
|
requestPath: "/api/dns/settings",
|
||||||
|
expectedStatus: http.StatusOK,
|
||||||
|
expectedBody: true,
|
||||||
|
expectedDNSSettings: &api.DNSSettings{
|
||||||
|
DisabledManagementGroups: baseExistingDNSSettings.DisabledManagementGroups,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Update DNS Settings",
|
||||||
|
requestType: http.MethodPut,
|
||||||
|
requestPath: "/api/dns/settings",
|
||||||
|
requestBody: bytes.NewBuffer(
|
||||||
|
[]byte("{\"disabled_management_groups\":[\"group1\",\"group2\"]}")),
|
||||||
|
expectedStatus: http.StatusOK,
|
||||||
|
expectedBody: true,
|
||||||
|
expectedDNSSettings: &api.DNSSettings{
|
||||||
|
DisabledManagementGroups: []string{"group1", "group2"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Update DNS Settings Empty Body",
|
||||||
|
requestType: http.MethodPut,
|
||||||
|
requestPath: "/api/dns/settings",
|
||||||
|
requestBody: bytes.NewBuffer(
|
||||||
|
[]byte("{}")),
|
||||||
|
expectedStatus: http.StatusOK,
|
||||||
|
expectedBody: true,
|
||||||
|
expectedDNSSettings: &api.DNSSettings{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
p := initDNSSettingsTestData()
|
||||||
|
|
||||||
|
for _, tc := range tt {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
recorder := httptest.NewRecorder()
|
||||||
|
req := httptest.NewRequest(tc.requestType, tc.requestPath, tc.requestBody)
|
||||||
|
|
||||||
|
router := mux.NewRouter()
|
||||||
|
router.HandleFunc("/api/dns/settings", p.GetDNSSettings).Methods("GET")
|
||||||
|
router.HandleFunc("/api/dns/settings", p.UpdateDNSSettings).Methods("PUT")
|
||||||
|
router.ServeHTTP(recorder, req)
|
||||||
|
|
||||||
|
res := recorder.Result()
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
content, err := io.ReadAll(res.Body)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("I don't know what I expected; %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if status := recorder.Code; status != tc.expectedStatus {
|
||||||
|
t.Errorf("handler returned wrong status code: got %v want %v, content: %s",
|
||||||
|
status, tc.expectedStatus, string(content))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !tc.expectedBody {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
got := &api.DNSSettings{}
|
||||||
|
if err = json.Unmarshal(content, &got); err != nil {
|
||||||
|
t.Fatalf("Sent content is not in correct json format; %v", err)
|
||||||
|
}
|
||||||
|
assert.Equal(t, tc.expectedDNSSettings, got)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -41,6 +41,7 @@ func APIHandler(accountManager s.AccountManager, authIssuer string, authAudience
|
|||||||
routesHandler := NewRoutes(accountManager, authAudience)
|
routesHandler := NewRoutes(accountManager, authAudience)
|
||||||
nameserversHandler := NewNameservers(accountManager, authAudience)
|
nameserversHandler := NewNameservers(accountManager, authAudience)
|
||||||
eventsHandler := NewEvents(accountManager, authAudience)
|
eventsHandler := NewEvents(accountManager, authAudience)
|
||||||
|
dnsSettingsHandler := NewDNSSettings(accountManager, authAudience)
|
||||||
|
|
||||||
apiHandler.HandleFunc("/peers", peersHandler.GetPeers).Methods("GET", "OPTIONS")
|
apiHandler.HandleFunc("/peers", peersHandler.GetPeers).Methods("GET", "OPTIONS")
|
||||||
apiHandler.HandleFunc("/peers/{id}", peersHandler.HandlePeer).
|
apiHandler.HandleFunc("/peers/{id}", peersHandler.HandlePeer).
|
||||||
@ -84,6 +85,9 @@ func APIHandler(accountManager s.AccountManager, authIssuer string, authAudience
|
|||||||
|
|
||||||
apiHandler.HandleFunc("/events", eventsHandler.GetEvents).Methods("GET", "OPTIONS")
|
apiHandler.HandleFunc("/events", eventsHandler.GetEvents).Methods("GET", "OPTIONS")
|
||||||
|
|
||||||
|
apiHandler.HandleFunc("/dns/settings", dnsSettingsHandler.GetDNSSettings).Methods("GET", "OPTIONS")
|
||||||
|
apiHandler.HandleFunc("/dns/settings", dnsSettingsHandler.UpdateDNSSettings).Methods("PUT", "OPTIONS")
|
||||||
|
|
||||||
err = apiHandler.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error {
|
err = apiHandler.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error {
|
||||||
methods, err := route.GetMethods()
|
methods, err := route.GetMethods()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -64,6 +64,8 @@ type MockAccountManager struct {
|
|||||||
GetAccountFromTokenFunc func(claims jwtclaims.AuthorizationClaims) (*server.Account, *server.User, error)
|
GetAccountFromTokenFunc func(claims jwtclaims.AuthorizationClaims) (*server.Account, *server.User, error)
|
||||||
GetDNSDomainFunc func() string
|
GetDNSDomainFunc func() string
|
||||||
GetEventsFunc func(accountID, userID string) ([]*activity.Event, error)
|
GetEventsFunc func(accountID, userID string) ([]*activity.Event, error)
|
||||||
|
GetDNSSettingsFunc func(accountID string, userID string) (*server.DNSSettings, error)
|
||||||
|
SaveDNSSettingsFunc func(accountID string, userID string, dnsSettingsToSave *server.DNSSettings) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUsersFromAccount mock implementation of GetUsersFromAccount from server.AccountManager interface
|
// GetUsersFromAccount mock implementation of GetUsersFromAccount from server.AccountManager interface
|
||||||
@ -499,3 +501,19 @@ func (am *MockAccountManager) GetEvents(accountID, userID string) ([]*activity.E
|
|||||||
}
|
}
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method GetEvents is not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method GetEvents is not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetDNSSettings mocks GetDNSSettings of the AccountManager interface
|
||||||
|
func (am *MockAccountManager) GetDNSSettings(accountID string, userID string) (*server.DNSSettings, error) {
|
||||||
|
if am.GetDNSSettingsFunc != nil {
|
||||||
|
return am.GetDNSSettingsFunc(accountID, userID)
|
||||||
|
}
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method GetDNSSettings is not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
// SaveDNSSettings mocks SaveDNSSettings of the AccountManager interface
|
||||||
|
func (am *MockAccountManager) SaveDNSSettings(accountID string, userID string, dnsSettingsToSave *server.DNSSettings) error {
|
||||||
|
if am.SaveDNSSettingsFunc != nil {
|
||||||
|
return am.SaveDNSSettingsFunc(accountID, userID, dnsSettingsToSave)
|
||||||
|
}
|
||||||
|
return status.Errorf(codes.Unimplemented, "method SaveDNSSettings is not implemented")
|
||||||
|
}
|
||||||
|
@ -1128,19 +1128,20 @@ func initTestNSAccount(t *testing.T, am *DefaultAccountManager) (*Account, error
|
|||||||
|
|
||||||
account.NameServerGroups[existingNSGroup.ID] = &existingNSGroup
|
account.NameServerGroups[existingNSGroup.ID] = &existingNSGroup
|
||||||
|
|
||||||
defaultGroup, err := account.GetGroupAll()
|
newGroup1 := &Group{
|
||||||
if err != nil {
|
ID: group1ID,
|
||||||
return nil, err
|
Name: group1ID,
|
||||||
|
}
|
||||||
|
|
||||||
|
newGroup2 := &Group{
|
||||||
|
ID: group2ID,
|
||||||
|
Name: group2ID,
|
||||||
}
|
}
|
||||||
newGroup1 := defaultGroup.Copy()
|
|
||||||
newGroup1.ID = group1ID
|
|
||||||
newGroup2 := defaultGroup.Copy()
|
|
||||||
newGroup2.ID = group2ID
|
|
||||||
|
|
||||||
account.Groups[newGroup1.ID] = newGroup1
|
account.Groups[newGroup1.ID] = newGroup1
|
||||||
account.Groups[newGroup2.ID] = newGroup2
|
account.Groups[newGroup2.ID] = newGroup2
|
||||||
|
|
||||||
err = am.Store.SaveAccount(account)
|
err := am.Store.SaveAccount(account)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -323,16 +323,19 @@ func (am *DefaultAccountManager) GetNetworkMap(peerPubKey string) (*NetworkMap,
|
|||||||
aclPeers := account.getPeersByACL(peerPubKey)
|
aclPeers := account.getPeersByACL(peerPubKey)
|
||||||
routesUpdate := account.getRoutesToSync(peerPubKey, aclPeers)
|
routesUpdate := account.getRoutesToSync(peerPubKey, aclPeers)
|
||||||
|
|
||||||
|
dnsManagementStatus := account.getPeerDNSManagementStatus(peerPubKey)
|
||||||
|
dnsUpdate := nbdns.Config{
|
||||||
|
ServiceEnable: dnsManagementStatus,
|
||||||
|
}
|
||||||
|
|
||||||
|
if dnsManagementStatus {
|
||||||
var zones []nbdns.CustomZone
|
var zones []nbdns.CustomZone
|
||||||
peersCustomZone := getPeersCustomZone(account, am.dnsDomain)
|
peersCustomZone := getPeersCustomZone(account, am.dnsDomain)
|
||||||
if peersCustomZone.Domain != "" {
|
if peersCustomZone.Domain != "" {
|
||||||
zones = append(zones, peersCustomZone)
|
zones = append(zones, peersCustomZone)
|
||||||
}
|
}
|
||||||
|
dnsUpdate.CustomZones = zones
|
||||||
dnsUpdate := nbdns.Config{
|
dnsUpdate.NameServerGroups = getPeerNSGroups(account, peerPubKey)
|
||||||
ServiceEnable: true,
|
|
||||||
CustomZones: zones,
|
|
||||||
NameServerGroups: getPeerNSGroups(account, peerPubKey),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return &NetworkMap{
|
return &NetworkMap{
|
||||||
|
Loading…
Reference in New Issue
Block a user