fix(valkey-operator): align ServiceMonitor with metrics.secure (skip-verify opt-in) - #231
fix(valkey-operator): align ServiceMonitor with metrics.secure (skip-verify opt-in)#231daanvinken wants to merge 3 commits into
Conversation
|
@daanvinken please rebase the branch |
When metrics.secure is true the metrics Service exposes port https, but the ServiceMonitor always targeted port http so scrapes failed. Use the matching port name, default scheme https, and insecureSkipVerify for the operator self-signed cert unless serviceMonitor overrides are set. Signed-off-by: daanvinken <daanvinken@tythus.com>
…itor Keep port/scheme aligned with metrics.secure. Do not default skip-verify; add metrics.serviceMonitor.insecureSkipVerify (false by default). Explicit tlsConfig still wins. Document secure scrape setup in the README. Signed-off-by: daanvinken <daanvinken@tythus.com>
0.4.1 already shipped on main with the log level description change. Move the ServiceMonitor secure-metrics fix notes to 0.4.2. Signed-off-by: daanvinken <daanvinken@tythus.com>
2db45ce to
d3dd681
Compare
|
Check |
|
| {{- else if .Values.metrics.secure }} | ||
| scheme: https |
There was a problem hiding this comment.
Secure ServiceMonitor lacks scrape authentication
When metrics.secure is enabled, this endpoint selects HTTPS but does not configure authorization or a bearer-token secret. The protected operator metrics endpoint requires the metrics-reader service-account token, so Prometheus sends an unauthenticated scrape and receives 401 even when the intended scraper identity has the required RBAC binding. Add a documented Secret-backed authorization configuration to the ServiceMonitor endpoint for secure metrics.
Artifacts
Secure metrics authentication-path test source
- Authored Python test source that checks the chart's secure endpoint and exercises an HTTPS metrics endpoint requiring a Bearer token; it demonstrates the required authentication condition.
HTTPS metrics request without ServiceMonitor authentication
- Executed HTTPS `/metrics` request after checking the chart's secure endpoint fields; no Authorization header was sent and the auth-enforcing endpoint returned 401, confirming rejection.
HTTPS metrics request with bound service account Bearer token
- Executed the same HTTPS `/metrics` request with the expected Bearer token; the endpoint returned 200 and metrics, confirming that token authentication is required.
| # Port name must match metrics-service.yaml (http when insecure, https when metrics.secure). | ||
| - port: {{ if .Values.metrics.secure }}https{{ else }}http{{ end }} | ||
| honorLabels: {{ .Values.metrics.serviceMonitor.honorLabels }} | ||
| {{- with .Values.metrics.serviceMonitor.interval }} | ||
| interval: {{ . }} | ||
| {{- end }} | ||
| {{- with .Values.metrics.serviceMonitor.scrapeTimeout }} | ||
| scrapeTimeout: {{ . }} | ||
| {{- end }} | ||
| {{- with .Values.metrics.serviceMonitor.scheme }} | ||
| scheme: {{ . }} | ||
| {{- if .Values.metrics.serviceMonitor.scheme }} | ||
| scheme: {{ .Values.metrics.serviceMonitor.scheme }} | ||
| {{- else if .Values.metrics.secure }} | ||
| scheme: https | ||
| {{- end }} | ||
| {{- with .Values.metrics.serviceMonitor.tlsConfig }} | ||
| {{- if .Values.metrics.serviceMonitor.tlsConfig }} | ||
| tlsConfig: | ||
| {{- toYaml . | nindent 6 }} | ||
| {{- toYaml .Values.metrics.serviceMonitor.tlsConfig | nindent 6 }} | ||
| {{- else if and .Values.metrics.secure .Values.metrics.serviceMonitor.insecureSkipVerify }} | ||
| # Opt-in: operator metrics use a self-signed cert by default. | ||
| tlsConfig: | ||
| insecureSkipVerify: true |
There was a problem hiding this comment.
Secure ServiceMonitor branches lack regression coverage
The focused ServiceMonitor suite only asserts the default insecure http endpoint. It never enables metrics.secure or exercises the explicit scheme, tlsConfig, and insecureSkipVerify paths, so regressions in secure port selection, HTTPS defaults, TLS-config precedence, or self-signed certificate handling pass the current tests. Add focused Helm unit tests for each secure rendering path.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Artifacts
Secure metrics authentication-path test source
- Authored Python test source that checks the chart's secure endpoint and exercises an HTTPS metrics endpoint requiring a Bearer token; it demonstrates the required authentication condition.
HTTPS metrics request without ServiceMonitor authentication
- Executed HTTPS `/metrics` request after checking the chart's secure endpoint fields; no Authorization header was sent and the auth-enforcing endpoint returned 401, confirming rejection.
HTTPS metrics request with bound service account Bearer token
- Executed the same HTTPS `/metrics` request with the expected Bearer token; the endpoint returned 200 and metrics, confirming that token authentication is required.
ServiceMonitor coverage and rendering harness source
- Authored shell harness searches the focused test suite for the claimed inputs and renders the three secure ServiceMonitor cases, providing a reproducible narrow check; it establishes how the observed outputs were produced.
Current ServiceMonitor unit suite passes without secure branch cases
- Executed `helm unittest valkey-operator -f tests/servicemonitor_test.yaml` with the helm-unittest plugin and recorded 10 passing tests; it shows the existing suite passes before any added coverage.
Secure ServiceMonitor branch coverage check and live renders
- Executed the authored harness with Helm and captured absent test-value inputs plus live secure-default, explicit-TLS-precedence, and insecure-skip-verify renders; it confirms the missing coverage and distinct untested outcomes.
Valkey operator chart lint result
- Executed Helm lint against the valkey-operator chart and captured one chart linted with zero failures; it confirms the rendered template is valid.
Summary
Fixes ServiceMonitor scrapes when
metrics.secureis true, and makes TLS skip-verify opt-in rather than a silent default.Bug
With
metrics.secure: true, the metrics Service exposes porthttps, but the ServiceMonitor always targeted porthttp, so scrapes never hit the right endpoint.What we change
metrics.secure(https+ defaultscheme: httpswhen secure andserviceMonitor.schemeis unset).metrics.serviceMonitor.insecureSkipVerify(defaultfalse). Only when this is true (andtlsConfigis empty) do we injecttlsConfig.insecureSkipVerify: truefor the operator's self-signed metrics cert. ExplicitserviceMonitor.tlsConfigalways wins.Design question for reviewers
Should skip-verify stay disabled by default?
false(this PR)insecureSkipVerify: trueor a realtlsConfig(CA). No silent MITM-friendly default.trueWe prefer default false: "secure" should not imply "do not verify." The operator cert is self-signed, so skip-verify is still available as an explicit one-liner for the common case.
If maintainers prefer out-of-the-box scrapes, flipping the default to
trueis a one-line change; the important part is that it is named and documented, not hard-coded only in the template.Docs
README (Metrics / ServiceMonitor), values comments, and CHANGELOG 0.4.1 describe port/scheme alignment and the opt-in flag.
Not in this PR
Bearer token for secure metrics auth (
WithAuthenticationAndAuthorization) is a separate follow-up so scrapes do not get 401 after TLS is fixed.Testing