While investigating 29936 I noticed one potential issue
in `LoadInsecureRegistries`.
The implementation of the func assumes that the format
of insecure registry should be `host:port` if not CIDR.
However, it is very common that user may incorrectly
provide a registry with a scheme (e.g, `http://myregistry.com:5000`)
Such a registry format with a scheme will cause docker pull to
always try https endpoint.
The reason is that the func of `isSecureIndex()` actually will
check for the map of the index server for `myregistry.com:5000`
while the insecure registry only has a record of `http://myregistry.com:5000`.
As a consequence, docker assumes that `myregistry.com:5000` is not
a insecure registry and will go ahead with https endpoint.
This fix addresses the issue by error out insecure registries with scheme.
A unit test has been added.
This fix is related to 29936.
Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
| ... | ... |
@@ -7,6 +7,7 @@ import ( |
| 7 | 7 |
"net/url" |
| 8 | 8 |
"strings" |
| 9 | 9 |
|
| 10 |
+ "github.com/Sirupsen/logrus" |
|
| 10 | 11 |
registrytypes "github.com/docker/docker/api/types/registry" |
| 11 | 12 |
"github.com/docker/docker/opts" |
| 12 | 13 |
"github.com/docker/docker/reference" |
| ... | ... |
@@ -150,6 +151,19 @@ skip: |
| 150 | 150 |
config.ServiceConfig.IndexConfigs = originalIndexInfos |
| 151 | 151 |
return err |
| 152 | 152 |
} |
| 153 |
+ if strings.HasPrefix(strings.ToLower(r), "http://") {
|
|
| 154 |
+ logrus.Warnf("insecure registry %s should not contain 'http://' and 'http://' has been removed from the insecure registry config", r)
|
|
| 155 |
+ r = r[7:] |
|
| 156 |
+ } else if strings.HasPrefix(strings.ToLower(r), "https://") {
|
|
| 157 |
+ logrus.Warnf("insecure registry %s should not contain 'https://' and 'https://' has been removed from the insecure registry config", r)
|
|
| 158 |
+ r = r[8:] |
|
| 159 |
+ } else if validateNoScheme(r) != nil {
|
|
| 160 |
+ // Insecure registry should not contain '://' |
|
| 161 |
+ // before returning err, roll back to original data |
|
| 162 |
+ config.ServiceConfig.InsecureRegistryCIDRs = originalCIDRs |
|
| 163 |
+ config.ServiceConfig.IndexConfigs = originalIndexInfos |
|
| 164 |
+ return fmt.Errorf("insecure registry %s should not contain '://'", r)
|
|
| 165 |
+ } |
|
| 153 | 166 |
// Check if CIDR was passed to --insecure-registry |
| 154 | 167 |
_, ipnet, err := net.ParseCIDR(r) |
| 155 | 168 |
if err == nil {
|
| ... | ... |
@@ -1,6 +1,7 @@ |
| 1 | 1 |
package registry |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
+ "strings" |
|
| 4 | 5 |
"testing" |
| 5 | 6 |
) |
| 6 | 7 |
|
| ... | ... |
@@ -48,3 +49,57 @@ func TestValidateMirror(t *testing.T) {
|
| 48 | 48 |
} |
| 49 | 49 |
} |
| 50 | 50 |
} |
| 51 |
+ |
|
| 52 |
+func TestLoadInsecureRegistries(t *testing.T) {
|
|
| 53 |
+ testCases := []struct {
|
|
| 54 |
+ registries []string |
|
| 55 |
+ index string |
|
| 56 |
+ err string |
|
| 57 |
+ }{
|
|
| 58 |
+ {
|
|
| 59 |
+ registries: []string{"http://mytest.com"},
|
|
| 60 |
+ index: "mytest.com", |
|
| 61 |
+ }, |
|
| 62 |
+ {
|
|
| 63 |
+ registries: []string{"https://mytest.com"},
|
|
| 64 |
+ index: "mytest.com", |
|
| 65 |
+ }, |
|
| 66 |
+ {
|
|
| 67 |
+ registries: []string{"HTTP://mytest.com"},
|
|
| 68 |
+ index: "mytest.com", |
|
| 69 |
+ }, |
|
| 70 |
+ {
|
|
| 71 |
+ registries: []string{"svn://mytest.com"},
|
|
| 72 |
+ err: "insecure registry svn://mytest.com should not contain '://'", |
|
| 73 |
+ }, |
|
| 74 |
+ {
|
|
| 75 |
+ registries: []string{"-invalid-registry"},
|
|
| 76 |
+ err: "Cannot begin or end with a hyphen", |
|
| 77 |
+ }, |
|
| 78 |
+ } |
|
| 79 |
+ for _, testCase := range testCases {
|
|
| 80 |
+ config := newServiceConfig(ServiceOptions{})
|
|
| 81 |
+ err := config.LoadInsecureRegistries(testCase.registries) |
|
| 82 |
+ if testCase.err == "" {
|
|
| 83 |
+ if err != nil {
|
|
| 84 |
+ t.Fatalf("expect no error, got '%s'", err)
|
|
| 85 |
+ } |
|
| 86 |
+ match := false |
|
| 87 |
+ for index := range config.IndexConfigs {
|
|
| 88 |
+ if index == testCase.index {
|
|
| 89 |
+ match = true |
|
| 90 |
+ } |
|
| 91 |
+ } |
|
| 92 |
+ if !match {
|
|
| 93 |
+ t.Fatalf("expect index configs to contain '%s', got %+v", testCase.index, config.IndexConfigs)
|
|
| 94 |
+ } |
|
| 95 |
+ } else {
|
|
| 96 |
+ if err == nil {
|
|
| 97 |
+ t.Fatalf("expect error '%s', got no error", testCase.err)
|
|
| 98 |
+ } |
|
| 99 |
+ if !strings.Contains(err.Error(), testCase.err) {
|
|
| 100 |
+ t.Fatalf("expect error '%s', got '%s'", testCase.err, err)
|
|
| 101 |
+ } |
|
| 102 |
+ } |
|
| 103 |
+ } |
|
| 104 |
+} |