Merge pull request #1839 from adamvduke/adamvduke/allow-http2-registry-clients
Allow registry clients to connect via http2master
						commit
						c4297ef9da
					
				|  | @ -123,6 +123,13 @@ type Configuration struct { | ||||||
| 			// Addr specifies the bind address for the debug server.
 | 			// Addr specifies the bind address for the debug server.
 | ||||||
| 			Addr string `yaml:"addr,omitempty"` | 			Addr string `yaml:"addr,omitempty"` | ||||||
| 		} `yaml:"debug,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"` | 	} `yaml:"http,omitempty"` | ||||||
| 
 | 
 | ||||||
| 	// Notifications specifies configuration about various endpoint to which
 | 	// Notifications specifies configuration about various endpoint to which
 | ||||||
|  |  | ||||||
|  | @ -82,6 +82,9 @@ var configStruct = Configuration{ | ||||||
| 		Debug   struct { | 		Debug   struct { | ||||||
| 			Addr string `yaml:"addr,omitempty"` | 			Addr string `yaml:"addr,omitempty"` | ||||||
| 		} `yaml:"debug,omitempty"` | 		} `yaml:"debug,omitempty"` | ||||||
|  | 		HTTP2 struct { | ||||||
|  | 			Disabled bool `yaml:"disabled,omitempty"` | ||||||
|  | 		} `yaml:"http2,omitempty"` | ||||||
| 	}{ | 	}{ | ||||||
| 		TLS: struct { | 		TLS: struct { | ||||||
| 			Certificate string   `yaml:"certificate,omitempty"` | 			Certificate string   `yaml:"certificate,omitempty"` | ||||||
|  | @ -97,6 +100,11 @@ var configStruct = Configuration{ | ||||||
| 		Headers: http.Header{ | 		Headers: http.Header{ | ||||||
| 			"X-Content-Type-Options": []string{"nosniff"}, | 			"X-Content-Type-Options": []string{"nosniff"}, | ||||||
| 		}, | 		}, | ||||||
|  | 		HTTP2: struct { | ||||||
|  | 			Disabled bool `yaml:"disabled,omitempty"` | ||||||
|  | 		}{ | ||||||
|  | 			Disabled: false, | ||||||
|  | 		}, | ||||||
| 	}, | 	}, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -198,6 +198,8 @@ information about each option that appears later in this page. | ||||||
|         addr: localhost:5001 |         addr: localhost:5001 | ||||||
|       headers: |       headers: | ||||||
|         X-Content-Type-Options: [nosniff] |         X-Content-Type-Options: [nosniff] | ||||||
|  |       http2: | ||||||
|  |         disabled: false | ||||||
|     notifications: |     notifications: | ||||||
|       endpoints: |       endpoints: | ||||||
|         - name: alistener |         - name: alistener | ||||||
|  | @ -910,6 +912,8 @@ configuration may contain both. | ||||||
|         addr: localhost:5001 |         addr: localhost:5001 | ||||||
|       headers: |       headers: | ||||||
|         X-Content-Type-Options: [nosniff] |         X-Content-Type-Options: [nosniff] | ||||||
|  |       http2: | ||||||
|  |         disabled: false | ||||||
| 
 | 
 | ||||||
| The `http` option details the configuration for the HTTP server that hosts the registry. | 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 | 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. | 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. | ||||||
|  | 
 | ||||||
|  | <table> | ||||||
|  |   <tr> | ||||||
|  |     <th>Parameter</th> | ||||||
|  |     <th>Required</th> | ||||||
|  |     <th>Description</th> | ||||||
|  |   </tr> | ||||||
|  |   <tr> | ||||||
|  |     <td> | ||||||
|  |       <code>disabled</code> | ||||||
|  |     </td> | ||||||
|  |     <td> | ||||||
|  |       no | ||||||
|  |     </td> | ||||||
|  |     <td> | ||||||
|  |        A boolean that determines if http2 support should be disabled | ||||||
|  |     </td> | ||||||
|  |   </tr> | ||||||
|  | </table> | ||||||
| 
 | 
 | ||||||
| ## notifications | ## notifications | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -116,7 +116,7 @@ func (registry *Registry) ListenAndServe() error { | ||||||
| 	if config.HTTP.TLS.Certificate != "" || config.HTTP.TLS.LetsEncrypt.CacheFile != "" { | 	if config.HTTP.TLS.Certificate != "" || config.HTTP.TLS.LetsEncrypt.CacheFile != "" { | ||||||
| 		tlsConf := &tls.Config{ | 		tlsConf := &tls.Config{ | ||||||
| 			ClientAuth:               tls.NoClientCert, | 			ClientAuth:               tls.NoClientCert, | ||||||
| 			NextProtos:               []string{"http/1.1"}, | 			NextProtos:               nextProtos(config), | ||||||
| 			MinVersion:               tls.VersionTLS10, | 			MinVersion:               tls.VersionTLS10, | ||||||
| 			PreferServerCipherSuites: true, | 			PreferServerCipherSuites: true, | ||||||
| 			CipherSuites: []uint16{ | 			CipherSuites: []uint16{ | ||||||
|  | @ -343,3 +343,12 @@ func resolveConfiguration(args []string) (*configuration.Configuration, error) { | ||||||
| 
 | 
 | ||||||
| 	return config, nil | 	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"} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -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) | ||||||
|  | 	} | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue