From 161f452289b430f3a0cf0759c340144ede7e529d Mon Sep 17 00:00:00 2001 From: Ayman Bagabas Date: Wed, 7 Dec 2022 14:17:03 -0500 Subject: [PATCH] fix(config): default to not private when looking up access --- server/config/access.go | 8 +- server/config/access_test.go | 466 +++++++++++++++++++++++++++++++++++ 2 files changed, 470 insertions(+), 4 deletions(-) create mode 100644 server/config/access_test.go diff --git a/server/config/access.go b/server/config/access.go index d040dd61e89cc5e56491c8b0c15b9f51632df958..ba41afec4cf5b98c0678d65edd2fcfb16d48259c 100644 --- a/server/config/access.go +++ b/server/config/access.go @@ -94,13 +94,13 @@ func (c *Config) accessForKey(repo string, pk ssh.PublicKey) proto.AccessLevel { return proto.AdminAccess } + var private bool anon := c.AnonAccess info, err := c.Metadata(repo) - if err != nil || info == nil { - log.Printf("error getting repo info: %v", err) - return anon + if err == nil && info != nil { + private = info.IsPrivate() } - private := info.IsPrivate() + log.Printf("auth key %s", authorizedKey(pk)) if pk != nil { isAdmin := c.IsAdmin(pk) diff --git a/server/config/access_test.go b/server/config/access_test.go new file mode 100644 index 0000000000000000000000000000000000000000..db734a1928c363df872906ccc356e2ce063d7078 --- /dev/null +++ b/server/config/access_test.go @@ -0,0 +1,466 @@ +package config + +import ( + "os" + "testing" + + "github.com/charmbracelet/soft-serve/proto" + "github.com/gliderlabs/ssh" + "github.com/matryer/is" +) + +func TestAuth(t *testing.T) { + is := is.New(t) + adminKey := "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINMwLvyV3ouVrTysUYGoJdl5Vgn5BACKov+n9PlzfPwH a@b" + adminPk, _, _, _, _ := ssh.ParseAuthorizedKey([]byte(adminKey)) + dummyKey := "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFxIobhwtfdwN7m1TFt9wx3PsfvcAkISGPxmbmbauST8 a@b" + dummyPk, _, _, _, _ := ssh.ParseAuthorizedKey([]byte(dummyKey)) + dp := t.TempDir() + is.NoErr(os.Setenv("SOFT_SERVE_INITIAL_ADMIN_KEY", adminKey)) + is.NoErr(os.Setenv("SOFT_SERVE_DATA_PATH", dp)) + t.Cleanup(func() { + is.NoErr(os.Unsetenv("SOFT_SERVE_INITIAL_ADMIN_KEY")) + is.NoErr(os.Unsetenv("SOFT_SERVE_DATA_PATH")) + is.NoErr(os.RemoveAll(dp)) + }) + cfg := DefaultConfig() + cases := []struct { + name string + repo string + key ssh.PublicKey + anonAccess proto.AccessLevel + expectedAccess proto.AccessLevel + }{ + // Repo access + { + name: "anon access: no-access, anonymous user", + anonAccess: proto.NoAccess, + expectedAccess: proto.NoAccess, + repo: "foo", + }, + { + name: "anon access: no-access, anonymous user with admin user", + expectedAccess: proto.NoAccess, + anonAccess: proto.NoAccess, + repo: "foo", + }, + { + name: "anon access: no-access, authd user", + key: dummyPk, + repo: "foo", + anonAccess: proto.NoAccess, + expectedAccess: proto.ReadOnlyAccess, + }, + { + name: "anon access: no-access, admin user", + repo: "foo", + key: adminPk, + anonAccess: proto.NoAccess, + expectedAccess: proto.AdminAccess, + }, + { + name: "anon access: read-only, anonymous user", + repo: "foo", + anonAccess: proto.ReadOnlyAccess, + expectedAccess: proto.ReadOnlyAccess, + }, + { + name: "anon access: read-only, authd user", + repo: "foo", + key: dummyPk, + anonAccess: proto.ReadOnlyAccess, + expectedAccess: proto.ReadOnlyAccess, + }, + { + name: "anon access: read-only, admin user", + repo: "foo", + key: adminPk, + anonAccess: proto.ReadOnlyAccess, + expectedAccess: proto.AdminAccess, + }, + { + name: "anon access: read-write, anonymous user", + repo: "foo", + anonAccess: proto.ReadWriteAccess, + expectedAccess: proto.ReadWriteAccess, + }, + { + name: "anon access: read-write, authd user", + repo: "foo", + key: dummyPk, + anonAccess: proto.ReadWriteAccess, + expectedAccess: proto.ReadWriteAccess, + }, + { + name: "anon access: read-write, admin user", + repo: "foo", + key: adminPk, + anonAccess: proto.ReadWriteAccess, + expectedAccess: proto.AdminAccess, + }, + { + name: "anon access: admin-access, anonymous user", + repo: "foo", + anonAccess: proto.AdminAccess, + expectedAccess: proto.AdminAccess, + }, + { + name: "anon access: admin-access, authd user", + repo: "foo", + key: dummyPk, + anonAccess: proto.AdminAccess, + expectedAccess: proto.AdminAccess, + }, + { + name: "anon access: admin-access, admin user", + repo: "foo", + key: adminPk, + anonAccess: proto.AdminAccess, + expectedAccess: proto.AdminAccess, + }, + + // TODO: fix this + // // Collabs + // { + // name: "anon access: no-access, authd user, collab", + // key: dummyPk, + // repo: "foo", + // expectedAccess: proto.ReadWriteAccess, + // cfg: Config{ + // AnonAccess: "no-access", + // Repos: []RepoConfig{ + // { + // Repo: "foo", + // Collabs: []string{ + // "user", + // }, + // }, + // }, + // Users: []User{ + // { + // Name: "user", + // PublicKeys: []string{ + // dummyKey, + // }, + // }, + // }, + // }, + // }, + // { + // name: "anon access: no-access, authd user, collab, private repo", + // key: dummyPk, + // repo: "foo", + // expectedAccess: proto.ReadWriteAccess, + // cfg: Config{ + // AnonAccess: "no-access", + // Repos: []RepoConfig{ + // { + // Repo: "foo", + // Private: true, + // Collabs: []string{ + // "user", + // }, + // }, + // }, + // Users: []User{ + // { + // Name: "user", + // PublicKeys: []string{ + // dummyKey, + // }, + // }, + // }, + // }, + // }, + // { + // name: "anon access: no-access, admin user, collab, private repo", + // repo: "foo", + // key: adminPk, + // expectedAccess: proto.AdminAccess, + // cfg: Config{ + // AnonAccess: "no-access", + // Repos: []RepoConfig{ + // { + // Repo: "foo", + // Private: true, + // Collabs: []string{ + // "user", + // }, + // }, + // }, + // Users: []User{ + // { + // Name: "admin", + // Admin: true, + // PublicKeys: []string{ + // adminKey, + // }, + // }, + // }, + // }, + // }, + // { + // name: "anon access: read-only, authd user, collab, private repo", + // repo: "foo", + // key: dummyPk, + // expectedAccess: proto.ReadWriteAccess, + // cfg: Config{ + // AnonAccess: "read-only", + // Repos: []RepoConfig{ + // { + // Repo: "foo", + // Private: true, + // Collabs: []string{ + // "user", + // }, + // }, + // }, + // Users: []User{ + // { + // Name: "user", + // PublicKeys: []string{ + // dummyKey, + // }, + // }, + // }, + // }, + // }, + // { + // name: "anon access: admin-access, anonymous user, collab", + // repo: "foo", + // expectedAccess: proto.AdminAccess, + // cfg: Config{ + // AnonAccess: "admin-access", + // Repos: []RepoConfig{ + // { + // Repo: "foo", + // Collabs: []string{ + // "user", + // }, + // }, + // }, + // }, + // }, + // { + // name: "anon access: admin-access, authd user, collab", + // repo: "foo", + // key: dummyPk, + // expectedAccess: proto.AdminAccess, + // cfg: Config{ + // AnonAccess: "admin-access", + // Repos: []RepoConfig{ + // { + // Repo: "foo", + // Collabs: []string{ + // "user", + // }, + // }, + // }, + // Users: []User{ + // { + // Name: "user", + // PublicKeys: []string{ + // dummyKey, + // }, + // }, + // }, + // }, + // }, { + // name: "anon access: admin-access, admin user, collab", + // repo: "foo", + // key: adminPk, + // expectedAccess: proto.AdminAccess, + // cfg: Config{ + // AnonAccess: "admin-access", + // Repos: []RepoConfig{ + // { + // Repo: "foo", + // Collabs: []string{ + // "user", + // }, + // }, + // }, + // Users: []User{ + // { + // Name: "admin", + // Admin: true, + // PublicKeys: []string{ + // adminKey, + // }, + // }, + // }, + // }, + // }, + + // New repo + { + name: "anon access: no-access, anonymous user, new repo", + anonAccess: proto.NoAccess, + expectedAccess: proto.NoAccess, + repo: "foo", + }, + { + name: "anon access: no-access, authd user, new repo", + key: dummyPk, + repo: "foo", + anonAccess: proto.NoAccess, + expectedAccess: proto.ReadOnlyAccess, + }, + { + name: "anon access: no-access, admin user, new repo", + repo: "foo", + key: adminPk, + anonAccess: proto.NoAccess, + expectedAccess: proto.AdminAccess, + }, + // { + // name: "anon access: read-only, anonymous user, new repo", + // repo: "foo", + // expectedAccess: proto.ReadOnlyAccess, + // cfg: Config{ + // AnonAccess: "read-only", + // }, + // }, + // { + // name: "anon access: read-only, authd user, new repo", + // repo: "foo", + // key: dummyPk, + // expectedAccess: proto.ReadOnlyAccess, + // cfg: Config{ + // AnonAccess: "read-only", + // Users: []User{ + // { + // PublicKeys: []string{ + // dummyKey, + // }, + // }, + // }, + // }, + // }, + // { + // name: "anon access: read-only, admin user, new repo", + // repo: "foo", + // key: adminPk, + // expectedAccess: proto.AdminAccess, + // cfg: Config{ + // AnonAccess: "read-only", + // Users: []User{ + // { + // Admin: true, + // PublicKeys: []string{ + // adminKey, + // }, + // }, + // }, + // }, + // }, + // { + // name: "anon access: read-write, anonymous user, new repo", + // repo: "foo", + // expectedAccess: proto.ReadWriteAccess, + // cfg: Config{ + // AnonAccess: "read-write", + // }, + // }, + // { + // name: "anon access: read-write, authd user, new repo", + // repo: "foo", + // key: dummyPk, + // expectedAccess: proto.ReadWriteAccess, + // cfg: Config{ + // AnonAccess: "read-write", + // Users: []User{ + // { + // PublicKeys: []string{ + // dummyKey, + // }, + // }, + // }, + // }, + // }, + // { + // name: "anon access: read-write, admin user, new repo", + // repo: "foo", + // key: adminPk, + // expectedAccess: proto.AdminAccess, + // cfg: Config{ + // AnonAccess: "read-write", + // Users: []User{ + // { + // Admin: true, + // PublicKeys: []string{ + // adminKey, + // }, + // }, + // }, + // }, + // }, + // { + // name: "anon access: admin-access, anonymous user, new repo", + // repo: "foo", + // expectedAccess: proto.AdminAccess, + // cfg: Config{ + // AnonAccess: "admin-access", + // }, + // }, + // { + // name: "anon access: admin-access, authd user, new repo", + // repo: "foo", + // key: dummyPk, + // expectedAccess: proto.AdminAccess, + // cfg: Config{ + // AnonAccess: "admin-access", + // Users: []User{ + // { + // PublicKeys: []string{ + // dummyKey, + // }, + // }, + // }, + // }, + // }, + // { + // name: "anon access: admin-access, admin user, new repo", + // repo: "foo", + // key: adminPk, + // expectedAccess: proto.AdminAccess, + // cfg: Config{ + // AnonAccess: "admin-access", + // Users: []User{ + // { + // Admin: true, + // PublicKeys: []string{ + // adminKey, + // }, + // }, + // }, + // }, + // }, + + // // No users + // { + // name: "anon access: read-only, no users", + // repo: "foo", + // expectedAccess: proto.ReadOnlyAccess, + // cfg: Config{ + // AnonAccess: "read-only", + // }, + // }, + // { + // name: "anon access: read-write, no users", + // repo: "foo", + // expectedAccess: proto.ReadWriteAccess, + // cfg: Config{ + // AnonAccess: "read-write", + // }, + // }, + } + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + is := is.New(t) + cfg.AnonAccess = c.anonAccess + al := cfg.accessForKey(c.repo, c.key) + is.Equal(al, c.expectedAccess) + }) + } +}