github.com/enmand/kubernetes@v1.2.0-alpha.0/pkg/credentialprovider/keyring_test.go (about)

     1  /*
     2  Copyright 2014 The Kubernetes Authors All rights reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package credentialprovider
    18  
    19  import (
    20  	"encoding/base64"
    21  	"fmt"
    22  	"testing"
    23  )
    24  
    25  func TestUrlsMatch(t *testing.T) {
    26  	tests := []struct {
    27  		globUrl       string
    28  		targetUrl     string
    29  		matchExpected bool
    30  	}{
    31  		// match when there is no path component
    32  		{
    33  			globUrl:       "*.kubernetes.io",
    34  			targetUrl:     "prefix.kubernetes.io",
    35  			matchExpected: true,
    36  		},
    37  		{
    38  			globUrl:       "prefix.*.io",
    39  			targetUrl:     "prefix.kubernetes.io",
    40  			matchExpected: true,
    41  		},
    42  		{
    43  			globUrl:       "prefix.kubernetes.*",
    44  			targetUrl:     "prefix.kubernetes.io",
    45  			matchExpected: true,
    46  		},
    47  		{
    48  			globUrl:       "*-good.kubernetes.io",
    49  			targetUrl:     "prefix-good.kubernetes.io",
    50  			matchExpected: true,
    51  		},
    52  		// match with path components
    53  		{
    54  			globUrl:       "*.kubernetes.io/blah",
    55  			targetUrl:     "prefix.kubernetes.io/blah",
    56  			matchExpected: true,
    57  		},
    58  		{
    59  			globUrl:       "prefix.*.io/foo",
    60  			targetUrl:     "prefix.kubernetes.io/foo/bar",
    61  			matchExpected: true,
    62  		},
    63  		// match with path components and ports
    64  		{
    65  			globUrl:       "*.kubernetes.io:1111/blah",
    66  			targetUrl:     "prefix.kubernetes.io:1111/blah",
    67  			matchExpected: true,
    68  		},
    69  		{
    70  			globUrl:       "prefix.*.io:1111/foo",
    71  			targetUrl:     "prefix.kubernetes.io:1111/foo/bar",
    72  			matchExpected: true,
    73  		},
    74  		// no match when number of parts mismatch
    75  		{
    76  			globUrl:       "*.kubernetes.io",
    77  			targetUrl:     "kubernetes.io",
    78  			matchExpected: false,
    79  		},
    80  		{
    81  			globUrl:       "*.*.kubernetes.io",
    82  			targetUrl:     "prefix.kubernetes.io",
    83  			matchExpected: false,
    84  		},
    85  		{
    86  			globUrl:       "*.*.kubernetes.io",
    87  			targetUrl:     "kubernetes.io",
    88  			matchExpected: false,
    89  		},
    90  		// no match when some parts mismatch
    91  		{
    92  			globUrl:       "kubernetes.io",
    93  			targetUrl:     "kubernetes.com",
    94  			matchExpected: false,
    95  		},
    96  		{
    97  			globUrl:       "k*.io",
    98  			targetUrl:     "quay.io",
    99  			matchExpected: false,
   100  		},
   101  		// no match when ports mismatch
   102  		{
   103  			globUrl:       "*.kubernetes.io:1234/blah",
   104  			targetUrl:     "prefix.kubernetes.io:1111/blah",
   105  			matchExpected: false,
   106  		},
   107  		{
   108  			globUrl:       "prefix.*.io/foo",
   109  			targetUrl:     "prefix.kubernetes.io:1111/foo/bar",
   110  			matchExpected: false,
   111  		},
   112  	}
   113  	for _, test := range tests {
   114  		matched, _ := urlsMatchStr(test.globUrl, test.targetUrl)
   115  		if matched != test.matchExpected {
   116  			t.Errorf("Expected match result of %s and %s to be %t, but was %t",
   117  				test.globUrl, test.targetUrl, test.matchExpected, matched)
   118  		}
   119  	}
   120  }
   121  
   122  func TestDockerKeyringForGlob(t *testing.T) {
   123  	tests := []struct {
   124  		globUrl   string
   125  		targetUrl string
   126  	}{
   127  		{
   128  			globUrl:   "hello.kubernetes.io",
   129  			targetUrl: "hello.kubernetes.io",
   130  		},
   131  		{
   132  			globUrl:   "*.docker.io",
   133  			targetUrl: "prefix.docker.io",
   134  		},
   135  		{
   136  			globUrl:   "prefix.*.io",
   137  			targetUrl: "prefix.docker.io",
   138  		},
   139  		{
   140  			globUrl:   "prefix.docker.*",
   141  			targetUrl: "prefix.docker.io",
   142  		},
   143  		{
   144  			globUrl:   "*.docker.io/path",
   145  			targetUrl: "prefix.docker.io/path",
   146  		},
   147  		{
   148  			globUrl:   "prefix.*.io/path",
   149  			targetUrl: "prefix.docker.io/path/subpath",
   150  		},
   151  		{
   152  			globUrl:   "prefix.docker.*/path",
   153  			targetUrl: "prefix.docker.io/path",
   154  		},
   155  		{
   156  			globUrl:   "*.docker.io:8888",
   157  			targetUrl: "prefix.docker.io:8888",
   158  		},
   159  		{
   160  			globUrl:   "prefix.*.io:8888",
   161  			targetUrl: "prefix.docker.io:8888",
   162  		},
   163  		{
   164  			globUrl:   "prefix.docker.*:8888",
   165  			targetUrl: "prefix.docker.io:8888",
   166  		},
   167  		{
   168  			globUrl:   "*.docker.io/path:1111",
   169  			targetUrl: "prefix.docker.io/path:1111",
   170  		},
   171  		{
   172  			globUrl:   "prefix.*.io/path:1111",
   173  			targetUrl: "prefix.docker.io/path/subpath:1111",
   174  		},
   175  		{
   176  			globUrl:   "prefix.docker.*/path:1111",
   177  			targetUrl: "prefix.docker.io/path:1111",
   178  		},
   179  	}
   180  	for _, test := range tests {
   181  		email := "foo@bar.baz"
   182  		username := "foo"
   183  		password := "bar"
   184  		auth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", username, password)))
   185  		sampleDockerConfig := fmt.Sprintf(`{
   186     "https://%s": {
   187       "email": %q,
   188       "auth": %q
   189     }
   190  }`, test.globUrl, email, auth)
   191  
   192  		keyring := &BasicDockerKeyring{}
   193  		if cfg, err := readDockerConfigFileFromBytes([]byte(sampleDockerConfig)); err != nil {
   194  			t.Errorf("Error processing json blob %q, %v", sampleDockerConfig, err)
   195  		} else {
   196  			keyring.Add(cfg)
   197  		}
   198  
   199  		creds, ok := keyring.Lookup(test.targetUrl + "/foo/bar")
   200  		if !ok {
   201  			t.Errorf("Didn't find expected URL: %s", test.targetUrl)
   202  			return
   203  		}
   204  		val := creds[0]
   205  
   206  		if username != val.Username {
   207  			t.Errorf("Unexpected username value, want: %s, got: %s", username, val.Username)
   208  		}
   209  		if password != val.Password {
   210  			t.Errorf("Unexpected password value, want: %s, got: %s", password, val.Password)
   211  		}
   212  		if email != val.Email {
   213  			t.Errorf("Unexpected email value, want: %s, got: %s", email, val.Email)
   214  		}
   215  	}
   216  }
   217  
   218  func TestKeyringMiss(t *testing.T) {
   219  	tests := []struct {
   220  		globUrl   string
   221  		lookupUrl string
   222  	}{
   223  		{
   224  			globUrl:   "hello.kubernetes.io",
   225  			lookupUrl: "world.mesos.org/foo/bar",
   226  		},
   227  		{
   228  			globUrl:   "*.docker.com",
   229  			lookupUrl: "prefix.docker.io",
   230  		},
   231  		{
   232  			globUrl:   "suffix.*.io",
   233  			lookupUrl: "prefix.docker.io",
   234  		},
   235  		{
   236  			globUrl:   "prefix.docker.c*",
   237  			lookupUrl: "prefix.docker.io",
   238  		},
   239  	}
   240  	for _, test := range tests {
   241  		email := "foo@bar.baz"
   242  		username := "foo"
   243  		password := "bar"
   244  		auth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", username, password)))
   245  		sampleDockerConfig := fmt.Sprintf(`{
   246     "https://%s": {
   247       "email": %q,
   248       "auth": %q
   249     }
   250  }`, test.globUrl, email, auth)
   251  
   252  		keyring := &BasicDockerKeyring{}
   253  		if cfg, err := readDockerConfigFileFromBytes([]byte(sampleDockerConfig)); err != nil {
   254  			t.Errorf("Error processing json blob %q, %v", sampleDockerConfig, err)
   255  		} else {
   256  			keyring.Add(cfg)
   257  		}
   258  
   259  		_, ok := keyring.Lookup(test.lookupUrl + "/foo/bar")
   260  		if ok {
   261  			t.Errorf("Expected not to find URL %s, but found", test.lookupUrl)
   262  		}
   263  	}
   264  
   265  }
   266  
   267  func TestKeyringMissWithDockerHubCredentials(t *testing.T) {
   268  	url := defaultRegistryHost
   269  	email := "foo@bar.baz"
   270  	username := "foo"
   271  	password := "bar"
   272  	auth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", username, password)))
   273  	sampleDockerConfig := fmt.Sprintf(`{
   274     "https://%s": {
   275       "email": %q,
   276       "auth": %q
   277     }
   278  }`, url, email, auth)
   279  
   280  	keyring := &BasicDockerKeyring{}
   281  	if cfg, err := readDockerConfigFileFromBytes([]byte(sampleDockerConfig)); err != nil {
   282  		t.Errorf("Error processing json blob %q, %v", sampleDockerConfig, err)
   283  	} else {
   284  		keyring.Add(cfg)
   285  	}
   286  
   287  	val, ok := keyring.Lookup("world.mesos.org/foo/bar")
   288  	if ok {
   289  		t.Errorf("Found unexpected credential: %+v", val)
   290  	}
   291  }
   292  
   293  func TestKeyringHitWithUnqualifiedDockerHub(t *testing.T) {
   294  	url := defaultRegistryHost
   295  	email := "foo@bar.baz"
   296  	username := "foo"
   297  	password := "bar"
   298  	auth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", username, password)))
   299  	sampleDockerConfig := fmt.Sprintf(`{
   300     "https://%s": {
   301       "email": %q,
   302       "auth": %q
   303     }
   304  }`, url, email, auth)
   305  
   306  	keyring := &BasicDockerKeyring{}
   307  	if cfg, err := readDockerConfigFileFromBytes([]byte(sampleDockerConfig)); err != nil {
   308  		t.Errorf("Error processing json blob %q, %v", sampleDockerConfig, err)
   309  	} else {
   310  		keyring.Add(cfg)
   311  	}
   312  
   313  	creds, ok := keyring.Lookup("google/docker-registry")
   314  	if !ok {
   315  		t.Errorf("Didn't find expected URL: %s", url)
   316  		return
   317  	}
   318  	if len(creds) > 1 {
   319  		t.Errorf("Got more hits than expected: %s", creds)
   320  	}
   321  	val := creds[0]
   322  
   323  	if username != val.Username {
   324  		t.Errorf("Unexpected username value, want: %s, got: %s", username, val.Username)
   325  	}
   326  	if password != val.Password {
   327  		t.Errorf("Unexpected password value, want: %s, got: %s", password, val.Password)
   328  	}
   329  	if email != val.Email {
   330  		t.Errorf("Unexpected email value, want: %s, got: %s", email, val.Email)
   331  	}
   332  }
   333  
   334  func TestKeyringHitWithUnqualifiedLibraryDockerHub(t *testing.T) {
   335  	url := defaultRegistryHost
   336  	email := "foo@bar.baz"
   337  	username := "foo"
   338  	password := "bar"
   339  	auth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", username, password)))
   340  	sampleDockerConfig := fmt.Sprintf(`{
   341     "https://%s": {
   342       "email": %q,
   343       "auth": %q
   344     }
   345  }`, url, email, auth)
   346  
   347  	keyring := &BasicDockerKeyring{}
   348  	if cfg, err := readDockerConfigFileFromBytes([]byte(sampleDockerConfig)); err != nil {
   349  		t.Errorf("Error processing json blob %q, %v", sampleDockerConfig, err)
   350  	} else {
   351  		keyring.Add(cfg)
   352  	}
   353  
   354  	creds, ok := keyring.Lookup("jenkins")
   355  	if !ok {
   356  		t.Errorf("Didn't find expected URL: %s", url)
   357  		return
   358  	}
   359  	if len(creds) > 1 {
   360  		t.Errorf("Got more hits than expected: %s", creds)
   361  	}
   362  	val := creds[0]
   363  
   364  	if username != val.Username {
   365  		t.Errorf("Unexpected username value, want: %s, got: %s", username, val.Username)
   366  	}
   367  	if password != val.Password {
   368  		t.Errorf("Unexpected password value, want: %s, got: %s", password, val.Password)
   369  	}
   370  	if email != val.Email {
   371  		t.Errorf("Unexpected email value, want: %s, got: %s", email, val.Email)
   372  	}
   373  }
   374  
   375  func TestKeyringHitWithQualifiedDockerHub(t *testing.T) {
   376  	url := defaultRegistryHost
   377  	email := "foo@bar.baz"
   378  	username := "foo"
   379  	password := "bar"
   380  	auth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", username, password)))
   381  	sampleDockerConfig := fmt.Sprintf(`{
   382     "https://%s": {
   383       "email": %q,
   384       "auth": %q
   385     }
   386  }`, url, email, auth)
   387  
   388  	keyring := &BasicDockerKeyring{}
   389  	if cfg, err := readDockerConfigFileFromBytes([]byte(sampleDockerConfig)); err != nil {
   390  		t.Errorf("Error processing json blob %q, %v", sampleDockerConfig, err)
   391  	} else {
   392  		keyring.Add(cfg)
   393  	}
   394  
   395  	creds, ok := keyring.Lookup(url + "/google/docker-registry")
   396  	if !ok {
   397  		t.Errorf("Didn't find expected URL: %s", url)
   398  		return
   399  	}
   400  	if len(creds) > 2 {
   401  		t.Errorf("Got more hits than expected: %s", creds)
   402  	}
   403  	val := creds[0]
   404  
   405  	if username != val.Username {
   406  		t.Errorf("Unexpected username value, want: %s, got: %s", username, val.Username)
   407  	}
   408  	if password != val.Password {
   409  		t.Errorf("Unexpected password value, want: %s, got: %s", password, val.Password)
   410  	}
   411  	if email != val.Email {
   412  		t.Errorf("Unexpected email value, want: %s, got: %s", email, val.Email)
   413  	}
   414  }
   415  
   416  func TestIsDefaultRegistryMatch(t *testing.T) {
   417  	samples := []map[bool]string{
   418  		{true: "foo/bar"},
   419  		{true: "docker.io/foo/bar"},
   420  		{true: "index.docker.io/foo/bar"},
   421  		{true: "foo"},
   422  		{false: ""},
   423  		{false: "registry.tld/foo/bar"},
   424  		{false: "registry:5000/foo/bar"},
   425  		{false: "myhostdocker.io/foo/bar"},
   426  	}
   427  	for _, sample := range samples {
   428  		for expected, imageName := range sample {
   429  			if got := isDefaultRegistryMatch(imageName); got != expected {
   430  				t.Errorf("Expected '%s' to be %t, got %t", imageName, expected, got)
   431  			}
   432  		}
   433  	}
   434  }
   435  
   436  type testProvider struct {
   437  	Count int
   438  }
   439  
   440  // Enabled implements dockerConfigProvider
   441  func (d *testProvider) Enabled() bool {
   442  	return true
   443  }
   444  
   445  // Provide implements dockerConfigProvider
   446  func (d *testProvider) Provide() DockerConfig {
   447  	d.Count += 1
   448  	return DockerConfig{}
   449  }
   450  
   451  func TestLazyKeyring(t *testing.T) {
   452  	provider := &testProvider{
   453  		Count: 0,
   454  	}
   455  	lazy := &lazyDockerKeyring{
   456  		Providers: []DockerConfigProvider{
   457  			provider,
   458  		},
   459  	}
   460  
   461  	if provider.Count != 0 {
   462  		t.Errorf("Unexpected number of Provide calls: %v", provider.Count)
   463  	}
   464  	lazy.Lookup("foo")
   465  	if provider.Count != 1 {
   466  		t.Errorf("Unexpected number of Provide calls: %v", provider.Count)
   467  	}
   468  	lazy.Lookup("foo")
   469  	if provider.Count != 2 {
   470  		t.Errorf("Unexpected number of Provide calls: %v", provider.Count)
   471  	}
   472  	lazy.Lookup("foo")
   473  	if provider.Count != 3 {
   474  		t.Errorf("Unexpected number of Provide calls: %v", provider.Count)
   475  	}
   476  }