Problem/Motivation

As a follow-up on #3392147: Add an allowed IP list to the Ban module I'm wondering if it's worth caching the config values somehow to not have a config get (even if read only) call in the middleware each time?

Steps to reproduce

Proposed resolution

Remaining tasks

User interface changes

API changes

Data model changes

Comments

anybody created an issue. See original summary.

berdir’s picture

Priority: Normal » Major

Yes, this is a problem and should not be done. IMHO the previous issue should be reverted, this is a significant performance regression that breaks major performance improvements in Drupal 11.3.

berdir’s picture

the fastest option would be to use a service provider and persist the information directly as a parameter to the service. However, that requires a container rebuild then, which is expensive. That *probably* doesn't happen often, but it's still a downside.

Config is already cached, the problem is that ConfigFactory is a pretty heavy dependency.

I also commented in #3579646: Injecting the config factory inside the middleware causes performance hit, which doesn't help this.

As mentioned above, my suggestion would be to revert this feature completely and consider performance from the start. Working with middlewares means that all changes must be carefully tested and profiled. I'd suggest adding a performance cache on a page cache hit response. That would not fully cover this, but it would at least point out the fact that this adds extra cache lookups.

anybody’s picture

Thanks @berdir, I very much appreciate your all-encompassing knowledge and highly valuable feedback. I was also struggling if we should merge it. And I think we can be sure your experience is broad enough to be sure this is a real-world issue.

Nevertheless, I still consider the allowlist functionality to be very useful and relevant and thinking about this for a while I thought maybe allowing (and visibly documenting) a setting (from settings.php) might be best from both worlds instead!
I guess performance-wise that would be acceptable and we wouldn't need a database call.

Sadly I didn't come to that idea earlier, but I think it might even be better than UI and typically the IPs you'd like to allow-list are limited and in some cases it might even be helpful to have them defined programmatically.

Short feedback would be great, we'll prepare the MR then!

Thank you very much, I really look up to you!

berdir’s picture

I didn't carefully read the original issue and the requirements, I was also wondering if that's a thing that you'd want to change frequently and immediately or if a deployment/file change is acceptable, then I think either settings.php or a container parameter would be fine yes.

I did have a quick look at the original issue now, but I'm not sure I really know more as there isn't a lot of detail/discussion.

What exactly is the use case I wonder? Unless you use something like perimeter or some other similar logic, IP's aren't suddenly going to appear in the banned IP list. Against what is that protection/allowance? Does it need to be at runtime? Would it make more sense to apply the allow-list to blocking an IP and disallow that?

Similar to auto_unban, if it's applied at banIp() and not isBanned(), then the closure is useful (it would be on a different service though) However, that won't automatically work with a module like auto_unban as that overrides that method.

anybody’s picture

Thanks @berdir. The requirement is simple: Ensure some (static) IPs are never being blocked (allow-list)

In different scenarios we saw website owner IPs or other related IPs getting blocked for different reasons, for example perimeter, crowdsec or others, mostly false-positives. If the owner (large companies) have a static IP, that should never get blocked, because it causes a lot more trouble than the risks are.

I think it's a fair functionality, while it shouldn't degrade performance.

anybody’s picture

If you're fine with the allowlist settings (settings.php) plus documentation, I think that's a nice, expected and helpful way to go! :)

I'd love to agree on that and I think it's even better than the database-driven list n the UI for such a technical functionality.

anybody’s picture

PS: I think ban would still be the best place, because it manages the list of banned IPs and it solves the case of "never ban this IP what ever happens" best, instead of integrating that into each of the other modules.

The other modules *could* even use that setting then (maybe we should put a service around) to get that list and not even start blocking it.

mstrelan’s picture

Depending on the hosting environment settings.php could be configured to read from a text file, env var or some other way (e.g. Pantheon secrets) to avoid deployments to add to the whitelist. We could make note of that in any documentation, although this applies pretty generally to anything else.

berdir’s picture

I'm fine with something settings or container parameter based.

Unsure when it should apply, on check or on ban, or or both. *If* the cost of checking the IP is near-zero (like settings.php), then there's even a performance improvement possible thanks to this, as the query doesn't need to run (as a follow-ip, it might be worth exploring to make either the ban ip manager in the middleware or the database connection in the ban ip manager a closure. Unfortunately, Drupal already opens the database connection when you inject the service and with this, there's a scenario where no query happens)

And yes, once such a setting exists, other modules could support it and don't block those IP's in the first place.

I'd still suggest opening a separate issue to add a performance test. It's fairly simple, see \Drupal\Tests\redirect\FunctionalJavascript\RedirectPerformanceTest for one in contrib, or the various core subclasses which do detailed query/cache statistics. The main challenge for a contrib module is that changes in core affect the results and it could be tedious to maintain and work on all supported core versions. That's why redirect only asserts it's own queries and ban could just check a page cache hit, where changes in core are quite unlikely. You'd not want to assert assets, just number of queries/cache statistics.

anybody’s picture

GREAT! Thanks @berdir and @mstrelan! We'll do it, just talked to @grevil. Hooray! :)

anybody’s picture

I've created two follow-ups and think we should close this won't fix now.

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.