Skip to content

Commit

Permalink
Support for value_from_key_vault in `azurerm_api_management_named_v…
Browse files Browse the repository at this point in the history
…alue` (#12309)

Fix #10416
  • Loading branch information
yupwei68 authored Jul 12, 2021
1 parent 9ef170c commit a04f4b5
Show file tree
Hide file tree
Showing 3 changed files with 288 additions and 16 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/clients"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/apimanagement/parse"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/apimanagement/schemaz"
keyVaultValidate "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/keyvault/validate"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tf/pluginsdk"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tf/validation"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts"
Expand Down Expand Up @@ -46,11 +47,33 @@ func resourceApiManagementNamedValue() *pluginsdk.Resource {
ValidateFunc: validation.StringIsNotEmpty,
},

"value_from_key_vault": {
Type: pluginsdk.TypeList,
Optional: true,
MaxItems: 1,
ExactlyOneOf: []string{"value", "value_from_key_vault"},
Elem: &pluginsdk.Resource{
Schema: map[string]*pluginsdk.Schema{
"secret_id": {
Type: pluginsdk.TypeString,
Required: true,
ValidateFunc: keyVaultValidate.NestedItemId,
},
"identity_client_id": {
Type: pluginsdk.TypeString,
Required: true,
ValidateFunc: validation.IsUUID,
},
},
},
},

"value": {
Type: pluginsdk.TypeString,
Required: true,
Optional: true,
Sensitive: true,
ValidateFunc: validation.StringIsNotEmpty,
ExactlyOneOf: []string{"value", "value_from_key_vault"},
},

"secret": {
Expand Down Expand Up @@ -96,10 +119,14 @@ func resourceApiManagementNamedValueCreateUpdate(d *pluginsdk.ResourceData, meta
NamedValueCreateContractProperties: &apimanagement.NamedValueCreateContractProperties{
DisplayName: utils.String(d.Get("display_name").(string)),
Secret: utils.Bool(d.Get("secret").(bool)),
Value: utils.String(d.Get("value").(string)),
KeyVault: expandApiManagementNamedValueKeyVault(d.Get("value_from_key_vault").([]interface{})),
},
}

if v, ok := d.GetOk("value"); ok {
parameters.NamedValueCreateContractProperties.Value = utils.String(v.(string))
}

if tags, ok := d.GetOk("tags"); ok {
parameters.NamedValueCreateContractProperties.Tags = utils.ExpandStringSlice(tags.([]interface{}))
}
Expand Down Expand Up @@ -160,6 +187,9 @@ func resourceApiManagementNamedValueRead(d *pluginsdk.ResourceData, meta interfa
if properties.Secret != nil && !*properties.Secret {
d.Set("value", properties.Value)
}
if err := d.Set("value_from_key_vault", flattenApiManagementNamedValueKeyVault(properties.KeyVault)); err != nil {
return fmt.Errorf("setting `value_from_key_vault`: %+v", err)
}
d.Set("tags", properties.Tags)
}

Expand Down Expand Up @@ -187,3 +217,37 @@ func resourceApiManagementNamedValueDelete(d *pluginsdk.ResourceData, meta inter

return nil
}

func expandApiManagementNamedValueKeyVault(inputs []interface{}) *apimanagement.KeyVaultContractCreateProperties {
if len(inputs) == 0 {
return nil
}
input := inputs[0].(map[string]interface{})

return &apimanagement.KeyVaultContractCreateProperties{
SecretIdentifier: utils.String(input["secret_id"].(string)),
IdentityClientID: utils.String(input["identity_client_id"].(string)),
}
}

func flattenApiManagementNamedValueKeyVault(input *apimanagement.KeyVaultContractProperties) []interface{} {
if input == nil {
return []interface{}{}
}

var secretId, clientId string
if input.SecretIdentifier != nil {
secretId = *input.SecretIdentifier
}

if input.IdentityClientID != nil {
clientId = *input.IdentityClientID
}

return []interface{}{
map[string]interface{}{
"secret_id": secretId,
"identity_client_id": clientId,
},
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,50 @@ func TestAccApiManagementNamedValue_basic(t *testing.T) {
})
}

func TestAccApiManagementNamedValue_keyVault(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_api_management_named_value", "test")
r := ApiManagementNamedValueResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.keyVault(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
})
}

func TestAccApiManagementNamedValue_keyVaultUpdate(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_api_management_named_value", "test")
r := ApiManagementNamedValueResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.keyVault(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
{
Config: r.keyVaultUpdate(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
{
Config: r.keyVaultUpdateToValue(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
})
}

func TestAccApiManagementNamedValue_update(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_api_management_named_value", "test")
r := ApiManagementNamedValueResource{}
Expand Down Expand Up @@ -70,7 +114,7 @@ func (ApiManagementNamedValueResource) Exists(ctx context.Context, clients *clie
return utils.Bool(resp.ID != nil), nil
}

func (ApiManagementNamedValueResource) basic(data acceptance.TestData) string {
func (ApiManagementNamedValueResource) template(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
features {}
Expand All @@ -90,6 +134,12 @@ resource "azurerm_api_management" "test" {
sku_name = "Consumption_0"
}
`, data.RandomInteger, data.Locations.Primary, data.RandomInteger)
}

func (r ApiManagementNamedValueResource) basic(data acceptance.TestData) string {
return fmt.Sprintf(`
%s
resource "azurerm_api_management_named_value" "test" {
name = "acctestAMProperty-%d"
Expand All @@ -99,38 +149,186 @@ resource "azurerm_api_management_named_value" "test" {
value = "Test Value"
tags = ["tag1", "tag2"]
}
`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger)
`, r.template(data), data.RandomInteger, data.RandomInteger)
}

func (r ApiManagementNamedValueResource) update(data acceptance.TestData) string {
return fmt.Sprintf(`
%s
resource "azurerm_api_management_named_value" "test" {
name = "acctestAMProperty-%d"
resource_group_name = azurerm_resource_group.test.name
api_management_name = azurerm_api_management.test.name
display_name = "TestProperty2%d"
value = "Test Value2"
secret = true
tags = ["tag3", "tag4"]
}
`, r.template(data), data.RandomInteger, data.RandomInteger)
}

func (ApiManagementNamedValueResource) update(data acceptance.TestData) string {
func (r ApiManagementNamedValueResource) keyVaultTemplate(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
features {}
features {
key_vault {
purge_soft_delete_on_destroy = true
}
}
}
resource "azurerm_resource_group" "test" {
name = "acctestRG-%d"
location = "%s"
name = "acctestRG-Apim-%[1]d"
location = "%[2]s"
}
resource "azurerm_user_assigned_identity" "test" {
name = "acctestUAI-%[1]d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
}
resource "azurerm_api_management" "test" {
name = "acctestAM-%d"
name = "acctestAM-%[1]d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
publisher_name = "pub1"
publisher_email = "[email protected]"
sku_name = "Consumption_0"
identity {
type = "UserAssigned"
identity_ids = [
azurerm_user_assigned_identity.test.id,
]
}
}
data "azurerm_client_config" "current" {}
resource "azurerm_key_vault" "test" {
name = "acctestKV-%[3]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"
}
resource "azurerm_key_vault_access_policy" "test" {
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
certificate_permissions = [
"Create",
"Delete",
"Deleteissuers",
"Get",
"Getissuers",
"Import",
"List",
"Listissuers",
"Managecontacts",
"Manageissuers",
"Setissuers",
"Update",
"Purge",
]
secret_permissions = [
"Get",
"Delete",
"List",
"Purge",
"Recover",
"Set",
]
}
resource "azurerm_key_vault_access_policy" "test2" {
key_vault_id = azurerm_key_vault.test.id
tenant_id = azurerm_user_assigned_identity.test.tenant_id
object_id = azurerm_user_assigned_identity.test.principal_id
secret_permissions = [
"Get",
"List",
]
}
resource "azurerm_key_vault_secret" "test" {
name = "secret-%[3]s"
value = "rick-and-morty"
key_vault_id = azurerm_key_vault.test.id
depends_on = [azurerm_key_vault_access_policy.test]
}
resource "azurerm_key_vault_secret" "test2" {
name = "secret2-%[3]s"
value = "rick-and-morty2"
key_vault_id = azurerm_key_vault.test.id
depends_on = [azurerm_key_vault_access_policy.test]
}
`, data.RandomInteger, data.Locations.Primary, data.RandomString)
}

func (r ApiManagementNamedValueResource) keyVault(data acceptance.TestData) string {
return fmt.Sprintf(`
%[1]s
resource "azurerm_api_management_named_value" "test" {
name = "acctestAMProperty-%[2]d"
resource_group_name = azurerm_resource_group.test.name
api_management_name = azurerm_api_management.test.name
display_name = "TestKeyVault%[2]d"
secret = true
value_from_key_vault {
secret_id = azurerm_key_vault_secret.test.id
identity_client_id = azurerm_user_assigned_identity.test.client_id
}
tags = ["tag1", "tag2"]
depends_on = [azurerm_key_vault_access_policy.test2]
}
`, r.keyVaultTemplate(data), data.RandomInteger)
}

func (r ApiManagementNamedValueResource) keyVaultUpdate(data acceptance.TestData) string {
return fmt.Sprintf(`
%[1]s
resource "azurerm_api_management_named_value" "test" {
name = "acctestAMProperty-%d"
resource_group_name = azurerm_api_management.test.resource_group_name
name = "acctestAMProperty-%[2]d"
resource_group_name = azurerm_resource_group.test.name
api_management_name = azurerm_api_management.test.name
display_name = "TestProperty2%d"
value = "Test Value2"
display_name = "TestKeyVault%[2]d"
secret = true
tags = ["tag3", "tag4"]
value_from_key_vault {
secret_id = azurerm_key_vault_secret.test2.id
identity_client_id = azurerm_user_assigned_identity.test.client_id
}
tags = ["tag3", "tag4"]
depends_on = [azurerm_key_vault_access_policy.test2]
}
`, r.keyVaultTemplate(data), data.RandomInteger)
}

func (r ApiManagementNamedValueResource) keyVaultUpdateToValue(data acceptance.TestData) string {
return fmt.Sprintf(`
%[1]s
resource "azurerm_api_management_named_value" "test" {
name = "acctestAMProperty-%[2]d"
resource_group_name = azurerm_resource_group.test.name
api_management_name = azurerm_api_management.test.name
display_name = "TestKeyVault%[2]d"
secret = false
value = "Key Vault to Value"
tags = ["tag5", "tag6"]
}
`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger)
`, r.keyVaultTemplate(data), data.RandomInteger)
}
Loading

0 comments on commit a04f4b5

Please sign in to comment.