Release catalyst

This commit is contained in:
Jonas Plum
2021-12-13 00:39:15 +01:00
commit 15cf0ebd49
339 changed files with 111677 additions and 0 deletions

34
service/artifact.go Normal file
View File

@@ -0,0 +1,34 @@
package service
import (
"context"
"github.com/google/uuid"
"github.com/SecurityBrewery/catalyst/generated/models"
"github.com/SecurityBrewery/catalyst/generated/restapi/api"
"github.com/SecurityBrewery/catalyst/generated/restapi/operations/tickets"
)
func (s *Service) RunArtifact(ctx context.Context, params *tickets.RunArtifactParams) *api.Response {
artifact, err := s.database.ArtifactGet(ctx, params.ID, params.Name)
if err != nil {
return response(nil, err)
}
jobID := uuid.NewString()
origin := &models.Origin{ArtifactOrigin: &models.ArtifactOrigin{TicketId: params.ID, Artifact: params.Name}}
return response(nil, s.bus.PublishJob(jobID, params.Automation, params.Name, &models.Context{Artifact: artifact}, origin))
}
func (s *Service) EnrichArtifact(ctx context.Context, params *tickets.EnrichArtifactParams) *api.Response {
return response(s.database.EnrichArtifact(ctx, params.ID, params.Name, params.Data))
}
func (s *Service) SetArtifact(ctx context.Context, params *tickets.SetArtifactParams) *api.Response {
return response(s.database.ArtifactUpdate(ctx, params.ID, params.Name, params.Artifact))
}
func (s *Service) GetArtifact(ctx context.Context, params *tickets.GetArtifactParams) *api.Response {
return response(s.database.ArtifactGet(ctx, params.ID, params.Name))
}

28
service/automation.go Normal file
View File

@@ -0,0 +1,28 @@
package service
import (
"context"
"github.com/SecurityBrewery/catalyst/generated/restapi/api"
"github.com/SecurityBrewery/catalyst/generated/restapi/operations/automations"
)
func (s *Service) CreateAutomation(ctx context.Context, params *automations.CreateAutomationParams) *api.Response {
return response(s.database.AutomationCreate(ctx, params.Automation))
}
func (s *Service) GetAutomation(ctx context.Context, params *automations.GetAutomationParams) *api.Response {
return response(s.database.AutomationGet(ctx, params.ID))
}
func (s *Service) UpdateAutomation(ctx context.Context, params *automations.UpdateAutomationParams) *api.Response {
return response(s.database.AutomationUpdate(ctx, params.ID, params.Automation))
}
func (s *Service) DeleteAutomation(ctx context.Context, params *automations.DeleteAutomationParams) *api.Response {
return response(nil, s.database.AutomationDelete(ctx, params.ID))
}
func (s *Service) ListAutomations(ctx context.Context) *api.Response {
return response(s.database.AutomationList(ctx))
}

29
service/job.go Normal file
View File

@@ -0,0 +1,29 @@
package service
import (
"context"
"github.com/google/uuid"
"github.com/SecurityBrewery/catalyst/generated/models"
"github.com/SecurityBrewery/catalyst/generated/restapi/api"
"github.com/SecurityBrewery/catalyst/generated/restapi/operations/jobs"
)
func (s *Service) RunJob(_ context.Context, params *jobs.RunJobParams) *api.Response {
msgContext := &models.Context{}
jobID := uuid.NewString()
return response(nil, s.bus.PublishJob(jobID, params.Job.Automation, params.Job.Payload, msgContext, params.Job.Origin))
}
func (s *Service) GetJob(ctx context.Context, params *jobs.GetJobParams) *api.Response {
return response(s.database.JobGet(ctx, params.ID))
}
func (s *Service) ListJobs(ctx context.Context) *api.Response {
return response(s.database.JobList(ctx))
}
func (s *Service) UpdateJob(ctx context.Context, params *jobs.UpdateJobParams) *api.Response {
return response(s.database.JobUpdate(ctx, params.ID, params.Job))
}

14
service/log.go Normal file
View File

