Skip to content

Commit 5873b76

Browse files
author
Igor Komlew
authored
extended microsoft.conditionalAccess with policies (#5637)
* extended microsoft.conditionalAccess with policies
1 parent 4962db8 commit 5873b76

File tree

4 files changed

+2240
-0
lines changed

4 files changed

+2240
-0
lines changed

providers/ms365/resources/conditional-access.go

Lines changed: 376 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,14 @@ package resources
55

66
import (
77
"context"
8+
"fmt"
89

910
"github.com/microsoftgraph/msgraph-sdk-go/models"
1011
"go.mondoo.com/cnquery/v11/llx"
12+
"go.mondoo.com/cnquery/v11/providers-sdk/v1/plugin"
13+
"go.mondoo.com/cnquery/v11/providers-sdk/v1/util/convert"
1114
"go.mondoo.com/cnquery/v11/providers/ms365/connection"
15+
"go.mondoo.com/cnquery/v11/types"
1216
)
1317

1418
func (m *mqlMicrosoftConditionalAccessIpNamedLocation) id() (string, error) {
@@ -109,3 +113,375 @@ func (a *mqlMicrosoftConditionalAccessNamedLocations) countryLocations() ([]inte
109113

110114
return locationDetails, nil
111115
}
116+
117+
func (m *mqlMicrosoftConditionalAccessPolicy) id() (string, error) {
118+
return m.Id.Data, nil
119+
}
120+
121+
func (m *mqlMicrosoftConditionalAccessPolicyConditions) id() (string, error) {
122+
return m.Id.Data, nil
123+
}
124+
125+
func (m *mqlMicrosoftConditionalAccessPolicyGrantControls) id() (string, error) {
126+
return m.Id.Data, nil
127+
}
128+
129+
func (m *mqlMicrosoftConditionalAccessPolicySessionControls) id() (string, error) {
130+
return m.Id.Data, nil
131+
}
132+
133+
// Conditional Access Policies
134+
func (a *mqlMicrosoftConditionalAccess) policies() ([]interface{}, error) {
135+
conn := a.MqlRuntime.Connection.(*connection.Ms365Connection)
136+
graphClient, err := conn.GraphClient()
137+
if err != nil {
138+
return nil, err
139+
}
140+
141+
ctx := context.Background()
142+
policies, err := graphClient.Identity().ConditionalAccess().Policies().Get(ctx, nil)
143+
if err != nil {
144+
return nil, transformError(err)
145+
}
146+
147+
var policyDetails []interface{}
148+
for _, policy := range policies.GetValue() {
149+
id := policy.GetId()
150+
displayName := policy.GetDisplayName()
151+
152+
if id != nil && displayName != nil {
153+
policyResource, err := a.createPolicyResource(policy)
154+
if err != nil {
155+
return nil, err
156+
}
157+
policyDetails = append(policyDetails, policyResource)
158+
}
159+
}
160+
161+
return policyDetails, nil
162+
}
163+
164+
// Helper methods for creating policy sub-resources
165+
func (a *mqlMicrosoftConditionalAccess) createPolicyResource(policy models.ConditionalAccessPolicyable) (interface{}, error) {
166+
id := policy.GetId()
167+
if id == nil {
168+
return nil, fmt.Errorf("policy ID cannot be nil")
169+
}
170+
171+
// Create conditions resource
172+
conditions, err := a.createConditionsResource(*id, policy.GetConditions())
173+
if err != nil {
174+
return nil, fmt.Errorf("failed to create conditions resource: %w", err)
175+
}
176+
177+
// Create grant controls resource
178+
grantControls, err := a.createGrantControlsResource(*id, policy.GetGrantControls())
179+
if err != nil {
180+
return nil, fmt.Errorf("failed to create grant controls resource: %w", err)
181+
}
182+
183+
// Create session controls resource
184+
sessionControls, err := a.createSessionControlsResource(*id, policy.GetSessionControls())
185+
if err != nil {
186+
return nil, fmt.Errorf("failed to create session controls resource: %w", err)
187+
}
188+
189+
policyInfo, err := CreateResource(a.MqlRuntime, "microsoft.conditionalAccess.policy",
190+
map[string]*llx.RawData{
191+
"id": llx.StringDataPtr(id),
192+
"templateId": llx.StringDataPtr(policy.GetTemplateId()),
193+
"displayName": llx.StringDataPtr(policy.GetDisplayName()),
194+
"createdDateTime": llx.TimeDataPtr(policy.GetCreatedDateTime()),
195+
"modifiedDateTime": llx.TimeDataPtr(policy.GetModifiedDateTime()),
196+
"state": llx.StringData(policy.GetState().String()),
197+
"sessionControls": llx.ResourceData(sessionControls, "microsoft.conditionalAccess.policy.sessionControls"),
198+
"conditions": llx.ResourceData(conditions, "microsoft.conditionalAccess.policy.conditions"),
199+
"grantControls": llx.ResourceData(grantControls, "microsoft.conditionalAccess.policy.grantControls"),
200+
})
201+
if err != nil {
202+
return nil, fmt.Errorf("failed to create policy resource: %w", err)
203+
}
204+
205+
return policyInfo, nil
206+
}
207+
208+
func (a *mqlMicrosoftConditionalAccess) createConditionsResource(
209+
policyId string,
210+
conditions models.ConditionalAccessConditionSetable,
211+
) (plugin.Resource, error) {
212+
conditionsId := policyId + "_conditions"
213+
214+
var err error
215+
var mqlApplications plugin.Resource
216+
var mqlUsers plugin.Resource
217+
var mqlLocations plugin.Resource
218+
var mqlPlatforms plugin.Resource
219+
var mqlClientApplications plugin.Resource
220+
var mqlAuthenticationFlows plugin.Resource
221+
222+
if conditions != nil && conditions.GetAuthenticationFlows() != nil {
223+
authenticationFlows := conditions.GetAuthenticationFlows()
224+
usersData := map[string]*llx.RawData{
225+
"transferMethods": llx.StringData(authenticationFlows.GetTransferMethods().String()),
226+
}
227+
228+
mqlClientApplications, err = CreateResource(a.MqlRuntime, "microsoft.conditionalAccess.policy.conditions.authenticationFlows", usersData)
229+
if err != nil {
230+
return nil, err
231+
}
232+
}
233+
234+
// Extract users
235+
if conditions != nil && conditions.GetUsers() != nil {
236+
users := conditions.GetUsers()
237+
usersData := map[string]*llx.RawData{
238+
"includeUsers": llx.ArrayData(convert.SliceAnyToInterface(users.GetIncludeUsers()), types.String),
239+
"excludeUsers": llx.ArrayData(convert.SliceAnyToInterface(users.GetExcludeUsers()), types.String),
240+
"includeGroups": llx.ArrayData(convert.SliceAnyToInterface(users.GetIncludeGroups()), types.String),
241+
"excludeGroups": llx.ArrayData(convert.SliceAnyToInterface(users.GetExcludeGroups()), types.String),
242+
"includeRoles": llx.ArrayData(convert.SliceAnyToInterface(users.GetIncludeRoles()), types.String),
243+
"excludeRoles": llx.ArrayData(convert.SliceAnyToInterface(users.GetExcludeRoles()), types.String),
244+
}
245+
246+
mqlUsers, err = CreateResource(a.MqlRuntime, "microsoft.conditionalAccess.policy.conditions.users", usersData)
247+
if err != nil {
248+
return nil, err
249+
}
250+
}
251+
252+
if conditions != nil && conditions.GetApplications() != nil {
253+
apps := conditions.GetApplications()
254+
mqlApplications, err = CreateResource(a.MqlRuntime, "microsoft.conditionalAccess.policy.conditions.applications", map[string]*llx.RawData{
255+
"includeApplications": llx.ArrayData(convert.SliceAnyToInterface(apps.GetIncludeApplications()), types.String),
256+
"excludeApplications": llx.ArrayData(convert.SliceAnyToInterface(apps.GetExcludeApplications()), types.String),
257+
"includeUserActions": llx.ArrayData(convert.SliceAnyToInterface(apps.GetIncludeUserActions()), types.String),
258+
})
259+
if err != nil {
260+
return nil, err
261+
}
262+
}
263+
264+
// Extract locations and create mqlLocations resource
265+
if conditions != nil && conditions.GetLocations() != nil {
266+
locations := conditions.GetLocations()
267+
locationsData := map[string]*llx.RawData{
268+
"includeLocations": llx.ArrayData(convert.SliceAnyToInterface(locations.GetIncludeLocations()), types.String),
269+
"excludeLocations": llx.ArrayData(convert.SliceAnyToInterface(locations.GetExcludeLocations()), types.String),
270+
}
271+
mqlLocations, err = CreateResource(a.MqlRuntime, "microsoft.conditionalAccess.policy.conditions.locations", locationsData)
272+
if err != nil {
273+
return nil, err
274+
}
275+
}
276+
277+
// Extract platforms and create mqlPlatforms resource
278+
if conditions != nil && conditions.GetPlatforms() != nil {
279+
platforms := conditions.GetPlatforms()
280+
platformsData := make(map[string]*llx.RawData)
281+
282+
var includePlatformStrings []string
283+
for _, platform := range platforms.GetIncludePlatforms() {
284+
if platform.String() != "" {
285+
includePlatformStrings = append(includePlatformStrings, platform.String())
286+
}
287+
}
288+
platformsData["includePlatforms"] = llx.ArrayData(convert.SliceAnyToInterface(includePlatformStrings), types.String)
289+
290+
var excludePlatformStrings []string
291+
for _, platform := range platforms.GetExcludePlatforms() {
292+
if platform.String() != "" {
293+
excludePlatformStrings = append(excludePlatformStrings, platform.String())
294+
}
295+
}
296+
platformsData["excludePlatforms"] = llx.ArrayData(convert.SliceAnyToInterface(excludePlatformStrings), types.String)
297+
298+
mqlPlatforms, err = CreateResource(a.MqlRuntime, "microsoft.conditionalAccess.policy.conditions.platforms", platformsData)
299+
if err != nil {
300+
return nil, err
301+
}
302+
}
303+
304+
// Extract client applications and create mqlClientApplications resource
305+
if conditions != nil && conditions.GetClientApplications() != nil {
306+
clientApps := conditions.GetClientApplications()
307+
clientApplicationsData := map[string]*llx.RawData{
308+
"includeServicePrincipals": llx.ArrayData(convert.SliceAnyToInterface(clientApps.GetIncludeServicePrincipals()), types.String),
309+
"excludeServicePrincipals": llx.ArrayData(convert.SliceAnyToInterface(clientApps.GetExcludeServicePrincipals()), types.String),
310+
}
311+
mqlClientApplications, err = CreateResource(a.MqlRuntime, "microsoft.conditionalAccess.policy.conditions.clientApplications", clientApplicationsData)
312+
if err != nil {
313+
return nil, err
314+
}
315+
}
316+
317+
var insiderRiskLevelsStr string
318+
if conditions != nil && conditions.GetInsiderRiskLevels() != nil {
319+
insiderRiskLevelsStr = conditions.GetInsiderRiskLevels().String()
320+
}
321+
322+
conditionsResource, err := CreateResource(a.MqlRuntime, "microsoft.conditionalAccess.policy.conditions",
323+
map[string]*llx.RawData{
324+
"id": llx.StringData(conditionsId),
325+
"applications": llx.ResourceData(mqlApplications, "microsoft.conditionalAccess.policy.conditions.applications"),
326+
"authenticationFlows": llx.ResourceData(mqlAuthenticationFlows, "microsoft.conditionalAccess.policy.conditions.authenticationFlows"),
327+
"users": llx.ResourceData(mqlUsers, "microsoft.conditionalAccess.policy.conditions.users"),
328+
"locations": llx.ResourceData(mqlLocations, "microsoft.conditionalAccess.policy.conditions.locations"),
329+
"platforms": llx.ResourceData(mqlPlatforms, "microsoft.conditionalAccess.policy.conditions.platforms"),
330+
"clientApplications": llx.ResourceData(mqlClientApplications, "microsoft.conditionalAccess.policy.conditions.clientApplications"),
331+
"insiderRiskLevels": llx.StringData(insiderRiskLevelsStr),
332+
"clientAppTypes": llx.ArrayData(convert.SliceAnyToInterface(convertEnumCollectionToStrings(conditions.GetClientAppTypes())), types.String),
333+
"userRiskLevels": llx.ArrayData(convert.SliceAnyToInterface(convertEnumCollectionToStrings(conditions.GetUserRiskLevels())), types.String),
334+
"signInRiskLevels": llx.ArrayData(convert.SliceAnyToInterface(convertEnumCollectionToStrings(conditions.GetSignInRiskLevels())), types.String),
335+
"servicePrincipalRiskLevels": llx.ArrayData(convert.SliceAnyToInterface(convertEnumCollectionToStrings(conditions.GetServicePrincipalRiskLevels())), types.String),
336+
})
337+
338+
return conditionsResource, err
339+
}
340+
341+
func (a *mqlMicrosoftConditionalAccess) createGrantControlsResource(
342+
policyId string,
343+
grantControls models.ConditionalAccessGrantControlsable,
344+
) (plugin.Resource, error) {
345+
grantControlsId := policyId + "_grantControls"
346+
347+
var mqlAuthStrength plugin.Resource
348+
349+
// Create authenticationStrength resource if it exists
350+
if grantControls.GetAuthenticationStrength() != nil {
351+
authStrength := grantControls.GetAuthenticationStrength()
352+
authStrengthData := map[string]*llx.RawData{
353+
"id": llx.StringDataPtr(authStrength.GetId()),
354+
"displayName": llx.StringDataPtr(authStrength.GetDisplayName()),
355+
"description": llx.StringDataPtr(authStrength.GetDescription()),
356+
"policyType": llx.StringData(authStrength.GetPolicyType().String()),
357+
"requirementsSatisfied": llx.StringData(authStrength.GetRequirementsSatisfied().String()),
358+
"allowedCombinations": llx.ArrayData(convert.SliceAnyToInterface(convertEnumCollectionToStrings(authStrength.GetAllowedCombinations())), types.String),
359+
"createdDateTime": llx.TimeDataPtr(authStrength.GetCreatedDateTime()),
360+
"modifiedDateTime": llx.TimeDataPtr(authStrength.GetModifiedDateTime()),
361+
}
362+
363+
var err error
364+
mqlAuthStrength, err = CreateResource(a.MqlRuntime, "microsoft.conditionalAccess.policy.grantControls.authenticationStrength", authStrengthData)
365+
if err != nil {
366+
return nil, err
367+
}
368+
}
369+
370+
customAuthFactors := grantControls.GetCustomAuthenticationFactors()
371+
termsOfUse := grantControls.GetTermsOfUse()
372+
builtInControls := convertEnumCollectionToStrings(grantControls.GetBuiltInControls())
373+
374+
return CreateResource(a.MqlRuntime, "microsoft.conditionalAccess.policy.grantControls",
375+
map[string]*llx.RawData{
376+
"id": llx.StringData(grantControlsId),
377+
"operator": llx.StringDataPtr(grantControls.GetOperator()),
378+
"builtInControls": llx.ArrayData(convert.SliceAnyToInterface(builtInControls), types.String),
379+
"customAuthenticationFactors": llx.ArrayData(convert.SliceAnyToInterface(customAuthFactors), types.String),
380+
"termsOfUse": llx.ArrayData(convert.SliceAnyToInterface(termsOfUse), types.String),
381+
"authenticationStrength": llx.ResourceData(mqlAuthStrength, "microsoft.conditionalAccess.policy.grantControls.authenticationStrength"),
382+
})
383+
}
384+
385+
func (a *mqlMicrosoftConditionalAccess) createSessionControlsResource(
386+
policyId string,
387+
sessionControls models.ConditionalAccessSessionControlsable,
388+
) (plugin.Resource, error) {
389+
sessionControlsId := policyId + "_sessionControls"
390+
391+
var mqlSignInFreq plugin.Resource
392+
var mqlCloudAppSecurity plugin.Resource
393+
var mqlPersistentBrowser plugin.Resource
394+
var mqlAppEnforcedRestrictions plugin.Resource
395+
var mqlSecureSignInSession plugin.Resource
396+
397+
// Create signInFrequency resource
398+
if sessionControls != nil && sessionControls.GetSignInFrequency() != nil {
399+
signInFreq := sessionControls.GetSignInFrequency()
400+
signInFreqData := map[string]*llx.RawData{
401+
"authenticationType": llx.StringData(signInFreq.GetAuthenticationType().String()),
402+
"frequencyInterval": llx.StringData(signInFreq.GetFrequencyInterval().String()),
403+
"isEnabled": llx.BoolDataPtr(signInFreq.GetIsEnabled()),
404+
}
405+
var err error
406+
mqlSignInFreq, err = CreateResource(a.MqlRuntime, "microsoft.conditionalAccess.policy.sessionControls.signInFrequency", signInFreqData)
407+
if err != nil {
408+
return nil, err
409+
}
410+
}
411+
412+
// Create cloudAppSecurity resource
413+
if sessionControls != nil && sessionControls.GetCloudAppSecurity() != nil {
414+
cloudAppSecurity := sessionControls.GetCloudAppSecurity()
415+
cloudAppSecurityData := map[string]*llx.RawData{
416+
"cloudAppSecurityType": llx.StringData(cloudAppSecurity.GetCloudAppSecurityType().String()),
417+
"isEnabled": llx.BoolDataPtr(cloudAppSecurity.GetIsEnabled()),
418+
}
419+
var err error
420+
mqlCloudAppSecurity, err = CreateResource(a.MqlRuntime, "microsoft.conditionalAccess.policy.sessionControls.cloudAppSecurity", cloudAppSecurityData)
421+
if err != nil {
422+
return nil, err
423+
}
424+
}
425+
426+
// Create persistentBrowser resource
427+
if sessionControls != nil && sessionControls.GetPersistentBrowser() != nil {
428+
persistentBrowser := sessionControls.GetPersistentBrowser()
429+
persistentBrowserData := map[string]*llx.RawData{
430+
"mode": llx.StringData(persistentBrowser.GetMode().String()),
431+
"isEnabled": llx.BoolDataPtr(persistentBrowser.GetIsEnabled()),
432+
}
433+
var err error
434+
mqlPersistentBrowser, err = CreateResource(a.MqlRuntime, "microsoft.conditionalAccess.policy.sessionControls.persistentBrowser", persistentBrowserData)
435+
if err != nil {
436+
return nil, err
437+
}
438+
}
439+
440+
// Create applicationEnforcedRestrictions resource
441+
if sessionControls != nil && sessionControls.GetApplicationEnforcedRestrictions() != nil {
442+
appEnforcedRestrictions := sessionControls.GetApplicationEnforcedRestrictions()
443+
appEnforcedRestrictionsData := map[string]*llx.RawData{
444+
"isEnabled": llx.BoolDataPtr(appEnforcedRestrictions.GetIsEnabled()),
445+
}
446+
var err error
447+
mqlAppEnforcedRestrictions, err = CreateResource(a.MqlRuntime, "microsoft.conditionalAccess.policy.sessionControls.applicationEnforcedRestrictions", appEnforcedRestrictionsData)
448+
if err != nil {
449+
return nil, err
450+
}
451+
}
452+
453+
// Create secureSignInSession resource
454+
if sessionControls != nil && sessionControls.GetDisableResilienceDefaults() != nil {
455+
secureSignInSessionData := map[string]*llx.RawData{
456+
"disableResilienceDefaults": llx.BoolDataPtr(sessionControls.GetDisableResilienceDefaults()),
457+
}
458+
var err error
459+
mqlSecureSignInSession, err = CreateResource(a.MqlRuntime, "microsoft.conditionalAccess.policy.sessionControls.secureSignInSession", secureSignInSessionData)
460+
if err != nil {
461+
return nil, err
462+
}
463+
}
464+
465+
return CreateResource(a.MqlRuntime, "microsoft.conditionalAccess.policy.sessionControls",
466+
map[string]*llx.RawData{
467+
"id": llx.StringData(sessionControlsId),
468+
"signInFrequency": llx.ResourceData(mqlSignInFreq, "microsoft.conditionalAccess.policy.sessionControls.signInFrequency"),
469+
"cloudAppSecurity": llx.ResourceData(mqlCloudAppSecurity, "microsoft.conditionalAccess.policy.sessionControls.cloudAppSecurity"),
470+
"persistentBrowser": llx.ResourceData(mqlPersistentBrowser, "microsoft.conditionalAccess.policy.sessionControls.persistentBrowser"),
471+
"applicationEnforcedRestrictions": llx.ResourceData(mqlAppEnforcedRestrictions, "microsoft.conditionalAccess.policy.sessionControls.applicationEnforcedRestrictions"),
472+
"secureSignInSession": llx.ResourceData(mqlSecureSignInSession, "microsoft.conditionalAccess.policy.sessionControls.secureSignInSession"),
473+
})
474+
}
475+
476+
func convertEnumCollectionToStrings[T fmt.Stringer](enums []T) []string {
477+
var result []string
478+
if enums == nil {
479+
return nil
480+
}
481+
for _, enum := range enums {
482+
if enum.String() != "" {
483+
result = append(result, enum.String())
484+
}
485+
}
486+
return result
487+
}

0 commit comments

Comments
 (0)