diff --git a/internal/config/config_validation_internal_test.go b/internal/config/config_validation_internal_test.go index cb8efb2..fdcd17b 100644 --- a/internal/config/config_validation_internal_test.go +++ b/internal/config/config_validation_internal_test.go @@ -633,14 +633,14 @@ func TestOmittedOriginTimeoutsAndSizeUseDefaults(t *testing.T) { // TestExplicitOriginTimeoutsAndSizeAreUsed checks that valid values for // the CORS origin, the two timeouts and the response size limit are used -// as given. +// as given. The size is the largest accepted, 1 GiB. func TestExplicitOriginTimeoutsAndSizeAreUsed(t *testing.T) { t.Parallel() c, err := configFromYAML(t, signingKeyLine+` access_control_allow_origin: https://app.example.com upstream_fetch_timeout: 10s -upstream_max_response_size: 1048576 +upstream_max_response_size: 1073741824 downstream_timeout: 2m `) if err != nil { @@ -656,8 +656,8 @@ downstream_timeout: 2m t.Errorf("UpstreamFetchTimeout = %v, want 10s", c.UpstreamFetchTimeout) } - if c.UpstreamMaxResponseSize != 1048576 { - t.Errorf("UpstreamMaxResponseSize = %d, want 1048576", + if c.UpstreamMaxResponseSize != 1073741824 { + t.Errorf("UpstreamMaxResponseSize = %d, want 1073741824", c.UpstreamMaxResponseSize) } @@ -667,11 +667,14 @@ downstream_timeout: 2m } // TestOriginWithPortOrAnyOriginIsAccepted checks the other accepted forms -// of access_control_allow_origin: "*", and an origin with a port. +// of access_control_allow_origin: "*", an origin with a port, and origins +// whose host is an IPv4 or IPv6 address. func TestOriginWithPortOrAnyOriginIsAccepted(t *testing.T) { t.Parallel() - for _, origin := range []string{"*", "http://localhost:3000"} { + for _, origin := range []string{ + "*", "http://localhost:3000", "http://192.0.2.1", "http://[2001:db8::1]:8080", + } { c, err := configFromYAML(t, signingKeyLine+ "access_control_allow_origin: \""+origin+"\"\n") if err != nil { @@ -739,11 +742,44 @@ func invalidTimeoutCases() []abortCase { } // invalidSizeAndOriginCases are configs where upstream_max_response_size -// is not a positive whole number of bytes, or access_control_allow_origin -// is neither "*" nor an origin; each must abort startup naming the key -// and the value. +// is not a whole number of bytes from 1 to 1 GiB, or +// access_control_allow_origin is neither "*" nor an origin; each must +// abort startup naming the key and the value. func invalidSizeAndOriginCases() []abortCase { - return []abortCase{ + badOrigins := []string{ + "", // empty + "example.com", // no scheme + "https://example.com/images", // a path + "https://example.com/", // a trailing slash + // The CORS middleware reads a * inside an origin as a pattern + // that lets other sites read responses. + "https://*", + "https://*.example.com", + "https://*example.com", + "https://a.com,b.com", // two hosts + "https://example.com:", // an empty port + "https://:8443", // no host + "https://example.com:0", // a port below 1 + "https://example.com:99999", // a port above 65535 + "https://exämple.com", // a host name that is not ASCII + } + + cases := make([]abortCase, 0, len(badOrigins)) + for _, origin := range badOrigins { + cases = append(cases, abortCase{ + name: "access_control_allow_origin " + origin, + yaml: signingKeyLine + + "access_control_allow_origin: \"" + origin + "\"\n", + wantErrSubstrings: []string{keyAccessControlAllowOrigin, origin}, + }) + } + + return append(cases, []abortCase{ + { + name: "access_control_allow_origin null", + yaml: signingKeyLine + "access_control_allow_origin: null\n", + wantErrSubstrings: []string{keyAccessControlAllowOrigin, nullValueText}, + }, { name: "upstream_max_response_size with a unit", yaml: signingKeyLine + "upstream_max_response_size: 50MB\n", @@ -770,56 +806,19 @@ func invalidSizeAndOriginCases() []abortCase { wantErrSubstrings: []string{keyUpstreamMaxResponseSize, nullValueText}, }, { - name: "access_control_allow_origin bare hostname", - yaml: signingKeyLine + "access_control_allow_origin: example.com\n", + name: "upstream_max_response_size above 1 GiB", + yaml: signingKeyLine + "upstream_max_response_size: 1073741825\n", + wantErrSubstrings: []string{keyUpstreamMaxResponseSize, "1073741825"}, + }, + { + name: "upstream_max_response_size largest 64-bit integer", + yaml: signingKeyLine + + "upstream_max_response_size: 9223372036854775807\n", wantErrSubstrings: []string{ - keyAccessControlAllowOrigin, "example.com", + keyUpstreamMaxResponseSize, "9223372036854775807", }, }, - { - name: "access_control_allow_origin with a path", - yaml: signingKeyLine + - "access_control_allow_origin: https://example.com/images\n", - wantErrSubstrings: []string{ - keyAccessControlAllowOrigin, "https://example.com/images", - }, - }, - { - name: "access_control_allow_origin trailing slash", - yaml: signingKeyLine + - "access_control_allow_origin: https://example.com/\n", - wantErrSubstrings: []string{ - keyAccessControlAllowOrigin, "https://example.com/", - }, - }, - { - name: "access_control_allow_origin host *", - yaml: signingKeyLine + "access_control_allow_origin: https://*\n", - wantErrSubstrings: []string{keyAccessControlAllowOrigin, "https://*"}, - }, - { - name: "access_control_allow_origin host *.example.com", - yaml: signingKeyLine + - "access_control_allow_origin: https://*.example.com\n", - wantErrSubstrings: []string{keyAccessControlAllowOrigin, "https://*.example.com"}, - }, - { - name: "access_control_allow_origin host *example.com", - yaml: signingKeyLine + - "access_control_allow_origin: https://*example.com\n", - wantErrSubstrings: []string{keyAccessControlAllowOrigin, "https://*example.com"}, - }, - { - name: "access_control_allow_origin empty", - yaml: signingKeyLine + "access_control_allow_origin: \"\"\n", - wantErrSubstrings: []string{keyAccessControlAllowOrigin}, - }, - { - name: "access_control_allow_origin null", - yaml: signingKeyLine + "access_control_allow_origin: null\n", - wantErrSubstrings: []string{keyAccessControlAllowOrigin, nullValueText}, - }, - } + }...) } // TestInvalidOriginTimeoutOrSizeAbortsStartup verifies the