Enable Modern Authentication on Office 365

I recently implemented Multifactor authentication for our O365/Azure users. Our users connect to Azure Portal and Office 365 using a variety of client apps. These applications handle MFA differently. I also needed to update Office 365 to allow modern authentication. This was required because Outlook 2016 for Windows was unable to add my Office 365 email account without modern authentication.


  1. Enable MFA using Azure Active Directory: https://docs.microsoft.com/en-us/azure/active-directory/authentication/howto-mfa-mfasettings     It also describes how to generate App Passwords. App Passwords are required for Office 365 clients that cannot handle MFA. App Password actually bypass MFA so use them only if needed.
  2. I tried to add my office 365 account in the mail client for my IPhone. To my surprise it allowed my to enter my password and MFA code to configure my mail account. It did not require using App passwords.
  3. I tried to add my Office 365 account to Outlook 2016 on windows 10. It failed to add my account and did not show a helpful message.
  4. To resolve above issue I had to enable modern authentication on my office 365 tenants. The steps were:
    1. Connect with Exchange Online PowerShell using the steps below: https://docs.microsoft.com/en-us/powershell/exchange/exchange-online/connect-to-exchange-online-powershell/connect-to-exchange-online-powershell?view=exchange-ps     When you run the script  you will need to use your App Password to authenticate with Office 365
    2. Once you are successfully connected you can view your current settings for OAuth2ClientProfileEnabled using the command:

  5. Set-OrganizationConfig -OAuth2ClientProfileEnabled $true

    Get-OrganizationConfig | Format-Table -Auto Name,OAuth*

    Name OAuth2ClientProfileEnabled
    ---- --------------------------
    xxxxxxxxxx.onmicrosoft.com True

  6. After enabling OAuth2ClientProfileEnabled I was able to successfully add my Office 365 email account to Outlook 2016 on Windows.
Posted in Uncategorized | Tagged | Leave a comment

DevOps – Infrastructure as Code on Azure Platform with Hashicorp Terraform Part 1

At Cheval Partners, we believe that infrastructure as code is essential to get most out of your cloud platforms. Infrastructure as code is also required to implement immutable infrastructure. Hashicorp has a suite of products that make it easy to implement infrastructure as code on numerous public and private cloud platforms. We have been leveraging Hashicorp tools for the past year for AWS implementations. We have many clients that are deploying applications on Azure Platform. We were unable to use Hashicorp tools with Azure because Azure Resource Manager support was missing. We were ecstatic to read this announcement from Hashicorp that Packer and Terraform now support Azure Resource manager.


I will use this blog post to introduce you to using Terraform to provision Azure Resource Manager resources.

Imperative or Declarative

There are two different ways in which you can implement infrastructure as code.


Imperative method uses scripts or code to provision your services. Here are a few examples:

AWS: You are using bash scripts that leverage AWS CLI. Another example of AWS is the excellent AWS python SDK boto3.

Azure: You use Azure PowerShell cmdlets to provision the services


Here you are defining templates for your infrastructure. Some examples of this are:

AWS: CloudFormation

Azure: Azure Resource Manager


Both Imperative and Declarative method of implementing infrastructure as code are better than manual error prone resource provisioning. However with imperative method you are responsible for deploying services in correct order and recovering from failures. As the number of services grows the scripts become brittle.


Terraform provides a common configuration to launch infrastructure — from physical and virtual servers to email and DNS providers. Once launched, Terraform safely and efficiently changes infrastructure as the configuration is evolved.

Simple file based configuration gives you a single view of your entire infrastructure. Terraform is a declarative method of resource provisioning.

Terraform can be used to provision resources in Azure, AWS, Google, Openstack, Digital Ocean and many other providers and services. You can see the complete list of supported providers here:


Terraform uses Hashicorp configuration language(HCL) to define the infrastructure. Once you learn HCL, you will be able to use many different providers for public and private clouds to provision infrastructure.

I want to take this opportunity to make a case for Terraform. I have heard many different arguments against using Terraform.

1. Not multi-cloud: Even if you are not provisioning infrastructure in multiple clouds you will find learning HCL to be easier and intuitive. It will also give you an ability to provision infrastructure in other clouds in future.

