Testing infrastructure#
You can use PSRule to create tests for Infrastructure as Code (IaC). Each test is called a rule.
PSRule allows you to write rules using YAML, JSON, or PowerShell. Regardless of the format you choose, any combination of YAML, JSON, or PowerShell rules can be used together.
Abstract
This topic covers how to create a rule using YAML, JSON, and PowerShell by example. This example, while fictitious is indicative of common testing and validation scenarios for IaC.
Sample data#
To get started authoring a rule, we will be working with a sample file settings.json.
This sample configuration file configures an application.
For the purpose of this example, one configuration setting supportsHttpsTrafficOnly is set.
This configuration setting can be either true or false.
When set to true, Transport Layer Security (TLS) is enforced.
When set to false, the application permits insecure communication with HTTP.
Contents of settings.json
Create a settings.json file in the root of your repository with the following contents.
{
"type": "app1",
"version": 1,
"configure": {
"supportsHttpsTrafficOnly": false
}
}
Define a rule#
To meet the requirements of our organization we want to write a rule to:
- Enforce secure traffic by requiring
supportsHttpsTrafficOnlyto betrue. - Enforce use of TLS 1.2 as a minimum by requiring
minTLSVersionto be1.2.
In this section the same rule will be authored using YAML, JSON, and PowerShell.
Tip
To make you editing experience even better, consider installing the Visual Studio Code extension.
Create a .ps-rule/Local.Rule.yaml file in your repository with the following contents.
---
# Synopsis: An example rule to require TLS.
apiVersion: github.com/microsoft/PSRule/v1
kind: Rule
metadata:
name: 'Local.YAML.RequireTLS'
spec:
condition:
field: 'configure.supportsHttpsTrafficOnly'
equals: true
- Use a short
Synopsis:to describe your rule in a line comment above your rule. For this to be interpreted by PSRule, only a single line is allowed. - Name your rule with a unique name.
- The
conditionproperty determines the checks PSRule will use to testsettings.json. Specifically, the object pathconfigures.supportsHttpsTrafficOnlymust exist and be set totrue.
Create a .ps-rule/Local.Rule.jsonc file in your repository with the following contents.
[
{
// Synopsis: An example rule to require TLS.
"apiVersion": "github.com/microsoft/PSRule/v1",
"kind": "Rule",
"metadata": {
"name": "Local.JSON.RequireTLS"
},
"spec": {
"condition": {
"field": "configure.supportsHttpsTrafficOnly",
"equals": true
}
}
}
]
- Use a short
Synopsis:to describe your rule in a line comment above your rule. For this to be interpreted by PSRule, only a single line is allowed. - Name your rule with a unique name.
- The
conditionproperty determines the checks PSRule will use to testsettings.json. Specifically, the object pathconfigures.supportsHttpsTrafficOnlymust exist and be set totrue.
Create a .ps-rule/Local.Rule.ps1 file in your repository with the following contents.
# Synopsis: An example rule to require TLS.
Rule 'Local.PS.RequireTLS' {
$Assert.HasFieldValue($TargetObject, 'configure.supportsHttpsTrafficOnly', $True)
}
- Use a short
Synopsis:to describe your rule in a line comment above your rule. For this to be interpreted by PSRule, only a single line is allowed. - Name your rule with a unique name.
- The condition contained within the curly braces
{ }determines the checks PSRule will use to testsettings.json. - The
$Assert.HasFieldValuemethod checks the object pathconfigures.supportsHttpsTrafficOnlyexists and is set totrue.
Tip
To learn more about recommended file and naming conventions for rules, continue reading Storing and naming rules.
Using multiple conditions#
Each rule must have at least one condition. Additional conditions can be combined to check multiple test cases.
In the example a minTLSVersion configuration setting does not exist and is not set.
Update .ps-rule/Local.Rule.yaml in your repository with the following contents.
---
# Synopsis: An example rule to require TLS.
apiVersion: github.com/microsoft/PSRule/v1
kind: Rule
metadata:
name: 'Local.YAML.RequireTLS'
spec:
condition:
allOf:
- field: 'configure.supportsHttpsTrafficOnly'
equals: true
- field: 'configure.minTLSVersion'
equals: '1.2'
- Using the
allOfexpression requires that all conditions be true for the rule to pass. This expression allows an array of one or more conditions to be provided. UsinganyOfwould pass the rule if any single condition is true.
Update .ps-rule/Local.Rule.jsonc in your repository with the following contents.
[
{
// Synopsis: An example rule to require TLS.
"apiVersion": "github.com/microsoft/PSRule/v1",
"kind": "Rule",
"metadata": {
"name": "Local.JSON.RequireTLS"
},
"spec": {
"condition": {
"allOf": [
{
"field": "configure.supportsHttpsTrafficOnly",
"equals": true
},
{
"field": "configure.minTLSVersion",
"equals": "1.2"
}
]
}
}
}
]
- Using the
allOfexpression requires that all conditions be true for the rule to pass. This expression allows an array of one or more conditions to be provided. UsinganyOfwould pass the rule if any single condition is true.
Update .ps-rule/Local.Rule.ps1 in your repository with the following contents.
# Synopsis: An example rule to require TLS.
Rule 'Local.PS.RequireTLS' {
$Assert.HasFieldValue($TargetObject, 'configure.supportsHttpsTrafficOnly', $True)
$Assert.HasFieldValue($TargetObject, 'configure.minTLSVersion', '1.2')
}
- An additional,
$Assert.HasFieldValueassertion helper method can be called. The rule will pass if all of the conditions return true.
Testing#
Testing manually#
To test the rule manually, run the following command.
Assert-PSRule -f ./settings.json
Advanced usage#
Severity level#
v2.0.0
When defining a rule, you can specify a severity level.
The severity level is used if the rule fails.
By default, the severity level for a rule is Error.
Error- A serious problem that must be addressed before going forward.Warning- A problem that should be addressed.Information- A minor problem or an opportunity to improve the code.
In a continuous integration (CI) pipeline, severity level is particularly important.
If any rule fails with a severity level of Error the pipeline will fail.
This helps prevent serious problems from being introduced into the code base or deployed.
The following example shows how to set the severity level to Warning.
---
# Synopsis: An example rule to require TLS.
apiVersion: github.com/microsoft/PSRule/v1
kind: Rule
metadata:
name: 'Local.YAML.RequireTLS'
spec:
level: Warning
condition:
allOf:
- field: 'configure.supportsHttpsTrafficOnly'
equals: true
- field: 'configure.minTLSVersion'
equals: '1.2'
[
{
// Synopsis: An example rule to require TLS.
"apiVersion": "github.com/microsoft/PSRule/v1",
"kind": "Rule",
"metadata": {
"name": "Local.JSON.RequireTLS"
},
"spec": {
"level": "Warning",
"condition": {
"allOf": [
{
"field": "configure.supportsHttpsTrafficOnly",
"equals": true
},
{
"field": "configure.minTLSVersion",
"equals": "1.2"
}
]
}
}
}
]
Update .ps-rule/Local.Rule.ps1 in your repository with the following contents.
# Synopsis: An example rule to require TLS.
Rule 'Local.PS.RequireTLS' -Level Warning {
$Assert.HasFieldValue($TargetObject, 'configure.supportsHttpsTrafficOnly', $True)
$Assert.HasFieldValue($TargetObject, 'configure.minTLSVersion', '1.2')
}