Hello community,
here is the log from the commit of package docker-distribution for
openSUSE:Factory checked in at 2017-04-14 13:41:14
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/docker-distribution (Old)
and /work/SRC/openSUSE:Factory/.docker-distribution.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "docker-distribution"
Fri Apr 14 13:41:14 2017 rev:12 rq:487302 version:2.6.1
Changes:
--------
--- /work/SRC/openSUSE:Factory/docker-distribution/docker-distribution.changes
2017-02-03 17:35:53.416079466 +0100
+++
/work/SRC/openSUSE:Factory/.docker-distribution.new/docker-distribution.changes
2017-04-14 13:41:16.449261605 +0200
@@ -1,0 +2,7 @@
+Thu Apr 6 14:49:36 UTC 2017 - [email protected]
+
+- Updated to 2.6.1;
+ * Fix Forwarded header handling, revert use of X-Forwarded-Port
+ * Use driver Stat for registry health check
+
+-------------------------------------------------------------------
Old:
----
distribution-2.6.0.tar.xz
New:
----
distribution-2.6.1.tar.xz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ docker-distribution.spec ++++++
--- /var/tmp/diff_new_pack.psprIM/_old 2017-04-14 13:41:17.157161555 +0200
+++ /var/tmp/diff_new_pack.psprIM/_new 2017-04-14 13:41:17.161160989 +0200
@@ -17,7 +17,7 @@
Name: docker-distribution
-Version: 2.6.0
+Version: 2.6.1
Release: 0
Summary: The Docker toolset to pack, ship, store, and deliver content
License: Apache-2.0
++++++ _service ++++++
--- /var/tmp/diff_new_pack.psprIM/_old 2017-04-14 13:41:17.209154206 +0200
+++ /var/tmp/diff_new_pack.psprIM/_new 2017-04-14 13:41:17.209154206 +0200
@@ -3,8 +3,8 @@
<param name="url">https://github.com/docker/distribution.git</param>
<param name="scm">git</param>
<param name="exclude">.git</param>
- <param name="versionformat">2.6.0</param>
- <param name="revision">v2.6.0</param>
+ <param name="versionformat">2.6.1</param>
+ <param name="revision">v2.6.1</param>
</service>
<service name="recompress" mode="disabled">
<param name="file">distribution-*.tar</param>
++++++ distribution-2.6.0.tar.xz -> distribution-2.6.1.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/distribution-2.6.0/CHANGELOG.md
new/distribution-2.6.1/CHANGELOG.md
--- old/distribution-2.6.0/CHANGELOG.md 2017-01-18 02:15:28.000000000 +0100
+++ new/distribution-2.6.1/CHANGELOG.md 2017-04-06 01:18:07.000000000 +0200
@@ -1,5 +1,11 @@
# Changelog
+## 2.6.1 (2017-04-05)
+
+#### Registry
+- Fix `Forwarded` header handling, revert use of `X-Forwarded-Port`
+- Use driver `Stat` for registry health check
+
## 2.6.0 (2017-01-18)
#### Storage
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/distribution-2.6.0/registry/api/v2/urls.go
new/distribution-2.6.1/registry/api/v2/urls.go
--- old/distribution-2.6.0/registry/api/v2/urls.go 2017-01-18
02:15:28.000000000 +0100
+++ new/distribution-2.6.1/registry/api/v2/urls.go 2017-04-06
01:18:07.000000000 +0200
@@ -1,10 +1,8 @@
package v2
import (
- "net"
"net/http"
"net/url"
- "strconv"
"strings"
"github.com/docker/distribution/reference"
@@ -48,66 +46,42 @@
// NewURLBuilderFromRequest uses information from an *http.Request to
// construct the root url.
func NewURLBuilderFromRequest(r *http.Request, relative bool) *URLBuilder {
- var scheme string
+ var (
+ scheme = "http"
+ host = r.Host
+ )
- forwardedProto := r.Header.Get("X-Forwarded-Proto")
- // TODO: log the error
- forwardedHeader, _, _ := parseForwardedHeader(r.Header.Get("Forwarded"))
-
- switch {
- case len(forwardedProto) > 0:
- scheme = forwardedProto
- case len(forwardedHeader["proto"]) > 0:
- scheme = forwardedHeader["proto"]
- case r.TLS != nil:
+ if r.TLS != nil {
scheme = "https"
- case len(r.URL.Scheme) > 0:
+ } else if len(r.URL.Scheme) > 0 {
scheme = r.URL.Scheme
- default:
- scheme = "http"
}
- host := r.Host
-
- if forwardedHost := r.Header.Get("X-Forwarded-Host");
len(forwardedHost) > 0 {
- // According to the Apache mod_proxy docs, X-Forwarded-Host can
be a
- // comma-separated list of hosts, to which each proxy appends
the
- // requested host. We want to grab the first from this
comma-separated
- // list.
- hosts := strings.SplitN(forwardedHost, ",", 2)
- host = strings.TrimSpace(hosts[0])
- } else if addr, exists := forwardedHeader["for"]; exists {
- host = addr
- } else if h, exists := forwardedHeader["host"]; exists {
- host = h
- }
-
- portLessHost, port := host, ""
- if !isIPv6Address(portLessHost) {
- // with go 1.6, this would treat the last part of IPv6 address
as a port
- portLessHost, port, _ = net.SplitHostPort(host)
- }
- if forwardedPort := r.Header.Get("X-Forwarded-Port"); len(port) == 0 &&
len(forwardedPort) > 0 {
- ports := strings.SplitN(forwardedPort, ",", 2)
- forwardedPort = strings.TrimSpace(ports[0])
- if _, err := strconv.ParseInt(forwardedPort, 10, 32); err ==
nil {
- port = forwardedPort
+ // Handle fowarded headers
+ // Prefer "Forwarded" header as defined by rfc7239 if given
+ // see https://tools.ietf.org/html/rfc7239
+ if forwarded := r.Header.Get("Forwarded"); len(forwarded) > 0 {
+ forwardedHeader, _, err := parseForwardedHeader(forwarded)
+ if err == nil {
+ if fproto := forwardedHeader["proto"]; len(fproto) > 0 {
+ scheme = fproto
+ }
+ if fhost := forwardedHeader["host"]; len(fhost) > 0 {
+ host = fhost
+ }
}
- }
-
- if len(portLessHost) > 0 {
- host = portLessHost
- }
- if len(port) > 0 {
- // remove enclosing brackets of ipv6 address otherwise they
will be duplicated
- if len(host) > 1 && host[0] == '[' && host[len(host)-1] == ']' {
- host = host[1 : len(host)-1]
+ } else {
+ if forwardedProto := r.Header.Get("X-Forwarded-Proto");
len(forwardedProto) > 0 {
+ scheme = forwardedProto
+ }
+ if forwardedHost := r.Header.Get("X-Forwarded-Host");
len(forwardedHost) > 0 {
+ // According to the Apache mod_proxy docs,
X-Forwarded-Host can be a
+ // comma-separated list of hosts, to which each proxy
appends the
+ // requested host. We want to grab the first from this
comma-separated
+ // list.
+ hosts := strings.SplitN(forwardedHost, ",", 2)
+ host = strings.TrimSpace(hosts[0])
}
- // JoinHostPort properly encloses ipv6 addresses in square
brackets
- host = net.JoinHostPort(host, port)
- } else if isIPv6Address(host) && host[0] != '[' {
- // ipv6 needs to be enclosed in square brackets in urls
- host = "[" + host + "]"
}
basePath := routeDescriptorsMap[RouteNameBase].Path
@@ -287,28 +261,3 @@
return appendValuesURL(up, values...).String()
}
-
-// isIPv6Address returns true if given string is a valid IPv6 address. No port
is allowed. The address may be
-// enclosed in square brackets.
-func isIPv6Address(host string) bool {
- if len(host) > 1 && host[0] == '[' && host[len(host)-1] == ']' {
- host = host[1 : len(host)-1]
- }
- // The IPv6 scoped addressing zone identifier starts after the last
percent sign.
- if i := strings.LastIndexByte(host, '%'); i > 0 {
- host = host[:i]
- }
- ip := net.ParseIP(host)
- if ip == nil {
- return false
- }
- if ip.To16() == nil {
- return false
- }
- if ip.To4() == nil {
- return true
- }
- // dot can be present in ipv4-mapped address, it needs to come after a
colon though
- i := strings.IndexAny(host, ":.")
- return i >= 0 && host[i] == ':'
-}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/distribution-2.6.0/registry/api/v2/urls_test.go
new/distribution-2.6.1/registry/api/v2/urls_test.go
--- old/distribution-2.6.0/registry/api/v2/urls_test.go 2017-01-18
02:15:28.000000000 +0100
+++ new/distribution-2.6.1/registry/api/v2/urls_test.go 2017-04-06
01:18:07.000000000 +0200
@@ -179,7 +179,7 @@
{
name: "https protocol forwarded with a non-standard
header",
request: &http.Request{URL: u, Host: u.Host, Header:
http.Header{
- "X-Forwarded-Proto": []string{"https"},
+ "X-Custom-Forwarded-Proto": []string{"https"},
}},
base: "http://example.com",
},
@@ -225,6 +225,7 @@
{
name: "forwarded port with a non-standard header",
request: &http.Request{URL: u, Host: u.Host, Header:
http.Header{
+ "X-Forwarded-Host":
[]string{"example.com:5000"},
"X-Forwarded-Port": []string{"5000"},
}},
base: "http://example.com:5000",
@@ -234,16 +235,33 @@
request: &http.Request{URL: u, Host: u.Host, Header:
http.Header{
"X-Forwarded-Port": []string{"443 , 5001"},
}},
- base: "http://example.com:443",
+ base: "http://example.com",
+ },
+ {
+ name: "forwarded standard port with non-standard
headers",
+ request: &http.Request{URL: u, Host: u.Host, Header:
http.Header{
+ "X-Forwarded-Proto": []string{"https"},
+ "X-Forwarded-Host": []string{"example.com"},
+ "X-Forwarded-Port": []string{"443"},
+ }},
+ base: "https://example.com",
+ },
+ {
+ name: "forwarded standard port with non-standard
headers and explicit port",
+ request: &http.Request{URL: u, Host: u.Host + ":443",
Header: http.Header{
+ "X-Forwarded-Proto": []string{"https"},
+ "X-Forwarded-Host": []string{u.Host + ":443"},
+ "X-Forwarded-Port": []string{"443"},
+ }},
+ base: "https://example.com:443",
},
{
name: "several non-standard headers",
request: &http.Request{URL: u, Host: u.Host, Header:
http.Header{
"X-Forwarded-Proto": []string{"https"},
- "X-Forwarded-Host": []string{"
first.example.com "},
- "X-Forwarded-Port": []string{" 12345 \t"},
+ "X-Forwarded-Host": []string{"
first.example.com:12345 "},
}},
- base: "http://first.example.com:12345",
+ base: "https://first.example.com:12345",
},
{
name: "forwarded host with port supplied takes
priority",
@@ -264,16 +282,16 @@
{
name: "forwarded protocol and addr using standard
header",
request: &http.Request{URL: u, Host: u.Host, Header:
http.Header{
- "Forwarded":
[]string{`proto=https;for="192.168.22.30:80"`},
+ "Forwarded":
[]string{`proto=https;host="192.168.22.30:80"`},
}},
base: "https://192.168.22.30:80",
},
{
- name: "forwarded addr takes priority over host",
+ name: "forwarded host takes priority over for",
request: &http.Request{URL: u, Host: u.Host, Header:
http.Header{
- "Forwarded":
[]string{`host=reg.example.com;for="192.168.22.30:5000"`},
+ "Forwarded":
[]string{`host="reg.example.com:5000";for="192.168.22.30"`},
}},
- base: "http://192.168.22.30:5000",
+ base: "http://reg.example.com:5000",
},
{
name: "forwarded host and protocol using standard
header",
@@ -292,92 +310,65 @@
{
name: "process just the first list element of standard
header",
request: &http.Request{URL: u, Host: u.Host, Header:
http.Header{
- "Forwarded":
[]string{`for="reg.example.com:443";proto=https,
for="reg.example.com:80";proto=http`},
+ "Forwarded":
[]string{`host="reg.example.com:443";proto=https,
host="reg.example.com:80";proto=http`},
}},
base: "https://reg.example.com:443",
},
{
- name: "IPv6 address override port",
+ name: "IPv6 address use host",
request: &http.Request{URL: u, Host: u.Host, Header:
http.Header{
- "Forwarded":
[]string{`for="2607:f0d0:1002:51::4"`},
- "X-Forwarded-Port": []string{"5001"},
+ "Forwarded":
[]string{`for="2607:f0d0:1002:51::4";host="[2607:f0d0:1002:51::4]:5001"`},
+ "X-Forwarded-Port": []string{"5002"},
}},
base: "http://[2607:f0d0:1002:51::4]:5001",
},
{
name: "IPv6 address with port",
request: &http.Request{URL: u, Host: u.Host, Header:
http.Header{
- "Forwarded":
[]string{`for="[2607:f0d0:1002:51::4]:4000"`},
+ "Forwarded":
[]string{`host="[2607:f0d0:1002:51::4]:4000"`},
"X-Forwarded-Port": []string{"5001"},
}},
base: "http://[2607:f0d0:1002:51::4]:4000",
},
{
- name: "IPv6 long address override port",
- request: &http.Request{URL: u, Host: u.Host, Header:
http.Header{
- "Forwarded":
[]string{`for="2607:f0d0:1002:0051:0000:0000:0000:0004"`},
- "X-Forwarded-Port": []string{"5001"},
- }},
- base:
"http://[2607:f0d0:1002:0051:0000:0000:0000:0004]:5001",
- },
- {
- name: "IPv6 long address enclosed in brackets - be
benevolent",
- request: &http.Request{URL: u, Host: u.Host, Header:
http.Header{
- "Forwarded":
[]string{`for="[2607:f0d0:1002:0051:0000:0000:0000:0004]"`},
- "X-Forwarded-Port": []string{"5001"},
- }},
- base:
"http://[2607:f0d0:1002:0051:0000:0000:0000:0004]:5001",
- },
- {
- name: "IPv6 long address with port",
- request: &http.Request{URL: u, Host: u.Host, Header:
http.Header{
- "Forwarded":
[]string{`for="[2607:f0d0:1002:0051:0000:0000:0000:0004]:4321"`},
- "X-Forwarded-Port": []string{"5001"},
- }},
- base:
"http://[2607:f0d0:1002:0051:0000:0000:0000:0004]:4321",
- },
- {
- name: "IPv6 address with zone ID",
- request: &http.Request{URL: u, Host: u.Host, Header:
http.Header{
- "Forwarded":
[]string{`for="fe80::bd0f:a8bc:6480:238b%11"`},
- "X-Forwarded-Port": []string{"5001"},
- }},
- base: "http://[fe80::bd0f:a8bc:6480:238b%2511]:5001",
- },
- {
- name: "IPv6 address with zone ID and port",
+ name: "non-standard and standard forward headers",
request: &http.Request{URL: u, Host: u.Host, Header:
http.Header{
- "Forwarded":
[]string{`for="[fe80::bd0f:a8bc:6480:238b%eth0]:12345"`},
- "X-Forwarded-Port": []string{"5001"},
+ "X-Forwarded-Proto": []string{`https`},
+ "X-Forwarded-Host":
[]string{`first.example.com`},
+ "X-Forwarded-Port": []string{``},
+ "Forwarded":
[]string{`host=first.example.com; proto=https`},
}},
- base: "http://[fe80::bd0f:a8bc:6480:238b%25eth0]:12345",
+ base: "https://first.example.com",
},
{
- name: "IPv6 address without port",
+ name: "standard header takes precedence over
non-standard headers",
request: &http.Request{URL: u, Host: u.Host, Header:
http.Header{
- "Forwarded":
[]string{`for="::FFFF:129.144.52.38"`},
+ "X-Forwarded-Proto": []string{`http`},
+ "Forwarded":
[]string{`host=second.example.com; proto=https`},
+ "X-Forwarded-Host":
[]string{`first.example.com`},
+ "X-Forwarded-Port": []string{`4000`},
}},
- base: "http://[::FFFF:129.144.52.38]",
+ base: "https://second.example.com",
},
{
- name: "non-standard and standard forward headers",
+ name: "incomplete standard header uses default",
request: &http.Request{URL: u, Host: u.Host, Header:
http.Header{
"X-Forwarded-Proto": []string{`https`},
+ "Forwarded": []string{`for=127.0.0.1`},
"X-Forwarded-Host":
[]string{`first.example.com`},
- "X-Forwarded-Port": []string{``},
- "Forwarded":
[]string{`host=first.example.com; proto=https`},
+ "X-Forwarded-Port": []string{`4000`},
}},
- base: "https://first.example.com",
+ base: "http://" + u.Host,
},
{
- name: "non-standard headers take precedence over
standard one",
+ name: "standard with just proto",
request: &http.Request{URL: u, Host: u.Host, Header:
http.Header{
- "X-Forwarded-Proto": []string{`http`},
- "Forwarded":
[]string{`host=second.example.com; proto=https`},
+ "X-Forwarded-Proto": []string{`https`},
+ "Forwarded": []string{`proto=https`},
"X-Forwarded-Host":
[]string{`first.example.com`},
"X-Forwarded-Port": []string{`4000`},
}},
- base: "http://first.example.com:4000",
+ base: "https://" + u.Host,
},
}
@@ -396,23 +387,9 @@
t.Fatalf("[relative=%t, request=%q,
case=%q]: error building url: %v", relative, tr.name, testCase.description, err)
}
- var expectedURL string
- proto, ok :=
tr.request.Header["X-Forwarded-Proto"]
- if !ok {
- expectedURL = testCase.expectedPath
- if !relative {
- expectedURL = tr.base +
expectedURL
- }
- } else {
- urlBase, err := url.Parse(tr.base)
- if err != nil {
- t.Fatal(err)
- }
- urlBase.Scheme = proto[0]
- expectedURL = testCase.expectedPath
- if !relative {
- expectedURL = urlBase.String()
+ expectedURL
- }
+ expectedURL := testCase.expectedPath
+ if !relative {
+ expectedURL = tr.base + expectedURL
}
if buildURL != expectedURL {
@@ -505,119 +482,3 @@
}
}
}
-
-func TestIsIPv6Address(t *testing.T) {
- for _, tc := range []struct {
- name string
- address string
- isIPv6 bool
- }{
- {
- name: "IPv6 short address",
- address: `2607:f0d0:1002:51::4`,
- isIPv6: true,
- },
- {
- name: "IPv6 short address enclosed in brackets",
- address: "[2607:f0d0:1002:51::4]",
- isIPv6: true,
- },
- {
- name: "IPv6 address",
- address: `2607:f0d0:1002:0051:0000:0000:0000:0004`,
- isIPv6: true,
- },
- {
- name: "IPv6 address with numeric zone ID",
- address: `fe80::bd0f:a8bc:6480:238b%11`,
- isIPv6: true,
- },
- {
- name: "IPv6 address with device name as zone ID",
- address: `fe80::bd0f:a8bc:6480:238b%eth0`,
- isIPv6: true,
- },
- {
- name: "IPv6 address with device name as zone ID
enclosed in brackets",
- address: `[fe80::bd0f:a8bc:6480:238b%eth0]`,
- isIPv6: true,
- },
- {
- name: "IPv4-mapped address",
- address: "::FFFF:129.144.52.38",
- isIPv6: true,
- },
- {
- name: "localhost",
- address: "::1",
- isIPv6: true,
- },
- {
- name: "localhost",
- address: "::1",
- isIPv6: true,
- },
- {
- name: "long localhost address",
- address: "0:0:0:0:0:0:0:1",
- isIPv6: true,
- },
- {
- name: "IPv6 long address with port",
- address:
"[2607:f0d0:1002:0051:0000:0000:0000:0004]:4321",
- isIPv6: false,
- },
- {
- name: "too many groups",
- address: "2607:f0d0:1002:0051:0000:0000:0000:0004:4321",
- isIPv6: false,
- },
- {
- name: "square brackets don't make an IPv6 address",
- address: "[2607:f0d0]",
- isIPv6: false,
- },
- {
- name: "require two consecutive colons in localhost",
- address: ":1",
- isIPv6: false,
- },
- {
- name: "more then 4 hexadecimal digits",
- address: "2607:f0d0b:1002:0051:0000:0000:0000:0004",
- isIPv6: false,
- },
- {
- name: "too short address",
- address: `2607:f0d0:1002:0000:0000:0000:0004`,
- isIPv6: false,
- },
- {
- name: "IPv4 address",
- address: `192.168.100.1`,
- isIPv6: false,
- },
- {
- name: "unclosed bracket",
- address: `[2607:f0d0:1002:0051:0000:0000:0000:0004`,
- isIPv6: false,
- },
- {
- name: "trailing bracket",
- address: `2607:f0d0:1002:0051:0000:0000:0000:0004]`,
- isIPv6: false,
- },
- {
- name: "domain name",
- address: `localhost`,
- isIPv6: false,
- },
- } {
- isIPv6 := isIPv6Address(tc.address)
- if isIPv6 && !tc.isIPv6 {
- t.Errorf("[%s] address %q falsely detected as IPv6
address", tc.name, tc.address)
- } else if !isIPv6 && tc.isIPv6 {
- t.Errorf("[%s] address %q not recognized as IPv6",
tc.name, tc.address)
- }
- }
-}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/distribution-2.6.0/registry/handlers/app.go
new/distribution-2.6.1/registry/handlers/app.go
--- old/distribution-2.6.0/registry/handlers/app.go 2017-01-18
02:15:28.000000000 +0100
+++ new/distribution-2.6.1/registry/handlers/app.go 2017-04-06
01:18:07.000000000 +0200
@@ -341,7 +341,7 @@
}
storageDriverCheck := func() error {
- _, err := app.driver.List(app, "/") // "/" should
always exist
+ _, err := app.driver.Stat(app, "/") // "/" should
always exist
return err // any error will
be treated as failure
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/distribution-2.6.0/registry/storage/driver/base/base.go
new/distribution-2.6.1/registry/storage/driver/base/base.go
--- old/distribution-2.6.0/registry/storage/driver/base/base.go 2017-01-18
02:15:28.000000000 +0100
+++ new/distribution-2.6.1/registry/storage/driver/base/base.go 2017-04-06
01:18:07.000000000 +0200
@@ -137,7 +137,7 @@
ctx, done := context.WithTrace(ctx)
defer done("%s.Stat(%q)", base.Name(), path)
- if !storagedriver.PathRegexp.MatchString(path) {
+ if !storagedriver.PathRegexp.MatchString(path) && path != "/" {
return nil, storagedriver.InvalidPathError{Path: path,
DriverName: base.StorageDriver.Name()}
}