From fba317473970097f0a4a3d4ae1ce7eb1fe8f1c7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Sibiril?= <81782+aureliensibiril@users.noreply.github.com> Date: Wed, 3 Jun 2026 18:02:44 +0200 Subject: [PATCH] Map Datadog account type, MFA, and job title MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com> --- pkg/accessreview/drivers/datadog.go | 54 +++++++++++++------ pkg/accessreview/drivers/datadog_test.go | 10 +++- .../drivers/testdata/datadog.yaml | 5 ++ 3 files changed, 52 insertions(+), 17 deletions(-) diff --git a/pkg/accessreview/drivers/datadog.go b/pkg/accessreview/drivers/datadog.go index caf45c558..6fe8b39a3 100644 --- a/pkg/accessreview/drivers/datadog.go +++ b/pkg/accessreview/drivers/datadog.go @@ -23,6 +23,8 @@ import ( "strconv" "strings" "time" + + "go.probo.inc/probo/pkg/coredata" ) // DatadogDriver lists Datadog org members via GET /api/v2/users. The API @@ -57,14 +59,17 @@ type datadogUsersResponse struct { Data []struct { ID string `json:"id"` Attributes struct { - Email string `json:"email"` - Name string `json:"name"` - Handle string `json:"handle"` - Disabled bool `json:"disabled"` - Status string `json:"status"` - Verified bool `json:"verified"` - CreatedAt string `json:"created_at"` - ModifiedAt string `json:"modified_at"` + Email string `json:"email"` + Name string `json:"name"` + Handle string `json:"handle"` + Title string `json:"title"` + Disabled bool `json:"disabled"` + Status string `json:"status"` + Verified bool `json:"verified"` + ServiceAccount bool `json:"service_account"` + MFAEnabled bool `json:"mfa_enabled"` + CreatedAt string `json:"created_at"` + ModifiedAt string `json:"modified_at"` } `json:"attributes"` Relationships struct { Roles struct { @@ -86,7 +91,7 @@ type datadogUsersResponse struct { func (d *DatadogDriver) ListAccounts(ctx context.Context) ([]AccountRecord, error) { var records []AccountRecord - for page := 0; page < maxPaginationPages; page++ { + for page := range maxPaginationPages { resp, err := d.queryUsers(ctx, page) if err != nil { return nil, err @@ -119,14 +124,31 @@ func (d *DatadogDriver) ListAccounts(ctx context.Context) ([]AccountRecord, erro } } + accountType := coredata.AccessEntryAccountTypeUser + if u.Attributes.ServiceAccount { + accountType = coredata.AccessEntryAccountTypeServiceAccount + } + + mfaStatus := coredata.MFAStatusDisabled + if u.Attributes.MFAEnabled { + mfaStatus = coredata.MFAStatusEnabled + } + records = append(records, AccountRecord{ - Email: u.Attributes.Email, - FullName: u.Attributes.Name, - Role: role, - Active: &active, - IsAdmin: isAdmin, - ExternalID: u.ID, - CreatedAt: parseDatadogTime(u.Attributes.CreatedAt), + Email: u.Attributes.Email, + FullName: u.Attributes.Name, + Role: role, + JobTitle: u.Attributes.Title, + Active: &active, + IsAdmin: isAdmin, + MFAStatus: mfaStatus, + // Datadog's /api/v2/users does not expose the login method + // used (no allowed_login_methods in the schema), so the + // auth method is unknown. + AuthMethod: coredata.AccessEntryAuthMethodUnknown, + AccountType: accountType, + ExternalID: u.ID, + CreatedAt: parseDatadogTime(u.Attributes.CreatedAt), }) } diff --git a/pkg/accessreview/drivers/datadog_test.go b/pkg/accessreview/drivers/datadog_test.go index ce9c5f19d..af22ae867 100644 --- a/pkg/accessreview/drivers/datadog_test.go +++ b/pkg/accessreview/drivers/datadog_test.go @@ -21,6 +21,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "go.probo.inc/probo/pkg/coredata" ) func TestDatadogDriver(t *testing.T) { @@ -42,8 +43,13 @@ func TestDatadogDriver(t *testing.T) { assert.True(t, *r.Active) assert.True(t, r.IsAdmin) assert.Equal(t, "Datadog Admin Role", r.Role) + assert.Equal(t, "Security Engineer", r.JobTitle) + assert.Equal(t, coredata.AccessEntryAccountTypeUser, r.AccountType) + assert.Equal(t, coredata.MFAStatusEnabled, r.MFAStatus) + assert.Equal(t, coredata.AccessEntryAuthMethodUnknown, r.AuthMethod) - // Second record exercises the inactive + non-admin branches. + // Second record exercises the inactive, non-admin, and service-account + // (MFA-disabled) branches. r2 := records[1] assert.Equal(t, "bob@example.com", r2.Email) assert.Equal(t, "abc-222", r2.ExternalID) @@ -51,4 +57,6 @@ func TestDatadogDriver(t *testing.T) { assert.False(t, *r2.Active) assert.False(t, r2.IsAdmin) assert.Equal(t, "Datadog Standard Role", r2.Role) + assert.Equal(t, coredata.AccessEntryAccountTypeServiceAccount, r2.AccountType) + assert.Equal(t, coredata.MFAStatusDisabled, r2.MFAStatus) } diff --git a/pkg/accessreview/drivers/testdata/datadog.yaml b/pkg/accessreview/drivers/testdata/datadog.yaml index c0346b679..7f6d14b06 100644 --- a/pkg/accessreview/drivers/testdata/datadog.yaml +++ b/pkg/accessreview/drivers/testdata/datadog.yaml @@ -41,9 +41,12 @@ interactions: "email": "alice@example.com", "name": "Alice Example", "handle": "alice@example.com", + "title": "Security Engineer", "disabled": false, "status": "Active", "verified": true, + "service_account": false, + "mfa_enabled": true, "created_at": "2025-01-02T03:04:05.000000+00:00" }, "relationships": { "roles": { "data": [ { "type": "roles", "id": "role-admin" } ] } } @@ -58,6 +61,8 @@ interactions: "disabled": true, "status": "Disabled", "verified": true, + "service_account": true, + "mfa_enabled": false, "created_at": "2025-02-02T03:04:05.000000+00:00" }, "relationships": { "roles": { "data": [ { "type": "roles", "id": "role-standard" } ] } }