From d07cbb92532ebead04ed8f956b53017ef0b7e798 Mon Sep 17 00:00:00 2001 From: ShocOne Date: Wed, 15 Jan 2025 14:54:50 +0000 Subject: [PATCH 01/14] feat: add device management template type attribute with validation options --- .../device_management_template/resource.go | 37 ++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/internal/resources/device_and_app_management/graph_beta/device_management_template/resource.go b/internal/resources/device_and_app_management/graph_beta/device_management_template/resource.go index 997750b3..b14f3d45 100644 --- a/internal/resources/device_and_app_management/graph_beta/device_management_template/resource.go +++ b/internal/resources/device_and_app_management/graph_beta/device_management_template/resource.go @@ -100,6 +100,41 @@ func (r *DeviceManagementTemplateResource) Schema(ctx context.Context, req resou PlanModifiers: []planmodifier.String{planmodifiers.DefaultValueString("")}, MarkdownDescription: "Policy description", }, + "device_management_template_type": schema.StringAttribute{ + Required: true, + MarkdownDescription: "Defines which device management template type with settings catalog setting that will be deployed. " + + "Options available are `macOS_disk_encryption`, `macOS_firewall`, `macOS_endpoint_detection_and_response`, `macOS_anti_virus`, " + + "`windows_account_protection`, `windows_anti_virus`, `windows_app_control_for_business`, `windows_attack_surface_reduction`, " + + "`windows_disk_encryption`, `windows_firewall`, `windows_firewall_rules`, `windows_hyper-v_firewall_rules`, " + + "`windows_firewall_config_manager`, `windows_firewall_profile_config_manager`, `windows_firewall_rules_config_manager`, " + + "`windows_endpoint_detection_and_response`, `windows_config_manager_anti_virus`, `windows_config_manager_attack_surface_reduction`, " + + "`windows_config_manager_endpoint_detection_and_response`, `linux_endpoint_detection_and_response`, `linux_anti_virus`.", + Validators: []validator.String{ + stringvalidator.OneOf( + "linux_endpoint_detection_and_response", + "linux_anti_virus", + "macOS_disk_encryption", + "macOS_firewall", + "macOS_endpoint_detection_and_response", + "macOS_anti_virus", + "windows_account_protection", + "windows_anti_virus", + "windows_app_control_for_business", + "windows_attack_surface_reduction", + "windows_disk_encryption", + "windows_firewall", + "windows_firewall_rules", + "windows_hyper-v_firewall_rules", + "windows_firewall_config_manager", + "windows_firewall_profile_config_manager", + "windows_firewall_rules_config_manager", + "windows_endpoint_detection_and_response", + "windows_config_manager_anti_virus", + "windows_config_manager_attack_surface_reduction", + "windows_config_manager_endpoint_detection_and_response", + ), + }, + }, "settings": schema.StringAttribute{ Required: true, MarkdownDescription: "Settings Catalog Policy settings defined as a valid JSON string. Provide JSON-encoded settings structure. " + @@ -110,7 +145,7 @@ func (r *DeviceManagementTemplateResource) Schema(ctx context.Context, req resou "A correctly formatted field in the HCL should begin and end like this:\n" + "```hcl\n" + "settings = jsonencode({\n" + - " \"settingsDetails\": [\n" + + " \"settings\": [\n" + " {\n" + " # ... settings configuration ...\n" + " }\n" + From 763c8aed4b7b9dedbc32d7a83397b3d08f1cc547 Mon Sep 17 00:00:00 2001 From: ShocOne Date: Wed, 15 Jan 2025 15:39:34 +0000 Subject: [PATCH 02/14] fix: update settings key in resource configuration for Endpoint Privilege Management --- .../resource.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_endpoint_privilege_management/resource.tf b/examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_endpoint_privilege_management/resource.tf index 155fd375..3a8f3a75 100644 --- a/examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_endpoint_privilege_management/resource.tf +++ b/examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_endpoint_privilege_management/resource.tf @@ -6,7 +6,7 @@ resource "microsoft365_graph_beta_device_and_app_management_endpoint_privilege_m settings = jsonencode({ - "settingsDetails" : [{ + "settings" : [{ "id" : "0", "settingInstance" : { "@odata.type" : "#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance", From 97a200cbe4e9805c166e3690322e885d507eabd3 Mon Sep 17 00:00:00 2001 From: ShocOne Date: Wed, 15 Jan 2025 15:43:56 +0000 Subject: [PATCH 03/14] fix: update Terraform version requirements in documentation and configuration --- templates/index.md.tmpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/index.md.tmpl b/templates/index.md.tmpl index 9f20b2f9..0196af1f 100644 --- a/templates/index.md.tmpl +++ b/templates/index.md.tmpl @@ -12,7 +12,7 @@ The community Microsoft 365 provider allows managing environments and other reso ## Requirements -This provider requires **Terraform >= 0.12**. For more information on provider installation and constraining provider versions, see the [Provider Requirements documentation](https://developer.hashicorp.com/terraform/language/providers/requirements). +This provider requires a minimum of **Terraform >= 1.10**. For more information on provider installation and constraining provider versions, see the [Provider Requirements documentation](https://developer.hashicorp.com/terraform/language/providers/requirements). ## Installation @@ -23,7 +23,7 @@ terraform { required_providers { microsoft365 = { source = "deploymenttheory/microsoft365" - version = "~> 0.4.0" # Replace with the latest version + version = "~> 1.10.4 # Replace with the latest version } } } From 01334e26b1fa9092bc9bd141ca161f7bdc0f0bef Mon Sep 17 00:00:00 2001 From: ShocOne Date: Wed, 15 Jan 2025 15:47:42 +0000 Subject: [PATCH 04/14] feat: add template for graph beta device and app management reusable policy setting documentation --- ...p_management_reuseable_policy_setting.md.tmpl | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 templates/data-sources/graph_beta_device_and_app_management_reuseable_policy_setting.md.tmpl diff --git a/templates/data-sources/graph_beta_device_and_app_management_reuseable_policy_setting.md.tmpl b/templates/data-sources/graph_beta_device_and_app_management_reuseable_policy_setting.md.tmpl new file mode 100644 index 00000000..239f916a --- /dev/null +++ b/templates/data-sources/graph_beta_device_and_app_management_reuseable_policy_setting.md.tmpl @@ -0,0 +1,16 @@ +--- +page_title: "{{.Name}} {{.Type}} - {{.ProviderName}}" +subcategory: "Intune" +description: |- +{{ .Description | plainmarkdown | trimspace | prefixlines " " }} +--- + +# {{.Name}} ({{.Type}}) + +The Microsoft 365 Intune role scope tag data source provides information about a specific scope tag. + +## Example Usage + +{{ tffile "examples/microsoft365_graph_beta/graph_beta_device_and_app_management_reuseable_policy_setting/datasource.tf" }} + +{{ .SchemaMarkdown | trimspace }} \ No newline at end of file From e35d96b0427531b27e321c42ae7cd59f3f8d976f Mon Sep 17 00:00:00 2001 From: ShocOne Date: Wed, 15 Jan 2025 17:08:55 +0000 Subject: [PATCH 05/14] refactor: update device management template resource model and schema validation --- .../construct_assignment.go | 184 -------------- .../construct_resource.go | 74 +++--- .../device_management_template/crud.go | 19 +- .../device_management_template/model.go | 25 -- .../device_management_template/resource.go | 14 +- .../state_assignment.go | 237 ------------------ .../state_base_resource.go | 3 +- .../state_settings.go | 71 ------ 8 files changed, 68 insertions(+), 559 deletions(-) delete mode 100644 internal/resources/device_and_app_management/graph_beta/device_management_template/construct_assignment.go delete mode 100644 internal/resources/device_and_app_management/graph_beta/device_management_template/model.go delete mode 100644 internal/resources/device_and_app_management/graph_beta/device_management_template/state_assignment.go delete mode 100644 internal/resources/device_and_app_management/graph_beta/device_management_template/state_settings.go diff --git a/internal/resources/device_and_app_management/graph_beta/device_management_template/construct_assignment.go b/internal/resources/device_and_app_management/graph_beta/device_management_template/construct_assignment.go deleted file mode 100644 index 1cbf468b..00000000 --- a/internal/resources/device_and_app_management/graph_beta/device_management_template/construct_assignment.go +++ /dev/null @@ -1,184 +0,0 @@ -package graphBetaDeviceManagementTemplate - -import ( - "context" - "fmt" - - "github.com/deploymenttheory/terraform-provider-microsoft365/internal/resources/common/constructors" - sharedmodels "github.com/deploymenttheory/terraform-provider-microsoft365/internal/resources/common/shared_models/graph_beta/device_and_app_management" - validators "github.com/deploymenttheory/terraform-provider-microsoft365/internal/resources/common/validators/graph_beta/device_and_app_management" - "github.com/hashicorp/terraform-plugin-log/tflog" - "github.com/microsoftgraph/msgraph-beta-sdk-go/devicemanagement" - graphsdkmodels "github.com/microsoftgraph/msgraph-beta-sdk-go/models" -) - -// constructAssignment constructs and returns a ConfigurationPoliciesItemAssignPostRequestBody -func constructAssignment(ctx context.Context, data *DeviceManagementTemplateResourceModel) (devicemanagement.ConfigurationPoliciesItemAssignPostRequestBodyable, error) { - if data.Assignments == nil { - return nil, fmt.Errorf("assignments configuration block is required even if empty. Minimum config requires all_devices and all_users booleans to be set to false") - } - - tflog.Debug(ctx, "Starting assignment construction") - - if err := validators.ValidateDeviceConfiguationAssignmentSettings(data.Assignments); err != nil { - return nil, err - } - - requestBody := devicemanagement.NewConfigurationPoliciesItemAssignPostRequestBody() - assignments := make([]graphsdkmodels.DeviceManagementConfigurationPolicyAssignmentable, 0) - - // Check All Devices - if !data.Assignments.AllDevices.IsNull() && data.Assignments.AllDevices.ValueBool() { - assignments = append(assignments, constructAllDevicesAssignment(ctx, data.Assignments)) - } - - // Check All Users - if !data.Assignments.AllUsers.IsNull() && data.Assignments.AllUsers.ValueBool() { - assignments = append(assignments, constructAllUsersAssignment(ctx, data.Assignments)) - } - - // Check Include Groups - if !data.Assignments.AllDevices.ValueBool() && - !data.Assignments.AllUsers.ValueBool() && - len(data.Assignments.IncludeGroups) > 0 { - for _, group := range data.Assignments.IncludeGroups { - if !group.GroupId.IsNull() && !group.GroupId.IsUnknown() && group.GroupId.ValueString() != "" { - assignments = append(assignments, constructGroupIncludeAssignments(ctx, data.Assignments)...) - break - } - } - } - - // Check Exclude Groups - if len(data.Assignments.ExcludeGroupIds) > 0 { - for _, id := range data.Assignments.ExcludeGroupIds { - if !id.IsNull() && !id.IsUnknown() && id.ValueString() != "" { - assignments = append(assignments, constructGroupExcludeAssignments(data.Assignments)...) - break - } - } - } - - // Always set assignments (will be empty array if no active assignments) - // as update http method is a post not patch. - requestBody.SetAssignments(assignments) - - if err := constructors.DebugLogGraphObject(ctx, "Constructed assignment request body", requestBody); err != nil { - tflog.Error(ctx, "Failed to debug log assignment request body", map[string]interface{}{ - "error": err.Error(), - }) - } - - return requestBody, nil -} - -// constructAllDevicesAssignment constructs and returns a DeviceManagementConfigurationPolicyAssignment object for all devices -func constructAllDevicesAssignment(ctx context.Context, config *sharedmodels.SettingsCatalogSettingsAssignmentResourceModel) graphsdkmodels.DeviceManagementConfigurationPolicyAssignmentable { - assignment := graphsdkmodels.NewDeviceManagementConfigurationPolicyAssignment() - target := graphsdkmodels.NewAllDevicesAssignmentTarget() - - if !config.AllDevicesFilterId.IsNull() && !config.AllDevicesFilterId.IsUnknown() && - config.AllDevicesFilterId.ValueString() != "" { - constructors.SetStringProperty(config.AllDevicesFilterId, target.SetDeviceAndAppManagementAssignmentFilterId) - - if !config.AllDevicesFilterType.IsNull() && !config.AllDevicesFilterType.IsUnknown() { - err := constructors.SetEnumProperty(config.AllDevicesFilterType, - graphsdkmodels.ParseDeviceAndAppManagementAssignmentFilterType, - target.SetDeviceAndAppManagementAssignmentFilterType) - if err != nil { - tflog.Warn(ctx, "Failed to parse all devices filter type", map[string]interface{}{ - "error": err.Error(), - }) - } - } - } - - assignment.SetTarget(target) - return assignment -} - -// constructAllUsersAssignment constructs and returns a DeviceManagementConfigurationPolicyAssignment object for all licensed users -func constructAllUsersAssignment(ctx context.Context, config *sharedmodels.SettingsCatalogSettingsAssignmentResourceModel) graphsdkmodels.DeviceManagementConfigurationPolicyAssignmentable { - assignment := graphsdkmodels.NewDeviceManagementConfigurationPolicyAssignment() - target := graphsdkmodels.NewAllLicensedUsersAssignmentTarget() - - if !config.AllUsersFilterId.IsNull() && !config.AllUsersFilterId.IsUnknown() && - config.AllUsersFilterId.ValueString() != "" { - constructors.SetStringProperty(config.AllUsersFilterId, target.SetDeviceAndAppManagementAssignmentFilterId) - - if !config.AllUsersFilterType.IsNull() && !config.AllUsersFilterType.IsUnknown() { - err := constructors.SetEnumProperty(config.AllUsersFilterType, - graphsdkmodels.ParseDeviceAndAppManagementAssignmentFilterType, - target.SetDeviceAndAppManagementAssignmentFilterType) - if err != nil { - tflog.Warn(ctx, "Failed to parse all users filter type", map[string]interface{}{ - "error": err.Error(), - }) - } - } - } - - assignment.SetTarget(target) - return assignment -} - -// constructGroupIncludeAssignments constructs and returns a list of DeviceManagementConfigurationPolicyAssignment objects for included groups -func constructGroupIncludeAssignments(ctx context.Context, config *sharedmodels.SettingsCatalogSettingsAssignmentResourceModel) []graphsdkmodels.DeviceManagementConfigurationPolicyAssignmentable { - var assignments []graphsdkmodels.DeviceManagementConfigurationPolicyAssignmentable - - for _, groupFilter := range config.IncludeGroups { - assignment := graphsdkmodels.NewDeviceManagementConfigurationPolicyAssignment() - target := graphsdkmodels.NewGroupAssignmentTarget() - - constructors.SetStringProperty(groupFilter.GroupId, target.SetGroupId) - - if !groupFilter.IncludeGroupsFilterId.IsNull() && !groupFilter.IncludeGroupsFilterType.IsNull() { - constructors.SetStringProperty(groupFilter.IncludeGroupsFilterId, - target.SetDeviceAndAppManagementAssignmentFilterId) - - err := constructors.SetEnumProperty(groupFilter.IncludeGroupsFilterType, - graphsdkmodels.ParseDeviceAndAppManagementAssignmentFilterType, - target.SetDeviceAndAppManagementAssignmentFilterType) - if err != nil { - tflog.Warn(ctx, "Failed to parse include groups filter type", map[string]interface{}{ - "error": err.Error(), - "groupId": groupFilter.GroupId.ValueString(), - }) - } - } - - assignment.SetTarget(target) - assignments = append(assignments, assignment) - } - - return assignments -} - -func constructGroupExcludeAssignments(config *sharedmodels.SettingsCatalogSettingsAssignmentResourceModel) []graphsdkmodels.DeviceManagementConfigurationPolicyAssignmentable { - var assignments []graphsdkmodels.DeviceManagementConfigurationPolicyAssignmentable - - // Check if we have any non-null, non-empty values - hasValidExcludes := false - for _, groupId := range config.ExcludeGroupIds { - if !groupId.IsNull() && !groupId.IsUnknown() && groupId.ValueString() != "" { - hasValidExcludes = true - break - } - } - - // Only process if we have valid excludes - if hasValidExcludes { - for _, groupId := range config.ExcludeGroupIds { - if !groupId.IsNull() && !groupId.IsUnknown() && groupId.ValueString() != "" { - assignment := graphsdkmodels.NewDeviceManagementConfigurationPolicyAssignment() - target := graphsdkmodels.NewExclusionGroupAssignmentTarget() - constructors.SetStringProperty(groupId, target.SetGroupId) - - assignment.SetTarget(target) - assignments = append(assignments, assignment) - } - } - } - - return assignments -} diff --git a/internal/resources/device_and_app_management/graph_beta/device_management_template/construct_resource.go b/internal/resources/device_and_app_management/graph_beta/device_management_template/construct_resource.go index 26aedfba..97327df4 100644 --- a/internal/resources/device_and_app_management/graph_beta/device_management_template/construct_resource.go +++ b/internal/resources/device_and_app_management/graph_beta/device_management_template/construct_resource.go @@ -3,16 +3,36 @@ package graphBetaDeviceManagementTemplate import ( "context" "fmt" - "strings" "github.com/deploymenttheory/terraform-provider-microsoft365/internal/resources/common/constructors" sharedConstructor "github.com/deploymenttheory/terraform-provider-microsoft365/internal/resources/common/constructors/graph_beta/device_and_app_management" + sharedmodels "github.com/deploymenttheory/terraform-provider-microsoft365/internal/resources/common/shared_models/graph_beta/device_and_app_management" "github.com/hashicorp/terraform-plugin-log/tflog" graphmodels "github.com/microsoftgraph/msgraph-beta-sdk-go/models" ) +// PolicyTemplateConfig is a struct that contains the platform, technologies, and template id for a device management policy. +type PolicyTemplateConfig struct { + Platform graphmodels.DeviceManagementConfigurationPlatforms + Technologies graphmodels.DeviceManagementConfigurationTechnologies + TemplateID string +} + +var policyConfigMap = map[string]PolicyTemplateConfig{ + "windows_anti_virus_defender_update_controls": { + Platform: graphmodels.WINDOWS10_DEVICEMANAGEMENTCONFIGURATIONPLATFORMS, + Technologies: graphmodels.MDM_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES | graphmodels.MICROSOFTSENSE_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES, + TemplateID: "e3f74c5a-a6de-411d-aef6-eb15628f3a0a_1", + }, + "windows_anti_virus_microsoft_defender_antivirus_exclusions": { + Platform: graphmodels.WINDOWS10_DEVICEMANAGEMENTCONFIGURATIONPLATFORMS, + Technologies: graphmodels.MDM_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES | graphmodels.MICROSOFTSENSE_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES, + TemplateID: "45fea5e9-280d-4da1-9792-fb5736da0ca9_1", + }, +} + // Main entry point to construct the intune settings catalog profile resource for the Terraform provider. -func constructResource(ctx context.Context, data *DeviceManagementTemplateResourceModel) (graphmodels.DeviceManagementConfigurationPolicyable, error) { +func constructResource(ctx context.Context, data *sharedmodels.SettingsCatalogProfileResourceModel) (graphmodels.DeviceManagementConfigurationPolicyable, error) { tflog.Debug(ctx, fmt.Sprintf("Constructing %s resource from model", ResourceName)) requestBody := graphmodels.NewDeviceManagementConfigurationPolicy() @@ -20,34 +40,9 @@ func constructResource(ctx context.Context, data *DeviceManagementTemplateResour constructors.SetStringProperty(data.Name, requestBody.SetName) constructors.SetStringProperty(data.Description, requestBody.SetDescription) - platformStr := data.Platforms.ValueString() - var platform graphmodels.DeviceManagementConfigurationPlatforms - switch platformStr { - case "android": - platform = graphmodels.ANDROID_DEVICEMANAGEMENTCONFIGURATIONPLATFORMS - case "androidEnterprise": - platform = graphmodels.ANDROIDENTERPRISE_DEVICEMANAGEMENTCONFIGURATIONPLATFORMS - case "aosp": - platform = graphmodels.AOSP_DEVICEMANAGEMENTCONFIGURATIONPLATFORMS - case "iOS": - platform = graphmodels.IOS_DEVICEMANAGEMENTCONFIGURATIONPLATFORMS - case "linux": - platform = graphmodels.LINUX_DEVICEMANAGEMENTCONFIGURATIONPLATFORMS - case "macOS": - platform = graphmodels.MACOS_DEVICEMANAGEMENTCONFIGURATIONPLATFORMS - case "windows10": - platform = graphmodels.WINDOWS10_DEVICEMANAGEMENTCONFIGURATIONPLATFORMS - case "windows10X": - platform = graphmodels.WINDOWS10X_DEVICEMANAGEMENTCONFIGURATIONPLATFORMS + if err := setTemplateContext(ctx, data, requestBody); err != nil { + return nil, err } - requestBody.SetPlatforms(&platform) - - var technologiesStr []string - for _, tech := range data.Technologies { - technologiesStr = append(technologiesStr, tech.ValueString()) - } - parsedTechnologies, _ := graphmodels.ParseDeviceManagementConfigurationTechnologies(strings.Join(technologiesStr, ",")) - requestBody.SetTechnologies(parsedTechnologies.(*graphmodels.DeviceManagementConfigurationTechnologies)) if err := constructors.SetStringList(ctx, data.RoleScopeTagIds, requestBody.SetRoleScopeTagIds); err != nil { return nil, fmt.Errorf("failed to set role scope tags: %s", err) @@ -66,3 +61,24 @@ func constructResource(ctx context.Context, data *DeviceManagementTemplateResour return requestBody, nil } + +// setTemplateContext sets the template specific settings for the device management template. +// It sets the platform, technologies, and template id reference. +func setTemplateContext(ctx context.Context, data *sharedmodels.SettingsCatalogProfileResourceModel, requestBody graphmodels.DeviceManagementConfigurationPolicyable) error { + config, exists := policyConfigMap[data.ConfigurationPolicyTemplateType.ValueString()] + if !exists { + tflog.Error(ctx, "Invalid configuration policy template type", map[string]interface{}{ + "configuration_policy_template_type": data.ConfigurationPolicyTemplateType.ValueString(), + }) + return fmt.Errorf("invalid configuration_policy_template_type: %s", data.ConfigurationPolicyTemplateType.ValueString()) + } + + requestBody.SetPlatforms(&config.Platform) + requestBody.SetTechnologies(&config.Technologies) + + templateReference := graphmodels.NewDeviceManagementConfigurationPolicyTemplateReference() + templateReference.SetTemplateId(&config.TemplateID) + requestBody.SetTemplateReference(templateReference) + + return nil +} diff --git a/internal/resources/device_and_app_management/graph_beta/device_management_template/crud.go b/internal/resources/device_and_app_management/graph_beta/device_management_template/crud.go index e8ef2d4d..be102ac4 100644 --- a/internal/resources/device_and_app_management/graph_beta/device_management_template/crud.go +++ b/internal/resources/device_and_app_management/graph_beta/device_management_template/crud.go @@ -6,8 +6,11 @@ import ( "time" "github.com/deploymenttheory/terraform-provider-microsoft365/internal/client/graphcustom" + construct "github.com/deploymenttheory/terraform-provider-microsoft365/internal/resources/common/constructors/graph_beta/device_and_app_management" "github.com/deploymenttheory/terraform-provider-microsoft365/internal/resources/common/crud" "github.com/deploymenttheory/terraform-provider-microsoft365/internal/resources/common/errors" + sharedmodels "github.com/deploymenttheory/terraform-provider-microsoft365/internal/resources/common/shared_models/graph_beta/device_and_app_management" + sharedstater "github.com/deploymenttheory/terraform-provider-microsoft365/internal/resources/common/state/graph_beta/device_and_app_management" "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -30,7 +33,7 @@ import ( // (if specified) are created properly. The settings must be defined during creation // as they are required for a successful deployment, while assignments are optional. func (r *DeviceManagementTemplateResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { - var object DeviceManagementTemplateResourceModel + var object sharedmodels.SettingsCatalogProfileResourceModel tflog.Debug(ctx, fmt.Sprintf("Starting creation of resource: %s_%s", r.ProviderTypeName, r.TypeName)) @@ -70,7 +73,7 @@ func (r *DeviceManagementTemplateResource) Create(ctx context.Context, req resou object.ID = types.StringValue(*createdResource.GetId()) if object.Assignments != nil { - requestAssignment, err := constructAssignment(ctx, &object) + requestAssignment, err := construct.ConstructConfigurationPolicyAssignment(ctx, object.Assignments) if err != nil { resp.Diagnostics.AddError( "Error constructing assignment for Create Method", @@ -143,7 +146,7 @@ func (r *DeviceManagementTemplateResource) Create(ctx context.Context, req resou // are properly read and mapped into the Terraform state, providing a complete view // of the resource's current configuration on the server. func (r *DeviceManagementTemplateResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { - var object DeviceManagementTemplateResourceModel + var object sharedmodels.SettingsCatalogProfileResourceModel var baseResource models.DeviceManagementConfigurationPolicyable var assignmentsResponse models.DeviceManagementConfigurationPolicyAssignmentCollectionResponseable @@ -198,7 +201,7 @@ func (r *DeviceManagementTemplateResource) Read(ctx context.Context, req resourc return } - MapRemoteSettingsStateToTerraform(ctx, &object, settingsResponse) + sharedstater.StateConfigurationPolicySettings(ctx, &object, settingsResponse) assignmentsResponse, err = r.client. DeviceManagement(). @@ -212,7 +215,7 @@ func (r *DeviceManagementTemplateResource) Read(ctx context.Context, req resourc return } - MapRemoteAssignmentStateToTerraform(ctx, &object, assignmentsResponse) + sharedstater.StateConfigurationPolicyAssignment(ctx, object.Assignments, assignmentsResponse) resp.Diagnostics.Append(resp.State.Set(ctx, &object)...) if resp.Diagnostics.HasError() { @@ -236,7 +239,7 @@ func (r *DeviceManagementTemplateResource) Read(ctx context.Context, req resourc // The function ensures that both the settings and assignments are updated atomically, // and the final state reflects the actual state of the resource on the server. func (r *DeviceManagementTemplateResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { - var object DeviceManagementTemplateResourceModel + var object sharedmodels.SettingsCatalogProfileResourceModel tflog.Debug(ctx, fmt.Sprintf("Starting Update of resource: %s_%s", r.ProviderTypeName, r.TypeName)) @@ -277,7 +280,7 @@ func (r *DeviceManagementTemplateResource) Update(ctx context.Context, req resou } if object.Assignments != nil { - requestAssignment, err := constructAssignment(ctx, &object) + requestAssignment, err := construct.ConstructConfigurationPolicyAssignment(ctx, object.Assignments) if err != nil { resp.Diagnostics.AddError( "Error constructing assignment for Update Method", @@ -341,7 +344,7 @@ func (r *DeviceManagementTemplateResource) Update(ctx context.Context, req resou // // All assignments and settings associated with the resource are automatically removed as part of the deletion. func (r *DeviceManagementTemplateResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { - var object DeviceManagementTemplateResourceModel + var object sharedmodels.SettingsCatalogProfileResourceModel tflog.Debug(ctx, fmt.Sprintf("Starting deletion of resource: %s_%s", r.ProviderTypeName, r.TypeName)) diff --git a/internal/resources/device_and_app_management/graph_beta/device_management_template/model.go b/internal/resources/device_and_app_management/graph_beta/device_management_template/model.go deleted file mode 100644 index ffa4b24a..00000000 --- a/internal/resources/device_and_app_management/graph_beta/device_management_template/model.go +++ /dev/null @@ -1,25 +0,0 @@ -package graphBetaDeviceManagementTemplate - -import ( - sharedmodels "github.com/deploymenttheory/terraform-provider-microsoft365/internal/resources/common/shared_models/graph_beta/device_and_app_management" - "github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts" - "github.com/hashicorp/terraform-plugin-framework/types" -) - -// DeviceManagementTemplateProfileResourceModel holds the configuration for a Settings Catalog profile. -// Reference: https://learn.microsoft.com/en-us/graph/api/resources/intune-deviceconfigv2-devicemanagementconfigurationpolicy?view=graph-rest-beta -type DeviceManagementTemplateResourceModel struct { - ID types.String `tfsdk:"id"` - Name types.String `tfsdk:"name"` - Description types.String `tfsdk:"description"` - Platforms types.String `tfsdk:"platforms"` - Technologies []types.String `tfsdk:"technologies"` - RoleScopeTagIds types.List `tfsdk:"role_scope_tag_ids"` - SettingsCount types.Int64 `tfsdk:"settings_count"` - IsAssigned types.Bool `tfsdk:"is_assigned"` - LastModifiedDateTime types.String `tfsdk:"last_modified_date_time"` - CreatedDateTime types.String `tfsdk:"created_date_time"` - Settings types.String `tfsdk:"settings"` - Assignments *sharedmodels.SettingsCatalogSettingsAssignmentResourceModel `tfsdk:"assignments"` - Timeouts timeouts.Value `tfsdk:"timeouts"` -} diff --git a/internal/resources/device_and_app_management/graph_beta/device_management_template/resource.go b/internal/resources/device_and_app_management/graph_beta/device_management_template/resource.go index b14f3d45..3d8d15e6 100644 --- a/internal/resources/device_and_app_management/graph_beta/device_management_template/resource.go +++ b/internal/resources/device_and_app_management/graph_beta/device_management_template/resource.go @@ -112,13 +112,18 @@ func (r *DeviceManagementTemplateResource) Schema(ctx context.Context, req resou Validators: []validator.String{ stringvalidator.OneOf( "linux_endpoint_detection_and_response", - "linux_anti_virus", + "linux_anti_virus_microsoft_defender_antivirus", + "linux_anti_virus_microsoft_defender_antivirus_exclusions", "macOS_disk_encryption", "macOS_firewall", "macOS_endpoint_detection_and_response", - "macOS_anti_virus", + "macOS_anti_virus_microsoft_defender_antivirus", + "macOS_anti_virus_microsoft_defender_antivirus_exclusions", "windows_account_protection", - "windows_anti_virus", + "windows_anti_virus_defender_update_controls", + "windows_anti_virus_microsoft_defender_antivirus", + "windows_anti_virus_microsoft_defender_antivirus_exclusions", + "windows_anti_virus_security_experience", "windows_app_control_for_business", "windows_attack_surface_reduction", "windows_disk_encryption", @@ -129,7 +134,8 @@ func (r *DeviceManagementTemplateResource) Schema(ctx context.Context, req resou "windows_firewall_profile_config_manager", "windows_firewall_rules_config_manager", "windows_endpoint_detection_and_response", - "windows_config_manager_anti_virus", + "windows_config_manage_anti_virus_microsoft_defender_antivirus", + "windows_config_manage_anti_virus_microsoft_defender_antivirus_exclusions", "windows_config_manager_attack_surface_reduction", "windows_config_manager_endpoint_detection_and_response", ), diff --git a/internal/resources/device_and_app_management/graph_beta/device_management_template/state_assignment.go b/internal/resources/device_and_app_management/graph_beta/device_management_template/state_assignment.go deleted file mode 100644 index 1f2ea9e8..00000000 --- a/internal/resources/device_and_app_management/graph_beta/device_management_template/state_assignment.go +++ /dev/null @@ -1,237 +0,0 @@ -package graphBetaDeviceManagementTemplate - -import ( - "context" - "sort" - - sharedmodels "github.com/deploymenttheory/terraform-provider-microsoft365/internal/resources/common/shared_models/graph_beta/device_and_app_management" - "github.com/deploymenttheory/terraform-provider-microsoft365/internal/resources/common/state" - "github.com/hashicorp/terraform-plugin-framework/types" - "github.com/hashicorp/terraform-plugin-log/tflog" - "github.com/microsoftgraph/msgraph-beta-sdk-go/models" -) - -// MapRemoteAssignmentStateToTerraform maps the remote policy assignment state to the Terraform state -func MapRemoteAssignmentStateToTerraform(ctx context.Context, data *DeviceManagementTemplateResourceModel, assignmentsResponse models.DeviceManagementConfigurationPolicyAssignmentCollectionResponseable) { - if assignmentsResponse == nil { - tflog.Debug(ctx, "Assignments response is nil") - return - } - - tflog.Debug(ctx, "Starting to map policy assignment to Terraform state") - - assignments := &sharedmodels.SettingsCatalogSettingsAssignmentResourceModel{ - AllDevices: types.BoolValue(false), - AllUsers: types.BoolValue(false), - } - - // Map All Devices assignments - allDeviceAssignments := GetAllDeviceAssignments(assignmentsResponse) - MapAllDeviceAssignments(assignments, allDeviceAssignments) - - // Map All Users assignments - allUserAssignments := GetAllUserAssignments(assignmentsResponse) - MapAllUserAssignments(assignments, allUserAssignments) - - // Map Include Group assignments - includeGroupAssignments := GetIncludeGroupAssignments(assignmentsResponse) - MapIncludeGroupAssignments(assignments, includeGroupAssignments) - - // Map Exclude Group assignments - excludeGroupAssignments := GetExcludeGroupAssignments(assignmentsResponse) - MapExcludeGroupAssignments(assignments, excludeGroupAssignments) - - data.Assignments = assignments - - tflog.Debug(ctx, "Finished mapping assignment to Terraform state") -} - -// MapAllDeviceAssignments maps the all devices assignment configuration to the assignments model -func MapAllDeviceAssignments(assignments *sharedmodels.SettingsCatalogSettingsAssignmentResourceModel, allDeviceAssignments []models.DeviceManagementConfigurationPolicyAssignmentable) { - if len(allDeviceAssignments) == 0 { - return - } - - assignments.AllDevices = types.BoolValue(true) - - if target := allDeviceAssignments[0].GetTarget(); target != nil { - if filterId := target.GetDeviceAndAppManagementAssignmentFilterId(); filterId != nil && *filterId != "" { - assignments.AllDevicesFilterId = types.StringValue(*filterId) - } else { - assignments.AllDevicesFilterId = types.StringNull() - } - - if filterType := target.GetDeviceAndAppManagementAssignmentFilterType(); filterType != nil && assignments.AllDevicesFilterId.ValueString() != "" { - assignments.AllDevicesFilterType = state.EnumPtrToTypeString(filterType) - } else { - assignments.AllDevicesFilterType = types.StringValue("none") - } - } -} - -// MapAllUserAssignments maps the all users assignment configuration to the assignments model -func MapAllUserAssignments(assignments *sharedmodels.SettingsCatalogSettingsAssignmentResourceModel, allUserAssignments []models.DeviceManagementConfigurationPolicyAssignmentable) { - if len(allUserAssignments) == 0 { - return - } - - assignments.AllUsers = types.BoolValue(true) - - if target := allUserAssignments[0].GetTarget(); target != nil { - if filterId := target.GetDeviceAndAppManagementAssignmentFilterId(); filterId != nil && *filterId != "" { - assignments.AllUsersFilterId = types.StringValue(*filterId) - } else { - assignments.AllUsersFilterId = types.StringNull() - } - - if filterType := target.GetDeviceAndAppManagementAssignmentFilterType(); filterType != nil && assignments.AllUsersFilterId.ValueString() != "" { - assignments.AllUsersFilterType = state.EnumPtrToTypeString(filterType) - } else { - assignments.AllUsersFilterType = types.StringValue("none") - } - } -} - -// MapIncludeGroupAssignments maps the include groups assignment configuration to the assignments model -func MapIncludeGroupAssignments(assignments *sharedmodels.SettingsCatalogSettingsAssignmentResourceModel, includeGroupAssignments []models.DeviceManagementConfigurationPolicyAssignmentable) { - if len(includeGroupAssignments) == 0 { - return - } - - assignments.IncludeGroups = make([]sharedmodels.IncludeGroup, 0, len(includeGroupAssignments)) - - for _, assignment := range includeGroupAssignments { - if target, ok := assignment.GetTarget().(models.GroupAssignmentTargetable); ok { - includeGroup := sharedmodels.IncludeGroup{ - GroupId: types.StringValue(state.StringPtrToString(target.GetGroupId())), - } - - if filterId := target.GetDeviceAndAppManagementAssignmentFilterId(); filterId != nil && *filterId != "" { - includeGroup.IncludeGroupsFilterId = types.StringValue(*filterId) - if filterType := target.GetDeviceAndAppManagementAssignmentFilterType(); filterType != nil { - includeGroup.IncludeGroupsFilterType = state.EnumPtrToTypeString(filterType) - } - } else { - includeGroup.IncludeGroupsFilterId = types.StringNull() - includeGroup.IncludeGroupsFilterType = types.StringValue("none") - } - - assignments.IncludeGroups = append(assignments.IncludeGroups, includeGroup) - } - } - - // Sort IncludeGroups by GroupId - sort.Slice(assignments.IncludeGroups, func(i, j int) bool { - return assignments.IncludeGroups[i].GroupId.ValueString() < assignments.IncludeGroups[j].GroupId.ValueString() - }) -} - -// MapExcludeGroupAssignments maps the exclude groups assignment configuration to the assignments model -func MapExcludeGroupAssignments(assignments *sharedmodels.SettingsCatalogSettingsAssignmentResourceModel, excludeGroupAssignments []models.DeviceManagementConfigurationPolicyAssignmentable) { - if len(excludeGroupAssignments) == 0 { - assignments.ExcludeGroupIds = nil - return - } - - excludeGroupIds := make([]types.String, 0, len(excludeGroupAssignments)) - for _, assignment := range excludeGroupAssignments { - if target, ok := assignment.GetTarget().(models.GroupAssignmentTargetable); ok { - if groupId := target.GetGroupId(); groupId != nil { - excludeGroupIds = append(excludeGroupIds, types.StringValue(*groupId)) - } - } - } - - // Sort exclude group IDs alphanumerically - sort.Slice(excludeGroupIds, func(i, j int) bool { - return excludeGroupIds[i].ValueString() < excludeGroupIds[j].ValueString() - }) - - if len(excludeGroupIds) > 0 { - assignments.ExcludeGroupIds = excludeGroupIds - } else { - assignments.ExcludeGroupIds = nil - } -} - -// Helpers - -// GetAllDeviceAssignments retrieves all device assignments from the list of assignments -func GetAllDeviceAssignments(assignmentsResponse models.DeviceManagementConfigurationPolicyAssignmentCollectionResponseable) []models.DeviceManagementConfigurationPolicyAssignmentable { - if assignmentsResponse == nil { - return nil - } - - var allDeviceAssignments []models.DeviceManagementConfigurationPolicyAssignmentable - assignments := assignmentsResponse.GetValue() - - for _, assignment := range assignments { - if target := assignment.GetTarget(); target != nil { - if odataType := target.GetOdataType(); odataType != nil && *odataType == "#microsoft.graph.allDevicesAssignmentTarget" { - allDeviceAssignments = append(allDeviceAssignments, assignment) - } - } - } - - return allDeviceAssignments -} - -// GetAllUserAssignments retrieves all user assignments from the list of assignments -func GetAllUserAssignments(assignmentsResponse models.DeviceManagementConfigurationPolicyAssignmentCollectionResponseable) []models.DeviceManagementConfigurationPolicyAssignmentable { - if assignmentsResponse == nil { - return nil - } - - var allUserAssignments []models.DeviceManagementConfigurationPolicyAssignmentable - assignments := assignmentsResponse.GetValue() - - for _, assignment := range assignments { - if target := assignment.GetTarget(); target != nil { - if odataType := target.GetOdataType(); odataType != nil && *odataType == "#microsoft.graph.allLicensedUsersAssignmentTarget" { - allUserAssignments = append(allUserAssignments, assignment) - } - } - } - - return allUserAssignments -} - -// GetIncludeGroupAssignments retrieves include group assignments from the list of assignments -func GetIncludeGroupAssignments(assignmentsResponse models.DeviceManagementConfigurationPolicyAssignmentCollectionResponseable) []models.DeviceManagementConfigurationPolicyAssignmentable { - if assignmentsResponse == nil { - return nil - } - - var includeGroupAssignments []models.DeviceManagementConfigurationPolicyAssignmentable - assignments := assignmentsResponse.GetValue() - - for _, assignment := range assignments { - if target := assignment.GetTarget(); target != nil { - if odataType := target.GetOdataType(); odataType != nil && *odataType == "#microsoft.graph.groupAssignmentTarget" { - includeGroupAssignments = append(includeGroupAssignments, assignment) - } - } - } - - return includeGroupAssignments -} - -// GetExcludeGroupAssignments retrieves exclude group assignments from the list of assignments -func GetExcludeGroupAssignments(assignmentsResponse models.DeviceManagementConfigurationPolicyAssignmentCollectionResponseable) []models.DeviceManagementConfigurationPolicyAssignmentable { - if assignmentsResponse == nil { - return nil - } - - var excludeGroupAssignments []models.DeviceManagementConfigurationPolicyAssignmentable - assignments := assignmentsResponse.GetValue() - - for _, assignment := range assignments { - if target := assignment.GetTarget(); target != nil { - if odataType := target.GetOdataType(); odataType != nil && *odataType == "#microsoft.graph.exclusionGroupAssignmentTarget" { - excludeGroupAssignments = append(excludeGroupAssignments, assignment) - } - } - } - - return excludeGroupAssignments -} diff --git a/internal/resources/device_and_app_management/graph_beta/device_management_template/state_base_resource.go b/internal/resources/device_and_app_management/graph_beta/device_management_template/state_base_resource.go index 461ca4c2..d1c7e422 100644 --- a/internal/resources/device_and_app_management/graph_beta/device_management_template/state_base_resource.go +++ b/internal/resources/device_and_app_management/graph_beta/device_management_template/state_base_resource.go @@ -3,6 +3,7 @@ package graphBetaDeviceManagementTemplate import ( "context" + sharedmodels "github.com/deploymenttheory/terraform-provider-microsoft365/internal/resources/common/shared_models/graph_beta/device_and_app_management" "github.com/deploymenttheory/terraform-provider-microsoft365/internal/resources/common/state" "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/types" @@ -11,7 +12,7 @@ import ( ) // MapRemoteResourceStateToTerraform states the base properties of a DeviceManagementTemplateResourceModel to a Terraform state -func MapRemoteResourceStateToTerraform(ctx context.Context, data *DeviceManagementTemplateResourceModel, remoteResource graphmodels.DeviceManagementConfigurationPolicyable) { +func MapRemoteResourceStateToTerraform(ctx context.Context, data *sharedmodels.SettingsCatalogProfileResourceModel, remoteResource graphmodels.DeviceManagementConfigurationPolicyable) { if remoteResource == nil { tflog.Debug(ctx, "Remote resource is nil") return diff --git a/internal/resources/device_and_app_management/graph_beta/device_management_template/state_settings.go b/internal/resources/device_and_app_management/graph_beta/device_management_template/state_settings.go deleted file mode 100644 index b352b763..00000000 --- a/internal/resources/device_and_app_management/graph_beta/device_management_template/state_settings.go +++ /dev/null @@ -1,71 +0,0 @@ -package graphBetaDeviceManagementTemplate - -import ( - "context" - "encoding/json" - - "github.com/deploymenttheory/terraform-provider-microsoft365/internal/resources/common/normalize" - "github.com/hashicorp/terraform-plugin-framework/types" - "github.com/hashicorp/terraform-plugin-log/tflog" -) - -// MapRemoteSettingsStateToTerraform maps the remote settings catalog settings state to the Terraform state -// taking the raw json from a custom GET request, normalizing the content and then stating. The stating logic: -// 1. Parses the original HCL settings to preserve secret values and states -// 2. Parses the raw response and extracts the settings content -// 3. Structures the content under settingsDetails like the PUT request -// 4. Recursively preserves secret setting values and states from the original HCL config -// 5. Converts the structured content to JSON and normalizes it alphabetically -// 6. States the normalized JSON in the Terraform state -func MapRemoteSettingsStateToTerraform(ctx context.Context, data *DeviceManagementTemplateResourceModel, resp []byte) { - var configSettings map[string]interface{} - if err := json.Unmarshal([]byte(data.Settings.ValueString()), &configSettings); err != nil { - tflog.Error(ctx, "Failed to unmarshal config settings", map[string]interface{}{"error": err.Error()}) - return - } - - var rawResponse map[string]interface{} - if err := json.Unmarshal(resp, &rawResponse); err != nil { - var arrayResponse []interface{} - if err := json.Unmarshal(resp, &arrayResponse); err != nil { - tflog.Error(ctx, "Failed to unmarshal settings response", map[string]interface{}{"error": err.Error()}) - return - } - rawResponse = map[string]interface{}{"value": arrayResponse} - } - - var settingsContent interface{} - if value, ok := rawResponse["value"]; ok { - settingsContent = value - } else if details, ok := rawResponse["settingsDetails"]; ok { - settingsContent = details - } else { - settingsContent = rawResponse - } - - structuredContent := map[string]interface{}{ - "settingsDetails": settingsContent, - } - - if err := normalize.PreserveSecretSettings(configSettings, structuredContent); err != nil { - tflog.Error(ctx, "Error stating settings catalog secret settings from HCL", map[string]interface{}{"error": err.Error()}) - return - } - - jsonBytes, err := json.Marshal(structuredContent) - if err != nil { - tflog.Error(ctx, "Failed to marshal JSON structured content during preparation for normalization", map[string]interface{}{"error": err.Error()}) - return - } - - normalizedJSON, err := normalize.JSONAlphabetically(string(jsonBytes)) - if err != nil { - tflog.Error(ctx, "Failed to normalize settings catalog JSON alphabetically", map[string]interface{}{"error": err.Error()}) - return - } - - tflog.Debug(ctx, "Original settings", map[string]interface{}{"settings": string(resp)}) - tflog.Debug(ctx, "Normalized settings", map[string]interface{}{"settings": normalizedJSON}) - - data.Settings = types.StringValue(normalizedJSON) -} From 45834c33cb439eb5166976e58abba68f3bfb5f76 Mon Sep 17 00:00:00 2001 From: ShocOne Date: Wed, 15 Jan 2025 17:15:12 +0000 Subject: [PATCH 06/14] feat: add new Windows Defender Antivirus policy templates to device management configuration --- .../device_management_template/construct_resource.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/internal/resources/device_and_app_management/graph_beta/device_management_template/construct_resource.go b/internal/resources/device_and_app_management/graph_beta/device_management_template/construct_resource.go index 97327df4..4bd04752 100644 --- a/internal/resources/device_and_app_management/graph_beta/device_management_template/construct_resource.go +++ b/internal/resources/device_and_app_management/graph_beta/device_management_template/construct_resource.go @@ -24,11 +24,21 @@ var policyConfigMap = map[string]PolicyTemplateConfig{ Technologies: graphmodels.MDM_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES | graphmodels.MICROSOFTSENSE_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES, TemplateID: "e3f74c5a-a6de-411d-aef6-eb15628f3a0a_1", }, + "windows_anti_virus_microsoft_defender_antivirus": { + Platform: graphmodels.WINDOWS10_DEVICEMANAGEMENTCONFIGURATIONPLATFORMS, + Technologies: graphmodels.MDM_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES | graphmodels.MICROSOFTSENSE_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES, + TemplateID: "804339ad-1553-4478-a742-138fb5807418_1", + }, "windows_anti_virus_microsoft_defender_antivirus_exclusions": { Platform: graphmodels.WINDOWS10_DEVICEMANAGEMENTCONFIGURATIONPLATFORMS, Technologies: graphmodels.MDM_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES | graphmodels.MICROSOFTSENSE_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES, TemplateID: "45fea5e9-280d-4da1-9792-fb5736da0ca9_1", }, + "windows_anti_virus_security_experience": { + Platform: graphmodels.WINDOWS10_DEVICEMANAGEMENTCONFIGURATIONPLATFORMS, + Technologies: graphmodels.MDM_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES | graphmodels.MICROSOFTSENSE_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES, + TemplateID: "d948ff9b-99cb-4ee0-8012-1fbc09685377_1", + }, } // Main entry point to construct the intune settings catalog profile resource for the Terraform provider. From a3b9a33347942f8545b4878d7de88dc195ab831e Mon Sep 17 00:00:00 2001 From: ShocOne Date: Thu, 16 Jan 2025 10:47:36 +0000 Subject: [PATCH 07/14] feat: add settings catalog template and update related configurations --- ...anagement_endpoint_privilege_management.md | 8 +- .../resource.tf | 2 +- .../README.md | 15 ++ .../import.sh | 4 + .../resource.tf | 214 ++++++++++++++++++ internal/provider/resources.go | 2 + .../resources/common/normalize/json_test.go | 56 ++--- .../settings_catalog_base.go | 28 +-- .../settings_catalog_reference.go | 2 +- .../settings_catalog_settings.go | 1 - .../configuration_policy_settings.go | 4 +- .../configuration_policy_settings_test.go | 16 +- internal/resources/common/validators/set.go | 68 ++++++ .../resources/common/validators/set_test.go | 151 ++++++++++++ .../resource_docs/map.md | 97 -------- .../validate_settings_catalog_settings.go | 201 ---------------- .../construct_resource.go | 6 +- .../endpoint_privilege_management/resource.go | 15 +- .../state_base_resource.go | 9 +- .../settings_catalog/construct_resource.go | 16 +- .../graph_beta/settings_catalog/resource.go | 11 +- .../settings_catalog/state_base_resource.go | 13 +- .../construct_resource.go | 59 ++++- .../crud.go | 0 .../modify_plan.go | 0 .../resource.go | 46 ++-- .../state_base_resource.go | 10 +- ...nagement_settings_catalog_template.md.tmpl | 23 ++ 28 files changed, 653 insertions(+), 424 deletions(-) create mode 100644 examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_settings_catalog_template/README.md create mode 100644 examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_settings_catalog_template/import.sh create mode 100644 examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_settings_catalog_template/resource.tf create mode 100644 internal/resources/common/validators/set.go create mode 100644 internal/resources/common/validators/set_test.go delete mode 100644 internal/resources/device_and_app_management/graph_beta/device_management_template/resource_docs/map.md delete mode 100644 internal/resources/device_and_app_management/graph_beta/device_management_template/validate_settings_catalog_settings.go rename internal/resources/device_and_app_management/graph_beta/{device_management_template => settings_catalog_template}/construct_resource.go (59%) rename internal/resources/device_and_app_management/graph_beta/{device_management_template => settings_catalog_template}/crud.go (100%) rename internal/resources/device_and_app_management/graph_beta/{device_management_template => settings_catalog_template}/modify_plan.go (100%) rename internal/resources/device_and_app_management/graph_beta/{device_management_template => settings_catalog_template}/resource.go (85%) rename internal/resources/device_and_app_management/graph_beta/{device_management_template => settings_catalog_template}/state_base_resource.go (92%) create mode 100644 templates/resources/graph_beta_device_and_app_management_settings_catalog_template.md.tmpl diff --git a/docs/resources/graph_beta_device_and_app_management_endpoint_privilege_management.md b/docs/resources/graph_beta_device_and_app_management_endpoint_privilege_management.md index f1a11824..8f5b8b00 100644 --- a/docs/resources/graph_beta_device_and_app_management_endpoint_privilege_management.md +++ b/docs/resources/graph_beta_device_and_app_management_endpoint_privilege_management.md @@ -16,11 +16,11 @@ resource "microsoft365_graph_beta_device_and_app_management_endpoint_privilege_m name = "EPM Base Elevation settings policy" description = "Elevation settings policy" role_scope_tag_ids = ["0"] - configuration_policy_template_type = "elevation_settings_policy" + settings_catalog_template_type = "elevation_settings_policy" settings = jsonencode({ - "settingsDetails" : [{ + "settings" : [{ "id" : "0", "settingInstance" : { "@odata.type" : "#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance", @@ -132,14 +132,14 @@ resource "microsoft365_graph_beta_device_and_app_management_endpoint_privilege_m ### Required -- `configuration_policy_template_type` (String) Defines which Endpoint Privilege Management Policy type with settings catalog setting will be deployed. Options available are `elevation_settings_policy` or `elevation_rules_policy`. +- `settings_catalog_template_type` (String) Defines which Endpoint Privilege Management Policy type with settings catalog setting will be deployed. Options available are `elevation_settings_policy` or `elevation_rules_policy`. - `name` (String) Policy name - `settings` (String) Endpoint Privilege Management Policy with settings catalog settings defined as a valid JSON string. Provide JSON-encoded settings structure. This can either be extracted from an existing policy using the Intune gui export to JSON, via a script such as [this PowerShell script](https://github.com/deploymenttheory/terraform-provider-microsoft365/blob/main/scripts/GetSettingsCatalogConfigurationById.ps1) or created from scratch. The JSON structure should match the graph schema of the settings catalog. Please look at the terraform documentation for the settings catalog for examples and how to correctly format the HCL. A correctly formatted field in the HCL should begin and end like this: ```hcl settings = jsonencode({ - "settingsDetails": [ + "settings": [ { # ... settings configuration ... } diff --git a/examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_endpoint_privilege_management/resource.tf b/examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_endpoint_privilege_management/resource.tf index 3a8f3a75..8f0fde3e 100644 --- a/examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_endpoint_privilege_management/resource.tf +++ b/examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_endpoint_privilege_management/resource.tf @@ -2,7 +2,7 @@ resource "microsoft365_graph_beta_device_and_app_management_endpoint_privilege_m name = "EPM Base Elevation settings policy" description = "Elevation settings policy" role_scope_tag_ids = ["0"] - configuration_policy_template_type = "elevation_settings_policy" + settings_catalog_template_type = "elevation_settings_policy" settings = jsonencode({ diff --git a/examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_settings_catalog_template/README.md b/examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_settings_catalog_template/README.md new file mode 100644 index 00000000..d398b52f --- /dev/null +++ b/examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_settings_catalog_template/README.md @@ -0,0 +1,15 @@ + +### Providers + +| Name | Version | +|------|---------| +| [microsoft365](#provider_microsoft365) | n/a | + +### Inputs + +No inputs. + +### Outputs + +No outputs. + \ No newline at end of file diff --git a/examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_settings_catalog_template/import.sh b/examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_settings_catalog_template/import.sh new file mode 100644 index 00000000..60ee43d3 --- /dev/null +++ b/examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_settings_catalog_template/import.sh @@ -0,0 +1,4 @@ +# Using the provider-default project ID, the import ID is: +# {resource_id} +terraform import microsoft365_graph_beta_device_and_app_management_settings_catalog_template.example settings-catalog-template-id + diff --git a/examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_settings_catalog_template/resource.tf b/examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_settings_catalog_template/resource.tf new file mode 100644 index 00000000..96468a54 --- /dev/null +++ b/examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_settings_catalog_template/resource.tf @@ -0,0 +1,214 @@ +resource "microsoft365_graph_beta_device_and_app_management_settings_catalog_template" "windows_anti_virus_defender_update_controls" { + name = "Windows - Defender Update controls" + description = "terraform test for settings catalog templates" + settings_catalog_template_type = "windows_anti_virus_defender_update_controls" + role_scope_tag_ids = ["0"] + + settings = jsonencode({ + "settings" : [ + { + "id" : "0", + "settingInstance" : { + "@odata.type" : "#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance", + "choiceSettingValue" : { + "value" : "device_vendor_msft_defender_configuration_engineupdateschannel_6", + "settingValueTemplateReference" : { + "settingValueTemplateId" : "afc8df70-7b19-4335-b200-bf4b7e098f67", + "useTemplateDefault" : false + }, + "children" : [] + }, + "settingInstanceTemplateReference" : { + "settingInstanceTemplateId" : "f7e1409d-9c85-4a3f-85a6-ad05cc8ccf13" + }, + "settingDefinitionId" : "device_vendor_msft_defender_configuration_engineupdateschannel" + } + }, + { + "id" : "1", + "settingInstance" : { + "@odata.type" : "#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance", + "choiceSettingValue" : { + "value" : "device_vendor_msft_defender_configuration_platformupdateschannel_5", + "settingValueTemplateReference" : { + "settingValueTemplateId" : "d3b0d61a-bdc5-4507-84d0-5f2a4a3e11a5", + "useTemplateDefault" : false + }, + "children" : [] + }, + "settingInstanceTemplateReference" : { + "settingInstanceTemplateId" : "e78b3ace-75d0-4aad-b3fa-4f49390d6483" + }, + "settingDefinitionId" : "device_vendor_msft_defender_configuration_platformupdateschannel" + } + }, + { + "id" : "2", + "settingInstance" : { + "@odata.type" : "#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance", + "choiceSettingValue" : { + "value" : "device_vendor_msft_defender_configuration_securityintelligenceupdateschannel_4", + "settingValueTemplateReference" : { + "settingValueTemplateId" : "41ea06bf-e94a-482a-9aaa-7fd535fb4150", + "useTemplateDefault" : false + }, + "children" : [] + }, + "settingInstanceTemplateReference" : { + "settingInstanceTemplateId" : "ba273649-e186-4377-89d5-87405bc9a87c" + }, + "settingDefinitionId" : "device_vendor_msft_defender_configuration_securityintelligenceupdateschannel" + } + } + ] + }) + + assignments = { + all_devices = false + # all_devices_filter_type = "exclude" + # all_devices_filter_id = "2d7956fb-e5b5-4fa3-90b2-5bee9bee7883" + + all_users = false + # all_users_filter_type = "include" + # all_users_filter_id = "80f8c0a5-f3ec-4936-bcbc-420dc0ca3665" + + include_groups = [ + { + group_id = "51a96cdd-4b9b-4849-b416-8c94a6d88797" + include_groups_filter_type = "include" + include_groups_filter_id = "80f8c0a5-f3ec-4936-bcbc-420dc0ca3665" + }, + { + group_id = "b15228f4-9d49-41ed-9b4f-0e7c721fd9c2" + include_groups_filter_type = "include" + include_groups_filter_id = "2d7956fb-e5b5-4fa3-90b2-5bee9bee7883" + }, + ] + + exclude_group_ids = [ + "b8c661c2-fa9a-4351-af86-adc1729c343f", + "f6ebd6ff-501e-4b3d-a00b-a2e102c3fa0f", + ] + } + + timeouts = { + create = "1m" + read = "1m" + update = "1m" + delete = "1m" + } +} + + +resource "microsoft365_graph_beta_device_and_app_management_settings_catalog_template" "windows_anti_virus_microsoft_defender_antivirus_exclusions" { + name = "Windows - Defender Update anti virus exclusions" + description = "terraform test for settings catalog templates" + settings_catalog_template_type = "windows_anti_virus_microsoft_defender_antivirus_exclusions" + role_scope_tag_ids = ["0"] + + settings = jsonencode({ + "settings" : [ + { + "settingInstance" : { + "settingDefinitionId" : "device_vendor_msft_policy_config_defender_excludedextensions", + "@odata.type" : "#microsoft.graph.deviceManagementConfigurationSimpleSettingCollectionInstance", + "simpleSettingCollectionValue" : [ + { + "settingValueTemplateReference" : null, + "@odata.type" : "#microsoft.graph.deviceManagementConfigurationStringSettingValue", + "value" : ".dll" + }, + { + "settingValueTemplateReference" : null, + "@odata.type" : "#microsoft.graph.deviceManagementConfigurationStringSettingValue", + "value" : ".exe" + } + ], + "settingInstanceTemplateReference" : { + "settingInstanceTemplateId" : "c203725b-17dc-427b-9470-673a2ce9cd5e" + } + }, + "id" : "0" + }, + { + "settingInstance" : { + "settingDefinitionId" : "device_vendor_msft_policy_config_defender_excludedpaths", + "@odata.type" : "#microsoft.graph.deviceManagementConfigurationSimpleSettingCollectionInstance", + "simpleSettingCollectionValue" : [ + { + "settingValueTemplateReference" : null, + "@odata.type" : "#microsoft.graph.deviceManagementConfigurationStringSettingValue", + "value" : "c:\\some\\path\\1" + }, + { + "settingValueTemplateReference" : null, + "@odata.type" : "#microsoft.graph.deviceManagementConfigurationStringSettingValue", + "value" : "c:\\some\\path\\2" + } + ], + "settingInstanceTemplateReference" : { + "settingInstanceTemplateId" : "aaf04adc-c639-464f-b4a7-152e784092e8" + } + }, + "id" : "1" + }, + { + "settingInstance" : { + "settingDefinitionId" : "device_vendor_msft_policy_config_defender_excludedprocesses", + "@odata.type" : "#microsoft.graph.deviceManagementConfigurationSimpleSettingCollectionInstance", + "simpleSettingCollectionValue" : [ + { + "settingValueTemplateReference" : null, + "@odata.type" : "#microsoft.graph.deviceManagementConfigurationStringSettingValue", + "value" : "process-1" + }, + { + "settingValueTemplateReference" : null, + "@odata.type" : "#microsoft.graph.deviceManagementConfigurationStringSettingValue", + "value" : "process-2" + } + ], + "settingInstanceTemplateReference" : { + "settingInstanceTemplateId" : "96b046ed-f138-4250-9ae0-b0772a93d16f" + } + }, + "id" : "2" + } + ] + }) + + assignments = { + all_devices = false + # all_devices_filter_type = "exclude" + # all_devices_filter_id = "2d7956fb-e5b5-4fa3-90b2-5bee9bee7883" + + all_users = false + # all_users_filter_type = "include" + # all_users_filter_id = "80f8c0a5-f3ec-4936-bcbc-420dc0ca3665" + + include_groups = [ + { + group_id = "51a96cdd-4b9b-4849-b416-8c94a6d88797" + include_groups_filter_type = "include" + include_groups_filter_id = "80f8c0a5-f3ec-4936-bcbc-420dc0ca3665" + }, + { + group_id = "b15228f4-9d49-41ed-9b4f-0e7c721fd9c2" + include_groups_filter_type = "include" + include_groups_filter_id = "2d7956fb-e5b5-4fa3-90b2-5bee9bee7883" + }, + ] + + exclude_group_ids = [ + "b8c661c2-fa9a-4351-af86-adc1729c343f", + "f6ebd6ff-501e-4b3d-a00b-a2e102c3fa0f", + ] + } + + timeouts = { + create = "1m" + read = "1m" + update = "1m" + delete = "1m" + } +} \ No newline at end of file diff --git a/internal/provider/resources.go b/internal/provider/resources.go index 0ea28283..c3613589 100644 --- a/internal/provider/resources.go +++ b/internal/provider/resources.go @@ -14,6 +14,7 @@ import ( graphBetaDeviceAndAppManagementRoleDefinition "github.com/deploymenttheory/terraform-provider-microsoft365/internal/resources/device_and_app_management/graph_beta/role_definition" graphBetaDeviceAndAppManagementRoleScopeTag "github.com/deploymenttheory/terraform-provider-microsoft365/internal/resources/device_and_app_management/graph_beta/role_scope_tag" graphBetaDeviceAndAppManagementSettingsCatalog "github.com/deploymenttheory/terraform-provider-microsoft365/internal/resources/device_and_app_management/graph_beta/settings_catalog" + graphBetaDeviceAndAppManagementSettingsCatalogTemplate "github.com/deploymenttheory/terraform-provider-microsoft365/internal/resources/device_and_app_management/graph_beta/settings_catalog_template" graphBetaDeviceAndAppManagementWindowsPlatformScript "github.com/deploymenttheory/terraform-provider-microsoft365/internal/resources/device_and_app_management/graph_beta/windows_platform_script" graphBetaDeviceAndAppManagementWinGetApp "github.com/deploymenttheory/terraform-provider-microsoft365/internal/resources/device_and_app_management/graph_beta/winget_app" @@ -50,6 +51,7 @@ func (p *M365Provider) Resources(ctx context.Context) []func() resource.Resource graphBetaDeviceAndAppManagementmacOSPlatformScript.NewMacOSPlatformScriptResource, graphBetaDeviceAndAppManagementM365AppsInstallationOptions.NewM365AppsInstallationOptionsResource, graphBetaDeviceAndAppManagementSettingsCatalog.NewSettingsCatalogResource, + graphBetaDeviceAndAppManagementSettingsCatalogTemplate.NewDeviceManagementTemplateResource, graphBetaDeviceAndAppManagementReuseablePolicySettings.NewReuseablePolicySettingsResource, graphBetaDeviceAndAppManagementRoleDefinition.NewRoleDefinitionResource, graphBetaDeviceAndAppManagementRoleScopeTag.NewRoleScopeTagResource, diff --git a/internal/resources/common/normalize/json_test.go b/internal/resources/common/normalize/json_test.go index 7888b0f6..91628c45 100644 --- a/internal/resources/common/normalize/json_test.go +++ b/internal/resources/common/normalize/json_test.go @@ -35,7 +35,7 @@ func TestNormalizeJSONAlphabetically(t *testing.T) { { name: "Complex nested structure", input: `{ - "settingsDetails": [ + "settings": [ { "id": "1", "settingInstance": { @@ -51,7 +51,7 @@ func TestNormalizeJSONAlphabetically(t *testing.T) { } ] }`, - expected: `{"settingsDetails":[{"id":"1","settingInstance":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance","settingDefinitionId":"test_id","settingInstanceTemplateReference":null,"simpleSettingValue":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationStringSettingValue","settingValueTemplateReference":null,"value":"test"}}}]}`, + expected: `{"settings":[{"id":"1","settingInstance":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance","settingDefinitionId":"test_id","settingInstanceTemplateReference":null,"simpleSettingValue":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationStringSettingValue","settingValueTemplateReference":null,"value":"test"}}}]}`, wantErr: false, }, { @@ -80,7 +80,7 @@ func TestNormalizeJSONAlphabetically(t *testing.T) { { name: "Choice setting collection with nested settings", input: `{ - "settingsDetails": [{ + "settings": [{ "id": "1", "settingInstance": { "choiceSettingCollectionValue": [{ @@ -100,13 +100,13 @@ func TestNormalizeJSONAlphabetically(t *testing.T) { } }] }`, - expected: `{"settingsDetails":[{"id":"1","settingInstance":{"choiceSettingCollectionValue":[{"children":[{"@odata.type":"#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance","settingDefinitionId":"test_id","settingInstanceTemplateReference":null,"simpleSettingValue":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationStringSettingValue","settingValueTemplateReference":null,"value":"test"}}],"settingValueTemplateReference":null,"value":"test_value"}]}}]}`, + expected: `{"settings":[{"id":"1","settingInstance":{"choiceSettingCollectionValue":[{"children":[{"@odata.type":"#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance","settingDefinitionId":"test_id","settingInstanceTemplateReference":null,"simpleSettingValue":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationStringSettingValue","settingValueTemplateReference":null,"value":"test"}}],"settingValueTemplateReference":null,"value":"test_value"}]}}]}`, wantErr: false, }, { name: "Deep nested group settings with all types", input: `{ - "settingsDetails": [{ + "settings": [{ "id": "1", "settingInstance": { "groupSettingCollectionValue": [{ @@ -133,13 +133,13 @@ func TestNormalizeJSONAlphabetically(t *testing.T) { } }] }`, - expected: `{"settingsDetails":[{"id":"1","settingInstance":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance","groupSettingCollectionValue":[{"children":[{"groupSettingCollectionValue":[{"children":[{"choiceSettingValue":{"children":[{"simpleSettingValue":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationIntegerSettingValue","settingValueTemplateReference":null,"value":123,"valueState":"valid"}}],"value":"choice_value"}}]}]}],"settingValueTemplateReference":null}]}}]}`, + expected: `{"settings":[{"id":"1","settingInstance":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance","groupSettingCollectionValue":[{"children":[{"groupSettingCollectionValue":[{"children":[{"choiceSettingValue":{"children":[{"simpleSettingValue":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationIntegerSettingValue","settingValueTemplateReference":null,"value":123,"valueState":"valid"}}],"value":"choice_value"}}]}]}],"settingValueTemplateReference":null}]}}]}`, wantErr: false, }, { name: "Multiple setting types in one structure", input: `{ - "settingsDetails": [{ + "settings": [{ "id": "1", "settingInstance": { "simpleSettingValue": { @@ -158,13 +158,13 @@ func TestNormalizeJSONAlphabetically(t *testing.T) { } }] }`, - expected: `{"settingsDetails":[{"id":"1","settingInstance":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationInstance","choiceSettingValue":{"children":[],"value":"choice"},"simpleSettingCollectionValue":[{"@odata.type":"#microsoft.graph.deviceManagementConfigurationStringSettingValue","value":"collection"}],"simpleSettingValue":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationStringSettingValue","value":"simple"}}}]}`, + expected: `{"settings":[{"id":"1","settingInstance":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationInstance","choiceSettingValue":{"children":[],"value":"choice"},"simpleSettingCollectionValue":[{"@odata.type":"#microsoft.graph.deviceManagementConfigurationStringSettingValue","value":"collection"}],"simpleSettingValue":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationStringSettingValue","value":"simple"}}}]}`, wantErr: false, }, { name: "MacOS Complex Group Setting Collection", input: `{ - "settingsDetails": [{ + "settings": [{ "id": "0", "settingInstance": { "groupSettingCollectionValue": [{ @@ -186,13 +186,13 @@ func TestNormalizeJSONAlphabetically(t *testing.T) { } }] }`, - expected: `{"settingsDetails":[{"id":"0","settingInstance":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance","groupSettingCollectionValue":[{"children":[{"@odata.type":"#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance","choiceSettingValue":{"children":[],"settingValueTemplateReference":null,"value":"com.apple.example_setting_true"},"settingDefinitionId":"com.apple.example_setting","settingInstanceTemplateReference":null}],"settingValueTemplateReference":null}],"settingDefinitionId":"com.apple.example","settingInstanceTemplateReference":null}}]}`, + expected: `{"settings":[{"id":"0","settingInstance":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance","groupSettingCollectionValue":[{"children":[{"@odata.type":"#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance","choiceSettingValue":{"children":[],"settingValueTemplateReference":null,"value":"com.apple.example_setting_true"},"settingDefinitionId":"com.apple.example_setting","settingInstanceTemplateReference":null}],"settingValueTemplateReference":null}],"settingDefinitionId":"com.apple.example","settingInstanceTemplateReference":null}}]}`, wantErr: false, }, { name: "Mixed Setting Types In Collection", input: `{ - "settingsDetails": [{ + "settings": [{ "id": "1", "settingInstance": { "groupSettingCollectionValue": [{ @@ -221,13 +221,13 @@ func TestNormalizeJSONAlphabetically(t *testing.T) { } }] }`, - expected: `{"settingsDetails":[{"id":"1","settingInstance":{"groupSettingCollectionValue":[{"children":[{"@odata.type":"#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance","settingDefinitionId":"com.apple.numeric_setting","settingInstanceTemplateReference":null,"simpleSettingValue":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationIntegerSettingValue","settingValueTemplateReference":null,"value":1}},{"@odata.type":"#microsoft.graph.deviceManagementConfigurationSimpleSettingCollectionInstance","settingDefinitionId":"com.apple.array_setting","settingInstanceTemplateReference":null,"simpleSettingCollectionValue":[{"@odata.type":"#microsoft.graph.deviceManagementConfigurationStringSettingValue","settingValueTemplateReference":null,"value":"thing"}]}],"settingValueTemplateReference":null}]}}]}`, + expected: `{"settings":[{"id":"1","settingInstance":{"groupSettingCollectionValue":[{"children":[{"@odata.type":"#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance","settingDefinitionId":"com.apple.numeric_setting","settingInstanceTemplateReference":null,"simpleSettingValue":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationIntegerSettingValue","settingValueTemplateReference":null,"value":1}},{"@odata.type":"#microsoft.graph.deviceManagementConfigurationSimpleSettingCollectionInstance","settingDefinitionId":"com.apple.array_setting","settingInstanceTemplateReference":null,"simpleSettingCollectionValue":[{"@odata.type":"#microsoft.graph.deviceManagementConfigurationStringSettingValue","settingValueTemplateReference":null,"value":"thing"}]}],"settingValueTemplateReference":null}]}}]}`, wantErr: false, }, { name: "Deeply Nested Group Collections", input: `{ - "settingsDetails": [{ + "settings": [{ "id": "6", "settingInstance": { "groupSettingCollectionValue": [{ @@ -251,13 +251,13 @@ func TestNormalizeJSONAlphabetically(t *testing.T) { } }] }`, - expected: `{"settingsDetails":[{"id":"6","settingInstance":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance","groupSettingCollectionValue":[{"children":[{"groupSettingCollectionValue":[{"children":[{"groupSettingCollectionValue":[{"children":[{"simpleSettingValue":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationStringSettingValue","settingValueTemplateReference":null,"value":"test"}}]}]}]}]}]}]}}]}`, + expected: `{"settings":[{"id":"6","settingInstance":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance","groupSettingCollectionValue":[{"children":[{"groupSettingCollectionValue":[{"children":[{"groupSettingCollectionValue":[{"children":[{"simpleSettingValue":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationStringSettingValue","settingValueTemplateReference":null,"value":"test"}}]}]}]}]}]}]}}]}`, wantErr: false, }, { name: "Choice Settings With Empty Children", input: `{ - "settingsDetails": [{ + "settings": [{ "id": "5", "settingInstance": { "choiceSettingValue": { @@ -269,13 +269,13 @@ func TestNormalizeJSONAlphabetically(t *testing.T) { } }] }`, - expected: `{"settingsDetails":[{"id":"5","settingInstance":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance","choiceSettingValue":{"children":[],"settingValueTemplateReference":null,"value":"com.apple.setting_true"}}}]}`, + expected: `{"settings":[{"id":"5","settingInstance":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance","choiceSettingValue":{"children":[],"settingValueTemplateReference":null,"value":"com.apple.setting_true"}}}]}`, wantErr: false, }, { name: "Multiple Choice Settings With Empty Children", input: `{ - "settingsDetails": [{ + "settings": [{ "id": "0", "settingInstance": { "choiceSettingValue": { @@ -302,13 +302,13 @@ func TestNormalizeJSONAlphabetically(t *testing.T) { } }] }`, - expected: `{"settingsDetails":[{"id":"0","settingInstance":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance","choiceSettingValue":{"children":[],"settingValueTemplateReference":null,"value":"device_vendor_msft_policy_config_something_1"},"settingDefinitionId":"device_vendor_msft_policy_config_something","settingInstanceTemplateReference":null}},{"id":"1","settingInstance":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance","choiceSettingValue":{"children":[],"settingValueTemplateReference":null,"value":"user_vendor_msft_policy_config_something_1"},"settingDefinitionId":"user_vendor_msft_policy_config_something","settingInstanceTemplateReference":null}}]}`, + expected: `{"settings":[{"id":"0","settingInstance":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance","choiceSettingValue":{"children":[],"settingValueTemplateReference":null,"value":"device_vendor_msft_policy_config_something_1"},"settingDefinitionId":"device_vendor_msft_policy_config_something","settingInstanceTemplateReference":null}},{"id":"1","settingInstance":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance","choiceSettingValue":{"children":[],"settingValueTemplateReference":null,"value":"user_vendor_msft_policy_config_something_1"},"settingDefinitionId":"user_vendor_msft_policy_config_something","settingInstanceTemplateReference":null}}]}`, wantErr: false, }, { name: "Choice Setting With Nested Choice Settings Array", input: `{ - "settingsDetails": [{ + "settings": [{ "id": "0", "settingInstance": { "choiceSettingValue": { @@ -343,13 +343,13 @@ func TestNormalizeJSONAlphabetically(t *testing.T) { } }] }`, - expected: `{"settingsDetails":[{"id":"0","settingInstance":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance","choiceSettingValue":{"children":[{"@odata.type":"#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance","choiceSettingValue":{"children":[],"settingValueTemplateReference":null,"value":"user_vendor_msft_policy_config_nested_1"},"settingDefinitionId":"user_vendor_msft_policy_config_nested","settingInstanceTemplateReference":null},{"@odata.type":"#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance","choiceSettingValue":{"children":[],"settingValueTemplateReference":null,"value":"user_vendor_msft_policy_config_nested2_1"},"settingDefinitionId":"user_vendor_msft_policy_config_nested2","settingInstanceTemplateReference":null}],"settingValueTemplateReference":null,"value":"parent_setting_value"},"settingDefinitionId":"parent_setting","settingInstanceTemplateReference":null}}]}`, + expected: `{"settings":[{"id":"0","settingInstance":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance","choiceSettingValue":{"children":[{"@odata.type":"#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance","choiceSettingValue":{"children":[],"settingValueTemplateReference":null,"value":"user_vendor_msft_policy_config_nested_1"},"settingDefinitionId":"user_vendor_msft_policy_config_nested","settingInstanceTemplateReference":null},{"@odata.type":"#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance","choiceSettingValue":{"children":[],"settingValueTemplateReference":null,"value":"user_vendor_msft_policy_config_nested2_1"},"settingDefinitionId":"user_vendor_msft_policy_config_nested2","settingInstanceTemplateReference":null}],"settingValueTemplateReference":null,"value":"parent_setting_value"},"settingDefinitionId":"parent_setting","settingInstanceTemplateReference":null}}]}`, wantErr: false, }, { name: "Choice Setting With Mixed GroupSettingCollection and SimpleSettingValue", input: `{ - "settingsDetails": [{ + "settings": [{ "id": "0", "settingInstance": { "choiceSettingValue": { @@ -396,13 +396,13 @@ func TestNormalizeJSONAlphabetically(t *testing.T) { } }] }`, - expected: `{"settingsDetails":[{"id":"0","settingInstance":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance","choiceSettingValue":{"children":[{"@odata.type":"#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance","groupSettingCollectionValue":[{"children":[{"@odata.type":"#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance","settingDefinitionId":"key_setting","settingInstanceTemplateReference":null,"simpleSettingValue":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationStringSettingValue","settingValueTemplateReference":null,"value":"key_value"}},{"@odata.type":"#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance","settingDefinitionId":"value_setting","settingInstanceTemplateReference":null,"simpleSettingValue":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationStringSettingValue","settingValueTemplateReference":null,"value":"value_string"}}],"settingValueTemplateReference":null}],"settingDefinitionId":"collection_setting","settingInstanceTemplateReference":null}],"settingValueTemplateReference":null,"value":"parent_value"},"settingDefinitionId":"parent_setting","settingInstanceTemplateReference":null}}]}`, + expected: `{"settings":[{"id":"0","settingInstance":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance","choiceSettingValue":{"children":[{"@odata.type":"#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance","groupSettingCollectionValue":[{"children":[{"@odata.type":"#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance","settingDefinitionId":"key_setting","settingInstanceTemplateReference":null,"simpleSettingValue":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationStringSettingValue","settingValueTemplateReference":null,"value":"key_value"}},{"@odata.type":"#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance","settingDefinitionId":"value_setting","settingInstanceTemplateReference":null,"simpleSettingValue":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationStringSettingValue","settingValueTemplateReference":null,"value":"value_string"}}],"settingValueTemplateReference":null}],"settingDefinitionId":"collection_setting","settingInstanceTemplateReference":null}],"settingValueTemplateReference":null,"value":"parent_value"},"settingDefinitionId":"parent_setting","settingInstanceTemplateReference":null}}]}`, wantErr: false, }, { name: "SimpleSettingCollectionValue With Multiple String Values", input: `{ - "settingsDetails": [{ + "settings": [{ "settingInstance": { "simpleSettingCollectionValue": [ { @@ -421,13 +421,13 @@ func TestNormalizeJSONAlphabetically(t *testing.T) { } }] }`, - expected: `{"settingsDetails":[{"settingInstance":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationSimpleSettingCollectionInstance","settingDefinitionId":"some_setting_alloweddomains","simpleSettingCollectionValue":[{"@odata.type":"#microsoft.graph.deviceManagementConfigurationStringSettingValue","settingValueTemplateReference":null,"value":"thing"},{"@odata.type":"#microsoft.graph.deviceManagementConfigurationStringSettingValue","settingValueTemplateReference":null,"value":"thing2"}]}}]}`, + expected: `{"settings":[{"settingInstance":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationSimpleSettingCollectionInstance","settingDefinitionId":"some_setting_alloweddomains","simpleSettingCollectionValue":[{"@odata.type":"#microsoft.graph.deviceManagementConfigurationStringSettingValue","settingValueTemplateReference":null,"value":"thing"},{"@odata.type":"#microsoft.graph.deviceManagementConfigurationStringSettingValue","settingValueTemplateReference":null,"value":"thing2"}]}}]}`, wantErr: false, }, { name: "Mixed Integer and String Values in Group Collection", input: `{ - "settingsDetails": [{ + "settings": [{ "settingInstance": { "groupSettingCollectionValue": [{ "children": [ @@ -457,13 +457,13 @@ func TestNormalizeJSONAlphabetically(t *testing.T) { } }] }`, - expected: `{"settingsDetails":[{"settingInstance":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance","groupSettingCollectionValue":[{"children":[{"@odata.type":"#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance","settingDefinitionId":"numeric_setting","simpleSettingValue":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationIntegerSettingValue","settingValueTemplateReference":null,"value":1}},{"@odata.type":"#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance","settingDefinitionId":"date_setting","simpleSettingValue":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationStringSettingValue","settingValueTemplateReference":null,"value":"2024-10-31T00:00:00"}}],"settingValueTemplateReference":null}],"settingDefinitionId":"mixed_settings"}}]}`, + expected: `{"settings":[{"settingInstance":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance","groupSettingCollectionValue":[{"children":[{"@odata.type":"#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance","settingDefinitionId":"numeric_setting","simpleSettingValue":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationIntegerSettingValue","settingValueTemplateReference":null,"value":1}},{"@odata.type":"#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance","settingDefinitionId":"date_setting","simpleSettingValue":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationStringSettingValue","settingValueTemplateReference":null,"value":"2024-10-31T00:00:00"}}],"settingValueTemplateReference":null}],"settingDefinitionId":"mixed_settings"}}]}`, wantErr: false, }, { name: "Nested Group Collections With Multiple Settings", input: `{ - "settingsDetails": [ + "settings": [ { "id": "0", "settingInstance": { @@ -537,7 +537,7 @@ func TestNormalizeJSONAlphabetically(t *testing.T) { } ] }`, - expected: `{"settingsDetails":[{"id":"0","settingInstance":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance","choiceSettingValue":{"children":[{"@odata.type":"#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance","groupSettingCollectionValue":[{"children":[{"@odata.type":"#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance","settingDefinitionId":"device_vendor_msft_policy_config_ppt16v2~policy~l_microsoftofficepowerpointmachine~l_convertersmachineppt_l_externalconverterasdefaultforfileextensionppt_l_listofexternalconvertersppt_key","settingInstanceTemplateReference":null,"simpleSettingValue":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationStringSettingValue","settingValueTemplateReference":null,"value":"thing"}},{"@odata.type":"#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance","settingDefinitionId":"device_vendor_msft_policy_config_ppt16v2~policy~l_microsoftofficepowerpointmachine~l_convertersmachineppt_l_externalconverterasdefaultforfileextensionppt_l_listofexternalconvertersppt_value","settingInstanceTemplateReference":null,"simpleSettingValue":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationStringSettingValue","settingValueTemplateReference":null,"value":"value1"}}],"settingValueTemplateReference":null},{"children":[{"@odata.type":"#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance","settingDefinitionId":"device_vendor_msft_policy_config_ppt16v2~policy~l_microsoftofficepowerpointmachine~l_convertersmachineppt_l_externalconverterasdefaultforfileextensionppt_l_listofexternalconvertersppt_key","settingInstanceTemplateReference":null,"simpleSettingValue":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationStringSettingValue","settingValueTemplateReference":null,"value":"thing2"}},{"@odata.type":"#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance","settingDefinitionId":"device_vendor_msft_policy_config_ppt16v2~policy~l_microsoftofficepowerpointmachine~l_convertersmachineppt_l_externalconverterasdefaultforfileextensionppt_l_listofexternalconvertersppt_value","settingInstanceTemplateReference":null,"simpleSettingValue":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationStringSettingValue","settingValueTemplateReference":null,"value":"value2"}}],"settingValueTemplateReference":null}],"settingDefinitionId":"device_vendor_msft_policy_config_ppt16v2~policy~l_microsoftofficepowerpointmachine~l_convertersmachineppt_l_externalconverterasdefaultforfileextensionppt_l_listofexternalconvertersppt","settingInstanceTemplateReference":null}],"settingValueTemplateReference":null,"value":"device_vendor_msft_policy_config_ppt16v2~policy~l_microsoftofficepowerpointmachine~l_convertersmachineppt_l_externalconverterasdefaultforfileextensionppt_1"},"settingDefinitionId":"device_vendor_msft_policy_config_ppt16v2~policy~l_microsoftofficepowerpointmachine~l_convertersmachineppt_l_externalconverterasdefaultforfileextensionppt","settingInstanceTemplateReference":null}}]}`, + expected: `{"settings":[{"id":"0","settingInstance":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance","choiceSettingValue":{"children":[{"@odata.type":"#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance","groupSettingCollectionValue":[{"children":[{"@odata.type":"#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance","settingDefinitionId":"device_vendor_msft_policy_config_ppt16v2~policy~l_microsoftofficepowerpointmachine~l_convertersmachineppt_l_externalconverterasdefaultforfileextensionppt_l_listofexternalconvertersppt_key","settingInstanceTemplateReference":null,"simpleSettingValue":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationStringSettingValue","settingValueTemplateReference":null,"value":"thing"}},{"@odata.type":"#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance","settingDefinitionId":"device_vendor_msft_policy_config_ppt16v2~policy~l_microsoftofficepowerpointmachine~l_convertersmachineppt_l_externalconverterasdefaultforfileextensionppt_l_listofexternalconvertersppt_value","settingInstanceTemplateReference":null,"simpleSettingValue":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationStringSettingValue","settingValueTemplateReference":null,"value":"value1"}}],"settingValueTemplateReference":null},{"children":[{"@odata.type":"#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance","settingDefinitionId":"device_vendor_msft_policy_config_ppt16v2~policy~l_microsoftofficepowerpointmachine~l_convertersmachineppt_l_externalconverterasdefaultforfileextensionppt_l_listofexternalconvertersppt_key","settingInstanceTemplateReference":null,"simpleSettingValue":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationStringSettingValue","settingValueTemplateReference":null,"value":"thing2"}},{"@odata.type":"#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance","settingDefinitionId":"device_vendor_msft_policy_config_ppt16v2~policy~l_microsoftofficepowerpointmachine~l_convertersmachineppt_l_externalconverterasdefaultforfileextensionppt_l_listofexternalconvertersppt_value","settingInstanceTemplateReference":null,"simpleSettingValue":{"@odata.type":"#microsoft.graph.deviceManagementConfigurationStringSettingValue","settingValueTemplateReference":null,"value":"value2"}}],"settingValueTemplateReference":null}],"settingDefinitionId":"device_vendor_msft_policy_config_ppt16v2~policy~l_microsoftofficepowerpointmachine~l_convertersmachineppt_l_externalconverterasdefaultforfileextensionppt_l_listofexternalconvertersppt","settingInstanceTemplateReference":null}],"settingValueTemplateReference":null,"value":"device_vendor_msft_policy_config_ppt16v2~policy~l_microsoftofficepowerpointmachine~l_convertersmachineppt_l_externalconverterasdefaultforfileextensionppt_1"},"settingDefinitionId":"device_vendor_msft_policy_config_ppt16v2~policy~l_microsoftofficepowerpointmachine~l_convertersmachineppt_l_externalconverterasdefaultforfileextensionppt","settingInstanceTemplateReference":null}}]}`, wantErr: false, }, } diff --git a/internal/resources/common/shared_models/graph_beta/device_and_app_management/settings_catalog_base.go b/internal/resources/common/shared_models/graph_beta/device_and_app_management/settings_catalog_base.go index 0009aa79..e6f196d2 100644 --- a/internal/resources/common/shared_models/graph_beta/device_and_app_management/settings_catalog_base.go +++ b/internal/resources/common/shared_models/graph_beta/device_and_app_management/settings_catalog_base.go @@ -8,18 +8,18 @@ import ( // SettingsCatalogProfileResourceModel holds the configuration for a Settings Catalog profile. // Reference: https://learn.microsoft.com/en-us/graph/api/resources/intune-deviceconfigv2-devicemanagementconfigurationpolicy?view=graph-rest-beta type SettingsCatalogProfileResourceModel struct { - ID types.String `tfsdk:"id"` - Name types.String `tfsdk:"name"` - Description types.String `tfsdk:"description"` - Platforms types.String `tfsdk:"platforms"` - Technologies []types.String `tfsdk:"technologies"` - ConfigurationPolicyTemplateType types.String `tfsdk:"configuration_policy_template_type"` - RoleScopeTagIds types.List `tfsdk:"role_scope_tag_ids"` - SettingsCount types.Int64 `tfsdk:"settings_count"` - IsAssigned types.Bool `tfsdk:"is_assigned"` - LastModifiedDateTime types.String `tfsdk:"last_modified_date_time"` - CreatedDateTime types.String `tfsdk:"created_date_time"` - Settings types.String `tfsdk:"settings"` - Assignments *SettingsCatalogSettingsAssignmentResourceModel `tfsdk:"assignments"` - Timeouts timeouts.Value `tfsdk:"timeouts"` + ID types.String `tfsdk:"id"` + Name types.String `tfsdk:"name"` + Description types.String `tfsdk:"description"` + Platforms types.String `tfsdk:"platforms"` + Technologies types.List `tfsdk:"technologies"` + SettingsCatalogTemplateType types.String `tfsdk:"settings_catalog_template_type"` + RoleScopeTagIds types.List `tfsdk:"role_scope_tag_ids"` + SettingsCount types.Int64 `tfsdk:"settings_count"` + IsAssigned types.Bool `tfsdk:"is_assigned"` + LastModifiedDateTime types.String `tfsdk:"last_modified_date_time"` + CreatedDateTime types.String `tfsdk:"created_date_time"` + Settings types.String `tfsdk:"settings"` + Assignments *SettingsCatalogSettingsAssignmentResourceModel `tfsdk:"assignments"` + Timeouts timeouts.Value `tfsdk:"timeouts"` } diff --git a/internal/resources/common/shared_models/graph_beta/device_and_app_management/settings_catalog_reference.go b/internal/resources/common/shared_models/graph_beta/device_and_app_management/settings_catalog_reference.go index da1d1d5c..9de4a46f 100644 --- a/internal/resources/common/shared_models/graph_beta/device_and_app_management/settings_catalog_reference.go +++ b/internal/resources/common/shared_models/graph_beta/device_and_app_management/settings_catalog_reference.go @@ -319,5 +319,5 @@ var DeviceConfigurationPolicyV2GraphServiceModelReference struct { Value interface{} `json:"value"` } `json:"simpleSettingValue,omitempty"` } `json:"settingInstance"` - } `json:"settingsDetails"` + } `json:"settings"` } diff --git a/internal/resources/common/shared_models/graph_beta/device_and_app_management/settings_catalog_settings.go b/internal/resources/common/shared_models/graph_beta/device_and_app_management/settings_catalog_settings.go index 2de0a8eb..a2962c7e 100644 --- a/internal/resources/common/shared_models/graph_beta/device_and_app_management/settings_catalog_settings.go +++ b/internal/resources/common/shared_models/graph_beta/device_and_app_management/settings_catalog_settings.go @@ -2,7 +2,6 @@ package sharedmodels // DeviceConfigV2GraphServiceResourceModel is the root configuration model type DeviceConfigV2GraphServiceResourceModel struct { - //SettingsDetails []SettingDetail `json:"settingsDetails"` Settings []Setting `json:"settings"` } diff --git a/internal/resources/common/validators/graph_beta/device_and_app_management/configuration_policy_settings.go b/internal/resources/common/validators/graph_beta/device_and_app_management/configuration_policy_settings.go index 5e8152cd..62b3138f 100644 --- a/internal/resources/common/validators/graph_beta/device_and_app_management/configuration_policy_settings.go +++ b/internal/resources/common/validators/graph_beta/device_and_app_management/configuration_policy_settings.go @@ -140,7 +140,7 @@ func validateSettingsCatalogIDSequences(path path.Path, data interface{}, resp * return } - settingsDetails, ok := dataMap["settingsDetails"].([]interface{}) + settingsDetails, ok := dataMap["settings"].([]interface{}) if !ok || len(settingsDetails) == 0 { return } @@ -231,7 +231,7 @@ func validateSettingsHierarchy(path path.Path, data interface{}, resp *validator return } - settingsDetails, ok := dataMap["settingsDetails"].([]interface{}) + settingsDetails, ok := dataMap["settings"].([]interface{}) if !ok || len(settingsDetails) == 0 { return } diff --git a/internal/resources/common/validators/graph_beta/device_and_app_management/configuration_policy_settings_test.go b/internal/resources/common/validators/graph_beta/device_and_app_management/configuration_policy_settings_test.go index 2ed01f99..026268e9 100644 --- a/internal/resources/common/validators/graph_beta/device_and_app_management/configuration_policy_settings_test.go +++ b/internal/resources/common/validators/graph_beta/device_and_app_management/configuration_policy_settings_test.go @@ -17,7 +17,7 @@ func Test_settingsCatalogValidator(t *testing.T) { { name: "valid_hierarchy", value: types.StringValue(`{ - "settingsDetails": [{ + "settings": [{ "id": "0", "settingInstance": { "@odata.type": "#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance", @@ -38,7 +38,7 @@ func Test_settingsCatalogValidator(t *testing.T) { { name: "invalid_hierarchy_extra_field", value: types.StringValue(`{ - "settingsDetails": [{ + "settings": [{ "@odata.type": "#microsoft.graph.deviceManagementConfigurationSetting", "id": "0", "settingInstance": {} @@ -49,7 +49,7 @@ func Test_settingsCatalogValidator(t *testing.T) { { name: "invalid_hierarchy_extra_field", value: types.StringValue(`{ - "settingsDetails": [{ + "settings": [{ "@odata.type": "#microsoft.graph.deviceManagementConfigurationSetting", "id": "0", "settingInstance": {} @@ -60,7 +60,7 @@ func Test_settingsCatalogValidator(t *testing.T) { { name: "valid_secret_setting", value: types.StringValue(`{ - "settingsDetails": [{ + "settings": [{ "id": "0", "settingInstance": { "@odata.type": "#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance", @@ -78,7 +78,7 @@ func Test_settingsCatalogValidator(t *testing.T) { { name: "invalid_secret_setting_state", value: types.StringValue(`{ - "settingsDetails": [{ + "settings": [{ "id": "0", "settingInstance": { "settingDefinitionId": "com.apple.loginwindow_autologinpassword", @@ -96,7 +96,7 @@ func Test_settingsCatalogValidator(t *testing.T) { { name: "invalid_id_sequence", value: types.StringValue(`{ - "settingsDetails": [{ + "settings": [{ "id": "0", "settingInstance": {} }, @@ -110,7 +110,7 @@ func Test_settingsCatalogValidator(t *testing.T) { { name: "invalid_id_format", value: types.StringValue(`{ - "settingsDetails": [{ + "settings": [{ "id": "abc", "settingInstance": {} }] @@ -120,7 +120,7 @@ func Test_settingsCatalogValidator(t *testing.T) { { name: "missing_id", value: types.StringValue(`{ - "settingsDetails": [{ + "settings": [{ "settingInstance": {} }] }`), diff --git a/internal/resources/common/validators/set.go b/internal/resources/common/validators/set.go new file mode 100644 index 00000000..c71aa620 --- /dev/null +++ b/internal/resources/common/validators/set.go @@ -0,0 +1,68 @@ +package validators + +import ( + "context" + "fmt" + + "github.com/hashicorp/terraform-plugin-framework/schema/validator" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +// stringSetValidator validates that a string set only contains allowed values. +type stringSetValidator struct { + allowedValues []string +} + +// Description describes the validation in plain text formatting. +func (v stringSetValidator) Description(_ context.Context) string { + return fmt.Sprintf("value must be one of: %v", v.allowedValues) +} + +// MarkdownDescription describes the validation in Markdown formatting. +func (v stringSetValidator) MarkdownDescription(ctx context.Context) string { + return v.Description(ctx) +} + +// ValidateSet performs the validation. +func (v stringSetValidator) ValidateSet(ctx context.Context, req validator.SetRequest, resp *validator.SetResponse) { + if req.ConfigValue.IsNull() || req.ConfigValue.IsUnknown() { + return + } + + setValues := make(map[string]struct{}) + for _, allowed := range v.allowedValues { + setValues[allowed] = struct{}{} + } + + elements := req.ConfigValue.Elements() + for _, element := range elements { + str, ok := element.(types.String) + if !ok { + resp.Diagnostics.AddError( + "Invalid Set Element", + "Set element is not a string type", + ) + return + } + + if str.IsNull() || str.IsUnknown() { + continue + } + + if _, ok := setValues[str.ValueString()]; !ok { + resp.Diagnostics.AddError( + "Invalid Set Element Value", + fmt.Sprintf("Set element value must be one of: %v", v.allowedValues), + ) + return + } + } +} + +// StringSetAllowedValues returns a Set validator which ensures that any configured +// string set value matches one of the allowed values exactly. +func StringSetAllowedValues(allowedValues ...string) validator.Set { + return &stringSetValidator{ + allowedValues: allowedValues, + } +} diff --git a/internal/resources/common/validators/set_test.go b/internal/resources/common/validators/set_test.go new file mode 100644 index 00000000..1708f90e --- /dev/null +++ b/internal/resources/common/validators/set_test.go @@ -0,0 +1,151 @@ +package validators + +import ( + "context" + "testing" + + "github.com/hashicorp/terraform-plugin-framework/attr" + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/stretchr/testify/assert" +) + +func TestStringSetValidator(t *testing.T) { + allowedValues := []string{ + "none", "mdm", "windows10XManagement", "configManager", + "intuneManagementExtension", "thirdParty", "documentGateway", + "appleRemoteManagement", "microsoftSense", "exchangeOnline", + "mobileApplicationManagement", "linuxMdm", "enrollment", + "endpointPrivilegeManagement", "unknownFutureValue", + "windowsOsRecovery", "android", + } + + testCases := []struct { + name string + values []string + expectError bool + errorContains string + }{ + { + name: "valid_single_value", + values: []string{"mdm"}, + expectError: false, + errorContains: "", + }, + { + name: "valid_multiple_values", + values: []string{"mdm", "microsoftSense", "configManager"}, + expectError: false, + errorContains: "", + }, + { + name: "invalid_value", + values: []string{"mdm", "invalid_value"}, + expectError: true, + errorContains: "Set element value must be one of:", + }, + { + name: "empty_set", + values: []string{}, + expectError: false, + errorContains: "", + }, + { + name: "duplicate_values", + values: []string{"mdm", "mdm", "microsoftSense"}, + expectError: false, + errorContains: "", + }, + { + name: "all_valid_values", + values: allowedValues, + expectError: false, + errorContains: "", + }, + } + + ctx := context.Background() + val := StringSetAllowedValues(allowedValues...) + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + // Convert string values to types.String + var elements []attr.Value + for _, v := range tc.values { + elements = append(elements, types.StringValue(v)) + } + + // Create set value + set, diags := types.SetValue(types.StringType, elements) + assert.False(t, diags.HasError(), "unexpected error creating set") + + // Create request and response + request := validator.SetRequest{ + ConfigValue: set, + Path: path.Root("test"), + PathExpression: path.MatchRoot("test"), + } + response := &validator.SetResponse{} + + // Validate + val.ValidateSet(ctx, request, response) + + if tc.expectError { + assert.True(t, response.Diagnostics.HasError(), "expected validation error") + assert.Contains(t, response.Diagnostics.Errors()[0].Detail(), tc.errorContains) + } else { + assert.False(t, response.Diagnostics.HasError(), "unexpected validation error") + } + }) + } +} + +func TestStringSetValidator_NullAndUnknown(t *testing.T) { + allowedValues := []string{"mdm", "microsoftSense"} + ctx := context.Background() + val := StringSetAllowedValues(allowedValues...) + + t.Run("null_value", func(t *testing.T) { + request := validator.SetRequest{ + ConfigValue: types.SetNull(types.StringType), + Path: path.Root("test"), + PathExpression: path.MatchRoot("test"), + } + response := &validator.SetResponse{} + + val.ValidateSet(ctx, request, response) + assert.False(t, response.Diagnostics.HasError(), "unexpected error for null value") + }) + + t.Run("unknown_value", func(t *testing.T) { + request := validator.SetRequest{ + ConfigValue: types.SetUnknown(types.StringType), + Path: path.Root("test"), + PathExpression: path.MatchRoot("test"), + } + response := &validator.SetResponse{} + + val.ValidateSet(ctx, request, response) + assert.False(t, response.Diagnostics.HasError(), "unexpected error for unknown value") + }) +} + +func TestStringSetValidator_Description(t *testing.T) { + allowedValues := []string{"mdm", "microsoftSense"} + val := StringSetAllowedValues(allowedValues...) + ctx := context.Background() + + description := val.(describer).Description(ctx) + assert.Contains(t, description, "mdm") + assert.Contains(t, description, "microsoftSense") + + markdownDescription := val.(describer).MarkdownDescription(ctx) + assert.Equal(t, description, markdownDescription) +} + +// Helper interface for testing Description methods +type describer interface { + Description(context.Context) string + MarkdownDescription(context.Context) string +} diff --git a/internal/resources/device_and_app_management/graph_beta/device_management_template/resource_docs/map.md b/internal/resources/device_and_app_management/graph_beta/device_management_template/resource_docs/map.md deleted file mode 100644 index b9eb6318..00000000 --- a/internal/resources/device_and_app_management/graph_beta/device_management_template/resource_docs/map.md +++ /dev/null @@ -1,97 +0,0 @@ -# Device Management Configuration Setting (Settings Catalog) Map - -This map represents the current supported odata hierarachy supported within this terraform resource. -It will updated as new requirements are identified. - -switch detail.SettingInstance.ODataType: -├── case "#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance" -│ └── choiceSettingValue.children[] switch ODataType: -│ ├── case "#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance" -│ │ └── simpleSettingValue switch ODataType: -│ │ ├── case "#microsoft.graph.deviceManagementConfigurationStringSettingValue" -│ │ └── case "#microsoft.graph.deviceManagementConfigurationIntegerSettingValue" -│ ├── case "#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance" -│ │ └── choiceSettingValue -│ │ └── children[] switch ODataType: -│ │ ├── case "#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance" -│ │ └── case "#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance" -│ ├── case "#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance" -│ │ └── groupSettingCollectionValue[] -│ │ └── children if ODataType == "#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance": -│ │ └── simpleSettingValue switch ODataType: -│ │ ├── case "#microsoft.graph.deviceManagementConfigurationStringSettingValue" -│ │ └── case "#microsoft.graph.deviceManagementConfigurationIntegerSettingValue" -│ └── case "#microsoft.graph.deviceManagementConfigurationSimpleSettingCollectionInstance" -│ └── simpleSettingCollectionValue[] -│ └── (@ODataType: "#microsoft.graph.deviceManagementConfigurationStringSettingValue") -│ -├── case "#microsoft.graph.deviceManagementConfigurationSimpleSettingCollectionInstance" -│ └── simpleSettingCollectionValue[] -│ └── (@ODataType: "#microsoft.graph.deviceManagementConfigurationStringSettingValue") -│ -├── case "#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance" -│ └── simpleSettingValue switch ODataType: -│ ├── case "#microsoft.graph.deviceManagementConfigurationStringSettingValue" -│ └── case "#microsoft.graph.deviceManagementConfigurationIntegerSettingValue" -│ -├── case "#microsoft.graph.deviceManagementConfigurationChoiceSettingCollectionInstance" -│ └── choiceSettingCollectionValue[] -│ └── children[].simpleSettingValue handle types: -│ ├── string -> StringSettingValue -│ └── float64 -> IntegerSettingValue -│ -└── case "#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance" - └── groupSettingCollectionValue[] - └── children[] switch ODataType: - ├── case "#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance" - │ └── groupSettingCollectionValue[] - │ └── children[] switch ODataType: - │ ├── case "#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance" - │ │ └── groupSettingCollectionValue[] - │ │ └── children[] switch ODataType: - │ │ ├── case "#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance" - │ │ │ └── choiceSettingValue - │ │ │ └── children[] switch ODataType: - │ │ │ └── case "#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance" - │ │ │ └── simpleSettingValue switch ODataType: - │ │ │ ├── case "#microsoft.graph.deviceManagementConfigurationStringSettingValue" - │ │ │ └── case "#microsoft.graph.deviceManagementConfigurationIntegerSettingValue" - │ │ ├── case "#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance" - │ │ │ └── simpleSettingValue switch ODataType: - │ │ │ ├── case "#microsoft.graph.deviceManagementConfigurationStringSettingValue" - │ │ │ ├── case "#microsoft.graph.deviceManagementConfigurationIntegerSettingValue" - │ │ │ └── case "#microsoft.graph.deviceManagementConfigurationSecretSettingValue" - │ │ └── case "#microsoft.graph.deviceManagementConfigurationSimpleSettingCollectionInstance" - │ │ └── simpleSettingCollectionValue[] // String values only - │ ├── case "#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance" - │ │ └── simpleSettingValue switch ODataType: - │ │ ├── case "#microsoft.graph.deviceManagementConfigurationStringSettingValue" - │ │ ├── case "#microsoft.graph.deviceManagementConfigurationIntegerSettingValue" - │ │ └── case "#microsoft.graph.deviceManagementConfigurationSecretSettingValue" - │ ├── case "#microsoft.graph.deviceManagementConfigurationSimpleSettingCollectionInstance" - │ │ └── simpleSettingCollectionValue[] // String values only - │ └── case "#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance" - │ └── choiceSettingValue - │ └── children[] switch ODataType: - │ └── case "#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance" - │ └── simpleSettingValue switch ODataType: - │ ├── case "#microsoft.graph.deviceManagementConfigurationStringSettingValue" - │ ├── case "#microsoft.graph.deviceManagementConfigurationIntegerSettingValue" - │ └── case "#microsoft.graph.deviceManagementConfigurationSecretSettingValue" - ├── case "#microsoft.graph.deviceManagementConfigurationSimpleSettingCollectionInstance" - │ └── simpleSettingCollectionValue[] // String values only - ├── case "#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance" - │ └── simpleSettingValue switch ODataType: - │ ├── case "#microsoft.graph.deviceManagementConfigurationStringSettingValue" - │ ├── case "#microsoft.graph.deviceManagementConfigurationIntegerSettingValue" - │ └── case "#microsoft.graph.deviceManagementConfigurationSecretSettingValue" - └── case "#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance" - └── choiceSettingValue - └── children[] switch ODataType: - ├── case "#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance" - │ └── choiceSettingValue - │ └── children[] // Empty array - └── case "#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance" - └── simpleSettingValue switch ODataType: - ├── case "#microsoft.graph.deviceManagementConfigurationStringSettingValue" - └── case "#microsoft.graph.deviceManagementConfigurationIntegerSettingValue" diff --git a/internal/resources/device_and_app_management/graph_beta/device_management_template/validate_settings_catalog_settings.go b/internal/resources/device_and_app_management/graph_beta/device_management_template/validate_settings_catalog_settings.go deleted file mode 100644 index 1b67eeae..00000000 --- a/internal/resources/device_and_app_management/graph_beta/device_management_template/validate_settings_catalog_settings.go +++ /dev/null @@ -1,201 +0,0 @@ -package graphBetaDeviceManagementTemplate - -import ( - "context" - "encoding/json" - "fmt" - "strconv" - - "github.com/hashicorp/terraform-plugin-framework/path" - "github.com/hashicorp/terraform-plugin-framework/schema/validator" -) - -// settingsCatalogValidator validates settings catalog json structure -type settingsCatalogValidator struct{} - -// SettingsCatalogValidator returns a validator which ensures settings catalog json is valid -func SettingsCatalogValidator() validator.String { - return &settingsCatalogValidator{} -} - -// Description describes the validation in plain text formatting. -func (v settingsCatalogValidator) Description(_ context.Context) string { - return "validates settings catalog configuration" -} - -// MarkdownDescription describes the validation in Markdown formatting. -func (v settingsCatalogValidator) MarkdownDescription(ctx context.Context) string { - return v.Description(ctx) -} - -// Validate performs the validation. -func (v settingsCatalogValidator) ValidateString(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) { - if req.ConfigValue.IsNull() || req.ConfigValue.IsUnknown() { - return - } - - var jsonData interface{} - if err := json.Unmarshal([]byte(req.ConfigValue.ValueString()), &jsonData); err != nil { - resp.Diagnostics.AddAttributeError( - req.Path, - "Invalid Settings Catalog JSON", - fmt.Sprintf("Error parsing settings catalog JSON: %s", err), - ) - return - } - - // Validate all secret settings in the JSON structure - validateSecretSettings(req.Path, jsonData, resp) - - // Validate settings catalog ID sequence and initial ID value is 0 - validateSettingsCatalogIDSequences(req.Path, jsonData, resp) -} - -// validateSecretSettings recursively searches through the JSON structure for secret settings -func validateSecretSettings(path path.Path, data interface{}, resp *validator.StringResponse) { - switch v := data.(type) { - case map[string]interface{}: - if isSecretSetting(v) { - validateSecretSettingState(path, v, resp) - } - for _, value := range v { - validateSecretSettings(path, value, resp) - } - case []interface{}: - for _, elem := range v { - validateSecretSettings(path, elem, resp) - } - } -} - -// isSecretSetting checks if the current map represents a secret setting -func isSecretSetting(m map[string]interface{}) bool { - odataType, ok := m["@odata.type"].(string) - return ok && odataType == "#microsoft.graph.deviceManagementConfigurationSecretSettingValue" -} - -// validateSecretSettingState checks the valueState of a secret setting -func validateSecretSettingState(path path.Path, secretSetting map[string]interface{}, resp *validator.StringResponse) { - const ( - expectedState = "notEncrypted" - invalidState = "encryptedValueToken" - ) - - valueState, ok := secretSetting["valueState"].(string) - if !ok { - return // valueState is not present or not a string - } - - if valueState == invalidState { - // Get the settingDefinitionId if available (walking up the structure) - settingId := findSettingDefinitionId(secretSetting) - - errorMsg := fmt.Sprintf("Secret Setting Value state must be '%s' when setting a new secret value, got '%s'", - expectedState, invalidState) - if settingId != "" { - errorMsg = fmt.Sprintf("Secret Setting Value (settingDefinitionId: %s) state must be '%s' when setting a new secret value, got '%s'", - settingId, expectedState, invalidState) - } - - resp.Diagnostics.AddAttributeError( - path, - "Invalid Secret Setting Value State", - errorMsg, - ) - } -} - -// findSettingDefinitionId attempts to find the settingDefinitionId associated with a secret setting -func findSettingDefinitionId(m map[string]interface{}) string { - - if id, ok := m["settingDefinitionId"].(string); ok { - return id - } - - if parent, ok := m["parent"].(map[string]interface{}); ok { - if id, ok := parent["settingDefinitionId"].(string); ok { - return id - } - } - - return "" -} - -// validateSettingsCatalogIDSequences validates that settings IDs start at 0 and increment sequentially -func validateSettingsCatalogIDSequences(path path.Path, data interface{}, resp *validator.StringResponse) { - - dataMap, ok := data.(map[string]interface{}) - if !ok { - return - } - - settingsDetails, ok := dataMap["settingsDetails"].([]interface{}) - if !ok || len(settingsDetails) == 0 { - return - } - - if firstSetting, ok := settingsDetails[0].(map[string]interface{}); ok { - if id, ok := firstSetting["id"].(string); ok { - if id != "0" { - resp.Diagnostics.AddAttributeError( - path, - "Invalid Initial Settings Catalog Settings ID", - fmt.Sprintf("Got '%s', expected '0'. Settings catalog setting instances must start from 0", id), - ) - return - } - } - } - - // Validate sequential ordering - for i := 1; i < len(settingsDetails); i++ { - setting, ok := settingsDetails[i].(map[string]interface{}) - if !ok { - continue - } - - currentID, ok := setting["id"].(string) - if !ok { - continue - } - - prevSetting, ok := settingsDetails[i-1].(map[string]interface{}) - if !ok { - continue - } - - previousID, ok := prevSetting["id"].(string) - if !ok { - continue - } - - curr, err := strconv.Atoi(currentID) - if err != nil { - resp.Diagnostics.AddAttributeError( - path, - "Invalid Settings ID Format", - fmt.Sprintf("Settings ID must be a number: %s", currentID), - ) - return - } - - prev, err := strconv.Atoi(previousID) - if err != nil { - resp.Diagnostics.AddAttributeError( - path, - "Invalid Settings ID Format", - fmt.Sprintf("Settings ID must be a number: %s", previousID), - ) - return - } - - if curr != prev+1 { - resp.Diagnostics.AddAttributeError( - path, - "Non-sequential Settings ID", - fmt.Sprintf("Settings IDs must increment by 1. Found ID %d after ID %d", curr, prev), - ) - return - } - } -} diff --git a/internal/resources/device_and_app_management/graph_beta/endpoint_privilege_management/construct_resource.go b/internal/resources/device_and_app_management/graph_beta/endpoint_privilege_management/construct_resource.go index 9bfb2a86..0edd3e05 100644 --- a/internal/resources/device_and_app_management/graph_beta/endpoint_privilege_management/construct_resource.go +++ b/internal/resources/device_and_app_management/graph_beta/endpoint_privilege_management/construct_resource.go @@ -38,9 +38,9 @@ func constructResource(ctx context.Context, data *sharedmodels.SettingsCatalogPr settings := sharedConstructor.ConstructSettingsCatalogSettings(ctx, data.Settings) requestBody.SetSettings(settings) - // Set the templateReference based on ConfigurationPolicyTemplateType + // Set the templateReference based on SettingsCatalogTemplateType templateReference := graphmodels.NewDeviceManagementConfigurationPolicyTemplateReference() - switch data.ConfigurationPolicyTemplateType.ValueString() { + switch data.SettingsCatalogTemplateType.ValueString() { case "elevation_settings_policy": templateId := "e7dcaba4-959b-46ed-88f0-16ba39b14fd8_1" // Template ID for Elevation Settings Policy templateReference.SetTemplateId(&templateId) @@ -48,7 +48,7 @@ func constructResource(ctx context.Context, data *sharedmodels.SettingsCatalogPr templateId := "cff02aad-51b1-498d-83ad-81161a393f56_1" // Template ID for Elevation Rules Policy templateReference.SetTemplateId(&templateId) default: - return nil, fmt.Errorf("invalid configuration_policy_template_type: %s", data.ConfigurationPolicyTemplateType.ValueString()) + return nil, fmt.Errorf("invalid settings_catalog_template_type: %s", data.SettingsCatalogTemplateType.ValueString()) } requestBody.SetTemplateReference(templateReference) diff --git a/internal/resources/device_and_app_management/graph_beta/endpoint_privilege_management/resource.go b/internal/resources/device_and_app_management/graph_beta/endpoint_privilege_management/resource.go index 4469b55d..50b4b401 100644 --- a/internal/resources/device_and_app_management/graph_beta/endpoint_privilege_management/resource.go +++ b/internal/resources/device_and_app_management/graph_beta/endpoint_privilege_management/resource.go @@ -101,7 +101,7 @@ func (r *EndpointPrivilegeManagementResource) Schema(ctx context.Context, req re PlanModifiers: []planmodifier.String{planmodifiers.DefaultValueString("")}, MarkdownDescription: "Endpoint Privilege Management Policy description", }, - "configuration_policy_template_type": schema.StringAttribute{ + "settings_catalog_template_type": schema.StringAttribute{ Required: true, MarkdownDescription: "Defines which Endpoint Privilege Management Policy type with settings catalog setting will be deployed. " + "Options available are `elevation_settings_policy` or `elevation_rules_policy`.", @@ -116,18 +116,19 @@ func (r *EndpointPrivilegeManagementResource) Schema(ctx context.Context, req re Required: true, MarkdownDescription: "Endpoint Privilege Management Policy with settings catalog settings defined as a valid JSON string. Provide JSON-encoded settings structure. " + "This can either be extracted from an existing policy using the Intune gui export to JSON, via a script such as" + - " [this PowerShell script](https://github.com/deploymenttheory/terraform-provider-microsoft365/blob/main/scripts/GetSettingsCatalogConfigurationById.ps1) " + + " [this PowerShell script](https://github.com/deploymenttheory/terraform-provider-microsoft365/blob/main/scripts/ExportSettingsCatalogConfigurationById.ps1) " + "or created from scratch. The JSON structure should match the graph schema of the settings catalog. Please look at the " + "terraform documentation for the settings catalog for examples and how to correctly format the HCL.\n\n" + "A correctly formatted field in the HCL should begin and end like this:\n" + "```hcl\n" + "settings = jsonencode({\n" + - " \"settingsDetails\": [\n" + + " \"settings\": [\n" + " {\n" + - " # ... settings configuration ...\n" + - " }\n" + - " ]\n" + - "})\n" + + " \"id\": \"0\",\n" + + " \"settingInstance\": {\n" + + " }\n" + + " }\n" + + " },\n" + "```\n\n" + "Note: When setting secret values (identified by `@odata.type: \"#microsoft.graph.deviceManagementConfigurationSecretSettingValue\"`), " + "ensure the `valueState` is set to `\"notEncrypted\"`. The value `\"encryptedValueToken\"` is reserved for server responses and " + diff --git a/internal/resources/device_and_app_management/graph_beta/endpoint_privilege_management/state_base_resource.go b/internal/resources/device_and_app_management/graph_beta/endpoint_privilege_management/state_base_resource.go index adc76574..3c5a82ec 100644 --- a/internal/resources/device_and_app_management/graph_beta/endpoint_privilege_management/state_base_resource.go +++ b/internal/resources/device_and_app_management/graph_beta/endpoint_privilege_management/state_base_resource.go @@ -44,7 +44,7 @@ func MapRemoteResourceStateToTerraform(ctx context.Context, data *sharedmodels.S data.Platforms = state.EnumPtrToTypeString(platforms) } if technologies := remoteResource.GetTechnologies(); technologies != nil { - data.Technologies = EnumBitmaskToTypeStringSlice(*technologies) + data.Technologies = DeviceManagementConfigurationTechnologiesEnumBitmaskToTypeList(*technologies) } tflog.Debug(ctx, "Finished mapping remote resource state to Terraform state", map[string]interface{}{ @@ -52,8 +52,8 @@ func MapRemoteResourceStateToTerraform(ctx context.Context, data *sharedmodels.S }) } -func EnumBitmaskToTypeStringSlice(technologies graphmodels.DeviceManagementConfigurationTechnologies) []types.String { - var values []types.String +func DeviceManagementConfigurationTechnologiesEnumBitmaskToTypeList(technologies graphmodels.DeviceManagementConfigurationTechnologies) types.List { + var values []attr.Value if technologies&graphmodels.NONE_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES != 0 { values = append(values, types.StringValue("none")) @@ -95,5 +95,6 @@ func EnumBitmaskToTypeStringSlice(technologies graphmodels.DeviceManagementConfi values = append(values, types.StringValue("windowsOsRecovery")) } - return values + // Return a types.List + return types.ListValueMust(types.StringType, values) } diff --git a/internal/resources/device_and_app_management/graph_beta/settings_catalog/construct_resource.go b/internal/resources/device_and_app_management/graph_beta/settings_catalog/construct_resource.go index 1be40240..cca3b167 100644 --- a/internal/resources/device_and_app_management/graph_beta/settings_catalog/construct_resource.go +++ b/internal/resources/device_and_app_management/graph_beta/settings_catalog/construct_resource.go @@ -8,6 +8,7 @@ import ( "github.com/deploymenttheory/terraform-provider-microsoft365/internal/resources/common/constructors" sharedConstructor "github.com/deploymenttheory/terraform-provider-microsoft365/internal/resources/common/constructors/graph_beta/device_and_app_management" sharedmodels "github.com/deploymenttheory/terraform-provider-microsoft365/internal/resources/common/shared_models/graph_beta/device_and_app_management" + tfTypes "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-log/tflog" graphmodels "github.com/microsoftgraph/msgraph-beta-sdk-go/models" ) @@ -44,11 +45,20 @@ func constructResource(ctx context.Context, data *sharedmodels.SettingsCatalogPr requestBody.SetPlatforms(&platform) var technologiesStr []string - for _, tech := range data.Technologies { - technologiesStr = append(technologiesStr, tech.ValueString()) + if data.Technologies.IsNull() || data.Technologies.IsUnknown() { + technologiesStr = nil // Handle null or unknown states if necessary + } else { + technologiesList := data.Technologies.Elements() + for _, tech := range technologiesList { + technologiesStr = append(technologiesStr, tech.(tfTypes.String).ValueString()) + } } + + // Join the strings and parse the technologies using the SDK function parsedTechnologies, _ := graphmodels.ParseDeviceManagementConfigurationTechnologies(strings.Join(technologiesStr, ",")) - requestBody.SetTechnologies(parsedTechnologies.(*graphmodels.DeviceManagementConfigurationTechnologies)) + if parsedTechnologies != nil { + requestBody.SetTechnologies(parsedTechnologies.(*graphmodels.DeviceManagementConfigurationTechnologies)) + } if err := constructors.SetStringList(ctx, data.RoleScopeTagIds, requestBody.SetRoleScopeTagIds); err != nil { return nil, fmt.Errorf("failed to set role scope tags: %s", err) diff --git a/internal/resources/device_and_app_management/graph_beta/settings_catalog/resource.go b/internal/resources/device_and_app_management/graph_beta/settings_catalog/resource.go index 40e0cdb3..d2a82e1b 100644 --- a/internal/resources/device_and_app_management/graph_beta/settings_catalog/resource.go +++ b/internal/resources/device_and_app_management/graph_beta/settings_catalog/resource.go @@ -101,7 +101,7 @@ func (r *SettingsCatalogResource) Schema(ctx context.Context, req resource.Schem PlanModifiers: []planmodifier.String{planmodifiers.DefaultValueString("")}, MarkdownDescription: "Optional description for the settings catalog policy.", }, - "configuration_policy_template_type": schema.StringAttribute{ + "settings_catalog_template_type": schema.StringAttribute{ Computed: true, MarkdownDescription: "Defines which settings catalog setting template will be deployed. " + "Unused by non settings catalog template items, but required in schema to satisify tfsdk model.", @@ -121,10 +121,11 @@ func (r *SettingsCatalogResource) Schema(ctx context.Context, req resource.Schem "settings = jsonencode({\n" + " \"settings\": [\n" + " {\n" + - " # ... settings configuration ...\n" + - " }\n" + - " ]\n" + - "})\n" + + " \"id\": \"0\",\n" + + " \"settingInstance\": {\n" + + " }\n" + + " }\n" + + " },\n" + "```\n\n" + "Note: When setting secret values (identified by `@odata.type: \"#microsoft.graph.deviceManagementConfigurationSecretSettingValue\"`), " + "ensure the `valueState` is set to `\"notEncrypted\"`. The value `\"encryptedValueToken\"` is reserved for server responses and " + diff --git a/internal/resources/device_and_app_management/graph_beta/settings_catalog/state_base_resource.go b/internal/resources/device_and_app_management/graph_beta/settings_catalog/state_base_resource.go index fabebfd9..f6441d92 100644 --- a/internal/resources/device_and_app_management/graph_beta/settings_catalog/state_base_resource.go +++ b/internal/resources/device_and_app_management/graph_beta/settings_catalog/state_base_resource.go @@ -29,8 +29,8 @@ func MapRemoteResourceStateToTerraform(ctx context.Context, data *sharedmodels.S data.CreatedDateTime = state.TimeToString(remoteResource.GetCreatedDateTime()) data.LastModifiedDateTime = state.TimeToString(remoteResource.GetLastModifiedDateTime()) data.SettingsCount = state.Int32PtrToTypeInt64(remoteResource.GetSettingCount()) - // ConfigurationPolicyTemplates are not set by this resource type. But the field is required to satisfy schema. - data.ConfigurationPolicyTemplateType = types.StringValue("") + // SettingsCatalogTemplateType are not set by this resource type. But the field is required to satisfy schema. + data.SettingsCatalogTemplateType = types.StringValue("") var roleScopeTagIds []attr.Value for _, v := range state.SliceToTypeStringSlice(remoteResource.GetRoleScopeTagIds()) { @@ -47,7 +47,7 @@ func MapRemoteResourceStateToTerraform(ctx context.Context, data *sharedmodels.S } if technologies := remoteResource.GetTechnologies(); technologies != nil { - data.Technologies = EnumBitmaskToTypeStringSlice(*technologies) + data.Technologies = DeviceManagementConfigurationTechnologiesEnumBitmaskToTypeList(*technologies) } tflog.Debug(ctx, "Finished mapping remote resource state to Terraform state", map[string]interface{}{ @@ -55,8 +55,8 @@ func MapRemoteResourceStateToTerraform(ctx context.Context, data *sharedmodels.S }) } -func EnumBitmaskToTypeStringSlice(technologies graphmodels.DeviceManagementConfigurationTechnologies) []types.String { - var values []types.String +func DeviceManagementConfigurationTechnologiesEnumBitmaskToTypeList(technologies graphmodels.DeviceManagementConfigurationTechnologies) types.List { + var values []attr.Value if technologies&graphmodels.NONE_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES != 0 { values = append(values, types.StringValue("none")) @@ -98,5 +98,6 @@ func EnumBitmaskToTypeStringSlice(technologies graphmodels.DeviceManagementConfi values = append(values, types.StringValue("windowsOsRecovery")) } - return values + // Return a types.List + return types.ListValueMust(types.StringType, values) } diff --git a/internal/resources/device_and_app_management/graph_beta/device_management_template/construct_resource.go b/internal/resources/device_and_app_management/graph_beta/settings_catalog_template/construct_resource.go similarity index 59% rename from internal/resources/device_and_app_management/graph_beta/device_management_template/construct_resource.go rename to internal/resources/device_and_app_management/graph_beta/settings_catalog_template/construct_resource.go index 4bd04752..0f1252d4 100644 --- a/internal/resources/device_and_app_management/graph_beta/device_management_template/construct_resource.go +++ b/internal/resources/device_and_app_management/graph_beta/settings_catalog_template/construct_resource.go @@ -13,12 +13,43 @@ import ( // PolicyTemplateConfig is a struct that contains the platform, technologies, and template id for a device management policy. type PolicyTemplateConfig struct { - Platform graphmodels.DeviceManagementConfigurationPlatforms - Technologies graphmodels.DeviceManagementConfigurationTechnologies - TemplateID string + Platform graphmodels.DeviceManagementConfigurationPlatforms + Technologies graphmodels.DeviceManagementConfigurationTechnologies + TemplateID string + CreationSource string } var policyConfigMap = map[string]PolicyTemplateConfig{ + "windows_config_manager_anti_virus_microsoft_defender_antivirus": { + Platform: graphmodels.WINDOWS10_DEVICEMANAGEMENTCONFIGURATIONPLATFORMS, + Technologies: graphmodels.CONFIGMANAGER_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES, + CreationSource: "SccmAV", + }, + "windows_config_manager_anti_virus_windows_security_experience": { + Platform: graphmodels.WINDOWS10_DEVICEMANAGEMENTCONFIGURATIONPLATFORMS, + Technologies: graphmodels.CONFIGMANAGER_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES, + CreationSource: "WindowsSecurity", + }, + "linux_anti_virus_microsoft_defender_antivirus": { + Platform: graphmodels.LINUX_DEVICEMANAGEMENTCONFIGURATIONPLATFORMS, + Technologies: graphmodels.MICROSOFTSENSE_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES, + TemplateID: "4cfd164c-5e8a-4ea9-b15d-9aa71e4ffff4_1", + }, + "linux_anti_virus_microsoft_defender_antivirus_exclusions": { + Platform: graphmodels.LINUX_DEVICEMANAGEMENTCONFIGURATIONPLATFORMS, + Technologies: graphmodels.MICROSOFTSENSE_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES, + TemplateID: "8a17a1e5-3df4-4e07-9d20-3878267a79b8_1", + }, + "macOS_anti_virus_microsoft_defender_antivirus": { + Platform: graphmodels.MACOS_DEVICEMANAGEMENTCONFIGURATIONPLATFORMS, + Technologies: graphmodels.MDM_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES | graphmodels.MICROSOFTSENSE_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES, + TemplateID: "2d345ec2-c817-49e5-9156-3ed416dc972a_1", + }, + "macOS_anti_virus_microsoft_defender_antivirus_exclusions": { + Platform: graphmodels.MACOS_DEVICEMANAGEMENTCONFIGURATIONPLATFORMS, + Technologies: graphmodels.MDM_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES | graphmodels.MICROSOFTSENSE_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES, + TemplateID: "43397174-2244-4006-b5ad-421b369e90d4_1", + }, "windows_anti_virus_defender_update_controls": { Platform: graphmodels.WINDOWS10_DEVICEMANAGEMENTCONFIGURATIONPLATFORMS, Technologies: graphmodels.MDM_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES | graphmodels.MICROSOFTSENSE_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES, @@ -75,20 +106,28 @@ func constructResource(ctx context.Context, data *sharedmodels.SettingsCatalogPr // setTemplateContext sets the template specific settings for the device management template. // It sets the platform, technologies, and template id reference. func setTemplateContext(ctx context.Context, data *sharedmodels.SettingsCatalogProfileResourceModel, requestBody graphmodels.DeviceManagementConfigurationPolicyable) error { - config, exists := policyConfigMap[data.ConfigurationPolicyTemplateType.ValueString()] + config, exists := policyConfigMap[data.SettingsCatalogTemplateType.ValueString()] if !exists { - tflog.Error(ctx, "Invalid configuration policy template type", map[string]interface{}{ - "configuration_policy_template_type": data.ConfigurationPolicyTemplateType.ValueString(), + tflog.Error(ctx, "Invalid settings catalog template type", map[string]interface{}{ + "settings_catalog_template_type": data.SettingsCatalogTemplateType.ValueString(), }) - return fmt.Errorf("invalid configuration_policy_template_type: %s", data.ConfigurationPolicyTemplateType.ValueString()) + return fmt.Errorf("invalid settings_catalog_template_type: %s", data.SettingsCatalogTemplateType.ValueString()) } + // Platform and Technologies are always required requestBody.SetPlatforms(&config.Platform) requestBody.SetTechnologies(&config.Technologies) - templateReference := graphmodels.NewDeviceManagementConfigurationPolicyTemplateReference() - templateReference.SetTemplateId(&config.TemplateID) - requestBody.SetTemplateReference(templateReference) + // Only set CreationSource / TemplateReference if it exists + if config.CreationSource != "" { + requestBody.SetCreationSource(&config.CreationSource) + } + + if config.TemplateID != "" { + templateReference := graphmodels.NewDeviceManagementConfigurationPolicyTemplateReference() + templateReference.SetTemplateId(&config.TemplateID) + requestBody.SetTemplateReference(templateReference) + } return nil } diff --git a/internal/resources/device_and_app_management/graph_beta/device_management_template/crud.go b/internal/resources/device_and_app_management/graph_beta/settings_catalog_template/crud.go similarity index 100% rename from internal/resources/device_and_app_management/graph_beta/device_management_template/crud.go rename to internal/resources/device_and_app_management/graph_beta/settings_catalog_template/crud.go diff --git a/internal/resources/device_and_app_management/graph_beta/device_management_template/modify_plan.go b/internal/resources/device_and_app_management/graph_beta/settings_catalog_template/modify_plan.go similarity index 100% rename from internal/resources/device_and_app_management/graph_beta/device_management_template/modify_plan.go rename to internal/resources/device_and_app_management/graph_beta/settings_catalog_template/modify_plan.go diff --git a/internal/resources/device_and_app_management/graph_beta/device_management_template/resource.go b/internal/resources/device_and_app_management/graph_beta/settings_catalog_template/resource.go similarity index 85% rename from internal/resources/device_and_app_management/graph_beta/device_management_template/resource.go rename to internal/resources/device_and_app_management/graph_beta/settings_catalog_template/resource.go index 3d8d15e6..46040c36 100644 --- a/internal/resources/device_and_app_management/graph_beta/device_management_template/resource.go +++ b/internal/resources/device_and_app_management/graph_beta/settings_catalog_template/resource.go @@ -8,6 +8,7 @@ import ( commonschema "github.com/deploymenttheory/terraform-provider-microsoft365/internal/resources/common/schema" commonschemagraphbeta "github.com/deploymenttheory/terraform-provider-microsoft365/internal/resources/common/schema/graph_beta/device_and_app_management" customValidator "github.com/deploymenttheory/terraform-provider-microsoft365/internal/resources/common/validators" + sharedValidators "github.com/deploymenttheory/terraform-provider-microsoft365/internal/resources/common/validators/graph_beta/device_and_app_management" "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/path" @@ -21,7 +22,7 @@ import ( ) const ( - ResourceName = "graph_beta_device_and_app_management_settings_catalog" + ResourceName = "graph_beta_device_and_app_management_settings_catalog_template" CreateTimeout = 180 UpdateTimeout = 180 ReadTimeout = 180 @@ -81,26 +82,26 @@ func (r *DeviceManagementTemplateResource) ImportState(ctx context.Context, req // Function to create the full device management configuration policy schema func (r *DeviceManagementTemplateResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { resp.Schema = schema.Schema{ - Description: "Manages a Settings Catalog policy in Microsoft Intune for Windows, macOS, iOS/iPadOS and Android.", + Description: "Manages a Settings Catalog policy template in Microsoft Intune for Windows, macOS, iOS/iPadOS and Android.", Attributes: map[string]schema.Attribute{ "id": schema.StringAttribute{ Computed: true, PlanModifiers: []planmodifier.String{ planmodifiers.UseStateForUnknownString(), }, - MarkdownDescription: "The unique identifier for this policy", + MarkdownDescription: "The unique identifier for this policy template", }, "name": schema.StringAttribute{ Required: true, - MarkdownDescription: "Policy name", + MarkdownDescription: "Settings Catalog Policy template name", }, "description": schema.StringAttribute{ Optional: true, Computed: true, PlanModifiers: []planmodifier.String{planmodifiers.DefaultValueString("")}, - MarkdownDescription: "Policy description", + MarkdownDescription: "Settings Catalog Policy template description", }, - "device_management_template_type": schema.StringAttribute{ + "settings_catalog_template_type": schema.StringAttribute{ Required: true, MarkdownDescription: "Defines which device management template type with settings catalog setting that will be deployed. " + "Options available are `macOS_disk_encryption`, `macOS_firewall`, `macOS_endpoint_detection_and_response`, `macOS_anti_virus`, " + @@ -134,8 +135,8 @@ func (r *DeviceManagementTemplateResource) Schema(ctx context.Context, req resou "windows_firewall_profile_config_manager", "windows_firewall_rules_config_manager", "windows_endpoint_detection_and_response", - "windows_config_manage_anti_virus_microsoft_defender_antivirus", - "windows_config_manage_anti_virus_microsoft_defender_antivirus_exclusions", + "windows_config_manager_anti_virus_microsoft_defender_antivirus", + "windows_config_manager_anti_virus_windows_security_experience", "windows_config_manager_attack_surface_reduction", "windows_config_manager_endpoint_detection_and_response", ), @@ -143,9 +144,9 @@ func (r *DeviceManagementTemplateResource) Schema(ctx context.Context, req resou }, "settings": schema.StringAttribute{ Required: true, - MarkdownDescription: "Settings Catalog Policy settings defined as a valid JSON string. Provide JSON-encoded settings structure. " + - "This can either be extracted from an existing policy using the Intune gui export to JSON, via a script such as" + - " [this PowerShell script](https://github.com/deploymenttheory/terraform-provider-microsoft365/blob/main/scripts/GetDeviceManagementTemplateConfigurationById.ps1) " + + MarkdownDescription: "Settings Catalog Policy template settings defined as a valid JSON string. Provide JSON-encoded settings structure. " + + "This can either be extracted from an existing policy using the Intune gui `export JSON` functionality, via a script such as" + + " [this PowerShell script](https://github.com/deploymenttheory/terraform-provider-microsoft365/blob/main/scripts/ExportSettingsCatalogConfigurationById.ps1) " + "or created from scratch. The JSON structure should match the graph schema of the settings catalog. Please look at the " + "terraform documentation for the settings catalog for examples and how to correctly format the HCL.\n\n" + "A correctly formatted field in the HCL should begin and end like this:\n" + @@ -153,24 +154,24 @@ func (r *DeviceManagementTemplateResource) Schema(ctx context.Context, req resou "settings = jsonencode({\n" + " \"settings\": [\n" + " {\n" + - " # ... settings configuration ...\n" + - " }\n" + - " ]\n" + - "})\n" + + " \"id\": \"0\",\n" + + " \"settingInstance\": {\n" + + " }\n" + + " }\n" + + " },\n" + "```\n\n" + "Note: When setting secret values (identified by `@odata.type: \"#microsoft.graph.deviceManagementConfigurationSecretSettingValue\"`), " + "ensure the `valueState` is set to `\"notEncrypted\"`. The value `\"encryptedValueToken\"` is reserved for server responses and " + "should not be used when creating or updating settings.", Validators: []validator.String{ customValidator.JSONSchemaValidator(), - SettingsCatalogValidator(), + sharedValidators.SettingsCatalogValidator(), }, PlanModifiers: []planmodifier.String{ planmodifiers.NormalizeJSONPlanModifier{}, }, }, "platforms": schema.StringAttribute{ - Optional: true, Computed: true, MarkdownDescription: "Platform type for this settings catalog policy." + "Can be one of: none, android, iOS, macOS, windows10X, windows10, linux," + @@ -185,9 +186,9 @@ func (r *DeviceManagementTemplateResource) Schema(ctx context.Context, req resou PlanModifiers: []planmodifier.String{planmodifiers.DefaultValueString("none")}, }, "technologies": schema.ListAttribute{ - ElementType: types.StringType, - Optional: true, - Computed: true, + ElementType: types.StringType, + Computed: true, + MarkdownDescription: "Describes a list of technologies this settings catalog setting can be deployed with. Valid values are: none, mdm, windows10XManagement, configManager, intuneManagementExtension, thirdParty, documentGateway, appleRemoteManagement, microsoftSense, exchangeOnline, mobileApplicationManagement, linuxMdm, enrollment, endpointPrivilegeManagement, unknownFutureValue, windowsOsRecovery, and android. Defaults to ['mdm'].", Validators: []validator.List{ customValidator.StringListAllowedValues( "none", "mdm", "windows10XManagement", "configManager", @@ -198,10 +199,6 @@ func (r *DeviceManagementTemplateResource) Schema(ctx context.Context, req resou "windowsOsRecovery", "android", ), }, - PlanModifiers: []planmodifier.List{ - planmodifiers.DefaultListValue([]attr.Value{types.StringValue("mdm")}), - }, - MarkdownDescription: "Describes a list of technologies this settings catalog setting can be deployed with. Defaults to 'mdm'.", }, "role_scope_tag_ids": schema.ListAttribute{ ElementType: types.StringType, @@ -213,7 +210,6 @@ func (r *DeviceManagementTemplateResource) Schema(ctx context.Context, req resou ), }, }, - "created_date_time": schema.StringAttribute{ Computed: true, PlanModifiers: []planmodifier.String{ diff --git a/internal/resources/device_and_app_management/graph_beta/device_management_template/state_base_resource.go b/internal/resources/device_and_app_management/graph_beta/settings_catalog_template/state_base_resource.go similarity index 92% rename from internal/resources/device_and_app_management/graph_beta/device_management_template/state_base_resource.go rename to internal/resources/device_and_app_management/graph_beta/settings_catalog_template/state_base_resource.go index d1c7e422..7965cacc 100644 --- a/internal/resources/device_and_app_management/graph_beta/device_management_template/state_base_resource.go +++ b/internal/resources/device_and_app_management/graph_beta/settings_catalog_template/state_base_resource.go @@ -43,8 +43,9 @@ func MapRemoteResourceStateToTerraform(ctx context.Context, data *sharedmodels.S if platforms := remoteResource.GetPlatforms(); platforms != nil { data.Platforms = state.EnumPtrToTypeString(platforms) } + if technologies := remoteResource.GetTechnologies(); technologies != nil { - data.Technologies = EnumBitmaskToTypeStringSlice(*technologies) + data.Technologies = DeviceManagementConfigurationTechnologiesEnumBitmaskToTypeList(*technologies) } tflog.Debug(ctx, "Finished mapping remote resource state to Terraform state", map[string]interface{}{ @@ -52,8 +53,8 @@ func MapRemoteResourceStateToTerraform(ctx context.Context, data *sharedmodels.S }) } -func EnumBitmaskToTypeStringSlice(technologies graphmodels.DeviceManagementConfigurationTechnologies) []types.String { - var values []types.String +func DeviceManagementConfigurationTechnologiesEnumBitmaskToTypeList(technologies graphmodels.DeviceManagementConfigurationTechnologies) types.List { + var values []attr.Value if technologies&graphmodels.NONE_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES != 0 { values = append(values, types.StringValue("none")) @@ -95,5 +96,6 @@ func EnumBitmaskToTypeStringSlice(technologies graphmodels.DeviceManagementConfi values = append(values, types.StringValue("windowsOsRecovery")) } - return values + // Return a types.List + return types.ListValueMust(types.StringType, values) } diff --git a/templates/resources/graph_beta_device_and_app_management_settings_catalog_template.md.tmpl b/templates/resources/graph_beta_device_and_app_management_settings_catalog_template.md.tmpl new file mode 100644 index 00000000..f9f1b9fc --- /dev/null +++ b/templates/resources/graph_beta_device_and_app_management_settings_catalog_template.md.tmpl @@ -0,0 +1,23 @@ +--- +page_title: "{{.Name}} {{.Type}} - {{.ProviderName}}" +subcategory: "Intune" +description: |- +{{ .Description | plainmarkdown | trimspace | prefixlines " " }} +--- + +# {{.Name}} ({{.Type}}) + +{{ .Description | trimspace }} + +## Example Usage + +{{ tffile "examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_settings_template/resource.tf" }} + +{{ .SchemaMarkdown | trimspace }} + +## Import + +Import is supported using the following syntax: + +{{ codefile "shell" "examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_settings_template/import.sh" }} + From 6f63c8579633a0596deb4ff416ae9ae5b6e130ae Mon Sep 17 00:00:00 2001 From: ShocOne Date: Thu, 16 Jan 2025 10:48:40 +0000 Subject: [PATCH 08/14] delete: remove deprecated role scope tag resource and data source documentation --- ...evice_and_app_management_assignment_filter | 229 ------------------ ...a_device_and_app_management_role_scope_tag | 130 ---------- ...a_device_and_app_management_role_scope_tag | 167 ------------- 3 files changed, 526 deletions(-) delete mode 100644 docs/data-sources/graph_beta_device_and_app_management_assignment_filter delete mode 100644 docs/data-sources/graph_beta_device_and_app_management_role_scope_tag delete mode 100644 docs/resources/graph_beta_device_and_app_management_role_scope_tag diff --git a/docs/data-sources/graph_beta_device_and_app_management_assignment_filter b/docs/data-sources/graph_beta_device_and_app_management_assignment_filter deleted file mode 100644 index 2d742b6f..00000000 --- a/docs/data-sources/graph_beta_device_and_app_management_assignment_filter +++ /dev/null @@ -1,229 +0,0 @@ ---- -page_title: "microsoft365_graph_beta_device_and_app_management_assignment_filter Data Source - terraform-provider-microsoft365" -subcategory: "Intune: Assignment Filter" -description: |- - ---- - -# microsoft365_graph_beta_device_and_app_management_assignment_filter (Data Source) - -The Microsoft 365 Intune assignment filter data source provides information about a specific Intune assignment filter. - -## Example Usage - -```terraform -# Basic usage - looking up a single filter by display name -data "microsoft365_graph_beta_device_and_app_management_assignment_filter" "by_name" { - display_name = "Filter | Android Enterprise Device Status Is Rooted" -} - -# Look up by ID -data "microsoft365_graph_beta_device_and_app_management_assignment_filter" "windows_vdi" { - id = "00000000-0000-0000-0000-000000000001" -} - -# Example: Create new filter based on existing one (using name lookup) -resource "microsoft365_graph_beta_device_and_app_management_assignment_filter" "clone_android" { - display_name = "Clone - Android Rooted Device Filter" - description = "Cloned from: ${data.microsoft365_graph_beta_device_and_app_management_assignment_filter.by_name.description}" - - # Copy configuration from existing filter - platform = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.by_name.platform - rule = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.by_name.rule - assignment_filter_management_type = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.by_name.assignment_filter_management_type - role_scope_tags = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.by_name.role_scope_tags - - timeouts = { - create = "10s" - read = "10s" - update = "10s" - delete = "10s" - } -} - -# Output showing all available attributes -output "filter_details" { - value = { - # Basic details - id = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.by_name.id - display_name = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.by_name.display_name - description = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.by_name.description - - # Filter configuration - platform = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.by_name.platform - rule = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.by_name.rule - assignment_filter_management_type = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.by_name.assignment_filter_management_type - - # Additional metadata - created_date_time = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.by_name.created_date_time - last_modified_date_time = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.by_name.last_modified_date_time - role_scope_tags = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.by_name.role_scope_tags - } -} - - -# Example: Create new filter based on Windows VDI filter (using ID lookup) -resource "microsoft365_graph_beta_device_and_app_management_assignment_filter" "clone_windows_vdi" { - display_name = "Clone - Windows VDI Device Filter" - description = "Cloned from: ${data.microsoft365_graph_beta_device_and_app_management_assignment_filter.windows_vdi.description}" - - # Copy configuration from existing filter - platform = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.windows_vdi.platform - rule = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.windows_vdi.rule - assignment_filter_management_type = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.windows_vdi.assignment_filter_management_type - role_scope_tags = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.windows_vdi.role_scope_tags - - timeouts = { - create = "10s" - read = "10s" - update = "10s" - delete = "10s" - } -} - -# Output showing Windows VDI filter attributes -output "vdi_filter_details" { - value = { - # Basic details - id = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.windows_vdi.id - display_name = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.windows_vdi.display_name - description = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.windows_vdi.description - - # Filter configuration - platform = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.windows_vdi.platform - rule = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.windows_vdi.rule - assignment_filter_management_type = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.windows_vdi.assignment_filter_management_type - - # Additional metadata - created_date_time = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.windows_vdi.created_date_time - last_modified_date_time = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.windows_vdi.last_modified_date_time - role_scope_tags = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.windows_vdi.role_scope_tags - } -} - - -# Use Case 1: Filter Migration - Export multiple filters as JSON for documentation/migration -output "all_filters_export" { - value = { - android_filter = { - name = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.by_name.display_name - config = { - platform = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.by_name.platform - rule = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.by_name.rule - type = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.by_name.assignment_filter_management_type - } - } - vdi_filter = { - name = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.windows_vdi.display_name - config = { - platform = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.windows_vdi.platform - rule = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.windows_vdi.rule - type = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.windows_vdi.assignment_filter_management_type - } - } - } -} - -# Use Case 2: Create multiple environment-specific clones with prefix -resource "microsoft365_graph_beta_device_and_app_management_assignment_filter" "prod_clone" { - display_name = "PROD - ${data.microsoft365_graph_beta_device_and_app_management_assignment_filter.windows_vdi.display_name}" - description = "Production clone of: ${data.microsoft365_graph_beta_device_and_app_management_assignment_filter.windows_vdi.description}" - - platform = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.windows_vdi.platform - rule = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.windows_vdi.rule - assignment_filter_management_type = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.windows_vdi.assignment_filter_management_type - role_scope_tags = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.windows_vdi.role_scope_tags - - timeouts = { - create = "10s" - read = "10s" - update = "10s" - delete = "10s" - } -} - -resource "microsoft365_graph_beta_device_and_app_management_assignment_filter" "dev_clone" { - display_name = "DEV - ${data.microsoft365_graph_beta_device_and_app_management_assignment_filter.windows_vdi.display_name}" - description = "Development clone of: ${data.microsoft365_graph_beta_device_and_app_management_assignment_filter.windows_vdi.description}" - - platform = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.windows_vdi.platform - rule = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.windows_vdi.rule - assignment_filter_management_type = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.windows_vdi.assignment_filter_management_type - role_scope_tags = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.windows_vdi.role_scope_tags - - timeouts = { - create = "10s" - read = "10s" - update = "10s" - delete = "10s" - } -} - -# Use Case 3: Create a modified clone with an enhanced rule -resource "microsoft365_graph_beta_device_and_app_management_assignment_filter" "enhanced_vdi_filter" { - display_name = "Enhanced - ${data.microsoft365_graph_beta_device_and_app_management_assignment_filter.windows_vdi.display_name}" - description = "Enhanced version with additional conditions" - - platform = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.windows_vdi.platform - # Original rule with additional conditions - rule = "${data.microsoft365_graph_beta_device_and_app_management_assignment_filter.windows_vdi.rule} and (device.manufacturer -eq \"Microsoft\")" - assignment_filter_management_type = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.windows_vdi.assignment_filter_management_type - role_scope_tags = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.windows_vdi.role_scope_tags - - timeouts = { - create = "10s" - read = "10s" - update = "10s" - delete = "10s" - } -} - -# Use Case 4: Output comparing multiple filters -output "filter_comparison" { - value = { - original_vs_enhanced = { - original_rule = data.microsoft365_graph_beta_device_and_app_management_assignment_filter.windows_vdi.rule - enhanced_rule = "${data.microsoft365_graph_beta_device_and_app_management_assignment_filter.windows_vdi.rule} and (device.manufacturer -eq \"Microsoft\")" - differences = { - platform_same = ( - data.microsoft365_graph_beta_device_and_app_management_assignment_filter.windows_vdi.platform == - data.microsoft365_graph_beta_device_and_app_management_assignment_filter.by_name.platform - ) - management_type_same = ( - data.microsoft365_graph_beta_device_and_app_management_assignment_filter.windows_vdi.assignment_filter_management_type == - data.microsoft365_graph_beta_device_and_app_management_assignment_filter.by_name.assignment_filter_management_type - ) - } - } - } -} -``` - - -## Schema - -### Optional - -- `display_name` (String) The display name of the assignment filter. -- `id` (String) The unique identifier of the assignment filter. -- `timeouts` (Attributes) (see [below for nested schema](#nestedatt--timeouts)) - -### Read-Only - -- `assignment_filter_management_type` (String) Indicates filter is applied to either 'devices' or 'apps' management type. -- `created_date_time` (String) The creation time of the assignment filter. -- `description` (String) The description of the assignment filter. -- `last_modified_date_time` (String) Last modified time of the assignment filter. -- `platform` (String) The Intune device management type (platform) for the assignment filter. -- `role_scope_tags` (List of String) Indicates role scope tags assigned for the assignment filter. -- `rule` (String) Rule definition of the assignment filter. - - -### Nested Schema for `timeouts` - -Optional: - -- `create` (String) A string that can be [parsed as a duration](https://pkg.go.dev/time#ParseDuration) consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours). -- `delete` (String) A string that can be [parsed as a duration](https://pkg.go.dev/time#ParseDuration) consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours). Setting a timeout for a Delete operation is only applicable if changes are saved into state before the destroy operation occurs. -- `read` (String) A string that can be [parsed as a duration](https://pkg.go.dev/time#ParseDuration) consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours). Read operations occur during any refresh or planning operation when refresh is enabled. -- `update` (String) A string that can be [parsed as a duration](https://pkg.go.dev/time#ParseDuration) consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours). \ No newline at end of file diff --git a/docs/data-sources/graph_beta_device_and_app_management_role_scope_tag b/docs/data-sources/graph_beta_device_and_app_management_role_scope_tag deleted file mode 100644 index 6c433a2f..00000000 --- a/docs/data-sources/graph_beta_device_and_app_management_role_scope_tag +++ /dev/null @@ -1,130 +0,0 @@ ---- -page_title: "microsoft365_graph_beta_device_and_app_management_role_scope_tag Data Source - terraform-provider-microsoft365" -subcategory: "Intune: Role Scope Tags" -description: |- - Retrieves information about a Role Scope Tag in Microsoft Intune. ---- - -# microsoft365_graph_beta_device_and_app_management_role_scope_tag (Data Source) - -The Microsoft 365 Intune role scope tag data source provides information about a specific scope tag. - -## Example Usage - -```terraform -# Basic lookup examples -# Look up by display name -data "microsoft365_graph_beta_device_and_app_management_role_scope_tag" "by_name" { - display_name = "Level1-Support" -} - -# Look up by ID -data "microsoft365_graph_beta_device_and_app_management_role_scope_tag" "by_id" { - id = "00000000-0000-0000-0000-000000000001" -} - -# Output showing role scope tag details -output "role_scope_tag_details" { - value = { - # Basic details - id = data.microsoft365_graph_beta_device_and_app_management_role_scope_tag.by_name.id - display_name = data.microsoft365_graph_beta_device_and_app_management_role_scope_tag.by_name.display_name - description = data.microsoft365_graph_beta_device_and_app_management_role_scope_tag.by_name.description - is_built_in = data.microsoft365_graph_beta_device_and_app_management_role_scope_tag.by_name.is_built_in - } -} - -# Use Case 1: Create new tag based on existing one -resource "microsoft365_graph_beta_device_and_app_management_role_scope_tag" "clone" { - display_name = "Clone - ${data.microsoft365_graph_beta_device_and_app_management_role_scope_tag.by_name.display_name}" - description = "Cloned from: ${data.microsoft365_graph_beta_device_and_app_management_role_scope_tag.by_name.description}" - - timeouts = { - create = "180s" - read = "180s" - update = "180s" - delete = "180s" - } -} - -# Use Case 2: Conditional tag creation based on built-in status -resource "microsoft365_graph_beta_device_and_app_management_role_scope_tag" "conditional" { - count = data.microsoft365_graph_beta_device_and_app_management_role_scope_tag.by_name.is_built_in ? 0 : 1 - - display_name = "Custom - ${data.microsoft365_graph_beta_device_and_app_management_role_scope_tag.by_name.display_name}" - description = "Custom version of non-built-in tag" - - timeouts = { - create = "180s" - read = "180s" - update = "180s" - delete = "180s" - } -} - -# Use Case 3: Look up multiple tags and compare -data "microsoft365_graph_beta_device_and_app_management_role_scope_tag" "level1" { - display_name = "Level1-Support" -} - -data "microsoft365_graph_beta_device_and_app_management_role_scope_tag" "level2" { - display_name = "Level2-Support" -} - -output "support_tags_comparison" { - value = { - level1 = { - id = data.microsoft365_graph_beta_device_and_app_management_role_scope_tag.level1.id - display_name = data.microsoft365_graph_beta_device_and_app_management_role_scope_tag.level1.display_name - is_built_in = data.microsoft365_graph_beta_device_and_app_management_role_scope_tag.level1.is_built_in - } - level2 = { - id = data.microsoft365_graph_beta_device_and_app_management_role_scope_tag.level2.id - display_name = data.microsoft365_graph_beta_device_and_app_management_role_scope_tag.level2.display_name - is_built_in = data.microsoft365_graph_beta_device_and_app_management_role_scope_tag.level2.is_built_in - } - comparison = { - both_built_in = ( - data.microsoft365_graph_beta_device_and_app_management_role_scope_tag.level1.is_built_in && - data.microsoft365_graph_beta_device_and_app_management_role_scope_tag.level2.is_built_in - ) - } - } -} - -# Use Case 4: Create dynamic outputs based on tag properties -output "tag_summary" { - value = { - tag_info = { - name = data.microsoft365_graph_beta_device_and_app_management_role_scope_tag.by_name.display_name - type = data.microsoft365_graph_beta_device_and_app_management_role_scope_tag.by_name.is_built_in ? "Built-in" : "Custom" - has_description = data.microsoft365_graph_beta_device_and_app_management_role_scope_tag.by_name.description != "" - } - } -} -``` - - -## Schema - -### Optional - -- `display_name` (String) The display or friendly name of the Role Scope Tag. -- `id` (String) The unique identifier for the Role Scope Tag. -- `timeouts` (Attributes) (see [below for nested schema](#nestedatt--timeouts)) - -### Read-Only - -- `assignments` (Set of String) The list of group assignments for the Intune Role Scope Tag. -- `description` (String) Description of the Role Scope Tag. -- `is_built_in` (Boolean) Indicates whether this is a built-in Role Scope Tag. This property is read-only. - - -### Nested Schema for `timeouts` - -Optional: - -- `create` (String) A string that can be [parsed as a duration](https://pkg.go.dev/time#ParseDuration) consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours). -- `delete` (String) A string that can be [parsed as a duration](https://pkg.go.dev/time#ParseDuration) consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours). Setting a timeout for a Delete operation is only applicable if changes are saved into state before the destroy operation occurs. -- `read` (String) A string that can be [parsed as a duration](https://pkg.go.dev/time#ParseDuration) consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours). Read operations occur during any refresh or planning operation when refresh is enabled. -- `update` (String) A string that can be [parsed as a duration](https://pkg.go.dev/time#ParseDuration) consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours). \ No newline at end of file diff --git a/docs/resources/graph_beta_device_and_app_management_role_scope_tag b/docs/resources/graph_beta_device_and_app_management_role_scope_tag deleted file mode 100644 index f3a3b233..00000000 --- a/docs/resources/graph_beta_device_and_app_management_role_scope_tag +++ /dev/null @@ -1,167 +0,0 @@ ---- -page_title: "microsoft365_graph_beta_device_and_app_management_role_scope_tag Resource - terraform-provider-microsoft365" -subcategory: "Intune" -description: |- - Manages Role Scope Tags in Microsoft Intune. ---- - -# microsoft365_graph_beta_device_and_app_management_role_scope_tag (Resource) - -Manages Role Scope Tags in Microsoft Intune. - -## Example Usage - -```terraform -# Example of creating a basic role scope tag with a group assignment -resource "microsoft365_graph_beta_device_and_app_management_role_scope_tag" "helpdesk" { - display_name = "Helpdesk Support Tag" - description = "Role scope tag for helpdesk support staff" - - assignments = ["00000000-0000-0000-0000-000000000001"] - - timeouts = { - create = "180s" - read = "180s" - update = "180s" - delete = "180s" - } -} - -# Example of creating multiple related role scope tags with assignments -resource "microsoft365_graph_beta_device_and_app_management_role_scope_tag" "it_support" { - display_name = "IT Support Tag" - description = "Role scope tag for IT support teams" - - assignments = ["00000000-0000-0000-0000-000000000002"] -} - -resource "microsoft365_graph_beta_device_and_app_management_role_scope_tag" "device_management" { - display_name = "Device Management Tag" - description = "Role scope tag for device management teams" - - assignments = [ - "00000000-0000-0000-0000-000000000003", - "00000000-0000-0000-0000-000000000004" - ] - - timeouts = { - create = "180s" - read = "180s" - update = "180s" - delete = "180s" - } -} - -# Example showing data source usage to reference an existing role scope tag -data "microsoft365_graph_beta_device_and_app_management_role_scope_tag" "existing" { - display_name = "Existing Tag" -} - -# Example of using variables with role scope tags including assignments -variable "support_teams" { - type = list(object({ - name = string - description = string - group_ids = list(string) - })) - default = [ - { - name = "Level1-Support" - description = "First level support team scope" - group_ids = ["00000000-0000-0000-0000-000000000005"] - }, - { - name = "Level2-Support" - description = "Second level support team scope" - group_ids = ["00000000-0000-0000-0000-000000000006", "00000000-0000-0000-0000-000000000007"] - } - ] -} - -# Creating multiple tags using variables -resource "microsoft365_graph_beta_device_and_app_management_role_scope_tag" "support_teams" { - for_each = { for team in var.support_teams : team.name => team } - - display_name = each.value.name - description = each.value.description - assignments = each.value.group_ids - - timeouts = { - create = "180s" - read = "180s" - update = "180s" - delete = "180s" - } -} - -# Output examples -output "helpdesk_tag_id" { - value = microsoft365_graph_beta_device_and_app_management_role_scope_tag.helpdesk.id -} - -output "all_support_team_ids" { - value = [for tag in microsoft365_graph_beta_device_and_app_management_role_scope_tag.support_teams : tag.id] -} - -# Example of a role scope tag with conditional assignments based on environment -variable "environment" { - type = string - default = "production" -} - -resource "microsoft365_graph_beta_device_and_app_management_role_scope_tag" "environment_specific" { - display_name = "Environment-Specific Support Tag" - description = "Role scope tag for ${var.environment} environment" - - assignments = (var.environment == "production" - ? ["00000000-0000-0000-0000-000000000008"] - : ["00000000-0000-0000-0000-000000000009"] - ) - - timeouts = { - create = "180s" - read = "180s" - update = "180s" - delete = "180s" - } -} -``` - - -## Schema - -### Required - -- `display_name` (String) The display or friendly name of the Role Scope Tag. - -### Optional - -- `assignments` (Set of String) The list of group assignments for the Intune Role Scope Tag. -- `description` (String) Description of the Role Scope Tag. -- `timeouts` (Attributes) (see [below for nested schema](#nestedatt--timeouts)) - -### Read-Only - -- `id` (String) Key of the entity. This is read-only and automatically generated. -- `is_built_in` (Boolean) Description of the Role Scope Tag. This property is read-only. - - -### Nested Schema for `timeouts` - -Optional: - -- `create` (String) A string that can be [parsed as a duration](https://pkg.go.dev/time#ParseDuration) consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours). -- `delete` (String) A string that can be [parsed as a duration](https://pkg.go.dev/time#ParseDuration) consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours). Setting a timeout for a Delete operation is only applicable if changes are saved into state before the destroy operation occurs. -- `read` (String) A string that can be [parsed as a duration](https://pkg.go.dev/time#ParseDuration) consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours). Read operations occur during any refresh or planning operation when refresh is enabled. -- `update` (String) A string that can be [parsed as a duration](https://pkg.go.dev/time#ParseDuration) consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours). - -## Import - -Import is supported using the following syntax: - -```shell -# Using the provider-default project ID, the import ID is: -# {resource_id} -terraform import microsoft365_graph_beta_device_and_app_management_role_scope_tag.example role-scope-tag-id -``` - From eec7669ad0cb63f0561f4617ed0509ef2eb21f35 Mon Sep 17 00:00:00 2001 From: ShocOne Date: Thu, 16 Jan 2025 14:27:38 +0000 Subject: [PATCH 09/14] feat: enhanced setting catalog construction logic --- .../configuration_policy_settings.go | 163 +++++++++++------- .../settings_catalog_settings.go | 7 +- .../construct_resource.go | 25 +-- .../settings_catalog_template/resource.go | 69 ++++++-- ...xportSettingsTemplateConfigurationById.ps1 | 109 ++++++++++-- scripts/settingCatalogTemplate.json | 156 +++++++++++++++++ 6 files changed, 421 insertions(+), 108 deletions(-) create mode 100644 scripts/settingCatalogTemplate.json diff --git a/internal/resources/common/constructors/graph_beta/device_and_app_management/configuration_policy_settings.go b/internal/resources/common/constructors/graph_beta/device_and_app_management/configuration_policy_settings.go index 0e8ab0d7..09d8b4ed 100644 --- a/internal/resources/common/constructors/graph_beta/device_and_app_management/configuration_policy_settings.go +++ b/internal/resources/common/constructors/graph_beta/device_and_app_management/configuration_policy_settings.go @@ -25,82 +25,119 @@ func ConstructSettingsCatalogSettings(ctx context.Context, settingsJSON types.St return nil } - tflog.Debug(ctx, "Unmarshaled settings catalog data from hcl", map[string]interface{}{ + tflog.Debug(ctx, "Unmarshaled settings catalog data from HCL", map[string]interface{}{ "data": configModel, }) - settingsCollection := make([]graphmodels.DeviceManagementConfigurationSettingable, 0) + constructedSettings := make([]graphmodels.DeviceManagementConfigurationSettingable, 0) - for _, setting := range configModel.Settings { - baseSetting := graphmodels.NewDeviceManagementConfigurationSetting() - instance, instanceType := createBaseInstance(ctx, setting.SettingInstance.ODataType, setting.SettingInstance.SettingDefinitionId) + if len(configModel.Settings) > 0 { + // Handle array of settings + for _, setting := range configModel.Settings { + processSetting(ctx, setting, &constructedSettings) + } + } else if configModel.Setting != nil { + // Handle single instance + processSetting(ctx, *configModel.Setting, &constructedSettings) + } + + tflog.Debug(ctx, "Constructed settings catalog settings", map[string]interface{}{ + "count": len(constructedSettings), + }) + + return constructedSettings +} + +// processSetting processes an individual settings catalog setting and appends it to the settingsRequestPayload. +// +// This function is part of the constructor logic and is responsible for creating and configuring +// instances of DeviceManagementConfigurationSetting based on the provided `setting`. It dynamically +// determines the type of setting based on the `@odata.type` field and handles different setting types, including: +// - Simple Settings +// - Choice Settings +// - Simple Collection Settings +// - Choice Collection Settings +// - Group Collection Settings +// +// Why Use a Separate Function for `processSetting`? +// ------------------------------------------------- +// The Microsoft Graph API returns settings in a consistent format but allows for various nested and typed +// configurations. This function abstracts the logic of initializing, configuring, and appending each setting +// instance to the request payload, ensuring modularity and readability. +// +// Why Handle Both `settings` (Array) and `setting` (Single Instance)? +// ------------------------------------------------------------------- +// The API always returns settings as an array, but it supports both single and multiple settings. As a result, the constructor +// allows for the definiton a single `setting` and `settings` array. +// +// Parameters: +// - ctx: Context for logging and cancellation. +// - setting: A `sharedmodels.Setting` object representing an individual setting to process. +// - settingsRequestPayload: A pointer to a slice of `DeviceManagementConfigurationSettingable` where the processed +// setting will be appended. +func processSetting(ctx context.Context, setting sharedmodels.Setting, settingsRequestPayload *[]graphmodels.DeviceManagementConfigurationSettingable) { + baseSetting := graphmodels.NewDeviceManagementConfigurationSetting() + instance, instanceType := createBaseInstance(ctx, setting.SettingInstance.ODataType, setting.SettingInstance.SettingDefinitionId) + + if instance == nil { + return + } - if instance == nil { - continue + switch instanceType { + case "simple": + simpleInstance := instance.(graphmodels.DeviceManagementConfigurationSimpleSettingInstanceable) + if setting.SettingInstance.SimpleSettingValue != nil { + simpleInstance.SetSimpleSettingValue(handleSimpleValue(ctx, setting.SettingInstance.SimpleSettingValue)) } + setInstanceTemplateReference(simpleInstance, setting.SettingInstance.SettingInstanceTemplateReference) + baseSetting.SetSettingInstance(simpleInstance) - switch instanceType { - case "simple": - simpleInstance := instance.(graphmodels.DeviceManagementConfigurationSimpleSettingInstanceable) - if setting.SettingInstance.SimpleSettingValue != nil { - simpleInstance.SetSimpleSettingValue(handleSimpleValue(ctx, setting.SettingInstance.SimpleSettingValue)) - } - setInstanceTemplateReference(simpleInstance, setting.SettingInstance.SettingInstanceTemplateReference) - baseSetting.SetSettingInstance(simpleInstance) - - case "choice": - choiceInstance := instance.(graphmodels.DeviceManagementConfigurationChoiceSettingInstanceable) - if setting.SettingInstance.ChoiceSettingValue != nil { - choiceValue := graphmodels.NewDeviceManagementConfigurationChoiceSettingValue() - choiceValue.SetValue(&setting.SettingInstance.ChoiceSettingValue.Value) - setValueTemplateReference(choiceValue, setting.SettingInstance.ChoiceSettingValue.SettingValueTemplateReference) - - if len(setting.SettingInstance.ChoiceSettingValue.Children) > 0 { - choiceChildren := handleChoiceSettingChildren(ctx, setting.SettingInstance.ChoiceSettingValue.Children) - choiceValue.SetChildren(choiceChildren) - } + case "choice": + choiceInstance := instance.(graphmodels.DeviceManagementConfigurationChoiceSettingInstanceable) + if setting.SettingInstance.ChoiceSettingValue != nil { + choiceValue := graphmodels.NewDeviceManagementConfigurationChoiceSettingValue() + choiceValue.SetValue(&setting.SettingInstance.ChoiceSettingValue.Value) + setValueTemplateReference(choiceValue, setting.SettingInstance.ChoiceSettingValue.SettingValueTemplateReference) - choiceInstance.SetChoiceSettingValue(choiceValue) + if len(setting.SettingInstance.ChoiceSettingValue.Children) > 0 { + choiceChildren := handleChoiceSettingChildren(ctx, setting.SettingInstance.ChoiceSettingValue.Children) + choiceValue.SetChildren(choiceChildren) } - setInstanceTemplateReference(choiceInstance, setting.SettingInstance.SettingInstanceTemplateReference) - baseSetting.SetSettingInstance(choiceInstance) - - case "simpleCollection": - collectionInstance := instance.(graphmodels.DeviceManagementConfigurationSimpleSettingCollectionInstanceable) - if len(setting.SettingInstance.SimpleSettingCollectionValue) > 0 { - values := handleSimpleSettingCollection(setting.SettingInstance.SimpleSettingCollectionValue) - collectionInstance.SetSimpleSettingCollectionValue(values) - } - setInstanceTemplateReference(collectionInstance, setting.SettingInstance.SettingInstanceTemplateReference) - baseSetting.SetSettingInstance(collectionInstance) - - case "choiceCollection": - collectionInstance := instance.(graphmodels.DeviceManagementConfigurationChoiceSettingCollectionInstanceable) - if len(setting.SettingInstance.ChoiceSettingCollectionValue) > 0 { - values := handleChoiceCollectionValue(ctx, setting.SettingInstance.ChoiceSettingCollectionValue) - collectionInstance.SetChoiceSettingCollectionValue(values) - } - setInstanceTemplateReference(collectionInstance, setting.SettingInstance.SettingInstanceTemplateReference) - baseSetting.SetSettingInstance(collectionInstance) - - case "groupCollection": - groupInstance := instance.(graphmodels.DeviceManagementConfigurationGroupSettingCollectionInstanceable) - if len(setting.SettingInstance.GroupSettingCollectionValue) > 0 { - values := handleGroupSettingCollection(ctx, setting.SettingInstance.GroupSettingCollectionValue) - groupInstance.SetGroupSettingCollectionValue(values) - } - setInstanceTemplateReference(groupInstance, setting.SettingInstance.SettingInstanceTemplateReference) - baseSetting.SetSettingInstance(groupInstance) + + choiceInstance.SetChoiceSettingValue(choiceValue) } + setInstanceTemplateReference(choiceInstance, setting.SettingInstance.SettingInstanceTemplateReference) + baseSetting.SetSettingInstance(choiceInstance) - settingsCollection = append(settingsCollection, baseSetting) - } + case "simpleCollection": + collectionInstance := instance.(graphmodels.DeviceManagementConfigurationSimpleSettingCollectionInstanceable) + if len(setting.SettingInstance.SimpleSettingCollectionValue) > 0 { + values := handleSimpleSettingCollection(setting.SettingInstance.SimpleSettingCollectionValue) + collectionInstance.SetSimpleSettingCollectionValue(values) + } + setInstanceTemplateReference(collectionInstance, setting.SettingInstance.SettingInstanceTemplateReference) + baseSetting.SetSettingInstance(collectionInstance) - tflog.Debug(ctx, "Constructed settings catalog settings", map[string]interface{}{ - "count": len(settingsCollection), - }) + case "choiceCollection": + collectionInstance := instance.(graphmodels.DeviceManagementConfigurationChoiceSettingCollectionInstanceable) + if len(setting.SettingInstance.ChoiceSettingCollectionValue) > 0 { + values := handleChoiceCollectionValue(ctx, setting.SettingInstance.ChoiceSettingCollectionValue) + collectionInstance.SetChoiceSettingCollectionValue(values) + } + setInstanceTemplateReference(collectionInstance, setting.SettingInstance.SettingInstanceTemplateReference) + baseSetting.SetSettingInstance(collectionInstance) + + case "groupCollection": + groupInstance := instance.(graphmodels.DeviceManagementConfigurationGroupSettingCollectionInstanceable) + if len(setting.SettingInstance.GroupSettingCollectionValue) > 0 { + values := handleGroupSettingCollection(ctx, setting.SettingInstance.GroupSettingCollectionValue) + groupInstance.SetGroupSettingCollectionValue(values) + } + setInstanceTemplateReference(groupInstance, setting.SettingInstance.SettingInstanceTemplateReference) + baseSetting.SetSettingInstance(groupInstance) + } - return settingsCollection + *settingsRequestPayload = append(*settingsRequestPayload, baseSetting) } // createBaseInstance creates and initializes a new setting instance based on the provided OData type and setting definition ID. diff --git a/internal/resources/common/shared_models/graph_beta/device_and_app_management/settings_catalog_settings.go b/internal/resources/common/shared_models/graph_beta/device_and_app_management/settings_catalog_settings.go index a2962c7e..af7b34e5 100644 --- a/internal/resources/common/shared_models/graph_beta/device_and_app_management/settings_catalog_settings.go +++ b/internal/resources/common/shared_models/graph_beta/device_and_app_management/settings_catalog_settings.go @@ -1,8 +1,11 @@ package sharedmodels -// DeviceConfigV2GraphServiceResourceModel is the root configuration model +// DeviceConfigV2GraphServiceResourceModel is the root settings catalog model +// Officially the api only recognises 'settings' as the root key, but we use 'settings' and 'setting' +// to support both single-instance and array-based settings. type DeviceConfigV2GraphServiceResourceModel struct { - Settings []Setting `json:"settings"` + Settings []Setting `json:"settings,omitempty"` // For array-based settings + Setting *Setting `json:"setting,omitempty"` // For single-instance settings } // SettingDetail represents a single setting detail diff --git a/internal/resources/device_and_app_management/graph_beta/settings_catalog_template/construct_resource.go b/internal/resources/device_and_app_management/graph_beta/settings_catalog_template/construct_resource.go index 0f1252d4..ddd96b2c 100644 --- a/internal/resources/device_and_app_management/graph_beta/settings_catalog_template/construct_resource.go +++ b/internal/resources/device_and_app_management/graph_beta/settings_catalog_template/construct_resource.go @@ -20,16 +20,6 @@ type PolicyTemplateConfig struct { } var policyConfigMap = map[string]PolicyTemplateConfig{ - "windows_config_manager_anti_virus_microsoft_defender_antivirus": { - Platform: graphmodels.WINDOWS10_DEVICEMANAGEMENTCONFIGURATIONPLATFORMS, - Technologies: graphmodels.CONFIGMANAGER_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES, - CreationSource: "SccmAV", - }, - "windows_config_manager_anti_virus_windows_security_experience": { - Platform: graphmodels.WINDOWS10_DEVICEMANAGEMENTCONFIGURATIONPLATFORMS, - Technologies: graphmodels.CONFIGMANAGER_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES, - CreationSource: "WindowsSecurity", - }, "linux_anti_virus_microsoft_defender_antivirus": { Platform: graphmodels.LINUX_DEVICEMANAGEMENTCONFIGURATIONPLATFORMS, Technologies: graphmodels.MICROSOFTSENSE_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES, @@ -40,6 +30,11 @@ var policyConfigMap = map[string]PolicyTemplateConfig{ Technologies: graphmodels.MICROSOFTSENSE_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES, TemplateID: "8a17a1e5-3df4-4e07-9d20-3878267a79b8_1", }, + "linux_endpoint_detection_and_response": { + Platform: graphmodels.LINUX_DEVICEMANAGEMENTCONFIGURATIONPLATFORMS, + Technologies: graphmodels.MICROSOFTSENSE_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES, + TemplateID: "3514388a-d4d1-4aa8-bd64-c317776008f5_1", + }, "macOS_anti_virus_microsoft_defender_antivirus": { Platform: graphmodels.MACOS_DEVICEMANAGEMENTCONFIGURATIONPLATFORMS, Technologies: graphmodels.MDM_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES | graphmodels.MICROSOFTSENSE_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES, @@ -70,6 +65,16 @@ var policyConfigMap = map[string]PolicyTemplateConfig{ Technologies: graphmodels.MDM_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES | graphmodels.MICROSOFTSENSE_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES, TemplateID: "d948ff9b-99cb-4ee0-8012-1fbc09685377_1", }, + "windows_(config_mgr)_anti_virus_microsoft_defender_antivirus": { + Platform: graphmodels.WINDOWS10_DEVICEMANAGEMENTCONFIGURATIONPLATFORMS, + Technologies: graphmodels.CONFIGMANAGER_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES, + CreationSource: "SccmAV", + }, + "windows_(config_mgr)_anti_virus_windows_security_experience": { + Platform: graphmodels.WINDOWS10_DEVICEMANAGEMENTCONFIGURATIONPLATFORMS, + Technologies: graphmodels.CONFIGMANAGER_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES, + CreationSource: "WindowsSecurity", + }, } // Main entry point to construct the intune settings catalog profile resource for the Terraform provider. diff --git a/internal/resources/device_and_app_management/graph_beta/settings_catalog_template/resource.go b/internal/resources/device_and_app_management/graph_beta/settings_catalog_template/resource.go index 46040c36..f011ef4b 100644 --- a/internal/resources/device_and_app_management/graph_beta/settings_catalog_template/resource.go +++ b/internal/resources/device_and_app_management/graph_beta/settings_catalog_template/resource.go @@ -103,23 +103,51 @@ func (r *DeviceManagementTemplateResource) Schema(ctx context.Context, req resou }, "settings_catalog_template_type": schema.StringAttribute{ Required: true, - MarkdownDescription: "Defines which device management template type with settings catalog setting that will be deployed. " + - "Options available are `macOS_disk_encryption`, `macOS_firewall`, `macOS_endpoint_detection_and_response`, `macOS_anti_virus`, " + - "`windows_account_protection`, `windows_anti_virus`, `windows_app_control_for_business`, `windows_attack_surface_reduction`, " + - "`windows_disk_encryption`, `windows_firewall`, `windows_firewall_rules`, `windows_hyper-v_firewall_rules`, " + - "`windows_firewall_config_manager`, `windows_firewall_profile_config_manager`, `windows_firewall_rules_config_manager`, " + - "`windows_endpoint_detection_and_response`, `windows_config_manager_anti_virus`, `windows_config_manager_attack_surface_reduction`, " + - "`windows_config_manager_endpoint_detection_and_response`, `linux_endpoint_detection_and_response`, `linux_anti_virus`.", + MarkdownDescription: "Defines the intune settings catalog template type to be deployed using the settings catalog.\n" + + "This value will automatically set the correct `platform` , `templateID` , `creationSource` and `technologies` values for the settings catalog policy.\n" + + "The available options include templates for various platforms and configurations, such as macOS, Windows, and Linux. Options available are:\n\n" + + "- `linux_anti_virus_microsoft_defender_antivirus`: Customers using Microsoft Defender for Endpoint on Linux can configure and deploy Antivirus settings to Linux devices.\n" + + "- `linux_anti_virus_microsoft_defender_antivirus_exclusions`: This template allows you to manage settings for Microsoft Defender Antivirus that define Antivirus exclusions for paths, extensions and processes. Antivirus exclusion are also managed by Microsoft Defender Antivirus policy, which includes identical settings for exclusions. Settings from both templates (Antivirus and Antivirus exclusions) are subject to policy merge, and create a super set of exclusions for applicable devices and users.\n" + + "- `linux_endpoint_detection_and_response`: Endpoint detection and response settings for Linux devices.\n" + + "- `macOS_anti_virus_microsoft_defender_antivirus`: Microsoft Defender Antivirus is the next-generation protection component of Microsoft Defender for Endpoint on Mac. Next-generation protection brings together machine learning, big-data analysis, in-depth threat resistance research, and cloud infrastructure to protect devices in your enterprise organization.\n" + + "- `macOS_anti_virus_microsoft_defender_antivirus_exclusions`: This template allows you to manage settings for Microsoft Defender Antivirus that define Antivirus exclusions for paths, extensions and processes. Antivirus exclusion are also managed by Microsoft Defender Antivirus policy, which includes identical settings for exclusions. Settings from both templates (Antivirus and Antivirus exclusions) are subject to policy merge, and create a super set of exclusions for applicable devices and users.\n" + + "- `macOS_disk_encryption`: Disk encryption settings for macOS devices.\n" + + "- `macOS_endpoint_detection_and_response`: Endpoint detection and response settings for macOS devices.\n" + + "- `macOS_firewall`: Firewall configuration for macOS devices.\n" + + "- `windows_account_protection`: Account protection policies help protect user credentials by using technology such as Windows Hello for Business and Credential Guard.\n" + + "- `windows_anti_virus_defender_update_controls`: Configure the gradual release rollout of Defender Updates to targeted device groups. Use a ringed approach to test, validate, and rollout updates to devices through release channels. Updates available are platform, engine, security intelligence updates. These policy types have pause, resume, manual rollback commands similar to Windows Update ring policies.\n" + + "- `windows_anti_virus_microsoft_defender_antivirus`: Windows Defender Antivirus is the next-generation protection component of Microsoft Defender for Endpoint. Next-generation protection brings together machine learning, big-data analysis, in-depth threat resistance research, and cloud infrastructure to protect devices in your enterprise organization.\n" + + "- `windows_anti_virus_microsoft_defender_antivirus_exclusions`: This template allows you to manage settings for Microsoft Defender Antivirus that define Antivirus exclusions for paths, extensions and processes. Antivirus exclusion are also managed by Microsoft Defender Antivirus policy, which includes identical settings for exclusions. Settings from both templates (Antivirus and Antivirus exclusions) are subject to policy merge, and create a super set of exclusions for applicable devices and users.\n" + + "- `windows_anti_virus_security_experience`: The Windows Security app is used by a number of Windows security features to provide notifications about the health and security of the machine. These include notifications about firewalls, antivirus products, Windows Defender SmartScreen, and others.\n" + + "- `windows_app_control_for_business`: Application control settings for Windows devices.\n" + + "- `windows_attack_surface_reduction`: Attack surface reduction rules for Windows devices.\n" + + "- `windows_disk_encryption`: Disk encryption settings for Windows devices.\n" + + "- `windows_endpoint_detection_and_response`: Endpoint detection and response settings for Windows devices.\n" + + "- `windows_firewall`: Firewall settings for Windows devices.\n" + + "- `windows_firewall_config_manager`: Firewall configuration manager for Windows devices.\n" + + "- `windows_firewall_profile_config_manager`: Profile-specific firewall configuration for Windows devices.\n" + + "- `windows_firewall_rules`: Firewall rules for Windows devices.\n" + + "- `windows_firewall_rules_config_manager`: Rules-based firewall configuration for Windows devices.\n" + + "- `windows_hyper-v_firewall_rules`: Hyper-V firewall rules for Windows devices.\n" + + "- `windows_local_admin_password_solution_(windows_LAPS)`: Windows Local Administrator Password Solution(Windows LAPS) is a Windows feature that automatically manages and backs up the password of a local administrator account on your Azure Active Directory - joined or Windows Server Active Directory - joined devices.\n" + + "- `windows_local_user_group_membership`: Local user group membership policies help to add, remove, or replace members of local groups on Windows devices..\n" + + "- `windows_(config_mgr)_anti_virus_microsoft_defender_antivirus`: Microsoft Defender Antivirus settings for Windows devices managed via Microsoft Configuration Manager.\n" + + "- `windows_(config_mgr)_anti_virus_windows_security_experience`: Security experience settings for Windows devices managed via Microsoft Configuration Manager.\n" + + "- `windows_(config_mgr)_attack_surface_reduction`: Attack surface reduction settings for Windows devices managed via Microsoft Configuration Manager.\n" + + "- `windows_(config_mgr)_endpoint_detection_and_response`: Endpoint detection and response settings for Windows devices managed via Microsoft Configuration Manager.\n" + + "- `windows_(config_mgr)_firewall`: Firewall settings for Windows devices managed via Microsoft Configuration Manager.\n" + + "- `windows_(config_mgr)_firewall_profile`: Profile-specific firewall configuration for Windows devices managed via Microsoft Configuration Manager.\n" + + "- `windows_(config_mgr)_firewall_rules`: Rules-based firewall configuration for Windows devices managed via Microsoft Configuration Manager.\n", Validators: []validator.String{ stringvalidator.OneOf( - "linux_endpoint_detection_and_response", "linux_anti_virus_microsoft_defender_antivirus", "linux_anti_virus_microsoft_defender_antivirus_exclusions", - "macOS_disk_encryption", - "macOS_firewall", - "macOS_endpoint_detection_and_response", + "linux_endpoint_detection_and_response", "macOS_anti_virus_microsoft_defender_antivirus", "macOS_anti_virus_microsoft_defender_antivirus_exclusions", + "macOS_disk_encryption", + "macOS_endpoint_detection_and_response", + "macOS_firewall", "windows_account_protection", "windows_anti_virus_defender_update_controls", "windows_anti_virus_microsoft_defender_antivirus", @@ -128,17 +156,22 @@ func (r *DeviceManagementTemplateResource) Schema(ctx context.Context, req resou "windows_app_control_for_business", "windows_attack_surface_reduction", "windows_disk_encryption", + "windows_endpoint_detection_and_response", "windows_firewall", - "windows_firewall_rules", - "windows_hyper-v_firewall_rules", "windows_firewall_config_manager", "windows_firewall_profile_config_manager", + "windows_firewall_rules", "windows_firewall_rules_config_manager", - "windows_endpoint_detection_and_response", - "windows_config_manager_anti_virus_microsoft_defender_antivirus", - "windows_config_manager_anti_virus_windows_security_experience", - "windows_config_manager_attack_surface_reduction", - "windows_config_manager_endpoint_detection_and_response", + "windows_hyper-v_firewall_rules", + "windows_local_admin_password_solution_(windows_LAPS)", + "windows_local_user_group_membership", + "windows_(config_mgr)_anti_virus_microsoft_defender_antivirus", + "windows_(config_mgr)_anti_virus_windows_security_experience", + "windows_(config_mgr)_attack_surface_reduction", + "windows_(config_mgr)_endpoint_detection_and_response", + "windows_(config_mgr)_firewall", + "windows_(config_mgr)_firewall_profile", + "windows_(config_mgr)_firewall_rules", ), }, }, diff --git a/scripts/ExportSettingsTemplateConfigurationById.ps1 b/scripts/ExportSettingsTemplateConfigurationById.ps1 index c9ac7547..1df267a9 100644 --- a/scripts/ExportSettingsTemplateConfigurationById.ps1 +++ b/scripts/ExportSettingsTemplateConfigurationById.ps1 @@ -36,20 +36,76 @@ function Get-Paginated { } function Get-SettingsTemplateById { + param ( + [Parameter(Mandatory=$true)] + [string]$DeviceConfigurationId + ) + + try { + $templateUri = "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('$DeviceConfigurationId')" + $template = Invoke-MgGraphRequest -Method GET -Uri $templateUri + + return $template + } + catch { + Write-Error "Error retrieving settings template: $_" + return $null + } +} + +function Get-ConfigurationPolicyAssignments { param ( [Parameter(Mandatory=$true)] - [string]$DeviceConfigurationId + [string]$ConfigurationPolicyId ) try { - # Get template details - $templateUri = "https://graph.microsoft.com/beta/deviceManagement/deviceConfigurations/$DeviceConfigurationId" - $template = Invoke-MgGraphRequest -Method GET -Uri $templateUri + $assignmentsUri = "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('$ConfigurationPolicyId')/assignments" + $assignments = Get-Paginated -InitialUri $assignmentsUri - return $template + Write-Host "Assignments retrieved successfully." + return $assignments } catch { - Write-Error "Error retrieving settings template: $_" + Write-Error "Error retrieving configuration policy assignments: $_" + return $null + } +} + +function Get-ConfigurationPolicySettings { + param ( + [Parameter(Mandatory=$true)] + [string]$ConfigurationPolicyId + ) + + try { + $settingsUri = "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('$ConfigurationPolicyId')/settings?$expand=settingDefinitions&$top=1000" + $settings = Get-Paginated -InitialUri $settingsUri + + Write-Host "Settings retrieved successfully." + return $settings + } + catch { + Write-Error "Error retrieving configuration policy settings: $_" + return $null + } +} + +function Get-SettingTemplates { + param ( + [Parameter(Mandatory=$true)] + [string]$PolicyTemplateId + ) + + try { + $settingTemplatesUri = "https://graph.microsoft.com/beta/deviceManagement/configurationPolicyTemplates('$PolicyTemplateId')/settingTemplates?$expand=settingDefinitions&$top=1000" + $settingTemplates = Get-Paginated -InitialUri $settingTemplatesUri + + Write-Host "Setting templates retrieved successfully." + return $settingTemplates + } + catch { + Write-Error "Error retrieving setting templates: $_" return $null } } @@ -67,17 +123,40 @@ Write-Host "Retrieving template with ID: $DeviceConfigurationId" $templateData = Get-SettingsTemplateById -DeviceConfigurationId $DeviceConfigurationId if ($null -ne $templateData) { - Write-Host "`nFull JSON output for settings template:" - $jsonString = $templateData | ConvertTo-Json -Depth 100 -Compress - # Format the JSON for readability - $jsonFormatted = $jsonString | ConvertFrom-Json | ConvertTo-Json -Depth 100 - - Write-Output $jsonFormatted - $jsonFormatted | Out-File "settingsTemplate.json" - Write-Host "`nJSON output has been saved to 'settingsTemplate.json'" + # Extract IDs dynamically + $configurationPolicyId = $templateData.id + $policyTemplateId = $templateData.templateReference.templateId + + Write-Host "Retrieving assignments for configuration policy..." + $assignments = Get-ConfigurationPolicyAssignments -ConfigurationPolicyId $configurationPolicyId + + Write-Host "Retrieving settings for configuration policy..." + $settings = Get-ConfigurationPolicySettings -ConfigurationPolicyId $configurationPolicyId + + # Ensure settings are always wrapped in an array + if ($null -eq $settings) { + $settings = @() # Empty array if no settings are found + } elseif ($settings -isnot [Array]) { + $settings = @($settings) # Wrap single setting in an array + } + + Write-Host "Retrieving setting templates..." + $settingTemplates = Get-SettingTemplates -PolicyTemplateId $policyTemplateId + + # Consolidate data into a single object + $outputData = [PSCustomObject]@{ + baseResource = $templateData + assignments = $assignments + settings = $settings + settingTemplates = $settingTemplates + } + + # Export to a single JSON file + $outputData | ConvertTo-Json -Depth 100 | Out-File "settingCatalogTemplate.json" + Write-Host "Consolidated JSON output has been saved to 'settingCatalogTemplate.json'" } else { Write-Host "No data found for the specified template ID." } Disconnect-MgGraph -Write-Host "Disconnected from Microsoft Graph." \ No newline at end of file +Write-Host "Disconnected from Microsoft Graph." diff --git a/scripts/settingCatalogTemplate.json b/scripts/settingCatalogTemplate.json new file mode 100644 index 00000000..814f4d71 --- /dev/null +++ b/scripts/settingCatalogTemplate.json @@ -0,0 +1,156 @@ +{ + "baseResource": { + "createdDateTime": "2025-01-16T14:07:54.5433192Z", + "lastModifiedDateTime": "2025-01-16T14:22:48.5907542Z", + "id": "bcf09e49-e36b-4995-b913-d460224b9129", + "technologies": "microsoftSense", + "platforms": "linux", + "priorityMetaData": null, + "roleScopeTagIds": [ + "0" + ], + "creationSource": null, + "@odata.context": "https://graph.microsoft.com/beta/$metadata#deviceManagement/configurationPolicies/$entity", + "settingCount": 1, + "description": "terraform test for settings catalog templates", + "name": "Linux - Endpoint Detection and Response", + "templateReference": { + "templateDisplayName": "Endpoint detection and response", + "templateId": "3514388a-d4d1-4aa8-bd64-c317776008f5_1", + "templateFamily": "endpointSecurityEndpointDetectionAndResponse", + "templateDisplayVersion": "Version 1" + } + }, + "assignments": [ + { + "target": { + "groupId": "51a96cdd-4b9b-4849-b416-8c94a6d88797", + "deviceAndAppManagementAssignmentFilterType": "none", + "deviceAndAppManagementAssignmentFilterId": null, + "@odata.type": "#microsoft.graph.groupAssignmentTarget" + }, + "source": "direct", + "sourceId": "bcf09e49-e36b-4995-b913-d460224b9129", + "id": "bcf09e49-e36b-4995-b913-d460224b9129_51a96cdd-4b9b-4849-b416-8c94a6d88797" + }, + { + "target": { + "groupId": "b15228f4-9d49-41ed-9b4f-0e7c721fd9c2", + "deviceAndAppManagementAssignmentFilterType": "none", + "deviceAndAppManagementAssignmentFilterId": null, + "@odata.type": "#microsoft.graph.groupAssignmentTarget" + }, + "source": "direct", + "sourceId": "bcf09e49-e36b-4995-b913-d460224b9129", + "id": "bcf09e49-e36b-4995-b913-d460224b9129_b15228f4-9d49-41ed-9b4f-0e7c721fd9c2" + }, + { + "target": { + "groupId": "b8c661c2-fa9a-4351-af86-adc1729c343f", + "deviceAndAppManagementAssignmentFilterType": "none", + "deviceAndAppManagementAssignmentFilterId": null, + "@odata.type": "#microsoft.graph.exclusionGroupAssignmentTarget" + }, + "source": "direct", + "sourceId": "bcf09e49-e36b-4995-b913-d460224b9129", + "id": "bcf09e49-e36b-4995-b913-d460224b9129_b8c661c2-fa9a-4351-af86-adc1729c343f" + }, + { + "target": { + "groupId": "f6ebd6ff-501e-4b3d-a00b-a2e102c3fa0f", + "deviceAndAppManagementAssignmentFilterType": "none", + "deviceAndAppManagementAssignmentFilterId": null, + "@odata.type": "#microsoft.graph.exclusionGroupAssignmentTarget" + }, + "source": "direct", + "sourceId": "bcf09e49-e36b-4995-b913-d460224b9129", + "id": "bcf09e49-e36b-4995-b913-d460224b9129_f6ebd6ff-501e-4b3d-a00b-a2e102c3fa0f" + } + ], + "settings": [ + { + "settingInstance": { + "settingDefinitionId": "linux_mdatp_managed_edr_tags", + "settingInstanceTemplateReference": { + "settingInstanceTemplateId": "d0eb0a92-3807-4d9d-8432-6edd1aa108ce" + }, + "@odata.type": "#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance", + "groupSettingCollectionValue": [ + { + "settingValueTemplateReference": null, + "children": [ + { + "settingDefinitionId": "linux_mdatp_managed_edr_tags_item_value", + "simpleSettingValue": { + "value": "tag-value", + "settingValueTemplateReference": null, + "@odata.type": "#microsoft.graph.deviceManagementConfigurationStringSettingValue" + }, + "settingInstanceTemplateReference": null, + "@odata.type": "#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance" + }, + { + "settingDefinitionId": "linux_mdatp_managed_edr_tags_item_key", + "choiceSettingValue": { + "value": "linux_mdatp_managed_edr_tags_item_key_0", + "settingValueTemplateReference": null, + "children": [] + }, + "settingInstanceTemplateReference": null, + "@odata.type": "#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance" + } + ] + } + ] + }, + "id": "0" + } + ], + "settingTemplates": { + "settingInstanceTemplate": { + "allowUnmanagedValues": true, + "settingInstanceTemplateId": "d0eb0a92-3807-4d9d-8432-6edd1aa108ce", + "@odata.type": "#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstanceTemplate", + "groupSettingCollectionValueTemplate": [ + { + "settingValueTemplateId": "5c747340-be04-4be0-85e5-1b5c22597cf5", + "children": [ + { + "settingDefinitionId": "linux_mdatp_managed_edr_tags_item_key", + "settingInstanceTemplateId": "1a07a95c-9e59-4e6d-b2dc-704566275ffc", + "isRequired": false, + "@odata.type": "#microsoft.graph.deviceManagementConfigurationChoiceSettingInstanceTemplate", + "choiceSettingValueTemplate": { + "settingValueTemplateId": "c8c0155a-7851-4cf6-931d-cb3ae94dabad", + "requiredValueDefinition": null, + "recommendedValueDefinition": null, + "defaultValue": { + "settingDefinitionOptionId": "linux_mdatp_managed_edr_tags_item_key_0", + "@odata.type": "#microsoft.graph.deviceManagementConfigurationChoiceSettingValueConstantDefaultTemplate", + "children": [] + } + } + }, + { + "settingDefinitionId": "linux_mdatp_managed_edr_tags_item_value", + "settingInstanceTemplateId": "27b00f90-03f1-42b5-84e7-1f3cf00b66e5", + "isRequired": false, + "simpleSettingValueTemplate": { + "settingValueTemplateId": "e0d5a815-438c-4c68-aea1-81aa67fdd483", + "defaultValue": { + "@odata.type": "#microsoft.graph.deviceManagementConfigurationStringSettingValueConstantDefaultTemplate", + "constantValue": "" + }, + "@odata.type": "#microsoft.graph.deviceManagementConfigurationStringSettingValueTemplate" + }, + "@odata.type": "#microsoft.graph.deviceManagementConfigurationSimpleSettingInstanceTemplate" + } + ] + } + ], + "settingDefinitionId": "linux_mdatp_managed_edr_tags", + "isRequired": false + }, + "id": "1" + } +} From 4b264f781e65bf776da40f17037a2a683b3860b1 Mon Sep 17 00:00:00 2001 From: ShocOne Date: Thu, 16 Jan 2025 15:12:14 +0000 Subject: [PATCH 10/14] feat: add Windows Firewall rules template and remove deprecated script --- .../construct_resource.go | 79 +++++++++++++------ .../endpoint_privilege_management/resource.go | 6 -- .../construct_resource.go | 5 ++ .../settings_catalog_template/resource.go | 4 +- ...tingsCatalogTemplateConfigurationById.ps1} | 0 5 files changed, 61 insertions(+), 33 deletions(-) rename scripts/{ExportSettingsTemplateConfigurationById.ps1 => ExportSettingsCatalogTemplateConfigurationById.ps1} (100%) diff --git a/internal/resources/device_and_app_management/graph_beta/endpoint_privilege_management/construct_resource.go b/internal/resources/device_and_app_management/graph_beta/endpoint_privilege_management/construct_resource.go index 0edd3e05..a48f7df7 100644 --- a/internal/resources/device_and_app_management/graph_beta/endpoint_privilege_management/construct_resource.go +++ b/internal/resources/device_and_app_management/graph_beta/endpoint_privilege_management/construct_resource.go @@ -5,54 +5,58 @@ import ( "fmt" "github.com/deploymenttheory/terraform-provider-microsoft365/internal/resources/common/constructors" - sharedConstructor "github.com/deploymenttheory/terraform-provider-microsoft365/internal/resources/common/constructors/graph_beta/device_and_app_management" sharedmodels "github.com/deploymenttheory/terraform-provider-microsoft365/internal/resources/common/shared_models/graph_beta/device_and_app_management" "github.com/hashicorp/terraform-plugin-log/tflog" graphmodels "github.com/microsoftgraph/msgraph-beta-sdk-go/models" ) +// PolicyTemplateConfig is a struct that contains the platform, technologies, and template id for a device management policy. +type PolicyTemplateConfig struct { + Platform graphmodels.DeviceManagementConfigurationPlatforms + Technologies graphmodels.DeviceManagementConfigurationTechnologies + TemplateID string +} + +// Mapping of supported settings catalog template types to their configuration. +var policyConfigMap = map[string]PolicyTemplateConfig{ + "elevation_settings_policy": { + Platform: graphmodels.WINDOWS10_DEVICEMANAGEMENTCONFIGURATIONPLATFORMS, + Technologies: graphmodels.MDM_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES | graphmodels.ENDPOINTPRIVILEGEMANAGEMENT_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES, + TemplateID: "e7dcaba4-959b-46ed-88f0-16ba39b14fd8_1", + }, + "elevation_rules_policy": { + Platform: graphmodels.WINDOWS10_DEVICEMANAGEMENTCONFIGURATIONPLATFORMS, + Technologies: graphmodels.ENDPOINTPRIVILEGEMANAGEMENT_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES, + TemplateID: "cff02aad-51b1-498d-83ad-81161a393f56_1", + }, +} + // Main entry point to construct the intune settings catalog profile resource for the Terraform provider. func constructResource(ctx context.Context, data *sharedmodels.SettingsCatalogProfileResourceModel) (graphmodels.DeviceManagementConfigurationPolicyable, error) { tflog.Debug(ctx, fmt.Sprintf("Constructing %s resource from model", ResourceName)) requestBody := graphmodels.NewDeviceManagementConfigurationPolicy() + // Set general properties constructors.SetStringProperty(data.Name, requestBody.SetName) constructors.SetStringProperty(data.Description, requestBody.SetDescription) - // Set platform (always Windows for this resource). may change in the future - platform := graphmodels.DeviceManagementConfigurationPlatforms(graphmodels.WINDOWS10_DEVICEMANAGEMENTCONFIGURATIONPLATFORMS) - requestBody.SetPlatforms(&platform) - - technologies := graphmodels.DeviceManagementConfigurationTechnologies( - graphmodels.MDM_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES | - graphmodels.ENDPOINTPRIVILEGEMANAGEMENT_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES, - ) - requestBody.SetTechnologies(&technologies) + // Configure template context + if err := setTemplateContext(ctx, data, requestBody); err != nil { + return nil, err + } + // Set role scope tag IDs if err := constructors.SetStringList(ctx, data.RoleScopeTagIds, requestBody.SetRoleScopeTagIds); err != nil { return nil, fmt.Errorf("failed to set role scope tags: %s", err) } + // Construct settings settings := sharedConstructor.ConstructSettingsCatalogSettings(ctx, data.Settings) requestBody.SetSettings(settings) - // Set the templateReference based on SettingsCatalogTemplateType - templateReference := graphmodels.NewDeviceManagementConfigurationPolicyTemplateReference() - switch data.SettingsCatalogTemplateType.ValueString() { - case "elevation_settings_policy": - templateId := "e7dcaba4-959b-46ed-88f0-16ba39b14fd8_1" // Template ID for Elevation Settings Policy - templateReference.SetTemplateId(&templateId) - case "elevation_rules_policy": - templateId := "cff02aad-51b1-498d-83ad-81161a393f56_1" // Template ID for Elevation Rules Policy - templateReference.SetTemplateId(&templateId) - default: - return nil, fmt.Errorf("invalid settings_catalog_template_type: %s", data.SettingsCatalogTemplateType.ValueString()) - } - - requestBody.SetTemplateReference(templateReference) - + // Log the constructed resource if err := constructors.DebugLogGraphObject(ctx, fmt.Sprintf("Final JSON to be sent to Graph API for resource %s", ResourceName), requestBody); err != nil { tflog.Error(ctx, "Failed to debug log object", map[string]interface{}{ "error": err.Error(), @@ -63,3 +67,28 @@ func constructResource(ctx context.Context, data *sharedmodels.SettingsCatalogPr return requestBody, nil } + +// setTemplateContext sets the template-specific settings for the device management template. +// It sets the platform, technologies, and template ID reference based on the `SettingsCatalogTemplateType`. +func setTemplateContext(ctx context.Context, data *sharedmodels.SettingsCatalogProfileResourceModel, requestBody graphmodels.DeviceManagementConfigurationPolicyable) error { + config, exists := policyConfigMap[data.SettingsCatalogTemplateType.ValueString()] + if !exists { + tflog.Error(ctx, "Invalid settings catalog template type", map[string]interface{}{ + "settings_catalog_template_type": data.SettingsCatalogTemplateType.ValueString(), + }) + return fmt.Errorf("invalid settings_catalog_template_type: %s", data.SettingsCatalogTemplateType.ValueString()) + } + + // Platform and Technologies are always required + requestBody.SetPlatforms(&config.Platform) + requestBody.SetTechnologies(&config.Technologies) + + // Set TemplateReference if TemplateID exists + if config.TemplateID != "" { + templateReference := graphmodels.NewDeviceManagementConfigurationPolicyTemplateReference() + templateReference.SetTemplateId(&config.TemplateID) + requestBody.SetTemplateReference(templateReference) + } + + return nil +} diff --git a/internal/resources/device_and_app_management/graph_beta/endpoint_privilege_management/resource.go b/internal/resources/device_and_app_management/graph_beta/endpoint_privilege_management/resource.go index 50b4b401..55e7f815 100644 --- a/internal/resources/device_and_app_management/graph_beta/endpoint_privilege_management/resource.go +++ b/internal/resources/device_and_app_management/graph_beta/endpoint_privilege_management/resource.go @@ -163,12 +163,6 @@ func (r *EndpointPrivilegeManagementResource) Schema(ctx context.Context, req re "mdm", "endpointPrivilegeManagement", ), }, - PlanModifiers: []planmodifier.List{ - planmodifiers.DefaultListValue([]attr.Value{ - types.StringValue("mdm"), - types.StringValue("endpointPrivilegeManagement"), - }), - }, }, "role_scope_tag_ids": schema.ListAttribute{ ElementType: types.StringType, diff --git a/internal/resources/device_and_app_management/graph_beta/settings_catalog_template/construct_resource.go b/internal/resources/device_and_app_management/graph_beta/settings_catalog_template/construct_resource.go index ddd96b2c..3694757d 100644 --- a/internal/resources/device_and_app_management/graph_beta/settings_catalog_template/construct_resource.go +++ b/internal/resources/device_and_app_management/graph_beta/settings_catalog_template/construct_resource.go @@ -65,6 +65,11 @@ var policyConfigMap = map[string]PolicyTemplateConfig{ Technologies: graphmodels.MDM_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES | graphmodels.MICROSOFTSENSE_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES, TemplateID: "d948ff9b-99cb-4ee0-8012-1fbc09685377_1", }, + "windows_firewall_rules": { + Platform: graphmodels.WINDOWS10_DEVICEMANAGEMENTCONFIGURATIONPLATFORMS, + Technologies: graphmodels.MDM_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES | graphmodels.MICROSOFTSENSE_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES, + TemplateID: "19c8aa67-f286-4861-9aa0-f23541d31680_1", + }, "windows_(config_mgr)_anti_virus_microsoft_defender_antivirus": { Platform: graphmodels.WINDOWS10_DEVICEMANAGEMENTCONFIGURATIONPLATFORMS, Technologies: graphmodels.CONFIGMANAGER_DEVICEMANAGEMENTCONFIGURATIONTECHNOLOGIES, diff --git a/internal/resources/device_and_app_management/graph_beta/settings_catalog_template/resource.go b/internal/resources/device_and_app_management/graph_beta/settings_catalog_template/resource.go index f011ef4b..c22b8a44 100644 --- a/internal/resources/device_and_app_management/graph_beta/settings_catalog_template/resource.go +++ b/internal/resources/device_and_app_management/graph_beta/settings_catalog_template/resource.go @@ -113,7 +113,7 @@ func (r *DeviceManagementTemplateResource) Schema(ctx context.Context, req resou "- `macOS_anti_virus_microsoft_defender_antivirus_exclusions`: This template allows you to manage settings for Microsoft Defender Antivirus that define Antivirus exclusions for paths, extensions and processes. Antivirus exclusion are also managed by Microsoft Defender Antivirus policy, which includes identical settings for exclusions. Settings from both templates (Antivirus and Antivirus exclusions) are subject to policy merge, and create a super set of exclusions for applicable devices and users.\n" + "- `macOS_disk_encryption`: Disk encryption settings for macOS devices.\n" + "- `macOS_endpoint_detection_and_response`: Endpoint detection and response settings for macOS devices.\n" + - "- `macOS_firewall`: Firewall configuration for macOS devices.\n" + + //"- `macOS_firewall`: Firewall configuration for macOS devices.\n" + "- `windows_account_protection`: Account protection policies help protect user credentials by using technology such as Windows Hello for Business and Credential Guard.\n" + "- `windows_anti_virus_defender_update_controls`: Configure the gradual release rollout of Defender Updates to targeted device groups. Use a ringed approach to test, validate, and rollout updates to devices through release channels. Updates available are platform, engine, security intelligence updates. These policy types have pause, resume, manual rollback commands similar to Windows Update ring policies.\n" + "- `windows_anti_virus_microsoft_defender_antivirus`: Windows Defender Antivirus is the next-generation protection component of Microsoft Defender for Endpoint. Next-generation protection brings together machine learning, big-data analysis, in-depth threat resistance research, and cloud infrastructure to protect devices in your enterprise organization.\n" + @@ -147,7 +147,7 @@ func (r *DeviceManagementTemplateResource) Schema(ctx context.Context, req resou "macOS_anti_virus_microsoft_defender_antivirus_exclusions", "macOS_disk_encryption", "macOS_endpoint_detection_and_response", - "macOS_firewall", + //"macOS_firewall", "windows_account_protection", "windows_anti_virus_defender_update_controls", "windows_anti_virus_microsoft_defender_antivirus", diff --git a/scripts/ExportSettingsTemplateConfigurationById.ps1 b/scripts/ExportSettingsCatalogTemplateConfigurationById.ps1 similarity index 100% rename from scripts/ExportSettingsTemplateConfigurationById.ps1 rename to scripts/ExportSettingsCatalogTemplateConfigurationById.ps1 From 26c03625cb8a2402ccf757aaa89bf1246907e9cc Mon Sep 17 00:00:00 2001 From: ShocOne Date: Thu, 16 Jan 2025 15:35:52 +0000 Subject: [PATCH 11/14] docs: add examples for EPM elevation settings and rules policies --- .../resource.tf | 188 ++++++++++++++++++ 1 file changed, 188 insertions(+) diff --git a/examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_endpoint_privilege_management/resource.tf b/examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_endpoint_privilege_management/resource.tf index 8f0fde3e..133bd211 100644 --- a/examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_endpoint_privilege_management/resource.tf +++ b/examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_endpoint_privilege_management/resource.tf @@ -1,3 +1,5 @@ +# epm elevation settings policy example + resource "microsoft365_graph_beta_device_and_app_management_endpoint_privilege_management" "epm_elevation_settings_policy" { name = "EPM Base Elevation settings policy" description = "Elevation settings policy" @@ -76,6 +78,192 @@ resource "microsoft365_graph_beta_device_and_app_management_endpoint_privilege_m }) + assignments = { + all_devices = false + # all_devices_filter_type = "exclude" + # all_devices_filter_id = "2d7956fb-e5b5-4fa3-90b2-5bee9bee7883" + + all_users = false + # all_users_filter_type = "include" + # all_users_filter_id = "80f8c0a5-f3ec-4936-bcbc-420dc0ca3665" + + include_groups = [ + { + group_id = "51a96cdd-4b9b-4849-b416-8c94a6d88797" + include_groups_filter_type = "include" + include_groups_filter_id = "80f8c0a5-f3ec-4936-bcbc-420dc0ca3665" + }, + { + group_id = "b15228f4-9d49-41ed-9b4f-0e7c721fd9c2" + include_groups_filter_type = "include" + include_groups_filter_id = "2d7956fb-e5b5-4fa3-90b2-5bee9bee7883" + }, + ] + + exclude_group_ids = [ + "b8c661c2-fa9a-4351-af86-adc1729c343f", + "f6ebd6ff-501e-4b3d-a00b-a2e102c3fa0f", + ] + } + + timeouts = { + create = "1m" + read = "1m" + update = "1m" + delete = "1m" + } +} + +# epm elevation rules policy example + +resource "microsoft365_graph_beta_device_and_app_management_endpoint_privilege_management" "epm_elevation_rules_policy" { + name = "EPM Elevation rules policy" + description = "Elevation rules policy" + role_scope_tag_ids = ["0"] + settings_catalog_template_type = "elevation_rules_policy" + + settings = jsonencode({ + "settings" : [ + { + "settingInstance" : { + "settingDefinitionId" : "device_vendor_msft_policy_privilegemanagement_elevationrules_{elevationrulename}", + "settingInstanceTemplateReference" : { + "settingInstanceTemplateId" : "ee3d2e5f-6b3d-4cb1-af9b-37b02d3dbae2" + }, + "@odata.type" : "#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance", + "groupSettingCollectionValue" : [ + { + "settingValueTemplateReference" : null, + "children" : [ + { + "settingDefinitionId" : "device_vendor_msft_policy_privilegemanagement_elevationrules_{elevationrulename}_appliesto", + "choiceSettingValue" : { + "value" : "device_vendor_msft_policy_privilegemanagement_elevationrules_{elevationrulename}_allusers", + "settingValueTemplateReference" : { + "settingValueTemplateId" : "2ec26569-c08f-434c-af3d-a50ac4a1ce26", + "useTemplateDefault" : false + }, + "children" : [] + }, + "settingInstanceTemplateReference" : { + "settingInstanceTemplateId" : "0cde1c42-c701-44b1-94b7-438dd4536128" + }, + "@odata.type" : "#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance" + }, + { + "settingDefinitionId" : "device_vendor_msft_policy_privilegemanagement_elevationrules_{elevationrulename}_filehash", + "simpleSettingValue" : { + "value" : "d5774b403ae04414c6c8e8eb2bc98fc55b1677684f8cee8a4b1c509e55e3d5c1", + "@odata.type" : "#microsoft.graph.deviceManagementConfigurationStringSettingValue", + "settingValueTemplateReference" : { + "settingValueTemplateId" : "1adcc6f7-9fa4-4ce3-8941-2ce22cf5e404", + "useTemplateDefault" : false + } + }, + "settingInstanceTemplateReference" : { + "settingInstanceTemplateId" : "e4436e2c-1584-4fba-8e38-78737cbbbfdf" + }, + "@odata.type" : "#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance" + }, + { + "settingDefinitionId" : "device_vendor_msft_policy_privilegemanagement_elevationrules_{elevationrulename}_ruletype", + "choiceSettingValue" : { + "value" : "device_vendor_msft_policy_privilegemanagement_elevationrules_{elevationrulename}_self", + "settingValueTemplateReference" : { + "settingValueTemplateId" : "cb2ea689-ebc3-42ea-a7a4-c704bb13e3ad", + "useTemplateDefault" : false + }, + "children" : [ + { + "settingDefinitionId" : "device_vendor_msft_policy_privilegemanagement_elevationrules_{elevationrulename}_ruletype_validation", + "choiceSettingCollectionValue" : [ + { + "value" : "device_vendor_msft_policy_privilegemanagement_elevationrules_{elevationrulename}_ruletype_validation_0", + "settingValueTemplateReference" : null, + "children" : [] + }, + { + "value" : "device_vendor_msft_policy_privilegemanagement_elevationrules_{elevationrulename}_ruletype_validation_1", + "settingValueTemplateReference" : null, + "children" : [] + } + ], + "settingInstanceTemplateReference" : null, + "@odata.type" : "#microsoft.graph.deviceManagementConfigurationChoiceSettingCollectionInstance" + } + ] + }, + "settingInstanceTemplateReference" : { + "settingInstanceTemplateId" : "bc5a31ac-95b5-4ec6-be1f-50a384bb165f" + }, + "@odata.type" : "#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance" + }, + { + "settingDefinitionId" : "device_vendor_msft_policy_privilegemanagement_elevationrules_{elevationrulename}_childprocessbehavior", + "choiceSettingValue" : { + "value" : "device_vendor_msft_policy_privilegemanagement_elevationrules_{elevationrulename}_allowrunelevatedrulerequired", + "settingValueTemplateReference" : null, + "children" : [] + }, + "settingInstanceTemplateReference" : null, + "@odata.type" : "#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance" + }, + { + "settingDefinitionId" : "device_vendor_msft_policy_privilegemanagement_elevationrules_{elevationrulename}_filename", + "simpleSettingValue" : { + "value" : "test.exe", + "@odata.type" : "#microsoft.graph.deviceManagementConfigurationStringSettingValue", + "settingValueTemplateReference" : { + "settingValueTemplateId" : "a165327c-f0e5-4c7d-9af1-d856b02191f7", + "useTemplateDefault" : false + } + }, + "settingInstanceTemplateReference" : { + "settingInstanceTemplateId" : "0c1ceb2b-bbd4-46d4-9ba5-9ee7abe1f094" + }, + "@odata.type" : "#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance" + }, + { + "settingDefinitionId" : "device_vendor_msft_policy_privilegemanagement_elevationrules_{elevationrulename}_name", + "simpleSettingValue" : { + "value" : "test", + "@odata.type" : "#microsoft.graph.deviceManagementConfigurationStringSettingValue", + "settingValueTemplateReference" : { + "settingValueTemplateId" : "03f003e5-43ef-4e7e-bf30-57f00781fdcc", + "useTemplateDefault" : false + } + }, + "settingInstanceTemplateReference" : { + "settingInstanceTemplateId" : "fdabfcf9-afa4-4dbf-a4ef-d5c1549065e1" + }, + "@odata.type" : "#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance" + }, + { + "settingDefinitionId" : "device_vendor_msft_policy_privilegemanagement_elevationrules_{elevationrulename}_filepath", + "simpleSettingValue" : { + "value" : "c:\\path", + "@odata.type" : "#microsoft.graph.deviceManagementConfigurationStringSettingValue", + "settingValueTemplateReference" : { + "settingValueTemplateId" : "f011bcfc-03cd-4b28-a1f4-305278d7a030", + "useTemplateDefault" : false + } + }, + "settingInstanceTemplateReference" : { + "settingInstanceTemplateId" : "c3b7fda4-db6a-421d-bf04-d485e9d0cfb1" + }, + "@odata.type" : "#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance" + } + ] + } + ] + }, + "id" : "0" + } + ], + + }) + + assignments = { all_devices = false # all_devices_filter_type = "exclude" From a94419961b97490b0b187dc3b29c41b16ce48405 Mon Sep 17 00:00:00 2001 From: ShocOne Date: Thu, 16 Jan 2025 15:46:06 +0000 Subject: [PATCH 12/14] fix: update example file path for reusable policy setting documentation --- ...a_device_and_app_management_reuseable_policy_setting.md.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/data-sources/graph_beta_device_and_app_management_reuseable_policy_setting.md.tmpl b/templates/data-sources/graph_beta_device_and_app_management_reuseable_policy_setting.md.tmpl index 239f916a..9fe9a4d6 100644 --- a/templates/data-sources/graph_beta_device_and_app_management_reuseable_policy_setting.md.tmpl +++ b/templates/data-sources/graph_beta_device_and_app_management_reuseable_policy_setting.md.tmpl @@ -11,6 +11,6 @@ The Microsoft 365 Intune role scope tag data source provides information about a ## Example Usage -{{ tffile "examples/microsoft365_graph_beta/graph_beta_device_and_app_management_reuseable_policy_setting/datasource.tf" }} +{{ tffile "examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_reuseable_policy_setting/datasource.tf" }} {{ .SchemaMarkdown | trimspace }} \ No newline at end of file From 73d8aa74907d8ceba173a6808885b94202b5531f Mon Sep 17 00:00:00 2001 From: ShocOne Date: Thu, 16 Jan 2025 15:56:45 +0000 Subject: [PATCH 13/14] docs: update example file paths for device and app management templates --- ...e_and_app_management_endpoint_privilege_management.md.tmpl | 1 - ...evice_and_app_management_settings_catalog_template.md.tmpl | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/templates/resources/graph_beta_device_and_app_management_endpoint_privilege_management.md.tmpl b/templates/resources/graph_beta_device_and_app_management_endpoint_privilege_management.md.tmpl index 0d33a906..1fb064cd 100644 --- a/templates/resources/graph_beta_device_and_app_management_endpoint_privilege_management.md.tmpl +++ b/templates/resources/graph_beta_device_and_app_management_endpoint_privilege_management.md.tmpl @@ -20,4 +20,3 @@ description: |- Import is supported using the following syntax: {{ codefile "shell" "examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_endpoint_privilege_management/import.sh" }} - diff --git a/templates/resources/graph_beta_device_and_app_management_settings_catalog_template.md.tmpl b/templates/resources/graph_beta_device_and_app_management_settings_catalog_template.md.tmpl index f9f1b9fc..119ef02f 100644 --- a/templates/resources/graph_beta_device_and_app_management_settings_catalog_template.md.tmpl +++ b/templates/resources/graph_beta_device_and_app_management_settings_catalog_template.md.tmpl @@ -11,7 +11,7 @@ description: |- ## Example Usage -{{ tffile "examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_settings_template/resource.tf" }} +{{ tffile "examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_settings_catalog_template/resource.tf" }} {{ .SchemaMarkdown | trimspace }} @@ -19,5 +19,5 @@ description: |- Import is supported using the following syntax: -{{ codefile "shell" "examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_settings_template/import.sh" }} +{{ codefile "shell" "examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_settings_catalog_template/import.sh" }} From 1a293359c43dcf66fd30b5e5c511869964a486c0 Mon Sep 17 00:00:00 2001 From: GitHub Actions Bot Date: Thu, 16 Jan 2025 16:03:06 +0000 Subject: [PATCH 14/14] chore: update go documentation, provider documentation and format terraform files Signed-off-by: GitHub Actions Bot --- ...anagement_endpoint_privilege_management.md | 208 +++++++++++++++++- ...ice_and_app_management_settings_catalog.md | 11 +- .../resource.tf | 6 +- 3 files changed, 207 insertions(+), 18 deletions(-) diff --git a/docs/resources/graph_beta_device_and_app_management_endpoint_privilege_management.md b/docs/resources/graph_beta_device_and_app_management_endpoint_privilege_management.md index 8f5b8b00..ee7e3d32 100644 --- a/docs/resources/graph_beta_device_and_app_management_endpoint_privilege_management.md +++ b/docs/resources/graph_beta_device_and_app_management_endpoint_privilege_management.md @@ -12,10 +12,12 @@ Manages a Endpoint Privilege Management Policy using Settings Catalog in Microso ## Example Usage ```terraform +# epm elevation settings policy example + resource "microsoft365_graph_beta_device_and_app_management_endpoint_privilege_management" "epm_elevation_settings_policy" { - name = "EPM Base Elevation settings policy" - description = "Elevation settings policy" - role_scope_tag_ids = ["0"] + name = "EPM Base Elevation settings policy" + description = "Elevation settings policy" + role_scope_tag_ids = ["0"] settings_catalog_template_type = "elevation_settings_policy" settings = jsonencode({ @@ -90,6 +92,192 @@ resource "microsoft365_graph_beta_device_and_app_management_endpoint_privilege_m }) + assignments = { + all_devices = false + # all_devices_filter_type = "exclude" + # all_devices_filter_id = "2d7956fb-e5b5-4fa3-90b2-5bee9bee7883" + + all_users = false + # all_users_filter_type = "include" + # all_users_filter_id = "80f8c0a5-f3ec-4936-bcbc-420dc0ca3665" + + include_groups = [ + { + group_id = "51a96cdd-4b9b-4849-b416-8c94a6d88797" + include_groups_filter_type = "include" + include_groups_filter_id = "80f8c0a5-f3ec-4936-bcbc-420dc0ca3665" + }, + { + group_id = "b15228f4-9d49-41ed-9b4f-0e7c721fd9c2" + include_groups_filter_type = "include" + include_groups_filter_id = "2d7956fb-e5b5-4fa3-90b2-5bee9bee7883" + }, + ] + + exclude_group_ids = [ + "b8c661c2-fa9a-4351-af86-adc1729c343f", + "f6ebd6ff-501e-4b3d-a00b-a2e102c3fa0f", + ] + } + + timeouts = { + create = "1m" + read = "1m" + update = "1m" + delete = "1m" + } +} + +# epm elevation rules policy example + +resource "microsoft365_graph_beta_device_and_app_management_endpoint_privilege_management" "epm_elevation_rules_policy" { + name = "EPM Elevation rules policy" + description = "Elevation rules policy" + role_scope_tag_ids = ["0"] + settings_catalog_template_type = "elevation_rules_policy" + + settings = jsonencode({ + "settings" : [ + { + "settingInstance" : { + "settingDefinitionId" : "device_vendor_msft_policy_privilegemanagement_elevationrules_{elevationrulename}", + "settingInstanceTemplateReference" : { + "settingInstanceTemplateId" : "ee3d2e5f-6b3d-4cb1-af9b-37b02d3dbae2" + }, + "@odata.type" : "#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance", + "groupSettingCollectionValue" : [ + { + "settingValueTemplateReference" : null, + "children" : [ + { + "settingDefinitionId" : "device_vendor_msft_policy_privilegemanagement_elevationrules_{elevationrulename}_appliesto", + "choiceSettingValue" : { + "value" : "device_vendor_msft_policy_privilegemanagement_elevationrules_{elevationrulename}_allusers", + "settingValueTemplateReference" : { + "settingValueTemplateId" : "2ec26569-c08f-434c-af3d-a50ac4a1ce26", + "useTemplateDefault" : false + }, + "children" : [] + }, + "settingInstanceTemplateReference" : { + "settingInstanceTemplateId" : "0cde1c42-c701-44b1-94b7-438dd4536128" + }, + "@odata.type" : "#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance" + }, + { + "settingDefinitionId" : "device_vendor_msft_policy_privilegemanagement_elevationrules_{elevationrulename}_filehash", + "simpleSettingValue" : { + "value" : "d5774b403ae04414c6c8e8eb2bc98fc55b1677684f8cee8a4b1c509e55e3d5c1", + "@odata.type" : "#microsoft.graph.deviceManagementConfigurationStringSettingValue", + "settingValueTemplateReference" : { + "settingValueTemplateId" : "1adcc6f7-9fa4-4ce3-8941-2ce22cf5e404", + "useTemplateDefault" : false + } + }, + "settingInstanceTemplateReference" : { + "settingInstanceTemplateId" : "e4436e2c-1584-4fba-8e38-78737cbbbfdf" + }, + "@odata.type" : "#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance" + }, + { + "settingDefinitionId" : "device_vendor_msft_policy_privilegemanagement_elevationrules_{elevationrulename}_ruletype", + "choiceSettingValue" : { + "value" : "device_vendor_msft_policy_privilegemanagement_elevationrules_{elevationrulename}_self", + "settingValueTemplateReference" : { + "settingValueTemplateId" : "cb2ea689-ebc3-42ea-a7a4-c704bb13e3ad", + "useTemplateDefault" : false + }, + "children" : [ + { + "settingDefinitionId" : "device_vendor_msft_policy_privilegemanagement_elevationrules_{elevationrulename}_ruletype_validation", + "choiceSettingCollectionValue" : [ + { + "value" : "device_vendor_msft_policy_privilegemanagement_elevationrules_{elevationrulename}_ruletype_validation_0", + "settingValueTemplateReference" : null, + "children" : [] + }, + { + "value" : "device_vendor_msft_policy_privilegemanagement_elevationrules_{elevationrulename}_ruletype_validation_1", + "settingValueTemplateReference" : null, + "children" : [] + } + ], + "settingInstanceTemplateReference" : null, + "@odata.type" : "#microsoft.graph.deviceManagementConfigurationChoiceSettingCollectionInstance" + } + ] + }, + "settingInstanceTemplateReference" : { + "settingInstanceTemplateId" : "bc5a31ac-95b5-4ec6-be1f-50a384bb165f" + }, + "@odata.type" : "#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance" + }, + { + "settingDefinitionId" : "device_vendor_msft_policy_privilegemanagement_elevationrules_{elevationrulename}_childprocessbehavior", + "choiceSettingValue" : { + "value" : "device_vendor_msft_policy_privilegemanagement_elevationrules_{elevationrulename}_allowrunelevatedrulerequired", + "settingValueTemplateReference" : null, + "children" : [] + }, + "settingInstanceTemplateReference" : null, + "@odata.type" : "#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance" + }, + { + "settingDefinitionId" : "device_vendor_msft_policy_privilegemanagement_elevationrules_{elevationrulename}_filename", + "simpleSettingValue" : { + "value" : "test.exe", + "@odata.type" : "#microsoft.graph.deviceManagementConfigurationStringSettingValue", + "settingValueTemplateReference" : { + "settingValueTemplateId" : "a165327c-f0e5-4c7d-9af1-d856b02191f7", + "useTemplateDefault" : false + } + }, + "settingInstanceTemplateReference" : { + "settingInstanceTemplateId" : "0c1ceb2b-bbd4-46d4-9ba5-9ee7abe1f094" + }, + "@odata.type" : "#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance" + }, + { + "settingDefinitionId" : "device_vendor_msft_policy_privilegemanagement_elevationrules_{elevationrulename}_name", + "simpleSettingValue" : { + "value" : "test", + "@odata.type" : "#microsoft.graph.deviceManagementConfigurationStringSettingValue", + "settingValueTemplateReference" : { + "settingValueTemplateId" : "03f003e5-43ef-4e7e-bf30-57f00781fdcc", + "useTemplateDefault" : false + } + }, + "settingInstanceTemplateReference" : { + "settingInstanceTemplateId" : "fdabfcf9-afa4-4dbf-a4ef-d5c1549065e1" + }, + "@odata.type" : "#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance" + }, + { + "settingDefinitionId" : "device_vendor_msft_policy_privilegemanagement_elevationrules_{elevationrulename}_filepath", + "simpleSettingValue" : { + "value" : "c:\\path", + "@odata.type" : "#microsoft.graph.deviceManagementConfigurationStringSettingValue", + "settingValueTemplateReference" : { + "settingValueTemplateId" : "f011bcfc-03cd-4b28-a1f4-305278d7a030", + "useTemplateDefault" : false + } + }, + "settingInstanceTemplateReference" : { + "settingInstanceTemplateId" : "c3b7fda4-db6a-421d-bf04-d485e9d0cfb1" + }, + "@odata.type" : "#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance" + } + ] + } + ] + }, + "id" : "0" + } + ], + + }) + + assignments = { all_devices = false # all_devices_filter_type = "exclude" @@ -132,22 +320,23 @@ resource "microsoft365_graph_beta_device_and_app_management_endpoint_privilege_m ### Required -- `settings_catalog_template_type` (String) Defines which Endpoint Privilege Management Policy type with settings catalog setting will be deployed. Options available are `elevation_settings_policy` or `elevation_rules_policy`. - `name` (String) Policy name -- `settings` (String) Endpoint Privilege Management Policy with settings catalog settings defined as a valid JSON string. Provide JSON-encoded settings structure. This can either be extracted from an existing policy using the Intune gui export to JSON, via a script such as [this PowerShell script](https://github.com/deploymenttheory/terraform-provider-microsoft365/blob/main/scripts/GetSettingsCatalogConfigurationById.ps1) or created from scratch. The JSON structure should match the graph schema of the settings catalog. Please look at the terraform documentation for the settings catalog for examples and how to correctly format the HCL. +- `settings` (String) Endpoint Privilege Management Policy with settings catalog settings defined as a valid JSON string. Provide JSON-encoded settings structure. This can either be extracted from an existing policy using the Intune gui export to JSON, via a script such as [this PowerShell script](https://github.com/deploymenttheory/terraform-provider-microsoft365/blob/main/scripts/ExportSettingsCatalogConfigurationById.ps1) or created from scratch. The JSON structure should match the graph schema of the settings catalog. Please look at the terraform documentation for the settings catalog for examples and how to correctly format the HCL. A correctly formatted field in the HCL should begin and end like this: ```hcl settings = jsonencode({ "settings": [ { - # ... settings configuration ... - } - ] -}) + "id": "0", + "settingInstance": { + } + } + }, ``` Note: When setting secret values (identified by `@odata.type: "#microsoft.graph.deviceManagementConfigurationSecretSettingValue"`), ensure the `valueState` is set to `"notEncrypted"`. The value `"encryptedValueToken"` is reserved for server responses and should not be used when creating or updating settings. +- `settings_catalog_template_type` (String) Defines which Endpoint Privilege Management Policy type with settings catalog setting will be deployed. Options available are `elevation_settings_policy` or `elevation_rules_policy`. ### Optional @@ -222,4 +411,3 @@ Import is supported using the following syntax: # {resource_id} terraform import microsoft365_graph_beta_device_and_app_management_endpoint_privilege_management.example epm-policy-id ``` - diff --git a/docs/resources/graph_beta_device_and_app_management_settings_catalog.md b/docs/resources/graph_beta_device_and_app_management_settings_catalog.md index ff5c5300..94a7f875 100644 --- a/docs/resources/graph_beta_device_and_app_management_settings_catalog.md +++ b/docs/resources/graph_beta_device_and_app_management_settings_catalog.md @@ -415,10 +415,11 @@ A correctly formatted field in the HCL should begin and end like this: settings = jsonencode({ "settings": [ { - # ... settings configuration ... - } - ] -}) + "id": "0", + "settingInstance": { + } + } + }, ``` Note: When setting secret values (identified by `@odata.type: "#microsoft.graph.deviceManagementConfigurationSecretSettingValue"`), ensure the `valueState` is set to `"notEncrypted"`. The value `"encryptedValueToken"` is reserved for server responses and should not be used when creating or updating settings. @@ -434,11 +435,11 @@ Note: When setting secret values (identified by `@odata.type: "#microsoft.graph. ### Read-Only -- `configuration_policy_template_type` (String) Defines which settings catalog setting template will be deployed. Unused by non settings catalog template items, but required in schema to satisify tfsdk model. - `created_date_time` (String) Creation date and time of the settings catalog policy - `id` (String) The unique identifier for this policy - `is_assigned` (Boolean) Indicates if the policy is assigned to any scope - `last_modified_date_time` (String) Last modification date and time of the settings catalog policy +- `settings_catalog_template_type` (String) Defines which settings catalog setting template will be deployed. Unused by non settings catalog template items, but required in schema to satisify tfsdk model. - `settings_count` (Number) Number of settings catalog settings with the policy. This will change over time as the resource is updated. diff --git a/examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_endpoint_privilege_management/resource.tf b/examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_endpoint_privilege_management/resource.tf index 133bd211..86dda2f7 100644 --- a/examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_endpoint_privilege_management/resource.tf +++ b/examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_endpoint_privilege_management/resource.tf @@ -1,9 +1,9 @@ # epm elevation settings policy example resource "microsoft365_graph_beta_device_and_app_management_endpoint_privilege_management" "epm_elevation_settings_policy" { - name = "EPM Base Elevation settings policy" - description = "Elevation settings policy" - role_scope_tag_ids = ["0"] + name = "EPM Base Elevation settings policy" + description = "Elevation settings policy" + role_scope_tag_ids = ["0"] settings_catalog_template_type = "elevation_settings_policy" settings = jsonencode({