mirror of
https://github.com/trufflesecurity/trufflehog.git
synced 2026-05-16 13:20:35 +00:00
0fa069c12f
* enable errcheck and staticcheck for golangci-lint v2 and resolve all issues * skip lint on intentional reference of deprecated DetectorType values
163 lines
4.2 KiB
Go
163 lines
4.2 KiB
Go
//go:generate generate_permissions permissions.yaml permissions.go asana
|
|
package asana
|
|
|
|
// ToDo: Add OAuth token support.
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"net/http"
|
|
"os"
|
|
|
|
"github.com/fatih/color"
|
|
"github.com/jedib0t/go-pretty/v6/table"
|
|
"github.com/trufflesecurity/trufflehog/v3/pkg/analyzer/analyzers"
|
|
"github.com/trufflesecurity/trufflehog/v3/pkg/analyzer/config"
|
|
"github.com/trufflesecurity/trufflehog/v3/pkg/context"
|
|
)
|
|
|
|
var _ analyzers.Analyzer = (*Analyzer)(nil)
|
|
|
|
type Analyzer struct {
|
|
Cfg *config.Config
|
|
}
|
|
|
|
func (Analyzer) Type() analyzers.AnalyzerType { return analyzers.AnalyzerTypeAsana }
|
|
|
|
func (a Analyzer) Analyze(_ context.Context, credInfo map[string]string) (*analyzers.AnalyzerResult, error) {
|
|
key, ok := credInfo["key"]
|
|
if !ok {
|
|
return nil, analyzers.NewAnalysisError(a.Type().String(), analyzers.OperationValidateCredentials, analyzers.ServiceConfig, "", errors.New("key not found in credInfo"),
|
|
)
|
|
}
|
|
|
|
info, err := AnalyzePermissions(a.Cfg, key)
|
|
if err != nil {
|
|
return nil, analyzers.NewAnalysisError(a.Type().String(), analyzers.OperationAnalyzePermissions, analyzers.ServiceAPI, "", err,
|
|
)
|
|
}
|
|
|
|
return secretInfoToAnalyzerResult(info), nil
|
|
}
|
|
|
|
func secretInfoToAnalyzerResult(info *SecretInfo) *analyzers.AnalyzerResult {
|
|
if info == nil {
|
|
return nil
|
|
}
|
|
|
|
result := analyzers.AnalyzerResult{}
|
|
|
|
// resources/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"`
|
|
}
|
|
|
|
func AnalyzeAndPrintPermissions(cfg *config.Config, key string) {
|
|
me, err := AnalyzePermissions(cfg, key)
|
|
if err != nil {
|
|
color.Red("[x] %s", err.Error())
|
|
return
|
|
}
|
|
printMetadata(me)
|
|
}
|
|
|
|
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)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
req.Header.Set("Authorization", "Bearer "+key)
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("invalid Asana API Key")
|
|
}
|
|
|
|
defer func() { _ = resp.Body.Close() }()
|
|
|
|
err = json.NewDecoder(resp.Body).Decode(&me)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if me.Data.Email == "" {
|
|
return nil, fmt.Errorf("invalid Asana API Key")
|
|
}
|
|
return &me, nil
|
|
}
|
|
|
|
func printMetadata(me *SecretInfo) {
|
|
color.Green("[!] Valid Asana API Key\n\n")
|
|
color.Yellow("[i] User Information")
|
|
color.Yellow(" Name: %s", me.Data.Name)
|
|
color.Yellow(" Email: %s", me.Data.Email)
|
|
color.Yellow(" Type: %s\n\n", me.Data.Type)
|
|
|
|
color.Green("[i] Permissions: Full Access\n\n")
|
|
|
|
color.Yellow("[i] Accessible Workspaces")
|
|
t := table.NewWriter()
|
|
t.SetOutputMirror(os.Stdout)
|
|
t.AppendHeader(table.Row{"Workspace Name"})
|
|
for _, workspace := range me.Data.Workspaces {
|
|
t.AppendRow(table.Row{color.GreenString(workspace.Name)})
|
|
}
|
|
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
|
|
}
|