mirror of
https://github.com/paralus/paralus.git
synced 2026-08-24 15:47:19 +00:00
added test cases
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/paralus/paralus/internal/models"
|
||||
"github.com/paralus/paralus/pkg/audit"
|
||||
"github.com/paralus/paralus/pkg/query"
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
@@ -19,7 +20,7 @@ func GetAuditLogAggregations(ctx context.Context, db *bun.DB, tag, field string,
|
||||
sq.ColumnExpr("data->>'type' as key").
|
||||
Where("tag = ?", tag).GroupExpr("data->>'type'")
|
||||
case "username":
|
||||
if tag != "kubectl_api" {
|
||||
if tag != audit.KUBECTL_API {
|
||||
sq.ColumnExpr("data->'actor'->'account'->>'username' as key").
|
||||
Where("tag = ?", tag).GroupExpr("data->'actor'->'account'->>'username'")
|
||||
} else {
|
||||
@@ -45,9 +46,9 @@ func GetAuditLogAggregations(ctx context.Context, db *bun.DB, tag, field string,
|
||||
|
||||
// add filters
|
||||
switch tag {
|
||||
case "kubectl_api":
|
||||
case audit.KUBECTL_API:
|
||||
sq = buildRelayAuditQuery(sq, filters)
|
||||
case "system", "kubectl_cmd":
|
||||
case audit.SYSTEM, audit.KUBECTL_CMD:
|
||||
sq = buildQuery(sq, filters)
|
||||
}
|
||||
|
||||
@@ -61,9 +62,9 @@ func GetAuditLogs(ctx context.Context, db *bun.DB, tag string, filters query.Que
|
||||
Where("tag = ?", tag)
|
||||
|
||||
switch tag {
|
||||
case "kubectl_api":
|
||||
case audit.KUBECTL_API:
|
||||
sq = buildRelayAuditQuery(sq, filters)
|
||||
case "system", "kubectl_cmd":
|
||||
case audit.SYSTEM, audit.KUBECTL_CMD:
|
||||
sq = buildQuery(sq, filters)
|
||||
}
|
||||
|
||||
|
||||
@@ -365,9 +365,9 @@ func setup() {
|
||||
gps = service.NewGroupPermissionService(db)
|
||||
|
||||
switch auditLogStorage {
|
||||
case "database":
|
||||
case audit.DATABASE:
|
||||
// audit services
|
||||
aus, err = service.NewAuditLogDatabaseService(db, "system")
|
||||
aus, err = service.NewAuditLogDatabaseService(db, audit.SYSTEM)
|
||||
if err != nil {
|
||||
if dev && strings.Contains(err.Error(), "connect: connection refused") {
|
||||
// This is primarily from ES not being available. ES being
|
||||
@@ -379,7 +379,7 @@ func setup() {
|
||||
_log.Fatalw("unable to create auditLog service", "error", err)
|
||||
}
|
||||
}
|
||||
ras, err = service.NewRelayAuditDatabaseService(db, "kubectl_api")
|
||||
ras, err = service.NewRelayAuditDatabaseService(db, audit.KUBECTL_API)
|
||||
if err != nil {
|
||||
if dev && strings.Contains(err.Error(), "connect: connection refused") {
|
||||
_log.Warn("unable to create relayAudit service: ", err)
|
||||
@@ -387,7 +387,7 @@ func setup() {
|
||||
_log.Fatalw("unable to create relayAudit service", "error", err)
|
||||
}
|
||||
}
|
||||
rcs, err = service.NewAuditLogDatabaseService(db, "kubectl_cmd")
|
||||
rcs, err = service.NewAuditLogDatabaseService(db, audit.KUBECTL_CMD)
|
||||
if err != nil {
|
||||
if dev && strings.Contains(err.Error(), "connect: connection refused") {
|
||||
_log.Warn("unable to create auditLog service:", err)
|
||||
@@ -395,7 +395,7 @@ func setup() {
|
||||
_log.Fatalw("unable to create auditLog service", "error", err)
|
||||
}
|
||||
}
|
||||
case "elasticsearch":
|
||||
case audit.ELASTICSEARCH:
|
||||
// audit services
|
||||
aus, err = service.NewAuditLogElasticSearchService(elasticSearchUrl, esIndexPrefix+"-*", "AuditLog API: ")
|
||||
if err != nil {
|
||||
@@ -426,7 +426,7 @@ func setup() {
|
||||
}
|
||||
}
|
||||
default:
|
||||
|
||||
_log.Warn("unable to create audit log service: invalid storage option ! should be either %s or %s", audit.DATABASE, audit.ELASTICSEARCH)
|
||||
}
|
||||
|
||||
// cluster bootstrap
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package audit
|
||||
|
||||
const (
|
||||
DATABASE string = "database"
|
||||
ELASTICSEARCH string = "elasticsearch"
|
||||
)
|
||||
|
||||
const (
|
||||
SYSTEM string = "system"
|
||||
KUBECTL_CMD string = "kubectl_cmd"
|
||||
KUBECTL_API string = "kubectl_api"
|
||||
)
|
||||
@@ -91,8 +91,14 @@ func (a *auditLogDatabaseService) GetAuditLogByProjects(req *v1.GetAuditLogSearc
|
||||
}
|
||||
|
||||
var resMap map[string]interface{}
|
||||
data, _ := json.Marshal(response)
|
||||
json.Unmarshal(data, &resMap)
|
||||
data, err := json.Marshal(response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = json.Unmarshal(data, &resMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result, _ := structpb.NewStruct(resMap)
|
||||
res = &v1.GetAuditLogSearchResponse{
|
||||
|
||||
@@ -0,0 +1,218 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"regexp"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/DATA-DOG/go-sqlmock"
|
||||
"github.com/paralus/paralus/pkg/audit"
|
||||
eventv1 "github.com/paralus/paralus/proto/rpc/audit"
|
||||
auditv1 "github.com/paralus/paralus/proto/types/audit"
|
||||
commonv3 "github.com/paralus/paralus/proto/types/commonpb/v3"
|
||||
)
|
||||
|
||||
const project = "projectone"
|
||||
|
||||
func TestAuditLog(t *testing.T) {
|
||||
|
||||
testcases := []struct {
|
||||
name string
|
||||
run func(t *testing.T)
|
||||
}{
|
||||
{
|
||||
name: "auditlog-lasthour",
|
||||
run: testGetAuditLogForLastHour(audit.SYSTEM),
|
||||
},
|
||||
{
|
||||
name: "auditlog-lastday",
|
||||
run: testGetAuditLogForDay(audit.SYSTEM),
|
||||
},
|
||||
{
|
||||
name: "kubectlcmd-lastday",
|
||||
run: testGetKubectlCommands(audit.KUBECTL_CMD),
|
||||
},
|
||||
}
|
||||
|
||||
t.Run("auditlogs", func(t *testing.T) {
|
||||
for _, testcase := range testcases {
|
||||
tc := testcase
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
tc.run(t)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func testGetAuditLogForLastHour(tag string) func(t *testing.T) {
|
||||
return func(t *testing.T) {
|
||||
|
||||
db, mock := getDB(t)
|
||||
defer db.Close()
|
||||
|
||||
as, err := NewAuditLogDatabaseService(db, tag)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
timefrom := "1h"
|
||||
auditrecord := "{\"actor\":{\"account\":{\"username\":\"admin@paralus.local\"},\"groups\":[\"All Local Users\",\"Organization Admins\"],\"type\":\"USER\"},\"category\":\"AUDIT\",\"client\":{\"host\":\"console-ic-oss.dev.rafay-edge.net\",\"ip\":\"10.0.0.147:47204\",\"type\":\"BROWSER\",\"user_agent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36\"},\"detail\":{\"message\":\"Cluster kind-local deleted\",\"meta\":{\"cluster_name\":\"kind-local\"}},\"origin\":\"core\",\"portal\":\"OPS\",\"project\":\"stage\",\"timestamp\":\"2022-11-21T09:48:30.597615647Z\",\"type\":\"cluster.delete.success\",\"version\":\"1.0\"}"
|
||||
|
||||
req := &eventv1.GetAuditLogSearchRequest{
|
||||
Metadata: &commonv3.Metadata{
|
||||
UrlScope: "auditlogs/" + project,
|
||||
},
|
||||
Filter: &eventv1.AuditLogQueryFilter{
|
||||
Timefrom: "now-" + timefrom,
|
||||
Projects: []string{project},
|
||||
},
|
||||
}
|
||||
|
||||
mock.ExpectQuery(regexp.QuoteMeta(`SELECT "auditlog"."tag", "auditlog"."time", "auditlog"."data" FROM "audit_logs" AS "auditlog" WHERE (tag = '` + tag + `') AND (data->>'project' = '` + project + `') AND (to_timestamp(data->>'timestamp', 'YYYY-MM-DD"T"HH:MI:SS') between now() - interval '` + timefrom + `' and now())`)).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"tag", "time", "data"}).AddRow("system", time.Now(), auditrecord))
|
||||
|
||||
mock.ExpectQuery(regexp.QuoteMeta(`SELECT count(1) as count, data->>'project' as key FROM "audit_logs" WHERE (tag = '` + tag + `') AND (data->>'project' = '` + project + `') AND (to_timestamp(data->>'timestamp', 'YYYY-MM-DD"T"HH:MI:SS') between now() - interval '` + timefrom + `' and now()) GROUP BY data->>'project'`)).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count", "key"}).AddRow(1, "cluster"))
|
||||
|
||||
mock.ExpectQuery(regexp.QuoteMeta(`SELECT count(1) as count, data->'actor'->'account'->>'username' as key FROM "audit_logs" WHERE (tag = '` + tag + `') AND (data->>'project' = '` + project + `') AND (to_timestamp(data->>'timestamp', 'YYYY-MM-DD"T"HH:MI:SS') between now() - interval '` + timefrom + `' and now()) GROUP BY data->'actor'->'account'->>'username'`)).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count", "key"}).AddRow(1, "username"))
|
||||
|
||||
mock.ExpectQuery(regexp.QuoteMeta(`SELECT count(1) as count, data->>'type' as key FROM "audit_logs" WHERE (tag = '` + tag + `') AND (data->>'project' = '` + project + `') AND (to_timestamp(data->>'timestamp', 'YYYY-MM-DD"T"HH:MI:SS') between now() - interval '` + timefrom + `' and now()) GROUP BY data->>'type'`)).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count", "key"}).AddRow(1, "type"))
|
||||
|
||||
res, err := as.GetAuditLogByProjects(req)
|
||||
if err != nil {
|
||||
t.Fatal("could not get audit logs:", err)
|
||||
}
|
||||
|
||||
var response auditv1.AuditResponse
|
||||
data, err := json.Marshal(res.Result)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = json.Unmarshal(data, &response)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(response.GetHits().Hits) != 1 {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testGetAuditLogForDay(tag string) func(t *testing.T) {
|
||||
return func(t *testing.T) {
|
||||
|
||||
db, mock := getDB(t)
|
||||
defer db.Close()
|
||||
|
||||
as, err := NewAuditLogDatabaseService(db, tag)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
timefrom := "1d"
|
||||
auditrecord := "{\"actor\":{\"account\":{\"username\":\"admin@paralus.local\"},\"groups\":[\"All Local Users\",\"Organization Admins\"],\"type\":\"USER\"},\"category\":\"AUDIT\",\"client\":{\"host\":\"console-ic-oss.dev.rafay-edge.net\",\"ip\":\"10.0.0.147:47204\",\"type\":\"BROWSER\",\"user_agent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36\"},\"detail\":{\"message\":\"Cluster kind-local deleted\",\"meta\":{\"cluster_name\":\"kind-local\"}},\"origin\":\"core\",\"portal\":\"OPS\",\"project\":\"stage\",\"timestamp\":\"2022-11-21T09:48:30.597615647Z\",\"type\":\"cluster.delete.success\",\"version\":\"1.0\"}"
|
||||
auditrecordtwo := "{\"actor\":{\"account\":{\"username\":\"admin@paralus.local\"},\"groups\":[\"All Local Users\",\"Organization Admins\"],\"type\":\"USER\"},\"category\":\"AUDIT\",\"client\":{\"host\":\"console-ic-oss.dev.rafay-edge.net\",\"ip\":\"10.0.0.147:47204\",\"type\":\"BROWSER\",\"user_agent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36\"},\"detail\":{\"message\":\"Cluster kind-local deleted\",\"meta\":{\"cluster_name\":\"kind-local\"}},\"origin\":\"core\",\"portal\":\"OPS\",\"project\":\"stage\",\"timestamp\":\"2022-11-21T09:48:30.597615647Z\",\"type\":\"cluster.delete.success\",\"version\":\"1.0\"}"
|
||||
|
||||
req := &eventv1.GetAuditLogSearchRequest{
|
||||
Metadata: &commonv3.Metadata{
|
||||
UrlScope: "auditlogs/" + project,
|
||||
},
|
||||
Filter: &eventv1.AuditLogQueryFilter{
|
||||
Timefrom: "now-" + timefrom,
|
||||
},
|
||||
}
|
||||
|
||||
mock.ExpectQuery(regexp.QuoteMeta(`SELECT "auditlog"."tag", "auditlog"."time", "auditlog"."data" FROM "audit_logs" AS "auditlog" WHERE (tag = '` + tag + `') AND (data->>'project' = '` + project + `') AND (to_timestamp(data->>'timestamp', 'YYYY-MM-DD"T"HH:MI:SS') between now() - interval '` + timefrom + `' and now())`)).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"tag", "time", "data"}).AddRow(tag, time.Now(), auditrecord).AddRow(tag, time.Now(), auditrecordtwo))
|
||||
|
||||
mock.ExpectQuery(regexp.QuoteMeta(`SELECT count(1) as count, data->>'project' as key FROM "audit_logs" WHERE (tag = '` + tag + `') AND (data->>'project' = '` + project + `') AND (to_timestamp(data->>'timestamp', 'YYYY-MM-DD"T"HH:MI:SS') between now() - interval '` + timefrom + `' and now()) GROUP BY data->>'project'`)).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count", "key"}).AddRow(1, "project"))
|
||||
|
||||
mock.ExpectQuery(regexp.QuoteMeta(`SELECT count(1) as count, data->'actor'->'account'->>'username' as key FROM "audit_logs" WHERE (tag = '` + tag + `') AND (data->>'project' = '` + project + `') AND (to_timestamp(data->>'timestamp', 'YYYY-MM-DD"T"HH:MI:SS') between now() - interval '` + timefrom + `' and now()) GROUP BY data->'actor'->'account'->>'username'`)).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count", "key"}).AddRow(1, "username"))
|
||||
|
||||
mock.ExpectQuery(regexp.QuoteMeta(`SELECT count(1) as count, data->>'type' as key FROM "audit_logs" WHERE (tag = '` + tag + `') AND (data->>'project' = '` + project + `') AND (to_timestamp(data->>'timestamp', 'YYYY-MM-DD"T"HH:MI:SS') between now() - interval '` + timefrom + `' and now()) GROUP BY data->>'type'`)).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count", "key"}).AddRow(1, "type"))
|
||||
|
||||
res, err := as.GetAuditLog(req)
|
||||
if err != nil {
|
||||
t.Fatal("could not get audit logs:", err)
|
||||
}
|
||||
|
||||
var response auditv1.AuditResponse
|
||||
data, err := json.Marshal(res.Result)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = json.Unmarshal(data, &response)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(response.GetHits().Hits) != 2 {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testGetKubectlCommands(tag string) func(t *testing.T) {
|
||||
return func(t *testing.T) {
|
||||
|
||||
db, mock := getDB(t)
|
||||
defer db.Close()
|
||||
|
||||
as, err := NewAuditLogDatabaseService(db, tag)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
timefrom := "1d"
|
||||
auditrecord := "{\"actor\":{\"account\":{\"username\":\"admin@paralus.local\"},\"groups\":[\"All Local Users\",\"Organization Admins\"],\"type\":\"USER\"},\"category\":\"AUDIT\",\"client\":{\"host\":\"console-ic-oss.dev.rafay-edge.net\",\"ip\":\"122.50.194.215\",\"type\":\"BROWSER\",\"user_agent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36\"},\"detail\":{\"message\":\"kubectl get all\",\"meta\":{\"cluster_name\":\"kind-local\"}},\"origin\":\"cluster\",\"portal\":\"ADMIN\",\"project\":\"stage\",\"timestamp\":\"2022-11-21T09:46:30.854455438Z\",\"type\":\"kubectl.command.detail\",\"version\":\"1.0\"}"
|
||||
auditrecordtwo := "{\"actor\":{\"account\":{\"username\":\"admin@paralus.local\"},\"groups\":[\"All Local Users\",\"Organization Admins\"],\"type\":\"USER\"},\"category\":\"AUDIT\",\"client\":{\"host\":\"console-ic-oss.dev.rafay-edge.net\",\"ip\":\"122.50.194.215\",\"type\":\"BROWSER\",\"user_agent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36\"},\"detail\":{\"message\":\"kubectl get all\",\"meta\":{\"cluster_name\":\"kind-local\"}},\"origin\":\"cluster\",\"portal\":\"ADMIN\",\"project\":\"stage\",\"timestamp\":\"2022-11-21T09:46:30.854455438Z\",\"type\":\"kubectl.command.detail\",\"version\":\"1.0\"}"
|
||||
|
||||
req := &eventv1.GetAuditLogSearchRequest{
|
||||
Metadata: &commonv3.Metadata{
|
||||
UrlScope: "auditlogs/" + project,
|
||||
},
|
||||
Filter: &eventv1.AuditLogQueryFilter{
|
||||
Timefrom: "now-" + timefrom,
|
||||
},
|
||||
}
|
||||
|
||||
mock.ExpectQuery(regexp.QuoteMeta(`SELECT "auditlog"."tag", "auditlog"."time", "auditlog"."data" FROM "audit_logs" AS "auditlog" WHERE (tag = '` + tag + `') AND (data->>'project' = '` + project + `') AND (to_timestamp(data->>'timestamp', 'YYYY-MM-DD"T"HH:MI:SS') between now() - interval '` + timefrom + `' and now())`)).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"tag", "time", "data"}).AddRow(tag, time.Now(), auditrecord).AddRow(tag, time.Now(), auditrecordtwo))
|
||||
|
||||
mock.ExpectQuery(regexp.QuoteMeta(`SELECT count(1) as count, data->>'project' as key FROM "audit_logs" WHERE (tag = '` + tag + `') AND (data->>'project' = '` + project + `') AND (to_timestamp(data->>'timestamp', 'YYYY-MM-DD"T"HH:MI:SS') between now() - interval '` + timefrom + `' and now()) GROUP BY data->>'project'`)).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count", "key"}).AddRow(1, "project"))
|
||||
|
||||
mock.ExpectQuery(regexp.QuoteMeta(`SELECT count(1) as count, data->'actor'->'account'->>'username' as key FROM "audit_logs" WHERE (tag = '` + tag + `') AND (data->>'project' = '` + project + `') AND (to_timestamp(data->>'timestamp', 'YYYY-MM-DD"T"HH:MI:SS') between now() - interval '` + timefrom + `' and now()) GROUP BY data->'actor'->'account'->>'username'`)).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count", "key"}).AddRow(1, "username"))
|
||||
|
||||
mock.ExpectQuery(regexp.QuoteMeta(`SELECT count(1) as count, data->>'type' as key FROM "audit_logs" WHERE (tag = '` + tag + `') AND (data->>'project' = '` + project + `') AND (to_timestamp(data->>'timestamp', 'YYYY-MM-DD"T"HH:MI:SS') between now() - interval '` + timefrom + `' and now()) GROUP BY data->>'type'`)).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count", "key"}).AddRow(1, "type"))
|
||||
|
||||
res, err := as.GetAuditLog(req)
|
||||
if err != nil {
|
||||
t.Fatal("could not get audit logs:", err)
|
||||
}
|
||||
|
||||
var response auditv1.AuditResponse
|
||||
data, err := json.Marshal(res.Result)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = json.Unmarshal(data, &response)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(response.GetHits().Hits) != 2 {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -88,7 +88,10 @@ func (ra *relayAuditDatabaseService) GetRelayAuditByProjects(req *v1.RelayAuditR
|
||||
}
|
||||
|
||||
var resMap map[string]interface{}
|
||||
data, _ := json.Marshal(response)
|
||||
data, err := json.Marshal(response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
json.Unmarshal(data, &resMap)
|
||||
|
||||
result, _ := structpb.NewStruct(resMap)
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"regexp"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/DATA-DOG/go-sqlmock"
|
||||
"github.com/paralus/paralus/pkg/audit"
|
||||
eventv1 "github.com/paralus/paralus/proto/rpc/audit"
|
||||
auditv1 "github.com/paralus/paralus/proto/types/audit"
|
||||
commonv3 "github.com/paralus/paralus/proto/types/commonpb/v3"
|
||||
)
|
||||
|
||||
func TestRelayAuditLog(t *testing.T) {
|
||||
|
||||
testcases := []struct {
|
||||
name string
|
||||
run func(t *testing.T)
|
||||
}{
|
||||
{
|
||||
name: "auditlog-kubectlapi-kind",
|
||||
run: testGetRelayAuditLogForKind(audit.KUBECTL_API),
|
||||
},
|
||||
{
|
||||
name: "auditlog-kubectlapi-cluster",
|
||||
run: testGetRelayAuditLogForCluster(audit.KUBECTL_API),
|
||||
},
|
||||
}
|
||||
|
||||
t.Run("relayauditlogs", func(t *testing.T) {
|
||||
for _, testcase := range testcases {
|
||||
tc := testcase
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
tc.run(t)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func testGetRelayAuditLogForCluster(tag string) func(t *testing.T) {
|
||||
return func(t *testing.T) {
|
||||
|
||||
db, mock := getDB(t)
|
||||
defer db.Close()
|
||||
|
||||
ras, err := NewRelayAuditDatabaseService(db, tag)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
timefrom := "1h"
|
||||
auditrecord := "{\"av\":\"flowcontrol.apiserver.k8s.io/v1beta2\",\"cn\":\"kind-2\",\"d\": 0.492472386,\"id\":\"cduajnic6p9tna60re3g\",\"k\":\"\",\"m\": \"GET\", \"n\": \"\", \"ns\": \"\", \"o\": \"9fcdf482-6191-44f1-987a-8469addf2566\", \"p\": \"ba184458-b899-4cf3-99fa-d77a21578ede\", \"q\": \"timeout=32s\", \"ra\": \"10.0.0.147\", \"sc\": 200, \"st\": \"browser shell\", \"ts\": \"2022-11-22T10:52:14.987Z\", \"un\": \"admin@paralus.local\", \"url\": \"/apis/flowcontrol.apiserver.k8s.io/v1beta2\", \"w\": 819 }\""
|
||||
|
||||
req := &eventv1.RelayAuditRequest{
|
||||
Metadata: &commonv3.Metadata{
|
||||
UrlScope: "auditlogs/" + project,
|
||||
},
|
||||
Filter: &eventv1.RelayAuditQueryFilter{
|
||||
Cluster: "kind-2",
|
||||
Timefrom: "now-" + timefrom,
|
||||
},
|
||||
}
|
||||
|
||||
mock.ExpectQuery(regexp.QuoteMeta(`SELECT "auditlog"."tag", "auditlog"."time", "auditlog"."data" FROM "audit_logs" AS "auditlog" WHERE (tag = '` + tag + `') AND (data->>'cn' = '` + req.Filter.Cluster + `') AND (to_timestamp(data->>'ts', 'YYYY-MM-DD"T"HH:MI:SS') between now() - interval '` + timefrom + `' and now())`)).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"tag", "time", "data"}).AddRow(tag, time.Now(), auditrecord))
|
||||
|
||||
mock.ExpectQuery(regexp.QuoteMeta(`SELECT count(1) as count, data->>'cn' as key FROM "audit_logs" WHERE (tag = '` + tag + `') AND (data->>'cn' = '` + req.Filter.Cluster + `') AND (to_timestamp(data->>'ts', 'YYYY-MM-DD"T"HH:MI:SS') between now() - interval '` + timefrom + `' and now()) GROUP BY data->>'cn'`)).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count", "key"}).AddRow(1, "cluster"))
|
||||
|
||||
mock.ExpectQuery(regexp.QuoteMeta(`SELECT count(1) as count, data->>'un' as key FROM "audit_logs" WHERE (tag = '` + tag + `') AND (data->>'cn' = '` + req.Filter.Cluster + `') AND (to_timestamp(data->>'ts', 'YYYY-MM-DD"T"HH:MI:SS') between now() - interval '` + timefrom + `' and now()) GROUP BY data->>'un'`)).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count", "key"}).AddRow(1, "username"))
|
||||
|
||||
mock.ExpectQuery(regexp.QuoteMeta(`SELECT count(1) as count, data->>'n' as key FROM "audit_logs" WHERE (tag = '` + tag + `') AND (data->>'cn' = '` + req.Filter.Cluster + `') AND (to_timestamp(data->>'ts', 'YYYY-MM-DD"T"HH:MI:SS') between now() - interval '` + timefrom + `' and now()) GROUP BY data->>'n'`)).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count", "key"}).AddRow(1, "namespace"))
|
||||
|
||||
mock.ExpectQuery(regexp.QuoteMeta(`SELECT count(1) as count, data->>'k' as key FROM "audit_logs" WHERE (tag = '` + tag + `') AND (data->>'cn' = '` + req.Filter.Cluster + `') AND (to_timestamp(data->>'ts', 'YYYY-MM-DD"T"HH:MI:SS') between now() - interval '` + timefrom + `' and now()) GROUP BY data->>'k'`)).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count", "key"}).AddRow(1, "kind"))
|
||||
|
||||
mock.ExpectQuery(regexp.QuoteMeta(`SELECT count(1) as count, data->>'m' as key FROM "audit_logs" WHERE (tag = '` + tag + `') AND (data->>'cn' = '` + req.Filter.Cluster + `') AND (to_timestamp(data->>'ts', 'YYYY-MM-DD"T"HH:MI:SS') between now() - interval '` + timefrom + `' and now()) GROUP BY data->>'m'`)).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count", "key"}).AddRow(1, "method"))
|
||||
|
||||
res, err := ras.GetRelayAudit(req)
|
||||
if err != nil {
|
||||
t.Fatal("could not get audit logs:", err)
|
||||
}
|
||||
|
||||
var response auditv1.AuditResponse
|
||||
data, err := json.Marshal(res.Result)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = json.Unmarshal(data, &response)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(response.GetHits().Hits) != 1 {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testGetRelayAuditLogForKind(tag string) func(t *testing.T) {
|
||||
return func(t *testing.T) {
|
||||
|
||||
db, mock := getDB(t)
|
||||
defer db.Close()
|
||||
|
||||
as, err := NewRelayAuditDatabaseService(db, tag)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
timefrom := "1d"
|
||||
auditrecord := "{\"av\":\"flowcontrol.apiserver.k8s.io/v1beta2\",\"cn\":\"kind-2\",\"d\": 0.492472386,\"id\":\"cduajnic6p9tna60re3g\",\"k\":\"namespace\",\"m\": \"GET\", \"n\": \"\", \"ns\": \"\", \"o\": \"9fcdf482-6191-44f1-987a-8469addf2566\", \"p\": \"ba184458-b899-4cf3-99fa-d77a21578ede\", \"q\": \"timeout=32s\", \"ra\": \"10.0.0.147\", \"sc\": 200, \"st\": \"browser shell\", \"ts\": \"2022-11-22T10:52:14.987Z\", \"un\": \"admin@paralus.local\", \"url\": \"/apis/flowcontrol.apiserver.k8s.io/v1beta2\", \"w\": 819 }\""
|
||||
auditrecordtwo := "{\"av\":\"flowcontrol.apiserver.k8s.io/v1beta2\",\"cn\":\"kind-2\",\"d\": 0.492472386,\"id\":\"cduajnic6p9tna60re3g\",\"k\":\"namespace\",\"m\": \"GET\", \"n\": \"\", \"ns\": \"\", \"o\": \"9fcdf482-6191-44f1-987a-8469addf2566\", \"p\": \"ba184458-b899-4cf3-99fa-d77a21578ede\", \"q\": \"timeout=32s\", \"ra\": \"10.0.0.147\", \"sc\": 200, \"st\": \"browser shell\", \"ts\": \"2022-11-22T10:52:14.987Z\", \"un\": \"admin@paralus.local\", \"url\": \"/apis/flowcontrol.apiserver.k8s.io/v1beta2\", \"w\": 819 }\""
|
||||
|
||||
req := &eventv1.RelayAuditRequest{
|
||||
Metadata: &commonv3.Metadata{
|
||||
UrlScope: "auditlogs/" + project,
|
||||
},
|
||||
Filter: &eventv1.RelayAuditQueryFilter{
|
||||
Kind: "namespace",
|
||||
Timefrom: "now-" + timefrom,
|
||||
},
|
||||
}
|
||||
|
||||
mock.ExpectQuery(regexp.QuoteMeta(`SELECT "auditlog"."tag", "auditlog"."time", "auditlog"."data" FROM "audit_logs" AS "auditlog" WHERE (tag = '` + tag + `') AND (data->>'k' = '` + req.Filter.Kind + `') AND (to_timestamp(data->>'ts', 'YYYY-MM-DD"T"HH:MI:SS') between now() - interval '` + timefrom + `' and now())`)).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"tag", "time", "data"}).AddRow(tag, time.Now(), auditrecord).AddRow(tag, time.Now(), auditrecordtwo))
|
||||
|
||||
mock.ExpectQuery(regexp.QuoteMeta(`SELECT count(1) as count, data->>'cn' as key FROM "audit_logs" WHERE (tag = '` + tag + `') AND (data->>'k' = '` + req.Filter.Kind + `') AND (to_timestamp(data->>'ts', 'YYYY-MM-DD"T"HH:MI:SS') between now() - interval '` + timefrom + `' and now()) GROUP BY data->>'cn'`)).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count", "key"}).AddRow(1, "cluster"))
|
||||
|
||||
mock.ExpectQuery(regexp.QuoteMeta(`SELECT count(1) as count, data->>'un' as key FROM "audit_logs" WHERE (tag = '` + tag + `') AND (data->>'k' = '` + req.Filter.Kind + `') AND (to_timestamp(data->>'ts', 'YYYY-MM-DD"T"HH:MI:SS') between now() - interval '` + timefrom + `' and now()) GROUP BY data->>'un'`)).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count", "key"}).AddRow(1, "username"))
|
||||
|
||||
mock.ExpectQuery(regexp.QuoteMeta(`SELECT count(1) as count, data->>'n' as key FROM "audit_logs" WHERE (tag = '` + tag + `') AND (data->>'k' = '` + req.Filter.Kind + `') AND (to_timestamp(data->>'ts', 'YYYY-MM-DD"T"HH:MI:SS') between now() - interval '` + timefrom + `' and now()) GROUP BY data->>'n'`)).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count", "key"}).AddRow(1, "namespace"))
|
||||
|
||||
mock.ExpectQuery(regexp.QuoteMeta(`SELECT count(1) as count, data->>'k' as key FROM "audit_logs" WHERE (tag = '` + tag + `') AND (data->>'k' = '` + req.Filter.Kind + `') AND (to_timestamp(data->>'ts', 'YYYY-MM-DD"T"HH:MI:SS') between now() - interval '` + timefrom + `' and now()) GROUP BY data->>'k'`)).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count", "key"}).AddRow(1, "kind"))
|
||||
|
||||
mock.ExpectQuery(regexp.QuoteMeta(`SELECT count(1) as count, data->>'m' as key FROM "audit_logs" WHERE (tag = '` + tag + `') AND (data->>'k' = '` + req.Filter.Kind + `') AND (to_timestamp(data->>'ts', 'YYYY-MM-DD"T"HH:MI:SS') between now() - interval '` + timefrom + `' and now()) GROUP BY data->>'m'`)).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count", "key"}).AddRow(1, "method"))
|
||||
|
||||
res, err := as.GetRelayAudit(req)
|
||||
if err != nil {
|
||||
t.Fatal("could not get audit logs:", err)
|
||||
}
|
||||
|
||||
var response auditv1.AuditResponse
|
||||
data, err := json.Marshal(res.Result)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = json.Unmarshal(data, &response)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(response.GetHits().Hits) != 2 {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user