270 lines
6.1 KiB
Go
270 lines
6.1 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"path"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
func TestEncodeDecodeCookie(t *testing.T) {
|
|
newTestServer(t)
|
|
|
|
for i := 0; i < 5; i++ {
|
|
value := uuid.New().String()
|
|
encoded := encodeCookie(value)
|
|
for j := 0; j < 5; j++ {
|
|
decoded, ok := decodeCookie(encoded)
|
|
if !ok || decoded != value {
|
|
t.Errorf("value=%s, encoded=%s, decoded=%s", value, encoded, decoded)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestEncodeDecodeUserCookie(t *testing.T) {
|
|
newTestServer(t)
|
|
|
|
user := User{
|
|
User: "abc",
|
|
Groups: []string{"def", "ghi"},
|
|
}
|
|
encoded := encodeUserCookie(user)
|
|
decoded, ok := decodeUserCookie(encoded)
|
|
if !ok {
|
|
t.Fatal(ok)
|
|
}
|
|
if fmt.Sprint(user) != fmt.Sprint(decoded) {
|
|
t.Fatal(user, decoded)
|
|
}
|
|
}
|
|
|
|
func TestGetCookie(t *testing.T) {
|
|
r := httptest.NewRequest(http.MethodGet, "/", nil)
|
|
r.AddCookie(&http.Cookie{
|
|
Name: "abc",
|
|
Value: "def",
|
|
Expires: time.Now().Add(time.Hour),
|
|
})
|
|
got, _ := getCookie("abc", r)
|
|
if got != "def" {
|
|
t.Fatal(r.Cookies(), got)
|
|
}
|
|
}
|
|
|
|
func TestGetSetLoginCookie(t *testing.T) {
|
|
w := httptest.NewRecorder()
|
|
r := httptest.NewRequest(http.MethodGet, "/", nil)
|
|
user := User{User: "a", Groups: []string{"g"}}
|
|
|
|
setLoginCookie(w, r, user)
|
|
if w.Header().Get("Set-Cookie") == "" {
|
|
t.Error(w.Header())
|
|
}
|
|
if r.Cookies()[0].Name != "login" {
|
|
t.Error(r.Cookies())
|
|
}
|
|
|
|
got, ok := loginCookie(r)
|
|
if !ok {
|
|
t.Error(ok)
|
|
}
|
|
if fmt.Sprint(user) != fmt.Sprint(got) {
|
|
t.Error(user, got)
|
|
}
|
|
}
|
|
|
|
func TestNeedsLogin(t *testing.T) {
|
|
w := httptest.NewRecorder()
|
|
user := User{User: "user", Groups: []string{"group0", "group1"}}
|
|
|
|
t.Run("no login provided", func(t *testing.T) {
|
|
r := httptest.NewRequest(http.MethodGet, "/", nil)
|
|
if ok, err := needsLogin(r); err != nil {
|
|
t.Fatal(err)
|
|
} else if !ok {
|
|
t.Fatal(ok)
|
|
}
|
|
})
|
|
|
|
t.Run("no namespace provided", func(t *testing.T) {
|
|
r := httptest.NewRequest(http.MethodGet, "/", nil)
|
|
setLoginCookie(w, r, user)
|
|
if ok, err := needsLogin(r); err != nil {
|
|
t.Fatal(err)
|
|
} else if !ok {
|
|
t.Fatal(ok)
|
|
}
|
|
})
|
|
|
|
t.Run("cookie tampered", func(t *testing.T) {
|
|
r := httptest.NewRequest(http.MethodGet, "/", nil)
|
|
setLoginCookie(w, r, user)
|
|
setNamespaceCookie(w, r, user.Groups[0])
|
|
cookieSecret += "modified"
|
|
if ok, err := needsLogin(r); err != nil {
|
|
t.Fatal(err)
|
|
} else if !ok {
|
|
t.Fatal(ok)
|
|
}
|
|
})
|
|
|
|
t.Run("bad namespace", func(t *testing.T) {
|
|
r := httptest.NewRequest(http.MethodGet, "/", nil)
|
|
setLoginCookie(w, r, user)
|
|
setNamespaceCookie(w, r, "teehee")
|
|
if ok, err := needsLogin(r); err != nil {
|
|
t.Fatal(err)
|
|
} else if !ok {
|
|
t.Fatal(ok)
|
|
}
|
|
})
|
|
|
|
t.Run("ok", func(t *testing.T) {
|
|
r := httptest.NewRequest(http.MethodGet, "/", nil)
|
|
setLoginCookie(w, r, user)
|
|
setNamespaceCookie(w, r, user.Groups[0])
|
|
if ok, err := needsLogin(r); err != nil {
|
|
t.Fatal(err)
|
|
} else if ok {
|
|
t.Fatal(ok)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestServerParseLogin(t *testing.T) {
|
|
server := newTestServer(t)
|
|
|
|
t.Run("no basic auth", func(t *testing.T) {
|
|
w := httptest.NewRecorder()
|
|
r := httptest.NewRequest(http.MethodGet, "/", nil)
|
|
if done, err := server.parseLogin(w, r); done || err != nil {
|
|
t.Fatal(done, err)
|
|
}
|
|
if w.Code == http.StatusUnauthorized {
|
|
t.Error(w.Code)
|
|
}
|
|
})
|
|
|
|
t.Run("bad basic auth", func(t *testing.T) {
|
|
w := httptest.NewRecorder()
|
|
r := httptest.NewRequest(http.MethodGet, "/", nil)
|
|
r.SetBasicAuth("junk", "junk")
|
|
if done, err := server.parseLogin(w, r); !done || err != nil {
|
|
t.Fatal(done, err)
|
|
}
|
|
if w.Code != http.StatusUnauthorized {
|
|
t.Error(w.Code)
|
|
}
|
|
})
|
|
|
|
t.Run("ok", func(t *testing.T) {
|
|
w := httptest.NewRecorder()
|
|
r := httptest.NewRequest(http.MethodGet, "/", nil)
|
|
r.SetBasicAuth("user", "passw")
|
|
if done, err := server.parseLogin(w, r); done || err != nil {
|
|
t.Fatal(done, err)
|
|
}
|
|
if w.Code == http.StatusUnauthorized {
|
|
t.Error(w.Code)
|
|
}
|
|
if len(w.Header()["Set-Cookie"]) != 2 {
|
|
t.Error(w.Header())
|
|
}
|
|
if len(r.Cookies()) != 2 {
|
|
t.Error(r.Cookies())
|
|
}
|
|
if v, ok := namespaceCookie(r); !ok || v != "group" {
|
|
t.Error(r.Cookies())
|
|
}
|
|
if user, ok := loginCookie(r); !ok || user.User != "user" || user.Groups[0] != "group" || user.Groups[1] != "othergroup" {
|
|
t.Error(user)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestServerAuthenticate(t *testing.T) {
|
|
server := newTestServer(t)
|
|
|
|
t.Run("ok: already logged in", func(t *testing.T) {
|
|
r := httptest.NewRequest(http.MethodGet, "/", nil)
|
|
setLoginCookie(httptest.NewRecorder(), r, User{User: "user", Groups: []string{"group", "othergroup"}})
|
|
setNamespaceCookie(httptest.NewRecorder(), r, "othergroup")
|
|
s2, done, err := server.authenticate(nil, r)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
if done {
|
|
t.Error(done)
|
|
}
|
|
if server == s2 {
|
|
t.Error(done)
|
|
}
|
|
if server.loggedIn != nil {
|
|
t.Error(server.loggedIn)
|
|
}
|
|
if s2.loggedIn == nil {
|
|
t.Error(s2.loggedIn)
|
|
}
|
|
if s2.loggedIn.user != "user" {
|
|
t.Error(s2.loggedIn)
|
|
}
|
|
if s2.loggedIn.group != "othergroup" {
|
|
t.Error(s2.loggedIn)
|
|
}
|
|
if fmt.Sprint(s2.loggedIn.groups) != fmt.Sprint([]string{"group", "othergroup"}) {
|
|
t.Error(s2.loggedIn)
|
|
}
|
|
})
|
|
|
|
t.Run("ok: basic auth", func(t *testing.T) {
|
|
r := httptest.NewRequest(http.MethodGet, "/", nil)
|
|
w := httptest.NewRecorder()
|
|
r.SetBasicAuth("user", "passw")
|
|
s2, done, err := server.authenticate(w, r)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
if done {
|
|
t.Error(done)
|
|
}
|
|
if server == s2 {
|
|
t.Error(done)
|
|
}
|
|
if server.loggedIn != nil {
|
|
t.Error(server.loggedIn)
|
|
}
|
|
if s2.loggedIn == nil {
|
|
t.Error(s2.loggedIn)
|
|
}
|
|
if s2.loggedIn.user != "user" {
|
|
t.Error(s2.loggedIn)
|
|
}
|
|
if s2.loggedIn.group != "group" {
|
|
t.Error(s2.loggedIn)
|
|
}
|
|
if fmt.Sprint(s2.loggedIn.groups) != fmt.Sprint([]string{"group", "othergroup"}) {
|
|
t.Error(s2.loggedIn)
|
|
}
|
|
if w.Code != http.StatusOK {
|
|
t.Error(w.Code)
|
|
}
|
|
if len(w.Header()["Set-Cookie"]) != 2 {
|
|
t.Error(w.Header())
|
|
}
|
|
})
|
|
}
|
|
|
|
func newTestServer(t *testing.T) *Server {
|
|
cookieSecret = uuid.New().String()
|
|
p := path.Join(t.TempDir(), "auth.yaml")
|
|
ensureAndWrite(p, []byte(`{"users":{"user":{"password":"passw", "groups":["group", "othergroup"]}}}`))
|
|
return &Server{
|
|
auth: NewFileAuth(p),
|
|
}
|
|
}
|