Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

azurerm_healthcare_service: support for customer managed key #11481

Merged
merged 9 commits into from
Apr 29, 2021
2 changes: 1 addition & 1 deletion azurerm/internal/services/healthcare/client/client.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package client

import (
healthcare "github.com/Azure/azure-sdk-for-go/services/healthcareapis/mgmt/2019-09-16/healthcareapis"
healthcare "github.com/Azure/azure-sdk-for-go/services/healthcareapis/mgmt/2020-03-30/healthcareapis"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/common"
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,21 @@ func dataSourceHealthcareService() *schema.Resource {
Computed: true,
},

"cosmosdb_throughput": {
Type: schema.TypeInt,
"cosmosdb_configuration": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"throughput": {
Type: schema.TypeInt,
Computed: true,
},
"key_vault_key_id": {
Type: schema.TypeString,
Computed: true,
},
},
},
b4rd marked this conversation as resolved.
Show resolved Hide resolved
},

"access_policy_object_ids": {
Expand Down Expand Up @@ -140,11 +152,9 @@ func dataSourceHealthcareServiceRead(d *schema.ResourceData, meta interface{}) e
return fmt.Errorf("Error setting `access_policy_object_ids`: %+v", err)
}

cosmosThroughput := 0
if props.CosmosDbConfiguration != nil && props.CosmosDbConfiguration.OfferThroughput != nil {
cosmosThroughput = int(*props.CosmosDbConfiguration.OfferThroughput)
if err := d.Set("cosmosdb_configuration", flattenCosmosDbConfig(props.CosmosDbConfiguration)); err != nil {
return fmt.Errorf("Error setting `cosmosdb_configuration`: %+v", err)
}
d.Set("cosmosdb_throughput", cosmosThroughput)

if err := d.Set("authentication_configuration", flattenHealthcareAuthConfig(props.AuthenticationConfiguration)); err != nil {
return fmt.Errorf("Error setting `authentication_configuration`: %+v", err)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ func TestAccHealthCareServiceDataSource_basic(t *testing.T) {
check.That(data.ResourceName).Key("location").Exists(),
check.That(data.ResourceName).Key("resource_group_name").Exists(),
check.That(data.ResourceName).Key("kind").Exists(),
check.That(data.ResourceName).Key("cosmosdb_throughput").Exists(),
check.That(data.ResourceName).Key("tags.%").HasValue("0"),
),
},
Expand Down
105 changes: 90 additions & 15 deletions azurerm/internal/services/healthcare/healthcare_service_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ package healthcare

import (
"fmt"
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"
b4rd marked this conversation as resolved.
Show resolved Hide resolved
"log"
"time"

"github.com/Azure/azure-sdk-for-go/services/healthcareapis/mgmt/2019-09-16/healthcareapis"
"github.com/Azure/azure-sdk-for-go/services/healthcareapis/mgmt/2020-03-30/healthcareapis"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
Expand Down Expand Up @@ -60,11 +62,27 @@ func resourceHealthcareService() *schema.Resource {
}, false),
},

"cosmosdb_throughput": {
Type: schema.TypeInt,
Optional: true,
Default: 1000,
ValidateFunc: validation.IntBetween(1, 10000),
"cosmosdb_configuration": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"throughput": {
Type: schema.TypeInt,
Optional: true,
Default: 1000,
ValidateFunc: validation.IntBetween(1, 10000),
},
"key_vault_key_id": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
DiffSuppressFunc: diffSuppressIgnoreKeyVaultKeyVersion,
ValidateFunc: keyVaultValidate.VersionlessNestedItemId,
},
},
},
b4rd marked this conversation as resolved.
Show resolved Hide resolved
},

