-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Expand file tree
/
Copy pathutils.go
More file actions
116 lines (102 loc) · 3.19 KB
/
utils.go
File metadata and controls
116 lines (102 loc) · 3.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package aws
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base32"
"encoding/binary"
"encoding/hex"
"fmt"
"strings"
regexp "github.com/wasilibs/go-re2"
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors"
)
// ResourceTypes derived from: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html#identifiers-unique-ids
var ResourceTypes = map[string]string{
"ABIA": "AWS STS service bearer token",
"ACCA": "Context-specific credential",
"AGPA": "User group",
"AIDA": "IAM user",
"AIPA": "Amazon EC2 instance profile",
"AKIA": "Access key",
"ANPA": "Managed policy",
"ANVA": "Version in a managed policy",
"APKA": "Public key",
"AROA": "Role",
"ASCA": "Certificate",
"ASIA": "Temporary (AWS STS) access key IDs",
}
// UrlEncodedReplacer helps capture base64-encoded results that may be url-encoded.
// TODO: Add this as a decoder, or make it a more generic.
var UrlEncodedReplacer = strings.NewReplacer(
"%2B", "+",
"%2b", "+",
"%2F", "/",
"%2f", "/",
"%3d", "=",
"%3D", "=",
)
// Hashes, like those for git, do technically match the secret pattern.
// But they are extremely unlikely to be generated as an actual AWS secret.
// So when we find them, if they're not verified, we should ignore the result.
var FalsePositiveSecretPat = regexp.MustCompile(`[a-f0-9]{40}`)
func GetAccountNumFromID(id string) (string, error) {
// Function to get the account number from an AWS ID (no verification required)
// Source: https://medium.com/@TalBeerySec/a-short-note-on-aws-key-id-f88cc4317489
if len(id) < 4 {
return "", fmt.Errorf("AWSID is too short")
}
if id[4] == 'I' || id[4] == 'J' {
return "", fmt.Errorf("can't get account number from AKIAJ/ASIAJ or AKIAI/ASIAI keys")
}
trimmedAWSID := id[4:]
decodedBytes, err := base32.StdEncoding.WithPadding(base32.NoPadding).DecodeString(strings.ToUpper(trimmedAWSID))
if err != nil {
return "", err
}
if len(decodedBytes) < 6 {
return "", fmt.Errorf("decoded AWSID is too short")
}
data := make([]byte, 8)
copy(data[2:], decodedBytes[0:6])
z := binary.BigEndian.Uint64(data)
const mask uint64 = 0x7fffffffff80
accountNum := (z & mask) >> 7
return fmt.Sprintf("%012d", accountNum), nil
}
func GetHash(input string) string {
data := []byte(input)
hasher := sha256.New()
hasher.Write(data)
return hex.EncodeToString(hasher.Sum(nil))
}
func GetHMAC(key []byte, data []byte) []byte {
hasher := hmac.New(sha256.New, key)
hasher.Write(data)
return hasher.Sum(nil)
}
func CleanResults(results []detectors.Result, verificationEnabled bool) []detectors.Result {
if len(results) == 0 {
return results
}
if !verificationEnabled {
return results
}
// For every ID, we want at most one result, preferably verified.
idResults := map[string]detectors.Result{}
for _, result := range results {
// Always accept the verified result as the result for the given ID.
if result.Verified {
idResults[result.Redacted] = result
continue
}
// Only include an unverified result if we don't already have a result for a given ID.
if _, exist := idResults[result.Redacted]; !exist {
idResults[result.Redacted] = result
}
}
var out []detectors.Result
for _, r := range idResults {
out = append(out, r)
}
return out
}