Skip to content

Commit

Permalink
feat: add support for artifacts
Browse files Browse the repository at this point in the history
  • Loading branch information
ayoubfaouzi committed May 7, 2024
1 parent 0636142 commit 2d39c38
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 1 deletion.
36 changes: 36 additions & 0 deletions internal/behavior/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ func RegisterHandlers(g *echo.Group, service Service,
g.GET("/behaviors/:id/", res.get, verifyID)
g.GET("/behaviors/:id/api-trace/", res.apis, verifyID)
g.GET("/behaviors/:id/sys-events/", res.events, verifyID)
g.GET("/behaviors/:id/artifacts/", res.artifacts, verifyID)

}

Expand Down Expand Up @@ -138,6 +139,41 @@ func (r resource) events(c echo.Context) error {
return c.JSON(http.StatusOK, pages)
}

// @Summary List of artifacts' metadata.
// @Description Returns a paginated list of artifacts' metadata such as memdumps, created files, etc ..
// @Tags Behavior
// @Param id path string true "Behavior report GUID"
// @Success 200 {object} object{}
// @Failure 400 {object} errors.ErrorResponse
// @Failure 500 {object} errors.ErrorResponse
// @Router /behaviors/{id}/artifacts/ [get]
func (r resource) artifacts(c echo.Context) error {
ctx := c.Request().Context()

if len(c.QueryParams()) > 0 {
queryParams := c.QueryParams()
delete(queryParams, pagination.PageSizeVar)
delete(queryParams, pagination.PageVar)
if len(queryParams) > 0 {
ctx = WithFilters(ctx, queryParams)
}
}

count, err := r.service.CountArtifacts(ctx, c.Param("id"))
if err != nil {
return err
}

pages := pagination.NewFromRequest(c.Request(), count)
events, err := r.service.Artifacts(
ctx, c.Param("id"), pages.Offset(), pages.Limit())
if err != nil {
return err
}
pages.Items = events
return c.JSON(http.StatusOK, pages)
}

// WithFilters returns a context that contains the API filters.
func WithFilters(ctx context.Context, value map[string][]string) context.Context {
return context.WithValue(ctx, filtersKey, value)
Expand Down
61 changes: 60 additions & 1 deletion internal/behavior/repostitory.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@ type Repository interface {

CountAPIs(ctx context.Context, id string) (int, error)
CountEvents(ctx context.Context, id string) (int, error)
CountArtifacts(ctx context.Context, id string) (int, error)
APIs(ctx context.Context, id string, offset, limit int) (
interface{}, error)
Events(ctx context.Context, id string, offset, limit int) (
interface{}, error)
Artifacts(ctx context.Context, id string, offset, limit int) (interface{}, error)
}

// repository persists file scan behaviors in database.
Expand Down Expand Up @@ -122,7 +124,7 @@ func (r repository) Query(ctx context.Context, offset, limit int) (
return behaviors, nil
}

// CountStrings returns the number of strings in a file doc in the database.
// CountAPIs returns the number of API calls for a behavior doc in the database.
func (r repository) CountAPIs(ctx context.Context, id string) (int, error) {
var count int
var statement string
Expand Down Expand Up @@ -155,6 +157,20 @@ func (r repository) CountAPIs(ctx context.Context, id string) (int, error) {
return count, err
}

// CountArtifacts returns the number of artifacts.
func (r repository) CountArtifacts(ctx context.Context, id string) (int, error) {
var count int
var statement string
params := make(map[string]interface{}, 1)
params["id"] = id
statement =
"SELECT RAW ARRAY_LENGTH(d.artifacts) AS count FROM `" + r.db.Bucket.Name() + "` d" +
" USE KEYS $id"

err := r.db.Count(ctx, statement, params, &count)
return count, err
}

// CountEvents returns the number of strings in a file doc in the database.
func (r repository) CountEvents(ctx context.Context, id string) (int, error) {
var count int
Expand Down Expand Up @@ -274,3 +290,46 @@ func (r repository) Events(ctx context.Context, id string, offset,
}
return results.([]interface{}), nil
}

func (r repository) Artifacts(ctx context.Context, id string, offset,
limit int) (interface{}, error) {

var results interface{}
var statement string

params := make(map[string]interface{}, 1)
params["offset"] = offset
params["limit"] = limit
params["id"] = id
statement =
"SELECT RAW artifacts FROM `" + r.db.Bucket.Name() + "` d" +
" USE KEYS $id UNNEST d.artifacts as artifacts"

filters, ok := ctx.Value(filtersKey).(map[string][]string)
if ok {

i := 0
for k, v := range filters {
if i == 0 {
statement += " WHERE"
} else {
statement += " AND"
}
i++
statement += fmt.Sprintf(" artifacts.%s IN $%s", k, k)
params[k] = v
}
}

statement += " OFFSET $offset LIMIT $limit"
err := r.db.Query(ctx, statement, params, &results)
if err != nil {
return nil, err
}
if len(results.([]interface{})) == 0 {
return results, nil
} else if len(results.([]interface{})) == 1 {
return results.([]interface{})[0], nil
}
return results.([]interface{}), nil
}
20 changes: 20 additions & 0 deletions internal/behavior/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ type Service interface {
Exists(ctx context.Context, id string) (bool, error)
Count(ctx context.Context) (int, error)
CountAPIs(ctx context.Context, id string) (int, error)
CountArtifacts(ctx context.Context, id string) (int, error)
CountEvents(ctx context.Context, id string) (int, error)
Artifacts(ctx context.Context, id string, offset, limit int) (interface{}, error)
APIs(ctx context.Context, id string, offset, limit int) (interface{}, error)
Events(ctx context.Context, id string, offset, limit int) (interface{}, error)
}
Expand Down Expand Up @@ -91,3 +93,21 @@ func (s service) Events(ctx context.Context, id string, offset, limit int) (
}
return result, nil
}

func (s service) CountArtifacts(ctx context.Context, id string) (int, error) {
count, err := s.repo.CountArtifacts(ctx, id)
if err != nil {
return 0, err
}
return count, err
}

func (s service) Artifacts(ctx context.Context, id string, offset, limit int) (
interface{}, error) {

result, err := s.repo.Artifacts(ctx, id, offset, limit)
if err != nil {
return nil, err
}
return result, nil
}
1 change: 1 addition & 0 deletions internal/entity/behavior.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ type Behavior struct {
Timestamp int64 `json:"timestamp,omitempty"`
Environment interface{} `json:"env,omitempty"`
APITrace interface{} `json:"api_trace,omitempty"`
Artifacts interface{} `json:"artifacts,omitempty"`
SystemEvents interface{} `json:"sys_events,omitempty"`
ProcessTree interface{} `json:"proc_tree,omitempty"`
Capabilities interface{} `json:"capabilities,omitempty"`
Expand Down

0 comments on commit 2d39c38

Please sign in to comment.