From 3cb95f1af570b113fb28904544a36f3bc7bfffd4 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Wed, 16 Dec 2020 17:43:55 +0100 Subject: [PATCH 01/18] r/keyvault: fixing a bug where application id couldn't be an empty string This field is optional, so this makes sense to be optional or a UUID --- .../services/keyvault/key_vault_resource.go | 2 +- .../services/keyvault/validate/uuid.go | 26 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 azurerm/internal/services/keyvault/validate/uuid.go diff --git a/azurerm/internal/services/keyvault/key_vault_resource.go b/azurerm/internal/services/keyvault/key_vault_resource.go index f4eff6aecd37..7953c18f41c8 100644 --- a/azurerm/internal/services/keyvault/key_vault_resource.go +++ b/azurerm/internal/services/keyvault/key_vault_resource.go @@ -103,7 +103,7 @@ func resourceArmKeyVault() *schema.Resource { "application_id": { Type: schema.TypeString, Optional: true, - ValidateFunc: validation.IsUUID, + ValidateFunc: validate.IsUUIDOrEmpty, }, "certificate_permissions": azure.SchemaKeyVaultCertificatePermissions(), "key_permissions": azure.SchemaKeyVaultKeyPermissions(), diff --git a/azurerm/internal/services/keyvault/validate/uuid.go b/azurerm/internal/services/keyvault/validate/uuid.go new file mode 100644 index 000000000000..d04b88fec581 --- /dev/null +++ b/azurerm/internal/services/keyvault/validate/uuid.go @@ -0,0 +1,26 @@ +package validate + +import ( + "fmt" + + "github.com/hashicorp/go-uuid" +) + +// IsUUIDOrEmpty is a ValidateFunc that ensures a string can be parsed as UUID or is empty +func IsUUIDOrEmpty(i interface{}, k string) (warnings []string, errors []error) { + v, ok := i.(string) + if !ok { + errors = append(errors, fmt.Errorf("expected type of %q to be string", k)) + return + } + + if v == "" { + return + } + + if _, err := uuid.ParseUUID(v); err != nil { + errors = append(errors, fmt.Errorf("expected %q to be a valid UUID, got %v", k, v)) + } + + return warnings, errors +} From 5d289a8d0ba8f39f2ca04f32e8c2ee3916d58d2e Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Thu, 17 Dec 2020 11:27:09 +0100 Subject: [PATCH 02/18] keyvault/nested-resources: purging during deletion --- .../key_vault_certificate_resource.go | 62 +++++++++++++++- .../keyvault/key_vault_key_resource.go | 71 ++++++++++++++++++- .../keyvault/key_vault_secret_resource.go | 71 ++++++++++++++++++- 3 files changed, 199 insertions(+), 5 deletions(-) diff --git a/azurerm/internal/services/keyvault/key_vault_certificate_resource.go b/azurerm/internal/services/keyvault/key_vault_certificate_resource.go index d2af55b7370c..87602b57dd69 100644 --- a/azurerm/internal/services/keyvault/key_vault_certificate_resource.go +++ b/azurerm/internal/services/keyvault/key_vault_certificate_resource.go @@ -602,13 +602,73 @@ func resourceArmKeyVaultCertificateDelete(d *schema.ResourceData, meta interface return nil } + log.Printf("[DEBUG] Deleting Certificate %q (Key Vault %q)..", id.Name, id.KeyVaultBaseUrl) resp, err := client.DeleteCertificate(ctx, id.KeyVaultBaseUrl, id.Name) if err != nil { if utils.ResponseWasNotFound(resp.Response) { return nil } - return fmt.Errorf("Error deleting Certificate %q from Key Vault: %+v", id.Name, err) + return fmt.Errorf("deleting Certificate %q (Key Vault %q): %+v", id.Name, id.KeyVaultBaseUrl, err) + } + log.Printf("[DEBUG] Waiting for Certificate %q (Key Vault %q) to finish deleting", id.Name, id.KeyVaultBaseUrl) + stateConf := &resource.StateChangeConf{ + Pending: []string{"InProgress"}, + Target: []string{"NotFound"}, + Refresh: func() (interface{}, string, error) { + key, err := client.GetCertificate(ctx, id.KeyVaultBaseUrl, id.Name, "") + if err != nil { + if utils.ResponseWasNotFound(key.Response) { + return key, "NotFound", nil + } + + return nil, "Error", err + } + + return key, "InProgress", nil + }, + ContinuousTargetOccurence: 3, + PollInterval: 5 * time.Second, + Timeout: d.Timeout(schema.TimeoutDelete), + } + if _, err := stateConf.WaitForState(); err != nil { + return fmt.Errorf("waiting for Certificate %q (Key Vault %q) to be deleted: %+v", id.Name, id.KeyVaultBaseUrl, err) + } + log.Printf("[DEBUG] Deleted Secret %q (Key Vault %q).", id.Name, id.KeyVaultBaseUrl) + + shouldPurge := true // meta.(*clients.Client).Features.KeyVault.PurgeNestedItemsOnDestroy + if shouldPurge { + log.Printf("[DEBUG] Purging Certificate %q (Key Vault %q)..", id.Name, id.KeyVaultBaseUrl) + if _, err := client.PurgeDeletedCertificate(ctx, id.KeyVaultBaseUrl, id.Name); err != nil { + return fmt.Errorf("purging Certificate %q (Key Vault %q): %+v", id.Name, id.KeyVaultBaseUrl, err) + } + + log.Printf("[DEBUG] Waiting for Certificate %q (Key Vault %q) to finish purging..", id.Name, id.KeyVaultBaseUrl) + stateConf := &resource.StateChangeConf{ + Pending: []string{"InProgress"}, + Target: []string{"NotFound"}, + Refresh: func() (interface{}, string, error) { + key, err := client.GetDeletedCertificate(ctx, id.KeyVaultBaseUrl, id.Name) + if err != nil { + if utils.ResponseWasNotFound(key.Response) { + return key, "NotFound", nil + } + + return nil, "Error", err + } + + return key, "InProgress", nil + }, + ContinuousTargetOccurence: 3, + PollInterval: 5 * time.Second, + Timeout: d.Timeout(schema.TimeoutDelete), + } + if _, err := stateConf.WaitForState(); err != nil { + return fmt.Errorf("waiting for Certificate %q (Key Vault %q) to finish purging: %+v", id.Name, id.KeyVaultBaseUrl, err) + } + log.Printf("[DEBUG] Purged Certificate %q (Key Vault %q).", id.Name, id.KeyVaultBaseUrl) + } else { + log.Printf("[DEBUG] Skipping purging of Certificate %q (Key Vault %q)..", id.Name, id.KeyVaultBaseUrl) } return nil diff --git a/azurerm/internal/services/keyvault/key_vault_key_resource.go b/azurerm/internal/services/keyvault/key_vault_key_resource.go index 690844ddad4f..c88593c5ed7d 100644 --- a/azurerm/internal/services/keyvault/key_vault_key_resource.go +++ b/azurerm/internal/services/keyvault/key_vault_key_resource.go @@ -429,8 +429,75 @@ func resourceArmKeyVaultKeyDelete(d *schema.ResourceData, meta interface{}) erro return nil } - _, err = client.DeleteKey(ctx, id.KeyVaultBaseUrl, id.Name) - return err + log.Printf("[DEBUG] Deleting Key %q (Key Vault %q)..", id.Name, id.KeyVaultBaseUrl) + if resp, err := client.DeleteKey(ctx, id.KeyVaultBaseUrl, id.Name); err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return nil + } + + return fmt.Errorf("deleting Key %q (Key Vault %q): %+v", id.Name, id.KeyVaultBaseUrl, err) + } + log.Printf("[DEBUG] Waiting for Key %q (Key Vault %q) to finish deleting", id.Name, id.KeyVaultBaseUrl) + stateConf := &resource.StateChangeConf{ + Pending: []string{"InProgress"}, + Target: []string{"NotFound"}, + Refresh: func() (interface{}, string, error) { + key, err := client.GetKey(ctx, id.KeyVaultBaseUrl, id.Name, "") + if err != nil { + if utils.ResponseWasNotFound(key.Response) { + return key, "NotFound", nil + } + + return nil, "Error", err + } + + return key, "InProgress", nil + }, + ContinuousTargetOccurence: 3, + PollInterval: 5 * time.Second, + Timeout: d.Timeout(schema.TimeoutDelete), + } + if _, err := stateConf.WaitForState(); err != nil { + return fmt.Errorf("waiting for Key %q (Key Vault %q) to be deleted: %+v", id.Name, id.KeyVaultBaseUrl, err) + } + log.Printf("[DEBUG] Deleted Key %q (Key Vault %q).", id.Name, id.KeyVaultBaseUrl) + + shouldPurge := true // meta.(*clients.Client).Features.KeyVault.PurgeNestedItemsOnDestroy + if shouldPurge { + log.Printf("[DEBUG] Purging Key %q (Key Vault %q)..", id.Name, id.KeyVaultBaseUrl) + if _, err := client.PurgeDeletedKey(ctx, id.KeyVaultBaseUrl, id.Name); err != nil { + return fmt.Errorf("purging Key %q (Key Vault %q): %+v", id.Name, id.KeyVaultBaseUrl, err) + } + + log.Printf("[DEBUG] Waiting for Key %q (Key Vault %q) to finish purging..", id.Name, id.KeyVaultBaseUrl) + stateConf := &resource.StateChangeConf{ + Pending: []string{"InProgress"}, + Target: []string{"NotFound"}, + Refresh: func() (interface{}, string, error) { + key, err := client.GetDeletedKey(ctx, id.KeyVaultBaseUrl, id.Name) + if err != nil { + if utils.ResponseWasNotFound(key.Response) { + return key, "NotFound", nil + } + + return nil, "Error", err + } + + return key, "InProgress", nil + }, + ContinuousTargetOccurence: 3, + PollInterval: 5 * time.Second, + Timeout: d.Timeout(schema.TimeoutDelete), + } + if _, err := stateConf.WaitForState(); err != nil { + return fmt.Errorf("waiting for Key %q (Key Vault %q) to finish purging: %+v", id.Name, id.KeyVaultBaseUrl, err) + } + log.Printf("[DEBUG] Purged Key %q (Key Vault %q).", id.Name, id.KeyVaultBaseUrl) + } else { + log.Printf("[DEBUG] Skipping purging of Key %q (Key Vault %q)..", id.Name, id.KeyVaultBaseUrl) + } + + return nil } func expandKeyVaultKeyOptions(d *schema.ResourceData) *[]keyvault.JSONWebKeyOperation { diff --git a/azurerm/internal/services/keyvault/key_vault_secret_resource.go b/azurerm/internal/services/keyvault/key_vault_secret_resource.go index 1f65a3c3b75a..2cea643f3d39 100644 --- a/azurerm/internal/services/keyvault/key_vault_secret_resource.go +++ b/azurerm/internal/services/keyvault/key_vault_secret_resource.go @@ -364,8 +364,75 @@ func resourceArmKeyVaultSecretDelete(d *schema.ResourceData, meta interface{}) e return nil } - _, err = client.DeleteSecret(ctx, id.KeyVaultBaseUrl, id.Name) - return err + log.Printf("[DEBUG] Deleting Secret %q (Key Vault %q).", id.Name, id.KeyVaultBaseUrl) + if resp, err := client.DeleteSecret(ctx, id.KeyVaultBaseUrl, id.Name); err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return nil + } + + return fmt.Errorf("deleting Secret %q (Key Vault %q): %+v", id.Name, id.KeyVaultBaseUrl, err) + } + log.Printf("[DEBUG] Waiting for Secret %q (Key Vault %q) to finish deleting", id.Name, id.KeyVaultBaseUrl) + stateConf := &resource.StateChangeConf{ + Pending: []string{"InProgress"}, + Target: []string{"NotFound"}, + Refresh: func() (interface{}, string, error) { + key, err := client.GetSecret(ctx, id.KeyVaultBaseUrl, id.Name, "") + if err != nil { + if utils.ResponseWasNotFound(key.Response) { + return key, "NotFound", nil + } + + return nil, "Error", err + } + + return key, "InProgress", nil + }, + ContinuousTargetOccurence: 3, + PollInterval: 5 * time.Second, + Timeout: d.Timeout(schema.TimeoutDelete), + } + if _, err := stateConf.WaitForState(); err != nil { + return fmt.Errorf("waiting for Secret %q (Key Vault %q) to be deleted: %+v", id.Name, id.KeyVaultBaseUrl, err) + } + log.Printf("[DEBUG] Deleted Secret %q (Key Vault %q).", id.Name, id.KeyVaultBaseUrl) + + shouldPurge := true // meta.(*clients.Client).Features.KeyVault.PurgeNestedItemsOnDestroy + if shouldPurge { + log.Printf("[DEBUG] Purging Secret %q (Key Vault %q)..", id.Name, id.KeyVaultBaseUrl) + if _, err := client.PurgeDeletedSecret(ctx, id.KeyVaultBaseUrl, id.Name); err != nil { + return fmt.Errorf("purging Secret %q (Key Vault %q): %+v", id.Name, id.KeyVaultBaseUrl, err) + } + + log.Printf("[DEBUG] Waiting for Secret %q (Key Vault %q) to finish purging..", id.Name, id.KeyVaultBaseUrl) + stateConf := &resource.StateChangeConf{ + Pending: []string{"InProgress"}, + Target: []string{"NotFound"}, + Refresh: func() (interface{}, string, error) { + key, err := client.GetDeletedSecret(ctx, id.KeyVaultBaseUrl, id.Name) + if err != nil { + if utils.ResponseWasNotFound(key.Response) { + return key, "NotFound", nil + } + + return nil, "Error", err + } + + return key, "InProgress", nil + }, + ContinuousTargetOccurence: 3, + PollInterval: 5 * time.Second, + Timeout: d.Timeout(schema.TimeoutDelete), + } + if _, err := stateConf.WaitForState(); err != nil { + return fmt.Errorf("waiting for Secret %q (Key Vault %q) to finish purging: %+v", id.Name, id.KeyVaultBaseUrl, err) + } + log.Printf("[DEBUG] Purged Secret %q (Key Vault %q).", id.Name, id.KeyVaultBaseUrl) + } else { + log.Printf("[DEBUG] Skipping purging of Secret %q (Key Vault %q)..", id.Name, id.KeyVaultBaseUrl) + } + + return nil } func keyVaultChildItemRefreshFunc(secretUri string) resource.StateRefreshFunc { From 3fa852e454009beb1201478ea528523e6d4dc58f Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Thu, 17 Dec 2020 12:04:43 +0100 Subject: [PATCH 03/18] keyvault/nested-items: reusing the `purge_soft_delete_on_destroy` feature flag Whilst initially I was intending to use a separate `purge_nested_items_on_destroy` flag the "recover" feature flag is shared between the Key Vault and it's Nested Items - as such to mirror that behaviour I'm reusing that feature flag. --- .../internal/services/keyvault/internal.go | 121 ++++++++++++++++++ .../key_vault_certificate_resource.go | 94 +++++--------- .../keyvault/key_vault_key_resource.go | 96 +++++--------- .../keyvault/key_vault_secret_resource.go | 112 +++++----------- 4 files changed, 217 insertions(+), 206 deletions(-) create mode 100644 azurerm/internal/services/keyvault/internal.go diff --git a/azurerm/internal/services/keyvault/internal.go b/azurerm/internal/services/keyvault/internal.go new file mode 100644 index 000000000000..e72027c0007f --- /dev/null +++ b/azurerm/internal/services/keyvault/internal.go @@ -0,0 +1,121 @@ +package keyvault + +import ( + "context" + "fmt" + "log" + "net/http" + "time" + + "github.com/Azure/go-autorest/autorest" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +type deleteAndPurgeNestedItem interface { + DeleteNestedItem(ctx context.Context) (autorest.Response, error) + NestedItemHasBeenDeleted(ctx context.Context) (autorest.Response, error) + + PurgeNestedItem(ctx context.Context) (autorest.Response, error) + NestedItemHasBeenPurged(ctx context.Context) (autorest.Response, error) +} + +func deleteAndOptionallyPurge(ctx context.Context, description string, shouldPurge bool, helper deleteAndPurgeNestedItem) error { + timeout, ok := ctx.Deadline() + if !ok { + return fmt.Errorf("context is missing a timeout") + } + + log.Printf("[DEBUG] Deleting %s..", description) + if resp, err := helper.DeleteNestedItem(ctx); err != nil { + if utils.ResponseWasNotFound(resp) { + return nil + } + + return fmt.Errorf("deleting %s: %+v", description, err) + } + log.Printf("[DEBUG] Waiting for %s to finish deleting..", description) + stateConf := &resource.StateChangeConf{ + Pending: []string{"InProgress"}, + Target: []string{"NotFound"}, + Refresh: func() (interface{}, string, error) { + item, err := helper.NestedItemHasBeenDeleted(ctx) + if err != nil { + if utils.ResponseWasNotFound(item) { + return item, "NotFound", nil + } + + return nil, "Error", err + } + + return item, "InProgress", nil + }, + ContinuousTargetOccurence: 3, + PollInterval: 5 * time.Second, + Timeout: time.Until(timeout), + } + if _, err := stateConf.WaitForState(); err != nil { + return fmt.Errorf("waiting for %s to be deleted: %+v", description, err) + } + log.Printf("[DEBUG] Deleted %s.", description) + + if !shouldPurge { + log.Printf("[DEBUG] Skipping purging of %s as opted-out..", description) + return nil + } + + log.Printf("[DEBUG] Purging %s..", description) + if _, err := helper.PurgeNestedItem(ctx); err != nil { + return fmt.Errorf("purging %s: %+v", description, err) + } + + log.Printf("[DEBUG] Waiting for %s to finish purging..", description) + stateConf = &resource.StateChangeConf{ + Pending: []string{"InProgress"}, + Target: []string{"NotFound"}, + Refresh: func() (interface{}, string, error) { + item, err := helper.NestedItemHasBeenPurged(ctx) + if err != nil { + if utils.ResponseWasNotFound(item) { + return item, "NotFound", nil + } + + return nil, "Error", err + } + + return item, "InProgress", nil + }, + ContinuousTargetOccurence: 3, + PollInterval: 5 * time.Second, + Timeout: time.Until(timeout), + } + if _, err := stateConf.WaitForState(); err != nil { + return fmt.Errorf("waiting for %s to finish purging: %+v", description, err) + } + log.Printf("[DEBUG] Purged %s.", description) + + return nil +} + +func keyVaultChildItemRefreshFunc(secretUri string) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + log.Printf("[DEBUG] Checking to see if KeyVault Secret %q is available..", secretUri) + + PTransport := &http.Transport{Proxy: http.ProxyFromEnvironment} + + client := &http.Client{ + Transport: PTransport, + } + + conn, err := client.Get(secretUri) + if err != nil { + log.Printf("[DEBUG] Didn't find KeyVault secret at %q", secretUri) + return nil, "pending", fmt.Errorf("Error checking secret at %q: %s", secretUri, err) + } + + defer conn.Body.Close() + + log.Printf("[DEBUG] Found KeyVault Secret %q", secretUri) + return "available", "available", nil + } +} diff --git a/azurerm/internal/services/keyvault/key_vault_certificate_resource.go b/azurerm/internal/services/keyvault/key_vault_certificate_resource.go index 87602b57dd69..aa88afd98e16 100644 --- a/azurerm/internal/services/keyvault/key_vault_certificate_resource.go +++ b/azurerm/internal/services/keyvault/key_vault_certificate_resource.go @@ -12,6 +12,7 @@ import ( "time" "github.com/Azure/azure-sdk-for-go/services/keyvault/2016-10-01/keyvault" + "github.com/Azure/go-autorest/autorest" "github.com/hashicorp/terraform-plugin-sdk/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/helper/validation" @@ -602,76 +603,45 @@ func resourceArmKeyVaultCertificateDelete(d *schema.ResourceData, meta interface return nil } - log.Printf("[DEBUG] Deleting Certificate %q (Key Vault %q)..", id.Name, id.KeyVaultBaseUrl) - resp, err := client.DeleteCertificate(ctx, id.KeyVaultBaseUrl, id.Name) - if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - return nil - } - - return fmt.Errorf("deleting Certificate %q (Key Vault %q): %+v", id.Name, id.KeyVaultBaseUrl, err) + shouldPurge := meta.(*clients.Client).Features.KeyVault.PurgeSoftDeleteOnDestroy + description := fmt.Sprintf("Certificate %q (Key Vault %q)", id.Name, id.KeyVaultBaseUrl) + deleter := deleteAndPurgeCertificate{ + client: client, + keyVaultUri: id.KeyVaultBaseUrl, + name: id.Name, + } + if err := deleteAndOptionallyPurge(ctx, description, shouldPurge, deleter); err != nil { + return err } - log.Printf("[DEBUG] Waiting for Certificate %q (Key Vault %q) to finish deleting", id.Name, id.KeyVaultBaseUrl) - stateConf := &resource.StateChangeConf{ - Pending: []string{"InProgress"}, - Target: []string{"NotFound"}, - Refresh: func() (interface{}, string, error) { - key, err := client.GetCertificate(ctx, id.KeyVaultBaseUrl, id.Name, "") - if err != nil { - if utils.ResponseWasNotFound(key.Response) { - return key, "NotFound", nil - } - return nil, "Error", err - } + return nil +} - return key, "InProgress", nil - }, - ContinuousTargetOccurence: 3, - PollInterval: 5 * time.Second, - Timeout: d.Timeout(schema.TimeoutDelete), - } - if _, err := stateConf.WaitForState(); err != nil { - return fmt.Errorf("waiting for Certificate %q (Key Vault %q) to be deleted: %+v", id.Name, id.KeyVaultBaseUrl, err) - } - log.Printf("[DEBUG] Deleted Secret %q (Key Vault %q).", id.Name, id.KeyVaultBaseUrl) +var _ deleteAndPurgeNestedItem = deleteAndPurgeCertificate{} - shouldPurge := true // meta.(*clients.Client).Features.KeyVault.PurgeNestedItemsOnDestroy - if shouldPurge { - log.Printf("[DEBUG] Purging Certificate %q (Key Vault %q)..", id.Name, id.KeyVaultBaseUrl) - if _, err := client.PurgeDeletedCertificate(ctx, id.KeyVaultBaseUrl, id.Name); err != nil { - return fmt.Errorf("purging Certificate %q (Key Vault %q): %+v", id.Name, id.KeyVaultBaseUrl, err) - } +type deleteAndPurgeCertificate struct { + client *keyvault.BaseClient + keyVaultUri string + name string +} - log.Printf("[DEBUG] Waiting for Certificate %q (Key Vault %q) to finish purging..", id.Name, id.KeyVaultBaseUrl) - stateConf := &resource.StateChangeConf{ - Pending: []string{"InProgress"}, - Target: []string{"NotFound"}, - Refresh: func() (interface{}, string, error) { - key, err := client.GetDeletedCertificate(ctx, id.KeyVaultBaseUrl, id.Name) - if err != nil { - if utils.ResponseWasNotFound(key.Response) { - return key, "NotFound", nil - } +func (d deleteAndPurgeCertificate) DeleteNestedItem(ctx context.Context) (autorest.Response, error) { + resp, err := d.client.DeleteCertificate(ctx, d.keyVaultUri, d.name) + return resp.Response, err +} - return nil, "Error", err - } +func (d deleteAndPurgeCertificate) NestedItemHasBeenDeleted(ctx context.Context) (autorest.Response, error) { + resp, err := d.client.GetCertificate(ctx, d.keyVaultUri, d.name, "") + return resp.Response, err +} - return key, "InProgress", nil - }, - ContinuousTargetOccurence: 3, - PollInterval: 5 * time.Second, - Timeout: d.Timeout(schema.TimeoutDelete), - } - if _, err := stateConf.WaitForState(); err != nil { - return fmt.Errorf("waiting for Certificate %q (Key Vault %q) to finish purging: %+v", id.Name, id.KeyVaultBaseUrl, err) - } - log.Printf("[DEBUG] Purged Certificate %q (Key Vault %q).", id.Name, id.KeyVaultBaseUrl) - } else { - log.Printf("[DEBUG] Skipping purging of Certificate %q (Key Vault %q)..", id.Name, id.KeyVaultBaseUrl) - } +func (d deleteAndPurgeCertificate) PurgeNestedItem(ctx context.Context) (autorest.Response, error) { + return d.client.PurgeDeletedCertificate(ctx, d.keyVaultUri, d.name) +} - return nil +func (d deleteAndPurgeCertificate) NestedItemHasBeenPurged(ctx context.Context) (autorest.Response, error) { + resp, err := d.client.GetDeletedCertificate(ctx, d.keyVaultUri, d.name) + return resp.Response, err } func expandKeyVaultCertificatePolicy(d *schema.ResourceData) keyvault.CertificatePolicy { diff --git a/azurerm/internal/services/keyvault/key_vault_key_resource.go b/azurerm/internal/services/keyvault/key_vault_key_resource.go index c88593c5ed7d..64e18bb5b8c6 100644 --- a/azurerm/internal/services/keyvault/key_vault_key_resource.go +++ b/azurerm/internal/services/keyvault/key_vault_key_resource.go @@ -1,12 +1,14 @@ package keyvault import ( + "context" "encoding/base64" "fmt" "log" "time" "github.com/Azure/azure-sdk-for-go/services/keyvault/2016-10-01/keyvault" + "github.com/Azure/go-autorest/autorest" "github.com/Azure/go-autorest/autorest/date" "github.com/hashicorp/terraform-plugin-sdk/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" @@ -429,75 +431,45 @@ func resourceArmKeyVaultKeyDelete(d *schema.ResourceData, meta interface{}) erro return nil } - log.Printf("[DEBUG] Deleting Key %q (Key Vault %q)..", id.Name, id.KeyVaultBaseUrl) - if resp, err := client.DeleteKey(ctx, id.KeyVaultBaseUrl, id.Name); err != nil { - if utils.ResponseWasNotFound(resp.Response) { - return nil - } - - return fmt.Errorf("deleting Key %q (Key Vault %q): %+v", id.Name, id.KeyVaultBaseUrl, err) + shouldPurge := meta.(*clients.Client).Features.KeyVault.PurgeSoftDeleteOnDestroy + description := fmt.Sprintf("Key %q (Key Vault %q)", id.Name, id.KeyVaultBaseUrl) + deleter := deleteAndPurgeKey{ + client: client, + keyVaultUri: id.KeyVaultBaseUrl, + name: id.Name, + } + if err := deleteAndOptionallyPurge(ctx, description, shouldPurge, deleter); err != nil { + return err } - log.Printf("[DEBUG] Waiting for Key %q (Key Vault %q) to finish deleting", id.Name, id.KeyVaultBaseUrl) - stateConf := &resource.StateChangeConf{ - Pending: []string{"InProgress"}, - Target: []string{"NotFound"}, - Refresh: func() (interface{}, string, error) { - key, err := client.GetKey(ctx, id.KeyVaultBaseUrl, id.Name, "") - if err != nil { - if utils.ResponseWasNotFound(key.Response) { - return key, "NotFound", nil - } - return nil, "Error", err - } + return nil +} - return key, "InProgress", nil - }, - ContinuousTargetOccurence: 3, - PollInterval: 5 * time.Second, - Timeout: d.Timeout(schema.TimeoutDelete), - } - if _, err := stateConf.WaitForState(); err != nil { - return fmt.Errorf("waiting for Key %q (Key Vault %q) to be deleted: %+v", id.Name, id.KeyVaultBaseUrl, err) - } - log.Printf("[DEBUG] Deleted Key %q (Key Vault %q).", id.Name, id.KeyVaultBaseUrl) +var _ deleteAndPurgeNestedItem = deleteAndPurgeKey{} - shouldPurge := true // meta.(*clients.Client).Features.KeyVault.PurgeNestedItemsOnDestroy - if shouldPurge { - log.Printf("[DEBUG] Purging Key %q (Key Vault %q)..", id.Name, id.KeyVaultBaseUrl) - if _, err := client.PurgeDeletedKey(ctx, id.KeyVaultBaseUrl, id.Name); err != nil { - return fmt.Errorf("purging Key %q (Key Vault %q): %+v", id.Name, id.KeyVaultBaseUrl, err) - } +type deleteAndPurgeKey struct { + client *keyvault.BaseClient + keyVaultUri string + name string +} - log.Printf("[DEBUG] Waiting for Key %q (Key Vault %q) to finish purging..", id.Name, id.KeyVaultBaseUrl) - stateConf := &resource.StateChangeConf{ - Pending: []string{"InProgress"}, - Target: []string{"NotFound"}, - Refresh: func() (interface{}, string, error) { - key, err := client.GetDeletedKey(ctx, id.KeyVaultBaseUrl, id.Name) - if err != nil { - if utils.ResponseWasNotFound(key.Response) { - return key, "NotFound", nil - } - - return nil, "Error", err - } +func (d deleteAndPurgeKey) DeleteNestedItem(ctx context.Context) (autorest.Response, error) { + resp, err := d.client.DeleteKey(ctx, d.keyVaultUri, d.name) + return resp.Response, err +} - return key, "InProgress", nil - }, - ContinuousTargetOccurence: 3, - PollInterval: 5 * time.Second, - Timeout: d.Timeout(schema.TimeoutDelete), - } - if _, err := stateConf.WaitForState(); err != nil { - return fmt.Errorf("waiting for Key %q (Key Vault %q) to finish purging: %+v", id.Name, id.KeyVaultBaseUrl, err) - } - log.Printf("[DEBUG] Purged Key %q (Key Vault %q).", id.Name, id.KeyVaultBaseUrl) - } else { - log.Printf("[DEBUG] Skipping purging of Key %q (Key Vault %q)..", id.Name, id.KeyVaultBaseUrl) - } +func (d deleteAndPurgeKey) NestedItemHasBeenDeleted(ctx context.Context) (autorest.Response, error) { + resp, err := d.client.GetKey(ctx, d.keyVaultUri, d.name, "") + return resp.Response, err +} - return nil +func (d deleteAndPurgeKey) PurgeNestedItem(ctx context.Context) (autorest.Response, error) { + return d.client.PurgeDeletedKey(ctx, d.keyVaultUri, d.name) +} + +func (d deleteAndPurgeKey) NestedItemHasBeenPurged(ctx context.Context) (autorest.Response, error) { + resp, err := d.client.GetDeletedKey(ctx, d.keyVaultUri, d.name) + return resp.Response, err } func expandKeyVaultKeyOptions(d *schema.ResourceData) *[]keyvault.JSONWebKeyOperation { diff --git a/azurerm/internal/services/keyvault/key_vault_secret_resource.go b/azurerm/internal/services/keyvault/key_vault_secret_resource.go index 2cea643f3d39..9f5f21a639b6 100644 --- a/azurerm/internal/services/keyvault/key_vault_secret_resource.go +++ b/azurerm/internal/services/keyvault/key_vault_secret_resource.go @@ -1,12 +1,13 @@ package keyvault import ( + "context" "fmt" "log" - "net/http" "time" "github.com/Azure/azure-sdk-for-go/services/keyvault/2016-10-01/keyvault" + "github.com/Azure/go-autorest/autorest" "github.com/Azure/go-autorest/autorest/date" "github.com/hashicorp/terraform-plugin-sdk/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" @@ -364,96 +365,43 @@ func resourceArmKeyVaultSecretDelete(d *schema.ResourceData, meta interface{}) e return nil } - log.Printf("[DEBUG] Deleting Secret %q (Key Vault %q).", id.Name, id.KeyVaultBaseUrl) - if resp, err := client.DeleteSecret(ctx, id.KeyVaultBaseUrl, id.Name); err != nil { - if utils.ResponseWasNotFound(resp.Response) { - return nil - } - - return fmt.Errorf("deleting Secret %q (Key Vault %q): %+v", id.Name, id.KeyVaultBaseUrl, err) + shouldPurge := meta.(*clients.Client).Features.KeyVault.PurgeSoftDeleteOnDestroy + description := fmt.Sprintf("Secret %q (Key Vault %q)", id.Name, id.KeyVaultBaseUrl) + deleter := deleteAndPurgeSecret{ + client: client, + keyVaultUri: id.KeyVaultBaseUrl, + name: id.Name, } - log.Printf("[DEBUG] Waiting for Secret %q (Key Vault %q) to finish deleting", id.Name, id.KeyVaultBaseUrl) - stateConf := &resource.StateChangeConf{ - Pending: []string{"InProgress"}, - Target: []string{"NotFound"}, - Refresh: func() (interface{}, string, error) { - key, err := client.GetSecret(ctx, id.KeyVaultBaseUrl, id.Name, "") - if err != nil { - if utils.ResponseWasNotFound(key.Response) { - return key, "NotFound", nil - } - - return nil, "Error", err - } - - return key, "InProgress", nil - }, - ContinuousTargetOccurence: 3, - PollInterval: 5 * time.Second, - Timeout: d.Timeout(schema.TimeoutDelete), - } - if _, err := stateConf.WaitForState(); err != nil { - return fmt.Errorf("waiting for Secret %q (Key Vault %q) to be deleted: %+v", id.Name, id.KeyVaultBaseUrl, err) - } - log.Printf("[DEBUG] Deleted Secret %q (Key Vault %q).", id.Name, id.KeyVaultBaseUrl) - - shouldPurge := true // meta.(*clients.Client).Features.KeyVault.PurgeNestedItemsOnDestroy - if shouldPurge { - log.Printf("[DEBUG] Purging Secret %q (Key Vault %q)..", id.Name, id.KeyVaultBaseUrl) - if _, err := client.PurgeDeletedSecret(ctx, id.KeyVaultBaseUrl, id.Name); err != nil { - return fmt.Errorf("purging Secret %q (Key Vault %q): %+v", id.Name, id.KeyVaultBaseUrl, err) - } - - log.Printf("[DEBUG] Waiting for Secret %q (Key Vault %q) to finish purging..", id.Name, id.KeyVaultBaseUrl) - stateConf := &resource.StateChangeConf{ - Pending: []string{"InProgress"}, - Target: []string{"NotFound"}, - Refresh: func() (interface{}, string, error) { - key, err := client.GetDeletedSecret(ctx, id.KeyVaultBaseUrl, id.Name) - if err != nil { - if utils.ResponseWasNotFound(key.Response) { - return key, "NotFound", nil - } - - return nil, "Error", err - } - - return key, "InProgress", nil - }, - ContinuousTargetOccurence: 3, - PollInterval: 5 * time.Second, - Timeout: d.Timeout(schema.TimeoutDelete), - } - if _, err := stateConf.WaitForState(); err != nil { - return fmt.Errorf("waiting for Secret %q (Key Vault %q) to finish purging: %+v", id.Name, id.KeyVaultBaseUrl, err) - } - log.Printf("[DEBUG] Purged Secret %q (Key Vault %q).", id.Name, id.KeyVaultBaseUrl) - } else { - log.Printf("[DEBUG] Skipping purging of Secret %q (Key Vault %q)..", id.Name, id.KeyVaultBaseUrl) + if err := deleteAndOptionallyPurge(ctx, description, shouldPurge, deleter); err != nil { + return err } return nil } -func keyVaultChildItemRefreshFunc(secretUri string) resource.StateRefreshFunc { - return func() (interface{}, string, error) { - log.Printf("[DEBUG] Checking to see if KeyVault Secret %q is available..", secretUri) +var _ deleteAndPurgeNestedItem = deleteAndPurgeSecret{} - PTransport := &http.Transport{Proxy: http.ProxyFromEnvironment} +type deleteAndPurgeSecret struct { + client *keyvault.BaseClient + keyVaultUri string + name string +} - client := &http.Client{ - Transport: PTransport, - } +func (d deleteAndPurgeSecret) DeleteNestedItem(ctx context.Context) (autorest.Response, error) { + resp, err := d.client.DeleteSecret(ctx, d.keyVaultUri, d.name) + return resp.Response, err +} - conn, err := client.Get(secretUri) - if err != nil { - log.Printf("[DEBUG] Didn't find KeyVault secret at %q", secretUri) - return nil, "pending", fmt.Errorf("Error checking secret at %q: %s", secretUri, err) - } +func (d deleteAndPurgeSecret) NestedItemHasBeenDeleted(ctx context.Context) (autorest.Response, error) { + resp, err := d.client.GetSecret(ctx, d.keyVaultUri, d.name, "") + return resp.Response, err +} - defer conn.Body.Close() +func (d deleteAndPurgeSecret) PurgeNestedItem(ctx context.Context) (autorest.Response, error) { + return d.client.PurgeDeletedSecret(ctx, d.keyVaultUri, d.name) +} - log.Printf("[DEBUG] Found KeyVault Secret %q", secretUri) - return "available", "available", nil - } +func (d deleteAndPurgeSecret) NestedItemHasBeenPurged(ctx context.Context) (autorest.Response, error) { + resp, err := d.client.GetDeletedSecret(ctx, d.keyVaultUri, d.name) + return resp.Response, err } From b0ab5688748efd99e162b6be1aa21d2329ccaa59 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Thu, 17 Dec 2020 12:16:25 +0100 Subject: [PATCH 04/18] key-vault/nested-item: moving the wayward func --- .../internal/services/keyvault/internal.go | 23 +++++++++++++++++++ .../key_vault_certificate_issuer_resource.go | 2 +- .../key_vault_certificate_resource.go | 23 +------------------ .../keyvault/key_vault_key_resource.go | 2 +- .../keyvault/key_vault_secret_resource.go | 2 +- 5 files changed, 27 insertions(+), 25 deletions(-) diff --git a/azurerm/internal/services/keyvault/internal.go b/azurerm/internal/services/keyvault/internal.go index e72027c0007f..08bba13f4f73 100644 --- a/azurerm/internal/services/keyvault/internal.go +++ b/azurerm/internal/services/keyvault/internal.go @@ -9,6 +9,10 @@ import ( "github.com/Azure/go-autorest/autorest" "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) @@ -119,3 +123,22 @@ func keyVaultChildItemRefreshFunc(secretUri string) resource.StateRefreshFunc { return "available", "available", nil } } + +func nestedItemResourceImporter(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + client := meta.(*clients.Client).KeyVault.VaultsClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := azure.ParseKeyVaultChildID(d.Id()) + if err != nil { + return []*schema.ResourceData{d}, fmt.Errorf("parsing ID %q for Key Vault Child import: %v", d.Id(), err) + } + + keyVaultId, err := azure.GetKeyVaultIDFromBaseUrl(ctx, client, id.KeyVaultBaseUrl) + if err != nil { + return []*schema.ResourceData{d}, fmt.Errorf("retrieving the Resource ID the Key Vault at URL %q: %s", id.KeyVaultBaseUrl, err) + } + d.Set("key_vault_id", keyVaultId) + + return []*schema.ResourceData{d}, nil +} diff --git a/azurerm/internal/services/keyvault/key_vault_certificate_issuer_resource.go b/azurerm/internal/services/keyvault/key_vault_certificate_issuer_resource.go index 4f42e8a2141c..e65bb3eb3ee6 100644 --- a/azurerm/internal/services/keyvault/key_vault_certificate_issuer_resource.go +++ b/azurerm/internal/services/keyvault/key_vault_certificate_issuer_resource.go @@ -24,7 +24,7 @@ func resourceArmKeyVaultCertificateIssuer() *schema.Resource { Read: resourceArmKeyVaultCertificateIssuerRead, Delete: resourceArmKeyVaultCertificateIssuerDelete, Importer: &schema.ResourceImporter{ - State: resourceArmKeyVaultChildResourceImporter, + State: nestedItemResourceImporter, }, Timeouts: &schema.ResourceTimeout{ diff --git a/azurerm/internal/services/keyvault/key_vault_certificate_resource.go b/azurerm/internal/services/keyvault/key_vault_certificate_resource.go index aa88afd98e16..667c814fe252 100644 --- a/azurerm/internal/services/keyvault/key_vault_certificate_resource.go +++ b/azurerm/internal/services/keyvault/key_vault_certificate_resource.go @@ -25,27 +25,6 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) -// todo refactor and find a home for this wayward func -func resourceArmKeyVaultChildResourceImporter(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { - client := meta.(*clients.Client).KeyVault.VaultsClient - ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) - defer cancel() - - id, err := azure.ParseKeyVaultChildID(d.Id()) - if err != nil { - return []*schema.ResourceData{d}, fmt.Errorf("Error Unable to parse ID (%s) for Key Vault Child import: %v", d.Id(), err) - } - - kvid, err := azure.GetKeyVaultIDFromBaseUrl(ctx, client, id.KeyVaultBaseUrl) - if err != nil { - return []*schema.ResourceData{d}, fmt.Errorf("Error retrieving the Resource ID the Key Vault at URL %q: %s", id.KeyVaultBaseUrl, err) - } - - d.Set("key_vault_id", kvid) - - return []*schema.ResourceData{d}, nil -} - func resourceArmKeyVaultCertificate() *schema.Resource { return &schema.Resource{ // TODO: support Updating once we have more information about what can be updated @@ -54,7 +33,7 @@ func resourceArmKeyVaultCertificate() *schema.Resource { Delete: resourceArmKeyVaultCertificateDelete, Importer: &schema.ResourceImporter{ - State: resourceArmKeyVaultChildResourceImporter, + State: nestedItemResourceImporter, }, Timeouts: &schema.ResourceTimeout{ diff --git a/azurerm/internal/services/keyvault/key_vault_key_resource.go b/azurerm/internal/services/keyvault/key_vault_key_resource.go index 64e18bb5b8c6..00d2ea0eb5f6 100644 --- a/azurerm/internal/services/keyvault/key_vault_key_resource.go +++ b/azurerm/internal/services/keyvault/key_vault_key_resource.go @@ -28,7 +28,7 @@ func resourceArmKeyVaultKey() *schema.Resource { Update: resourceArmKeyVaultKeyUpdate, Delete: resourceArmKeyVaultKeyDelete, Importer: &schema.ResourceImporter{ - State: resourceArmKeyVaultChildResourceImporter, + State: nestedItemResourceImporter, }, Timeouts: &schema.ResourceTimeout{ diff --git a/azurerm/internal/services/keyvault/key_vault_secret_resource.go b/azurerm/internal/services/keyvault/key_vault_secret_resource.go index 9f5f21a639b6..e9439b74f7ef 100644 --- a/azurerm/internal/services/keyvault/key_vault_secret_resource.go +++ b/azurerm/internal/services/keyvault/key_vault_secret_resource.go @@ -27,7 +27,7 @@ func resourceArmKeyVaultSecret() *schema.Resource { Update: resourceArmKeyVaultSecretUpdate, Delete: resourceArmKeyVaultSecretDelete, Importer: &schema.ResourceImporter{ - State: resourceArmKeyVaultChildResourceImporter, + State: nestedItemResourceImporter, }, Timeouts: &schema.ResourceTimeout{ From b9c5ca4599f976c62f4aeaa85a25e029fd293198 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Thu, 17 Dec 2020 12:23:41 +0100 Subject: [PATCH 05/18] keyvault/nested-item: updating the docs --- .../r/key_vault_access_policy.html.markdown | 25 ++++++---------- .../r/key_vault_certificate.html.markdown | 30 ++++++------------- ...key_vault_certificate_issuer.html.markdown | 8 ++--- website/docs/r/key_vault_key.html.markdown | 26 ++++------------ website/docs/r/key_vault_secret.html.markdown | 28 ++++------------- 5 files changed, 33 insertions(+), 84 deletions(-) diff --git a/website/docs/r/key_vault_access_policy.html.markdown b/website/docs/r/key_vault_access_policy.html.markdown index fb9bcc1bcd16..ab946fdbe862 100644 --- a/website/docs/r/key_vault_access_policy.html.markdown +++ b/website/docs/r/key_vault_access_policy.html.markdown @@ -17,32 +17,25 @@ Manages a Key Vault Access Policy. ## Example Usage ```hcl +data "azurerm_client_config" "current" {} + resource "azurerm_resource_group" "example" { - name = "resourceGroup1" - location = azurerm_resource_group.example.location + name = "example-resources" + location = "West Europe" } resource "azurerm_key_vault" "example" { - name = "testvault" + name = "examplekeyvault" location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name - - sku_name = "standard" - - tenant_id = "22222222-2222-2222-2222-222222222222" - - enabled_for_disk_encryption = true - - tags = { - environment = "Production" - } + tenant_id = data.azurerm_client_config.current.tenant_id + sku_name = "premium" } resource "azurerm_key_vault_access_policy" "example" { key_vault_id = azurerm_key_vault.example.id - - tenant_id = "00000000-0000-0000-0000-000000000000" - object_id = "11111111-1111-1111-1111-111111111111" + tenant_id = data.azurerm_client_config.current.tenant_id + object_id = data.azurerm_client_config.current.object_id key_permissions = [ "get", diff --git a/website/docs/r/key_vault_certificate.html.markdown b/website/docs/r/key_vault_certificate.html.markdown index 586828e2a714..fa7c7886779e 100644 --- a/website/docs/r/key_vault_certificate.html.markdown +++ b/website/docs/r/key_vault_certificate.html.markdown @@ -16,21 +16,19 @@ Manages a Key Vault Certificate. ~> **Note:** this example assumed the PFX file is located in the same directory at `certificate-to-import.pfx`. ```hcl -data "azurerm_client_config" "current" { -} +data "azurerm_client_config" "current" {} resource "azurerm_resource_group" "example" { - name = "key-vault-certificate-example" + name = "example-resources" location = "West Europe" } resource "azurerm_key_vault" "example" { - name = "keyvaultcertexample" + name = "examplekeyvault" location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name tenant_id = data.azurerm_client_config.current.tenant_id - - sku_name = "standard" + sku_name = "premium" access_policy { tenant_id = data.azurerm_client_config.current.tenant_id @@ -81,10 +79,6 @@ resource "azurerm_key_vault" "example" { "set", ] } - - tags = { - environment = "Production" - } } resource "azurerm_key_vault_certificate" "example" { @@ -118,21 +112,19 @@ resource "azurerm_key_vault_certificate" "example" { ## Example Usage (Generating a new certificate) ```hcl -data "azurerm_client_config" "current" { -} +data "azurerm_client_config" "current" {} resource "azurerm_resource_group" "example" { - name = "key-vault-certificate-example" + name = "example-resources" location = "West Europe" } resource "azurerm_key_vault" "example" { - name = "keyvaultcertexample" + name = "examplekeyvault" location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name tenant_id = data.azurerm_client_config.current.tenant_id - - sku_name = "standard" + sku_name = "premium" access_policy { tenant_id = data.azurerm_client_config.current.tenant_id @@ -183,10 +175,6 @@ resource "azurerm_key_vault" "example" { "set", ] } - - tags = { - environment = "Production" - } } resource "azurerm_key_vault_certificate" "example" { @@ -356,5 +344,5 @@ The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/d Key Vault Certificates can be imported using the `resource id`, e.g. ```shell -terraform import azurerm_key_vault_certificate.examplehttps://example-keyvault.vault.azure.net/certificates/example/fdf067c93bbb4b22bff4d8b7a9a56217 +terraform import azurerm_key_vault_certificate.example https://example-keyvault.vault.azure.net/certificates/example/fdf067c93bbb4b22bff4d8b7a9a56217 ``` diff --git a/website/docs/r/key_vault_certificate_issuer.html.markdown b/website/docs/r/key_vault_certificate_issuer.html.markdown index 5c39755eb5fe..7b93d43be68c 100644 --- a/website/docs/r/key_vault_certificate_issuer.html.markdown +++ b/website/docs/r/key_vault_certificate_issuer.html.markdown @@ -13,15 +13,15 @@ Manages a Key Vault Certificate Issuer. ## Example Usage ```hcl +data "azurerm_client_config" "current" {} + resource "azurerm_resource_group" "example" { name = "example-resources" - location = "West US" + location = "West Europe" } -data "azurerm_client_config" "current" {} - resource "azurerm_key_vault" "example" { - name = "example-key-vault" + name = "examplekeyvault" location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name sku_name = "standard" diff --git a/website/docs/r/key_vault_key.html.markdown b/website/docs/r/key_vault_key.html.markdown index 31a2c1ad3219..e20e729c3861 100644 --- a/website/docs/r/key_vault_key.html.markdown +++ b/website/docs/r/key_vault_key.html.markdown @@ -14,29 +14,19 @@ Manages a Key Vault Key. ## Example Usage ```hcl -data "azurerm_client_config" "current" { -} +data "azurerm_client_config" "current" {} resource "azurerm_resource_group" "example" { - name = "my-resource-group" - location = "West US" -} - -resource "random_id" "server" { - keepers = { - ami_id = 1 - } - - byte_length = 8 + name = "example-resources" + location = "West Europe" } resource "azurerm_key_vault" "example" { - name = "keyvaultkeyexample" + name = "examplekeyvault" location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name tenant_id = data.azurerm_client_config.current.tenant_id - - sku_name = "premium" + sku_name = "premium" access_policy { tenant_id = data.azurerm_client_config.current.tenant_id @@ -51,10 +41,6 @@ resource "azurerm_key_vault" "example" { "set", ] } - - tags = { - environment = "Production" - } } resource "azurerm_key_vault_key" "generated" { @@ -123,5 +109,5 @@ The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/d Key Vault Key which is Enabled can be imported using the `resource id`, e.g. ```shell -terraform import azurerm_key_vault_key.examplehttps://example-keyvault.vault.azure.net/keys/example/fdf067c93bbb4b22bff4d8b7a9a56217 +terraform import azurerm_key_vault_key.example https://example-keyvault.vault.azure.net/keys/example/fdf067c93bbb4b22bff4d8b7a9a56217 ``` diff --git a/website/docs/r/key_vault_secret.html.markdown b/website/docs/r/key_vault_secret.html.markdown index 611827bd4d92..eee03ee6a05b 100644 --- a/website/docs/r/key_vault_secret.html.markdown +++ b/website/docs/r/key_vault_secret.html.markdown @@ -17,29 +17,19 @@ Manages a Key Vault Secret. ## Example Usage ```hcl -data "azurerm_client_config" "current" { -} +data "azurerm_client_config" "current" {} resource "azurerm_resource_group" "example" { - name = "my-resource-group" - location = "West US" -} - -resource "random_id" "server" { - keepers = { - ami_id = 1 - } - - byte_length = 8 + name = "example-resources" + location = "West Europe" } resource "azurerm_key_vault" "example" { - name = format("%s%s", "kv", random_id.server.hex) + name = "examplekeyvault" location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name tenant_id = data.azurerm_client_config.current.tenant_id - - sku_name = "premium" + sku_name = "premium" access_policy { tenant_id = data.azurerm_client_config.current.tenant_id @@ -56,20 +46,12 @@ resource "azurerm_key_vault" "example" { "delete", ] } - - tags = { - environment = "Production" - } } resource "azurerm_key_vault_secret" "example" { name = "secret-sauce" value = "szechuan" key_vault_id = azurerm_key_vault.example.id - - tags = { - environment = "Production" - } } ``` From 7ecfd90334569d9aacf7863fb1e4b6fcb4363ae9 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Thu, 17 Dec 2020 12:26:23 +0100 Subject: [PATCH 06/18] website: updating the features block --- website/docs/index.html.markdown | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/website/docs/index.html.markdown b/website/docs/index.html.markdown index 228acc03d310..e48ff4d60d39 100644 --- a/website/docs/index.html.markdown +++ b/website/docs/index.html.markdown @@ -169,13 +169,13 @@ The `features` block supports the following: The `key_vault` block supports the following: -* `recover_soft_deleted_key_vaults` - (Optional) Should the `azurerm_key_vault` resource recover a Key Vault which has previously been Soft Deleted? Defaults to `true`. +* `recover_soft_deleted_key_vaults` - (Optional) Should the `azurerm_key_vault`, `azurerm_key_vault_certificate`, `azurerm_key_vault_key` and `azurerm_key_vault_secret` resources recover a Soft-Deleted Key Vault/Item? Defaults to `true`. -* `purge_soft_delete_on_destroy` - (Optional) Should the `azurerm_key_vault` resource be permanently deleted (e.g. purged) when destroyed? Defaults to `true`. +~> **Note:** When recovering soft-deleted Key Vault items (Keys, Certificates, and Secrets) the Principal used by Terraform needs the `"recover"` permission. -~> **Note:** When purge protection is enabled, a key vault or an object in the deleted state cannot be purged until the retention period(90 days) has passed. +* `purge_soft_delete_on_destroy` - (Optional) Should the `azurerm_key_vault`, `azurerm_key_vault_certificate`, `azurerm_key_vault_key` and `azurerm_key_vault_secret` resources be permanently deleted (e.g. purged) when destroyed? Defaults to `true`. -~> **Note:** When recovering soft-deleted Key Vault items (Keys, Certificates, and Secrets) the Principal used by Terraform needs the `"recover"` permission. +~> **Note:** When purge protection is enabled, a key vault or an object in the deleted state cannot be purged until the retention period (7-90 days) has passed. --- From b124d42175e58b2e842aa0a5f99cc3a26c4b051e Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Thu, 17 Dec 2020 12:54:42 +0100 Subject: [PATCH 07/18] r/key_vault_certificate: adding a ForceNew This is implied since the resource doesn't support Update --- .../internal/services/keyvault/key_vault_certificate_resource.go | 1 + 1 file changed, 1 insertion(+) diff --git a/azurerm/internal/services/keyvault/key_vault_certificate_resource.go b/azurerm/internal/services/keyvault/key_vault_certificate_resource.go index 667c814fe252..38e83ea56e86 100644 --- a/azurerm/internal/services/keyvault/key_vault_certificate_resource.go +++ b/azurerm/internal/services/keyvault/key_vault_certificate_resource.go @@ -215,6 +215,7 @@ func resourceArmKeyVaultCertificate() *schema.Resource { "key_usage": { Type: schema.TypeList, Required: true, + ForceNew: true, Elem: &schema.Schema{ Type: schema.TypeString, ValidateFunc: validation.StringInSlice([]string{ From 14744b0bac52f800d70e1df6b42878bfa0b33bcb Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Thu, 17 Dec 2020 13:30:34 +0100 Subject: [PATCH 08/18] keyvault: quoting the ID to handle escape on shells --- website/docs/r/key_vault_certificate.html.markdown | 2 +- website/docs/r/key_vault_key.html.markdown | 2 +- website/docs/r/key_vault_secret.html.markdown | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/website/docs/r/key_vault_certificate.html.markdown b/website/docs/r/key_vault_certificate.html.markdown index fa7c7886779e..71593f3b4e9a 100644 --- a/website/docs/r/key_vault_certificate.html.markdown +++ b/website/docs/r/key_vault_certificate.html.markdown @@ -344,5 +344,5 @@ The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/d Key Vault Certificates can be imported using the `resource id`, e.g. ```shell -terraform import azurerm_key_vault_certificate.example https://example-keyvault.vault.azure.net/certificates/example/fdf067c93bbb4b22bff4d8b7a9a56217 +terraform import azurerm_key_vault_certificate.example "https://example-keyvault.vault.azure.net/certificates/example/fdf067c93bbb4b22bff4d8b7a9a56217" ``` diff --git a/website/docs/r/key_vault_key.html.markdown b/website/docs/r/key_vault_key.html.markdown index e20e729c3861..593e33ec442f 100644 --- a/website/docs/r/key_vault_key.html.markdown +++ b/website/docs/r/key_vault_key.html.markdown @@ -109,5 +109,5 @@ The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/d Key Vault Key which is Enabled can be imported using the `resource id`, e.g. ```shell -terraform import azurerm_key_vault_key.example https://example-keyvault.vault.azure.net/keys/example/fdf067c93bbb4b22bff4d8b7a9a56217 +terraform import azurerm_key_vault_key.example "https://example-keyvault.vault.azure.net/keys/example/fdf067c93bbb4b22bff4d8b7a9a56217" ``` diff --git a/website/docs/r/key_vault_secret.html.markdown b/website/docs/r/key_vault_secret.html.markdown index eee03ee6a05b..ba3da05eabb4 100644 --- a/website/docs/r/key_vault_secret.html.markdown +++ b/website/docs/r/key_vault_secret.html.markdown @@ -98,5 +98,5 @@ The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/d Key Vault Secrets which are Enabled can be imported using the `resource id`, e.g. ```shell -terraform import azurerm_key_vault_secret.example https://example-keyvault.vault.azure.net/secrets/example/fdf067c93bbb4b22bff4d8b7a9a56217 +terraform import azurerm_key_vault_secret.example "https://example-keyvault.vault.azure.net/secrets/example/fdf067c93bbb4b22bff4d8b7a9a56217" ``` From 6f6ca1f5de990c841928cb87ff8dddd108a05bb6 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Thu, 17 Dec 2020 13:38:32 +0100 Subject: [PATCH 09/18] r/key_vault_certificate: refactoring the tests to use a template where possible --- .../key_vault_certificate_resource_test.go | 389 +++--------------- 1 file changed, 68 insertions(+), 321 deletions(-) diff --git a/azurerm/internal/services/keyvault/key_vault_certificate_resource_test.go b/azurerm/internal/services/keyvault/key_vault_certificate_resource_test.go index 4a1dc680d747..2c329e78e600 100644 --- a/azurerm/internal/services/keyvault/key_vault_certificate_resource_test.go +++ b/azurerm/internal/services/keyvault/key_vault_certificate_resource_test.go @@ -407,46 +407,13 @@ func testCheckAzureRMKeyVaultCertificateDisappears(resourceName string) resource } func testAccAzureRMKeyVaultCertificate_basicImportPFX(data acceptance.TestData) string { + template := testAccAzureRMKeyVaultCertificate_template(data) return fmt.Sprintf(` provider "azurerm" { features {} } -data "azurerm_client_config" "current" { -} - -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_key_vault" "test" { - name = "acctestkeyvault%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" - - access_policy { - tenant_id = data.azurerm_client_config.current.tenant_id - object_id = data.azurerm_client_config.current.object_id - - certificate_permissions = [ - "delete", - "import", - "get", - ] - - key_permissions = [ - "create", - ] - - secret_permissions = [ - "set", - ] - } -} +%s resource "azurerm_key_vault_certificate" "test" { name = "acctestcert%s" @@ -474,7 +441,7 @@ resource "azurerm_key_vault_certificate" "test" { } } } -`, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString) +`, template, data.RandomString) } func testAccAzureRMKeyVaultCertificate_requiresImport(data acceptance.TestData) string { @@ -512,51 +479,13 @@ resource "azurerm_key_vault_certificate" "import" { } func testAccAzureRMKeyVaultCertificate_basicGenerate(data acceptance.TestData) string { + template := testAccAzureRMKeyVaultCertificate_template(data) return fmt.Sprintf(` provider "azurerm" { features {} } -data "azurerm_client_config" "current" { -} - -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_key_vault" "test" { - name = "acctestkeyvault%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" - - access_policy { - tenant_id = data.azurerm_client_config.current.tenant_id - object_id = data.azurerm_client_config.current.object_id - - certificate_permissions = [ - "create", - "delete", - "get", - "update", - ] - - key_permissions = [ - "create", - ] - - secret_permissions = [ - "set", - ] - - storage_permissions = [ - "set", - ] - } -} +%s resource "azurerm_key_vault_certificate" "test" { name = "acctestcert%s" @@ -603,55 +532,17 @@ resource "azurerm_key_vault_certificate" "test" { } } } -`, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString) +`, template, data.RandomString) } func testAccAzureRMKeyVaultCertificate_basicGenerateUnknownIssuer(data acceptance.TestData) string { + template := testAccAzureRMKeyVaultCertificate_template(data) return fmt.Sprintf(` provider "azurerm" { features {} } -data "azurerm_client_config" "current" { -} - -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_key_vault" "test" { - name = "acctestkeyvault%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" - - access_policy { - tenant_id = data.azurerm_client_config.current.tenant_id - object_id = data.azurerm_client_config.current.object_id - - certificate_permissions = [ - "create", - "delete", - "get", - "update", - ] - - key_permissions = [ - "create", - ] - - secret_permissions = [ - "set", - ] - - storage_permissions = [ - "set", - ] - } -} +%s resource "azurerm_key_vault_certificate" "test" { name = "acctestcert%s" @@ -698,55 +589,17 @@ resource "azurerm_key_vault_certificate" "test" { } } } -`, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString) +`, template, data.RandomString) } func testAccAzureRMKeyVaultCertificate_basicGenerateSans(data acceptance.TestData) string { + template := testAccAzureRMKeyVaultCertificate_template(data) return fmt.Sprintf(` provider "azurerm" { features {} } -data "azurerm_client_config" "current" { -} - -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_key_vault" "test" { - name = "acctestkeyvault%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" - - access_policy { - tenant_id = data.azurerm_client_config.current.tenant_id - object_id = data.azurerm_client_config.current.object_id - - certificate_permissions = [ - "create", - "delete", - "get", - "update", - ] - - key_permissions = [ - "create", - ] - - secret_permissions = [ - "set", - ] - - storage_permissions = [ - "set", - ] - } -} +%s resource "azurerm_key_vault_certificate" "test" { name = "acctestcert%s" @@ -800,51 +653,17 @@ resource "azurerm_key_vault_certificate" "test" { } } } -`, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString) +`, template, data.RandomString) } func testAccAzureRMKeyVaultCertificate_basicGenerateTags(data acceptance.TestData) string { + template := testAccAzureRMKeyVaultCertificate_template(data) return fmt.Sprintf(` provider "azurerm" { features {} } -data "azurerm_client_config" "current" { -} - -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_key_vault" "test" { - name = "acctestkeyvault%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" - - access_policy { - tenant_id = data.azurerm_client_config.current.tenant_id - object_id = data.azurerm_client_config.current.object_id - - certificate_permissions = [ - "create", - "delete", - "get", - "update", - ] - - key_permissions = [ - "create", - ] - - secret_permissions = [ - "set", - ] - } -} +%s resource "azurerm_key_vault_certificate" "test" { name = "acctestcert%s" @@ -895,55 +714,17 @@ resource "azurerm_key_vault_certificate" "test" { "hello" = "world" } } -`, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString) +`, template, data.RandomString) } func testAccAzureRMKeyVaultCertificate_basicExtendedKeyUsage(data acceptance.TestData) string { + template := testAccAzureRMKeyVaultCertificate_template(data) return fmt.Sprintf(` provider "azurerm" { features {} } -data "azurerm_client_config" "current" { -} - -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_key_vault" "test" { - name = "acctestkeyvault%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" - - access_policy { - tenant_id = data.azurerm_client_config.current.tenant_id - object_id = data.azurerm_client_config.current.object_id - - certificate_permissions = [ - "create", - "delete", - "get", - "update", - ] - - key_permissions = [ - "create", - ] - - secret_permissions = [ - "set", - ] - - storage_permissions = [ - "set", - ] - } -} +%s resource "azurerm_key_vault_certificate" "test" { name = "acctestcert%s" @@ -996,55 +777,17 @@ resource "azurerm_key_vault_certificate" "test" { } } } -`, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString) +`, template, data.RandomString) } func testAccAzureRMKeyVaultCertificate_emptyExtendedKeyUsage(data acceptance.TestData) string { + template := testAccAzureRMKeyVaultCertificate_template(data) return fmt.Sprintf(` provider "azurerm" { features {} } -data "azurerm_client_config" "current" { -} - -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_key_vault" "test" { - name = "acctestkeyvault%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" - - access_policy { - tenant_id = data.azurerm_client_config.current.tenant_id - object_id = data.azurerm_client_config.current.object_id - - certificate_permissions = [ - "create", - "delete", - "get", - "update", - ] - - key_permissions = [ - "create", - ] - - secret_permissions = [ - "set", - ] - - storage_permissions = [ - "set", - ] - } -} +%s resource "azurerm_key_vault_certificate" "test" { name = "acctestcert%s" @@ -1093,10 +836,11 @@ resource "azurerm_key_vault_certificate" "test" { } } } -`, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString) +`, template, data.RandomString) } func testAccAzureRMKeyVaultCertificate_softDeleteRecovery(data acceptance.TestData, purge bool) string { + template := testAccAzureRMKeyVaultCertificate_template(data) return fmt.Sprintf(` provider "azurerm" { features { @@ -1107,48 +851,7 @@ provider "azurerm" { } } -data "azurerm_client_config" "current" { -} - -resource "azurerm_resource_group" "test" { - name = "acctestRG-kvc-%d" - location = "%s" -} - -resource "azurerm_key_vault" "test" { - name = "acctestkeyvault%s" - location = azurerm_resource_group.test.location - resource_group_name = azurerm_resource_group.test.name - tenant_id = data.azurerm_client_config.current.tenant_id - soft_delete_enabled = true - - sku_name = "standard" - - access_policy { - tenant_id = data.azurerm_client_config.current.tenant_id - object_id = data.azurerm_client_config.current.object_id - - certificate_permissions = [ - "create", - "delete", - "get", - "recover", - "update", - ] - - key_permissions = [ - "create", - ] - - secret_permissions = [ - "set", - ] - - storage_permissions = [ - "set", - ] - } -} +%s resource "azurerm_key_vault_certificate" "test" { name = "acctestcert%s" @@ -1195,7 +898,7 @@ resource "azurerm_key_vault_certificate" "test" { } } } -`, purge, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString) +`, purge, template, data.RandomString) } func testAccAzureRMKeyVaultCertificate_withExternalAccessPolicy(data acceptance.TestData) string { @@ -1393,3 +1096,47 @@ resource "azurerm_key_vault_certificate" "test" { } `, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString) } + +func testAccAzureRMKeyVaultCertificate_template(data acceptance.TestData) string { + return fmt.Sprintf(` +data "azurerm_client_config" "current" {} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_key_vault" "test" { + name = "acctestkeyvault%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" + + access_policy { + tenant_id = data.azurerm_client_config.current.tenant_id + object_id = data.azurerm_client_config.current.object_id + + certificate_permissions = [ + "create", + "delete", + "get", + "update", + ] + + key_permissions = [ + "create", + ] + + secret_permissions = [ + "set", + ] + + storage_permissions = [ + "set", + ] + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomString) +} From f36f5ade9253a20acdc23a7c4d704cbfd9bcc864 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Thu, 17 Dec 2020 13:39:27 +0100 Subject: [PATCH 10/18] r/key_vault_certificate: adding the purge permission to the tests --- .../services/keyvault/key_vault_certificate_resource_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/azurerm/internal/services/keyvault/key_vault_certificate_resource_test.go b/azurerm/internal/services/keyvault/key_vault_certificate_resource_test.go index 2c329e78e600..4cb27313d8ed 100644 --- a/azurerm/internal/services/keyvault/key_vault_certificate_resource_test.go +++ b/azurerm/internal/services/keyvault/key_vault_certificate_resource_test.go @@ -933,6 +933,7 @@ resource "azurerm_key_vault_access_policy" "test" { "create", "delete", "get", + "purge", "update", ] @@ -1032,6 +1033,7 @@ resource "azurerm_key_vault_access_policy" "test" { "delete", "get", "recover", + "purge", "update", ] @@ -1122,6 +1124,7 @@ resource "azurerm_key_vault" "test" { "create", "delete", "get", + "purge", "update", ] From 0ef6fcf58721edc26ca77d93d6cabfe319919ca4 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Thu, 17 Dec 2020 13:39:56 +0100 Subject: [PATCH 11/18] r/key_vault_certificate: and to the docs --- website/docs/r/key_vault_certificate.html.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/website/docs/r/key_vault_certificate.html.markdown b/website/docs/r/key_vault_certificate.html.markdown index 71593f3b4e9a..9151e8ee962a 100644 --- a/website/docs/r/key_vault_certificate.html.markdown +++ b/website/docs/r/key_vault_certificate.html.markdown @@ -141,6 +141,7 @@ resource "azurerm_key_vault" "example" { "listissuers", "managecontacts", "manageissuers", + "purge", "setissuers", "update", ] From ca034e3f6622c4494f4d18446c91e01636e380a2 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Thu, 17 Dec 2020 13:46:55 +0100 Subject: [PATCH 12/18] r/key_vault_certificate: enabling soft-delete for the tests by default --- .../key_vault_certificate_resource_test.go | 41 ++++++++++--------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/azurerm/internal/services/keyvault/key_vault_certificate_resource_test.go b/azurerm/internal/services/keyvault/key_vault_certificate_resource_test.go index 4cb27313d8ed..b49dad1ab599 100644 --- a/azurerm/internal/services/keyvault/key_vault_certificate_resource_test.go +++ b/azurerm/internal/services/keyvault/key_vault_certificate_resource_test.go @@ -916,13 +916,13 @@ resource "azurerm_resource_group" "test" { } resource "azurerm_key_vault" "test" { - name = "acctestkeyvault%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" - + name = "acctestkeyvault%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 + soft_delete_retention_days = 7 } resource "azurerm_key_vault_access_policy" "test" { @@ -1014,13 +1014,13 @@ resource "azurerm_resource_group" "test" { } resource "azurerm_key_vault" "test" { - name = "acctestkeyvault%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" - + name = "acctestkeyvault%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 + soft_delete_retention_days = 7 } resource "azurerm_key_vault_access_policy" "test" { @@ -1109,12 +1109,13 @@ resource "azurerm_resource_group" "test" { } resource "azurerm_key_vault" "test" { - name = "acctestkeyvault%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" + name = "acctestkeyvault%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 + soft_delete_retention_days = 7 access_policy { tenant_id = data.azurerm_client_config.current.tenant_id From 31df6de60a65dde4798d7b4f79703ab7821dc00e Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Thu, 17 Dec 2020 13:49:47 +0100 Subject: [PATCH 13/18] r/key_vault_certificate: adding soft delete to the example --- website/docs/r/key_vault_certificate.html.markdown | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/website/docs/r/key_vault_certificate.html.markdown b/website/docs/r/key_vault_certificate.html.markdown index 9151e8ee962a..2275fcd92d5b 100644 --- a/website/docs/r/key_vault_certificate.html.markdown +++ b/website/docs/r/key_vault_certificate.html.markdown @@ -120,11 +120,13 @@ resource "azurerm_resource_group" "example" { } resource "azurerm_key_vault" "example" { - name = "examplekeyvault" - location = azurerm_resource_group.example.location - resource_group_name = azurerm_resource_group.example.name - tenant_id = data.azurerm_client_config.current.tenant_id - sku_name = "premium" + name = "examplekeyvault" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + tenant_id = data.azurerm_client_config.current.tenant_id + sku_name = "standard" + soft_delete_enabled = true + soft_delete_retention_days = 7 access_policy { tenant_id = data.azurerm_client_config.current.tenant_id From cd42a1d9a5dbdf4a0c4e59bda955a58d2472483e Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Thu, 17 Dec 2020 13:54:37 +0100 Subject: [PATCH 14/18] keyvault/key & secret: updating the examples --- website/docs/r/key_vault_key.html.markdown | 14 +++++++++----- website/docs/r/key_vault_secret.html.markdown | 14 +++++++++----- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/website/docs/r/key_vault_key.html.markdown b/website/docs/r/key_vault_key.html.markdown index 593e33ec442f..f576130f819f 100644 --- a/website/docs/r/key_vault_key.html.markdown +++ b/website/docs/r/key_vault_key.html.markdown @@ -22,11 +22,13 @@ resource "azurerm_resource_group" "example" { } resource "azurerm_key_vault" "example" { - name = "examplekeyvault" - location = azurerm_resource_group.example.location - resource_group_name = azurerm_resource_group.example.name - tenant_id = data.azurerm_client_config.current.tenant_id - sku_name = "premium" + name = "examplekeyvault" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + tenant_id = data.azurerm_client_config.current.tenant_id + sku_name = "premium" + soft_delete_enabled = true + soft_delete_retention_days = 7 access_policy { tenant_id = data.azurerm_client_config.current.tenant_id @@ -35,6 +37,8 @@ resource "azurerm_key_vault" "example" { key_permissions = [ "create", "get", + "purge", + "recover" ] secret_permissions = [ diff --git a/website/docs/r/key_vault_secret.html.markdown b/website/docs/r/key_vault_secret.html.markdown index ba3da05eabb4..2422040b9131 100644 --- a/website/docs/r/key_vault_secret.html.markdown +++ b/website/docs/r/key_vault_secret.html.markdown @@ -25,11 +25,13 @@ resource "azurerm_resource_group" "example" { } resource "azurerm_key_vault" "example" { - name = "examplekeyvault" - location = azurerm_resource_group.example.location - resource_group_name = azurerm_resource_group.example.name - tenant_id = data.azurerm_client_config.current.tenant_id - sku_name = "premium" + name = "examplekeyvault" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + tenant_id = data.azurerm_client_config.current.tenant_id + sku_name = "premium" + soft_delete_enabled = true + soft_delete_retention_days = 7 access_policy { tenant_id = data.azurerm_client_config.current.tenant_id @@ -44,6 +46,8 @@ resource "azurerm_key_vault" "example" { "set", "get", "delete", + "purge", + "recover" ] } } From 22e62fe0105499366b9f1f21ec2fee47c2d87008 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Thu, 17 Dec 2020 14:07:55 +0100 Subject: [PATCH 15/18] r/key_vault_key & secret: updating the tests to use templates & enable soft-delete --- .../keyvault/key_vault_key_resource_test.go | 450 ++++-------------- .../key_vault_secret_resource_test.go | 349 +++++--------- 2 files changed, 203 insertions(+), 596 deletions(-) diff --git a/azurerm/internal/services/keyvault/key_vault_key_resource_test.go b/azurerm/internal/services/keyvault/key_vault_key_resource_test.go index 0bdfcc0a7a2d..cb7b3b0e1c50 100644 --- a/azurerm/internal/services/keyvault/key_vault_key_resource_test.go +++ b/azurerm/internal/services/keyvault/key_vault_key_resource_test.go @@ -495,49 +495,13 @@ func testCheckAzureRMKeyVaultKeyDisappears(resourceName string) resource.TestChe } func testAccAzureRMKeyVaultKey_basicEC(data acceptance.TestData) string { + template := testAccAzureRMKeyVaultKey_template(data) return fmt.Sprintf(` provider "azurerm" { features {} } -data "azurerm_client_config" "current" { -} - -resource "azurerm_resource_group" "test" { - name = "acctestRG-%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 = "premium" - - access_policy { - tenant_id = data.azurerm_client_config.current.tenant_id - object_id = data.azurerm_client_config.current.object_id - - key_permissions = [ - "create", - "delete", - "get", - "update", - ] - - secret_permissions = [ - "get", - "delete", - "set", - ] - } - - tags = { - environment = "Production" - } -} +%s resource "azurerm_key_vault_key" "test" { name = "key-%s" @@ -550,53 +514,17 @@ resource "azurerm_key_vault_key" "test" { "verify", ] } -`, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString) +`, template, data.RandomString) } func testAccAzureRMKeyVaultKey_basicECUpdatedExternally(data acceptance.TestData) string { + template := testAccAzureRMKeyVaultKey_template(data) return fmt.Sprintf(` provider "azurerm" { features {} } -data "azurerm_client_config" "current" { -} - -resource "azurerm_resource_group" "test" { - name = "acctestRG-%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 = "premium" - - access_policy { - tenant_id = data.azurerm_client_config.current.tenant_id - object_id = data.azurerm_client_config.current.object_id - - key_permissions = [ - "create", - "delete", - "get", - "update", - ] - - secret_permissions = [ - "get", - "delete", - "set", - ] - } - - tags = { - environment = "Production" - } -} +%s resource "azurerm_key_vault_key" "test" { name = "key-%s" @@ -614,7 +542,7 @@ resource "azurerm_key_vault_key" "test" { Rick = "Morty" } } -`, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString) +`, template, data.RandomString) } func testAccAzureRMKeyVaultKey_requiresImport(data acceptance.TestData) string { @@ -637,49 +565,13 @@ resource "azurerm_key_vault_key" "import" { } func testAccAzureRMKeyVaultKey_basicRSA(data acceptance.TestData) string { + template := testAccAzureRMKeyVaultKey_template(data) return fmt.Sprintf(` provider "azurerm" { features {} } -data "azurerm_client_config" "current" { -} - -resource "azurerm_resource_group" "test" { - name = "acctestRG-%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 = "premium" - - access_policy { - tenant_id = data.azurerm_client_config.current.tenant_id - object_id = data.azurerm_client_config.current.object_id - - key_permissions = [ - "create", - "delete", - "get", - "update", - ] - - secret_permissions = [ - "get", - "delete", - "set", - ] - } - - tags = { - environment = "Production" - } -} +%s resource "azurerm_key_vault_key" "test" { name = "key-%s" @@ -696,52 +588,17 @@ resource "azurerm_key_vault_key" "test" { "wrapKey", ] } -`, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString) +`, template, data.RandomString) } func testAccAzureRMKeyVaultKey_basicRSAHSM(data acceptance.TestData) string { + template := testAccAzureRMKeyVaultKey_template(data) return fmt.Sprintf(` provider "azurerm" { features {} } -data "azurerm_client_config" "current" { -} - -resource "azurerm_resource_group" "test" { - name = "acctestRG-%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 = "premium" - - access_policy { - tenant_id = data.azurerm_client_config.current.tenant_id - object_id = data.azurerm_client_config.current.object_id - - key_permissions = [ - "create", - "delete", - "get", - ] - - secret_permissions = [ - "get", - "delete", - "set", - ] - } - - tags = { - environment = "Production" - } -} +%s resource "azurerm_key_vault_key" "test" { name = "key-%s" @@ -758,52 +615,17 @@ resource "azurerm_key_vault_key" "test" { "wrapKey", ] } -`, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString) +`, template, data.RandomString) } func testAccAzureRMKeyVaultKey_complete(data acceptance.TestData) string { + template := testAccAzureRMKeyVaultKey_template(data) return fmt.Sprintf(` provider "azurerm" { features {} } -data "azurerm_client_config" "current" { -} - -resource "azurerm_resource_group" "test" { - name = "acctestRG-%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 = "premium" - - access_policy { - tenant_id = data.azurerm_client_config.current.tenant_id - object_id = data.azurerm_client_config.current.object_id - - key_permissions = [ - "create", - "delete", - "get", - ] - - secret_permissions = [ - "get", - "delete", - "set", - ] - } - - tags = { - environment = "Production" - } -} +%s resource "azurerm_key_vault_key" "test" { name = "key-%s" @@ -826,53 +648,17 @@ resource "azurerm_key_vault_key" "test" { "hello" = "world" } } -`, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString) +`, template, data.RandomString) } func testAccAzureRMKeyVaultKey_basicUpdated(data acceptance.TestData) string { + template := testAccAzureRMKeyVaultKey_template(data) return fmt.Sprintf(` provider "azurerm" { features {} } -data "azurerm_client_config" "current" { -} - -resource "azurerm_resource_group" "test" { - name = "acctestRG-%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 = "premium" - - access_policy { - tenant_id = data.azurerm_client_config.current.tenant_id - object_id = data.azurerm_client_config.current.object_id - - key_permissions = [ - "create", - "delete", - "get", - "update", - ] - - secret_permissions = [ - "get", - "delete", - "set", - ] - } - - tags = { - environment = "Production" - } -} +%s resource "azurerm_key_vault_key" "test" { name = "key-%s" @@ -888,52 +674,17 @@ resource "azurerm_key_vault_key" "test" { "wrapKey", ] } -`, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString) +`, template, data.RandomString) } func testAccAzureRMKeyVaultKey_curveEC(data acceptance.TestData) string { + template := testAccAzureRMKeyVaultKey_template(data) return fmt.Sprintf(` provider "azurerm" { features {} } -data "azurerm_client_config" "current" { -} - -resource "azurerm_resource_group" "test" { - name = "acctestRG-%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 = "premium" - - access_policy { - tenant_id = data.azurerm_client_config.current.tenant_id - object_id = data.azurerm_client_config.current.object_id - - key_permissions = [ - "create", - "delete", - "get", - ] - - secret_permissions = [ - "get", - "delete", - "set", - ] - } - - tags = { - environment = "Production" - } -} +%s resource "azurerm_key_vault_key" "test" { name = "key-%s" @@ -946,52 +697,17 @@ resource "azurerm_key_vault_key" "test" { "verify", ] } -`, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString) +`, template, data.RandomString) } func testAccAzureRMKeyVaultKey_basicECHSM(data acceptance.TestData) string { + template := testAccAzureRMKeyVaultKey_template(data) return fmt.Sprintf(` provider "azurerm" { features {} } -data "azurerm_client_config" "current" { -} - -resource "azurerm_resource_group" "test" { - name = "acctestRG-%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 = "premium" - - access_policy { - tenant_id = data.azurerm_client_config.current.tenant_id - object_id = data.azurerm_client_config.current.object_id - - key_permissions = [ - "create", - "delete", - "get", - ] - - secret_permissions = [ - "get", - "delete", - "set", - ] - } - - tags = { - environment = "Production" - } -} +%s resource "azurerm_key_vault_key" "test" { name = "key-%s" @@ -1004,10 +720,11 @@ resource "azurerm_key_vault_key" "test" { "verify", ] } -`, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString) +`, template, data.RandomString) } func testAccAzureRMKeyVaultKey_softDeleteRecovery(data acceptance.TestData, purge bool) string { + template := testAccAzureRMKeyVaultKey_template(data) return fmt.Sprintf(` provider "azurerm" { features { @@ -1018,45 +735,7 @@ provider "azurerm" { } } -data "azurerm_client_config" "current" { -} - -resource "azurerm_resource_group" "test" { - name = "acctestRG-kvk-%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 - soft_delete_enabled = true - - sku_name = "premium" - - access_policy { - tenant_id = data.azurerm_client_config.current.tenant_id - object_id = data.azurerm_client_config.current.object_id - - key_permissions = [ - "create", - "recover", - "delete", - "get", - ] - - secret_permissions = [ - "get", - "delete", - "set", - ] - } - - tags = { - environment = "Production" - } -} +%s resource "azurerm_key_vault_key" "test" { name = "key-%s" @@ -1079,7 +758,7 @@ resource "azurerm_key_vault_key" "test" { "hello" = "world" } } -`, purge, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString) +`, purge, template, data.RandomString) } func testAccAzureRMKeyVaultKey_withExternalAccessPolicy(data acceptance.TestData) string { @@ -1097,12 +776,13 @@ resource "azurerm_resource_group" "test" { } 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 = "premium" + 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 = "premium" + soft_delete_enabled = true + soft_delete_retention_days = 7 tags = { environment = "accTest" @@ -1118,6 +798,8 @@ resource "azurerm_key_vault_access_policy" "test" { "create", "delete", "get", + "purge", + "recover", "update", ] @@ -1159,12 +841,13 @@ resource "azurerm_resource_group" "test" { } 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 = "premium" + 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 = "premium" + soft_delete_enabled = true + soft_delete_retention_days = 7 tags = { environment = "accTest" @@ -1181,6 +864,8 @@ resource "azurerm_key_vault_access_policy" "test" { "delete", "encrypt", "get", + "purge", + "recover", "update", ] @@ -1206,3 +891,48 @@ resource "azurerm_key_vault_key" "test" { } `, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString) } + +func testAccAzureRMKeyVaultKey_template(data acceptance.TestData) string { + return fmt.Sprintf(` +data "azurerm_client_config" "current" {} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%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 = "premium" + 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 = [ + "create", + "delete", + "get", + "purge", + "recover", + "update", + ] + + secret_permissions = [ + "get", + "delete", + "set", + ] + } + + tags = { + environment = "Production" + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomString) +} diff --git a/azurerm/internal/services/keyvault/key_vault_secret_resource_test.go b/azurerm/internal/services/keyvault/key_vault_secret_resource_test.go index 32c91779b170..a210bc994614 100644 --- a/azurerm/internal/services/keyvault/key_vault_secret_resource_test.go +++ b/azurerm/internal/services/keyvault/key_vault_secret_resource_test.go @@ -395,53 +395,117 @@ func updateKeyVaultSecretValue(resourceName, value string) resource.TestCheckFun } func testAccAzureRMKeyVaultSecret_basic(data acceptance.TestData) string { + template := testAccAzureRMKeyVaultSecret_template(data) return fmt.Sprintf(` provider "azurerm" { features {} } -data "azurerm_client_config" "current" { +%s + +resource "azurerm_key_vault_secret" "test" { + name = "secret-%s" + value = "rick-and-morty" + key_vault_id = azurerm_key_vault.test.id +} +`, template, data.RandomString) } -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" +func testAccAzureRMKeyVaultSecret_updateTags(data acceptance.TestData) string { + template := testAccAzureRMKeyVaultSecret_template(data) + return fmt.Sprintf(` +provider "azurerm" { + features {} } -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 +%s - sku_name = "premium" +resource "azurerm_key_vault_secret" "test" { + name = "secret-%s" + value = "mad-scientist" + key_vault_id = azurerm_key_vault.test.id - access_policy { - tenant_id = data.azurerm_client_config.current.tenant_id - object_id = data.azurerm_client_config.current.object_id + tags = { + Rick = "Morty" + } +} +`, template, data.RandomString) +} - key_permissions = [ - "get", - ] +func testAccAzureRMKeyVaultSecret_requiresImport(data acceptance.TestData) string { + template := testAccAzureRMKeyVaultSecret_basic(data) + return fmt.Sprintf(` +%s - secret_permissions = [ - "get", - "delete", - "set", - ] - } +resource "azurerm_key_vault_secret" "import" { + name = azurerm_key_vault_secret.test.name + value = azurerm_key_vault_secret.test.value + key_vault_id = azurerm_key_vault_secret.test.key_vault_id +} +`, template) +} + +func testAccAzureRMKeyVaultSecret_complete(data acceptance.TestData) string { + template := testAccAzureRMKeyVaultSecret_template(data) + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +%s + +resource "azurerm_key_vault_secret" "test" { + name = "secret-%s" + value = "" + key_vault_id = azurerm_key_vault.test.id + content_type = "application/xml" + not_before_date = "2019-01-01T01:02:03Z" + expiration_date = "2020-01-01T01:02:03Z" tags = { - environment = "Production" + "hello" = "world" } } +`, template, data.RandomString) +} + +func testAccAzureRMKeyVaultSecret_basicUpdated(data acceptance.TestData) string { + template := testAccAzureRMKeyVaultSecret_template(data) + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +%s + +resource "azurerm_key_vault_secret" "test" { + name = "secret-%s" + value = "szechuan" + key_vault_id = azurerm_key_vault.test.id +} +`, template, data.RandomString) +} + +func testAccAzureRMKeyVaultSecret_softDeleteRecovery(data acceptance.TestData, purge bool) string { + template := testAccAzureRMKeyVaultSecret_template(data) + return fmt.Sprintf(` +provider "azurerm" { + features { + key_vault { + purge_soft_delete_on_destroy = "%t" + recover_soft_deleted_key_vaults = true + } + } +} + +%s resource "azurerm_key_vault_secret" "test" { name = "secret-%s" value = "rick-and-morty" key_vault_id = azurerm_key_vault.test.id } -`, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString) +`, purge, template, data.RandomString) } func testAccAzureRMKeyVaultSecret_withExternalAccessPolicy(data acceptance.TestData) string { @@ -459,12 +523,13 @@ resource "azurerm_resource_group" "test" { } 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 = "premium" + 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 = "premium" + soft_delete_enabled = true + soft_delete_retention_days = 7 tags = { environment = "Production" @@ -510,12 +575,13 @@ resource "azurerm_resource_group" "test" { } 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 = "premium" + 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 = "premium" + soft_delete_enabled = true + soft_delete_retention_days = 7 tags = { environment = "Production" @@ -547,81 +613,9 @@ resource "azurerm_key_vault_secret" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString) } -func testAccAzureRMKeyVaultSecret_updateTags(data acceptance.TestData) string { - return fmt.Sprintf(` -provider "azurerm" { - features {} -} - -data "azurerm_client_config" "current" { -} - -resource "azurerm_resource_group" "test" { - name = "acctestRG-%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 = "premium" - - access_policy { - tenant_id = data.azurerm_client_config.current.tenant_id - object_id = data.azurerm_client_config.current.object_id - - key_permissions = [ - "get", - ] - - secret_permissions = [ - "get", - "delete", - "set", - ] - } - - tags = { - environment = "Production" - } -} - -resource "azurerm_key_vault_secret" "test" { - name = "secret-%s" - value = "mad-scientist" - key_vault_id = azurerm_key_vault.test.id - - tags = { - Rick = "Morty" - } -} -`, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString) -} - -func testAccAzureRMKeyVaultSecret_requiresImport(data acceptance.TestData) string { - template := testAccAzureRMKeyVaultSecret_basic(data) +func testAccAzureRMKeyVaultSecret_template(data acceptance.TestData) string { return fmt.Sprintf(` -%s - -resource "azurerm_key_vault_secret" "import" { - name = azurerm_key_vault_secret.test.name - value = azurerm_key_vault_secret.test.value - key_vault_id = azurerm_key_vault_secret.test.key_vault_id -} -`, template) -} - -func testAccAzureRMKeyVaultSecret_complete(data acceptance.TestData) string { - return fmt.Sprintf(` -provider "azurerm" { - features {} -} - -data "azurerm_client_config" "current" { -} +data "azurerm_client_config" "current" {} resource "azurerm_resource_group" "test" { name = "acctestRG-%d" @@ -629,138 +623,27 @@ resource "azurerm_resource_group" "test" { } 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 = "premium" + 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 = "premium" + 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 = [ - "create", - ] - - secret_permissions = [ "get", - "delete", - "set", - ] - } - - tags = { - environment = "Production" - } -} - -resource "azurerm_key_vault_secret" "test" { - name = "secret-%s" - value = "" - key_vault_id = azurerm_key_vault.test.id - content_type = "application/xml" - not_before_date = "2019-01-01T01:02:03Z" - expiration_date = "2020-01-01T01:02:03Z" - - tags = { - "hello" = "world" - } -} -`, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString) -} - -func testAccAzureRMKeyVaultSecret_basicUpdated(data acceptance.TestData) string { - return fmt.Sprintf(` -provider "azurerm" { - features {} -} - -data "azurerm_client_config" "current" { -} - -resource "azurerm_resource_group" "test" { - name = "acctestRG-%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 = "premium" - - access_policy { - tenant_id = data.azurerm_client_config.current.tenant_id - object_id = data.azurerm_client_config.current.object_id - - key_permissions = [ - "create", ] secret_permissions = [ "get", "delete", - "set", - ] - } - - tags = { - environment = "Production" - } -} - -resource "azurerm_key_vault_secret" "test" { - name = "secret-%s" - value = "szechuan" - key_vault_id = azurerm_key_vault.test.id -} -`, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString) -} - -func testAccAzureRMKeyVaultSecret_softDeleteRecovery(data acceptance.TestData, purge bool) string { - return fmt.Sprintf(` -provider "azurerm" { - features { - key_vault { - purge_soft_delete_on_destroy = "%t" - recover_soft_deleted_key_vaults = true - } - } -} - -data "azurerm_client_config" "current" { -} - -resource "azurerm_resource_group" "test" { - name = "acctestRG-kvs-%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 - soft_delete_enabled = true - - sku_name = "standard" - - access_policy { - tenant_id = data.azurerm_client_config.current.tenant_id - object_id = data.azurerm_client_config.current.object_id - - key_permissions = [ - "get", - ] - - secret_permissions = [ - "get", + "purge", "recover", - "delete", "set", ] } @@ -769,11 +652,5 @@ resource "azurerm_key_vault" "test" { environment = "Production" } } - -resource "azurerm_key_vault_secret" "test" { - name = "secret-%s" - value = "rick-and-morty" - key_vault_id = azurerm_key_vault.test.id -} -`, purge, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString) +`, data.RandomInteger, data.Locations.Primary, data.RandomString) } From 752d39ad62a02c62327391db122666d590208c59 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Thu, 17 Dec 2020 14:14:43 +0100 Subject: [PATCH 16/18] r/key_vault: enabling soft delete by default --- .../keyvault/key_vault_resource_test.go | 169 ++++++++++-------- 1 file changed, 91 insertions(+), 78 deletions(-) diff --git a/azurerm/internal/services/keyvault/key_vault_resource_test.go b/azurerm/internal/services/keyvault/key_vault_resource_test.go index b7d367fb1e17..f1a305a05932 100644 --- a/azurerm/internal/services/keyvault/key_vault_resource_test.go +++ b/azurerm/internal/services/keyvault/key_vault_resource_test.go @@ -631,12 +631,13 @@ resource "azurerm_resource_group" "test" { } resource "azurerm_key_vault" "test" { - name = "vault%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 = "premium" + name = "vault%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 = "premium" + soft_delete_enabled = true + soft_delete_retention_days = 7 access_policy { tenant_id = data.azurerm_client_config.current.tenant_id @@ -664,12 +665,13 @@ func testAccAzureRMKeyVault_requiresImport(data acceptance.TestData) string { %s resource "azurerm_key_vault" "import" { - name = azurerm_key_vault.test.name - location = azurerm_key_vault.test.location - resource_group_name = azurerm_key_vault.test.resource_group_name - tenant_id = azurerm_key_vault.test.tenant_id - - sku_name = "premium" + name = azurerm_key_vault.test.name + location = azurerm_key_vault.test.location + resource_group_name = azurerm_key_vault.test.resource_group_name + tenant_id = azurerm_key_vault.test.tenant_id + sku_name = "premium" + soft_delete_enabled = true + soft_delete_retention_days = 7 access_policy { tenant_id = data.azurerm_client_config.current.tenant_id @@ -732,12 +734,13 @@ func testAccAzureRMKeyVault_networkAcls(data acceptance.TestData) string { %s resource "azurerm_key_vault" "test" { - name = "vault%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 = "premium" + name = "vault%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 = "premium" + soft_delete_enabled = true + soft_delete_retention_days = 7 access_policy { tenant_id = data.azurerm_client_config.current.tenant_id @@ -767,12 +770,13 @@ func testAccAzureRMKeyVault_networkAclsUpdated(data acceptance.TestData) string %s resource "azurerm_key_vault" "test" { - name = "vault%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 = "premium" + name = "vault%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 = "premium" + soft_delete_enabled = true + soft_delete_retention_days = 7 access_policy { tenant_id = data.azurerm_client_config.current.tenant_id @@ -803,12 +807,13 @@ func testAccAzureRMKeyVault_networkAclsAllowed(data acceptance.TestData) string %s resource "azurerm_key_vault" "test" { - name = "vault%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 = "premium" + name = "vault%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 = "premium" + soft_delete_enabled = true + soft_delete_retention_days = 7 access_policy { tenant_id = data.azurerm_client_config.current.tenant_id @@ -846,12 +851,13 @@ resource "azurerm_resource_group" "test" { } resource "azurerm_key_vault" "test" { - name = "vault%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 = "premium" + name = "vault%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 = "premium" + soft_delete_enabled = true + soft_delete_retention_days = 7 access_policy { tenant_id = data.azurerm_client_config.current.tenant_id @@ -893,12 +899,13 @@ resource "azurerm_resource_group" "test" { } resource "azurerm_key_vault" "test" { - name = "vault%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 = "premium" + name = "vault%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 = "premium" + soft_delete_enabled = true + soft_delete_retention_days = 7 enabled_for_deployment = true enabled_for_disk_encryption = true @@ -927,12 +934,13 @@ resource "azurerm_resource_group" "test" { } resource "azurerm_key_vault" "test" { - name = "vault%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 = "premium" + name = "vault%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 = "premium" + soft_delete_enabled = true + soft_delete_retention_days = 7 access_policy = [] @@ -963,12 +971,13 @@ resource "azurerm_resource_group" "test" { } resource "azurerm_key_vault" "test" { - name = "vault%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 = "premium" + name = "vault%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 = "premium" + soft_delete_enabled = true + soft_delete_retention_days = 7 access_policy { tenant_id = data.azurerm_client_config.current.tenant_id @@ -1010,12 +1019,13 @@ resource "azurerm_resource_group" "test" { } resource "azurerm_key_vault" "test" { - name = "vault%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 = "premium" + name = "vault%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 = "premium" + soft_delete_enabled = true + soft_delete_retention_days = 7 access_policy { tenant_id = data.azurerm_client_config.current.tenant_id @@ -1052,12 +1062,14 @@ resource "azurerm_resource_group" "test" { } resource "azurerm_key_vault" "test" { - name = "vault%d" - location = azurerm_resource_group.test.location - resource_group_name = azurerm_resource_group.test.name - tenant_id = data.azurerm_client_config.current.tenant_id + name = "vault%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 = "premium" + soft_delete_enabled = true + soft_delete_retention_days = 7 - sku_name = "premium" %s } @@ -1227,7 +1239,6 @@ resource "azurerm_key_vault" "test" { soft_delete_enabled = true soft_delete_retention_days = 7 purge_protection_enabled = true - } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } @@ -1247,12 +1258,13 @@ resource "azurerm_resource_group" "test" { } resource "azurerm_key_vault" "test" { - name = "vault%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 = "premium" + name = "vault%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 = "premium" + soft_delete_enabled = true + soft_delete_retention_days = 7 access_policy = [] } @@ -1274,12 +1286,13 @@ resource "azurerm_resource_group" "test" { } resource "azurerm_key_vault" "test" { - name = "vault%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 = "premium" + name = "vault%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 = "premium" + soft_delete_enabled = true + soft_delete_retention_days = 7 access_policy { tenant_id = data.azurerm_client_config.current.tenant_id From 9406666783eabc6b49238d7989443796361ba943 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Thu, 17 Dec 2020 14:59:34 +0100 Subject: [PATCH 17/18] r/key_vault_certificate: adding import/recover permissions for the tests --- .../services/keyvault/key_vault_certificate_resource_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/azurerm/internal/services/keyvault/key_vault_certificate_resource_test.go b/azurerm/internal/services/keyvault/key_vault_certificate_resource_test.go index b49dad1ab599..24d25476da6f 100644 --- a/azurerm/internal/services/keyvault/key_vault_certificate_resource_test.go +++ b/azurerm/internal/services/keyvault/key_vault_certificate_resource_test.go @@ -934,6 +934,7 @@ resource "azurerm_key_vault_access_policy" "test" { "delete", "get", "purge", + "recover", "update", ] @@ -1125,7 +1126,9 @@ resource "azurerm_key_vault" "test" { "create", "delete", "get", + "import", "purge", + "recover", "update", ] From 8bcf259d8a724380161d70014068a6a4f3612a08 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Thu, 17 Dec 2020 17:10:08 +0100 Subject: [PATCH 18/18] r/key_vault_secret: adding purge protection --- .../services/keyvault/key_vault_secret_resource_test.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/azurerm/internal/services/keyvault/key_vault_secret_resource_test.go b/azurerm/internal/services/keyvault/key_vault_secret_resource_test.go index a210bc994614..ac03cd61ca53 100644 --- a/azurerm/internal/services/keyvault/key_vault_secret_resource_test.go +++ b/azurerm/internal/services/keyvault/key_vault_secret_resource_test.go @@ -548,6 +548,8 @@ resource "azurerm_key_vault_access_policy" "test" { "set", "get", "delete", + "purge", + "recover" ] } @@ -600,7 +602,8 @@ resource "azurerm_key_vault_access_policy" "test" { "set", "get", "delete", - "recover", + "purge", + "recover" ] }