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}