...

Source file src/github.com/docker/docker-credential-helpers/wincred/wincred_test.go

Documentation: github.com/docker/docker-credential-helpers/wincred

     1  //go:build windows
     2  
     3  package wincred
     4  
     5  import (
     6  	"fmt"
     7  	"strings"
     8  	"testing"
     9  
    10  	"github.com/docker/docker-credential-helpers/credentials"
    11  )
    12  
    13  func TestWinCredHelper(t *testing.T) {
    14  	creds := &credentials.Credentials{
    15  		ServerURL: "https://foobar.docker.io:2376/v1",
    16  		Username:  "foobar",
    17  		Secret:    "foobarbaz",
    18  	}
    19  	creds1 := &credentials.Credentials{
    20  		ServerURL: "https://foobar.docker.io:2376/v2",
    21  		Username:  "foobarbaz",
    22  		Secret:    "foobar",
    23  	}
    24  
    25  	helper := Wincred{}
    26  
    27  	// check for and remove remaining credentials from previous fail tests
    28  	oldauths, err := helper.List()
    29  	if err != nil {
    30  		t.Fatal(err)
    31  	}
    32  
    33  	for k, v := range oldauths {
    34  		if strings.Compare(k, creds.ServerURL) == 0 && strings.Compare(v, creds.Username) == 0 {
    35  			if err := helper.Delete(creds.ServerURL); err != nil {
    36  				t.Fatal(err)
    37  			}
    38  		} else if strings.Compare(k, creds1.ServerURL) == 0 && strings.Compare(v, creds1.Username) == 0 {
    39  			if err := helper.Delete(creds1.ServerURL); err != nil {
    40  				t.Fatal(err)
    41  			}
    42  		}
    43  	}
    44  
    45  	// recount for credentials
    46  	oldauths, err = helper.List()
    47  	if err != nil {
    48  		t.Fatal(err)
    49  	}
    50  
    51  	if err := helper.Add(creds); err != nil {
    52  		t.Fatal(err)
    53  	}
    54  
    55  	username, secret, err := helper.Get(creds.ServerURL)
    56  	if err != nil {
    57  		t.Fatal(err)
    58  	}
    59  
    60  	if username != "foobar" {
    61  		t.Fatalf("expected %s, got %s\n", "foobar", username)
    62  	}
    63  
    64  	if secret != "foobarbaz" {
    65  		t.Fatalf("expected %s, got %s\n", "foobarbaz", secret)
    66  	}
    67  
    68  	auths, err := helper.List()
    69  	if err != nil || len(auths)-len(oldauths) != 1 {
    70  		t.Fatal(err)
    71  	}
    72  
    73  	helper.Add(creds1)
    74  	defer helper.Delete(creds1.ServerURL)
    75  	newauths, err := helper.List()
    76  	if err != nil {
    77  		t.Fatal(err)
    78  	}
    79  
    80  	if len(newauths)-len(auths) != 1 {
    81  		if err == nil {
    82  			t.Fatalf("Error: len(newauths): %d, len(auths): %d", len(newauths), len(auths))
    83  		}
    84  		t.Fatalf("Error: len(newauths): %d, len(auths): %d\n Error= %v", len(newauths), len(auths), err)
    85  	}
    86  
    87  	if err := helper.Delete(creds.ServerURL); err != nil {
    88  		t.Fatal(err)
    89  	}
    90  }
    91  
    92  // TestWinCredHelperRetrieveAliases verifies that secrets can be accessed
    93  // through variations on the URL
    94  func TestWinCredHelperRetrieveAliases(t *testing.T) {
    95  	tests := []struct {
    96  		doc      string
    97  		storeURL string
    98  		readURL  string
    99  	}{
   100  		{
   101  			doc:      "stored with port, retrieved without",
   102  			storeURL: "https://foobar.docker.io:2376",
   103  			readURL:  "https://foobar.docker.io",
   104  		},
   105  		{
   106  			doc:      "stored as https, retrieved without scheme",
   107  			storeURL: "https://foobar.docker.io",
   108  			readURL:  "foobar.docker.io",
   109  		},
   110  		{
   111  			doc:      "stored with path, retrieved without",
   112  			storeURL: "https://foobar.docker.io/one/two",
   113  			readURL:  "https://foobar.docker.io",
   114  		},
   115  	}
   116  
   117  	helper := Wincred{}
   118  	t.Cleanup(func() {
   119  		for _, tc := range tests {
   120  			if err := helper.Delete(tc.storeURL); err != nil && !credentials.IsErrCredentialsNotFound(err) {
   121  				t.Errorf("cleanup: failed to delete '%s': %v", tc.storeURL, err)
   122  			}
   123  		}
   124  	})
   125  
   126  	// Clean store before testing.
   127  	for _, tc := range tests {
   128  		if err := helper.Delete(tc.storeURL); err != nil && !credentials.IsErrCredentialsNotFound(err) {
   129  			t.Errorf("prepare: failed to delete '%s': %v", tc.storeURL, err)
   130  		}
   131  	}
   132  
   133  	for _, tc := range tests {
   134  		tc := tc
   135  		t.Run(tc.doc, func(t *testing.T) {
   136  			c := &credentials.Credentials{ServerURL: tc.storeURL, Username: "hello", Secret: "world"}
   137  			if err := helper.Add(c); err != nil {
   138  				t.Fatalf("Error: failed to store secret for URL %q: %s", tc.storeURL, err)
   139  			}
   140  			if _, _, err := helper.Get(tc.readURL); err != nil {
   141  				t.Errorf("Error: failed to read secret for URL %q using %q", tc.storeURL, tc.readURL)
   142  			}
   143  			if err := helper.Delete(tc.storeURL); err != nil {
   144  				t.Error(err)
   145  			}
   146  		})
   147  	}
   148  }
   149  
   150  // TestWinCredHelperRetrieveStrict verifies that only matching secrets are
   151  // returned.
   152  func TestWinCredHelperRetrieveStrict(t *testing.T) {
   153  	tests := []struct {
   154  		doc      string
   155  		storeURL string
   156  		readURL  string
   157  	}{
   158  		{
   159  			doc:      "stored as https, retrieved using http",
   160  			storeURL: "https://foobar.docker.io:2376",
   161  			readURL:  "http://foobar.docker.io:2376",
   162  		},
   163  		{
   164  			doc:      "stored as http, retrieved using https",
   165  			storeURL: "http://foobar.docker.io:2376",
   166  			readURL:  "https://foobar.docker.io:2376",
   167  		},
   168  		{
   169  			// stored as http, retrieved without a scheme specified (hence, using the default https://)
   170  			doc:      "stored as http, retrieved without scheme",
   171  			storeURL: "http://foobar.docker.io",
   172  			readURL:  "foobar.docker.io:5678",
   173  		},
   174  		{
   175  			doc:      "non-matching ports",
   176  			storeURL: "https://foobar.docker.io:1234",
   177  			readURL:  "https://foobar.docker.io:5678",
   178  		},
   179  		// TODO: is this desired behavior? The other way round does work
   180  		// {
   181  		// 	doc:      "non-matching ports (stored without port)",
   182  		// 	storeURL: "https://foobar.docker.io",
   183  		// 	readURL:  "https://foobar.docker.io:5678",
   184  		// },
   185  		{
   186  			doc:      "non-matching paths",
   187  			storeURL: "https://foobar.docker.io:1234/one/two",
   188  			readURL:  "https://foobar.docker.io:1234/five/six",
   189  		},
   190  	}
   191  
   192  	helper := Wincred{}
   193  	t.Cleanup(func() {
   194  		for _, tc := range tests {
   195  			if err := helper.Delete(tc.storeURL); err != nil && !credentials.IsErrCredentialsNotFound(err) {
   196  				t.Errorf("cleanup: failed to delete '%s': %v", tc.storeURL, err)
   197  			}
   198  		}
   199  	})
   200  
   201  	// Clean store before testing.
   202  	for _, tc := range tests {
   203  		if err := helper.Delete(tc.storeURL); err != nil && !credentials.IsErrCredentialsNotFound(err) {
   204  			t.Errorf("prepare: failed to delete '%s': %v", tc.storeURL, err)
   205  		}
   206  	}
   207  
   208  	for _, tc := range tests {
   209  		tc := tc
   210  		t.Run(tc.doc, func(t *testing.T) {
   211  			c := &credentials.Credentials{ServerURL: tc.storeURL, Username: "hello", Secret: "world"}
   212  			if err := helper.Add(c); err != nil {
   213  				t.Fatalf("Error: failed to store secret for URL %q: %s", tc.storeURL, err)
   214  			}
   215  			if _, _, err := helper.Get(tc.readURL); err == nil {
   216  				t.Errorf("Error: managed to read secret for URL %q using %q, but should not be able to", tc.storeURL, tc.readURL)
   217  			}
   218  			if err := helper.Delete(tc.storeURL); err != nil {
   219  				t.Error(err)
   220  			}
   221  		})
   222  	}
   223  }
   224  
   225  // TestWinCredHelperStoreRetrieve verifies that secrets stored in the
   226  // the keychain can be read back using the URL that was used to store them.
   227  func TestWinCredHelperStoreRetrieve(t *testing.T) {
   228  	tests := []struct {
   229  		url string
   230  	}{
   231  		{url: "foobar.docker.io"},
   232  		{url: "foobar.docker.io:2376"},
   233  		{url: "//foobar.docker.io:2376"},
   234  		{url: "https://foobar.docker.io:2376"},
   235  		{url: "http://foobar.docker.io:2376"},
   236  		{url: "https://foobar.docker.io:2376/some/path"},
   237  		{url: "https://foobar.docker.io:2376/some/other/path"},
   238  		{url: "https://foobar.docker.io:2376/some/other/path?foo=bar"},
   239  	}
   240  
   241  	helper := Wincred{}
   242  	t.Cleanup(func() {
   243  		for _, tc := range tests {
   244  			if err := helper.Delete(tc.url); err != nil && !credentials.IsErrCredentialsNotFound(err) {
   245  				t.Errorf("cleanup: failed to delete '%s': %v", tc.url, err)
   246  			}
   247  		}
   248  	})
   249  
   250  	// Clean store before testing.
   251  	for _, tc := range tests {
   252  		if err := helper.Delete(tc.url); err != nil && !credentials.IsErrCredentialsNotFound(err) {
   253  			t.Errorf("prepare: failed to delete '%s': %v", tc.url, err)
   254  		}
   255  	}
   256  
   257  	// Note that we don't delete between individual tests here, to verify that
   258  	// subsequent stores/overwrites don't affect storing / retrieving secrets.
   259  	for i, tc := range tests {
   260  		tc := tc
   261  		t.Run(tc.url, func(t *testing.T) {
   262  			c := &credentials.Credentials{
   263  				ServerURL: tc.url,
   264  				Username:  fmt.Sprintf("user-%d", i),
   265  				Secret:    fmt.Sprintf("secret-%d", i),
   266  			}
   267  
   268  			if err := helper.Add(c); err != nil {
   269  				t.Fatalf("Error: failed to store secret for URL: %s: %s", tc.url, err)
   270  			}
   271  			user, secret, err := helper.Get(tc.url)
   272  			if err != nil {
   273  				t.Fatalf("Error: failed to read secret for URL %q: %s", tc.url, err)
   274  			}
   275  			if user != c.Username {
   276  				t.Errorf("Error: expected username %s, got username %s for URL: %s", c.Username, user, tc.url)
   277  			}
   278  			if secret != c.Secret {
   279  				t.Errorf("Error: expected secret %s, got secret %s for URL: %s", c.Secret, secret, tc.url)
   280  			}
   281  		})
   282  	}
   283  }
   284  
   285  func TestMissingCredentials(t *testing.T) {
   286  	helper := Wincred{}
   287  	_, _, err := helper.Get("https://adsfasdf.wrewerwer.com/asdfsdddd")
   288  	if !credentials.IsErrCredentialsNotFound(err) {
   289  		t.Fatalf("expected ErrCredentialsNotFound, got %v", err)
   290  	}
   291  }
   292  

View as plain text