2. Can’t keep up with cloud provider: I heard that most of the cloud providers(AWS, Azure) are constantly adding new services. So tools like Terraform will fall behind. However, open source community and Hashicorp has done an excellent job of keeping up and in some cases staying ahead of the cloud provider. This is especially true for their AWS provider. In mid December AWS released NAT Gateway. By the time I went to the google group for Terraform: https://groups.google.com/forum/#!forum/terraform-tool somebody had already asked about Terraform AWS Nat Gateway suppord and they were told that support is coming.  AWS Nat Gateway was supported by Terraform even before AWS CloudFormation.

4. What if a certain feature is not supported in Terraform? Terraform allows you to call AWS CloudFormation or ARM Templates, and you can also use a custom script that invokes CLI to provision resources that are not supported by Terraform. You can implement the feature and contribute it back to the community. If you still have concerns check out their change log and release schedule here: https://github.com/hashicorp/terraform/blob/master/CHANGELOG.md.

They have been releasing new features and services on a monthly basis.

5. What happens if Hashicorp ceases to exist? Hashicorp is a startup but most of their tools are open source. Vagrant is one of their first tool and it has been around for long time. No one can predict the future but the community is active and engaged and supporting Terraform. Containers, Microservices, Multi-cloud deployments are here to stay and Hashicorp tools can help.


Azure Provider for Hashicorp is located here:


Use cases: https://www.terraform.io/intro/use-cases.html

Terraform vs Other Software: https://www.terraform.io/intro/vs/index.html


Terraform is an open source tool developed in go language. Since it was developed in go language, it is can run on 6 different operating systems including Windows and Mac OS. Same is true for other Hashicorp tools as well. We will cover those in future blog posts.

Installation is as simple as downloading the version suitable for your operating system from here: https://www.terraform.io/downloads.html

It is an executable so you will just have to add it to your path to make it convenient for you to run it.

Verify installation

I installed Terraform on Windows I opened a cmd window and ran

terraform –version

to view its version. I got the following output.


Azure Credentials for Terraform

The process to get Azure credentials for Terraform is a bit convoluted.

You need the subscription_id, client_id, client_secret, tenant_id.

1:  # Configure the Azure Resource Manager Provider  
2:  provider "azurerm" {  
3:   subscription_id = "..."  
4:   client_id    = "..."  
5:   client_secret  = "..."  
6:   tenant_id    = "..."  
7:  }  


You can use the new Azure Portal http://portal.azure.com to find subscription_id. You can browse the list of subscriptions and get the subscription_id.


You can get the value of client_id, client_secret and tenant_id using these steps:

  1. Creating Azure Active directory application
  2. Creating an authentication key
  3. Setting delegated permissions
  4. Assigning application to a role that has appropriate permissions to provision resources.

You will not have to perform this setup frequently so it may be easiest to use the portal.


Here are the instructions If you want to use PowerShell to perform these steps:


Show me HCL

The following script creates a new resource group and provisions a virtual network.

Lines 10-13 specify the name of the new resource group and its location.

Lines 15-25 define an ARM virtual network named “productionNetwork”. It also defined three subnets.

1:  # Configure the Azure Resource Manager Provider  
2:  provider "azurerm" {  
3:   subscription_id = "..."  
4:   client_id    = "..."  
5:   client_secret  = "..."  
6:   tenant_id    = "..."  
7:  }  
9:  # Create a resource group  
10:  resource "azurerm_resource_group" "production" {  
11:    name   = "production"  
12:    location = "West US"  
13:  }  
15:  # Create a virtual network in the web_servers resource group  
16:  resource "azurerm_virtual_network" "network" {  
17:   name        = "productionNetwork"  
18:   address_space    = [""]  
19:   location      = "West US"  
20:   resource_group_name = "${azurerm_resource_group.production.name}"  
22:   subnet {  
23:    name      = "subnet1"  
24:    address_prefix = ""  
25:   }  
27:   subnet {  
28:    name      = "subnet2"  
29:    address_prefix = ""  
30:   }  
32:   subnet {  
33:    name      = "subnet3"  
34:    address_prefix = ""  
35:   }  
36:  }  


After saving the script you can first execute the statement

terraform plan

You can review the full help for terraform plan command here:


This command examines your configuration and your current state. It lists resources it will create, destroy or modify. It is one of the best features of Terraform. Terraform allows you to organize your configuration into modules. My current example does not use modules. If you were using modules you will need to run the command:

terraform plan –module-depth=-1

As you can see from the output below it shows that a new resource group will be provisioned. It also shows that a new virtual network with 3 subnets will be provisioned.


terraform apply

If the plan shows you the services, you wanted to provision the next step is to provision the infrastructure. You need to use apply command to provision or update your infrastructure.

