Skip to content

Commit 8ca58a1

Browse files
committed
Merge origin/main into fix-http-headers-setdirectory
2 parents 3c24acf + f84efec commit 8ca58a1

30 files changed

Lines changed: 754 additions & 190 deletions

.github/workflows/golangci-lint.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@ jobs:
2626
runs-on: ubuntu-latest
2727
steps:
2828
- name: Checkout repository
29-
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
29+
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
3030
with:
3131
persist-credentials: false
3232
- name: Install Go
33-
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
33+
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
3434
with:
3535
go-version: 1.26.x
3636
- name: Install snmp_exporter/generator dependencies
@@ -40,7 +40,7 @@ jobs:
4040
id: golangci-lint-version
4141
run: echo "version=$(make print-golangci-lint-version)" >> $GITHUB_OUTPUT
4242
- name: Lint
43-
uses: golangci/golangci-lint-action@1e7e51e771db61008b38414a730f564565cf7c20 # v9.2.0
43+
uses: golangci/golangci-lint-action@82606bf257cbaff209d206a39f5134f0cfbfd2ee # v9.2.1
4444
with:
4545
args: --verbose
4646
version: ${{ steps.golangci-lint-version.outputs.version }}

.github/workflows/govulncheck.yml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
name: govulncheck
3+
on:
4+
pull_request:
5+
paths:
6+
- VERSION
7+
- .github/workflows/govulncheck.yml
8+
push:
9+
branches:
10+
- main
11+
- master
12+
schedule:
13+
- cron: '33 2 * * *'
14+
15+
permissions:
16+
contents: read
17+
18+
jobs:
19+
govulncheck:
20+
runs-on: ubuntu-latest
21+
name: Run govulncheck
22+
steps:
23+
- id: govulncheck
24+
uses: golang/govulncheck-action@b625fbe08f3bccbe446d94fbf87fcc875a4f50ee # v1.0.4
25+
env:
26+
GOOS: ${{ contains(github.repository, 'windows_exporter') && 'windows' || '' }}

.golangci.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ linters:
1111
- govet
1212
- loggercheck
1313
- misspell
14+
- modernize
1415
- nilnesserr
1516
# TODO(bwplotka): Enable once https://github.com/golangci/golangci-lint/issues/3228 is fixed.
1617
# - nolintlint
@@ -43,6 +44,9 @@ linters:
4344
- linters:
4445
- gocritic
4546
text: "appendAssign"
47+
- linters:
48+
- errcheck
49+
path: _test.go
4650
warn-unused: true
4751
settings:
4852
depguard:
@@ -77,6 +81,15 @@ linters:
7781
- shadow
7882
- fieldalignment
7983
enable-all: true
84+
modernize:
85+
disable:
86+
# Suggest replacing omitempty with omitzero for struct fields.
87+
# Disable this check for now since it introduces too many changes in our existing codebase.
88+
# See https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#hdr-Analyzer_omitzero for more details.
89+
- omitzero
90+
# Disable newexpr check for now since it introduces too many changes in our existing codebase.
91+
# To be re-enabled as a part of https://github.com/prometheus/prometheus/issues/18066.
92+
- newexpr
8093
perfsprint:
8194
# Optimizes even if it requires an int or uint type cast.
8295
int-conversion: true

Makefile.common

Lines changed: 2 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ PROMU_URL := https://github.com/prometheus/promu/releases/download/v$(PROMU_
6161
SKIP_GOLANGCI_LINT :=
6262
GOLANGCI_LINT :=
6363
GOLANGCI_LINT_OPTS ?=
64-
GOLANGCI_LINT_VERSION ?= v2.10.1
64+
GOLANGCI_LINT_VERSION ?= v2.11.4
6565
GOLANGCI_FMT_OPTS ?=
6666
# golangci-lint only supports linux, darwin and windows platforms on i386/amd64/arm64.
6767
# windows isn't included here because of the path separator being different.
@@ -90,9 +90,7 @@ ifdef DOCKERFILE_PATH
9090
$(error DOCKERFILE_PATH is deprecated. Use DOCKERFILE_VARIANTS ?= $(DOCKERFILE_PATH) in the Makefile)
9191
endif
9292

93-
DOCKER_ARCHS ?= amd64 armv7 arm64 ppc64le riscv64 s390x
94-
DOCKERFILE_ARCH_EXCLUSIONS ?=
95-
DOCKER_REGISTRY_ARCH_EXCLUSIONS ?= quay.io:riscv64
93+
DOCKER_ARCHS ?= amd64 arm64 armv7 ppc64le riscv64 s390x
9694
DOCKERFILE_VARIANTS ?= $(wildcard Dockerfile Dockerfile.*)
9795

