Skip to content

Commit

Permalink
WIP tests, policy
Browse files Browse the repository at this point in the history
  • Loading branch information
gigovich committed Mar 1, 2023
1 parent 2b51e89 commit ad3a8be
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 64 deletions.
31 changes: 22 additions & 9 deletions management/server/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,6 @@ func (a *Account) GetExpiredPeers() []*Peer {
// If there is no peer that expires this function returns false and a duration of 0.
// This function only considers peers that haven't been expired yet and that are connected.
func (a *Account) GetNextPeerExpiration() (time.Duration, bool) {

peersWithExpiry := a.GetPeersWithExpiration()
if len(peersWithExpiry) == 0 {
return 0, false
Expand Down Expand Up @@ -600,6 +599,27 @@ func (a *Account) GetPeer(peerID string) *Peer {
return a.Peers[peerID]
}

// ruleToPolicy converts a Rule to a Policy query object
func (a *Account) ruleToPolicy(rule *Rule) *Policy {
getGroups := func(groups []string) (result string) {
for i := range groups {
groups[i] = fmt.Sprintf(`"%s"`, strings.Trim(groups[i], `"`))
}
return strings.Join(groups, ",")
}
return &Policy{
ID: rule.ID,
Name: rule.Name,
Description: rule.Description,
Query: fmt.Sprintf(
defaultPolicy,
getGroups(rule.Destination),
getGroups(rule.Source),
),
Disabled: rule.Disabled,
}
}

// BuildManager creates a new DefaultAccountManager with a provided Store
func BuildManager(store Store, peersUpdateManager *PeersUpdateManager, idpManager idp.Manager,
singleAccountModeDomain string, dnsDomain string, eventStore activity.Store,
Expand Down Expand Up @@ -1268,14 +1288,7 @@ func addAllGroup(account *Account) {
}
account.Rules = map[string]*Rule{defaultRule.ID: defaultRule}

defaultPolicy := &Policy{
ID: xid.New().String(),
Name: DefaultPolicyName,
Disabled: false,
Description: DefaultPolicyDescription,
Query: fmt.Sprintf(defaultPolicy, allGroup.ID, allGroup.ID),
}
account.Policies = []*Policy{defaultPolicy}
account.Policies = []*Policy{account.ruleToPolicy(defaultRule)}
}
}

Expand Down
19 changes: 9 additions & 10 deletions management/server/account_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1299,6 +1299,7 @@ func TestDefaultAccountManager_DefaultAccountSettings(t *testing.T) {
assert.Equal(t, account.Settings.PeerLoginExpirationEnabled, true)
assert.Equal(t, account.Settings.PeerLoginExpiration, 24*time.Hour)
}

func TestDefaultAccountManager_UpdatePeer_PeerLoginExpiration(t *testing.T) {
manager, err := createManager(t)
require.NoError(t, err, "unable to create account manager")
Expand All @@ -1318,7 +1319,8 @@ func TestDefaultAccountManager_UpdatePeer_PeerLoginExpiration(t *testing.T) {
require.NoError(t, err, "unable to mark peer connected")
account, err = manager.UpdateAccountSettings(account.Id, userID, &Settings{
PeerLoginExpiration: time.Hour,
PeerLoginExpirationEnabled: true})
PeerLoginExpirationEnabled: true,
})
require.NoError(t, err, "expecting to update account settings successfully but got error")

wg := &sync.WaitGroup{}
Expand Down Expand Up @@ -1365,7 +1367,8 @@ func TestDefaultAccountManager_MarkPeerConnected_PeerLoginExpiration(t *testing.
require.NoError(t, err, "unable to add peer")
_, err = manager.UpdateAccountSettings(account.Id, userID, &Settings{
PeerLoginExpiration: time.Hour,
PeerLoginExpirationEnabled: true})
PeerLoginExpirationEnabled: true,
})
require.NoError(t, err, "expecting to update account settings successfully but got error")

wg := &sync.WaitGroup{}
Expand All @@ -1387,7 +1390,6 @@ func TestDefaultAccountManager_MarkPeerConnected_PeerLoginExpiration(t *testing.
if failed {
t.Fatal("timeout while waiting for test to finish")
}

}

func TestDefaultAccountManager_UpdateAccountSettings_PeerLoginExpiration(t *testing.T) {
Expand Down Expand Up @@ -1421,7 +1423,8 @@ func TestDefaultAccountManager_UpdateAccountSettings_PeerLoginExpiration(t *test
// enabling PeerLoginExpirationEnabled should trigger the expiration job
account, err = manager.UpdateAccountSettings(account.Id, userID, &Settings{
PeerLoginExpiration: time.Hour,
PeerLoginExpirationEnabled: true})
PeerLoginExpirationEnabled: true,
})
require.NoError(t, err, "expecting to update account settings successfully but got error")

failed := waitTimeout(wg, time.Second)
Expand All @@ -1433,7 +1436,8 @@ func TestDefaultAccountManager_UpdateAccountSettings_PeerLoginExpiration(t *test
// disabling PeerLoginExpirationEnabled should trigger cancel
_, err = manager.UpdateAccountSettings(account.Id, userID, &Settings{
PeerLoginExpiration: time.Hour,
PeerLoginExpirationEnabled: false})
PeerLoginExpirationEnabled: false,
})
require.NoError(t, err, "expecting to update account settings successfully but got error")
failed = waitTimeout(wg, time.Second)
if failed {
Expand Down Expand Up @@ -1555,7 +1559,6 @@ func TestAccount_GetExpiredPeers(t *testing.T) {
}
})
}

}

