access_test.go

  1package config
  2
  3import (
  4	"os"
  5	"testing"
  6
  7	"github.com/charmbracelet/soft-serve/proto"
  8	"github.com/gliderlabs/ssh"
  9	"github.com/matryer/is"
 10)
 11
 12func TestAuth(t *testing.T) {
 13	is := is.New(t)
 14	adminKey := "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINMwLvyV3ouVrTysUYGoJdl5Vgn5BACKov+n9PlzfPwH a@b"
 15	adminPk, _, _, _, _ := ssh.ParseAuthorizedKey([]byte(adminKey))
 16	dummyKey := "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFxIobhwtfdwN7m1TFt9wx3PsfvcAkISGPxmbmbauST8 a@b"
 17	dummyPk, _, _, _, _ := ssh.ParseAuthorizedKey([]byte(dummyKey))
 18	dp := t.TempDir()
 19	is.NoErr(os.Setenv("SOFT_SERVE_INITIAL_ADMIN_KEY", adminKey))
 20	is.NoErr(os.Setenv("SOFT_SERVE_DATA_PATH", dp))
 21	t.Cleanup(func() {
 22		is.NoErr(os.Unsetenv("SOFT_SERVE_INITIAL_ADMIN_KEY"))
 23		is.NoErr(os.Unsetenv("SOFT_SERVE_DATA_PATH"))
 24		is.NoErr(os.RemoveAll(dp))
 25	})
 26	cfg := DefaultConfig()
 27	cases := []struct {
 28		name           string
 29		repo           string
 30		key            ssh.PublicKey
 31		anonAccess     proto.AccessLevel
 32		expectedAccess proto.AccessLevel
 33	}{
 34		// Repo access
 35		{
 36			name:           "anon access: no-access, anonymous user",
 37			anonAccess:     proto.NoAccess,
 38			expectedAccess: proto.NoAccess,
 39			repo:           "foo",
 40		},
 41		{
 42			name:           "anon access: no-access, anonymous user with admin user",
 43			expectedAccess: proto.NoAccess,
 44			anonAccess:     proto.NoAccess,
 45			repo:           "foo",
 46		},
 47		{
 48			name:           "anon access: no-access, authd user",
 49			key:            dummyPk,
 50			repo:           "foo",
 51			anonAccess:     proto.NoAccess,
 52			expectedAccess: proto.ReadOnlyAccess,
 53		},
 54		{
 55			name:           "anon access: no-access, admin user",
 56			repo:           "foo",
 57			key:            adminPk,
 58			anonAccess:     proto.NoAccess,
 59			expectedAccess: proto.AdminAccess,
 60		},
 61		{
 62			name:           "anon access: read-only, anonymous user",
 63			repo:           "foo",
 64			anonAccess:     proto.ReadOnlyAccess,
 65			expectedAccess: proto.ReadOnlyAccess,
 66		},
 67		{
 68			name:           "anon access: read-only, authd user",
 69			repo:           "foo",
 70			key:            dummyPk,
 71			anonAccess:     proto.ReadOnlyAccess,
 72			expectedAccess: proto.ReadOnlyAccess,
 73		},
 74		{
 75			name:           "anon access: read-only, admin user",
 76			repo:           "foo",
 77			key:            adminPk,
 78			anonAccess:     proto.ReadOnlyAccess,
 79			expectedAccess: proto.AdminAccess,
 80		},
 81		{
 82			name:           "anon access: read-write, anonymous user",
 83			repo:           "foo",
 84			anonAccess:     proto.ReadWriteAccess,
 85			expectedAccess: proto.ReadWriteAccess,
 86		},
 87		{
 88			name:           "anon access: read-write, authd user",
 89			repo:           "foo",
 90			key:            dummyPk,
 91			anonAccess:     proto.ReadWriteAccess,
 92			expectedAccess: proto.ReadWriteAccess,
 93		},
 94		{
 95			name:           "anon access: read-write, admin user",
 96			repo:           "foo",
 97			key:            adminPk,
 98			anonAccess:     proto.ReadWriteAccess,
 99			expectedAccess: proto.AdminAccess,
100		},
101		{
102			name:           "anon access: admin-access, anonymous user",
103			repo:           "foo",
104			anonAccess:     proto.AdminAccess,
105			expectedAccess: proto.AdminAccess,
106		},
107		{
108			name:           "anon access: admin-access, authd user",
109			repo:           "foo",
110			key:            dummyPk,
111			anonAccess:     proto.AdminAccess,
112			expectedAccess: proto.AdminAccess,
113		},
114		{
115			name:           "anon access: admin-access, admin user",
116			repo:           "foo",
117			key:            adminPk,
118			anonAccess:     proto.AdminAccess,
119			expectedAccess: proto.AdminAccess,
120		},
121
122		// TODO: fix this
123		// // Collabs
124		// {
125		// 	name:           "anon access: no-access, authd user, collab",
126		// 	key:            dummyPk,
127		// 	repo:           "foo",
128		// 	expectedAccess: proto.ReadWriteAccess,
129		// 	cfg: Config{
130		// 		AnonAccess: "no-access",
131		// 		Repos: []RepoConfig{
132		// 			{
133		// 				Repo: "foo",
134		// 				Collabs: []string{
135		// 					"user",
136		// 				},
137		// 			},
138		// 		},
139		// 		Users: []User{
140		// 			{
141		// 				Name: "user",
142		// 				PublicKeys: []string{
143		// 					dummyKey,
144		// 				},
145		// 			},
146		// 		},
147		// 	},
148		// },
149		// {
150		// 	name:           "anon access: no-access, authd user, collab, private repo",
151		// 	key:            dummyPk,
152		// 	repo:           "foo",
153		// 	expectedAccess: proto.ReadWriteAccess,
154		// 	cfg: Config{
155		// 		AnonAccess: "no-access",
156		// 		Repos: []RepoConfig{
157		// 			{
158		// 				Repo:    "foo",
159		// 				Private: true,
160		// 				Collabs: []string{
161		// 					"user",
162		// 				},
163		// 			},
164		// 		},
165		// 		Users: []User{
166		// 			{
167		// 				Name: "user",
168		// 				PublicKeys: []string{
169		// 					dummyKey,
170		// 				},
171		// 			},
172		// 		},
173		// 	},
174		// },
175		// {
176		// 	name:           "anon access: no-access, admin user, collab, private repo",
177		// 	repo:           "foo",
178		// 	key:            adminPk,
179		// 	expectedAccess: proto.AdminAccess,
180		// 	cfg: Config{
181		// 		AnonAccess: "no-access",
182		// 		Repos: []RepoConfig{
183		// 			{
184		// 				Repo:    "foo",
185		// 				Private: true,
186		// 				Collabs: []string{
187		// 					"user",
188		// 				},
189		// 			},
190		// 		},
191		// 		Users: []User{
192		// 			{
193		// 				Name:  "admin",
194		// 				Admin: true,
195		// 				PublicKeys: []string{
196		// 					adminKey,
197		// 				},
198		// 			},
199		// 		},
200		// 	},
201		// },
202		// {
203		// 	name:           "anon access: read-only, authd user, collab, private repo",
204		// 	repo:           "foo",
205		// 	key:            dummyPk,
206		// 	expectedAccess: proto.ReadWriteAccess,
207		// 	cfg: Config{
208		// 		AnonAccess: "read-only",
209		// 		Repos: []RepoConfig{
210		// 			{
211		// 				Repo:    "foo",
212		// 				Private: true,
213		// 				Collabs: []string{
214		// 					"user",
215		// 				},
216		// 			},
217		// 		},
218		// 		Users: []User{
219		// 			{
220		// 				Name: "user",
221		// 				PublicKeys: []string{
222		// 					dummyKey,
223		// 				},
224		// 			},
225		// 		},
226		// 	},
227		// },
228		// {
229		// 	name:           "anon access: admin-access, anonymous user, collab",
230		// 	repo:           "foo",
231		// 	expectedAccess: proto.AdminAccess,
232		// 	cfg: Config{
233		// 		AnonAccess: "admin-access",
234		// 		Repos: []RepoConfig{
235		// 			{
236		// 				Repo: "foo",
237		// 				Collabs: []string{
238		// 					"user",
239		// 				},
240		// 			},
241		// 		},
242		// 	},
243		// },
244		// {
245		// 	name:           "anon access: admin-access, authd user, collab",
246		// 	repo:           "foo",
247		// 	key:            dummyPk,
248		// 	expectedAccess: proto.AdminAccess,
249		// 	cfg: Config{
250		// 		AnonAccess: "admin-access",
251		// 		Repos: []RepoConfig{
252		// 			{
253		// 				Repo: "foo",
254		// 				Collabs: []string{
255		// 					"user",
256		// 				},
257		// 			},
258		// 		},
259		// 		Users: []User{
260		// 			{
261		// 				Name: "user",
262		// 				PublicKeys: []string{
263		// 					dummyKey,
264		// 				},
265		// 			},
266		// 		},
267		// 	},
268		// }, {
269		// 	name:           "anon access: admin-access, admin user, collab",
270		// 	repo:           "foo",
271		// 	key:            adminPk,
272		// 	expectedAccess: proto.AdminAccess,
273		// 	cfg: Config{
274		// 		AnonAccess: "admin-access",
275		// 		Repos: []RepoConfig{
276		// 			{
277		// 				Repo: "foo",
278		// 				Collabs: []string{
279		// 					"user",
280		// 				},
281		// 			},
282		// 		},
283		// 		Users: []User{
284		// 			{
285		// 				Name:  "admin",
286		// 				Admin: true,
287		// 				PublicKeys: []string{
288		// 					adminKey,
289		// 				},
290		// 			},
291		// 		},
292		// 	},
293		// },
294
295		// New repo
296		{
297			name:           "anon access: no-access, anonymous user, new repo",
298			anonAccess:     proto.NoAccess,
299			expectedAccess: proto.NoAccess,
300			repo:           "foo",
301		},
302		{
303			name:           "anon access: no-access, authd user, new repo",
304			key:            dummyPk,
305			repo:           "foo",
306			anonAccess:     proto.NoAccess,
307			expectedAccess: proto.ReadOnlyAccess,
308		},
309		{
310			name:           "anon access: no-access, admin user, new repo",
311			repo:           "foo",
312			key:            adminPk,
313			anonAccess:     proto.NoAccess,
314			expectedAccess: proto.AdminAccess,
315		},
316		// {
317		// 	name:           "anon access: read-only, anonymous user, new repo",
318		// 	repo:           "foo",
319		// 	expectedAccess: proto.ReadOnlyAccess,
320		// 	cfg: Config{
321		// 		AnonAccess: "read-only",
322		// 	},
323		// },
324		// {
325		// 	name:           "anon access: read-only, authd user, new repo",
326		// 	repo:           "foo",
327		// 	key:            dummyPk,
328		// 	expectedAccess: proto.ReadOnlyAccess,
329		// 	cfg: Config{
330		// 		AnonAccess: "read-only",
331		// 		Users: []User{
332		// 			{
333		// 				PublicKeys: []string{
334		// 					dummyKey,
335		// 				},
336		// 			},
337		// 		},
338		// 	},
339		// },
340		// {
341		// 	name:           "anon access: read-only, admin user, new repo",
342		// 	repo:           "foo",
343		// 	key:            adminPk,
344		// 	expectedAccess: proto.AdminAccess,
345		// 	cfg: Config{
346		// 		AnonAccess: "read-only",
347		// 		Users: []User{
348		// 			{
349		// 				Admin: true,
350		// 				PublicKeys: []string{
351		// 					adminKey,
352		// 				},
353		// 			},
354		// 		},
355		// 	},
356		// },
357		// {
358		// 	name:           "anon access: read-write, anonymous user, new repo",
359		// 	repo:           "foo",
360		// 	expectedAccess: proto.ReadWriteAccess,
361		// 	cfg: Config{
362		// 		AnonAccess: "read-write",
363		// 	},
364		// },
365		// {
366		// 	name:           "anon access: read-write, authd user, new repo",
367		// 	repo:           "foo",
368		// 	key:            dummyPk,
369		// 	expectedAccess: proto.ReadWriteAccess,
370		// 	cfg: Config{
371		// 		AnonAccess: "read-write",
372		// 		Users: []User{
373		// 			{
374		// 				PublicKeys: []string{
375		// 					dummyKey,
376		// 				},
377		// 			},
378		// 		},
379		// 	},
380		// },
381		// {
382		// 	name:           "anon access: read-write, admin user, new repo",
383		// 	repo:           "foo",
384		// 	key:            adminPk,
385		// 	expectedAccess: proto.AdminAccess,
386		// 	cfg: Config{
387		// 		AnonAccess: "read-write",
388		// 		Users: []User{
389		// 			{
390		// 				Admin: true,
391		// 				PublicKeys: []string{
392		// 					adminKey,
393		// 				},
394		// 			},
395		// 		},
396		// 	},
397		// },
398		// {
399		// 	name:           "anon access: admin-access, anonymous user, new repo",
400		// 	repo:           "foo",
401		// 	expectedAccess: proto.AdminAccess,
402		// 	cfg: Config{
403		// 		AnonAccess: "admin-access",
404		// 	},
405		// },
406		// {
407		// 	name:           "anon access: admin-access, authd user, new repo",
408		// 	repo:           "foo",
409		// 	key:            dummyPk,
410		// 	expectedAccess: proto.AdminAccess,
411		// 	cfg: Config{
412		// 		AnonAccess: "admin-access",
413		// 		Users: []User{
414		// 			{
415		// 				PublicKeys: []string{
416		// 					dummyKey,
417		// 				},
418		// 			},
419		// 		},
420		// 	},
421		// },
422		// {
423		// 	name:           "anon access: admin-access, admin user, new repo",
424		// 	repo:           "foo",
425		// 	key:            adminPk,
426		// 	expectedAccess: proto.AdminAccess,
427		// 	cfg: Config{
428		// 		AnonAccess: "admin-access",
429		// 		Users: []User{
430		// 			{
431		// 				Admin: true,
432		// 				PublicKeys: []string{
433		// 					adminKey,
434		// 				},
435		// 			},
436		// 		},
437		// 	},
438		// },
439
440		// // No users
441		// {
442		// 	name:           "anon access: read-only, no users",
443		// 	repo:           "foo",
444		// 	expectedAccess: proto.ReadOnlyAccess,
445		// 	cfg: Config{
446		// 		AnonAccess: "read-only",
447		// 	},
448		// },
449		// {
450		// 	name:           "anon access: read-write, no users",
451		// 	repo:           "foo",
452		// 	expectedAccess: proto.ReadWriteAccess,
453		// 	cfg: Config{
454		// 		AnonAccess: "read-write",
455		// 	},
456		// },
457	}
458	for _, c := range cases {
459		t.Run(c.name, func(t *testing.T) {
460			is := is.New(t)
461			cfg.AnonAccess = c.anonAccess
462			al := cfg.accessForKey(c.repo, c.key)
463			is.Equal(al, c.expectedAccess)
464		})
465	}
466}