From ac0ccbe60c0c4b12a7c75bf41c0f3c95ceb2072a Mon Sep 17 00:00:00 2001 From: lstolyarov Date: Thu, 31 May 2018 15:55:13 +0100 Subject: [PATCH 01/10] Add the storage account object id as an output --- azurerm/resource_arm_storage_account.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/azurerm/resource_arm_storage_account.go b/azurerm/resource_arm_storage_account.go index c95c8839d337..508c45dfcebb 100644 --- a/azurerm/resource_arm_storage_account.go +++ b/azurerm/resource_arm_storage_account.go @@ -223,6 +223,11 @@ func resourceArmStorageAccount() *schema.Resource { Sensitive: true, }, + "object_id": { + Type: schema.TypeString, + Computed: true, + }, + "tags": tagsSchema(), }, } @@ -495,6 +500,11 @@ func resourceArmStorageAccountRead(d *schema.ResourceData, meta interface{}) err } d.Set("account_kind", resp.Kind) + log.Printf("[INFO] Identity is %q", resp.Identity) + if identity := resp.Identity; identity != nil { + d.Set("object_id", identity.PrincipalID) + } + if sku := resp.Sku; sku != nil { d.Set("account_type", sku.Name) d.Set("account_tier", sku.Tier) From 68d994de0ed9bab0935fe0bafe5cd63c7ba09115 Mon Sep 17 00:00:00 2001 From: lstolyarov Date: Sat, 2 Jun 2018 13:26:54 +0100 Subject: [PATCH 02/10] Update the storage account resource to include identity --- azurerm/resource_arm_storage_account.go | 80 ++++++++++++++++++++++--- 1 file changed, 73 insertions(+), 7 deletions(-) diff --git a/azurerm/resource_arm_storage_account.go b/azurerm/resource_arm_storage_account.go index 508c45dfcebb..aa042b7fffd2 100644 --- a/azurerm/resource_arm_storage_account.go +++ b/azurerm/resource_arm_storage_account.go @@ -223,9 +223,31 @@ func resourceArmStorageAccount() *schema.Resource { Sensitive: true, }, - "object_id": { - Type: schema.TypeString, + "identity": { + Type: schema.TypeList, + Optional: true, Computed: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": { + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: ignoreCaseDiffSuppressFunc, + ValidateFunc: validation.StringInSlice([]string{ + "SystemAssigned", + }, true), + }, + "principal_id": { + Type: schema.TypeString, + Computed: true, + }, + "tenant_id": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, }, "tags": tagsSchema(), @@ -269,6 +291,11 @@ func resourceArmStorageAccountCreate(d *schema.ResourceData, meta interface{}) e }, } + if _, ok := d.GetOk("identity"); ok { + storageAccountIdentity := expandAzureRmStorageAccountIdentity(d) + parameters.Identity = storageAccountIdentity + } + if v, ok := d.GetOk("enable_file_encryption"); ok { parameters.Encryption.Services.File = &storage.EncryptionService{ Enabled: utils.Bool(v.(bool)), @@ -462,6 +489,18 @@ func resourceArmStorageAccountUpdate(d *schema.ResourceData, meta interface{}) e d.SetPartial("enable_https_traffic_only") } + if d.HasChange("identity") { + storageAccountIdentity := expandAzureRmStorageAccountIdentity(d) + + opts := storage.AccountUpdateParameters{ + Identity: storageAccountIdentity, + } + _, err := client.Update(ctx, resourceGroupName, storageAccountName, opts) + if err != nil { + return fmt.Errorf("Error updating Azure Storage Account identity %q: %+v", storageAccountName, err) + } + } + d.Partial(false) return nil } @@ -500,11 +539,6 @@ func resourceArmStorageAccountRead(d *schema.ResourceData, meta interface{}) err } d.Set("account_kind", resp.Kind) - log.Printf("[INFO] Identity is %q", resp.Identity) - if identity := resp.Identity; identity != nil { - d.Set("object_id", identity.PrincipalID) - } - if sku := resp.Sku; sku != nil { d.Set("account_type", sku.Name) d.Set("account_tier", sku.Tier) @@ -586,6 +620,11 @@ func resourceArmStorageAccountRead(d *schema.ResourceData, meta interface{}) err d.Set("primary_access_key", accessKeys[0].Value) d.Set("secondary_access_key", accessKeys[1].Value) + identity := flattenAzureRmStorageAccountIdentity(resp.Identity) + if err := d.Set("identity", identity); err != nil { + return err + } + flattenAndSetTags(d, resp.Tags) return nil @@ -661,3 +700,30 @@ func validateArmStorageAccountType(v interface{}, k string) (ws []string, es []e es = append(es, fmt.Errorf("Invalid storage account type %q", input)) return } + +func expandAzureRmStorageAccountIdentity(d *schema.ResourceData) *storage.Identity { + identities := d.Get("identity").([]interface{}) + identity := identities[0].(map[string]interface{}) + identityType := identity["type"].(string) + return &storage.Identity{ + Type: &identityType, + } +} + +func flattenAzureRmStorageAccountIdentity(identity *storage.Identity) []interface{} { + if identity == nil { + return make([]interface{}, 0) + } + + result := make(map[string]interface{}) + result["type"] = *identity.Type + + if identity.PrincipalID != nil { + result["principal_id"] = *identity.PrincipalID + } + if identity.TenantID != nil { + result["tenant_id"] = *identity.TenantID + } + + return []interface{}{result} +} From 28f4b30c4d53bfb8d56010f6b3a7d8f364826742 Mon Sep 17 00:00:00 2001 From: lstolyarov Date: Sat, 2 Jun 2018 13:27:29 +0100 Subject: [PATCH 03/10] Add the storage account identity tests --- azurerm/resource_arm_storage_account_test.go | 90 ++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/azurerm/resource_arm_storage_account_test.go b/azurerm/resource_arm_storage_account_test.go index 8a50dca6654d..269347165ae0 100644 --- a/azurerm/resource_arm_storage_account_test.go +++ b/azurerm/resource_arm_storage_account_test.go @@ -3,6 +3,7 @@ package azurerm import ( "fmt" "net/http" + "regexp" "testing" "github.com/hashicorp/terraform/helper/acctest" @@ -345,6 +346,69 @@ func TestAccAzureRMStorageAccount_NonStandardCasing(t *testing.T) { }) } +func TestAccAzureRMStorageAccount_enableIdentity(t *testing.T) { + resourceName := "azurerm_storage_account.testsa" + + ri := acctest.RandInt() + rs := acctest.RandString(4) + config := testAccAzureRMStorageAccount_identity(ri, rs, testLocation()) + + uuidMatch := regexp.MustCompile("^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-4[a-fA-F0-9]{3}-[8|9|aA|bB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}$") + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMStorageAccountDestroy, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMStorageAccountExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "identity.0.type", "SystemAssigned"), + resource.TestMatchResourceAttr(resourceName, "identity.0.principal_id", uuidMatch), + resource.TestMatchResourceAttr(resourceName, "identity.0.tenant_id", uuidMatch), + ), + }, + }, + }) +} + +func TestAccAzureRMStorageAccount_updateResourceByEnablingIdentity(t *testing.T) { + resourceName := "azurerm_storage_account.testsa" + + ri := acctest.RandInt() + rs := acctest.RandString(4) + + basicResourceNoManagedIdentity := testAccAzureRMStorageAccount_basic(ri, rs, testLocation()) + managedIdentityEnabled := testAccAzureRMStorageAccount_identity(ri, rs, testLocation()) + + uuidMatch := regexp.MustCompile("^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-4[a-fA-F0-9]{3}-[8|9|aA|bB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}$") + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMStorageAccountDestroy, + Steps: []resource.TestStep{ + { + Config: basicResourceNoManagedIdentity, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMStorageAccountExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "identity.#", "0"), + ), + }, + { + Config: managedIdentityEnabled, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMStorageAccountExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "identity.0.type", "SystemAssigned"), + resource.TestMatchResourceAttr(resourceName, "identity.0.principal_id", uuidMatch), + resource.TestMatchResourceAttr(resourceName, "identity.0.tenant_id", uuidMatch), + ), + }, + }, + }) +} + func testCheckAzureRMStorageAccountExists(name string) resource.TestCheckFunc { return func(s *terraform.State) error { // Ensure we have enough information in state to look up in API @@ -738,3 +802,29 @@ resource "azurerm_storage_account" "testsa" { } `, rInt, location, rString) } + +func testAccAzureRMStorageAccount_identity(rInt int, rString string, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "testrg" { + name = "testAccAzureRMSA-%d" + location = "%s" +} + +resource "azurerm_storage_account" "testsa" { + name = "unlikely23exst2acct%s" + resource_group_name = "${azurerm_resource_group.testrg.name}" + + location = "${azurerm_resource_group.testrg.location}" + account_tier = "Standard" + account_replication_type = "LRS" + + identity { + type = "SystemAssigned" + } + + tags { + environment = "production" + } +} +`, rInt, location, rString) +} From c3f58daca90dd5b2bdcf0099cd730c483bc1a8e9 Mon Sep 17 00:00:00 2001 From: lstolyarov Date: Sat, 2 Jun 2018 13:28:09 +0100 Subject: [PATCH 04/10] Update the storage account identity block documentation --- website/docs/r/storage_account.html.markdown | 25 ++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/website/docs/r/storage_account.html.markdown b/website/docs/r/storage_account.html.markdown index f2eb13964f24..ded0bae47793 100644 --- a/website/docs/r/storage_account.html.markdown +++ b/website/docs/r/storage_account.html.markdown @@ -45,8 +45,8 @@ The following arguments are supported: * `location` - (Required) Specifies the supported Azure location where the resource exists. Changing this forces a new resource to be created. -* `account_kind` - (Optional) Defines the Kind of account. Valid options are `Storage`, - `StorageV2` and `BlobStorage`. Changing this forces a new resource to be created. +* `account_kind` - (Optional) Defines the Kind of account. Valid options are `Storage`, + `StorageV2` and `BlobStorage`. Changing this forces a new resource to be created. Defaults to `Storage`. * `account_tier` - (Required) Defines the Tier to use for this storage account. Valid options are `Standard` and `Premium`. Changing this forces a new resource to be created @@ -72,6 +72,8 @@ The following arguments are supported: * `tags` - (Optional) A mapping of tags to assign to the resource. +* `identity` - (Optional) A Managed Service Identity block as defined below. + --- * `custom_domain` supports the following: @@ -81,6 +83,14 @@ The following arguments are supported: ~> **Note:** [More information on Validation is available here](https://docs.microsoft.com/en-gb/azure/storage/blobs/storage-custom-domain-name) +--- + +`identity` supports the following: + +* `type` - (Required) Specifies the identity type of the Storage Account. At this time the only allowed value is `SystemAssigned`. + +~> The assigned `principal_id` and `tenant_id` can be retrieved after the Storage Account has been created. More details are available below. + ## Attributes Reference The following attributes are exported in addition to the arguments listed above: @@ -101,6 +111,17 @@ The following attributes are exported in addition to the arguments listed above: * `secondary_connection_string` - The connection string associated with the secondary location * `primary_blob_connection_string` - The connection string associated with the primary blob location * `secondary_blob_connection_string` - The connection string associated with the secondary blob location +* `identity` - An `identity` block as defined below, which contains the Identity information for this Storage Account. + +--- + +`identity` exports the following: + +* `principal_id` - The Principal ID for the Service Principal associated with the Identity of this Storage Account. + +* `tenant_id` - The Tenant ID for the Service Principal associated with the Identity of this Storage Account. + +-> You can access the Principal ID via `${azurerm_storage_account.test.identity.0.principal_id}` and the Tenant ID via `${azurerm_storage_account.test.identity.0.tenant_id}` ## Import From f7df70dc396edf68c279505d3068b2668eced086 Mon Sep 17 00:00:00 2001 From: lstolyarov Date: Fri, 8 Jun 2018 09:40:38 +0100 Subject: [PATCH 05/10] Checking identity type is not nill --- azurerm/resource_arm_storage_account.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/azurerm/resource_arm_storage_account.go b/azurerm/resource_arm_storage_account.go index aa042b7fffd2..a9cca7404bdb 100644 --- a/azurerm/resource_arm_storage_account.go +++ b/azurerm/resource_arm_storage_account.go @@ -716,8 +716,9 @@ func flattenAzureRmStorageAccountIdentity(identity *storage.Identity) []interfac } result := make(map[string]interface{}) - result["type"] = *identity.Type - + if identity.Type != nil { + result["type"] = *identity.Type + } if identity.PrincipalID != nil { result["principal_id"] = *identity.PrincipalID } From 8dd38e2dc058c57d27f23eeddd5bbcb105579639 Mon Sep 17 00:00:00 2001 From: lstolyarov Date: Fri, 8 Jun 2018 09:45:39 +0100 Subject: [PATCH 06/10] Updating storage account identity documentation --- website/docs/r/storage_account.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/storage_account.html.markdown b/website/docs/r/storage_account.html.markdown index ded0bae47793..cc68d2e495b2 100644 --- a/website/docs/r/storage_account.html.markdown +++ b/website/docs/r/storage_account.html.markdown @@ -89,7 +89,7 @@ The following arguments are supported: * `type` - (Required) Specifies the identity type of the Storage Account. At this time the only allowed value is `SystemAssigned`. -~> The assigned `principal_id` and `tenant_id` can be retrieved after the Storage Account has been created. More details are available below. +~> The assigned `principal_id` and `tenant_id` can be retrieved after the identity `type` has been set to `SystemAssigned` and Storage Account has been created. More details are available below. ## Attributes Reference From 8a2457ebedefef8b5ec365426a3516da46a93481 Mon Sep 17 00:00:00 2001 From: lstolyarov Date: Wed, 13 Jun 2018 15:35:38 +0100 Subject: [PATCH 07/10] Updating to make the updateResourceByEnablingIdentity test pass --- azurerm/resource_arm_storage_account.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurerm/resource_arm_storage_account.go b/azurerm/resource_arm_storage_account.go index a9cca7404bdb..d7111591813c 100644 --- a/azurerm/resource_arm_storage_account.go +++ b/azurerm/resource_arm_storage_account.go @@ -502,7 +502,7 @@ func resourceArmStorageAccountUpdate(d *schema.ResourceData, meta interface{}) e } d.Partial(false) - return nil + return resourceArmStorageAccountRead(d, meta) } func resourceArmStorageAccountRead(d *schema.ResourceData, meta interface{}) error { From cb8dd586f25a435faeb4488597ed6c2377dbe26f Mon Sep 17 00:00:00 2001 From: lstolyarov Date: Wed, 13 Jun 2018 15:51:30 +0100 Subject: [PATCH 08/10] Running fmt --- azurerm/resource_arm_storage_account.go | 8 ++++---- azurerm/resource_arm_storage_account_test.go | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/azurerm/resource_arm_storage_account.go b/azurerm/resource_arm_storage_account.go index 63a2d98f29b5..50ba72ab65c7 100644 --- a/azurerm/resource_arm_storage_account.go +++ b/azurerm/resource_arm_storage_account.go @@ -533,7 +533,7 @@ func resourceArmStorageAccountUpdate(d *schema.ResourceData, meta interface{}) e d.SetPartial("enable_https_traffic_only") } - if d.HasChange("identity") { + if d.HasChange("identity") { storageAccountIdentity := expandAzureRmStorageAccountIdentity(d) opts := storage.AccountUpdateParameters{ @@ -543,9 +543,9 @@ func resourceArmStorageAccountUpdate(d *schema.ResourceData, meta interface{}) e if err != nil { return fmt.Errorf("Error updating Azure Storage Account identity %q: %+v", storageAccountName, err) } - } - - if d.HasChange("network_rules") { + } + + if d.HasChange("network_rules") { networkRules := expandStorageAccountNetworkRules(d) opts := storage.AccountUpdateParameters{ diff --git a/azurerm/resource_arm_storage_account_test.go b/azurerm/resource_arm_storage_account_test.go index 6c457c1b27f7..3b8a167f275b 100644 --- a/azurerm/resource_arm_storage_account_test.go +++ b/azurerm/resource_arm_storage_account_test.go @@ -408,7 +408,7 @@ func TestAccAzureRMStorageAccount_updateResourceByEnablingIdentity(t *testing.T) }, }) } - + func TestAccAzureRMStorageAccount_networkRules(t *testing.T) { resourceName := "azurerm_storage_account.testsa" ri := acctest.RandInt() @@ -473,7 +473,7 @@ func TestAccAzureRMStorageAccount_networkRulesDeleted(t *testing.T) { }, }, }) -} +} func testCheckAzureRMStorageAccountExists(name string) resource.TestCheckFunc { return func(s *terraform.State) error { @@ -967,4 +967,4 @@ resource "azurerm_storage_account" "testsa" { } } `, rInt, location, rInt, rInt, rString) -} \ No newline at end of file +} From a0db137fcf0c6a4668e01ab3afa66fb3a4e0cf1d Mon Sep 17 00:00:00 2001 From: kt Date: Wed, 13 Jun 2018 19:33:36 -0700 Subject: [PATCH 09/10] Update resource_arm_storage_account.go Removed some lines that were accidentally merged back in. --- azurerm/resource_arm_storage_account.go | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/azurerm/resource_arm_storage_account.go b/azurerm/resource_arm_storage_account.go index 50ba72ab65c7..4b8c7df84420 100644 --- a/azurerm/resource_arm_storage_account.go +++ b/azurerm/resource_arm_storage_account.go @@ -339,13 +339,7 @@ func resourceArmStorageAccountCreate(d *schema.ResourceData, meta interface{}) e storageAccountIdentity := expandAzureRmStorageAccountIdentity(d) parameters.Identity = storageAccountIdentity } - - if v, ok := d.GetOk("enable_file_encryption"); ok { - parameters.Encryption.Services.File = &storage.EncryptionService{ - Enabled: utils.Bool(v.(bool)), - } - } - + if _, ok := d.GetOk("custom_domain"); ok { parameters.CustomDomain = expandStorageAccountCustomDomain(d) } From 86fe88cd0030f03f1bf6ed9b679b24f4a3a30e23 Mon Sep 17 00:00:00 2001 From: kt Date: Wed, 13 Jun 2018 19:43:32 -0700 Subject: [PATCH 10/10] Update resource_arm_storage_account.go fix go fmt issues --- azurerm/resource_arm_storage_account.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurerm/resource_arm_storage_account.go b/azurerm/resource_arm_storage_account.go index 4b8c7df84420..be90c7050a59 100644 --- a/azurerm/resource_arm_storage_account.go +++ b/azurerm/resource_arm_storage_account.go @@ -339,7 +339,7 @@ func resourceArmStorageAccountCreate(d *schema.ResourceData, meta interface{}) e storageAccountIdentity := expandAzureRmStorageAccountIdentity(d) parameters.Identity = storageAccountIdentity } - + if _, ok := d.GetOk("custom_domain"); ok { parameters.CustomDomain = expandStorageAccountCustomDomain(d) }