diff --git a/configuration/configuration.go b/configuration/configuration.go index 68b02a41..95fad34e 100644 --- a/configuration/configuration.go +++ b/configuration/configuration.go @@ -123,6 +123,13 @@ type Configuration struct { // Addr specifies the bind address for the debug server. Addr string `yaml:"addr,omitempty"` } `yaml:"debug,omitempty"` + + // HTTP2 configuration options + HTTP2 struct { + // Specifies wether the registry should disallow clients attempting + // to connect via http2. If set to true, only http/1.1 is supported. + Disabled bool `yaml:"disabled,omitempty"` + } `yaml:"http2,omitempty"` } `yaml:"http,omitempty"` // Notifications specifies configuration about various endpoint to which diff --git a/configuration/configuration_test.go b/configuration/configuration_test.go index 86f048ad..1768894e 100644 --- a/configuration/configuration_test.go +++ b/configuration/configuration_test.go @@ -82,6 +82,9 @@ var configStruct = Configuration{ Debug struct { Addr string `yaml:"addr,omitempty"` } `yaml:"debug,omitempty"` + HTTP2 struct { + Disabled bool `yaml:"disabled,omitempty"` + } `yaml:"http2,omitempty"` }{ TLS: struct { Certificate string `yaml:"certificate,omitempty"` @@ -97,6 +100,11 @@ var configStruct = Configuration{ Headers: http.Header{ "X-Content-Type-Options": []string{"nosniff"}, }, + HTTP2: struct { + Disabled bool `yaml:"disabled,omitempty"` + }{ + Disabled: false, + }, }, } diff --git a/docs/configuration.md b/docs/configuration.md index cd7703ac..1f82e854 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -198,6 +198,8 @@ information about each option that appears later in this page. addr: localhost:5001 headers: X-Content-Type-Options: [nosniff] + http2: + disabled: false notifications: endpoints: - name: alistener @@ -910,6 +912,8 @@ configuration may contain both. addr: localhost:5001 headers: X-Content-Type-Options: [nosniff] + http2: + disabled: false The `http` option details the configuration for the HTTP server that hosts the registry. @@ -1112,6 +1116,29 @@ Including `X-Content-Type-Options: [nosniff]` is recommended, so that browsers will not interpret content as HTML if they are directed to load a page from the registry. This header is included in the example configuration files. +### http2 + +The `http2` struct within `http` is **optional**. Use this to control http2 +settings for the registry. + + + + + + + + + + + + +
ParameterRequiredDescription
+ disabled + + no + + A boolean that determines if http2 support should be disabled +
## notifications diff --git a/registry/registry.go b/registry/registry.go index 559f724c..2dd23aa7 100644 --- a/registry/registry.go +++ b/registry/registry.go @@ -116,7 +116,7 @@ func (registry *Registry) ListenAndServe() error { if config.HTTP.TLS.Certificate != "" || config.HTTP.TLS.LetsEncrypt.CacheFile != "" { tlsConf := &tls.Config{ ClientAuth: tls.NoClientCert, - NextProtos: []string{"http/1.1"}, + NextProtos: nextProtos(config), MinVersion: tls.VersionTLS10, PreferServerCipherSuites: true, CipherSuites: []uint16{ @@ -343,3 +343,12 @@ func resolveConfiguration(args []string) (*configuration.Configuration, error) { return config, nil } + +func nextProtos(config *configuration.Configuration) []string { + switch config.HTTP.HTTP2.Disabled { + case true: + return []string{"http/1.1"} + default: + return []string{"h2", "http/1.1"} + } +} diff --git a/registry/registry_test.go b/registry/registry_test.go new file mode 100644 index 00000000..34673117 --- /dev/null +++ b/registry/registry_test.go @@ -0,0 +1,30 @@ +package registry + +import ( + "reflect" + "testing" + + "github.com/docker/distribution/configuration" +) + +// Tests to ensure nextProtos returns the correct protocols when: +// * config.HTTP.HTTP2.Disabled is not explicitly set => [h2 http/1.1] +// * config.HTTP.HTTP2.Disabled is explicitly set to false [h2 http/1.1] +// * config.HTTP.HTTP2.Disabled is explicitly set to true [http/1.1] +func TestNextProtos(t *testing.T) { + config := &configuration.Configuration{} + protos := nextProtos(config) + if !reflect.DeepEqual(protos, []string{"h2", "http/1.1"}) { + t.Fatalf("expected protos to equal [h2 http/1.1], got %s", protos) + } + config.HTTP.HTTP2.Disabled = false + protos = nextProtos(config) + if !reflect.DeepEqual(protos, []string{"h2", "http/1.1"}) { + t.Fatalf("expected protos to equal [h2 http/1.1], got %s", protos) + } + config.HTTP.HTTP2.Disabled = true + protos = nextProtos(config) + if !reflect.DeepEqual(protos, []string{"http/1.1"}) { + t.Fatalf("expected protos to equal [http/1.1], got %s", protos) + } +}