Validate insecure registry (`--insecure-registry`) values

This fix is based on:
https://github.com/docker/docker/issues/29936#issuecomment-277494885

Currently the insecure registry is only checked to see if it contains
scheme (`http(s)://`) or not. No fully validation is done and this
caused many confusions like in #29936.

This fix tries to address the issue.

This fix adds additional validation so that an insecure registry
is validated to make sure it is in `host:port` format where host
could be IPv4/IPv6 or a host name, and port could be an integer
between 0-65535.

Additional unit tests have been added.

This fix is related to #29936.

Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
This commit is contained in:
Yong Tang 2017-02-04 23:58:12 -08:00
parent fddab1444f
commit e49589505a
2 changed files with 72 additions and 0 deletions

View File

@ -4,6 +4,8 @@ import (
"fmt"
"net"
"net/url"
"regexp"
"strconv"
"strings"
"github.com/Sirupsen/logrus"
@ -62,6 +64,10 @@ var (
emptyServiceConfig = newServiceConfig(ServiceOptions{})
)
var (
validHostPortRegex = regexp.MustCompile(`^` + reference.DomainRegexp.String() + `$`)
)
// for mocking in unit tests
var lookupIP = net.LookupIP
@ -178,6 +184,12 @@ skip:
config.InsecureRegistryCIDRs = append(config.InsecureRegistryCIDRs, data)
} else {
if err := validateHostPort(r); err != nil {
config.ServiceConfig.InsecureRegistryCIDRs = originalCIDRs
config.ServiceConfig.IndexConfigs = originalIndexInfos
return fmt.Errorf("insecure registry %s is not valid: %v", r, err)
}
// Assume `host:port` if not CIDR.
config.IndexConfigs[r] = &registrytypes.IndexInfo{
Name: r,
@ -288,6 +300,30 @@ func validateNoScheme(reposName string) error {
return nil
}
func validateHostPort(s string) error {
// Split host and port, and in case s can not be splitted, assume host only
host, port, err := net.SplitHostPort(s)
if err != nil {
host = s
port = ""
}
// If match against the `host:port` pattern fails,
// it might be `IPv6:port`, which will be captured by net.ParseIP(host)
if !validHostPortRegex.MatchString(s) && net.ParseIP(host) == nil {
return fmt.Errorf("invalid host %q", host)
}
if port != "" {
v, err := strconv.Atoi(port)
if err != nil {
return err
}
if v < 0 || v > 65535 {
return fmt.Errorf("invalid port %q", port)
}
}
return nil
}
// newIndexInfo returns IndexInfo configuration from indexName
func newIndexInfo(config *serviceConfig, indexName string) (*registrytypes.IndexInfo, error) {
var err error

View File

@ -56,6 +56,22 @@ func TestLoadInsecureRegistries(t *testing.T) {
index string
err string
}{
{
registries: []string{"127.0.0.1"},
index: "127.0.0.1",
},
{
registries: []string{"127.0.0.1:8080"},
index: "127.0.0.1:8080",
},
{
registries: []string{"2001:db8::1"},
index: "2001:db8::1",
},
{
registries: []string{"[2001:db8::1]:80"},
index: "[2001:db8::1]:80",
},
{
registries: []string{"http://mytest.com"},
index: "mytest.com",
@ -76,6 +92,26 @@ func TestLoadInsecureRegistries(t *testing.T) {
registries: []string{"-invalid-registry"},
err: "Cannot begin or end with a hyphen",
},
{
registries: []string{`mytest-.com`},
err: `insecure registry mytest-.com is not valid: invalid host "mytest-.com"`,
},
{
registries: []string{`1200:0000:AB00:1234:0000:2552:7777:1313:8080`},
err: `insecure registry 1200:0000:AB00:1234:0000:2552:7777:1313:8080 is not valid: invalid host "1200:0000:AB00:1234:0000:2552:7777:1313:8080"`,
},
{
registries: []string{`mytest.com:500000`},
err: `insecure registry mytest.com:500000 is not valid: invalid port "500000"`,
},
{
registries: []string{`"mytest.com"`},
err: `insecure registry "mytest.com" is not valid: invalid host "\"mytest.com\""`,
},
{
registries: []string{`"mytest.com:5000"`},
err: `insecure registry "mytest.com:5000" is not valid: invalid host "\"mytest.com"`,
},
}
for _, testCase := range testCases {
config := newServiceConfig(ServiceOptions{})