Skip to main content
Pure Technical Services

Deploy using Terraform | Pure CBS on Azure

Currently viewing public documentation. Please login to access the full scope of documentation.


This KB is updated for Terrafrom-provider-cbs v0.9.0


This document demonstrates the steps required to deploy Pure Cloud Block Store (CBS) in Azure using Terraform. 


CBS Prerequisites

A number of mandatory resources have to be checked and configured prior to deployment, please refer to the Cloud Block Store Deployment and Configuration Guide for Azure for more details on the following high-level steps: 

  • Region selected is supported by CBS. 
  • Have an Azure Active Directory Premium 2 license. 
  • Set the appropriate User IAM roles and permissions. 
  • Networking - VNet and Subnets. 
  • Networking – Outbound Internet access using NAT GW or Azure Firewall.
  • Networking – service endpoint (CosmosDB and KeyVault) attached to the designated subnet.
  • Cloud Block Store license key. 

For POC purposes, there is a Quick Launch Terraform module that would create all the CBS prerequisites and also deploy CBS with a Jump Host. Refer to this link: cbs-deploy-terraform github repo

Terraform Prerequisites

The following are infrastructure and resources are mandatory for successful Terraform deployment:

Local or Virtual Machine

The machine running Terraform code whether its local machine or an Azure VMIt has to have two characteristics: 

  1. Has connectivity to CBS Azure VNet network mentioned in the previous section. 
  2. Can authenticate to Azure using one of the methods listed below: Azure CLI or Azure Service Principle.  

The recommended method for connectivity is to have an Azure VM to run the Terraform code, Then peer the VM VNet with the CBS VNet. 

Example for Azure Portal, Azure CLI, and PowerShell can be found here Create a peering

Install Terraform

Download and install the appropriate Terraform package for your operating system and hardware architecture via the link below:

Download CBS Terraform provider files Edit section

Create a new directory for the Terraform deployment, and copy or download Terraform provider sample for CBS Azure (Three files shown on the screenshot)from the below link:



Authenticate to Azure

There are two ways to authenticate to an Azure account:

1. Azure CLI

Download and install the latest version of the Azure CLI tool via the link below:

For authentication, log in to the Azure CLI:

az login

And list the Subscriptions associated with the account:

az account list

if the user logging in has more than one Subscription. Specify the Subscription to be the default:

az account set --subscription="SUBSCRIPTION_ID"

2.Azure Service Principal

Terraform can be authenticated with a Service Principal in the provider configuration under file by adding the following:

