swarm-otel: scrape grafana through its published name
Grafana's own metrics were scraped over loopback through the `grafana-metrics` nginx vhost, declared only where grafana and the collector share a host, so a collector on any other host had no job for it. Its target is now declared on every host as `https://<swarm.grafana.domain>/metrics`, next to the other published targets, and grafana's vhost serves `= /metrics` behind the collector's auth subrequest (`/__grafana_metrics_authz`, the forge's shape). The rules derived from `publishedScrapeTargets` admit the collector's client there and deny every other subject. The loopback scrape is gone with the vhost that served it and its `swarm.grafana.metricsPort` option, so a single host still scrapes grafana once, now by name. A config that sets that option now fails evaluation with "option does not exist". On the published vhost `/metrics` was answered with 403 for everyone. It now answers the collector's token, and a plain session gets authelia's `deny`. The design note that ruled the published vhost out for scraping predates the collector's credential; it is replaced by the location's own comment and a line on `swarm.grafana.domain`. Part of #5205
This commit is contained in:
parent
6f071f7963
commit
54f6061d41
1 changed files with 145 additions and 99 deletions
|
|
@ -108,6 +108,7 @@ let
|
|||
|
||||
forgeMetricsUrl = "https://forge.t.local/metrics";
|
||||
autheliaMetricsUrl = "https://auth.t.local/metrics";
|
||||
grafanaMetricsUrl = "https://grafana.t.local/metrics";
|
||||
logsMetricsUrl = "https://logs.t.local/metrics";
|
||||
vmMetricsUrl = "https://metrics.t.local/metrics";
|
||||
|
||||
|
|
@ -374,10 +375,11 @@ let
|
|||
lib.sort lib.lessThan (lib.attrValues h.swarm.otel.publishedScrapeTargets) == [
|
||||
autheliaMetricsUrl
|
||||
forgeMetricsUrl
|
||||
grafanaMetricsUrl
|
||||
logsMetricsUrl
|
||||
vmMetricsUrl
|
||||
]
|
||||
&& lib.length targets == 8
|
||||
&& lib.length targets == 10
|
||||
&& lib.all (t: policy collector t == "one_factor") targets
|
||||
&& lib.all (t: policy "user:someone" t == "deny") targets
|
||||
&& lib.all (t: policy "group:admins" t == "deny") targets;
|
||||
|
|
@ -425,7 +427,7 @@ let
|
|||
];
|
||||
matched = row: builtins.match re row.path != null;
|
||||
in
|
||||
lib.length metricsRules == 6
|
||||
lib.length metricsRules == 8
|
||||
&& lib.all (r: r.resources == [ re ]) metricsRules
|
||||
&& re == "^/metrics([?].*)?$"
|
||||
&& lib.all (row: matched row == (row.nginx == "= /metrics")) table;
|
||||
|
|
@ -562,6 +564,63 @@ let
|
|||
&& lib.length jobs == 1
|
||||
&& (lib.head jobs).static_configs == [ { targets = [ "logs.t.local" ]; } ];
|
||||
}
|
||||
{
|
||||
name = "a collector on a host without grafana scrapes it by name";
|
||||
ok =
|
||||
let
|
||||
s = otelSettings otelRemoteAuthelia;
|
||||
job = lib.findFirst (j: j.job_name == "grafana") null s.receivers.prometheus.config.scrape_configs;
|
||||
in
|
||||
!otelRemoteAuthelia.services.hyperhive.deploy.grafana.enable
|
||||
&& job != null
|
||||
&& job.static_configs == [ { targets = [ "grafana.t.local" ]; } ]
|
||||
&& job.metrics_path == "/metrics"
|
||||
&& job.oauth2.endpoint_params.audience == grafanaMetricsUrl;
|
||||
}
|
||||
{
|
||||
# The `deny` that confines grafana's `/metrics` is scoped to that path,
|
||||
# and comes after the collector's rule: every other path on the name
|
||||
# still reaches `default_policy`, as it did with no rule at all.
|
||||
name = "authelia confines grafana's /metrics to the collector and leaves its other paths alone";
|
||||
ok =
|
||||
let
|
||||
h = autheliaOnly.services.hyperhive;
|
||||
collector = "oauth2:client:${h.swarm.otel.clientId}";
|
||||
rules =
|
||||
autheliaOnly.containers.swarm-authelia.config.services.authelia.instances.swarm.settings.access_control.rules;
|
||||
grafanaRules = lib.filter (r: r.domain == "grafana.t.local") rules;
|
||||
policy = subject: autheliaPolicy autheliaOnly subject "grafana.t.local";
|
||||
in
|
||||
map (r: r.policy) grafanaRules == [
|
||||
"one_factor"
|
||||
"deny"
|
||||
]
|
||||
&& lib.all (r: r.resources == [ "^/metrics([?].*)?$" ]) grafanaRules
|
||||
&& (lib.head grafanaRules).subject == [ collector ]
|
||||
&& policy collector "/metrics" == "one_factor"
|
||||
&& policy "user:someone" "/metrics" == "deny"
|
||||
&& policy "user:someone" "/metrics?x=1" == "deny"
|
||||
&& policy "group:admins" "/metrics" == "deny"
|
||||
&& policy "user:someone" "/" == "one_factor"
|
||||
&& policy "user:someone" "/login/generic_oauth" == "one_factor";
|
||||
}
|
||||
{
|
||||
# Single host: grafana is scraped once, by its published name.
|
||||
name = "a host running grafana and the collector scrapes it once, by name";
|
||||
ok =
|
||||
let
|
||||
o = allLocal.services.hyperhive.swarm.otel;
|
||||
jobs =
|
||||
lib.filter (j: j.job_name == "grafana")
|
||||
(otelSettings allLocal).receivers.prometheus.config.scrape_configs;
|
||||
in
|
||||
allLocal.services.hyperhive.deploy.grafana.enable
|
||||
&& allLocal.services.hyperhive.deploy.swarm-otel.enable
|
||||
&& !(o.scrapeTargets ? grafana)
|
||||
&& (o.publishedScrapeTargets.grafana or null) == grafanaMetricsUrl
|
||||
&& lib.length jobs == 1
|
||||
&& (lib.head jobs).static_configs == [ { targets = [ "grafana.t.local" ]; } ];
|
||||
}
|
||||
{
|
||||
# Read against the roster the fixture declares rather than against
|
||||
# names spelled here: an arm naming `h1` passes on a single-hive
|
||||
|
|
|
|||
Loading…
Reference in a new issue