Skip to content

Commit

Permalink
Support for user_assigned_identity_id in `azurerm_storage_account_c…
Browse files Browse the repository at this point in the history
…ustomer_managed_key` (#12516)

Close #12489
  • Loading branch information
shibayan authored Jul 15, 2021
1 parent 3536261 commit d36c256
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/locks"
keyVaultParse "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/keyvault/parse"
keyVaultValidate "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/keyvault/validate"
msivalidate "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/msi/validate"
storageParse "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/storage/parse"
storageValidate "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/storage/validate"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tf/pluginsdk"
Expand Down Expand Up @@ -62,6 +63,12 @@ func resourceStorageAccountCustomerManagedKey() *pluginsdk.Resource {
Optional: true,
ValidateFunc: validation.StringIsNotEmpty,
},

"user_assigned_identity_id": {
Type: pluginsdk.TypeString,
Optional: true,
ValidateFunc: msivalidate.UserAssignedIdentityID,
},
},
}
}
Expand Down Expand Up @@ -139,6 +146,7 @@ func resourceStorageAccountCustomerManagedKeyCreateUpdate(d *pluginsdk.ResourceD

keyName := d.Get("key_name").(string)
keyVersion := d.Get("key_version").(string)
userAssignedIdentity := d.Get("user_assigned_identity_id").(string)

props := storage.AccountUpdateParameters{
AccountPropertiesUpdateParameters: &storage.AccountPropertiesUpdateParameters{
Expand All @@ -151,6 +159,9 @@ func resourceStorageAccountCustomerManagedKeyCreateUpdate(d *pluginsdk.ResourceD
Enabled: utils.Bool(true),
},
},
EncryptionIdentity: &storage.EncryptionIdentity{
EncryptionUserAssignedIdentity: utils.String(userAssignedIdentity),
},
KeySource: storage.KeySourceMicrosoftKeyvault,
KeyVaultProperties: &storage.KeyVaultProperties{
KeyName: utils.String(keyName),
Expand Down Expand Up @@ -217,6 +228,13 @@ func resourceStorageAccountCustomerManagedKeyRead(d *pluginsdk.ResourceData, met
}
}

userAssignedIdentity := ""
if props := encryption.EncryptionIdentity; props != nil {
if props.EncryptionUserAssignedIdentity != nil {
userAssignedIdentity = *props.EncryptionUserAssignedIdentity
}
}

if keyVaultURI == "" {
return fmt.Errorf("Error retrieving Storage Account %q (Resource Group %q): `properties.encryption.keyVaultProperties.keyVaultURI` was nil", storageAccountID.Name, storageAccountID.ResourceGroup)
}
Expand All @@ -232,6 +250,7 @@ func resourceStorageAccountCustomerManagedKeyRead(d *pluginsdk.ResourceData, met
d.Set("key_vault_id", keyVaultID)
d.Set("key_name", keyName)
d.Set("key_version", keyVersion)
d.Set("user_assigned_identity_id", userAssignedIdentity)

return nil
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,22 @@ func TestAccAzureRMStorageAccountCustomerManagedKey_remoteKeyVault(t *testing.T)
})
}

func TestAccStorageAccountCustomerManagedKey_userAssignedIdentity(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_storage_account_customer_managed_key", "test")
r := StorageAccountCustomerManagedKeyResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.userAssignedIdentity(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
check.That(data.ResourceName).Key("user_assigned_identity_id").Exists(),
),
},
data.ImportStep(),
})
}

