package gcp import ( "bytes" "context" "encoding/json" "strconv" "strings" regexp "github.com/wasilibs/go-re2" "golang.org/x/oauth2/google" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors" "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" ) type Scanner struct{} // Ensure the Scanner satisfies the interface at compile time. var _ interface { detectors.Detector detectors.CustomFalsePositiveChecker detectors.MaxSecretSizeProvider detectors.StartOffsetProvider } = (*Scanner)(nil) var ( keyPat = regexp.MustCompile(`\{[^{]+auth_provider_x509_cert_url[^}]+\}`) ) type gcpKey struct { Type string `json:"type"` ProjectID string `json:"project_id"` PrivateKeyID string `json:"private_key_id"` PrivateKey string `json:"private_key"` ClientEmail string `json:"client_email"` ClientID string `json:"client_id"` AuthURI string `json:"auth_uri"` TokenURI string `json:"token_uri"` AuthProviderX509CertURL string `json:"auth_provider_x509_cert_url"` ClientX509CertURL string `json:"client_x509_cert_url"` } // Keywords are used for efficiently pre-filtering chunks. // Use identifiers in the secret preferably, or the provider name. func (s Scanner) Keywords() []string { return []string{"provider_x509"} } const maxGCPKeySize = 2048 // MaxSecretSize returns the maximum size of a secret that this detector can find. func (Scanner) MaxSecretSize() int64 { return maxGCPKeySize } const startOffset = 4096 // StartOffset returns the start offset for the secret this detector finds. func (Scanner) StartOffset() int64 { return startOffset } func (s Scanner) Type() detectorspb.DetectorType { return detectorspb.DetectorType_GCP } func (s Scanner) Description() string { return "GCP (Google Cloud Platform) is a suite of cloud computing services that runs on the same infrastructure that Google uses internally for its end-user products. GCP keys can be used to access and manage these services." } // FromData will find and optionally verify GCP secrets in a given set of bytes. func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (results []detectors.Result, err error) { dataStr := string(data) uniqueMatches := make(map[string]struct{}) for _, match := range keyPat.FindAllString(dataStr, -1) { uniqueMatches[match] = struct{}{} } for match := range uniqueMatches { key := cleanInput(match) creds := gcpKey{} if err := json.NewDecoder(strings.NewReader(key)).Decode(&creds); err != nil { continue } // for Slack mangling (mailto scheme and hyperlinks) if strings.Contains(creds.ClientEmail, `") return s } //endregion