"access_policy_object_ids": {
Expand Down Expand Up @@ -196,7 +214,6 @@ func resourceHealthcareServiceCreateUpdate(d *schema.ResourceData, meta interfac
t := d.Get("tags").(map[string]interface{})

kind := d.Get("kind").(string)
cdba := int32(d.Get("cosmosdb_throughput").(int))

if d.IsNewResource() {
existing, err := client.Get(ctx, resGroup, name)
Expand All @@ -211,15 +228,18 @@ func resourceHealthcareServiceCreateUpdate(d *schema.ResourceData, meta interfac
}
}

cosmosDbConfiguration, err := expandAzureRMhealthcareapisCosmosDbConfiguration(d)
if err != nil {
return fmt.Errorf("Error expanding cosmosdb_configuration: %+v", err)
}

healthcareServiceDescription := healthcareapis.ServicesDescription{
Location: utils.String(location),
Tags: tags.Expand(t),
Kind: healthcareapis.Kind(kind),
Properties: &healthcareapis.ServicesProperties{
AccessPolicies: expandAzureRMhealthcareapisAccessPolicyEntries(d),
CosmosDbConfiguration: &healthcareapis.ServiceCosmosDbConfigurationInfo{
OfferThroughput: &cdba,
},
AccessPolicies: expandAzureRMhealthcareapisAccessPolicyEntries(d),
CosmosDbConfiguration: cosmosDbConfiguration,
CorsConfiguration: expandAzureRMhealthcareapisCorsConfiguration(d),
AuthenticationConfiguration: expandAzureRMhealthcareapisAuthentication(d),
},
Expand Down Expand Up @@ -282,11 +302,9 @@ func resourceHealthcareServiceRead(d *schema.ResourceData, meta interface{}) err
return fmt.Errorf("Error setting `access_policy_object_ids`: %+v", err)
}

cosmosThroughput := 0
if props.CosmosDbConfiguration != nil && props.CosmosDbConfiguration.OfferThroughput != nil {
cosmosThroughput = int(*props.CosmosDbConfiguration.OfferThroughput)
if err := d.Set("cosmosdb_configuration", flattenCosmosDbConfig(props.CosmosDbConfiguration)); err != nil {
return fmt.Errorf("Error setting `cosmosdb_configuration`: %+v", err)
}
d.Set("cosmosdb_throughput", cosmosThroughput)

if err := d.Set("authentication_configuration", flattenHealthcareAuthConfig(props.AuthenticationConfiguration)); err != nil {
return fmt.Errorf("Error setting `authentication_configuration`: %+v", err)
Expand Down Expand Up @@ -379,6 +397,28 @@ func expandAzureRMhealthcareapisAuthentication(d *schema.ResourceData) *healthca
return auth
}

func expandAzureRMhealthcareapisCosmosDbConfiguration(d *schema.ResourceData) (*healthcareapis.ServiceCosmosDbConfigurationInfo, error) {
cosmosDbConfigRaw := d.Get("cosmosdb_configuration").([]interface{})

if len(cosmosDbConfigRaw) == 0 {
return &healthcareapis.ServiceCosmosDbConfigurationInfo{}, nil
}

cosmosDbConfigAttr := cosmosDbConfigRaw[0].(map[string]interface{})
cosmosdb := &healthcareapis.ServiceCosmosDbConfigurationInfo{
OfferThroughput: utils.Int32(int32(cosmosDbConfigAttr["throughput"].(int))),
}
if keyVaultKeyIDRaw := cosmosDbConfigAttr["key_vault_key_id"]; keyVaultKeyIDRaw != "" {
keyVaultKey, err := keyVaultParse.ParseOptionallyVersionedNestedItemID(keyVaultKeyIDRaw.(string))
if err != nil {
return nil, fmt.Errorf("could not parse Key Vault Key ID: %+v", err)
}
cosmosdb.KeyVaultKeyURI = utils.String(keyVaultKey.ID())
}

return cosmosdb, nil
}

func flattenHealthcareAccessPolicies(policies *[]healthcareapis.ServiceAccessPolicyEntry) []string {
result := make([]string, 0)

Expand All @@ -395,6 +435,28 @@ func flattenHealthcareAccessPolicies(policies *[]healthcareapis.ServiceAccessPol
return result
}

func flattenCosmosDbConfig(input *healthcareapis.ServiceCosmosDbConfigurationInfo) []interface{} {
if input == nil {
return []interface{}{}
}

throughput := 0
if input.OfferThroughput != nil {
throughput = int(*input.OfferThroughput)
}
keyVaultKeyId := ""
if input.KeyVaultKeyURI != nil {
keyVaultKeyId = *input.KeyVaultKeyURI
}

return []interface{}{
map[string]interface{}{
"throughput": throughput,
"key_vault_key_id": keyVaultKeyId,
},
}
}

func flattenHealthcareAuthConfig(input *healthcareapis.ServiceAuthenticationConfigurationInfo) []interface{} {
if input == nil {
return []interface{}{}
Expand Down Expand Up @@ -445,3 +507,16 @@ func flattenHealthcareCorsConfig(input *healthcareapis.ServiceCorsConfigurationI
},
}
}

func diffSuppressIgnoreKeyVaultKeyVersion(k, old, new string, d *schema.ResourceData) bool {
oldKey, err := keyVaultParse.ParseOptionallyVersionedNestedItemID(old)
if err != nil {
return false
}
newKey, err := keyVaultParse.ParseOptionallyVersionedNestedItemID(new)
if err != nil {
return false
}

return (oldKey.KeyVaultBaseUrl == newKey.KeyVaultBaseUrl) && (oldKey.Name == newKey.Name)
}
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ resource "azurerm_healthcare_service" "test" {
access_policy_object_ids = [
data.azurerm_client_config.current.object_id,
]

cosmosdb_configuration {
}
}
`, data.RandomInteger, location, data.RandomIntOfLength(17)) // name can only be 24 chars long
}
Expand All @@ -127,17 +130,80 @@ func (HealthCareServiceResource) complete(data acceptance.TestData) string {

return fmt.Sprintf(`
provider "azurerm" {
features {}
features {
key_vault {
purge_soft_delete_on_destroy = false
}
}
}

provider "azuread" {}

data "azurerm_client_config" "current" {
}

data "azuread_service_principal" "cosmosdb" {
display_name = "Azure Cosmos DB"
}

resource "azurerm_resource_group" "test" {
name = "acctestRG-health-%d"
location = "%s"
}

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"

purge_protection_enabled = true
soft_delete_enabled = true
soft_delete_retention_days = 7

access_policy {
tenant_id = data.azurerm_client_config.current.tenant_id
object_id = data.azurerm_client_config.current.object_id

key_permissions = [
"list",
"create",
"delete",
"get",
"purge",
"update",
]
}

access_policy {
tenant_id = data.azurerm_client_config.current.tenant_id
object_id = data.azuread_service_principal.cosmosdb.id

key_permissions = [
"get",
"unwrapKey",
"wrapKey",
]
}
}

resource "azurerm_key_vault_key" "test" {
name = "examplekey"
key_vault_id = azurerm_key_vault.test.id
key_type = "RSA"
key_size = 2048

key_opts = [
"decrypt",
"encrypt",
"sign",
"unwrapKey",
"verify",
"wrapKey",
]
}

resource "azurerm_healthcare_service" "test" {
name = "testacc%d"
location = azurerm_resource_group.test.location
Expand Down Expand Up @@ -165,6 +231,11 @@ resource "azurerm_healthcare_service" "test" {
max_age_in_seconds = 500
allow_credentials = true
}

cosmosdb_configuration {
throughput = 400
key_vault_key_id = azurerm_key_vault_key.test.versionless_id
}
}
`, data.RandomInteger, location, data.RandomIntOfLength(17)) // name can only be 24 chars long
`, data.RandomInteger, location, data.RandomString, data.RandomIntOfLength(17)) // name can only be 24 chars long
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading