From 63b9bd05d4fac376052ca5d1d329b4b3b3879be8 Mon Sep 17 00:00:00 2001 From: ShocOne Date: Thu, 5 Sep 2024 17:29:06 +0100 Subject: [PATCH 1/3] added browser site to device and app management --- ...ce_and_app_management_assignment_filter.md | 30 +++ ...app_management_device_management_script.md | 62 ++++++ .../graph_cloud_pc_device_image.md | 32 +++ docs/index.md | 146 +------------- .../index.md.tmpl => docs/index.md.tmpl.back | 0 ...nagement_m365_apps_installation_options.md | 60 ++++++ ...d_app_management_cloud_pc_device_image.md} | 4 +- ...anagement_cloud_pc_provisioning_policy.md} | 4 +- ...d_app_management_cloud_pc_user_setting.md} | 4 +- .../resource.tf | 15 ++ .../beta/browser_site/construct.go | 159 +++++++++++++++ .../beta/browser_site/crud.go | 183 ++++++++++++++++++ .../beta/browser_site/model.go | 52 +++++ .../beta/browser_site/resource.go | 149 ++++++++++++++ .../beta/browser_site/resource_model.json | 101 ++++++++++ .../beta/browser_site/state.go | 99 ++++++++++ templates/index.md.tmpl.back | 16 ++ 17 files changed, 970 insertions(+), 146 deletions(-) create mode 100644 docs/data-sources/graph_beta_device_and_app_management_assignment_filter.md create mode 100644 docs/data-sources/graph_beta_device_and_app_management_device_management_script.md create mode 100644 docs/data-sources/graph_cloud_pc_device_image.md rename templates/index.md.tmpl => docs/index.md.tmpl.back (100%) create mode 100644 docs/resources/graph_beta_device_and_app_management_m365_apps_installation_options.md rename docs/resources/{graph_cloud_pc_device_image.md => graph_device_and_app_management_cloud_pc_device_image.md} (95%) rename docs/resources/{graph_cloud_pc_provisioning_policy.md => graph_device_and_app_management_cloud_pc_provisioning_policy.md} (97%) rename docs/resources/{graph_cloud_pc_user_setting.md => graph_device_and_app_management_cloud_pc_user_setting.md} (95%) create mode 100644 examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_browser_site/resource.tf create mode 100644 internal/resources/device_and_app_management/beta/browser_site/construct.go create mode 100644 internal/resources/device_and_app_management/beta/browser_site/crud.go create mode 100644 internal/resources/device_and_app_management/beta/browser_site/model.go create mode 100644 internal/resources/device_and_app_management/beta/browser_site/resource.go create mode 100644 internal/resources/device_and_app_management/beta/browser_site/resource_model.json create mode 100644 internal/resources/device_and_app_management/beta/browser_site/state.go create mode 100644 templates/index.md.tmpl.back diff --git a/docs/data-sources/graph_beta_device_and_app_management_assignment_filter.md b/docs/data-sources/graph_beta_device_and_app_management_assignment_filter.md new file mode 100644 index 00000000..da76b446 --- /dev/null +++ b/docs/data-sources/graph_beta_device_and_app_management_assignment_filter.md @@ -0,0 +1,30 @@ +--- +page_title: "Data Source: microsoft365_graph_beta_device_and_app_management_assignment_filter" +description: |- + +--- + +# Data Source: microsoft365_graph_beta_device_and_app_management_assignment_filter + + + + + + +## Schema + +### Required + +- `display_name` (String) The display name of the assignment filter. + +### 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. +- `id` (String) The unique identifier 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. + diff --git a/docs/data-sources/graph_beta_device_and_app_management_device_management_script.md b/docs/data-sources/graph_beta_device_and_app_management_device_management_script.md new file mode 100644 index 00000000..e9ea3354 --- /dev/null +++ b/docs/data-sources/graph_beta_device_and_app_management_device_management_script.md @@ -0,0 +1,62 @@ +--- +page_title: "Data Source: microsoft365_graph_beta_device_and_app_management_device_management_script" +description: |- + Retrieves information about a device management script. +--- + +# Data Source: microsoft365_graph_beta_device_and_app_management_device_management_script + +Retrieves information about a device management script. + + + + +## Schema + +### Required + +- `id` (String) Unique identifier for the device management script. + +### Read-Only + +- `assignments` (Attributes List) The assignments of the device management script. (see [below for nested schema](#nestedatt--assignments)) +- `created_date_time` (String) The date and time the device management script was created. +- `description` (String) Description of the device management script. +- `display_name` (String) Name of the device management script. +- `enforce_signature_check` (Boolean) Indicate whether the script signature needs be checked. +- `file_name` (String) Script file name. +- `group_assignments` (Attributes List) The group assignments of the device management script. (see [below for nested schema](#nestedatt--group_assignments)) +- `last_modified_date_time` (String) The date and time the device management script was last modified. +- `role_scope_tag_ids` (List of String) List of Scope Tag IDs for this PowerShellScript instance. +- `run_as_32_bit` (Boolean) A value indicating whether the PowerShell script should run as 32-bit. +- `run_as_account` (String) Indicates the type of execution context. +- `script_content` (String, Sensitive) The script content. + + +### Nested Schema for `assignments` + +Read-Only: + +- `id` (String) Key of the device management script assignment entity. +- `target` (Attributes) The target of the assignment. (see [below for nested schema](#nestedatt--assignments--target)) + + +### Nested Schema for `assignments.target` + +Read-Only: + +- `device_and_app_management_assignment_filter_id` (String) The Id of the filter for the target assignment. +- `device_and_app_management_assignment_filter_type` (String) The type of filter of the target assignment. +- `entra_object_id` (String) The ID of the Azure Active Directory object. +- `target_type` (String) The target type of the assignment. + + + + +### Nested Schema for `group_assignments` + +Read-Only: + +- `id` (String) Key of the device management script group assignment entity. +- `target_group_id` (String) The Id of the Azure Active Directory group we are targeting the script to. + diff --git a/docs/data-sources/graph_cloud_pc_device_image.md b/docs/data-sources/graph_cloud_pc_device_image.md new file mode 100644 index 00000000..e593a730 --- /dev/null +++ b/docs/data-sources/graph_cloud_pc_device_image.md @@ -0,0 +1,32 @@ +--- +page_title: "Data Source: microsoft365_graph_cloud_pc_device_image" +description: |- + +--- + +# Data Source: microsoft365_graph_cloud_pc_device_image + + + + + + +## Schema + +### Required + +- `id` (String) The unique identifier (ID) of the image resource on the Cloud PC. + +### Read-Only + +- `display_name` (String) The display name of the associated device image. +- `error_code` (String) The error code of the status of the image that indicates why the upload failed, if applicable. +- `expiration_date` (String) The date when the image became unavailable. +- `last_modified_date_time` (String) The date and time when the image was last modified. +- `operating_system` (String) The operating system (OS) of the image. +- `os_build_number` (String) The OS build version of the image. +- `os_status` (String) The OS status of this image. +- `source_image_resource_id` (String) The unique identifier (ID) of the source image resource on Azure. +- `status` (String) The status of the image on the Cloud PC. +- `version` (String) The image version. + diff --git a/docs/index.md b/docs/index.md index 428773e3..4e6a06bf 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,150 +1,16 @@ --- -page_title: "Provider: m365" +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "microsoft365 Provider" +subcategory: "" description: |- - The m365 provider is used to manage m365 resources. + --- -# m365 Provider +# microsoft365 Provider -The Terraform m365 msgraph provider is a plugin for Terraform that allows for the -management of [m365](https://github.com/microsoftgraph/msgraph-metadata) resources. -## Example Usage -```terraform -# Example backend -terraform { - required_providers { - microsoft365 = { - source = "deploymenttheory/terraform-provider-microsoft365" - version = "~> 1.0.0" - } - } -} - -# Example provider -provider "microsoft365" { - tenant_id = var.tenant_id - auth_method = var.auth_method - client_id = var.client_id - client_secret = var.client_secret - client_certificate = var.client_certificate - client_certificate_password = var.client_certificate_password - username = var.username - password = var.password - redirect_url = var.redirect_url - use_proxy = var.use_proxy - proxy_url = var.proxy_url - cloud = var.cloud - enable_chaos = var.enable_chaos - telemetry_optout = var.telemetry_optout - debug_mode = var.debug_mode -} - - -# Example resource -resource "microsoft365_graph_beta_device_and_app_management_assignment_filter" "example" { - display_name = "Example Filter" - description = "This is an example filter" - platform = "windows10" - rule = "(device.manufacturer -eq \"Microsoft\")" -} - -# Variables -variable "cloud" { - description = "The cloud to use for authentication and Graph / Graph Beta API requests. Default is `public`. Valid values are `public`, `gcc`, `gcchigh`, `china`, `dod`, `ex`, `rx`. Can also be set using the `M365_CLOUD` environment variable." - type = string - default = "public" -} - -variable "tenant_id" { - description = "The M365 tenant ID for the Entra ID application. This ID uniquely identifies your Entra ID (EID) instance. It can be found in the Azure portal under Entra ID > Properties. Can also be set using the `M365_TENANT_ID` environment variable." - type = string - default = "" -} - -variable "auth_method" { - description = "The authentication method to use for the Entra ID application to authenticate the provider. Options: 'device_code', 'client_secret', 'client_certificate', 'interactive_browser', 'username_password'. Can also be set using the `M365_AUTH_METHOD` environment variable." - type = string - default = "client_secret" -} - -variable "client_id" { - description = "The client ID for the Entra ID application. This ID is generated when you register an application in the Entra ID (Azure AD) and can be found under App registrations > YourApp > Overview. Can also be set using the `M365_CLIENT_ID` environment variable." - type = string - default = "" -} - -variable "client_secret" { - description = "The client secret for the Entra ID application. This secret is generated in the Entra ID (Azure AD) and is required for authentication flows such as client credentials and on-behalf-of flows. It can be found under App registrations > YourApp > Certificates & secrets. Required for client credentials and on-behalf-of flows. Can also be set using the `M365_CLIENT_SECRET` environment variable." - type = string - sensitive = true - default = "" -} - -variable "client_certificate" { - description = "The path to the Client Certificate associated with the Service Principal for use when authenticating as a Service Principal using a Client Certificate. Can also be set using the `M365_CLIENT_CERTIFICATE_FILE_PATH` environment variable." - type = string - sensitive = true - default = "" -} -variable "client_certificate_password" { - description = "The password associated with the Client Certificate. For use when authenticating as a Service Principal using a Client Certificate. Can also be set using the `M365_CLIENT_CERTIFICATE_PASSWORD` environment variable." - type = string - sensitive = true - default = "" -} - -variable "username" { - description = "The username for username/password authentication. Can also be set using the `M365_USERNAME` environment variable." - type = string - default = "" -} - -variable "password" { - description = "The password for username/password authentication. Can also be set using the `M365_PASSWORD` environment variable." - type = string - sensitive = true - default = "" -} - -variable "redirect_url" { - description = "The redirect URL for interactive browser authentication. Can also be set using the `M365_REDIRECT_URL` environment variable." - type = string - default = "" -} - -variable "use_proxy" { - description = "Enables the use of an HTTP proxy for network requests. When set to true, the provider will route all HTTP requests through the specified proxy server. This can be useful for environments that require proxy access for internet connectivity or for monitoring and logging HTTP traffic. Can also be set using the `M365_USE_PROXY` environment variable." - type = bool - default = false -} - -variable "proxy_url" { - description = "Specifies the URL of the HTTP proxy server. This URL should be in a valid URL format (e.g., 'http://proxy.example.com:8080'). When 'use_proxy' is enabled, this URL is used to configure the HTTP client to route requests through the proxy. Ensure the proxy server is reachable and correctly configured to handle the network traffic. Can also be set using the `M365_PROXY_URL` environment variable." - type = string - default = "" -} - -variable "enable_chaos" { - description = "Enable the chaos handler for testing purposes. When enabled, the chaos handler can simulate specific failure scenarios and random errors in API responses to help test the robustness and resilience of the terraform provider against intermittent issues. This is particularly useful for testing how the provider handles various error conditions and ensures it can recover gracefully. Use with caution in production environments. Can also be set using the `M365_ENABLE_CHAOS` environment variable." - type = bool - default = false -} - -variable "telemetry_optout" { - description = "Flag to indicate whether to opt out of telemetry. Default is `false`. Can also be set using the `M365_TELEMETRY_OPTOUT` environment variable." - type = bool - default = false -} - -variable "debug_mode" { - description = "Flag to enable debug mode for the provider. When enabled, the provider will output additional debug information to the console to help diagnose issues. Can also be set using the `M365_DEBUG_MODE` environment variable." - type = bool - default = false -} -``` ## Schema @@ -363,4 +229,4 @@ Usage: - Typically, this is the user's email address or User Principal Name (UPN) - Ensure the user has appropriate permissions for the required operations -Can be set using the `M365_USERNAME` environment variable. \ No newline at end of file +Can be set using the `M365_USERNAME` environment variable. diff --git a/templates/index.md.tmpl b/docs/index.md.tmpl.back similarity index 100% rename from templates/index.md.tmpl rename to docs/index.md.tmpl.back diff --git a/docs/resources/graph_beta_device_and_app_management_m365_apps_installation_options.md b/docs/resources/graph_beta_device_and_app_management_m365_apps_installation_options.md new file mode 100644 index 00000000..42044c84 --- /dev/null +++ b/docs/resources/graph_beta_device_and_app_management_m365_apps_installation_options.md @@ -0,0 +1,60 @@ +--- +page_title: "Resource: microsoft365_graph_beta_device_and_app_management_m365_apps_installation_options" +description: |- + +--- + +# Resource: microsoft365_graph_beta_device_and_app_management_m365_apps_installation_options + + + + + + +## Schema + +### Required + +- `apps_for_mac` (Attributes) The Microsoft 365 apps installation options container object for a MAC platform. (see [below for nested schema](#nestedatt--apps_for_mac)) +- `apps_for_windows` (Attributes) The Microsoft 365 apps installation options container object for a Windows platform. (see [below for nested schema](#nestedatt--apps_for_windows)) +- `update_channel` (String) Specifies how often users get feature updates for Microsoft 365 apps installed on devices running Windows. The possible values are: `current`, `monthlyEnterprise`, or `semiAnnual`, with corresponding update frequencies of `As soon as they're ready`, `Once a month`, and `Every six months`. + +### Optional + +- `timeouts` (Attributes) (see [below for nested schema](#nestedatt--timeouts)) + +### Read-Only + +- `id` (String) The unique identifier for the M365AppsInstallationOptions. + + +### Nested Schema for `apps_for_mac` + +Required: + +- `is_microsoft_365_apps_enabled` (Boolean) Specifies whether users can install Microsoft 365 apps on their MAC devices. The default value is `true`. +- `is_skype_for_business_enabled` (Boolean) Specifies whether users can install Skype for Business on their MAC devices running OS X El Capitan 10.11 or later. The default value is `true`. + + + +### Nested Schema for `apps_for_windows` + +Required: + +- `is_microsoft_365_apps_enabled` (Boolean) Specifies whether users can install Microsoft 365 apps, including Skype for Business, on their Windows devices. The default value is `true`. +- `is_project_enabled` (Boolean) Specifies whether users can install Microsoft Project on their Windows devices. The default value is `true`. +- `is_skype_for_business_enabled` (Boolean) Specifies whether users can install Skype for Business (standalone) on their Windows devices. The default value is `true`. +- `is_visio_enabled` (Boolean) Specifies whether users can install Visio on their Windows devices. The default value is `true`. + + + +### 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). + + diff --git a/docs/resources/graph_cloud_pc_device_image.md b/docs/resources/graph_device_and_app_management_cloud_pc_device_image.md similarity index 95% rename from docs/resources/graph_cloud_pc_device_image.md rename to docs/resources/graph_device_and_app_management_cloud_pc_device_image.md index bbcad507..5acc1db2 100644 --- a/docs/resources/graph_cloud_pc_device_image.md +++ b/docs/resources/graph_device_and_app_management_cloud_pc_device_image.md @@ -1,10 +1,10 @@ --- -page_title: "Resource: microsoft365_graph_cloud_pc_device_image" +page_title: "Resource: microsoft365_graph_device_and_app_management_cloud_pc_device_image" description: |- --- -# Resource: microsoft365_graph_cloud_pc_device_image +# Resource: microsoft365_graph_device_and_app_management_cloud_pc_device_image diff --git a/docs/resources/graph_cloud_pc_provisioning_policy.md b/docs/resources/graph_device_and_app_management_cloud_pc_provisioning_policy.md similarity index 97% rename from docs/resources/graph_cloud_pc_provisioning_policy.md rename to docs/resources/graph_device_and_app_management_cloud_pc_provisioning_policy.md index 0f12f80e..95560881 100644 --- a/docs/resources/graph_cloud_pc_provisioning_policy.md +++ b/docs/resources/graph_device_and_app_management_cloud_pc_provisioning_policy.md @@ -1,10 +1,10 @@ --- -page_title: "Resource: microsoft365_graph_cloud_pc_provisioning_policy" +page_title: "Resource: microsoft365_graph_device_and_app_management_cloud_pc_provisioning_policy" description: |- --- -# Resource: microsoft365_graph_cloud_pc_provisioning_policy +# Resource: microsoft365_graph_device_and_app_management_cloud_pc_provisioning_policy diff --git a/docs/resources/graph_cloud_pc_user_setting.md b/docs/resources/graph_device_and_app_management_cloud_pc_user_setting.md similarity index 95% rename from docs/resources/graph_cloud_pc_user_setting.md rename to docs/resources/graph_device_and_app_management_cloud_pc_user_setting.md index 53eaae76..16b187cb 100644 --- a/docs/resources/graph_cloud_pc_user_setting.md +++ b/docs/resources/graph_device_and_app_management_cloud_pc_user_setting.md @@ -1,10 +1,10 @@ --- -page_title: "Resource: microsoft365_graph_cloud_pc_user_setting" +page_title: "Resource: microsoft365_graph_device_and_app_management_cloud_pc_user_setting" description: |- --- -# Resource: microsoft365_graph_cloud_pc_user_setting +# Resource: microsoft365_graph_device_and_app_management_cloud_pc_user_setting diff --git a/examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_browser_site/resource.tf b/examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_browser_site/resource.tf new file mode 100644 index 00000000..8a650171 --- /dev/null +++ b/examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_browser_site/resource.tf @@ -0,0 +1,15 @@ +resource "microsoft365_graph_beta_device_and_app_management_browser_site" "example" { + allow_redirect = true + comment = "Example browser site for Contoso" + compatibility_mode = "default" + merge_type = "default" + target_environment = "internetExplorerMode" + web_url = "https://www.contoso.com" + + timeouts { + create = "30m" + read = "10m" + update = "30m" + delete = "10m" + } +} \ No newline at end of file diff --git a/internal/resources/device_and_app_management/beta/browser_site/construct.go b/internal/resources/device_and_app_management/beta/browser_site/construct.go new file mode 100644 index 00000000..6949eb19 --- /dev/null +++ b/internal/resources/device_and_app_management/beta/browser_site/construct.go @@ -0,0 +1,159 @@ +package graphbetabrowsersite + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/hashicorp/terraform-plugin-log/tflog" + models "github.com/microsoftgraph/msgraph-beta-sdk-go/models" +) + +func constructResource(ctx context.Context, data *BrowserSiteResourceModel) (models.BrowserSiteable, error) { + tflog.Debug(ctx, "Constructing BrowserSite resource") + + site := models.NewBrowserSite() + + if !data.AllowRedirect.IsNull() && !data.AllowRedirect.IsUnknown() { + allowRedirect := data.AllowRedirect.ValueBool() + site.SetAllowRedirect(&allowRedirect) + } + + if !data.Comment.IsNull() && !data.Comment.IsUnknown() { + comment := data.Comment.ValueString() + site.SetComment(&comment) + } + + if !data.CompatibilityMode.IsNull() && !data.CompatibilityMode.IsUnknown() { + compatibilityModeStr := data.CompatibilityMode.ValueString() + compatibilityModeAny, err := models.ParseBrowserSiteCompatibilityMode(compatibilityModeStr) + if err != nil { + return nil, fmt.Errorf("error parsing CompatibilityMode: %v", err) + } + if compatibilityModeAny != nil { + compatibilityMode, ok := compatibilityModeAny.(*models.BrowserSiteCompatibilityMode) + if !ok { + return nil, fmt.Errorf("unexpected type for CompatibilityMode: %T", compatibilityModeAny) + } + site.SetCompatibilityMode(compatibilityMode) + } + } + + if !data.MergeType.IsNull() && !data.MergeType.IsUnknown() { + mergeTypeStr := data.MergeType.ValueString() + mergeTypeAny, err := models.ParseBrowserSiteMergeType(mergeTypeStr) + if err != nil { + return nil, fmt.Errorf("error parsing MergeType: %v", err) + } + if mergeTypeAny != nil { + mergeType, ok := mergeTypeAny.(*models.BrowserSiteMergeType) + if !ok { + return nil, fmt.Errorf("unexpected type for MergeType: %T", mergeTypeAny) + } + site.SetMergeType(mergeType) + } + } + + if !data.TargetEnvironment.IsNull() && !data.TargetEnvironment.IsUnknown() { + targetEnvironmentStr := data.TargetEnvironment.ValueString() + targetEnvironmentAny, err := models.ParseBrowserSiteTargetEnvironment(targetEnvironmentStr) + if err != nil { + return nil, fmt.Errorf("error parsing TargetEnvironment: %v", err) + } + if targetEnvironmentAny != nil { + targetEnvironment, ok := targetEnvironmentAny.(*models.BrowserSiteTargetEnvironment) + if !ok { + return nil, fmt.Errorf("unexpected type for TargetEnvironment: %T", targetEnvironmentAny) + } + site.SetTargetEnvironment(targetEnvironment) + } + } + + if !data.WebUrl.IsNull() && !data.WebUrl.IsUnknown() { + webUrl := data.WebUrl.ValueString() + site.SetWebUrl(&webUrl) + } + + requestBodyJSON, err := json.MarshalIndent(site, "", " ") + if err != nil { + return nil, fmt.Errorf("error marshalling request body to JSON: %s", err) + } + + tflog.Debug(ctx, "Constructed BrowserSite resource:\n"+string(requestBodyJSON)) + + return site, nil +} + +func constructHistory(ctx context.Context, history []BrowserSiteHistoryModel) ([]models.BrowserSiteHistoryable, error) { + var constructedHistory []models.BrowserSiteHistoryable + + for _, historyItem := range history { + newHistoryItem := models.NewBrowserSiteHistory() + + if !historyItem.AllowRedirect.IsNull() && !historyItem.AllowRedirect.IsUnknown() { + allowRedirect := historyItem.AllowRedirect.ValueBool() + newHistoryItem.SetAllowRedirect(&allowRedirect) + } + + if !historyItem.Comment.IsNull() && !historyItem.Comment.IsUnknown() { + comment := historyItem.Comment.ValueString() + newHistoryItem.SetComment(&comment) + } + + if !historyItem.CompatibilityMode.IsNull() && !historyItem.CompatibilityMode.IsUnknown() { + compatibilityModeStr := historyItem.CompatibilityMode.ValueString() + compatibilityModeAny, err := models.ParseBrowserSiteCompatibilityMode(compatibilityModeStr) + if err != nil { + return nil, fmt.Errorf("error parsing CompatibilityMode in history: %v", err) + } + if compatibilityModeAny != nil { + compatibilityMode, ok := compatibilityModeAny.(*models.BrowserSiteCompatibilityMode) + if !ok { + return nil, fmt.Errorf("unexpected type for CompatibilityMode in history: %T", compatibilityModeAny) + } + newHistoryItem.SetCompatibilityMode(compatibilityMode) + } + } + + if !historyItem.MergeType.IsNull() && !historyItem.MergeType.IsUnknown() { + mergeTypeStr := historyItem.MergeType.ValueString() + mergeTypeAny, err := models.ParseBrowserSiteMergeType(mergeTypeStr) + if err != nil { + return nil, fmt.Errorf("error parsing MergeType in history: %v", err) + } + if mergeTypeAny != nil { + mergeType, ok := mergeTypeAny.(*models.BrowserSiteMergeType) + if !ok { + return nil, fmt.Errorf("unexpected type for MergeType in history: %T", mergeTypeAny) + } + newHistoryItem.SetMergeType(mergeType) + } + } + + if !historyItem.TargetEnvironment.IsNull() && !historyItem.TargetEnvironment.IsUnknown() { + targetEnvironmentStr := historyItem.TargetEnvironment.ValueString() + targetEnvironmentAny, err := models.ParseBrowserSiteTargetEnvironment(targetEnvironmentStr) + if err != nil { + return nil, fmt.Errorf("error parsing TargetEnvironment in history: %v", err) + } + if targetEnvironmentAny != nil { + targetEnvironment, ok := targetEnvironmentAny.(*models.BrowserSiteTargetEnvironment) + if !ok { + return nil, fmt.Errorf("unexpected type for TargetEnvironment in history: %T", targetEnvironmentAny) + } + newHistoryItem.SetTargetEnvironment(targetEnvironment) + } + } + + constructedHistory = append(constructedHistory, newHistoryItem) + } + + historyJSON, err := json.MarshalIndent(constructedHistory, "", " ") + if err != nil { + return nil, fmt.Errorf("error marshalling history to JSON: %s", err) + } + + tflog.Debug(ctx, "Constructed BrowserSite history:\n"+string(historyJSON)) + + return constructedHistory, nil +} diff --git a/internal/resources/device_and_app_management/beta/browser_site/crud.go b/internal/resources/device_and_app_management/beta/browser_site/crud.go new file mode 100644 index 00000000..0fd1f2c4 --- /dev/null +++ b/internal/resources/device_and_app_management/beta/browser_site/crud.go @@ -0,0 +1,183 @@ +package graphbetabrowsersite + +import ( + "context" + "fmt" + "time" + + "github.com/deploymenttheory/terraform-provider-microsoft365/internal/resources/common/crud" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-log/tflog" +) + +// Create handles the Create operation. +func (r *BrowserSiteResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + var plan BrowserSiteResourceModel + + tflog.Debug(ctx, fmt.Sprintf("Starting creation of resource: %s_%s", r.ProviderTypeName, r.TypeName)) + + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + if resp.Diagnostics.HasError() { + return + } + + ctx, cancel := crud.HandleTimeout(ctx, plan.Timeouts.Create, 30*time.Second, &resp.Diagnostics) + if cancel == nil { + return + } + defer cancel() + + requestBody, err := constructResource(ctx, &plan) + if err != nil { + resp.Diagnostics.AddError( + "Error constructing browser site", + fmt.Sprintf("Could not construct resource: %s_%s: %s", r.ProviderTypeName, r.TypeName, err.Error()), + ) + return + } + + browserSiteListId := "default" // TODO figure out how to get this id + + createdSite, err := r.client.Admin().Edge().InternetExplorerMode().SiteLists().ByBrowserSiteListId(browserSiteListId).Sites().Post(ctx, requestBody, nil) + if err != nil { + resp.Diagnostics.AddError( + "Error creating browser site", + fmt.Sprintf("Could not create browser site: %s", err.Error()), + ) + return + } + + plan.ID = types.StringValue(*createdSite.GetId()) + + MapRemoteStateToTerraform(ctx, &plan, createdSite) + + resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) + + tflog.Debug(ctx, fmt.Sprintf("Finished Create Method: %s_%s", r.ProviderTypeName, r.TypeName)) +} + +// Read handles the Read operation. +func (r *BrowserSiteResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var state BrowserSiteResourceModel + tflog.Debug(ctx, "Starting Read method for browser site") + + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + + if resp.Diagnostics.HasError() { + return + } + + tflog.Debug(ctx, fmt.Sprintf("Reading browser site with ID: %s", state.ID.ValueString())) + + ctx, cancel := crud.HandleTimeout(ctx, state.Timeouts.Read, 30*time.Second, &resp.Diagnostics) + if cancel == nil { + return + } + defer cancel() + // TODO figure out how to get this id + // Assuming we have a default or known browserSiteList-id + // You may need to implement logic to determine the correct browserSiteList-id + browserSiteListId := "default" // or some other way to determine the correct ID + + browserSite, err := r.client.Admin().Edge().InternetExplorerMode().SiteLists(). + ByBrowserSiteListId(browserSiteListId). + Sites(). + ByBrowserSiteId(state.ID.ValueString()). + Get(ctx, nil) + + if err != nil { + crud.HandleReadErrorIfNotFound(ctx, resp, r, &state, err) + return + } + + MapRemoteStateToTerraform(ctx, &state, browserSite) + resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) + tflog.Debug(ctx, fmt.Sprintf("Finished Read Method: %s_%s", r.ProviderTypeName, r.TypeName)) +} + +// Update handles the Update operation. +func (r *BrowserSiteResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + var plan BrowserSiteResourceModel + + tflog.Debug(ctx, fmt.Sprintf("Starting Update of resource: %s_%s", r.ProviderTypeName, r.TypeName)) + + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + if resp.Diagnostics.HasError() { + return + } + + ctx, cancel := crud.HandleTimeout(ctx, plan.Timeouts.Update, 30*time.Second, &resp.Diagnostics) + if cancel == nil { + return + } + defer cancel() + + requestBody, err := constructResource(ctx, &plan) + if err != nil { + resp.Diagnostics.AddError( + "Error constructing browser site", + fmt.Sprintf("Could not construct resource: %s_%s: %s", r.ProviderTypeName, r.TypeName, err.Error()), + ) + return + } + + // Assuming we have a default or known browserSiteList-id + // You may need to implement logic to determine the correct browserSiteList-id + browserSiteListId := "default" // or some other way to determine the correct ID + + _, err = r.client.Admin().Edge().InternetExplorerMode().SiteLists(). + ByBrowserSiteListId(browserSiteListId). + Sites(). + ByBrowserSiteId(plan.ID.ValueString()). + Patch(ctx, requestBody, nil) + + if err != nil { + crud.HandleUpdateErrorIfNotFound(ctx, resp, r, &plan, err) + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) + + tflog.Debug(ctx, fmt.Sprintf("Finished Update Method: %s_%s", r.ProviderTypeName, r.TypeName)) +} + +// Delete handles the Delete operation. +func (r *BrowserSiteResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + var data BrowserSiteResourceModel + + tflog.Debug(ctx, fmt.Sprintf("Starting deletion of resource: %s_%s", r.ProviderTypeName, r.TypeName)) + + resp.Diagnostics.Append(req.State.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + + ctx, cancel := crud.HandleTimeout(ctx, data.Timeouts.Delete, 30*time.Second, &resp.Diagnostics) + if cancel == nil { + return + } + defer cancel() + + // Assuming we have a default or known browserSiteList-id + // You may need to implement logic to determine the correct browserSiteList-id + browserSiteListId := "default" // or some other way to determine the correct ID + + err := r.client.Admin().Edge().InternetExplorerMode().SiteLists(). + ByBrowserSiteListId(browserSiteListId). + Sites(). + ByBrowserSiteId(data.ID.ValueString()). + Delete(ctx, nil) + + if err != nil { + resp.Diagnostics.AddError( + fmt.Sprintf("Client error when deleting %s_%s", r.ProviderTypeName, r.TypeName), + err.Error(), + ) + return + } + + tflog.Debug(ctx, fmt.Sprintf("Finished Delete Method: %s_%s", r.ProviderTypeName, r.TypeName)) + + resp.State.RemoveResource(ctx) +} diff --git a/internal/resources/device_and_app_management/beta/browser_site/model.go b/internal/resources/device_and_app_management/beta/browser_site/model.go new file mode 100644 index 00000000..5e73ca18 --- /dev/null +++ b/internal/resources/device_and_app_management/beta/browser_site/model.go @@ -0,0 +1,52 @@ +package graphbetabrowsersite + +import ( + "github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +type BrowserSiteResourceModel struct { + ID types.String `tfsdk:"id"` + AllowRedirect types.Bool `tfsdk:"allow_redirect"` + Comment types.String `tfsdk:"comment"` + CompatibilityMode types.String `tfsdk:"compatibility_mode"` + CreatedDateTime types.String `tfsdk:"created_date_time"` + DeletedDateTime types.String `tfsdk:"deleted_date_time"` + History []BrowserSiteHistoryModel `tfsdk:"history"` + LastModifiedBy IdentitySetModel `tfsdk:"last_modified_by"` + LastModifiedDateTime types.String `tfsdk:"last_modified_date_time"` + MergeType types.String `tfsdk:"merge_type"` + Status types.String `tfsdk:"status"` + TargetEnvironment types.String `tfsdk:"target_environment"` + WebUrl types.String `tfsdk:"web_url"` + Timeouts timeouts.Value `tfsdk:"timeouts"` +} + +type BrowserSiteHistoryModel struct { + AllowRedirect types.Bool `tfsdk:"allow_redirect"` + Comment types.String `tfsdk:"comment"` + CompatibilityMode types.String `tfsdk:"compatibility_mode"` + LastModifiedBy IdentitySetModel `tfsdk:"last_modified_by"` + MergeType types.String `tfsdk:"merge_type"` + PublishedDateTime types.String `tfsdk:"published_date_time"` + TargetEnvironment types.String `tfsdk:"target_environment"` +} + +type IdentitySetModel struct { + Application IdentityModel `tfsdk:"application"` + ApplicationInstance IdentityModel `tfsdk:"application_instance"` + Conversation IdentityModel `tfsdk:"conversation"` + ConversationIdentityType IdentityModel `tfsdk:"conversation_identity_type"` + Device IdentityModel `tfsdk:"device"` + Encrypted IdentityModel `tfsdk:"encrypted"` + OnPremises IdentityModel `tfsdk:"on_premises"` + Guest IdentityModel `tfsdk:"guest"` + Phone IdentityModel `tfsdk:"phone"` + User IdentityModel `tfsdk:"user"` +} + +type IdentityModel struct { + DisplayName types.String `tfsdk:"display_name"` + ID types.String `tfsdk:"id"` + TenantID types.String `tfsdk:"tenant_id"` +} diff --git a/internal/resources/device_and_app_management/beta/browser_site/resource.go b/internal/resources/device_and_app_management/beta/browser_site/resource.go new file mode 100644 index 00000000..4e0353bb --- /dev/null +++ b/internal/resources/device_and_app_management/beta/browser_site/resource.go @@ -0,0 +1,149 @@ +package graphbetabrowsersite + +import ( + "context" + + "github.com/deploymenttheory/terraform-provider-microsoft365/internal/resources/common" + commonschema "github.com/deploymenttheory/terraform-provider-microsoft365/internal/resources/common/schema" + "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" + + msgraphbetasdk "github.com/microsoftgraph/msgraph-beta-sdk-go" +) + +// Ensure provider defined types fully satisfy framework interfaces +var _ resource.Resource = &BrowserSiteResource{} +var _ resource.ResourceWithConfigure = &BrowserSiteResource{} +var _ resource.ResourceWithImportState = &BrowserSiteResource{} + +func NewBrowserSiteResource() resource.Resource { + return &BrowserSiteResource{} +} + +type BrowserSiteResource struct { + client *msgraphbetasdk.GraphServiceClient + ProviderTypeName string + TypeName string +} + +// GetID returns the ID of a resource from the state model. +func (s *BrowserSiteResourceModel) GetID() string { + return s.ID.ValueString() +} + +// GetTypeName returns the type name of the resource from the state model. +func (r *BrowserSiteResource) GetTypeName() string { + return r.TypeName +} + +// Metadata returns the resource type name. +func (r *BrowserSiteResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_graph_beta_device_and_app_management_browser_site" +} + +// Configure sets the client for the resource. +func (r *BrowserSiteResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { + r.client = common.SetGraphBetaClientForResource(ctx, req, resp, r.TypeName) +} + +// ImportState imports the resource state. +func (r *BrowserSiteResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) +} + +func (r *BrowserSiteResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Description: "Manages a browser site in Microsoft Intune.", + Attributes: map[string]schema.Attribute{ + "id": schema.StringAttribute{ + Description: "The unique identifier for the site.", + Computed: true, + }, + "allow_redirect": schema.BoolAttribute{ + Description: "Controls the behavior of redirected sites. If `true`, indicates that the site will open in Internet Explorer 11 or Microsoft Edge even if the site is navigated to as part of a HTTP or meta refresh redirection chain.", + Required: true, + }, + "comment": schema.StringAttribute{ + Description: "The comment for the site.", + Optional: true, + }, + "compatibility_mode": schema.StringAttribute{ + Description: "Controls what compatibility setting is used for specific sites or domains.", + Required: true, + Validators: []validator.String{ + stringvalidator.OneOf("default", "internetExplorer8Enterprise", "internetExplorer7Enterprise", "internetExplorer11", "internetExplorer10", "internetExplorer9", "internetExplorer8", "internetExplorer7", "internetExplorer5", "unknownFutureValue"), + }, + }, + "created_date_time": schema.StringAttribute{ + Description: "The date and time when the site was created.", + Computed: true, + }, + "deleted_date_time": schema.StringAttribute{ + Description: "The date and time when the site was deleted.", + Computed: true, + }, + "history": schema.ListNestedAttribute{ + Description: "The history of modifications applied to the site.", + Computed: true, + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "allow_redirect": schema.BoolAttribute{ + Description: "Controls the behavior of redirected sites for this history entry.", + Computed: true, + }, + "comment": schema.StringAttribute{ + Description: "The comment for this history entry.", + Computed: true, + }, + "compatibility_mode": schema.StringAttribute{ + Description: "The compatibility mode for this history entry.", + Computed: true, + }, + "merge_type": schema.StringAttribute{ + Description: "The merge type for this history entry.", + Computed: true, + }, + "published_date_time": schema.StringAttribute{ + Description: "The date and time when this history entry was published.", + Computed: true, + }, + "target_environment": schema.StringAttribute{ + Description: "The target environment for this history entry.", + Computed: true, + }, + }, + }, + }, + "last_modified_date_time": schema.StringAttribute{ + Description: "The date and time when the site was last modified.", + Computed: true, + }, + "merge_type": schema.StringAttribute{ + Description: "The merge type of the site.", + Required: true, + Validators: []validator.String{ + stringvalidator.OneOf("noMerge", "default", "unknownFutureValue"), + }, + }, + "status": schema.StringAttribute{ + Description: "Indicates the status of the site.", + Computed: true, + }, + "target_environment": schema.StringAttribute{ + Description: "The target environment that the site should open in.", + Required: true, + Validators: []validator.String{ + stringvalidator.OneOf("internetExplorerMode", "internetExplorer11", "microsoftEdge", "configurable", "none", "unknownFutureValue"), + }, + }, + "web_url": schema.StringAttribute{ + Description: "The URL of the site.", + Required: true, + }, + "timeouts": commonschema.Timeouts(ctx), + }, + } +} diff --git a/internal/resources/device_and_app_management/beta/browser_site/resource_model.json b/internal/resources/device_and_app_management/beta/browser_site/resource_model.json new file mode 100644 index 00000000..c881f5de --- /dev/null +++ b/internal/resources/device_and_app_management/beta/browser_site/resource_model.json @@ -0,0 +1,101 @@ +{ + "@odata.type": "#microsoft.graph.browserSite", + "allowRedirect": "Boolean", + "comment": "String", + "compatibilityMode": "String", + "createdDateTime": "String (timestamp)", + "deletedDateTime": "String (timestamp)", + "history": [ + { + "@odata.type": "#microsoft.graph.browserSiteHistory", + "allowRedirect": "Boolean", + "comment": "String", + "compatibilityMode": "String", + "lastModifiedBy": { + "@odata.type": "microsoft.graph.identitySet", + "application": { + "@odata.type": "microsoft.graph.identity", + "displayName": "String", + "id": "String (identifier)", + "tenantId": "String" + }, + "applicationInstance": { + "@odata.type": "microsoft.graph.identity", + "displayName": "String", + "id": "String (identifier)", + "tenantId": "String" + }, + "conversation": { + "@odata.type": "microsoft.graph.identity", + "displayName": "String", + "id": "String (identifier)", + "tenantId": "String" + }, + "conversationIdentityType": { + "@odata.type": "microsoft.graph.identity", + "displayName": "String", + "id": "String (identifier)", + "tenantId": "String" + }, + "device": { + "@odata.type": "microsoft.graph.identity", + "displayName": "String", + "id": "String (identifier)", + "tenantId": "String" + }, + "encrypted": { + "@odata.type": "microsoft.graph.identity", + "displayName": "String", + "id": "String (identifier)", + "tenantId": "String" + }, + "onPremises": { + "@odata.type": "microsoft.graph.identity", + "displayName": "String", + "id": "String (identifier)", + "tenantId": "String" + }, + "guest": { + "@odata.type": "microsoft.graph.identity", + "displayName": "String", + "id": "String (identifier)", + "tenantId": "String" + }, + "phone": { + "@odata.type": "microsoft.graph.identity", + "displayName": "String", + "id": "String (identifier)", + "tenantId": "String" + }, + "user": { + "@odata.type": "microsoft.graph.identity", + "displayName": "String", + "id": "String (identifier)", + "tenantId": "String" + } + }, + "mergeType": "String", + "publishedDateTime": "String (timestamp)", + "targetEnvironment": "String" + } + ], + "id": "String (identifier)", + "lastModifiedBy": { + "@odata.type": "microsoft.graph.identitySet", + "application": {"@odata.type": "microsoft.graph.identity"}, + "applicationInstance": {"@odata.type": "microsoft.graph.identity"}, + "conversation": {"@odata.type": "microsoft.graph.identity"}, + "conversationIdentityType": {"@odata.type": "microsoft.graph.identity"}, + "device": {"@odata.type": "microsoft.graph.identity"}, + "encrypted": {"@odata.type": "microsoft.graph.identity"}, + "onPremises": {"@odata.type": "microsoft.graph.identity"}, + "guest": {"@odata.type": "microsoft.graph.identity"}, + "phone": {"@odata.type": "microsoft.graph.identity"}, + "user": {"@odata.type": "microsoft.graph.identity"} + }, + "lastModifiedDateTime": "String (timestamp)", + "mergeType": "String", + "status": "String", + "targetEnvironment": "String", + "webUrl": "String" +} \ No newline at end of file diff --git a/internal/resources/device_and_app_management/beta/browser_site/state.go b/internal/resources/device_and_app_management/beta/browser_site/state.go new file mode 100644 index 00000000..590dba0b --- /dev/null +++ b/internal/resources/device_and_app_management/beta/browser_site/state.go @@ -0,0 +1,99 @@ +package graphbetabrowsersite + +import ( + "context" + + "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" +) + +func MapRemoteStateToTerraform(ctx context.Context, data *BrowserSiteResourceModel, remoteResource models.BrowserSiteable) { + if remoteResource == nil { + tflog.Debug(ctx, "Remote resource is nil") + return + } + + tflog.Debug(ctx, "Starting to map remote state to Terraform state", map[string]interface{}{ + "resourceId": state.StringPtrToString(remoteResource.GetId()), + }) + + data.ID = types.StringValue(state.StringPtrToString(remoteResource.GetId())) + data.AllowRedirect = types.BoolValue(state.BoolPtrToBool(remoteResource.GetAllowRedirect())) + data.Comment = types.StringValue(state.StringPtrToString(remoteResource.GetComment())) + data.CompatibilityMode = state.EnumPtrToTypeString(remoteResource.GetCompatibilityMode()) + data.CreatedDateTime = state.TimeToString(remoteResource.GetCreatedDateTime()) + data.DeletedDateTime = state.TimeToString(remoteResource.GetDeletedDateTime()) + data.LastModifiedDateTime = state.TimeToString(remoteResource.GetLastModifiedDateTime()) + data.MergeType = state.EnumPtrToTypeString(remoteResource.GetMergeType()) + data.Status = state.EnumPtrToTypeString(remoteResource.GetStatus()) + data.TargetEnvironment = state.EnumPtrToTypeString(remoteResource.GetTargetEnvironment()) + data.WebUrl = types.StringValue(state.StringPtrToString(remoteResource.GetWebUrl())) + + // Handle History + history := remoteResource.GetHistory() + if len(history) == 0 { + data.History = []BrowserSiteHistoryModel{} + } else { + data.History = make([]BrowserSiteHistoryModel, len(history)) + for i, historyItem := range history { + data.History[i] = MapHistoryRemoteStateToTerraform(historyItem) + } + } + + // Handle LastModifiedBy + if lastModifiedBy := remoteResource.GetLastModifiedBy(); lastModifiedBy != nil { + data.LastModifiedBy = MapIdentitySetRemoteStateToTerraform(lastModifiedBy) + } + + tflog.Debug(ctx, "Finished mapping remote state to Terraform state", map[string]interface{}{ + "resourceId": data.ID.ValueString(), + }) +} + +func MapHistoryRemoteStateToTerraform(historyItem models.BrowserSiteHistoryable) BrowserSiteHistoryModel { + return BrowserSiteHistoryModel{ + AllowRedirect: types.BoolValue(state.BoolPtrToBool(historyItem.GetAllowRedirect())), + Comment: types.StringValue(state.StringPtrToString(historyItem.GetComment())), + CompatibilityMode: state.EnumPtrToTypeString(historyItem.GetCompatibilityMode()), + LastModifiedBy: MapIdentitySetRemoteStateToTerraform(historyItem.GetLastModifiedBy()), + MergeType: state.EnumPtrToTypeString(historyItem.GetMergeType()), + PublishedDateTime: state.TimeToString(historyItem.GetPublishedDateTime()), + TargetEnvironment: state.EnumPtrToTypeString(historyItem.GetTargetEnvironment()), + } +} + +func MapIdentitySetRemoteStateToTerraform(identitySet models.IdentitySetable) IdentitySetModel { + if identitySet == nil { + return IdentitySetModel{} + } + + return IdentitySetModel{ + Application: MapIdentityRemoteStateToTerraform(identitySet.GetApplication()), + User: MapIdentityRemoteStateToTerraform(identitySet.GetUser()), + Device: MapIdentityRemoteStateToTerraform(identitySet.GetDevice()), + // TODO - not in SDK + // Encrypted: MapIdentityRemoteStateToTerraform(identitySet.GetEncrypted()), + // OnPremises: MapIdentityRemoteStateToTerraform(identitySet.GetOnPremises()), + // Guest: MapIdentityRemoteStateToTerraform(identitySet.GetGuest()), + // Phone: MapIdentityRemoteStateToTerraform(identitySet.GetPhone()), + // ApplicationInstance: MapIdentityRemoteStateToTerraform(identitySet.GetApplicationInstance()), + // Conversation: MapIdentityRemoteStateToTerraform(identitySet.GetConversation()), + // ConversationIdentityType: MapIdentityRemoteStateToTerraform(identitySet.GetConversation()), + + } +} + +func MapIdentityRemoteStateToTerraform(identity models.Identityable) IdentityModel { + if identity == nil { + return IdentityModel{} + } + + return IdentityModel{ + DisplayName: types.StringValue(state.StringPtrToString(identity.GetDisplayName())), + ID: types.StringValue(state.StringPtrToString(identity.GetId())), + // TODO - field missing from SDK + //TenantID: types.StringValue(state.StringPtrToString(identity.GetTenantId())), + } +} diff --git a/templates/index.md.tmpl.back b/templates/index.md.tmpl.back new file mode 100644 index 00000000..dfc79a48 --- /dev/null +++ b/templates/index.md.tmpl.back @@ -0,0 +1,16 @@ +--- +page_title: "Provider: m365" +description: |- + The m365 provider is used to manage m365 resources. +--- + +# m365 Provider + +The Terraform m365 msgraph provider is a plugin for Terraform that allows for the +management of [m365](https://github.com/microsoftgraph/msgraph-metadata) resources. + +## Example Usage + +{{ tffile "examples/main.tf" }} + +{{ .SchemaMarkdown | trimspace }} \ No newline at end of file From b0632a9e13fa6edd09f53fb0ad8b7effcd2f2f37 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 5 Sep 2024 16:31:55 +0000 Subject: [PATCH 2/3] terraform-docs: automated action --- .../README.md | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_browser_site/README.md diff --git a/examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_browser_site/README.md b/examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_browser_site/README.md new file mode 100644 index 00000000..dd8b003f --- /dev/null +++ b/examples/microsoft365_graph_beta/microsoft365_graph_beta_device_and_app_management_browser_site/README.md @@ -0,0 +1,29 @@ + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [microsoft365](#provider_microsoft365) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [microsoft365_graph_beta_device_and_app_management_browser_site.example](https://registry.terraform.io/providers/hashicorp/microsoft365/latest/docs/resources/graph_beta_device_and_app_management_browser_site) | resource | + +## Inputs + +No inputs. + +## Outputs + +No outputs. + \ No newline at end of file From 65e34ca9b9da6d2b57a5b3d350b27f598edc7fdb Mon Sep 17 00:00:00 2001 From: ShocOne Date: Thu, 5 Sep 2024 17:33:45 +0100 Subject: [PATCH 3/3] docs --- docs/provider.md | 138 +++++++++++++++++++++++++++++++++++++ templates/provider.md.tmpl | 16 +++++ 2 files changed, 154 insertions(+) create mode 100644 docs/provider.md create mode 100644 templates/provider.md.tmpl diff --git a/docs/provider.md b/docs/provider.md new file mode 100644 index 00000000..b587d5ac --- /dev/null +++ b/docs/provider.md @@ -0,0 +1,138 @@ +--- +page_title: "Provider: m365" +description: |- + The m365 provider is used to manage m365 resources. +--- + +# m365 Provider + +The Terraform m365 msgraph provider is a plugin for Terraform that allows for the +management of [m365](https://github.com/microsoftgraph/msgraph-metadata) resources. + +## Example Usage + +```terraform +# Example backend +terraform { + required_providers { + microsoft365 = { + source = "deploymenttheory/terraform-provider-microsoft365" + version = "~> 1.0.0" + } + } +} + +# Example provider +provider "microsoft365" { + tenant_id = var.tenant_id + auth_method = var.auth_method + client_id = var.client_id + client_secret = var.client_secret + client_certificate = var.client_certificate + client_certificate_password = var.client_certificate_password + username = var.username + password = var.password + redirect_url = var.redirect_url + use_proxy = var.use_proxy + proxy_url = var.proxy_url + cloud = var.cloud + enable_chaos = var.enable_chaos + telemetry_optout = var.telemetry_optout + debug_mode = var.debug_mode +} + +variable "cloud" { + description = "The cloud to use for authentication and Graph / Graph Beta API requests. Default is `public`. Valid values are `public`, `gcc`, `gcchigh`, `china`, `dod`, `ex`, `rx`. Can also be set using the `M365_CLOUD` environment variable." + type = string + default = "public" +} + +variable "tenant_id" { + description = "The M365 tenant ID for the Entra ID application. This ID uniquely identifies your Entra ID (EID) instance. It can be found in the Azure portal under Entra ID > Properties. Can also be set using the `M365_TENANT_ID` environment variable." + type = string + default = "" +} + +variable "auth_method" { + description = "The authentication method to use for the Entra ID application to authenticate the provider. Options: 'device_code', 'client_secret', 'client_certificate', 'interactive_browser', 'username_password'. Can also be set using the `M365_AUTH_METHOD` environment variable." + type = string + default = "client_secret" +} + +variable "client_id" { + description = "The client ID for the Entra ID application. This ID is generated when you register an application in the Entra ID (Azure AD) and can be found under App registrations > YourApp > Overview. Can also be set using the `M365_CLIENT_ID` environment variable." + type = string + default = "" +} + +variable "client_secret" { + description = "The client secret for the Entra ID application. This secret is generated in the Entra ID (Azure AD) and is required for authentication flows such as client credentials and on-behalf-of flows. It can be found under App registrations > YourApp > Certificates & secrets. Required for client credentials and on-behalf-of flows. Can also be set using the `M365_CLIENT_SECRET` environment variable." + type = string + sensitive = true + default = "" +} + +variable "client_certificate" { + description = "The path to the Client Certificate associated with the Service Principal for use when authenticating as a Service Principal using a Client Certificate. Can also be set using the `M365_CLIENT_CERTIFICATE_FILE_PATH` environment variable." + type = string + sensitive = true + default = "" +} + +variable "client_certificate_password" { + description = "The password associated with the Client Certificate. For use when authenticating as a Service Principal using a Client Certificate. Can also be set using the `M365_CLIENT_CERTIFICATE_PASSWORD` environment variable." + type = string + sensitive = true + default = "" +} + +variable "username" { + description = "The username for username/password authentication. Can also be set using the `M365_USERNAME` environment variable." + type = string + default = "" +} + +variable "password" { + description = "The password for username/password authentication. Can also be set using the `M365_PASSWORD` environment variable." + type = string + sensitive = true + default = "" +} + +variable "redirect_url" { + description = "The redirect URL for interactive browser authentication. Can also be set using the `M365_REDIRECT_URL` environment variable." + type = string + default = "" +} + +variable "use_proxy" { + description = "Enables the use of an HTTP proxy for network requests. When set to true, the provider will route all HTTP requests through the specified proxy server. This can be useful for environments that require proxy access for internet connectivity or for monitoring and logging HTTP traffic. Can also be set using the `M365_USE_PROXY` environment variable." + type = bool + default = false +} + +variable "proxy_url" { + description = "Specifies the URL of the HTTP proxy server. This URL should be in a valid URL format (e.g., 'http://proxy.example.com:8080'). When 'use_proxy' is enabled, this URL is used to configure the HTTP client to route requests through the proxy. Ensure the proxy server is reachable and correctly configured to handle the network traffic. Can also be set using the `M365_PROXY_URL` environment variable." + type = string + default = "" +} + +variable "enable_chaos" { + description = "Enable the chaos handler for testing purposes. When enabled, the chaos handler can simulate specific failure scenarios and random errors in API responses to help test the robustness and resilience of the terraform provider against intermittent issues. This is particularly useful for testing how the provider handles various error conditions and ensures it can recover gracefully. Use with caution in production environments. Can also be set using the `M365_ENABLE_CHAOS` environment variable." + type = bool + default = false +} + +variable "telemetry_optout" { + description = "Flag to indicate whether to opt out of telemetry. Default is `false`. Can also be set using the `M365_TELEMETRY_OPTOUT` environment variable." + type = bool + default = false +} + +variable "debug_mode" { + description = "Flag to enable debug mode for the provider. When enabled, the provider will output additional debug information to the console to help diagnose issues. Can also be set using the `M365_DEBUG_MODE` environment variable." + type = bool + default = false +} +``` + diff --git a/templates/provider.md.tmpl b/templates/provider.md.tmpl new file mode 100644 index 00000000..2d49bc19 --- /dev/null +++ b/templates/provider.md.tmpl @@ -0,0 +1,16 @@ +--- +page_title: "Provider: m365" +description: |- + The m365 provider is used to manage m365 resources. +--- + +# m365 Provider + +The Terraform m365 msgraph provider is a plugin for Terraform that allows for the +management of [m365](https://github.com/microsoftgraph/msgraph-metadata) resources. + +## Example Usage + +{{ tffile "examples/microsoft365_provider/provider.tf" }} + +{{ .SchemaMarkdown | trimspace }} \ No newline at end of file