Skip to content
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
bab758d
[INS-241] New detector (datadogapikey) for datadog apikeys
MuneebUllahKhan222 Dec 29, 2025
a942fe2
Analyzer updated to cater endpoint
MuneebUllahKhan222 Dec 30, 2025
8d6a588
Added new tests for anlyzers
MuneebUllahKhan222 Dec 30, 2025
7951443
Removed print statement
MuneebUllahKhan222 Jan 2, 2026
c6a2b6f
resolved comments and fixed integration tests.
MuneebUllahKhan222 Jan 5, 2026
3152a40
resolved comments
MuneebUllahKhan222 Jan 5, 2026
3e3a7de
changed cli prompt
MuneebUllahKhan222 Jan 5, 2026
ffb8d69
Merge branch 'main' into datadogapikey-detector
MuneebUllahKhan222 Jan 7, 2026
5fa6481
Merge branch 'main' into datadogapikey-detector
MuneebUllahKhan222 Jan 8, 2026
30bc23c
Fixed the comments and added app key validation in analyzer
MuneebUllahKhan222 Jan 9, 2026
e2bc5d8
Merge branch 'datadogapikey-detector' of https://github.com/MuneebUll…
MuneebUllahKhan222 Jan 9, 2026
829c986
Merge branch 'main' into datadogapikey-detector
MuneebUllahKhan222 Jan 9, 2026
20f4f19
renamed regex variable
MuneebUllahKhan222 Jan 12, 2026
491341c
Added found verified endpoint to ExtraData
MuneebUllahKhan222 Jan 12, 2026
8dd5d50
Merge branch 'main' into datadogapikey-detector
MuneebUllahKhan222 Jan 19, 2026
a82c86d
Clean up Analyze function by removing comments
MuneebUllahKhan222 Jan 23, 2026
b41f6a3
[INS-286] Added support to analyze just the apikey in datadog's analyzer
MuneebUllahKhan222 Jan 26, 2026
52b1a19
Merge branch 'main' into datadogapikey-detector
MuneebUllahKhan222 Jan 26, 2026
a475fbf
fixed linter issue
MuneebUllahKhan222 Jan 26, 2026
19fea8a
Merge branch 'main' into datadogapikey-detector
MuneebUllahKhan222 Jan 27, 2026
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
49 changes: 35 additions & 14 deletions pkg/analyzer/analyzers/datadog/datadog.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,29 +26,33 @@ func (a Analyzer) Type() analyzers.AnalyzerType {

// Analyze performs the analysis of the Datadog API key and returns the analyzer result.
func (a Analyzer) Analyze(ctx context.Context, credInfo map[string]string) (*analyzers.AnalyzerResult, error) {
apiKey, exist := credInfo["apiKey"]
if !exist {
return nil, errors.New("API key not found in credentials info")
}
apiKey := credInfo["apiKey"]

// Get appKey if provided
appKey := credInfo["appKey"]

info, err := AnalyzePermissions(a.Cfg, apiKey, appKey)
// Endpoint
endpoint := credInfo["endpoint"]

info, err := AnalyzePermissions(a.Cfg, apiKey, appKey, endpoint)
if err != nil {
return nil, err
}

return secretInfoToAnalyzerResult(info), nil
}

func AnalyzeAndPrintPermissions(cfg *config.Config, apiKey string, appKey string) {
info, err := AnalyzePermissions(cfg, apiKey, appKey)
func AnalyzeAndPrintPermissions(cfg *config.Config, apiKey, appKey, endpoint string) {
info, err := AnalyzePermissions(cfg, apiKey, appKey, endpoint)
if err != nil {
// just print the error in cli and continue as a partial success
color.Red("[x] Error : %s", err.Error())
}

if info == nil {
color.Red("[x] No information retrieved")
return
}

color.Green("[i] Valid Datadog API Key\n")

printUser(info.User)
Expand All @@ -57,16 +61,30 @@ func AnalyzeAndPrintPermissions(cfg *config.Config, apiKey string, appKey string
}

// AnalyzePermissions will collect all the scopes assigned to token along with resource it can access
func AnalyzePermissions(cfg *config.Config, apiKey string, appKey string) (*SecretInfo, error) {
func AnalyzePermissions(cfg *config.Config, apiKey, appKey, endpoint string) (*SecretInfo, error) {
if apiKey == "" {
return nil, errors.New("api key not found in credentials info")
}
if appKey == "" {
return nil, errors.New("app key not found in credentials info")
}

// create the http client
client := analyzers.NewAnalyzeClient(cfg)

var secretInfo = &SecretInfo{}

// First detect which DataDog domain works with this API key
baseURL, err := DetectDomain(client, apiKey, appKey)
if err != nil {
return nil, fmt.Errorf("[x] %v", err)
var baseURL string
var err error

// If endpoint is provided, use it directly; otherwise detect domain
if endpoint != "" {
baseURL = endpoint + "/api"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue: Let's use url.JoinPath here instead (I can't remember if I've given you my spiel about manipulating URLs as strings, but tl;dr: it's risky). There's a few places in this PR where we should change this; I won't note them though.

} else {
baseURL, err = DetectDomain(client, apiKey, appKey)
if err != nil {
return nil, fmt.Errorf("[x] %v", err)
}
}

// capture user information in secretInfo
Expand Down Expand Up @@ -114,7 +132,10 @@ func secretInfoToAnalyzerResult(info *SecretInfo) *analyzers.AnalyzerResult {
}

permissionBindings := secretInfoPermissionsToAnalyzerPermission(info.Permissions)
result.Bindings = analyzers.BindAllPermissions(*userResource, *permissionBindings...)

if userResource != nil && len(*permissionBindings) > 0 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: I might unify these under an if len(*permissionBindings) > 0 block; it makes it more clear that condition is required to set bindings here.

result.Bindings = analyzers.BindAllPermissions(*userResource, *permissionBindings...)
}

// Extract information from resources to create bindings
for _, resource := range info.Resources {
Expand Down
34 changes: 28 additions & 6 deletions pkg/analyzer/analyzers/datadog/datadog_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,12 @@ func TestAnalyzer_Analyze(t *testing.T) {
}

tests := []struct {
name string
apiKey string
appKey string
want []byte // JSON string
wantErr bool
name string
apiKey string
appKey string
endpoint string
want []byte // JSON string
wantErr bool
}{
{
name: "valid datadog credentials",
Expand All @@ -51,6 +52,27 @@ func TestAnalyzer_Analyze(t *testing.T) {
want: expectedOutput,
wantErr: false,
},
{
name: "valid datadog credentials with endpoint",
apiKey: apiKey,
appKey: appKey,
endpoint: "https://api.us5.datadoghq.com",
want: expectedOutput,
wantErr: false,
},
{
name: "valid datadog credentials with invalid endpoint",
apiKey: apiKey,
appKey: appKey,
endpoint: "https://api.eu.datadoghq.com",
want: []byte(fmt.Sprintf(`{
"AnalyzerType": %s,
"Bindings": [],
"UnboundedResources": null,
"Metadata": {}
}`, analyzers.AnalyzerTypeDatadog)),
wantErr: true,
},
{
name: "invalid credentials",
apiKey: "invalid_api_key",
Expand All @@ -63,7 +85,7 @@ func TestAnalyzer_Analyze(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
a := Analyzer{Cfg: &config.Config{}}
got, err := a.Analyze(ctx, map[string]string{"apiKey": tt.apiKey, "appKey": tt.appKey})
got, err := a.Analyze(ctx, map[string]string{"apiKey": tt.apiKey, "appKey": tt.appKey, "endpoint": tt.endpoint})

if (err != nil) != tt.wantErr {
t.Errorf("Analyzer.Analyze() error = %v, wantErr %v", err, tt.wantErr)
Expand Down
Loading
Loading