...

Source file src/k8s.io/kubernetes/pkg/credentialprovider/config_test.go

Documentation: k8s.io/kubernetes/pkg/credentialprovider

     1  /*
     2  Copyright 2014 The Kubernetes Authors.
     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  	"encoding/json"
    22  	"os"
    23  	"path/filepath"
    24  	"reflect"
    25  	"testing"
    26  )
    27  
    28  func TestReadDockerConfigFile(t *testing.T) {
    29  	configJSONFileName := "config.json"
    30  	var fileInfo *os.File
    31  
    32  	//test dockerconfig json
    33  	inputDockerconfigJSONFile := "{ \"auths\": { \"http://foo.example.com\":{\"auth\":\"Zm9vOmJhcgo=\",\"email\":\"foo@example.com\"}}}"
    34  
    35  	preferredPath, err := os.MkdirTemp("", "test_foo_bar_dockerconfigjson_")
    36  	if err != nil {
    37  		t.Fatalf("Creating tmp dir fail: %v", err)
    38  		return
    39  	}
    40  	defer os.RemoveAll(preferredPath)
    41  	absDockerConfigFileLocation, err := filepath.Abs(filepath.Join(preferredPath, configJSONFileName))
    42  	if err != nil {
    43  		t.Fatalf("While trying to canonicalize %s: %v", preferredPath, err)
    44  	}
    45  
    46  	if _, err := os.Stat(absDockerConfigFileLocation); os.IsNotExist(err) {
    47  		//create test cfg file
    48  		fileInfo, err = os.OpenFile(absDockerConfigFileLocation, os.O_CREATE|os.O_RDWR, 0664)
    49  		if err != nil {
    50  			t.Fatalf("While trying to create file %s: %v", absDockerConfigFileLocation, err)
    51  		}
    52  		defer fileInfo.Close()
    53  	}
    54  
    55  	fileInfo.WriteString(inputDockerconfigJSONFile)
    56  
    57  	orgPreferredPath := GetPreferredDockercfgPath()
    58  	SetPreferredDockercfgPath(preferredPath)
    59  	defer SetPreferredDockercfgPath(orgPreferredPath)
    60  	if _, err := ReadDockerConfigFile(); err != nil {
    61  		t.Errorf("Getting docker config file fail : %v preferredPath : %q", err, preferredPath)
    62  	}
    63  }
    64  func TestDockerConfigJsonJSONDecode(t *testing.T) {
    65  	// Fake values for testing.
    66  	input := []byte(`{"auths": {"http://foo.example.com":{"username": "foo", "password": "bar", "email": "foo@example.com"}, "http://bar.example.com":{"username": "bar", "password": "baz", "email": "bar@example.com"}}}`)
    67  
    68  	expect := DockerConfigJSON{
    69  		Auths: DockerConfig(map[string]DockerConfigEntry{
    70  			"http://foo.example.com": {
    71  				Username: "foo",
    72  				Password: "bar",
    73  				Email:    "foo@example.com",
    74  			},
    75  			"http://bar.example.com": {
    76  				Username: "bar",
    77  				Password: "baz",
    78  				Email:    "bar@example.com",
    79  			},
    80  		}),
    81  	}
    82  
    83  	var output DockerConfigJSON
    84  	err := json.Unmarshal(input, &output)
    85  	if err != nil {
    86  		t.Errorf("Received unexpected error: %v", err)
    87  	}
    88  
    89  	if !reflect.DeepEqual(expect, output) {
    90  		t.Errorf("Received unexpected output. Expected %#v, got %#v", expect, output)
    91  	}
    92  }
    93  
    94  func TestDockerConfigJSONDecode(t *testing.T) {
    95  	// Fake values for testing.
    96  	input := []byte(`{"http://foo.example.com":{"username": "foo", "password": "bar", "email": "foo@example.com"}, "http://bar.example.com":{"username": "bar", "password": "baz", "email": "bar@example.com"}}`)
    97  
    98  	expect := DockerConfig(map[string]DockerConfigEntry{
    99  		"http://foo.example.com": {
   100  			Username: "foo",
   101  			Password: "bar",
   102  			Email:    "foo@example.com",
   103  		},
   104  		"http://bar.example.com": {
   105  			Username: "bar",
   106  			Password: "baz",
   107  			Email:    "bar@example.com",
   108  		},
   109  	})
   110  
   111  	var output DockerConfig
   112  	err := json.Unmarshal(input, &output)
   113  	if err != nil {
   114  		t.Errorf("Received unexpected error: %v", err)
   115  	}
   116  
   117  	if !reflect.DeepEqual(expect, output) {
   118  		t.Errorf("Received unexpected output. Expected %#v, got %#v", expect, output)
   119  	}
   120  }
   121  
   122  func TestDockerConfigEntryJSONDecode(t *testing.T) {
   123  	tests := []struct {
   124  		input  []byte
   125  		expect DockerConfigEntry
   126  		fail   bool
   127  	}{
   128  		// simple case, just decode the fields
   129  		{
   130  			// Fake values for testing.
   131  			input: []byte(`{"username": "foo", "password": "bar", "email": "foo@example.com"}`),
   132  			expect: DockerConfigEntry{
   133  				Username: "foo",
   134  				Password: "bar",
   135  				Email:    "foo@example.com",
   136  			},
   137  			fail: false,
   138  		},
   139  
   140  		// auth field decodes to username & password
   141  		{
   142  			input: []byte(`{"auth": "Zm9vOmJhcg==", "email": "foo@example.com"}`),
   143  			expect: DockerConfigEntry{
   144  				Username: "foo",
   145  				Password: "bar",
   146  				Email:    "foo@example.com",
   147  			},
   148  			fail: false,
   149  		},
   150  
   151  		// auth field overrides username & password
   152  		{
   153  			// Fake values for testing.
   154  			input: []byte(`{"username": "foo", "password": "bar", "auth": "cGluZzpwb25n", "email": "foo@example.com"}`),
   155  			expect: DockerConfigEntry{
   156  				Username: "ping",
   157  				Password: "pong",
   158  				Email:    "foo@example.com",
   159  			},
   160  			fail: false,
   161  		},
   162  
   163  		// poorly-formatted auth causes failure
   164  		{
   165  			input: []byte(`{"auth": "pants", "email": "foo@example.com"}`),
   166  			expect: DockerConfigEntry{
   167  				Username: "",
   168  				Password: "",
   169  				Email:    "foo@example.com",
   170  			},
   171  			fail: true,
   172  		},
   173  
   174  		// invalid JSON causes failure
   175  		{
   176  			input: []byte(`{"email": false}`),
   177  			expect: DockerConfigEntry{
   178  				Username: "",
   179  				Password: "",
   180  				Email:    "",
   181  			},
   182  			fail: true,
   183  		},
   184  	}
   185  
   186  	for i, tt := range tests {
   187  		var output DockerConfigEntry
   188  		err := json.Unmarshal(tt.input, &output)
   189  		if (err != nil) != tt.fail {
   190  			t.Errorf("case %d: expected fail=%t, got err=%v", i, tt.fail, err)
   191  		}
   192  
   193  		if !reflect.DeepEqual(tt.expect, output) {
   194  			t.Errorf("case %d: expected output %#v, got %#v", i, tt.expect, output)
   195  		}
   196  	}
   197  }
   198  
   199  func TestDecodeDockerConfigFieldAuth(t *testing.T) {
   200  	tests := []struct {
   201  		input    string
   202  		username string
   203  		password string
   204  		fail     bool
   205  	}{
   206  		// auth field decodes to username & password
   207  		{
   208  			input:    "Zm9vOmJhcg==",
   209  			username: "foo",
   210  			password: "bar",
   211  		},
   212  
   213  		// some test as before but with field not well padded
   214  		{
   215  			input:    "Zm9vOmJhcg",
   216  			username: "foo",
   217  			password: "bar",
   218  		},
   219  
   220  		// some test as before but with new line characters
   221  		{
   222  			input:    "Zm9vOm\nJhcg==\n",
   223  			username: "foo",
   224  			password: "bar",
   225  		},
   226  
   227  		// standard encoding (with padding)
   228  		{
   229  			input:    base64.StdEncoding.EncodeToString([]byte("foo:bar")),
   230  			username: "foo",
   231  			password: "bar",
   232  		},
   233  
   234  		// raw encoding (without padding)
   235  		{
   236  			input:    base64.RawStdEncoding.EncodeToString([]byte("foo:bar")),
   237  			username: "foo",
   238  			password: "bar",
   239  		},
   240  
   241  		// the input is encoded with encodeDockerConfigFieldAuth (standard encoding)
   242  		{
   243  			input:    encodeDockerConfigFieldAuth("foo", "bar"),
   244  			username: "foo",
   245  			password: "bar",
   246  		},
   247  
   248  		// good base64 data, but no colon separating username & password
   249  		{
   250  			input: "cGFudHM=",
   251  			fail:  true,
   252  		},
   253  
   254  		// only new line characters are ignored
   255  		{
   256  			input: "Zm9vOmJhcg== ",
   257  			fail:  true,
   258  		},
   259  
   260  		// bad base64 data
   261  		{
   262  			input: "pants",
   263  			fail:  true,
   264  		},
   265  	}
   266  
   267  	for i, tt := range tests {
   268  		username, password, err := decodeDockerConfigFieldAuth(tt.input)
   269  		if (err != nil) != tt.fail {
   270  			t.Errorf("case %d: expected fail=%t, got err=%v", i, tt.fail, err)
   271  		}
   272  
   273  		if tt.username != username {
   274  			t.Errorf("case %d: expected username %q, got %q", i, tt.username, username)
   275  		}
   276  
   277  		if tt.password != password {
   278  			t.Errorf("case %d: expected password %q, got %q", i, tt.password, password)
   279  		}
   280  	}
   281  }
   282  
   283  func TestDockerConfigEntryJSONCompatibleEncode(t *testing.T) {
   284  	tests := []struct {
   285  		input  DockerConfigEntry
   286  		expect []byte
   287  	}{
   288  		// simple case, just decode the fields
   289  		{
   290  			// Fake values for testing.
   291  			expect: []byte(`{"username":"foo","password":"bar","email":"foo@example.com","auth":"Zm9vOmJhcg=="}`),
   292  			input: DockerConfigEntry{
   293  				Username: "foo",
   294  				Password: "bar",
   295  				Email:    "foo@example.com",
   296  			},
   297  		},
   298  	}
   299  
   300  	for i, tt := range tests {
   301  		actual, err := json.Marshal(tt.input)
   302  		if err != nil {
   303  			t.Errorf("case %d: unexpected error: %v", i, err)
   304  		}
   305  
   306  		if string(tt.expect) != string(actual) {
   307  			t.Errorf("case %d: expected %v, got %v", i, string(tt.expect), string(actual))
   308  		}
   309  	}
   310  }
   311  
   312  func TestReadDockerConfigFileFromBytes(t *testing.T) {
   313  	testCases := []struct {
   314  		id               string
   315  		input            []byte
   316  		expectedCfg      DockerConfig
   317  		errorExpected    bool
   318  		expectedErrorMsg string
   319  	}{
   320  		{
   321  			id:    "valid input, no error expected",
   322  			input: []byte(`{"http://foo.example.com":{"username": "foo", "password": "bar", "email": "foo@example.com"}}`),
   323  			expectedCfg: DockerConfig(map[string]DockerConfigEntry{
   324  				"http://foo.example.com": {
   325  					Username: "foo",
   326  					Password: "bar",
   327  					Email:    "foo@example.com",
   328  				},
   329  			}),
   330  		},
   331  		{
   332  			id:               "invalid input, error expected",
   333  			input:            []byte(`{"http://foo.example.com":{"username": "foo", "password": "bar", "email": "foo@example.com"`),
   334  			errorExpected:    true,
   335  			expectedErrorMsg: "error occurred while trying to unmarshal json",
   336  		},
   337  	}
   338  
   339  	for _, tc := range testCases {
   340  		cfg, err := ReadDockerConfigFileFromBytes(tc.input)
   341  		if err != nil && !tc.errorExpected {
   342  			t.Fatalf("Error was not expected: %v", err)
   343  		}
   344  		if err != nil && tc.errorExpected {
   345  			if !reflect.DeepEqual(err.Error(), tc.expectedErrorMsg) {
   346  				t.Fatalf("Expected error message: `%s` got `%s`", tc.expectedErrorMsg, err.Error())
   347  			}
   348  		} else {
   349  			if !reflect.DeepEqual(cfg, tc.expectedCfg) {
   350  				t.Fatalf("expected: %v got %v", tc.expectedCfg, cfg)
   351  			}
   352  		}
   353  	}
   354  }
   355  
   356  func TestReadDockerConfigJSONFileFromBytes(t *testing.T) {
   357  	testCases := []struct {
   358  		id               string
   359  		input            []byte
   360  		expectedCfg      DockerConfig
   361  		errorExpected    bool
   362  		expectedErrorMsg string
   363  	}{
   364  		{
   365  			id:    "valid input, no error expected",
   366  			input: []byte(`{"auths": {"http://foo.example.com":{"username": "foo", "password": "bar", "email": "foo@example.com"}, "http://bar.example.com":{"username": "bar", "password": "baz", "email": "bar@example.com"}}}`),
   367  			expectedCfg: DockerConfig(map[string]DockerConfigEntry{
   368  				"http://foo.example.com": {
   369  					Username: "foo",
   370  					Password: "bar",
   371  					Email:    "foo@example.com",
   372  				},
   373  				"http://bar.example.com": {
   374  					Username: "bar",
   375  					Password: "baz",
   376  					Email:    "bar@example.com",
   377  				},
   378  			}),
   379  		},
   380  		{
   381  			id:               "invalid input, error expected",
   382  			input:            []byte(`{"auths": {"http://foo.example.com":{"username": "foo", "password": "bar", "email": "foo@example.com"}, "http://bar.example.com":{"username": "bar", "password": "baz", "email": "bar@example.com"`),
   383  			errorExpected:    true,
   384  			expectedErrorMsg: "error occurred while trying to unmarshal json",
   385  		},
   386  	}
   387  
   388  	for _, tc := range testCases {
   389  		cfg, err := readDockerConfigJSONFileFromBytes(tc.input)
   390  		if err != nil && !tc.errorExpected {
   391  			t.Fatalf("Error was not expected: %v", err)
   392  		}
   393  		if err != nil && tc.errorExpected {
   394  			if !reflect.DeepEqual(err.Error(), tc.expectedErrorMsg) {
   395  				t.Fatalf("Expected error message: `%s` got `%s`", tc.expectedErrorMsg, err.Error())
   396  			}
   397  		} else {
   398  			if !reflect.DeepEqual(cfg, tc.expectedCfg) {
   399  				t.Fatalf("expected: %v got %v", tc.expectedCfg, cfg)
   400  			}
   401  		}
   402  	}
   403  }
   404  

View as plain text