diff --git a/pkg/analyzer/analyzers/asana/asana.go b/pkg/analyzer/analyzers/asana/asana.go index 7b8aa611d..2b6f9b3a6 100644 --- a/pkg/analyzer/analyzers/asana/asana.go +++ b/pkg/analyzer/analyzers/asana/asana.go @@ -1,9 +1,11 @@ +//go:generate generate_permissions permissions.yaml permissions.go asana package asana // ToDo: Add OAuth token support. import ( "encoding/json" + "errors" "fmt" "net/http" "os" @@ -25,19 +27,64 @@ type Analyzer struct { func (Analyzer) Type() analyzerpb.AnalyzerType { return analyzerpb.AnalyzerType_Asana } func (a Analyzer) Analyze(_ context.Context, credInfo map[string]string) (*analyzers.AnalyzerResult, error) { - _, err := AnalyzePermissions(a.Cfg, credInfo["key"]) + key, ok := credInfo["key"] + if !ok { + return nil, errors.New("key not found in credInfo") + } + + info, err := AnalyzePermissions(a.Cfg, key) if err != nil { return nil, err } - return nil, fmt.Errorf("not implemented") + + return secretInfoToAnalyzerResult(info), nil } -type MeJSON struct { +func secretInfoToAnalyzerResult(info *SecretInfo) *analyzers.AnalyzerResult { + if info == nil { + return nil + } + + result := analyzers.AnalyzerResult{} + + // resoures/permission setup + permissions := allPermissions() + userResource := analyzers.Resource{ + Name: info.Data.Name, + FullyQualifiedName: info.Data.ID, + Type: "user", + Metadata: map[string]any{ + "email": info.Data.Email, + "type": info.Data.Type, + }, + } + + // bindings to all permissions to resources + bindings := analyzers.BindAllPermissions(userResource, permissions...) + result.Bindings = append(result.Bindings, bindings...) + + // unbounded resources + result.UnboundedResources = make([]analyzers.Resource, 0, len(info.Data.Workspaces)) + for _, workspace := range info.Data.Workspaces { + resource := analyzers.Resource{ + Name: workspace.Name, + FullyQualifiedName: workspace.ID, + Type: "workspace", + } + result.UnboundedResources = append(result.UnboundedResources, resource) + } + + return &result +} + +type SecretInfo struct { Data struct { + ID string `json:"gid"` Email string `json:"email"` Name string `json:"name"` Type string `json:"resource_type"` Workspaces []struct { + ID string `json:"gid"` Name string `json:"name"` } `json:"workspaces"` } `json:"data"` @@ -52,8 +99,8 @@ func AnalyzeAndPrintPermissions(cfg *config.Config, key string) { printMetadata(me) } -func AnalyzePermissions(cfg *config.Config, key string) (*MeJSON, error) { - var me MeJSON +func AnalyzePermissions(cfg *config.Config, key string) (*SecretInfo, error) { + var me SecretInfo client := analyzers.NewAnalyzeClient(cfg) req, err := http.NewRequest("GET", "https://app.asana.com/api/1.0/users/me", nil) @@ -84,7 +131,7 @@ func AnalyzePermissions(cfg *config.Config, key string) (*MeJSON, error) { return &me, nil } -func printMetadata(me *MeJSON) { +func printMetadata(me *SecretInfo) { color.Green("[!] Valid Asana API Key\n\n") color.Yellow("[i] User Information") color.Yellow(" Name: %s", me.Data.Name) @@ -102,3 +149,13 @@ func printMetadata(me *MeJSON) { } t.Render() } + +func allPermissions() []analyzers.Permission { + permissions := make([]analyzers.Permission, 0, len(PermissionStrings)) + for _, permission := range PermissionStrings { + permissions = append(permissions, analyzers.Permission{ + Value: permission, + }) + } + return permissions +} diff --git a/pkg/analyzer/analyzers/asana/asana_test.go b/pkg/analyzer/analyzers/asana/asana_test.go new file mode 100644 index 000000000..e71f4066a --- /dev/null +++ b/pkg/analyzer/analyzers/asana/asana_test.go @@ -0,0 +1,100 @@ +package asana + +import ( + _ "embed" + "encoding/json" + "sort" + "testing" + "time" + + "github.com/trufflesecurity/trufflehog/v3/pkg/analyzer/analyzers" + "github.com/trufflesecurity/trufflehog/v3/pkg/analyzer/config" + "github.com/trufflesecurity/trufflehog/v3/pkg/common" + "github.com/trufflesecurity/trufflehog/v3/pkg/context" +) + +//go:embed expected_output.json +var expectedOutput []byte + +func TestAnalyzer_Analyze(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) + defer cancel() + testSecrets, err := common.GetSecret(ctx, "trufflehog-testing", "detectors3") + if err != nil { + t.Fatalf("could not get test secrets from GCP: %s", err) + } + + tests := []struct { + name string + key string + want string // JSON string + wantErr bool + }{ + { + name: "valid Asana OAUTH Token", + key: testSecrets.MustGetField("ASANAOAUTH_TOKEN"), + want: string(expectedOutput), + wantErr: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + a := Analyzer{Cfg: &config.Config{}} + got, err := a.Analyze(ctx, map[string]string{"key": tt.key}) + if (err != nil) != tt.wantErr { + t.Errorf("Analyzer.Analyze() error = %v, wantErr %v", err, tt.wantErr) + return + } + + // bindings need to be in the same order to be comparable + sortBindings(got.Bindings) + + // Marshal the actual result to JSON + gotJSON, err := json.Marshal(got) + if err != nil { + t.Fatalf("could not marshal got to JSON: %s", err) + } + + // Parse the expected JSON string + var wantObj analyzers.AnalyzerResult + if err := json.Unmarshal([]byte(tt.want), &wantObj); err != nil { + t.Fatalf("could not unmarshal want JSON string: %s", err) + } + + // bindings need to be in the same order to be comparable + sortBindings(wantObj.Bindings) + + // Marshal the expected result to JSON (to normalize) + wantJSON, err := json.Marshal(wantObj) + if err != nil { + t.Fatalf("could not marshal want to JSON: %s", err) + } + + // Compare the JSON strings + if string(gotJSON) != string(wantJSON) { + // Pretty-print both JSON strings for easier comparison + var gotIndented, wantIndented []byte + gotIndented, err = json.MarshalIndent(got, "", " ") + if err != nil { + t.Fatalf("could not marshal got to indented JSON: %s", err) + } + wantIndented, err = json.MarshalIndent(wantObj, "", " ") + if err != nil { + t.Fatalf("could not marshal want to indented JSON: %s", err) + } + t.Errorf("Analyzer.Analyze() = %s, want %s", gotIndented, wantIndented) + } + }) + } +} + +// Helper function to sort bindings +func sortBindings(bindings []analyzers.Binding) { + sort.SliceStable(bindings, func(i, j int) bool { + if bindings[i].Resource.Name == bindings[j].Resource.Name { + return bindings[i].Permission.Value < bindings[j].Permission.Value + } + return bindings[i].Resource.Name < bindings[j].Resource.Name + }) +} diff --git a/pkg/analyzer/analyzers/asana/expected_output.json b/pkg/analyzer/analyzers/asana/expected_output.json new file mode 100644 index 000000000..598ef72e9 --- /dev/null +++ b/pkg/analyzer/analyzers/asana/expected_output.json @@ -0,0 +1 @@ +{"AnalyzerType":0,"Bindings":[{"Resource":{"Name":"rendyplayground","FullyQualifiedName":"1200552284974896","Type":"user","Metadata":{"email":"rendyplayground@gmail.com","type":"user"},"Parent":null},"Permission":{"Value":"autdit_logs:read","Parent":null}},{"Resource":{"Name":"rendyplayground","FullyQualifiedName":"1200552284974896","Type":"user","Metadata":{"email":"rendyplayground@gmail.com","type":"user"},"Parent":null},"Permission":{"Value":"portfolios:write","Parent":null}},{"Resource":{"Name":"rendyplayground","FullyQualifiedName":"1200552284974896","Type":"user","Metadata":{"email":"rendyplayground@gmail.com","type":"user"},"Parent":null},"Permission":{"Value":"sections:read","Parent":null}},{"Resource":{"Name":"rendyplayground","FullyQualifiedName":"1200552284974896","Type":"user","Metadata":{"email":"rendyplayground@gmail.com","type":"user"},"Parent":null},"Permission":{"Value":"tasks:read","Parent":null}},{"Resource":{"Name":"rendyplayground","FullyQualifiedName":"1200552284974896","Type":"user","Metadata":{"email":"rendyplayground@gmail.com","type":"user"},"Parent":null},"Permission":{"Value":"user_task_lists:read","Parent":null}},{"Resource":{"Name":"rendyplayground","FullyQualifiedName":"1200552284974896","Type":"user","Metadata":{"email":"rendyplayground@gmail.com","type":"user"},"Parent":null},"Permission":{"Value":"user_task_lists:write","Parent":null}},{"Resource":{"Name":"rendyplayground","FullyQualifiedName":"1200552284974896","Type":"user","Metadata":{"email":"rendyplayground@gmail.com","type":"user"},"Parent":null},"Permission":{"Value":"autdit_logs:write","Parent":null}},{"Resource":{"Name":"rendyplayground","FullyQualifiedName":"1200552284974896","Type":"user","Metadata":{"email":"rendyplayground@gmail.com","type":"user"},"Parent":null},"Permission":{"Value":"jobs:write","Parent":null}},{"Resource":{"Name":"rendyplayground","FullyQualifiedName":"1200552284974896","Type":"user","Metadata":{"email":"rendyplayground@gmail.com","type":"user"},"Parent":null},"Permission":{"Value":"portfolios:read","Parent":null}},{"Resource":{"Name":"rendyplayground","FullyQualifiedName":"1200552284974896","Type":"user","Metadata":{"email":"rendyplayground@gmail.com","type":"user"},"Parent":null},"Permission":{"Value":"project_memberships:read","Parent":null}},{"Resource":{"Name":"rendyplayground","FullyQualifiedName":"1200552284974896","Type":"user","Metadata":{"email":"rendyplayground@gmail.com","type":"user"},"Parent":null},"Permission":{"Value":"project_memberships:write","Parent":null}},{"Resource":{"Name":"rendyplayground","FullyQualifiedName":"1200552284974896","Type":"user","Metadata":{"email":"rendyplayground@gmail.com","type":"user"},"Parent":null},"Permission":{"Value":"users:read","Parent":null}},{"Resource":{"Name":"rendyplayground","FullyQualifiedName":"1200552284974896","Type":"user","Metadata":{"email":"rendyplayground@gmail.com","type":"user"},"Parent":null},"Permission":{"Value":"users:write","Parent":null}},{"Resource":{"Name":"rendyplayground","FullyQualifiedName":"1200552284974896","Type":"user","Metadata":{"email":"rendyplayground@gmail.com","type":"user"},"Parent":null},"Permission":{"Value":"memberships:read","Parent":null}},{"Resource":{"Name":"rendyplayground","FullyQualifiedName":"1200552284974896","Type":"user","Metadata":{"email":"rendyplayground@gmail.com","type":"user"},"Parent":null},"Permission":{"Value":"custom_fields:write","Parent":null}},{"Resource":{"Name":"rendyplayground","FullyQualifiedName":"1200552284974896","Type":"user","Metadata":{"email":"rendyplayground@gmail.com","type":"user"},"Parent":null},"Permission":{"Value":"goals:write","Parent":null}},{"Resource":{"Name":"rendyplayground","FullyQualifiedName":"1200552284974896","Type":"user","Metadata":{"email":"rendyplayground@gmail.com","type":"user"},"Parent":null},"Permission":{"Value":"jobs:read","Parent":null}},{"Resource":{"Name":"rendyplayground","FullyQualifiedName":"1200552284974896","Type":"user","Metadata":{"email":"rendyplayground@gmail.com","type":"user"},"Parent":null},"Permission":{"Value":"tags:write","Parent":null}},{"Resource":{"Name":"rendyplayground","FullyQualifiedName":"1200552284974896","Type":"user","Metadata":{"email":"rendyplayground@gmail.com","type":"user"},"Parent":null},"Permission":{"Value":"teams:read","Parent":null}},{"Resource":{"Name":"rendyplayground","FullyQualifiedName":"1200552284974896","Type":"user","Metadata":{"email":"rendyplayground@gmail.com","type":"user"},"Parent":null},"Permission":{"Value":"teams:write","Parent":null}},{"Resource":{"Name":"rendyplayground","FullyQualifiedName":"1200552284974896","Type":"user","Metadata":{"email":"rendyplayground@gmail.com","type":"user"},"Parent":null},"Permission":{"Value":"custom_field_settings:write","Parent":null}},{"Resource":{"Name":"rendyplayground","FullyQualifiedName":"1200552284974896","Type":"user","Metadata":{"email":"rendyplayground@gmail.com","type":"user"},"Parent":null},"Permission":{"Value":"projects:read","Parent":null}},{"Resource":{"Name":"rendyplayground","FullyQualifiedName":"1200552284974896","Type":"user","Metadata":{"email":"rendyplayground@gmail.com","type":"user"},"Parent":null},"Permission":{"Value":"sections:write","Parent":null}},{"Resource":{"Name":"rendyplayground","FullyQualifiedName":"1200552284974896","Type":"user","Metadata":{"email":"rendyplayground@gmail.com","type":"user"},"Parent":null},"Permission":{"Value":"allocations:read","Parent":null}},{"Resource":{"Name":"rendyplayground","FullyQualifiedName":"1200552284974896","Type":"user","Metadata":{"email":"rendyplayground@gmail.com","type":"user"},"Parent":null},"Permission":{"Value":"custom_fields:read","Parent":null}},{"Resource":{"Name":"rendyplayground","FullyQualifiedName":"1200552284974896","Type":"user","Metadata":{"email":"rendyplayground@gmail.com","type":"user"},"Parent":null},"Permission":{"Value":"projects:write","Parent":null}},{"Resource":{"Name":"rendyplayground","FullyQualifiedName":"1200552284974896","Type":"user","Metadata":{"email":"rendyplayground@gmail.com","type":"user"},"Parent":null},"Permission":{"Value":"allocations:write","Parent":null}},{"Resource":{"Name":"rendyplayground","FullyQualifiedName":"1200552284974896","Type":"user","Metadata":{"email":"rendyplayground@gmail.com","type":"user"},"Parent":null},"Permission":{"Value":"custom_field_settings:read","Parent":null}},{"Resource":{"Name":"rendyplayground","FullyQualifiedName":"1200552284974896","Type":"user","Metadata":{"email":"rendyplayground@gmail.com","type":"user"},"Parent":null},"Permission":{"Value":"batch_api:read","Parent":null}},{"Resource":{"Name":"rendyplayground","FullyQualifiedName":"1200552284974896","Type":"user","Metadata":{"email":"rendyplayground@gmail.com","type":"user"},"Parent":null},"Permission":{"Value":"events:read","Parent":null}},{"Resource":{"Name":"rendyplayground","FullyQualifiedName":"1200552284974896","Type":"user","Metadata":{"email":"rendyplayground@gmail.com","type":"user"},"Parent":null},"Permission":{"Value":"tasks:write","Parent":null}},{"Resource":{"Name":"rendyplayground","FullyQualifiedName":"1200552284974896","Type":"user","Metadata":{"email":"rendyplayground@gmail.com","type":"user"},"Parent":null},"Permission":{"Value":"rules:read","Parent":null}},{"Resource":{"Name":"rendyplayground","FullyQualifiedName":"1200552284974896","Type":"user","Metadata":{"email":"rendyplayground@gmail.com","type":"user"},"Parent":null},"Permission":{"Value":"batch_api:write","Parent":null}},{"Resource":{"Name":"rendyplayground","FullyQualifiedName":"1200552284974896","Type":"user","Metadata":{"email":"rendyplayground@gmail.com","type":"user"},"Parent":null},"Permission":{"Value":"goals:read","Parent":null}},{"Resource":{"Name":"rendyplayground","FullyQualifiedName":"1200552284974896","Type":"user","Metadata":{"email":"rendyplayground@gmail.com","type":"user"},"Parent":null},"Permission":{"Value":"tags:read","Parent":null}},{"Resource":{"Name":"rendyplayground","FullyQualifiedName":"1200552284974896","Type":"user","Metadata":{"email":"rendyplayground@gmail.com","type":"user"},"Parent":null},"Permission":{"Value":"memberships:write","Parent":null}},{"Resource":{"Name":"rendyplayground","FullyQualifiedName":"1200552284974896","Type":"user","Metadata":{"email":"rendyplayground@gmail.com","type":"user"},"Parent":null},"Permission":{"Value":"attachments:read","Parent":null}},{"Resource":{"Name":"rendyplayground","FullyQualifiedName":"1200552284974896","Type":"user","Metadata":{"email":"rendyplayground@gmail.com","type":"user"},"Parent":null},"Permission":{"Value":"attachments:write","Parent":null}},{"Resource":{"Name":"rendyplayground","FullyQualifiedName":"1200552284974896","Type":"user","Metadata":{"email":"rendyplayground@gmail.com","type":"user"},"Parent":null},"Permission":{"Value":"events:write","Parent":null}},{"Resource":{"Name":"rendyplayground","FullyQualifiedName":"1200552284974896","Type":"user","Metadata":{"email":"rendyplayground@gmail.com","type":"user"},"Parent":null},"Permission":{"Value":"rules:write","Parent":null}}],"UnboundedResources":[{"Name":"Design","FullyQualifiedName":"1200552201649567","Type":"workspace","Metadata":null,"Parent":null}],"Metadata":null} \ No newline at end of file diff --git a/pkg/analyzer/analyzers/asana/permissions.go b/pkg/analyzer/analyzers/asana/permissions.go new file mode 100644 index 000000000..577508c5d --- /dev/null +++ b/pkg/analyzer/analyzers/asana/permissions.go @@ -0,0 +1,256 @@ +// Code generated by go generate; DO NOT EDIT. +package asana + +import "errors" + +type Permission int + +const ( + Invalid Permission = iota + AllocationsRead Permission = iota + AllocationsWrite Permission = iota + AttachmentsRead Permission = iota + AttachmentsWrite Permission = iota + AutditLogsRead Permission = iota + AutditLogsWrite Permission = iota + CustomFieldsRead Permission = iota + CustomFieldsWrite Permission = iota + CustomFieldSettingsRead Permission = iota + CustomFieldSettingsWrite Permission = iota + BatchApiRead Permission = iota + BatchApiWrite Permission = iota + EventsRead Permission = iota + EventsWrite Permission = iota + GoalsRead Permission = iota + GoalsWrite Permission = iota + JobsRead Permission = iota + JobsWrite Permission = iota + PortfoliosRead Permission = iota + PortfoliosWrite Permission = iota + ProjectsRead Permission = iota + ProjectsWrite Permission = iota + ProjectMembershipsRead Permission = iota + ProjectMembershipsWrite Permission = iota + SectionsRead Permission = iota + SectionsWrite Permission = iota + TagsRead Permission = iota + TagsWrite Permission = iota + TasksRead Permission = iota + TasksWrite Permission = iota + TeamsRead Permission = iota + TeamsWrite Permission = iota + UsersRead Permission = iota + UsersWrite Permission = iota + UserTaskListsRead Permission = iota + UserTaskListsWrite Permission = iota + MembershipsRead Permission = iota + MembershipsWrite Permission = iota + RulesRead Permission = iota + RulesWrite Permission = iota +) + +var ( + PermissionStrings = map[Permission]string{ + AllocationsRead: "allocations:read", + AllocationsWrite: "allocations:write", + AttachmentsRead: "attachments:read", + AttachmentsWrite: "attachments:write", + AutditLogsRead: "autdit_logs:read", + AutditLogsWrite: "autdit_logs:write", + CustomFieldsRead: "custom_fields:read", + CustomFieldsWrite: "custom_fields:write", + CustomFieldSettingsRead: "custom_field_settings:read", + CustomFieldSettingsWrite: "custom_field_settings:write", + BatchApiRead: "batch_api:read", + BatchApiWrite: "batch_api:write", + EventsRead: "events:read", + EventsWrite: "events:write", + GoalsRead: "goals:read", + GoalsWrite: "goals:write", + JobsRead: "jobs:read", + JobsWrite: "jobs:write", + PortfoliosRead: "portfolios:read", + PortfoliosWrite: "portfolios:write", + ProjectsRead: "projects:read", + ProjectsWrite: "projects:write", + ProjectMembershipsRead: "project_memberships:read", + ProjectMembershipsWrite: "project_memberships:write", + SectionsRead: "sections:read", + SectionsWrite: "sections:write", + TagsRead: "tags:read", + TagsWrite: "tags:write", + TasksRead: "tasks:read", + TasksWrite: "tasks:write", + TeamsRead: "teams:read", + TeamsWrite: "teams:write", + UsersRead: "users:read", + UsersWrite: "users:write", + UserTaskListsRead: "user_task_lists:read", + UserTaskListsWrite: "user_task_lists:write", + MembershipsRead: "memberships:read", + MembershipsWrite: "memberships:write", + RulesRead: "rules:read", + RulesWrite: "rules:write", + } + + StringToPermission = map[string]Permission{ + "allocations:read": AllocationsRead, + "allocations:write": AllocationsWrite, + "attachments:read": AttachmentsRead, + "attachments:write": AttachmentsWrite, + "autdit_logs:read": AutditLogsRead, + "autdit_logs:write": AutditLogsWrite, + "custom_fields:read": CustomFieldsRead, + "custom_fields:write": CustomFieldsWrite, + "custom_field_settings:read": CustomFieldSettingsRead, + "custom_field_settings:write": CustomFieldSettingsWrite, + "batch_api:read": BatchApiRead, + "batch_api:write": BatchApiWrite, + "events:read": EventsRead, + "events:write": EventsWrite, + "goals:read": GoalsRead, + "goals:write": GoalsWrite, + "jobs:read": JobsRead, + "jobs:write": JobsWrite, + "portfolios:read": PortfoliosRead, + "portfolios:write": PortfoliosWrite, + "projects:read": ProjectsRead, + "projects:write": ProjectsWrite, + "project_memberships:read": ProjectMembershipsRead, + "project_memberships:write": ProjectMembershipsWrite, + "sections:read": SectionsRead, + "sections:write": SectionsWrite, + "tags:read": TagsRead, + "tags:write": TagsWrite, + "tasks:read": TasksRead, + "tasks:write": TasksWrite, + "teams:read": TeamsRead, + "teams:write": TeamsWrite, + "users:read": UsersRead, + "users:write": UsersWrite, + "user_task_lists:read": UserTaskListsRead, + "user_task_lists:write": UserTaskListsWrite, + "memberships:read": MembershipsRead, + "memberships:write": MembershipsWrite, + "rules:read": RulesRead, + "rules:write": RulesWrite, + } + + PermissionIDs = map[Permission]int{ + AllocationsRead: 1, + AllocationsWrite: 2, + AttachmentsRead: 3, + AttachmentsWrite: 4, + AutditLogsRead: 5, + AutditLogsWrite: 6, + CustomFieldsRead: 7, + CustomFieldsWrite: 8, + CustomFieldSettingsRead: 9, + CustomFieldSettingsWrite: 10, + BatchApiRead: 11, + BatchApiWrite: 12, + EventsRead: 13, + EventsWrite: 14, + GoalsRead: 15, + GoalsWrite: 16, + JobsRead: 17, + JobsWrite: 18, + PortfoliosRead: 19, + PortfoliosWrite: 20, + ProjectsRead: 21, + ProjectsWrite: 22, + ProjectMembershipsRead: 23, + ProjectMembershipsWrite: 24, + SectionsRead: 25, + SectionsWrite: 26, + TagsRead: 27, + TagsWrite: 28, + TasksRead: 29, + TasksWrite: 30, + TeamsRead: 31, + TeamsWrite: 32, + UsersRead: 33, + UsersWrite: 34, + UserTaskListsRead: 35, + UserTaskListsWrite: 36, + MembershipsRead: 37, + MembershipsWrite: 38, + RulesRead: 39, + RulesWrite: 40, + } + + IdToPermission = map[int]Permission{ + 1: AllocationsRead, + 2: AllocationsWrite, + 3: AttachmentsRead, + 4: AttachmentsWrite, + 5: AutditLogsRead, + 6: AutditLogsWrite, + 7: CustomFieldsRead, + 8: CustomFieldsWrite, + 9: CustomFieldSettingsRead, + 10: CustomFieldSettingsWrite, + 11: BatchApiRead, + 12: BatchApiWrite, + 13: EventsRead, + 14: EventsWrite, + 15: GoalsRead, + 16: GoalsWrite, + 17: JobsRead, + 18: JobsWrite, + 19: PortfoliosRead, + 20: PortfoliosWrite, + 21: ProjectsRead, + 22: ProjectsWrite, + 23: ProjectMembershipsRead, + 24: ProjectMembershipsWrite, + 25: SectionsRead, + 26: SectionsWrite, + 27: TagsRead, + 28: TagsWrite, + 29: TasksRead, + 30: TasksWrite, + 31: TeamsRead, + 32: TeamsWrite, + 33: UsersRead, + 34: UsersWrite, + 35: UserTaskListsRead, + 36: UserTaskListsWrite, + 37: MembershipsRead, + 38: MembershipsWrite, + 39: RulesRead, + 40: RulesWrite, + } +) + +// ToString converts a Permission enum to its string representation +func (p Permission) ToString() (string, error) { + if str, ok := PermissionStrings[p]; ok { + return str, nil + } + return "", errors.New("invalid permission") +} + +// ToID converts a Permission enum to its ID +func (p Permission) ToID() (int, error) { + if id, ok := PermissionIDs[p]; ok { + return id, nil + } + return 0, errors.New("invalid permission") +} + +// PermissionFromString converts a string representation to its Permission enum +func PermissionFromString(s string) (Permission, error) { + if p, ok := StringToPermission[s]; ok { + return p, nil + } + return 0, errors.New("invalid permission string") +} + +// PermissionFromID converts an ID to its Permission enum +func PermissionFromID(id int) (Permission, error) { + if p, ok := IdToPermission[id]; ok { + return p, nil + } + return 0, errors.New("invalid permission ID") +} diff --git a/pkg/analyzer/analyzers/asana/permissions.yaml b/pkg/analyzer/analyzers/asana/permissions.yaml new file mode 100644 index 000000000..3d3ebd2cb --- /dev/null +++ b/pkg/analyzer/analyzers/asana/permissions.yaml @@ -0,0 +1,41 @@ +permissions: + - allocations:read + - allocations:write + - attachments:read + - attachments:write + - autdit_logs:read + - autdit_logs:write + - custom_fields:read + - custom_fields:write + - custom_field_settings:read + - custom_field_settings:write + - batch_api:read + - batch_api:write + - events:read + - events:write + - goals:read + - goals:write + - jobs:read + - jobs:write + - portfolios:read + - portfolios:write + - projects:read + - projects:write + - project_memberships:read + - project_memberships:write + - sections:read + - sections:write + - tags:read + - tags:write + - tasks:read + - tasks:write + - teams:read + - teams:write + - users:read + - users:write + - user_task_lists:read + - user_task_lists:write + - memberships:read + - memberships:write + - rules:read + - rules:write diff --git a/pkg/detectors/asanaoauth/asanaoauth.go b/pkg/detectors/asanaoauth/asanaoauth.go index ee7df3d2d..aa8bbea82 100644 --- a/pkg/detectors/asanaoauth/asanaoauth.go +++ b/pkg/detectors/asanaoauth/asanaoauth.go @@ -3,10 +3,11 @@ package asanaoauth import ( "context" "fmt" - regexp "github.com/wasilibs/go-re2" "net/http" "strings" + regexp "github.com/wasilibs/go-re2" + "github.com/trufflesecurity/trufflehog/v3/pkg/common" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors" "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" @@ -58,6 +59,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result defer res.Body.Close() if res.StatusCode >= 200 && res.StatusCode < 300 { s1.Verified = true + s1.AnalysisInfo = map[string]string{"key": resMatch} } } } diff --git a/pkg/detectors/asanaoauth/asanaoauth_test.go b/pkg/detectors/asanaoauth/asanaoauth_test.go index 88f93066d..063c55b0c 100644 --- a/pkg/detectors/asanaoauth/asanaoauth_test.go +++ b/pkg/detectors/asanaoauth/asanaoauth_test.go @@ -95,6 +95,7 @@ func TestAsanaOauth_FromChunk(t *testing.T) { t.Fatalf("no raw secret present: \n %+v", got[i]) } got[i].Raw = nil + got[i].AnalysisInfo = nil } if diff := pretty.Compare(got, tt.want); diff != "" { t.Errorf("AsanaOauth.FromData() %s diff: (-got +want)\n%s", tt.name, diff)