Conversation
02f3532 to
e21071c
Compare
2a857f1 to
4534aad
Compare
4534aad to
36314e1
Compare
36314e1 to
a39fd7b
Compare
a39fd7b to
4caf9db
Compare
There was a problem hiding this comment.
Pull request overview
This PR restructures Icinga Web’s authentication flow to be performed explicitly during bootstrap (including for static resources) and introduces Fiber-based suspension/resumption so module loading and configuration evaluation can defer user-dependent logic until authentication has completed.
Changes:
- Add
Auth::authenticate()and makeAuth::isAuthenticated()block (via Fiber suspension) until authentication has been performed. - Move initial user setup responsibility into
EmbeddedWeb(and simplifyWebby removing now-obsolete session setup and duplicative user setup). - Load enabled modules/config scripts “asynchronously” using Fibers, and deprecate providing user/user-group backends from
configuration.php(expectrun.phpinstead).
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
library/Icinga/Authentication/Auth.php |
Introduces explicit authentication and Fiber suspension/resumption behavior |
library/Icinga/Application/Web.php |
Removes legacy session/user setup and delegates initial user setup to EmbeddedWeb |
library/Icinga/Application/EmbeddedWeb.php |
Performs authentication + initial user setup during embedded bootstrap |
library/Icinga/Application/Modules/Manager.php |
Loads enabled modules in Fibers (non-CLI) to allow suspension during auth |
library/Icinga/Application/Modules/Module.php |
Runs module config scripts in Fibers for backend discovery + adds deprecation warnings |
doc/80-Upgrading.md |
Documents deprecation: custom backends must move from configuration.php to run.php |
Comments suppressed due to low confidence (1)
library/Icinga/Application/Modules/Manager.php:213
- In async mode, loadEnabledModules() sets $this->loadedAllEnabledModules = true even though module loading is happening inside fibers that can suspend during authentication. This can leave enabled modules not actually loaded/registered while loadedAllEnabledModules() returns true, which breaks the ClassLoader fallback path that conditionally calls $modules->loadModule() when not all modules are loaded. Track the fibers and only flip this flag once they have terminated, or keep the flag false in async mode until authentication resumes all suspended module-load fibers.
if (! $this->loadedAllEnabledModules) {
$async = ! $this->app->isCli();
foreach ($this->listEnabledModules() as $name) {
if ($async) {
// May be suspended during authentication and resumed upon finish
(new Fiber(function () use ($name) {
Logger::debug(
'Loading enabled module "%s" asynchronously (Process %d; Fiber %d)',
$name,
getmypid() ?: 0,
spl_object_id(Fiber::getCurrent())
);
$this->loadModule($name);
}))->start();
} else {
$this->loadModule($name);
}
}
$this->loadedAllEnabledModules = true;
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
4caf9db to
d467ad1
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Since authentication is now performed even for static resources, there's no reason anymore to support implicit authentication. This also limits authentication attempts to a single one, previously failed attempts were repeated. Requiring authentication during bootstrapping, i.e. before authentication has been performed, will now throw an error. refs #5265
So that authentication can suspend it. There are cases, e.g. cube, where authentication is required in run.php. During bootstrapping loading modules is mostly required to load libraries, register routes and hooks. Most of the time authentication is not required for these, but if it is, evaluation is now interrupted and continued after authentication has actually been performed. I don't see a real risk for any breaking change here, since authentication happens shortly after. It actually avoids a breaking change, since without this, cube's Icinga DB support would break or at least malfunction. And cube is only a single example. refs #5265
The related controller action is gone since b6b5caa
Providing a user or user group backend in configuration.php now triggers a deprecation or warning. They are expected to be announced in run.php, just like hooks. Authentication attempts during a configuration.php run, while Authentication has not been performed yet, will be also suspended now. This ensures that the current behavior, being broken or working, stays the same. refs #5265
d467ad1 to
5478d4a
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
library/Icinga/Application/Modules/Manager.php:213
- loadEnabledModules() now starts module registration in separate Fibers and immediately sets $this->loadedAllEnabledModules = true, even though some module-load fibers may still be suspended (e.g. when module code calls Auth::isAuthenticated() before Auth::authenticate()). This can leave the manager in an inconsistent state where “all enabled modules are loaded” is reported while $this->loadedModules is still missing modules, and downstream logic that relies on this flag (e.g. module lazy-loading in ClassLoader, or one-time caching of custom backends from getLoadedModules()) may never re-check once the suspended fibers finally resume. Consider deferring loadedAllEnabledModules=true until all module fibers have completed (or tracking/waiting for pending fibers and only flipping the flag once the loadedModules map is complete).
}
$this->loadedAllEnabledModules = true;
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This is split into four distinct parts: (One commit is only performing a clean up)
1. EmbeddedWeb: Explicitly perform authentication
It is nowadays no exception that stylesheet may be dependent on who's using the app. So to avoid race conditions like in #5385 authentication is an explicit step during bootstrap now.
EmbeddedWebnow knows about and is responsible to initially set up the user object. So this does not change whenWebsets up the user, it just allowsEmbeddedWebto do it.A small side-effect introduced by this change is fully optional, but doesn't break anything either: Method
Web::setupSession()and the accompanyingWeb::$sessionproperty are gone now as the property was obsolete already. Initializing the session is still done at the previous stage though, but implicitly byWeb::setupNotifications().2. Auth: Perform authentication only once and not lazily
Since authentication is now performed even for static resources, there's no reason anymore to support implicit authentication. This also limits authentication attempts to a single one, previously failed attempts were repeated. Requiring authentication during bootstrapping, i.e. before authentication has been performed, will now throw an error.
This conflicts with #5430 as it also affects
Auth::isAuthenticated(). But this should be easy to resolve.3. Manager: Perform module loading asynchronously
So that authentication can suspend it. There are cases, e.g. cube, where authentication is required in run.php. During bootstrapping loading modules is mostly required to load libraries, register routes and hooks. Most of the time authentication is not required for these, but if it is, evaluation is now interrupted and continued after authentication has actually been performed.
I don't see a real risk for any breaking change here, since authentication happens shortly after. It actually avoids a breaking change, since without this, cube's Icinga DB support would break or at least malfunction.
And cube is only a single example. As long as the monitoring module is still supported by them, they will keep being affected.
Enable the monitoring module and Icinga DB Web in an environment and look at the debug log to see this change in effect.
4. Module: Expect user and group backends upon registration
Providing a user or user group backend in configuration.php now triggers a deprecation or warning. They are expected to be announced in run.php, just like hooks. Authentication attempts during a configuration.php run, while Authentication has not been performed yet, will be also suspended now. This ensures that the current behavior, being broken or working, stays the same.
You might think that this is a breaking change, but it was rather always broken and only worked in such particular situations that custom backends were never used in conjunction with any of the official modules mentioned in 3.
Removing the compatibility layer (the suspension part) with v2.15 might indeed be a bit hasty. But I rather like to get rid of this as early as possible and I think those who have custom extensions like this, in a functional state, are a minority and known to us. (i.e. Icinga partners which we can forewarn)