provider "cbs" {
    azure {
        client_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
        client_secret = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
        subscription_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
        tenant_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

For step-by-step on how to create Azure Service Principle, follow this link:  Creating a Service Principal in the Azure Portal

Key Vault

Along with the infrastructure components defined in the CBS Prerequisite, an Azure Key Vault is required to deploy Cloud Block Store in Azure using Terraform. An existing Key Vault may be used, or a new one can be created for the array. Multiple arrays may reuse the same Key Vault.

Any Azure account that wishes to use Terraform to perform management operations on the array must be granted GetSetDeleteList, and Recoverpermissions on secrets within the Key Vault. All secrets created or accessed by the CBS Terraform Provider will use a cbs- prefix.

An example Key Vault creation using the azurerm_key_vault resource from the azurerm provider is shown below. 

## Add This snippet to
data "azurerm_client_config" "client_config" {}

// Key Vault name must be globally unique
resource "random_id" "vault_id" {
    byte_length = 8

resource "azurerm_key_vault" "cbs_key_vault" {
    name                        = "cbs-${random_id.vault_id.hex}"
    location                    = "location_xxxx"
    resource_group_name         = "resource_yyyy"
    tenant_id                   = data.azurerm_client_config.client_config.tenant_id

    sku_name = "standard"

    access_policy {
        tenant_id          = data.azurerm_client_config.client_config.tenant_id
        object_id          = data.azurerm_client_config.client_config.object_id
        secret_permissions = ["Get", "Set", "Delete", "List", "Recover"]

User Managed Identity

After Purity 6.4.7, CBS deployment would require passing a user managed identity with specific role permissions. In order to configure the Azure role assignment and create a user managed identity within Terraform, you can copy the example below to  which is following Azure least privilege access. More information about User Managed Identity in implementing guide.  

data "azurerm_subscription" "primary" {

resource "azurerm_user_assigned_identity" "user_identity" {
  location            = var.resource_group_location
  resource_group_name = var.resource_group_name
  name                = format("%s%s", var.resource_group_name, "user-assigned-identity")
  tags                = var.tags

data "azurerm_resource_group" "rg_id" {
  name = var.resource_group_name

resource "azurerm_role_definition" "cbs_role" {
  name  = format("%s%s", var.resource_group_name, "cbs-custom-role-definition")
  scope =

  permissions {
    actions     = ["Microsoft.Network/virtualNetworks/subnets/joinViaServiceEndpoint/action"]
    not_actions = []

resource "azurerm_role_assignment" "role_assignment" {
  scope                = var.cbs_vnet_id
  role_definition_name =
  principal_id         = azurerm_user_assigned_identity.user_identity.principal_id

Private Key

In order to set up long term management of new arrays, the provider must obtain access to the array during deployment in order to obtain management credentials. In order to accomplish this, the provider must be supplied a private SSH key, either a file path to the key with the pureuser_private_key_path parameter or the key text itself with the pureuser_private_key parameter. The management credentials are stored in the Azure Key Vault that is specified by the key_vault_id parameter. To retrieve the credentials, the provider requires access to the management port of the array, and therefore the machine running Terraform must be able to access the management subnet used for the array.


By navigating to the downloaded Terraform sample, use any text editor to edit the terraform.tfvars file and fill the prerequisites. An example screenshot is provided below for additional guidance.


Variables Reference:

  1. array_name (Required) - Name of the array, and the name of the managed application.
  2. location (Required) - Azure location in which to deploy the array.
  3. resource_group_name (Required) - Name of the resource group in which to deploy the managed application.
  4. license_key (Required) - Pure Storage-provided license key. 
    - For Evaluation Mode Trial License use this key: CBS-TRIAL-LICENSE
  5. log_sender_domain (Required) - Domain name used to determine how CBS logs are parsed and treated by Pure Storage Support and Escalations.
  6. alert_recipients (Optional) - List of email addresses to receive alerts.
  7. array_model (Required) - CBS array size to launch. The possible values are V10MUR1 or V20MUR1 or V20MP2R2.
  8. zone (Required) - The Availability Zone within the deployment location.
  9. virtual_network_id (Required) - Virtual network id that contains the network interfaces of the array.
  10. key_vault_id (Required) - Key Vault where provider stores sensitive information
    - Do not include this on terraform.tfvars nor if you would like to use the Terraform code from Key Vault section. 
  11. management_subnet (Required) - Subnet containing the management interfaces on the array.
  12. system_subnet (Required) - Subnet for the system interface of the Array.
  13. iscsi_subnet (Required) - Subnet containing the iSCSI interfaces on the array.
  14. replication_subnet (Required) - Subnet containing the replication interfaces on the array.
  15. jit-groups-ids (Required) - A list of Azure Active Directory groups that enable their users to approve JIT access requests.
  16. plan_name (Required) - Specifies the name of the plan from the marketplace.
  17. plan_product (Required) - Specifies the product of the plan from the marketplace.
  18. plan_publisher (Required) - Specifies the publisher of the plan.
  19. pureuser_private_key_path (Required) - File path of the private key to enable SSH access to the controllers. You must specify one pureuser_private_key_path or one pureuser_private_key.
  20. pureuser_private_key (Required) - Text content of the private key to enable SSH access to the controllers. You must specify one pureuser_private_key_path or one pureuser_private_key.
  21. user_managed_identity (Required) - Specifies the id of the user managed identity, read more in User Managed Identity section.
  22. tags (Optional) - A list of tags to apply to all resources in the managed application.

Save the changes to the file, and open a terminal window and navigate to the Terraform deployment directory that has been created, and Run terraform init command to initialize the working directory.


Next, Run the terraform plan command to create the execution plan.



Finally, Run the terraform apply command to execute the plan and start deploying.


The Cloud Block Store deployment process takes around 10 to 15 minutes. Go to Azure Managed Applications, A new managed application should be created and in the deployment state.


Once the terraform apply command is complete, Run terraform show command to list the output information of the CBS deployment stack. This includes the management IP address that is used to log into the CBS.


More information can be found by logging to Azure console and navigating to Managed Application, then under the tab Parameters and Output. The Management IP address used to log in CBS is addressed as FloatingManagementIP.


Use the Management IP address to log into GUI Management Console via any browser. To access the CBS instance via CLI, refer to Logging onto CBS via CLI section in the Deployment and Configuration Guide.



Do not use the terraform destroy command to destroy Cloud Block Store instance deployed via Terraform. Please refer to Removing Cloud Block Store section in the Deployment and Configuration Guide and follow the instructions. 


Marketplace Offer Terms are not Accepted 

│ Error: failed to create Managed Application "tf-adam-fusion-cbs-EASTUS-CBS" (Resource Group "tf-adam-fusion-cbs-EASTUS"): 
managedapplications.ApplicationsClient#CreateOrUpdate: Failure sending request: StatusCode=400 
-- Original Error: Code="ResourcePurchaseValidationFailed" Message="User failed validation to purchase resources. 
Error message: 'You have not accepted the legal terms on this subscription: '81cefe76-78c0-4df5-a564-e900f1ae2ba0' for this plan. 
Before the subscription can be used, you need to accept the legal terms of the image. 
To read and accept legal terms, use the Azure CLI commands described at 
or the PowerShell commands available at 
Alternatively, deploying via the Azure portal provides a UI experience for reading and accepting the legal terms. 
Offer details: publisher='purestoragemarketplaceadmin' offer = 'pure_storage_cloud_block_store_deployment', 
sku = 'cbs_azure_6_4_5', Correlation Id: 'a13685de-a008-48a8-8ff8-ecfcfd00e043'.'"
│   with cbs_array_azure.azure_cbs,
│   on line 200, in resource "cbs_array_azure" "azure_cbs":
│  200: resource "cbs_array_azure" "azure_cbs" {

To resolve this, you can choose to accept the offer via Azure CLI or Azure PowerShell SDK. 


az vm image terms accept [--offer] [--plan] [--publisher]

Example (Parameters from the error above): 

az vm image terms accept --offer "pure_storage_cloud_block_store_deployment" --plan "cbs_azure_6_4_5" --publisher "purestoragemarketplaceadmin"


Get-AzMarketplaceTerms -Publisher '<publisher name>'-Product '<product name>' -Name '<plan name>' | Set-AzMarketplaceTerms -Accept

Example (Parameters from the error above): 

Get-AzMarketplaceTerms -Publisher 'purestoragemarketplaceadmin' -Product 'pure_storage_cloud_block_store_deployment' -Name 'cbs_azure_6_4_5' | Set-AzMarketplaceTerms -Accept

Marketplace Plan already Exists 

If you have already deployed the same version of Cloud Block Store (ex: 6.4.2) in the same subscription. You might get the below error after applying the code. 

azurerm_key_vault.cbs_key_vault: Creation complete after 2m34s [id=/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/
│ Error: A resource with the ID "/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.MarketplaceOrdering/agreements/
already exists - to be managed via Terraform this resource needs to be imported into the State. Please see the resource documentation for "azurerm_marketplace_agreement" for more information.
│   with azurerm_marketplace_agreement.plan,
│   on line 27, in resource "azurerm_marketplace_agreement" "plan":
│   27: resource "azurerm_marketplace_agreement" "plan" {

To resolve this, you would need to import the plan to Terraform state 

terraform import azurerm_marketplace_agreement.plan /subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.MarketplaceOrdering/agreements/purestoragemarketplaceadmin/offers/pure_storage_cloud_block_store_deployment/plans/cbs_azure_6_4_2