diff --git a/providers/azure/resources/azure.lr b/providers/azure/resources/azure.lr index 3e1d44b677..ea20e2722f 100644 --- a/providers/azure/resources/azure.lr +++ b/providers/azure/resources/azure.lr @@ -1520,7 +1520,7 @@ private azure.subscription.keyVaultService.vault @defaults("vaultName type vault // Azure Key Vault key auto-rotation private azure.subscription.keyVaultService.key.autorotation @defaults("enabled") { - // Key ID (Key Identifier) + // Key ID kid string // Auto-rotation enabled status enabled bool diff --git a/providers/ms365/resources/conditional-access.go b/providers/ms365/resources/conditional-access.go new file mode 100644 index 0000000000..9a5389396d --- /dev/null +++ b/providers/ms365/resources/conditional-access.go @@ -0,0 +1,57 @@ +// Copyright (c) Mondoo, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package resources + +import ( + "context" + + "github.com/microsoftgraph/msgraph-sdk-go/models" + "go.mondoo.com/cnquery/v11/llx" + "go.mondoo.com/cnquery/v11/providers/ms365/connection" +) + +func (a *mqlMicrosoftConditionalAccess) namedLocations() ([]interface{}, error) { + conn := a.MqlRuntime.Connection.(*connection.Ms365Connection) + graphClient, err := conn.GraphClient() + if err != nil { + return nil, err + } + + ctx := context.Background() + namedLocations, err := graphClient.Identity().ConditionalAccess().NamedLocations().Get(ctx, nil) + if err != nil { + return nil, transformError(err) + } + + var locationDetails []interface{} + for _, location := range namedLocations.GetValue() { + if ipLocation, ok := location.(*models.IpNamedLocation); ok { + displayName := ipLocation.GetDisplayName() + isTrusted := ipLocation.GetIsTrusted() + + if displayName != nil { + trusted := false + if isTrusted != nil { + trusted = *isTrusted + } + + locationInfo, err := CreateResource(a.MqlRuntime, "microsoft.conditionalAccess.ipNamedLocation", + map[string]*llx.RawData{ + "name": llx.StringDataPtr(displayName), + "trusted": llx.BoolData(trusted), + }) + if err != nil { + return nil, err + } + locationDetails = append(locationDetails, locationInfo) + } + } + } + + if len(locationDetails) == 0 { + return nil, nil + } + + return locationDetails, nil +} diff --git a/providers/ms365/resources/ms365.lr b/providers/ms365/resources/ms365.lr index 395f75d446..39b7f29469 100644 --- a/providers/ms365/resources/ms365.lr +++ b/providers/ms365/resources/ms365.lr @@ -56,6 +56,20 @@ microsoft.tenant @defaults("name") { subscriptions() []dict } +// Microsoft Conditional Access Policies +microsoft.conditionalAccess { + // IP named location + namedLocations() []microsoft.conditionalAccess.ipNamedLocation +} + +// Microsoft Conditional Access IP named location +microsoft.conditionalAccess.ipNamedLocation @defaults("name trusted") { + // Named location name + name string + // Whether the location is marked as trusted + trusted bool +} + // Microsoft Entra ID user private microsoft.user @defaults("id displayName userPrincipalName") { // User Object ID diff --git a/providers/ms365/resources/ms365.lr.go b/providers/ms365/resources/ms365.lr.go index f4476575cc..65b7b69ab4 100644 --- a/providers/ms365/resources/ms365.lr.go +++ b/providers/ms365/resources/ms365.lr.go @@ -26,6 +26,14 @@ func init() { Init: initMicrosoftTenant, Create: createMicrosoftTenant, }, + "microsoft.conditionalAccess": { + // to override args, implement: initMicrosoftConditionalAccess(runtime *plugin.Runtime, args map[string]*llx.RawData) (map[string]*llx.RawData, plugin.Resource, error) + Create: createMicrosoftConditionalAccess, + }, + "microsoft.conditionalAccess.ipNamedLocation": { + // to override args, implement: initMicrosoftConditionalAccessIpNamedLocation(runtime *plugin.Runtime, args map[string]*llx.RawData) (map[string]*llx.RawData, plugin.Resource, error) + Create: createMicrosoftConditionalAccessIpNamedLocation, + }, "microsoft.user": { Init: initMicrosoftUser, Create: createMicrosoftUser, @@ -289,6 +297,15 @@ var getDataFields = map[string]func(r plugin.Resource) *plugin.DataRes{ "microsoft.tenant.subscriptions": func(r plugin.Resource) *plugin.DataRes { return (r.(*mqlMicrosoftTenant).GetSubscriptions()).ToDataRes(types.Array(types.Dict)) }, + "microsoft.conditionalAccess.namedLocations": func(r plugin.Resource) *plugin.DataRes { + return (r.(*mqlMicrosoftConditionalAccess).GetNamedLocations()).ToDataRes(types.Array(types.Resource("microsoft.conditionalAccess.ipNamedLocation"))) + }, + "microsoft.conditionalAccess.ipNamedLocation.name": func(r plugin.Resource) *plugin.DataRes { + return (r.(*mqlMicrosoftConditionalAccessIpNamedLocation).GetName()).ToDataRes(types.String) + }, + "microsoft.conditionalAccess.ipNamedLocation.trusted": func(r plugin.Resource) *plugin.DataRes { + return (r.(*mqlMicrosoftConditionalAccessIpNamedLocation).GetTrusted()).ToDataRes(types.Bool) + }, "microsoft.user.id": func(r plugin.Resource) *plugin.DataRes { return (r.(*mqlMicrosoftUser).GetId()).ToDataRes(types.String) }, @@ -1233,6 +1250,26 @@ var setDataFields = map[string]func(r plugin.Resource, v *llx.RawData) bool { r.(*mqlMicrosoftTenant).Subscriptions, ok = plugin.RawToTValue[[]interface{}](v.Value, v.Error) return }, + "microsoft.conditionalAccess.__id": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlMicrosoftConditionalAccess).__id, ok = v.Value.(string) + return + }, + "microsoft.conditionalAccess.namedLocations": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlMicrosoftConditionalAccess).NamedLocations, ok = plugin.RawToTValue[[]interface{}](v.Value, v.Error) + return + }, + "microsoft.conditionalAccess.ipNamedLocation.__id": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlMicrosoftConditionalAccessIpNamedLocation).__id, ok = v.Value.(string) + return + }, + "microsoft.conditionalAccess.ipNamedLocation.name": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlMicrosoftConditionalAccessIpNamedLocation).Name, ok = plugin.RawToTValue[string](v.Value, v.Error) + return + }, + "microsoft.conditionalAccess.ipNamedLocation.trusted": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlMicrosoftConditionalAccessIpNamedLocation).Trusted, ok = plugin.RawToTValue[bool](v.Value, v.Error) + return + }, "microsoft.user.__id": func(r plugin.Resource, v *llx.RawData) (ok bool) { r.(*mqlMicrosoftUser).__id, ok = v.Value.(string) return @@ -2799,6 +2836,111 @@ func (c *mqlMicrosoftTenant) GetSubscriptions() *plugin.TValue[[]interface{}] { }) } +// mqlMicrosoftConditionalAccess for the microsoft.conditionalAccess resource +type mqlMicrosoftConditionalAccess struct { + MqlRuntime *plugin.Runtime + __id string + // optional: if you define mqlMicrosoftConditionalAccessInternal it will be used here + NamedLocations plugin.TValue[[]interface{}] +} + +// createMicrosoftConditionalAccess creates a new instance of this resource +func createMicrosoftConditionalAccess(runtime *plugin.Runtime, args map[string]*llx.RawData) (plugin.Resource, error) { + res := &mqlMicrosoftConditionalAccess{ + MqlRuntime: runtime, + } + + err := SetAllData(res, args) + if err != nil { + return res, err + } + + // to override __id implement: id() (string, error) + + if runtime.HasRecording { + args, err = runtime.ResourceFromRecording("microsoft.conditionalAccess", res.__id) + if err != nil || args == nil { + return res, err + } + return res, SetAllData(res, args) + } + + return res, nil +} + +func (c *mqlMicrosoftConditionalAccess) MqlName() string { + return "microsoft.conditionalAccess" +} + +func (c *mqlMicrosoftConditionalAccess) MqlID() string { + return c.__id +} + +func (c *mqlMicrosoftConditionalAccess) GetNamedLocations() *plugin.TValue[[]interface{}] { + return plugin.GetOrCompute[[]interface{}](&c.NamedLocations, func() ([]interface{}, error) { + if c.MqlRuntime.HasRecording { + d, err := c.MqlRuntime.FieldResourceFromRecording("microsoft.conditionalAccess", c.__id, "namedLocations") + if err != nil { + return nil, err + } + if d != nil { + return d.Value.([]interface{}), nil + } + } + + return c.namedLocations() + }) +} + +// mqlMicrosoftConditionalAccessIpNamedLocation for the microsoft.conditionalAccess.ipNamedLocation resource +type mqlMicrosoftConditionalAccessIpNamedLocation struct { + MqlRuntime *plugin.Runtime + __id string + // optional: if you define mqlMicrosoftConditionalAccessIpNamedLocationInternal it will be used here + Name plugin.TValue[string] + Trusted plugin.TValue[bool] +} + +// createMicrosoftConditionalAccessIpNamedLocation creates a new instance of this resource +func createMicrosoftConditionalAccessIpNamedLocation(runtime *plugin.Runtime, args map[string]*llx.RawData) (plugin.Resource, error) { + res := &mqlMicrosoftConditionalAccessIpNamedLocation{ + MqlRuntime: runtime, + } + + err := SetAllData(res, args) + if err != nil { + return res, err + } + + // to override __id implement: id() (string, error) + + if runtime.HasRecording { + args, err = runtime.ResourceFromRecording("microsoft.conditionalAccess.ipNamedLocation", res.__id) + if err != nil || args == nil { + return res, err + } + return res, SetAllData(res, args) + } + + return res, nil +} + +func (c *mqlMicrosoftConditionalAccessIpNamedLocation) MqlName() string { + return "microsoft.conditionalAccess.ipNamedLocation" +} + +func (c *mqlMicrosoftConditionalAccessIpNamedLocation) MqlID() string { + return c.__id +} + +func (c *mqlMicrosoftConditionalAccessIpNamedLocation) GetName() *plugin.TValue[string] { + return &c.Name +} + +func (c *mqlMicrosoftConditionalAccessIpNamedLocation) GetTrusted() *plugin.TValue[bool] { + return &c.Trusted +} + // mqlMicrosoftUser for the microsoft.user resource type mqlMicrosoftUser struct { MqlRuntime *plugin.Runtime diff --git a/providers/ms365/resources/ms365.lr.manifest.yaml b/providers/ms365/resources/ms365.lr.manifest.yaml index 87d39b4c2c..e5a6242e79 100755 --- a/providers/ms365/resources/ms365.lr.manifest.yaml +++ b/providers/ms365/resources/ms365.lr.manifest.yaml @@ -5,6 +5,8 @@ resources: microsoft: fields: applications: {} + conditionalAccess: + min_mondoo_version: 9.0.0 domains: {} enterpriseApplications: min_mondoo_version: latest @@ -118,6 +120,22 @@ resources: value: {} is_private: true min_mondoo_version: 9.0.0 + microsoft.conditionalAccess: + fields: + name: {} + namedLocations: {} + trusted: {} + min_mondoo_version: 9.0.0 + microsoft.conditionalAccess.ipNamedLocation: + fields: + name: {} + trusted: {} + min_mondoo_version: 9.0.0 + microsoft.conditionalAccess.namedLocation: + fields: + name: {} + trusted: {} + min_mondoo_version: 9.0.0 microsoft.devicemanagement: fields: deviceCompliancePolicies: {}