@@ -0,0 +1,14 @@
package service
import (
"context"
"net/url"
"github.com/SecurityBrewery/catalyst/generated/restapi/api"
"github.com/SecurityBrewery/catalyst/generated/restapi/operations/logs"
)
func (s *Service) GetLogs(ctx context.Context, params *logs.GetLogsParams) *api.Response {
id, _ := url.QueryUnescape(params.Reference)
return response(s.database.LogList(ctx, id))
}

53
service/playbook.go Normal file
View File

@@ -0,0 +1,53 @@
package service
import (
"context"
"fmt"
"strings"
"github.com/xeipuuv/gojsonschema"
"github.com/SecurityBrewery/catalyst/generated/models"
"github.com/SecurityBrewery/catalyst/generated/restapi/api"
"github.com/SecurityBrewery/catalyst/generated/restapi/operations/playbooks"
)
func (s *Service) CreatePlaybook(ctx context.Context, params *playbooks.CreatePlaybookParams) *api.Response {
return response(s.database.PlaybookCreate(ctx, params.Playbook))
}
func (s *Service) GetPlaybook(ctx context.Context, params *playbooks.GetPlaybookParams) *api.Response {
return response(s.database.PlaybookGet(ctx, params.ID))
}
func (s *Service) UpdatePlaybook(ctx context.Context, params *playbooks.UpdatePlaybookParams) *api.Response {
if err := validate(params.Playbook, models.PlaybookTemplateFormSchema); err != nil {
return response(nil, err)
}
return response(s.database.PlaybookUpdate(ctx, params.ID, params.Playbook))
}
func (s *Service) DeletePlaybook(ctx context.Context, params *playbooks.DeletePlaybookParams) *api.Response {
return response(nil, s.database.PlaybookDelete(ctx, params.ID))
}
func (s *Service) ListPlaybooks(ctx context.Context) *api.Response {
return response(s.database.PlaybookList(ctx))
}
func validate(e interface{}, schema *gojsonschema.Schema) error {
res, err := schema.Validate(gojsonschema.NewGoLoader(e))
if err != nil {
return err
}
if len(res.Errors()) > 0 {
var l []string
for _, e := range res.Errors() {
l = append(l, e.String())
}
return fmt.Errorf("validation failed: %v", strings.Join(l, ", "))
}
return nil
}

51
service/service.go Normal file
View File

@@ -0,0 +1,51 @@
package service
import (
"errors"
"log"
"net/http"
"github.com/arangodb/go-driver"
"github.com/gin-gonic/gin"
"github.com/SecurityBrewery/catalyst/bus"
"github.com/SecurityBrewery/catalyst/database"
"github.com/SecurityBrewery/catalyst/generated/models"
"github.com/SecurityBrewery/catalyst/generated/restapi/api"
"github.com/SecurityBrewery/catalyst/storage"
)
type Service struct {
bus *bus.Bus
database *database.Database
settings *models.Settings
storage *storage.Storage
}
func New(bus *bus.Bus, database *database.Database, storage *storage.Storage, settings *models.Settings) (*Service, error) {
return &Service{database: database, bus: bus, settings: settings, storage: storage}, nil
}
func (s *Service) Healthy() bool {
return true
}
func response(v interface{}, err error) *api.Response {
if err != nil {
log.Println(err)
return &api.Response{Code: httpStatus(err), Body: gin.H{"error": err.Error()}}
}
if v == nil {
return &api.Response{Code: http.StatusNoContent, Body: v}
}
return &api.Response{Code: http.StatusOK, Body: v}
}
func httpStatus(err error) int {
ae := driver.ArangoError{}
if errors.As(err, &ae) {
return ae.Code
}
return http.StatusInternalServerError
}

11
service/statistics.go Normal file
View File

@@ -0,0 +1,11 @@
package service
import (
"context"
"github.com/SecurityBrewery/catalyst/generated/restapi/api"
)
func (s *Service) GetStatistics(ctx context.Context) *api.Response {
return response(s.database.Statistics(ctx))
}

11
service/task.go Normal file
View File

@@ -0,0 +1,11 @@
package service
import (
"context"
"github.com/SecurityBrewery/catalyst/generated/restapi/api"
)
func (s *Service) ListTasks(ctx context.Context) *api.Response {
return response(s.database.TaskList(ctx))
}

28
service/template.go Normal file
View File

@@ -0,0 +1,28 @@
package service
import (
"context"
"github.com/SecurityBrewery/catalyst/generated/restapi/api"
"github.com/SecurityBrewery/catalyst/generated/restapi/operations/templates"
)
func (s *Service) CreateTemplate(ctx context.Context, params *templates.CreateTemplateParams) *api.Response {
return response(s.database.TemplateCreate(ctx, params.Template))
}
func (s *Service) GetTemplate(ctx context.Context, params *templates.GetTemplateParams) *api.Response {
return response(s.database.TemplateGet(ctx, params.ID))
}
func (s *Service) UpdateTemplate(ctx context.Context, params *templates.UpdateTemplateParams) *api.Response {
return response(s.database.TemplateUpdate(ctx, params.ID, params.Template))
}
func (s *Service) DeleteTemplate(ctx context.Context, params *templates.DeleteTemplateParams) *api.Response {
return response(nil, s.database.TemplateDelete(ctx, params.ID))
}
func (s *Service) ListTemplates(ctx context.Context) *api.Response {
return response(s.database.TemplateList(ctx))
}

52
service/ticket.go Normal file
View File

@@ -0,0 +1,52 @@
package service
import (
"context"
"fmt"
"github.com/SecurityBrewery/catalyst/generated/models"
"github.com/SecurityBrewery/catalyst/generated/restapi/api"
"github.com/SecurityBrewery/catalyst/generated/restapi/operations/tickets"
)
func (s *Service) CreateTicket(ctx context.Context, params *tickets.CreateTicketParams) *api.Response {
createdTickets, err := s.database.TicketBatchCreate(ctx, []*models.TicketForm{params.Ticket})
if len(createdTickets) > 0 {
return response(createdTickets[0], err)
}
return response(nil, err)
}
func (s *Service) CreateTicketBatch(ctx context.Context, params *tickets.CreateTicketBatchParams) *api.Response {
_, err := s.database.TicketBatchCreate(ctx, params.Ticket)
return response(nil, err)
}
func (s *Service) GetTicket(ctx context.Context, params *tickets.GetTicketParams) *api.Response {
return response(s.database.TicketGet(ctx, params.ID))
}
func (s *Service) UpdateTicket(ctx context.Context, params *tickets.UpdateTicketParams) *api.Response {
return response(s.database.TicketUpdate(ctx, params.ID, params.Ticket))
}
func (s *Service) DeleteTicket(ctx context.Context, params *tickets.DeleteTicketParams) *api.Response {
if err := s.database.TicketDelete(ctx, params.ID); err != nil {
return response(nil, err)
}
_ = s.storage.DeleteBucket(fmt.Sprint(params.ID))
return response(nil, nil)
}
func (s *Service) ListTickets(ctx context.Context, params *tickets.ListTicketsParams) *api.Response {
q := ""
if params.Query != nil && *params.Query != "" {
q = *params.Query
}
t := ""
if params.Type != nil && *params.Type != "" {
t = *params.Type
}
return response(s.database.TicketList(ctx, t, q, params.Sort, params.Desc, *params.Offset, *params.Count))
}

74
service/ticket_field.go Normal file
View File

@@ -0,0 +1,74 @@
package service
import (
"context"
"github.com/SecurityBrewery/catalyst/generated/restapi/api"
"github.com/SecurityBrewery/catalyst/generated/restapi/operations/tickets"
)
func (s *Service) AddArtifact(ctx context.Context, params *tickets.AddArtifactParams) *api.Response {
return response(s.database.AddArtifact(ctx, params.ID, params.Artifact))
}
func (s *Service) RemoveArtifact(ctx context.Context, params *tickets.RemoveArtifactParams) *api.Response {
return response(s.database.RemoveArtifact(ctx, params.ID, params.Name))
}
func (s *Service) SetSchema(ctx context.Context, params *tickets.SetSchemaParams) *api.Response {
return response(s.database.SetTemplate(ctx, params.ID, params.Schema))
}
func (s *Service) AddComment(ctx context.Context, params *tickets.AddCommentParams) *api.Response {
return response(s.database.AddComment(ctx, params.ID, params.Comment))
}
func (s *Service) RemoveComment(ctx context.Context, params *tickets.RemoveCommentParams) *api.Response {
return response(s.database.RemoveComment(ctx, params.ID, params.CommentID))
}
func (s *Service) LinkTicket(ctx context.Context, params *tickets.LinkTicketParams) *api.Response {
err := s.database.RelatedCreate(ctx, params.ID, params.LinkedID)
if err != nil {
return response(nil, err)
}
return s.GetTicket(ctx, &tickets.GetTicketParams{ID: params.ID})
}
func (s *Service) UnlinkTicket(ctx context.Context, params *tickets.UnlinkTicketParams) *api.Response {
err := s.database.RelatedRemove(ctx, params.ID, params.LinkedID)
if err != nil {
return response(nil, err)
}
return s.GetTicket(ctx, &tickets.GetTicketParams{ID: params.ID})
}
func (s Service) SetReferences(ctx context.Context, params *tickets.SetReferencesParams) *api.Response {
return response(s.database.SetReferences(ctx, params.ID, params.References))
}
func (s Service) LinkFiles(ctx context.Context, params *tickets.LinkFilesParams) *api.Response {
return response(s.database.LinkFiles(ctx, params.ID, params.Files))
}
func (s Service) AddTicketPlaybook(ctx context.Context, params *tickets.AddTicketPlaybookParams) *api.Response {
return response(s.database.AddTicketPlaybook(ctx, params.ID, params.Playbook))
}
func (s Service) RemoveTicketPlaybook(ctx context.Context, params *tickets.RemoveTicketPlaybookParams) *api.Response {
return response(s.database.RemoveTicketPlaybook(ctx, params.ID, params.PlaybookID))
}
func (s Service) CompleteTask(ctx context.Context, params *tickets.CompleteTaskParams) *api.Response {
return response(s.database.TaskComplete(ctx, params.ID, params.PlaybookID, params.TaskID, params.Data))
}
func (s Service) SetTask(ctx context.Context, params *tickets.SetTaskParams) *api.Response {
return response(s.database.TaskUpdate(ctx, params.ID, params.PlaybookID, params.TaskID, params.Task))
}
func (s *Service) RunTask(ctx context.Context, params *tickets.RunTaskParams) *api.Response {
return response(nil, s.database.TaskRun(ctx, params.ID, params.PlaybookID, params.TaskID))
}

28
service/tickettype.go Normal file
View File

@@ -0,0 +1,28 @@
package service
import (
"context"
"github.com/SecurityBrewery/catalyst/generated/restapi/api"
"github.com/SecurityBrewery/catalyst/generated/restapi/operations/tickettypes"
)
func (s *Service) CreateTicketType(ctx context.Context, params *tickettypes.CreateTicketTypeParams) *api.Response {
return response(s.database.TicketTypeCreate(ctx, params.Tickettype))
}
func (s *Service) GetTicketType(ctx context.Context, params *tickettypes.GetTicketTypeParams) *api.Response {
return response(s.database.TicketTypeGet(ctx, params.ID))
}
func (s *Service) UpdateTicketType(ctx context.Context, params *tickettypes.UpdateTicketTypeParams) *api.Response {
return response(s.database.TicketTypeUpdate(ctx, params.ID, params.Tickettype))
}
func (s *Service) DeleteTicketType(ctx context.Context, params *tickettypes.DeleteTicketTypeParams) *api.Response {
return response(nil, s.database.TicketTypeDelete(ctx, params.ID))
}
func (s *Service) ListTicketTypes(ctx context.Context) *api.Response {
return response(s.database.TicketTypeList(ctx))
}

46
service/uisettings.go Normal file
View File

