Skip to content

Commit

Permalink
Fix Santa partally allowlist rule post reset
Browse files Browse the repository at this point in the history
Only allow users that have voted AFTER the reset
  • Loading branch information
np5 committed Jan 24, 2025
1 parent c249404 commit 26e28b3
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 4 deletions.
35 changes: 35 additions & 0 deletions tests/santa/test_ballot_box.py
Original file line number Diff line number Diff line change
Expand Up @@ -933,10 +933,12 @@ def test_ballot_box_target_state_reset(self):
can_reset_target=True, voting_weight=100)
ballot_box = BallotBox.for_realm_user(self.file_target, realm_user, all_configurations=True)
ballot_box.cast_default_votes(False, None)
ts = TargetState.objects.get(target=self.file_target, configuration=configuration)
self.assertEqual(rules_qs.count(), 1)
rule = rules_qs.first()
self.assertEqual(rule.target, self.file_target)
self.assertEqual(rule.policy, Rule.Policy.BLOCKLIST)
self.assertEqual(len(rule.primary_users), 0)
self.assertEqual(votes_qs.count(), 1)
vote = votes_qs.first()
self.assertEqual(vote.weight, 100)
Expand Down Expand Up @@ -983,6 +985,39 @@ def test_ballot_box_target_state_reset(self):
self.assertEqual(votes_qs.count(), 1)
self.assertEqual(votes_qs.first(), vote)

def test_ballot_box_partially_allowlist_post_reset(self):
realm, realm_user = force_realm_user()
_, realm_user2 = force_realm_user(realm=realm)
configuration = force_configuration(
voting_realm=realm,
default_ballot_target_types=[Target.Type.BINARY],
default_voting_weight=1,
partially_allowlisted_threshold=2,
)
ballot_box = BallotBox.for_realm_user(self.file_target, realm_user, all_configurations=True)
ballot_box.cast_default_votes(True, self.file_target)
ballot_box2 = BallotBox.for_realm_user(self.file_target, realm_user2, all_configurations=True)
ballot_box2.cast_default_votes(True, self.file_target)
rule_qs = configuration.rule_set.all()
self.assertEqual(rule_qs.count(), 1)
rule = rule_qs.first()
self.assertEqual(set(rule.primary_users), set(u.username for u in (realm_user, realm_user2)))
# simulate reset
ts = TargetState.objects.get(target=self.file_target, configuration=configuration)
ts.score = 0
ts.state = TargetState.State.UNTRUSTED
ts.reset_at = datetime.utcnow()
ts.save()
configuration.default_voting_weight = 3
configuration.save()
ballot_box3 = BallotBox.for_realm_user(self.file_target, realm_user, all_configurations=True)
ballot_box3.cast_default_votes(True, self.file_target)
rule_qs = configuration.rule_set.all()
self.assertEqual(rule_qs.count(), 1)
rule = rule_qs.first()
# only the user with a vote post reset
self.assertEqual(set(rule.primary_users), set(u.username for u in (realm_user,)))

# update target states

def test_update_target_states(self):
Expand Down
8 changes: 4 additions & 4 deletions zentral/contrib/santa/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -460,13 +460,13 @@ def update_voting_rules(configurations):
" where id in %(configuration_ids)s"
" for update"
"), target_states as ("
" select ts.target_id, ts.configuration_id, ts.state, coalesce(u.username, b.user_uid) user"
" select ts.target_id, ts.configuration_id, ts.state,"
" case when v.was_yes_vote = 't' then coalesce(u.username, b.user_uid) else null end user"
" from santa_targetstate ts"
" join santa_ballot b on (b.target_id = ts.target_id)"
" join santa_vote v on (v.ballot_id = b.id and v.configuration_id = ts.configuration_id)"
" join realms_realmuser u on (b.realm_user_id = u.uuid)"
" where v.was_yes_vote = 't'"
" and ts.state >= 50 or ts.state <= -100" # only those states will generate rules
" where (ts.state >= 50 or ts.state <= -100)" # only those states will generate rules
" and b.replaced_by_id is null"
" and (ts.reset_at is null or b.created_at > ts.reset_at)"
" and v.configuration_id in %(configuration_ids)s"
Expand All @@ -490,7 +490,7 @@ def update_voting_rules(configurations):
" join santa_bundle_binary_targets bt on (bt.bundle_id = b.id)"
"), aggregated_rule_target_states as ("
" select rts.target_id, rts.configuration_id, max(rts.state) state,"
" array_agg(distinct rts.user order by rts.user asc) users"
" array_agg(distinct rts.user order by rts.user asc) filter (where rts.user is not null) users"
" from rule_target_states rts"
" group by rts.target_id, rts.configuration_id"
"), rules as ("
Expand Down

0 comments on commit 26e28b3

Please sign in to comment.