Testing and Validation of Bicep Templates using PSRule
Stephen Tulp
December 13, 2023
7 minutes to read
Introduction
In this blog post, we will look at how we can use PSRule to introduce validation and testing of Bicep modules and templates against things like the Azure Well-Architected Framework.
What is PSRule?
PSRule is a PowerShell module that allows you to validate infrastructure as code (IaC) and objects using PowerShell rules. It is an open-source, cross-platform, and general-purpose rules engine that integrates with popular continuous integration (CI) systems. You can use PSRule to define reusable business rules, provide recommendations, and share rules across teams or an organizations. PSRule support various scenarios such as validating Azure resources and GitHub repositories.
Why Should I use it?
PSRule assists in identifying changes to improve the quality of deployments into Azure using the principles of the Azure Well-Architected Framework (WAF) to:
- Provide alignment to the WAF: Helps to improve the quality of IaC.
- Link to documentation: Provides guidance on how to implement the change.
- Examples: Examples are provided in Azure Bicep and ARM templates syntax that you can leverage in your own code.
- Extensible: Use over 400 built-in tests or write your own tests in PowerShell, YAML, or JSON.
Testing Bicep Templates with PSRule
Now lets install PSRule locally and test one of the Bicep templates.
- Install locally by running the following commands in a PowerShell.
Install-Module -Name 'PsRule' -Repository PSGallery -Scope CurrentUser -Force
Install-Module -Name 'PSRule.Rules.Azure' -Repository PSGallery -Scope CurrentUser -Force
Note: For the full installation instructions (local, Azure Devops & GitHub) use this link, we will use the GitHub option for tomorrows post.
- We will need a
ps-rule.yaml
file in the root of our Bicep template folder, this file contains settings for PSRule, (EXAMPLE)
# Use rules from the following modules. - https://microsoft.github.io/PSRule/v2/concepts/PSRule/en-US/about_PSRule_Options/#includemodule
include:
module:
- PSRule.Rules.Azure
- PSRule.Rules.CAF
# Require a minimum version of modules that include referenced baseline. - https://microsoft.github.io/PSRule/v2/concepts/PSRule/en-US/about_PSRule_Options/#requires
requires:
PSRule: "@pre >=2.3.2"
PSRule.Rules.Azure: "@pre >=1.18.1"
# Reference the repository in output (Change this to your GitHub Repo) - https://microsoft.github.io/PSRule/v2/concepts/PSRule/en-US/about_PSRule_Options/#repositoryurl
repository:
url: https://github.com/Insight-Services-APAC/insight-bicep-advent-calendar
execution:
# Ignore warnings for resources and objects that don't have any rules. - https://microsoft.github.io/PSRule/v2/concepts/PSRule/en-US/about_PSRule_Options/#executionunprocessedobject
unprocessedObject: Ignore
# Define baseline configuration - https://microsoft.github.io/PSRule/v2/concepts/PSRule/en-US/about_PSRule_Options/#configuration
configuration:
# Enable expansion for Bicep source files.
AZURE_BICEP_FILE_EXPANSION: true
# Expand Bicep module from Azure parameter files.
AZURE_PARAMETER_FILE_EXPANSION: true
# Set timeout for expanding Bicep source files.
AZURE_BICEP_FILE_EXPANSION_TIMEOUT: 45
# Set allowed locations for resources.
AZURE_RESOURCE_ALLOWED_LOCATIONS:
- australiaeast
# Set allowed locations for resource groups.
AZURE_RESOURCE_GROUP:
location: australiaeast
input:
# Ignore common files that don't need analysis. - https://microsoft.github.io/PSRule/v2/concepts/PSRule/en-US/about_PSRule_Options/#inputpathignore
pathIgnore:
- "**/bicepconfig.json"
- "*.yaml"
- "*.yml"
- "*.md"
- "*.ps1"
- "*.png"
- ".github/"
- "src/modules/CARML/"
binding:
# When binding has been configured these values override automatic binding by default - https://microsoft.github.io/PSRule/v2/concepts/PSRule/en-US/about_PSRule_Options/#bindingprefertargetinfo
preferTargetInfo: true
# When an object is passed from the pipeline, PSRule assigns the object a TargetType. TargetType is used to filter rules based on object type and appears in output results. - https://microsoft.github.io/PSRule/v2/concepts/PSRule/en-US/about_PSRule_Options/#bindingtargettype
targetType:
- resourceType
- type
rule:
# Exclude specific rules from being validated. - https://microsoft.github.io/PSRule/v2/concepts/PSRule/en-US/about_PSRule_Options/#ruleexclude
exclude:
- Azure.Resource.UseTags
- Azure.NSG.LateralTraversal
output:
# Using the output/culture property. - https://microsoft.github.io/PSRule/v2/concepts/PSRule/en-US/about_PSRule_Options/#outputculture
culture: ["en-AU", "en-US"]
Lets run PSRule across an example Bicep template and see the results.
Invoke-PSRule -InputPath '.\blog\storageAccount-v1.bicep' -Module 'PSRule.Rules.Azure'
As we can see from the output above, we have a number of pass
and fails
outcomes and also a recommendation for each rulename. From the image we can see the following failures:
- Azure.Storage.UseReplication
- Azure.Storage.SoftDelete
- Azure.Storage.ContainerSoftDelete
- Azure.Storage.Firewall
- Azure.Storage.MinTLS
- Azure.Storage.BlobPublicAccess
If we want to get a better understanding of these failures, we can run the following command to get more information.
Assert-PSRule -InputPath '.\blog\storageAccount-v1.bicep' -Format Detect
Now we have a better understanding of the failures and also a link to the documentation on how to fix the issue. Now lets run the validation on another template that has addressed the failures from the previous template.
Assert-PSRule -InputPath '.\blog\storageAccount-v2.bicep' -Format Detect
We can now see that there is only one failure and that is for the Azure.Storage.UseReplication
rule, lets have a look at the output.
We have a couple of options to address this failure:
- We can exclude the rule from validation by adding the following to the
ps-rule.yaml
file. This will suppress the rule from being validated for all storage accounts and would be useful if you are only using a single Azure region.
rule:
# Exclude specific rules from being validated. - https://microsoft.github.io/PSRule/v2/concepts/PSRule/en-US/about_PSRule_Options/#ruleexclude
exclude:
- Azure.Resource.UseTags # Tags deployed via templates.
- Azure.NSG.LateralTraversal
- Azure.Storage.UseReplication # Storage replication is not required for all storage accounts as only a single region is used.
- We can get really specific and create a suppression group for the rule and only suppress it for the storage account that we are deploying. This is useful if you are deploying to multiple regions and only want to suppress the rule for a specific storage account.
For details on authoring suppression groups see Suppression Groups and Expressions.
Conclusion
PSRule is very powerful and provides a variety of configuration options to test and validate IaC deployments. In this post we have only scratched the surface of what PSRule can do.
Further Reading
Some further reading on the topics covered in this post: