Compare commits

...

3 Commits

Author SHA1 Message Date
Dustin Decker f8284323d9 Use structpb for Extra Data to support other types 2023-03-20 10:17:05 -07:00
Dustin Decker f52778985c update aws test 2023-03-20 09:57:08 -07:00
Dustin Decker 77f1c28eea update extra data type 2023-03-20 09:56:58 -07:00
13 changed files with 1116 additions and 1059 deletions
+7 -4
View File
@@ -15,6 +15,7 @@ import (
"github.com/trufflesecurity/trufflehog/v3/pkg/common" "github.com/trufflesecurity/trufflehog/v3/pkg/common"
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors"
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb"
"google.golang.org/protobuf/types/known/structpb"
) )
type scanner struct { type scanner struct {
@@ -179,10 +180,12 @@ func (s scanner) FromData(ctx context.Context, verify bool, data []byte) (result
err := json.NewDecoder(res.Body).Decode(&identityInfo) err := json.NewDecoder(res.Body).Decode(&identityInfo)
if err == nil { if err == nil {
s1.Verified = true s1.Verified = true
s1.ExtraData = map[string]string{ s1.ExtraData = &structpb.Struct{
"account": identityInfo.GetCallerIdentityResponse.GetCallerIdentityResult.Account, Fields: map[string]*structpb.Value{
"user_id": identityInfo.GetCallerIdentityResponse.GetCallerIdentityResult.UserID, "account": structpb.NewStringValue(identityInfo.GetCallerIdentityResponse.GetCallerIdentityResult.Account),
"arn": identityInfo.GetCallerIdentityResponse.GetCallerIdentityResult.Arn, "user_id": structpb.NewStringValue(identityInfo.GetCallerIdentityResponse.GetCallerIdentityResult.UserID),
"arn": structpb.NewStringValue(identityInfo.GetCallerIdentityResponse.GetCallerIdentityResult.Arn),
},
} }
} }
res.Body.Close() res.Body.Close()
+30 -17
View File
@@ -15,6 +15,8 @@ import (
"github.com/trufflesecurity/trufflehog/v3/pkg/common" "github.com/trufflesecurity/trufflehog/v3/pkg/common"
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors"
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/structpb"
) )
func TestAWS_FromChunk(t *testing.T) { func TestAWS_FromChunk(t *testing.T) {
@@ -56,11 +58,13 @@ func TestAWS_FromChunk(t *testing.T) {
{ {
DetectorType: detectorspb.DetectorType_AWS, DetectorType: detectorspb.DetectorType_AWS,
Verified: true, Verified: true,
Redacted: "AKIAWARWQKZNHMZBLY4I", Redacted: "AKIASP2TPHJSQH3FJRUX",
ExtraData: map[string]string{ ExtraData: &structpb.Struct{
"account": "413504919130", Fields: map[string]*structpb.Value{
"arn": "arn:aws:iam::413504919130:root", "account": structpb.NewStringValue("171436882533"),
"user_id": "413504919130", "arn": structpb.NewStringValue("arn:aws:iam::171436882533:user/canarytokens.com@@4dxkh0pdeop3bzu9zx5wob793"),
"user_id": structpb.NewStringValue("AIDASP2TPHJSUFRSTTZX4"),
},
}, },
}, },
}, },
@@ -78,7 +82,7 @@ func TestAWS_FromChunk(t *testing.T) {
{ {
DetectorType: detectorspb.DetectorType_AWS, DetectorType: detectorspb.DetectorType_AWS,
Verified: false, Verified: false,
Redacted: "AKIAWARWQKZNHMZBLY4I", Redacted: "AKIASP2TPHJSQH3FJRUX",
ExtraData: nil, ExtraData: nil,
}, },
}, },
@@ -108,10 +112,12 @@ func TestAWS_FromChunk(t *testing.T) {
DetectorType: detectorspb.DetectorType_AWS, DetectorType: detectorspb.DetectorType_AWS,
Verified: true, Verified: true,
Redacted: id, Redacted: id,
ExtraData: map[string]string{ ExtraData: &structpb.Struct{
"account": "413504919130", Fields: map[string]*structpb.Value{
"arn": "arn:aws:iam::413504919130:root", "account": structpb.NewStringValue("171436882533"),
"user_id": "413504919130", "arn": structpb.NewStringValue("arn:aws:iam::171436882533:user/canarytokens.com@@4dxkh0pdeop3bzu9zx5wob793"),
"user_id": structpb.NewStringValue("AIDASP2TPHJSUFRSTTZX4"),
},
}, },
}, },
{ {
@@ -146,10 +152,12 @@ func TestAWS_FromChunk(t *testing.T) {
DetectorType: detectorspb.DetectorType_AWS, DetectorType: detectorspb.DetectorType_AWS,
Verified: true, Verified: true,
Redacted: id, Redacted: id,
ExtraData: map[string]string{ ExtraData: &structpb.Struct{
"account": "413504919130", Fields: map[string]*structpb.Value{
"arn": "arn:aws:iam::413504919130:root", "account": structpb.NewStringValue("171436882533"),
"user_id": "413504919130", "arn": structpb.NewStringValue("arn:aws:iam::171436882533:user/canarytokens.com@@4dxkh0pdeop3bzu9zx5wob793"),
"user_id": structpb.NewStringValue("AIDASP2TPHJSUFRSTTZX4"),
},
}, },
}, },
{ {
@@ -172,7 +180,7 @@ func TestAWS_FromChunk(t *testing.T) {
{ {
DetectorType: detectorspb.DetectorType_AWS, DetectorType: detectorspb.DetectorType_AWS,
Verified: false, Verified: false,
Redacted: "AKIAWARWQKZNHMZBLY4I", Redacted: "AKIASP2TPHJSQH3FJRUX",
}, },
}, },
wantErr: false, wantErr: false,
@@ -181,7 +189,7 @@ func TestAWS_FromChunk(t *testing.T) {
name: "skipped", name: "skipped",
s: scanner{ s: scanner{
skipIDs: map[string]struct{}{ skipIDs: map[string]struct{}{
"AKIAWARWQKZNHMZBLY4I": {}, "AKIASP2TPHJSQH3FJRUX": {},
}, },
}, },
args: args{ args: args{
@@ -201,11 +209,16 @@ func TestAWS_FromChunk(t *testing.T) {
return return
} }
for i := range got { for i := range got {
if tt.want[i].ExtraData != nil {
if !proto.Equal(got[i].ExtraData, tt.want[i].ExtraData) {
t.Errorf("AWS.FromData() %s extra data not equal: got %+v, want %+v", tt.name, got[i].ExtraData, tt.want[i].ExtraData)
}
}
if len(got[i].Raw) == 0 { if len(got[i].Raw) == 0 {
t.Fatalf("no raw secret present: \n %+v", got[i]) t.Fatalf("no raw secret present: \n %+v", got[i])
} }
} }
ignoreOpts := cmpopts.IgnoreFields(detectors.Result{}, "RawV2", "Raw") ignoreOpts := cmpopts.IgnoreFields(detectors.Result{}, "RawV2", "Raw", "ExtraData")
if diff := cmp.Diff(got, tt.want, ignoreOpts); diff != "" { if diff := cmp.Diff(got, tt.want, ignoreOpts); diff != "" {
t.Errorf("AWS.FromData() %s diff: (-got +want)\n%s", tt.name, diff) t.Errorf("AWS.FromData() %s diff: (-got +want)\n%s", tt.name, diff)
} }
+2 -1
View File
@@ -12,6 +12,7 @@ import (
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/source_metadatapb" "github.com/trufflesecurity/trufflehog/v3/pkg/pb/source_metadatapb"
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/sourcespb" "github.com/trufflesecurity/trufflehog/v3/pkg/pb/sourcespb"
"github.com/trufflesecurity/trufflehog/v3/pkg/sources" "github.com/trufflesecurity/trufflehog/v3/pkg/sources"
"google.golang.org/protobuf/types/known/structpb"
) )
// Detector defines an interface for scanning for and verifying secrets. // Detector defines an interface for scanning for and verifying secrets.
@@ -45,7 +46,7 @@ type Result struct {
// Redacted contains the redacted version of the raw secret identification data for display purposes. // Redacted contains the redacted version of the raw secret identification data for display purposes.
// A secret ID should be used if available. // A secret ID should be used if available.
Redacted string Redacted string
ExtraData map[string]string ExtraData *structpb.Struct
StructuredData *detectorspb.StructuredData StructuredData *detectorspb.StructuredData
} }
@@ -3,7 +3,6 @@ package fastlypersonaltoken
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"fmt"
"io" "io"
"net/http" "net/http"
"regexp" "regexp"
@@ -12,6 +11,7 @@ import (
"github.com/trufflesecurity/trufflehog/v3/pkg/common" "github.com/trufflesecurity/trufflehog/v3/pkg/common"
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors"
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb"
"google.golang.org/protobuf/types/known/structpb"
) )
type Scanner struct{} type Scanner struct{}
@@ -76,12 +76,14 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
continue continue
} }
s1.Verified = true s1.Verified = true
s1.ExtraData = map[string]string{ s1.ExtraData = &structpb.Struct{
"username": userRes.Login, Fields: map[string]*structpb.Value{
"name": userRes.Name, "username": structpb.NewStringValue(userRes.Login),
"role": userRes.Role, "name": structpb.NewStringValue(userRes.Name),
"locked": fmt.Sprintf("%t", userRes.Locked), "role": structpb.NewStringValue(userRes.Role),
"two_factor_auth_enabled": fmt.Sprintf("%t", userRes.TwoFactorAuthEnabled), "locked": structpb.NewBoolValue(userRes.Locked),
"two_factor_auth_enabled": structpb.NewBoolValue(userRes.TwoFactorAuthEnabled),
},
} }
} else { } else {
if detectors.IsKnownFalsePositive(resMatch, detectors.DefaultFalsePositives, true) { if detectors.IsKnownFalsePositive(resMatch, detectors.DefaultFalsePositives, true) {
@@ -95,6 +95,7 @@ func TestFastlyPersonalToken_FromChunk(t *testing.T) {
t.Fatalf("no raw secret present: \n %+v", got[i]) t.Fatalf("no raw secret present: \n %+v", got[i])
} }
got[i].Raw = nil got[i].Raw = nil
got[i].ExtraData = nil
} }
if diff := pretty.Compare(got, tt.want); diff != "" { if diff := pretty.Compare(got, tt.want); diff != "" {
t.Errorf("FastlyPersonalToken.FromData() %s diff: (-got +want)\n%s", tt.name, diff) t.Errorf("FastlyPersonalToken.FromData() %s diff: (-got +want)\n%s", tt.name, diff)
+10 -7
View File
@@ -9,6 +9,7 @@ import (
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors"
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb"
"google.golang.org/protobuf/types/known/structpb"
"github.com/trufflesecurity/trufflehog/v3/pkg/common" "github.com/trufflesecurity/trufflehog/v3/pkg/common"
) )
@@ -85,13 +86,15 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
res.Body.Close() res.Body.Close()
if err == nil { if err == nil {
s1.Verified = true s1.Verified = true
s1.ExtraData = map[string]string{ s1.ExtraData = &structpb.Struct{
"username": userResponse.Login, Fields: map[string]*structpb.Value{
"url": userResponse.UserURL, "username": structpb.NewStringValue(userResponse.Login),
"account_type": userResponse.Type, "url": structpb.NewStringValue(userResponse.UserURL),
"site_admin": fmt.Sprintf("%t", userResponse.SiteAdmin), "account_type": structpb.NewStringValue(userResponse.Type),
"name": userResponse.Name, "site_admin": structpb.NewBoolValue(userResponse.SiteAdmin),
"company": userResponse.Company, "name": structpb.NewStringValue(userResponse.Name),
"company": structpb.NewStringValue(userResponse.Company),
},
} }
} }
} }
+12 -10
View File
@@ -6,10 +6,10 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"regexp" "regexp"
"strconv"
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors"
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb"
"google.golang.org/protobuf/types/known/structpb"
"github.com/trufflesecurity/trufflehog/v3/pkg/common" "github.com/trufflesecurity/trufflehog/v3/pkg/common"
) )
@@ -83,15 +83,17 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
if err == nil { if err == nil {
s1.Verified = true s1.Verified = true
org := orgs.Data[0] org := orgs.Data[0]
s1.ExtraData = map[string]string{ s1.ExtraData = &structpb.Struct{
"id": org.Id, Fields: map[string]*structpb.Value{
"title": org.Title, "id": structpb.NewStringValue(org.Id),
"user": org.User, "title": structpb.NewStringValue(org.Title),
"description": org.Description, "user": structpb.NewStringValue(org.User),
"role": org.Role, "description": structpb.NewStringValue(org.Description),
"is_personal": strconv.FormatBool(org.Personal), "role": structpb.NewStringValue(org.Role),
"is_default": strconv.FormatBool(org.Default), "is_personal": structpb.NewBoolValue(org.Personal),
"total_orgs": fmt.Sprintf("%d", len(orgs.Data)), "is_default": structpb.NewBoolValue(org.Default),
"total_orgs": structpb.NewNumberValue(float64(len(orgs.Data))),
},
} }
} }
} }
-10
View File
@@ -69,16 +69,6 @@ func TestOpenAI_FromChunk(t *testing.T) {
DetectorType: detectorspb.DetectorType_OpenAI, DetectorType: detectorspb.DetectorType_OpenAI,
Verified: true, Verified: true,
Redacted: "sk-...xxxx", Redacted: "sk-...xxxx",
ExtraData: map[string]string{
"description": "",
"id": "",
"is_default": "",
"is_personal": "",
"role": "",
"title": "",
"total_orgs": "",
"user": "",
},
}, },
}, },
wantErr: false, wantErr: false,
+7 -5
View File
@@ -10,6 +10,7 @@ import (
"github.com/trufflesecurity/trufflehog/v3/pkg/common" "github.com/trufflesecurity/trufflehog/v3/pkg/common"
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors"
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb"
"google.golang.org/protobuf/types/known/structpb"
) )
type Scanner struct{} type Scanner struct{}
@@ -62,14 +63,15 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
shopifyTokenAccessScopes := shopifyTokenAccessScopes{} shopifyTokenAccessScopes := shopifyTokenAccessScopes{}
err := json.NewDecoder(res.Body).Decode(&shopifyTokenAccessScopes) err := json.NewDecoder(res.Body).Decode(&shopifyTokenAccessScopes)
if err == nil { if err == nil {
var handleArray []string var handleArray []*structpb.Value
for _, handle := range shopifyTokenAccessScopes.AccessScopes { for _, handle := range shopifyTokenAccessScopes.AccessScopes {
handleArray = append(handleArray, handle.Handle) handleArray = append(handleArray, structpb.NewStringValue(handle.Handle))
} }
s1.Verified = true s1.Verified = true
s1.ExtraData = map[string]string{ s1.ExtraData = &structpb.Struct{
"access_scopes": strings.Join(handleArray, ","), Fields: map[string]*structpb.Value{
"access_scopes": structpb.NewListValue(&structpb.ListValue{Values: handleArray}),
},
} }
} }
res.Body.Close() res.Body.Close()
+19 -5
View File
@@ -6,8 +6,11 @@ import (
"testing" "testing"
"time" "time"
"github.com/kylelemons/godebug/pretty" "github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/structpb"
"github.com/trufflesecurity/trufflehog/v3/pkg/common" "github.com/trufflesecurity/trufflehog/v3/pkg/common"
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb"
@@ -49,8 +52,13 @@ func TestShopify_FromChunk(t *testing.T) {
DetectorType: detectorspb.DetectorType_Shopify, DetectorType: detectorspb.DetectorType_Shopify,
Redacted: domain, Redacted: domain,
Verified: true, Verified: true,
ExtraData: map[string]string{ ExtraData: &structpb.Struct{
"access_scopes": "read_analytics,unauthenticated_read_selling_plans", Fields: map[string]*structpb.Value{
"access_scopes": structpb.NewListValue(&structpb.ListValue{Values: []*structpb.Value{
structpb.NewStringValue("read_analytics"),
structpb.NewStringValue("unauthenticated_read_selling_plans"),
}}),
},
}, },
}, },
}, },
@@ -95,13 +103,19 @@ func TestShopify_FromChunk(t *testing.T) {
return return
} }
for i := range got { for i := range got {
if tt.want[i].ExtraData != nil {
if !proto.Equal(got[i].ExtraData, tt.want[i].ExtraData) {
t.Errorf("AWS.FromData() %s extra data not equal: got %+v, want %+v", tt.name, got[i].ExtraData, tt.want[i].ExtraData)
}
}
if len(got[i].Raw) == 0 { if len(got[i].Raw) == 0 {
t.Fatalf("no raw secret present: \n %+v", got[i]) t.Fatalf("no raw secret present: \n %+v", got[i])
} }
got[i].Raw = nil got[i].Raw = nil
} }
if diff := pretty.Compare(got, tt.want); diff != "" { ignoreOpts := cmpopts.IgnoreFields(detectors.Result{}, "RawV2", "Raw", "ExtraData")
t.Errorf("Shopify.FromData() %s diff: (-got +want)\n%s", tt.name, diff) if diff := cmp.Diff(got, tt.want, ignoreOpts); diff != "" {
t.Errorf("AWS.FromData() %s diff: (-got +want)\n%s", tt.name, diff)
} }
}) })
} }
File diff suppressed because it is too large Load Diff
+28 -1
View File
@@ -64,7 +64,34 @@ func (m *Result) validate(all bool) error {
// no validation rules for Hash // no validation rules for Hash
// no validation rules for ExtraData if all {
switch v := interface{}(m.GetExtraData()).(type) {
case interface{ ValidateAll() error }:
if err := v.ValidateAll(); err != nil {
errors = append(errors, ResultValidationError{
field: "ExtraData",
reason: "embedded message failed validation",
cause: err,
})
}
case interface{ Validate() error }:
if err := v.Validate(); err != nil {
errors = append(errors, ResultValidationError{
field: "ExtraData",
reason: "embedded message failed validation",
cause: err,
})
}
}
} else if v, ok := interface{}(m.GetExtraData()).(interface{ Validate() error }); ok {
if err := v.Validate(); err != nil {
return ResultValidationError{
field: "ExtraData",
reason: "embedded message failed validation",
cause: err,
}
}
}
if all { if all {
switch v := interface{}(m.GetStructuredData()).(type) { switch v := interface{}(m.GetStructuredData()).(type) {
+3 -2
View File
@@ -4,6 +4,8 @@ package detectors;
option go_package = "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb"; option go_package = "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb";
import "google/protobuf/struct.proto";
enum DecoderType { enum DecoderType {
UNKNOWN = 0; UNKNOWN = 0;
PLAIN = 1; PLAIN = 1;
@@ -926,12 +928,11 @@ message Result {
string redacted = 3; string redacted = 3;
bool verified = 4; bool verified = 4;
string hash = 5; string hash = 5;
map<string, string> extra_data = 6; google.protobuf.Struct extra_data = 6;
StructuredData structured_data = 7; StructuredData structured_data = 7;
string hash_v2 = 8; string hash_v2 = 8;
DecoderType decoder_type = 9; DecoderType decoder_type = 9;
} }
message StructuredData { message StructuredData {
repeated TlsPrivateKey tls_private_key = 1; repeated TlsPrivateKey tls_private_key = 1;
repeated GitHubSSHKey github_ssh_key = 2; repeated GitHubSSHKey github_ssh_key = 2;