How to Validate Your IaC Before Deployment Using Azure DevOps and PSRules
Introduction
Infrastructure as Code (IaC) is a modern approach to managing and administering infrastructure. It enables the definition and configuration of resources through files of code.
This new approach has gained significant popularity in recent years with the use of cloud providers such as Azure, AWS, and GCP. DevOps practices also contribute to this adoption by emphasizing the importance of centralized and versioned code, enabling Continuous Integration (CI) and Continuous Deployment (CD).
While there are numerous benefits to using IaC, we often overlook the importance of validating whether our IaC adheres to best practices or meets minimum requirements before deployment. This validation process is crucial in order to mitigate potential risks to our applications caused by future changes that could have been addressed during the earlier stages of development.
In this article, we will demonstrate how to validate IaC written in Bicep code using Azure Pipelines and the PSRules module. The outcome of this validation will be a comprehensive report containing recommendations for the resources involved.
Key Concepts
It’s important to be familiar with DevOps, CI/CD tools such as Azure DevOps or GitHub Actions, and IaC languages such as Bicep or Terraform. Here are some key concepts about the tools that are used in the exercise:
- Azure Pipelines: It is a module provided by Azure DevOps that enables the automation, testing, and deployment of code projects. More information: What is Azure Pipelines? — Azure Pipelines | Microsoft Learn
- Bicep: It is a declarative language used to deploy Azure resources. It can be used instead of ARM templates to deploy resources in Azure. More information: Bicep language for deploying Azure resources
- PSRule for Azure: It is an open-source project that aims to identify resource enhancements using a set of rules based on the Azure Well-Architected Framework (WAF). More information: About — PSRule for Azure
- Azure Well-Architected Framework (WAF): It is a set of guidelines and principles. Those are used as a reference to identify and improve the quality of any system. More information: Microsoft Azure Well-Architected Framework
Exercise Summary
With the above concepts in mind, the goal of this exercise is to use the PSRule module to visualize the status of resources described in Bicep code before deployment through a pipeline
Here is the order of the exercise steps:
- Installation of the PSRule extension in Azure DevOps.
- Creation of a code-based pipeline hosted in a repository.
- Validation of the three pipeline tasks.
- Execution of the pipeline.
- Visualization of the report.
- Customization of the module.
By the end of the exercise, we should have:
- A code-based pipeline hosted in a repository (as shown in the orange box in the image1 — Left Box).
- An execution pipeline report with the recommendations (as shown in the purple box in the image1 — Right Box).
The following structure file and code are used during the development of the exercise so that you can clone it from this repository. This is the structure of the project:
── modules
│ ├── sqlserver.bicep = Bicep code with declaration of SQL Server and database resources
│ ├── vm.bicep = Bicep code with declaration of Virtual Machine resources
│ ├── vnet.bicep = Bicep code with declaration of Virtual Network and Subnet
│ └── webapp.bicep = Bicep code with declaration of App Plan Service and App Service Resources
├── main.bicep = Main bicep file with declaration of modules
├── main.bicepparam = Parameters file used by main.bicep
├── azure-pipeline.yaml = Definition of pipeline
└── ps-rule.yaml = File used to custom the PSRule module
Exercise Development
Let’s get started with the exercise. Now we will go step by step from installing and configuring the PSRule extension and getting our recommendations report at the end.
Install the PSRule extension
Go to the organization settings in Azure DevOps, bottom-left corner, then select “Extensions” from the menu:
Then click the “Browse Marketplace” option in the top-right corner:
In the Marketplace, search for “PSRule” and click on the PSRule icon that appears in the search results:
Now, click on the “Get it free” button:
A web page requesting the organization’s information to proceed with the installation will appear. Fill in the requested information and proceed with the installation. Once installed, the extension will be visible in the extensions section, as shown in the image:
Note: To install extensions, you must be a member of the Project Collection Administrators group. Check the prerequisites at the following link: Install Extensions.
Create a pipeline as code
Now, we will create the pipeline that runs the validation. Be aware you must have a repository created with the downloaded code. You can use this one as a start.
Go to the project where we will create the pipeline. A project called “bicepcode” has been created as a Git repository in the example. The repository contains the Bicep and YAML code explained in the summary section. Follow these steps:
Go to the Pipelines section of our project, and click “New Pipeline” in the upper-right corner:
Choose Azure Repos Git as source:
Select the repository:
Select the second option to create the pipeline as code:
Finally, select the /azure-pipeline.yaml
file and click on “Continue”:
You should see a screen similar to the following, showing the pipeline code with the three tasks. Finally, click on the “save” button:
Validation of tasks
Let’s check the tasks now. For the pipeline to work correctly, the three tasks must be properly configured. Open the azure-pipeline.yaml
to see the details of the tasks. The following image gives an overview of them:
Install PSRule: This task installs the module on the agent that will execute the pipeline. In the module option, enter PSRule.Rules.Azure
:
- task: ps-rule-install@2
displayName: "Install PSRule"
inputs:
module: PSRule.Rules.Azure
latest: true
prerelease: false
Run PSRule Validation: This task validates the IaC using the PSRule module. The result of this validation is delivered in a file:
- task: ps-rule-assert@2
displayName: "Run PSRule Validation"
continueOnError: true
inputs:
inputPath:
modules: 'PSRule.Rules.Azure'
option: 'ps-rule.yaml'
outputFormat: 'NUnit3'
outputPath: 'ps-rule-results.xml'
This task can be used since it was automatically installed by the extension through the task. The psrule.yaml
file is used to customize the module, which will be explained later in Customization section.
The continueOnError
option is set to true to enable the pipeline to continue to the next task and see the results as a report. More options to control or stop the pipeline execution are in Stop the Execution section.
Publish PSRule Results: This task publishes and formats the result of the previous task into a detailed report:
- task: PublishTestResults@2
displayName: "Publish PSRule results"
inputs:
testResultsFormat: 'NUnit'
testResultsFiles: 'ps-rule-results.xml'
failTaskOnFailedTests: false
testRunTitle: 'PSRule-File'
This task is an Azure DevOps standard task.
The failTaskOnFailedTest
option is set to false to enable the pipeline to continue and see the results as a report. More options to control or stop the pipeline execution are in Break the Execution section.
Pipeline execution
Now that the pipeline is created, let’s follow the following instructions to run it.
Click on the “run” button located in the upper-right corner. A screen will appear to validate the branch and other options. Click on “run”.
Azure DevOps Run pipeline options
A screen with the running job should appear.
Now, click on the job, and you will see a screen with the running log of each task.
Wait for the job to finish, then go back to the previous screen, where you will see a summary of the job execution. Click on the percentage (%) as illustrated in the following image:
Viewing the final report
Now that the pipeline is finished let’s check the report. The report shows us the details of the scanning performed by the module through the pipeline. Additionally, it shows the rule that was validated for each of the components in the bicep code:
Let’s check this example; the following recommendation should appear in the report:
By clicking on it, we will see that the TLS version for the web application is set to 1.0, and the recommendation is a minimum of 1.2:
This configuration is intentionally set in the AppService module (modules/webapp.bicep
) to be reflected in the report. Change minTlsVersion:'1.0'
to minTlsVersion:'1.2'
. Run the pipeline again and the recommendation will disappear from the report:
resource appService 'Microsoft.Web/sites@2020-06-01' = {
name: webAppName
location: location
properties: {
serverFarmId: appServicePlan.id
siteConfig: {
linuxFxVersion: 'PHP|8.0'
minTlsVersion: '1.0'
We can change the filter of the report to see all scanned rules that passed the test and the Azure Well-Architected Framework best practices:
Note: PSRule also allows evaluating the current state of already deployed resources. This will be explained in a future article.
Customization
In our environments, some of these rules may not align with our needs, so we may want to customize the scan. That customization is possible through a file. The psrule.yaml
file contains sections that enable customization of many features, such as:
- Rules to exclude
- Output language
- Folders or files to ignore during scanning
Note: In the repository, there is a psrule.yaml
file with some preconfigured settings.
The previous image shows the Azure.Template.UseDescriptions
rule placed in the rule:exclude
section. That means the scanning will not recommend using descriptions for any declared parameter in the code. You can check every rule that PSRule includes for each kind of resource at the following link: By resource — PSRule for Azure. For customization options and configurations, check at this link: Configuring options — PSRule for Azure
Stop the execution
Finally, we are in the last step and we will see some options you can customize to stop the pipeline execution to avoid deploying code with no compliance:
failTaskOnFailedTests
option onPublishTestResults@2
: This task could show a fail status if there are test failures during the execution. The default is false, which will simply publish the results from the results file and the pipeline will stop the execution.continueOnError
on any task: if future steps should run even if this step fails. This is a standard option for any task in the pipeline, so you can control if the pipeline stops as soon as any task fails.Outcome
option onps-rule-assert@2
: This option filters output to include results with the specified outcome like Fail, Pass, Error, Processed, Problem, All. So this option could be helpful to show only specific outcomes to decide whether the code should be deployed or not.- Using Azure DevOps stages and approvals: You can configure a pipeline with two stages, one to validate the IaC and publish the result and a second stage to deploy the code. Azure DevOps gives the option to run the second stage only if some conditions are met and approval is given, so there is a chance to stop or continue the execution according to the needs. See the following image:
Conclusions
One of the main challenges when deploying IaC is ensuring it meets minimum security standards and best practices. Thanks to modules like PSRule, the IaC can be assessed before deployment, allowing for timely action to make any necessary changes to enhance the quality of the resources. It is important to be aware of the status of our IaC before deployment; this will reduce the technical debt and ensure the stability and scalability of the resources.