405 lines
10 KiB
Go
405 lines
10 KiB
Go
package useractivity
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
portainer "github.com/portainer/portainer/api"
|
|
)
|
|
|
|
func BenchmarkAuthLog(b *testing.B) {
|
|
defer timeTrack(time.Now(), "AuthActivityLog")
|
|
|
|
// https://github.com/golang/go/issues/41062
|
|
// bug in go 1.15 causes b.TempDir() to break in benchmarks
|
|
// TODO remove in go 1.16
|
|
|
|
err := os.RemoveAll("./useractivity.db")
|
|
if err != nil {
|
|
b.Fatalf("Failed removing db: %s", err)
|
|
}
|
|
|
|
store, err := setup("")
|
|
if err != nil {
|
|
b.Fatalf("Failed setup: %s", err)
|
|
}
|
|
|
|
defer store.Close()
|
|
|
|
for i := 0; i < 100; i++ {
|
|
_, err = store.LogAuthActivity("username", "endpoint", portainer.AuthenticationInternal, testType)
|
|
if err != nil {
|
|
b.Fatalf("Failed adding activity log: %s", err)
|
|
}
|
|
}
|
|
|
|
count, err := store.db.Count(&portainer.AuthActivityLog{})
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
}
|
|
|
|
fmt.Printf("Number of logs: %d\n", count)
|
|
|
|
}
|
|
|
|
const (
|
|
testType = portainer.AuthenticationActivityType(0)
|
|
)
|
|
|
|
func setup(path string) (*Store, error) {
|
|
store, err := NewUserActivityStore(path)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Failed creating new store: %w", err)
|
|
}
|
|
|
|
return store, nil
|
|
}
|
|
|
|
func TestAddActivity(t *testing.T) {
|
|
store, err := setup(t.TempDir())
|
|
if err != nil {
|
|
t.Fatalf("Failed setup: %s", err)
|
|
}
|
|
|
|
defer store.Close()
|
|
|
|
_, err = store.LogAuthActivity("username", "endpoint", portainer.AuthenticationInternal, testType)
|
|
if err != nil {
|
|
t.Fatalf("Failed adding activity log: %s", err)
|
|
}
|
|
|
|
count, err := store.db.Count(&portainer.AuthActivityLog{})
|
|
if err != nil {
|
|
t.Fatalf("Failed counting activities: %s", err)
|
|
}
|
|
|
|
assert.Equal(t, 1, count, "Store should have one element")
|
|
}
|
|
|
|
func TestGetLogs(t *testing.T) {
|
|
store, err := setup(t.TempDir())
|
|
if err != nil {
|
|
t.Fatalf("Failed setup: %s", err)
|
|
}
|
|
|
|
defer store.Close()
|
|
|
|
log1, err := store.LogAuthActivity("username1", "endpoint1", portainer.AuthenticationInternal, testType)
|
|
if err != nil {
|
|
t.Fatalf("Failed adding activity log: %s", err)
|
|
}
|
|
|
|
log2, err := store.LogAuthActivity("username2", "endpoint2", portainer.AuthenticationInternal, testType)
|
|
if err != nil {
|
|
t.Fatalf("Failed adding activity log: %s", err)
|
|
}
|
|
|
|
log3, err := store.LogAuthActivity("username3", "endpoint3", portainer.AuthenticationInternal, testType)
|
|
if err != nil {
|
|
t.Fatalf("Failed adding activity log: %s", err)
|
|
}
|
|
|
|
logs, _, err := store.GetAuthLogs(portainer.AuthLogsQuery{})
|
|
if err != nil {
|
|
t.Fatalf("failed fetching logs: %s", err)
|
|
}
|
|
|
|
assert.Equal(t, []*portainer.AuthActivityLog{log1, log2, log3}, logs)
|
|
}
|
|
|
|
func TestGetLogsByTimestamp(t *testing.T) {
|
|
store, err := setup(t.TempDir())
|
|
if err != nil {
|
|
t.Fatalf("Failed setup: %s", err)
|
|
}
|
|
|
|
defer store.Close()
|
|
|
|
log1, err := store.LogAuthActivity("username1", "endpoint1", portainer.AuthenticationInternal, testType)
|
|
if err != nil {
|
|
t.Fatalf("Failed adding activity log: %s", err)
|
|
}
|
|
|
|
time.Sleep(time.Second * 1)
|
|
|
|
log2, err := store.LogAuthActivity("username2", "endpoint2", portainer.AuthenticationInternal, testType)
|
|
if err != nil {
|
|
t.Fatalf("Failed adding activity log: %s", err)
|
|
}
|
|
|
|
time.Sleep(time.Second * 1)
|
|
|
|
log3, err := store.LogAuthActivity("username3", "endpoint3", portainer.AuthenticationInternal, testType)
|
|
if err != nil {
|
|
t.Fatalf("Failed adding activity log: %s", err)
|
|
}
|
|
|
|
logs, _, err := store.GetAuthLogs(portainer.AuthLogsQuery{
|
|
BeforeTimestamp: log3.Timestamp - 1,
|
|
AfterTimestamp: log1.Timestamp + 1,
|
|
})
|
|
|
|
if err != nil {
|
|
t.Fatalf("failed fetching logs: %s", err)
|
|
}
|
|
|
|
assert.Equal(t, log2, logs[0], "logs are not equal")
|
|
}
|
|
|
|
func TestGetLogsByKeyword(t *testing.T) {
|
|
store, err := setup(t.TempDir())
|
|
if err != nil {
|
|
t.Fatalf("Failed setup: %s", err)
|
|
}
|
|
|
|
defer store.Close()
|
|
|
|
log1, err := store.LogAuthActivity("username1", "endpoint1", portainer.AuthenticationInternal, testType)
|
|
if err != nil {
|
|
t.Fatalf("Failed adding activity log: %s", err)
|
|
}
|
|
|
|
log2, err := store.LogAuthActivity("username2", "endpoint2", portainer.AuthenticationInternal, testType)
|
|
if err != nil {
|
|
t.Fatalf("Failed adding activity log: %s", err)
|
|
}
|
|
|
|
log3, err := store.LogAuthActivity("username3", "endpoint3", portainer.AuthenticationInternal, testType)
|
|
if err != nil {
|
|
t.Fatalf("Failed adding activity log: %s", err)
|
|
}
|
|
|
|
// like
|
|
shouldHaveAllLogs, _, err := store.GetAuthLogs(portainer.AuthLogsQuery{
|
|
Keyword: "username",
|
|
})
|
|
|
|
if err != nil {
|
|
t.Fatalf("failed fetching logs: %s", err)
|
|
}
|
|
|
|
assert.Equal(t, []*portainer.AuthActivityLog{log1, log2, log3}, shouldHaveAllLogs)
|
|
|
|
// username
|
|
shouldHaveOnlyLog1, _, err := store.GetAuthLogs(portainer.AuthLogsQuery{
|
|
Keyword: "username1",
|
|
})
|
|
|
|
if err != nil {
|
|
t.Fatalf("failed fetching logs: %s", err)
|
|
}
|
|
|
|
assert.Equal(t, log1, shouldHaveOnlyLog1[0])
|
|
|
|
// origin
|
|
shouldHaveOnlyLog3, _, err := store.GetAuthLogs(portainer.AuthLogsQuery{
|
|
Keyword: "endpoint3",
|
|
})
|
|
|
|
if err != nil {
|
|
t.Fatalf("failed fetching logs: %s", err)
|
|
}
|
|
|
|
assert.Equal(t, log3, shouldHaveOnlyLog3[0])
|
|
}
|
|
|
|
func TestGetLogsByContext(t *testing.T) {
|
|
store, err := setup(t.TempDir())
|
|
if err != nil {
|
|
t.Fatalf("Failed setup: %s", err)
|
|
}
|
|
|
|
defer store.Close()
|
|
|
|
log1, err := store.LogAuthActivity("username1", "endpoint1", portainer.AuthenticationInternal, testType)
|
|
if err != nil {
|
|
t.Fatalf("Failed adding activity log: %s", err)
|
|
}
|
|
|
|
log2, err := store.LogAuthActivity("username2", "endpoint2", portainer.AuthenticationLDAP, testType)
|
|
if err != nil {
|
|
t.Fatalf("Failed adding activity log: %s", err)
|
|
}
|
|
|
|
log3, err := store.LogAuthActivity("username3", "endpoint3", portainer.AuthenticationOAuth, testType)
|
|
if err != nil {
|
|
t.Fatalf("Failed adding activity log: %s", err)
|
|
}
|
|
|
|
// one type
|
|
shouldHaveLog2, _, err := store.GetAuthLogs(portainer.AuthLogsQuery{
|
|
ContextTypes: []portainer.AuthenticationMethod{
|
|
portainer.AuthenticationLDAP,
|
|
},
|
|
})
|
|
|
|
if err != nil {
|
|
t.Fatalf("failed fetching logs: %s", err)
|
|
}
|
|
|
|
assert.Equal(t, []*portainer.AuthActivityLog{log2}, shouldHaveLog2)
|
|
|
|
// two types
|
|
shouldHaveLog1And3, _, err := store.GetAuthLogs(portainer.AuthLogsQuery{
|
|
ContextTypes: []portainer.AuthenticationMethod{
|
|
portainer.AuthenticationInternal,
|
|
portainer.AuthenticationOAuth,
|
|
},
|
|
})
|
|
|
|
if err != nil {
|
|
t.Fatalf("failed fetching logs: %s", err)
|
|
}
|
|
|
|
assert.Equal(t, []*portainer.AuthActivityLog{log1, log3}, shouldHaveLog1And3)
|
|
}
|
|
|
|
func TestGetLogsByType(t *testing.T) {
|
|
store, err := setup(t.TempDir())
|
|
if err != nil {
|
|
t.Fatalf("Failed setup: %s", err)
|
|
}
|
|
|
|
defer store.Close()
|
|
|
|
log1, err := store.LogAuthActivity("username1", "endpoint1", portainer.AuthenticationInternal, portainer.AuthenticationActivityFailure)
|
|
if err != nil {
|
|
t.Fatalf("Failed adding activity log: %s", err)
|
|
}
|
|
|
|
log2, err := store.LogAuthActivity("username2", "endpoint2", portainer.AuthenticationLDAP, portainer.AuthenticationActivityLogOut)
|
|
if err != nil {
|
|
t.Fatalf("Failed adding activity log: %s", err)
|
|
}
|
|
|
|
log3, err := store.LogAuthActivity("username3", "endpoint3", portainer.AuthenticationOAuth, portainer.AuthenticationActivitySuccess)
|
|
if err != nil {
|
|
t.Fatalf("Failed adding activity log: %s", err)
|
|
}
|
|
|
|
// one type
|
|
shouldHaveLog2, _, err := store.GetAuthLogs(portainer.AuthLogsQuery{
|
|
ActivityTypes: []portainer.AuthenticationActivityType{
|
|
portainer.AuthenticationActivityLogOut,
|
|
},
|
|
})
|
|
|
|
if err != nil {
|
|
t.Fatalf("failed fetching logs: %s", err)
|
|
}
|
|
|
|
assert.Equal(t, []*portainer.AuthActivityLog{log2}, shouldHaveLog2)
|
|
|
|
// two types
|
|
shouldHaveLog1And3, _, err := store.GetAuthLogs(portainer.AuthLogsQuery{
|
|
ActivityTypes: []portainer.AuthenticationActivityType{
|
|
portainer.AuthenticationActivityFailure,
|
|
portainer.AuthenticationActivitySuccess,
|
|
},
|
|
})
|
|
|
|
if err != nil {
|
|
t.Fatalf("failed fetching logs: %s", err)
|
|
}
|
|
|
|
assert.Equal(t, []*portainer.AuthActivityLog{log1, log3}, shouldHaveLog1And3)
|
|
}
|
|
|
|
func TestSortOrderAndPaginate(t *testing.T) {
|
|
store, err := setup(t.TempDir())
|
|
if err != nil {
|
|
t.Fatalf("Failed setup: %s", err)
|
|
}
|
|
|
|
defer store.Close()
|
|
|
|
log1, err := store.LogAuthActivity("username1", "endpoint1", portainer.AuthenticationInternal, testType)
|
|
if err != nil {
|
|
t.Fatalf("Failed adding activity log: %s", err)
|
|
}
|
|
|
|
log2, err := store.LogAuthActivity("username2", "endpoint2", portainer.AuthenticationInternal, testType)
|
|
if err != nil {
|
|
t.Fatalf("Failed adding activity log: %s", err)
|
|
}
|
|
|
|
log3, err := store.LogAuthActivity("username3", "endpoint3", portainer.AuthenticationInternal, testType)
|
|
if err != nil {
|
|
t.Fatalf("Failed adding activity log: %s", err)
|
|
}
|
|
|
|
log4, err := store.LogAuthActivity("username4", "endpoint4", portainer.AuthenticationInternal, testType)
|
|
if err != nil {
|
|
t.Fatalf("Failed adding activity log: %s", err)
|
|
}
|
|
|
|
shouldBeLog4AndLog3, _, err := store.GetAuthLogs(portainer.AuthLogsQuery{
|
|
SortDesc: true,
|
|
SortBy: "Username",
|
|
Offset: 0,
|
|
Limit: 2,
|
|
})
|
|
|
|
if err != nil {
|
|
t.Fatalf("failed fetching logs: %s", err)
|
|
}
|
|
|
|
assert.Equal(t, []*portainer.AuthActivityLog{log4, log3}, shouldBeLog4AndLog3)
|
|
|
|
shouldBeLog2AndLog1, _, err := store.GetAuthLogs(portainer.AuthLogsQuery{
|
|
SortDesc: true,
|
|
SortBy: "Username",
|
|
Offset: 2,
|
|
Limit: 2,
|
|
})
|
|
|
|
if err != nil {
|
|
t.Fatalf("failed fetching logs: %s", err)
|
|
}
|
|
|
|
assert.Equal(t, []*portainer.AuthActivityLog{log2, log1}, shouldBeLog2AndLog1)
|
|
}
|
|
|
|
func TestGetLogsDesc(t *testing.T) {
|
|
store, err := setup(t.TempDir())
|
|
if err != nil {
|
|
t.Fatalf("Failed setup: %s", err)
|
|
}
|
|
|
|
defer store.Close()
|
|
|
|
log1, err := store.LogAuthActivity("username1", "endpoint1", portainer.AuthenticationInternal, testType)
|
|
if err != nil {
|
|
t.Fatalf("Failed adding activity log: %s", err)
|
|
}
|
|
|
|
log2, err := store.LogAuthActivity("username2", "endpoint2", portainer.AuthenticationInternal, testType)
|
|
if err != nil {
|
|
t.Fatalf("Failed adding activity log: %s", err)
|
|
}
|
|
|
|
log3, err := store.LogAuthActivity("username3", "endpoint3", portainer.AuthenticationInternal, testType)
|
|
if err != nil {
|
|
t.Fatalf("Failed adding activity log: %s", err)
|
|
}
|
|
|
|
logs, _, err := store.GetAuthLogs(portainer.AuthLogsQuery{
|
|
SortDesc: true,
|
|
})
|
|
|
|
if err != nil {
|
|
t.Fatalf("failed fetching logs: %s", err)
|
|
}
|
|
|
|
assert.Equal(t, []*portainer.AuthActivityLog{log3, log2, log1}, logs)
|
|
}
|
|
|
|
func timeTrack(start time.Time, name string) {
|
|
elapsed := time.Since(start)
|
|
fmt.Printf("%s took %s\n", name, elapsed)
|
|
}
|