From 36ed027fdd02b6f4eb10932596d1e4c320e30d99 Mon Sep 17 00:00:00 2001 From: jackofallops <11830746+jackofallops@users.noreply.github.com> Date: Thu, 16 Nov 2023 12:51:08 +0000 Subject: [PATCH] `appservice` - support disabling access for default basic auth (#23900) --- .../linux_function_app_data_source.go | 71 ++++++--- .../appservice/linux_function_app_resource.go | 120 +++++++++++--- .../linux_function_app_resource_test.go | 6 + .../linux_function_app_slot_resource.go | 147 +++++++++++++----- .../linux_function_app_slot_resource_test.go | 3 + .../appservice/linux_web_app_data_source.go | 99 +++++++----- .../appservice/linux_web_app_resource.go | 145 ++++++++++++----- .../appservice/linux_web_app_resource_test.go | 71 ++++++++- .../appservice/linux_web_app_slot_resource.go | 139 +++++++++++++---- .../linux_web_app_slot_resource_test.go | 64 ++++++++ .../windows_function_app_data_source.go | 67 +++++--- .../windows_function_app_resource.go | 119 +++++++++++--- .../windows_function_app_resource_test.go | 3 + .../windows_function_app_slot_resource.go | 122 ++++++++++++--- ...windows_function_app_slot_resource_test.go | 3 + .../appservice/windows_web_app_data_source.go | 91 +++++++---- .../appservice/windows_web_app_resource.go | 141 +++++++++++++---- .../windows_web_app_resource_test.go | 19 ++- .../windows_web_app_slot_resource.go | 137 ++++++++++++---- .../windows_web_app_slot_resource_test.go | 3 + .../docs/d/linux_function_app.html.markdown | 6 + website/docs/d/linux_web_app.html.markdown | 8 +- .../docs/d/windows_function_app.html.markdown | 6 + website/docs/d/windows_web_app.html.markdown | 6 + .../docs/r/linux_function_app.html.markdown | 6 + .../r/linux_function_app_slot.html.markdown | 4 + website/docs/r/linux_web_app.html.markdown | 6 + .../docs/r/linux_web_app_slot.html.markdown | 6 + .../docs/r/windows_function_app.html.markdown | 6 + .../r/windows_function_app_slot.html.markdown | 4 + website/docs/r/windows_web_app.html.markdown | 6 + .../docs/r/windows_web_app_slot.html.markdown | 6 + 32 files changed, 1295 insertions(+), 345 deletions(-) diff --git a/internal/services/appservice/linux_function_app_data_source.go b/internal/services/appservice/linux_function_app_data_source.go index e659c2e07c6f..abccfbdeb45d 100644 --- a/internal/services/appservice/linux_function_app_data_source.go +++ b/internal/services/appservice/linux_function_app_data_source.go @@ -36,27 +36,29 @@ type LinuxFunctionAppDataSourceModel struct { StorageUsesMSI bool `tfschema:"storage_uses_managed_identity"` // Storage uses MSI not account key StorageKeyVaultSecretID string `tfschema:"storage_key_vault_secret_id"` - AppSettings map[string]string `tfschema:"app_settings"` - AuthSettings []helpers.AuthSettings `tfschema:"auth_settings"` - AuthV2Settings []helpers.AuthV2Settings `tfschema:"auth_settings_v2"` - Availability string `tfschema:"availability"` - Backup []helpers.Backup `tfschema:"backup"` // Not supported on Dynamic or Basic plans - BuiltinLogging bool `tfschema:"builtin_logging_enabled"` - ClientCertEnabled bool `tfschema:"client_certificate_enabled"` - ClientCertMode string `tfschema:"client_certificate_mode"` - ClientCertExclusionPaths string `tfschema:"client_certificate_exclusion_paths"` - ConnectionStrings []helpers.ConnectionString `tfschema:"connection_string"` - DailyMemoryTimeQuota int `tfschema:"daily_memory_time_quota"` - Enabled bool `tfschema:"enabled"` - FunctionExtensionsVersion string `tfschema:"functions_extension_version"` - ForceDisableContentShare bool `tfschema:"content_share_force_disabled"` - HttpsOnly bool `tfschema:"https_only"` - PublicNetworkAccess bool `tfschema:"public_network_access_enabled"` - SiteConfig []helpers.SiteConfigLinuxFunctionApp `tfschema:"site_config"` - StickySettings []helpers.StickySettings `tfschema:"sticky_settings"` - Tags map[string]string `tfschema:"tags"` - VirtualNetworkSubnetID string `tfschema:"virtual_network_subnet_id"` - + AppSettings map[string]string `tfschema:"app_settings"` + AuthSettings []helpers.AuthSettings `tfschema:"auth_settings"` + AuthV2Settings []helpers.AuthV2Settings `tfschema:"auth_settings_v2"` + Availability string `tfschema:"availability"` + Backup []helpers.Backup `tfschema:"backup"` // Not supported on Dynamic or Basic plans + BuiltinLogging bool `tfschema:"builtin_logging_enabled"` + ClientCertEnabled bool `tfschema:"client_certificate_enabled"` + ClientCertMode string `tfschema:"client_certificate_mode"` + ClientCertExclusionPaths string `tfschema:"client_certificate_exclusion_paths"` + ConnectionStrings []helpers.ConnectionString `tfschema:"connection_string"` + DailyMemoryTimeQuota int `tfschema:"daily_memory_time_quota"` + Enabled bool `tfschema:"enabled"` + FunctionExtensionsVersion string `tfschema:"functions_extension_version"` + ForceDisableContentShare bool `tfschema:"content_share_force_disabled"` + HttpsOnly bool `tfschema:"https_only"` + PublicNetworkAccess bool `tfschema:"public_network_access_enabled"` + PublishingDeployBasicAuthEnabled bool `tfschema:"webdeploy_publish_basic_authentication_enabled"` + PublishingFTPBasicAuthEnabled bool `tfschema:"ftp_publish_basic_authentication_enabled"` + SiteConfig []helpers.SiteConfigLinuxFunctionApp `tfschema:"site_config"` + StickySettings []helpers.StickySettings `tfschema:"sticky_settings"` + Tags map[string]string `tfschema:"tags"` + + VirtualNetworkSubnetID string `tfschema:"virtual_network_subnet_id"` CustomDomainVerificationId string `tfschema:"custom_domain_verification_id"` DefaultHostname string `tfschema:"default_hostname"` HostingEnvId string `tfschema:"hosting_environment_id"` @@ -257,6 +259,16 @@ func (d LinuxFunctionAppDataSource) Attributes() map[string]*pluginsdk.Schema { "site_credential": helpers.SiteCredentialSchema(), + "webdeploy_publish_basic_authentication_enabled": { + Type: pluginsdk.TypeBool, + Computed: true, + }, + + "ftp_publish_basic_authentication_enabled": { + Type: pluginsdk.TypeBool, + Computed: true, + }, + "sticky_settings": helpers.StickySettingsComputedSchema(), "virtual_network_subnet_id": { @@ -362,6 +374,23 @@ func (d LinuxFunctionAppDataSource) Read() sdk.ResourceFunc { PublicNetworkAccess: !strings.EqualFold(pointer.From(props.PublicNetworkAccess), helpers.PublicNetworkAccessDisabled), } + basicAuthFTP := true + if basicAuthFTPResp, err := client.GetFtpAllowed(ctx, id.ResourceGroup, id.SiteName); err != nil { + return fmt.Errorf("retrieving state of FTP Basic Auth for %s: %+v", id, err) + } else if csmProps := basicAuthFTPResp.CsmPublishingCredentialsPoliciesEntityProperties; csmProps != nil { + basicAuthFTP = pointer.From(csmProps.Allow) + } + + basicAuthWebDeploy := true + if basicAuthWebDeployResp, err := client.GetScmAllowed(ctx, id.ResourceGroup, id.SiteName); err != nil { + return fmt.Errorf("retrieving state of WebDeploy Basic Auth for %s: %+v", id, err) + } else if csmProps := basicAuthWebDeployResp.CsmPublishingCredentialsPoliciesEntityProperties; csmProps != nil { + basicAuthWebDeploy = pointer.From(csmProps.Allow) + } + + state.PublishingFTPBasicAuthEnabled = basicAuthFTP + state.PublishingDeployBasicAuthEnabled = basicAuthWebDeploy + if hostingEnv := props.HostingEnvironmentProfile; hostingEnv != nil { state.HostingEnvId = pointer.From(hostingEnv.ID) } diff --git a/internal/services/appservice/linux_function_app_resource.go b/internal/services/appservice/linux_function_app_resource.go index 13c9326515e0..0f7741ca081d 100644 --- a/internal/services/appservice/linux_function_app_resource.go +++ b/internal/services/appservice/linux_function_app_resource.go @@ -41,28 +41,30 @@ type LinuxFunctionAppModel struct { StorageUsesMSI bool `tfschema:"storage_uses_managed_identity"` // Storage uses MSI not account key StorageKeyVaultSecretID string `tfschema:"storage_key_vault_secret_id"` - AppSettings map[string]string `tfschema:"app_settings"` - StickySettings []helpers.StickySettings `tfschema:"sticky_settings"` - AuthSettings []helpers.AuthSettings `tfschema:"auth_settings"` - AuthV2Settings []helpers.AuthV2Settings `tfschema:"auth_settings_v2"` - Backup []helpers.Backup `tfschema:"backup"` // Not supported on Dynamic or Basic plans - BuiltinLogging bool `tfschema:"builtin_logging_enabled"` - ClientCertEnabled bool `tfschema:"client_certificate_enabled"` - ClientCertMode string `tfschema:"client_certificate_mode"` - ClientCertExclusionPaths string `tfschema:"client_certificate_exclusion_paths"` - ConnectionStrings []helpers.ConnectionString `tfschema:"connection_string"` - DailyMemoryTimeQuota int `tfschema:"daily_memory_time_quota"` // TODO - Value ignored in for linux apps, even in Consumption plans? - Enabled bool `tfschema:"enabled"` - FunctionExtensionsVersion string `tfschema:"functions_extension_version"` - ForceDisableContentShare bool `tfschema:"content_share_force_disabled"` - HttpsOnly bool `tfschema:"https_only"` - KeyVaultReferenceIdentityID string `tfschema:"key_vault_reference_identity_id"` - PublicNetworkAccess bool `tfschema:"public_network_access_enabled"` - SiteConfig []helpers.SiteConfigLinuxFunctionApp `tfschema:"site_config"` - StorageAccounts []helpers.StorageAccount `tfschema:"storage_account"` - Tags map[string]string `tfschema:"tags"` - VirtualNetworkSubnetID string `tfschema:"virtual_network_subnet_id"` - ZipDeployFile string `tfschema:"zip_deploy_file"` + AppSettings map[string]string `tfschema:"app_settings"` + StickySettings []helpers.StickySettings `tfschema:"sticky_settings"` + AuthSettings []helpers.AuthSettings `tfschema:"auth_settings"` + AuthV2Settings []helpers.AuthV2Settings `tfschema:"auth_settings_v2"` + Backup []helpers.Backup `tfschema:"backup"` // Not supported on Dynamic or Basic plans + BuiltinLogging bool `tfschema:"builtin_logging_enabled"` + ClientCertEnabled bool `tfschema:"client_certificate_enabled"` + ClientCertMode string `tfschema:"client_certificate_mode"` + ClientCertExclusionPaths string `tfschema:"client_certificate_exclusion_paths"` + ConnectionStrings []helpers.ConnectionString `tfschema:"connection_string"` + DailyMemoryTimeQuota int `tfschema:"daily_memory_time_quota"` // TODO - Value ignored in for linux apps, even in Consumption plans? + Enabled bool `tfschema:"enabled"` + FunctionExtensionsVersion string `tfschema:"functions_extension_version"` + ForceDisableContentShare bool `tfschema:"content_share_force_disabled"` + HttpsOnly bool `tfschema:"https_only"` + KeyVaultReferenceIdentityID string `tfschema:"key_vault_reference_identity_id"` + PublicNetworkAccess bool `tfschema:"public_network_access_enabled"` + SiteConfig []helpers.SiteConfigLinuxFunctionApp `tfschema:"site_config"` + StorageAccounts []helpers.StorageAccount `tfschema:"storage_account"` + Tags map[string]string `tfschema:"tags"` + VirtualNetworkSubnetID string `tfschema:"virtual_network_subnet_id"` + ZipDeployFile string `tfschema:"zip_deploy_file"` + PublishingDeployBasicAuthEnabled bool `tfschema:"webdeploy_publish_basic_authentication_enabled"` + PublishingFTPBasicAuthEnabled bool `tfschema:"ftp_publish_basic_authentication_enabled"` // Computed CustomDomainVerificationId string `tfschema:"custom_domain_verification_id"` @@ -262,6 +264,18 @@ func (r LinuxFunctionAppResource) Arguments() map[string]*pluginsdk.Schema { Default: true, }, + "webdeploy_publish_basic_authentication_enabled": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: true, + }, + + "ftp_publish_basic_authentication_enabled": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: true, + }, + "site_config": helpers.SiteConfigSchemaLinuxFunctionApp(), "sticky_settings": helpers.StickySettingsSchema(), @@ -531,6 +545,29 @@ func (r LinuxFunctionAppResource) Create() sdk.ResourceFunc { return fmt.Errorf("waiting for creation of Linux %s: %+v", id, err) } + // (@jackofallops) - updating the policy for publishing credentials resets the `Use32BitWorkerProcess` property + if !functionApp.PublishingDeployBasicAuthEnabled { + sitePolicy := web.CsmPublishingCredentialsPoliciesEntity{ + CsmPublishingCredentialsPoliciesEntityProperties: &web.CsmPublishingCredentialsPoliciesEntityProperties{ + Allow: pointer.To(false), + }, + } + if _, err := client.UpdateScmAllowed(ctx, id.ResourceGroup, id.SiteName, sitePolicy); err != nil { + return fmt.Errorf("setting basic auth for deploy publishing credentials for %s: %+v", id, err) + } + } + + if !functionApp.PublishingFTPBasicAuthEnabled { + sitePolicy := web.CsmPublishingCredentialsPoliciesEntity{ + CsmPublishingCredentialsPoliciesEntityProperties: &web.CsmPublishingCredentialsPoliciesEntityProperties{ + Allow: pointer.To(false), + }, + } + if _, err := client.UpdateFtpAllowed(ctx, id.ResourceGroup, id.SiteName, sitePolicy); err != nil { + return fmt.Errorf("setting basic auth for ftp publishing credentials for %s: %+v", id, err) + } + } + updateFuture, err := client.CreateOrUpdate(ctx, id.ResourceGroup, id.SiteName, siteEnvelope) if err != nil { return fmt.Errorf("updating properties of Linux %s: %+v", id, err) @@ -689,6 +726,20 @@ func (r LinuxFunctionAppResource) Read() sdk.ResourceFunc { return fmt.Errorf("reading logs configuration for Linux %s: %+v", id, err) } + basicAuthFTP := true + if basicAuthFTPResp, err := client.GetFtpAllowed(ctx, id.ResourceGroup, id.SiteName); err != nil { + return fmt.Errorf("retrieving state of FTP Basic Auth for %s: %+v", id, err) + } else if csmProps := basicAuthFTPResp.CsmPublishingCredentialsPoliciesEntityProperties; csmProps != nil { + basicAuthFTP = pointer.From(csmProps.Allow) + } + + basicAuthWebDeploy := true + if basicAuthWebDeployResp, err := client.GetScmAllowed(ctx, id.ResourceGroup, id.SiteName); err != nil { + return fmt.Errorf("retrieving state of WebDeploy Basic Auth for %s: %+v", id, err) + } else if csmProps := basicAuthWebDeployResp.CsmPublishingCredentialsPoliciesEntityProperties; csmProps != nil { + basicAuthWebDeploy = pointer.From(csmProps.Allow) + } + state := LinuxFunctionAppModel{ Name: id.SiteName, ResourceGroup: id.ResourceGroup, @@ -707,6 +758,9 @@ func (r LinuxFunctionAppResource) Read() sdk.ResourceFunc { PublicNetworkAccess: !strings.EqualFold(pointer.From(props.PublicNetworkAccess), helpers.PublicNetworkAccessDisabled), } + state.PublishingFTPBasicAuthEnabled = basicAuthFTP + state.PublishingDeployBasicAuthEnabled = basicAuthWebDeploy + if hostingEnv := props.HostingEnvironmentProfile; hostingEnv != nil { hostingEnvId, err := parse.AppServiceEnvironmentIDInsensitively(*hostingEnv.ID) if err != nil { @@ -1005,6 +1059,28 @@ func (r LinuxFunctionAppResource) Update() sdk.ResourceFunc { return fmt.Errorf("waiting to update %s: %+v", id, err) } + if metadata.ResourceData.HasChange("ftp_publish_basic_authentication_enabled") { + sitePolicy := web.CsmPublishingCredentialsPoliciesEntity{ + CsmPublishingCredentialsPoliciesEntityProperties: &web.CsmPublishingCredentialsPoliciesEntityProperties{ + Allow: pointer.To(state.PublishingFTPBasicAuthEnabled), + }, + } + if _, err := client.UpdateFtpAllowed(ctx, id.ResourceGroup, id.SiteName, sitePolicy); err != nil { + return fmt.Errorf("setting basic auth for ftp publishing credentials for %s: %+v", id, err) + } + } + + if metadata.ResourceData.HasChange("webdeploy_publish_basic_authentication_enabled") { + sitePolicy := web.CsmPublishingCredentialsPoliciesEntity{ + CsmPublishingCredentialsPoliciesEntityProperties: &web.CsmPublishingCredentialsPoliciesEntityProperties{ + Allow: pointer.To(state.PublishingDeployBasicAuthEnabled), + }, + } + if _, err := client.UpdateScmAllowed(ctx, id.ResourceGroup, id.SiteName, sitePolicy); err != nil { + return fmt.Errorf("setting basic auth for deploy publishing credentials for %s: %+v", id, err) + } + } + if _, err := client.UpdateConfiguration(ctx, id.ResourceGroup, id.SiteName, web.SiteConfigResource{SiteConfig: existing.SiteConfig}); err != nil { return fmt.Errorf("updating Site Config for Linux %s: %+v", id, err) } diff --git a/internal/services/appservice/linux_function_app_resource_test.go b/internal/services/appservice/linux_function_app_resource_test.go index 66d3b234599b..a83a105377a3 100644 --- a/internal/services/appservice/linux_function_app_resource_test.go +++ b/internal/services/appservice/linux_function_app_resource_test.go @@ -2903,6 +2903,9 @@ resource "azurerm_linux_function_app" "test" { } } + ftp_publish_basic_authentication_enabled = false + webdeploy_publish_basic_authentication_enabled = false + tags = { terraform = "true" Env = "AccTest" @@ -3095,6 +3098,9 @@ resource "azurerm_linux_function_app" "test" { connection_string_names = ["First"] } + ftp_publish_basic_authentication_enabled = false + webdeploy_publish_basic_authentication_enabled = false + tags = { terraform = "true" Env = "AccTest" diff --git a/internal/services/appservice/linux_function_app_slot_resource.go b/internal/services/appservice/linux_function_app_slot_resource.go index f78512de28a2..509621cdfa95 100644 --- a/internal/services/appservice/linux_function_app_slot_resource.go +++ b/internal/services/appservice/linux_function_app_slot_resource.go @@ -31,42 +31,44 @@ import ( type LinuxFunctionAppSlotResource struct{} type LinuxFunctionAppSlotModel struct { - Name string `tfschema:"name"` - FunctionAppID string `tfschema:"function_app_id"` - ServicePlanID string `tfschema:"service_plan_id"` - StorageAccountName string `tfschema:"storage_account_name"` - StorageAccountKey string `tfschema:"storage_account_access_key"` - StorageUsesMSI bool `tfschema:"storage_uses_managed_identity"` // Storage uses MSI not account key - StorageKeyVaultSecretID string `tfschema:"storage_key_vault_secret_id"` - AppSettings map[string]string `tfschema:"app_settings"` - AuthSettings []helpers.AuthSettings `tfschema:"auth_settings"` - AuthV2Settings []helpers.AuthV2Settings `tfschema:"auth_settings_v2"` - Backup []helpers.Backup `tfschema:"backup"` // Not supported on Dynamic or Basic plans - BuiltinLogging bool `tfschema:"builtin_logging_enabled"` - ClientCertEnabled bool `tfschema:"client_certificate_enabled"` - ClientCertMode string `tfschema:"client_certificate_mode"` - ClientCertExclusionPaths string `tfschema:"client_certificate_exclusion_paths"` - ConnectionStrings []helpers.ConnectionString `tfschema:"connection_string"` - DailyMemoryTimeQuota int `tfschema:"daily_memory_time_quota"` // TODO - Value ignored in for linux apps, even in Consumption plans? - Enabled bool `tfschema:"enabled"` - FunctionExtensionsVersion string `tfschema:"functions_extension_version"` - ForceDisableContentShare bool `tfschema:"content_share_force_disabled"` - HttpsOnly bool `tfschema:"https_only"` - KeyVaultReferenceIdentityID string `tfschema:"key_vault_reference_identity_id"` - SiteConfig []helpers.SiteConfigLinuxFunctionAppSlot `tfschema:"site_config"` - Tags map[string]string `tfschema:"tags"` - VirtualNetworkSubnetID string `tfschema:"virtual_network_subnet_id"` - CustomDomainVerificationId string `tfschema:"custom_domain_verification_id"` - HostingEnvId string `tfschema:"hosting_environment_id"` - DefaultHostname string `tfschema:"default_hostname"` - Kind string `tfschema:"kind"` - OutboundIPAddresses string `tfschema:"outbound_ip_addresses"` - OutboundIPAddressList []string `tfschema:"outbound_ip_address_list"` - PossibleOutboundIPAddresses string `tfschema:"possible_outbound_ip_addresses"` - PossibleOutboundIPAddressList []string `tfschema:"possible_outbound_ip_address_list"` - PublicNetworkAccess bool `tfschema:"public_network_access_enabled"` - SiteCredentials []helpers.SiteCredential `tfschema:"site_credential"` - StorageAccounts []helpers.StorageAccount `tfschema:"storage_account"` + Name string `tfschema:"name"` + FunctionAppID string `tfschema:"function_app_id"` + ServicePlanID string `tfschema:"service_plan_id"` + StorageAccountName string `tfschema:"storage_account_name"` + StorageAccountKey string `tfschema:"storage_account_access_key"` + StorageUsesMSI bool `tfschema:"storage_uses_managed_identity"` // Storage uses MSI not account key + StorageKeyVaultSecretID string `tfschema:"storage_key_vault_secret_id"` + AppSettings map[string]string `tfschema:"app_settings"` + AuthSettings []helpers.AuthSettings `tfschema:"auth_settings"` + AuthV2Settings []helpers.AuthV2Settings `tfschema:"auth_settings_v2"` + Backup []helpers.Backup `tfschema:"backup"` // Not supported on Dynamic or Basic plans + BuiltinLogging bool `tfschema:"builtin_logging_enabled"` + ClientCertEnabled bool `tfschema:"client_certificate_enabled"` + ClientCertMode string `tfschema:"client_certificate_mode"` + ClientCertExclusionPaths string `tfschema:"client_certificate_exclusion_paths"` + ConnectionStrings []helpers.ConnectionString `tfschema:"connection_string"` + DailyMemoryTimeQuota int `tfschema:"daily_memory_time_quota"` // TODO - Value ignored in for linux apps, even in Consumption plans? + Enabled bool `tfschema:"enabled"` + FunctionExtensionsVersion string `tfschema:"functions_extension_version"` + ForceDisableContentShare bool `tfschema:"content_share_force_disabled"` + HttpsOnly bool `tfschema:"https_only"` + KeyVaultReferenceIdentityID string `tfschema:"key_vault_reference_identity_id"` + SiteConfig []helpers.SiteConfigLinuxFunctionAppSlot `tfschema:"site_config"` + Tags map[string]string `tfschema:"tags"` + VirtualNetworkSubnetID string `tfschema:"virtual_network_subnet_id"` + CustomDomainVerificationId string `tfschema:"custom_domain_verification_id"` + HostingEnvId string `tfschema:"hosting_environment_id"` + DefaultHostname string `tfschema:"default_hostname"` + Kind string `tfschema:"kind"` + OutboundIPAddresses string `tfschema:"outbound_ip_addresses"` + OutboundIPAddressList []string `tfschema:"outbound_ip_address_list"` + PossibleOutboundIPAddresses string `tfschema:"possible_outbound_ip_addresses"` + PossibleOutboundIPAddressList []string `tfschema:"possible_outbound_ip_address_list"` + PublicNetworkAccess bool `tfschema:"public_network_access_enabled"` + PublishingDeployBasicAuthEnabled bool `tfschema:"webdeploy_publish_basic_authentication_enabled"` + PublishingFTPBasicAuthEnabled bool `tfschema:"ftp_publish_basic_authentication_enabled"` + SiteCredentials []helpers.SiteCredential `tfschema:"site_credential"` + StorageAccounts []helpers.StorageAccount `tfschema:"storage_account"` } var _ sdk.ResourceWithUpdate = LinuxFunctionAppSlotResource{} @@ -253,6 +255,18 @@ func (r LinuxFunctionAppSlotResource) Arguments() map[string]*pluginsdk.Schema { Default: true, }, + "webdeploy_publish_basic_authentication_enabled": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: true, + }, + + "ftp_publish_basic_authentication_enabled": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: true, + }, + "site_config": helpers.SiteConfigSchemaLinuxFunctionAppSlot(), "storage_account": helpers.StorageAccountSchema(), @@ -528,6 +542,28 @@ func (r LinuxFunctionAppSlotResource) Create() sdk.ResourceFunc { return fmt.Errorf("waiting for creation of Linux %s: %+v", id, err) } + if !functionAppSlot.PublishingDeployBasicAuthEnabled { + sitePolicy := web.CsmPublishingCredentialsPoliciesEntity{ + CsmPublishingCredentialsPoliciesEntityProperties: &web.CsmPublishingCredentialsPoliciesEntityProperties{ + Allow: pointer.To(false), + }, + } + if _, err := client.UpdateScmAllowedSlot(ctx, id.ResourceGroup, id.SiteName, sitePolicy, id.SlotName); err != nil { + return fmt.Errorf("setting basic auth for deploy publishing credentials for %s: %+v", id, err) + } + } + + if !functionAppSlot.PublishingFTPBasicAuthEnabled { + sitePolicy := web.CsmPublishingCredentialsPoliciesEntity{ + CsmPublishingCredentialsPoliciesEntityProperties: &web.CsmPublishingCredentialsPoliciesEntityProperties{ + Allow: pointer.To(false), + }, + } + if _, err := client.UpdateFtpAllowedSlot(ctx, id.ResourceGroup, id.SiteName, sitePolicy, id.SlotName); err != nil { + return fmt.Errorf("setting basic auth for ftp publishing credentials for %s: %+v", id, err) + } + } + updateFuture, err := client.CreateOrUpdateSlot(ctx, id.ResourceGroup, id.SiteName, siteEnvelope, id.SlotName) if err != nil { return fmt.Errorf("updating properties of Linux %s: %+v", id, err) @@ -665,6 +701,20 @@ func (r LinuxFunctionAppSlotResource) Read() sdk.ResourceFunc { return fmt.Errorf("reading logs configuration for Linux %s: %+v", id, err) } + basicAuthFTP := true + if basicAuthFTPResp, err := client.GetFtpAllowedSlot(ctx, id.ResourceGroup, id.SiteName, id.SlotName); err != nil { + return fmt.Errorf("retrieving state of FTP Basic Auth for %s: %+v", id, err) + } else if csmProps := basicAuthFTPResp.CsmPublishingCredentialsPoliciesEntityProperties; csmProps != nil { + basicAuthFTP = pointer.From(csmProps.Allow) + } + + basicAuthWebDeploy := true + if basicAuthWebDeployResp, err := client.GetScmAllowedSlot(ctx, id.ResourceGroup, id.SiteName, id.SlotName); err != nil { + return fmt.Errorf("retrieving state of WebDeploy Basic Auth for %s: %+v", id, err) + } else if csmProps := basicAuthWebDeployResp.CsmPublishingCredentialsPoliciesEntityProperties; csmProps != nil { + basicAuthWebDeploy = pointer.From(csmProps.Allow) + } + state := LinuxFunctionAppSlotModel{ Name: id.SlotName, FunctionAppID: parse.NewFunctionAppID(id.SubscriptionId, id.ResourceGroup, id.SiteName).ID(), @@ -680,6 +730,9 @@ func (r LinuxFunctionAppSlotResource) Read() sdk.ResourceFunc { PublicNetworkAccess: !strings.EqualFold(pointer.From(props.PublicNetworkAccess), helpers.PublicNetworkAccessDisabled), } + state.PublishingFTPBasicAuthEnabled = basicAuthFTP + state.PublishingDeployBasicAuthEnabled = basicAuthWebDeploy + if hostingEnv := props.HostingEnvironmentProfile; hostingEnv != nil { state.HostingEnvId = pointer.From(hostingEnv.ID) } @@ -950,6 +1003,28 @@ func (r LinuxFunctionAppSlotResource) Update() sdk.ResourceFunc { return fmt.Errorf("waiting to update %s: %+v", id, err) } + if metadata.ResourceData.HasChange("ftp_publish_basic_authentication_enabled") { + sitePolicy := web.CsmPublishingCredentialsPoliciesEntity{ + CsmPublishingCredentialsPoliciesEntityProperties: &web.CsmPublishingCredentialsPoliciesEntityProperties{ + Allow: pointer.To(state.PublishingFTPBasicAuthEnabled), + }, + } + if _, err := client.UpdateFtpAllowedSlot(ctx, id.ResourceGroup, id.SiteName, sitePolicy, id.SlotName); err != nil { + return fmt.Errorf("setting basic auth for ftp publishing credentials for %s: %+v", id, err) + } + } + + if metadata.ResourceData.HasChange("webdeploy_publish_basic_authentication_enabled") { + sitePolicy := web.CsmPublishingCredentialsPoliciesEntity{ + CsmPublishingCredentialsPoliciesEntityProperties: &web.CsmPublishingCredentialsPoliciesEntityProperties{ + Allow: pointer.To(state.PublishingDeployBasicAuthEnabled), + }, + } + if _, err := client.UpdateScmAllowedSlot(ctx, id.ResourceGroup, id.SiteName, sitePolicy, id.SlotName); err != nil { + return fmt.Errorf("setting basic auth for deploy publishing credentials for %s: %+v", id, err) + } + } + if _, err := client.UpdateConfigurationSlot(ctx, id.ResourceGroup, id.SiteName, web.SiteConfigResource{SiteConfig: siteConfig}, id.SlotName); err != nil { return fmt.Errorf("updating Site Config for Linux %s: %+v", id, err) } diff --git a/internal/services/appservice/linux_function_app_slot_resource_test.go b/internal/services/appservice/linux_function_app_slot_resource_test.go index 38b2e1b1bf4d..e79b7af93db8 100644 --- a/internal/services/appservice/linux_function_app_slot_resource_test.go +++ b/internal/services/appservice/linux_function_app_slot_resource_test.go @@ -2066,6 +2066,9 @@ resource "azurerm_linux_function_app_slot" "test" { } } + ftp_publish_basic_authentication_enabled = false + webdeploy_publish_basic_authentication_enabled = false + tags = { terraform = "true" Env = "AccTest" diff --git a/internal/services/appservice/linux_web_app_data_source.go b/internal/services/appservice/linux_web_app_data_source.go index 6d8b8c48ff8e..eddaa1f91fc2 100644 --- a/internal/services/appservice/linux_web_app_data_source.go +++ b/internal/services/appservice/linux_web_app_data_source.go @@ -24,41 +24,43 @@ import ( type LinuxWebAppDataSource struct{} type LinuxWebAppDataSourceModel struct { - Name string `tfschema:"name"` - ResourceGroup string `tfschema:"resource_group_name"` - Location string `tfschema:"location"` - ServicePlanId string `tfschema:"service_plan_id"` - AppSettings map[string]string `tfschema:"app_settings"` - AuthSettings []helpers.AuthSettings `tfschema:"auth_settings"` - AuthV2Settings []helpers.AuthV2Settings `tfschema:"auth_settings_v2"` - Availability string `tfschema:"availability"` - Backup []helpers.Backup `tfschema:"backup"` - ClientAffinityEnabled bool `tfschema:"client_affinity_enabled"` - ClientCertEnabled bool `tfschema:"client_certificate_enabled"` - ClientCertMode string `tfschema:"client_certificate_mode"` - ClientCertExclusionPaths string `tfschema:"client_certificate_exclusion_paths"` - Enabled bool `tfschema:"enabled"` - HttpsOnly bool `tfschema:"https_only"` - KeyVaultReferenceIdentityID string `tfschema:"key_vault_reference_identity_id"` - LogsConfig []helpers.LogsConfig `tfschema:"logs"` - MetaData map[string]string `tfschema:"app_metadata"` - SiteConfig []helpers.SiteConfigLinux `tfschema:"site_config"` - StickySettings []helpers.StickySettings `tfschema:"sticky_settings"` - StorageAccounts []helpers.StorageAccount `tfschema:"storage_account"` - ConnectionStrings []helpers.ConnectionString `tfschema:"connection_string"` - Tags map[string]string `tfschema:"tags"` - CustomDomainVerificationId string `tfschema:"custom_domain_verification_id"` - HostingEnvId string `tfschema:"hosting_environment_id"` - DefaultHostname string `tfschema:"default_hostname"` - Kind string `tfschema:"kind"` - OutboundIPAddresses string `tfschema:"outbound_ip_addresses"` - OutboundIPAddressList []string `tfschema:"outbound_ip_address_list"` - PossibleOutboundIPAddresses string `tfschema:"possible_outbound_ip_addresses"` - PossibleOutboundIPAddressList []string `tfschema:"possible_outbound_ip_address_list"` - PublicNetworkAccess bool `tfschema:"public_network_access_enabled"` - Usage string `tfschema:"usage"` - SiteCredentials []helpers.SiteCredential `tfschema:"site_credential"` - VirtualNetworkSubnetID string `tfschema:"virtual_network_subnet_id"` + Name string `tfschema:"name"` + ResourceGroup string `tfschema:"resource_group_name"` + Location string `tfschema:"location"` + ServicePlanId string `tfschema:"service_plan_id"` + AppSettings map[string]string `tfschema:"app_settings"` + AuthSettings []helpers.AuthSettings `tfschema:"auth_settings"` + AuthV2Settings []helpers.AuthV2Settings `tfschema:"auth_settings_v2"` + Availability string `tfschema:"availability"` + Backup []helpers.Backup `tfschema:"backup"` + ClientAffinityEnabled bool `tfschema:"client_affinity_enabled"` + ClientCertEnabled bool `tfschema:"client_certificate_enabled"` + ClientCertMode string `tfschema:"client_certificate_mode"` + ClientCertExclusionPaths string `tfschema:"client_certificate_exclusion_paths"` + Enabled bool `tfschema:"enabled"` + HttpsOnly bool `tfschema:"https_only"` + KeyVaultReferenceIdentityID string `tfschema:"key_vault_reference_identity_id"` + LogsConfig []helpers.LogsConfig `tfschema:"logs"` + MetaData map[string]string `tfschema:"app_metadata"` + SiteConfig []helpers.SiteConfigLinux `tfschema:"site_config"` + StickySettings []helpers.StickySettings `tfschema:"sticky_settings"` + StorageAccounts []helpers.StorageAccount `tfschema:"storage_account"` + ConnectionStrings []helpers.ConnectionString `tfschema:"connection_string"` + Tags map[string]string `tfschema:"tags"` + CustomDomainVerificationId string `tfschema:"custom_domain_verification_id"` + HostingEnvId string `tfschema:"hosting_environment_id"` + DefaultHostname string `tfschema:"default_hostname"` + Kind string `tfschema:"kind"` + OutboundIPAddresses string `tfschema:"outbound_ip_addresses"` + OutboundIPAddressList []string `tfschema:"outbound_ip_address_list"` + PossibleOutboundIPAddresses string `tfschema:"possible_outbound_ip_addresses"` + PossibleOutboundIPAddressList []string `tfschema:"possible_outbound_ip_address_list"` + PublicNetworkAccess bool `tfschema:"public_network_access_enabled"` + Usage string `tfschema:"usage"` + PublishingDeployBasicAuthEnabled bool `tfschema:"webdeploy_publish_basic_authentication_enabled"` + PublishingFTPBasicAuthEnabled bool `tfschema:"ftp_publish_basic_authentication_enabled"` + SiteCredentials []helpers.SiteCredential `tfschema:"site_credential"` + VirtualNetworkSubnetID string `tfschema:"virtual_network_subnet_id"` } var _ sdk.DataSource = LinuxWebAppDataSource{} @@ -215,6 +217,16 @@ func (r LinuxWebAppDataSource) Attributes() map[string]*pluginsdk.Schema { "site_credential": helpers.SiteCredentialSchema(), + "webdeploy_publish_basic_authentication_enabled": { + Type: pluginsdk.TypeBool, + Computed: true, + }, + + "ftp_publish_basic_authentication_enabled": { + Type: pluginsdk.TypeBool, + Computed: true, + }, + "service_plan_id": { Type: pluginsdk.TypeString, Computed: true, @@ -354,6 +366,23 @@ func (r LinuxWebAppDataSource) Read() sdk.ResourceFunc { webApp.PublicNetworkAccess = !strings.EqualFold(pointer.From(props.PublicNetworkAccess), helpers.PublicNetworkAccessDisabled) } + basicAuthFTP := true + if basicAuthFTPResp, err := client.GetFtpAllowed(ctx, id.ResourceGroup, id.SiteName); err != nil { + return fmt.Errorf("retrieving state of FTP Basic Auth for %s: %+v", id, err) + } else if csmProps := basicAuthFTPResp.CsmPublishingCredentialsPoliciesEntityProperties; csmProps != nil { + basicAuthFTP = pointer.From(csmProps.Allow) + } + + basicAuthWebDeploy := true + if basicAuthWebDeployResp, err := client.GetScmAllowed(ctx, id.ResourceGroup, id.SiteName); err != nil { + return fmt.Errorf("retrieving state of WebDeploy Basic Auth for %s: %+v", id, err) + } else if csmProps := basicAuthWebDeployResp.CsmPublishingCredentialsPoliciesEntityProperties; csmProps != nil { + basicAuthWebDeploy = pointer.From(csmProps.Allow) + } + + webApp.PublishingFTPBasicAuthEnabled = basicAuthFTP + webApp.PublishingDeployBasicAuthEnabled = basicAuthWebDeploy + webApp.AuthSettings = helpers.FlattenAuthSettings(auth) webApp.AuthV2Settings = helpers.FlattenAuthV2Settings(authV2) diff --git a/internal/services/appservice/linux_web_app_resource.go b/internal/services/appservice/linux_web_app_resource.go index 37f116a7ab7f..e32a12052faf 100644 --- a/internal/services/appservice/linux_web_app_resource.go +++ b/internal/services/appservice/linux_web_app_resource.go @@ -29,39 +29,41 @@ import ( type LinuxWebAppResource struct{} type LinuxWebAppModel struct { - Name string `tfschema:"name"` - ResourceGroup string `tfschema:"resource_group_name"` - Location string `tfschema:"location"` - ServicePlanId string `tfschema:"service_plan_id"` - AppSettings map[string]string `tfschema:"app_settings"` - StickySettings []helpers.StickySettings `tfschema:"sticky_settings"` - AuthSettings []helpers.AuthSettings `tfschema:"auth_settings"` - AuthV2Settings []helpers.AuthV2Settings `tfschema:"auth_settings_v2"` - Backup []helpers.Backup `tfschema:"backup"` - ClientAffinityEnabled bool `tfschema:"client_affinity_enabled"` - ClientCertEnabled bool `tfschema:"client_certificate_enabled"` - ClientCertMode string `tfschema:"client_certificate_mode"` - ClientCertExclusionPaths string `tfschema:"client_certificate_exclusion_paths"` - Enabled bool `tfschema:"enabled"` - HttpsOnly bool `tfschema:"https_only"` - VirtualNetworkSubnetID string `tfschema:"virtual_network_subnet_id"` - KeyVaultReferenceIdentityID string `tfschema:"key_vault_reference_identity_id"` - LogsConfig []helpers.LogsConfig `tfschema:"logs"` - SiteConfig []helpers.SiteConfigLinux `tfschema:"site_config"` - StorageAccounts []helpers.StorageAccount `tfschema:"storage_account"` - ConnectionStrings []helpers.ConnectionString `tfschema:"connection_string"` - ZipDeployFile string `tfschema:"zip_deploy_file"` - Tags map[string]string `tfschema:"tags"` - CustomDomainVerificationId string `tfschema:"custom_domain_verification_id"` - HostingEnvId string `tfschema:"hosting_environment_id"` - DefaultHostname string `tfschema:"default_hostname"` - Kind string `tfschema:"kind"` - OutboundIPAddresses string `tfschema:"outbound_ip_addresses"` - OutboundIPAddressList []string `tfschema:"outbound_ip_address_list"` - PossibleOutboundIPAddresses string `tfschema:"possible_outbound_ip_addresses"` - PossibleOutboundIPAddressList []string `tfschema:"possible_outbound_ip_address_list"` - PublicNetworkAccess bool `tfschema:"public_network_access_enabled"` - SiteCredentials []helpers.SiteCredential `tfschema:"site_credential"` + Name string `tfschema:"name"` + ResourceGroup string `tfschema:"resource_group_name"` + Location string `tfschema:"location"` + ServicePlanId string `tfschema:"service_plan_id"` + AppSettings map[string]string `tfschema:"app_settings"` + StickySettings []helpers.StickySettings `tfschema:"sticky_settings"` + AuthSettings []helpers.AuthSettings `tfschema:"auth_settings"` + AuthV2Settings []helpers.AuthV2Settings `tfschema:"auth_settings_v2"` + Backup []helpers.Backup `tfschema:"backup"` + ClientAffinityEnabled bool `tfschema:"client_affinity_enabled"` + ClientCertEnabled bool `tfschema:"client_certificate_enabled"` + ClientCertMode string `tfschema:"client_certificate_mode"` + ClientCertExclusionPaths string `tfschema:"client_certificate_exclusion_paths"` + Enabled bool `tfschema:"enabled"` + HttpsOnly bool `tfschema:"https_only"` + VirtualNetworkSubnetID string `tfschema:"virtual_network_subnet_id"` + KeyVaultReferenceIdentityID string `tfschema:"key_vault_reference_identity_id"` + LogsConfig []helpers.LogsConfig `tfschema:"logs"` + SiteConfig []helpers.SiteConfigLinux `tfschema:"site_config"` + StorageAccounts []helpers.StorageAccount `tfschema:"storage_account"` + ConnectionStrings []helpers.ConnectionString `tfschema:"connection_string"` + ZipDeployFile string `tfschema:"zip_deploy_file"` + Tags map[string]string `tfschema:"tags"` + CustomDomainVerificationId string `tfschema:"custom_domain_verification_id"` + HostingEnvId string `tfschema:"hosting_environment_id"` + DefaultHostname string `tfschema:"default_hostname"` + Kind string `tfschema:"kind"` + OutboundIPAddresses string `tfschema:"outbound_ip_addresses"` + OutboundIPAddressList []string `tfschema:"outbound_ip_address_list"` + PossibleOutboundIPAddresses string `tfschema:"possible_outbound_ip_addresses"` + PossibleOutboundIPAddressList []string `tfschema:"possible_outbound_ip_address_list"` + PublicNetworkAccess bool `tfschema:"public_network_access_enabled"` + PublishingDeployBasicAuthEnabled bool `tfschema:"webdeploy_publish_basic_authentication_enabled"` + PublishingFTPBasicAuthEnabled bool `tfschema:"ftp_publish_basic_authentication_enabled"` + SiteCredentials []helpers.SiteCredential `tfschema:"site_credential"` } var _ sdk.ResourceWithUpdate = LinuxWebAppResource{} @@ -162,13 +164,25 @@ func (r LinuxWebAppResource) Arguments() map[string]*pluginsdk.Schema { ValidateFunc: commonids.ValidateUserAssignedIdentityID, }, + "logs": helpers.LogsConfigSchema(), + "public_network_access_enabled": { Type: pluginsdk.TypeBool, Optional: true, Default: true, }, - "logs": helpers.LogsConfigSchema(), + "webdeploy_publish_basic_authentication_enabled": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: true, + }, + + "ftp_publish_basic_authentication_enabled": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: true, + }, "site_config": helpers.SiteConfigSchemaLinux(), @@ -188,8 +202,6 @@ func (r LinuxWebAppResource) Arguments() map[string]*pluginsdk.Schema { } } -// TODO - Feature: Deployments (Preview)? - func (r LinuxWebAppResource) Attributes() map[string]*pluginsdk.Schema { return map[string]*pluginsdk.Schema{ "custom_domain_verification_id": { @@ -467,6 +479,28 @@ func (r LinuxWebAppResource) Create() sdk.ResourceFunc { } } + if !webApp.PublishingDeployBasicAuthEnabled { + sitePolicy := web.CsmPublishingCredentialsPoliciesEntity{ + CsmPublishingCredentialsPoliciesEntityProperties: &web.CsmPublishingCredentialsPoliciesEntityProperties{ + Allow: pointer.To(false), + }, + } + if _, err := client.UpdateScmAllowed(ctx, id.ResourceGroup, id.SiteName, sitePolicy); err != nil { + return fmt.Errorf("setting basic auth for deploy publishing credentials for %s: %+v", id, err) + } + } + + if !webApp.PublishingFTPBasicAuthEnabled { + sitePolicy := web.CsmPublishingCredentialsPoliciesEntity{ + CsmPublishingCredentialsPoliciesEntityProperties: &web.CsmPublishingCredentialsPoliciesEntityProperties{ + Allow: pointer.To(false), + }, + } + if _, err := client.UpdateFtpAllowed(ctx, id.ResourceGroup, id.SiteName, sitePolicy); err != nil { + return fmt.Errorf("setting basic auth for ftp publishing credentials for %s: %+v", id, err) + } + } + return nil }, } @@ -553,6 +587,20 @@ func (r LinuxWebAppResource) Read() sdk.ResourceFunc { return fmt.Errorf("reading Site Publishing Credential information for Linux %s: %+v", id, err) } + basicAuthFTP := true + if basicAuthFTPResp, err := client.GetFtpAllowed(ctx, id.ResourceGroup, id.SiteName); err != nil { + return fmt.Errorf("retrieving state of FTP Basic Auth for %s: %+v", id, err) + } else if csmProps := basicAuthFTPResp.CsmPublishingCredentialsPoliciesEntityProperties; csmProps != nil { + basicAuthFTP = pointer.From(csmProps.Allow) + } + + basicAuthWebDeploy := true + if basicAuthWebDeployResp, err := client.GetScmAllowed(ctx, id.ResourceGroup, id.SiteName); err != nil { + return fmt.Errorf("retrieving state of WebDeploy Basic Auth for %s: %+v", id, err) + } else if csmProps := basicAuthWebDeployResp.CsmPublishingCredentialsPoliciesEntityProperties; csmProps != nil { + basicAuthWebDeploy = pointer.From(csmProps.Allow) + } + state := LinuxWebAppModel{} if props := webApp.SiteProperties; props != nil { state = LinuxWebAppModel{ @@ -592,6 +640,9 @@ func (r LinuxWebAppResource) Read() sdk.ResourceFunc { } } + state.PublishingFTPBasicAuthEnabled = basicAuthFTP + state.PublishingDeployBasicAuthEnabled = basicAuthWebDeploy + state.AppSettings = helpers.FlattenWebStringDictionary(appSettings) state.AuthSettings = helpers.FlattenAuthSettings(auth) @@ -918,6 +969,28 @@ func (r LinuxWebAppResource) Update() sdk.ResourceFunc { } } + if metadata.ResourceData.HasChange("ftp_publish_basic_authentication_enabled") { + sitePolicy := web.CsmPublishingCredentialsPoliciesEntity{ + CsmPublishingCredentialsPoliciesEntityProperties: &web.CsmPublishingCredentialsPoliciesEntityProperties{ + Allow: pointer.To(state.PublishingFTPBasicAuthEnabled), + }, + } + if _, err := client.UpdateFtpAllowed(ctx, id.ResourceGroup, id.SiteName, sitePolicy); err != nil { + return fmt.Errorf("setting basic auth for ftp publishing credentials for %s: %+v", id, err) + } + } + + if metadata.ResourceData.HasChange("webdeploy_publish_basic_authentication_enabled") { + sitePolicy := web.CsmPublishingCredentialsPoliciesEntity{ + CsmPublishingCredentialsPoliciesEntityProperties: &web.CsmPublishingCredentialsPoliciesEntityProperties{ + Allow: pointer.To(state.PublishingDeployBasicAuthEnabled), + }, + } + if _, err := client.UpdateScmAllowed(ctx, id.ResourceGroup, id.SiteName, sitePolicy); err != nil { + return fmt.Errorf("setting basic auth for deploy publishing credentials for %s: %+v", id, err) + } + } + return nil }, } diff --git a/internal/services/appservice/linux_web_app_resource_test.go b/internal/services/appservice/linux_web_app_resource_test.go index 928c69114806..df01ffc26a56 100644 --- a/internal/services/appservice/linux_web_app_resource_test.go +++ b/internal/services/appservice/linux_web_app_resource_test.go @@ -1372,6 +1372,52 @@ func TestAccLinuxWebApp_zipDeploy(t *testing.T) { }) } +func TestAccLinuxWebApp_disableDeployBasicAuth(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_linux_web_app", "test") + r := LinuxWebAppResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.deployBasicAuthDisabled(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("kind").HasValue("app,linux"), + ), + }, + data.ImportStep(), + }) +} + +func TestAccLinuxWebApp_disableDeployBasicAuthUpdate(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_linux_web_app", "test") + r := LinuxWebAppResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("kind").HasValue("app,linux"), + ), + }, + data.ImportStep(), { + Config: r.deployBasicAuthDisabled(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("kind").HasValue("app,linux"), + ), + }, + data.ImportStep(), { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("kind").HasValue("app,linux"), + ), + }, + data.ImportStep(), + }) +} + // Network tests func TestAccLinuxWebApp_vNetIntegration(t *testing.T) { @@ -1728,6 +1774,9 @@ resource "azurerm_linux_web_app" "test" { mount_path = "/storage/files" } + ftp_publish_basic_authentication_enabled = false + webdeploy_publish_basic_authentication_enabled = false + tags = { Environment = "AccTest" foo = "bar" @@ -3193,7 +3242,27 @@ resource "azurerm_linux_web_app" "test" { `, r.baseTemplate(data), data.RandomInteger) } -// TODO - Test for new acr creds? +func (r LinuxWebAppResource) deployBasicAuthDisabled(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +%s + +resource "azurerm_linux_web_app" "test" { + name = "acctestWA-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + service_plan_id = azurerm_service_plan.test.id + + ftp_publish_basic_authentication_enabled = false + webdeploy_publish_basic_authentication_enabled = false + + site_config {} +} +`, r.baseTemplate(data), data.RandomInteger) +} // Templates diff --git a/internal/services/appservice/linux_web_app_slot_resource.go b/internal/services/appservice/linux_web_app_slot_resource.go index 93821b25053c..65337dbd9581 100644 --- a/internal/services/appservice/linux_web_app_slot_resource.go +++ b/internal/services/appservice/linux_web_app_slot_resource.go @@ -29,38 +29,40 @@ import ( type LinuxWebAppSlotResource struct{} type LinuxWebAppSlotModel struct { - Name string `tfschema:"name"` - AppServiceId string `tfschema:"app_service_id"` - ServicePlanID string `tfschema:"service_plan_id"` - AppSettings map[string]string `tfschema:"app_settings"` - AuthSettings []helpers.AuthSettings `tfschema:"auth_settings"` - AuthV2Settings []helpers.AuthV2Settings `tfschema:"auth_settings_v2"` - Backup []helpers.Backup `tfschema:"backup"` - ClientAffinityEnabled bool `tfschema:"client_affinity_enabled"` - ClientCertEnabled bool `tfschema:"client_certificate_enabled"` - ClientCertMode string `tfschema:"client_certificate_mode"` - ClientCertExclusionPaths string `tfschema:"client_certificate_exclusion_paths"` - Enabled bool `tfschema:"enabled"` - HttpsOnly bool `tfschema:"https_only"` - KeyVaultReferenceIdentityID string `tfschema:"key_vault_reference_identity_id"` - LogsConfig []helpers.LogsConfig `tfschema:"logs"` - MetaData map[string]string `tfschema:"app_metadata"` - SiteConfig []helpers.SiteConfigLinuxWebAppSlot `tfschema:"site_config"` - StorageAccounts []helpers.StorageAccount `tfschema:"storage_account"` - ConnectionStrings []helpers.ConnectionString `tfschema:"connection_string"` - ZipDeployFile string `tfschema:"zip_deploy_file"` - Tags map[string]string `tfschema:"tags"` - CustomDomainVerificationId string `tfschema:"custom_domain_verification_id"` - DefaultHostname string `tfschema:"default_hostname"` - HostingEnvId string `tfschema:"hosting_environment_id"` - Kind string `tfschema:"kind"` - OutboundIPAddresses string `tfschema:"outbound_ip_addresses"` - OutboundIPAddressList []string `tfschema:"outbound_ip_address_list"` - PossibleOutboundIPAddresses string `tfschema:"possible_outbound_ip_addresses"` - PossibleOutboundIPAddressList []string `tfschema:"possible_outbound_ip_address_list"` - PublicNetworkAccess bool `tfschema:"public_network_access_enabled"` - SiteCredentials []helpers.SiteCredential `tfschema:"site_credential"` - VirtualNetworkSubnetID string `tfschema:"virtual_network_subnet_id"` + Name string `tfschema:"name"` + AppServiceId string `tfschema:"app_service_id"` + ServicePlanID string `tfschema:"service_plan_id"` + AppSettings map[string]string `tfschema:"app_settings"` + AuthSettings []helpers.AuthSettings `tfschema:"auth_settings"` + AuthV2Settings []helpers.AuthV2Settings `tfschema:"auth_settings_v2"` + Backup []helpers.Backup `tfschema:"backup"` + ClientAffinityEnabled bool `tfschema:"client_affinity_enabled"` + ClientCertEnabled bool `tfschema:"client_certificate_enabled"` + ClientCertMode string `tfschema:"client_certificate_mode"` + ClientCertExclusionPaths string `tfschema:"client_certificate_exclusion_paths"` + Enabled bool `tfschema:"enabled"` + HttpsOnly bool `tfschema:"https_only"` + KeyVaultReferenceIdentityID string `tfschema:"key_vault_reference_identity_id"` + LogsConfig []helpers.LogsConfig `tfschema:"logs"` + MetaData map[string]string `tfschema:"app_metadata"` + SiteConfig []helpers.SiteConfigLinuxWebAppSlot `tfschema:"site_config"` + StorageAccounts []helpers.StorageAccount `tfschema:"storage_account"` + ConnectionStrings []helpers.ConnectionString `tfschema:"connection_string"` + ZipDeployFile string `tfschema:"zip_deploy_file"` + Tags map[string]string `tfschema:"tags"` + CustomDomainVerificationId string `tfschema:"custom_domain_verification_id"` + DefaultHostname string `tfschema:"default_hostname"` + HostingEnvId string `tfschema:"hosting_environment_id"` + Kind string `tfschema:"kind"` + OutboundIPAddresses string `tfschema:"outbound_ip_addresses"` + OutboundIPAddressList []string `tfschema:"outbound_ip_address_list"` + PossibleOutboundIPAddresses string `tfschema:"possible_outbound_ip_addresses"` + PossibleOutboundIPAddressList []string `tfschema:"possible_outbound_ip_address_list"` + PublicNetworkAccess bool `tfschema:"public_network_access_enabled"` + PublishingDeployBasicAuthEnabled bool `tfschema:"webdeploy_publish_basic_authentication_enabled"` + PublishingFTPBasicAuthEnabled bool `tfschema:"ftp_publish_basic_authentication_enabled"` + SiteCredentials []helpers.SiteCredential `tfschema:"site_credential"` + VirtualNetworkSubnetID string `tfschema:"virtual_network_subnet_id"` } var _ sdk.ResourceWithUpdate = LinuxWebAppSlotResource{} @@ -179,6 +181,18 @@ func (r LinuxWebAppSlotResource) Arguments() map[string]*pluginsdk.Schema { Default: true, }, + "webdeploy_publish_basic_authentication_enabled": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: true, + }, + + "ftp_publish_basic_authentication_enabled": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: true, + }, + "logs": helpers.LogsConfigSchema(), "site_config": helpers.SiteConfigSchemaLinuxWebAppSlot(), @@ -435,6 +449,28 @@ func (r LinuxWebAppSlotResource) Create() sdk.ResourceFunc { } } + if !webAppSlot.PublishingDeployBasicAuthEnabled { + sitePolicy := web.CsmPublishingCredentialsPoliciesEntity{ + CsmPublishingCredentialsPoliciesEntityProperties: &web.CsmPublishingCredentialsPoliciesEntityProperties{ + Allow: pointer.To(false), + }, + } + if _, err := client.UpdateScmAllowedSlot(ctx, id.ResourceGroup, id.SiteName, sitePolicy, id.SlotName); err != nil { + return fmt.Errorf("setting basic auth for deploy publishing credentials for %s: %+v", id, err) + } + } + + if !webAppSlot.PublishingFTPBasicAuthEnabled { + sitePolicy := web.CsmPublishingCredentialsPoliciesEntity{ + CsmPublishingCredentialsPoliciesEntityProperties: &web.CsmPublishingCredentialsPoliciesEntityProperties{ + Allow: pointer.To(false), + }, + } + if _, err := client.UpdateFtpAllowedSlot(ctx, id.ResourceGroup, id.SiteName, sitePolicy, id.SlotName); err != nil { + return fmt.Errorf("setting basic auth for ftp publishing credentials for %s: %+v", id, err) + } + } + return nil }, } @@ -525,6 +561,20 @@ func (r LinuxWebAppSlotResource) Read() sdk.ResourceFunc { return fmt.Errorf("reading parent Function App Service Plan information for Linux %s: %+v", *id, err) } + basicAuthFTP := true + if basicAuthFTPResp, err := client.GetFtpAllowedSlot(ctx, id.ResourceGroup, id.SiteName, id.SlotName); err != nil { + return fmt.Errorf("retrieving state of FTP Basic Auth for %s: %+v", id, err) + } else if csmProps := basicAuthFTPResp.CsmPublishingCredentialsPoliciesEntityProperties; csmProps != nil { + basicAuthFTP = pointer.From(csmProps.Allow) + } + + basicAuthWebDeploy := true + if basicAuthWebDeployResp, err := client.GetScmAllowedSlot(ctx, id.ResourceGroup, id.SiteName, id.SlotName); err != nil { + return fmt.Errorf("retrieving state of WebDeploy Basic Auth for %s: %+v", id, err) + } else if csmProps := basicAuthWebDeployResp.CsmPublishingCredentialsPoliciesEntityProperties; csmProps != nil { + basicAuthWebDeploy = pointer.From(csmProps.Allow) + } + state := LinuxWebAppSlotModel{} if props := webAppSlot.SiteProperties; props != nil { state = LinuxWebAppSlotModel{ @@ -569,6 +619,9 @@ func (r LinuxWebAppSlotResource) Read() sdk.ResourceFunc { } } + state.PublishingFTPBasicAuthEnabled = basicAuthFTP + state.PublishingDeployBasicAuthEnabled = basicAuthWebDeploy + state.AppSettings = helpers.FlattenWebStringDictionary(appSettings) if err != nil { return fmt.Errorf("flattening app settings for Linux %s: %+v", id, err) @@ -865,6 +918,28 @@ func (r LinuxWebAppSlotResource) Update() sdk.ResourceFunc { } } + if metadata.ResourceData.HasChange("ftp_publish_basic_authentication_enabled") { + sitePolicy := web.CsmPublishingCredentialsPoliciesEntity{ + CsmPublishingCredentialsPoliciesEntityProperties: &web.CsmPublishingCredentialsPoliciesEntityProperties{ + Allow: pointer.To(state.PublishingFTPBasicAuthEnabled), + }, + } + if _, err := client.UpdateFtpAllowedSlot(ctx, id.ResourceGroup, id.SiteName, sitePolicy, id.SlotName); err != nil { + return fmt.Errorf("setting basic auth for ftp publishing credentials for %s: %+v", id, err) + } + } + + if metadata.ResourceData.HasChange("webdeploy_publish_basic_authentication_enabled") { + sitePolicy := web.CsmPublishingCredentialsPoliciesEntity{ + CsmPublishingCredentialsPoliciesEntityProperties: &web.CsmPublishingCredentialsPoliciesEntityProperties{ + Allow: pointer.To(state.PublishingDeployBasicAuthEnabled), + }, + } + if _, err := client.UpdateScmAllowedSlot(ctx, id.ResourceGroup, id.SiteName, sitePolicy, id.SlotName); err != nil { + return fmt.Errorf("setting basic auth for deploy publishing credentials for %s: %+v", id, err) + } + } + return nil }, } diff --git a/internal/services/appservice/linux_web_app_slot_resource_test.go b/internal/services/appservice/linux_web_app_slot_resource_test.go index 42d209d61a05..1f84d11f04b1 100644 --- a/internal/services/appservice/linux_web_app_slot_resource_test.go +++ b/internal/services/appservice/linux_web_app_slot_resource_test.go @@ -1147,6 +1147,50 @@ func TestAccLinuxWebAppSlot_zipDeploy(t *testing.T) { }) } +func TestAccLinuxWebAppSlot_disableDeployBasicAuth(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_linux_web_app_slot", "test") + r := LinuxWebAppSlotResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.deployBasicAuthDisabled(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func TestAccLinuxWebAppSlot_disableDeployBasicAuthUpdate(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_linux_web_app_slot", "test") + r := LinuxWebAppSlotResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + { + Config: r.deployBasicAuthDisabled(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + // Network tests func TestAccLinuxWebAppSlot_vNetIntegration(t *testing.T) { @@ -2538,6 +2582,26 @@ resource "azurerm_linux_web_app_slot" "test" { `, r.baseTemplate(data), data.RandomInteger) } +func (r LinuxWebAppSlotResource) deployBasicAuthDisabled(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +%s + +resource "azurerm_linux_web_app_slot" "test" { + name = "acctestWAS-%d" + app_service_id = azurerm_linux_web_app.test.id + + ftp_publish_basic_authentication_enabled = false + webdeploy_publish_basic_authentication_enabled = false + + site_config {} +} +`, r.baseTemplate(data), data.RandomInteger) +} + // Templates func (LinuxWebAppSlotResource) baseTemplate(data acceptance.TestData) string { diff --git a/internal/services/appservice/windows_function_app_data_source.go b/internal/services/appservice/windows_function_app_data_source.go index 8c462eb91ecd..412f49cf0250 100644 --- a/internal/services/appservice/windows_function_app_data_source.go +++ b/internal/services/appservice/windows_function_app_data_source.go @@ -36,25 +36,27 @@ type WindowsFunctionAppDataSourceModel struct { StorageUsesMSI bool `tfschema:"storage_uses_managed_identity"` StorageKeyVaultSecretID string `tfschema:"storage_key_vault_secret_id"` - AppSettings map[string]string `tfschema:"app_settings"` - AuthSettings []helpers.AuthSettings `tfschema:"auth_settings"` - AuthV2Settings []helpers.AuthV2Settings `tfschema:"auth_settings_v2"` - Backup []helpers.Backup `tfschema:"backup"` - BuiltinLogging bool `tfschema:"builtin_logging_enabled"` - ClientCertEnabled bool `tfschema:"client_certificate_enabled"` - ClientCertMode string `tfschema:"client_certificate_mode"` - ClientCertExclusionPaths string `tfschema:"client_certificate_exclusion_paths"` - ConnectionStrings []helpers.ConnectionString `tfschema:"connection_string"` - DailyMemoryTimeQuota int `tfschema:"daily_memory_time_quota"` - Enabled bool `tfschema:"enabled"` - FunctionExtensionsVersion string `tfschema:"functions_extension_version"` - ForceDisableContentShare bool `tfschema:"content_share_force_disabled"` - HttpsOnly bool `tfschema:"https_only"` - PublicNetworkAccess bool `tfschema:"public_network_access_enabled"` - SiteConfig []helpers.SiteConfigWindowsFunctionApp `tfschema:"site_config"` - StickySettings []helpers.StickySettings `tfschema:"sticky_settings"` - Tags map[string]string `tfschema:"tags"` - VirtualNetworkSubnetId string `tfschema:"virtual_network_subnet_id"` + AppSettings map[string]string `tfschema:"app_settings"` + AuthSettings []helpers.AuthSettings `tfschema:"auth_settings"` + AuthV2Settings []helpers.AuthV2Settings `tfschema:"auth_settings_v2"` + Backup []helpers.Backup `tfschema:"backup"` + BuiltinLogging bool `tfschema:"builtin_logging_enabled"` + ClientCertEnabled bool `tfschema:"client_certificate_enabled"` + ClientCertMode string `tfschema:"client_certificate_mode"` + ClientCertExclusionPaths string `tfschema:"client_certificate_exclusion_paths"` + ConnectionStrings []helpers.ConnectionString `tfschema:"connection_string"` + DailyMemoryTimeQuota int `tfschema:"daily_memory_time_quota"` + Enabled bool `tfschema:"enabled"` + FunctionExtensionsVersion string `tfschema:"functions_extension_version"` + ForceDisableContentShare bool `tfschema:"content_share_force_disabled"` + HttpsOnly bool `tfschema:"https_only"` + PublicNetworkAccess bool `tfschema:"public_network_access_enabled"` + PublishingDeployBasicAuthEnabled bool `tfschema:"webdeploy_publish_basic_authentication_enabled"` + PublishingFTPBasicAuthEnabled bool `tfschema:"ftp_publish_basic_authentication_enabled"` + SiteConfig []helpers.SiteConfigWindowsFunctionApp `tfschema:"site_config"` + StickySettings []helpers.StickySettings `tfschema:"sticky_settings"` + Tags map[string]string `tfschema:"tags"` + VirtualNetworkSubnetId string `tfschema:"virtual_network_subnet_id"` CustomDomainVerificationId string `tfschema:"custom_domain_verification_id"` DefaultHostname string `tfschema:"default_hostname"` @@ -236,6 +238,16 @@ func (d WindowsFunctionAppDataSource) Attributes() map[string]*pluginsdk.Schema "site_credential": helpers.SiteCredentialSchema(), + "webdeploy_publish_basic_authentication_enabled": { + Type: pluginsdk.TypeBool, + Computed: true, + }, + + "ftp_publish_basic_authentication_enabled": { + Type: pluginsdk.TypeBool, + Computed: true, + }, + "site_config": helpers.SiteConfigSchemaWindowsFunctionAppComputed(), "sticky_settings": helpers.StickySettingsComputedSchema(), @@ -293,6 +305,23 @@ func (d WindowsFunctionAppDataSource) Read() sdk.ResourceFunc { functionApp.VirtualNetworkSubnetId = utils.NormalizeNilableString(props.VirtualNetworkSubnetID) functionApp.PublicNetworkAccess = !strings.EqualFold(pointer.From(props.PublicNetworkAccess), helpers.PublicNetworkAccessDisabled) + basicAuthFTP := true + if basicAuthFTPResp, err := client.GetFtpAllowed(ctx, id.ResourceGroup, id.SiteName); err != nil { + return fmt.Errorf("retrieving state of FTP Basic Auth for %s: %+v", id, err) + } else if csmProps := basicAuthFTPResp.CsmPublishingCredentialsPoliciesEntityProperties; csmProps != nil { + basicAuthFTP = pointer.From(csmProps.Allow) + } + + basicAuthWebDeploy := true + if basicAuthWebDeployResp, err := client.GetScmAllowed(ctx, id.ResourceGroup, id.SiteName); err != nil { + return fmt.Errorf("retrieving state of WebDeploy Basic Auth for %s: %+v", id, err) + } else if csmProps := basicAuthWebDeployResp.CsmPublishingCredentialsPoliciesEntityProperties; csmProps != nil { + basicAuthWebDeploy = pointer.From(csmProps.Allow) + } + + functionApp.PublishingFTPBasicAuthEnabled = basicAuthFTP + functionApp.PublishingDeployBasicAuthEnabled = basicAuthWebDeploy + if hostingEnv := props.HostingEnvironmentProfile; hostingEnv != nil { functionApp.HostingEnvId = pointer.From(hostingEnv.ID) } diff --git a/internal/services/appservice/windows_function_app_resource.go b/internal/services/appservice/windows_function_app_resource.go index 41b5497281c3..bb69eaad0471 100644 --- a/internal/services/appservice/windows_function_app_resource.go +++ b/internal/services/appservice/windows_function_app_resource.go @@ -41,28 +41,30 @@ type WindowsFunctionAppModel struct { StorageUsesMSI bool `tfschema:"storage_uses_managed_identity"` // Storage uses MSI not account key StorageKeyVaultSecretID string `tfschema:"storage_key_vault_secret_id"` - AppSettings map[string]string `tfschema:"app_settings"` - StickySettings []helpers.StickySettings `tfschema:"sticky_settings"` - AuthSettings []helpers.AuthSettings `tfschema:"auth_settings"` - AuthV2Settings []helpers.AuthV2Settings `tfschema:"auth_settings_v2"` - Backup []helpers.Backup `tfschema:"backup"` // Not supported on Dynamic or Basic plans - BuiltinLogging bool `tfschema:"builtin_logging_enabled"` - ClientCertEnabled bool `tfschema:"client_certificate_enabled"` - ClientCertMode string `tfschema:"client_certificate_mode"` - ClientCertExclusionPaths string `tfschema:"client_certificate_exclusion_paths"` - ConnectionStrings []helpers.ConnectionString `tfschema:"connection_string"` - DailyMemoryTimeQuota int `tfschema:"daily_memory_time_quota"` - Enabled bool `tfschema:"enabled"` - FunctionExtensionsVersion string `tfschema:"functions_extension_version"` - ForceDisableContentShare bool `tfschema:"content_share_force_disabled"` - HttpsOnly bool `tfschema:"https_only"` - KeyVaultReferenceIdentityID string `tfschema:"key_vault_reference_identity_id"` - PublicNetworkAccess bool `tfschema:"public_network_access_enabled"` - SiteConfig []helpers.SiteConfigWindowsFunctionApp `tfschema:"site_config"` - StorageAccounts []helpers.StorageAccount `tfschema:"storage_account"` - Tags map[string]string `tfschema:"tags"` - VirtualNetworkSubnetID string `tfschema:"virtual_network_subnet_id"` - ZipDeployFile string `tfschema:"zip_deploy_file"` + AppSettings map[string]string `tfschema:"app_settings"` + StickySettings []helpers.StickySettings `tfschema:"sticky_settings"` + AuthSettings []helpers.AuthSettings `tfschema:"auth_settings"` + AuthV2Settings []helpers.AuthV2Settings `tfschema:"auth_settings_v2"` + Backup []helpers.Backup `tfschema:"backup"` // Not supported on Dynamic or Basic plans + BuiltinLogging bool `tfschema:"builtin_logging_enabled"` + ClientCertEnabled bool `tfschema:"client_certificate_enabled"` + ClientCertMode string `tfschema:"client_certificate_mode"` + ClientCertExclusionPaths string `tfschema:"client_certificate_exclusion_paths"` + ConnectionStrings []helpers.ConnectionString `tfschema:"connection_string"` + DailyMemoryTimeQuota int `tfschema:"daily_memory_time_quota"` + Enabled bool `tfschema:"enabled"` + FunctionExtensionsVersion string `tfschema:"functions_extension_version"` + ForceDisableContentShare bool `tfschema:"content_share_force_disabled"` + HttpsOnly bool `tfschema:"https_only"` + KeyVaultReferenceIdentityID string `tfschema:"key_vault_reference_identity_id"` + PublicNetworkAccess bool `tfschema:"public_network_access_enabled"` + SiteConfig []helpers.SiteConfigWindowsFunctionApp `tfschema:"site_config"` + StorageAccounts []helpers.StorageAccount `tfschema:"storage_account"` + Tags map[string]string `tfschema:"tags"` + VirtualNetworkSubnetID string `tfschema:"virtual_network_subnet_id"` + ZipDeployFile string `tfschema:"zip_deploy_file"` + PublishingDeployBasicAuthEnabled bool `tfschema:"webdeploy_publish_basic_authentication_enabled"` + PublishingFTPBasicAuthEnabled bool `tfschema:"ftp_publish_basic_authentication_enabled"` // Computed CustomDomainVerificationId string `tfschema:"custom_domain_verification_id"` @@ -262,6 +264,18 @@ func (r WindowsFunctionAppResource) Arguments() map[string]*pluginsdk.Schema { Default: true, }, + "webdeploy_publish_basic_authentication_enabled": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: true, + }, + + "ftp_publish_basic_authentication_enabled": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: true, + }, + "site_config": helpers.SiteConfigSchemaWindowsFunctionApp(), "sticky_settings": helpers.StickySettingsSchema(), @@ -528,6 +542,28 @@ func (r WindowsFunctionAppResource) Create() sdk.ResourceFunc { return fmt.Errorf("waiting for creation of Windows %s: %+v", id, err) } + if !functionApp.PublishingDeployBasicAuthEnabled { + sitePolicy := web.CsmPublishingCredentialsPoliciesEntity{ + CsmPublishingCredentialsPoliciesEntityProperties: &web.CsmPublishingCredentialsPoliciesEntityProperties{ + Allow: pointer.To(false), + }, + } + if _, err := client.UpdateScmAllowed(ctx, id.ResourceGroup, id.SiteName, sitePolicy); err != nil { + return fmt.Errorf("setting basic auth for deploy publishing credentials for %s: %+v", id, err) + } + } + + if !functionApp.PublishingFTPBasicAuthEnabled { + sitePolicy := web.CsmPublishingCredentialsPoliciesEntity{ + CsmPublishingCredentialsPoliciesEntityProperties: &web.CsmPublishingCredentialsPoliciesEntityProperties{ + Allow: pointer.To(false), + }, + } + if _, err := client.UpdateFtpAllowed(ctx, id.ResourceGroup, id.SiteName, sitePolicy); err != nil { + return fmt.Errorf("setting basic auth for ftp publishing credentials for %s: %+v", id, err) + } + } + updateFuture, err := client.CreateOrUpdate(ctx, id.ResourceGroup, id.SiteName, siteEnvelope) if err != nil { return fmt.Errorf("updating properties of Windows %s: %+v", id, err) @@ -686,6 +722,20 @@ func (r WindowsFunctionAppResource) Read() sdk.ResourceFunc { return fmt.Errorf("reading logs configuration for Windows %s: %+v", id, err) } + basicAuthFTP := true + if basicAuthFTPResp, err := client.GetFtpAllowed(ctx, id.ResourceGroup, id.SiteName); err != nil { + return fmt.Errorf("retrieving state of FTP Basic Auth for %s: %+v", id, err) + } else if csmProps := basicAuthFTPResp.CsmPublishingCredentialsPoliciesEntityProperties; csmProps != nil { + basicAuthFTP = pointer.From(csmProps.Allow) + } + + basicAuthWebDeploy := true + if basicAuthWebDeployResp, err := client.GetScmAllowed(ctx, id.ResourceGroup, id.SiteName); err != nil { + return fmt.Errorf("retrieving state of WebDeploy Basic Auth for %s: %+v", id, err) + } else if csmProps := basicAuthWebDeployResp.CsmPublishingCredentialsPoliciesEntityProperties; csmProps != nil { + basicAuthWebDeploy = pointer.From(csmProps.Allow) + } + state := WindowsFunctionAppModel{ Name: id.SiteName, ResourceGroup: id.ResourceGroup, @@ -704,6 +754,9 @@ func (r WindowsFunctionAppResource) Read() sdk.ResourceFunc { PublicNetworkAccess: !strings.EqualFold(pointer.From(props.PublicNetworkAccess), helpers.PublicNetworkAccessDisabled), } + state.PublishingFTPBasicAuthEnabled = basicAuthFTP + state.PublishingDeployBasicAuthEnabled = basicAuthWebDeploy + if hostingEnv := props.HostingEnvironmentProfile; hostingEnv != nil { hostingEnvId, err := parse.AppServiceEnvironmentIDInsensitively(*hostingEnv.ID) if err != nil { @@ -1004,6 +1057,28 @@ func (r WindowsFunctionAppResource) Update() sdk.ResourceFunc { return fmt.Errorf("waiting to update %s: %+v", id, err) } + if metadata.ResourceData.HasChange("ftp_publish_basic_authentication_enabled") { + sitePolicy := web.CsmPublishingCredentialsPoliciesEntity{ + CsmPublishingCredentialsPoliciesEntityProperties: &web.CsmPublishingCredentialsPoliciesEntityProperties{ + Allow: pointer.To(state.PublishingFTPBasicAuthEnabled), + }, + } + if _, err := client.UpdateFtpAllowed(ctx, id.ResourceGroup, id.SiteName, sitePolicy); err != nil { + return fmt.Errorf("setting basic auth for ftp publishing credentials for %s: %+v", id, err) + } + } + + if metadata.ResourceData.HasChange("webdeploy_publish_basic_authentication_enabled") { + sitePolicy := web.CsmPublishingCredentialsPoliciesEntity{ + CsmPublishingCredentialsPoliciesEntityProperties: &web.CsmPublishingCredentialsPoliciesEntityProperties{ + Allow: pointer.To(state.PublishingDeployBasicAuthEnabled), + }, + } + if _, err := client.UpdateScmAllowed(ctx, id.ResourceGroup, id.SiteName, sitePolicy); err != nil { + return fmt.Errorf("setting basic auth for deploy publishing credentials for %s: %+v", id, err) + } + } + if _, err := client.UpdateConfiguration(ctx, id.ResourceGroup, id.SiteName, web.SiteConfigResource{SiteConfig: existing.SiteConfig}); err != nil { return fmt.Errorf("updating Site Config for Windows %s: %+v", id, err) } diff --git a/internal/services/appservice/windows_function_app_resource_test.go b/internal/services/appservice/windows_function_app_resource_test.go index 70b002028d4e..80e91dee804f 100644 --- a/internal/services/appservice/windows_function_app_resource_test.go +++ b/internal/services/appservice/windows_function_app_resource_test.go @@ -2063,6 +2063,9 @@ resource "azurerm_windows_function_app" "test" { } } + ftp_publish_basic_authentication_enabled = false + webdeploy_publish_basic_authentication_enabled = false + tags = { terraform = "true" Env = "AccTest" diff --git a/internal/services/appservice/windows_function_app_slot_resource.go b/internal/services/appservice/windows_function_app_slot_resource.go index a3eb4e1b5496..afe88b392bf4 100644 --- a/internal/services/appservice/windows_function_app_slot_resource.go +++ b/internal/services/appservice/windows_function_app_slot_resource.go @@ -31,29 +31,32 @@ import ( type WindowsFunctionAppSlotResource struct{} type WindowsFunctionAppSlotModel struct { - Name string `tfschema:"name"` - FunctionAppID string `tfschema:"function_app_id"` - ServicePlanID string `tfschema:"service_plan_id"` - StorageAccountName string `tfschema:"storage_account_name"` - StorageAccountKey string `tfschema:"storage_account_access_key"` - StorageUsesMSI bool `tfschema:"storage_uses_managed_identity"` // Storage uses MSI not account key - StorageKeyVaultSecretID string `tfschema:"storage_key_vault_secret_id"` - AppSettings map[string]string `tfschema:"app_settings"` - AuthSettings []helpers.AuthSettings `tfschema:"auth_settings"` - AuthV2Settings []helpers.AuthV2Settings `tfschema:"auth_settings_v2"` - Backup []helpers.Backup `tfschema:"backup"` // Not supported on Dynamic or Basic plans - BuiltinLogging bool `tfschema:"builtin_logging_enabled"` - ClientCertEnabled bool `tfschema:"client_certificate_enabled"` - ClientCertMode string `tfschema:"client_certificate_mode"` - ClientCertExclusionPaths string `tfschema:"client_certificate_exclusion_paths"` - ConnectionStrings []helpers.ConnectionString `tfschema:"connection_string"` - DailyMemoryTimeQuota int `tfschema:"daily_memory_time_quota"` - Enabled bool `tfschema:"enabled"` - FunctionExtensionsVersion string `tfschema:"functions_extension_version"` - ForceDisableContentShare bool `tfschema:"content_share_force_disabled"` - HttpsOnly bool `tfschema:"https_only"` - KeyVaultReferenceIdentityID string `tfschema:"key_vault_reference_identity_id"` - PublicNetworkAccess bool `tfschema:"public_network_access_enabled"` + Name string `tfschema:"name"` + FunctionAppID string `tfschema:"function_app_id"` + ServicePlanID string `tfschema:"service_plan_id"` + StorageAccountName string `tfschema:"storage_account_name"` + StorageAccountKey string `tfschema:"storage_account_access_key"` + StorageUsesMSI bool `tfschema:"storage_uses_managed_identity"` // Storage uses MSI not account key + StorageKeyVaultSecretID string `tfschema:"storage_key_vault_secret_id"` + AppSettings map[string]string `tfschema:"app_settings"` + AuthSettings []helpers.AuthSettings `tfschema:"auth_settings"` + AuthV2Settings []helpers.AuthV2Settings `tfschema:"auth_settings_v2"` + Backup []helpers.Backup `tfschema:"backup"` // Not supported on Dynamic or Basic plans + BuiltinLogging bool `tfschema:"builtin_logging_enabled"` + ClientCertEnabled bool `tfschema:"client_certificate_enabled"` + ClientCertMode string `tfschema:"client_certificate_mode"` + ClientCertExclusionPaths string `tfschema:"client_certificate_exclusion_paths"` + ConnectionStrings []helpers.ConnectionString `tfschema:"connection_string"` + DailyMemoryTimeQuota int `tfschema:"daily_memory_time_quota"` + Enabled bool `tfschema:"enabled"` + FunctionExtensionsVersion string `tfschema:"functions_extension_version"` + ForceDisableContentShare bool `tfschema:"content_share_force_disabled"` + HttpsOnly bool `tfschema:"https_only"` + KeyVaultReferenceIdentityID string `tfschema:"key_vault_reference_identity_id"` + PublicNetworkAccess bool `tfschema:"public_network_access_enabled"` + PublishingDeployBasicAuthEnabled bool `tfschema:"webdeploy_publish_basic_authentication_enabled"` + PublishingFTPBasicAuthEnabled bool `tfschema:"ftp_publish_basic_authentication_enabled"` + SiteConfig []helpers.SiteConfigWindowsFunctionAppSlot `tfschema:"site_config"` Tags map[string]string `tfschema:"tags"` CustomDomainVerificationId string `tfschema:"custom_domain_verification_id"` @@ -253,6 +256,18 @@ func (r WindowsFunctionAppSlotResource) Arguments() map[string]*pluginsdk.Schema Default: true, }, + "webdeploy_publish_basic_authentication_enabled": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: true, + }, + + "ftp_publish_basic_authentication_enabled": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: true, + }, + "site_config": helpers.SiteConfigSchemaWindowsFunctionAppSlot(), "storage_account": helpers.StorageAccountSchemaWindows(), @@ -535,6 +550,28 @@ func (r WindowsFunctionAppSlotResource) Create() sdk.ResourceFunc { return fmt.Errorf("waiting for creation of Windows %s: %+v", id, err) } + if !functionAppSlot.PublishingDeployBasicAuthEnabled { + sitePolicy := web.CsmPublishingCredentialsPoliciesEntity{ + CsmPublishingCredentialsPoliciesEntityProperties: &web.CsmPublishingCredentialsPoliciesEntityProperties{ + Allow: pointer.To(false), + }, + } + if _, err := client.UpdateScmAllowedSlot(ctx, id.ResourceGroup, id.SiteName, sitePolicy, id.SlotName); err != nil { + return fmt.Errorf("setting basic auth for deploy publishing credentials for %s: %+v", id, err) + } + } + + if !functionAppSlot.PublishingFTPBasicAuthEnabled { + sitePolicy := web.CsmPublishingCredentialsPoliciesEntity{ + CsmPublishingCredentialsPoliciesEntityProperties: &web.CsmPublishingCredentialsPoliciesEntityProperties{ + Allow: pointer.To(false), + }, + } + if _, err := client.UpdateFtpAllowedSlot(ctx, id.ResourceGroup, id.SiteName, sitePolicy, id.SlotName); err != nil { + return fmt.Errorf("setting basic auth for ftp publishing credentials for %s: %+v", id, err) + } + } + updateFuture, err := client.CreateOrUpdateSlot(ctx, id.ResourceGroup, id.SiteName, siteEnvelope, id.SlotName) if err != nil { return fmt.Errorf("updating properties of Windows %s: %+v", id, err) @@ -673,6 +710,20 @@ func (r WindowsFunctionAppSlotResource) Read() sdk.ResourceFunc { return fmt.Errorf("reading logs configuration for Windows %s: %+v", id, err) } + basicAuthFTP := true + if basicAuthFTPResp, err := client.GetFtpAllowedSlot(ctx, id.ResourceGroup, id.SiteName, id.SlotName); err != nil { + return fmt.Errorf("retrieving state of FTP Basic Auth for %s: %+v", id, err) + } else if csmProps := basicAuthFTPResp.CsmPublishingCredentialsPoliciesEntityProperties; csmProps != nil { + basicAuthFTP = pointer.From(csmProps.Allow) + } + + basicAuthWebDeploy := true + if basicAuthWebDeployResp, err := client.GetScmAllowedSlot(ctx, id.ResourceGroup, id.SiteName, id.SlotName); err != nil { + return fmt.Errorf("retrieving state of WebDeploy Basic Auth for %s: %+v", id, err) + } else if csmProps := basicAuthWebDeployResp.CsmPublishingCredentialsPoliciesEntityProperties; csmProps != nil { + basicAuthWebDeploy = pointer.From(csmProps.Allow) + } + state := WindowsFunctionAppSlotModel{ Name: id.SlotName, FunctionAppID: parse.NewFunctionAppID(id.SubscriptionId, id.ResourceGroup, id.SiteName).ID(), @@ -688,6 +739,9 @@ func (r WindowsFunctionAppSlotResource) Read() sdk.ResourceFunc { PublicNetworkAccess: !strings.EqualFold(pointer.From(props.PublicNetworkAccess), helpers.PublicNetworkAccessDisabled), } + state.PublishingFTPBasicAuthEnabled = basicAuthFTP + state.PublishingDeployBasicAuthEnabled = basicAuthWebDeploy + if hostingEnv := props.HostingEnvironmentProfile; hostingEnv != nil { state.HostingEnvId = pointer.From(hostingEnv.ID) } @@ -955,6 +1009,28 @@ func (r WindowsFunctionAppSlotResource) Update() sdk.ResourceFunc { return fmt.Errorf("waiting to update %s: %+v", id, err) } + if metadata.ResourceData.HasChange("ftp_publish_basic_authentication_enabled") { + sitePolicy := web.CsmPublishingCredentialsPoliciesEntity{ + CsmPublishingCredentialsPoliciesEntityProperties: &web.CsmPublishingCredentialsPoliciesEntityProperties{ + Allow: pointer.To(state.PublishingFTPBasicAuthEnabled), + }, + } + if _, err := client.UpdateFtpAllowedSlot(ctx, id.ResourceGroup, id.SiteName, sitePolicy, id.SlotName); err != nil { + return fmt.Errorf("setting basic auth for ftp publishing credentials for %s: %+v", id, err) + } + } + + if metadata.ResourceData.HasChange("webdeploy_publish_basic_authentication_enabled") { + sitePolicy := web.CsmPublishingCredentialsPoliciesEntity{ + CsmPublishingCredentialsPoliciesEntityProperties: &web.CsmPublishingCredentialsPoliciesEntityProperties{ + Allow: pointer.To(state.PublishingDeployBasicAuthEnabled), + }, + } + if _, err := client.UpdateScmAllowedSlot(ctx, id.ResourceGroup, id.SiteName, sitePolicy, id.SlotName); err != nil { + return fmt.Errorf("setting basic auth for deploy publishing credentials for %s: %+v", id, err) + } + } + if _, err := client.UpdateConfigurationSlot(ctx, id.ResourceGroup, id.SiteName, web.SiteConfigResource{SiteConfig: siteConfig}, id.SlotName); err != nil { return fmt.Errorf("updating Site Config for Windows %s: %+v", id, err) } diff --git a/internal/services/appservice/windows_function_app_slot_resource_test.go b/internal/services/appservice/windows_function_app_slot_resource_test.go index cedd3608770b..a2bf08ed38d3 100644 --- a/internal/services/appservice/windows_function_app_slot_resource_test.go +++ b/internal/services/appservice/windows_function_app_slot_resource_test.go @@ -1538,6 +1538,9 @@ resource "azurerm_windows_function_app_slot" "test" { } } + ftp_publish_basic_authentication_enabled = false + webdeploy_publish_basic_authentication_enabled = false + tags = { terraform = "true" Env = "AccTest" diff --git a/internal/services/appservice/windows_web_app_data_source.go b/internal/services/appservice/windows_web_app_data_source.go index 047fc0716f6a..e7137c3b958c 100644 --- a/internal/services/appservice/windows_web_app_data_source.go +++ b/internal/services/appservice/windows_web_app_data_source.go @@ -24,37 +24,39 @@ import ( type WindowsWebAppDataSource struct{} type WindowsWebAppDataSourceModel struct { - Name string `tfschema:"name"` - ResourceGroup string `tfschema:"resource_group_name"` - Location string `tfschema:"location"` - ServicePlanId string `tfschema:"service_plan_id"` - AppSettings map[string]string `tfschema:"app_settings"` - AuthSettings []helpers.AuthSettings `tfschema:"auth_settings"` - AuthV2Settings []helpers.AuthV2Settings `tfschema:"auth_settings_v2"` - Backup []helpers.Backup `tfschema:"backup"` - ClientAffinityEnabled bool `tfschema:"client_affinity_enabled"` - ClientCertEnabled bool `tfschema:"client_certificate_enabled"` - ClientCertMode string `tfschema:"client_certificate_mode"` - ClientCertExclusionPaths string `tfschema:"client_certificate_exclusion_paths"` - Enabled bool `tfschema:"enabled"` - HttpsOnly bool `tfschema:"https_only"` - LogsConfig []helpers.LogsConfig `tfschema:"logs"` - PublicNetworkAccess bool `tfschema:"public_network_access_enabled"` - SiteConfig []helpers.SiteConfigWindows `tfschema:"site_config"` - StickySettings []helpers.StickySettings `tfschema:"sticky_settings"` - StorageAccounts []helpers.StorageAccount `tfschema:"storage_account"` - ConnectionStrings []helpers.ConnectionString `tfschema:"connection_string"` - CustomDomainVerificationId string `tfschema:"custom_domain_verification_id"` - HostingEnvId string `tfschema:"hosting_environment_id"` - DefaultHostname string `tfschema:"default_hostname"` - Kind string `tfschema:"kind"` - OutboundIPAddresses string `tfschema:"outbound_ip_addresses"` - OutboundIPAddressList []string `tfschema:"outbound_ip_address_list"` - PossibleOutboundIPAddresses string `tfschema:"possible_outbound_ip_addresses"` - PossibleOutboundIPAddressList []string `tfschema:"possible_outbound_ip_address_list"` - SiteCredentials []helpers.SiteCredential `tfschema:"site_credential"` - Tags map[string]string `tfschema:"tags"` - VirtualNetworkSubnetID string `tfschema:"virtual_network_subnet_id"` + Name string `tfschema:"name"` + ResourceGroup string `tfschema:"resource_group_name"` + Location string `tfschema:"location"` + ServicePlanId string `tfschema:"service_plan_id"` + AppSettings map[string]string `tfschema:"app_settings"` + AuthSettings []helpers.AuthSettings `tfschema:"auth_settings"` + AuthV2Settings []helpers.AuthV2Settings `tfschema:"auth_settings_v2"` + Backup []helpers.Backup `tfschema:"backup"` + ClientAffinityEnabled bool `tfschema:"client_affinity_enabled"` + ClientCertEnabled bool `tfschema:"client_certificate_enabled"` + ClientCertMode string `tfschema:"client_certificate_mode"` + ClientCertExclusionPaths string `tfschema:"client_certificate_exclusion_paths"` + Enabled bool `tfschema:"enabled"` + HttpsOnly bool `tfschema:"https_only"` + LogsConfig []helpers.LogsConfig `tfschema:"logs"` + PublicNetworkAccess bool `tfschema:"public_network_access_enabled"` + PublishingDeployBasicAuthEnabled bool `tfschema:"webdeploy_publish_basic_authentication_enabled"` + PublishingFTPBasicAuthEnabled bool `tfschema:"ftp_publish_basic_authentication_enabled"` + SiteConfig []helpers.SiteConfigWindows `tfschema:"site_config"` + StickySettings []helpers.StickySettings `tfschema:"sticky_settings"` + StorageAccounts []helpers.StorageAccount `tfschema:"storage_account"` + ConnectionStrings []helpers.ConnectionString `tfschema:"connection_string"` + CustomDomainVerificationId string `tfschema:"custom_domain_verification_id"` + HostingEnvId string `tfschema:"hosting_environment_id"` + DefaultHostname string `tfschema:"default_hostname"` + Kind string `tfschema:"kind"` + OutboundIPAddresses string `tfschema:"outbound_ip_addresses"` + OutboundIPAddressList []string `tfschema:"outbound_ip_address_list"` + PossibleOutboundIPAddresses string `tfschema:"possible_outbound_ip_addresses"` + PossibleOutboundIPAddressList []string `tfschema:"possible_outbound_ip_address_list"` + SiteCredentials []helpers.SiteCredential `tfschema:"site_credential"` + Tags map[string]string `tfschema:"tags"` + VirtualNetworkSubnetID string `tfschema:"virtual_network_subnet_id"` } var _ sdk.DataSource = WindowsWebAppDataSource{} @@ -193,6 +195,16 @@ func (d WindowsWebAppDataSource) Attributes() map[string]*pluginsdk.Schema { Computed: true, }, + "webdeploy_publish_basic_authentication_enabled": { + Type: pluginsdk.TypeBool, + Computed: true, + }, + + "ftp_publish_basic_authentication_enabled": { + Type: pluginsdk.TypeBool, + Computed: true, + }, + "site_config": helpers.SiteConfigSchemaWindowsComputed(), "sticky_settings": helpers.StickySettingsComputedSchema(), @@ -331,6 +343,23 @@ func (d WindowsWebAppDataSource) Read() sdk.ResourceFunc { webApp.PublicNetworkAccess = !strings.EqualFold(pointer.From(props.PublicNetworkAccess), helpers.PublicNetworkAccessDisabled) } + basicAuthFTP := true + if basicAuthFTPResp, err := client.GetFtpAllowed(ctx, id.ResourceGroup, id.SiteName); err != nil { + return fmt.Errorf("retrieving state of FTP Basic Auth for %s: %+v", id, err) + } else if csmProps := basicAuthFTPResp.CsmPublishingCredentialsPoliciesEntityProperties; csmProps != nil { + basicAuthFTP = pointer.From(csmProps.Allow) + } + + basicAuthWebDeploy := true + if basicAuthWebDeployResp, err := client.GetScmAllowed(ctx, id.ResourceGroup, id.SiteName); err != nil { + return fmt.Errorf("retrieving state of WebDeploy Basic Auth for %s: %+v", id, err) + } else if csmProps := basicAuthWebDeployResp.CsmPublishingCredentialsPoliciesEntityProperties; csmProps != nil { + basicAuthWebDeploy = pointer.From(csmProps.Allow) + } + + webApp.PublishingFTPBasicAuthEnabled = basicAuthFTP + webApp.PublishingDeployBasicAuthEnabled = basicAuthWebDeploy + webApp.AuthSettings = helpers.FlattenAuthSettings(auth) webApp.AuthV2Settings = helpers.FlattenAuthV2Settings(authV2) diff --git a/internal/services/appservice/windows_web_app_resource.go b/internal/services/appservice/windows_web_app_resource.go index 28bef126429b..e66b8d6ba4f6 100644 --- a/internal/services/appservice/windows_web_app_resource.go +++ b/internal/services/appservice/windows_web_app_resource.go @@ -29,39 +29,41 @@ import ( type WindowsWebAppResource struct{} type WindowsWebAppModel struct { - Name string `tfschema:"name"` - ResourceGroup string `tfschema:"resource_group_name"` - Location string `tfschema:"location"` - ServicePlanId string `tfschema:"service_plan_id"` - AppSettings map[string]string `tfschema:"app_settings"` - StickySettings []helpers.StickySettings `tfschema:"sticky_settings"` - AuthSettings []helpers.AuthSettings `tfschema:"auth_settings"` - AuthV2Settings []helpers.AuthV2Settings `tfschema:"auth_settings_v2"` - Backup []helpers.Backup `tfschema:"backup"` - ClientAffinityEnabled bool `tfschema:"client_affinity_enabled"` - ClientCertEnabled bool `tfschema:"client_certificate_enabled"` - ClientCertMode string `tfschema:"client_certificate_mode"` - ClientCertExclusionPaths string `tfschema:"client_certificate_exclusion_paths"` - Enabled bool `tfschema:"enabled"` - HttpsOnly bool `tfschema:"https_only"` - KeyVaultReferenceIdentityID string `tfschema:"key_vault_reference_identity_id"` - LogsConfig []helpers.LogsConfig `tfschema:"logs"` - PublicNetworkAccess bool `tfschema:"public_network_access_enabled"` - SiteConfig []helpers.SiteConfigWindows `tfschema:"site_config"` - StorageAccounts []helpers.StorageAccount `tfschema:"storage_account"` - ConnectionStrings []helpers.ConnectionString `tfschema:"connection_string"` - CustomDomainVerificationId string `tfschema:"custom_domain_verification_id"` - HostingEnvId string `tfschema:"hosting_environment_id"` - DefaultHostname string `tfschema:"default_hostname"` - Kind string `tfschema:"kind"` - OutboundIPAddresses string `tfschema:"outbound_ip_addresses"` - OutboundIPAddressList []string `tfschema:"outbound_ip_address_list"` - PossibleOutboundIPAddresses string `tfschema:"possible_outbound_ip_addresses"` - PossibleOutboundIPAddressList []string `tfschema:"possible_outbound_ip_address_list"` - SiteCredentials []helpers.SiteCredential `tfschema:"site_credential"` - ZipDeployFile string `tfschema:"zip_deploy_file"` - Tags map[string]string `tfschema:"tags"` - VirtualNetworkSubnetID string `tfschema:"virtual_network_subnet_id"` + Name string `tfschema:"name"` + ResourceGroup string `tfschema:"resource_group_name"` + Location string `tfschema:"location"` + ServicePlanId string `tfschema:"service_plan_id"` + AppSettings map[string]string `tfschema:"app_settings"` + StickySettings []helpers.StickySettings `tfschema:"sticky_settings"` + AuthSettings []helpers.AuthSettings `tfschema:"auth_settings"` + AuthV2Settings []helpers.AuthV2Settings `tfschema:"auth_settings_v2"` + Backup []helpers.Backup `tfschema:"backup"` + ClientAffinityEnabled bool `tfschema:"client_affinity_enabled"` + ClientCertEnabled bool `tfschema:"client_certificate_enabled"` + ClientCertMode string `tfschema:"client_certificate_mode"` + ClientCertExclusionPaths string `tfschema:"client_certificate_exclusion_paths"` + Enabled bool `tfschema:"enabled"` + HttpsOnly bool `tfschema:"https_only"` + KeyVaultReferenceIdentityID string `tfschema:"key_vault_reference_identity_id"` + LogsConfig []helpers.LogsConfig `tfschema:"logs"` + PublicNetworkAccess bool `tfschema:"public_network_access_enabled"` + PublishingDeployBasicAuthEnabled bool `tfschema:"webdeploy_publish_basic_authentication_enabled"` + PublishingFTPBasicAuthEnabled bool `tfschema:"ftp_publish_basic_authentication_enabled"` + SiteConfig []helpers.SiteConfigWindows `tfschema:"site_config"` + StorageAccounts []helpers.StorageAccount `tfschema:"storage_account"` + ConnectionStrings []helpers.ConnectionString `tfschema:"connection_string"` + CustomDomainVerificationId string `tfschema:"custom_domain_verification_id"` + HostingEnvId string `tfschema:"hosting_environment_id"` + DefaultHostname string `tfschema:"default_hostname"` + Kind string `tfschema:"kind"` + OutboundIPAddresses string `tfschema:"outbound_ip_addresses"` + OutboundIPAddressList []string `tfschema:"outbound_ip_address_list"` + PossibleOutboundIPAddresses string `tfschema:"possible_outbound_ip_addresses"` + PossibleOutboundIPAddressList []string `tfschema:"possible_outbound_ip_address_list"` + SiteCredentials []helpers.SiteCredential `tfschema:"site_credential"` + ZipDeployFile string `tfschema:"zip_deploy_file"` + Tags map[string]string `tfschema:"tags"` + VirtualNetworkSubnetID string `tfschema:"virtual_network_subnet_id"` } var _ sdk.ResourceWithCustomImporter = WindowsWebAppResource{} @@ -162,6 +164,18 @@ func (r WindowsWebAppResource) Arguments() map[string]*pluginsdk.Schema { Default: true, }, + "webdeploy_publish_basic_authentication_enabled": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: true, + }, + + "ftp_publish_basic_authentication_enabled": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: true, + }, + "site_config": helpers.SiteConfigSchemaWindows(), "sticky_settings": helpers.StickySettingsSchema(), @@ -484,6 +498,28 @@ func (r WindowsWebAppResource) Create() sdk.ResourceFunc { } } + if !webApp.PublishingDeployBasicAuthEnabled { + sitePolicy := web.CsmPublishingCredentialsPoliciesEntity{ + CsmPublishingCredentialsPoliciesEntityProperties: &web.CsmPublishingCredentialsPoliciesEntityProperties{ + Allow: pointer.To(false), + }, + } + if _, err := client.UpdateScmAllowed(ctx, id.ResourceGroup, id.SiteName, sitePolicy); err != nil { + return fmt.Errorf("setting basic auth for deploy publishing credentials for %s: %+v", id, err) + } + } + + if !webApp.PublishingFTPBasicAuthEnabled { + sitePolicy := web.CsmPublishingCredentialsPoliciesEntity{ + CsmPublishingCredentialsPoliciesEntityProperties: &web.CsmPublishingCredentialsPoliciesEntityProperties{ + Allow: pointer.To(false), + }, + } + if _, err := client.UpdateFtpAllowed(ctx, id.ResourceGroup, id.SiteName, sitePolicy); err != nil { + return fmt.Errorf("setting basic auth for ftp publishing credentials for %s: %+v", id, err) + } + } + return nil }, @@ -577,6 +613,20 @@ func (r WindowsWebAppResource) Read() sdk.ResourceFunc { return fmt.Errorf("reading Site Metadata for Windows %s: %+v", id, err) } + basicAuthFTP := true + if basicAuthFTPResp, err := client.GetFtpAllowed(ctx, id.ResourceGroup, id.SiteName); err != nil { + return fmt.Errorf("retrieving state of FTP Basic Auth for %s: %+v", id, err) + } else if csmProps := basicAuthFTPResp.CsmPublishingCredentialsPoliciesEntityProperties; csmProps != nil { + basicAuthFTP = pointer.From(csmProps.Allow) + } + + basicAuthWebDeploy := true + if basicAuthWebDeployResp, err := client.GetScmAllowed(ctx, id.ResourceGroup, id.SiteName); err != nil { + return fmt.Errorf("retrieving state of WebDeploy Basic Auth for %s: %+v", id, err) + } else if csmProps := basicAuthWebDeployResp.CsmPublishingCredentialsPoliciesEntityProperties; csmProps != nil { + basicAuthWebDeploy = pointer.From(csmProps.Allow) + } + state := WindowsWebAppModel{} if props := webApp.SiteProperties; props != nil { state = WindowsWebAppModel{ @@ -630,6 +680,9 @@ func (r WindowsWebAppResource) Read() sdk.ResourceFunc { } + state.PublishingFTPBasicAuthEnabled = basicAuthFTP + state.PublishingDeployBasicAuthEnabled = basicAuthWebDeploy + state.AppSettings = helpers.FlattenWebStringDictionary(appSettings) currentStack := "" @@ -965,6 +1018,28 @@ func (r WindowsWebAppResource) Update() sdk.ResourceFunc { } } + if metadata.ResourceData.HasChange("ftp_publish_basic_authentication_enabled") { + sitePolicy := web.CsmPublishingCredentialsPoliciesEntity{ + CsmPublishingCredentialsPoliciesEntityProperties: &web.CsmPublishingCredentialsPoliciesEntityProperties{ + Allow: pointer.To(state.PublishingFTPBasicAuthEnabled), + }, + } + if _, err := client.UpdateFtpAllowed(ctx, id.ResourceGroup, id.SiteName, sitePolicy); err != nil { + return fmt.Errorf("setting basic auth for ftp publishing credentials for %s: %+v", id, err) + } + } + + if metadata.ResourceData.HasChange("webdeploy_publish_basic_authentication_enabled") { + sitePolicy := web.CsmPublishingCredentialsPoliciesEntity{ + CsmPublishingCredentialsPoliciesEntityProperties: &web.CsmPublishingCredentialsPoliciesEntityProperties{ + Allow: pointer.To(state.PublishingDeployBasicAuthEnabled), + }, + } + if _, err := client.UpdateScmAllowed(ctx, id.ResourceGroup, id.SiteName, sitePolicy); err != nil { + return fmt.Errorf("setting basic auth for deploy publishing credentials for %s: %+v", id, err) + } + } + return nil }, } diff --git a/internal/services/appservice/windows_web_app_resource_test.go b/internal/services/appservice/windows_web_app_resource_test.go index bcaf1a609592..f5bc76de64e9 100644 --- a/internal/services/appservice/windows_web_app_resource_test.go +++ b/internal/services/appservice/windows_web_app_resource_test.go @@ -67,6 +67,13 @@ func TestAccWindowsWebApp_completeUpdated(t *testing.T) { r := WindowsWebAppResource{} data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), { Config: r.complete(data), Check: acceptance.ComposeTestCheckFunc( @@ -81,6 +88,13 @@ func TestAccWindowsWebApp_completeUpdated(t *testing.T) { ), }, data.ImportStep(), + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), }) } @@ -2280,8 +2294,6 @@ resource "azurerm_windows_web_app" "test" { minimum_tls_version = "1.2" scm_minimum_tls_version = "1.2" cors { - allowed_origins = [] - support_credentials = true } @@ -2306,6 +2318,9 @@ resource "azurerm_windows_web_app" "test" { // auto_swap_slot_name = // TODO - Not supported yet } + ftp_publish_basic_authentication_enabled = false + webdeploy_publish_basic_authentication_enabled = false + tags = { foo = "bar" } diff --git a/internal/services/appservice/windows_web_app_slot_resource.go b/internal/services/appservice/windows_web_app_slot_resource.go index 0b19e1406f70..bd9341af0fb4 100644 --- a/internal/services/appservice/windows_web_app_slot_resource.go +++ b/internal/services/appservice/windows_web_app_slot_resource.go @@ -29,37 +29,39 @@ import ( type WindowsWebAppSlotResource struct{} type WindowsWebAppSlotModel struct { - Name string `tfschema:"name"` - AppServiceId string `tfschema:"app_service_id"` - ServicePlanID string `tfschema:"service_plan_id"` - AppSettings map[string]string `tfschema:"app_settings"` - AuthSettings []helpers.AuthSettings `tfschema:"auth_settings"` - AuthV2Settings []helpers.AuthV2Settings `tfschema:"auth_settings_v2"` - Backup []helpers.Backup `tfschema:"backup"` - ClientAffinityEnabled bool `tfschema:"client_affinity_enabled"` - ClientCertEnabled bool `tfschema:"client_certificate_enabled"` - ClientCertMode string `tfschema:"client_certificate_mode"` - ClientCertExclusionPaths string `tfschema:"client_certificate_exclusion_paths"` - Enabled bool `tfschema:"enabled"` - HttpsOnly bool `tfschema:"https_only"` - KeyVaultReferenceIdentityID string `tfschema:"key_vault_reference_identity_id"` - LogsConfig []helpers.LogsConfig `tfschema:"logs"` - PublicNetworkAccess bool `tfschema:"public_network_access_enabled"` - SiteConfig []helpers.SiteConfigWindowsWebAppSlot `tfschema:"site_config"` - StorageAccounts []helpers.StorageAccount `tfschema:"storage_account"` - ConnectionStrings []helpers.ConnectionString `tfschema:"connection_string"` - CustomDomainVerificationId string `tfschema:"custom_domain_verification_id"` - HostingEnvId string `tfschema:"hosting_environment_id"` - DefaultHostname string `tfschema:"default_hostname"` - Kind string `tfschema:"kind"` - OutboundIPAddresses string `tfschema:"outbound_ip_addresses"` - OutboundIPAddressList []string `tfschema:"outbound_ip_address_list"` - PossibleOutboundIPAddresses string `tfschema:"possible_outbound_ip_addresses"` - PossibleOutboundIPAddressList []string `tfschema:"possible_outbound_ip_address_list"` - SiteCredentials []helpers.SiteCredential `tfschema:"site_credential"` - ZipDeployFile string `tfschema:"zip_deploy_file"` - Tags map[string]string `tfschema:"tags"` - VirtualNetworkSubnetID string `tfschema:"virtual_network_subnet_id"` + Name string `tfschema:"name"` + AppServiceId string `tfschema:"app_service_id"` + ServicePlanID string `tfschema:"service_plan_id"` + AppSettings map[string]string `tfschema:"app_settings"` + AuthSettings []helpers.AuthSettings `tfschema:"auth_settings"` + AuthV2Settings []helpers.AuthV2Settings `tfschema:"auth_settings_v2"` + Backup []helpers.Backup `tfschema:"backup"` + ClientAffinityEnabled bool `tfschema:"client_affinity_enabled"` + ClientCertEnabled bool `tfschema:"client_certificate_enabled"` + ClientCertMode string `tfschema:"client_certificate_mode"` + ClientCertExclusionPaths string `tfschema:"client_certificate_exclusion_paths"` + Enabled bool `tfschema:"enabled"` + HttpsOnly bool `tfschema:"https_only"` + KeyVaultReferenceIdentityID string `tfschema:"key_vault_reference_identity_id"` + LogsConfig []helpers.LogsConfig `tfschema:"logs"` + PublicNetworkAccess bool `tfschema:"public_network_access_enabled"` + PublishingDeployBasicAuthEnabled bool `tfschema:"webdeploy_publish_basic_authentication_enabled"` + PublishingFTPBasicAuthEnabled bool `tfschema:"ftp_publish_basic_authentication_enabled"` + SiteConfig []helpers.SiteConfigWindowsWebAppSlot `tfschema:"site_config"` + StorageAccounts []helpers.StorageAccount `tfschema:"storage_account"` + ConnectionStrings []helpers.ConnectionString `tfschema:"connection_string"` + CustomDomainVerificationId string `tfschema:"custom_domain_verification_id"` + HostingEnvId string `tfschema:"hosting_environment_id"` + DefaultHostname string `tfschema:"default_hostname"` + Kind string `tfschema:"kind"` + OutboundIPAddresses string `tfschema:"outbound_ip_addresses"` + OutboundIPAddressList []string `tfschema:"outbound_ip_address_list"` + PossibleOutboundIPAddresses string `tfschema:"possible_outbound_ip_addresses"` + PossibleOutboundIPAddressList []string `tfschema:"possible_outbound_ip_address_list"` + SiteCredentials []helpers.SiteCredential `tfschema:"site_credential"` + ZipDeployFile string `tfschema:"zip_deploy_file"` + Tags map[string]string `tfschema:"tags"` + VirtualNetworkSubnetID string `tfschema:"virtual_network_subnet_id"` } var _ sdk.ResourceWithUpdate = WindowsWebAppSlotResource{} @@ -175,6 +177,18 @@ func (r WindowsWebAppSlotResource) Arguments() map[string]*pluginsdk.Schema { Default: true, }, + "webdeploy_publish_basic_authentication_enabled": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: true, + }, + + "ftp_publish_basic_authentication_enabled": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: true, + }, + "site_config": helpers.SiteConfigSchemaWindowsWebAppSlot(), "storage_account": helpers.StorageAccountSchemaWindows(), @@ -451,6 +465,28 @@ func (r WindowsWebAppSlotResource) Create() sdk.ResourceFunc { } } + if !webAppSlot.PublishingDeployBasicAuthEnabled { + sitePolicy := web.CsmPublishingCredentialsPoliciesEntity{ + CsmPublishingCredentialsPoliciesEntityProperties: &web.CsmPublishingCredentialsPoliciesEntityProperties{ + Allow: pointer.To(false), + }, + } + if _, err := client.UpdateScmAllowedSlot(ctx, id.ResourceGroup, id.SiteName, sitePolicy, id.SlotName); err != nil { + return fmt.Errorf("setting basic auth for deploy publishing credentials for %s: %+v", id, err) + } + } + + if !webAppSlot.PublishingFTPBasicAuthEnabled { + sitePolicy := web.CsmPublishingCredentialsPoliciesEntity{ + CsmPublishingCredentialsPoliciesEntityProperties: &web.CsmPublishingCredentialsPoliciesEntityProperties{ + Allow: pointer.To(false), + }, + } + if _, err := client.UpdateFtpAllowedSlot(ctx, id.ResourceGroup, id.SiteName, sitePolicy, id.SlotName); err != nil { + return fmt.Errorf("setting basic auth for ftp publishing credentials for %s: %+v", id, err) + } + } + return nil }, @@ -548,6 +584,20 @@ func (r WindowsWebAppSlotResource) Read() sdk.ResourceFunc { return fmt.Errorf("reading parent Function App Service Plan information for Linux %s: %+v", *id, err) } + basicAuthFTP := true + if basicAuthFTPResp, err := client.GetFtpAllowedSlot(ctx, id.ResourceGroup, id.SiteName, id.SlotName); err != nil { + return fmt.Errorf("retrieving state of FTP Basic Auth for %s: %+v", id, err) + } else if csmProps := basicAuthFTPResp.CsmPublishingCredentialsPoliciesEntityProperties; csmProps != nil { + basicAuthFTP = pointer.From(csmProps.Allow) + } + + basicAuthWebDeploy := true + if basicAuthWebDeployResp, err := client.GetScmAllowedSlot(ctx, id.ResourceGroup, id.SiteName, id.SlotName); err != nil { + return fmt.Errorf("retrieving state of WebDeploy Basic Auth for %s: %+v", id, err) + } else if csmProps := basicAuthWebDeployResp.CsmPublishingCredentialsPoliciesEntityProperties; csmProps != nil { + basicAuthWebDeploy = pointer.From(csmProps.Allow) + } + state := WindowsWebAppSlotModel{} if props := webAppSlot.SiteProperties; props != nil { state = WindowsWebAppSlotModel{ @@ -599,6 +649,9 @@ func (r WindowsWebAppSlotResource) Read() sdk.ResourceFunc { } } + state.PublishingFTPBasicAuthEnabled = basicAuthFTP + state.PublishingDeployBasicAuthEnabled = basicAuthWebDeploy + state.AppSettings = helpers.FlattenWebStringDictionary(appSettings) currentStack := "" currentStackPtr, ok := siteMetadata.Properties["CURRENT_STACK"] @@ -905,6 +958,28 @@ func (r WindowsWebAppSlotResource) Update() sdk.ResourceFunc { } } + if metadata.ResourceData.HasChange("ftp_publish_basic_authentication_enabled") { + sitePolicy := web.CsmPublishingCredentialsPoliciesEntity{ + CsmPublishingCredentialsPoliciesEntityProperties: &web.CsmPublishingCredentialsPoliciesEntityProperties{ + Allow: pointer.To(state.PublishingFTPBasicAuthEnabled), + }, + } + if _, err := client.UpdateFtpAllowedSlot(ctx, id.ResourceGroup, id.SiteName, sitePolicy, id.SlotName); err != nil { + return fmt.Errorf("setting basic auth for ftp publishing credentials for %s: %+v", id, err) + } + } + + if metadata.ResourceData.HasChange("webdeploy_publish_basic_authentication_enabled") { + sitePolicy := web.CsmPublishingCredentialsPoliciesEntity{ + CsmPublishingCredentialsPoliciesEntityProperties: &web.CsmPublishingCredentialsPoliciesEntityProperties{ + Allow: pointer.To(state.PublishingDeployBasicAuthEnabled), + }, + } + if _, err := client.UpdateScmAllowedSlot(ctx, id.ResourceGroup, id.SiteName, sitePolicy, id.SlotName); err != nil { + return fmt.Errorf("setting basic auth for deploy publishing credentials for %s: %+v", id, err) + } + } + return nil }, } diff --git a/internal/services/appservice/windows_web_app_slot_resource_test.go b/internal/services/appservice/windows_web_app_slot_resource_test.go index 48889ee497e3..966ed62dcab2 100644 --- a/internal/services/appservice/windows_web_app_slot_resource_test.go +++ b/internal/services/appservice/windows_web_app_slot_resource_test.go @@ -1373,6 +1373,9 @@ resource "azurerm_windows_web_app_slot" "test" { mount_path = "/mounts/files" } + ftp_publish_basic_authentication_enabled = false + webdeploy_publish_basic_authentication_enabled = false + tags = { Environment = "AccTest" foo = "bar" diff --git a/website/docs/d/linux_function_app.html.markdown b/website/docs/d/linux_function_app.html.markdown index 20727bfdca78..e71d91425015 100644 --- a/website/docs/d/linux_function_app.html.markdown +++ b/website/docs/d/linux_function_app.html.markdown @@ -71,6 +71,8 @@ In addition to the Arguments listed above - the following Attributes are exporte * `enabled` - Is the Function App enabled? +* `ftp_publish_basic_authentication_enabled` - Are the default FTP Basic Authentication publishing credentials enabled. + * `functions_extension_version` - The runtime version associated with the Function App. * `https_only` - Can the Function App only be accessed via HTTPS? @@ -87,6 +89,8 @@ In addition to the Arguments listed above - the following Attributes are exporte * `possible_outbound_ip_addresses` - A comma separated list of possible outbound IP addresses as a string. For example `52.23.25.3,52.143.43.12,52.143.43.17`. This is a superset of `outbound_ip_addresses`. +* `public_network_access_enabled` - Is Public Network Access enabled for this Linux Function App. + * `service_plan_id` - The ID of the App Service Plan within which this Function App has been created. * `site_config` - A `site_config` block as defined below. @@ -109,6 +113,8 @@ In addition to the Arguments listed above - the following Attributes are exporte * `virtual_network_subnet_id` - The subnet id which the Linux Function App is vNet Integrated with. +* `webdeploy_publish_basic_authentication_enabled` - Are the default WebDeploy Basic Authentication publishing credentials enabled. + --- An `active_directory` block exports the following: diff --git a/website/docs/d/linux_web_app.html.markdown b/website/docs/d/linux_web_app.html.markdown index 11101b402b8d..4c8a57bbca18 100644 --- a/website/docs/d/linux_web_app.html.markdown +++ b/website/docs/d/linux_web_app.html.markdown @@ -46,7 +46,7 @@ In addition to the Arguments listed above - the following Attributes are exporte * `auth_settings_v2` - An `auth_settings_v2` block as defined below. * `availability` - The current availability state. Possible values are `Normal`, `Limited`, and `DisasterRecoveryMode`. -* + * `backup` - A `backup` block as defined below. * `client_affinity_enabled` - Is Client Affinity enabled? @@ -67,6 +67,8 @@ In addition to the Arguments listed above - the following Attributes are exporte * `enabled` - Is the Linux Web App enabled? +* `ftp_publish_basic_authentication_enabled` - Are the default FTP Basic Authentication publishing credentials enabled. + * `https_only` - Should the Linux Web App require HTTPS connections. * `identity` - A `identity` block as defined below. @@ -85,6 +87,8 @@ In addition to the Arguments listed above - the following Attributes are exporte * `possible_outbound_ip_addresses` - A comma separated list of outbound IP addresses - such as `52.23.25.3,52.143.43.12,52.143.43.17` - not all of which are necessarily in use. Superset of `outbound_ip_addresses`. +* `public_network_access_enabled` - Is Public Network Access enabled for this Linux Web App. + * `service_plan_id` - The ID of the Service Plan that this Linux Web App exists in. * `site_config` - A `site_config` block as defined below. @@ -99,6 +103,8 @@ In addition to the Arguments listed above - the following Attributes are exporte * `usage` - The current usage state. Possible values are `Normal` and `Exceeded`. +* `webdeploy_publish_basic_authentication_enabled` - Are the default WebDeploy Basic Authentication publishing credentials enabled. + * `tags` - A mapping of tags assigned to the Linux Web App. --- diff --git a/website/docs/d/windows_function_app.html.markdown b/website/docs/d/windows_function_app.html.markdown index e1ef02f217a2..27a108c32e2a 100644 --- a/website/docs/d/windows_function_app.html.markdown +++ b/website/docs/d/windows_function_app.html.markdown @@ -67,6 +67,8 @@ In addition to the Arguments listed above - the following Attributes are exporte * `enabled` - Is the Function App enabled? +* `ftp_publish_basic_authentication_enabled` - Are the default FTP Basic Authentication publishing credentials enabled. + * `functions_extension_version` - The runtime version associated with the Function App. * `https_only` - Is the Function App only accessible via HTTPS? @@ -85,6 +87,8 @@ In addition to the Arguments listed above - the following Attributes are exporte * `possible_outbound_ip_addresses` - A comma separated list of possible outbound IP addresses as a string. For example `52.23.25.3,52.143.43.12,52.143.43.17`. This is a superset of `outbound_ip_addresses`. +* `public_network_access_enabled` - Is Public Network Access enabled for the Windows Function App. + * `service_plan_id` - The ID of the App Service Plan. * `site_config` - A `site_config` block as defined below. @@ -105,6 +109,8 @@ In addition to the Arguments listed above - the following Attributes are exporte * `virtual_network_subnet_id` - The subnet id which the Windows Function App is vNet Integrated with. +* `webdeploy_publish_basic_authentication_enabled` - Are the default WebDeploy Basic Authentication publishing credentials enabled. + --- An `active_directory` block exports the following: diff --git a/website/docs/d/windows_web_app.html.markdown b/website/docs/d/windows_web_app.html.markdown index 804743da7afd..7f6bee5d6acf 100644 --- a/website/docs/d/windows_web_app.html.markdown +++ b/website/docs/d/windows_web_app.html.markdown @@ -63,6 +63,8 @@ In addition to the Arguments listed above - the following Attributes are exporte * `enabled` - Is the Windows Web App enabled? +* `ftp_publish_basic_authentication_enabled` - Are the default FTP Basic Authentication publishing credentials enabled. + * `https_only` - Does the Windows Web App require HTTPS connections. * `identity` - A `identity` block as defined below. @@ -81,6 +83,8 @@ In addition to the Arguments listed above - the following Attributes are exporte * `possible_outbound_ip_addresses` - The string representation of the list of Possible Outbound IP Addresses that could be used by this Windows Web App. +* `public_network_access_enabled` - Is Public Network Access enabled for the Windows Web App. + * `service_plan_id` - The ID of the Service Plan in which this Windows Web App resides. * `site_config` - A `site_config` block as defined below. @@ -95,6 +99,8 @@ In addition to the Arguments listed above - the following Attributes are exporte * `virtual_network_subnet_id` - The subnet id which the Windows Web App is vNet Integrated with. +* `webdeploy_publish_basic_authentication_enabled` - Are the default WebDeploy Basic Authentication publishing credentials enabled. + --- A `action` block exports the following: diff --git a/website/docs/r/linux_function_app.html.markdown b/website/docs/r/linux_function_app.html.markdown index 34c8988a6262..58e1a5868746 100644 --- a/website/docs/r/linux_function_app.html.markdown +++ b/website/docs/r/linux_function_app.html.markdown @@ -103,6 +103,8 @@ The following arguments are supported: * `functions_extension_version` - (Optional) The runtime version associated with the Function App. Defaults to `~4`. +* `ftp_publish_basic_authentication_enabled` - Should the default FTP Basic Authentication publishing profile be enabled. Defaults to `true`. + * `https_only` - (Optional) Can the Function App only be accessed via HTTPS? Defaults to `false`. * `public_network_access_enabled` - (Optional) Should public network access be enabled for the Function App. Defaults to `true`. @@ -137,6 +139,10 @@ The following arguments are supported: ~> **Note:** Assigning the `virtual_network_subnet_id` property requires [RBAC permissions on the subnet](https://docs.microsoft.com/en-us/azure/app-service/overview-vnet-integration#permissions) +* `webdeploy_publish_basic_authentication_enabled` - Should the default WebDeploy Basic Authentication publishing credentials enabled. Defaults to`true`. + +~> **NOTE:** Setting this value to true will disable the ability to use `zip_deploy_file` which currently relies on the default publishing profile. + * `zip_deploy_file` - (Optional) The local path and filename of the Zip packaged application to deploy to this Linux Function App. ~> **Note:** Using this value requires either `WEBSITE_RUN_FROM_PACKAGE=1` or `SCM_DO_BUILD_DURING_DEPLOYMENT=true` to be set on the App in `app_settings`. Refer to the [Azure docs](https://learn.microsoft.com/en-us/azure/azure-functions/functions-deployment-technologies) for further details. diff --git a/website/docs/r/linux_function_app_slot.html.markdown b/website/docs/r/linux_function_app_slot.html.markdown index 6f91c4c6cec6..09282b54052a 100644 --- a/website/docs/r/linux_function_app_slot.html.markdown +++ b/website/docs/r/linux_function_app_slot.html.markdown @@ -94,6 +94,8 @@ The following arguments are supported: * `enabled` - (Optional) Is the Linux Function App Slot enabled. Defaults to `true`. +* `ftp_publish_basic_authentication_enabled` - Are the default FTP Basic Authentication publishing credentials enabled. + * `functions_extension_version` - (Optional) The runtime version associated with the Function App Slot. Defaults to `~4`. * `https_only` - (Optional) Can the Function App Slot only be accessed via HTTPS? @@ -129,6 +131,8 @@ The following arguments are supported: ~> **NOTE on regional virtual network integration:** The AzureRM Terraform provider provides regional virtual network integration via the standalone resource [app_service_virtual_network_swift_connection](app_service_virtual_network_swift_connection.html) and in-line within this resource using the `virtual_network_subnet_id` property. You cannot use both methods simultaneously. If the virtual network is set via the resource `app_service_virtual_network_swift_connection` then `ignore_changes` should be used in the function app slot configuration. ~> **Note:** Assigning the `virtual_network_subnet_id` property requires [RBAC permissions on the subnet](https://docs.microsoft.com/en-us/azure/app-service/overview-vnet-integration#permissions) + +* `webdeploy_publish_basic_authentication_enabled` - Should the default WebDeploy Basic Authentication publishing credentials enabled. Defaults to`true`. --- diff --git a/website/docs/r/linux_web_app.html.markdown b/website/docs/r/linux_web_app.html.markdown index 984b5f852a04..5e17cc0fe389 100644 --- a/website/docs/r/linux_web_app.html.markdown +++ b/website/docs/r/linux_web_app.html.markdown @@ -79,6 +79,8 @@ The following arguments are supported: * `enabled` - (Optional) Should the Linux Web App be enabled? Defaults to `true`. +* `ftp_publish_basic_authentication_enabled` - Should the default FTP Basic Authentication publishing profile be enabled. Defaults to `true`. + * `https_only` - (Optional) Should the Linux Web App require HTTPS connections. * `public_network_access_enabled` - (Optional) Should public network access be enabled for the Web App. Defaults to `true`. @@ -99,6 +101,10 @@ The following arguments are supported: ~> **Note:** Assigning the `virtual_network_subnet_id` property requires [RBAC permissions on the subnet](https://docs.microsoft.com/en-us/azure/app-service/overview-vnet-integration#permissions) +* `webdeploy_publish_basic_authentication_enabled` - Should the default WebDeploy Basic Authentication publishing credentials enabled. Defaults to`true`. + +~> **NOTE:** Setting this value to true will disable the ability to use `zip_deploy_file` which currently relies on the default publishing profile. + * `zip_deploy_file` - (Optional) The local path and filename of the Zip packaged application to deploy to this Linux Web App. ~> **Note:** Using this value requires either `WEBSITE_RUN_FROM_PACKAGE=1` or `SCM_DO_BUILD_DURING_DEPLOYMENT=true` to be set on the App in `app_settings`. Refer to the Azure docs on [running the Web App directly from the Zip package](https://learn.microsoft.com/en-us/azure/app-service/deploy-run-package), or [automating the build for Zip deploy](https://learn.microsoft.com/en-us/azure/app-service/deploy-zip#enable-build-automation-for-zip-deploy) for further details. diff --git a/website/docs/r/linux_web_app_slot.html.markdown b/website/docs/r/linux_web_app_slot.html.markdown index 605fcb088385..04cab3c48d51 100644 --- a/website/docs/r/linux_web_app_slot.html.markdown +++ b/website/docs/r/linux_web_app_slot.html.markdown @@ -82,6 +82,8 @@ The following arguments are supported: * `enabled` - (Optional) Should the Linux Web App be enabled? Defaults to `true`. +* `ftp_publish_basic_authentication_enabled` - Should the default FTP Basic Authentication publishing profile be enabled. Defaults to `true`. + * `https_only` - (Optional) Should the Linux Web App require HTTPS connections. * `public_network_access_enabled` - (Optional) Should public network access be enabled for the Web App. Defaults to `true`. @@ -102,6 +104,10 @@ The following arguments are supported: ~> **Note:** Assigning the `virtual_network_subnet_id` property requires [RBAC permissions on the subnet](https://docs.microsoft.com/en-us/azure/app-service/overview-vnet-integration#permissions) +* `webdeploy_publish_basic_authentication_enabled` - Should the default WebDeploy Basic Authentication publishing credentials enabled. Defaults to`true`. + +~> **NOTE:** Setting this value to true will disable the ability to use `zip_deploy_file` which currently relies on the default publishing profile. + * `zip_deploy_file` - (Optional) The local path and filename of the Zip packaged application to deploy to this Linux Web App. ~> **Note:** Using this value requires `WEBSITE_RUN_FROM_PACKAGE=1` to be set on the App in `app_settings`. Refer to the [Azure docs](https://docs.microsoft.com/en-us/azure/app-service/deploy-run-package) for further details. diff --git a/website/docs/r/windows_function_app.html.markdown b/website/docs/r/windows_function_app.html.markdown index f59c812c6d4e..95194b0fb9b6 100644 --- a/website/docs/r/windows_function_app.html.markdown +++ b/website/docs/r/windows_function_app.html.markdown @@ -101,6 +101,8 @@ The following arguments are supported: * `enabled` - (Optional) Is the Function App enabled? Defaults to `true`. +* `ftp_publish_basic_authentication_enabled` - Should the default FTP Basic Authentication publishing profile be enabled. Defaults to `true`. + * `functions_extension_version` - (Optional) The runtime version associated with the Function App. Defaults to `~4`. * `https_only` - (Optional) Can the Function App only be accessed via HTTPS? Defaults to `false`. @@ -137,6 +139,10 @@ The following arguments are supported: ~> **Note:** Assigning the `virtual_network_subnet_id` property requires [RBAC permissions on the subnet](https://docs.microsoft.com/en-us/azure/app-service/overview-vnet-integration#permissions) +* `webdeploy_publish_basic_authentication_enabled` - Should the default WebDeploy Basic Authentication publishing credentials enabled. Defaults to`true`. + +~> **NOTE:** Setting this value to true will disable the ability to use `zip_deploy_file` which currently relies on the default publishing profile. + * `zip_deploy_file` - (Optional) The local path and filename of the Zip packaged application to deploy to this Windows Function App. ~> **Note:** Using this value requires `WEBSITE_RUN_FROM_PACKAGE=1` to be set on the App in `app_settings`. Refer to the [Azure docs](https://learn.microsoft.com/en-us/azure/azure-functions/functions-deployment-technologies) for further details. diff --git a/website/docs/r/windows_function_app_slot.html.markdown b/website/docs/r/windows_function_app_slot.html.markdown index 98c4ee7265d2..f4c763c88f3e 100644 --- a/website/docs/r/windows_function_app_slot.html.markdown +++ b/website/docs/r/windows_function_app_slot.html.markdown @@ -93,6 +93,8 @@ The following arguments are supported: * `enabled` - (Optional) Is the Windows Function App Slot enabled. Defaults to `true`. +* `ftp_publish_basic_authentication_enabled` - Should the default FTP Basic Authentication publishing profile be enabled. Defaults to `true`. + * `functions_extension_version` - (Optional) The runtime version associated with the Function App Slot. Defaults to `~4`. * `https_only` - (Optional) Can the Function App Slot only be accessed via HTTPS? @@ -129,6 +131,8 @@ The following arguments are supported: ~> **Note:** Assigning the `virtual_network_subnet_id` property requires [RBAC permissions on the subnet](https://docs.microsoft.com/en-us/azure/app-service/overview-vnet-integration#permissions) +* `webdeploy_publish_basic_authentication_enabled` - Should the default WebDeploy Basic Authentication publishing credentials enabled. Defaults to`true`. + --- An `auth_settings` block supports the following: diff --git a/website/docs/r/windows_web_app.html.markdown b/website/docs/r/windows_web_app.html.markdown index 3472ee8f585a..13b81683e9c1 100644 --- a/website/docs/r/windows_web_app.html.markdown +++ b/website/docs/r/windows_web_app.html.markdown @@ -76,6 +76,8 @@ The following arguments are supported: * `enabled` - (Optional) Should the Windows Web App be enabled? Defaults to `true`. +* `ftp_publish_basic_authentication_enabled` - Should the default FTP Basic Authentication publishing profile be enabled. Defaults to `true`. + * `https_only` - (Optional) Should the Windows Web App require HTTPS connections. * `public_network_access_enabled` - (Optional) Should public network access be enabled for the Web App. Defaults to `true`. @@ -100,6 +102,10 @@ The following arguments are supported: ~> **Note:** Assigning the `virtual_network_subnet_id` property requires [RBAC permissions on the subnet](https://docs.microsoft.com/en-us/azure/app-service/overview-vnet-integration#permissions) +* `webdeploy_publish_basic_authentication_enabled` - Should the default WebDeploy Basic Authentication publishing credentials enabled. Defaults to`true`. + +~> **NOTE:** Setting this value to true will disable the ability to use `zip_deploy_file` which currently relies on the default publishing profile. + * `zip_deploy_file` - (Optional) The local path and filename of the Zip packaged application to deploy to this Windows Web App. ~> **Note:** Using this value requires either `WEBSITE_RUN_FROM_PACKAGE=1` or `SCM_DO_BUILD_DURING_DEPLOYMENT=true` to be set on the App in `app_settings`. Refer to the Azure docs on [running the Web App directly from the Zip package](https://learn.microsoft.com/en-us/azure/app-service/deploy-run-package), or [automating the build for Zip deploy](https://learn.microsoft.com/en-us/azure/app-service/deploy-zip#enable-build-automation-for-zip-deploy) for further details. diff --git a/website/docs/r/windows_web_app_slot.html.markdown b/website/docs/r/windows_web_app_slot.html.markdown index 6447465e1e26..de3bf5159d8c 100644 --- a/website/docs/r/windows_web_app_slot.html.markdown +++ b/website/docs/r/windows_web_app_slot.html.markdown @@ -82,6 +82,8 @@ The following arguments are supported: * `enabled` - (Optional) Should the Windows Web App Slot be enabled? Defaults to `true`. +* `ftp_publish_basic_authentication_enabled` - Should the default FTP Basic Authentication publishing profile be enabled. Defaults to `true`. + * `https_only` - (Optional) Should the Windows Web App Slot require HTTPS connections. * `public_network_access_enabled` - (Optional) Should public network access be enabled for the Web App. Defaults to `true`. @@ -106,6 +108,10 @@ The following arguments are supported: ~> **Note:** Assigning the `virtual_network_subnet_id` property requires [RBAC permissions on the subnet](https://docs.microsoft.com/en-us/azure/app-service/overview-vnet-integration#permissions) +* `webdeploy_publish_basic_authentication_enabled` - Should the default WebDeploy Basic Authentication publishing credentials enabled. Defaults to`true`. + +~> **NOTE:** Setting this value to true will disable the ability to use `zip_deploy_file` which currently relies on the default publishing profile. + * `zip_deploy_file` - (Optional) The local path and filename of the Zip packaged application to deploy to this Windows Web App. ---