Skip to content

Move IP Rule fetching, caching, and refreshing logic into in interface in ip_rules_enforcer#11595

Merged
iain-macdonald merged 1 commit intomasterfrom
im/093fd44aff1
Mar 17, 2026
Merged

Move IP Rule fetching, caching, and refreshing logic into in interface in ip_rules_enforcer#11595
iain-macdonald merged 1 commit intomasterfrom
im/093fd44aff1

Conversation

@iain-macdonald
Copy link
Contributor

@iain-macdonald iain-macdonald commented Mar 13, 2026

This change decouples the logic for fetching, caching, and refreshing IP rules from the logic that enforces those rules via an interface in ip_rules_enforcer. It's pretty mechanical, just moving some logic around without any change in functionality. I still want to do more cleanup before adding the remote version, like cleaning up the interface and correctly halting the background goroutine, but wanted to keep this PR reasonable. After cleaning up the interface a little bit more, I'll add a remote IP rules provider that fetches IP rules from the app for use in the proxy.

Related issues: https://github.com/buildbuddy-io/buildbuddy-internal/issues/6797

@iain-macdonald iain-macdonald marked this pull request as ready for review March 13, 2026 23:14
Copilot AI review requested due to automatic review settings March 13, 2026 23:14
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Refactors the enterprise IP rules enforcer to fetch/cache parsed rules (including rule IDs) via a provider abstraction, and adds a notification-driven cache refresher that shuts down cleanly with the server lifecycle.

Changes:

  • Introduces ipRulesProvider (dbIPRulesProvider) to centralize DB loading + in-memory caching of parsed CIDRs with rule IDs.
  • Adds a server-notification-driven refresher loop with HealthChecker-managed shutdown.
  • Adds a unit test ensuring the refresher stops on shutdown and no longer refreshes the cache afterward.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
enterprise/server/ip_rules_enforcer/ip_rules_enforcer.go Introduces provider abstraction + notification refresher; updates cache to store ipRule (CIDR + rule ID) and updates enforcement logic accordingly.
enterprise/server/ip_rules_enforcer/ip_rules_enforcer_test.go Adds a fake notification service and a shutdown behavior test for the refresher.
enterprise/server/ip_rules_enforcer/BUILD Adds proto/protobuf deps needed by the new test.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Refactors the IP rules enforcer to separate “how rules are fetched/refreshed” from “how rules are enforced”, by introducing an internal provider abstraction backed by the DB + cache. This keeps Enforcer focused on authorization logic while the provider owns caching and refresh behavior.

Changes:

  • Introduced an internal ipRulesProvider interface to abstract IP rule retrieval and refresh.
  • Added dbIPRulesProvider to encapsulate DB access + caching + notification-driven refresh.
  • Updated Enforcer to depend on ipRulesProvider and delegate rule loading/caching to it.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +153 to +161
for msg := range sns.Subscribe(&snpb.InvalidateIPRulesCache{}) {
ic, ok := msg.(*snpb.InvalidateIPRulesCache)
if !ok {
alert.UnexpectedEvent("iprules_invalid_proto_type", "received proto type %T", msg)
continue
}
if err := p.refreshRules(env.GetServerContext(), ic.GetGroupId()); err != nil {
log.Warningf("could not refresh IP rules for group %q: %s", ic.GetGroupId(), err)
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gonna do this next 🙂

}

func (p *dbIPRulesProvider) get(ctx context.Context, groupID string, skipCache bool, skipRuleID string) ([]*net.IPNet, error) {
allowed, ok := p.cache.Get(groupID)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we get the result from the cache, skipRuleID is ignored. That seems weird.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's the way it currently works and I'd like to get rid of these parameters, so I'm gonna leave it as is. But yeah, it's confusing 😛

@iain-macdonald iain-macdonald merged commit d71d04f into master Mar 17, 2026
12 checks passed
@iain-macdonald iain-macdonald deleted the im/093fd44aff1 branch March 17, 2026 23:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants