Skip to content

Commit

Permalink
Added AI category to test Agents in Workflows
Browse files Browse the repository at this point in the history
  • Loading branch information
frikky committed Feb 3, 2025
1 parent f0f8532 commit 78e662f
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 72 deletions.
4 changes: 2 additions & 2 deletions app_upload/stitcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -865,8 +865,8 @@ func main() {
bucketName = os.Args[5]
}

appname := "shuffle-tools"
appversion := "1.2.0"
appname := "shuffle-ai"
appversion := "1.0.0"
err := deployConfigToBackend(appfolder, appname, appversion)
if err != nil {
log.Printf("[WARNING] Failed uploading config: %s", err)
Expand Down
6 changes: 6 additions & 0 deletions blobs.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,12 @@ func GetAppCategories() []AppCategory {
Icon: "network",
ActionLabels: []string{"Get Rules", "Allow IP", "Block IP"},
},
AppCategory{
Name: "AI",
Color: "#FFC107",
Icon: "AI",
ActionLabels: []string{"Answer Question", "Run Action"},
},
AppCategory{
Name: "Other",
Color: "#FFC107",
Expand Down
6 changes: 2 additions & 4 deletions db-connector.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ import (
"os"
"strconv"

//"strconv"
//"encoding/binary"
"math"
"math/rand"
"sort"
Expand Down Expand Up @@ -5000,12 +4998,12 @@ func GetOpenApiDatastore(ctx context.Context, id string) (ParsedOpenApi, error)
err := project.Dbclient.Get(ctx, key, api)
//if (err != nil || len(api.Body) == 0) && !strings.Contains(fmt.Sprintf("%s", err), "no such") {
if err != nil || len(api.Body) == 0 {
log.Printf("Some API issue: %s", err)

if strings.Contains(fmt.Sprintf("%s", err), "cannot load field") {
return *api, nil
}

log.Printf("[ERROR] Some OpenAPI refissue for ID '%s': %s", id, err)

//project.BucketName := project.BucketName
fullParsedPath := fmt.Sprintf("extra_specs/%s/openapi.json", id)
//gs://shuffler.appspot.com/extra_specs/0373ed696a3a2cba0a2b6838068f2b80
Expand Down
8 changes: 4 additions & 4 deletions health.go
Original file line number Diff line number Diff line change
Expand Up @@ -1499,7 +1499,7 @@ func GetStaticWorkflowHealth(ctx context.Context, workflow Workflow) (Workflow,
allNames := []string{}
for _, action := range workflow.Actions {

if action.AppID == "integration" {
if action.AppID == "integration" || action.AppID == "shuffle_agent" {
if action.IsStartNode {
startnodeFound = true
}
Expand Down Expand Up @@ -1773,7 +1773,7 @@ func GetStaticWorkflowHealth(ctx context.Context, workflow Workflow) (Workflow,

// Handle app versions & upgrades
for _, action := range workflow.Actions {
if action.AppID == "integration" {
if action.AppID == "integration" || action.AppID == "shuffle_agent" {
if action.IsStartNode {
startnodeFound = true
}
Expand Down Expand Up @@ -2173,7 +2173,7 @@ func GetStaticWorkflowHealth(ctx context.Context, workflow Workflow) (Workflow,
}
}

if curapp.ID == "" && action.AppID != "integration" {
if curapp.ID == "" && action.AppID != "integration" && action.AppID != "shuffle_agent" {
//log.Printf("[WARNING] Didn't find the App ID for action %s (%s) with appname %s", action.Label, action.AppID, action.AppName)
for _, app := range workflowapps {
if app.ID == action.AppID {
Expand Down Expand Up @@ -2212,7 +2212,7 @@ func GetStaticWorkflowHealth(ctx context.Context, workflow Workflow) (Workflow,
}

if curapp.ID != action.AppID && curapp.Name != action.AppName {
if action.AppID == "integration" {
if action.AppID == "integration" || action.AppID == "shuffle_agent" {
for _, param := range action.Parameters {
if param.Name == "action" {
if len(param.Value) > 0 {
Expand Down
95 changes: 48 additions & 47 deletions shared.go
Original file line number Diff line number Diff line change
Expand Up @@ -25091,6 +25091,8 @@ func RunCategoryAction(resp http.ResponseWriter, request *http.Request) {
foundCategory = org.SecurityFramework.IAM
} else if foundAppType == "siem" {
foundCategory = org.SecurityFramework.SIEM
} else if foundAppType == "ai" {
foundCategory = org.SecurityFramework.AI
} else {
if len(foundAppType) > 0 {
log.Printf("[ERROR] Unknown app type in category action: %#v", foundAppType)
Expand Down Expand Up @@ -25279,7 +25281,7 @@ func RunCategoryAction(resp http.ResponseWriter, request *http.Request) {
if err != nil {
log.Printf("[DEBUG] Error with getting file '%s' in category action autorun: %s", discoverFile, err)
} else {
log.Printf("\n\n\n[DEBUG] Found file in category action: %#v. Status: %s. Category: %s\n\n\n", file, file.Status, file.Namespace)
log.Printf("[DEBUG] Found tranlsation file in category action: %#v. Status: %s. Category: %s", file, file.Status, file.Namespace)

if file.Status == "active" {
fieldFileFound = true
Expand Down Expand Up @@ -25543,7 +25545,7 @@ func RunCategoryAction(resp http.ResponseWriter, request *http.Request) {
}

if len(foundAuthenticationId) == 0 {
log.Printf("[WARNING] Couldn't find auth for app %s in org %s (%s)", selectedApp.Name, user.ActiveOrg.Name, user.ActiveOrg.Id)
//log.Printf("[WARNING] Couldn't find auth for app %s in org %s (%s)", selectedApp.Name, user.ActiveOrg.Name, user.ActiveOrg.Id)

requiresAuth := false
for _, action := range selectedApp.Actions {
Expand All @@ -25560,58 +25562,58 @@ func RunCategoryAction(resp http.ResponseWriter, request *http.Request) {
}

if !requiresAuth {
log.Printf("\n\n[ERROR] App '%s' doesn't require auth, but we are still sending back with auth requires\n\n", selectedApp.Name)
}
//log.Printf("\n\n[ERROR] App '%s' doesn't require auth\n\n", selectedApp.Name)
} else {
// Reducing size drastically as it isn't really necessary
selectedApp.Actions = []WorkflowAppAction{}
//selectedApp.Authentication = Authentication{}
selectedApp.ChildIds = []string{}
selectedApp.SmallImage = ""
structuredFeedback := StructuredCategoryAction{
Success: false,
Action: "app_authentication",
Category: discoveredCategory,
Reason: fmt.Sprintf("Authenticate %s first.", selectedApp.Name),
Label: value.Label,
Apps: []WorkflowApp{
selectedApp,
},

// Reducing size drastically as it isn't really necessary
selectedApp.Actions = []WorkflowAppAction{}
//selectedApp.Authentication = Authentication{}
selectedApp.ChildIds = []string{}
selectedApp.SmallImage = ""
structuredFeedback := StructuredCategoryAction{
Success: false,
Action: "app_authentication",
Category: discoveredCategory,
Reason: fmt.Sprintf("Authenticate %s first.", selectedApp.Name),
Label: value.Label,
Apps: []WorkflowApp{
selectedApp,
},
AvailableLabels: availableLabels,
}

AvailableLabels: availableLabels,
}
// Check for user agent including shufflepy
useragent := request.Header.Get("User-Agent")
if strings.Contains(strings.ToLower(useragent), "shufflepy") {
structuredFeedback.Apps = []WorkflowApp{}

// Find current domain from the url
currentUrl := fmt.Sprintf("%s://%s", request.URL.Scheme, request.URL.Host)
if project.Environment == "cloud" {
currentUrl = "https://shuffler.io"
}

// Check for user agent including shufflepy
useragent := request.Header.Get("User-Agent")
if strings.Contains(strings.ToLower(useragent), "shufflepy") {
structuredFeedback.Apps = []WorkflowApp{}
// FIXME: Implement this. Uses org's auth
orgAuth := org.OrgAuth.Token

// Find current domain from the url
currentUrl := fmt.Sprintf("%s://%s", request.URL.Scheme, request.URL.Host)
if project.Environment == "cloud" {
currentUrl = "https://shuffler.io"
structuredFeedback.Reason = fmt.Sprintf("Authenticate here: %s/appauth?app_id=%s&auth=%s", currentUrl, selectedApp.ID, orgAuth)
}

// FIXME: Implement this. Uses org's auth
orgAuth := org.OrgAuth.Token
jsonFormatted, err := json.MarshalIndent(structuredFeedback, "", " ")
if err != nil {
log.Printf("[WARNING] Failed marshalling structured feedback: %s", err)
resp.WriteHeader(500)
resp.Write([]byte(`{"success": false, "reason": "Failed formatting your data"}`))
return
}

structuredFeedback.Reason = fmt.Sprintf("Authenticate here: %s/appauth?app_id=%s&auth=%s", currentUrl, selectedApp.ID, orgAuth)
}
// Replace \u0026 with &
jsonFormatted = bytes.Replace(jsonFormatted, []byte("\\u0026"), []byte("&"), -1)

jsonFormatted, err := json.MarshalIndent(structuredFeedback, "", " ")
if err != nil {
log.Printf("[WARNING] Failed marshalling structured feedback: %s", err)
resp.WriteHeader(500)
resp.Write([]byte(`{"success": false, "reason": "Failed formatting your data"}`))
resp.WriteHeader(400)
resp.Write(jsonFormatted)
return
}

// Replace \u0026 with &
jsonFormatted = bytes.Replace(jsonFormatted, []byte("\\u0026"), []byte("&"), -1)

resp.WriteHeader(400)
resp.Write(jsonFormatted)
return
}

// Send back with SUCCESS as we already have an authentication
Expand Down Expand Up @@ -25909,7 +25911,7 @@ func RunCategoryAction(resp http.ResponseWriter, request *http.Request) {
// Finds WHERE in the destination to put the input data
// Loops through input fields, then takes the data from them
if len(fieldFileContentMap) > 0 {
log.Printf("\n\n[DEBUG] Found file content map (Reverse Schemaless): %#v\n\n", fieldFileContentMap)
//log.Printf("[DEBUG] Found file content map (Reverse Schemaless): %#v", fieldFileContentMap)

for key, mapValue := range fieldFileContentMap {
if _, ok := mapValue.(string); !ok {
Expand Down Expand Up @@ -26381,9 +26383,8 @@ func RunCategoryAction(resp http.ResponseWriter, request *http.Request) {
}

// Finds location of some data in another part of the data. This is to have a predefined location in subsequent requests
//log.Printf("\n\n\nREVERSE TRANSLATING FROM: %s\n\nTO: %s\n\n\n", parsedParameterMap, inputFieldMap)
// Allows us to map text -> field and not just field -> text (2-way)
reversed, err := schemaless.ReverseTranslate(parsedParameterMap, inputFieldMap)
//reversed, err := schemaless.ReverseTranslate(inputFieldMap, parsedParameterMap)
if err != nil {
log.Printf("[ERROR] Problem with reversing: %s", err)
} else {
Expand Down
33 changes: 18 additions & 15 deletions structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ type WorkflowAppActionParameter struct {
ValueReplace []Valuereplace `json:"value_replace" datastore:"value_replace,noindex" yaml:"value_replace,omitempty"`
UniqueToggled bool `json:"unique_toggled" datastore:"unique_toggled" yaml:"unique_toggled"`
Error string `json:"error" datastore:"error" yaml:"error"`
Hidden bool `json:"hidden" datastore:"hidden" yaml:"hidden"`
}

type Valuereplace struct {
Expand Down Expand Up @@ -1376,6 +1377,7 @@ type Categories struct {
Intel Category `json:"intel" datastore:"intel"`
EDR Category `json:"edr" datastore:"edr"`
IAM Category `json:"iam" datastore:"IAM"`
AI Category `json:"iam" datastore:"IAM"`

Email Category `json:"email" datastore:"email"`
Other Category `json:"other" datastore:"other"`
Expand Down Expand Up @@ -1523,11 +1525,11 @@ type ValidationProblem struct {
}

type TypeValidation struct {
Valid bool `json:"valid" datastore:"valid"`
ChangedAt int64 `json:"changed_at" datastore:"changed_at"`
LastValid int64 `json:"last_valid" datastore:"last_valid"`
ValidationRan bool `json:"validation_ran" datastore:"validation_ran"`
NotificationsCreated int64 `json:"notifications_created" datastore:"notifications_created"`
Valid bool `json:"valid" datastore:"valid"`
ChangedAt int64 `json:"changed_at" datastore:"changed_at"`
LastValid int64 `json:"last_valid" datastore:"last_valid"`
ValidationRan bool `json:"validation_ran" datastore:"validation_ran"`
NotificationsCreated int64 `json:"notifications_created" datastore:"notifications_created"`

// For the last update, which did it
WorkflowId string `json:"workflow_id" datastore:"workflow_id"`
Expand Down Expand Up @@ -4052,7 +4054,6 @@ type StructuredCategoryAction struct {
MissingFields []string `json:"missing_fields,omitempty"`

Translated bool `json:"translated,omitempty"`

}

type ModelLabelParameter struct {
Expand All @@ -4070,15 +4071,17 @@ type UserRequest struct {
}

type HTTPOutput struct {
Success bool `json:"success"`
Status int `json:"status"`
Url string `json:"url"`
Body interface{} `json:"body"`
Headers map[string]string `json:"headers"`
Cookies map[string]string `json:"cookies"`
Errors []string `json:"errors"`

Reason string `json:"reason,omitempty"`
Success bool `json:"success"`
Reason string `json:"reason,omitempty"`
Exception string `json:"exception,omitempty"`
Details string `json:"details,omitempty"`

Status int `json:"status,omitempty"`
Url string `json:"url,omitempty"`
Body interface{} `json:"body,omitempty"`
Headers map[string]string `json:"headers,omitempty"`
Cookies map[string]string `json:"cookies,omitempty"`
Errors []string `json:"errors,omitempty"`
}

type SnappStep struct {
Expand Down

0 comments on commit 78e662f

Please sign in to comment.