terraform apply –help

shows you various command line options that are available.

You can also see the detailed help here:



terraform apply output is shown above. It shows that a new resource group and virtual network. You can use the portal and verify that these resources were created successfully. It also shows that the state of your infrastructure was saved successfully to terraform.tfstate file. This file needs to be saved and checked into source control. There are other options to store this file in a central location. They will be covered in a future blog post.

Remove the infrastructure

You can delete your entire infrastructure provisioned by terraform using the command.

terraform destroy command is used to destroy the infrastructure. You are prompted to confirm before the actual destruction takes place.




Closing Thoughts

I have introduced Terraform and shown how you can use it to provision resources on Azure Platform. Terraform Azure Resource Manager provider is less than a week old. It does not cover all the services yet. With their monthly releases, more services will be supported in near future. If you find issues or have feature requests you can log them here:


If you want to contribute you can make a pull request here:


In part 2 of this blog post series I will added virtual machine, public IP’s and manage DNS using Azure DNS.

Posted in ARM, Automation, Azure, DevOps, Hashicorp | Tagged , , , , | 2 Comments

Steps to becoming Self Employed

Over 15 years ago I decided to become self-employed IT Consultant. I was already a consultant for 5 years before that so becoming self-employed seemed the next logical step to me. At that time, I had written a word document that described the steps I took to setup my consulting business. Over the years, I shared this document with many people and asked them to update it and share it back with me. If you are considering self-employment I want to share these resources with you. I live in Minnesota so some of the information may not apply to you.

Legal Entity

The very first decision you need to make is what type of legal entity you need to setup for your business. Here are some options:

LLC’s have fewer paperwork requirements and are easier to manage as compared with S. Corporation. Your circumstances may vary so this is one of the first decision you need to make. You may want to consult your Certified Public Accountant to determine which option is best for you.

Name of your Legal Entity

Once you have decided the type of legal entity you need to create you will need to select its name. Most businesses have a website so you may start with finding out if a domain name is still available.

Domain Name

You website address is also known as your domain name. You can check if a domain name is still available from any website registrar like GoDaddy. https://www.godaddy.com/

Legal Entity Name

Before you purchase your domain name you need to make sure that the name is available in the state where you are forming the legal entity. Most states have business information lookup website you can use.

In Minnesota, you can l do a name search at https://mblsportal.sos.state.mn.us/

Federal Tax Identification Number

Every Legal entity is required to have a Federal Tax Identification Number. You can apply for it online: https://www.irs.gov/Businesses/Small-Businesses-&-Self-Employed/Apply-for-an-Employer-Identification-Number-(EIN)-Online

State Tax Identification Number

Most states require you to get a state tax identification number. For the state of Minnesota, you can get a tax identification number here: http://www.revenue.state.mn.us/businesses/withholding/Pages/HowdoIgetaMinnesotawithholdingtaxIDnumber.aspx

State Unemployment ID

You will also need to setup an account with your state unemployment office. In Minnesota you can open your account here:



You will need to open a dedicated business checking account for your business. You will need to have Federal TIN before you can open a business checking account. You may also want to open a business savings account.

You can look at http://www.bankrate.com to find a bank that will meet your needs.

Credit/Debit Cards

When opening your bank account you may also want to apply for a credit and debit cards. Always charge your business related expenses on your business credit card. This makes it easier to do your bookkeeping.

Business Checks

I found Costco to be one of the least expensive places to print business checks.



Certified Pubic Accountant

Business taxes are different than personal taxes so it may be worthwhile to find a reputable Certified Public Accountant(CPA) to help you with your business Taxes

Accounting Software

