mirror of
https://github.com/paralus/paralus.git
synced 2026-08-21 04:16:20 +00:00
feat: changes to view audit logs by project and cluster role users --------- Signed-off-by: niravparikh05 <nir.parikh05@gmail.com>
181 lines
6.6 KiB
Go
181 lines
6.6 KiB
Go
package service
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"regexp"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/DATA-DOG/go-sqlmock"
|
|
"github.com/google/uuid"
|
|
"github.com/paralus/paralus/pkg/common"
|
|
v1 "github.com/paralus/paralus/proto/rpc/audit"
|
|
v3 "github.com/paralus/paralus/proto/types/commonpb/v3"
|
|
)
|
|
|
|
type md struct {
|
|
Source []string `json:"_source"`
|
|
Aggs struct {
|
|
GroupByProject struct {
|
|
Aggs struct {
|
|
GroupByType struct {
|
|
Terms struct {
|
|
Field string `json:"field"`
|
|
Size int `json:"size"`
|
|
} `json:"terms"`
|
|
} `json:"group_by_type"`
|
|
GroupByUsername struct {
|
|
Terms struct {
|
|
Field string `json:"field"`
|
|
Size int `json:"size"`
|
|
} `json:"terms"`
|
|
} `json:"group_by_username"`
|
|
} `json:"aggs"`
|
|
Terms struct {
|
|
Field string `json:"field"`
|
|
Size int `json:"size"`
|
|
} `json:"terms"`
|
|
} `json:"group_by_project"`
|
|
GroupByType struct {
|
|
Terms struct {
|
|
Field string `json:"field"`
|
|
} `json:"terms"`
|
|
} `json:"group_by_type"`
|
|
GroupByUsername struct {
|
|
Terms struct {
|
|
Field string `json:"field"`
|
|
} `json:"terms"`
|
|
} `json:"group_by_username"`
|
|
} `json:"aggs"`
|
|
Query struct {
|
|
Bool struct {
|
|
Filter struct {
|
|
Range struct {
|
|
JSONTimestamp struct {
|
|
Gte string `json:"gte"`
|
|
Lt string `json:"lt"`
|
|
} `json:"json.timestamp"`
|
|
} `json:"range"`
|
|
} `json:"filter"`
|
|
Must []struct {
|
|
Term struct {
|
|
JSONCategory string `json:"json.category"`
|
|
} `json:"term,omitempty"`
|
|
Terms struct {
|
|
JSONProject []string `json:"json.project"`
|
|
} `json:"terms,omitempty"`
|
|
QueryString struct {
|
|
Query string `json:"query"`
|
|
} `json:"query_string,omitempty"`
|
|
} `json:"must"`
|
|
} `json:"bool"`
|
|
} `json:"query"`
|
|
Size int `json:"size"`
|
|
Sort struct {
|
|
JSONTimestamp struct {
|
|
Order string `json:"order"`
|
|
} `json:"json.timestamp"`
|
|
} `json:"sort"`
|
|
}
|
|
|
|
type mockElasticSearchQuery struct {
|
|
msg []bytes.Buffer
|
|
}
|
|
|
|
func (m *mockElasticSearchQuery) Handle(msg bytes.Buffer) (map[string]interface{}, error) {
|
|
m.msg = append(m.msg, msg)
|
|
return map[string]interface{}{}, nil
|
|
}
|
|
|
|
func TestGetAuditLogByProjectsSimple(t *testing.T) {
|
|
|
|
db, mock := getDB(t)
|
|
defer db.Close()
|
|
|
|
esq := &mockElasticSearchQuery{}
|
|
al := &auditLogElasticSearchService{auditQuery: esq, db: db}
|
|
req := v1.GetAuditLogSearchRequest{
|
|
Filter: &v1.AuditLogQueryFilter{
|
|
QueryString: "query-string",
|
|
Projects: []string{"project-one", "project-two"},
|
|
Timefrom: "now-1h",
|
|
Type: "fake-type",
|
|
User: "fake-user",
|
|
Client: "fake-client",
|
|
DashboardData: true,
|
|
},
|
|
}
|
|
uuid := uuid.New().String()
|
|
mock.ExpectQuery(regexp.QuoteMeta(`SELECT "sap"."account_id", "sap"."project_id", "sap"."group_id", "sap"."role_id", "sap"."role_name", "sap"."organization_id", "sap"."partner_id", "sap"."is_global", "sap"."scope", "sap"."permission_name", "sap"."base_url", "sap"."urls" FROM "sentry_account_permission" AS "sap" WHERE (account_id = '` + uuid + `') AND (partner_id = '` + uuid + `') AND (lower(role_name) = 'admin') AND (lower(scope) = 'organization')`)).
|
|
WillReturnRows(sqlmock.NewRows([]string{"account_id", "role_name", "scope"}).AddRow(uuid, "admin", "organization"))
|
|
|
|
sd := v3.SessionData{
|
|
Account: uuid,
|
|
Organization: uuid,
|
|
Partner: uuid,
|
|
Username: "user",
|
|
}
|
|
ctx := context.WithValue(context.Background(), common.SessionDataKey, &sd)
|
|
|
|
_, err := al.GetAuditLogByProjects(ctx, &req)
|
|
if err != nil {
|
|
t.Error("unable to get audit logs")
|
|
}
|
|
if len(esq.msg) != 1 {
|
|
t.Fatalf("incorrect number of searches; expected '%v', got '%v'", 1, len(esq.msg))
|
|
}
|
|
m := &md{}
|
|
err = json.Unmarshal(esq.msg[0].Bytes(), m)
|
|
if err != nil {
|
|
t.Fatal("unable to unmarshall es request")
|
|
}
|
|
expected := `{"_source":["json"],"aggs":{"group_by_project":{"aggs":{"group_by_type":{"terms":{"field":"json.type","size":1000}},"group_by_username":{"terms":{"field":"json.actor.account.username","size":1000}}},"terms":{"field":"json.project","size":1000}},"group_by_type":{"terms":{"field":"json.type"}},"group_by_username":{"terms":{"field":"json.actor.account.username"}}},"query":{"bool":{"filter":{"range":{"json.timestamp":{"gte":"now-1h","lt":"now"}}},"must":[{"term":{"json.category":"AUDIT"}},{"term":{"json.type":"fake-type"}},{"term":{"json.actor.account.username":"fake-user"}},{"term":{"json.client.type":"fake-client"}},{"terms":{"json.project":["project-one","project-two"]}},{"query_string":{"query":"query-string"}}]}},"size":0,"sort":{"json.timestamp":{"order":"desc"}}}`
|
|
if strings.TrimSpace(esq.msg[0].String()) != expected {
|
|
t.Errorf("incorrect es query; expected '%v', got '%v'", expected, strings.TrimSpace(esq.msg[0].String()))
|
|
}
|
|
}
|
|
|
|
func TestGetAuditLogByProjectsNoProject(t *testing.T) {
|
|
db, mock := getDB(t)
|
|
defer db.Close()
|
|
|
|
esq := &mockElasticSearchQuery{}
|
|
al := &auditLogElasticSearchService{auditQuery: esq, db: db}
|
|
req := v1.GetAuditLogSearchRequest{
|
|
Metadata: &v3.Metadata{UrlScope: "url/project"},
|
|
Filter: &v1.AuditLogQueryFilter{
|
|
QueryString: "query-string",
|
|
},
|
|
}
|
|
uuid := uuid.New().String()
|
|
mock.ExpectQuery(regexp.QuoteMeta(`SELECT "sap"."account_id", "sap"."project_id", "sap"."group_id", "sap"."role_id", "sap"."role_name", "sap"."organization_id", "sap"."partner_id", "sap"."is_global", "sap"."scope", "sap"."permission_name", "sap"."base_url", "sap"."urls" FROM "sentry_account_permission" AS "sap" WHERE (account_id = '` + uuid + `') AND (partner_id = '` + uuid + `') AND (lower(role_name) = 'admin') AND (lower(scope) = 'organization')`)).
|
|
WillReturnRows(sqlmock.NewRows([]string{"account_id", "role_name", "scope"}).AddRow(uuid, "admin", "organization"))
|
|
|
|
sd := v3.SessionData{
|
|
Account: uuid,
|
|
Organization: uuid,
|
|
Partner: uuid,
|
|
Username: "user",
|
|
}
|
|
ctx := context.WithValue(context.Background(), common.SessionDataKey, &sd)
|
|
_, err := al.GetAuditLog(ctx, &req)
|
|
if err != nil {
|
|
t.Error("unable to get audit logs", err)
|
|
}
|
|
if len(esq.msg) != 1 {
|
|
t.Fatalf("incorrect number of searches; expected '%v', got '%v'", 1, len(esq.msg))
|
|
}
|
|
m := &md{}
|
|
err = json.Unmarshal(esq.msg[0].Bytes(), m)
|
|
if err != nil {
|
|
t.Fatal("unable to unmarshall es request")
|
|
}
|
|
|
|
expected := `{"_source":["json"],"aggs":{"group_by_type":{"terms":{"field":"json.type"}},"group_by_username":{"terms":{"field":"json.actor.account.username"}}},"query":{"bool":{"must":[{"term":{"json.category":"AUDIT"}},{"terms":{"json.project":["project"]}},{"query_string":{"query":"query-string"}}]}},"size":500,"sort":{"json.timestamp":{"order":"desc"}}}`
|
|
if strings.TrimSpace(esq.msg[0].String()) != expected {
|
|
t.Errorf("incorrect es query; expected '%v', got '%v'", expected, strings.TrimSpace(esq.msg[0].String()))
|
|
}
|
|
}
|