func TestAccount_GetPeersWithExpiration(t *testing.T) {
Expand Down Expand Up @@ -1621,11 +1624,9 @@ func TestAccount_GetPeersWithExpiration(t *testing.T) {
}
})
}

}

func TestAccount_GetNextPeerExpiration(t *testing.T) {

type test struct {
name string
peers map[string]*Peer
Expand Down Expand Up @@ -1749,10 +1750,8 @@ func TestAccount_GetNextPeerExpiration(t *testing.T) {
} else {
assert.Equal(t, expiration, testCase.expectedNextExpiration)
}

})
}

}

func createManager(t *testing.T) (*DefaultAccountManager, error) {
Expand Down
4 changes: 2 additions & 2 deletions management/server/peer.go
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ func (am *DefaultAccountManager) MarkPeerConnected(peerPubKey string, connected

if oldStatus.LoginExpired {
// we need to update other peers because when peer login expires all other peers are notified to disconnect from
//the expired one. Here we notify them that connection is now allowed again.
// the expired one. Here we notify them that connection is now allowed again.
err = am.updateAccountPeers(account)
if err != nil {
return err
Expand Down Expand Up @@ -702,7 +702,7 @@ func (am *DefaultAccountManager) GetPeer(accountID, peerID, userID string) (*Pee
}

for _, p := range userPeers {
aclPeers := account.getPeersByACL(p.ID)
aclPeers, _ := account.getPeersByPolicy(p.ID)
for _, aclPeer := range aclPeers {
if aclPeer.ID == peerID {
return peer, nil
Expand Down
58 changes: 35 additions & 23 deletions management/server/policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -276,17 +276,7 @@ func (am *DefaultAccountManager) SavePolicy(accountID, userID string, policy *Po
return err
}

exists := false
for i, p := range account.Policies {
if p.ID == policy.ID {
account.Policies[i] = policy
exists = true
break
}
}
if !exists {
account.Policies = append(account.Policies, policy)
}
exists := am.savePolicy(account, policy)

account.Network.IncSerial()
if err = am.Store.SaveAccount(account); err != nil {
Expand Down Expand Up @@ -372,20 +362,11 @@ func (am *DefaultAccountManager) DeletePolicy(accountID, policyID, userID string
return err
}

policyIdx := -1
for i, policy := range account.Policies {
if policy.ID == policyID {
policyIdx = i
break
}
}
if policyIdx < 0 {
return status.Errorf(status.NotFound, "rule with ID %s doesn't exist", policyID)
policy, err := am.deletePolicy(account, policyID)
if err != nil {
return err
}

policy := account.Policies[policyIdx]
account.Policies = append(account.Policies[:policyIdx], account.Policies[policyIdx+1:]...)

account.Network.IncSerial()
if err = am.Store.SaveAccount(account); err != nil {
return err
Expand Down Expand Up @@ -417,3 +398,34 @@ func (am *DefaultAccountManager) ListPolicies(accountID, userID string) ([]*Poli

return account.Policies[:], nil
}

func (am *DefaultAccountManager) deletePolicy(account *Account, policyID string) (*Policy, error) {
policyIdx := -1
for i, policy := range account.Policies {
if policy.ID == policyID {
policyIdx = i
break
}
}
if policyIdx < 0 {
return nil, status.Errorf(status.NotFound, "rule with ID %s doesn't exist", policyID)
}

policy := account.Policies[policyIdx]
account.Policies = append(account.Policies[:policyIdx], account.Policies[policyIdx+1:]...)
return policy, nil
}

func (am *DefaultAccountManager) savePolicy(account *Account, policy *Policy) (exists bool) {
for i, p := range account.Policies {
if p.ID == policy.ID {
account.Policies[i] = policy
exists = true
break
}
}
if !exists {
account.Policies = append(account.Policies, policy)
}
return
}
4 changes: 2 additions & 2 deletions management/server/rego/default_policy.rego
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ package netbird
# all rules for peer connectivity and firewall
all[rule] {
rule := array.concat(
rules_from_groups([%v], "dst", "accept", ""),
rules_from_groups([%v], "src", "accept", ""))[_]
rules_from_groups([%s], "dst", "accept", ""),
rules_from_groups([%s], "src", "accept", ""))[_]
}
39 changes: 21 additions & 18 deletions management/server/rego/default_policy_module.rego
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,33 @@ import future.keywords.in
import future.keywords.contains

# get_rule builds a netbird rule object from given parameters
get_rule(peer_id, peer_ip, direction, action, port) := rule if {
rule := {
"ID": peer_id,
"IP": peer_ip,
"Direction": direction,
"Action": action,
"Port": port,
}
get_rule(peer_id, direction, action, port) := rule if {
peer := input.peers[_]
peer.ID == peer_id
rule := {
"ID": peer.ID,
"IP": peer.IP,
"Direction": direction,
"Action": action,
"Port": port,
}
}

# is_peer_group returns group by id if peer_id present in group peers
get_peer_group(peer_id, group_id) := group if {
group := input.groups[_]
group.ID == group_id
}

# peers_from_group returns a list of peer ids for a given group id
peers_from_group(group_id) := peers if {
some group in input.groups
group := get_peer_group(input.peer_id, group_id)
group.ID == group_id
peers := [peer | peer := group.Peers[_]; peer != input.peer_id]
peers := [ peer | peer := group.Peers[_]; peer == input.peer_id ]
}

# netbird_rules_from_groups returns a list of netbird rules for a given list of group names
rules_from_groups(groups, direction, action, port) := policies if {
some group_name in groups
peers := peers_from_group(group_name)
policies := [
get_rule(peer.ID, peer.IP, direction, action, port) |
peer_id := peers[_]
peer := input.peers[peer_id]
]
rules_from_groups(groups, direction, action, port) := rules if {
group_id := groups[_]
rules := [ get_rule(peer, direction, action, port) | peer := peers_from_group(group_id)[_] ]
}
5 changes: 5 additions & 0 deletions management/server/rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ func (am *DefaultAccountManager) SaveRule(accountID, userID string, rule *Rule)
_, exists := account.Rules[rule.ID]

account.Rules[rule.ID] = rule
// temporary solution until we drop rules support
_ = am.savePolicy(account, account.ruleToPolicy(rule))

account.Network.IncSerial()
if err = am.Store.SaveAccount(account); err != nil {
Expand Down Expand Up @@ -244,6 +246,9 @@ func (am *DefaultAccountManager) DeleteRule(accountID, ruleID, userID string) er
return status.Errorf(status.NotFound, "rule with ID %s doesn't exist", ruleID)
}
delete(account.Rules, ruleID)
if _, err = am.deletePolicy(account, ruleID); err != nil {
return status.Errorf(status.NotFound, "policy with ID %s doesn't exist", ruleID)
}

account.Network.IncSerial()
if err = am.Store.SaveAccount(account); err != nil {
Expand Down

0 comments on commit ad3a8be

Please sign in to comment.