diff --git a/docs/swarm/sso.md b/docs/swarm/sso.md index cb38d00a..fe17e5b8 100644 --- a/docs/swarm/sso.md +++ b/docs/swarm/sso.md @@ -242,18 +242,11 @@ page-only check. This was verified that way when the split was introduced. ## What this doesn't do -- **It doesn't disable local login — except on Grafana.** Forgejo and - tuwunel keep their password databases and gain a second door: an identity - provider that can take a service offline when it hiccups is worse than one - with two ways in, and making authelia the only path there is a separate, - reversible switch (tuwunel's `login_with_password`, forgejo's own setting). - ⚠️ **Grafana is the exception, and not a reversible one.** Its module sets - `auth.disable_login_form` unconditionally, because Grafana ships an - `admin`/`admin` account and its vhost is on the public gateway — so a - password box there is a way in whatever the deployment. SSO is the only - door, and a dead provider locks everyone out, the built-in admin - included. That's why `swarm.grafana.oidc.role` defaults to `Admin`; see - [`services.md`](services.md#metrics-victoriametrics--grafana). +- **It doesn't disable local login.** Each service keeps its password + database and gains a second door. An identity provider that can take a + service offline when it hiccups is worse than one with two ways in. + Making authelia the only path is a separate, reversible switch per + service (tuwunel's `login_with_password`, forgejo's own setting). - **It doesn't provision users.** Agents are created and destroyed continuously, so the subject set belongs to a program rather than to a config file; today that program is `swarmctl`. diff --git a/nix/host-modules/swarm-grafana.nix b/nix/host-modules/swarm-grafana.nix index 81ec4374..bbc68473 100644 --- a/nix/host-modules/swarm-grafana.nix +++ b/nix/host-modules/swarm-grafana.nix @@ -701,17 +701,10 @@ in # whole host fails to build. The unit below generates it. security.secret_key = "$__file{${secretKeyPath}}"; - # No local password path, ever. This is not tidiness: Grafana - # ships an `admin`/`admin` account and this vhost is on the - # public gateway, so SSO is the only way in — not merely the - # preferred one. - # - # Deliberately NOT `ssoLocal`: whether a password box sits on a - # public login page cannot depend on which host happens to run - # authelia. The OIDC block below is still gated on locality; - # making that follow the same swarm-wide question is a larger - # change tracked on its own. - auth.disable_login_form = true; + # No local password path at all when SSO is configured. This + # is not tidiness: Grafana ships an `admin`/`admin` account, + # and this vhost is on the public gateway. + auth.disable_login_form = ssoLocal; } // lib.optionalAttrs ssoLocal { "auth.generic_oauth" = { diff --git a/nix/module-eval.nix b/nix/module-eval.nix index 74b04cc9..839365b0 100644 --- a/nix/module-eval.nix +++ b/nix/module-eval.nix @@ -655,16 +655,6 @@ let rule: lib.hasInfix "/run/test-grafana-sock" rule ) grafanaOldPath.systemd.tmpfiles.rules; } - { - # This fixture enables grafana and NOT authelia, which is the shape the - # login form used to stay enabled in: the toggle read "both services are - # on this host" rather than "grafana requires SSO". Grafana ships an - # `admin`/`admin` account and its vhost is on the public gateway, so a - # password box there is a way in whatever the topology. - name = "grafana disables its local login form even where authelia is not on this host"; - ok = - grafanaOldPath.containers.swarm-grafana.config.services.grafana.settings.auth.disable_login_form; - } { # Reads the daemon's rendered unit, not the options: the queue address # arrives as an env var whose whole attrset is guarded on `natsUrl`, and