top of page

Recent Posts

Archive

Tags

Terraform Part 3: Transposing ARM to Terraform

This post is part of a short Terraform series which will take you through some of my learning about Terraform with examples. Now that I have shared some thoughts on Terraform as well as how easy it is to get started with your own deployments, I wanted to share some tips and tools that I used to help transpose an ARM template that I was working on to Terraform. The first step may seem obvious but ensure that you understand what is being deployed in the ARM template. It often helps to do a template deployment and go into the portal so see any child resources or dependencies that get created. In the Azure portal, you can go to services > template deployment and try deploying the template easily from there just to get a view of what is being deployed. JSON can be difficult to parse visually and this can be a helpful step if you have a complex ARM template. If you go the resource group in the Azure portal and click on the deployments section, you will be able to see each parent and child resource that is deployed. It's always good to be sure that you have a list of resources to translate to Terraform templating language. Now that you have a list of resources, let's set up our environment. One of the tools that I use for validating ARM templates themselves is the ARM template schema documentation. This helps me to take the guesswork out of what properties belong in an ARM template and what I can use that I previously had not known about. This will also help you know what to look for in the Terraform documentation for a 1-1 comparison of properties. It's important to note that as a first class customer, ARM templates will likely have more properties than are available in Terraform but the most common, useful properties will be available. Here is a link to the template that I want to convert: microsoft-teams-apps-company-communicator/azuredeploy.json at master · OfficeDev/microsoft-teams-apps-company-communicator (github.com). This ARM template deploys the Teams App Company Communicator to a Teams instance. Here are the instructions for the full deployment. I will only dealing with the ARM template deployment piece but ensure that you follow the deployment guide for a full deployment of the app if you are interested. A hard requirement was to make this work in a hybrid cloud environment. Sometime customers have different subscriptions and tenants. This is a little different as I was working with Government customers who needed the deployment to be in two different clouds: GCC and GCC High. This is mainly for security reasons. Azure has many cloud offerings for geographic regions and government. My particular task was to deploy this infrastructure in Azure GCC for the bot and identity portion of the deployment and Azure GCC High for the rest of the infrastructure deployment. I won't go into details about the different Azure Government clouds available here but just know that the deployment had to be in two parts. The outline of the deployment is as follows: Deployment 1: App Registrations for the Web App Bots Web App Bots Teams Channel Registrations associated with the Bots Application Insights Deployment 2: 1 App Service 1 Web App with Source Control 3 Function Apps with Source Control 1 Service Bus 4 Service Bus Queues We have to ensure that we are using the appropriate providers in the deployment. Here we are not only using the AzureRM provider for the resource deployment but also the AzureAD provider for the app registration deployment. I am placing these specifications at the top of my main.tf file.


Take note that you should always double check your provider versions. Terraform updates providers very often and while, for the most part, you will not need to update with each provider version, it is helpful to go to the provider documentation section and get the latest version available. We now come to one of my favorite features of Terraform, being able to deploy app registrations, service principals and secrets with Terraform. Deploying service principals is not currently possible with ARM templates and the instructions for deploying this ARM template in the link above specify to deploy the app registrations manually. Now that we can automate the deployment of the app registrations, we can be sure that the deployment is just a bit more secure because we know that the permissions will be assigned correctly the first time and every time. Here is an example of how to create an app registration with a secret configured to it. The first resource is the azuread application with any permissions and settings that we want. Next, we create the service principal for the app registration. We can use the random string resource to create a complex random password. Notice the special property set to true here. This is to allow special characters (@$%) in the password. Lastly, we create the azuread application password resource to associate the password with the application registration. The Company Communicator teams app requires two service principals with different settings and permissions so we just repeat the process for the second application registration. Having the app registrations created automatically can help to ensure that they get created correctly every time, with the correct permissions and a secret to secure it. This is one way that I have improved the security of the deployment just by using Terraform and I am pleased that this option is available. Note that since this will be two deployments, that the secrets created for the service principals are persisted in state to be used in Deployment 2. If all of the resources were in the same template, I would access the secret via azuread_application_password.author_app_registration_sp_secret.value

What follows is the part of the Terraform template that creates the Web App Bots, the Teams Channel Registrations, and an instance of Application Insights.

Notice that even though the depends on section is not required, I prefer to enforce order here in case anything goes awry with the application registrations because the client IDs of the application registrations are used in the Bot Web Apps. I prefer not to begin the deployment but this is a preference since Terraform will keep state and continue the deployment where it left off if the bot web apps cannot access the App Registrations. It is important to note here that Terraform can figure out dependencies on its own, as long as there is a link between the parent and child resources, such as the app_service_plan_id property on the azurerm_app_service resource and the name property of the azure_app_service_plan resource. If there is not link, which is not a common occurrence, then you may have to use the depends_on option to ensure that the parent resource comes first. You can find the secrets, client IDs, and more needed for Deployment 2 in the state file after you deploy for the first time. Deployment 2 will be deployed in a different Azure cloud offering but as part of the same solution, which is why I have each in separate deployment folder and files. Deployment 2 contains the same preliminary elements, such as the required providers and provider configuration. I will go into some of the more interesting parts of transposing this template into Terraform. I will start with the web app service, which includes a source control deployment. When I transpose this resource to Terraform, notice the lifecycle configuration here at the top of the resource, which is used to indicate that the web app service will not be updated if the source control is added or changed.

This is important because we do not want any of the settings for our web app service to change if we update the source control component, as it could affect the availability of the web app. Another interesting item involving the web app service is that there is a bug specifically for web apps in Terraform that involves the app settings and the source control parts. If there are app settings and source control present in the web app service deployment, the source control component will fail. This is because ARM has a lock on the web app resource but the app settings and the source control apply simultaneously in Terraform. Because the source control component utilizes the app settings parameters as input to source control, the source control will fail. This bug is documented in a link to an issue in Terraforms Github in Part 1 of this Terraform series. Because we cannot make the source control portion wait for the app settings to be applied, I use a feature in Terraform, the azurerm_resource_group_deployment resource. This allows us to deploy an ARM template with Terraform. I consider this option to be the nuclear option as it can be a bit clunky to use. You need to have the ARM template as a JSON file in your deployment folder and reference it:

Note that, even though this is a child resource that we want to ensure runs after the app service, there is no need for a depends on statement as the app service resource and template deployment resource are linked through the name of the azurerm_resource_group_deployment resource. Terraform makes the connection for us. We have to declare these template deployment resources for each resource that contains a source control deployment: For each app service, function or web, we have to specify the path to the deployment code in the app settings. Make sure to properly escape the path like so:

Note the double back slashes between each element of the path. From here I complete the template with the Service Bus and Queues and that will round out the deployment. There is another consideration when transposing ARM templates to Terraform and that is the API schema for Azure versus the Terraform schema for resources. As you can see, I had to comment out some of the properties of the web app:

That is because, while these properties are available in the ARM template, they may not be available in Terraform. One tool that you can use to validate Azure schema versions against Terraform documentation are the specifications for the resource. This link takes you to the specification of a web app. You can drill out and take a look at other API versions to see how the resource may have changed. You can compare this to the Terraform documentation to web apps in order to do a sanity check. In the end, we may have to stick with removing or commenting out features that are not available in Terraform. Also consider the ARM template deployment resource to deploy missing features, where possible. I hope that this post and the Terraform series has been helpful in getting a jump start in working with Terraform. Happy Coding! The completed Terraform template can be seen here: https://github.com/jhajduk-microsoft/blog_demo/tree/master/Hybrid

Comments


Single post: Blog_Single_Post_Widget

Follow

  • LinkedIn

©2018 by Jennifer Morris

bottom of page