diff --git a/internal/services/containers/container_group_resource.go b/internal/services/containers/container_group_resource.go index d3b2fcb8aed9..ca0cfcbae8cf 100644 --- a/internal/services/containers/container_group_resource.go +++ b/internal/services/containers/container_group_resource.go @@ -553,6 +553,12 @@ func resourceContainerGroup() *pluginsdk.Resource { ForceNew: true, ValidateFunc: keyVaultValidate.NestedItemId, }, + + "key_vault_user_assigned_identity_id": { + Type: pluginsdk.TypeString, + Optional: true, + ValidateFunc: commonids.ValidateUserAssignedIdentityID, + }, }, } } @@ -777,6 +783,10 @@ func resourceContainerGroupCreate(d *pluginsdk.ResourceData, meta interface{}) e KeyName: keyId.Name, KeyVersion: keyId.Version, } + + if keyVaultUAI := d.Get("key_vault_user_assigned_identity_id").(string); keyVaultUAI != "" { + containerGroup.Properties.EncryptionProperties.Identity = &keyVaultUAI + } } // Avoid parallel provisioning if "subnet_ids" are given. @@ -942,6 +952,7 @@ func resourceContainerGroupRead(d *pluginsdk.ResourceData, meta interface{}) err return err } d.Set("key_vault_key_id", keyId.ID()) + d.Set("key_vault_user_assigned_identity_id", pointer.From(kvProps.Identity)) } } diff --git a/internal/services/containers/container_group_resource_test.go b/internal/services/containers/container_group_resource_test.go index 671a180f4fda..1cdc1790fe56 100644 --- a/internal/services/containers/container_group_resource_test.go +++ b/internal/services/containers/container_group_resource_test.go @@ -695,6 +695,21 @@ func TestAccContainerGroup_encryption(t *testing.T) { }) } +func TestAccContainerGroup_encryptionWithUserAssignedIdentity(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_container_group", "test") + r := ContainerGroupResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.encryptionWithUserAssignedIdentity(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + func TestAccContainerGroup_securityContext(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_container_group", "test") r := ContainerGroupResource{} @@ -2489,6 +2504,112 @@ resource "azurerm_container_group" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } +func (ContainerGroupResource) encryptionWithUserAssignedIdentity(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%[1]d" + location = "%[2]s" +} + +data "azurerm_client_config" "current" {} + +resource "azurerm_key_vault" "test" { + name = "acc-%[1]d" + 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" +} + +resource "azurerm_key_vault_access_policy" "terraform" { + key_vault_id = azurerm_key_vault.test.id + key_permissions = [ + "Create", + "Delete", + "Get", + "List", + "Purge", + "Update", + "GetRotationPolicy", + ] + + secret_permissions = [ + "Get", + "Delete", + "Set", + ] + tenant_id = data.azurerm_client_config.current.tenant_id + object_id = data.azurerm_client_config.current.object_id +} + +resource "azurerm_key_vault_key" "test" { + name = "key-%[1]d" + 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.terraform] +} + +resource "azurerm_user_assigned_identity" "test" { + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + name = "uai-%[1]d" +} + +resource "azurerm_key_vault_access_policy" "test" { + key_vault_id = azurerm_key_vault.test.id + key_permissions = [ + "Get", + "UnwrapKey", + "WrapKey", + "GetRotationPolicy", + ] + tenant_id = azurerm_user_assigned_identity.test.tenant_id + object_id = azurerm_user_assigned_identity.test.principal_id + depends_on = [azurerm_key_vault_access_policy.terraform] +} + +resource "azurerm_container_group" "test" { + name = "acctestcontainergroup-%[1]d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + ip_address_type = "Public" + os_type = "Linux" + + container { + name = "hw" + image = "ubuntu:20.04" + cpu = "0.5" + memory = "0.5" + ports { + port = 80 + protocol = "TCP" + } + } + key_vault_key_id = azurerm_key_vault_key.test.id + key_vault_user_assigned_identity_id = azurerm_user_assigned_identity.test.id + identity { + type = "UserAssigned" + identity_ids = [azurerm_user_assigned_identity.test.id] + } + depends_on = [azurerm_key_vault_access_policy.test] +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) +} + func (ContainerGroupResource) securityContextPriviledged(data acceptance.TestData, v bool) string { return fmt.Sprintf(` provider "azurerm" { diff --git a/website/docs/r/container_group.html.markdown b/website/docs/r/container_group.html.markdown index db1d29cc7841..6ef1889f9c30 100644 --- a/website/docs/r/container_group.html.markdown +++ b/website/docs/r/container_group.html.markdown @@ -99,6 +99,8 @@ The following arguments are supported: * `key_vault_key_id` - (Optional) The Key Vault key URI for CMK encryption. Changing this forces a new resource to be created. +* `key_vault_user_assigned_identity_id` - (Optional) The user assigned identity that has access to the Key Vault Key. If not specified, the RP principal named "Azure Container Instance Service" will be used instead. Make sure the identity has the proper `key_permissions` set, at least with `Get`, `UnwrapKey`, `WrapKey` and `GetRotationPolicy`. + * `subnet_ids` - (Optional) The subnet resource IDs for a container group. Changing this forces a new resource to be created. * `image_registry_credential` - (Optional) An `image_registry_credential` block as documented below. Changing this forces a new resource to be created.