From 1e9deb10021df51b61c8c994dbc9850b9a66166d Mon Sep 17 00:00:00 2001 From: GoncaloGarcia Date: Thu, 2 Apr 2026 12:24:59 +0100 Subject: [PATCH] TUN-9952: Bump go to 1.26 --- .ci/image/Dockerfile | 2 +- .ci/linux.gitlab-ci.yml | 4 +-- .gitlab-ci.yml | 2 +- .golangci.yaml | 22 ++++++++++------ Dockerfile | 2 +- Dockerfile.amd64 | 2 +- Dockerfile.arm64 | 2 +- README.md | 2 +- cmd/cloudflared/access/validation.go | 20 +++++++++++++++ cmd/cloudflared/access/validation_test.go | 31 ++++++++++++++++++++--- go.mod | 2 +- 11 files changed, 71 insertions(+), 20 deletions(-) diff --git a/.ci/image/Dockerfile b/.ci/image/Dockerfile index 033ecc2a..4e3103db 100644 --- a/.ci/image/Dockerfile +++ b/.ci/image/Dockerfile @@ -6,7 +6,7 @@ RUN apt-get update && \ apt-get install --no-install-recommends --allow-downgrades -y \ build-essential \ git \ - go-boring=1.24.13-1 \ + go-boring=1.26.0-1 \ libffi-dev \ procps \ python3-dev \ diff --git a/.ci/linux.gitlab-ci.yml b/.ci/linux.gitlab-ci.yml index 4554feec..d0c48727 100644 --- a/.ci/linux.gitlab-ci.yml +++ b/.ci/linux.gitlab-ci.yml @@ -4,8 +4,8 @@ outputDir: artifacts runner: linux-x86-8cpu-16gb stage: build - golangVersion: "boring-1.24" - imageVersion: "3462-0b23466e0715@sha256:42e8533370666a2463041572293a79e1449001ef803a993e6a860be00858c806" + golangVersion: "boring-1.26" + imageVersion: "3501-fc698419a625@sha256:aff18c895a50e8451982484e629319e893ebd411675e0482d247079801253e7b" CGO_ENABLED: 1 .default-packaging-job: &packaging-job-defaults diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index fb416459..4444e161 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,5 +1,5 @@ variables: - GO_VERSION: "1.24.13" + GO_VERSION: "1.26.0" MAC_GO_VERSION: "go@$GO_VERSION" WIN_GO_VERSION: "go$GO_VERSION" GIT_DEPTH: "0" diff --git a/.golangci.yaml b/.golangci.yaml index 615dc280..b11059fa 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -1,3 +1,5 @@ +version: "2" + linters: enable: # Some of the linters below are commented out. We should uncomment and start running them, but they return @@ -14,10 +16,7 @@ linters: - errcheck # Errcheck is a program for checking for unchecked errors in Go code. These unchecked errors can be critical bugs in some cases. - errname # Checks that sentinel errors are prefixed with the Err and error types are suffixed with the Error. - exhaustive # Check exhaustiveness of enum switch statements. - - gofmt # Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification. - - goimports # Check import statements are formatted according to the 'goimport' command. Reformat imports in autofix mode. - gosec # Inspects source code for security problems. - - gosimple # Linter for Go source code that specializes in simplifying code. - govet # Vet examines Go source code and reports suspicious constructs. It is roughly the same as 'go vet' and uses its passes. - ineffassign # Detects when assignments to existing variables are not used. - importas # Enforces consistent import aliases. @@ -36,7 +35,13 @@ linters: - wastedassign # Finds wasted assignment statements. - whitespace # Whitespace is a linter that checks for unnecessary newlines at the start and end of functions, if, for, etc. - zerologlint # Detects the wrong usage of zerolog that a user forgets to dispatch with Send or Msg. - # Other linters are disabled, list of all is here: https://golangci-lint.run/usage/linters/ + # Other linters are disabled, list of all is here: https://golangci-lint.run/usage/linters/ + +formatters: + enable: + - gofmt # Formats code according to Go standard formatting + - goimports # Formats imports and groups them properly + run: timeout: 5m modules-download-mode: vendor @@ -44,9 +49,10 @@ run: # output configuration options output: formats: - - format: 'colored-line-number' - print-issued-lines: true - print-linter-name: true + text: + colors: true + print-linter-name: true + print-issued-lines: true issues: # Maximum issues count per one linter. @@ -67,7 +73,7 @@ issues: new: true # Show only new issues created after git revision `REV`. # Default: "" - new-from-rev: ac34f94d423273c8fa8fdbb5f2ac60e55f2c77d5 + new-from-rev: d2a87e9b93456ad7f82417400f4209d513668487 # Show issues in any part of update files (requires new-from-rev or new-from-patch). # Default: false whole-files: true diff --git a/Dockerfile b/Dockerfile index 8ef07376..aa00af9d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ # use a builder image for building cloudflare ARG TARGET_GOOS ARG TARGET_GOARCH -FROM golang:1.24.13 AS builder +FROM golang:1.26.0 AS builder ENV GO111MODULE=on \ CGO_ENABLED=0 \ TARGET_GOOS=${TARGET_GOOS} \ diff --git a/Dockerfile.amd64 b/Dockerfile.amd64 index bbace987..224d1f04 100644 --- a/Dockerfile.amd64 +++ b/Dockerfile.amd64 @@ -1,5 +1,5 @@ # use a builder image for building cloudflare -FROM golang:1.24.13 AS builder +FROM golang:1.26.0 AS builder ENV GO111MODULE=on \ CGO_ENABLED=0 \ # the CONTAINER_BUILD envvar is used set github.com/cloudflare/cloudflared/metrics.Runtime=virtual diff --git a/Dockerfile.arm64 b/Dockerfile.arm64 index d6ec6718..fc9e2a9d 100644 --- a/Dockerfile.arm64 +++ b/Dockerfile.arm64 @@ -1,5 +1,5 @@ # use a builder image for building cloudflare -FROM golang:1.24.13 AS builder +FROM golang:1.26.0 AS builder ENV GO111MODULE=on \ CGO_ENABLED=0 \ # the CONTAINER_BUILD envvar is used set github.com/cloudflare/cloudflared/metrics.Runtime=virtual diff --git a/README.md b/README.md index a7eb0a32..7c5b60db 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ For example, as of January 2023 Cloudflare will support cloudflared version 2023 ### Requirements - [GNU Make](https://www.gnu.org/software/make/) - [capnp](https://capnproto.org/install.html) -- [go >= 1.24](https://go.dev/doc/install) +- [go >= 1.26](https://go.dev/doc/install) - Optional tools: - [capnpc-go](https://pkg.go.dev/zombiezen.com/go/capnproto2/capnpc-go) - [goimports](https://pkg.go.dev/golang.org/x/tools/cmd/goimports) diff --git a/cmd/cloudflared/access/validation.go b/cmd/cloudflared/access/validation.go index 1157aab5..7b057db9 100644 --- a/cmd/cloudflared/access/validation.go +++ b/cmd/cloudflared/access/validation.go @@ -3,6 +3,7 @@ package access import ( "errors" "fmt" + "net" "net/http" "net/url" "strings" @@ -23,6 +24,24 @@ func parseRequestHeaders(values []string) http.Header { return headers } +// bracketBareIPv6 wraps bare IPv6 addresses in a URL with square brackets. +// Go 1.26 tightened net/url parsing to strictly require RFC 3986 bracket syntax +// for IPv6 addresses in URLs. Before Go 1.26, bare forms like "http://::1" were +// accepted; now they are rejected. This function detects bare IPv6 in the host +// portion and brackets it so that url.ParseRequestURI can parse it correctly. +func bracketBareIPv6(input string) string { + prefix := input[:strings.Index(input, "://")+3] + rest := input[len(prefix):] + host := rest + if i := strings.IndexAny(rest, "/?#"); i >= 0 { + host = rest[:i] + } + if net.ParseIP(host) != nil && strings.Contains(host, ":") { + return prefix + "[" + host + "]" + rest[len(host):] + } + return input +} + // parseHostname will attempt to convert a user provided URL string into a string with some light error checking on // certain expectations from the URL. // Will convert all HTTP URLs to HTTPS @@ -33,6 +52,7 @@ func parseURL(input string) (*url.URL, error) { if !strings.HasPrefix(input, "https://") && !strings.HasPrefix(input, "http://") { input = fmt.Sprintf("https://%s", input) } + input = bracketBareIPv6(input) url, err := url.ParseRequestURI(input) if err != nil { return nil, fmt.Errorf("failed to parse as URL: %w", err) diff --git a/cmd/cloudflared/access/validation_test.go b/cmd/cloudflared/access/validation_test.go index dbfb974e..0b659fc3 100644 --- a/cmd/cloudflared/access/validation_test.go +++ b/cmd/cloudflared/access/validation_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestParseRequestHeaders(t *testing.T) { @@ -15,6 +16,30 @@ func TestParseRequestHeaders(t *testing.T) { assert.Equal(t, "000:000:0:1:asd", values.Get("cf-trace-id")) } +func TestBracketBareIPv6(t *testing.T) { + tests := []struct { + input string + expected string + }{ + {"https://::1", "https://[::1]"}, + {"https://::1/path", "https://[::1]/path"}, + {"https://::1:8080", "https://[::1:8080]"}, + {"https://::1:8080/path", "https://[::1:8080]/path"}, + {"https://::1?query=1", "https://[::1]?query=1"}, // query without path + {"https://::1#fragment", "https://[::1]#fragment"}, // fragment without path + {"https://[::1]", "https://[::1]"}, // already bracketed + {"https://[::1]:8080", "https://[::1]:8080"}, // already bracketed with port + {"https://127.0.0.1", "https://127.0.0.1"}, // IPv4 unchanged + {"https://example.com", "https://example.com"}, // hostname unchanged + {"https://example.com:8080", "https://example.com:8080"}, // hostname:port unchanged + } + for _, tt := range tests { + t.Run(tt.input, func(t *testing.T) { + assert.Equal(t, tt.expected, bracketBareIPv6(tt.input)) + }) + } +} + func TestParseURL(t *testing.T) { schemes := []string{ "http://", @@ -28,8 +53,8 @@ func TestParseURL(t *testing.T) { {"localhost", "localhost"}, {"127.0.0.1", "127.0.0.1"}, {"127.0.0.1:9090", "127.0.0.1:9090"}, - {"::1", "::1"}, - {"::1:8080", "::1:8080"}, + {"::1", "[::1]"}, + {"::1:8080", "[::1:8080]"}, {"[::1]", "[::1]"}, {"[::1]:8080", "[::1]:8080"}, {":8080", ":8080"}, @@ -49,7 +74,7 @@ func TestParseURL(t *testing.T) { input := fmt.Sprintf("%s%s%s", scheme, host.input, path) expected := fmt.Sprintf("%s%s%s", "https://", host.expected, path) url, err := parseURL(input) - assert.NoError(t, err, "input: %s\texpected: %s", input, expected) + require.NoError(t, err, "input: %s\texpected: %s", input, expected) assert.Equal(t, expected, url.String()) assert.Equal(t, host.expected, url.Host) assert.Equal(t, "https", url.Scheme) diff --git a/go.mod b/go.mod index 2e8194bf..d94efc49 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/cloudflare/cloudflared -go 1.24.0 +go 1.26 require ( github.com/coreos/go-oidc/v3 v3.17.0