Skip to content

Commit

Permalink
⭐️ Microsoft 365 risky users resource (#4570)
Browse files Browse the repository at this point in the history
  • Loading branch information
chris-rock authored Aug 19, 2024
1 parent 6e02adf commit 54e8063
Show file tree
Hide file tree
Showing 6 changed files with 317 additions and 2 deletions.
22 changes: 22 additions & 0 deletions providers/ms365/resources/ms365.lr
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,8 @@ microsoft.security {
secureScores() []microsoft.security.securityscore
// Latest security score
latestSecureScores() microsoft.security.securityscore
// List Microsoft Entra users who are at risk
riskyUsers() []microsoft.security.riskyUser
}

// Microsoft Secure Score
Expand Down Expand Up @@ -423,6 +425,26 @@ private microsoft.security.securityscore @defaults("id azureTenantId") {
vendorInformation dict
}

// Microsoft Entra users who are at risk
microsoft.security.riskyUser @defaults("principalName riskLevel riskState lastUpdatedAt"){
// Risky user ID
id string
// User name
name string
// User principal
principalName string
// Entra User
user() microsoft.user
// Risk detail
riskDetail string
// Risk level
riskLevel string
// Risk state
riskState string
// Risk last updated
lastUpdatedAt time
}

// Microsoft policies
microsoft.policies {
// Authorization policy
Expand Down
179 changes: 179 additions & 0 deletions providers/ms365/resources/ms365.lr.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions providers/ms365/resources/ms365.lr.manifest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -254,8 +254,21 @@ resources:
microsoft.security:
fields:
latestSecureScores: {}
riskyUsers:
min_mondoo_version: 9.0.0
secureScores: {}
min_mondoo_version: 5.15.0
microsoft.security.riskyUser:
fields:
id: {}
lastUpdatedAt: {}
name: {}
principalName: {}
riskDetail: {}
riskLevel: {}
riskState: {}
user: {}
min_mondoo_version: 9.0.0
microsoft.security.securityscore:
fields:
activeUserCount: {}
Expand Down
98 changes: 98 additions & 0 deletions providers/ms365/resources/security_riskyusers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// Copyright (c) Mondoo, Inc.
// SPDX-License-Identifier: BUSL-1.1

package resources

import (
"context"
"github.com/microsoftgraph/msgraph-sdk-go/identityprotection"
"github.com/microsoftgraph/msgraph-sdk-go/models"
"go.mondoo.com/cnquery/v11/llx"
"go.mondoo.com/cnquery/v11/providers-sdk/v1/plugin"
"go.mondoo.com/cnquery/v11/providers/ms365/connection"
)

// riskyUsers returns a list of risky users
// requires IdentityRiskyUser.Read.All permission
// see https://learn.microsoft.com/en-us/graph/api/resources/riskyuser?view=graph-rest-1.0
func (a *mqlMicrosoftSecurity) riskyUsers() ([]interface{}, error) {
conn := a.MqlRuntime.Connection.(*connection.Ms365Connection)
graphClient, err := conn.GraphClient()
if err != nil {
return nil, err
}
ctx := context.Background()

filter := "riskState eq 'atRisk'"
resp, err := graphClient.IdentityProtection().RiskyUsers().Get(ctx, &identityprotection.RiskyUsersRequestBuilderGetRequestConfiguration{
QueryParameters: &identityprotection.RiskyUsersRequestBuilderGetQueryParameters{
Filter: &filter,
},
})
if err != nil {
return nil, transformError(err)
}

res := []interface{}{}
users := resp.GetValue()
for i := range users {
riskyUser := users[i]
mqlResource, err := newMqlMicrosoftRiskyUser(a.MqlRuntime, riskyUser)
if err != nil {
return nil, err
}

res = append(res, mqlResource)
}
return res, nil
}

func newMqlMicrosoftRiskyUser(runtime *plugin.Runtime, riskyUser models.RiskyUserable) (*mqlMicrosoftSecurityRiskyUser, error) {
if riskyUser == nil {
return nil, nil
}

var detail *string
if riskyUser.GetRiskDetail() != nil {
detailData := riskyUser.GetRiskDetail().String()
detail = &detailData
}

var riskLevel *string
if riskyUser.GetRiskLevel() != nil {
riskLevelData := riskyUser.GetRiskLevel().String()
riskLevel = &riskLevelData
}

var riskState *string
if riskyUser.GetRiskState() != nil {
riskStateData := riskyUser.GetRiskState().String()
riskState = &riskStateData
}

mqlResource, err := CreateResource(runtime, "microsoft.security.riskyUser",
map[string]*llx.RawData{
"__id": llx.StringDataPtr(riskyUser.GetId()),
"id": llx.StringDataPtr(riskyUser.GetId()),
"name": llx.StringDataPtr(riskyUser.GetUserDisplayName()),
"principalName": llx.StringDataPtr(riskyUser.GetUserPrincipalName()),
"riskDetail": llx.StringDataPtr(detail),
"riskLevel": llx.StringDataPtr(riskLevel),
"riskState": llx.StringDataPtr(riskState),
"lastUpdatedAt": llx.TimeDataPtr(riskyUser.GetRiskLastUpdatedDateTime()),
})
if err != nil {
return nil, err
}
return mqlResource.(*mqlMicrosoftSecurityRiskyUser), nil
}

func (r *mqlMicrosoftSecurityRiskyUser) user() (*mqlMicrosoftUser, error) {
user, err := NewResource(r.MqlRuntime, "microsoft.user", map[string]*llx.RawData{
"id": llx.StringData(r.Id.Data),
})
if err != nil {
return nil, err
}
return user.(*mqlMicrosoftUser), nil
}
Loading

0 comments on commit 54e8063

Please sign in to comment.