9896
# Function to extract variant from Dockerfile label.
@@ -111,24 +109,6 @@ endif
111109
# Build variant:dockerfile pairs for shell iteration.
112110
DOCKERFILE_VARIANTS_WITH_NAMES := $(foreach df,$(DOCKERFILE_VARIANTS),$(call dockerfile_variant,$(df)):$(df))
113111

114-
# Shell helper to check whether a dockerfile/arch pair is excluded.
115-
define dockerfile_arch_is_excluded
116-
case " $(DOCKERFILE_ARCH_EXCLUSIONS) " in \
117-
*" $$dockerfile:$(1) "*) true ;; \
118-
*) false ;; \
119-
esac
120-
endef
121-
122-
# Shell helper to check whether a registry/arch pair is excluded.
123-
# Extracts registry from DOCKER_REPO (e.g., quay.io/prometheus -> quay.io)
124-
define registry_arch_is_excluded
125-
registry=$$(echo "$(DOCKER_REPO)" | cut -d'/' -f1); \
126-
case " $(DOCKER_REGISTRY_ARCH_EXCLUSIONS) " in \
127-
*" $$registry:$(1) "*) true ;; \
128-
*) false ;; \
129-
esac
130-
endef
131-
132112
BUILD_DOCKER_ARCHS = $(addprefix common-docker-,$(DOCKER_ARCHS))
133113
PUBLISH_DOCKER_ARCHS = $(addprefix common-docker-publish-,$(DOCKER_ARCHS))
134114
TAG_DOCKER_ARCHS = $(addprefix common-docker-tag-latest-,$(DOCKER_ARCHS))
@@ -270,10 +250,6 @@ $(BUILD_DOCKER_ARCHS): common-docker-%:
270250
@for variant in $(DOCKERFILE_VARIANTS_WITH_NAMES); do \
271251
dockerfile=$${variant#*:}; \
272252
variant_name=$${variant%%:*}; \
273-
if $(call dockerfile_arch_is_excluded,$*); then \
274-
echo "Skipping $$variant_name variant for linux-$* (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \
275-
continue; \
276-
fi; \
277253
distroless_arch="$*"; \
278254
if [ "$*" = "armv7" ]; then \
279255
distroless_arch="arm"; \
@@ -308,14 +284,6 @@ $(PUBLISH_DOCKER_ARCHS): common-docker-publish-%:
308284
@for variant in $(DOCKERFILE_VARIANTS_WITH_NAMES); do \
309285
dockerfile=$${variant#*:}; \
310286
variant_name=$${variant%%:*}; \
311-
if $(call dockerfile_arch_is_excluded,$*); then \
312-
echo "Skipping push for $$variant_name variant on linux-$* (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \
313-
continue; \
314-
fi; \
315-
if $(call registry_arch_is_excluded,$*); then \
316-
echo "Skipping push for $$variant_name variant on linux-$* to $(DOCKER_REPO) (excluded by DOCKER_REGISTRY_ARCH_EXCLUSIONS)"; \
317-
continue; \
318-
fi; \
319287
if [ "$$dockerfile" != "Dockerfile" ] || [ "$$variant_name" != "default" ]; then \
320288
echo "Pushing $$variant_name variant for linux-$*"; \
321289
docker push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)-$$variant_name"; \
@@ -343,14 +311,6 @@ $(TAG_DOCKER_ARCHS): common-docker-tag-latest-%:
343311
@for variant in $(DOCKERFILE_VARIANTS_WITH_NAMES); do \
344312
dockerfile=$${variant#*:}; \
345313
variant_name=$${variant%%:*}; \
346-
if $(call dockerfile_arch_is_excluded,$*); then \
347-
echo "Skipping tag for $$variant_name variant on linux-$* (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \
348-
continue; \
349-
fi; \
350-
if $(call registry_arch_is_excluded,$*); then \
351-
echo "Skipping tag for $$variant_name variant on linux-$* for $(DOCKER_REPO) (excluded by DOCKER_REGISTRY_ARCH_EXCLUSIONS)"; \
352-
continue; \
353-
fi; \
354314
if [ "$$dockerfile" != "Dockerfile" ] || [ "$$variant_name" != "default" ]; then \
355315
echo "Tagging $$variant_name variant for linux-$* as latest"; \
356316
docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)-$$variant_name" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:latest-$$variant_name"; \
@@ -372,14 +332,6 @@ common-docker-manifest:
372332
echo "Creating manifest for $$variant_name variant"; \
373333
refs=""; \
374334
for arch in $(DOCKER_ARCHS); do \
375-
if $(call dockerfile_arch_is_excluded,$$arch); then \
376-
echo " Skipping $$arch for $$variant_name (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \
377-
continue; \
378-
fi; \
379-
if $(call registry_arch_is_excluded,$$arch); then \
380-
echo " Skipping $$arch for $$variant_name on $(DOCKER_REPO) (excluded by DOCKER_REGISTRY_ARCH_EXCLUSIONS)"; \
381-
continue; \
382-
fi; \
383335
refs="$$refs $(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$$arch:$(SANITIZED_DOCKER_IMAGE_TAG)-$$variant_name"; \
384336
done; \
385337
if [ -z "$$refs" ]; then \
@@ -393,14 +345,6 @@ common-docker-manifest:
393345
echo "Creating default variant ($$variant_name) manifest"; \
394346
refs=""; \
395347
for arch in $(DOCKER_ARCHS); do \
396-
if $(call dockerfile_arch_is_excluded,$$arch); then \
397-
echo " Skipping $$arch for default variant (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \
398-
continue; \
399-
fi; \
400-
if $(call registry_arch_is_excluded,$$arch); then \
401-
echo " Skipping $$arch for default variant on $(DOCKER_REPO) (excluded by DOCKER_REGISTRY_ARCH_EXCLUSIONS)"; \
402-
continue; \
403-
fi; \
404348
refs="$$refs $(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$$arch:$(SANITIZED_DOCKER_IMAGE_TAG)"; \
405349
done; \
406350
if [ -z "$$refs" ]; then \
@@ -415,14 +359,6 @@ common-docker-manifest:
415359
echo "Creating manifest for $$variant_name variant version tag"; \
416360
refs=""; \
417361
for arch in $(DOCKER_ARCHS); do \
418-
if $(call dockerfile_arch_is_excluded,$$arch); then \
419-
echo " Skipping $$arch for $$variant_name version tag (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \
420-
continue; \
421-
fi; \
422-
if $(call registry_arch_is_excluded,$$arch); then \
423-
echo " Skipping $$arch for $$variant_name version tag on $(DOCKER_REPO) (excluded by DOCKER_REGISTRY_ARCH_EXCLUSIONS)"; \
424-
continue; \
425-
fi; \
426362
refs="$$refs $(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$$arch:v$(DOCKER_MAJOR_VERSION_TAG)-$$variant_name"; \
427363
done; \
428364
if [ -z "$$refs" ]; then \
@@ -436,14 +372,6 @@ common-docker-manifest:
436372
echo "Creating default variant version tag manifest"; \
437373
refs=""; \
438374
for arch in $(DOCKER_ARCHS); do \
439-
if $(call dockerfile_arch_is_excluded,$$arch); then \
440-
echo " Skipping $$arch for default variant version tag (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \
441-
continue; \
442-
fi; \
443-
if $(call registry_arch_is_excluded,$$arch); then \
444-
echo " Skipping $$arch for default variant version tag on $(DOCKER_REPO) (excluded by DOCKER_REGISTRY_ARCH_EXCLUSIONS)"; \
445-
continue; \
446-
fi; \
447375
refs="$$refs $(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$$arch:v$(DOCKER_MAJOR_VERSION_TAG)"; \
448376
done; \
449377
if [ -z "$$refs" ]; then \
@@ -497,9 +425,3 @@ $(1)_precheck:
497425
exit 1; \
498426
fi
499427
endef
500-
501-
govulncheck: install-govulncheck
502-
govulncheck ./...
503-
504-
install-govulncheck:
505-
command -v govulncheck > /dev/null || go install golang.org/x/vuln/cmd/govulncheck@latest

SECURITY.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33
The Prometheus security policy, including how to report vulnerabilities, can be
44
found here:
55

6-
<https://prometheus.io/docs/operating/security/>
6+
[https://prometheus.io/docs/operating/security/](https://prometheus.io/docs/operating/security/)

config/config.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ type Secret string
3333
var MarshalSecretValue = false
3434

3535
// MarshalYAML implements the yaml.Marshaler interface for Secrets.
36-
func (s Secret) MarshalYAML() (interface{}, error) {
36+
func (s Secret) MarshalYAML() (any, error) {
3737
if MarshalSecretValue {
3838
return string(s), nil
3939
}
@@ -44,7 +44,7 @@ func (s Secret) MarshalYAML() (interface{}, error) {
4444
}
4545

4646
// UnmarshalYAML implements the yaml.Unmarshaler interface for Secrets.
47-
func (s *Secret) UnmarshalYAML(unmarshal func(interface{}) error) error {
47+
func (s *Secret) UnmarshalYAML(unmarshal func(any) error) error {
4848
type plain Secret
4949
return unmarshal((*plain)(s))
5050
}

config/headers_test.go

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,13 @@
1717
package config
1818

1919
import (
20+
"fmt"
21+
"io"
22+
"net"
2023
"net/http"
24+
"net/http/httptest"
2125
"path/filepath"
26+
"strings"
2227
"testing"
2328

2429
"github.com/stretchr/testify/require"
@@ -49,3 +54,111 @@ func TestHeadersSetDirectory(t *testing.T) {
4954
headers.Headers["X-Test"].Files,
5055
)
5156
}
57+
58+
func TestHeadersRoundTripperSameHost(t *testing.T) {
59+
// All headers, including sensitive ones, must be forwarded on same-host requests.
60+
for _, header := range []string{"Cookie", "X-Custom-Header"} {
61+
t.Run(header, func(t *testing.T) {
62+
received := ""
63+
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
64+
received = r.Header.Get(header)
65+
fmt.Fprint(w, "ok")
66+
}))
67+
t.Cleanup(server.Close)
68+
69+
headers := &Headers{
70+
Headers: map[string]Header{
71+
header: {Values: []string{"testvalue"}},
72+
},
73+
}
74+
rt := NewHeadersRoundTripper(headers, http.DefaultTransport)
75+
76+
req, err := http.NewRequest(http.MethodGet, server.URL, nil)
77+
require.NoError(t, err)
78+
79+
resp, err := rt.RoundTrip(req)
80+
require.NoError(t, err)
81+
defer resp.Body.Close()
82+
body, err := io.ReadAll(resp.Body)
83+
require.NoError(t, err)
84+
require.Equal(t, "ok", strings.TrimSpace(string(body)))
85+
require.Equalf(t, "testvalue", received, "header %q must be forwarded on same-host request", header)
86+
})
87+
}
88+
}
89+
90+
func TestHeadersRoundTripperCrossHostRedirect(t *testing.T) {
91+
// Cookie must be set on the initial request but stripped on cross-host redirects.
92+
cookieOnRedirect := ""
93+
target := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
94+
cookieOnRedirect = r.Header.Get("Cookie")
95+
fmt.Fprint(w, "ok")
96+
}))
97+
t.Cleanup(target.Close)
98+
99+
// Use "localhost" as the redirect target hostname so that it differs from
100+
// "127.0.0.1" used by the origin server, making it a cross-host redirect.
101+
targetPort := target.Listener.Addr().(*net.TCPAddr).Port
102+
targetURL := fmt.Sprintf("http://localhost:%d", targetPort)
103+
104+
cookieOnOrigin := ""
105+
origin := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
106+
cookieOnOrigin = r.Header.Get("Cookie")
107+
http.Redirect(w, r, targetURL, http.StatusFound)
108+
}))
109+
t.Cleanup(origin.Close)
110+
111+
cfg := HTTPClientConfig{
112+
FollowRedirects: true,
113+
HTTPHeaders: &Headers{
114+
Headers: map[string]Header{
115+
"Cookie": {Values: []string{"session=abc"}},
116+
},
117+
},
118+
}
119+
client, err := NewClientFromConfig(cfg, "test")
120+
require.NoError(t, err)
121+
122+
resp, err := client.Get(origin.URL)
123+
require.NoError(t, err)
124+
defer resp.Body.Close()
125+
_, err = io.ReadAll(resp.Body)
126+
require.NoError(t, err)
127+
128+
require.Equalf(t, "session=abc", cookieOnOrigin, "Cookie must be set on the initial request.")
129+
require.Emptyf(t, cookieOnRedirect, "Cookie must not be forwarded on a cross-host redirect.")
130+
}
131+
132+
func TestHeadersRoundTripperSameHostRedirect(t *testing.T) {
133+
// Cookie must be forwarded on same-host redirects.
134+
mux := http.NewServeMux()
135+
cookieOnRedirect := ""
136+
mux.HandleFunc("/start", func(w http.ResponseWriter, r *http.Request) {
137+
http.Redirect(w, r, "/end", http.StatusFound)
138+
})
139+
mux.HandleFunc("/end", func(w http.ResponseWriter, r *http.Request) {
140+
cookieOnRedirect = r.Header.Get("Cookie")
141+
fmt.Fprint(w, "ok")
142+
})
143+
server := httptest.NewServer(mux)
144+
t.Cleanup(server.Close)
145+
146+
cfg := HTTPClientConfig{
147+
FollowRedirects: true,
148+
HTTPHeaders: &Headers{
149+
Headers: map[string]Header{
150+
"Cookie": {Values: []string{"session=abc"}},
151+
},
152+
},
153+
}
154+
client, err := NewClientFromConfig(cfg, "test")
155+
require.NoError(t, err)
156+
157+
resp, err := client.Get(server.URL + "/start")
158+
require.NoError(t, err)
159+
defer resp.Body.Close()
160+
_, err = io.ReadAll(resp.Body)
161+
require.NoError(t, err)
162+
163+
require.Equalf(t, "session=abc", cookieOnRedirect, "Cookie must be forwarded on a same-host redirect.")
164+
}

0 commit comments

Comments
 (0)