From ef752ebc53f06892ddb48c4cd94558c221e204ce Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Thu, 4 Oct 2018 17:07:22 +1300 Subject: [PATCH 1/6] Upgrading to version `2018-02-14` of the Key Vault API --- azurerm/config.go | 2 +- azurerm/data_source_key_vault.go | 2 +- .../data_source_key_vault_access_policy.go | 2 +- .../helpers/azure/key_vault_access_policy.go | 2 +- azurerm/resource_arm_key_vault.go | 2 +- .../resource_arm_key_vault_access_policy.go | 2 +- azurerm/resource_arm_key_vault_migration.go | 2 +- .../keyvault/client.go | 2 +- .../keyvault/models.go | 98 ++++++++++++++++++- .../keyvault/operations.go | 2 +- .../keyvault/vaults.go | 48 ++++----- .../keyvault/version.go | 2 +- vendor/vendor.json | 4 +- 13 files changed, 132 insertions(+), 38 deletions(-) rename vendor/github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/{2016-10-01 => 2018-02-14}/keyvault/client.go (98%) rename vendor/github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/{2016-10-01 => 2018-02-14}/keyvault/models.go (88%) rename vendor/github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/{2016-10-01 => 2018-02-14}/keyvault/operations.go (99%) rename vendor/github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/{2016-10-01 => 2018-02-14}/keyvault/vaults.go (97%) rename vendor/github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/{2016-10-01 => 2018-02-14}/keyvault/version.go (93%) diff --git a/azurerm/config.go b/azurerm/config.go index 80bd6139ca97..1cf30ebd1384 100644 --- a/azurerm/config.go +++ b/azurerm/config.go @@ -29,7 +29,7 @@ import ( "github.com/Azure/azure-sdk-for-go/services/graphrbac/1.6/graphrbac" "github.com/Azure/azure-sdk-for-go/services/iothub/mgmt/2018-04-01/devices" keyVault "github.com/Azure/azure-sdk-for-go/services/keyvault/2016-10-01/keyvault" - "github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2016-10-01/keyvault" + "github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2018-02-14/keyvault" "github.com/Azure/azure-sdk-for-go/services/logic/mgmt/2016-06-01/logic" "github.com/Azure/azure-sdk-for-go/services/mysql/mgmt/2017-12-01/mysql" "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2018-04-01/network" diff --git a/azurerm/data_source_key_vault.go b/azurerm/data_source_key_vault.go index 41c1a8f14165..8c49985c77dc 100644 --- a/azurerm/data_source_key_vault.go +++ b/azurerm/data_source_key_vault.go @@ -3,7 +3,7 @@ package azurerm import ( "fmt" - "github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2016-10-01/keyvault" + "github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2018-02-14/keyvault" "github.com/hashicorp/terraform/helper/schema" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" diff --git a/azurerm/data_source_key_vault_access_policy.go b/azurerm/data_source_key_vault_access_policy.go index 6fa888c0f37e..db67f470885d 100644 --- a/azurerm/data_source_key_vault_access_policy.go +++ b/azurerm/data_source_key_vault_access_policy.go @@ -3,7 +3,7 @@ package azurerm import ( "strings" - "github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2016-10-01/keyvault" + "github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2018-02-14/keyvault" "github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/helper/validation" ) diff --git a/azurerm/helpers/azure/key_vault_access_policy.go b/azurerm/helpers/azure/key_vault_access_policy.go index fafcdec9a84d..5f1ff0fa7550 100644 --- a/azurerm/helpers/azure/key_vault_access_policy.go +++ b/azurerm/helpers/azure/key_vault_access_policy.go @@ -1,7 +1,7 @@ package azure import ( - "github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2016-10-01/keyvault" + "github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2018-02-14/keyvault" "github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/helper/validation" "github.com/satori/go.uuid" diff --git a/azurerm/resource_arm_key_vault.go b/azurerm/resource_arm_key_vault.go index fd1c5ee8ef84..571e35513a63 100644 --- a/azurerm/resource_arm_key_vault.go +++ b/azurerm/resource_arm_key_vault.go @@ -7,7 +7,7 @@ import ( "regexp" "time" - "github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2016-10-01/keyvault" + "github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2018-02-14/keyvault" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/helper/validation" diff --git a/azurerm/resource_arm_key_vault_access_policy.go b/azurerm/resource_arm_key_vault_access_policy.go index 24c96612df59..b084e620957b 100644 --- a/azurerm/resource_arm_key_vault_access_policy.go +++ b/azurerm/resource_arm_key_vault_access_policy.go @@ -6,7 +6,7 @@ import ( "strings" - "github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2016-10-01/keyvault" + "github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2018-02-14/keyvault" "github.com/hashicorp/terraform/helper/schema" "github.com/satori/go.uuid" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" diff --git a/azurerm/resource_arm_key_vault_migration.go b/azurerm/resource_arm_key_vault_migration.go index ba88720978b4..239dbf7c61e9 100644 --- a/azurerm/resource_arm_key_vault_migration.go +++ b/azurerm/resource_arm_key_vault_migration.go @@ -5,7 +5,7 @@ import ( "log" "strings" - "github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2016-10-01/keyvault" + "github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2018-02-14/keyvault" "github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/terraform" ) diff --git a/vendor/github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2016-10-01/keyvault/client.go b/vendor/github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2018-02-14/keyvault/client.go similarity index 98% rename from vendor/github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2016-10-01/keyvault/client.go rename to vendor/github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2018-02-14/keyvault/client.go index 3d2740e41370..4491a94067c5 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2016-10-01/keyvault/client.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2018-02-14/keyvault/client.go @@ -1,4 +1,4 @@ -// Package keyvault implements the Azure ARM Keyvault service API version 2016-10-01. +// Package keyvault implements the Azure ARM Keyvault service API version 2018-02-14. // // The Azure management API provides a RESTful set of web services that interact with Azure Key Vault. package keyvault diff --git a/vendor/github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2016-10-01/keyvault/models.go b/vendor/github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2018-02-14/keyvault/models.go similarity index 88% rename from vendor/github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2016-10-01/keyvault/models.go rename to vendor/github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2018-02-14/keyvault/models.go index f28e0abbb3d0..1c4cbca7aae0 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2016-10-01/keyvault/models.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2018-02-14/keyvault/models.go @@ -48,6 +48,8 @@ func PossibleAccessPolicyUpdateKindValues() []AccessPolicyUpdateKind { type CertificatePermissions string const ( + // Backup ... + Backup CertificatePermissions = "backup" // Create ... Create CertificatePermissions = "create" // Delete ... @@ -72,6 +74,8 @@ const ( Purge CertificatePermissions = "purge" // Recover ... Recover CertificatePermissions = "recover" + // Restore ... + Restore CertificatePermissions = "restore" // Setissuers ... Setissuers CertificatePermissions = "setissuers" // Update ... @@ -80,7 +84,7 @@ const ( // PossibleCertificatePermissionsValues returns an array of possible values for the CertificatePermissions const type. func PossibleCertificatePermissionsValues() []CertificatePermissions { - return []CertificatePermissions{Create, Delete, Deleteissuers, Get, Getissuers, Import, List, Listissuers, Managecontacts, Manageissuers, Purge, Recover, Setissuers, Update} + return []CertificatePermissions{Backup, Create, Delete, Deleteissuers, Get, Getissuers, Import, List, Listissuers, Managecontacts, Manageissuers, Purge, Recover, Restore, Setissuers, Update} } // CreateMode enumerates the values for create mode. @@ -141,6 +145,36 @@ func PossibleKeyPermissionsValues() []KeyPermissions { return []KeyPermissions{KeyPermissionsBackup, KeyPermissionsCreate, KeyPermissionsDecrypt, KeyPermissionsDelete, KeyPermissionsEncrypt, KeyPermissionsGet, KeyPermissionsImport, KeyPermissionsList, KeyPermissionsPurge, KeyPermissionsRecover, KeyPermissionsRestore, KeyPermissionsSign, KeyPermissionsUnwrapKey, KeyPermissionsUpdate, KeyPermissionsVerify, KeyPermissionsWrapKey} } +// NetworkRuleAction enumerates the values for network rule action. +type NetworkRuleAction string + +const ( + // Allow ... + Allow NetworkRuleAction = "Allow" + // Deny ... + Deny NetworkRuleAction = "Deny" +) + +// PossibleNetworkRuleActionValues returns an array of possible values for the NetworkRuleAction const type. +func PossibleNetworkRuleActionValues() []NetworkRuleAction { + return []NetworkRuleAction{Allow, Deny} +} + +// NetworkRuleBypassOptions enumerates the values for network rule bypass options. +type NetworkRuleBypassOptions string + +const ( + // AzureServices ... + AzureServices NetworkRuleBypassOptions = "AzureServices" + // None ... + None NetworkRuleBypassOptions = "None" +) + +// PossibleNetworkRuleBypassOptionsValues returns an array of possible values for the NetworkRuleBypassOptions const type. +func PossibleNetworkRuleBypassOptionsValues() []NetworkRuleBypassOptions { + return []NetworkRuleBypassOptions{AzureServices, None} +} + // Reason enumerates the values for reason. type Reason string @@ -411,6 +445,12 @@ func (dvp DeletedVaultProperties) MarshalJSON() ([]byte, error) { return json.Marshal(objectMap) } +// IPRule a rule governing the accesibility of a vault from a specific ip address or ip range. +type IPRule struct { + // Value - An IPv4 address range in CIDR notation, such as '124.56.78.91' (simple IP address) or '124.56.78.0/24' (all addresses that start with 124.56.78). + Value *string `json:"value,omitempty"` +} + // LogSpecification log specification of operation. type LogSpecification struct { // Name - Name of log specification. @@ -421,6 +461,18 @@ type LogSpecification struct { BlobDuration *string `json:"blobDuration,omitempty"` } +// NetworkRuleSet a set of rules governing the network accessibility of a vault. +type NetworkRuleSet struct { + // Bypass - Tells what traffic can bypass network rules. This can be 'AzureServices' or 'None'. If not specified the default is 'AzureServices'. Possible values include: 'AzureServices', 'None' + Bypass NetworkRuleBypassOptions `json:"bypass,omitempty"` + // DefaultAction - The default action when no rule from ipRules and from virtualNetworkRules match. This is only used after the bypass property has been evaluated. Possible values include: 'Allow', 'Deny' + DefaultAction NetworkRuleAction `json:"defaultAction,omitempty"` + // IPRules - The list of IP address rules. + IPRules *[]IPRule `json:"ipRules,omitempty"` + // VirtualNetworkRules - The list of virtual network rules. + VirtualNetworkRules *[]VirtualNetworkRule `json:"virtualNetworkRules,omitempty"` +} + // Operation key Vault REST API operation definition. type Operation struct { // Name - Operation name: {provider}/{resource}/{operation} @@ -1017,12 +1069,14 @@ type VaultPatchProperties struct { EnabledForDiskEncryption *bool `json:"enabledForDiskEncryption,omitempty"` // EnabledForTemplateDeployment - Property to specify whether Azure Resource Manager is permitted to retrieve secrets from the key vault. EnabledForTemplateDeployment *bool `json:"enabledForTemplateDeployment,omitempty"` - // EnableSoftDelete - Property specifying whether recoverable deletion ('soft' delete) is enabled for this key vault. The property may not be set to false. + // EnableSoftDelete - Property to specify whether the 'soft delete' functionality is enabled for this key vault. It does not accept false value. EnableSoftDelete *bool `json:"enableSoftDelete,omitempty"` // CreateMode - The vault's create mode to indicate whether the vault need to be recovered or not. Possible values include: 'CreateModeRecover', 'CreateModeDefault' CreateMode CreateMode `json:"createMode,omitempty"` - // EnablePurgeProtection - Property specifying whether protection against purge is enabled for this vault; it is only effective if soft delete is also enabled. Once activated, the property may no longer be reset to false. + // EnablePurgeProtection - Property specifying whether protection against purge is enabled for this vault. Setting this property to true activates protection against purge for this vault and its content - only the Key Vault service may initiate a hard, irrecoverable deletion. The setting is effective only if soft delete is also enabled. Enabling this functionality is irreversible - that is, the property does not accept false as its value. EnablePurgeProtection *bool `json:"enablePurgeProtection,omitempty"` + // NetworkAcls - A collection of rules governing the accessibility of the vault from specific network locations. + NetworkAcls *NetworkRuleSet `json:"networkAcls,omitempty"` } // VaultProperties properties of the vault @@ -1041,12 +1095,42 @@ type VaultProperties struct { EnabledForDiskEncryption *bool `json:"enabledForDiskEncryption,omitempty"` // EnabledForTemplateDeployment - Property to specify whether Azure Resource Manager is permitted to retrieve secrets from the key vault. EnabledForTemplateDeployment *bool `json:"enabledForTemplateDeployment,omitempty"` - // EnableSoftDelete - Property specifying whether recoverable deletion is enabled for this key vault. Setting this property to true activates the soft delete feature, whereby vaults or vault entities can be recovered after deletion. Enabling this functionality is irreversible - that is, the property does not accept false as its value. + // EnableSoftDelete - Property to specify whether the 'soft delete' functionality is enabled for this key vault. It does not accept false value. EnableSoftDelete *bool `json:"enableSoftDelete,omitempty"` // CreateMode - The vault's create mode to indicate whether the vault need to be recovered or not. Possible values include: 'CreateModeRecover', 'CreateModeDefault' CreateMode CreateMode `json:"createMode,omitempty"` // EnablePurgeProtection - Property specifying whether protection against purge is enabled for this vault. Setting this property to true activates protection against purge for this vault and its content - only the Key Vault service may initiate a hard, irrecoverable deletion. The setting is effective only if soft delete is also enabled. Enabling this functionality is irreversible - that is, the property does not accept false as its value. EnablePurgeProtection *bool `json:"enablePurgeProtection,omitempty"` + // NetworkAcls - A collection of rules governing the accessibility of the vault from specific network locations. + NetworkAcls *NetworkRuleSet `json:"networkAcls,omitempty"` +} + +// VaultsCreateOrUpdateFuture an abstraction for monitoring and retrieving the results of a long-running operation. +type VaultsCreateOrUpdateFuture struct { + azure.Future +} + +// Result returns the result of the asynchronous operation. +// If the operation has not completed it will return an error. +func (future *VaultsCreateOrUpdateFuture) Result(client VaultsClient) (vVar Vault, err error) { + var done bool + done, err = future.Done(client) + if err != nil { + err = autorest.NewErrorWithError(err, "keyvault.VaultsCreateOrUpdateFuture", "Result", future.Response(), "Polling failure") + return + } + if !done { + err = azure.NewAsyncOpIncompleteError("keyvault.VaultsCreateOrUpdateFuture") + return + } + sender := autorest.DecorateSender(client, autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...)) + if vVar.Response.Response, err = future.GetResult(sender); err == nil && vVar.Response.Response.StatusCode != http.StatusNoContent { + vVar, err = client.CreateOrUpdateResponder(vVar.Response.Response) + if err != nil { + err = autorest.NewErrorWithError(err, "keyvault.VaultsCreateOrUpdateFuture", "Result", vVar.Response.Response, "Failure responding to request") + } + } + return } // VaultsPurgeDeletedFuture an abstraction for monitoring and retrieving the results of a long-running operation. @@ -1070,3 +1154,9 @@ func (future *VaultsPurgeDeletedFuture) Result(client VaultsClient) (ar autorest ar.Response = future.Response() return } + +// VirtualNetworkRule a rule governing the accesibility of a vault from a specific virtual network. +type VirtualNetworkRule struct { + // ID - Full resource id of a vnet subnet, such as '/subscriptions/subid/resourceGroups/rg1/providers/Microsoft.Network/virtualNetworks/test-vnet/subnets/subnet1'. + ID *string `json:"id,omitempty"` +} diff --git a/vendor/github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2016-10-01/keyvault/operations.go b/vendor/github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2018-02-14/keyvault/operations.go similarity index 99% rename from vendor/github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2016-10-01/keyvault/operations.go rename to vendor/github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2018-02-14/keyvault/operations.go index b2325f7b1413..13d26390d2b2 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2016-10-01/keyvault/operations.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2018-02-14/keyvault/operations.go @@ -66,7 +66,7 @@ func (client OperationsClient) List(ctx context.Context) (result OperationListRe // ListPreparer prepares the List request. func (client OperationsClient) ListPreparer(ctx context.Context) (*http.Request, error) { - const APIVersion = "2016-10-01" + const APIVersion = "2018-02-14" queryParameters := map[string]interface{}{ "api-version": APIVersion, } diff --git a/vendor/github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2016-10-01/keyvault/vaults.go b/vendor/github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2018-02-14/keyvault/vaults.go similarity index 97% rename from vendor/github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2016-10-01/keyvault/vaults.go rename to vendor/github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2018-02-14/keyvault/vaults.go index b9bf8b24951e..826a1b38bcdd 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2016-10-01/keyvault/vaults.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2018-02-14/keyvault/vaults.go @@ -79,7 +79,7 @@ func (client VaultsClient) CheckNameAvailabilityPreparer(ctx context.Context, va "subscriptionId": autorest.Encode("path", client.SubscriptionID), } - const APIVersion = "2016-10-01" + const APIVersion = "2018-02-14" queryParameters := map[string]interface{}{ "api-version": APIVersion, } @@ -119,7 +119,7 @@ func (client VaultsClient) CheckNameAvailabilityResponder(resp *http.Response) ( // resourceGroupName - the name of the Resource Group to which the server belongs. // vaultName - name of the vault // parameters - parameters to create or update the vault -func (client VaultsClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, vaultName string, parameters VaultCreateOrUpdateParameters) (result Vault, err error) { +func (client VaultsClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, vaultName string, parameters VaultCreateOrUpdateParameters) (result VaultsCreateOrUpdateFuture, err error) { if err := validation.Validate([]validation.Validation{ {TargetValue: vaultName, Constraints: []validation.Constraint{{Target: "vaultName", Name: validation.Pattern, Rule: `^[a-zA-Z0-9-]{3,24}$`, Chain: nil}}}, @@ -139,18 +139,12 @@ func (client VaultsClient) CreateOrUpdate(ctx context.Context, resourceGroupName return } - resp, err := client.CreateOrUpdateSender(req) + result, err = client.CreateOrUpdateSender(req) if err != nil { - result.Response = autorest.Response{Response: resp} - err = autorest.NewErrorWithError(err, "keyvault.VaultsClient", "CreateOrUpdate", resp, "Failure sending request") + err = autorest.NewErrorWithError(err, "keyvault.VaultsClient", "CreateOrUpdate", result.Response(), "Failure sending request") return } - result, err = client.CreateOrUpdateResponder(resp) - if err != nil { - err = autorest.NewErrorWithError(err, "keyvault.VaultsClient", "CreateOrUpdate", resp, "Failure responding to request") - } - return } @@ -162,7 +156,7 @@ func (client VaultsClient) CreateOrUpdatePreparer(ctx context.Context, resourceG "vaultName": autorest.Encode("path", vaultName), } - const APIVersion = "2016-10-01" + const APIVersion = "2018-02-14" queryParameters := map[string]interface{}{ "api-version": APIVersion, } @@ -179,9 +173,19 @@ func (client VaultsClient) CreateOrUpdatePreparer(ctx context.Context, resourceG // CreateOrUpdateSender sends the CreateOrUpdate request. The method will close the // http.Response Body if it receives an error. -func (client VaultsClient) CreateOrUpdateSender(req *http.Request) (*http.Response, error) { - return autorest.SendWithSender(client, req, +func (client VaultsClient) CreateOrUpdateSender(req *http.Request) (future VaultsCreateOrUpdateFuture, err error) { + var resp *http.Response + resp, err = autorest.SendWithSender(client, req, azure.DoRetryWithRegistration(client.Client)) + if err != nil { + return + } + err = autorest.Respond(resp, azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusCreated)) + if err != nil { + return + } + future.Future, err = azure.NewFutureFromResponse(resp) + return } // CreateOrUpdateResponder handles the response to the CreateOrUpdate request. The method always @@ -231,7 +235,7 @@ func (client VaultsClient) DeletePreparer(ctx context.Context, resourceGroupName "vaultName": autorest.Encode("path", vaultName), } - const APIVersion = "2016-10-01" + const APIVersion = "2018-02-14" queryParameters := map[string]interface{}{ "api-version": APIVersion, } @@ -297,7 +301,7 @@ func (client VaultsClient) GetPreparer(ctx context.Context, resourceGroupName st "vaultName": autorest.Encode("path", vaultName), } - const APIVersion = "2016-10-01" + const APIVersion = "2018-02-14" queryParameters := map[string]interface{}{ "api-version": APIVersion, } @@ -364,7 +368,7 @@ func (client VaultsClient) GetDeletedPreparer(ctx context.Context, vaultName str "vaultName": autorest.Encode("path", vaultName), } - const APIVersion = "2016-10-01" + const APIVersion = "2018-02-14" queryParameters := map[string]interface{}{ "api-version": APIVersion, } @@ -528,7 +532,7 @@ func (client VaultsClient) ListByResourceGroupPreparer(ctx context.Context, reso "subscriptionId": autorest.Encode("path", client.SubscriptionID), } - const APIVersion = "2016-10-01" + const APIVersion = "2018-02-14" queryParameters := map[string]interface{}{ "api-version": APIVersion, } @@ -623,7 +627,7 @@ func (client VaultsClient) ListBySubscriptionPreparer(ctx context.Context, top * "subscriptionId": autorest.Encode("path", client.SubscriptionID), } - const APIVersion = "2016-10-01" + const APIVersion = "2018-02-14" queryParameters := map[string]interface{}{ "api-version": APIVersion, } @@ -716,7 +720,7 @@ func (client VaultsClient) ListDeletedPreparer(ctx context.Context) (*http.Reque "subscriptionId": autorest.Encode("path", client.SubscriptionID), } - const APIVersion = "2016-10-01" + const APIVersion = "2018-02-14" queryParameters := map[string]interface{}{ "api-version": APIVersion, } @@ -804,7 +808,7 @@ func (client VaultsClient) PurgeDeletedPreparer(ctx context.Context, vaultName s "vaultName": autorest.Encode("path", vaultName), } - const APIVersion = "2016-10-01" + const APIVersion = "2018-02-14" queryParameters := map[string]interface{}{ "api-version": APIVersion, } @@ -887,7 +891,7 @@ func (client VaultsClient) UpdatePreparer(ctx context.Context, resourceGroupName "vaultName": autorest.Encode("path", vaultName), } - const APIVersion = "2016-10-01" + const APIVersion = "2018-02-14" queryParameters := map[string]interface{}{ "api-version": APIVersion, } @@ -968,7 +972,7 @@ func (client VaultsClient) UpdateAccessPolicyPreparer(ctx context.Context, resou "vaultName": autorest.Encode("path", vaultName), } - const APIVersion = "2016-10-01" + const APIVersion = "2018-02-14" queryParameters := map[string]interface{}{ "api-version": APIVersion, } diff --git a/vendor/github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2016-10-01/keyvault/version.go b/vendor/github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2018-02-14/keyvault/version.go similarity index 93% rename from vendor/github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2016-10-01/keyvault/version.go rename to vendor/github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2018-02-14/keyvault/version.go index fb6a25c73006..c6119f5e941f 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2016-10-01/keyvault/version.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2018-02-14/keyvault/version.go @@ -21,7 +21,7 @@ import "github.com/Azure/azure-sdk-for-go/version" // UserAgent returns the UserAgent string to use when sending http.Requests. func UserAgent() string { - return "Azure-SDK-For-Go/" + version.Number + " keyvault/2016-10-01" + return "Azure-SDK-For-Go/" + version.Number + " keyvault/2018-02-14" } // Version returns the semantic version (see http://semver.org) of the client. diff --git a/vendor/vendor.json b/vendor/vendor.json index c3363a0b3fe8..c0115a215875 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -155,8 +155,8 @@ "versionExact": "v21.1.0" }, { - "checksumSHA1": "V8yVJJDoKLdBxvAHshfWc0N6oeA=", - "path": "github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2016-10-01/keyvault", + "checksumSHA1": "RZpLYjpPpobqat3uLWXPC8H33EQ=", + "path": "github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2018-02-14/keyvault", "revision": "6d20bdbae88c06c36d72eb512295417693bfdf4e", "revisionTime": "2018-09-28T00:20:07Z", "version": "v21.1.0", From 0f8534a2f30cbd5031e0787da0c30905d11e1362 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Fri, 5 Oct 2018 14:08:08 +1000 Subject: [PATCH 2/6] Key Vault: support for Network ACL's --- azurerm/resource_arm_key_vault.go | 214 +++++++++++++++++++++++-- azurerm/resource_arm_key_vault_test.go | 141 +++++++++++++++- website/docs/r/key_vault.html.markdown | 93 ++++++----- 3 files changed, 388 insertions(+), 60 deletions(-) diff --git a/azurerm/resource_arm_key_vault.go b/azurerm/resource_arm_key_vault.go index 571e35513a63..e67b032aef38 100644 --- a/azurerm/resource_arm_key_vault.go +++ b/azurerm/resource_arm_key_vault.go @@ -13,6 +13,8 @@ import ( "github.com/hashicorp/terraform/helper/validation" "github.com/satori/go.uuid" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/response" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/set" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) @@ -119,6 +121,44 @@ func resourceArmKeyVault() *schema.Resource { Optional: true, }, + "network_acls": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "default_action": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + string(keyvault.Allow), + string(keyvault.Deny), + }, false), + }, + "bypass": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + string(keyvault.None), + string(keyvault.AzureServices), + }, false), + }, + "ip_rules": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, + }, + "virtual_network_subnet_ids": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: set.HashStringIgnoreCase, + }, + }, + }, + }, + "tags": tagsSchema(), }, } @@ -130,14 +170,17 @@ func resourceArmKeyVaultCreateUpdate(d *schema.ResourceData, meta interface{}) e log.Printf("[INFO] preparing arguments for Azure ARM KeyVault creation.") name := d.Get("name").(string) + resourceGroup := d.Get("resource_group_name").(string) location := azureRMNormalizeLocation(d.Get("location").(string)) - resGroup := d.Get("resource_group_name").(string) tenantUUID := uuid.FromStringOrNil(d.Get("tenant_id").(string)) enabledForDeployment := d.Get("enabled_for_deployment").(bool) enabledForDiskEncryption := d.Get("enabled_for_disk_encryption").(bool) enabledForTemplateDeployment := d.Get("enabled_for_template_deployment").(bool) tags := d.Get("tags").(map[string]interface{}) + networkAclsRaw := d.Get("network_acls").([]interface{}) + networkAcls, subnetIds := expandKeyVaultNetworkAcls(networkAclsRaw) + policies := d.Get("access_policy").([]interface{}) accessPolicies, err := azure.ExpandKeyVaultAccessPolicies(policies) if err != nil { @@ -153,6 +196,7 @@ func resourceArmKeyVaultCreateUpdate(d *schema.ResourceData, meta interface{}) e EnabledForDeployment: &enabledForDeployment, EnabledForDiskEncryption: &enabledForDiskEncryption, EnabledForTemplateDeployment: &enabledForTemplateDeployment, + NetworkAcls: networkAcls, }, Tags: expandTags(tags), } @@ -162,17 +206,32 @@ func resourceArmKeyVaultCreateUpdate(d *schema.ResourceData, meta interface{}) e azureRMLockByName(name, keyVaultResourceName) defer azureRMUnlockByName(name, keyVaultResourceName) - _, err = client.CreateOrUpdate(ctx, resGroup, name, parameters) + // also lock on the Virtual Network ID's since modifications in the networking stack are exclusive + virtualNetworkNames := make([]string, 0) + for _, v := range subnetIds { + id, err := parseAzureResourceID(v) + if err != nil { + return err + } + + virtualNetworkName := id.Path["virtualNetworks"] + virtualNetworkNames = append(virtualNetworkNames, virtualNetworkName) + } + + azureRMLockMultipleByName(&virtualNetworkNames, virtualNetworkResourceName) + defer azureRMUnlockMultipleByName(&virtualNetworkNames, virtualNetworkResourceName) + + _, err = client.CreateOrUpdate(ctx, resourceGroup, name, parameters) if err != nil { - return fmt.Errorf("Error updating Key Vault %q (Resource Group %q): %+v", name, resGroup, err) + return fmt.Errorf("Error updating Key Vault %q (Resource Group %q): %+v", name, resourceGroup, err) } - read, err := client.Get(ctx, resGroup, name) + read, err := client.Get(ctx, resourceGroup, name) if err != nil { - return fmt.Errorf("Error retrieving Key Vault %q (Resource Group %q): %+v", name, resGroup, err) + return fmt.Errorf("Error retrieving Key Vault %q (Resource Group %q): %+v", name, resourceGroup, err) } if read.ID == nil { - return fmt.Errorf("Cannot read KeyVault %s (resource Group %q) ID", name, resGroup) + return fmt.Errorf("Cannot read KeyVault %s (resource Group %q) ID", name, resourceGroup) } d.SetId(*read.ID) @@ -180,7 +239,7 @@ func resourceArmKeyVaultCreateUpdate(d *schema.ResourceData, meta interface{}) e if d.IsNewResource() { if props := read.Properties; props != nil { if vault := props.VaultURI; vault != nil { - log.Printf("[DEBUG] Waiting for Key Vault %q (Resource Group %q) to become available", name, resGroup) + log.Printf("[DEBUG] Waiting for Key Vault %q (Resource Group %q) to become available", name, resourceGroup) stateConf := &resource.StateChangeConf{ Pending: []string{"pending"}, Target: []string{"available"}, @@ -192,7 +251,7 @@ func resourceArmKeyVaultCreateUpdate(d *schema.ResourceData, meta interface{}) e } if _, err := stateConf.WaitForState(); err != nil { - return fmt.Errorf("Error waiting for Key Vault %q (Resource Group %q) to become available: %s", name, resGroup, err) + return fmt.Errorf("Error waiting for Key Vault %q (Resource Group %q) to become available: %s", name, resourceGroup, err) } } } @@ -209,20 +268,21 @@ func resourceArmKeyVaultRead(d *schema.ResourceData, meta interface{}) error { if err != nil { return err } - resGroup := id.ResourceGroup + resourceGroup := id.ResourceGroup name := id.Path["vaults"] - resp, err := client.Get(ctx, resGroup, name) + resp, err := client.Get(ctx, resourceGroup, name) if err != nil { if utils.ResponseWasNotFound(resp.Response) { + log.Printf("[DEBUG] Key Vault %q was not found in Resource Group %q - removing from state!", name, resourceGroup) d.SetId("") return nil } - return fmt.Errorf("Error making Read request on KeyVault %q (Resource Group %q): %+v", name, resGroup, err) + return fmt.Errorf("Error making Read request on KeyVault %q (Resource Group %q): %+v", name, resourceGroup, err) } d.Set("name", resp.Name) - d.Set("resource_group_name", resGroup) + d.Set("resource_group_name", resourceGroup) if location := resp.Location; location != nil { d.Set("location", azureRMNormalizeLocation(*location)) } @@ -232,15 +292,20 @@ func resourceArmKeyVaultRead(d *schema.ResourceData, meta interface{}) error { d.Set("enabled_for_deployment", props.EnabledForDeployment) d.Set("enabled_for_disk_encryption", props.EnabledForDiskEncryption) d.Set("enabled_for_template_deployment", props.EnabledForTemplateDeployment) + d.Set("vault_uri", props.VaultURI) + if err := d.Set("sku", flattenKeyVaultSku(props.Sku)); err != nil { return fmt.Errorf("Error flattening `sku` for KeyVault %q: %+v", *resp.Name, err) } + if err := d.Set("network_acls", flattenKeyVaultNetworkAcls(props.NetworkAcls)); err != nil { + return fmt.Errorf("Error flattening `network_acls` for KeyVault %q: %+v", *resp.Name, err) + } + flattenedPolicies := azure.FlattenKeyVaultAccessPolicies(props.AccessPolicies) if err := d.Set("access_policy", flattenedPolicies); err != nil { return fmt.Errorf("Error flattening `access_policy` for KeyVault %q: %+v", *resp.Name, err) } - d.Set("vault_uri", props.VaultURI) } flattenAndSetTags(d, resp.Tags) @@ -255,15 +320,54 @@ func resourceArmKeyVaultDelete(d *schema.ResourceData, meta interface{}) error { if err != nil { return err } - resGroup := id.ResourceGroup + resourceGroup := id.ResourceGroup name := id.Path["vaults"] azureRMLockByName(name, keyVaultResourceName) defer azureRMUnlockByName(name, keyVaultResourceName) - _, err = client.Delete(ctx, resGroup, name) + read, err := client.Get(ctx, resourceGroup, name) + if err != nil { + if utils.ResponseWasNotFound(read.Response) { + return nil + } + + return fmt.Errorf("Error retrieving Key Vault %q (Resource Group %q): %+v", name, resourceGroup, err) + } + + // ensure we lock on the latest network names, to ensure we handle Azure's networking layer being limited to one change at a time + virtualNetworkNames := make([]string, 0) + if props := read.Properties; props != nil { + if acls := props.NetworkAcls; acls != nil { + if rules := acls.VirtualNetworkRules; rules != nil { + for _, v := range *rules { + if v.ID == nil { + continue + } + + id, err := parseAzureResourceID(*v.ID) + if err != nil { + return err + } + + networkName := id.Path["virtualNetworks"] + virtualNetworkNames = append(virtualNetworkNames, networkName) + } + } + } + } + + azureRMLockMultipleByName(&virtualNetworkNames, virtualNetworkResourceName) + defer azureRMUnlockMultipleByName(&virtualNetworkNames, virtualNetworkResourceName) + + resp, err := client.Delete(ctx, resourceGroup, name) + if err != nil { + if !response.WasNotFound(resp.Response) { + return fmt.Errorf("Error retrieving Key Vault %q (Resource Group %q): %+v", name, resourceGroup, err) + } + } - return err + return nil } func expandKeyVaultSku(d *schema.ResourceData) *keyvault.Sku { @@ -284,6 +388,43 @@ func flattenKeyVaultSku(sku *keyvault.Sku) []interface{} { return []interface{}{result} } +func flattenKeyVaultNetworkAcls(input *keyvault.NetworkRuleSet) []interface{} { + if input == nil { + return []interface{}{} + } + + output := make(map[string]interface{}, 0) + + output["bypass"] = string(input.Bypass) + output["default_action"] = string(input.DefaultAction) + + ipRules := make([]interface{}, 0) + if input.IPRules != nil { + for _, v := range *input.IPRules { + if v.Value == nil { + continue + } + + ipRules = append(ipRules, *v.Value) + } + } + output["ip_rules"] = schema.NewSet(schema.HashString, ipRules) + + virtualNetworkRules := make([]interface{}, 0) + if input.VirtualNetworkRules != nil { + for _, v := range *input.VirtualNetworkRules { + if v.ID == nil { + continue + } + + virtualNetworkRules = append(virtualNetworkRules, *v.ID) + } + } + output["virtual_network_subnet_ids"] = schema.NewSet(schema.HashString, virtualNetworkRules) + + return []interface{}{output} +} + func validateKeyVaultName(v interface{}, k string) (ws []string, errors []error) { value := v.(string) if matched := regexp.MustCompile(`^[a-zA-Z0-9-]{3,24}$`).Match([]byte(value)); !matched { @@ -315,3 +456,44 @@ func keyVaultRefreshFunc(vaultUri string) resource.StateRefreshFunc { return "available", "available", nil } } + +func expandKeyVaultNetworkAcls(input []interface{}) (*keyvault.NetworkRuleSet, []string) { + subnetIds := make([]string, 0) + if len(input) == 0 { + return nil, subnetIds + } + + v := input[0].(map[string]interface{}) + + bypass := v["bypass"].(string) + defaultAction := v["default_action"].(string) + + ipRulesRaw := v["ip_rules"].(*schema.Set) + ipRules := make([]keyvault.IPRule, 0) + + for _, v := range ipRulesRaw.List() { + rule := keyvault.IPRule{ + Value: utils.String(v.(string)), + } + ipRules = append(ipRules, rule) + } + + networkRulesRaw := v["virtual_network_subnet_ids"].(*schema.Set) + networkRules := make([]keyvault.VirtualNetworkRule, 0) + for _, v := range networkRulesRaw.List() { + rawId := v.(string) + subnetIds = append(subnetIds, rawId) + rule := keyvault.VirtualNetworkRule{ + ID: utils.String(rawId), + } + networkRules = append(networkRules, rule) + } + + ruleSet := keyvault.NetworkRuleSet{ + Bypass: keyvault.NetworkRuleBypassOptions(bypass), + DefaultAction: keyvault.NetworkRuleAction(defaultAction), + IPRules: &ipRules, + VirtualNetworkRules: &networkRules, + } + return &ruleSet, subnetIds +} diff --git a/azurerm/resource_arm_key_vault_test.go b/azurerm/resource_arm_key_vault_test.go index c8d589e1cc8f..1c8c55487fc1 100644 --- a/azurerm/resource_arm_key_vault_test.go +++ b/azurerm/resource_arm_key_vault_test.go @@ -70,6 +70,7 @@ func TestAccAzureRMKeyVault_name(t *testing.T) { } func TestAccAzureRMKeyVault_basic(t *testing.T) { + resourceName := "azurerm_key_vault.test" ri := acctest.RandInt() config := testAccAzureRMKeyVault_basic(ri, testLocation()) @@ -81,7 +82,44 @@ func TestAccAzureRMKeyVault_basic(t *testing.T) { { Config: config, Check: resource.ComposeTestCheckFunc( - testCheckAzureRMKeyVaultExists("azurerm_key_vault.test"), + testCheckAzureRMKeyVaultExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "network_acls.#", "0"), + ), + }, + }, + }) +} + +func TestAccAzureRMKeyVault_networkAcls(t *testing.T) { + resourceName := "azurerm_key_vault.test" + ri := acctest.RandInt() + location := testLocation() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMKeyVaultDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMKeyVault_networkAcls(ri, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMKeyVaultExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "network_acls.#", "1"), + resource.TestCheckResourceAttr(resourceName, "network_acls.0.bypass", "None"), + resource.TestCheckResourceAttr(resourceName, "network_acls.0.default_action", "Deny"), + resource.TestCheckResourceAttr(resourceName, "network_acls.0.ip_rules.#", "0"), + resource.TestCheckResourceAttr(resourceName, "network_acls.0.virtual_network_subnet_ids.#", "1"), + ), + }, + { + Config: testAccAzureRMKeyVault_networkAclsUpdated(ri, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMKeyVaultExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "network_acls.#", "1"), + resource.TestCheckResourceAttr(resourceName, "network_acls.0.bypass", "AzureServices"), + resource.TestCheckResourceAttr(resourceName, "network_acls.0.default_action", "Allow"), + resource.TestCheckResourceAttr(resourceName, "network_acls.0.ip_rules.#", "1"), + resource.TestCheckResourceAttr(resourceName, "network_acls.0.virtual_network_subnet_ids.#", "1"), ), }, }, @@ -287,6 +325,107 @@ resource "azurerm_key_vault" "test" { `, rInt, location, rInt) } +func testAccAzureRMKeyVault_networkAclsTemplate(rInt int, location string) string { + return fmt.Sprintf(` +data "azurerm_client_config" "current" {} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_virtual_network" "test" { + name = "acctestvirtnet%d" + address_space = ["10.0.0.0/16"] + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" +} + +resource "azurerm_subnet" "test" { + name = "acctestsubnet%d" + resource_group_name = "${azurerm_resource_group.test.name}" + virtual_network_name = "${azurerm_virtual_network.test.name}" + address_prefix = "10.0.2.0/24" + service_endpoints = ["Microsoft.KeyVault",] +} +`, rInt, location, rInt, rInt) +} + +func testAccAzureRMKeyVault_networkAcls(rInt int, location string) string { + template := testAccAzureRMKeyVault_networkAclsTemplate(rInt, location) + return fmt.Sprintf(` +%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" + } + + access_policy { + tenant_id = "${data.azurerm_client_config.current.tenant_id}" + object_id = "${data.azurerm_client_config.current.client_id}" + + key_permissions = [ + "create", + ] + + secret_permissions = [ + "set", + ] + } + + network_acls { + default_action = "Deny" + bypass = "None" + virtual_network_subnet_ids = ["${azurerm_subnet.test.id}"] + } +} +`, template, rInt) +} + +func testAccAzureRMKeyVault_networkAclsUpdated(rInt int, location string) string { + template := testAccAzureRMKeyVault_networkAclsTemplate(rInt, location) + return fmt.Sprintf(` +%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" + } + + access_policy { + tenant_id = "${data.azurerm_client_config.current.tenant_id}" + object_id = "${data.azurerm_client_config.current.client_id}" + + key_permissions = [ + "create", + ] + + secret_permissions = [ + "set", + ] + } + + network_acls { + default_action = "Allow" + bypass = "AzureServices" + ip_rules = ["10.0.0.102/32"] + virtual_network_subnet_ids = ["${azurerm_subnet.test.id}"] + } +} +`, template, rInt) +} + func testAccAzureRMKeyVault_update(rInt int, location string) string { return fmt.Sprintf(` data "azurerm_client_config" "current" {} diff --git a/website/docs/r/key_vault.html.markdown b/website/docs/r/key_vault.html.markdown index b672109071f0..22739b3b856d 100644 --- a/website/docs/r/key_vault.html.markdown +++ b/website/docs/r/key_vault.html.markdown @@ -21,15 +21,16 @@ resource "azurerm_resource_group" "test" { } resource "azurerm_key_vault" "test" { - name = "testvault" - location = "West US" - resource_group_name = "${azurerm_resource_group.test.name}" + name = "testvault" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + enabled_for_disk_encryption = true + tenant_id = "d6e396d0-5584-41dc-9fc0-268df99bc610" sku { name = "standard" } - tenant_id = "d6e396d0-5584-41dc-9fc0-268df99bc610" access_policy { tenant_id = "d6e396d0-5584-41dc-9fc0-268df99bc610" @@ -44,7 +45,11 @@ resource "azurerm_key_vault" "test" { ] } - enabled_for_disk_encryption = true + network_acls { + default_action = "Deny" + bypass = "None" + virtual_network_subnet_ids = ["${azurerm_subnet.test.id}"] + } tags { environment = "Production" @@ -56,71 +61,73 @@ resource "azurerm_key_vault" "test" { The following arguments are supported: -* `name` - (Required) Specifies the name of the Key Vault. Changing this - forces a new resource to be created. +* `name` - (Required) Specifies the name of the Key Vault. Changing this forces a new resource to be created. -* `location` - (Required) Specifies the supported Azure location where the resource exists. - Changing this forces a new resource to be created. +* `location` - (Required) Specifies the supported Azure location where the resource exists. Changing this forces a new resource to be created. -* `resource_group_name` - (Required) The name of the resource group in which to - create the Key Vault. Changing this forces a new resource to be created. +* `resource_group_name` - (Required) The name of the resource group in which to create the Key Vault. Changing this forces a new resource to be created. * `sku` - (Required) An SKU block as described below. -* `tenant_id` - (Required) The Azure Active Directory tenant ID that should be - used for authenticating requests to the key vault. +* `tenant_id` - (Required) The Azure Active Directory tenant ID that should be used for authenticating requests to the key vault. -* `access_policy` - (Optional) An access policy block as described below. A maximum of 16 - may be declared. +* `access_policy` - (Optional) An access policy block as described below. A maximum of 16 may be declared. ~> **NOTE:** It's possible to define Key Vault Access Policies both within [the `azurerm_key_vault` resource](key_vault.html) via the `access_policy` block and by using [the `azurerm_key_vault_access_policy` resource](key_vault_access_policy.html). However it's not possible to use both methods to manage Access Policies within a KeyVault, since there'll be conflicts. -* `enabled_for_deployment` - (Optional) Boolean flag to specify whether Azure Virtual - Machines are permitted to retrieve certificates stored as secrets from the key - vault. Defaults to false. +* `enabled_for_deployment` - (Optional) Boolean flag to specify whether Azure Virtual Machines are permitted to retrieve certificates stored as secrets from the key vault. Defaults to `false`. -* `enabled_for_disk_encryption` - (Optional) Boolean flag to specify whether Azure - Disk Encryption is permitted to retrieve secrets from the vault and unwrap keys. - Defaults to false. +* `enabled_for_disk_encryption` - (Optional) Boolean flag to specify whether Azure Disk Encryption is permitted to retrieve secrets from the vault and unwrap keys. Defaults to `false`. -* `enabled_for_template_deployment` - (Optional) Boolean flag to specify whether - Azure Resource Manager is permitted to retrieve secrets from the key vault. - Defaults to false. +* `enabled_for_template_deployment` - (Optional) Boolean flag to specify whether Azure Resource Manager is permitted to retrieve secrets from the key vault. Defaults to `false`. -* `tags` - (Optional) A mapping of tags to assign to the resource. +* `network_acls` - (Optional) A `network_acls` block as defined below. -`sku` supports the following: +* `tags` - (Optional) A mapping of tags to assign to the resource. -* `name` - (Required) SKU name to specify whether the key vault is a `standard` - or `premium` vault. +--- -`access_policy` supports the following: +A `access_policy` block supports the following: -* `tenant_id` - (Required) The Azure Active Directory tenant ID that should be used - for authenticating requests to the key vault. Must match the `tenant_id` used - above. +* `tenant_id` - (Required) The Azure Active Directory tenant ID that should be used for authenticating requests to the key vault. Must match the `tenant_id` used above. -* `object_id` - (Required) The object ID of a user, service principal or security - group in the Azure Active Directory tenant for the vault. The object ID must - be unique for the list of access policies. +* `object_id` - (Required) The object ID of a user, service principal or security group in the Azure Active Directory tenant for the vault. The object ID must be unique for the list of access policies. * `application_id` - (Optional) The object ID of an Application in Azure Active Directory. -* `certificate_permissions` - (Optional) List of certificate permissions, must be one or more from - the following: `create`, `delete`, `deleteissuers`, `get`, `getissuers`, `import`, `list`, `listissuers`, `managecontacts`, `manageissuers`, `purge`, `recover`, `setissuers` and `update`. +* `certificate_permissions` - (Optional) List of certificate permissions, must be one or more from the following: `create`, `delete`, `deleteissuers`, `get`, `getissuers`, `import`, `list`, `listissuers`, `managecontacts`, `manageissuers`, `purge`, `recover`, `setissuers` and `update`. + +* `key_permissions` - (Required) List of key permissions, must be one or more from the following: `backup`, `create`, `decrypt`, `delete`, `encrypt`, `get`, `import`, `list`, `purge`, `recover`, `restore`, `sign`, `unwrapKey`, `update`, `verify` and `wrapKey`. + +* `secret_permissions` - (Required) List of secret permissions, must be one or more from the following: `backup`, `delete`, `get`, `list`, `purge`, `recover`, `restore` and `set`. + + +--- + +A `network_acls` block supports the following: + +* `bypass` - (Required) Specifies which traffic can bypass the network rules. Possible values are `AzureServices` and `None`. + +* `default_action` - (Required) The Default Action to use when no rules match from `ip_rules` / `virtual_network_subnet_ids`. Possible values are `Allow` and `Deny`. + +* `ip_rules` - (Optional) One or more IP Addresses, or CIDR Blocks which should be able to access thie Key Vault. -* `key_permissions` - (Required) List of key permissions, must be one or more from - the following: `backup`, `create`, `decrypt`, `delete`, `encrypt`, `get`, `import`, `list`, `purge`, `recover`, `restore`, `sign`, `unwrapKey`, `update`, `verify` and `wrapKey`. +* `virtual_network_subnet_ids` - (Optional) One or more Subnet ID's which should be able to access this Key Vault. + +--- + +A `sku` block supports the following: + +* `name` - (Required) The Name of the SKU used for this Key Vault. Possible values are `Standard` and `Premium`. -* `secret_permissions` - (Required) List of secret permissions, must be one or more - from the following: `backup`, `delete`, `get`, `list`, `purge`, `recover`, `restore` and `set`. ## Attributes Reference The following attributes are exported: -* `id` - The Vault ID. -* `vault_uri` - The URI of the vault for performing operations on keys and secrets. +* `id` - The ID of the Key Vault. + +* `vault_uri` - The URI of the Key Vault, used for performing operations on keys and secrets. ## Import From 5ec189ae8fe1d43bbee7ff4775d038d85f7e5458 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Fri, 5 Oct 2018 14:16:46 +1000 Subject: [PATCH 3/6] Storage Account: ensuring we lock on the Virtual Network name during deletion Fixes #1491 ``` $ acctests azurerm TestAccAzureRMStorageAccount_networkRules === RUN TestAccAzureRMStorageAccount_networkRules --- PASS: TestAccAzureRMStorageAccount_networkRules (242.68s) === RUN TestAccAzureRMStorageAccount_networkRulesDeleted --- PASS: TestAccAzureRMStorageAccount_networkRulesDeleted (193.87s) PASS ok github.com/terraform-providers/terraform-provider-azurerm/azurerm 437.440s ``` --- azurerm/resource_arm_storage_account.go | 42 +++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/azurerm/resource_arm_storage_account.go b/azurerm/resource_arm_storage_account.go index b1740bcc0714..b3aac9b856a6 100644 --- a/azurerm/resource_arm_storage_account.go +++ b/azurerm/resource_arm_storage_account.go @@ -10,6 +10,7 @@ import ( "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2017-10-01/storage" "github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/helper/validation" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/response" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) @@ -730,11 +731,46 @@ func resourceArmStorageAccountDelete(d *schema.ResourceData, meta interface{}) e return err } name := id.Path["storageAccounts"] - resGroup := id.ResourceGroup + resourceGroup := id.ResourceGroup + + read, err := client.GetProperties(ctx, resourceGroup, name) + if err != nil { + if utils.ResponseWasNotFound(read.Response) { + return nil + } + + return fmt.Errorf("Error retrieving Storage Account %q (Resource Group %q): %+v", name, resourceGroup, err) + } + + virtualNetworkNames := make([]string, 0) + if props := read.AccountProperties; props != nil { + if rules := props.NetworkRuleSet; rules != nil { + if vnr := rules.VirtualNetworkRules; vnr != nil { + for _, v := range *vnr { + if v.VirtualNetworkResourceID == nil { + continue + } - _, err = client.Delete(ctx, resGroup, name) + id, err := parseAzureResourceID(*v.VirtualNetworkResourceID) + if err != nil { + return err + } + + networkName := id.Path["virtualNetworks"] + virtualNetworkNames = append(virtualNetworkNames, networkName) + } + } + } + } + + azureRMLockMultipleByName(&virtualNetworkNames, virtualNetworkResourceName) + defer azureRMUnlockMultipleByName(&virtualNetworkNames, virtualNetworkResourceName) + + resp, err := client.Delete(ctx, resourceGroup, name) if err != nil { - return fmt.Errorf("Error issuing AzureRM delete request for storage account %q: %+v", name, err) + if !response.WasNotFound(resp.Response) { + return fmt.Errorf("Error issuing delete request for Storage Account %q (Resource Group %q): %+v", name, resourceGroup, err) + } } return nil From 50ac1d748f654d6d39f52bd29e0a8dcf0d817626 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Fri, 5 Oct 2018 15:05:53 +1000 Subject: [PATCH 4/6] Data Source: `azurerm_key_vault` - exposing `network_acls` --- azurerm/data_source_key_vault.go | 74 ++++++++++++++++++++++++++- azurerm/data_source_key_vault_test.go | 43 ++++++++++++++++ 2 files changed, 116 insertions(+), 1 deletion(-) diff --git a/azurerm/data_source_key_vault.go b/azurerm/data_source_key_vault.go index 8c49985c77dc..9e69afe476e2 100644 --- a/azurerm/data_source_key_vault.go +++ b/azurerm/data_source_key_vault.go @@ -6,6 +6,7 @@ import ( "github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2018-02-14/keyvault" "github.com/hashicorp/terraform/helper/schema" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/set" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) @@ -105,6 +106,35 @@ func dataSourceArmKeyVault() *schema.Resource { Computed: true, }, + "network_acls": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "default_action": { + Type: schema.TypeString, + Computed: true, + }, + "bypass": { + Type: schema.TypeString, + Computed: true, + }, + "ip_rules": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, + }, + "virtual_network_subnet_ids": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: set.HashStringIgnoreCase, + }, + }, + }, + }, + "tags": tagsForDataSourceSchema(), }, } @@ -138,6 +168,8 @@ func dataSourceArmKeyVaultRead(d *schema.ResourceData, meta interface{}) error { d.Set("enabled_for_deployment", props.EnabledForDeployment) d.Set("enabled_for_disk_encryption", props.EnabledForDiskEncryption) d.Set("enabled_for_template_deployment", props.EnabledForTemplateDeployment) + d.Set("vault_uri", props.VaultURI) + if err := d.Set("sku", flattenKeyVaultDataSourceSku(props.Sku)); err != nil { return fmt.Errorf("Error flattening `sku` for KeyVault %q: %+v", *resp.Name, err) } @@ -146,7 +178,10 @@ func dataSourceArmKeyVaultRead(d *schema.ResourceData, meta interface{}) error { if err := d.Set("access_policy", flattenedPolicies); err != nil { return fmt.Errorf("Error flattening `access_policy` for KeyVault %q: %+v", *resp.Name, err) } - d.Set("vault_uri", props.VaultURI) + + if err := d.Set("network_acls", flattenKeyVaultDataSourceNetworkAcls(props.NetworkAcls)); err != nil { + return fmt.Errorf("Error flattening `network_acls` for KeyVault %q: %+v", *resp.Name, err) + } } flattenAndSetTags(d, resp.Tags) @@ -161,3 +196,40 @@ func flattenKeyVaultDataSourceSku(sku *keyvault.Sku) []interface{} { return []interface{}{result} } + +func flattenKeyVaultDataSourceNetworkAcls(input *keyvault.NetworkRuleSet) []interface{} { + if input == nil { + return []interface{}{} + } + + output := make(map[string]interface{}, 0) + + output["bypass"] = string(input.Bypass) + output["default_action"] = string(input.DefaultAction) + + ipRules := make([]interface{}, 0) + if input.IPRules != nil { + for _, v := range *input.IPRules { + if v.Value == nil { + continue + } + + ipRules = append(ipRules, *v.Value) + } + } + output["ip_rules"] = schema.NewSet(schema.HashString, ipRules) + + virtualNetworkRules := make([]interface{}, 0) + if input.VirtualNetworkRules != nil { + for _, v := range *input.VirtualNetworkRules { + if v.ID == nil { + continue + } + + virtualNetworkRules = append(virtualNetworkRules, *v.ID) + } + } + output["virtual_network_subnet_ids"] = schema.NewSet(schema.HashString, virtualNetworkRules) + + return []interface{}{output} +} diff --git a/azurerm/data_source_key_vault_test.go b/azurerm/data_source_key_vault_test.go index d2881e3e799c..53817cc29578 100644 --- a/azurerm/data_source_key_vault_test.go +++ b/azurerm/data_source_key_vault_test.go @@ -65,6 +65,37 @@ func TestAccDataSourceAzureRMKeyVault_complete(t *testing.T) { }) } +func TestAccDataSourceAzureRMKeyVault_networkAcls(t *testing.T) { + dataSourceName := "data.azurerm_key_vault.test" + ri := acctest.RandInt() + location := testLocation() + config := testAccDataSourceAzureRMKeyVault_networkAcls(ri, location) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMKeyVaultDestroy, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMKeyVaultExists(dataSourceName), + resource.TestCheckResourceAttrSet(dataSourceName, "tenant_id"), + resource.TestCheckResourceAttrSet(dataSourceName, "sku.0.name"), + resource.TestCheckResourceAttrSet(dataSourceName, "access_policy.0.tenant_id"), + resource.TestCheckResourceAttrSet(dataSourceName, "access_policy.0.object_id"), + resource.TestCheckResourceAttr(dataSourceName, "access_policy.0.key_permissions.0", "get"), + resource.TestCheckResourceAttr(dataSourceName, "access_policy.0.secret_permissions.0", "get"), + resource.TestCheckResourceAttr(dataSourceName, "network_acls.#", "1"), + resource.TestCheckResourceAttr(dataSourceName, "network_acls.0.default_action", "Allow"), + resource.TestCheckResourceAttr(dataSourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(dataSourceName, "tags.environment", "Production"), + ), + }, + }, + }) +} + func testAccDataSourceAzureRMKeyVault_basic(rInt int, location string) string { resource := testAccAzureRMKeyVault_basic(rInt, location) return fmt.Sprintf(` @@ -88,3 +119,15 @@ data "azurerm_key_vault" "test" { } `, resource) } + +func testAccDataSourceAzureRMKeyVault_networkAcls(rInt int, location string) string { + resource := testAccAzureRMKeyVault_networkAclsUpdated(rInt, location) + return fmt.Sprintf(` +%s + +data "azurerm_key_vault" "test" { + name = "${azurerm_key_vault.test.name}" + resource_group_name = "${azurerm_key_vault.test.resource_group_name}" +} +`, resource) +} From 6c78838b76252cf8cd11f647b275403c00ee8aa9 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Fri, 5 Oct 2018 23:39:45 +1000 Subject: [PATCH 5/6] Fixing the data source test ``` $ acctests azurerm TestAccDataSourceAzureRMKeyVault_networkAcls === RUN TestAccDataSourceAzureRMKeyVault_networkAcls --- PASS: TestAccDataSourceAzureRMKeyVault_networkAcls (310.74s) PASS ok github.com/terraform-providers/terraform-provider-azurerm/azurerm 311.651s ``` --- azurerm/data_source_key_vault_test.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/azurerm/data_source_key_vault_test.go b/azurerm/data_source_key_vault_test.go index 53817cc29578..950016cdf2db 100644 --- a/azurerm/data_source_key_vault_test.go +++ b/azurerm/data_source_key_vault_test.go @@ -84,12 +84,11 @@ func TestAccDataSourceAzureRMKeyVault_networkAcls(t *testing.T) { resource.TestCheckResourceAttrSet(dataSourceName, "sku.0.name"), resource.TestCheckResourceAttrSet(dataSourceName, "access_policy.0.tenant_id"), resource.TestCheckResourceAttrSet(dataSourceName, "access_policy.0.object_id"), - resource.TestCheckResourceAttr(dataSourceName, "access_policy.0.key_permissions.0", "get"), - resource.TestCheckResourceAttr(dataSourceName, "access_policy.0.secret_permissions.0", "get"), + resource.TestCheckResourceAttr(dataSourceName, "access_policy.0.key_permissions.0", "create"), + resource.TestCheckResourceAttr(dataSourceName, "access_policy.0.secret_permissions.0", "set"), resource.TestCheckResourceAttr(dataSourceName, "network_acls.#", "1"), resource.TestCheckResourceAttr(dataSourceName, "network_acls.0.default_action", "Allow"), - resource.TestCheckResourceAttr(dataSourceName, "tags.%", "1"), - resource.TestCheckResourceAttr(dataSourceName, "tags.environment", "Production"), + resource.TestCheckResourceAttr(dataSourceName, "tags.%", "0"), ), }, }, From 5b9b2a982f6b6ad864b04a30b947a19ee0ede9d1 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Sat, 6 Oct 2018 12:07:59 +1000 Subject: [PATCH 6/6] Documenting why we're locking --- azurerm/resource_arm_storage_account.go | 1 + 1 file changed, 1 insertion(+) diff --git a/azurerm/resource_arm_storage_account.go b/azurerm/resource_arm_storage_account.go index b3aac9b856a6..c7b6fe2ac113 100644 --- a/azurerm/resource_arm_storage_account.go +++ b/azurerm/resource_arm_storage_account.go @@ -742,6 +742,7 @@ func resourceArmStorageAccountDelete(d *schema.ResourceData, meta interface{}) e return fmt.Errorf("Error retrieving Storage Account %q (Resource Group %q): %+v", name, resourceGroup, err) } + // the networking api's only allow a single change to be made to a network layout at once, so let's lock to handle that virtualNetworkNames := make([]string, 0) if props := read.AccountProperties; props != nil { if rules := props.NetworkRuleSet; rules != nil {