diff --git a/nix/module-eval.nix b/nix/module-eval.nix index 25208745..2be72a41 100644 --- a/nix/module-eval.nix +++ b/nix/module-eval.nix @@ -1785,6 +1785,60 @@ let && !(lib.hasInfix "error_page" l) && lib.hasInfix "error_page" browser; } + { + # The read counterpart to the ingest location: an agent queries the log + # store with a bearer token, and the `/` catch-all is the browser's + # route. Riding it would mean inheriting the login redirect the next + # case is about, so the route has to exist separately to be gated + # separately. + name = "the log store's vhost has an authenticated machine query location"; + ok = + let + q = allLocal.services.nginx.virtualHosts."logs.t.local".locations."^~ /select/logsql/" or null; + in + q != null && lib.hasInfix "auth_request" q.extraConfig; + } + { + # Same trap as the ingest case, on the read side, where it is worse: a + # redirected pusher at least stores nothing visibly, while a redirected + # *reader* is handed a 200 carrying login HTML and records a query that + # succeeded and matched no logs. The browser clause is the positive + # control — that location really does redirect to the login host — so a + # pass means these two routes differ rather than that the strings are + # absent from the whole vhost. + name = "the machine query location answers 401 instead of redirecting to a login page"; + ok = + let + v = allLocal.services.nginx.virtualHosts; + q = v."logs.t.local".locations."^~ /select/logsql/".extraConfig; + browser = v."logs.t.local".locations."/".extraConfig; + in + !(lib.hasInfix "error_page" q) + && !(lib.hasInfix "auth.t.local" q) + && lib.hasInfix "error_page" browser + && lib.hasInfix "auth.t.local" browser; + } + { + # Read access is deliberately unscoped: an authenticated caller reads + # the whole swarm's logs until a permission system exists. Pinned so a + # scoping parameter arriving later is a visible diff here rather than a + # quiet change of rule — and pinned on `proxyPass` too, because + # VictoriaLogs takes its filters as request parameters, which ride an + # upstream URI as easily as a directive. The first clause is the + # control: it proves the location resolved and that `hasInfix` finds + # what is genuinely in this string, so the absences below mean absent + # rather than unreadable. + name = "the machine query location forwards the caller's query unmodified"; + ok = + let + q = allLocal.services.nginx.virtualHosts."logs.t.local".locations."^~ /select/logsql/"; + in + lib.hasInfix "auth_request" q.extraConfig + && !(lib.hasInfix "extra_filters" q.extraConfig) + && !(lib.hasInfix "extra_stream_filters" q.extraConfig) + && !(lib.hasInfix "$args" q.extraConfig) + && !(lib.hasInfix "?" q.proxyPass); + } { # Defining an exporter and REFERENCING it are two separate lists, and # the second is where the original gate also lived. An exporter no