Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update metadata for DataDog for API + APPKey #2879

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions pkg/detectors/datadogtoken/datadogtoken.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package datadogtoken

import (
"context"
"encoding/json"
"net/http"
"strings"

Expand Down Expand Up @@ -30,6 +31,65 @@ var (
apiPat = regexp.MustCompile(detectors.PrefixRegex([]string{"datadog", "dd"}) + `\b([a-zA-Z-0-9]{32})\b`)
)

type userServiceResponse struct {
Data []*user `json:"data"`
Included []*options `json:"included"`
}

type user struct {
Attributes userAttributes `json:"attributes"`
}

type userAttributes struct {
Email string `json:"email"`
IsServiceAccount bool `json:"service_account"`
Verified bool `json:"verified"`
Disabled bool `json:"disabled"`
}

type options struct {
Type string `json:"type"`
Attributes optionAttribute `json:"attributes"`
}

type optionAttribute struct {
Url string `json:"url"`
Name string `json:"name"`
Disabled bool `json:"disabled"`
}

func setUserEmails(data []*user, s1 *detectors.Result) {
var emails []string
for _, user := range data {
// filter out non verified emails, disabled emails, service accounts
if user.Attributes.Verified && !user.Attributes.Disabled && !user.Attributes.IsServiceAccount {
emails = append(emails, user.Attributes.Email)
}
}

if len(emails) == 0 && len(data) > 0 {
emails = append(emails, data[0].Attributes.Email)
}

s1.ExtraData["user_emails"] = strings.Join(emails, ", ")
}

func setOrganizationInfo(opt []*options, s1 *detectors.Result) {
var orgs *options
for _, option := range opt {
if option.Type == "orgs" && !option.Attributes.Disabled {
orgs = option
break
}
}

if orgs != nil {
s1.ExtraData["org_name"] = orgs.Attributes.Name
s1.ExtraData["org_url"] = orgs.Attributes.Url
}

}

// Keywords are used for efficiently pre-filtering chunks.
// Use identifiers in the secret preferably, or the provider name.
func (s Scanner) Keywords() []string {
Expand Down Expand Up @@ -78,6 +138,17 @@ 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
var serviceResponse userServiceResponse
if err := json.NewDecoder(res.Body).Decode(&serviceResponse); err == nil {
// setup emails
if len(serviceResponse.Data) > 0 {
setUserEmails(serviceResponse.Data, &s1)
}
// setup organizations
if len(serviceResponse.Included) > 0 {
setOrganizationInfo(serviceResponse.Included, &s1)
}
}
}
}
}
Expand Down