func (r StorageAccountCustomerManagedKeyResource) accountHasDefaultSettings(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) error {
accountId, err := storageParse.StorageAccountID(state.Attributes["id"])
if err != nil {
Expand Down Expand Up @@ -248,6 +264,21 @@ resource "azurerm_storage_account_customer_managed_key" "test" {
`, template)
}

func (r StorageAccountCustomerManagedKeyResource) userAssignedIdentity(data acceptance.TestData) string {
template := r.userAssignedIdentityTemplate(data)
return fmt.Sprintf(`
%s
resource "azurerm_storage_account_customer_managed_key" "test" {
storage_account_id = azurerm_storage_account.test.id
key_vault_id = azurerm_key_vault.test.id
key_name = azurerm_key_vault_key.first.name
key_version = azurerm_key_vault_key.first.version
user_assigned_identity_id = azurerm_user_assigned_identity.test.id
}
`, template)
}

// (@jackofallops) - This test spans 2 subscriptions to check that it's possible to use a CMK stored in a vault in a non-local subscription. This is temporarily making use of an extra providerfactory which will need to be removed after the move to plugin-sdk-go
// TODO - review this config when plugin-sdk-go is implemented in the provider / test framework.
func (r StorageAccountCustomerManagedKeyResource) remoteKeyVault(data acceptance.TestData) string {
Expand Down Expand Up @@ -357,6 +388,85 @@ resource "azurerm_storage_account_customer_managed_key" "test" {
`, clientData.SubscriptionIDAlt, clientData.TenantID, data.RandomInteger, data.Locations.Primary, data.RandomString, clientData.TenantID, data.RandomInteger, data.Locations.Primary, data.RandomString)
}

func (r StorageAccountCustomerManagedKeyResource) userAssignedIdentityTemplate(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
features {
key_vault {
purge_soft_delete_on_destroy = false
}
}
}
data "azurerm_client_config" "current" {}
resource "azurerm_resource_group" "test" {
name = "acctestRG-%d"
location = "%s"
}
resource "azurerm_user_assigned_identity" "test" {
name = "acctestmi%s"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
}
resource "azurerm_key_vault" "test" {
name = "acctestkv%s"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
tenant_id = data.azurerm_client_config.current.tenant_id
sku_name = "standard"
soft_delete_enabled = true
purge_protection_enabled = true
}
resource "azurerm_key_vault_access_policy" "storage" {
key_vault_id = azurerm_key_vault.test.id
tenant_id = data.azurerm_client_config.current.tenant_id
object_id = azurerm_user_assigned_identity.test.principal_id
key_permissions = ["get", "create", "list", "restore", "recover", "unwrapkey", "wrapkey", "purge", "encrypt", "decrypt", "sign", "verify"]
secret_permissions = ["get"]
}
resource "azurerm_key_vault_access_policy" "client" {
key_vault_id = azurerm_key_vault.test.id
tenant_id = data.azurerm_client_config.current.tenant_id
object_id = data.azurerm_client_config.current.object_id
key_permissions = ["get", "create", "delete", "list", "restore", "recover", "unwrapkey", "wrapkey", "purge", "encrypt", "decrypt", "sign", "verify"]
secret_permissions = ["get"]
}
resource "azurerm_key_vault_key" "first" {
name = "first"
key_vault_id = azurerm_key_vault.test.id
key_type = "RSA"
key_size = 2048
key_opts = ["decrypt", "encrypt", "sign", "unwrapKey", "verify", "wrapKey"]
depends_on = [
azurerm_key_vault_access_policy.client,
azurerm_key_vault_access_policy.storage,
]
}
resource "azurerm_storage_account" "test" {
name = "acctestsa%s"
resource_group_name = azurerm_resource_group.test.name
location = azurerm_resource_group.test.location
account_tier = "Standard"
account_replication_type = "LRS"
identity {
type = "UserAssigned"
identity_ids = [azurerm_user_assigned_identity.test.id]
}
}
`, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString, data.RandomString)
}

func (r StorageAccountCustomerManagedKeyResource) template(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ The following arguments are supported:

* `key_version` - (Optional) The version of Key Vault Key. Remove or omit this argument to enable Automatic Key Rotation.

* `user_assigned_identity_id` - (Optional) The ID of a user assigned identity.

## Attributes Reference

The following attributes are exported in addition to the arguments listed above:
Expand Down

0 comments on commit d36c256

Please sign in to comment.