1
2
3 package osxkeychain
4
5 import (
6 "fmt"
7 "testing"
8
9 "github.com/docker/docker-credential-helpers/credentials"
10 )
11
12 func TestOSXKeychainHelper(t *testing.T) {
13 creds := &credentials.Credentials{
14 ServerURL: "https://foobar.example.com:2376/v1",
15 Username: "foobar",
16 Secret: "foobarbaz",
17 }
18 creds1 := &credentials.Credentials{
19 ServerURL: "https://foobar.example.com:2376/v2",
20 Username: "foobarbaz",
21 Secret: "foobar",
22 }
23 helper := Osxkeychain{}
24 if err := helper.Add(creds); err != nil {
25 t.Fatal(err)
26 }
27
28 username, secret, err := helper.Get(creds.ServerURL)
29 if err != nil {
30 t.Fatal(err)
31 }
32
33 if username != "foobar" {
34 t.Fatalf("expected %s, got %s\n", "foobar", username)
35 }
36
37 if secret != "foobarbaz" {
38 t.Fatalf("expected %s, got %s\n", "foobarbaz", secret)
39 }
40
41 auths, err := helper.List()
42 if err != nil || len(auths) == 0 {
43 t.Fatal(err)
44 }
45
46 helper.Add(creds1)
47 defer helper.Delete(creds1.ServerURL)
48 newauths, err := helper.List()
49 if len(newauths)-len(auths) != 1 {
50 if err == nil {
51 t.Fatalf("Error: len(newauths): %d, len(auths): %d", len(newauths), len(auths))
52 }
53 t.Fatalf("Error: len(newauths): %d, len(auths): %d\n Error= %v", len(newauths), len(auths), err)
54 }
55
56 if err := helper.Delete(creds.ServerURL); err != nil {
57 t.Fatal(err)
58 }
59 }
60
61
62
63 func TestOSXKeychainHelperRetrieveAliases(t *testing.T) {
64 tests := []struct {
65 doc string
66 storeURL string
67 readURL string
68 }{
69 {
70 doc: "stored with port, retrieved without",
71 storeURL: "https://foobar.example.com:2376",
72 readURL: "https://foobar.example.com",
73 },
74 {
75 doc: "stored as https, retrieved without scheme",
76 storeURL: "https://foobar.example.com:2376",
77 readURL: "foobar.example.com",
78 },
79 {
80 doc: "stored with path, retrieved without",
81 storeURL: "https://foobar.example.com:1234/one/two",
82 readURL: "https://foobar.example.com:1234",
83 },
84 }
85
86 helper := Osxkeychain{}
87 t.Cleanup(func() {
88 for _, tc := range tests {
89 if err := helper.Delete(tc.storeURL); err != nil && !credentials.IsErrCredentialsNotFound(err) {
90 t.Errorf("cleanup: failed to delete '%s': %v", tc.storeURL, err)
91 }
92 }
93 })
94
95
96 for _, tc := range tests {
97 if err := helper.Delete(tc.storeURL); err != nil && !credentials.IsErrCredentialsNotFound(err) {
98 t.Errorf("prepare: failed to delete '%s': %v", tc.storeURL, err)
99 }
100 }
101
102 for _, tc := range tests {
103 tc := tc
104 t.Run(tc.doc, func(t *testing.T) {
105 c := &credentials.Credentials{ServerURL: tc.storeURL, Username: "hello", Secret: "world"}
106 if err := helper.Add(c); err != nil {
107 t.Fatalf("Error: failed to store secret for URL %q: %s", tc.storeURL, err)
108 }
109 if _, _, err := helper.Get(tc.readURL); err != nil {
110 t.Errorf("Error: failed to read secret for URL %q using %q", tc.storeURL, tc.readURL)
111 }
112 if err := helper.Delete(tc.storeURL); err != nil {
113 t.Error(err)
114 }
115 })
116 }
117 }
118
119
120
121 func TestOSXKeychainHelperRetrieveStrict(t *testing.T) {
122 tests := []struct {
123 doc string
124 storeURL string
125 readURL string
126 }{
127 {
128 doc: "stored as https, retrieved using http",
129 storeURL: "https://foobar.example.com:2376",
130 readURL: "http://foobar.example.com:2376",
131 },
132 {
133 doc: "stored as http, retrieved using https",
134 storeURL: "http://foobar.example.com:2376",
135 readURL: "https://foobar.example.com:2376",
136 },
137 {
138
139 doc: "stored as http, retrieved without scheme",
140 storeURL: "http://foobar.example.com",
141 readURL: "foobar.example.com:5678",
142 },
143 {
144 doc: "non-matching ports",
145 storeURL: "https://foobar.example.com:1234",
146 readURL: "https://foobar.example.com:5678",
147 },
148
149
150
151
152
153
154 {
155 doc: "non-matching paths",
156 storeURL: "https://foobar.example.com:1234/one/two",
157 readURL: "https://foobar.example.com:1234/five/six",
158 },
159 }
160
161 helper := Osxkeychain{}
162 t.Cleanup(func() {
163 for _, tc := range tests {
164 if err := helper.Delete(tc.storeURL); err != nil && !credentials.IsErrCredentialsNotFound(err) {
165 t.Errorf("cleanup: failed to delete '%s': %v", tc.storeURL, err)
166 }
167 }
168 })
169
170
171 for _, tc := range tests {
172 if err := helper.Delete(tc.storeURL); err != nil && !credentials.IsErrCredentialsNotFound(err) {
173 t.Errorf("prepare: failed to delete '%s': %v", tc.storeURL, err)
174 }
175 }
176
177 for _, tc := range tests {
178 tc := tc
179 t.Run(tc.doc, func(t *testing.T) {
180 c := &credentials.Credentials{ServerURL: tc.storeURL, Username: "hello", Secret: "world"}
181 if err := helper.Add(c); err != nil {
182 t.Fatalf("Error: failed to store secret for URL %q: %s", tc.storeURL, err)
183 }
184 if _, _, err := helper.Get(tc.readURL); err == nil {
185 t.Errorf("Error: managed to read secret for URL %q using %q, but should not be able to", tc.storeURL, tc.readURL)
186 }
187 if err := helper.Delete(tc.storeURL); err != nil {
188 t.Error(err)
189 }
190 })
191 }
192 }
193
194
195
196 func TestOSXKeychainHelperStoreRetrieve(t *testing.T) {
197 tests := []struct {
198 url string
199 }{
200 {url: "foobar.example.com"},
201 {url: "foobar.example.com:2376"},
202 {url: "//foobar.example.com:2376"},
203 {url: "https://foobar.example.com:2376"},
204 {url: "http://foobar.example.com:2376"},
205 {url: "https://foobar.example.com:2376/some/path"},
206 {url: "https://foobar.example.com:2376/some/other/path"},
207 {url: "https://foobar.example.com:2376/some/other/path?foo=bar"},
208 }
209
210 helper := Osxkeychain{}
211 t.Cleanup(func() {
212 for _, tc := range tests {
213 if err := helper.Delete(tc.url); err != nil && !credentials.IsErrCredentialsNotFound(err) {
214 t.Errorf("cleanup: failed to delete '%s': %v", tc.url, err)
215 }
216 }
217 })
218
219
220 for _, tc := range tests {
221 if err := helper.Delete(tc.url); err != nil && !credentials.IsErrCredentialsNotFound(err) {
222 t.Errorf("prepare: failed to delete '%s': %v", tc.url, err)
223 }
224 }
225
226
227
228 for i, tc := range tests {
229 tc := tc
230 t.Run(tc.url, func(t *testing.T) {
231 c := &credentials.Credentials{
232 ServerURL: tc.url,
233 Username: fmt.Sprintf("user-%d", i),
234 Secret: fmt.Sprintf("secret-%d", i),
235 }
236
237 if err := helper.Add(c); err != nil {
238 t.Fatalf("Error: failed to store secret for URL: %s: %s", tc.url, err)
239 }
240 user, secret, err := helper.Get(tc.url)
241 if err != nil {
242 t.Fatalf("Error: failed to read secret for URL %q: %s", tc.url, err)
243 }
244 if user != c.Username {
245 t.Errorf("Error: expected username %s, got username %s for URL: %s", c.Username, user, tc.url)
246 }
247 if secret != c.Secret {
248 t.Errorf("Error: expected secret %s, got secret %s for URL: %s", c.Secret, secret, tc.url)
249 }
250 })
251 }
252 }
253
254 func TestMissingCredentials(t *testing.T) {
255 const nonExistingCred = "https://adsfasdf.invalid/asdfsdddd"
256 helper := Osxkeychain{}
257 _, _, err := helper.Get(nonExistingCred)
258 if !credentials.IsErrCredentialsNotFound(err) {
259 t.Errorf("expected ErrCredentialsNotFound, got %v", err)
260 }
261 err = helper.Delete(nonExistingCred)
262 if !credentials.IsErrCredentialsNotFound(err) {
263 t.Errorf("expected ErrCredentialsNotFound, got %v", err)
264 }
265 }
266
View as plain text