In addition, to finding a CPA you also need to determine how you will keep track of your business related transactions. Most commonly used business accounting software is QuickBooks. I used QuickBooks for many years. For the past 1.5 years, I have started using a service called Xero (http://www.xero.com ). They have an application for IPhone along with a website. I also evaluated Freshbooks but I chose Xero as they had double entry accounting which is helpful for business related accounting. Xero does offer payroll service in some of the states in the US. They currently don’t support a payroll service in Minnesota. Xero was an easy choice because they were inexpensive, they automatically downloaded banking and credit card transactions, allowed me to give access to the books to my accountant, partners, and their mobile application allowed uploading receipts. They also had a large number of integrations with other services. Even their service levels could be adjusted in the middle of the month to save money on their service charges.


I have always used a third party payroll provider to do my payroll and all the associated filings. The cost of payroll can vary a lot. The majority of payroll services are providing a similar type of services but they reserve the right to charge you exorbitant fees to prey upon your ignorance.

I currently use a service called Gusto (http://www.gusto.com ). They had lower fees than most other payroll providers, they allowed me to run an unlimited amount of payrolls every month, they did all the quarterly filings and provided W2 every year for no additional cost.

I have seen others use these types of services for payroll:

  • QuickBooks
  • Wells Fargo Payroll
  • Sure Payroll
  • Use and accountant
  • Do your own payroll and business filings


When you are self-employed you will be pay self-employment taxes. If you have a payroll provider you will not have to do anything else but you may still want to read about self-employment taxes here:



Time Management Software

Over the years, I have used a variety of methods to keep track of my time to bill my clients. If you have more than one clients I highly recommend Harvest App. They have the web and mobile applications. They are super easy to use and inexpensive. You can learn more about Harvest app here: https://www.getharvest.com



In addition to looking at ease of use, cost and features one other criterion you should use while selecting an application are integration. In my case, I chose Xero, Harvest, and Gusto. All of them integrate well. I can keep track of my time in Harvest and the invoices from Harvest are automatically transferred into Xero. I use Gusto for payroll and the transactions automatically flow into Xero. Xero automatically downloads the transactions from my bank accounts and credit cards.


Workers Comp Insurance

If you are self-employed your state will most likely require you to purchase workers comp insurance. Since you are working for yourself you are not allowed to file a worker comp claim against yourself but you will still be required to purchase workers comp insurance.

I have been purchasing my workers comp insurance from State Farm. Their prices seemed reasonable to me.

Commercial General Liability Insurance

If you are signing contracts with your clients you will be required to purchase Commercial General Liability Insurance. Most of the time my clients require 1 to 2 Million dollar General Liability insurance policy. I currently use State Farm for my general liability insurance. They were cheaper than most other providers.

Professional Liability Insurance

There have been times when I was asked to purchase Professional Liability Insurance. This is typically a lot more expensive than General Liability Insurance. I don’t have a recommendation for a specific provider. You should try to avoid an annual contract for your insurance. Pay your premium monthly so you can cancel this policy if it is no longer necessary.

Automobile Expenses

If you use your car for a business related activity you will be able to charge some of these expenses to your business. You should talk with your CPA to determine the option that works best for you. Here are a few options:

1. Purchase or Lease the car for your business

2. Use your personal car and keep track of miles you are driving for business.

Mileage Tracking App

I recommend MileIQ https://dashboard.mileiq.com application as it makes it super easy to keep track of business-related driving.

Health Insurance

If your spouse is employed your best bet is to get your Health Insurance benefits from her employer. This may be less expensive than purchasing health insurance in the open market.

Even if your spouse does not work you will be able to purchase quality health insurance as a result of Obamacare. You can shop for plans here: https://www.healthcare.gov/

Disability Insurance

I highly recommend purchasing a quality disability insurance. There are many types of disability insurance policies and options. Disability insurance can expensive so you need to do your research. Your cost of insurance goes up as you get older. I recommend working with an independent agent and purchase a disability insurance policy that will meet your needs. I purchased my disability insurance from Guardian. They are used by physicians and IT consultants I know. I purchased my disability insurance more than 10 years ago so I don’t remember all the features I looked for but here are a few things to keep in mind:

  • Select a Policy that allows you to define your “Owner Occupation”
  • Cost of Living Adjustment Rider is worth pay for
  • Make sure your disability insurance kicks in after your employer based short term disability stops
  • Since you are paying your disability insurance premium with after tax dollars you will get payments that will not be taxable.

Retirement Plans

One of the best parts of being self-employed is to be able to contribute more to your retirement. If your self-employment income varies greatly you have the option not make any payments into your retirement plan until the 4th Quarter of calendar year. A few different type of retirement plans is available for self-employed folks. Two of the best choices are:

  • Solo 401K Plan
  • SEP Plan

Both of them don’t require a lot of paperwork. I like Solo 401K more because it allows me to contribute more per year as compared with SEP Plan. There are two types of contribution in a Solo 401K Plan:

  • Employee 401K Contribution: For 2015 an employee can defer $18000 of their income into their Solo 401K plan
  • Employer 401K Contribution: Employer can contribute up to 25% of your annual income to your 401K.

The total annual contribution into a Solo 401K plan for participants 50 years and younger in 2015 cannot exceed $53000

IRS website provides a good overview of these plans: https://www.irs.gov/Retirement-Plans/One-Participant-401(k)-Plans

There are a large number of financial institutions that offer Solo 401K plans. Here are a few good options:

  • Vanguard
  • Fidelity
  • Schwab

I have used all three but my favorite is Vanguard because of their low costs.

Business Stationary

You will most likely need business cards and letterheads. There are a large number of inexpensive choices available. Here are two options worth considering:

  • moo.com
  • vistaprint.com


Messaging and Collaboration

Cloud Software as a Service(SAAS) offerings will be your best bet. They are inexpensive, don’t require large upfront investment, easy to setup and can grow with your needs.

Office 365 is a SAAS is by far my favorite service for messaging and collaboration. They have plans starting as low as $5 per employee per month and it includes:

  • Email
  • SharePoint Online for Collaboration
  • Skype for Communication
  • One Drive for secure file exchange.


Website Hosting

Office 365 allows you to host a public website but they are deprecating this feature. There are many great options for hosting your public facing website. Some of these are:


Content Management System

There are many great options here as well. WordPress is by far one of the most popular content management systems. There are dedicated WordPress hosting providers. More technical folks may install WordPress, MySQL in a VM for most of you may be better off selecting a provider that spins up a website for you and allows you to manage your content.

Customer Relationship Management

This software helps businesses manage customer data and customer interaction, access business information, automate sales, marketing and customer support and also manage employee, vendor and partner relationships. In the past CRM software was primarily used by larger enterprises. With the advent of Software as Service applications now any sized business can use this type of software. Two of the best CRM products are:

  • Sales Force
  • Microsoft CRM Online

Both of them are easy to set up, require no upfront investment and will grow as your business grows.


Once you are self-employed your continued employment will depend on your brand and your network. You will find numerous resources on the web that will cover this topic. I will share a few suggestions:

  • Leverage Social Media: Twitter, LinkedIn, and SlideShare
  • Join professional organizations to connect with your peers
  • Participate in Meetups and local events
  • Plan to spend 20% of time training and business development
  • Participate in the relevant communities like StackExchange for developers
  • Blog consistently and publish it in LinkedIn, personal/business website
  • Find a Mentor
  • Give back and help others

I hope you found some of these resources helpful. I wish you the very best in your self-employment journey.

Posted in Business, Finance | Tagged , | Leave a comment

How to upgrade Azure DS Series VM to GS Series VM

Azure GS Series VM released on September 2nd 2015. G Series VM’s were released earlier this year.

GS Series added ability to use SSD backed premium storage to the largest/fastest virtual machines on Azure platform.

You can read more about them here:


GS Series VM’s are not available in all regions yet.

I had a DS Series VM running on “West US” region. This VM was in an availability set.

We needed to upgrade this VM to GS Series VM. When I looked at http://portal.azure.com  and tried to resize the VM I did not see GS Series VM in the list upgrade options. I knew that GS Series was available in “West US” so I needed to find a way to resize my VM.

Azure Resource Explorer


If you are writing Azure Resource Management Templates you will find Azure resource explorer invaluable. Documentation for services is often incomplete so I create a resource using azure management portal. Once the resource has been created I use resource explorer to understand the properties of the resource. Majority of time I use resource explorer to read information. However in this particular case I used resource explorer to upgrade the VM. I only tried it in Dev and it worked.

Here is my DS1 instance running in West US.


Here is how this VM looks like in the resource explorer.


My VM was running. I tried updating the VM to Standard_GS1 using these steps:

1. You have to be appropriate access to the Azure subscription/resource group where the VM is running.

2. Log into resource explorer using “ReadWrite” mode and select the subscription, resource, compute and virtual machine.


3. Select the virtual machine and press the “Edit” button as shown.


4. Update the value of vmSize to Standard_GS1 as shown below and press “PUT”


5. The operation failed with this error below. I found that I had to stop/deallocate my VM even if it was not in the availability set. Error message was very descriptive.

1:  {  
2:   "error": {  
3:    "code": "OperationNotAllowed",  
4:    "target": "vmSize",  
5:    "message": "Unable to update the VM. The requested VM size 'Standard_GS1' may not be available in the resources supporting the existing allocation. Please try again later, try with a different VM size or create a VM with a new availability set or no availability set binding."  
6:   }  
7:  }  

6. I went to the preview portal and stopped the VM. The status of the VM will change to stopped (deallocated).

7. I refreshed the resource explorer to make sure it had the latest settings for the VM.

8. I repeated the steps 2, 3 and 4 again. This time there were no errors.

9. I verified in the portal that size had change to Standard_GS1 as shown below.


10. Don’t forget to shutdown the VM after your experiment is over.


Upgrading a DS Series VM to GS Series VM is possible however a reboot is required. Reboot is required if the VM is standalone or in an availability set. When new services are launched on Azure platform they may not have PowerShell or Azure CLI available or documented. Azure Resource Explorer allows us directly interact with the Azure platform. It can be used to manage resources.

Posted in ARM, Azure, DevOps, IAAS | Tagged , , , | Leave a comment

Adventures with Azure Resource Manager Part I


In this series of blog posts I will create ARM templates used to provision Azure resources. I will kick things off by creating a template that shows you have to create multiple storage accounts. It also shows:

  1. How to use parameters of type arrays
  2. How to use length operator to iterate over elements of array
  3. How to use copy
  4. How to use output section of the template to display information about newly created resources.
  5. How you can use parameter files to provision resources in your dev, test and production environment.

Show me my template

Parameters: Lines 4-11

Like any other ARM template this template starts with a parameters section. Line 5 declares a parameter of type storageAccountList. It is of type array. This parameter will pass in an array of objects which will provide all the required details to provision a storage account.

Resources: Lines 12-26

This is the section where we iterate through the list of objects in the storageAccountList and provision storage accounts in a resource loop.

Line 14: Sets the name property of the storage account being provisioned

Line 17: Sets the Location property of the storage account being provisioned

Line 20: Uses length function to determine the number of elements in the storageAccountList

Line 23: Sets the accountType property of the storage account being provisioned

Outputs: Lines  27-40

This section displays details about the storage accounts that were provisioned.

Lines 30, 34 and 38 reference the storage accounts that were provisioned.

1:  {  
2:    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",  
3:    "contentVersion": "",  
4:    "parameters": {  
5:      "storageAccountList": {  
6:        "type": "array",  
7:        "metadata": {  
8:          "description": "List of storage accounts that need to be created"  
9:        }  
10:      }  
11:    },  
12:    "resources": [  
13:      {  
14:        "name": "[parameters('storageAccountList')[copyIndex()].name]",  
15:        "type": "Microsoft.Storage/storageAccounts",  
16:        "apiVersion": "2015-05-01-preview",  
17:        "location": "[parameters('storageAccountList')[copyIndex()].location]",  
18:        "copy": {  
19:          "name": "storageAccountLoop",  
20:          "count": "[length(parameters('storageAccountList'))]"  
21:        },  
22:        "properties": {  
23:          "accountType": "[parameters('storageAccountList')[copyIndex()].storageAccountType]"  
24:        }  
25:      }  
26:    ],  
27:    "outputs": {  
28:      "stgobject1": {  
29:        "type": "object",  
30:        "value": "[reference(concat('Microsoft.Storage/storageAccounts/', parameters('storageAccountList')[0].name),providers('Microsoft.Storage', 'storageAccounts').apiVersions[0])]"  
31:      },  
32:      "stgobject2": {  
33:        "type": "object",  
34:        "value": "[reference(concat('Microsoft.Storage/storageAccounts/', parameters('storageAccountList')[1].name),providers('Microsoft.Storage', 'storageAccounts').apiVersions[0])]"  
35:      },  
36:      "stgobject3": {  
37:        "type": "object",  
38:        "value": "[reference(concat('Microsoft.Storage/storageAccounts/', parameters('storageAccountList')[2].name),providers('Microsoft.Storage', 'storageAccounts').apiVersions[0])]"  
39:      }  
40:    }  
41:  }  

Parameter Files

You created one template which is parameterized. After the template has been tested you can use different parameter files with the same template to provision resources in different environments.

Dev Parameters File

This parameter file defines a storage account list. It defines name, location and storageAccountType properties for each storage account. It can be used to provision storage account in a dev environment. 

1:  {  
2:    "storageAccountList": {  
3:      "value": [  
4:        { "name": "rajappdev", "location": "Central US", "storageAccountType": "Standard_LRS" },  
5:        { "name": "rajdbdev", "location": "Central US", "storageAccountType": "Standard_GRS" },  
6:        { "name": "rajwebdev", "location": "Central US", "storageAccountType": "Standard_ZRS" },  
7:        { "name": "rajarchdev", "location": "West US", "storageAccountType": "Premium_LRS" }  
8:        ]  
9:    }  
10:  }  

Test Parameters File

This parameter file defines a storage account list. It defines name, location and storageAccountType properties for each storage account. It can be used to provision storage account in a test environment. 

1:  {  
2:    "storageAccountList": {  
3:      "value": [  
4:        { "name": "rajapptest", "location": "Central US", "storageAccountType": "Standard_LRS" },  
5:        { "name": "rajdbtest", "location": "Central US", "storageAccountType": "Standard_GRS" },  
6:        { "name": "rajwebtest", "location": "Central US", "storageAccountType": "Standard_ZRS" },  
7:        { "name": "rajarchtest", "location": "West US", "storageAccountType": "Premium_LRS" }  
8:        ]  
9:    }  
10:  }  

Prod Parameters File

This parameter file defines a storage account list. It defines name, location and storageAccountType properties for each storage account. It can be used to provision storage account in a prod environment. 

1:  {  
2:    "storageAccountList": {  
3:      "value": [  
4:        { "name": "rajappprod", "location": "Central US", "storageAccountType": "Standard_LRS" },  
5:        { "name": "rajdbprod", "location": "Central US", "storageAccountType": "Standard_GRS" },  
6:        { "name": "rajwebprod", "location": "Central US", "storageAccountType": "Standard_ZRS" },  
7:        { "name": "rajarchprod", "location": "West US", "storageAccountType": "Premium_LRS" }  
8:        ]  
9:    }  
10:  }  


Ship It (Make it so Number 2)

Now that our templates are ready we are ready to execute them to provision resources.

Here is a short script that is used to provision resources.

Lines 16-30: Create the resource group if it does not already exist

Line 40: Uses the template and a parameters file to  provision storage accounts.

1:  Param  
2:  (  
3:    [Parameter (Mandatory = $true)]  
4:    [string] $ResourceGroupName,  
6:    [Parameter (Mandatory = $true)]  
7:    [string] $Location,  
9:    [Parameter (Mandatory = $true)]  
10:    [string] $ParametersFile  
11:  )  
13:  #publish version of the the powershell cmdlets we are using  
14:  (Get-Module Azure).Version  
16:  $rg = Get-AzureResourceGroup -Name $ResourceGroupName -ErrorAction SilentlyContinue  
18:  if (!$rg)  
19:  {  
20:    # Create a new storage account  
21:    Write-Output "";  
22:    Write-Output "Creating Resource Group [$ResourceGroupName] in location [$Location]"  
25:    New-AzureResourceGroup -Name "$ResourceGroupName" -Force -Location $Location -ErrorVariable errorVariable -ErrorAction SilentlyContinue | Out-Null  
27:    if (!($?))   
28:    {   
29:      throw "Cannot create new Resource Group [$ResourceGroupName] in region [$Location]. Error Detail: $errorVariable"   
30:    }  
32:    Write-Output "Resource Group [$ResourceGroupName] was created"   
34:  }  
35:  else  
36:  {  
37:    Write-Output "Resource Group [$ResourceGroupName] already exists"  
38:  }  
40:  New-AzureResourceGroupDeployment -Name stgdeployment -ResourceGroupName $ResourceGroupName -TemplateFile .\createstorageaccts.json -TemplateParameterFile $ParametersFile  


Trust but Verify

Line 1: It calls deploy.ps1 script and passes in resource group name, location and parameters file.

Line 54-92: Show the details of the storage accounts that were provisioned.

1:  PS C:\git\ArmExamples\CreateStorageAccounts> .\deploy.ps1 -ResourceGroupName ARM-Dev -Location "West US" -ParametersFile  
2:   .\storageaccts-dev.json  
4:  Creating Resource Group [ARM-Dev] in location [West US]  
5:  VERBOSE: 3:54:11 PM - Created resource group 'ARM-Dev' in location 'westus'  
6:  Resource Group [ARM-Dev] was created  
7:  VERBOSE: 3:54:13 PM - Template is valid.  
8:  VERBOSE: 3:54:14 PM - Create template deployment 'stgdeployment'.  
9:  VERBOSE: 3:54:22 PM - Resource Microsoft.Storage/storageAccounts 'rajarchdev' provisioning status is running  
10:  VERBOSE: 3:54:22 PM - Resource Microsoft.Storage/storageAccounts 'rajwebdev' provisioning status is running  
11:  VERBOSE: 3:54:24 PM - Resource Microsoft.Storage/storageAccounts 'rajappdev' provisioning status is running  
12:  VERBOSE: 3:54:24 PM - Resource Microsoft.Storage/storageAccounts 'rajdbdev' provisioning status is running  
13:  VERBOSE: 4:04:03 PM - Resource Microsoft.Storage/storageAccounts 'rajappdev' provisioning status is succeeded  
14:  VERBOSE: 4:04:03 PM - Resource Microsoft.Storage/storageAccounts 'rajarchdev' provisioning status is succeeded  
15:  VERBOSE: 4:04:05 PM - Resource Microsoft.Storage/storageAccounts 'rajappdev' provisioning status is succeeded  
16:  VERBOSE: 4:04:13 PM - Resource Microsoft.Storage/storageAccounts 'rajdbdev' provisioning status is succeeded  
17:  VERBOSE: 4:04:13 PM - Resource Microsoft.Storage/storageAccounts 'rajwebdev' provisioning status is succeeded  
18:  VERBOSE: 4:04:13 PM - Resource Microsoft.Storage/storageAccounts 'rajdbdev' provisioning status is succeeded  
19:  VERBOSE: 4:04:13 PM - Resource Microsoft.Storage/storageAccounts 'rajwebdev' provisioning status is succeeded  
22:  DeploymentName  : stgdeployment  
23:  ResourceGroupName : ARM-Dev  
24:  ProvisioningState : Succeeded  
25:  Timestamp     : 8/14/2015 9:04:25 PM  
26:  Mode       : Incremental  
27:  TemplateLink   :  
28:  Parameters    :  
29:            Name       Type            Value  
30:            =============== ========================= ==========  
31:            storageAccountList Array           [  
32:             {  
33:              "name": "rajappdev",  
34:              "location": "Central US",  
35:              "storageAccountType": "Standard_LRS"  
36:             },  
37:             {  
38:              "name": "rajdbdev",  
39:              "location": "Central US",  
40:              "storageAccountType": "Standard_GRS"  
41:             },  
42:             {  
43:              "name": "rajwebdev",  
44:              "location": "Central US",  
45:              "storageAccountType": "Standard_ZRS"  
46:             },  
47:             {  
48:              "name": "rajarchdev",  
49:              "location": "West US",  
50:              "storageAccountType": "Premium_LRS"  
51:             }  
52:            ]  
54:  Outputs      :  
55:            Name       Type            Value  
56:            =============== ========================= ==========  
57:            stgobject1    Object           {  
58:             "provisioningState": "Succeeded",  
59:             "accountType": "Standard_LRS",  
60:             "primaryEndpoints": {  
61:              "blob": "https://rajappdev.blob.core.windows.net/",  
62:              "queue": "https://rajappdev.queue.core.windows.net/",  
63:              "table": "https://rajappdev.table.core.windows.net/"  
64:             },  
65:             "primaryLocation": "Central US",  
66:             "statusOfPrimary": "Available",  
67:             "creationTime": "2015-08-14T20:54:32.9062387Z"  
68:            }  
69:            stgobject2    Object           {  
70:             "provisioningState": "Succeeded",  
71:             "accountType": "Standard_GRS",  
72:             "primaryEndpoints": {  
73:              "blob": "https://rajdbdev.blob.core.windows.net/",  
74:              "queue": "https://rajdbdev.queue.core.windows.net/",  
75:              "table": "https://rajdbdev.table.core.windows.net/"  
76:             },  
77:             "primaryLocation": "Central US",  
78:             "statusOfPrimary": "Available",  
79:             "secondaryLocation": "East US 2",  
80:             "statusOfSecondary": "Available",  
81:             "creationTime": "2015-08-14T20:54:32.0468124Z"  
82:            }  
83:            stgobject3    Object           {  
84:             "provisioningState": "Succeeded",  
85:             "accountType": "Standard_ZRS",  
86:             "primaryEndpoints": {  
87:              "blob": "https://rajwebdev.blob.core.windows.net/"  
88:             },  
89:             "primaryLocation": "Central US",  
90:             "statusOfPrimary": "Available",  
91:             "creationTime": "2015-08-14T20:54:29.9062389Z"  
92:            }  


To remove all the resources you provisioned you can use the Remove-AzureResoureGroup cmdlet as shown below

  Remove-AzureResourceGroup -Name ARM-Dev  

Doggy Bag Please

You can access all the samples from my GitHub Repository here: https://github.com/rajinders/ArmExamples


I hope you found this sample helpful. I will post more samples on a regular basis.

Posted in ARM, Automation, Azure, DevOps, PowerShell | Tagged , , , | Leave a comment