From fd3779b5c7cda74d38c576bf85236ec5647ff815 Mon Sep 17 00:00:00 2001 From: Allan Targino <13934447+allantargino@users.noreply.github.com> Date: Wed, 14 Apr 2021 16:36:30 -0300 Subject: [PATCH 1/4] adding cmk to synapse --- .../synapse/synapse_workspace_resource.go | 37 +++++++++- .../synapse_workspace_resource_test.go | 72 ++++++++++++++++++- .../docs/r/synapse_workspace.html.markdown | 2 + 3 files changed, 109 insertions(+), 2 deletions(-) diff --git a/azurerm/internal/services/synapse/synapse_workspace_resource.go b/azurerm/internal/services/synapse/synapse_workspace_resource.go index 2673377f3caf..4c5e0c53de80 100644 --- a/azurerm/internal/services/synapse/synapse_workspace_resource.go +++ b/azurerm/internal/services/synapse/synapse_workspace_resource.go @@ -15,6 +15,7 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/location" + keyVaultValidate "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/keyvault/validate" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/synapse/parse" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/synapse/validate" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" @@ -228,6 +229,12 @@ func resourceSynapseWorkspace() *schema.Resource { Optional: true, }, + "customer_managed_key": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: keyVaultValidate.VersionlessNestedItemId, + }, + "tags": tags.Schema(), }, } @@ -267,6 +274,7 @@ func resourceSynapseWorkspaceCreate(d *schema.ResourceData, meta interface{}) er SQLAdministratorLoginPassword: utils.String(d.Get("sql_administrator_login_password").(string)), ManagedResourceGroupName: utils.String(d.Get("managed_resource_group_name").(string)), WorkspaceRepositoryConfiguration: expandWorkspaceRepositoryConfiguration(d), + Encryption: expandEncryptionDetails(d), }, Identity: &synapse.ManagedIdentity{ Type: synapse.ResourceIdentityTypeSystemAssigned, @@ -363,6 +371,7 @@ func resourceSynapseWorkspaceRead(d *schema.ResourceData, meta interface{}) erro d.Set("sql_administrator_login", props.SQLAdministratorLogin) d.Set("managed_resource_group_name", props.ManagedResourceGroupName) d.Set("connectivity_endpoints", utils.FlattenMapStringPtrString(props.ConnectivityEndpoints)) + d.Set("customer_managed_key", flattenEncryptionDetails(props.Encryption)) repoType, repo := flattenWorkspaceRepositoryConfiguration(props.WorkspaceRepositoryConfiguration) if repoType == workspaceVSTSConfiguration { @@ -397,12 +406,13 @@ func resourceSynapseWorkspaceUpdate(d *schema.ResourceData, meta interface{}) er return err } - if d.HasChanges("tags", "sql_administrator_login_password", "github_repo", "azure_devops_repo") { + if d.HasChanges("tags", "sql_administrator_login_password", "github_repo", "azure_devops_repo", "customer_managed_key") { workspacePatchInfo := synapse.WorkspacePatchInfo{ Tags: tags.Expand(d.Get("tags").(map[string]interface{})), WorkspacePatchProperties: &synapse.WorkspacePatchProperties{ SQLAdministratorLoginPassword: utils.String(d.Get("sql_administrator_login_password").(string)), WorkspaceRepositoryConfiguration: expandWorkspaceRepositoryConfiguration(d), + Encryption: expandEncryptionDetails(d), }, } @@ -542,6 +552,20 @@ func expandIdentityControlSQLSettings(enabled bool) *synapse.ManagedIdentitySQLC } } +func expandEncryptionDetails(d *schema.ResourceData) *synapse.EncryptionDetails { + if key, ok := d.GetOk("customer_managed_key"); ok { + return &synapse.EncryptionDetails{ + Cmk: &synapse.CustomerManagedKeyDetails{ + Key: &synapse.WorkspaceKeyDetails{ + Name: utils.String("cmk"), + KeyVaultURL: utils.String(key.(string)), + }, + }, + } + } + return nil +} + func flattenArmWorkspaceManagedIdentity(input *synapse.ManagedIdentity) []interface{} { if input == nil { return make([]interface{}, 0) @@ -642,3 +666,14 @@ func flattenIdentityControlSQLSettings(settings synapse.ManagedIdentitySQLContro return false } + +func flattenEncryptionDetails(encryption *synapse.EncryptionDetails) string { + if cmk := encryption.Cmk; cmk != nil { + if key := cmk.Key; key != nil { + if keyVaultUrl := key.KeyVaultURL; keyVaultUrl != nil { + return *keyVaultUrl + } + } + } + return "" +} diff --git a/azurerm/internal/services/synapse/synapse_workspace_resource_test.go b/azurerm/internal/services/synapse/synapse_workspace_resource_test.go index 922837120d72..ea8ea2d534fc 100644 --- a/azurerm/internal/services/synapse/synapse_workspace_resource_test.go +++ b/azurerm/internal/services/synapse/synapse_workspace_resource_test.go @@ -130,6 +130,22 @@ func TestAccSynapseWorkspace_github(t *testing.T) { }) } +func TestAccSynapseWorkspace_customerManagedKey(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_synapse_workspace", "test") + r := SynapseWorkspaceResource{} + + data.ResourceTest(t, r, []resource.TestStep{ + { + Config: r.customerManagedKey(data), + Check: resource.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("customer_managed_key").Exists(), + ), + }, + data.ImportStep("sql_administrator_login_password"), + }) +} + func (r SynapseWorkspaceResource) Exists(ctx context.Context, client *clients.Client, state *terraform.InstanceState) (*bool, error) { id, err := parse.WorkspaceID(state.ID) if err != nil { @@ -280,10 +296,64 @@ resource "azurerm_synapse_workspace" "test" { `, template, data.RandomInteger) } +func (r SynapseWorkspaceResource) customerManagedKey(data acceptance.TestData) string { + template := r.template(data) + return fmt.Sprintf(` +%s + +data "azurerm_client_config" "current" {} + +resource "azurerm_key_vault" "test" { + name = "acckv%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" + purge_protection_enabled = true + + access_policy { + tenant_id = data.azurerm_client_config.current.tenant_id + object_id = data.azurerm_client_config.current.object_id + key_permissions = [ + "create", + "get", + "delete", + "purge" + ] + } +} + +resource "azurerm_key_vault_key" "test" { + name = "key" + key_vault_id = azurerm_key_vault.test.id + key_type = "RSA" + key_size = 2048 + key_opts = [ + "unwrapKey", + "wrapKey" + ] +} + +resource "azurerm_synapse_workspace" "test" { + name = "acctestsw%d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + storage_data_lake_gen2_filesystem_id = azurerm_storage_data_lake_gen2_filesystem.test.id + sql_administrator_login = "sqladminuser" + sql_administrator_login_password = "H@Sh1CoR3!" + customer_managed_key = azurerm_key_vault_key.test.versionless_id +} +`, template, data.RandomInteger, data.RandomInteger) +} + func (r SynapseWorkspaceResource) template(data acceptance.TestData) string { return fmt.Sprintf(` provider "azurerm" { - features {} + features { + key_vault { + purge_soft_delete_on_destroy = false + } + } } resource "azurerm_resource_group" "test" { diff --git a/website/docs/r/synapse_workspace.html.markdown b/website/docs/r/synapse_workspace.html.markdown index ccaf404b8a4e..77b39c919e49 100644 --- a/website/docs/r/synapse_workspace.html.markdown +++ b/website/docs/r/synapse_workspace.html.markdown @@ -81,6 +81,8 @@ The following arguments are supported: * `github_repo` - (Optional) A `github_repo` block as defined below. +* `customer_managed_key` - (Optional) An Azure Key Vault key ID used as a Customer Managed Key (CMK) for double encryption. + * `tags` - (Optional) A mapping of tags which should be assigned to the Synapse Workspace. --- From f386a6b8e3b974413597283a7cc85ddfa8e4c045 Mon Sep 17 00:00:00 2001 From: Allan Targino <13934447+allantargino@users.noreply.github.com> Date: Wed, 14 Apr 2021 16:56:31 -0300 Subject: [PATCH 2/4] removing deprecated functionality --- .../services/synapse/synapse_workspace_resource.go | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/azurerm/internal/services/synapse/synapse_workspace_resource.go b/azurerm/internal/services/synapse/synapse_workspace_resource.go index 4c5e0c53de80..86b8cef8de14 100644 --- a/azurerm/internal/services/synapse/synapse_workspace_resource.go +++ b/azurerm/internal/services/synapse/synapse_workspace_resource.go @@ -308,16 +308,10 @@ func resourceSynapseWorkspaceCreate(d *schema.ResourceData, meta interface{}) er return fmt.Errorf("Granting workspace identity control for SQL pool: %+v", err) } - resp, err := client.Get(ctx, resourceGroup, name) - if err != nil { - return fmt.Errorf("retrieving Synapse Workspace %q (Resource Group %q): %+v", name, resourceGroup, err) - } - - if resp.ID == nil || *resp.ID == "" { - return fmt.Errorf("empty or nil ID returned for Synapse Workspace %q (Resource Group %q) ID", name, resourceGroup) - } + subscriptionId := meta.(*clients.Client).Account.SubscriptionId + id := parse.NewWorkspaceID(subscriptionId, resourceGroup, name) + d.SetId(id.ID()) - d.SetId(*resp.ID) return resourceSynapseWorkspaceRead(d, meta) } From 092b03c07e2e8024786d0e0ce059bf257fa02941 Mon Sep 17 00:00:00 2001 From: Allan Targino <13934447+allantargino@users.noreply.github.com> Date: Thu, 22 Apr 2021 14:57:22 -0300 Subject: [PATCH 3/4] renaming to customer_managed_key_versionless_id --- .../synapse/synapse_workspace_resource.go | 16 +++++++--------- .../synapse/synapse_workspace_resource_test.go | 9 ++------- website/docs/r/synapse_workspace.html.markdown | 2 +- 3 files changed, 10 insertions(+), 17 deletions(-) diff --git a/azurerm/internal/services/synapse/synapse_workspace_resource.go b/azurerm/internal/services/synapse/synapse_workspace_resource.go index 86b8cef8de14..6d0613a5a94c 100644 --- a/azurerm/internal/services/synapse/synapse_workspace_resource.go +++ b/azurerm/internal/services/synapse/synapse_workspace_resource.go @@ -229,7 +229,7 @@ func resourceSynapseWorkspace() *schema.Resource { Optional: true, }, - "customer_managed_key": { + "customer_managed_key_versionless_id": { Type: schema.TypeString, Optional: true, ValidateFunc: keyVaultValidate.VersionlessNestedItemId, @@ -365,7 +365,7 @@ func resourceSynapseWorkspaceRead(d *schema.ResourceData, meta interface{}) erro d.Set("sql_administrator_login", props.SQLAdministratorLogin) d.Set("managed_resource_group_name", props.ManagedResourceGroupName) d.Set("connectivity_endpoints", utils.FlattenMapStringPtrString(props.ConnectivityEndpoints)) - d.Set("customer_managed_key", flattenEncryptionDetails(props.Encryption)) + d.Set("customer_managed_key_versionless_id", flattenEncryptionDetails(props.Encryption)) repoType, repo := flattenWorkspaceRepositoryConfiguration(props.WorkspaceRepositoryConfiguration) if repoType == workspaceVSTSConfiguration { @@ -400,7 +400,7 @@ func resourceSynapseWorkspaceUpdate(d *schema.ResourceData, meta interface{}) er return err } - if d.HasChanges("tags", "sql_administrator_login_password", "github_repo", "azure_devops_repo", "customer_managed_key") { + if d.HasChanges("tags", "sql_administrator_login_password", "github_repo", "azure_devops_repo", "customer_managed_key_versionless_id") { workspacePatchInfo := synapse.WorkspacePatchInfo{ Tags: tags.Expand(d.Get("tags").(map[string]interface{})), WorkspacePatchProperties: &synapse.WorkspacePatchProperties{ @@ -547,7 +547,7 @@ func expandIdentityControlSQLSettings(enabled bool) *synapse.ManagedIdentitySQLC } func expandEncryptionDetails(d *schema.ResourceData) *synapse.EncryptionDetails { - if key, ok := d.GetOk("customer_managed_key"); ok { + if key, ok := d.GetOk("customer_managed_key_versionless_id"); ok { return &synapse.EncryptionDetails{ Cmk: &synapse.CustomerManagedKeyDetails{ Key: &synapse.WorkspaceKeyDetails{ @@ -661,13 +661,11 @@ func flattenIdentityControlSQLSettings(settings synapse.ManagedIdentitySQLContro return false } -func flattenEncryptionDetails(encryption *synapse.EncryptionDetails) string { +func flattenEncryptionDetails(encryption *synapse.EncryptionDetails) *string { if cmk := encryption.Cmk; cmk != nil { if key := cmk.Key; key != nil { - if keyVaultUrl := key.KeyVaultURL; keyVaultUrl != nil { - return *keyVaultUrl - } + return key.KeyVaultURL } } - return "" + return nil } diff --git a/azurerm/internal/services/synapse/synapse_workspace_resource_test.go b/azurerm/internal/services/synapse/synapse_workspace_resource_test.go index ea8ea2d534fc..5921f3250c17 100644 --- a/azurerm/internal/services/synapse/synapse_workspace_resource_test.go +++ b/azurerm/internal/services/synapse/synapse_workspace_resource_test.go @@ -139,7 +139,7 @@ func TestAccSynapseWorkspace_customerManagedKey(t *testing.T) { Config: r.customerManagedKey(data), Check: resource.ComposeTestCheckFunc( check.That(data.ResourceName).ExistsInAzure(r), - check.That(data.ResourceName).Key("customer_managed_key").Exists(), + check.That(data.ResourceName).Key("customer_managed_key_versionless_id").Exists(), ), }, data.ImportStep("sql_administrator_login_password"), @@ -341,7 +341,7 @@ resource "azurerm_synapse_workspace" "test" { storage_data_lake_gen2_filesystem_id = azurerm_storage_data_lake_gen2_filesystem.test.id sql_administrator_login = "sqladminuser" sql_administrator_login_password = "H@Sh1CoR3!" - customer_managed_key = azurerm_key_vault_key.test.versionless_id + customer_managed_key_versionless_id = azurerm_key_vault_key.test.versionless_id } `, template, data.RandomInteger, data.RandomInteger) } @@ -349,11 +349,6 @@ resource "azurerm_synapse_workspace" "test" { func (r SynapseWorkspaceResource) template(data acceptance.TestData) string { return fmt.Sprintf(` provider "azurerm" { - features { - key_vault { - purge_soft_delete_on_destroy = false - } - } } resource "azurerm_resource_group" "test" { diff --git a/website/docs/r/synapse_workspace.html.markdown b/website/docs/r/synapse_workspace.html.markdown index 77b39c919e49..21d020074e3b 100644 --- a/website/docs/r/synapse_workspace.html.markdown +++ b/website/docs/r/synapse_workspace.html.markdown @@ -81,7 +81,7 @@ The following arguments are supported: * `github_repo` - (Optional) A `github_repo` block as defined below. -* `customer_managed_key` - (Optional) An Azure Key Vault key ID used as a Customer Managed Key (CMK) for double encryption. +* `customer_managed_key_versionless_id` - (Optional) The Azure Key Vault Key Versionless ID to be used as the Customer Managed Key (CMK) for double encryption (e.g. `https://example-keyvault.vault.azure.net/type/cmk/`). * `tags` - (Optional) A mapping of tags which should be assigned to the Synapse Workspace. From f37ed5e75b5550e79ed58c018935b9c7cad56df8 Mon Sep 17 00:00:00 2001 From: Allan Targino <13934447+allantargino@users.noreply.github.com> Date: Thu, 22 Apr 2021 15:18:38 -0300 Subject: [PATCH 4/4] adding purge_soft_delete_on_destroy again --- .../services/synapse/synapse_workspace_resource_test.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/azurerm/internal/services/synapse/synapse_workspace_resource_test.go b/azurerm/internal/services/synapse/synapse_workspace_resource_test.go index 5921f3250c17..f8de21709125 100644 --- a/azurerm/internal/services/synapse/synapse_workspace_resource_test.go +++ b/azurerm/internal/services/synapse/synapse_workspace_resource_test.go @@ -349,6 +349,11 @@ resource "azurerm_synapse_workspace" "test" { func (r SynapseWorkspaceResource) template(data acceptance.TestData) string { return fmt.Sprintf(` provider "azurerm" { + features { + key_vault { + purge_soft_delete_on_destroy = false + } + } } resource "azurerm_resource_group" "test" {