diff --git a/internal/services/storage/storage_account_resource.go b/internal/services/storage/storage_account_resource.go index faf76407fdcf..33bb641ca451 100644 --- a/internal/services/storage/storage_account_resource.go +++ b/internal/services/storage/storage_account_resource.go @@ -190,12 +190,6 @@ func resourceStorageAccount() *pluginsdk.Resource { MaxItems: 1, Elem: &pluginsdk.Resource{ Schema: map[string]*pluginsdk.Schema{ - "storage_sid": { - Type: pluginsdk.TypeString, - Required: true, - ValidateFunc: validation.StringIsNotEmpty, - }, - "domain_guid": { Type: pluginsdk.TypeString, Required: true, @@ -208,21 +202,27 @@ func resourceStorageAccount() *pluginsdk.Resource { ValidateFunc: validation.StringIsNotEmpty, }, + "storage_sid": { + Type: pluginsdk.TypeString, + Optional: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + "domain_sid": { Type: pluginsdk.TypeString, - Required: true, + Optional: true, ValidateFunc: validation.StringIsNotEmpty, }, "forest_name": { Type: pluginsdk.TypeString, - Required: true, + Optional: true, ValidateFunc: validation.StringIsNotEmpty, }, "netbios_domain_name": { Type: pluginsdk.TypeString, - Required: true, + Optional: true, ValidateFunc: validation.StringIsNotEmpty, }, }, @@ -2461,14 +2461,31 @@ func expandArmStorageAccountAzureFilesAuthentication(input []interface{}) (*stor v := input[0].(map[string]interface{}) + ad := expandArmStorageAccountActiveDirectoryProperties(v["active_directory"].([]interface{})) + directoryOption := storage.DirectoryServiceOptions(v["directory_type"].(string)) - if _, ok := v["active_directory"]; directoryOption == storage.DirectoryServiceOptionsAD && !ok { - return nil, fmt.Errorf("`active_directory` is required when `directory_type` is `AD`") + + if directoryOption == storage.DirectoryServiceOptionsAD { + if ad == nil { + return nil, fmt.Errorf("`active_directory` is required when `directory_type` is `AD`") + } + if ad.AzureStorageSid == nil { + return nil, fmt.Errorf("`active_directory.0.storage_sid` is required when `directory_type` is `AD`") + } + if ad.DomainSid == nil { + return nil, fmt.Errorf("`active_directory.0.domain_sid` is required when `directory_type` is `AD`") + } + if ad.ForestName == nil { + return nil, fmt.Errorf("`active_directory.0.forest_name` is required when `directory_type` is `AD`") + } + if ad.NetBiosDomainName == nil { + return nil, fmt.Errorf("`active_directory.0.netbios_domain_name` is required when `directory_type` is `AD`") + } } return &storage.AzureFilesIdentityBasedAuthentication{ DirectoryServiceOptions: directoryOption, - ActiveDirectoryProperties: expandArmStorageAccountActiveDirectoryProperties(v["active_directory"].([]interface{})), + ActiveDirectoryProperties: ad, }, nil } @@ -2476,15 +2493,25 @@ func expandArmStorageAccountActiveDirectoryProperties(input []interface{}) *stor if len(input) == 0 { return nil } - v := input[0].(map[string]interface{}) - return &storage.ActiveDirectoryProperties{ - AzureStorageSid: utils.String(v["storage_sid"].(string)), - DomainGUID: utils.String(v["domain_guid"].(string)), - DomainName: utils.String(v["domain_name"].(string)), - DomainSid: utils.String(v["domain_sid"].(string)), - ForestName: utils.String(v["forest_name"].(string)), - NetBiosDomainName: utils.String(v["netbios_domain_name"].(string)), + m := input[0].(map[string]interface{}) + + output := &storage.ActiveDirectoryProperties{ + DomainGUID: utils.String(m["domain_guid"].(string)), + DomainName: utils.String(m["domain_name"].(string)), + } + if v := m["storage_sid"]; v != "" { + output.AzureStorageSid = utils.String(v.(string)) + } + if v := m["domain_sid"]; v != "" { + output.DomainSid = utils.String(v.(string)) + } + if v := m["forest_name"]; v != "" { + output.ForestName = utils.String(v.(string)) + } + if v := m["netbios_domain_name"]; v != "" { + output.NetBiosDomainName = utils.String(v.(string)) } + return output } func expandArmStorageAccountRouting(input []interface{}) *storage.RoutingPreference { diff --git a/internal/services/storage/storage_account_resource_test.go b/internal/services/storage/storage_account_resource_test.go index 75c41b4c46df..e6bc663bddf0 100644 --- a/internal/services/storage/storage_account_resource_test.go +++ b/internal/services/storage/storage_account_resource_test.go @@ -909,6 +909,18 @@ func TestAccAzureRMStorageAccount_azureFilesAuthentication(t *testing.T) { ), }, data.ImportStep(), + { + Config: r.azureFilesAuthenticationAADKERBUpdate(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep( + "azure_files_authentication.0.active_directory.0.storage_sid", + "azure_files_authentication.0.active_directory.0.domain_sid", + "azure_files_authentication.0.active_directory.0.forest_name", + "azure_files_authentication.0.active_directory.0.netbios_domain_name", + ), { Config: r.basic(data), Check: acceptance.ComposeTestCheckFunc( @@ -3287,6 +3299,48 @@ resource "azurerm_storage_account" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomString) } +func (r StorageAccountResource) azureFilesAuthenticationAADKERBUpdate(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-storage-%d" + location = "%s" +} + +resource "azurerm_storage_account" "test" { + name = "unlikely23exst2acct%s" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + account_tier = "Standard" + account_replication_type = "LRS" + + azure_files_authentication { + directory_type = "AADKERB" + active_directory { + domain_name = "adtest2.com" + domain_guid = "13a20c9a-d491-47e6-8a39-299e7a32ea27" + } + } + + tags = { + environment = "production" + } + + lifecycle { + ignore_changes = [ + azure_files_authentication.0.active_directory.0.storage_sid, + azure_files_authentication.0.active_directory.0.domain_sid, + azure_files_authentication.0.active_directory.0.forest_name, + azure_files_authentication.0.active_directory.0.netbios_domain_name, + ] + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomString) +} + func (r StorageAccountResource) routing(data acceptance.TestData) string { return fmt.Sprintf(` provider "azurerm" { diff --git a/website/docs/r/storage_account.html.markdown b/website/docs/r/storage_account.html.markdown index 166b2ecb83c4..e301ad8edd02 100644 --- a/website/docs/r/storage_account.html.markdown +++ b/website/docs/r/storage_account.html.markdown @@ -344,23 +344,21 @@ A `azure_files_authentication` block supports the following: * `active_directory` - (Optional) A `active_directory` block as defined below. Required when `directory_type` is `AD`. -~> **Note:** If `directory_type` is set to `AADKERB`, `active_directory` is not supported. Use [icals](https://learn.microsoft.com/en-us/azure/storage/files/storage-files-identity-auth-azure-active-directory-enable?tabs=azure-portal#configure-directory-and-file-level-permissions) to configure directory and file level permissions. - --- A `active_directory` block supports the following: -* `storage_sid` - (Required) Specifies the security identifier (SID) for Azure Storage. - * `domain_name` - (Required) Specifies the primary domain that the AD DNS server is authoritative for. -* `domain_sid` - (Required) Specifies the security identifier (SID). - * `domain_guid` - (Required) Specifies the domain GUID. -* `forest_name` - (Required) Specifies the Active Directory forest. +* `domain_sid` - (Optional) Specifies the security identifier (SID). This is required when `directory_type` is set to `AD`. + +* `storage_sid` - (Optional) Specifies the security identifier (SID) for Azure Storage. This is required when `directory_type` is set to `AD`. + +* `forest_name` - (Optional) Specifies the Active Directory forest. This is required when `directory_type` is set to `AD`. -* `netbios_domain_name` - (Required) Specifies the NetBIOS domain name. +* `netbios_domain_name` - (Optional) Specifies the NetBIOS domain name. This is required when `directory_type` is set to `AD`. ---