@@ -0,0 +1,46 @@
package service
import (
"context"
"errors"
"sort"
"github.com/SecurityBrewery/catalyst/database/busdb"
"github.com/SecurityBrewery/catalyst/generated/models"
"github.com/SecurityBrewery/catalyst/generated/restapi/api"
"github.com/SecurityBrewery/catalyst/role"
)
func (s *Service) GetSettings(ctx context.Context) *api.Response {
user, ok := busdb.UserFromContext(ctx)
if !ok {
return response(nil, errors.New("no user in context"))
}
setting, err := s.database.UserDataGet(ctx, user.ID)
if err != nil {
return response(nil, err)
}
settings := mergeSettings(s.settings, setting)
ticketTypeList, err := s.database.TicketTypeList(ctx)
if err != nil {
return response(nil, err)
}
settings.TicketTypes = ticketTypeList
return response(settings, nil)
}
func mergeSettings(globalSettings *models.Settings, user *models.UserDataResponse) *models.Settings {
if user.Timeformat != nil {
globalSettings.Timeformat = *user.Timeformat
}
roles := role.Strings(role.List())
sort.Strings(roles)
globalSettings.Roles = roles
return globalSettings
}

38
service/user.go Normal file
View File

@@ -0,0 +1,38 @@
package service
import (
"context"
"errors"
"github.com/SecurityBrewery/catalyst/database/busdb"
"github.com/SecurityBrewery/catalyst/generated/restapi/api"
"github.com/SecurityBrewery/catalyst/generated/restapi/operations/users"
)
func (s *Service) GetUser(ctx context.Context, params *users.GetUserParams) *api.Response {
return response(s.database.UserGet(ctx, params.ID))
}
func (s *Service) ListUsers(ctx context.Context) *api.Response {
return response(s.database.UserList(ctx))
}
func (s *Service) CreateUser(ctx context.Context, params *users.CreateUserParams) *api.Response {
return response(s.database.UserCreate(ctx, params.User))
}
func (s *Service) DeleteUser(ctx context.Context, params *users.DeleteUserParams) *api.Response {
return response(nil, s.database.UserDelete(ctx, params.ID))
}
func (s *Service) CurrentUser(ctx context.Context) *api.Response {
user, ok := busdb.UserFromContext(ctx)
if !ok {
return response(nil, errors.New("no user in context"))
}
return response(user, nil)
}
func (s *Service) UpdateUser(ctx context.Context, params *users.UpdateUserParams) *api.Response {
return response(s.database.UserUpdate(ctx, params.ID, params.User))
}

39
service/userdata.go Normal file
View File

@@ -0,0 +1,39 @@
package service
import (
"context"
"errors"
"github.com/SecurityBrewery/catalyst/database/busdb"
"github.com/SecurityBrewery/catalyst/generated/restapi/api"
"github.com/SecurityBrewery/catalyst/generated/restapi/operations/userdata"
)
func (s *Service) GetUserData(ctx context.Context, params *userdata.GetUserDataParams) *api.Response {
return response(s.database.UserDataGet(ctx, params.ID))
}
func (s *Service) ListUserData(ctx context.Context) *api.Response {
return response(s.database.UserDataList(ctx))
}
func (s *Service) UpdateUserData(ctx context.Context, params *userdata.UpdateUserDataParams) *api.Response {
return response(s.database.UserDataUpdate(ctx, params.ID, params.Userdata))
}
func (s *Service) CurrentUserData(ctx context.Context) *api.Response {
user, ok := busdb.UserFromContext(ctx)
if !ok {
return response(nil, errors.New("no user in context"))
}
return s.GetUserData(ctx, &userdata.GetUserDataParams{ID: user.ID})
}
func (s *Service) UpdateCurrentUserData(ctx context.Context, params *userdata.UpdateCurrentUserDataParams) *api.Response {
user, ok := busdb.UserFromContext(ctx)
if !ok {
return response(nil, errors.New("no user in context"))
}
return response(s.database.UserDataUpdate(ctx, user.ID, params.Userdata))
}