Skip to content

Commit

Permalink
appservice - support disabling access for default basic auth (#23900)
Browse files Browse the repository at this point in the history
  • Loading branch information
jackofallops authored Nov 16, 2023
1 parent b10a6db commit 36ed027
Show file tree
Hide file tree
Showing 32 changed files with 1,295 additions and 345 deletions.
71 changes: 50 additions & 21 deletions internal/services/appservice/linux_function_app_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
Expand Down Expand Up @@ -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": {
Expand Down Expand Up @@ -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)
}
Expand Down
120 changes: 98 additions & 22 deletions internal/services/appservice/linux_function_app_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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,
Expand All @@ -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 {
Expand Down Expand Up @@ -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)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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"
Expand Down
Loading

0 comments on commit 36ed027

Please sign in to comment.