Map Datadog account type, MFA, and job title
Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
This commit is contained in:
@@ -23,6 +23,8 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"go.probo.inc/probo/pkg/coredata"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DatadogDriver lists Datadog org members via GET /api/v2/users. The API
|
// DatadogDriver lists Datadog org members via GET /api/v2/users. The API
|
||||||
@@ -57,14 +59,17 @@ type datadogUsersResponse struct {
|
|||||||
Data []struct {
|
Data []struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Attributes struct {
|
Attributes struct {
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Handle string `json:"handle"`
|
Handle string `json:"handle"`
|
||||||
Disabled bool `json:"disabled"`
|
Title string `json:"title"`
|
||||||
Status string `json:"status"`
|
Disabled bool `json:"disabled"`
|
||||||
Verified bool `json:"verified"`
|
Status string `json:"status"`
|
||||||
CreatedAt string `json:"created_at"`
|
Verified bool `json:"verified"`
|
||||||
ModifiedAt string `json:"modified_at"`
|
ServiceAccount bool `json:"service_account"`
|
||||||
|
MFAEnabled bool `json:"mfa_enabled"`
|
||||||
|
CreatedAt string `json:"created_at"`
|
||||||
|
ModifiedAt string `json:"modified_at"`
|
||||||
} `json:"attributes"`
|
} `json:"attributes"`
|
||||||
Relationships struct {
|
Relationships struct {
|
||||||
Roles struct {
|
Roles struct {
|
||||||
@@ -86,7 +91,7 @@ type datadogUsersResponse struct {
|
|||||||
func (d *DatadogDriver) ListAccounts(ctx context.Context) ([]AccountRecord, error) {
|
func (d *DatadogDriver) ListAccounts(ctx context.Context) ([]AccountRecord, error) {
|
||||||
var records []AccountRecord
|
var records []AccountRecord
|
||||||
|
|
||||||
for page := 0; page < maxPaginationPages; page++ {
|
for page := range maxPaginationPages {
|
||||||
resp, err := d.queryUsers(ctx, page)
|
resp, err := d.queryUsers(ctx, page)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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{
|
records = append(records, AccountRecord{
|
||||||
Email: u.Attributes.Email,
|
Email: u.Attributes.Email,
|
||||||
FullName: u.Attributes.Name,
|
FullName: u.Attributes.Name,
|
||||||
Role: role,
|
Role: role,
|
||||||
Active: &active,
|
JobTitle: u.Attributes.Title,
|
||||||
IsAdmin: isAdmin,
|
Active: &active,
|
||||||
ExternalID: u.ID,
|
IsAdmin: isAdmin,
|
||||||
CreatedAt: parseDatadogTime(u.Attributes.CreatedAt),
|
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),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
"go.probo.inc/probo/pkg/coredata"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDatadogDriver(t *testing.T) {
|
func TestDatadogDriver(t *testing.T) {
|
||||||
@@ -42,8 +43,13 @@ func TestDatadogDriver(t *testing.T) {
|
|||||||
assert.True(t, *r.Active)
|
assert.True(t, *r.Active)
|
||||||
assert.True(t, r.IsAdmin)
|
assert.True(t, r.IsAdmin)
|
||||||
assert.Equal(t, "Datadog Admin Role", r.Role)
|
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]
|
r2 := records[1]
|
||||||
assert.Equal(t, "bob@example.com", r2.Email)
|
assert.Equal(t, "bob@example.com", r2.Email)
|
||||||
assert.Equal(t, "abc-222", r2.ExternalID)
|
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.Active)
|
||||||
assert.False(t, r2.IsAdmin)
|
assert.False(t, r2.IsAdmin)
|
||||||
assert.Equal(t, "Datadog Standard Role", r2.Role)
|
assert.Equal(t, "Datadog Standard Role", r2.Role)
|
||||||
|
assert.Equal(t, coredata.AccessEntryAccountTypeServiceAccount, r2.AccountType)
|
||||||
|
assert.Equal(t, coredata.MFAStatusDisabled, r2.MFAStatus)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,9 +41,12 @@ interactions:
|
|||||||
"email": "alice@example.com",
|
"email": "alice@example.com",
|
||||||
"name": "Alice Example",
|
"name": "Alice Example",
|
||||||
"handle": "alice@example.com",
|
"handle": "alice@example.com",
|
||||||
|
"title": "Security Engineer",
|
||||||
"disabled": false,
|
"disabled": false,
|
||||||
"status": "Active",
|
"status": "Active",
|
||||||
"verified": true,
|
"verified": true,
|
||||||
|
"service_account": false,
|
||||||
|
"mfa_enabled": true,
|
||||||
"created_at": "2025-01-02T03:04:05.000000+00:00"
|
"created_at": "2025-01-02T03:04:05.000000+00:00"
|
||||||
},
|
},
|
||||||
"relationships": { "roles": { "data": [ { "type": "roles", "id": "role-admin" } ] } }
|
"relationships": { "roles": { "data": [ { "type": "roles", "id": "role-admin" } ] } }
|
||||||
@@ -58,6 +61,8 @@ interactions:
|
|||||||
"disabled": true,
|
"disabled": true,
|
||||||
"status": "Disabled",
|
"status": "Disabled",
|
||||||
"verified": true,
|
"verified": true,
|
||||||
|
"service_account": true,
|
||||||
|
"mfa_enabled": false,
|
||||||
"created_at": "2025-02-02T03:04:05.000000+00:00"
|
"created_at": "2025-02-02T03:04:05.000000+00:00"
|
||||||
},
|
},
|
||||||
"relationships": { "roles": { "data": [ { "type": "roles", "id": "role-standard" } ] } }
|
"relationships": { "roles": { "data": [ { "type": "roles", "id": "role-standard" } ] } }
|
||||||
|
|||||||
Reference in New Issue
Block a user